diff --git a/shared/common/package.json b/shared/common/package.json index 33cb16a9..f369596a 100644 --- a/shared/common/package.json +++ b/shared/common/package.json @@ -3,7 +3,7 @@ "version": "0.0.0", "private": true, "peerDependencies": { - "edgedb": "^1.2.0", + "edgedb": "^1.4.0", "react": "^17.0.0", "react-dom": "^17.0.0" }, diff --git a/shared/common/schemaData/index.ts b/shared/common/schemaData/index.ts index afe5fcbd..ee1564e7 100644 --- a/shared/common/schemaData/index.ts +++ b/shared/common/schemaData/index.ts @@ -85,6 +85,11 @@ export interface SchemaMultirangeType { name: string; escapedName: string; elementType: SchemaType; + rangeType: { + schemaType: "Range"; + name: string; + elementType: SchemaType; + }; } interface _SchemaPointer { @@ -750,6 +755,14 @@ export function buildTypesGraph(data: RawIntrospectionResult): { ); } (types.get(type.id) as SchemaRangeType).elementType = elementType; + + if (type.type === "schema::MultiRange") { + (types.get(type.id) as SchemaMultirangeType).rangeType = { + schemaType: "Range", + name: `range<${elementType.name}>`, + elementType, + }; + } break; } case "schema::ObjectType": { diff --git a/shared/inspector/buildItem.tsx b/shared/inspector/buildItem.tsx index 95a4a515..e3550457 100644 --- a/shared/inspector/buildItem.tsx +++ b/shared/inspector/buildItem.tsx @@ -353,7 +353,7 @@ export function expandItem( } const itemTypes: { - [key in Exclude]: { + [key in Exclude]: { type: ItemType; brackets: string; }; @@ -390,7 +390,11 @@ export function buildItem( ? "set" : base.codec.getKind(); - if (codecKind === "scalar" || codecKind === "range") { + if ( + codecKind === "scalar" || + codecKind === "range" || + codecKind === "multirange" + ) { return buildScalarItem(base, data, index, comma, noMultiline); } diff --git a/shared/inspector/buildScalar.tsx b/shared/inspector/buildScalar.tsx index 20ea9766..457897a7 100644 --- a/shared/inspector/buildScalar.tsx +++ b/shared/inspector/buildScalar.tsx @@ -1,10 +1,10 @@ -import {PropsWithChildren, useState} from "react"; -import {_ICodec, Range} from "edgedb"; +import {PropsWithChildren, useState, Fragment} from "react"; +import {_ICodec, Range, MultiRange} from "edgedb"; import cn from "@edgedb/common/utils/classNames"; import {EnumCodec} from "edgedb/dist/codecs/enum"; -import {RangeCodec} from "edgedb/dist/codecs/range"; +import {RangeCodec, MultiRangeCodec} from "edgedb/dist/codecs/range"; import {Item, ItemType} from "./buildItem"; @@ -28,7 +28,7 @@ export function buildScalarItem( data, base.codec.getKnownTypeName(), base.codec instanceof EnumCodec, - base.codec instanceof RangeCodec + base.codec instanceof RangeCodec || base.codec instanceof MultiRangeCodec ? base.codec.getSubcodecs()[0].getKnownTypeName() : undefined, undefined, @@ -197,6 +197,31 @@ export function renderValue( ), }; } + if (value instanceof MultiRange) { + const ranges = [...value]; + + return { + body: ( + + multirange( + {ranges.map((range, i) => ( + + { + renderValue( + range, + `multirange<${rangeKnownTypeName!}>`, + false, + rangeKnownTypeName! + ).body + } + {i < ranges.length - 1 ? ", " : null} + + ))} + ) + + ), + }; + } if (value instanceof Uint8Array) { return { diff --git a/shared/inspector/package.json b/shared/inspector/package.json index 0dda9bbb..389afb3e 100644 --- a/shared/inspector/package.json +++ b/shared/inspector/package.json @@ -5,7 +5,7 @@ "license": "UNLICENSED", "peerDependencies": { "@types/react": "^16.9.34", - "edgedb": "^1.3.0", + "edgedb": "^1.4.0", "react": "^17.0.0", "react-dom": "^17.0.0" }, diff --git a/shared/inspector/renderJsonResult.ts b/shared/inspector/renderJsonResult.ts index 28f2e4e4..470d55b5 100644 --- a/shared/inspector/renderJsonResult.ts +++ b/shared/inspector/renderJsonResult.ts @@ -51,23 +51,12 @@ export function _renderToJson( } } case "range": { - if (val.isEmpty) { - return `{"empty": true}`; - } - const subcodec = codec.getSubcodecs()[0]; - return `{"lower": ${_renderToJson( - val.lower, - subcodec, - depth, - implicitLimit - )}, "upper": ${_renderToJson( - val.upper, - subcodec, - depth, - implicitLimit - )}, "inc_lower": ${val.incLower ? "true" : "false"}, "inc_upper": ${ - val.incUpper ? "true" : "false" - }}`; + return _renderRangeToJSON(val, codec, depth, implicitLimit); + } + case "multirange": { + return `[${[...val] + .map((range) => _renderRangeToJSON(range, codec, depth, implicitLimit)) + .join(", ")}]`; } case "set": case "array": @@ -129,3 +118,28 @@ export function _renderToJson( throw new Error("unexpected sparse_object"); } } + +function _renderRangeToJSON( + val: any, + codec: ICodec, + depth: string, + implicitLimit: number | null +) { + if (val.isEmpty) { + return `{"empty": true}`; + } + const subcodec = codec.getSubcodecs()[0]; + return `{"lower": ${_renderToJson( + val.lower, + subcodec, + depth, + implicitLimit + )}, "upper": ${_renderToJson( + val.upper, + subcodec, + depth, + implicitLimit + )}, "inc_lower": ${val.incLower ? "true" : "false"}, "inc_upper": ${ + val.incUpper ? "true" : "false" + }}`; +} diff --git a/shared/lang-edgeql/debug.js b/shared/lang-edgeql/debug.js index ab0faf7e..ca525c9d 100644 --- a/shared/lang-edgeql/debug.js +++ b/shared/lang-edgeql/debug.js @@ -74,6 +74,8 @@ const code = `select { d := $d, e := $e, f := >$f, + g := >$g, + h := >$h }`; const tree = parser.parse(code); diff --git a/shared/lang-edgeql/lang.grammar b/shared/lang-edgeql/lang.grammar index d91d0581..1b4ab988 100644 --- a/shared/lang-edgeql/lang.grammar +++ b/shared/lang-edgeql/lang.grammar @@ -15,6 +15,7 @@ element { Punctuation | Cast | compoundType | + fns | QueryParameter | Parens { "(" element* ")" } | Braces { "{" (element | ";")* "}" } | @@ -38,11 +39,15 @@ TupleType { } RangeType { - BuiltinName { @specialize } castStart Name ">" + BuiltinName { @specialize } castStart Name ">" } compoundType { ArrayType | TupleType } +fns { + BuiltinName { @specialize } +} + Cast { castStart ( Name | compoundType | RangeType ) ~cast ">" } QueryParameter[@dynamicPrecedence=1] { diff --git a/shared/lang-edgeql/lang.js b/shared/lang-edgeql/lang.js index e3b159aa..53a2a107 100644 --- a/shared/lang-edgeql/lang.js +++ b/shared/lang-edgeql/lang.js @@ -1,25 +1,25 @@ // This file was generated by lezer-generator. You probably shouldn't edit it. import {LRParser} from "@lezer/lr" import {strPrefix, dollarStr, operatorHacks, bigNumber, specializeIdent} from "./tokens.js" -const spec_operator = {__proto__:null,"<":141} -const spec_shortName = {__proto__:null,array:144, tuple:146, range:152} +const spec_operator = {__proto__:null,"<":143} +const spec_shortName = {__proto__:null,array:146, tuple:148, range:154, multirange:154} export const parser = LRParser.deserialize({ version: 14, - states: "/lOYQgOOO!jQgO'#CeOOQO'#DT'#DTO$^Q`O'#DiOOQV'#Ce'#CeOOQV'#Cg'#CgOOQV'#Ch'#ChO$iOpO'#CiO$wOpO'#CiO%VO`O'#CiOOQV'#Ci'#CiO%_O`O'#CkO%gQoO'#CmOOQO'#Cq'#CqOOQO'#Cs'#CsOOQV'#Du'#DuO'ZQ`O'#CxO'`QgO'#C}O'gQgO'#DQO'qQgO'#DROOQV'#Dg'#DgOOQV'#DS'#DSO'xQgO'#CdQ(SQ`OOO(XQ`O'#CrO(^Q`O'#CpO(tQ`O'#CoOOQO,59Q,59QO)OQgO,5:TOOQO-E7R-E7ROOQV,5:T,5:TOOOO'#DU'#DUO*rOpO,59TOOQV,59T,59TOOOO'#DV'#DVO+QOpO,59TO+`O!bO,59TO+nO!bO,59TO+|O#tO,59VO,_O#tO,59VOOQV,59X,59XOOQV,59d,59dOOQV,59i,59iO,pQgO,59iOOQV'#D]'#D]O,wQgO,59lOOQV,59l,59lOOQV,59m,59mO-RQgO,59mOOQV-E7Q-E7QOOQV'#D_'#D_O-YQgO'#D^Q(SQ`OOO-aQ`O,59^O-rQ`O,59[O.QQ&jO'#CeOOQO'#Cv'#CvO.]Q`O'#CuO.bQ&jO,59ZO.gQ`O,59eP.xQ`O'#CfOOOO-E7S-E7SOOQV1G.o1G.oOOOO-E7T-E7TOOOO'#DW'#DWO.}O!bO1G.oOOOO'#DX'#DXO/]O!bO1G.oOOOO'#DY'#DYO/kO#tO1G.qOOQV1G.q1G.qOOOO'#DZ'#DZO/|O#tO1G.qOOQV1G/T1G/TOOQV-E7Z-E7ZOOQV1G/W1G/WOOQV1G/X1G/XOOQV-E7]-E7]OOQO,59x,59xOOQO-E7[-E7[O0_Q&jO'#CeO0mQ&jO'#DxO0uQ&jO'#DxO0zQ&jO1G.xO1PQ&jO1G.vO1UQ&jO,5:TO1aQ`O,59aO1iQgO1G.uO3]Q&jO1G/POOOO-E7U-E7UOOQV7+$Z7+$ZOOOO-E7V-E7VOOOO-E7W-E7WOOQV7+$]7+$]OOOO-E7X-E7XO3bQ`O'#D[O3sQ&jO,5:dO.gQ`O,5:dOOQV7+$d7+$dOOQV7+$b7+$bO3{Q&jO1G.{OOQO7+$k7+$kO4QQ&jO'#CeOOQO,59v,59vO4`Q&jO,59vOOQO-E7Y-E7YO4eQ&jO1G0OOOQO7+$g7+$gO.gQ`O1G/bO4mQ&jO7+%jOOQO7+$|7+$|O4uQ`O'#Di", - stateData: "5Q~O!YOSUOS~OPXOQZOSSOTdObdOpaOsbO!TYO!UUO!VTO!WTO![PO!_UO!`VO!bWO!f[O!hjO!j]O!k^O!rcO~O!^kOPXXQXXSXXTXXbXXpXXsXX!SXX!TXX!UXX!VXX!WXX![XX!_XX!`XX!bXX!fXX!hXX!jXX!kXX!pXX!rXXoXXrXX!qXX~OSnO!WnO![lO~O^oO!`qO!aoO!boO~O^rO!`rO!arO!bqO~O!`tO!buO~O!`vO!bwO~ORxOPaXQaXSaXTaXbaXpaXsaX!SaX!TaX!UaX!VaX!WaX![aX!_aX!`aX!baX!faX!haX!jaX!kaX!paX!raXoaXraX!qaX~OnyO~OozO~PYOr!OO!p|O~PYO!q!PO~PYO!SWX!pWX~PYO!p!SO~O!h!VO~O!h!WO~OSSO!VTO!WTO!j]O!k^O~O![!XO!n!YO~P(cO!^kOP!]aQ!]aS!]aT!]ab!]ap!]as!]a!S!]a!T!]a!U!]a!V!]a!W!]a![!]a!_!]a!`!]a!b!]a!f!]a!h!]a!j!]a!k!]a!p!]a!r!]ao!]ar!]a!q!]a~O^oO!`!`O!aoO!boO~O^rO!`rO!arO!b!`O~O!`!`O!a!bO!b!bO!c!bO~O!`!dO!a!dO!b!`O!c!dO~O`!fO!`!hO!b!fO!d!fO!e!fO~O`!iO!`!iO!b!hO!d!iO!e!iO~Oo!kO~PYOr!mO!p|O~PYO!q!nO~PYO!p!SO~PYOSSO![!rO!j]O!k^O!n!YO~OSSO![!XO!k^O!n!YO~O!^kO!gXX!oXX~O!h!xO~O!g!yO~OSSO![!XO!j]O!k^O!n!YO~O!^kO~O!`!|O!a!bO!b!bO!c!bO~O!`!dO!a!dO!b!|O!c!dO~O`!fO!`#PO!b!fO!d!fO!e!fO~O`!iO!`!iO!b#PO!d!iO!e!iO~O!^kO!gXX!mhX!oXX~O!o#RO!g!lX~O!m#TO~O!g#UO~O!g#VO~O!^kO!g!]a!o!]a~OSSO![!XO~OPciQciSciTcibcinmipcisci!Sci!Tci!Uci!Vci!Wci![ci!_ci!`ci!bci!fci!hci!jci!kci!pci!rciocirci!qci~O!g#XO~OSSO![#YO!j]O!k^O!n!YO~O!o#RO!g!la~O!g#_O~O!^kO!gXX!mkX!oXX~O!m#`O~O!o#RO!g!li~O!o#RO!g!lq~OSnO!WnO![!wO~O", - goto: "*u!mPPPPPPPP!n!t#i$O$^$^P$^P$^P$^$i$z%]%q&T&W&m&v$^&yPPP$^PP$^$^'U'e(O(U([(b(h(n(t)O)U)[PPPPPPP)cP)pPPPPPPPPPPP*TPP*rQgOR!p!TbdOabcf{}!Q!TQ![jQ!s!VQ!v!WQ!z!]Q#W!xQ#Z#RQ#^#TR#b#`wQORabcfj{}!Q!T!V!W!]!x#R#T#`#cbdOabcf{}!Q!TR!]jcdOabcf{}!Q!To_Oabcfj{}!Q!T!V!]#R#T#`oiOabcfj{}!Q!T!V!]#R#T#`n_Oabcfj{}!Q!T!V!]#R#T#`R!v!WqhOabcfj{}!Q!T!V!W!]#R#T#`R!t!VQ![jQ!s!VQ!v!WQ!z!]Q#Z#RQ#^#TR#b#`_!Zj!V!W!]#R#T#`R#[#Rc`Oabcf{}!Q!TSfO!TQ{aQ!QcV!Rf{!QbROabcf{}!Q!TSmR#ca#cj!V!W!]!x#R#T#`QpVR!_pQsWR!asQ!ctR!{!cQ!euR!}!eQ!gvR#O!gQ!jwR#Q!jQ#S!sS#]#S#aR#a#^Q}bR!l}Q!UgR!q!US!Tg!UR!o!T^eOacf{!Q!TT|b}sSOabcfj{}!Q!T!V!W!]!x#R#T#`bdOabcf{}!Q!TQ![jQ!s!VQ!z!]Q#Z#RQ#^#TR#b#`R!u!V", - nodeNames: "⚠ RawStringPrefix ByteStringPrefix BigNumberPostfix BuiltinName Bool Comment Script Statement Name ModuleName Keyword Operator String StringEscape ByteString ByteEscape Number Punctuation Cast ArrayType BuiltinName TupleType BuiltinName TupleFieldName RangeType BuiltinName TupleFieldName QueryParameter Cast QueryParameterName ) ( Parens } { Braces Brackets", - maxTerm: 80, + states: "/rOYQgOOO!mQgO'#CeOOQO'#DU'#DUO$dQ`O'#DjOOQV'#Ce'#CeOOQV'#Cg'#CgOOQV'#Ch'#ChO$oOpO'#CiO$}OpO'#CiO%]O`O'#CiOOQV'#Ci'#CiO%eO`O'#CkO%mQoO'#CmOOQO'#Cq'#CqOOQO'#Cs'#CsOOQV'#Dv'#DvOOQV'#Cx'#CxO'dQ`O'#CyO'iQgO'#DOO'pQgO'#DRO'zQgO'#DSOOQV'#Dh'#DhOOQV'#DT'#DTO(RQgO'#CdQ(]Q`OOO(bQ`O'#CrO(gQ`O'#CpO(}Q`O'#CoOOQO,59Q,59QO)XQgO,5:UOOQO-E7S-E7SOOQV,5:U,5:UOOOO'#DV'#DVO+OOpO,59TOOQV,59T,59TOOOO'#DW'#DWO+^OpO,59TO+lO!bO,59TO+zO!bO,59TO,YO#tO,59VO,kO#tO,59VOOQV,59X,59XOOQV,59e,59eOOQV,59j,59jO,|QgO,59jOOQV'#D^'#D^O-TQgO,59mOOQV,59m,59mOOQV,59n,59nO-_QgO,59nOOQV-E7R-E7ROOQV'#D`'#D`O-fQgO'#D_Q(]Q`OOO-mQ`O,59^O.OQ`O,59[O.^Q&jO'#CeOOQO'#Cv'#CvO.iQ`O'#CuO.nQ&jO,59ZO.sQ`O,59fP/UQ`O'#CfOOOO-E7T-E7TOOQV1G.o1G.oOOOO-E7U-E7UOOOO'#DX'#DXO/ZO!bO1G.oOOOO'#DY'#DYO/iO!bO1G.oOOOO'#DZ'#DZO/wO#tO1G.qOOQV1G.q1G.qOOOO'#D['#D[O0YO#tO1G.qOOQV1G/U1G/UOOQV-E7[-E7[OOQV1G/X1G/XOOQV1G/Y1G/YOOQV-E7^-E7^OOQO,59y,59yOOQO-E7]-E7]O0kQ&jO'#CeO0yQ&jO'#DyO1RQ&jO'#DyO1WQ&jO1G.xO1]Q&jO1G.vO1bQ&jO,5:UO1mQ`O,59aO1uQgO1G.uO3lQ&jO1G/QOOOO-E7V-E7VOOQV7+$Z7+$ZOOOO-E7W-E7WOOOO-E7X-E7XOOQV7+$]7+$]OOOO-E7Y-E7YO3qQ`O'#D]O4SQ&jO,5:eO.sQ`O,5:eOOQV7+$d7+$dOOQV7+$b7+$bO4[Q&jO1G.{OOQO7+$l7+$lO4aQ&jO'#CeOOQO,59w,59wO4oQ&jO,59wOOQO-E7Z-E7ZO4tQ&jO1G0POOQO7+$g7+$gO.sQ`O1G/cO4|Q&jO7+%kOOQO7+$}7+$}O5UQ`O'#Dj", + stateData: "5a~O!ZOSUOS~OPXOQZOSSOTeObeOqbOtcO!UYO!VUO!WTO!XTO!]PO!`UO!aVO!cWO!g[O!ikO!k]O!l^O!o`O!sdO~O!_lOPXXQXXSXXTXXbXXqXXtXX!TXX!UXX!VXX!WXX!XXX!]XX!`XX!aXX!cXX!gXX!iXX!kXX!lXX!oXX!qXX!sXXpXXsXX!rXX~OSoO!XoO!]mO~O^pO!arO!bpO!cpO~O^sO!asO!bsO!crO~O!auO!cvO~O!awO!cxO~ORyOPaXQaXSaXTaXbaXqaXtaX!TaX!UaX!VaX!WaX!XaX!]aX!`aX!aaX!caX!gaX!iaX!kaX!laX!oaX!qaX!saXpaXsaX!raX~OozO~Op{O~PYOs!PO!q}O~PYO!r!QO~PYO!TWX!qWX~PYO!q!TO~O!i!WO~O!i!XO~OSSO!WTO!XTO!k]O!l^O~O!]!YO!o!ZO~P(lO!_lOP!^aQ!^aS!^aT!^ab!^aq!^at!^a!T!^a!U!^a!V!^a!W!^a!X!^a!]!^a!`!^a!a!^a!c!^a!g!^a!i!^a!k!^a!l!^a!o!^a!q!^a!s!^ap!^as!^a!r!^a~O^pO!a!aO!bpO!cpO~O^sO!asO!bsO!c!aO~O!a!aO!b!cO!c!cO!d!cO~O!a!eO!b!eO!c!aO!d!eO~O`!gO!a!iO!c!gO!e!gO!f!gO~O`!jO!a!jO!c!iO!e!jO!f!jO~Op!lO~PYOs!nO!q}O~PYO!r!oO~PYO!q!TO~PYOSSO!]!sO!k]O!l^O!o!ZO~OSSO!]!YO!l^O!o!ZO~O!_lO!hXX!pXX~O!i!yO~O!h!zO~OSSO!]!YO!k]O!l^O!o!ZO~O!_lO~O!a!}O!b!cO!c!cO!d!cO~O!a!eO!b!eO!c!}O!d!eO~O`!gO!a#QO!c!gO!e!gO!f!gO~O`!jO!a!jO!c#QO!e!jO!f!jO~O!_lO!hXX!nhX!pXX~O!p#SO!h!mX~O!n#UO~O!h#VO~O!h#WO~O!_lO!h!^a!p!^a~OSSO!]!YO~OPciQciSciTcibcioniqcitci!Tci!Uci!Vci!Wci!Xci!]ci!`ci!aci!cci!gci!ici!kci!lci!oci!qci!scipcisci!rci~O!h#YO~OSSO!]#ZO!k]O!l^O!o!ZO~O!p#SO!h!ma~O!h#`O~O!_lO!hXX!nkX!pXX~O!n#aO~O!p#SO!h!mi~O!p#SO!h!mq~OSoO!XoO!]!xO~O", + goto: "*v!nPPPPPPPP!o!u#j$P$_$_P$_P$_P$_$j${%^%r&U&X&n&w$_$_&zPPP$_PP$_$_'V'f(P(V(](c(i(o(u)P)V)]PPPPPPP)dP)qPPPPPPPPPPP*UPP*sQhOR!q!UbeObcdg|!O!R!UQ!]kQ!t!WQ!w!XQ!{!^Q#X!yQ#[#SQ#_#UR#c#awQORbcdgk|!O!R!U!W!X!^!y#S#U#a#dbeObcdg|!O!R!UR!^kceObcdg|!O!R!Uo_Obcdgk|!O!R!U!W!^#S#U#aojObcdgk|!O!R!U!W!^#S#U#an_Obcdgk|!O!R!U!W!^#S#U#aR!w!XqiObcdgk|!O!R!U!W!X!^#S#U#aR!u!WQ!]kQ!t!WQ!w!XQ!{!^Q#[#SQ#_#UR#c#a_![k!W!X!^#S#U#aR#]#ScaObcdg|!O!R!USgO!UQ|bQ!RdV!Sg|!RbRObcdg|!O!R!USnR#da#dk!W!X!^!y#S#U#aQqVR!`qQtWR!btQ!duR!|!dQ!fvR#O!fQ!hwR#P!hQ!kxR#R!kQ#T!tS#^#T#bR#b#_Q!OcR!m!OQ!VhR!r!VS!Uh!VR!p!U^fObdg|!R!UT}c!OsSObcdgk|!O!R!U!W!X!^!y#S#U#abeObcdg|!O!R!UQ!]kQ!t!WQ!{!^Q#[#SQ#_#UR#c#aR!v!W", + nodeNames: "⚠ RawStringPrefix ByteStringPrefix BigNumberPostfix BuiltinName Bool Comment Script Statement Name ModuleName Keyword Operator String StringEscape ByteString ByteEscape Number Punctuation Cast ArrayType BuiltinName TupleType BuiltinName TupleFieldName RangeType BuiltinName TupleFieldName BuiltinName QueryParameter Cast QueryParameterName ) ( Parens } { Braces Brackets", + maxTerm: 81, nodeProps: [ - ["openedBy", 31,"(",34,"{"], - ["closedBy", 32,")",35,"}"] + ["openedBy", 32,"(",35,"{"], + ["closedBy", 33,")",36,"}"] ], skippedNodes: [0,6], repeatNodeCount: 12, - tokenData: "4Z~R|OX#{XY$QYZ$XZ]#{]^$Q^p#{pq$bqr$krs$zst%Ptu%kuv'avw'jwx'qxy'vyz(Pz{'a{|(Y|}(f}!O(q!O!P)Q!P!Q)^!Q!R)j!R![+]![!],Z!]!^,q!^!_,z!_!`'a!`!a-W!a!b-f!b!c-|!c!}.V!}#O.}#O#P/W#P#Q2{#Q#R'a#R#S.V#S#T3U#T#o.V#o#p3w#p#q'j#q#r4Q#r#s'j#s~#{U$QO!aUg$XO!aU!Yao$bO!eW!aU!Yao$kO!dW!aU!Ya_$rP!dW!aU!_!`$uP$zO!_P~%PO!`~o%YQUa!dW!aUOY%`Z~%`a%eQUaOY%`Z~%`_%rU!dW!aU!Q!R&U!R![&Z!c!}&f#R#S&f#S#T&w#T#o&fP&ZOnPP&`QnP!Q![&Z#R#S&ZP&kSnP!Q![&f!c!}&f#R#S&f#T#o&fP&zRO!b'T!c#S'T#T~'TP'WRO#S'T#S#T&U#T~'T_'jO!dW!_P!aU^'qO!dW!aU~'vO!b~_(POpP!dW!aU_(YOoP!dW!aU_(cP!dW!_P!aU{|$uo(qO!o`bP!dW!aU_(xP!dW!aU!`!a({P)QObP_)ZPbP!dW!aU!^!_({_)gP!dW!_P!aU!P!Q$u_)sR!dW!fP!aU!O!P)|!g!h*h#X#Y*hP*PQ!Q![*V#R#S*VP*[S!fP!Q![*V!g!h*h#R#S*V#X#Y*hP*kS{|*w}!O*w!Q![+Q#R#S+QP*zQ!Q![+Q#R#S+QP+VQ!fP!Q![+Q#R#S+Q_+fT!dW!fP!aU!O!P)|!Q![+u!g!h*h#R#S+u#X#Y*hP+zT!fP!O!P)|!Q![+u!g!h*h#R#S+u#X#Y*ho,fQ!m`bP!dW!aU![!],l!_!`$ua,qO!^a_,zO!pP!dW!aU_-TP!dW!_P!aU!_!`$uo-cP!g`!dW!_P!aU!_!`$u_-mR!dW!aUqr-v!_!`$u!a!b$uP-yP!_!`$u_.VObP!dW!aU_.`S!dW![P!aU!Q![.l!c!}.l#R#S.l#T#o.lP.qS![P!Q![.l!c!}.l#R#S.l#T#o.l_/WO!rP!dW!aU^/][!cSYZ0Rrs0Rwx0R!w!x0Y#O#P0R#U#V0R#Y#Z0R#b#c0R#f#g0R#h#i0R#i#j1[#l#m2cY0YO`W^QQ0]R!Q![0f!c!i0f#T#Z0fQ0iR!Q![0r!c!i0r#T#Z0rQ0uR!Q![1O!c!i1O#T#Z1OQ1RR!Q![1[!c!i1[#T#Z1[Q1_R!Q![1h!c!i1h#T#Z1hQ1kR!Q![1t!c!i1t#T#Z1tQ1wR!Q![2Q!c!i2Q#T#Z2QQ2TR!Q![2^!c!i2^#T#Z2^Q2cO^QY2fR!Q![2o!c!i2o#T#Z2oY2rR!Q![0R!c!i0R#T#Z0R_3UO!qP!dW!aU_3]R!dW!aUO!b3f!c#S3f#T~3fP3iRO#S3f#S#T3r#T~3fP3wO![P_4QOsP!dW!aU_4ZOrP!dW!aU", + tokenData: "4Z~R|OX#{XY$QYZ$XZ]#{]^$Q^p#{pq$bqr$krs$zst%Ptu%kuv'avw'jwx'qxy'vyz(Pz{'a{|(Y|}(f}!O(q!O!P)Q!P!Q)^!Q!R)j!R![+]![!],Z!]!^,q!^!_,z!_!`'a!`!a-W!a!b-f!b!c-|!c!}.V!}#O.}#O#P/W#P#Q2{#Q#R'a#R#S.V#S#T3U#T#o.V#o#p3w#p#q'j#q#r4Q#r#s'j#s~#{U$QO!bUg$XO!bU!Zao$bO!fW!bU!Zao$kO!eW!bU!Za_$rP!eW!bU!_!`$uP$zO!`P~%PO!a~o%YQUa!eW!bUOY%`Z~%`a%eQUaOY%`Z~%`_%rU!eW!bU!Q!R&U!R![&Z!c!}&f#R#S&f#S#T&w#T#o&fP&ZOoPP&`QoP!Q![&Z#R#S&ZP&kSoP!Q![&f!c!}&f#R#S&f#T#o&fP&zRO!b'T!c#S'T#T~'TP'WRO#S'T#S#T&U#T~'T_'jO!eW!`P!bU^'qO!eW!bU~'vO!c~_(POqP!eW!bU_(YOpP!eW!bU_(cP!eW!`P!bU{|$uo(qO!p`bP!eW!bU_(xP!eW!bU!`!a({P)QObP_)ZPbP!eW!bU!^!_({_)gP!eW!`P!bU!P!Q$u_)sR!eW!gP!bU!O!P)|!g!h*h#X#Y*hP*PQ!Q![*V#R#S*VP*[S!gP!Q![*V!g!h*h#R#S*V#X#Y*hP*kS{|*w}!O*w!Q![+Q#R#S+QP*zQ!Q![+Q#R#S+QP+VQ!gP!Q![+Q#R#S+Q_+fT!eW!gP!bU!O!P)|!Q![+u!g!h*h#R#S+u#X#Y*hP+zT!gP!O!P)|!Q![+u!g!h*h#R#S+u#X#Y*ho,fQ!n`bP!eW!bU![!],l!_!`$ua,qO!_a_,zO!qP!eW!bU_-TP!eW!`P!bU!_!`$uo-cP!h`!eW!`P!bU!_!`$u_-mR!eW!bUqr-v!_!`$u!a!b$uP-yP!_!`$u_.VObP!eW!bU_.`S!eW!]P!bU!Q![.l!c!}.l#R#S.l#T#o.lP.qS!]P!Q![.l!c!}.l#R#S.l#T#o.l_/WO!sP!eW!bU^/][!dSYZ0Rrs0Rwx0R!w!x0Y#O#P0R#U#V0R#Y#Z0R#b#c0R#f#g0R#h#i0R#i#j1[#l#m2cY0YO`W^QQ0]R!Q![0f!c!i0f#T#Z0fQ0iR!Q![0r!c!i0r#T#Z0rQ0uR!Q![1O!c!i1O#T#Z1OQ1RR!Q![1[!c!i1[#T#Z1[Q1_R!Q![1h!c!i1h#T#Z1hQ1kR!Q![1t!c!i1t#T#Z1tQ1wR!Q![2Q!c!i2Q#T#Z2QQ2TR!Q![2^!c!i2^#T#Z2^Q2cO^QY2fR!Q![2o!c!i2o#T#Z2oY2rR!Q![0R!c!i0R#T#Z0R_3UO!rP!eW!bU_3]R!eW!bUO!b3f!c#S3f#T~3fP3iRO#S3f#S#T3r#T~3fP3wO!]P_4QOtP!eW!bU_4ZOsP!eW!bU", tokenizers: [strPrefix, dollarStr, operatorHacks, bigNumber, 0, 1, 2, 3, 4], topRules: {"Script":[0,7]}, - dynamicPrecedences: {"28":1}, - specialized: [{term: 58, get: (value, stack) => (specializeIdent(value, stack) << 1)},{term: 61, get: value => spec_operator[value] || -1},{term: 58, get: value => spec_shortName[value] || -1}], + dynamicPrecedences: {"29":1}, + specialized: [{term: 59, get: (value, stack) => (specializeIdent(value, stack) << 1)},{term: 62, get: value => spec_operator[value] || -1},{term: 59, get: value => spec_shortName[value] || -1}], tokenPrec: 0 }) diff --git a/shared/lang-edgeql/lang.terms.js b/shared/lang-edgeql/lang.terms.js index 3ea76fd8..f97e7adc 100644 --- a/shared/lang-edgeql/lang.terms.js +++ b/shared/lang-edgeql/lang.terms.js @@ -2,11 +2,11 @@ export const RawStringPrefix = 1, ByteStringPrefix = 2, - dollarString = 51, - opHack = 52, + dollarString = 52, + opHack = 53, BigNumberPostfix = 3, - reservedKeyword = 53, - unreservedKeyword = 54, + reservedKeyword = 54, + unreservedKeyword = 55, BuiltinName = 4, Bool = 5, Comment = 6, @@ -25,5 +25,5 @@ export const ArrayType = 20, TupleType = 22, RangeType = 25, - QueryParameter = 28, - QueryParameterName = 30 + QueryParameter = 29, + QueryParameterName = 31 diff --git a/shared/lang-edgeql/meta.d.ts b/shared/lang-edgeql/meta.d.ts index fc34b4f7..33f78f32 100644 --- a/shared/lang-edgeql/meta.d.ts +++ b/shared/lang-edgeql/meta.d.ts @@ -5,5 +5,6 @@ export const type_builtins: string[]; export const module_builtins: string[]; export const constraint_builtins: string[]; export const fn_builtins: string[]; +export const index_builtins: string[]; export const operators: string[]; -export const navigation: string[]; \ No newline at end of file +export const navigation: string[]; diff --git a/shared/lang-edgeql/meta.js b/shared/lang-edgeql/meta.js index 2e28c589..39e68568 100644 --- a/shared/lang-edgeql/meta.js +++ b/shared/lang-edgeql/meta.js @@ -13,6 +13,7 @@ export const reserved_keywords = [ "analyze", "and", "anyarray", + "anyobject", "anytuple", "anytype", "begin", @@ -196,10 +197,16 @@ export const unreserved_keywords = [ export const bool_literals = ["false", "true"]; export const type_builtins = [ + "Base64Alphabet", "BaseObject", + "ElasticLanguage", "FreeObject", "JsonEmpty", + "Language", + "LuceneLanguage", "Object", + "PGLanguage", + "Weight", "anycontiguous", "anydiscrete", "anyenum", @@ -216,6 +223,7 @@ export const type_builtins = [ "date_duration", "datetime", "decimal", + "document", "duration", "enum", "float32", @@ -227,7 +235,8 @@ export const type_builtins = [ "local_date", "local_datetime", "local_time", - "range", + // "multirange", + // "range", "relative_duration", "sequence", "str", @@ -238,6 +247,7 @@ export const type_builtins = [ export const module_builtins = [ "cal", "cfg", + "enc", "ext", "fts", "math", @@ -321,11 +331,11 @@ export const fn_builtins = [ "max", "mean", "min", - "multirange", + // "multirange", "multirange_unpack", "overlaps", "random", - "range", + // "range", "range_get_lower", "range_get_upper", "range_is_empty", @@ -337,6 +347,7 @@ export const fn_builtins = [ "re_replace", "re_test", "round", + "search", "sequence_next", "sequence_reset", "sqrt", @@ -363,6 +374,7 @@ export const fn_builtins = [ "sum", "time_get", "to_bigint", + "to_bytes", "to_date_duration", "to_datetime", "to_decimal", @@ -382,6 +394,17 @@ export const fn_builtins = [ "uuid_generate_v4", "var", "var_pop", + "with_options", +]; + +export const index_builtins = [ + "brin", + "btree", + "gin", + "gist", + "hash", + "index", + "spgist", ]; export const operators = [ diff --git a/shared/lang-edgeql/tokens.js b/shared/lang-edgeql/tokens.js index 2a8b5ed0..51f2988a 100644 --- a/shared/lang-edgeql/tokens.js +++ b/shared/lang-edgeql/tokens.js @@ -1,4 +1,4 @@ -import { ExternalTokenizer } from "@lezer/lr"; +import {ExternalTokenizer} from "@lezer/lr"; import { reservedKeyword, unreservedKeyword, @@ -16,6 +16,7 @@ import { constraint_builtins, fn_builtins, type_builtins, + index_builtins, } from "./meta.js"; const reservedKeywords = new Set(reserved_keywords); @@ -24,6 +25,7 @@ const builtins = new Set([ ...constraint_builtins, ...fn_builtins, ...type_builtins, + ...index_builtins, ]); const chars = { diff --git a/shared/schemaGraph/package.json b/shared/schemaGraph/package.json index b4402a8b..1e8d574f 100644 --- a/shared/schemaGraph/package.json +++ b/shared/schemaGraph/package.json @@ -5,7 +5,7 @@ "license": "UNLICENSED", "peerDependencies": { "@types/react": "^17.0.0", - "edgedb": "^1.2.0", + "edgedb": "^1.4.0", "react": "^17.0.0", "react-dom": "^17.0.0" }, diff --git a/shared/studio/components/dataEditor/dataEditor.module.scss b/shared/studio/components/dataEditor/dataEditor.module.scss index 57b794e8..8be9cc6b 100644 --- a/shared/studio/components/dataEditor/dataEditor.module.scss +++ b/shared/studio/components/dataEditor/dataEditor.module.scss @@ -422,6 +422,12 @@ } } + &.isMultirange { + &:before { + content: "multirange"; + } + } + .arrayItem { display: flex; align-items: flex-start; diff --git a/shared/studio/components/dataEditor/index.tsx b/shared/studio/components/dataEditor/index.tsx index 81a458e4..ecb74ba1 100644 --- a/shared/studio/components/dataEditor/index.tsx +++ b/shared/studio/components/dataEditor/index.tsx @@ -10,6 +10,7 @@ import styles from "./dataEditor.module.scss"; import {EmptySetIcon, SubmitChangesIcon} from "../../icons"; import { EditorArrayType, + EditorMultirangeType, EditorRangeType, EditorRangeValue, EditorTupleType, @@ -207,6 +208,8 @@ export function getInputComponent( Input = TupleEditor; } else if (type.schemaType === "Range") { Input = RangeEditor; + } else if (type.schemaType === "Multirange") { + Input = MultiRangeEditor; } else { Input = () => <>; } @@ -442,6 +445,77 @@ export const RangeEditor = forwardRef(function RangeEditor( ); }); +export const MultiRangeEditor = forwardRef(function MultiRangeEditor( + { + type, + value, + onChange, + depth, + }: { + type: EditorMultirangeType; + value: EditorValue[]; + onChange: (val: EditorValue[], error: boolean) => void; + depth: number; + }, + ref +) { + const [errs, setErrs] = useState( + Array(value?.length ?? 0).fill(false) + ); + + return ( +
+ {value.map((val, i) => { + return ( +
+ { + const newVal = [...value]; + const newErrs = [...errs]; + newVal[i] = val; + newErrs[i] = err; + setErrs(newErrs); + onChange(newVal, newErrs.includes(true)); + }} + /> +
{ + const newVal = [...value]; + const newErrs = [...errs]; + newVal.splice(i, 1); + newErrs.splice(i, 1); + setErrs(newErrs); + onChange(newVal, newErrs.includes(true)); + }} + > + +
+
+ ); + })} +
{ + const [val, err] = newPrimitiveValue(type.rangeType); + setErrs([...errs, err]); + onChange([...value, val], errs.includes(true)); + }} + > + + +
+
+ ); +}); + const EnumEditor = forwardRef(function EnumEditor( { type, @@ -670,7 +744,7 @@ const nullableInputs = new Map([ ), ] as [any, any] ), - ...[ArrayEditor, TupleEditor, RangeEditor].map( + ...[ArrayEditor, TupleEditor, RangeEditor, MultiRangeEditor].map( (Input: any) => [ Input, diff --git a/shared/studio/components/dataEditor/utils.ts b/shared/studio/components/dataEditor/utils.ts index bfb4373f..09d084b0 100644 --- a/shared/studio/components/dataEditor/utils.ts +++ b/shared/studio/components/dataEditor/utils.ts @@ -1,4 +1,4 @@ -import {Range} from "edgedb"; +import {MultiRange, Range} from "edgedb"; import {SchemaScalarType} from "@edgedb/common/schemaData"; import {assertNever} from "@edgedb/common/utils/assertNever"; @@ -28,9 +28,16 @@ export interface EditorRangeType { elementType: SchemaScalarType; } +export interface EditorMultirangeType { + schemaType: "Multirange"; + name: string; + rangeType: EditorRangeType; +} + export type PrimitiveType = | SchemaScalarType | EditorRangeType + | EditorMultirangeType | EditorArrayType | EditorTupleType; @@ -55,6 +62,7 @@ export function newPrimitiveValue( (type.knownBaseType ?? type).name !== "std::str", ]; case "Array": + case "Multirange": return [[], false]; case "Range": return [ @@ -130,6 +138,13 @@ export function valueToEditorValue( incUpper: value.incUpper, empty: value.isEmpty, }; + case "Multirange": + if (!(value instanceof MultiRange)) { + throw new Error(`Expected MultiRange value for multirange type`); + } + return [...value].map((range) => + valueToEditorValue(range, type.rangeType) + ); default: assertNever(schemaType); } @@ -200,6 +215,14 @@ export function parseEditorValue( val.incUpper ); } + case "Multirange": { + if (!Array.isArray(value)) { + throw new Error(`Expected array value for array type`); + } + return new MultiRange( + value.map((val) => parseEditorValue(val, type.rangeType)) + ); + } default: assertNever(schemaType); } diff --git a/shared/studio/package.json b/shared/studio/package.json index 1aeaf8d5..371b636e 100644 --- a/shared/studio/package.json +++ b/shared/studio/package.json @@ -23,7 +23,7 @@ "react-hook-form": "^7.32.2" }, "peerDependencies": { - "edgedb": "^1.3.1", + "edgedb": "^1.4.0", "react": "^17.0.0", "react-dom": "^17.0.0" }, diff --git a/shared/studio/tabs/dataview/dataInspector.tsx b/shared/studio/tabs/dataview/dataInspector.tsx index 8151c5e6..2158e074 100644 --- a/shared/studio/tabs/dataview/dataInspector.tsx +++ b/shared/studio/tabs/dataview/dataInspector.tsx @@ -14,7 +14,7 @@ import {VariableSizeGrid as Grid} from "react-window"; import {ICodec} from "edgedb/dist/codecs/ifaces"; import {EnumCodec} from "edgedb/dist/codecs/enum"; import {NamedTupleCodec} from "edgedb/dist/codecs/namedtuple"; -import {RangeCodec} from "edgedb/dist/codecs/range"; +import {MultiRangeCodec, RangeCodec} from "edgedb/dist/codecs/range"; import cn from "@edgedb/common/utils/classNames"; @@ -259,11 +259,12 @@ function renderCellValue(value: any, codec: ICodec): JSX.Element { switch (codec.getKind()) { case "scalar": case "range": + case "multirange": return renderValue( value, codec.getKnownTypeName(), codec instanceof EnumCodec, - codec instanceof RangeCodec + codec instanceof RangeCodec || codec instanceof MultiRangeCodec ? codec.getSubcodecs()[0].getKnownTypeName() : undefined, false, diff --git a/shared/studio/tabs/dataview/reviewEditsModal.tsx b/shared/studio/tabs/dataview/reviewEditsModal.tsx index a83e895c..e4b327b5 100644 --- a/shared/studio/tabs/dataview/reviewEditsModal.tsx +++ b/shared/studio/tabs/dataview/reviewEditsModal.tsx @@ -171,7 +171,9 @@ function renderParam({ value, type.name, type.schemaType === "Scalar" && !!type.enum_values, - type.schemaType === "Range" ? type.elementType.name : undefined, + type.schemaType === "Range" || type.schemaType === "Multirange" + ? type.elementType.name + : undefined, false ).body; } diff --git a/shared/studio/tabs/dataview/state/edits.ts b/shared/studio/tabs/dataview/state/edits.ts index 74e716d6..4f61ba9a 100644 --- a/shared/studio/tabs/dataview/state/edits.ts +++ b/shared/studio/tabs/dataview/state/edits.ts @@ -691,7 +691,11 @@ function generateParamExpr( .join(", ")}}`; } - if (type.schemaType === "Scalar" || type.schemaType === "Range") { + if ( + type.schemaType === "Scalar" || + type.schemaType === "Range" || + type.schemaType === "Multirange" + ) { const paramName = `p${Object.keys(params).length}`; params[paramName] = {type, value: data}; return `<${type.name}>$${paramName}`; diff --git a/shared/studio/tabs/queryEditor/state/extractQueryParameters.ts b/shared/studio/tabs/queryEditor/state/extractQueryParameters.ts index c279669a..3fb4351f 100644 --- a/shared/studio/tabs/queryEditor/state/extractQueryParameters.ts +++ b/shared/studio/tabs/queryEditor/state/extractQueryParameters.ts @@ -4,7 +4,10 @@ import {parser} from "@edgedb/lang-edgeql"; import {KnownScalarTypes, SchemaScalarType} from "@edgedb/common/schemaData"; import {getAllChildren, getNodeText} from "../../../utils/syntaxTree"; -import {PrimitiveType} from "../../../components/dataEditor/utils"; +import { + EditorRangeType, + PrimitiveType, +} from "../../../components/dataEditor/utils"; export type ResolvedParameter = | { @@ -77,6 +80,7 @@ function resolveCastType( }; } case "RangeType": { + const type = getNodeText(query, castNode.firstChild!); const elementType = resolveCastType( query, schemaScalars, @@ -86,13 +90,20 @@ function resolveCastType( elementType.schemaType !== "Scalar" || !validRangeScalars.has((elementType.knownBaseType ?? elementType).name) ) { - throw new Error("Invalid type in range type"); + throw new Error(`Invalid type in ${type} type`); } - return { + const rangeType: EditorRangeType = { schemaType: "Range", name: `range<${elementType.name}>`, elementType, }; + return type === "multirange" + ? { + schemaType: "Multirange", + name: `multirange<${elementType.name}>`, + rangeType, + } + : rangeType; } case "TupleType": { let elementNode = castNode.firstChild?.nextSibling ?? null; diff --git a/web/package.json b/web/package.json index b6c7f9b0..4f9e1eb2 100644 --- a/web/package.json +++ b/web/package.json @@ -14,7 +14,7 @@ "@types/react": "^17.0.20", "@types/react-dom": "^17.0.9", "buffer": "^6.0.3", - "edgedb": "^1.3.1", + "edgedb": "^1.4.0", "hash.js": "^1.1.7", "mobx": "^6.5.0", "mobx-keystone": "^0.67.2", diff --git a/yarn.lock b/yarn.lock index f35fe6e4..4b7571c2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1996,7 +1996,7 @@ __metadata: version: 0.0.0-use.local resolution: "@edgedb/common@workspace:shared/common" peerDependencies: - edgedb: ^1.2.0 + edgedb: ^1.4.0 react: ^17.0.0 react-dom: ^17.0.0 languageName: unknown @@ -2014,7 +2014,7 @@ __metadata: react-window: ^1.8.6 peerDependencies: "@types/react": ^16.9.34 - edgedb: ^1.3.0 + edgedb: ^1.4.0 react: ^17.0.0 react-dom: ^17.0.0 languageName: unknown @@ -2044,7 +2044,7 @@ __metadata: webcola: ^3.4.0 peerDependencies: "@types/react": ^17.0.0 - edgedb: ^1.2.0 + edgedb: ^1.4.0 react: ^17.0.0 react-dom: ^17.0.0 languageName: unknown @@ -2073,7 +2073,7 @@ __metadata: react-error-boundary: ^3.1.4 react-hook-form: ^7.32.2 peerDependencies: - edgedb: ^1.3.1 + edgedb: ^1.4.0 react: ^17.0.0 react-dom: ^17.0.0 languageName: unknown @@ -6487,12 +6487,12 @@ __metadata: languageName: node linkType: hard -"edgedb@npm:^1.3.1": - version: 1.3.1 - resolution: "edgedb@npm:1.3.1" +"edgedb@npm:^1.4.0": + version: 1.4.0 + resolution: "edgedb@npm:1.4.0" bin: edgeql-js: dist/cli.js - checksum: 35fcec5deffd5ed151cf3a9f2f517a83a4164415b8c6cf8be9155b4b7429a93079566c68b74128dbb14a668a723ab2e21cd8ecb40f80808743878c3114d65c00 + checksum: 1102299b12998c25ea152c9a6a7b5be59563799b814b00dc96b3630b5941e932d4578f58fa5f4e78945092773d2150af358e316f05da84fea30395a24a8568bd languageName: node linkType: hard @@ -14453,7 +14453,7 @@ __metadata: "@types/react-dom": ^17.0.9 "@types/selenium-webdriver": ^4.1.10 buffer: ^6.0.3 - edgedb: ^1.3.1 + edgedb: ^1.4.0 hash.js: ^1.1.7 jest: ^29.4.0 mobx: ^6.5.0