(**************************************************************************)
(*                   Cameleon                                             *)
(*                                                                        *)
(*      Copyright (C) 2002 Institut National de Recherche en Informatique et   *)
(*      en Automatique. All rights reserved.                              *)
(*                                                                        *)
(*      This program is free software; you can redistribute it and/or modify  *)
(*      it under the terms of the GNU General Public License as published by  *)
(*      the Free Software Foundation; either version 2 of the License, or  *)
(*      any later version.                                                *)
(*                                                                        *)
(*      This program is distributed in the hope that it will be useful,   *)
(*      but WITHOUT ANY WARRANTY; without even the implied warranty of    *)
(*      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     *)
(*      GNU General Public License for more details.                      *)
(*                                                                        *)
(*      You should have received a copy of the GNU General Public License  *)
(*      along with this program; if not, write to the Free Software       *)
(*      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA          *)
(*      02111-1307  USA                                                   *)
(*                                                                        *)
(*      Contact: Maxence.Guesdon@inria.fr                                *)
(**************************************************************************)

(*[Mo] This module contains the functions used to print sql expressions, statements, ...[Mo]*)

open Ocamlsql_types

let string_of_string_list sep l =
  let rec iter acc = function
      [] -> acc
    | e :: [] -> acc^e
    | e :: q -> iter (acc^e^sep) q
  in
  iter "" l


let rec string_of_action action =
  match action with
    Action_select -> "SELECT "
  | Action_delete -> "DELETE "
  | Action_insert privilege_column_list -> 
      "INSERT "^
      (match privilege_column_list with
	[] -> ""
      | l -> "("^(string_of_string_list ", " (List.map string_of_privilege_column l))^") ")
  | Action_update privilege_column_list ->
      "UPDATE "^
      (match privilege_column_list with
	[] -> ""
      | l -> "("^(string_of_string_list ", " (List.map string_of_privilege_column l))^") ")
  | Action_references privilege_column_list ->
      "REFERENCES "^
      (match privilege_column_list with
	[] -> ""
      | l -> "("^(string_of_string_list ", " (List.map string_of_privilege_column l))^") ")
  | Action_usage -> "USAGE"
	

and string_of_alter_column_action action =
  match action with
    Set_column_default_clause default_clause -> "SET "^(string_of_default_clause default_clause)
  | Drop_column_default_clause -> "DROP DEFAULT "


and string_of_alter_domain_action action =
  match action with
    Add_domain_constraint domain_constraint -> "ADD "^(string_of_domain_constraint domain_constraint)
  | Drop_domain_constraint constraint_name -> "DROP CONSTRAINT "^(string_of_constraint_name constraint_name)^" "
  | Set_domain_default_clause default_clause -> "SET "^(string_of_default_clause default_clause)
  | Drop_domain_default_clause -> "DROP DEFAULT "

and string_of_alter_table_action action =
  match action with
    Add_column column_def -> "ADD COLUMN "^(string_of_column_def column_def)
  | Alter_column (column_name, alter_column_action) ->
      "ALTER COLUMN "^(string_of_column_name column_name)^" "^(string_of_alter_column_action alter_column_action)
  | Add_table_constraint table_constraint_def ->
      "ADD "^(string_of_table_constraint_def table_constraint_def)
  | Drop_column (column_name, drop_behavior) ->
      "DROP COLUMN "^(string_of_column_name column_name)^" "^(string_of_drop_behavior drop_behavior)
  | Drop_table_constraint (constraint_name, drop_behavior) ->
      "DROP CONSTRAINT "^(string_of_constraint_name constraint_name)^" "^(string_of_drop_behavior drop_behavior)

and string_of_approximate_num_lit (mantissa, exponent) =
  (string_of_float mantissa)^"E"^(string_of_int exponent)

and string_of_approx_num_type t =
  match t with
    Float precision_opt ->
      "FLOAT"^
      (match precision_opt with
	None -> ""
      |	Some precision -> "("^(string_of_precision precision)^")")^
      " "
  | Real ->
      "REAL "
  | Double precision ->
      "DOUBLE("^(string_of_precision precision)^") "

and string_of_author_id id = string_of_id id

and string_of_boolean_factor bf =
  match bf with
    Boolean_test boolean_test -> string_of_boolean_test boolean_test
  | Not_boolean_test boolean_test -> "NOT "^(string_of_boolean_test boolean_test)

and string_of_boolean_primary bp =
  match bp with
    Boolean_predicate predicate -> string_of_predicate predicate
  | Boolean_search_condition search_condition -> "("^(string_of_search_condition search_condition)^") "

and string_of_boolean_term bt =
  match bt with
    Boolean_factor boolean_factor -> string_of_boolean_factor boolean_factor
  | Boolean_and (boolean_term, boolean_factor) -> 
      (string_of_boolean_term boolean_term)^"AND "^(string_of_boolean_factor boolean_factor)

and string_of_boolean_test bt =
  match bt with
    Boolean_primary boolean_primary -> string_of_boolean_primary boolean_primary
  | Boolean_primary_is (boolean_primary, truth_value) ->
      (string_of_boolean_primary boolean_primary)^"IS "^(string_of_truth_value truth_value)^" "
  | Boolean_primary_is_not (boolean_primary, truth_value) ->
      (string_of_boolean_primary boolean_primary)^"IS NOT "^(string_of_truth_value truth_value)^" "

and string_of_cast_operand o =
  match o with
    Cast_op_value value_exp -> string_of_value_exp value_exp
  | Cast_op_null -> "NULL "

and string_of_cast_spec (cast_oper, cast_target) =
  "CAST ("^(string_of_cast_operand cast_oper)^"AS "^(string_of_cast_target cast_target)^") "

and string_of_cast_target ct =
  match ct with
    Cast_domain domain_name -> string_of_domain_name domain_name
  | Cast_data_type data_type -> string_of_data_type data_type

and string_of_catalog_name id = string_of_id id

and string_of_char_factor (char_primary, collation_name_opt) =
  (string_of_char_primary char_primary)^" "^
  (match collation_name_opt with
    None -> ""
  | Some collation_name -> (string_of_collation_name collation_name)^" ")

and string_of_char_primary cp =
  match cp with
    Char_primary_value_exp value_exp_primary -> string_of_value_exp_primary value_exp_primary
  | Char_primary_string_value_fct string_value_fct -> string_of_string_value_fct string_value_fct

and string_of_char_string_lit s = "\""^s^"\""

and string_of_char_value_exp v =
  match v with
    Concatenation concatenation -> string_of_concatenation concatenation
  | Char_factor char_factor -> string_of_char_factor char_factor

and string_of_char_value_fct v =
  match v with
    Char_substring_fct (char_value_exp, start_position, string_length_opt) ->
      "SUBSTRING ("^(string_of_char_value_exp char_value_exp)^" FROM "^
      (string_of_start_position start_position)^" "^
      (match string_length_opt with
	None -> ""
      |	Some string_length -> "FOR "^(string_of_string_length string_length))^") "

  | Char_translation (char_value_exp, translation_name) ->
      "TRANSLATE ("^(string_of_char_value_exp char_value_exp)^" USING "^
      (string_of_translation_name translation_name)^") " 

  | Char_fold (fold_style, char_value_exp) ->
      (string_of_fold_style fold_style)^"("^
      (string_of_char_value_exp char_value_exp)^")"

  | Char_form_conversion (char_value_exp, form_conversion_name) ->
      "CONVERT("^(string_of_char_value_exp char_value_exp)^"USING "^
      (string_of_form_conversion_name form_conversion_name)^") "

  | Char_trim_fct trim_operands -> 
      "TRIM("^(string_of_trim_operands trim_operands)^") "

