diff options
Diffstat (limited to 'lib/analysers/chunk.ml')
-rw-r--r-- | lib/analysers/chunk.ml | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/lib/analysers/chunk.ml b/lib/analysers/chunk.ml new file mode 100644 index 0000000..2fa4808 --- /dev/null +++ b/lib/analysers/chunk.ml @@ -0,0 +1,102 @@ +(** The module allow to create fragment in the query which keep together the + binderd parameters and the text of the query.contents. + + This is used a lot in order to create the CTE, where you need the create + fragment used both in the main request and partially in the CTE itself. + + The content is mutable and all the functions are returning [unit]. *) + +type t = { + b : Buffer.t; + parameters : ImportCSV.DataType.t Queue.t; +} + +let create : unit -> t = + fun () -> { b = Buffer.create 16; parameters = Queue.create () } + +let create' : Buffer.t -> ImportCSV.DataType.t Queue.t -> t = + fun b parameters -> { b; parameters } + +(* Append the element from [tail] at the end of [head] + + Tail is destroyed during the operation. + *) +let append : head:t -> tail:t -> unit = + fun ~head ~tail -> + match Buffer.length tail.b with + | 0 -> () + | _ -> + Buffer.add_buffer head.b tail.b; + Queue.transfer tail.parameters head.parameters; + () + +(** Add a litteral string in the sequence *) +let add_string : t -> string -> unit = fun t v -> Buffer.add_string t.b v + +let copy : t -> t = + fun t -> + let b = Buffer.create 16 and parameters = Queue.copy t.parameters in + Buffer.add_buffer b t.b; + { b; parameters } + +let add_parameters : t -> ImportCSV.DataType.t Seq.t -> unit = + fun t p -> Queue.add_seq t.parameters p + +module Syntax = ImportConf.Syntax +module Table = ImportDataTypes.Table +module Q = ImportExpression.Query +open StdLabels + +(** Extract the informations from the dependancies. We get two informations here + : + + - the join query in order to load the data from the external column + - the column corresponding to the key in order to identify the missing links + later. *) +let join_external : conf:Syntax.t -> join_buffer:t -> Syntax.Extern.t -> unit = + fun ~conf ~join_buffer external_ -> + let extern_table = Table.name external_.target in + + let formatter = Format.formatter_of_buffer join_buffer.b in + Format.fprintf formatter "\nLEFT JOIN '%s' AS '%s' ON %t = %s" extern_table + external_.target.name + (Printers.prepare_key ~f:(fun f -> + let q = + Q.query_of_expression Q.BindParam f (Printers.path ~conf) + external_.intern_key + in + + add_parameters join_buffer (Queue.to_seq q))) + (Table.print_column external_.Syntax.Extern.target + ("key_" ^ external_.Syntax.Extern.target.name)); + + Format.pp_print_flush formatter () + +(** Create the from part of the query, adding all the required externals (even + when not required) + + SQLite is able to optimize the query and do not load the table not used in + the select clause. *) +let create_from_statement_of_chunck : + ?externals:Syntax.Extern.t list -> Syntax.t -> t -> unit = + fun ?externals conf c -> + let externals = Option.value externals ~default:conf.externals in + add_string c "\nFROM '"; + add_string c (Table.name conf.source); + add_string c "' AS '"; + add_string c conf.source.name; + add_string c "'"; + + (* Add the externals in the query *) + List.iter externals ~f:(join_external ~conf ~join_buffer:c) + +let add_expression : + conf:Syntax.t -> t -> ImportDataTypes.Path.t ImportExpression.T.t -> unit = + fun ~conf group expression -> + let formatter = Format.formatter_of_buffer group.b in + let queue = + ImportExpression.Query.query_of_expression ImportExpression.Query.BindParam + formatter (Printers.path ~conf) expression + in + Format.pp_print_flush formatter (); + add_parameters group (Queue.to_seq queue) |