open Dbf_sql.SQL_db
open Dbf_sql


let print = fun tmpl__env tmpl__channel ->
  Pervasives.output_string tmpl__channel "\n";
  Pervasives.output_string tmpl__channel "\n";
  begin 
let (table,module_name,_idx) = tmpl__env in

let pkey    =
  match table.SQL_db.ta_pkey with
    | [] -> None
    | pkey -> Some { SQL_db.idx_name    = "";
                     SQL_db.idx_columns = pkey;
                     SQL_db.idx_unique  = true;
                     SQL_db.idx_db      = table.SQL_db.ta_db; }

and sql_pkey =
  if table.SQL_db.ta_pkey <> [] then
    Some (Dbf_misc.join
            ~sep:", "
            ~to_string:(fun c -> c.col_name)
            table.SQL_db.ta_pkey)
  else
    None
in

let indexes =
  (match pkey with None -> [] | Some i -> [i]) @ _idx
and columns = table.ta_columns
in

let table_name  = table.ta_name in
let log_table_name = Printf.sprintf "%s_log" table_name in
let log_table =
  { table with
    ta_name = log_table_name ;
    ta_logged = false ;
    ta_pkey = [] ;
  }
in
let log_columns =
  let col ~name ~ty ~ocaml_ty ~sql2ml ~ml2sql =
    { col_name = name ;
      col_comment = "" ;
      col_type = ty ;
      col_table = log_table ;
      col_nullable = false ;
      col_spec_options = Dbf_misc.StringMap.empty;
      col_spec_ty = Dbf_misc.StringMap.empty;
      col_ocaml_ty = ocaml_ty ;
      col_sql2ml = sql2ml ;
      col_ml2sql = ml2sql ;
    }
  in
  [
    col ~name: "log_who" ~ty: (Int (NoneNO_None))
      ~ocaml_ty: "int"
      ~sql2ml: "Sql.sql2int" ~ml2sql: "Sql.int2sql" ;

    col ~name: "log_date" ~ty: (SQL_db.Double (NoneNO_None))
      ~ocaml_ty: "float"
      ~sql2ml: "Sql.sql2float" ~ml2sql: "Sql.float2sql" ;

    col ~name: "log_action" ~ty: (SQL_db.TinyInt (None,NO_None))
      ~ocaml_ty: "Dbf_sql_misc.log_action"
      ~sql2ml: "Dbf_sql_misc.action_of_string"
      ~ml2sql: "Dbf_sql_misc.string_of_action";
  ]
in
log_table.ta_columns <- log_columns @ table.ta_columns;

let idx_name    = fun index -> index.idx_name

and col_name     = fun column -> column.col_name
and col_ocaml_ty = fun opt column ->
  if opt && column.col_nullable then
    Printf.sprintf "%s option" column.col_ocaml_ty
  else
    column.col_ocaml_ty
in

let args_of_columns = fun ~nullty ~opt columns ->
  let print =
    if   opt
    then (fun s1 s2 -> Printf.sprintf "?(%s : %s option)" s1 s2)
    else (fun s1 s2 -> Printf.sprintf "~(%s : %s)" s1 s2)
  in
    Dbf_misc.join
      ~sep:" "
      ~to_string:
        (fun c -> print c.col_name (col_ocaml_ty nullty c))
      columns

and sql_columns_spec_infos =
  let sql_column_spec_infos = fun column ->
    let db2 =
      Dbf_misc.StringMap.fold (fun k _ acc -> k :: acc)
        column.SQL_db.col_spec_ty []
    and db1 =
      Dbf_misc.StringMap.fold (fun k _ acc -> k :: acc)
        column.SQL_db.col_spec_options []
    in
    let dbs = Dbf_misc.uniq ~sorted:false (db1 @ db2) in
    let infos_for_db = fun db ->
      let spec_ty =
        try  Printf.sprintf "Some \"%s\""
          (String.escaped
             (Dbf_misc.StringMap.find db column.SQL_db.col_spec_ty))
        with Not_found ->
          "None"
      and spec_options =
        try
          Printf.sprintf "Some \"%s\""
            (String.escaped
               (Dbf_misc.join ~sep:" " ~to_string:(fun x -> x)
                  (Dbf_misc.StringMap.find db column.SQL_db.col_spec_options)))
        with
          | Not_found ->
              "None"
      in
        (Printf.sprintf "\"%s\"" (String.escaped db),
         Printf.sprintf "(%s, %s)" spec_ty spec_options)
    in
      List.map infos_for_db dbs
  in
    List.map
      (fun c -> (Printf.sprintf "\"%s\""
                   (String.escaped c.SQL_db.col_name),
                 Printf.sprintf "\"%s %s\""
                   (String.escaped (SQL_ty.fullstring_of_type c.col_type))
                   (if c.SQL_db.col_nullable then "NULL" else "NOT NULL"),
                 sql_column_spec_infos c))
      columns

and sql_columns =
  Dbf_misc.join
    ~sep:", "
    ~to_string:(fun c -> c.col_name)
    columns