and string_of_check_constraint sc = string_of_search_condition sc

and string_of_collate_clause cn = "COLLATE "^(string_of_collation_name cn)^" "

and string_of_collation_def n = n

and string_of_collation_name n = string_of_qualified_name n

and string_of_column_constraint cc =
  match cc with
    Column_not_null -> "NOT NULL "
  | Column_unique unique_spec -> string_of_unique_spec unique_spec
  | Column_refs refs_spec -> string_of_refs_spec refs_spec
  | Column_check_constraint search_condition  ->
      "CHECK("^(string_of_search_condition search_condition)^") "

and string_of_column_constraint_def
    (constraint_name_def_opt, column_constraint, constraint_attribute_list) =
  (match constraint_name_def_opt with
    None -> ""
  | Some constraint_name_def -> (string_of_constraint_name_def constraint_name_def)^" ")^
  (string_of_column_constraint column_constraint)^
  (string_of_string_list " "
     (List.map string_of_constraint_attribute constraint_attribute_list))^
  " "
and string_of_column_type ct =
  match ct with
    Data_type data_type -> string_of_data_type data_type
  | Domain domain_name -> (string_of_domain_name domain_name)^" "

and string_of_column_def c =
  (string_of_column_name c.col_name)^" "^
  (string_of_column_type c.col_type)^
  (match c.col_default_clause with
    None -> ""
  | Some default_clause -> string_of_default_clause default_clause)^
  (string_of_string_list ", "
     (List.map string_of_column_constraint_def c.col_constaints))^" "^
  (match c.col_collate_clause with
    None -> ""
  | Some collation_name -> "COLLATE "^(string_of_collation_name collation_name)^" ")

and string_of_column_name id = string_of_id id

and string_of_column_name_list l = 
  (string_of_string_list ", " (List.map string_of_column_name l))^" "

and string_of_column_ref (qualifier_opt, column_name) =
  (match qualifier_opt with
    None -> ""
  | Some q -> (string_of_qualifier q)^".")^
  (string_of_column_name column_name)^
  " "

and string_of_comp_op op =
  match op with
    Equals -> "="
  | Not_equals -> "!="
  | Strict_less -> "<"
  | Strict_greater -> ">"
  | Less_or_equals -> "<="
  | Greater_or_equals -> ">="

and string_of_comp_predicate (row_value_cons1, comp_op, row_value_cons2) =
  (string_of_row_value_cons row_value_cons1)^
  (string_of_comp_op comp_op)^" "^
  (string_of_row_value_cons row_value_cons2)^
  " "

and string_of_concatenation (char_value_exp, char_factor) =
  (string_of_char_value_exp char_value_exp)^
  "@"^
  (string_of_char_factor char_factor)^
  " "

and string_of_constraint_attribute ca =
  match ca with
  | Deferrrable -> "DEFERRABLE "
  | Not_deferrable -> "NOT DEFERRABLE "
  | Initially_deferred -> "INITIALLY DEFERRED "
  | Initially_immediate -> "INITIALLY IMMEDIATE "

and string_of_constraint_name n = string_of_qualified_name n

and string_of_constraint_name_def constraint_name = 
  "CONSTRAINT "^(string_of_constraint_name constraint_name)^" "

and string_of_correlation_name id = string_of_id id

and string_of_corresponding_column_list l = string_of_column_name_list l

and string_of_corresponding_spec l = 
  "CORRESPONDING "^
  (match l with
    [] -> ""
  | _ -> "BY ("^(string_of_corresponding_column_list l)^") ")

and string_of_data_type dt =
  match dt with
  | Char length_opt ->
      "CHAR"^
      (match length_opt with 
	None -> ""
      | Some l -> "("^(string_of_length l)^")")^
      " "
	
  | VarChar length ->
      "VARCHAR("^(string_of_length length)^") "
					      
  | NationalChar length_opt ->
      "NATIONAL CHAR"^
      (match length_opt with 
	None -> ""
      | Some l -> "("^(string_of_length l)^")")^
      " "

  | NationalVarChar length ->
      "NATIONAL VARCHAR("^(string_of_length length)^") "

  | Bit length_opt ->
      "BIT"^
      (match length_opt with 
	None -> ""
      | Some l -> "("^(string_of_length l)^")")^
      " "

  | VarBit length ->
      "VARBIT("^(string_of_length length)^") "

  | Num num_type ->
      string_of_num_type num_type

  | Date ->
      "DATE "

  | Time (time_precision_opt, with_time_zone) ->
      "TIME "^
      (match time_precision_opt with
	None -> ""
      |	Some t -> "("^(string_of_int t)^") ")^
      (if with_time_zone then
	"WITH TIME ZONE "
      else
	""
      )
	(* bool is true = "with time zone" *)
	(* for
	   | "time" [ "(" time_precision ")" ] 
	   [ "with" "time" "zone" ]
	*)
	
  | Timestamp (timestamp_precision_opt, with_time_zone) ->
      "TIMESTAMP "^
      (match timestamp_precision_opt with
	None -> ""
      |	Some t -> "("^(string_of_int t)^") ")^
      (if with_time_zone then
	"WITH TIME ZONE "
      else
	""
      )
	(* bool is true = "with time zone" *)
	(* for
	   | "timestamp" [ "(" time_precision ")" ] 
	   [ "with" "time" "zone" ]
	*)

  | Interval interval_qualifier ->
      "INTERVAL "^(string_of_interval_qualifier interval_qualifier)

and string_of_datetime_factor (datetime_primary, time_zone_opt) =
  (string_of_datetime_primary datetime_primary)^
  (match time_zone_opt with
    None -> ""
  | Some time_zone -> string_of_time_zone time_zone)

and string_of_datetime_field f = 
  match f with
    Datetime_field_second -> "SECOND "
  | Datetime_field_minute -> "MINUTE "
  | Datetime_field_hour -> "HOUR "
  | Datetime_field_day -> "DAY "
  | Datetime_field_month -> "MONTH "
  | Datetime_field_year -> "YEAR "

and string_of_datetime_lit l =
  match l with
    Date_lit date_value -> "DATE '"^(string_of_date_value date_value)^"' "
  | Time_lit time_lit -> string_of_time_lit time_lit
  | Timestamp_lit timestamp_lit -> string_of_timestamp_lit timestamp_lit

and string_of_datetime_primary dp =
  match dp with
    Datetime_value_exp value_exp_primary ->
      string_of_value_exp_primary value_exp_primary
  | Datetime_value_fct datetime_value_fct ->
      string_of_datetime_value_fct datetime_value_fct

and string_of_datetime_term t = string_of_datetime_factor t

and string_of_datetime_value n = string_of_int n

and string_of_datetime_value_exp dve = 
  match dve with
    Datetime_term datetime_term -> string_of_datetime_term datetime_term
  | Datetime_interval_value_plus_term (interval_value_exp, datetime_term) -> 
      (string_of_interval_value_exp interval_value_exp)^"+ "^(string_of_datetime_term datetime_term)
  | Datetime_value_plus_interval_term (datetime_value_exp, interval_term) -> 
      (string_of_datetime_value_exp datetime_value_exp)^"+ "^(string_of_interval_term interval_term)
  | Datetime_value_minus_interval_term (datetime_value_exp, interval_term) ->
      (string_of_datetime_value_exp datetime_value_exp)^"- "^(string_of_interval_term interval_term)

