123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296(** *)openPrintfopenExtLibopenPreludetypepos=int*int[@@derivingshow]type'alocated={value:'a;pos:pos}[@@derivingshow,make]type'acollated={collated:'a;collation:stringlocatedoption}[@@derivingshow,make]letdummy_pos:pos=(0,0)letdummy_locvalue={value;pos=dummy_pos}moduleType=structmoduleEnum_kind=structmoduleCtors=structincludeSet.Make(String)letppfmts=Format.fprintffmt"{%s}"(String.concat"; "(elementss))endtypet=Ctors.t[@@derivingeq,show{with_path=false}]letmakectors=Ctors.of_listctorsendtypeunion={ctors:Enum_kind.t;is_closed:bool}[@@derivingeq,show{with_path=false}]typedecimal={precision:intoption;scale:intoption}[@@derivingeq,show{with_path=false}]typekind=|Int|UInt64|Text|Blob|Float|Bool|Datetime|Decimalofdecimal|Unionofunion|StringLiteralofstring|FloatingLiteraloffloat|Json_path|One_or_all|Json|Any(* FIXME - Top and Bottom ? *)[@@derivingeq,show{with_path=false}](* TODO NULL is currently typed as Any? which actually is a misnormer *)letshow_kind=function|Union{ctors;_}->sprintf"Union (%s)"(String.concat"| "(Enum_kind.Ctors.elementsctors))|StringLiterall->sprintf"StringLiteral (%s)"l|FloatingLiteralf->sprintf"FloatingLiteral (%g)"f|Decimal{precision=Somep;scale=Somes}->sprintf"Decimal(%d,%d)"ps|Decimal{precision=Somep;scale=None}->sprintf"Decimal(%d)"p|Decimal_->"Decimal"|k->show_kindktypenullability=|Nullable(** can be NULL *)|Strict(** cannot be NULL *)|Depends(** unknown, to be determined *)[@@derivingeq,show{with_path=false}]typet={t:kind;nullability:nullability;}[@@derivingeq,show{with_path=false}]letnullabilitynullability=funt->{t;nullability}letstrict=nullabilityStrictletdepends=nullabilityDependsletnullable=nullabilityNullableletmake_nullable{t;nullability=_}=nullabletletmake_strict{t;nullability=_}=stricttletmake_enum_kindctors=Union{ctors=(Enum_kind.makectors);is_closed=true}letis_strict{nullability;_}=nullability=Strictletis_nullable{nullability;_}=nullability=Nullablelet(=):t->t->bool=equalletshow{t;nullability;}=show_kindt^(matchnullabilitywithNullable->"?"|Depends->"??"|Strict->"")let_=ppletpppft=Format.pp_print_stringpf(showt)lettype_namet=show_kindt.tletis_any{t;nullability=_}=equal_kindtAnyletis_one_or_alls=List.mem(String.lowercase_asciis)["one";"all"]letcheck_exact_exact_numbervalue{precision;scale}=matchprecision,scalewith|Somep,Somes->letmax=(10.**float_of_int(p-s))-.(10.**(-.float_of_ints))invalue>=-.max&&value<=max|_->true(** @return (subtype, supertype) *)letorder_kindxy=matchx,ywith|x,ywhenequal_kindxy->`Equal|StringLiterala,StringLiteralb->`StringLiteralUnion(Union{ctors=(Enum_kind.make[a;b]);is_closed=false})|StringLiterala,Unionu|Unionu,StringLiterala->letb=u.ctorsinletb'=Enum_kind.Ctors.addabinbeginmatchEnum_kind.Ctors.memab,u.is_closedwith|true,true->`Equal|true,false->`Order(StringLiterala,Union{uwithctors=b'})|false,false->`StringLiteralUnion(Union{ctors=b';is_closed=false})|false,true->`Noend|StringLiteral_asx,Text->`Order(x,Text)|Text,(StringLiteral_asx)->`Order(x,Text)|Text,(Union_asx)->`Order(x,Text)|Union{ctors=a;_}asx1,(Union{ctors=b;_}asx2)whenEnum_kind.Ctors.subsetba->`Order(x2,x1)|StringLiteralx,Datetime|Datetime,StringLiteralx->`Order(Datetime,StringLiteralx)|StringLiteralx,Blob|Blob,StringLiteralx->`Order(Blob,StringLiteralx)|Any,t|t,Any->`Order(t,t)|Int,Decimaldec|Decimaldec,Int->`Order(Int,Decimaldec)|Decimald1,Decimald2whend1<>d2->letscale=matchd1.scale,d2.scalewith|None,_|_,None->None|Somea,Someb->Some(maxab)inletcommon=Decimal{precision=None;scale}in`Order(common,common)|FloatingLiteral_,FloatingLiteral_->`Order(Float,Float)|Int,Float|Float,Int->`Order(Int,Float)|Decimal_,Float|Float,Decimal_->`No|FloatingLiteral_,Int|Int,FloatingLiteral_->`Order(Int,Float)|FloatingLiteralx,Float|Float,FloatingLiteralx->`Order(FloatingLiteralx,Float)|FloatingLiteralf,Decimaldec|Decimaldec,FloatingLiteralf->ifcheck_exact_exact_numberfdecthen`Equalelse`No(* UInt64 cannot be a subtype of Float: double precision only guarantees exact
representation up to 2^53 (~9e15), but UInt64 can hold values up to 2^64-1 (~18e18).
Converting large UInt64 values to Float would lose precision *)|UInt64,Int|Int,UInt64->`Order(Int,UInt64)|Text,Blob|Blob,Text->`Order(Text,Blob)|Int,Datetime|Datetime,Int->`Order(Int,Datetime)|Text,Datetime|Datetime,Text->`Order(Datetime,Text)(* JSON literal validation:
sqlgg can statically validate JSON string literals at compile time:
Valid JSON literals are accepted:
'{"valid": "example"}' -> StringLiteral is subtype of Json
'["array", "example"]' -> StringLiteral is subtype of Json
'"simple string"' -> StringLiteral is subtype of Json
Invalid JSON literals are rejected:
'{NOTVALID|}' -> No subtype relation, compile error
'{missing: quotes}' -> No subtype relation, compile error
However, sqlgg cannot validate JSON strings constructed dynamically:
CONCAT('{"key": "', user_input, '"}') -> Text type, no validation
CONCAT('{"key": "', column_name, '"}') -> Text type, no validation (column value unknown)
JSON_EXTRACT(dynamic_column, '$.path') -> Json type, runtime validation
This static validation helps catch JSON syntax errors early in development
while still allowing dynamic JSON construction when needed.
*)|Json,StringLiteralx|StringLiteralx,Json->beginmatchYojson.Safe.from_stringxwith|_->`Order(StringLiteralx,Json)|exceptionYojson.Json_error_->`Noend|Text,Json|Json,Text->`Order(Json,Text)|Blob,Json|Json,Blob->`Order(Json,Blob)|(Json_path,StringLiteralx|StringLiteralx,Json_path)whenSqlgg_json_path.Json_path.is_validx->`Order(StringLiteralx,Json_path)|Json_path,Text|Text,Json_path->`Order(Json_path,Text)|(One_or_all,StringLiteralx|StringLiteralx,One_or_all)whenis_one_or_allx->`Order(StringLiteralx,One_or_all)|Json,One_or_all|One_or_all,Json->`Order(One_or_all,Text)|_->`Noletorder_nullabilityxy=matchx,ywith|Depends,Depends->`EqualDepends|Nullable,Nullable->`EqualNullable|Strict,Strict->`EqualStrict|Depends,n|n,Depends->`Equaln(* Order ? *)|Strict,Nullable->`Strict_Nullable|Nullable,Strict->`Nullable_Strictletcommon_nullability=List.fold_left(funacct->matchacc,t.nullabilitywith|_,Nullable|Nullable,_->Nullable|_,Strict|Strict,_->Strict|Depends,Depends->Depends)Dependsletcommon_nullabilityl=matchcommon_nullabilitylwithDepends->Strict|n->nletundependtnullability=ifequal_nullabilityt.nullabilityDependsthen{twithnullability}elsetletcommon_type_orderxy=matchorder_nullabilityx.nullabilityy.nullability,order_kindx.ty.twith|_,`No->None|`Equalnullability,`Orderpair->`CommonTypepair|>order|>Option.map(funt->{t=t;nullability})|`Equalnullability,`Equal->Some{xwithnullability}|(`Nullable_Strict|`Strict_Nullable),`Equal->Some(nullablex.t)(* FIXME need nullability order? *)|(`Nullable_Strict|`Strict_Nullable),`Orderpair->`CommonTypepair|>order|>Option.mapnullable|`Equalnullability,`StringLiteralUniont->`StringLiteralUniont|>order|>Option.map(funt->{t=t;nullability})|(`Nullable_Strict|`Strict_Nullable),`StringLiteralUniont->`StringLiteralUniont|>order|>Option.mapnullableletcommon_type_l_order=function|[]->None|t::ts->List.fold_left(funacct->matchaccwithNone->None|Someprev->common_type_orderprevt)(Somet)tsletget_subtype=function|`CommonTypet->Some(fstt)|`StringLiteralUniont->Sometletget_supertype=function|`CommonTypet->Some(sndt)|`StringLiteralUniont->Sometletsubtype=common_type_get_subtypeletsupertype=common_type_get_supertypeletcommon_subtypetypes=matchcommon_type_l_get_subtypetypeswith|Some{t=FloatingLiteral_;nullability}->Some{t=Float;nullability}|result->resultletcommon_supertypetypes=matchcommon_type_l_get_supertypetypeswith|Some{t=FloatingLiteral_;nullability}->Some{t=Float;nullability}|result->resultletcommon_type=subtypelethas_common_typexy=Option.is_some@@subtypexytypetyvar=Typoft|Varofint[@@derivingshow{with_path=false}]letstring_of_tyvar=functionTypt->showt|Vari->sprintf"'%c"(Char.chr@@Char.code'a'+i)endmoduleConstraint=structmoduleStringSet=structincludeSet.Make(String)letshows=[%derive.show:stringlist](elementss)letppfmts=Format.fprintffmt"%s"(shows)endtypeconflict_algo=|Ignore|Replace|Abort|Fail|Rollback[@@derivingshow{with_path=false},ord,eq]typecomposite=|CompositePrimaryofStringSet.t|CompositeUniqueofStringSet.t[@@derivingshow{with_path=false},ord,eq]typet=|PrimaryKey|NotNull|Null|Unique|Autoincrement|OnConflictofconflict_algo|WithDefault|Compositeofcomposite[@@derivingshow{with_path=false},ord,eq]letmake_composite_primarycols=Composite(CompositePrimary(StringSet.of_listcols))letmake_composite_uniquecols=Composite(CompositeUnique(StringSet.of_listcols))endmoduleConstraints=structincludeSet.Make(Constraint)letshows=[%derive.show:Constraint.tlist](elementss)letppfmts=Format.fprintffmt"%s"(shows)endmoduleMeta=structmoduleStringMap=Map.Make(String)typet=stringStringMap.tletof_listlist=List.fold_left(funmap(k,v)->StringMap.addkvmap)StringMap.emptylistletempty()=StringMap.emptyletfind_optkmap=StringMap.find_optmapkletmemkmap=StringMap.memmapkletppfmtt=ifStringMap.is_emptytthenFormat.fprintffmt"{}"elsebeginFormat.fprintffmt"{";letfirst_key=fst(StringMap.min_bindingt)inStringMap.iter(funkv->ifk=first_keythenFormat.fprintffmt"%s = %s"kvelseFormat.fprintffmt"; %s = %s"kv)t;Format.fprintffmt"}"endletequal=StringMap.equalString.equalletmerge_rightt1t2=StringMap.merge(fun_v1v2->matchv1,v2with|Somev,None->Somev|Some_,Somev2->Somev2|None,Somev->Somev|None,None->None)t1t2letget_is_non_nullifiablemeta=Option.default"false"(find_optmeta"non_nullifiable")="true"endtypeattr={name:string;domain:Type.t;extra:Constraints.t;meta:Meta.t;}[@@derivingshow{with_path=false}]letunique_keysschema=letkeys_ofa=Constraints.fold(funcacc->matchcwith|Constraint.PrimaryKey|Unique->Constraint.StringSet.singletona.name::acc|Composite(CompositePrimarys|CompositeUniques)->s::acc|NotNull|Null|Autoincrement|OnConflict_|WithDefault->acc)a.extra[]inList.concat_mapkeys_ofschema|>List.sort_uniqConstraint.StringSet.compareletmake_attributenamekindextra~meta=ifConstraints.memNullextra&&Constraints.memNotNullextrathenfail"Column %s can be either NULL or NOT NULL, but not both"name;letdomain=Type.{t=Option.defaultIntkind;nullability=ifList.exists(funcstrt->Constraints.memcstrtextra)[NotNull;PrimaryKey]thenStrictelseNullable}in{name;domain;extra;meta=Meta.of_listmeta;}letunnamed_attribute?(meta=Meta.empty())domain={name="";domain;extra=Constraints.empty;meta;}letmake_attribute'?(extra=Constraints.empty)?(meta=[])namedomain={name;domain;extra;meta=Meta.of_listmeta;}moduleSchema=structtypet=attrlist[@@derivingshow]exceptionErroroft*stringmoduleSource=structmoduleAttr=structtype'at={attr:attr;sources:'alist}[@@derivingshow]letby_namenamesattr=sattr.attr.name=nameletmap_attrfsattr={sattrwithattr=fsattr.attr}endtype'at='aAttr.tlistletfind_by_nametname=List.find_all(Attr.by_namename)tletfindtname=matchfind_by_nametnamewith|[x]->x|[]->raise(Error(List.map(funi->i.Attr.attr)t,"missing attribute : "^name))|_->raise(Error(List.map(funi->i.Attr.attr)t,"duplicate attribute : "^name))letmem_by_nameta=matchfind_by_nameta.Attr.attr.namewith|[_]->true|[]->false|_->raise(Error(List.map(funi->i.Attr.attr)t,"duplicate attribute : "^a.attr.name))letsub_by_nameldel=List.filter(funx->not(mem_by_namedelx))lletfrom_schemalist=List.map(funsattr->sattr.Attr.attr)listendletraise_errortfmt=Printf.ksprintf(funs->raise(Error(t,s)))fmt(** FIXME attribute case sensitivity? *)letby_namename=functionattr->attr.name=nameletfind_by_nametname=List.find_all(by_namename)tletfindtname=matchfind_by_nametnamewith|[x]->x|[]->raise(Error(t,"missing attribute : "^name))|_->raise(Error(t,"duplicate attribute : "^name))letmake_unique=List.unique~cmp:(funa1a2->a1.name=a2.name&&a1.name<>"")letis_uniquet=List.length(make_uniquet)=List.lengthtletcheck_uniquet=is_uniquet||raise(Error(t,"duplicate attributes"))letprojectnamest=List.map(findt)namesletchange_inplacetbeforeafter=ignore(findtbefore);List.map(funattr->matchby_namebeforeattrwith|true->after|false->attr)tletexiststname=match(findtname:attr)with|_->true|exception_->falseletrenametoldnamenewname=ifnot(existstoldname)thenraise@@Error(t,"no such column : "^oldname);ifexiststnewnamethenraise@@Error(t,"column already exists : "^newname);List.map(funattr->ifattr.name=oldnamethen{attrwithname=newname}elseattr)tletto_stringv=v|>List.map(funattr->sprintf"%s %s"(Type.showattr.domain)attr.name)|>String.concat", "|>sprintf"[%s]"letnamest=t|>List.map(funattr->attr.name)|>String.concat","|>sprintf"[%s]"moduleJoin=structtype'acondition=Onof'a|Default|Natural|Usingofstringlist[@@derivingshow]typetyp=Left|Right|Full|Inner|Straight[@@derivingshow]letcrosst1t2=t1@t2(* TODO check that attribute types match (ignoring nullability)? *)letnaturalt1t2=let(common,t1only)=List.partition(funa->Source.mem_by_namet2a)t1inSource.Attr.(if0=List.lengthcommonthenlett1_attrs=List.map(funi->i.attr)t1inraise(Error(t1_attrs,"no common attributes for natural join of "^(names(t1_attrs))^" and "^(names(List.map(funi->i.attr)t2)))));common@t1only@Source.sub_by_namet2commonletusinglt1t2=letcommon=List.map(Source.findt1)linList.iter(funa->let_=Source.findt2a.Source.Attr.attr.namein())common;common@Source.sub_by_namet1common@Source.sub_by_namet2commonletjointypcondab=letnullable=List.map(fundata->Source.Attr.{datawithattr={data.attrwithdomain=Type.make_nullabledata.attr.domain}})inletaction=matchcondwithDefault|On_->cross|Natural->natural|Usingl->usinglinmatchtypwith|Inner|Straight->actionab|Left->actiona(nullableb)|Right->action(nullablea)b|Full->action(nullablea)(nullableb)endletcross_alll=List.fold_leftJoin.cross[]lletcompoundt1t2=letopenSourceinletopenAttrinifList.lengtht1<>List.lengtht2thenraise(Error(List.map(funi->i.attr)t1,(to_string(List.map(funi->i.attr)t1))^" differs in size to "^(to_string(List.map(funi->i.attr)t2))));letshow_nameia=matcha.namewith|""->sprintf"column %d (of %d)"(i+1)(List.lengtht1)|s->sinList.combinet1t2|>List.mapibeginfuni(a1,a2)->matchType.supertypea1.attr.domaina2.attr.domainwith|Somet->Attr.map_attr(funattr->{attrwithdomain=t})a1|None->raise(Error(List.map(funi->i.attr)t1,sprintf"Attributes do not match : %s of type %s and %s of type %s"(show_nameia1.attr)(Type.showa1.attr.domain)(show_nameia2.attr)(Type.showa2.attr.domain)))endletaddtcolpos=matchfind_by_nametcol.namewith|[]->beginmatchposwith|`First->col::t|`Default->t@[col]|`Aftername->trylet(i,_)=List.findi(fun_attr->by_namenameattr)tinlet(l1,l2)=List.split_nth(i+1)tinl1@(col::l2)withNot_found->raise(Error(t,"Can't insert column "^col.name^" after non-existing column "^name))end|_->raise(Error(t,"Already has column "^col.name))letdroptcol=ignore(findtcol);List.remove_if(by_namecol)tletchangetoldcolcolpos=matchposwith|`Default->change_inplacetoldcolcol|`First|`After_->add(droptoldcol)colposletto_string=showletprintx=prerr_endline(to_stringx)endtypetable_name={db:stringoption;tn:string}[@@derivingshow]letshow_table_name{db;tn}=matchdbwithSomedb->sprintf"%s.%s"dbtn|None->tnletmake_table_name?dbtn={db;tn}typeschema=Schema.t[@@derivingshow]typetable=table_name*schema[@@derivingshow]typejoin_source={table:table_name;alias:table_nameoption}[@@derivingshow]letjoin_source_name{table;alias}=Option.defaulttablealiasletprint_tableout(name,schema)=IO.write_lineout(show_table_namename);schema|>List.iterbeginfun{name;domain;extra;_}->IO.printfout"%10s %s %s\n"(Type.showdomain)name(Constraints.showextra)end;IO.write_lineout""(** optional name and start/end position in string *)typeparam_id=stringoptionlocated[@@derivingshow]typeshared_query_ref_id=stringlocated[@@derivingshow]typeint_size=Tiny|Small|Medium|Big[@@derivingshow{with_path=false},eq]typelob_size=Tiny|Medium|Long[@@derivingshow{with_path=false},eq]typesignedness=Signed|Unsigned[@@derivingshow{with_path=false},eq]typefloat_precision=Single|Double[@@derivingshow{with_path=false},eq]moduleSource_type=structtypetext_flavor=|PlainTextoflob_sizeoption|Charofintoption|Varcharofintoption|Varchar2ofintoption[@@derivingshow,eq]typeblob_flavor=|PlainBloboflob_sizeoption|Varbinaryofintoption[@@derivingshow,eq]typekind=InferofType.kind|Intof{size:int_sizeoption;sign:signedness;display_width:intoption}|Floatoffloat_precision|Blobofblob_flavor|Textoftext_flavor[@@derivingshow,eq]typet={t:kind;nullability:Type.nullability;}[@@derivingeq,show{with_path=false},make]letnullabilitynullabilityt={t=Infert;nullability}letstrict=nullabilityType.Strictletdepends=nullabilityType.Dependsletnullable=nullabilityType.Nullableletkind_to_type_kind=function|Inferty->ty|Int{size=SomeBig;sign=Unsigned;_}->Type.UInt64|Int_->Type.Int|Float_->Type.Float|Blob_->Type.Blob|Text_->Type.Textletto_infer_type{t;nullability;}={Type.t=kind_to_type_kindt;nullability}endtype'tparam={id:param_id;typ:'t;}[@@derivingshow,make]typeoption_actions_kind=BoolChoices|SetDefault[@@derivingshow]typeparams=Type.tparamlist[@@derivingshow]typein_or_not_in=[`In|`NotIn][@@derivingshow]typector=|Simpleofparam_id*varlistoption|Verbatimofstring*stringandvar=|SingleofType.tparam*Meta.t|SingleInofType.tparam*Meta.t|ChoiceInof{param:param_id;kind:in_or_not_in;vars:varlist}|Choiceofparam_id*ctorlist|DynamicSelectofparam_id*ctorlist|DynamicSelectJoinof{pid:param_id;pos:pos;source:join_source}|TupleListofparam_id*tuple_list_kind(* It differs from Choice that in this case we should generate sql "TRUE", it doesn't seem reusable *)|OptionActionChoiceofparam_id*varlist*(pos*pos)*option_actions_kind|SharedVarsGroupofvars*shared_query_ref_idandtuple_list_kind=|Insertionofschema|Where_inof((Type.t*Meta.t)list*in_or_not_in)located|ValueRowsof{types:Type.tlist;values_start_pos:int;}[@@derivingshow]andvars=varlist[@@derivingshow]letctor_vars=function|Simple(_,vars)->Option.default[]vars|Verbatim_->[]letsub_vars=function|Single_|SingleIn_|TupleList_|DynamicSelectJoin_->[]|ChoiceIn{vars;_}->vars|OptionActionChoice(_,vars,_,_)->vars|SharedVarsGroup(vars,_)->vars|Choice(_,ctors)|DynamicSelect(_,ctors)->List.concat_mapctor_varsctorsletmap_sub_varsf=letmap_ctor=function|Simple(n,vars)->Simple(n,Option.mapfvars)|Verbatim_asc->cinfunction|Single_|SingleIn_|TupleList_|DynamicSelectJoin_asv->v|ChoiceInt->ChoiceIn{twithvars=ft.vars}|OptionActionChoice(p,vars,pos,kind)->OptionActionChoice(p,fvars,pos,kind)|SharedVarsGroup(vars,id)->SharedVarsGroup(fvars,id)|Choice(p,ctors)->Choice(p,List.mapmap_ctorctors)|DynamicSelect(p,ctors)->DynamicSelect(p,List.mapmap_ctorctors)letvar_pos=function|Single(p,_)|SingleIn(p,_)->fstp.id.pos|Choice(id,_)|DynamicSelect(id,_)|TupleList(id,_)|OptionActionChoice(id,_,_,_)->fstid.pos|ChoiceIn{param;_}->fstparam.pos|SharedVarsGroup(_,id)->fstid.pos|DynamicSelectJoin{pos=(j1,_);_}->j1typealter_pos=[`Afterofstring|`Default|`First][@@derivingshow{with_path=false}]typedirection=[`Fixed|`Paramofparam_id][@@derivingshow]typecte_supported_compound_op=[`Union|`Union_all][@@derivingshow]typecompound_op=[cte_supported_compound_op|`Except|`Intersect][@@derivingshow]typeint_or_param=[`Constofint|`LimitofSource_type.tparam]typelimit_t=[`Limit|`Offset]typecol_name={cname:string;(** column name *)tname:table_nameoption;}[@@derivingshow]typelogical_op=And|Or|Xor[@@derivingshow]typecomparison_op=Comp_equal|Comp_num_cmp|Comp_num_eq|Not_distinct_op|Is_null|Is_not_null[@@derivingeq,show]typenull_handling_fn_kind=CoalesceofType.tyvar*Type.tyvar|Null_if|If_null[@@derivingshow]typesource_alias={table_name:table_name;column_aliases:schemaoption}[@@derivingshow]typeselect_row_locking_kind=For_update|For_share[@@derivingshow]andlimit=Source_type.tparamlist*boolandnested=source*(source*Schema.Join.typlocated*join_condition)locatedlist[@@derivingshow]andsource_kind=[`Selectofselect_full|`Tableoftable_name|`Nestedofnested|`ValueRowsofrow_values]andsource=(source_kind*source_aliasoption)(* alias, position *)andjoin_condition=exprSchema.Join.conditionandselect={columns:columnlist;from:nestedoption;where:exproption;group:exprlist;having:exproption;}andcte_item={cte_name:string;cols:schemaoption;stmt:cte_stmt;}[@@derivingshow]andcte_stmt=CteInlineofselect_complete|CteSharedQueryofshared_query_ref_id[@@derivingshow]andcte={cte_items:cte_itemlist;is_recursive:bool;}[@@derivingshow]andselect_complete={select:select*(compound_op*select)list;order:order;limit:limitoption;select_row_locking:select_row_locking_kindlocatedoption;}andselect_full={select_complete:select_complete;cte:cteoption;}androw_constructor_list=RowExprListofexprlistlist|RowParamof{id:param_id;types:Source_type.tlist;values_start_pos:int;}androw_values={row_constructor_list:row_constructor_list;row_order:order;row_limit:limitoption;}andorder=(expr*directionoption)listandagg_with_order_kind=|Group_concat|Json_arrayaggandagg_fun=Self(* self means that it returns the same type what aggregated columns have. ie: max, min *)|Count(* count it's count function which never returns null *)|Avg(* avg it's avg function that returns float *)|With_orderof{with_order_kind:agg_with_order_kind;order:order;}and'tfunc=|Aggofagg_fun(* 'a -> 'a | 'a -> t *)|Null_handlingofnull_handling_fn_kind|Comparisonofcomparison_op|Logicaloflogical_op|Negation|Retof't(* _ -> t *)(* TODO eliminate *)|FofType.tyvar*Type.tyvarlist|Col_assignof{ret_t:Type.tyvar;col_t:Type.tyvar;arg_t:Type.tyvar;}|Multiof{ret:Type.tyvar;fixed_args:Type.tyvarlist;repeating_pattern:Type.tyvarlist}(* repeating_pattern is needed for functions with fixed initial args + optional repeating pattern
Example: JSON_ARRAY_APPEND(json_doc, path, val[, path, val] ...)
- return_type: what function returns
- fixed_args: required initial arguments [json_doc, path, val]
- repeating_pattern: list of types that repeat [path_type, val_type]
Valid calls: f(a,b,c) or f(a,b,c,d,e) or f(a,b,c,d,e,f,g) etc. *)[@@derivingshow]and'exprchoices=(param_id*'exproption)listand'tfun_={fn_name:string;kind:'tfunc;parameters:exprlist;is_over_clause:bool;}[@@derivingshow]andcase_branch={when_:expr;then_:expr}andcase={case:exproption;branches:case_branchlist;else_:exproption;}[@@derivingshow]andin_tuple_list={exprs:exprlist;param_id:param_id;kind_in_tuple_list:in_or_not_in;}[@@derivingshow]andexpr=|ValueofType.tcollated(** literal value *)|ParamofSource_type.tparam*Meta.t|InparamofSource_type.tparam*Meta.t|Choicesofparam_id*exprchoices|InChoiceofparam_id*in_or_not_in*expr|FunofSource_type.tfun_|SelectExprofselect_full*[`AsValue|`Exists]|Columnofcol_namecollated|InTupleListofin_tuple_listlocated(* pos - full syntax pos from {, to }?, pos is only sql, that inside {}?
to use it during the substitution and to not depend on the magic numbers there.
*)|OptionActionsof{choice:expr;pos:(pos*pos);kind:option_actions_kind}|Caseofcase|Of_valuesofstring(** VALUES(col_name) *)andcolumn=column_kindlocated[@@derivingshow{with_path=false}]andcolumn_kind=|All|AllOfoftable_name|Exprofexprlocated*stringoptiontypecolumns=columnlist[@@derivingshow]letsource_fun_kind_to_infer=function|Rett->Ret(Source_type.to_infer_typet)|Agg(Self|Count|Avg|With_order_)|Null_handling_|Comparison_|Logical_|Negation|F_|Col_assign_|Multi_asfn->fnletexpr_to_string=show_exprletsub_exprs=function|Value_|Param_|Inparam_|Column_|Of_values_|SelectExpr_->[]|Choices(_,l)->List.filter_mapsndl|InChoice(_,_,e)->[e]|OptionActions{choice;_}->[choice]|Fun{kind=Agg(With_order{order;_});parameters;_}->parameters@List.mapfstorder|Fun{parameters;_}->parameters|InTupleList{value={exprs;_};_}->exprs|Case{case;branches;else_}->option_listcase@List.concat_map(fun(b:case_branch)->[b.when_;b.then_])branches@option_listelse_letmap_sub_exprsf=function|Value_|Param_|Inparam_|Column_|Of_values_|SelectExpr_ase->e|Choices(n,l)->Choices(n,List.map(fun(n,e)->n,Option.mapfe)l)|InChoice(n,k,e)->InChoice(n,k,fe)|OptionActions({choice;_}aso)->OptionActions{owithchoice=fchoice}|Fun({kind=Agg(With_order({order;_}aswo));parameters;_}asfn)->Fun{fnwithkind=Agg(With_order{wowithorder=List.map(fun(e,dir)->fe,dir)order});parameters=List.mapfparameters}|Fun({parameters;_}asfn)->Fun{fnwithparameters=List.mapfparameters}|InTupleList({value={exprs;_}astl;_}asloc)->InTupleList{locwithvalue={tlwithexprs=List.mapfexprs}}|Case{case;branches;else_}->Case{case=Option.mapfcase;branches=List.map(fun(b:case_branch)->{when_=fb.when_;then_=fb.then_})branches;else_=Option.mapfelse_;}letrecexpr_existspe=pe||List.exists(expr_existsp)(sub_exprse)letmake_partition_by=List.iter(function|Value_->fail"ORDER BY or PARTITION BY uses legacy position indication which is not supported, use expression."|_->())typeassignment_expr=|RegularExprofexpr|AssignDefault|WithDefaultParamofexpr*(pos*pos)[@@derivingshow{with_path=false}]typeassignments=(col_name*assignment_expr)list[@@derivingshow]typeon_conflict=Do_updateofassignments|Do_nothing[@@derivingshow]typeconflict_clause=|On_duplicateof{assignments:assignments;}|On_conflictof{action:on_conflict;attrs:col_namelist;}[@@derivingshow]typeinsert_action_kind=Insert_into|Replace_intoofpos[@@derivingshow]typeinsert_action={insert_action_kind:insert_action_kind;target:table_name;action:[`Setofassignmentsoption|`Valuesof(stringlistoption*assignment_exprlistlistoption)(* column names * list of value tuples *)|`Paramof(stringlistoption*param_id)|`Selectof(stringlistoption*select_full)];on_conflict_clause:conflict_clauselocatedoption;}[@@derivingshow{with_path=false}]typetable_constraints=[`Ignore|`Primaryofstringlist|`Uniqueofstringoption*stringlist][@@derivingshow{with_path=false}]typeindex_kind=|Regular_idx|Fulltext|Spatial[@@derivingshow{with_path=false}]moduleAlter_action_attr=structtypedefault={expr:exprlocated;sql:stringoption}[@@derivingshow{with_path=false}]typeconstraint_=Syntax_constraintofConstraint.t|Defaultofdefault[@@derivingshow{with_path=false}]typet={name:string;kind:Source_type.kindcollatedlocatedoption;extra:constraint_locatedlist;meta:(string*string)list;}[@@derivingshow{with_path=false}]letconstraint_to_syntax_constraint=function|Syntax_constraintc->c|Default_->WithDefaultletdefault_sql(col:t)=List.find_map(fun(c:constraint_located)->matchc.valuewith|Default{sql;_}->sql|Syntax_constraint_->None)col.extraletto_attr(x:t):attr=make_attributex.name(Option.map_default(funk->Some(Source_type.kind_to_type_kindk.value.collated))Nonex.kind)(Constraints.of_list(List.map(func->constraint_to_syntax_constraintc.value)x.extra))~meta:x.meta(* All attributes were already checked for dialect and default expression when writing to Tables,
we deliberately make the fields dummy to reconstruct
*)letfrom_attr(attr:attr):t=letextra=attr.extra|>Constraints.elements|>List.map(func->letc=matchcwith|Constraint.WithDefault->Default{expr=make_located~pos:(0,0)~value:(Value(make_collated~collated:(Type.dependsAny)()));sql=None;}|x->Syntax_constraintxinmake_located~pos:(0,0)~value:c)inletkind=Some(make_located~pos:(0,0)~value:(make_collated~collated:(Source_type.Inferattr.domain.Type.t)()))inletmeta=Meta.StringMap.bindingsattr.metain{name=attr.name;kind;extra;meta}endtypeindex_op_kind=|Plain_idx|Unique_idx|Fulltext_idx|Spatial_idx[@@derivingshow{with_path=false},eq]typetable_inline_index={idx_kind:index_kind;idx_name:stringoption;idx_cols:stringlist;idx_unique:bool;}[@@derivingshow{with_path=false}]typeadd_index={add_idx_name:stringoption;add_idx_kind:index_op_kind;add_idx_cols:stringlist}[@@derivingshow{with_path=false}]typecreate_index_def={ci_name:string;ci_table:table_name;ci_cols:stringcollatedlist;ci_kind:index_op_kind;}[@@derivingshow{with_path=false}]typecreate_target_schema={schema:Alter_action_attr.tlist;constraints:table_constraintslist;indexes:table_inline_indexlocatedlist;}[@@derivingshow]typecreate_target=|Schemaofcreate_target_schema|Selectofselect_fulllocated[@@derivingshow{with_path=false}]typecharset_name=Namedofstring|Binary|Ascii|Unicode[@@derivingshow{with_path=false}]typettl_option=[`TtlSetofstring*int*string|`TtlEnableofstring][@@derivingshow{with_path=false}]moduleAlter_column_pg=structtypet=|Set_typeofSource_type.kindcollatedlocated|Set_not_null|Drop_not_null|Set_default|Drop_default[@@derivingshow{with_path=false}]endtypealter_action=[|`AddofAlter_action_attr.t*alter_pos|`RenameTableoftable_name|`RenameColumnofstring*string|`RenameIndexofstring*string|`Dropofstring|`Changeofstring*Alter_action_attr.t*alter_pos|`AddIndexofadd_index|`DropIndexofstring|`AddPrimaryKeyofstringlist|`DropPrimaryKey|`AddConstraintofstringoption|`DropConstraintofstring|`Default_or_convert_toof(charset_name*stringlocatedoption)|`TtlOptionsofttl_optionlist*pos|`RemoveTtlofpos|`AlterColumnPGofstring*Alter_column_pg.tlocated][@@derivingshow{with_path=false}]typecreate_type_target=|TypeEnumofstringlist[@@derivingshow{with_path=false}]typestmt=|Createoftable_name*create_target|Dropoftable_name|Alteroftable_name*alter_actionlist|Renameof(table_name*table_name)list|CreateIndexofcreate_index_def|Insertofinsert_action|Deleteoftable_name*exproption|DeleteMultioftable_namelist*nested*exproption|Setof(string*expr)list*stmtoption|Updateoftable_name*assignments*exproption*order*Source_type.tparamlist(* where, order, limit *)|UpdateMultiofnestedlist*assignments*exproption*order*Source_type.tparamlist(* where, order, limit *)|Selectofselect_full|CreateRoutineoftable_name*Source_type.kindcollatedlocatedoption*(string*Source_type.kindcollatedlocated*exproption)list(* table_name represents possibly namespaced function name *)|CreateTypeofstring*create_type_target|DropTypeofstring*bool[@@derivingshow{with_path=false}](*
open Schema
let test = [{name="a";domain=Type.Int}; {name="b";domain=Type.Int}; {name="c";domain=Type.Text};];;
let () = print test
let () = print (project ["b";"c";"b"] test)
let () = print (project ["b";"d"] test)
let () = print (rename test "a" "new_a")
*)type'attrdynamic_field={field_id:param_id;field_attr:'attr;join_deps:intlist;}[@@derivingshow]typeschema_column_with_sources=|AttrWithSourcesoftable_nameSchema.Source.Attr.t|DynamicWithSourcesofparam_id*table_nameSchema.Source.Attr.tdynamic_fieldlist[@@derivingshow]typeschema_column=|Attrofattr|Dynamicofparam_id*attrdynamic_fieldlist[@@derivingshow]letdrop_sources:schema_column_with_sources->schema_column=function|AttrWithSources{attr;_}->Attrattr|DynamicWithSources(p,l)->Dynamic(p,List.map(fun{field_id;field_attr={Schema.Source.Attr.attr;_};join_deps}->{field_id;field_attr=attr;join_deps})l)letmonomorphicretargs=F(Typret,List.map(funt->Type.Typt)args)letfixedretargs=monomorphic(Type.dependsret)(List.mapType.dependsargs)letfun_identity=F(Var0,[Var0])letpp_funcppf=letopenFormatinletrecaux=function|AggSelf->fprintfpp"|'a| -> 'a"|AggAvg->fprintfpp"|'a| -> float"|AggCount->fprintfpp"|'a| -> int"|Agg(With_order{with_order_kind=Group_concat;_})->fprintfpp"|'a| -> text"|Agg(With_order{with_order_kind=Json_arrayagg;_})->fprintfpp"|'a| -> json"|Retret->fprintfpp"_ -> %s"(Type.showret)|F(ret,args)->fprintfpp"%s -> %s"(String.concat" -> "@@List.mapType.string_of_tyvarargs)(Type.string_of_tyvarret)|Col_assign{ret_t=ret;col_t;arg_t}->aux(F(ret,[col_t;arg_t]))|Null_handling(Coalesce(ret,each_arg))->fprintfpp"{ %s }+ -> %s"(Type.string_of_tyvareach_arg)(Type.string_of_tyvarret)|Null_handling_->fprintfpp"'a -> 'a -> 'a"|Comparison_->fprintfpp"'a -> 'a -> %s"(Type.show_kindBool)|Logical_->fprintfpp"'a -> 'a -> %s"(Type.show_kindBool)|Negation->fprintfpp"'a -> %s"(Type.show_kindBool)|Multi{ret;fixed_args;repeating_pattern}->letfixed_str=matchfixed_argswith|[]->""|args->String.concat" -> "(List.mapType.string_of_tyvarargs)^" -> "inletrepeating_str=String.concat", "(List.mapType.string_of_tyvarrepeating_pattern)infprintfpp"%s[%s]* -> %s"fixed_strrepeating_str(Type.string_of_tyvarret)inauxfletstring_of_func=Format.asprintf"%a"pp_funcletis_grouping=function|Agg_->true|Col_assign_|Ret_|F_|Multi_|Null_handling_|Comparison_|Negation|Logical_->falsemoduleFunction:sigvallookup:string->int->Source_type.tfuncvallookup_agg:string->int->Source_type.tfuncvaladd:int->Source_type.tfunc->string->unitvalexclude:int->string->unitvalmonomorphic:Type.t->Type.tlist->string->unitvalmulti:ret:Type.tyvar->Type.tyvar->string->unitvalmulti_polymorphic:string->unitvaladd_multi:Source_type.tfunc->string->unitvalsponge:Source_type.tfuncvaladd_fixed_then_pairs:ret:Type.tyvar->fixed_args:Type.tyvarlist->repeating_pattern:Type.tyvarlist->string->unitend=structleth=Hashtbl.create10letadd_nargtypname=letname=String.lowercase_asciinameinifHashtbl.memh(name,narg)thenletfunc=matchnargwithNone->sprintf"%S"name|Somen->sprintf"%S of %d arguments"nameninfail"Function %s already registered"funcelseHashtbl.addh(name,narg)typletexcludenargname=add_(Somenarg)Nonenameletadd_multitypname=add_None(Sometyp)nameletaddnargtypname=add_(Somenarg)(Sometyp)nameletsponge=letopenTypeinletany=dependsAnyinMulti{ret=Typany;fixed_args=[];repeating_pattern=[Typany]}letlookupnamenarg=letname=String.lowercase_asciinameinmatchHashtbl.findh(name,Somenarg)with|None->eprintfn"W: wrong number of arguments for known function %S, treating as untyped"name;sponge|Somet->t|exception_->matchHashtbl.findh(name,None)with|None->assertfalse|Somet->t|exception_->eprintfn"W: unknown function %S of %d arguments, treating as untyped"namenarg;spongeletlookup_aggnamenarg=matchlookupnamenargwith|Agg_asa->a|_->fail"Function %s is not an aggregate function"nameletmonomorphicretargsname=add(List.lengthargs)(monomorphicretargs)nameletmulti_polymorphicname=add_multi(Multi{ret=Var0;fixed_args=[];repeating_pattern=[Var0]})nameletmulti~retargsname=add_multi(Multi{ret;fixed_args=[];repeating_pattern=[args]})nameletadd_fixed_then_pairs~ret~fixed_args~repeating_patternname=add_multi(Multi{ret;fixed_args;repeating_pattern})nameendlet()=letopenTypeinletopenFunctioninlet(||>)xf=List.iterfxinletint=strictIntinletfloat=strictFloatinlettext=strictTextinletjson=strictJsoninletjson_path=strictJson_pathinletdatetime=strictDatetimeinletbool=strictBoolin"count"|>add0(AggCount);(* count( * ) - asterisk is treated as no parameters in parser *)"count"|>add1(AggCount);["max";"min";"sum";]||>add1(AggSelf);"avg"|>add1(Agg(Avg));["max";"min"]||>multi_polymorphic;(* sqlite3 *)["lower";"upper";"unhex";"md5";"sha";"sha1";"sha2";"trim";"to_base64"]||>monomorphictext[text];"hex"|>monomorphictext[int];"length"|>monomorphicint[text];["random"]||>monomorphicint[];"rand"|>monomorphicint[];"rand"|>monomorphicint[int];"floor"|>monomorphicint[float];"nullif"|>add2(Null_handlingNull_if);"ifnull"|>add2(Null_handlingIf_null);["least";"greatest";]||>multi_polymorphic;"strftime"|>exclude1;(* requires at least 2 arguments *)["concat";"concat_ws";"strftime"]||>multi~ret:(Typ(dependsText))(Typ(dependsText));"date"|>monomorphicdatetime[datetime];"time"|>monomorphictext[datetime];"julianday"|>multi~ret:(Typfloat)(Typtext);"from_unixtime"|>monomorphicdatetime[int];"from_unixtime"|>monomorphictext[int;text];["pow";"power"]||>monomorphicfloat[float;int];"unix_timestamp"|>monomorphicint[];"unix_timestamp"|>monomorphicint[datetime];["extract";"dayofmonth";"dayofweek";"dayofyear";]||>monomorphicint[datetime];"last_day"|>monomorphicdatetime[datetime];["microsecond";"second";"minute";"hour";"day";"week";"month";"quarter";"year"]||>monomorphicint[datetime];["current_date";"current_timestamp";"current_time";"localtime";"localtimestamp";"now"]||>monomorphicdatetime[];"getdate"|>monomorphicdatetime[];["timestampdiff";"timestampadd"]||>monomorphicint[strict@@Datetime;datetime;datetime];["date_add";"date_sub"]||>monomorphicdatetime[datetime;strict@@Datetime];["date_format";"time_format"]||>monomorphictext[datetime;text];"str_to_date"|>monomorphicdatetime[text;text];"any_value"|>add1(F(Var0,[Var0]));(* 'a -> 'a but not aggregate *)["substring";"sha2"]||>monomorphictext[text;int];"substring"|>monomorphictext[text;int;int];"substring_index"|>monomorphictext[text;text;int];"replace"|>monomorphictext[text;text;text];"last_insert_id"|>monomorphicint[];"last_insert_id"|>monomorphicint[int];add_multiType.(Null_handling(Coalesce(Var0,Var0)))"coalesce";"uuid"|>monomorphictext[];"uuid_short"|>monomorphicint[];"is_uuid"|>monomorphicbool[text];"makedate"|>monomorphicdatetime[int;int];(*
Any is used instead of Var because MySQL JSON functions have unique semantics:
1. ACCEPT ANY DATA TYPE: MySQL JSON functions accept values of any type
and automatically serialize them to JSON according to built-in rules
2. PRESERVE TYPES IN JSON: each type is serialized differently:
- Numbers → JSON numbers (123 → 123)
- Strings → JSON strings ("text" → "text")
- Booleans → JSON booleans (true → true)
- NULL → JSON null
- JSON-like strings remain STRINGS: '{"a":1}' → "{\"a\":1}" (not parsed!)
3. ONLY RESULTS OF JSON FUNCTIONS become JSON objects:
JSON_SET(data, '$.obj', JSON_OBJECT('key', 'value')) -- JSON object
JSON_SET(data, '$.str', '{"key": "value"}') -- string!
4. CRITICAL: different values in a single call can have DIFFERENT types
Example of valid MySQL query:
JSON_SET(
data,
'$.user.name', 'Alice', -- Text
'$.user.age', 25, -- Int
'$.user.active', true, -- Bool
'$.user.score', 99.5, -- Float
'$.user.meta', JSON_OBJECT('x', 1) -- Json
)
WHY NOT Var 0:
If we used ~repeating_pattern:[Typ json_path; Var 0], then:
- First value 'Alice' (Text) → Var 0 becomes Text
- Second value 25 (Int) → requires Text, but gets Int → TYPE ERROR
- Valid MySQL query would be rejected!
WHY NOT fresh Var for each cycle:
Consider this example:
JSON_ARRAY_APPEND(
data,
'$[0].items', 123, -- Int
'$[1].props', "hello", -- Text
'$[2].flags', true, -- Bool
'$[3].meta', null, -- Null
'$[4].nested', JSON_OBJECT('x', 'y') -- Json
)
With fresh Var this would be:
json -> json_path -> 'a -> json_path -> 'b -> json_path -> 'c -> json_path -> 'd -> json_path -> 'e -> json
This is essentially an existential type: json -> (json_path -> ∃a. a)* -> json
But this complicates implementation for the same effect as Any:
- Fresh Var can be any type = Any
- In our type system: | Any, t | t, Any -> `Order (t, t)
- Any already correctly handles unification with any types
Applied to: JSON_SET, JSON_ARRAY_APPEND, JSON_OBJECT, JSON_ARRAY, etc.
*)"json_array_append"|>add_fixed_then_pairs~ret:(Typ(dependsJson))~fixed_args:[Typ(dependsJson);Typjson_path;Typ(dependsAny)]~repeating_pattern:[Typjson_path;Typ(dependsAny)];"json_search"|>monomorphic((nullableJson))[json;strictOne_or_all;text];"json_search"|>add_fixed_then_pairs~ret:(Typ(nullableJson))~fixed_args:[Typjson;Typ(strictOne_or_all);Typtext;Typtext]~repeating_pattern:[Typjson_path];"json_remove"|>add_fixed_then_pairs~ret:(Typ(dependsJson))~fixed_args:[Typ(dependsJson);Typ(dependsJson_path)]~repeating_pattern:[Typ(dependsJson_path)];"json_set"|>add_fixed_then_pairs~ret:(Typ(dependsJson))~fixed_args:[(Typ(dependsJson));Typ(dependsJson_path);Typ(dependsAny)]~repeating_pattern:[Typ(dependsJson_path);Typ(dependsAny)];"json_array"|>multi~ret:(Typjson)(Typ(dependsAny));"json_object"|>add0(F(Typjson,[]));"json_object"|>add_fixed_then_pairs~ret:(Typjson)~fixed_args:[Typtext;Typ(dependsAny)]~repeating_pattern:[Typtext;Typ(dependsAny)];"json_contains"|>add2(F(Typ(nullableBool),[Typjson;Typjson]));"json_contains"|>add3(F(Typ(nullableBool),[Typjson;Typjson;Typjson_path]));"json_unquote"|>monomorphic(dependsText)[depends(Json)];"json_extract"|>add_fixed_then_pairs~ret:(Typ(nullableJson))~fixed_args:[Typjson;Typjson_path]~repeating_pattern:[Typjson_path];"json_array_insert"|>add_fixed_then_pairs~ret:(Typ(dependsJson))~fixed_args:[Typjson;Typjson_path;Typ(strictAny)]~repeating_pattern:[Typjson_path;Typ(strictAny)];"json_contains_path"|>add_fixed_then_pairs~ret:(Typ(dependsBool))~fixed_args:[Typ(dependsJson);Typ(dependsOne_or_all);Typ(dependsJson_path)]~repeating_pattern:[Typ(dependsJson_path)];"json_depth"|>add1(F(Typ(dependsInt),[Typ(strictJson)]));"json_insert"|>add_fixed_then_pairs~ret:(Typ(dependsJson))~fixed_args:[Typjson;Typjson_path;Typ(strictAny)]~repeating_pattern:[Typjson_path;Typ(strictAny)];"json_keys"|>add1(F(Typ(dependsJson),[Typjson]));"json_keys"|>add2(F(Typ(dependsJson),[Typjson;Typjson_path]));"json_length"|>add1(F(Typ(strictInt),[Typjson]));"json_length"|>add2(F(Typ(strictInt),[Typjson;Typjson_path]));"json_merge"|>multi~ret:(Typ(dependsJson))(Typjson);"json_merge_patch"|>multi~ret:(Typ(dependsJson))(Typjson);"json_merge_preserve"|>multi~ret:(Typ(dependsJson))(Typjson);"json_pretty"|>monomorphic(dependsText)[json];"json_quote"|>monomorphic(dependsText)[text];"json_replace"|>add_fixed_then_pairs~ret:(Typ(dependsJson))~fixed_args:[Typjson;Typjson_path;Typ(strictAny)]~repeating_pattern:[Typjson_path;Typ(strictAny)];"json_storage_size"|>add1(F(Typ(dependsInt),[Typjson]));"json_type"|>add1(F(Typ(dependsText),[Typjson]));"json_valid"|>add1(F(Typ(dependsBool),[Typtext]));()