123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552(**************************************************************************)(* Copyright (c) 2003 Christian Szegedy <csdontspam871@metamatix.org> *)(* *)(* Copyright (c) 2007 Jane Street Holding, LLC *)(* Author: Markus Mottl <markus.mottl@gmail.com> *)(* *)(* Permission is hereby granted, free of charge, to any person *)(* obtaining a copy of this software and associated documentation files *)(* (the "Software"), to deal in the Software without restriction, *)(* including without limitation the rights to use, copy, modify, merge, *)(* publish, distribute, sublicense, and/or sell copies of the Software, *)(* and to permit persons to whom the Software is furnished to do so, *)(* subject to the following conditions: *)(* *)(* The above copyright notice and this permission notice shall be *)(* included in all copies or substantial portions of the Software. *)(* *)(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, *)(* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES *)(* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND *)(* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS *)(* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN *)(* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN *)(* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE *)(* SOFTWARE. *)(**************************************************************************)openPrintfexceptionInternalErrorofstringexceptionErrorofstringexceptionRangeErrorofint*intexceptionDataTypeErrorofstringexceptionSqliteErrorofstringtypedbtypestmtmoduleRc=structtypeunknownexternalint_of_unknown:unknown->int="%identity"typet=|OK|ERROR|INTERNAL|PERM|ABORT|BUSY|LOCKED|NOMEM|READONLY|INTERRUPT|IOERR|CORRUPT|NOTFOUND|FULL|CANTOPEN|PROTOCOL|EMPTY|SCHEMA|TOOBIG|CONSTRAINT|MISMATCH|MISUSE|NOFLS|AUTH|FORMAT|RANGE|NOTADB|ROW|DONE|UNKNOWNofunknownletto_string=function|OK->"OK"|ERROR->"ERROR"|INTERNAL->"INTERNAL"|PERM->"PERM"|ABORT->"ABORT"|BUSY->"BUSY"|LOCKED->"LOCKED"|NOMEM->"NOMEM"|READONLY->"READONLY"|INTERRUPT->"INTERRUPT"|IOERR->"IOERR"|CORRUPT->"CORRUPT"|NOTFOUND->"NOTFOUND"|FULL->"FULL"|CANTOPEN->"CANTOPEN"|PROTOCOL->"PROTOCOL"|EMPTY->"EMPTY"|SCHEMA->"SCHEMA"|TOOBIG->"TOOBIG"|CONSTRAINT->"CONSTRAINT"|MISMATCH->"MISMATCH"|MISUSE->"MISUSE"|NOFLS->"NOLFS"|AUTH->"AUTH"|FORMAT->"FORMAT"|RANGE->"RANGE"|NOTADB->"NOTADB"|ROW->"ROW"|DONE->"DONE"|UNKNOWNn->sprintf"UNKNOWN %d"(int_of_unknownn)letis_success=functionOK|DONE->true|_->falseletcheckrc=ifnot(is_successrc)thenraise(SqliteError(to_stringrc))end(* Rc *)moduleData=structtypet=|NONE|NULL|INTofint64|FLOAToffloat|TEXTofstring|BLOBofstringletopt_text=functionSomes->TEXTs|None->NULLletopt_int=functionSomen->INT(Int64.of_intn)|None->NULLletopt_nativeint=function|Somen->INT(Int64.of_nativeintn)|None->NULLletopt_int32=functionSomen->INT(Int64.of_int32n)|None->NULLletopt_int64=functionSomen->INTn|None->NULLletopt_float=functionSomen->FLOATn|None->NULLletopt_bool=function|Somefalse->INTInt64.zero|Sometrue->INTInt64.one|None->NULL(* Exception-based type conversion *)letto_string_debug=function|NONE->"NONE"|NULL->"NULL"|INTi->sprintf"INT <%Ld>"i|FLOATf->sprintf"FLOAT <%f>"f|TEXTt->sprintf"TEXT <%S>"t|BLOBb->sprintf"BLOB <%d>"(String.lengthb)letdata_type_errortpdata=letgot=to_string_debugdatainraise(DataTypeError(Printf.sprintf"Expected %s but got %s"tpgot))letto_string_exn=function|TEXTs|BLOBs->s|data->data_type_error"TEXT or BLOB"dataletmin_int_as_int64=Int64.of_intmin_intletmax_int_as_int64=Int64.of_intmax_intletmin_nativeint_as_int64=Int64.of_nativeintNativeint.min_intletmax_nativeint_as_int64=Int64.of_nativeintNativeint.max_intletmin_int32_as_int64=Int64.of_int32Int32.min_intletmax_int32_as_int64=Int64.of_int32Int32.max_intletsafe_get_intn=ifn>max_int_as_int64thenfailwith(Printf.sprintf"Sqlite3.Data.safe_get_int: overflow: %Ld"n)elseifn<min_int_as_int64thenfailwith(Printf.sprintf"Sqlite3.Data.safe_get_int: underflow: %Ld"n)elseInt64.to_intnletsafe_get_nativeintn=ifn>max_nativeint_as_int64thenfailwith(Printf.sprintf"Sqlite3.Data.safe_get_nativeint: overflow: %Ld"n)elseifn<min_nativeint_as_int64thenfailwith(Printf.sprintf"Sqlite3.Data.safe_get_nativeint: underflow: %Ld"n)elseInt64.to_nativeintnletsafe_get_int32n=ifn>max_int32_as_int64thenfailwith(Printf.sprintf"Sqlite3.Data.safe_get_int32: overflow: %Ld"n)elseifn<min_int32_as_int64thenfailwith(Printf.sprintf"Sqlite3.Data.safe_get_int32: underflow: %Ld"n)elseInt64.to_int32nletto_int_exn=function|INTn->safe_get_intn|data->data_type_error"INT"dataletto_nativeint_exn=function|INTn->safe_get_nativeintn|data->data_type_error"INT"dataletto_int32_exn=function|INTn->safe_get_int32n|data->data_type_error"INT"dataletto_int64_exn=function|INTn->n|data->data_type_error"INT"dataletto_float_exn=function|FLOATn->n|data->data_type_error"FLOAT"dataletbool_of_int64=function|0L->false|1L->true|n->failwith(Printf.sprintf"Sqlite3.Data.bool_of_native_int: %Ld"n)letint64_of_bool=functionfalse->0L|true->1Lletto_bool_exn=function|INTn->bool_of_int64n|data->data_type_error"INT 0L/1L"data(* Option-based type conversion *)letto_string=functionTEXTs|BLOBs->Somes|_->Noneletto_int=functionINTn->Some(safe_get_intn)|_->Noneletto_nativeint=functionINTn->Some(safe_get_nativeintn)|_->Noneletto_int32=functionINTn->Some(safe_get_int32n)|_->Noneletto_int64=functionINTn->Somen|_->Noneletto_float=functionFLOATn->Somen|_->Noneletto_bool=function|INT0L->Somefalse|INT1L->Sometrue|_->None(* Simplified string coercion *)letto_string_coerce=function|NONE|NULL->""|INTn->Int64.to_stringn|FLOATn->string_of_floatn|TEXTt|BLOBt->tend(* Data *)typeheader=stringtypeheaders=headerarraytyperow=stringoptionarraytyperow_not_null=stringarraymoduleMode=structtypet=Read_write_create|Read_write|Read_onlyletlift=function|None->Read_write_create|Some`READONLY->Read_only|Some`NO_CREATE->Read_writeend(* Mode *)moduleMut=structtypet=NOTHING|NO|FULLletlift=functionNone->NOTHING|Some`NO->NO|Some`FULL->FULLend(* Mut *)moduleCache=structtypet=NOTHING|SHARED|PRIVATEletlift=functionNone->NOTHING|Some`SHARED->SHARED|Some`PRIVATE->PRIVATEend(* Cache *)externalsqlite_version:unit->int="caml_sqlite3_version"externalsqlite_version_info:unit->string="caml_sqlite3_version_info"externaldb_open:mode:Mode.t->uri:bool->memory:bool->mutex:Mut.t->cache:Cache.t->?vfs:string->string->db="caml_sqlite3_open_bc""caml_sqlite3_open"letdb_open?mode?(uri=false)?(memory=false)?mutex?cache?vfsname=letmode=Mode.liftmodeinletmutex=Mut.liftmutexinletcache=Cache.liftcacheindb_open~mode~uri~memory~mutex~cache?vfsnameexternaldb_close:db->bool="caml_sqlite3_close"let(let&)dbf=letclose_or_exn()=ifnot(db_closedb)thenfailwith"Sqlite3.( let& ): could not close database"inFun.protect~finally:close_or_exn(fun()->fdb)externalerrcode:db->Rc.t="caml_sqlite3_errcode"externalerrmsg:db->string="caml_sqlite3_errmsg"externallast_insert_rowid:db->(int64[@unboxed])="caml_sqlite3_last_insert_rowid_bc""caml_sqlite3_last_insert_rowid"[@@noalloc]externalexec:db->?cb:(stringoptionarray->headers->unit)->string->Rc.t="caml_sqlite3_exec"externalexec_no_headers:db->cb:(stringoptionarray->unit)->string->Rc.t="caml_sqlite3_exec_no_headers"externalexec_not_null:db->cb:(stringarray->headers->unit)->string->Rc.t="caml_sqlite3_exec_not_null"externalexec_not_null_no_headers:db->cb:(stringarray->unit)->string->Rc.t="caml_sqlite3_exec_not_null_no_headers"externalchanges:db->(int[@untagged])="caml_sqlite3_changes_bc""caml_sqlite3_changes"externalprepare:db->string->stmt="caml_sqlite3_prepare"externalprepare_tail:stmt->stmtoption="caml_sqlite3_prepare_tail"externalrecompile:stmt->unit="caml_sqlite3_recompile"externalstep:stmt->Rc.t="caml_sqlite3_step"externalreset:stmt->Rc.t="caml_sqlite3_stmt_reset"letprepare_or_resetdbopt_stmt_refsql=match!opt_stmt_refwith|Somestmt->resetstmt|>Rc.check;stmt|None->letstmt=preparedbsqlinopt_stmt_ref:=Somestmt;stmtexternalsleep:(int[@untagged])->(int[@untagged])="caml_sqlite3_sleep_bc""caml_sqlite3_sleep"externalfinalize:stmt->Rc.t="caml_sqlite3_stmt_finalize"externaldata_count:stmt->(int[@untagged])="caml_sqlite3_data_count_bc""caml_sqlite3_data_count"externalcolumn_count:stmt->(int[@untagged])="caml_sqlite3_column_count_bc""caml_sqlite3_column_count"externalcolumn_blob:stmt->(int[@untagged])->string="caml_sqlite3_column_blob_bc""caml_sqlite3_column_blob"externalcolumn_double:stmt->(int[@untagged])->(float[@unboxed])="caml_sqlite3_column_double_bc""caml_sqlite3_column_double"externalcolumn_int32:stmt->(int[@untagged])->(int32[@unboxed])="caml_sqlite3_column_int32_bc""caml_sqlite3_column_int32"externalcolumn_int64:stmt->(int[@untagged])->(int64[@unboxed])="caml_sqlite3_column_int64_bc""caml_sqlite3_column_int64"letcolumn_intstmtpos=Data.safe_get_int(column_int64stmtpos)letcolumn_nativeintstmtpos=Data.safe_get_nativeint(column_int64stmtpos)externalcolumn_text:stmt->(int[@untagged])->string="caml_sqlite3_column_text_bc""caml_sqlite3_column_text"letcolumn_boolstmtpos=Data.bool_of_int64(column_int64stmtpos)externalcolumn:stmt->(int[@untagged])->Data.t="caml_sqlite3_column_bc""caml_sqlite3_column"externalcolumn_name:stmt->(int[@untagged])->string="caml_sqlite3_column_name_bc""caml_sqlite3_column_name"externalcolumn_decltype:stmt->(int[@untagged])->stringoption="caml_sqlite3_column_decltype_bc""caml_sqlite3_column_decltype"externalbind:stmt->(int[@untagged])->Data.t->Rc.t="caml_sqlite3_bind_bc""caml_sqlite3_bind"externalbind_parameter_count:stmt->(int[@untagged])="caml_sqlite3_bind_parameter_count_bc""caml_sqlite3_bind_parameter_count"externalbind_parameter_name:stmt->(int[@untagged])->stringoption="caml_sqlite3_bind_parameter_name_bc""caml_sqlite3_bind_parameter_name"externalbind_parameter_index:stmt->string->(int[@untagged])="caml_sqlite3_bind_parameter_index_bc""caml_sqlite3_bind_parameter_index"externalbind_blob:stmt->(int[@untagged])->string->Rc.t="caml_sqlite3_bind_blob_bc""caml_sqlite3_bind_blob"externalbind_double:stmt->(int[@untagged])->(float[@unboxed])->Rc.t="caml_sqlite3_bind_double_bc""caml_sqlite3_bind_double"externalbind_int32:stmt->(int[@untagged])->(int32[@unboxed])->Rc.t="caml_sqlite3_bind_int32_bc""caml_sqlite3_bind_int32"externalbind_int64:stmt->(int[@untagged])->(int64[@unboxed])->Rc.t="caml_sqlite3_bind_int64_bc""caml_sqlite3_bind_int64"letbind_intstmtposn=bind_int64stmtpos(Int64.of_intn)letbind_nativeintstmtposn=bind_int64stmtpos(Int64.of_nativeintn)letbind_boolstmtposb=bind_int64stmtpos(Data.int64_of_boolb)externalbind_text:stmt->(int[@untagged])->string->Rc.t="caml_sqlite3_bind_text_bc""caml_sqlite3_bind_text"letbind_namestmtnamedata=bindstmt(bind_parameter_indexstmtname)dataletbind_namesstmtlst=letrecloop=function|[]->Rc.OK|(name,data)::rest->letrc=bind_namestmtnamedatainifrc=Rc.OKthenlooprestelsercinlooplstletbind_valuesstmtlst=letrecloopi=function|[]->Rc.OK|data::rest->letrc=bindstmtidatainifrc=Rc.OKthenloop(i+1)restelsercinloop1lstexternalclear_bindings:stmt->Rc.t="caml_sqlite3_clear_bindings"externalbusy_timeout:db->(int[@untagged])->unit="caml_sqlite3_busy_timeout_bc""caml_sqlite3_busy_timeout"externalenable_load_extension:db->bool->bool="caml_sqlite3_enable_load_extension"letrow_blobsstmt=Array.init(data_countstmt)(column_blobstmt)letrow_datastmt=Array.init(data_countstmt)(columnstmt)letrow_namesstmt=Array.init(data_countstmt)(column_namestmt)letrow_decltypesstmt=Array.init(data_countstmt)(column_decltypestmt)letattempt_resetstmtrc=matchresetstmtwith|Rc.OK->rc|reset_rc->reset_rcletiterstmt~f=letrecloop()=matchstepstmtwith|Rc.ROW->f(row_datastmt);loop()|rc->attempt_resetstmtrcinloop()letfoldstmt~f~init=letrecloopacc=matchstepstmtwith|Rc.ROW->loop(facc(row_datastmt))|rc->attempt_resetstmtrc,accinloopinit(* Function registration *)externalcreate_function:db->string->(int[@untagged])->(Data.tarray->Data.t)->unit="caml_sqlite3_create_function_bc""caml_sqlite3_create_function"letcreate_funNdbnamef=create_functiondbname(-1)fletcreate_fun0dbnamef=create_functiondbname0(fun_->f())letcreate_fun1dbnamef=create_functiondbname1(funargs->fargs.(0))letcreate_fun2dbnamef=create_functiondbname2(funargs->fargs.(0)args.(1))letcreate_fun3dbnamef=create_functiondbname3(funargs->fargs.(0)args.(1)args.(2))externaldelete_function:db->string->unit="caml_sqlite3_delete_function"moduleAggregate=structexternalcreate_function:db->string->(int[@untagged])->'a->('a->Data.tarray->'a)->('a->Data.tarray->'a)option->('a->Data.t)option->('a->Data.t)->unit="caml_sqlite3_create_aggregate_function_bc""caml_sqlite3_create_aggregate_function"letcreate_funN?inverse?valuedbname~init~step~final=create_functiondbname(-1)initstepinversevaluefinalletcreate_fun0?inverse?valuedbname~init~step~final=create_functiondbname0init(funacc_->stepacc)(matchinversewith|Someinv->Some(funacc_->invacc)|None->None)valuefinalletcreate_fun1?inverse?valuedbname~init~step~final=create_functiondbname1init(funaccargs->stepaccargs.(0))(matchinversewith|Someinv->Some(funaccargs->invaccargs.(0))|None->None)valuefinalletcreate_fun2?inverse?valuedbname~init~step~final=create_functiondbname2init(funaccargs->stepaccargs.(0)args.(1))(matchinversewith|Someinv->Some(funaccargs->invaccargs.(0)args.(1))|None->None)valuefinalletcreate_fun3?inverse?valuedbname~init~step~final=create_functiondbname3init(funaccargs->stepaccargs.(0)args.(1)args.(2))(matchinversewith|Someinv->Some(funaccargs->invaccargs.(0)args.(1)args.(2))|None->None)valuefinalend(* Aggregate *)moduleBackup=structtypetexternalinit:dst:db->dst_name:string->src:db->src_name:string->t="caml_sqlite3_backup_init"externalstep:t->(int[@untagged])->Rc.t="caml_sqlite3_backup_step_bc""caml_sqlite3_backup_step"externalfinish:t->Rc.t="caml_sqlite3_backup_finish"externalremaining:t->(int[@untagged])="caml_sqlite3_backup_remaining_bc""caml_sqlite3_backup_remaining"[@@noalloc]externalpagecount:t->(int[@untagged])="caml_sqlite3_backup_pagecount_bc""caml_sqlite3_backup_pagecount"[@@noalloc]end(* Backup *)(* Initialisation *)externalinit:unit->unit="caml_sqlite3_init"externalcleanup:unit->unit="caml_sqlite3_cleanup"let()=Callback.register_exception"Sqlite3.InternalError"(InternalError"");Callback.register_exception"Sqlite3.Error"(Error"");Callback.register_exception"Sqlite3.RangeError"(RangeError(0,0));at_exitcleanup;init()