and string_of_datetime_value_fct dvf =
  match dvf with
    Current_timestamp timestamp_precision_opt ->
      "CURRENT_TIMESTAMP "^
      (match timestamp_precision_opt with
	None -> ""
      |	Some t -> "("^(string_of_int t)^") ")
  | Current_date -> "CURRENT_DATE "
  | Current_time time_precision_opt ->
      "CURRENT_TIME "^
      (match time_precision_opt with
	None -> ""
      |	Some t -> "("^(string_of_int t)^") ")

and string_of_date_value dv =
  (string_of_int dv.date_year)^"-"^
  (string_of_int dv.date_month)^"-"^
  (string_of_int dv.date_day)

and string_of_default_clause dc =
  "DEFAULT "^
  (
   match dc with
     Default_lit lit -> string_of_lit lit
   | Default_datetime_value_fct datetime_value_fct -> string_of_datetime_value_fct datetime_value_fct
   | Default_user -> "USER "
   | Default_current_user -> "CURRENT_USER "
   | Default_session_user -> "SESSION_USER "
   | Default_system_user -> "SYSTEM_USER "
   | Default_null -> "NULL "
  )

and string_of_delete_rule ref_ac = 
  "ON DELETE "^(string_of_ref_action ref_ac)

and string_of_delete_stmt_searched (table_name, search_condition_opt) =
  "DELETE FROM "^(string_of_table_name table_name)^" "^
  (match search_condition_opt with
    None -> ""
  | Some s -> "WHERE "^(string_of_search_condition s))

and string_of_derived_column (value_exp, column_name_opt) =
  (string_of_value_exp value_exp)^" "^
  (match column_name_opt with
    None -> ""
  | Some c -> "AS "^(string_of_column_name c)^" ")

and string_of_derived_column_list l = string_of_column_name_list l

and string_of_derived_table q = string_of_table_subquery q

and string_of_direct_sql_stmt s = (string_of_directly_exec_stmt s)^";"

and string_of_directly_exec_stmt des =
  match des with
    Direct_sql_data_stmt direct_sql_data_stmt -> string_of_direct_sql_data_stmt direct_sql_data_stmt
  | Sql_schema_stmt sql_schema_stmt -> string_of_sql_schema_stmt sql_schema_stmt
  | Sql_transaction_stmt sql_transaction_stmt -> string_of_sql_transaction_stmt sql_transaction_stmt
  | Sql_connection_stmt sql_connection_stmt -> string_of_sql_connection_stmt sql_connection_stmt
  | Sql_session_stmt sql_session_stmt -> string_of_sql_session_stmt sql_session_stmt

and string_of_direct_sql_data_stmt d =
  match d with
    Direct_delete_stmt_searched delete_stmt_searched -> string_of_delete_stmt_searched delete_stmt_searched
  | Direct_select_stmt_n_rows direct_select_stmt_n_rows -> string_of_direct_select_stmt_n_rows direct_select_stmt_n_rows
  | Direct_insert_stmt insert_stmt -> string_of_insert_stmt insert_stmt
  | Direct_update_stmt_searched update_stmt_searched -> string_of_update_stmt_searched update_stmt_searched
  | Direct_temporary_table_decl temporary_table_decl -> string_of_temporary_table_decl temporary_table_decl

and string_of_direct_select_stmt_n_rows (query_exp, order_by_clause_opt) =
  (string_of_query_exp query_exp)^" "^
  (match order_by_clause_opt with
    None -> ""
  | Some o -> string_of_order_by_clause o)

and string_of_domain_constraint (constraint_name_def_opt, check_constraint, constraint_attribute_list) =
  (match constraint_name_def_opt with
    None -> ""
  | Some n -> (string_of_constraint_name n)^" ")^
  (string_of_check_constraint check_constraint)^" "^
  (string_of_string_list " " (List.map string_of_constraint_attribute constraint_attribute_list))^" "

and string_of_domain_def d =
  "CREATE DOMAIN "^(string_of_domain_name d.dom_name)^" "^
  "AS "^(string_of_data_type d.dom_data_type)^
  (match d.dom_default_clause with
    None -> ""
  | Some dc -> (string_of_default_clause dc)^" ")^
  (string_of_string_list " " (List.map string_of_domain_constraint d.dom_constaints))^" "^
  (match d.dom_collate_clause with
    None -> ""
  | Some c -> "COLLATE "^(string_of_collation_name c)^" ")

and string_of_domain_name n = string_of_qualified_name n

and string_of_drop_behavior db =
  match db with
    Cascade -> "CASCADE "
  | Restrict -> "RESTRICT "

and string_of_end_field (datetime_field, int_opt) =
  (string_of_datetime_field datetime_field)^" "^
  (match int_opt with
    None -> ""
  | Some n -> "("^(string_of_int n)^") ")

and string_of_escape_char e = string_of_char_value_exp e

and string_of_exact_num_lit enl = 
  match enl with
    Exact_float f -> (string_of_float f)^" "
  | Exact_int i -> (string_of_int i)^" "

and string_of_exact_num_type ent =
  match ent with
      | Numeric precision_scale_opt_opt -> 
	  "NUMERIC "^
	  (match precision_scale_opt_opt with
	    None -> ""
	  | Some (precision, scale_opt) ->
	      "("^(string_of_precision precision)^
	      (match scale_opt with
		None -> ""
	      |	Some s -> ", "^(string_of_scale s))^
	      ") ")

  | Decimal precision_scale_opt_opt -> 
	  "DECIMAL "^
	  (match precision_scale_opt_opt with
	    None -> ""
	  | Some (precision, scale_opt) ->
	      "("^(string_of_precision precision)^
	      (match scale_opt with
		None -> ""
	      |	Some s -> ", "^(string_of_scale s))^
	      ") ")

  | Integer -> "INTEGER "

  | SmallInteger -> "SMALLINT "

and string_of_explicit_table t = "TABLE "^(string_of_table_name t)^" "

and string_of_extract_field ef =
  match ef with 
    Extract_datetime datetime_field -> string_of_datetime_field datetime_field
  | Extract_time_zone time_zone_field -> string_of_time_zone_field time_zone_field

and string_of_extract_source es = 
  match es with
    Extract_source_datetime datetime_value_exp -> string_of_datetime_value_exp datetime_value_exp
  | Extract_source_interval interval_value_exp -> string_of_interval_value_exp interval_value_exp

and string_of_factor (sign_opt, num_primary) =
  (match sign_opt with
    None -> ""
  | Some s -> string_of_sign s)^
  (string_of_num_primary num_primary)

and string_of_fold_style fs = 
  match fs with
    Fold_upper -> "UPPER "
  | Fold_lower -> "LOWER "

and string_of_form_conversion_name n = string_of_qualified_name n

and string_of_from_clause table_ref_list =
  "FROM "^
  (string_of_string_list ", " (List.map string_of_table_ref table_ref_list))^" "

and string_of_general_lit gl =
  match gl with
    Char_string_lit char_string_lit ->
      string_of_char_string_lit char_string_lit
  | National_char_string_lit national_char_string_lit ->
      string_of_national_char_string_lit national_char_string_lit
  | Datetime_lit datetime_lit ->
      string_of_datetime_lit datetime_lit
  | Interval_lit interval_lit ->
      string_of_interval_lit interval_lit