and idx_sql_columns = fun index ->
  Dbf_misc.join ~sep:", " ~to_string:(fun c -> c.col_name) index.idx_columns

    in Pervasives.output_string tmpl__channel "\n";
    Pervasives.output_string tmpl__channel "\n";
    Pervasives.output_string tmpl__channel "module ";
    begin
      let string = (module_name)
        in
        Pervasives.output_string tmpl__channel string
    end;
    Pervasives.output_string tmpl__channel " = functor (Sql : Dbf_sql_driver.SqlDriver) ->\n";
    Pervasives.output_string tmpl__channel "  struct\n";
    Pervasives.output_string tmpl__channel "    type t = {\n";
    Pervasives.output_string tmpl__channel "        ";
    begin
      List.iter
        (fun column -> begin
          Pervasives.output_string tmpl__channel "\n";
          Pervasives.output_string tmpl__channel "        ";
          begin
            let string = (col_name column)
              in
              Pervasives.output_string tmpl__channel string
          end;
          Pervasives.output_string tmpl__channel " : ";
          begin
            let string = (col_ocaml_ty true column)
              in
              Pervasives.output_string tmpl__channel string
          end;
          Pervasives.output_string tmpl__channel " ;\n";
          Pervasives.output_string tmpl__channel "        "end)
        columns
    end;
    Pervasives.output_string tmpl__channel "\n";
    Pervasives.output_string tmpl__channel "      }\n";
    Pervasives.output_string tmpl__channel "\n";
    Pervasives.output_string tmpl__channel "    let opt_values_of_args = fun ";
    begin
      let string = (args_of_columns true true columns)
        in
        Pervasives.output_string tmpl__channel string
    end;
    Pervasives.output_string tmpl__channel " () ->\n";
    Pervasives.output_string tmpl__channel "      [";
    begin
      List.iter
        (fun c -> begin
          Pervasives.output_string tmpl__channel "\n";
          Pervasives.output_string tmpl__channel "        begin match ";
          begin
            let string = (col_name c)
              in
              Pervasives.output_string tmpl__channel string
          end;
          Pervasives.output_string tmpl__channel " with\n";
          Pervasives.output_string tmpl__channel "        | None   -> None\n";
          Pervasives.output_string tmpl__channel "        | Some v -> begin\n";
          Pervasives.output_string tmpl__channel "            ";
          if (c.col_nullable) then begin
            Pervasives.output_string tmpl__channel "\n";
            Pervasives.output_string tmpl__channel "              match v with\n";
            Pervasives.output_string tmpl__channel "              | None   ->\n";
            Pervasives.output_string tmpl__channel "                  Some (None,\n";
            Pervasives.output_string tmpl__channel "                        \"";
            begin
              let string = (col_name c)
                in
                Pervasives.output_string tmpl__channel string
            end;
            Pervasives.output_string tmpl__channel "\")\n";
            Pervasives.output_string tmpl__channel "              | Some v ->\n";
            Pervasives.output_string tmpl__channel "                  Some (Some (Sql.escape_value ((";
            begin
              let string = (c.col_ml2sql)
                in
                Pervasives.output_string tmpl__channel string
            end;
            Pervasives.output_string tmpl__channel ") v)),\n";
            Pervasives.output_string tmpl__channel "                        \"";
            begin
              let string = (col_name c)
                in
                Pervasives.output_string tmpl__channel string
            end;
            Pervasives.output_string tmpl__channel "\")\n";
            Pervasives.output_string tmpl__channel "                    ";
            
            end;
            if (not c.col_nullable) then begin
              Pervasives.output_string tmpl__channel "\n";
              Pervasives.output_string tmpl__channel "                      Some (Some (Sql.escape_value ((";
              begin
                let string = (c.col_ml2sql)
                  in
                  Pervasives.output_string tmpl__channel string
              end;
              Pervasives.output_string tmpl__channel ") v)),\n";
              Pervasives.output_string tmpl__channel "                            \"";
              begin
                let string = (col_name c)
                  in
                  Pervasives.output_string tmpl__channel string
              end;
              Pervasives.output_string tmpl__channel "\")\n";
              Pervasives.output_string tmpl__channel "                        ";
              
              end;
              Pervasives.output_string tmpl__channel "\n";
              Pervasives.output_string tmpl__channel "        end\n";
              Pervasives.output_string tmpl__channel "        end ;\n";
              Pervasives.output_string tmpl__channel "        "end)
            columns
        end;
        Pervasives.output_string tmpl__channel "]\n";
        Pervasives.output_string tmpl__channel "\n";
        Pervasives.output_string tmpl__channel "    let condition_of_args = fun ";
        begin
          let string = (args_of_columns true true columns)
            in
            Pervasives.output_string tmpl__channel string
        end;
        Pervasives.output_string tmpl__channel " () ->\n";
        Pervasives.output_string tmpl__channel "      let vals = opt_values_of_args\n";
        Pervasives.output_string tmpl__channel "          ";
        begin
          List.iter
            (fun c -> begin
              Pervasives.output_string tmpl__channel "?";
              begin
                let string = (c.col_name)
                  in
                  Pervasives.output_string tmpl__channel string
              end;
              Pervasives.output_string tmpl__channel " "end)
            columns
        end;
        Pervasives.output_string tmpl__channel " ()\n";
        Pervasives.output_string tmpl__channel "      in\n";
        Pervasives.output_string tmpl__channel "      let columns = List.fold_left\n";
        Pervasives.output_string tmpl__channel "          (fun acc opt ->\n";
        Pervasives.output_string tmpl__channel "            match opt with\n";
        Pervasives.output_string tmpl__channel "              None -> acc\n";
        Pervasives.output_string tmpl__channel "            | Some (v,name) -> (v,String.escaped name) :: acc)\n";
        Pervasives.output_string tmpl__channel "          []\n";
        Pervasives.output_string tmpl__channel "          vals\n";
        Pervasives.output_string tmpl__channel "      in\n";
        Pervasives.output_string tmpl__channel "      Dbf_sql_misc.join\n";
        Pervasives.output_string tmpl__channel "        ~sep:\" AND \"\n";
        Pervasives.output_string tmpl__channel "        ~to_string:\n";
        Pervasives.output_string tmpl__channel "        (function\n";
        Pervasives.output_string tmpl__channel "            (None, name) -> Printf.sprintf \"%s IS NULL\" name\n";
        Pervasives.output_string tmpl__channel "          | (Some value, name)->\n";
        Pervasives.output_string tmpl__channel "              Printf.sprintf \"%s = %s\" name value\n";
        Pervasives.output_string tmpl__channel "        )\n";
        Pervasives.output_string tmpl__channel "        columns\n";
        Pervasives.output_string tmpl__channel "\n";
        Pervasives.output_string tmpl__channel "    let columns_decls =\n";
        Pervasives.output_string tmpl__channel "      [";
        begin
          List.iter
            (fun c -> begin
              Pervasives.output_string tmpl__channel "\n";
              Pervasives.output_string tmpl__channel "        ";
              begin let (name, ty, infos) = c in
                Pervasives.output_string tmpl__channel "\n";
                Pervasives.output_string tmpl__channel "        (";
                begin
                  let string = (name)
                    in
                    Pervasives.output_string tmpl__channel string
                end;
                Pervasives.output_string tmpl__channel ", ";
                begin
                  let string = (ty)
                    in
                    Pervasives.output_string tmpl__channel string
                end;
                Pervasives.output_string tmpl__channel ",\n";
                Pervasives.output_string tmpl__channel "         [";
                begin
                  List.iter
                    (fun info -> begin
                      Pervasives.output_string tmpl__channel "(";
                      begin
                        let string = (fst info)
                          in
                          Pervasives.output_string tmpl__channel string
                      end;
                      Pervasives.output_string tmpl__channel ", ";
                      begin
                        let string = (snd info)
                          in
                          Pervasives.output_string tmpl__channel string
                      end;
                      Pervasives.output_string tmpl__channel ");"end)
                    infos
                end;
                Pervasives.output_string tmpl__channel "]) ;\n";
                Pervasives.output_string tmpl__channel "        "
              end;
              end)
            sql_columns_spec_infos
        end;
        Pervasives.output_string tmpl__channel "]\n";
        Pervasives.output_string tmpl__channel "\n";
        Pervasives.output_string tmpl__channel "\n";
        Pervasives.output_string tmpl__channel "    let log_sql_columns_decls =\n";
        Pervasives.output_string tmpl__channel "      let sql_column_decl = fun (name, ty, opts) ->\n";
        Pervasives.output_string tmpl__channel "        let ty =\n";
        Pervasives.output_string tmpl__channel "          try\n";
        Pervasives.output_string tmpl__channel "            match List.assoc Sql.db_id opts with\n";
        Pervasives.output_string tmpl__channel "            | None,         _ -> ty\n";
        Pervasives.output_string tmpl__channel "            | Some spec_ty, _ -> spec_ty\n";
        Pervasives.output_string tmpl__channel "          with\n";
        Pervasives.output_string tmpl__channel "          | Not_found -> ty\n";
        Pervasives.output_string tmpl__channel "        in\n";
        Pervasives.output_string tmpl__channel "        Printf.sprintf \"%s %s\" name ty\n";
        Pervasives.output_string tmpl__channel "      in\n";
        Pervasives.output_string tmpl__channel "      Dbf_sql_misc.join\n";
        Pervasives.output_string tmpl__channel "        ~sep:\", \"\n";
        Pervasives.output_string tmpl__channel "        ~to_string:sql_column_decl\n";
        Pervasives.output_string tmpl__channel "        columns_decls\n";
        Pervasives.output_string tmpl__channel "\n";
        Pervasives.output_string tmpl__channel "    let sql_columns_decls =\n";
        Pervasives.output_string tmpl__channel "      let sql_column_decl = fun (name, ty, opts) ->\n";
        Pervasives.output_string tmpl__channel "        let (ty, options) =\n";
        Pervasives.output_string tmpl__channel "          try\n";
        Pervasives.output_string tmpl__channel "            match List.assoc Sql.db_id opts with\n";
        Pervasives.output_string tmpl__channel "            | None,         None      -> (ty, \"\")\n";
        Pervasives.output_string tmpl__channel "            | Some spec_ty, None      -> (spec_ty, \"\")\n";
        Pervasives.output_string tmpl__channel "            | None,         Some opts -> (ty, opts)\n";
        Pervasives.output_string tmpl__channel "            | Some spec_ty, Some opts -> (spec_ty, opts)\n";
        Pervasives.output_string tmpl__channel "          with\n";
        Pervasives.output_string tmpl__channel "          | Not_found -> (ty, \"\")\n";
        Pervasives.output_string tmpl__channel "        in\n";
        Pervasives.output_string tmpl__channel "        Printf.sprintf \"%s %s %s\" name ty options\n";
        Pervasives.output_string tmpl__channel "      in\n";
        Pervasives.output_string tmpl__channel "      let decls =\n";
        Pervasives.output_string tmpl__channel "        Dbf_sql_misc.join\n";
        Pervasives.output_string tmpl__channel "          ~sep:\", \"\n";
        Pervasives.output_string tmpl__channel "          ~to_string:sql_column_decl\n";
        Pervasives.output_string tmpl__channel "          columns_decls\n";
        Pervasives.output_string tmpl__channel "      in\n";
        Pervasives.output_string tmpl__channel "      ";
        if (sql_pkey <> Nonethen begin
          Pervasives.output_string tmpl__channel "\n";
          Pervasives.output_string tmpl__channel "        let decls = Printf.sprintf \"%s, PRIMARY KEY (%s)\"\n";
          Pervasives.output_string tmpl__channel "            decls \"";
          begin
            let string = (String.escaped (Dbf_misc.unopt sql_pkey))
              in
              Pervasives.output_string tmpl__channel string
          end;
          Pervasives.output_string tmpl__channel "\" in\n";
          Pervasives.output_string tmpl__channel "        ";
          
          end;
          Pervasives.output_string tmpl__channel "\n";
          Pervasives.output_string tmpl__channel "          decls\n";
          Pervasives.output_string tmpl__channel "\n";
          Pervasives.output_string tmpl__channel "    let row_as_record = fun ?(offset = 0) row ->\n";
          Pervasives.output_string tmpl__channel "      {\n";
          Pervasives.output_string tmpl__channel "        ";
          begin
            let (min, max) = ((0, List.length columns - 1))
              in 
              for idx = min to max do
              Pervasives.output_string tmpl__channel "\n";
              Pervasives.output_string tmpl__channel "        ";
              begin let column = List.nth columns idx in
                Pervasives.output_string tmpl__channel "\n";
                Pervasives.output_string tmpl__channel "        ";
                begin
                  let string = (col_name column)
                    in
                    Pervasives.output_string tmpl__channel string
                end;
                Pervasives.output_string tmpl__channel " =\n";
                Pervasives.output_string tmpl__channel "        ";
                if (column.col_nullable) then begin
                  Pervasives.output_string tmpl__channel "\n";
                  Pervasives.output_string tmpl__channel "          Dbf_sql_misc.apply_opt\n";
                  Pervasives.output_string tmpl__channel "            (";
                  begin
                    let string = (column.col_sql2ml)
                      in
                      Pervasives.output_string tmpl__channel string
                  end;
                  Pervasives.output_string tmpl__channel ") row.(";
                  begin
                    let string = (string_of_int (idx))
                      in
                      Pervasives.output_string tmpl__channel string
                  end;
                  Pervasives.output_string tmpl__channel " + offset) ;\n";
                  Pervasives.output_string tmpl__channel "        ";
                  
                  end;
                  if (not column.col_nullable) then begin
                    Pervasives.output_string tmpl__channel "\n";
                    Pervasives.output_string tmpl__channel "          (";
                    begin
                      let string = (column.col_sql2ml)
                        in
                        Pervasives.output_string tmpl__channel string
                    end;
                    Pervasives.output_string tmpl__channel ")\n";
                    Pervasives.output_string tmpl__channel "            (Dbf_sql_misc.unopt row.(";
                    begin
                      let string = (string_of_int (idx))
                        in
                        Pervasives.output_string tmpl__channel string
                    end;
                    Pervasives.output_string tmpl__channel " + offset)) ;\n";
                    Pervasives.output_string tmpl__channel "        ";
                    
                    end;
                    Pervasives.output_string tmpl__channel "\n";
                    Pervasives.output_string tmpl__channel "          "
                  end;
                  Pervasives.output_string tmpl__channel "\n";
                  Pervasives.output_string tmpl__channel "          "
                  done;
              end;
              Pervasives.output_string tmpl__channel "\n";
              Pervasives.output_string tmpl__channel "          }\n";
              Pervasives.output_string tmpl__channel "\n";
              Pervasives.output_string tmpl__channel "    ";
              if (table.ta_logged) then begin
                Pervasives.output_string tmpl__channel "\n";
                Pervasives.output_string tmpl__channel "    let drop_log = fun db ->\n";
                Pervasives.output_string tmpl__channel "      ignore (Sql.exec db \"DROP TABLE ";
                begin
                  let string = (table_name)
                    in
                    Pervasives.output_string tmpl__channel string
                end;
                Pervasives.output_string tmpl__channel "\")\n";
                Pervasives.output_string tmpl__channel "    ";
                
                end;
                Pervasives.output_string tmpl__channel "\n";
                Pervasives.output_string tmpl__channel "\n";
                Pervasives.output_string tmpl__channel "    let drop = fun db ->\n";
                Pervasives.output_string tmpl__channel "      ignore (Sql.exec db \"DROP TABLE ";
                begin
                  let string = (log_table_name)
                    in
                    Pervasives.output_string tmpl__channel string
                end;
                Pervasives.output_string tmpl__channel "\")\n";
                Pervasives.output_string tmpl__channel "      ";
                if (table.ta_logged) then begin
                  Pervasives.output_string tmpl__channel "; drop_log db";
                  
                  end;
                  Pervasives.output_string tmpl__channel "\n";
                  Pervasives.output_string tmpl__channel "\n";
                  Pervasives.output_string tmpl__channel "    ";
                  if (table.ta_logged) then begin
                    Pervasives.output_string tmpl__channel "\n";
                    Pervasives.output_string tmpl__channel "    let create_log = fun db ->\n";
                    Pervasives.output_string tmpl__channel "      let decls = Printf.sprintf \"%s,%s,%s,%s\"\n";
                    Pervasives.output_string tmpl__channel "          \"log_who int not null\"\n";
                    Pervasives.output_string tmpl__channel "          \"log_date double not null\"\n";
                    Pervasives.output_string tmpl__channel "          \"log_action tinyint not null\"\n";
                    Pervasives.output_string tmpl__channel "          log_sql_columns_decls\n";
                    Pervasives.output_string tmpl__channel "      in\n";
                    Pervasives.output_string tmpl__channel "      let q = Printf.sprintf \"CREATE TABLE ";
                    begin
                      let string = (log_table_name)
                        in
                        Pervasives.output_string tmpl__channel string
                    end;
                    Pervasives.output_string tmpl__channel " ( %s )\" decls in\n";
                    Pervasives.output_string tmpl__channel "      ignore (Sql.exec db q)\n";
                    Pervasives.output_string tmpl__channel "    ";
                    
                    end;
                    Pervasives.output_string tmpl__channel "\n";
                    Pervasives.output_string tmpl__channel "\n";
                    Pervasives.output_string tmpl__channel "    let create = fun db ->\n";
                    Pervasives.output_string tmpl__channel "      let create_table = fun () ->\n";
                    Pervasives.output_string tmpl__channel "        ignore (\n";
                    Pervasives.output_string tmpl__channel "        Sql.exec db\n";
                    Pervasives.output_string tmpl__channel "          (Printf.sprintf\n";
                    Pervasives.output_string tmpl__channel "             \"CREATE TABLE ";
                    begin
                      let string = (table_name)
                        in
                        Pervasives.output_string tmpl__channel string
                    end;
                    Pervasives.output_string tmpl__channel " ( %s )\"\n";
                    Pervasives.output_string tmpl__channel "             sql_columns_decls)\n";
                    Pervasives.output_string tmpl__channel "       )\n";
                    Pervasives.output_string tmpl__channel "          ";
                    begin
                      List.iter
                        (fun idx -> begin
                          if (idx.SQL_db.idx_name <> ""then begin
                            Pervasives.output_string tmpl__channel "\n";
                            Pervasives.output_string tmpl__channel "      and create_index_";
                            begin
                              let string = (idx_name idx)
                                in
                                Pervasives.output_string tmpl__channel string
                            end;
                            Pervasives.output_string tmpl__channel " = fun () ->\n";
                            Pervasives.output_string tmpl__channel "        ignore (\n";
                            Pervasives.output_string tmpl__channel "        Sql.exec db\n";
                            Pervasives.output_string tmpl__channel "          (\"CREATE ";
                            if (idx.idx_unique) then begin
                              Pervasives.output_string tmpl__channel "UNIQUE";
                              
                              end;
                              Pervasives.output_string tmpl__channel " INDEX \" ^\n";
                              Pervasives.output_string tmpl__channel "           \"";
                              begin
                                let string = (idx_name idx)
                                  in
                                  Pervasives.output_string tmpl__channel string
                              end;
                              Pervasives.output_string tmpl__channel " ON ";
                              begin
                                let string = (table_name)
                                  in
                                  Pervasives.output_string tmpl__channel string
                              end;
                              Pervasives.output_string tmpl__channel " \" ^\n";
                              Pervasives.output_string tmpl__channel "           \"( ";
                              begin
                                let string = (idx_sql_columns idx)
                                  in
                                  Pervasives.output_string tmpl__channel string
                              end;
                              Pervasives.output_string tmpl__channel " )\")\n";
                              Pervasives.output_string tmpl__channel "       )\n";
                              Pervasives.output_string tmpl__channel "          ";
                              
                              end;
                              end)
                            indexes
                        end;
                        Pervasives.output_string tmpl__channel "\n";
                        Pervasives.output_string tmpl__channel "      in begin\n";
                        Pervasives.output_string tmpl__channel "        create_table ();\n";
                        Pervasives.output_string tmpl__channel "        ";
                        if (table.ta_logged) then begin
                          Pervasives.output_string tmpl__channel "create_log db;";
                          
                          end;
                          Pervasives.output_string tmpl__channel "\n";
                          Pervasives.output_string tmpl__channel "        ";
                          begin
                            List.iter
                              (fun index -> begin
                                if (index.SQL_db.idx_name <> ""then begin
                                  Pervasives.output_string tmpl__channel "\n";
                                  Pervasives.output_string tmpl__channel "          create_index_";
                                  begin
                                    let string = (idx_name index)
                                      in
                                      Pervasives.output_string tmpl__channel string
                                  end;
                                  Pervasives.output_string tmpl__channel " ();\n";
                                  Pervasives.output_string tmpl__channel "        ";
                                  
                                  end;
                                  end)
                                indexes
                            end;
                            Pervasives.output_string tmpl__channel "\n";
                            Pervasives.output_string tmpl__channel "      end\n";
                            Pervasives.output_string tmpl__channel "\n";
                            Pervasives.output_string tmpl__channel "    let select_where = fun db ?(table_alias=\"\") condition ->\n";
                            Pervasives.output_string tmpl__channel "      let query =\n";
                            Pervasives.output_string tmpl__channel "        Printf.sprintf\n";
                            Pervasives.output_string tmpl__channel "          \"SELECT ";
                            begin
                              let string = (sql_columns)
                                in
                                Pervasives.output_string tmpl__channel string
                            end;
                            Pervasives.output_string tmpl__channel " FROM ";
                            begin
                              let string = (table_name)
                                in
                                Pervasives.output_string tmpl__channel string
                            end;
                            Pervasives.output_string tmpl__channel " %s %s\"\n";
                            Pervasives.output_string tmpl__channel "          table_alias\n";
                            Pervasives.output_string tmpl__channel "          (match Dbf_sql_misc.no_blanks condition with\n";
                            Pervasives.output_string tmpl__channel "            \"\" -> \"\"\n";
                            Pervasives.output_string tmpl__channel "          | _ -> Printf.sprintf \"WHERE %s\" condition\n";
                            Pervasives.output_string tmpl__channel "          )\n";
                            Pervasives.output_string tmpl__channel "      in\n";
                            Pervasives.output_string tmpl__channel "      Sql.exec db query\n";
                            Pervasives.output_string tmpl__channel "\n";
                            Pervasives.output_string tmpl__channel "    let fetch = fun result ->\n";
                            Pervasives.output_string tmpl__channel "      match Sql.fetch_row result with\n";
                            Pervasives.output_string tmpl__channel "      | None                    -> None\n";
                            Pervasives.output_string tmpl__channel "      | Some (Sql.FR_Array row) -> Some (row_as_record row)\n";
                            Pervasives.output_string tmpl__channel "      | _                       -> Dbf_sql_misc.ie ()\n";
                            Pervasives.output_string tmpl__channel "\n";
                            Pervasives.output_string tmpl__channel "    let fetch_all = fun result ->\n";
                            Pervasives.output_string tmpl__channel "      let to_array = function\n";
                            Pervasives.output_string tmpl__channel "        | Sql.FR_Array a -> a\n";
                            Pervasives.output_string tmpl__channel "        | _ -> Dbf_sql_misc.ie ()\n";
                            Pervasives.output_string tmpl__channel "      in\n";
                            Pervasives.output_string tmpl__channel "      Sql.map result ~f:(fun r -> row_as_record (to_array r))\n";
                            Pervasives.output_string tmpl__channel "\n";
                            Pervasives.output_string tmpl__channel "    let select = fun db ";
                            begin
                              List.iter
                                (fun col -> begin
                                  Pervasives.output_string tmpl__channel "?";
                                  begin
                                    let string = (col.col_name)
                                      in
                                      Pervasives.output_string tmpl__channel string
                                  end;
                                  Pervasives.output_string tmpl__channel " "end)
                                columns
                            end;
                            Pervasives.output_string tmpl__channel "() ->\n";
                            Pervasives.output_string tmpl__channel "      let cond = condition_of_args\n";
                            Pervasives.output_string tmpl__channel "          ";
                            begin
                              List.iter
                                (fun col -> begin
                                  Pervasives.output_string tmpl__channel "?";
                                  begin
                                    let string = (col.col_name)
                                      in
                                      Pervasives.output_string tmpl__channel string
                                  end;
                                  Pervasives.output_string tmpl__channel " "end)
                                columns
                            end;
                            Pervasives.output_string tmpl__channel "()\n";
                            Pervasives.output_string tmpl__channel "      in\n";
                            Pervasives.output_string tmpl__channel "      match select_where db cond with\n";
                            Pervasives.output_string tmpl__channel "      | Sql.R_Ok\n";
                            Pervasives.output_string tmpl__channel "      | Sql.R_Empty -> []\n";
                            Pervasives.output_string tmpl__channel "      | Sql.R_Fetch cursor -> fetch_all cursor\n";
                            Pervasives.output_string tmpl__channel "\n";
                            Pervasives.output_string tmpl__channel "    ";
                            if (table.ta_logged) then begin
                              Pervasives.output_string tmpl__channel "\n";
                              Pervasives.output_string tmpl__channel "    let log_row_as_record = fun ?(offset = 0) row ->\n";
                              Pervasives.output_string tmpl__channel "      let t = row_as_record ~offset: (offset+3) row in\n";
                              Pervasives.output_string tmpl__channel "      (Sql.sql2int (Dbf_sql_misc.unopt row.(0)),\n";
                              Pervasives.output_string tmpl__channel "       Sql.sql2float (Dbf_sql_misc.unopt row.(1)),\n";
                              Pervasives.output_string tmpl__channel "       Dbf_sql_misc.action_of_string (Dbf_sql_misc.unopt row.(2)),\n";
                              Pervasives.output_string tmpl__channel "       t\n";
                              Pervasives.output_string tmpl__channel "      )\n";
                              Pervasives.output_string tmpl__channel "\n";
                              Pervasives.output_string tmpl__channel "    let log_fetch_all = fun result ->\n";
                              Pervasives.output_string tmpl__channel "      let to_array = function\n";
                              Pervasives.output_string tmpl__channel "        | Sql.FR_Array a -> a\n";
                              Pervasives.output_string tmpl__channel "        | _ -> Dbf_sql_misc.ie ()\n";
                              Pervasives.output_string tmpl__channel "      in\n";
                              Pervasives.output_string tmpl__channel "      Sql.map result ~f:(fun r -> log_row_as_record (to_array r))\n";
                              Pervasives.output_string tmpl__channel "\n";
                              Pervasives.output_string tmpl__channel "    let select_log_where = fun db ?(table_alias=\"\") condition ->\n";
                              Pervasives.output_string tmpl__channel "      let query =\n";
                              Pervasives.output_string tmpl__channel "        Printf.sprintf\n";
                              Pervasives.output_string tmpl__channel "          \"SELECT log_who, log_date, log_action, ";
                              begin
                                let string = (sql_columns)
                                  in
                                  Pervasives.output_string tmpl__channel string
                              end;
                              Pervasives.output_string tmpl__channel " FROM ";
                              begin
                                let string = (log_table_name)
                                  in
                                  Pervasives.output_string tmpl__channel string
                              end;
                              Pervasives.output_string tmpl__channel " %s %s\"\n";
                              Pervasives.output_string tmpl__channel "          table_alias\n";
                              Pervasives.output_string tmpl__channel "          (match Dbf_sql_misc.no_blanks condition with\n";
                              Pervasives.output_string tmpl__channel "            \"\" -> \"\"\n";
                              Pervasives.output_string tmpl__channel "          | _ -> Printf.sprintf \"WHERE %s\" condition\n";
                              Pervasives.output_string tmpl__channel "          )\n";
                              Pervasives.output_string tmpl__channel "      in\n";
                              Pervasives.output_string tmpl__channel "      Sql.exec db query\n";
                              Pervasives.output_string tmpl__channel "\n";
                              Pervasives.output_string tmpl__channel "    let select_log = fun db ";
                              begin
                                List.iter
                                  (fun col -> begin
                                    Pervasives.output_string tmpl__channel "?";
                                    begin
                                      let string = (col.col_name)
                                        in
                                        Pervasives.output_string tmpl__channel string
                                    end;
                                    Pervasives.output_string tmpl__channel " ";
                                    end)
                                  columns
                              end;
                              Pervasives.output_string tmpl__channel "() ->\n";
                              Pervasives.output_string tmpl__channel "      let cond = condition_of_args\n";
                              Pervasives.output_string tmpl__channel "          ";
                              begin
                                List.iter
                                  (fun col -> begin
                                    Pervasives.output_string tmpl__channel "?";
                                    begin
                                      let string = (col.col_name)
                                        in
                                        Pervasives.output_string tmpl__channel string
                                    end;
                                    Pervasives.output_string tmpl__channel " ";
                                    end)
                                  columns
                              end;
                              Pervasives.output_string tmpl__channel "()\n";
                              Pervasives.output_string tmpl__channel "      in\n";
                              Pervasives.output_string tmpl__channel "      match select_log_where db cond with\n";
                              Pervasives.output_string tmpl__channel "      | Sql.R_Ok\n";
                              Pervasives.output_string tmpl__channel "      | Sql.R_Empty -> []\n";
                              Pervasives.output_string tmpl__channel "      | Sql.R_Fetch cursor -> log_fetch_all cursor\n";
                              Pervasives.output_string tmpl__channel "\n";
                              Pervasives.output_string tmpl__channel "    let insert_log = fun db log_action log_date ->\n";
                              Pervasives.output_string tmpl__channel "      let log_who = !log_who () in\n";
                              Pervasives.output_string tmpl__channel "      fun t ->\n";
                              Pervasives.output_string tmpl__channel "        let columns =\n";
                              Pervasives.output_string tmpl__channel "          opt_values_of_args\n";
                              Pervasives.output_string tmpl__channel "            ";
                              begin
                                List.iter
                                  (fun c -> begin
                                    begin
                                      let string = ("~" ^ (col_name c) ^ ": t." ^ (col_name c))
                                        in
                                        Pervasives.output_string tmpl__channel string
                                    end;
                                    end)
                                  columns
                              end;
                              Pervasives.output_string tmpl__channel "\n";
                              Pervasives.output_string tmpl__channel "          ()\n";
                              Pervasives.output_string tmpl__channel "        in\n";
                              Pervasives.output_string tmpl__channel "        let columns = List.fold_left\n";
                              Pervasives.output_string tmpl__channel "            (fun acc opt ->\n";
                              Pervasives.output_string tmpl__channel "              match opt with\n";
                              Pervasives.output_string tmpl__channel "                None -> acc\n";
                              Pervasives.output_string tmpl__channel "              | Some (None,name) -> (\"NULL\",name)::acc\n";
                              Pervasives.output_string tmpl__channel "              | Some (Some v,name) -> (v,name)::acc\n";
                              Pervasives.output_string tmpl__channel "            )\n";
                              Pervasives.output_string tmpl__channel "            []\n";
                              Pervasives.output_string tmpl__channel "            columns\n";
                              Pervasives.output_string tmpl__channel "        in\n";
                              Pervasives.output_string tmpl__channel "        let columns =\n";
                              Pervasives.output_string tmpl__channel "          (Sql.escape_value (Sql.int2sql log_who), \"log_who\") ::\n";
                              Pervasives.output_string tmpl__channel "          (Sql.escape_value (Sql.float2sql log_date), \"log_date\") ::\n";
                              Pervasives.output_string tmpl__channel "          (Sql.escape_value (Dbf_sql_misc.string_of_action log_action), \"log_action\") ::\n";
                              Pervasives.output_string tmpl__channel "          columns\n";
                              Pervasives.output_string tmpl__channel "        in\n";
                              Pervasives.output_string tmpl__channel "        let query =\n";
                              Pervasives.output_string tmpl__channel "          Printf.sprintf \"INSERT INTO ";
                              begin
                                let string = (log_table_name)
                                  in
                                  Pervasives.output_string tmpl__channel string
                              end;
                              Pervasives.output_string tmpl__channel " (%s) VALUES (%s)\"\n";
                              Pervasives.output_string tmpl__channel "            (Dbf_sql_misc.join ~sep:\", \" ~to_string:snd columns)\n";
                              Pervasives.output_string tmpl__channel "            (Dbf_sql_misc.join ~sep:\", \" ~to_string:fst columns)\n";
                              Pervasives.output_string tmpl__channel "        in\n";
                              Pervasives.output_string tmpl__channel "        ignore (Sql.exec db query)\n";
                              Pervasives.output_string tmpl__channel "    ";
                              
                              end;
                              Pervasives.output_string tmpl__channel "\n";
                              Pervasives.output_string tmpl__channel "\n";
                              Pervasives.output_string tmpl__channel "    let delete_where = fun db ?(table_alias=\"\") condition ->\n";
                              Pervasives.output_string tmpl__channel "      ";
                              if (table.ta_logged) then begin
                                Pervasives.output_string tmpl__channel "\n";
                                Pervasives.output_string tmpl__channel "      let impacted = match select_where db ~table_alias condition with\n";
                                Pervasives.output_string tmpl__channel "        | Sql.R_Ok\n";
                                Pervasives.output_string tmpl__channel "        | Sql.R_Empty -> []\n";
                                Pervasives.output_string tmpl__channel "        | Sql.R_Fetch cursor -> fetch_all cursor\n";
                                Pervasives.output_string tmpl__channel "      in\n";
                                Pervasives.output_string tmpl__channel "      ";
                                
                                end;
                                Pervasives.output_string tmpl__channel "\n";
                                Pervasives.output_string tmpl__channel "      let query =\n";
                                Pervasives.output_string tmpl__channel "        Printf.sprintf\n";
                                Pervasives.output_string tmpl__channel "          \"DELETE FROM ";
                                begin
                                  let string = (table_name)
                                    in
                                    Pervasives.output_string tmpl__channel string
                                end;
                                Pervasives.output_string tmpl__channel " %s %s\"\n";
                                Pervasives.output_string tmpl__channel "          table_alias\n";
                                Pervasives.output_string tmpl__channel "          (match Dbf_sql_misc.no_blanks condition with\n";
                                Pervasives.output_string tmpl__channel "            \"\" -> \"\"\n";
                                Pervasives.output_string tmpl__channel "          | _ -> Printf.sprintf \"WHERE %s\" condition\n";
                                Pervasives.output_string tmpl__channel "          )\n";
                                Pervasives.output_string tmpl__channel "      in\n";
                                Pervasives.output_string tmpl__channel "      ignore (Sql.exec db query);\n";
                                Pervasives.output_string tmpl__channel "      ";
                                if (table.ta_logged) then begin
                                  Pervasives.output_string tmpl__channel "\n";
                                  Pervasives.output_string tmpl__channel "      List.iter (insert_log db Dbf_sql_misc.Delete (Unix.time())) impacted;\n";
                                  Pervasives.output_string tmpl__channel "      ";
                                  
                                  end;
                                  Pervasives.output_string tmpl__channel "\n";
                                  Pervasives.output_string tmpl__channel "      ()\n";
                                  Pervasives.output_string tmpl__channel "\n";
                                  Pervasives.output_string tmpl__channel "    let delete = fun db ";
                                  begin
                                    let string = (args_of_columns true true columns)
                                      in
                                      Pervasives.output_string tmpl__channel string
                                  end;
                                  Pervasives.output_string tmpl__channel " () ->\n";
                                  Pervasives.output_string tmpl__channel "      let cond = condition_of_args\n";
                                  Pervasives.output_string tmpl__channel "          ";
                                  begin
                                    List.iter
                                      (fun col -> begin
                                        Pervasives.output_string tmpl__channel "?";
                                        begin
                                          let string = (col.col_name)
                                            in
                                            Pervasives.output_string tmpl__channel string
                                        end;
                                        Pervasives.output_string tmpl__channel " ";
                                        end)
                                      columns
                                  end;
                                  Pervasives.output_string tmpl__channel "()\n";
                                  Pervasives.output_string tmpl__channel "      in\n";
                                  Pervasives.output_string tmpl__channel "      delete_where db cond\n";
                                  Pervasives.output_string tmpl__channel "\n";
                                  Pervasives.output_string tmpl__channel "    let update = fun db ";
                                  begin
                                    List.iter
                                      (fun col -> begin
                                        Pervasives.output_string tmpl__channel "\n";
                                        Pervasives.output_string tmpl__channel "      ?key_";
                                        begin
                                          let string = (col.col_name)
                                            in
                                            Pervasives.output_string tmpl__channel string
                                        end;
                                        Pervasives.output_string tmpl__channel "\n";
                                        Pervasives.output_string tmpl__channel "      ";
                                        end)
                                      columns
                                  end;
                                  begin
                                    let string = (args_of_columns true true columns)
                                      in
                                      Pervasives.output_string tmpl__channel string
                                  end;
                                  Pervasives.output_string tmpl__channel " () ->\n";
                                  Pervasives.output_string tmpl__channel "        let cond = condition_of_args\n";
                                  Pervasives.output_string tmpl__channel "            ";
                                  begin
                                    List.iter
                                      (fun col -> begin
                                        Pervasives.output_string tmpl__channel "?";
                                        begin
                                          let string = (col.col_name)
                                            in
                                            Pervasives.output_string tmpl__channel string
                                        end;
                                        Pervasives.output_string tmpl__channel ": key_";
                                        begin
                                          let string = (col.col_name)
                                            in
                                            Pervasives.output_string tmpl__channel string
                                        end;
                                        Pervasives.output_string tmpl__channel " ";
                                        end)
                                      columns
                                  end;
                                  Pervasives.output_string tmpl__channel "()\n";
                                  Pervasives.output_string tmpl__channel "        and out_columns =\n";
                                  Pervasives.output_string tmpl__channel "          opt_values_of_args\n";
                                  Pervasives.output_string tmpl__channel "            ";
                                  begin
                                    List.iter
                                      (fun c -> begin
                                        begin
                                          let string = ("?" ^ (col_name c)  ^ " ")
                                            in
                                            Pervasives.output_string tmpl__channel string
                                        end;
                                        end)
                                      columns
                                  end;
                                  Pervasives.output_string tmpl__channel "\n";
                                  Pervasives.output_string tmpl__channel "          ()\n";
                                  Pervasives.output_string tmpl__channel "        in\n";
                                  Pervasives.output_string tmpl__channel "        ";
                                  if (table.ta_logged) then begin
                                    Pervasives.output_string tmpl__channel "\n";
                                    Pervasives.output_string tmpl__channel "        let impacted = match select_where db cond with\n";
                                    Pervasives.output_string tmpl__channel "        | Sql.R_Ok\n";
                                    Pervasives.output_string tmpl__channel "        | Sql.R_Empty -> []\n";
                                    Pervasives.output_string tmpl__channel "        | Sql.R_Fetch cursor -> fetch_all cursor\n";
                                    Pervasives.output_string tmpl__channel "        in\n";
                                    Pervasives.output_string tmpl__channel "        ";
                                    
                                    end;
                                    Pervasives.output_string tmpl__channel "\n";
                                    Pervasives.output_string tmpl__channel "        let query =\n";
                                    Pervasives.output_string tmpl__channel "          Printf.sprintf \"UPDATE ";
                                    begin
                                      let string = (table_name)
                                        in
                                        Pervasives.output_string tmpl__channel string
                                    end;
                                    Pervasives.output_string tmpl__channel " SET %s %s\"\n";
                                    Pervasives.output_string tmpl__channel "            (Dbf_sql_misc.join_opt\n";
                                    Pervasives.output_string tmpl__channel "               ~sep:\" , \"\n";
                                    Pervasives.output_string tmpl__channel "               ~to_string:\n";
                                    Pervasives.output_string tmpl__channel "               (function\n";
                                    Pervasives.output_string tmpl__channel "                 | (None, name) -> Printf.sprintf \"%s = NULL\" name\n";
                                    Pervasives.output_string tmpl__channel "                 | (Some value, name) ->\n";
                                    Pervasives.output_string tmpl__channel "                     Printf.sprintf \"%s = %s\" name value\n";
                                    Pervasives.output_string tmpl__channel "               )\n";
                                    Pervasives.output_string tmpl__channel "               out_columns\n";
                                    Pervasives.output_string tmpl__channel "            )\n";
                                    Pervasives.output_string tmpl__channel "            (match Dbf_sql_misc.no_blanks cond with\n";
                                    Pervasives.output_string tmpl__channel "              \"\" -> \"\"\n";
                                    Pervasives.output_string tmpl__channel "            | _ -> Printf.sprintf \"WHERE %s\" cond\n";
                                    Pervasives.output_string tmpl__channel "            )\n";
                                    Pervasives.output_string tmpl__channel "        in\n";
                                    Pervasives.output_string tmpl__channel "        ignore (Sql.exec db query);\n";
                                    Pervasives.output_string tmpl__channel "        ";
                                    if (table.ta_logged) then begin
                                      Pervasives.output_string tmpl__channel "\n";
                                      Pervasives.output_string tmpl__channel "        List.iter (insert_log db Dbf_sql_misc.Update (Unix.time())) impacted;\n";
                                      Pervasives.output_string tmpl__channel "        ";
                                      
                                      end;
                                      Pervasives.output_string tmpl__channel "\n";
                                      Pervasives.output_string tmpl__channel "        ()\n";
                                      Pervasives.output_string tmpl__channel "\n";
                                      Pervasives.output_string tmpl__channel "    let insert = fun db ";
                                      begin
                                        let string = (args_of_columns true true columns)
                                          in
                                          Pervasives.output_string tmpl__channel string
                                      end;
                                      Pervasives.output_string tmpl__channel " () ->\n";
                                      Pervasives.output_string tmpl__channel "      let selected_columns =\n";
                                      Pervasives.output_string tmpl__channel "        opt_values_of_args\n";
                                      Pervasives.output_string tmpl__channel "          ";
                                      begin
                                        List.iter
                                          (fun c -> begin
                                            begin
                                              let string = ("?" ^ (col_name c) ^ " ")
                                                in
                                                Pervasives.output_string tmpl__channel string
                                            end;
                                            end)
                                          columns
                                      end;
                                      Pervasives.output_string tmpl__channel "\n";
                                      Pervasives.output_string tmpl__channel "        ()\n";
                                      Pervasives.output_string tmpl__channel "      in\n";
                                      Pervasives.output_string tmpl__channel "      let selected_columns = List.map\n";
                                      Pervasives.output_string tmpl__channel "          (function None -> None\n";
                                      Pervasives.output_string tmpl__channel "            | Some (None,name) -> Some (\"NULL\",name)\n";
                                      Pervasives.output_string tmpl__channel "            | Some (Some v,name) -> Some (v,name)\n";
                                      Pervasives.output_string tmpl__channel "          )\n";
                                      Pervasives.output_string tmpl__channel "          selected_columns\n";
                                      Pervasives.output_string tmpl__channel "      in\n";
                                      Pervasives.output_string tmpl__channel "      let query =\n";
                                      Pervasives.output_string tmpl__channel "        Printf.sprintf \"INSERT INTO ";
                                      begin
                                        let string = (table_name)
                                          in
                                          Pervasives.output_string tmpl__channel string
                                      end;
                                      Pervasives.output_string tmpl__channel " (%s) VALUES (%s)\"\n";
                                      Pervasives.output_string tmpl__channel "          (Dbf_sql_misc.join_opt ~sep:\", \" ~to_string:snd selected_columns)\n";
                                      Pervasives.output_string tmpl__channel "          (Dbf_sql_misc.join_opt ~sep:\", \" ~to_string:fst selected_columns)\n";
                                      Pervasives.output_string tmpl__channel "      in\n";
                                      Pervasives.output_string tmpl__channel "      ignore (Sql.exec db query);\n";
                                      Pervasives.output_string tmpl__channel "      ";
                                      if (table.ta_logged) then begin
                                        Pervasives.output_string tmpl__channel "\n";
                                        Pervasives.output_string tmpl__channel "      let selected_columns =\n";
                                        Pervasives.output_string tmpl__channel "        (Some (Sql.escape_value (Sql.int2sql (!log_who())), \"log_who\")) ::\n";
                                        Pervasives.output_string tmpl__channel "        (Some (Sql.escape_value (Sql.float2sql (Unix.time())), \"log_date\")) ::\n";
                                        Pervasives.output_string tmpl__channel "        (Some (Sql.escape_value (Dbf_sql_misc.string_of_action Dbf_sql_misc.Insert), \"log_action\")) ::\n";
                                        Pervasives.output_string tmpl__channel "        selected_columns\n";
                                        Pervasives.output_string tmpl__channel "      in\n";
                                        Pervasives.output_string tmpl__channel "      let query =\n";
                                        Pervasives.output_string tmpl__channel "        Printf.sprintf \"INSERT INTO ";
                                        begin
                                          let string = (log_table_name)
                                            in
                                            Pervasives.output_string tmpl__channel string
                                        end;
                                        Pervasives.output_string tmpl__channel " (%s) VALUES (%s)\"\n";
                                        Pervasives.output_string tmpl__channel "          (Dbf_sql_misc.join_opt ~sep:\", \" ~to_string:snd selected_columns)\n";
                                        Pervasives.output_string tmpl__channel "          (Dbf_sql_misc.join_opt ~sep:\", \" ~to_string:fst selected_columns)\n";
                                        Pervasives.output_string tmpl__channel "      in\n";
                                        Pervasives.output_string tmpl__channel "      ignore (Sql.exec db query);\n";
                                        Pervasives.output_string tmpl__channel "      ";
                                        
                                        end;
                                        Pervasives.output_string tmpl__channel "\n";
                                        Pervasives.output_string tmpl__channel "      ()\n";
                                        Pervasives.output_string tmpl__channel "\n";
                                        Pervasives.output_string tmpl__channel "  (*=======================================\\\n";
                                        Pervasives.output_string tmpl__channel "     | Insertion/update/deletion with indexes |\n";
                                        Pervasives.output_string tmpl__channel "     \\=======================================*)\n";
                                        Pervasives.output_string tmpl__channel "        ";
                                        begin
                                          List.iter
                                            (fun idx -> begin
                                              if (idx.idx_unique) then begin
                                                Pervasives.output_string tmpl__channel "\n";
                                                Pervasives.output_string tmpl__channel "          ";
                                                begin 
          let (in_idx, out_idx) =
            List.partition (fun c -> List.memq c idx.idx_columns) columns
          and module_name =
            if idx.SQL_db.idx_name = "" then
              "PKey"
            else
              Printf.sprintf "I_%s" (idx_name idx)
        
                                                  in
                                                  Pervasives.output_string tmpl__channel "\n";
                                                  Pervasives.output_string tmpl__channel "    module ";
                                                  begin
                                                    let string = (module_name)
                                                      in
                                                      Pervasives.output_string tmpl__channel string
                                                  end;
                                                  Pervasives.output_string tmpl__channel " =\n";
                                                  Pervasives.output_string tmpl__channel "      struct\n";
                                                  Pervasives.output_string tmpl__channel "        let delete = fun db ";
                                                  begin
                                                    let string = (args_of_columns false false in_idx)
                                                      in
                                                      Pervasives.output_string tmpl__channel string
                                                  end;
                                                  Pervasives.output_string tmpl__channel " ->\n";
                                                  Pervasives.output_string tmpl__channel "          let condition =\n";
                                                  Pervasives.output_string tmpl__channel "            condition_of_args ";
                                                  begin
                                                    List.iter
                                                      (fun c -> begin
                                                        Pervasives.output_string tmpl__channel "~";
                                                        begin
                                                          let string = (col_name c)
                                                            in
                                                            Pervasives.output_string tmpl__channel string
                                                        end;
                                                        Pervasives.output_string tmpl__channel " ";
                                                        end)
                                                      in_idx
                                                  end;
                                                  Pervasives.output_string tmpl__channel " ()\n";
                                                  Pervasives.output_string tmpl__channel "          in\n";
                                                  Pervasives.output_string tmpl__channel "          delete_where db condition\n";
                                                  Pervasives.output_string tmpl__channel "\n";
                                                  Pervasives.output_string tmpl__channel "        let search = fun db ";
                                                  begin
                                                    let string = (args_of_columns false false in_idx)
                                                      in
                                                      Pervasives.output_string tmpl__channel string
                                                  end;
                                                  Pervasives.output_string tmpl__channel " ->\n";
                                                  Pervasives.output_string tmpl__channel "          let condition =\n";
                                                  Pervasives.output_string tmpl__channel "            (condition_of_args ";
                                                  begin
                                                    List.iter
                                                      (fun c -> begin
                                                        Pervasives.output_string tmpl__channel "~";
                                                        begin
                                                          let string = (col_name c)
                                                            in
                                                            Pervasives.output_string tmpl__channel string
                                                        end;
                                                        Pervasives.output_string tmpl__channel " ";
                                                        end)
                                                      in_idx
                                                  end;
                                                  Pervasives.output_string tmpl__channel " ())\n";
                                                  Pervasives.output_string tmpl__channel "          in\n";
                                                  Pervasives.output_string tmpl__channel "          match select_where db condition with\n";
                                                  Pervasives.output_string tmpl__channel "          | Sql.R_Fetch r -> fetch r\n";
                                                  Pervasives.output_string tmpl__channel "          | _             -> None\n";
                                                  Pervasives.output_string tmpl__channel "\n";
                                                  Pervasives.output_string tmpl__channel "                ";
                                                  if (out_idx <> []) then begin
                                                    Pervasives.output_string tmpl__channel "\n";
                                                    Pervasives.output_string tmpl__channel "                  let update = fun db ";
                                                    begin
                                                      let string = (args_of_columns false false in_idx)
                                                        in
                                                        Pervasives.output_string tmpl__channel string
                                                    end;
                                                    Pervasives.output_string tmpl__channel "\n";
                                                    Pervasives.output_string tmpl__channel "                    ";
                                                    begin
                                                      let string = (args_of_columns true true out_idx)
                                                        in
                                                        Pervasives.output_string tmpl__channel string
                                                    end;
                                                    Pervasives.output_string tmpl__channel "\n";
                                                    Pervasives.output_string tmpl__channel "                    () ->\n";
                                                    Pervasives.output_string tmpl__channel "                      let in_columns =\n";
                                                    Pervasives.output_string tmpl__channel "                        [";
                                                    begin
                                                      List.iter
                                                        (fun c -> begin
                                                          Pervasives.output_string tmpl__channel "\n";
                                                          Pervasives.output_string tmpl__channel "                          (Sql.escape_value ((";
                                                          begin
                                                            let string = (c.col_ml2sql)
                                                              in
                                                              Pervasives.output_string tmpl__channel string
                                                          end;
                                                          Pervasives.output_string tmpl__channel ") ";
                                                          begin
                                                            let string = (col_name c)
                                                              in
                                                              Pervasives.output_string tmpl__channel string
                                                          end;
                                                          Pervasives.output_string tmpl__channel "),\n";
                                                          Pervasives.output_string tmpl__channel "                           \"";
                                                          begin
                                                            let string = (String.escaped (col_name c))
                                                              in
                                                              Pervasives.output_string tmpl__channel string
                                                          end;
                                                          Pervasives.output_string tmpl__channel "\") ;\n";
                                                          Pervasives.output_string tmpl__channel "                          ";
                                                          end)
                                                        in_idx
                                                    end;
                                                    Pervasives.output_string tmpl__channel "]\n";
                                                    Pervasives.output_string tmpl__channel "                      and out_columns =\n";
                                                    Pervasives.output_string tmpl__channel "                        opt_values_of_args\n";
                                                    Pervasives.output_string tmpl__channel "                          ";
                                                    begin
                                                      List.iter
                                                        (fun c -> begin
                                                          begin
                                                            let string = ("?" ^ (col_name c)  ^ " ")
                                                              in
                                                              Pervasives.output_string tmpl__channel string
                                                          end;
                                                          end)
                                                        out_idx
                                                    end;
                                                    Pervasives.output_string tmpl__channel "\n";
                                                    Pervasives.output_string tmpl__channel "                        ()\n";
                                                    Pervasives.output_string tmpl__channel "                      in\n";
                                                    Pervasives.output_string tmpl__channel "                      let query =\n";
                                                    Pervasives.output_string tmpl__channel "                        Printf.sprintf \"UPDATE ";
                                                    begin
                                                      let string = (table_name)
                                                        in
                                                        Pervasives.output_string tmpl__channel string
                                                    end;
                                                    Pervasives.output_string tmpl__channel " SET %s WHERE %s\"\n";
                                                    Pervasives.output_string tmpl__channel "                          (Dbf_sql_misc.join_opt\n";
                                                    Pervasives.output_string tmpl__channel "                             ~sep:\" , \"\n";
                                                    Pervasives.output_string tmpl__channel "                             ~to_string:\n";
                                                    Pervasives.output_string tmpl__channel "                             (function\n";
                                                    Pervasives.output_string tmpl__channel "                               | (None, name) -> Printf.sprintf \"%s = NULL\" name\n";
                                                    Pervasives.output_string tmpl__channel "                               | (Some value, name) ->\n";
                                                    Pervasives.output_string tmpl__channel "                                   Printf.sprintf \"%s = %s\" name value\n";
                                                    Pervasives.output_string tmpl__channel "                             )\n";
                                                    Pervasives.output_string tmpl__channel "                             out_columns)\n";
                                                    Pervasives.output_string tmpl__channel "                          (Dbf_sql_misc.join\n";
                                                    Pervasives.output_string tmpl__channel "                             ~sep:\" AND \"\n";
                                                    Pervasives.output_string tmpl__channel "                             ~to_string:\n";
                                                    Pervasives.output_string tmpl__channel "                             (fun (value, name)-> Printf.sprintf \"%s = %s\" name value)\n";
                                                    Pervasives.output_string tmpl__channel "                             in_columns)\n";
                                                    Pervasives.output_string tmpl__channel "                      in\n";
                                                    Pervasives.output_string tmpl__channel "                      ignore (Sql.exec db query)\n";
                                                    Pervasives.output_string tmpl__channel "                        ";
                                                    
                                                    end;
                                                    Pervasives.output_string tmpl__channel "\n";
                                                    Pervasives.output_string tmpl__channel "\n";
                                                    Pervasives.output_string tmpl__channel "      end\n";
                                                    Pervasives.output_string tmpl__channel "        ";
                                                    
                                                  end;
                                                  
                                                  end;
                                                  end)
                                                indexes
                                            end;
                                            Pervasives.output_string tmpl__channel "\n";
                                            Pervasives.output_string tmpl__channel "\n";
                                            Pervasives.output_string tmpl__channel "  end\n";
                                            Pervasives.output_string tmpl__channel "    ";
                                            
                                          end;
                                          Pervasives.output_string tmpl__channel "\n";