and string_of_general_set_fct (set_fct_type, set_quantifier_opt, value_exp) =
  (string_of_set_fct_type set_fct_type)^" ("^
  (match set_quantifier_opt with 
    None -> ""
  | Some q -> (string_of_set_quantifier q)^" ")^
  (string_of_value_exp value_exp)^") "

and string_of_general_value_spec gvs =
  match gvs with
  | Gen_val_user -> "USER "
  | Gen_val_current_user -> "CURRENT_USER "
  | Gen_val_session_user -> "SESSION_USER "
  | Gen_val_system_user -> "SYSTEM_USER "
  | Gen_val_value -> "VALUE "

and string_of_grantee g =
  match g with
    Grantee_public -> "PUBLIC "
  | Grantee_author_id author_id -> string_of_author_id author_id

and string_of_grant_stmt g =
  "GRANT "^(string_of_privileges g.grant_privileges)^
  "ON "^(string_of_object_name g.grant_object)^" "^
  "TO "^(string_of_string_list ", " (List.map string_of_grantee g.grant_grantees))^" "^
  (if g.grant_with_grant_option then
    "WITH GRANT OPTION "
  else
    "")

and string_of_grouping_column_ref (column_ref, collation_name_opt) =
  (string_of_column_ref column_ref)^" "^
  (match collation_name_opt with
    None -> ""
  | Some c -> "COLLATE "^(string_of_collation_name c)^" ")

and string_of_group_by_clause grouping_column_ref_list =
  "GROUP BY "^(string_of_string_list ", "
     (List.map string_of_grouping_column_ref grouping_column_ref_list))^
  " "

and string_of_having_clause search_condition =
  "HAVNIG "^(string_of_search_condition search_condition)

and string_of_id id = id

and string_of_insert_columns_and_source i =
  match i with
    Insert_query_exp (insert_column_list, query_exp) ->
      (match insert_column_list with
	[] -> ""
      |	l -> "("^(string_of_insert_column_list insert_column_list)^") ")^
      (string_of_query_exp query_exp)
  | Insert_default_values ->
      "DEFAULT VALUES "

and string_of_insert_column_list l = string_of_column_name_list l

and string_of_insert_stmt (table_name, insert_columns_and_source) =
  "INSERT INTO "^
  (string_of_table_name table_name)^" "^
  (string_of_insert_columns_and_source insert_columns_and_source)

and string_of_interval_factor (sign_opt, interval_primary) =
  (match sign_opt with
    None -> ""
  | Some s -> (string_of_sign s)^" ")^
  (string_of_interval_primary interval_primary)

and string_of_interval_lit (sign_opt, interval_string, interval_qualifier) =
    "INTERVAL "^
  (match sign_opt with
    None -> ""
  | Some s -> (string_of_sign s)^" ")^
  (string_of_interval_string interval_string)^" "^
  (string_of_interval_qualifier interval_qualifier)

and string_of_interval_primary (value_exp_primary, interval_qualifier_opt) =
  (string_of_value_exp_primary value_exp_primary)^" "^
  (match interval_qualifier_opt with
    None -> ""
  | Some i -> string_of_interval_qualifier i)

and string_of_interval_qualifier iq = 
  match iq with
    Interval_start_end (start_field, end_field) ->
      (string_of_start_field start_field)^"TO "^(string_of_end_field end_field)
  | Interval_single_datetime_field single_datetime_field ->
      (string_of_single_datetime_field single_datetime_field)

and string_of_interval_string id = id (* string A VOIR *)

and string_of_interval_term it =
  match it with
    Interval_term_factor interval_factor -> string_of_interval_factor interval_factor
  | Interval_term_div (interval_term, factor) ->
      (string_of_interval_term interval_term)^"/ "^(string_of_factor factor)
  | Interval_term_mult (interval_term, factor) ->
      (string_of_interval_term interval_term)^"* "^(string_of_factor factor)
  | Interval_term_mult_interval (term, interval_factor) ->
      (string_of_term term)^"* "^(string_of_interval_factor interval_factor)

and string_of_interval_value_exp ive =
  match ive with
    Interval_value_term interval_term -> string_of_interval_term interval_term
  | Interval_value_plus (interval_value_exp, interval_term) ->
      (string_of_interval_value_exp interval_value_exp)^"+ "^(string_of_interval_term interval_term)
  | Interval_value_minus (interval_value_exp, interval_term) ->
      (string_of_interval_value_exp interval_value_exp)^"- "^(string_of_interval_term interval_term)
  | Interval_value_date (datetime_value_exp, datetime_term, interval_qualifier) ->
      "("^(string_of_datetime_value_exp datetime_value_exp)^"- "^
      (string_of_datetime_term datetime_term)^") "^
      (string_of_interval_qualifier interval_qualifier)

and string_of_in_predicate_value ipv =
  match ipv with
    In_subquery table_subquery -> string_of_table_subquery table_subquery
  | In_values in_value_list -> "("^(string_of_in_value_list in_value_list)^") "

and string_of_in_value_list value_exp_list =
  (string_of_string_list ", "
    (List.map string_of_value_exp value_exp_list))^
  " "

and string_of_joined_table jt =
  match jt with
    Cross_join (table_ref1, table_ref2) ->
      (string_of_table_ref table_ref1)^"CROSS JOIN "^(string_of_table_ref table_ref2)
  | Qualified_join qualified_join -> 
      string_of_qualified_join qualified_join

and string_of_join_column_list l = string_of_column_name_list l

and string_of_join_condition search_condition =
    "ON "^(string_of_search_condition search_condition)

and string_of_join_spec js =
  match js with
    Join_condition join_condition ->
      string_of_join_condition join_condition
  | Join_named_columns named_columns_join ->
      string_of_named_columns_join named_columns_join

and string_of_join_type jt =
  match jt with
    Inner_join -> "INNER "
  | Union -> "UNION "
  | Left_outer_join -> "LEFT OUTER "
  | Right_outer_join -> "RIGHT OUTER "
  | Full_outer_join -> "FULL OUTER "

and string_of_length n = string_of_int n

and string_of_length_exp le =
  match le with
    Char_length_exp string_value_exp ->
      "CHAR_LENGTH ("^(string_of_string_value_exp string_value_exp)^") "
  | Octet_length_exp string_value_exp ->
      "OCTET_LENGTH ("^(string_of_string_value_exp string_value_exp)^") "
  | Bit_length_exp string_value_exp ->
      "BIT_LENGTH ("^(string_of_string_value_exp string_value_exp)^") "

and string_of_levels_clause lc =
  match lc with
    Levels_cascaded -> "CASCADED "
  | Levels_local -> "LOCAL "

and string_of_lit l = 
  match l with
    Signed_num_lit signed_num_lit -> string_of_signed_num_lit signed_num_lit
  | General_lit general_lit -> string_of_general_lit general_lit

and string_of_local_table_name n = string_of_qualified_id n

and string_of_match_predicate (row_value_cons, unique, match_type, table_subquery) =
  (string_of_row_value_cons row_value_cons)^"MATCH "^
  (if unique then "UNIQUE " else "")^
  (string_of_match_type match_type)^
  (string_of_table_subquery table_subquery)

and string_of_match_type mt = 
  match mt with
    Match_partial -> "PARTIAL "
  | Match_full -> "FULL "

and string_of_match_value e = string_of_char_value_exp e

and string_of_named_columns_join ncj = 
  "USING ("^(string_of_join_column_list ncj)^") "

and string_of_national_char_string_lit s =
  "n \'"^s^"\'"

and string_of_non_join_query_exp e =
  match e with
    Non_join_query_term non_join_query_term -> string_of_non_join_query_term non_join_query_term
  | Non_join_query_union (query_exp, all, corresponding_spec_opt, query_term) ->
      (string_of_query_exp query_exp)^"UNION "^
      (if all then "ALL " else "")^
      (match corresponding_spec_opt with
	None -> ""
      |	Some c -> string_of_corresponding_spec c)^
      (string_of_query_term query_term)

  | Non_join_query_except (query_exp, all, corresponding_spec_opt, query_term) ->
      (string_of_query_exp query_exp)^"EXCEPT "^
      (if all then "ALL " else "")^
      (match corresponding_spec_opt with
	None -> ""
      |	Some c -> string_of_corresponding_spec c)^
      (string_of_query_term query_term)

and string_of_non_join_query_primary p =
  match p with
    Non_join_simple_table simple_table -> string_of_simple_table simple_table
  | Non_join_query_exp non_join_query_exp -> string_of_non_join_query_exp non_join_query_exp

and string_of_non_join_query_term t =
  match t with
    Non_join_query_primary non_join_query_primary -> string_of_non_join_query_primary non_join_query_primary
  | Intersect (query_term, all, corresponding_spec_opt, query_primary) ->
      (string_of_query_term query_term)^"INTERSECT "^
      (if all then "ALL " else "")^
      (match corresponding_spec_opt with
	None -> ""
      |	Some c -> string_of_corresponding_spec c)^
      (string_of_query_primary query_primary)

and string_of_num_primary p = 
  match p with
    Num_value value_exp_primary -> string_of_value_exp_primary value_exp_primary
  | Num_fct num_value_fct -> string_of_num_value_fct num_value_fct

and string_of_num_type t =
  match t with
    ExactNumType exact_num_type -> string_of_exact_num_type exact_num_type
  | Approximate_num_type approx_num_type -> string_of_approx_num_type approx_num_type

and string_of_num_value_exp e =
  match e with
    Num_term term -> string_of_term term
  | Num_plus (num_value_exp, term) -> (string_of_num_value_exp num_value_exp)^"+ "^(string_of_term term)
  | Num_minus (num_value_exp, term) -> (string_of_num_value_exp num_value_exp)^"- "^(string_of_term term)

and string_of_num_value_fct fct =
  match fct with
    Fct_extract (extract_field, extract_source) ->
      "EXTRACT ("^(string_of_extract_field extract_field)^"FROM "^(string_of_extract_source extract_source)^") "
  | Fct_position (char_value_exp1, char_value_exp2) ->
      "POSITION ("^(string_of_char_value_exp char_value_exp1)^"IN "^(string_of_char_value_exp char_value_exp2)^") "
  | Fct_length length_exp ->
      string_of_length_exp length_exp

and string_of_object_column n = string_of_column_name n

and string_of_object_name n =
  match n with
    Object_table table_name -> "TABLE "^(string_of_table_name table_name)
  | Object_domain domain_name -> "DOMAIN "^(string_of_domain_name domain_name)
  | Object_collation collation_name -> "COLLATION "^(string_of_collation_name collation_name)
  | Object_translation translation_name -> "TRANSLATION "^(string_of_translation_name translation_name)

and string_of_order_by_clause s = 
  "ORDER BY "^(string_of_sort_spec_list s)

and string_of_ordering_spec os =
  match os with
    Asc -> "ASC "
  | Desc -> "DESC "

and string_of_pattern e = string_of_char_value_exp e

and string_of_precision n = string_of_int n

and string_of_predicate p =
  match p with
  | Predicate_between (row_value_cons1, row_value_cons2, row_value_cons3) ->
      (string_of_row_value_cons row_value_cons1)^"BETWEEN "^
      (string_of_row_value_cons row_value_cons2)^"AND "^
      (string_of_row_value_cons row_value_cons3)
  | Predicate_not_between (row_value_cons1, row_value_cons2, row_value_cons3) ->
      (string_of_row_value_cons row_value_cons1)^"NOT BETWEEN "^
      (string_of_row_value_cons row_value_cons2)^"AND "^
      (string_of_row_value_cons row_value_cons3)
  | Predicate_exists table_subquery ->
      "EXISTS "^(string_of_table_subquery table_subquery)
  | Predicate_in (row_value_cons, in_predicate_value) ->
      (string_of_row_value_cons row_value_cons)^"IN "^
      (string_of_in_predicate_value in_predicate_value)
  | Predicate_not_in (row_value_cons, in_predicate_value) ->
      (string_of_row_value_cons row_value_cons)^"NOT IN "^
      (string_of_in_predicate_value in_predicate_value)
  | Predicate_like (match_value, pattern, escape_char_opt) ->
      (string_of_match_value match_value)^"LIKE "^
      (string_of_pattern pattern)^
      (match escape_char_opt with
	None -> ""
      |	Some e -> "ESCAPE "^(string_of_escape_char e)^" ")
  | Predicate_not_like (match_value, pattern, escape_char_opt) ->
      (string_of_match_value match_value)^"NOT LIKE "^
      (string_of_pattern pattern)^
      (match escape_char_opt with
	None -> ""
      |	Some e -> "ESCAPE "^(string_of_escape_char e)^" ")
  | Predicate_match match_predicate ->
      string_of_match_predicate match_predicate
  | Predicate_is_null row_value_cons ->
      (string_of_row_value_cons row_value_cons)^"IS NULL "
  | Predicate_is_not_null row_value_cons ->
      (string_of_row_value_cons row_value_cons)^"IS NOT NULL "
  | Predicate_overlaps (row_value_cons1, row_value_cons2) ->
      (string_of_row_value_cons row_value_cons1)^"OVERLAPS "^(string_of_row_value_cons row_value_cons2)
  | Predicate_comp (row_value_cons1, comp_op, row_value_cons2) ->
      (string_of_row_value_cons row_value_cons1)^
      (string_of_comp_op comp_op)^" "^
      (string_of_row_value_cons row_value_cons2)
  | Predicate_quantified_comp (row_value_cons, comp_op, quantifier, table_subquery) ->
      (string_of_row_value_cons row_value_cons)^
      (string_of_comp_op comp_op)^
      (string_of_quantifier quantifier)^
      (string_of_table_subquery table_subquery)
  | Predicate_unique table_subquery ->
      "UNIQUE "^(string_of_table_subquery table_subquery)

and string_of_privilege_column n = string_of_column_name n

and string_of_privileges p =
  match p with
    All_privileges -> "ALL PRIVILEGES "
  | Actions action_list -> 
      (string_of_string_list ", "
	 (List.map string_of_action action_list))^" "

and string_of_qualified_id id = string_of_id id

and string_of_qualified_join (table_ref1, natural, join_type_opt, table_ref2, join_spec_opt) = 
  (string_of_table_ref table_ref1)^
  (if natural then "NATURAL " else "")^
  (match join_type_opt with
    None -> ""
  | Some j -> string_of_join_type j)^
  "JOIN "^
  (string_of_table_ref table_ref2)^
  (match join_spec_opt with
    None -> ""
  | Some j -> string_of_join_spec j)

and string_of_qualified_local_table_name t = 
  "MODULE."^(string_of_local_table_name t)

and string_of_qualified_name (schema_name_opt, qualified_id) =
  (match schema_name_opt with
    None -> ""
  | Some s -> (string_of_schema_name s)^".")^
  (string_of_qualified_id qualified_id)

and string_of_qualifier q =
  match q with
    Qualifier_table table_name ->
      string_of_table_name table_name
  | Qualifier_correlation correlation_name ->
      string_of_correlation_name correlation_name

and string_of_quantified_comp_predicate (row_value_cons, comp_op, quantifier, table_subquery) =
  (string_of_row_value_cons row_value_cons)^
  (string_of_comp_op comp_op)^" "^
  (string_of_quantifier quantifier)^
  (string_of_table_subquery table_subquery)

and string_of_quantifier q =
  match q with
    Quantifier_all -> "ALL "
  | Quantifier_some -> "SOME "

and string_of_query_exp e = 
  match e with
  | Query_exp_non_join non_join_query_exp ->
      string_of_non_join_query_exp non_join_query_exp
  | Query_exp_joined_table joined_table ->
      string_of_joined_table joined_table

and string_of_query_primary p = 
  match p with
    | Query_prim_non_join non_join_query_primary ->
	string_of_non_join_query_primary non_join_query_primary
    | Query_prim_joined_table joined_table ->
	string_of_joined_table joined_table

and string_of_query_spec (set_quantifier_opt, select_list, table_exp) =
  "SELECT "^
  (match set_quantifier_opt with None -> "" | Some sq -> (string_of_set_quantifier sq)^" ")^
  (string_of_select_list select_list)^
  (string_of_table_exp table_exp)

and string_of_query_term t = 
  match t with
    | Query_term_non_join non_join_query_term -> 
	string_of_non_join_query_term non_join_query_term
    | Query_term_joined_table joined_table ->
	string_of_joined_table joined_table

and string_of_refd_table_and_columns (table_name, ref_column_list) =
  (string_of_table_name table_name)^
  (match ref_column_list with
    [] -> ""
  | l -> "("^(string_of_ref_column_list ref_column_list)^") ")

and string_of_referencing_columns l = string_of_ref_column_list l

and string_of_refs_spec (refd_table_and_columns, match_type_opt, ref_triggered_action_opt) =
  "REFERENCES "^(string_of_refd_table_and_columns refd_table_and_columns)^
  (match match_type_opt with
    None -> ""
  | Some t -> (string_of_match_type t)^" ")^
  (match ref_triggered_action_opt with
    None -> ""
  | Some r -> (string_of_ref_triggered_action r)^" ")

and string_of_ref_action ra =
  match ra with
  | Action_cascade -> "CASCADE "
  | Action_set_null -> "SET NULL "
  | Action_set_default -> "SET DEFAULT "
  | Action_no_action -> "NO ACTION "

and string_of_ref_column_list l = string_of_column_name_list l

and string_of_ref_constraint_def (referencing_columns, refs_spec) = 
  "FOREIGN KEY ("^ 
  (string_of_referencing_columns referencing_columns)^
  (string_of_refs_spec  refs_spec)

and string_of_ref_triggered_action (update_rule_opt, delete_rule_opt) =
  (match update_rule_opt with
    None -> ""
  | Some ur -> string_of_update_rule ur)^
  (match delete_rule_opt with
    None -> ""
  | Some dr -> string_of_delete_rule dr)

and string_of_result_exp e = string_of_value_exp e

and string_of_row_subquery q = string_of_subquery q

and string_of_row_value_cons rvc =
  match rvc with
    Row_value_elem row_value_cons_elem ->
      string_of_row_value_cons_elem row_value_cons_elem
  | Row_value_const_list row_value_const_list ->
      "("^(string_of_row_value_const_list row_value_const_list)^") "
  | Row_value_subquery row_subquery ->
      string_of_row_subquery row_subquery

and string_of_row_value_cons_elem e =
  match e with
    Row_value_exp value_exp -> string_of_value_exp value_exp
  | Row_value_null -> "NULL "
  | Row_value_default -> "DEFAULT "

and string_of_row_value_const_list row_value_cons_elem_list =
  (string_of_string_list ", "
     (List.map string_of_row_value_cons_elem row_value_cons_elem_list))^
  " "

and string_of_scalar_subquery q = string_of_subquery q

and string_of_scale n = string_of_int n

and string_of_schema_author_id id = string_of_author_id id

and string_of_schema_collation_name n = string_of_collation_name n

and string_of_schema_def x = x (* A VOIR *)

and string_of_schema_name (catalog_name_opt, unqualified_schema_name) =
  (match catalog_name_opt with
    None -> ""
  | Some c -> (string_of_catalog_name c)^".")^
  (string_of_unqualified_schema_name unqualified_schema_name)

and string_of_schema_translation_name n = string_of_translation_name n

and string_of_search_condition sc = 
  match sc with
    Search_cond_boolean boolean_term -> string_of_boolean_term boolean_term
  | Search_cond_or (search_condition, boolean_term) ->
      (string_of_search_condition search_condition)^"OR "^
      (string_of_boolean_term boolean_term)

and string_of_seconds_value f = string_of_float f

and string_of_select_list sl =
  match sl with
    Select_all -> "* "
  | Select_list select_sublist_list ->
      (string_of_string_list ", "
	(List.map string_of_select_sublist select_sublist_list))^
      " "

and string_of_select_sublist ss =
  match ss with
    Select_column derived_column -> string_of_derived_column derived_column
  | Select_qualifier qualifier -> (string_of_qualifier qualifier)^".* "

and string_of_set_clause (object_column, update_source) =
  (string_of_object_column object_column)^"= "^(string_of_update_source update_source)

and string_of_set_clause_list set_clause_list =
  (string_of_string_list ", "
     (List.map string_of_set_clause set_clause_list))^
  " "

and string_of_set_column_default_clause default_clause =
  "SET "^(string_of_default_clause default_clause)

and string_of_set_fct_spec s = 
  match s with
    Set_fct_spec_count -> "COUNT(*) "
  | Set_fct_spec_general general_set_fct -> string_of_general_set_fct general_set_fct

and string_of_set_fct_type t = 
  match t with 
    Set_fct_avg -> "AVG "
  | Set_fct_max -> "MAX "
  | Set_fct_min -> "MIN "
  | Set_fct_sum -> "SUM "
  | Set_fct_count -> "COUNT "

and string_of_set_quantifier q = 
  match q with
    Distinct -> "DISTINCT "
  | All -> "ALL "

and string_of_sign s = 
  match s with
    Sign_plus -> "+"
  | Sign_minus -> "-"

and string_of_signed_num_lit (sign_opt, unsigned_num_lit) =
  (match sign_opt with None -> ""  | Some s -> string_of_sign s)^
  (string_of_unsigned_num_lit unsigned_num_lit)

and string_of_simple_table st =
  match st with
    Simple_table_query query_spec ->
      string_of_query_spec query_spec
  | Simple_table_value table_value_constructor ->
      string_of_table_value_constructor table_value_constructor
  | Simple_table_explicit explicit_table ->
      string_of_explicit_table explicit_table

and string_of_single_datetime_field df =
  match df with
    Single_datetime_non_second (datetime_field, int_opt) ->
      (string_of_datetime_field datetime_field)^
      (match int_opt with
	None -> ""
      |	Some n -> "("^(string_of_int n)^") ")
  | Single_datetime_second None ->
      "SECOND "
  | Single_datetime_second (Some (interval_leading_fieldprec, interval_frac_seconds_prec_opt)) ->
      "SECOND ("^
      (string_of_int interval_leading_fieldprec)^
      (match interval_frac_seconds_prec_opt with
	None -> ""
      |	Some n -> ", "^(string_of_int n))^") "

and string_of_sort_key sk =
  match sk with
    Sort_key_column column_name ->
      string_of_column_name column_name
  | Sort_key_int n ->
      string_of_int n

and string_of_sort_spec (sort_key, collate_clause_opt, ordering_spec_opt) =
  (string_of_sort_key sort_key)^" "^
  (match collate_clause_opt with
    None -> ""
  | Some c -> (string_of_collate_clause c)^" ")^
  (match ordering_spec_opt with
    None -> ""
  | Some o -> (string_of_ordering_spec o)^" ")

and string_of_sort_spec_list sort_spec_list =
  (string_of_string_list ", "
     (List.map string_of_sort_spec sort_spec_list))^
  " "

and string_of_sql_connection_stmt x = x (* A VOIR *)

and string_of_sql_data_change_stmt s =
  match s with
  | Delete_stmt_searched delete_stmt_searched ->
      string_of_delete_stmt_searched delete_stmt_searched
  | Insert_stmt (table_name, insert_columns_and_source) ->
      "INSERT INTO "^(string_of_table_name table_name)^" "^
      (string_of_insert_columns_and_source insert_columns_and_source)
  | Update_stmt_searched update_stmt_searched ->
      string_of_update_stmt_searched update_stmt_searched

and string_of_sql_schema_def_stmt s =
  match s with
  | Schema_def schema_def -> string_of_schema_def schema_def
  | Table_def table_def -> string_of_table_def table_def
  | View_def view_def -> string_of_view_def view_def
  | Grant grant_stmt -> string_of_grant_stmt grant_stmt
  | Domain_def domain_def -> string_of_domain_def domain_def
  | Collation_def collation_def -> string_of_collation_def collation_def

and string_of_sql_schema_manipulat_stmt s =
  match s with
    Alter_domain_stmt (domain_name, alter_domain_action) ->
      "ALTER DOMAIN "^(string_of_domain_name domain_name)^" "^(string_of_alter_domain_action alter_domain_action)
  | Alter_table_stmt (table_name, alter_table_action) ->
      "ALTER TABLE "^(string_of_table_name table_name)^" "^(string_of_alter_table_action alter_table_action)
  | Drop_assertion_stmt constraint_name ->
      "DROP ASSERTION "^(string_of_constraint_name constraint_name)^" "
  | Drop_translation_stmt translation_name ->
      "DROP TRANSLATION "^(string_of_translation_name translation_name)^" "
  | Drop_collation_stmt collation_name -> 
      "DROP COLLATION "^(string_of_collation_name collation_name)^" "
  | Drop_domain_stmt (domain_name, drop_behavior) ->
      "DROP DOMAIN "^(string_of_domain_name domain_name)^" "^(string_of_drop_behavior drop_behavior)
  | Drop_schema_stmt (schema_name, drop_behavior) ->
      "DROP SCHEMA "^(string_of_schema_name schema_name)^" "^(string_of_drop_behavior drop_behavior)
  | Drop_table_stmt (table_name, drop_behavior) ->
      "DROP TABLE "^(string_of_table_name table_name)^" "^(string_of_drop_behavior drop_behavior)
  | Drop_view_stmt (table_name, drop_behavior) ->
      "DROP VIEW "^(string_of_table_name table_name)^" "^(string_of_drop_behavior drop_behavior)
  | Revoke_stmt (grant_option, privileges, object_name, grantee_list, drop_behavior) ->
      "REVOKE "^
      (if grant_option then "GRANT OPTION FOR " else "")^
      (string_of_privileges privileges)^
      "ON "^
      (string_of_object_name object_name)^" FROM "^
      (string_of_string_list ", " (List.map string_of_grantee grantee_list))^" "^
      (string_of_drop_behavior drop_behavior)

and string_of_sql_schema_stmt s = 
  match s with
    Schema_def_stmt sql_schema_def_stmt ->
      string_of_sql_schema_def_stmt sql_schema_def_stmt
  | Schema_manipulat_stmt sql_schema_manipulat_stmt ->
      string_of_sql_schema_manipulat_stmt sql_schema_manipulat_stmt

and string_of_sql_session_stmt x = x (* A VOIR *)

and string_of_sql_transaction_stmt x = x (* A VOIR *)

and string_of_start_field (datetime_field, int_opt (*interval_leading_fieldprec*)) =
  (string_of_datetime_field datetime_field)^
  (match int_opt with
    None -> ""
  | Some n -> "("^(string_of_int n)^") ")

and string_of_start_position e = string_of_num_value_exp e (* A VOIR *)

and string_of_std_collation_name n = string_of_collation_name n

and string_of_std_translation_name n = string_of_translation_name n

and string_of_string_length e = string_of_num_value_exp e

and string_of_string_value_exp e = 
  match e with
    | String_value_char char_value_exp -> string_of_char_value_exp char_value_exp

and string_of_string_value_fct fct = 
  match fct with
    | String_fct_char char_value_fct -> string_of_char_value_fct char_value_fct

and string_of_subquery q = "("^(string_of_query_exp q)^") "

and string_of_table_constraint tc =
  match tc with
  | Table_unique_constraint unique_constraint_def ->
      string_of_unique_constraint_def unique_constraint_def
  | Table_ref_constraint ref_constraint_def ->
      string_of_ref_constraint_def ref_constraint_def
  | Table_check_constraint check_constraint ->
      "CHECK ("^(string_of_check_constraint check_constraint)^") "

and string_of_table_constraint_def (constraint_name_def_opt, table_constraint, constraint_attribute_list) =
  (match constraint_name_def_opt with
    None -> ""
  | Some c -> (string_of_constraint_name_def c)^" ")^
  (string_of_table_constraint table_constraint)^
  (string_of_string_list " " (List.map string_of_constraint_attribute constraint_attribute_list))^" "

and string_of_table_def t =
  "CREATE "^
  (match t.tab_temporary with
    None -> ""
  | Some temp -> (string_of_temporary_scope temp)^"TEMPORARY ")^
  "TABLE "^
  (string_of_table_name t.tab_name)^" "^
  (string_of_table_element_list t.tab_elements)^
  (match t.tab_on_commit_action with
    None -> ""
  | Some oca -> "ON COMMIT "^(string_of_on_commit_action oca))
  
and string_of_temporary_scope t =
  match t with
    Global -> "GLOBAL "
  | Local -> "LOCAL "

and string_of_on_commit_action oca =
  match oca with
    Delete_rows -> "DELETE ROWS "
  | Preserve_rows -> "PRESERVE ROWS "

and string_of_table_element e =
  match e with
    Column_def column_def -> 
      string_of_column_def column_def
  | Table_constraint_def table_constraint_def ->
      string_of_table_constraint_def table_constraint_def

and string_of_table_element_list table_element_list =
  "("^
  (string_of_string_list ", "
     (List.map string_of_table_element table_element_list))^
  ") "

and string_of_table_exp (from_clause, where_clause_opt, group_by_clause_opt, having_clause_opt) =
  (string_of_from_clause from_clause)^
  (match where_clause_opt with None -> "" | Some w -> string_of_where_clause w)^
  (match group_by_clause_opt with None -> "" | Some g -> string_of_group_by_clause g)^
  (match having_clause_opt with None -> "" | Some h -> string_of_having_clause h)

and string_of_table_name t =
  match t with
    Qualified_table_name qualified_name ->
      string_of_qualified_name qualified_name
  | Qualified_local_table_name qualified_local_table_name ->
      string_of_qualified_local_table_name qualified_local_table_name

and string_of_table_ref tr = 
  match tr with
    Table_ref_name (table_name, None) ->
      (string_of_table_name table_name)^" "
  | Table_ref_name (table_name, Some (correlation_name, derived_column_list)) ->
      (string_of_table_name table_name)^" AS "^
      (string_of_correlation_name correlation_name)^" "^
      (match derived_column_list with
	[] -> ""
      |	l -> "("^(string_of_derived_column_list l)^") ")
  | Table_ref_derived (derived_table, correlation_name, derived_column_list) ->
      (string_of_derived_table derived_table)^"AS "^(string_of_correlation_name correlation_name)^" "^
      (match derived_column_list with
	[] -> ""
      |	l -> "("^(string_of_derived_column_list l)^") ")
  | Table_ref_joined joined_table ->
      string_of_joined_table joined_table

and string_of_table_subquery q = string_of_subquery q

and string_of_table_value_constructor table_value_const_list =
  "VALUES "^(string_of_table_value_const_list table_value_const_list)

and string_of_table_value_const_list row_value_cons_list =
  (string_of_string_list ", "
    (List.map string_of_row_value_cons row_value_cons_list))^
  " "

and string_of_temporary_table_decl x = x (* A VOIR*)

and string_of_term t = 
  match t with
    Factor factor -> string_of_factor factor
  | Mult (term,  factor) ->  (string_of_term term)^"* "^(string_of_factor factor)
  | Div (term, factor) -> (string_of_term term)^"/ "^(string_of_factor factor)

and string_of_timestamp_lit s = "TIMESTAMP "^(string_of_timestamp_string s)

and string_of_timestamp_precision n = string_of_int n

and string_of_timestamp_string x = x (* A VOIR*)

and string_of_time_lit s = "TIME "^(string_of_time_string s)

and string_of_time_precision n = string_of_int n

and string_of_time_string (time_value, time_zone_interval_opt) =
  "'"^(string_of_time_value time_value)^
  (match time_zone_interval_opt with None -> "" | Some t -> string_of_time_zone_interval t)^
  "' "

and string_of_time_value t =
  (string_of_int t.time_hour)^":"^
  (string_of_int t.time_minute)^":"^
  (string_of_seconds_value t.time_second)

and string_of_time_zone time_zone_specifier =
  "AT "^(string_of_time_zone_specifier time_zone_specifier)

and string_of_time_zone_field f =
  match f with
    Time_zone_hour -> "TIMEZONE_HOUR "
  | Time_zone_minute -> "TIMEZONE_MINUTE "

and string_of_time_zone_interval x = x (* A VOIR*)

and string_of_time_zone_specifier s =
  match s with
    Local_time_zone -> "LOCAL "
  | Interval_time_zone interval_value_exp -> "TIME ZONE "^(string_of_interval_value_exp interval_value_exp)

and string_of_translation_name n = string_of_qualified_name n

and string_of_trim_char e = string_of_char_value_exp e

and string_of_trim_operands (trim_spec_opt, trim_char_opt, trim_source) =
  (match trim_spec_opt with
    None -> ""
  | Some t -> string_of_trim_spec t)^
  (match trim_char_opt with
    None -> ""
  | Some t -> string_of_trim_char t)^
  (match trim_spec_opt, trim_char_opt with (None, None) -> "" | _ -> "FROM ")^
  (string_of_trim_source trim_source)

and string_of_trim_source e = string_of_char_value_exp e

and string_of_trim_spec s = 
  match s with
    Trim_leading -> "LEADING "
  | Trim_trailing -> "TRAILING "
  | Trim_both -> "BOTH "

and string_of_truth_value v = 
  match v with
    True -> "true "
  | False -> "false "
  | Unknown -> "unknown "

and string_of_unique_column_list l = string_of_column_name_list l

and string_of_unique_constraint_def (unique_spec, unique_column_list) =
  (string_of_unique_spec unique_spec)^"("^
  (string_of_unique_column_list unique_column_list)^") "

and string_of_unique_spec s =
  match s with
    Unique -> "UNIQUE "
  | Primary_key -> "PRIMARY KEY "

and string_of_unqualified_schema_name id = string_of_id id

and string_of_unsigned_lit l = 
  match l with
    Unsigned_num_lit unsigned_num_lit -> string_of_unsigned_num_lit unsigned_num_lit
  | Unsigned_general_lit general_lit -> string_of_general_lit general_lit

and string_of_unsigned_num_lit l = 
  match l with
    Exact_num_lit exact_num_lit -> string_of_exact_num_lit exact_num_lit
  | Approximate_num_lit approximate_num_lit -> string_of_approximate_num_lit approximate_num_lit

and string_of_unsigned_value_spec s =
  match s with
    Unsigned_lit unsigned_lit -> string_of_unsigned_lit unsigned_lit
  | General_value general_value_spec -> string_of_general_value_spec general_value_spec

and string_of_update_rule ref_action =
  "ON UPDATE "^(string_of_ref_action ref_action)

and string_of_update_source s = 
  match s with
    Update_value value_exp -> string_of_value_exp value_exp
  | Update_null -> "NULL "
  | Update_default -> "DEFAULT "

and string_of_update_stmt_searched (table_name, set_clause_list, search_condition_opt) =
  "UPDATE "^(string_of_table_name table_name)^" SET "^
  (string_of_set_clause_list set_clause_list)^
  (match search_condition_opt with
    None -> ""
  | Some sc -> "WHERE "^(string_of_search_condition sc))

and string_of_value_exp e = 
  match e with
    Value_exp_num num_value_exp -> string_of_num_value_exp num_value_exp
  | Value_exp_string string_value_exp -> string_of_string_value_exp string_value_exp
  | Value_exp_datetime datetime_value_exp -> string_of_datetime_value_exp datetime_value_exp
  | Value_exp_interval interval_value_exp -> string_of_interval_value_exp interval_value_exp

and string_of_value_exp_primary p = 
  match p with
    Unsigned_value_exp unsigned_value_spec -> string_of_unsigned_value_spec unsigned_value_spec
  | Column_ref column_ref -> string_of_column_ref column_ref
  | Set_fct_spec set_fct_spec -> string_of_set_fct_spec set_fct_spec
  | Scalar_subquery scalar_subquery -> string_of_scalar_subquery scalar_subquery
  | Value_exp value_exp -> "("^(string_of_value_exp value_exp)^") "
  | Cast_spec cast_spec -> string_of_cast_spec cast_spec

and string_of_value_spec s =
  match s with
    Lit lit -> string_of_lit lit
  | General_value_spec general_value_spec -> string_of_general_value_spec general_value_spec

and string_of_view_column_list l = string_of_column_name_list l

and string_of_view_def v =
  "CREATE VIEW "^(string_of_table_name v.view_name)^" "^
  (match v.view_columns with
    [] -> ""
  | l -> "("^(string_of_view_column_list l)^") ")^
  "AS "^
  (string_of_query_exp v.view_query)^
  (if v.view_with_check_option then
    (
     "WITH "^
     (match v.view_levels with 
       None -> ""
     | Some l -> string_of_levels_clause l)^
     "CHECK OPTION "
    )
  else
    ""
  )

and string_of_where_clause search_condition =
  "WHERE "^(string_of_search_condition search_condition)
