├── src ├── lang │ ├── type │ │ ├── index.js │ │ └── DataType.js │ ├── registry.js │ ├── expr │ │ ├── ref │ │ │ ├── abstracts │ │ │ │ ├── ErrorRefUnknown.js │ │ │ │ ├── ErrorRefAmbiguous.js │ │ │ │ ├── ErrorFKInvalid.js │ │ │ │ ├── AbstractMagicRef.js │ │ │ │ └── AbstractClassicRef.js │ │ │ ├── TableRef2.js │ │ │ ├── WindowRef.js │ │ │ ├── LQDeepDeepRef2.js │ │ │ ├── TableRef0.js │ │ │ ├── ColumnRef0.js │ │ │ ├── LQBackRefAbstraction.js │ │ │ ├── LQBackRefEndpoint.js │ │ │ ├── LQDeepRef2.js │ │ │ ├── Identifier.js │ │ │ ├── index.js │ │ │ ├── LQBackBackRef.js │ │ │ └── LQDeepDeepRef1.js │ │ ├── case │ │ │ ├── index.js │ │ │ ├── CaseBranch.js │ │ │ └── CaseExpr.js │ │ ├── var │ │ │ ├── index.js │ │ │ ├── BindVar.js │ │ │ ├── UserVar.js │ │ │ └── SystemVar.js │ │ ├── call │ │ │ ├── constructs │ │ │ │ ├── index.js │ │ │ │ ├── PGFilterClause.js │ │ │ │ └── PGWithinGroupClause.js │ │ │ └── index.js │ │ ├── AbstractClassicExpr.js │ │ ├── etc │ │ │ ├── index.js │ │ │ ├── PredicateExpr.js │ │ │ ├── QuantitativeExpr.js │ │ │ ├── ExtractExpr.js │ │ │ └── CastExpr.js │ │ ├── abstraction │ │ │ ├── index.js │ │ │ ├── TypedRowConstructor.js │ │ │ ├── ParenExpr.js │ │ │ └── ScalarSubquery.js │ │ ├── literals │ │ │ ├── NullLiteral.js │ │ │ ├── UnknownLiteral.js │ │ │ ├── DefaultLiteral.js │ │ │ ├── AbstractLiteral.js │ │ │ ├── TypedDateLiteral.js │ │ │ ├── BitLiteral.js │ │ │ ├── BoolLiteral.js │ │ │ ├── HexLiteral.js │ │ │ ├── TypedTimeZoneLiteral.js │ │ │ ├── NumberLiteral.js │ │ │ ├── AbstractLQJsonLiteral.js │ │ │ ├── StringLiteral.js │ │ │ ├── TypedLiteral.js │ │ │ ├── TypedTimeLiteral.js │ │ │ ├── TypedTimestampLiteral.js │ │ │ ├── index.js │ │ │ ├── PGTypedArrayLiteral.js │ │ │ └── LQArrayLiteral.js │ │ ├── op │ │ │ ├── index.js │ │ │ ├── InExpr.js │ │ │ ├── DistinctFromExpr.js │ │ │ ├── BetweenExpr.js │ │ │ ├── PGCastExpr2.js │ │ │ ├── UnaryExpr.js │ │ │ ├── AtTimeZoneExpr.js │ │ │ └── BinaryExpr.js │ │ ├── index.js │ │ └── Expr.js │ ├── ddl │ │ ├── index │ │ │ ├── index.js │ │ │ ├── IndexDiff.js │ │ │ └── IndexSchema.js │ │ ├── table │ │ │ ├── index.js │ │ │ └── TableDiff.js │ │ ├── column │ │ │ ├── index.js │ │ │ └── ColumnDiff.js │ │ ├── namespace │ │ │ ├── index.js │ │ │ ├── SchemaDiff.js │ │ │ └── NamespaceSchema.js │ │ ├── ident │ │ │ ├── NamespaceIdent.js │ │ │ ├── index.js │ │ │ ├── ColumnIdent.js │ │ │ └── TableIdent.js │ │ ├── constraint │ │ │ ├── constructs │ │ │ │ ├── PGIndexParameters.js │ │ │ │ ├── PGIndexParamUsing.js │ │ │ │ ├── FKMatchRule.js │ │ │ │ ├── FKDeleteRule.js │ │ │ │ ├── FKUpdateRule.js │ │ │ │ ├── index.js │ │ │ │ ├── PGIndexParamInclude.js │ │ │ │ ├── PGIndexParamWith.js │ │ │ │ ├── ReferentialAction.js │ │ │ │ └── PGTableEXConstraintItem.js │ │ │ ├── MYColumnCommentModifier.js │ │ │ ├── MYColumnVisibilityModifier.js │ │ │ ├── MYColumnOnUpdateModifier.js │ │ │ ├── ColumnDefaultConstraint.js │ │ │ ├── ColumnNullConstraint.js │ │ │ ├── MYColumnAutoIncrementModifier.js │ │ │ ├── ColumnPKConstraint.js │ │ │ ├── TablePKConstraint.js │ │ │ ├── CheckConstraint.js │ │ │ ├── index.js │ │ │ ├── ColumnExpressionConstraint.js │ │ │ ├── ColumnIdentityConstraint.js │ │ │ ├── ColumnFKConstraint.js │ │ │ ├── TableFKConstraint.js │ │ │ ├── TableUKConstraint.js │ │ │ ├── ColumnUKConstraint.js │ │ │ └── PGTableEXConstraint.js │ │ ├── index.js │ │ ├── DDLStmt.js │ │ ├── DropTableStmt.js │ │ ├── DropSchemaStmt.js │ │ └── CreateTableStmt.js │ ├── abstracts │ │ ├── SugarMixin.js │ │ ├── AbstractDiff.js │ │ ├── TypeSysMixin.js │ │ ├── JSONSchema.js │ │ ├── AbstractNodeList.js │ │ ├── AbstractStmt.js │ │ ├── ResultSchemaMixin.js │ │ ├── AbstractNonDDLStmt.js │ │ ├── OriginSchemasMixin.js │ │ ├── AbstractSchema.js │ │ └── util.js │ ├── qualif │ │ ├── index.js │ │ ├── LQVersionSpec.js │ │ └── AggrNotation.js │ ├── cte │ │ ├── constructs │ │ │ ├── index.js │ │ │ ├── PGSearchClause.js │ │ │ └── PGCycleClause.js │ │ ├── index.js │ │ ├── CTEItemAlias.js │ │ └── CTE.js │ ├── dml │ │ ├── TA │ │ │ └── index.js │ │ ├── constructors │ │ │ ├── index.js │ │ │ ├── ColumnsConstructor.js │ │ │ └── ValuesConstructor.js │ │ ├── expr │ │ │ ├── KW.js │ │ │ ├── index.js │ │ │ ├── MYVarAssignmentExpr.js │ │ │ ├── AssignmentExpr.js │ │ │ ├── ConfigAssignmentExpr.js │ │ │ ├── ConfigAssignmentExprAlt1.js │ │ │ └── ConfigAssignmentExprAlt2.js │ │ ├── clauses │ │ │ ├── ReturningClause.js │ │ │ ├── PGDefaultValuesClause.js │ │ │ ├── UsingFromClause.js │ │ │ ├── SetClause.js │ │ │ ├── ColumnsSpec.js │ │ │ ├── ValuesClause.js │ │ │ ├── MYPartitionClause.js │ │ │ ├── PGWhereCurrentClause.js │ │ │ ├── index.js │ │ │ ├── MYOnDuplicateKeyUpdateClause.js │ │ │ ├── PGConflictTargetIndexSpec.js │ │ │ ├── PGConflictTarget.js │ │ │ └── PGOnConflictClause.js │ │ ├── index.js │ │ ├── MYSetStmt.js │ │ ├── PGSetStmt.js │ │ └── DMLStmt.js │ ├── dql │ │ ├── clauses │ │ │ ├── FieldsSpec.js │ │ │ ├── Field.js │ │ │ ├── OnClause.js │ │ │ ├── WhereClause.js │ │ │ ├── FromClause.js │ │ │ ├── HavingClause.js │ │ │ ├── WindowClause.js │ │ │ ├── PGOrderOperator.js │ │ │ ├── WindowDeclaration.js │ │ │ ├── PartitionByClause.js │ │ │ ├── OffsetClause.js │ │ │ ├── UsingClause.js │ │ │ ├── OrderByClause.js │ │ │ ├── OrderElement.js │ │ │ ├── WindowSpec.js │ │ │ ├── WindowFrameBound.js │ │ │ ├── GroupByClause.js │ │ │ ├── DistinctClause.js │ │ │ ├── index.js │ │ │ ├── PGFetchClause.js │ │ │ ├── LimitClause.js │ │ │ ├── GroupingElement.js │ │ │ └── WindowFrameSpec.js │ │ ├── TA │ │ │ ├── ValuesTableLiteral.js │ │ │ ├── index.js │ │ │ ├── SRFExprDDL1.js │ │ │ ├── SRFExprDDL2.js │ │ │ ├── SelectItemAlias.js │ │ │ ├── FromItemAlias.js │ │ │ └── SRFExpr1.js │ │ ├── index.js │ │ ├── CompleteSelectStmt.js │ │ └── TableStmt.js │ ├── index.js │ └── Script.js ├── index.js ├── flashql │ ├── fetch │ │ ├── FlashRequest.js │ │ └── AbstractFetchClient.js │ └── ConflictError.js └── entry │ ├── Result.js │ └── abstracts │ ├── Spawnable.js │ └── SimpleEmitter.js ├── site ├── .vitepress │ ├── cache │ │ └── deps │ │ │ ├── package.json │ │ │ ├── vue.js.map │ │ │ ├── vitepress___@vueuse_core.js.map │ │ │ └── _metadata.json │ ├── dist │ │ ├── img │ │ │ └── brand │ │ │ │ ├── linked-ql-logo.png │ │ │ │ ├── linked-ql-main.png │ │ │ │ ├── linked-ql-min.png │ │ │ │ ├── linked-ql-min2.png │ │ │ │ └── linked-ql-main2.png │ │ ├── assets │ │ │ ├── inter-italic-greek.DJ8dCoTZ.woff2 │ │ │ ├── inter-italic-latin.C2AdPX0b.woff2 │ │ │ ├── inter-roman-greek.BBVDIX6e.woff2 │ │ │ ├── inter-roman-latin.Di8DUHzh.woff2 │ │ │ ├── inter-italic-cyrillic.By2_1cv3.woff2 │ │ │ ├── inter-roman-cyrillic.C5lxZ8CY.woff2 │ │ │ ├── inter-roman-greek-ext.CqjqNYQ-.woff2 │ │ │ ├── inter-roman-latin-ext.4ZJIpNVo.woff2 │ │ │ ├── inter-italic-greek-ext.1u6EdAuj.woff2 │ │ │ ├── inter-italic-latin-ext.CN1xVJS-.woff2 │ │ │ ├── inter-italic-vietnamese.BSbpV94h.woff2 │ │ │ ├── inter-roman-vietnamese.BjW4sHH5.woff2 │ │ │ ├── inter-italic-cyrillic-ext.r48I6akx.woff2 │ │ │ ├── inter-roman-cyrillic-ext.BBPuwvHQ.woff2 │ │ │ ├── flashql.md.dxGRqIGO.lean.js │ │ │ ├── docs.md.CwIgAZwB.lean.js │ │ │ ├── docs_setup.md.xW8pIM-m.lean.js │ │ │ ├── capabilities.md.BztTe5GT.lean.js │ │ │ ├── flashql_lang.md.-dKEfD4V.lean.js │ │ │ ├── docs_query-api.md.Bm8hN7oZ.lean.js │ │ │ ├── capabilities_upsert.md.hDNJkkyH.lean.js │ │ │ ├── overview.md.CIcdfHfj.lean.js │ │ │ ├── capabilities_deeprefs.md.CYOx2SXL.lean.js │ │ │ ├── flashql_foreign-io.md.B-X4SFru.lean.js │ │ │ ├── capabilities_live-queries.md.CHhoCYV3.lean.js │ │ │ ├── capabilities_json-literals.md.rGE9X-tr.lean.js │ │ │ ├── app.Ds4M_nwI.js │ │ │ ├── index.md.BsUu5Xl8.js │ │ │ └── index.md.BsUu5Xl8.lean.js │ │ ├── hashmap.json │ │ └── vp-icons.css │ └── theme │ │ ├── index.ts │ │ └── custom.css ├── public │ └── img │ │ └── brand │ │ ├── linked-ql-min.png │ │ ├── linked-ql-logo.png │ │ ├── linked-ql-main.png │ │ ├── linked-ql-main2.png │ │ └── linked-ql-min2.png └── index.md ├── resources ├── linked-ql-logo-2.af ├── linked-ql-logo.af ├── linked-ql-logo.png ├── linked-ql-main.png ├── linked-ql-main2.png ├── linked-ql-min.png ├── linked-ql-min2.png ├── linked-ql-main-a.png ├── linked-ql-main-b.png ├── linked-ql-main-c.png ├── linked-ql-mobile.png ├── linked-ql-mobile2.png ├── linked-ql-logo.afdesign ├── linked-ql-main.afdesign ├── linked-ql-main2.afdesign ├── linked-ql-min.afdesign ├── linked-ql-min2.afdesign ├── linked-ql-mobile-a.png ├── linked-ql-mobile.afdesign └── linked-ql-mobile2.afdesign ├── .gitignore ├── .eslintrc.yml ├── test ├── 00.live 2.js └── 00.live.js ├── .github ├── FUNDING.yml └── workflows │ └── publish.yml └── LICENSE /src/lang/type/index.js: -------------------------------------------------------------------------------- 1 | export { DataType } from './DataType.js'; 2 | -------------------------------------------------------------------------------- /src/lang/registry.js: -------------------------------------------------------------------------------- 1 | export const registry = Object.create(null); 2 | -------------------------------------------------------------------------------- /site/.vitepress/cache/deps/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "module" 3 | } 4 | -------------------------------------------------------------------------------- /src/lang/expr/ref/abstracts/ErrorRefUnknown.js: -------------------------------------------------------------------------------- 1 | export class ErrorRefUnknown extends Error {} -------------------------------------------------------------------------------- /src/lang/expr/ref/abstracts/ErrorRefAmbiguous.js: -------------------------------------------------------------------------------- 1 | export class ErrorRefAmbiguous extends Error {} -------------------------------------------------------------------------------- /resources/linked-ql-logo-2.af: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/resources/linked-ql-logo-2.af -------------------------------------------------------------------------------- /resources/linked-ql-logo.af: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/resources/linked-ql-logo.af -------------------------------------------------------------------------------- /resources/linked-ql-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/resources/linked-ql-logo.png -------------------------------------------------------------------------------- /resources/linked-ql-main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/resources/linked-ql-main.png -------------------------------------------------------------------------------- /resources/linked-ql-main2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/resources/linked-ql-main2.png -------------------------------------------------------------------------------- /resources/linked-ql-min.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/resources/linked-ql-min.png -------------------------------------------------------------------------------- /resources/linked-ql-min2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/resources/linked-ql-min2.png -------------------------------------------------------------------------------- /resources/linked-ql-main-a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/resources/linked-ql-main-a.png -------------------------------------------------------------------------------- /resources/linked-ql-main-b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/resources/linked-ql-main-b.png -------------------------------------------------------------------------------- /resources/linked-ql-main-c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/resources/linked-ql-main-c.png -------------------------------------------------------------------------------- /resources/linked-ql-mobile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/resources/linked-ql-mobile.png -------------------------------------------------------------------------------- /resources/linked-ql-mobile2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/resources/linked-ql-mobile2.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .* 2 | !/.github 3 | !.vitepress 4 | !/.gitignore 5 | !.eslintrc.yml 6 | coverage 7 | demo 8 | node_modules 9 | -------------------------------------------------------------------------------- /resources/linked-ql-logo.afdesign: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/resources/linked-ql-logo.afdesign -------------------------------------------------------------------------------- /resources/linked-ql-main.afdesign: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/resources/linked-ql-main.afdesign -------------------------------------------------------------------------------- /resources/linked-ql-main2.afdesign: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/resources/linked-ql-main2.afdesign -------------------------------------------------------------------------------- /resources/linked-ql-min.afdesign: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/resources/linked-ql-min.afdesign -------------------------------------------------------------------------------- /resources/linked-ql-min2.afdesign: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/resources/linked-ql-min2.afdesign -------------------------------------------------------------------------------- /resources/linked-ql-mobile-a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/resources/linked-ql-mobile-a.png -------------------------------------------------------------------------------- /src/lang/expr/case/index.js: -------------------------------------------------------------------------------- 1 | export { CaseExpr } from './CaseExpr.js'; 2 | export { CaseBranch } from './CaseBranch.js'; 3 | -------------------------------------------------------------------------------- /resources/linked-ql-mobile.afdesign: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/resources/linked-ql-mobile.afdesign -------------------------------------------------------------------------------- /resources/linked-ql-mobile2.afdesign: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/resources/linked-ql-mobile2.afdesign -------------------------------------------------------------------------------- /src/lang/ddl/index/index.js: -------------------------------------------------------------------------------- 1 | export { IndexDiff } from './IndexDiff.js'; 2 | export { IndexSchema } from './IndexSchema.js'; 3 | -------------------------------------------------------------------------------- /src/lang/ddl/table/index.js: -------------------------------------------------------------------------------- 1 | export { TableDiff } from './TableDiff.js'; 2 | export { TableSchema } from './TableSchema.js'; 3 | -------------------------------------------------------------------------------- /site/public/img/brand/linked-ql-min.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/site/public/img/brand/linked-ql-min.png -------------------------------------------------------------------------------- /src/lang/abstracts/SugarMixin.js: -------------------------------------------------------------------------------- 1 | export const SugarMixin = Class => class extends Class { 2 | get isSugar() { return true; } 3 | } -------------------------------------------------------------------------------- /src/lang/ddl/column/index.js: -------------------------------------------------------------------------------- 1 | export { ColumnDiff } from './ColumnDiff.js'; 2 | export { ColumnSchema } from './ColumnSchema.js'; 3 | -------------------------------------------------------------------------------- /site/public/img/brand/linked-ql-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/site/public/img/brand/linked-ql-logo.png -------------------------------------------------------------------------------- /site/public/img/brand/linked-ql-main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/site/public/img/brand/linked-ql-main.png -------------------------------------------------------------------------------- /site/public/img/brand/linked-ql-main2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/site/public/img/brand/linked-ql-main2.png -------------------------------------------------------------------------------- /site/public/img/brand/linked-ql-min2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/site/public/img/brand/linked-ql-min2.png -------------------------------------------------------------------------------- /src/lang/qualif/index.js: -------------------------------------------------------------------------------- 1 | export { AggrNotation } from './AggrNotation.js'; 2 | export { LQVersionSpec } from './LQVersionSpec.js'; 3 | -------------------------------------------------------------------------------- /src/lang/ddl/namespace/index.js: -------------------------------------------------------------------------------- 1 | export { SchemaDiff } from './SchemaDiff.js'; 2 | export { NamespaceSchema } from './NamespaceSchema.js'; 3 | -------------------------------------------------------------------------------- /src/lang/cte/constructs/index.js: -------------------------------------------------------------------------------- 1 | export { PGCycleClause } from './PGCycleClause.js'; 2 | export { PGSearchClause } from './PGSearchClause.js'; 3 | -------------------------------------------------------------------------------- /site/.vitepress/dist/img/brand/linked-ql-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/site/.vitepress/dist/img/brand/linked-ql-logo.png -------------------------------------------------------------------------------- /site/.vitepress/dist/img/brand/linked-ql-main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/site/.vitepress/dist/img/brand/linked-ql-main.png -------------------------------------------------------------------------------- /site/.vitepress/dist/img/brand/linked-ql-min.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/site/.vitepress/dist/img/brand/linked-ql-min.png -------------------------------------------------------------------------------- /site/.vitepress/dist/img/brand/linked-ql-min2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/site/.vitepress/dist/img/brand/linked-ql-min2.png -------------------------------------------------------------------------------- /src/lang/ddl/column/ColumnDiff.js: -------------------------------------------------------------------------------- 1 | import { AbstractDiff } from '../../abstracts/AbstractDiff.js'; 2 | 3 | export class ColumnDiff extends AbstractDiff {} -------------------------------------------------------------------------------- /src/lang/ddl/index/IndexDiff.js: -------------------------------------------------------------------------------- 1 | import { AbstractDiff } from '../../abstracts/AbstractDiff.js'; 2 | 3 | export class IndexDiff extends AbstractDiff {} -------------------------------------------------------------------------------- /src/lang/ddl/table/TableDiff.js: -------------------------------------------------------------------------------- 1 | import { AbstractDiff } from '../../abstracts/AbstractDiff.js'; 2 | 3 | export class TableDiff extends AbstractDiff {} -------------------------------------------------------------------------------- /src/lang/dml/TA/index.js: -------------------------------------------------------------------------------- 1 | export { TableAbstraction2 } from './TableAbstraction2.js'; 2 | export { TableAbstraction1 } from './TableAbstraction1.js'; 3 | -------------------------------------------------------------------------------- /site/.vitepress/cache/deps/vue.js.map: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "sources": [], 4 | "sourcesContent": [], 5 | "mappings": "", 6 | "names": [] 7 | } 8 | -------------------------------------------------------------------------------- /site/.vitepress/dist/img/brand/linked-ql-main2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/site/.vitepress/dist/img/brand/linked-ql-main2.png -------------------------------------------------------------------------------- /src/lang/ddl/ident/NamespaceIdent.js: -------------------------------------------------------------------------------- 1 | import { Identifier } from '../../expr/ref/Identifier.js'; 2 | 3 | export class NamespaceIdent extends Identifier {} 4 | -------------------------------------------------------------------------------- /src/lang/ddl/namespace/SchemaDiff.js: -------------------------------------------------------------------------------- 1 | import { AbstractDiff } from '../../abstracts/AbstractDiff.js'; 2 | 3 | export class SchemaDiff extends AbstractDiff {} -------------------------------------------------------------------------------- /site/.vitepress/theme/index.ts: -------------------------------------------------------------------------------- 1 | import DefaultTheme from 'vitepress/theme' 2 | import './custom.css' 3 | 4 | export default { 5 | extends: DefaultTheme 6 | } 7 | -------------------------------------------------------------------------------- /src/lang/expr/var/index.js: -------------------------------------------------------------------------------- 1 | export { BindVar } from './BindVar.js'; 2 | export { SystemVar } from './SystemVar.js'; 3 | export { UserVar } from './UserVar.js'; 4 | -------------------------------------------------------------------------------- /src/lang/dml/constructors/index.js: -------------------------------------------------------------------------------- 1 | export { ColumnsConstructor } from './ColumnsConstructor.js'; 2 | export { ValuesConstructor } from './ValuesConstructor.js'; 3 | -------------------------------------------------------------------------------- /src/lang/expr/call/constructs/index.js: -------------------------------------------------------------------------------- 1 | export { PGFilterClause } from './PGFilterClause.js'; 2 | export { PGWithinGroupClause } from './PGWithinGroupClause.js'; 3 | -------------------------------------------------------------------------------- /src/lang/expr/call/index.js: -------------------------------------------------------------------------------- 1 | export * from './constructs/index.js'; 2 | export { AggrCallExpr } from './AggrCallExpr.js'; 3 | export { CallExpr } from './CallExpr.js'; 4 | -------------------------------------------------------------------------------- /.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | browser: true 3 | es2021: true 4 | extends: 'eslint:recommended' 5 | parserOptions: 6 | ecmaVersion: 12 7 | sourceType: module 8 | rules: {} 9 | -------------------------------------------------------------------------------- /site/.vitepress/dist/assets/inter-italic-greek.DJ8dCoTZ.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/site/.vitepress/dist/assets/inter-italic-greek.DJ8dCoTZ.woff2 -------------------------------------------------------------------------------- /site/.vitepress/dist/assets/inter-italic-latin.C2AdPX0b.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/site/.vitepress/dist/assets/inter-italic-latin.C2AdPX0b.woff2 -------------------------------------------------------------------------------- /site/.vitepress/dist/assets/inter-roman-greek.BBVDIX6e.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/site/.vitepress/dist/assets/inter-roman-greek.BBVDIX6e.woff2 -------------------------------------------------------------------------------- /site/.vitepress/dist/assets/inter-roman-latin.Di8DUHzh.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/site/.vitepress/dist/assets/inter-roman-latin.Di8DUHzh.woff2 -------------------------------------------------------------------------------- /site/.vitepress/cache/deps/vitepress___@vueuse_core.js.map: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "sources": [], 4 | "sourcesContent": [], 5 | "mappings": "", 6 | "names": [] 7 | } 8 | -------------------------------------------------------------------------------- /site/.vitepress/dist/assets/inter-italic-cyrillic.By2_1cv3.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/site/.vitepress/dist/assets/inter-italic-cyrillic.By2_1cv3.woff2 -------------------------------------------------------------------------------- /site/.vitepress/dist/assets/inter-roman-cyrillic.C5lxZ8CY.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/site/.vitepress/dist/assets/inter-roman-cyrillic.C5lxZ8CY.woff2 -------------------------------------------------------------------------------- /site/.vitepress/dist/assets/inter-roman-greek-ext.CqjqNYQ-.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/site/.vitepress/dist/assets/inter-roman-greek-ext.CqjqNYQ-.woff2 -------------------------------------------------------------------------------- /site/.vitepress/dist/assets/inter-roman-latin-ext.4ZJIpNVo.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/site/.vitepress/dist/assets/inter-roman-latin-ext.4ZJIpNVo.woff2 -------------------------------------------------------------------------------- /site/.vitepress/dist/assets/inter-italic-greek-ext.1u6EdAuj.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/site/.vitepress/dist/assets/inter-italic-greek-ext.1u6EdAuj.woff2 -------------------------------------------------------------------------------- /site/.vitepress/dist/assets/inter-italic-latin-ext.CN1xVJS-.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/site/.vitepress/dist/assets/inter-italic-latin-ext.CN1xVJS-.woff2 -------------------------------------------------------------------------------- /site/.vitepress/dist/assets/inter-italic-vietnamese.BSbpV94h.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/site/.vitepress/dist/assets/inter-italic-vietnamese.BSbpV94h.woff2 -------------------------------------------------------------------------------- /site/.vitepress/dist/assets/inter-roman-vietnamese.BjW4sHH5.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/site/.vitepress/dist/assets/inter-roman-vietnamese.BjW4sHH5.woff2 -------------------------------------------------------------------------------- /src/lang/abstracts/AbstractDiff.js: -------------------------------------------------------------------------------- 1 | import { AbstractNodeList } from './AbstractNodeList.js'; 2 | 3 | export class AbstractDiff extends AbstractNodeList { 4 | 5 | /* AST API */ 6 | } -------------------------------------------------------------------------------- /src/lang/ddl/ident/index.js: -------------------------------------------------------------------------------- 1 | export { ColumnIdent } from './ColumnIdent.js'; 2 | export { NamespaceIdent } from './NamespaceIdent.js'; 3 | export { TableIdent } from './TableIdent.js'; 4 | -------------------------------------------------------------------------------- /site/.vitepress/dist/assets/inter-italic-cyrillic-ext.r48I6akx.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/site/.vitepress/dist/assets/inter-italic-cyrillic-ext.r48I6akx.woff2 -------------------------------------------------------------------------------- /site/.vitepress/dist/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linked-db/linked-ql/HEAD/site/.vitepress/dist/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2 -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import './lang/index.js'; 2 | import { FlashQL } from './flashql/FlashQL.js'; 3 | import { Script } from './lang/Script.js'; 4 | 5 | export { FlashQL } 6 | export { Script }; 7 | -------------------------------------------------------------------------------- /src/lang/expr/ref/TableRef2.js: -------------------------------------------------------------------------------- 1 | import { TableRef1 } from './TableRef1.js'; 2 | 3 | export class TableRef2 extends TableRef1 { 4 | 5 | canReferenceInlineTables() { return false; } 6 | } -------------------------------------------------------------------------------- /src/lang/cte/index.js: -------------------------------------------------------------------------------- 1 | export * from './constructs/index.js'; 2 | export { CTE } from './CTE.js'; 3 | export { CTEItem } from './CTEItem.js'; 4 | export { CTEItemAlias } from './CTEItemAlias.js'; 5 | -------------------------------------------------------------------------------- /src/lang/expr/ref/abstracts/ErrorFKInvalid.js: -------------------------------------------------------------------------------- 1 | export class ErrorFKInvalid extends Error { 2 | 3 | constructor(message) { 4 | super(message); 5 | this.name = 'ErrorFKInvalid'; 6 | } 7 | 8 | } -------------------------------------------------------------------------------- /src/flashql/fetch/FlashRequest.js: -------------------------------------------------------------------------------- 1 | import { JSONSchema } from '../../lang/abstracts/JSONSchema.js'; 2 | 3 | export class FlashRequest extends Request { 4 | resultSchema() { 5 | return new JSONSchema 6 | } 7 | } -------------------------------------------------------------------------------- /src/lang/expr/ref/WindowRef.js: -------------------------------------------------------------------------------- 1 | import { Identifier } from './Identifier.js'; 2 | 3 | export class WindowRef extends Identifier { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxPriority() { return -1; } 8 | } -------------------------------------------------------------------------------- /src/lang/abstracts/TypeSysMixin.js: -------------------------------------------------------------------------------- 1 | import { registry } from '../registry.js'; 2 | 3 | export const TypeSysMixin = (Class) => class extends Class { 4 | 5 | dataType() { return registry.DataType.fromJSON({ value: 'TEXT' }); }; 6 | } -------------------------------------------------------------------------------- /src/lang/expr/AbstractClassicExpr.js: -------------------------------------------------------------------------------- 1 | import { TypeSysMixin } from '../abstracts/TypeSysMixin.js'; 2 | import { AbstractNode } from '../abstracts/AbstractNode.js'; 3 | 4 | export class AbstractClassicExpr extends TypeSysMixin(AbstractNode) {} -------------------------------------------------------------------------------- /src/lang/expr/etc/index.js: -------------------------------------------------------------------------------- 1 | export { CastExpr } from './CastExpr.js'; 2 | export { ExtractExpr } from './ExtractExpr.js'; 3 | export { PredicateExpr } from './PredicateExpr.js'; 4 | export { QuantitativeExpr } from './QuantitativeExpr.js'; 5 | -------------------------------------------------------------------------------- /src/lang/expr/abstraction/index.js: -------------------------------------------------------------------------------- 1 | export { ParenExpr } from './ParenExpr.js'; 2 | export { RowConstructor } from './RowConstructor.js'; 3 | export { ScalarSubquery } from './ScalarSubquery.js'; 4 | export { TypedRowConstructor } from './TypedRowConstructor.js'; 5 | -------------------------------------------------------------------------------- /src/lang/dql/clauses/FieldsSpec.js: -------------------------------------------------------------------------------- 1 | import { AbstractNodeList } from '../../expr/abstracts/AbstractNodeList.js'; 2 | import { Field } from './Field.js'; 3 | 4 | export class FieldsSpec extends AbstractNodeList { 5 | static get EXPECTED_TYPES() { return [Field]; } 6 | } -------------------------------------------------------------------------------- /src/lang/expr/literals/NullLiteral.js: -------------------------------------------------------------------------------- 1 | import { AbstractLiteral } from './AbstractLiteral.js'; 2 | 3 | export class NullLiteral extends AbstractLiteral { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { return { type: 'null_literal', as: '.' }; } 8 | } -------------------------------------------------------------------------------- /src/lang/dql/clauses/Field.js: -------------------------------------------------------------------------------- 1 | import { AbstractAliasableExpr } from '../../expr/abstracts/AbstractAliasableExpr.js'; 2 | import { Exprs } from '../../expr/grammar.js'; 3 | 4 | export class Field extends AbstractAliasableExpr { 5 | static get EXPECTED_TYPES() { return Exprs; } 6 | } -------------------------------------------------------------------------------- /src/lang/expr/literals/UnknownLiteral.js: -------------------------------------------------------------------------------- 1 | import { AbstractLiteral } from './AbstractLiteral.js'; 2 | 3 | export class UnknownLiteral extends AbstractLiteral { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { return { type: 'unknown_literal', as: '.' }; } 8 | } -------------------------------------------------------------------------------- /src/flashql/ConflictError.js: -------------------------------------------------------------------------------- 1 | export class ConflictError extends Error { 2 | 3 | #existing; 4 | get existing() { return this.#existing; } 5 | 6 | constructor(message, existing) { 7 | super(message); 8 | this.#existing = existing; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/lang/expr/literals/DefaultLiteral.js: -------------------------------------------------------------------------------- 1 | import { AbstractLiteral } from './AbstractLiteral.js'; 2 | 3 | export class DefaultLiteral extends AbstractLiteral { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { return { type: 'keyword', as: '.', value: 'DEFAULT' }; } 8 | } -------------------------------------------------------------------------------- /src/lang/ddl/ident/ColumnIdent.js: -------------------------------------------------------------------------------- 1 | import { PathMixin } from '../../abstracts/PathMixin.js'; 2 | import { Identifier } from '../../expr/index.js'; 3 | 4 | export class ColumnIdent extends PathMixin(Identifier) { 5 | 6 | /* SYNTAX RULES */ 7 | 8 | static get _qualifierType() { return 'TableRef2'; } 9 | } -------------------------------------------------------------------------------- /src/lang/ddl/ident/TableIdent.js: -------------------------------------------------------------------------------- 1 | import { PathMixin } from '../../abstracts/PathMixin.js'; 2 | import { Identifier } from '../../expr/index.js'; 3 | 4 | export class TableIdent extends PathMixin(Identifier) { 5 | 6 | /* SYNTAX RULES */ 7 | 8 | static get _qualifierType() { return 'NamespaceRef'; } 9 | } -------------------------------------------------------------------------------- /src/lang/dml/expr/KW.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../abstracts/AbstractNode.js'; 2 | 3 | export class KW extends AbstractNode { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { return { type: 'keyword', as: '.' }; } 8 | 9 | /* AST API */ 10 | 11 | value() { return this._get('value'); } 12 | } -------------------------------------------------------------------------------- /src/lang/expr/var/BindVar.js: -------------------------------------------------------------------------------- 1 | import { AbstractClassicExpr } from '../AbstractClassicExpr.js'; 2 | 3 | export class BindVar extends AbstractClassicExpr { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { return { type: 'bind_var', as: '.' }; } 8 | 9 | /* AST API */ 10 | 11 | value() { return this._get('value'); } 12 | } -------------------------------------------------------------------------------- /src/lang/ddl/index/IndexSchema.js: -------------------------------------------------------------------------------- 1 | import { AbstractSchema } from '../../abstracts/AbstractSchema.js'; 2 | 3 | export class IndexSchema extends AbstractSchema { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return [ 9 | { type: 'Identifier', as: 'name', assert: true }, 10 | ]; 11 | } 12 | } -------------------------------------------------------------------------------- /src/lang/expr/literals/AbstractLiteral.js: -------------------------------------------------------------------------------- 1 | import { AbstractClassicExpr } from '../AbstractClassicExpr.js'; 2 | 3 | export class AbstractLiteral extends AbstractClassicExpr { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxPriority() { return 49; } 8 | 9 | /* AST API */ 10 | 11 | value() { return this._get('value'); } 12 | } -------------------------------------------------------------------------------- /src/lang/expr/var/UserVar.js: -------------------------------------------------------------------------------- 1 | import { AbstractClassicExpr } from '../AbstractClassicExpr.js'; 2 | 3 | export class UserVar extends AbstractClassicExpr { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { return { type: 'user_var', as: '.' }; } 8 | 9 | /* AST API */ 10 | 11 | value() { return this._get('value'); } 12 | } -------------------------------------------------------------------------------- /src/lang/expr/var/SystemVar.js: -------------------------------------------------------------------------------- 1 | import { AbstractClassicExpr } from '../AbstractClassicExpr.js'; 2 | 3 | export class SystemVar extends AbstractClassicExpr { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { return { type: 'system_var', as: '.' }; } 8 | 9 | /* AST API */ 10 | 11 | value() { return this._get('value'); } 12 | } -------------------------------------------------------------------------------- /src/lang/dql/TA/ValuesTableLiteral.js: -------------------------------------------------------------------------------- 1 | import { ValuesConstructor } from '../../dml/constructors/ValuesConstructor.js'; 2 | 3 | export class ValuesTableLiteral extends ValuesConstructor { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return { type: 'paren_block', syntax: super.syntaxRules, autoIndent: true }; 9 | } 10 | } -------------------------------------------------------------------------------- /src/lang/dql/index.js: -------------------------------------------------------------------------------- 1 | export * from './clauses/index.js'; 2 | export * from './TA/index.js'; 3 | export { CompleteSelectStmt } from './CompleteSelectStmt.js'; 4 | export { BasicSelectStmt } from './BasicSelectStmt.js'; 5 | export { CompositeSelectStmt } from './CompositeSelectStmt.js'; 6 | export { SelectStmt } from './SelectStmt.js'; 7 | export { TableStmt } from './TableStmt.js'; 8 | -------------------------------------------------------------------------------- /src/entry/Result.js: -------------------------------------------------------------------------------- 1 | export class Result { 2 | 3 | #rows 4 | #rowCount 5 | 6 | get rows() { return this.#rows; } 7 | get rowCount() { return this.#rowCount; } 8 | get affectedRows() { return this.#rowCount; } 9 | 10 | constructor({ rows = [], rowCount = 0 } = {}) { 11 | this.#rows = rows; 12 | this.#rowCount = rowCount; 13 | } 14 | } -------------------------------------------------------------------------------- /src/lang/expr/op/index.js: -------------------------------------------------------------------------------- 1 | export { AtTimeZoneExpr } from './AtTimeZoneExpr.js'; 2 | export { BetweenExpr } from './BetweenExpr.js'; 3 | export { BinaryExpr } from './BinaryExpr.js'; 4 | export { DistinctFromExpr } from './DistinctFromExpr.js'; 5 | export { InExpr } from './InExpr.js'; 6 | export { PGCastExpr2 } from './PGCastExpr2.js'; 7 | export { UnaryExpr } from './UnaryExpr.js'; 8 | -------------------------------------------------------------------------------- /src/lang/dml/clauses/ReturningClause.js: -------------------------------------------------------------------------------- 1 | import { SelectList } from '../../dql/clauses/SelectList.js'; 2 | 3 | export class ReturningClause extends SelectList { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return [ 9 | { type: 'keyword', value: 'RETURNING' }, 10 | ...[].concat(super.syntaxRules), 11 | ]; 12 | } 13 | } -------------------------------------------------------------------------------- /src/lang/abstracts/JSONSchema.js: -------------------------------------------------------------------------------- 1 | import { AbstractNodeList } from './AbstractNodeList.js'; 2 | 3 | export class JSONSchema extends AbstractNodeList { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return { type: ['JSONSchema', 'TableSchema', 'ColumnSchema', 'ColumnRef1'/* result of resolving ColumnRef0 */], as: 'entries', arity: Infinity }; 9 | } 10 | } -------------------------------------------------------------------------------- /src/lang/dml/expr/index.js: -------------------------------------------------------------------------------- 1 | export { AssignmentExpr } from './AssignmentExpr.js'; 2 | export { ConfigAssignmentExpr } from './ConfigAssignmentExpr.js'; 3 | export { ConfigAssignmentExprAlt1 } from './ConfigAssignmentExprAlt1.js'; 4 | export { ConfigAssignmentExprAlt2 } from './ConfigAssignmentExprAlt2.js'; 5 | export { MYVarAssignmentExpr } from './MYVarAssignmentExpr.js'; 6 | export { KW } from './KW.js'; 7 | -------------------------------------------------------------------------------- /src/lang/expr/literals/TypedDateLiteral.js: -------------------------------------------------------------------------------- 1 | import { TypedLiteral } from './TypedLiteral.js'; 2 | 3 | export class TypedDateLiteral extends TypedLiteral { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return [ 9 | { type: 'data_type', as: 'data_type', value: 'DATE' }, 10 | { type: 'string_literal', as: 'value' }, 11 | ]; 12 | } 13 | } -------------------------------------------------------------------------------- /src/lang/qualif/LQVersionSpec.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../abstracts/AbstractNode.js'; 2 | 3 | export class LQVersionSpec extends AbstractNode { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { return { type: 'version_spec', as: '.' }; } 8 | 9 | static get syntaxPriority() { return -1; } 10 | 11 | /* AST API */ 12 | 13 | value() { return this._get('value'); } 14 | } -------------------------------------------------------------------------------- /site/.vitepress/dist/assets/flashql.md.dxGRqIGO.lean.js: -------------------------------------------------------------------------------- 1 | import{_ as a,c as n,o as l,ag as e}from"./chunks/framework.B-XtCDNB.js";const d=JSON.parse('{"title":"FlashQL","description":"","frontmatter":{},"headers":[],"relativePath":"flashql.md","filePath":"flashql.md"}'),p={name:"flashql.md"};function o(t,s,r,c,i,y){return l(),n("div",null,[...s[0]||(s[0]=[e("",46)])])}const F=a(p,[["render",o]]);export{d as __pageData,F as default}; 2 | -------------------------------------------------------------------------------- /src/lang/qualif/AggrNotation.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../abstracts/AbstractNode.js'; 2 | 3 | export class AggrNotation extends AbstractNode { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return { 9 | type: 'bracket_block', syntax: { type: 'Expr', as: '_', arity: 0, assert: true } 10 | }; 11 | } 12 | 13 | static get syntaxPriority() { return -1; } 14 | } -------------------------------------------------------------------------------- /site/.vitepress/dist/assets/docs.md.CwIgAZwB.lean.js: -------------------------------------------------------------------------------- 1 | import{_ as a,c as n,o as e,ag as l}from"./chunks/framework.B-XtCDNB.js";const D=JSON.parse('{"title":"Getting Started with LinkedQL","description":"","frontmatter":{},"headers":[],"relativePath":"docs.md","filePath":"docs.md"}'),t={name:"docs.md"};function o(p,s,r,i,c,d){return e(),n("div",null,[...s[0]||(s[0]=[l("",28)])])}const F=a(t,[["render",o]]);export{D as __pageData,F as default}; 2 | -------------------------------------------------------------------------------- /src/lang/expr/literals/BitLiteral.js: -------------------------------------------------------------------------------- 1 | import { AbstractLiteral } from './AbstractLiteral.js'; 2 | import { registry } from '../../registry.js'; 3 | 4 | export class BitLiteral extends AbstractLiteral { 5 | 6 | /* SYNTAX RULES */ 7 | 8 | static get syntaxRules() { return { type: 'bit_literal', as: '.' }; } 9 | 10 | /* TYPESYS API */ 11 | 12 | dataType() { return registry.DataType.fromJSON({ value: 'BINARY' }); } 13 | } -------------------------------------------------------------------------------- /src/lang/expr/literals/BoolLiteral.js: -------------------------------------------------------------------------------- 1 | import { AbstractLiteral } from './AbstractLiteral.js'; 2 | import { registry } from '../../registry.js'; 3 | 4 | export class BoolLiteral extends AbstractLiteral { 5 | 6 | /* SYNTAX RULES */ 7 | 8 | static get syntaxRules() { return { type: 'bool_literal', as: '.' }; } 9 | 10 | /* TYPESYS API */ 11 | 12 | dataType() { return registry.DataType.fromJSON({ value: 'BOOLEAN' }); } 13 | } -------------------------------------------------------------------------------- /src/lang/expr/literals/HexLiteral.js: -------------------------------------------------------------------------------- 1 | import { AbstractLiteral } from './AbstractLiteral.js'; 2 | import { registry } from '../../registry.js'; 3 | 4 | export class HexLiteral extends AbstractLiteral { 5 | 6 | /* SYNTAX RULES */ 7 | 8 | static get syntaxRules() { return { type: 'hex_literal', as: '.' }; } 9 | 10 | /* TYPESYS API */ 11 | 12 | dataType() { return registry.DataType.fromJSON({ value: 'BINARY' }); } 13 | } -------------------------------------------------------------------------------- /src/lang/expr/literals/TypedTimeZoneLiteral.js: -------------------------------------------------------------------------------- 1 | import { TypedLiteral } from './TypedLiteral.js'; 2 | import { registry } from '../../registry.js'; 3 | 4 | export class TypedTimeZoneLiteral extends TypedLiteral { 5 | 6 | /* SYNTAX RULES */ 7 | 8 | static get syntaxRules() { 9 | return [ 10 | { type: 'keyword', value: 'TIME ZONE' }, 11 | { type: 'Expr', as: 'value' }, 12 | ]; 13 | } 14 | } -------------------------------------------------------------------------------- /src/lang/expr/literals/NumberLiteral.js: -------------------------------------------------------------------------------- 1 | import { AbstractLiteral } from './AbstractLiteral.js'; 2 | import { registry } from '../../registry.js'; 3 | 4 | export class NumberLiteral extends AbstractLiteral { 5 | 6 | /* SYNTAX RULES */ 7 | 8 | static get syntaxRules() { return { type: 'number_literal', as: '.' }; } 9 | 10 | /* TYPESYS API */ 11 | 12 | dataType() { return registry.DataType.fromJSON({ value: 'INT' }); } 13 | } -------------------------------------------------------------------------------- /site/.vitepress/dist/assets/docs_setup.md.xW8pIM-m.lean.js: -------------------------------------------------------------------------------- 1 | import{_ as a,c as l,o as n,ag as t}from"./chunks/framework.B-XtCDNB.js";const F=JSON.parse('{"title":"Dialects & Clients","description":"","frontmatter":{},"headers":[],"relativePath":"docs/setup.md","filePath":"docs/setup.md"}'),e={name:"docs/setup.md"};function o(p,s,c,r,i,y){return n(),l("div",null,[...s[0]||(s[0]=[t("",38)])])}const d=a(e,[["render",o]]);export{F as __pageData,d as default}; 2 | -------------------------------------------------------------------------------- /site/.vitepress/dist/assets/capabilities.md.BztTe5GT.lean.js: -------------------------------------------------------------------------------- 1 | import{_ as a,c as n,o as l,ag as e}from"./chunks/framework.B-XtCDNB.js";const F=JSON.parse('{"title":"Capabilities Overview","description":"","frontmatter":{},"headers":[],"relativePath":"capabilities.md","filePath":"capabilities.md"}'),t={name:"capabilities.md"};function o(p,s,r,c,i,y){return l(),n("div",null,[...s[0]||(s[0]=[e("",32)])])}const d=a(t,[["render",o]]);export{F as __pageData,d as default}; 2 | -------------------------------------------------------------------------------- /site/.vitepress/dist/assets/flashql_lang.md.-dKEfD4V.lean.js: -------------------------------------------------------------------------------- 1 | import{_ as e,c as d,o as l,ag as n}from"./chunks/framework.B-XtCDNB.js";const x=JSON.parse('{"title":"Language Reference","description":"","frontmatter":{},"headers":[],"relativePath":"flashql/lang.md","filePath":"flashql/lang.md"}'),a={name:"flashql/lang.md"};function c(i,t,s,r,o,g){return l(),d("div",null,[...t[0]||(t[0]=[n("",17)])])}const f=e(a,[["render",c]]);export{x as __pageData,f as default}; 2 | -------------------------------------------------------------------------------- /site/.vitepress/dist/assets/docs_query-api.md.Bm8hN7oZ.lean.js: -------------------------------------------------------------------------------- 1 | import{_ as a,c as e,o as n,ag as t}from"./chunks/framework.B-XtCDNB.js";const D=JSON.parse('{"title":"Query Interface","description":"","frontmatter":{},"headers":[],"relativePath":"docs/query-api.md","filePath":"docs/query-api.md"}'),l={name:"docs/query-api.md"};function o(p,s,r,c,i,y){return n(),e("div",null,[...s[0]||(s[0]=[t("",46)])])}const F=a(l,[["render",o]]);export{D as __pageData,F as default}; 2 | -------------------------------------------------------------------------------- /src/lang/ddl/constraint/constructs/PGIndexParameters.js: -------------------------------------------------------------------------------- 1 | import { AbstractNodeList } from '../../../abstracts/AbstractNodeList.js'; 2 | 3 | export class PGIndexParameters extends AbstractNodeList { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return [ 9 | { type: ['PGIndexParamInclude', 'PGIndexParamUsing', 'PGIndexParamWith'], as: 'entries', arity: Infinity, singletons: true }, 10 | ]; 11 | } 12 | } -------------------------------------------------------------------------------- /src/lang/dql/clauses/OnClause.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../abstracts/AbstractNode.js'; 2 | 3 | export class OnClause extends AbstractNode { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return [ 9 | { type: 'keyword', value: 'ON' }, 10 | { type: 'Expr', as: 'expr', assert: true } 11 | ]; 12 | } 13 | 14 | /* AST API */ 15 | 16 | expr() { return this._get('expr'); } 17 | } -------------------------------------------------------------------------------- /src/lang/dml/expr/MYVarAssignmentExpr.js: -------------------------------------------------------------------------------- 1 | import { BinaryExpr } from '../../expr/op/BinaryExpr.js'; 2 | 3 | export class MYVarAssignmentExpr extends BinaryExpr { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return [ 9 | { type: ['UserVar', 'SystemVar'], as: 'left' }, 10 | { type: 'operator', as: 'operator', value: ['=', ':='] }, 11 | { type: 'Expr', as: 'right' }, 12 | ]; 13 | } 14 | } -------------------------------------------------------------------------------- /src/lang/expr/abstraction/TypedRowConstructor.js: -------------------------------------------------------------------------------- 1 | import { RowConstructor } from './RowConstructor.js'; 2 | 3 | export class TypedRowConstructor extends RowConstructor { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return [ 9 | { type: 'keyword', value: 'ROW' }, 10 | ...[].concat(super.syntaxRules) 11 | ]; 12 | } 13 | 14 | static get syntaxPriority() { return 52; } // Above CallExpr 15 | } -------------------------------------------------------------------------------- /site/.vitepress/dist/assets/capabilities_upsert.md.hDNJkkyH.lean.js: -------------------------------------------------------------------------------- 1 | import{_ as a,c as e,o as n,ag as l}from"./chunks/framework.B-XtCDNB.js";const D=JSON.parse('{"title":"UPSERT","description":"","frontmatter":{},"headers":[],"relativePath":"capabilities/upsert.md","filePath":"capabilities/upsert.md"}'),o={name:"capabilities/upsert.md"};function p(t,s,c,r,i,y){return n(),e("div",null,[...s[0]||(s[0]=[l("",32)])])}const u=a(o,[["render",p]]);export{D as __pageData,u as default}; 2 | -------------------------------------------------------------------------------- /site/.vitepress/dist/assets/overview.md.CIcdfHfj.lean.js: -------------------------------------------------------------------------------- 1 | import{_ as e,c as a,o as i,ag as n}from"./chunks/framework.B-XtCDNB.js";const p=JSON.parse('{"title":"LinkedQL — A Modern Take on SQL and SQL Databases","description":"","frontmatter":{},"headers":[],"relativePath":"overview.md","filePath":"overview.md"}'),r={name:"overview.md"};function s(l,t,o,d,h,g){return i(),a("div",null,[...t[0]||(t[0]=[n("",19)])])}const f=e(r,[["render",s]]);export{p as __pageData,f as default}; 2 | -------------------------------------------------------------------------------- /site/.vitepress/dist/hashmap.json: -------------------------------------------------------------------------------- 1 | {"capabilities.md":"BztTe5GT","capabilities_deeprefs.md":"CYOx2SXL","capabilities_json-literals.md":"rGE9X-tr","capabilities_live-queries.md":"CHhoCYV3","capabilities_upsert.md":"hDNJkkyH","docs.md":"CwIgAZwB","docs_query-api.md":"Bm8hN7oZ","docs_setup.md":"xW8pIM-m","engineering_realtime-engine.md":"DjOtRGtl","flashql.md":"dxGRqIGO","flashql_foreign-io.md":"B-X4SFru","flashql_lang.md":"-dKEfD4V","index.md":"BsUu5Xl8","overview.md":"CIcdfHfj"} 2 | -------------------------------------------------------------------------------- /src/lang/dml/index.js: -------------------------------------------------------------------------------- 1 | export * from './clauses/index.js'; 2 | export * from './constructors/index.js'; 3 | export * from './expr/index.js'; 4 | export * from './TA/index.js'; 5 | export { DeleteStmt } from './DeleteStmt.js'; 6 | export { InsertStmt } from './InsertStmt.js'; 7 | export { MYSetStmt } from './MYSetStmt.js'; 8 | export { PGSetStmt } from './PGSetStmt.js'; 9 | export { UpdateStmt } from './UpdateStmt.js'; 10 | export { UpsertStmt } from './UpsertStmt.js'; 11 | -------------------------------------------------------------------------------- /src/lang/dql/clauses/WhereClause.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../abstracts/AbstractNode.js'; 2 | 3 | export class WhereClause extends AbstractNode { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return [ 9 | { type: 'keyword', value: 'WHERE' }, 10 | { type: 'Expr', as: 'expr', assert: true } 11 | ]; 12 | } 13 | 14 | /* AST API */ 15 | 16 | expr() { return this._get('expr'); } 17 | } -------------------------------------------------------------------------------- /src/lang/expr/literals/AbstractLQJsonLiteral.js: -------------------------------------------------------------------------------- 1 | import { SugarMixin } from '../../abstracts/SugarMixin.js'; 2 | import { TypeSysMixin } from '../../abstracts/TypeSysMixin.js'; 3 | import { AbstractNodeList } from '../../abstracts/AbstractNodeList.js'; 4 | import { registry } from '../../registry.js'; 5 | 6 | export class AbstractLQJsonLiteral extends SugarMixin(TypeSysMixin(AbstractNodeList)) { 7 | 8 | dataType() { return registry.DataType.fromJSON({ value: 'JSON' }); } 9 | } -------------------------------------------------------------------------------- /site/.vitepress/dist/assets/capabilities_deeprefs.md.CYOx2SXL.lean.js: -------------------------------------------------------------------------------- 1 | import{_ as a,c as n,o as e,ag as l}from"./chunks/framework.B-XtCDNB.js";const B=JSON.parse('{"title":"DeepRefs","description":"","frontmatter":{},"headers":[],"relativePath":"capabilities/deeprefs.md","filePath":"capabilities/deeprefs.md"}'),o={name:"capabilities/deeprefs.md"};function p(t,s,c,r,i,y){return e(),n("div",null,[...s[0]||(s[0]=[l("",196)])])}const C=a(o,[["render",p]]);export{B as __pageData,C as default}; 2 | -------------------------------------------------------------------------------- /site/.vitepress/dist/assets/flashql_foreign-io.md.B-X4SFru.lean.js: -------------------------------------------------------------------------------- 1 | import{_ as a,c as n,o as l,ag as p}from"./chunks/framework.B-XtCDNB.js";const y=JSON.parse('{"title":"Federation & Sync (Alpha)","description":"","frontmatter":{},"headers":[],"relativePath":"flashql/foreign-io.md","filePath":"flashql/foreign-io.md"}'),o={name:"flashql/foreign-io.md"};function e(t,s,c,r,i,D){return l(),n("div",null,[...s[0]||(s[0]=[p("",39)])])}const d=a(o,[["render",e]]);export{y as __pageData,d as default}; 2 | -------------------------------------------------------------------------------- /site/.vitepress/dist/assets/capabilities_live-queries.md.CHhoCYV3.lean.js: -------------------------------------------------------------------------------- 1 | import{_ as a,c as n,o as e,ag as l}from"./chunks/framework.B-XtCDNB.js";const F=JSON.parse('{"title":"Live Queries","description":"","frontmatter":{},"headers":[],"relativePath":"capabilities/live-queries.md","filePath":"capabilities/live-queries.md"}'),o={name:"capabilities/live-queries.md"};function p(t,s,c,r,i,y){return e(),n("div",null,[...s[0]||(s[0]=[l("",166)])])}const d=a(o,[["render",p]]);export{F as __pageData,d as default}; 2 | -------------------------------------------------------------------------------- /src/lang/ddl/constraint/MYColumnCommentModifier.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../abstracts/AbstractNode.js'; 2 | 3 | export class MYColumnCommentModifier extends AbstractNode { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return { 9 | dialect: 'mysql', 10 | syntax: [ 11 | { type: 'keyword', value: 'COMMENT' }, 12 | { type: 'string_literal', as: '.' }, 13 | ], 14 | }; 15 | } 16 | } -------------------------------------------------------------------------------- /site/.vitepress/dist/assets/capabilities_json-literals.md.rGE9X-tr.lean.js: -------------------------------------------------------------------------------- 1 | import{_ as a,c as e,o as n,ag as t}from"./chunks/framework.B-XtCDNB.js";const h=JSON.parse('{"title":"JSON Literals","description":"","frontmatter":{},"headers":[],"relativePath":"capabilities/json-literals.md","filePath":"capabilities/json-literals.md"}'),l={name:"capabilities/json-literals.md"};function o(p,s,r,c,i,d){return n(),e("div",null,[...s[0]||(s[0]=[t("",53)])])}const u=a(l,[["render",o]]);export{h as __pageData,u as default}; 2 | -------------------------------------------------------------------------------- /src/lang/dml/clauses/PGDefaultValuesClause.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../abstracts/AbstractNode.js'; 2 | 3 | export class PGDefaultValuesClause extends AbstractNode { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return { 9 | dialect: 'postgres', 10 | syntax: [ 11 | { type: 'keyword', as: '.', value: 'DEFAULT' }, 12 | { type: 'keyword', value: 'VALUES' }, 13 | ] 14 | }; 15 | } 16 | } -------------------------------------------------------------------------------- /src/lang/dql/clauses/FromClause.js: -------------------------------------------------------------------------------- 1 | import { AbstractNodeList } from '../../abstracts/AbstractNodeList.js'; 2 | 3 | export class FromClause extends AbstractNodeList { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | const itemSeparator = { type: 'punctuation', value: ',' }; 9 | return [ 10 | { type: 'keyword', value: 'FROM' }, 11 | { type: 'FromItem', as: 'entries', arity: { min: 1 }, itemSeparator, assert: true } 12 | ]; 13 | } 14 | } -------------------------------------------------------------------------------- /src/lang/ddl/constraint/constructs/PGIndexParamUsing.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../../abstracts/AbstractNode.js'; 2 | 3 | export class PGIndexParamUsing extends AbstractNode { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return [ 9 | { type: 'keyword', value: 'USING' }, 10 | { type: 'keyword', value: 'INDEX' }, 11 | { type: 'keyword', value: 'TABLESPACE' }, 12 | { type: 'identifier', as: '.' }, 13 | ]; 14 | } 15 | } -------------------------------------------------------------------------------- /src/lang/dml/clauses/UsingFromClause.js: -------------------------------------------------------------------------------- 1 | import { AbstractNodeList } from '../../abstracts/AbstractNodeList.js'; 2 | 3 | export class UsingFromClause extends AbstractNodeList { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | const itemSeparator = { type: 'punctuation', value: ',' }; 9 | return [ 10 | { type: 'keyword', value: 'USING' }, 11 | { type: 'FromItem', as: 'entries', arity: { min: 1 }, itemSeparator, assert: true } 12 | ]; 13 | } 14 | } -------------------------------------------------------------------------------- /src/lang/ddl/constraint/MYColumnVisibilityModifier.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../abstracts/AbstractNode.js'; 2 | 3 | export class MYColumnVisibilityModifier extends AbstractNode { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return { 9 | dialect: 'mysql', 10 | syntaxes: [ 11 | { type: 'keyword', as: '.', value: 'VISIBLE' }, 12 | { type: 'keyword', as: '.', value: 'INVISIBLE' }, 13 | ], 14 | }; 15 | } 16 | } -------------------------------------------------------------------------------- /src/lang/ddl/constraint/constructs/FKMatchRule.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../../abstracts/AbstractNode.js'; 2 | 3 | export class FKMatchRule extends AbstractNode { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return [ 9 | { type: 'keyword', value: 'MATCH' }, 10 | { type: 'keyword', as: 'value', value: ['FULL', 'PARTIAL', 'SIMPLE'], assert: true }, 11 | ]; 12 | } 13 | 14 | /*. AST API */ 15 | 16 | value() { return this._get('value'); } 17 | } -------------------------------------------------------------------------------- /src/lang/dml/clauses/SetClause.js: -------------------------------------------------------------------------------- 1 | import { AbstractNodeList } from '../../abstracts/AbstractNodeList.js'; 2 | 3 | export class SetClause extends AbstractNodeList { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | const itemSeparator = { type: 'punctuation', value: ',' }; 9 | return [ 10 | { type: 'keyword', value: 'SET' }, 11 | { type: 'AssignmentExpr', as: 'entries', arity: { min: 1 }, itemSeparator, assert: true, autoIndent: 2 }, 12 | ]; 13 | } 14 | } -------------------------------------------------------------------------------- /src/lang/dql/clauses/HavingClause.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../abstracts/AbstractNode.js'; 2 | 3 | export class HavingClause extends AbstractNode { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return [ 9 | { type: 'keyword', value: 'HAVING' }, 10 | { type: 'Expr', as: 'expr', assert: true } 11 | ]; 12 | } 13 | 14 | static get syntaxPriority() { return -1; } 15 | 16 | /* AST API */ 17 | 18 | expr() { return this._get('expr'); } 19 | } -------------------------------------------------------------------------------- /src/lang/ddl/index.js: -------------------------------------------------------------------------------- 1 | export * from './column/index.js'; 2 | export * from './constraint/index.js'; 3 | export * from './ident/index.js'; 4 | export * from './index/index.js'; 5 | export * from './namespace/index.js'; 6 | export * from './table/index.js'; 7 | export { CreateSchemaStmt } from './CreateSchemaStmt.js'; 8 | export { DropSchemaStmt } from './DropSchemaStmt.js'; 9 | export { CreateTableStmt } from './CreateTableStmt.js'; 10 | export { DropTableStmt } from './DropTableStmt.js'; 11 | export { DDLStmt } from './DDLStmt.js' 12 | -------------------------------------------------------------------------------- /src/lang/expr/literals/StringLiteral.js: -------------------------------------------------------------------------------- 1 | import { AbstractLiteral } from './AbstractLiteral.js'; 2 | import { registry } from '../../registry.js'; 3 | 4 | export class StringLiteral extends AbstractLiteral { 5 | 6 | /* SYNTAX RULES */ 7 | 8 | static get syntaxRules() { return { type: 'string_literal', as: '.' }; } 9 | 10 | /* AST API */ 11 | 12 | qualifier() { return this._get('qualifier'); } 13 | 14 | /* TYPESYS API */ 15 | 16 | dataType() { return registry.DataType.fromJSON({ value: 'TEXT' }); } 17 | } -------------------------------------------------------------------------------- /src/lang/dql/clauses/WindowClause.js: -------------------------------------------------------------------------------- 1 | import { AbstractNodeList } from '../../abstracts/AbstractNodeList.js'; 2 | 3 | export class WindowClause extends AbstractNodeList { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | const itemSeparator = { type: 'punctuation', value: ',' }; 9 | return [ 10 | { type: 'keyword', value: 'WINDOW' }, 11 | { type: 'WindowDeclaration', as: 'entries', arity: { min: 1 }, itemSeparator, assert: true, autoIndent: 2 }, 12 | ]; 13 | } 14 | } -------------------------------------------------------------------------------- /src/lang/ddl/constraint/MYColumnOnUpdateModifier.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../abstracts/AbstractNode.js'; 2 | 3 | export class MYColumnOnUpdateModifier extends AbstractNode { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return { 9 | dialect: 'mysql', 10 | syntax: [ 11 | { type: 'keyword', value: 'ON' }, 12 | { type: 'keyword', value: 'UPDATE' }, 13 | { type: 'keyword', as: '.' }, 14 | ], 15 | }; 16 | } 17 | } -------------------------------------------------------------------------------- /src/lang/ddl/constraint/constructs/FKDeleteRule.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../../abstracts/AbstractNode.js'; 2 | 3 | export class FKDeleteRule extends AbstractNode { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return [ 9 | { type: 'keyword', value: 'ON' }, 10 | { type: 'keyword', value: 'DELETE' }, 11 | { type: 'ReferentialAction', as: 'action', assert: true }, 12 | ]; 13 | } 14 | 15 | /*. AST API */ 16 | 17 | action() { return this._get('action'); } 18 | } -------------------------------------------------------------------------------- /src/lang/ddl/constraint/constructs/FKUpdateRule.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../../abstracts/AbstractNode.js'; 2 | 3 | export class FKUpdateRule extends AbstractNode { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return [ 9 | { type: 'keyword', value: 'ON' }, 10 | { type: 'keyword', value: 'UPDATE' }, 11 | { type: 'ReferentialAction', as: 'action', assert: true }, 12 | ]; 13 | } 14 | 15 | /*. AST API */ 16 | 17 | action() { return this._get('action'); } 18 | } -------------------------------------------------------------------------------- /src/lang/dml/clauses/ColumnsSpec.js: -------------------------------------------------------------------------------- 1 | import { AbstractNodeList } from '../../expr/abstracts/AbstractNodeList.js'; 2 | import { ColumnRef } from '../../expr/refs/ColumnRef.js'; 3 | import { PathRight } from '../../expr/path/PathRight.js'; 4 | 5 | export class ColumnsSpec extends AbstractNodeList { 6 | static get EXPECTED_TYPES() { return [PathRight, ColumnRef]; } 7 | static get TAGS() { return ['(', ')']; } 8 | 9 | static get expose() { 10 | return { 11 | columns: (context, ...entries) => this.fromJSON(context, { entries }), 12 | }; 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /src/lang/dql/clauses/PGOrderOperator.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../abstracts/AbstractNode.js'; 2 | 3 | export class PGOrderOperator extends AbstractNode { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return { 9 | dialect: 'postgres', 10 | syntax: [ 11 | { type: 'keyword', value: 'USING' }, 12 | { type: 'operator', as: '.', assert: true }, 13 | ], 14 | }; 15 | } 16 | 17 | /* AST API */ 18 | 19 | value() { return this._get('value'); } 20 | } -------------------------------------------------------------------------------- /src/lang/dml/clauses/ValuesClause.js: -------------------------------------------------------------------------------- 1 | import { AbstractNodeList } from '../../expr/abstracts/AbstractNodeList.js'; 2 | import { Parens } from '../../expr/Parens.js'; 3 | import { RowSpec } from './RowSpec.js'; 4 | 5 | export class ValuesClause extends AbstractNodeList { 6 | static get EXPECTED_TYPES() { return [RowSpec, Parens]; } 7 | static get ARGS_DELEGATION() { return 'add'; } 8 | static get CLAUSE() { return 'VALUES'; } 9 | 10 | static get expose() { 11 | return { 12 | values: (context, ...entries) => this.fromJSON(context, { entries }), 13 | }; 14 | } 15 | } -------------------------------------------------------------------------------- /src/lang/dql/clauses/WindowDeclaration.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../abstracts/AbstractNode.js'; 2 | 3 | export class WindowDeclaration extends AbstractNode { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return [ 9 | { type: 'Identifier', as: 'name' }, 10 | { type: 'keyword', value: 'AS' }, 11 | { type: 'WindowSpec', as: 'spec', assert: true } 12 | ]; 13 | } 14 | 15 | /* AST API */ 16 | 17 | name() { return this._get('name'); } 18 | 19 | spec() { return this._get('spec'); } 20 | } -------------------------------------------------------------------------------- /src/lang/ddl/constraint/constructs/index.js: -------------------------------------------------------------------------------- 1 | export { FKMatchRule } from './FKMatchRule.js'; 2 | export { FKDeleteRule } from './FKDeleteRule.js'; 3 | export { FKUpdateRule } from './FKUpdateRule.js'; 4 | export { PGIndexParameters } from './PGIndexParameters.js'; 5 | export { PGIndexParamInclude } from './PGIndexParamInclude.js'; 6 | export { PGIndexParamUsing } from './PGIndexParamUsing.js'; 7 | export { PGIndexParamWith } from './PGIndexParamWith.js'; 8 | export { PGTableEXConstraintItem } from './PGTableEXConstraintItem.js'; 9 | export { ReferentialAction } from './ReferentialAction.js'; 10 | -------------------------------------------------------------------------------- /src/lang/expr/ref/LQDeepDeepRef2.js: -------------------------------------------------------------------------------- 1 | import { LQDeepDeepRef1 } from './LQDeepDeepRef1.js'; 2 | import { registry } from '../../registry.js'; 3 | 4 | export class LQDeepDeepRef2 extends LQDeepDeepRef1 { 5 | 6 | /* SYNTAX RULES */ 7 | 8 | static get _rightType() { return ['LQDeepDeepRef2', 'ColumnRef2', 'ColumnsConstructor']; } // for inheritance 9 | 10 | /* JSON API */ 11 | 12 | jsonfy({ toDeepRef = false, toKind = 2, ...options } = {}, transformer = null, schemaInference = null) { 13 | return super.jsonfy({ toDeepRef, toKind, ...options }, transformer = null, schemaInference); 14 | } 15 | } -------------------------------------------------------------------------------- /src/lang/expr/ref/TableRef0.js: -------------------------------------------------------------------------------- 1 | import { TableRef1 } from './TableRef1.js'; 2 | import { registry } from '../../registry.js'; 3 | 4 | export class TableRef0 extends TableRef1 { 5 | 6 | /* SYNTAX RULES */ 7 | 8 | static get _qualifierType() { return ['NamespaceRef']; } 9 | 10 | static get syntaxRules() { 11 | return this.buildSyntaxRules({ type: 'operator', as: '.', value: '*', autoSpacing: false }); 12 | } 13 | 14 | static get syntaxPriority() { return -1; } 15 | 16 | /* API */ 17 | 18 | dataType() { return registry.DataType.fromJSON({ value: 'SET' }); } 19 | } -------------------------------------------------------------------------------- /src/lang/dql/clauses/PartitionByClause.js: -------------------------------------------------------------------------------- 1 | import { AbstractNodeList } from '../../abstracts/AbstractNodeList.js'; 2 | 3 | export class PartitionByClause extends AbstractNodeList { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | const itemSeparator = { type: 'punctuation', value: ',' }; 9 | return [ 10 | { type: 'keyword', value: 'PARTITION' }, 11 | { type: 'keyword', value: 'BY', assert: true }, 12 | { type: 'Expr', as: 'entries', arity: { min: 1 }, itemSeparator, assert: true, autoIndent: 2 } 13 | ]; 14 | } 15 | } -------------------------------------------------------------------------------- /src/lang/expr/ref/ColumnRef0.js: -------------------------------------------------------------------------------- 1 | import { ColumnRef1 } from './ColumnRef1.js'; 2 | import { registry } from '../../registry.js'; 3 | 4 | export class ColumnRef0 extends ColumnRef1 { 5 | 6 | /* SYNTAX RULES */ 7 | 8 | static get _qualifierType() { return ['TableRef1']; } 9 | 10 | static get syntaxRules() { 11 | return this.buildSyntaxRules({ type: 'operator', as: '.', value: '*', autoSpacing: false }); 12 | } 13 | 14 | static get syntaxPriority() { return -1; } 15 | 16 | /* API */ 17 | 18 | dataType() { return registry.DataType.fromJSON({ value: 'SET' }); } 19 | } -------------------------------------------------------------------------------- /src/lang/expr/op/InExpr.js: -------------------------------------------------------------------------------- 1 | import { BinaryExpr } from './BinaryExpr.js'; 2 | 3 | export class InExpr extends BinaryExpr { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return [ 9 | { type: 'Expr', as: 'left', peek: [1, 'operator', ['NOT', 'IN']] }, 10 | { type: 'operator', as: 'negation', value: 'NOT', booleanfy: true, optional: true }, 11 | { type: 'operator', as: 'operator', value: 'IN' }, 12 | { type: ['DerivedQuery', 'RowConstructor', 'TypedRowConstructor'], as: 'right', assert: true }, 13 | ]; 14 | } 15 | } -------------------------------------------------------------------------------- /src/lang/dml/clauses/MYPartitionClause.js: -------------------------------------------------------------------------------- 1 | import { AbstractNodeList } from '../../abstracts/AbstractNodeList.js'; 2 | 3 | export class MYPartitionClause extends AbstractNodeList { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | const itemSeparator = { type: 'punctuation', value: ',' }; 9 | return { 10 | dialect: 'mysql', 11 | syntax: [ 12 | { type: 'keyword', value: 'PARTITION' }, 13 | { type: 'Identifier', as: 'entries', arity: { min: 1 }, itemSeparator, assert: true } 14 | ], 15 | }; 16 | } 17 | } -------------------------------------------------------------------------------- /src/lang/ddl/constraint/constructs/PGIndexParamInclude.js: -------------------------------------------------------------------------------- 1 | import { AbstractNodeList } from '../../../abstracts/AbstractNodeList.js'; 2 | 3 | export class PGIndexParamInclude extends AbstractNodeList { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | const itemSeparator = { type: 'punctuation', value: ',' }; 9 | return [ 10 | { type: 'keyword', value: 'INCLUDE' }, 11 | { 12 | type: 'paren_block', 13 | syntax: { type: 'ColumnRef2', as: 'entries', arity: { min: 1 }, itemSeparator }, 14 | } 15 | ]; 16 | } 17 | } -------------------------------------------------------------------------------- /src/lang/ddl/constraint/constructs/PGIndexParamWith.js: -------------------------------------------------------------------------------- 1 | import { AbstractNodeList } from '../../../abstracts/AbstractNodeList.js'; 2 | 3 | export class PGIndexParamWith extends AbstractNodeList { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | const itemSeparator = { type: 'punctuation', value: ',' }; 9 | return [ 10 | { type: 'keyword', value: 'WITH' }, 11 | { 12 | type: 'paren_block', 13 | syntax: { type: 'ConfigAssignmentExprAlt2', as: 'entries', arity: { min: 1 }, itemSeparator }, 14 | } 15 | ]; 16 | } 17 | } -------------------------------------------------------------------------------- /src/lang/dql/TA/index.js: -------------------------------------------------------------------------------- 1 | export { DerivedQuery } from './DerivedQuery.js'; 2 | export { FromItem } from './FromItem.js'; 3 | export { FromItemAlias } from './FromItemAlias.js'; 4 | export { SelectItem } from './SelectItem.js'; 5 | export { SelectItemAlias } from './SelectItemAlias.js'; 6 | export { SRFExpr1 } from './SRFExpr1.js'; 7 | export { SRFExpr2 } from './SRFExpr2.js'; 8 | export { SRFExpr3 } from './SRFExpr3.js'; 9 | export { SRFExpr4 } from './SRFExpr4.js'; 10 | export { SRFExprDDL1 } from './SRFExprDDL1.js'; 11 | export { SRFExprDDL2 } from './SRFExprDDL2.js'; 12 | export { ValuesTableLiteral } from './ValuesTableLiteral.js'; 13 | -------------------------------------------------------------------------------- /src/lang/index.js: -------------------------------------------------------------------------------- 1 | import * as cte from './cte/index.js'; 2 | import * as ddl from './ddl/index.js'; 3 | import * as dml from './dml/index.js'; 4 | import * as dql from './dql/index.js'; 5 | import * as expr from './expr/index.js'; 6 | import * as qualif from './qualif/index.js'; 7 | import * as type from './type/index.js'; 8 | import { JSONSchema } from './abstracts/JSONSchema.js'; 9 | import { StdStmt } from './StdStmt.js'; 10 | import { Script } from './Script.js'; 11 | import { registry } from './registry.js'; 12 | 13 | Object.assign(registry, { ...cte, ...ddl, ...dml, ...dql, ...expr, ...qualif, ...type, StdStmt, Script, JSONSchema }); 14 | -------------------------------------------------------------------------------- /src/lang/expr/op/DistinctFromExpr.js: -------------------------------------------------------------------------------- 1 | import { BinaryExpr } from './BinaryExpr.js'; 2 | 3 | export class DistinctFromExpr extends BinaryExpr { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return [ 9 | { type: 'Expr', as: 'left', peek: [1, 'operator', ['IS', 'IS NOT']] }, 10 | { type: 'operator', as: 'logic', value: ['IS', 'IS NOT'] }, 11 | { type: 'operator', as: 'operator', value: 'DISTINCT FROM' }, 12 | { type: 'Expr', as: 'right', assert: true }, 13 | ]; 14 | } 15 | 16 | /* AST API */ 17 | 18 | logic() { return this._get('logic'); } 19 | } -------------------------------------------------------------------------------- /src/lang/dml/expr/AssignmentExpr.js: -------------------------------------------------------------------------------- 1 | import { BinaryExpr } from '../../expr/op/BinaryExpr.js'; 2 | 3 | export class AssignmentExpr extends BinaryExpr { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return [ 9 | { type: ['LQDeepRef2', 'ColumnsConstructor', 'ColumnRef2'], as: 'left', dialect: 'postgres' }, 10 | { type: ['LQDeepRef2', 'ColumnRef1'], as: 'left', dialect: 'mysql' }, 11 | { type: 'operator', as: 'operator', value: '=' }, 12 | { type: ['ValuesTableLiteral'/* For deep dimensional inserts */, 'DerivedQuery', 'Expr'], as: 'right' }, 13 | ]; 14 | } 15 | } -------------------------------------------------------------------------------- /src/lang/ddl/DDLStmt.js: -------------------------------------------------------------------------------- 1 | import { AbstractStmt } from '../abstracts/AbstractStmt.js'; 2 | 3 | export class DDLStmt extends AbstractStmt { 4 | 5 | 6 | /* SYNTAX RULES */ 7 | 8 | static get syntaxRules() { return { type: ['CreateSchemaStmt', 'DropSchemaStmt', 'CreateTableStmt', 'DropTableStmt'] }; } 9 | 10 | /** API */ 11 | 12 | jsonfy({ deSugar, ...options } = {}, transformer = null, schemaInference = null) { 13 | if (this.returningClause?.()) { 14 | options = { deSugar, ...options }; 15 | } 16 | return super.jsonfy(options, transformer, schemaInference); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/lang/expr/ref/LQBackRefAbstraction.js: -------------------------------------------------------------------------------- 1 | import { ParenExpr } from '../abstraction/ParenExpr.js'; 2 | 3 | export class LQBackRefAbstraction extends ParenExpr { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return { 9 | type: 'paren_block', 10 | syntaxes: [ 11 | { type: 'Expr', as: 'expr', peek: [1, 'operator', '<~'] }, // (fk <~ fk2 <~ tbl) 12 | { type: 'Expr', as: 'expr', peek: [2, 'operator', '<~'] }, // ((alias) fk <~ fk2 <~ tbl) 13 | ], 14 | }; 15 | } 16 | 17 | static get syntaxPriority() { return 51; } // Above RowConstructor 18 | 19 | /* AST API */ 20 | 21 | expr() { return this._get('expr'); } 22 | } -------------------------------------------------------------------------------- /src/lang/dml/clauses/PGWhereCurrentClause.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../abstracts/AbstractNode.js'; 2 | 3 | export class PGWhereCurrentClause extends AbstractNode { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return { 9 | dialect: 'postgres', 10 | syntax: [ 11 | { type: 'keyword', value: 'WHERE' }, 12 | { type: 'keyword', value: 'CURRENT OF' }, 13 | { type: 'identifier', as: 'cursor_name', assert: true } 14 | ] 15 | }; 16 | } 17 | 18 | /* AST API */ 19 | 20 | cursorName() { return this._get('cursor_name'); } 21 | } -------------------------------------------------------------------------------- /src/lang/dql/clauses/OffsetClause.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../abstracts/AbstractNode.js'; 2 | 3 | export class OffsetClause extends AbstractNode { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return [ 9 | { type: 'keyword', value: 'OFFSET' }, 10 | { type: 'Expr', as: 'expr', assert: true, }, 11 | { type: 'keyword', as: 'pg_row_kw', value: ['ROW', 'ROWS'], optional: true, dialect: 'postgres' }, 12 | ]; 13 | } 14 | 15 | /* AST API */ 16 | 17 | expr() { return this._get('expr'); } 18 | 19 | // -- Postgres 20 | 21 | pgRowKW() { return this._get('pg_row_kw'); } 22 | } -------------------------------------------------------------------------------- /src/lang/expr/case/CaseBranch.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../abstracts/AbstractNode.js'; 2 | 3 | export class CaseBranch extends AbstractNode { 4 | 5 | /* DEFS */ 6 | 7 | static get syntaxRules() { 8 | return [ 9 | { type: 'keyword', value: 'WHEN' }, 10 | { type: 'Expr', as: 'condition' }, 11 | { type: 'keyword', value: 'THEN' }, 12 | { type: 'Expr', as: 'consequent' } 13 | ]; 14 | } 15 | 16 | static get syntaxPriority() { return -1; } 17 | 18 | /* AST API */ 19 | 20 | condition() { return this._get('condition'); } 21 | 22 | consequent() { return this._get('consequent'); } 23 | } -------------------------------------------------------------------------------- /src/lang/dml/clauses/index.js: -------------------------------------------------------------------------------- 1 | export { MYOnDuplicateKeyUpdateClause } from './MYOnDuplicateKeyUpdateClause.js'; 2 | export { MYPartitionClause } from './MYPartitionClause.js'; 3 | export { PGConflictTarget } from './PGConflictTarget.js'; 4 | export { PGConflictTargetIndexSpec } from './PGConflictTargetIndexSpec.js'; 5 | export { PGDefaultValuesClause } from './PGDefaultValuesClause.js'; 6 | export { PGOnConflictClause } from './PGOnConflictClause.js'; 7 | export { ReturningClause } from './ReturningClause.js'; 8 | export { PGWhereCurrentClause } from './PGWhereCurrentClause.js'; 9 | export { SetClause } from './SetClause.js'; 10 | export { UsingFromClause } from './UsingFromClause.js'; 11 | -------------------------------------------------------------------------------- /src/lang/expr/literals/TypedLiteral.js: -------------------------------------------------------------------------------- 1 | import { AbstractClassicExpr } from '../AbstractClassicExpr.js'; 2 | import { registry } from '../../registry.js'; 3 | 4 | export class TypedLiteral extends AbstractClassicExpr { 5 | 6 | /* SYNTAX RULES */ 7 | 8 | static get syntaxRules() { 9 | return [ 10 | { type: 'data_type', as: 'data_type' }, 11 | { type: 'string_literal', as: 'value' }, 12 | ]; 13 | } 14 | 15 | static get syntaxPriority() { return 50; } 16 | 17 | /* AST API */ 18 | 19 | dataType() { return registry.DataType.fromJSON({ value: this._get('data_type') }); } 20 | 21 | value() { return this._get('value'); } 22 | } -------------------------------------------------------------------------------- /src/lang/expr/op/BetweenExpr.js: -------------------------------------------------------------------------------- 1 | import { BinaryExpr } from './BinaryExpr.js'; 2 | 3 | export class BetweenExpr extends BinaryExpr { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | const itemSeparator = { type: 'operator', value: 'AND' }; 9 | return [ 10 | { type: 'Expr', as: 'left', peek: [1, 'operator', ['NOT', 'BETWEEN']] }, 11 | { type: 'operator', as: 'negation', value: 'NOT', booleanfy: true, optional: true }, 12 | { type: 'operator', as: 'operator', value: 'BETWEEN' }, 13 | { type: 'Expr', as: 'right', arity: { min: 2, max: 2, eager: false }, itemSeparator, assert: true }, 14 | ]; 15 | } 16 | } -------------------------------------------------------------------------------- /src/lang/expr/ref/LQBackRefEndpoint.js: -------------------------------------------------------------------------------- 1 | import { ColumnRef2 } from './ColumnRef2.js'; 2 | 3 | export class LQBackRefEndpoint extends ColumnRef2 { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return [ 9 | { 10 | optional: true, 11 | type: 'paren_block', 12 | syntax: { type: 'Identifier', as: 'qualifier' }, 13 | }, 14 | { ...[].concat(super.syntaxRules)[0], peek: [1, 'operator', '<~'] }, 15 | ]; 16 | } 17 | 18 | static get syntaxPriority() { return 52; } // Above ColumnRef1 19 | 20 | static morphsTo() { return ColumnRef2; } 21 | 22 | /* API */ 23 | 24 | qualifier() { return this._get('qualifier'); } 25 | } -------------------------------------------------------------------------------- /src/lang/ddl/constraint/ColumnDefaultConstraint.js: -------------------------------------------------------------------------------- 1 | import { ConstraintSchema } from './ConstraintSchema.js'; 2 | 3 | export class ColumnDefaultConstraint extends ConstraintSchema { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return this.buildSyntaxRules([ 9 | { type: 'keyword', value: 'DEFAULT' }, 10 | { type: 'Expr', as: 'expr', assert: true, dialect: 'postgres' }, 11 | { type: ['NumberLiteral', 'StringLiteral', 'NullLiteral', 'BoolLiteral', 'CallExpr', 'RowConstructor'], as: 'expr', assert: true, dialect: 'mysql' }, 12 | ]); 13 | } 14 | 15 | /* AST API */ 16 | 17 | expr() { return this._get('expr'); } 18 | } -------------------------------------------------------------------------------- /src/lang/dml/constructors/ColumnsConstructor.js: -------------------------------------------------------------------------------- 1 | import { AbstractNodeList } from '../../abstracts/AbstractNodeList.js'; 2 | 3 | export class ColumnsConstructor extends AbstractNodeList { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | const itemSeparator = { type: 'punctuation', value: ',' }; 9 | return { 10 | syntax: [ 11 | { 12 | type: 'paren_block', 13 | syntax: { type: ['LQDeepRef2', 'ColumnRef2'], as: 'entries', arity: Infinity, itemSeparator, autoIndent: 10 }, 14 | }, 15 | ], 16 | }; 17 | } 18 | 19 | static get syntaxPriority() { return -1; } 20 | } -------------------------------------------------------------------------------- /src/lang/expr/ref/LQDeepRef2.js: -------------------------------------------------------------------------------- 1 | import { LQDeepRef1 } from './LQDeepRef1.js'; 2 | 3 | export class LQDeepRef2 extends LQDeepRef1 { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get _rightType() { return ['LQDeepDeepRef2', 'ColumnRef2', 'ColumnsConstructor']; } // for inheritance 8 | 9 | static get syntaxPriority() { return -1; } 10 | 11 | /* JSON API */ 12 | 13 | resolve(transformer, schemaInference, toKind = 2) { 14 | return super.resolve(transformer, schemaInference, toKind); 15 | } 16 | 17 | jsonfy({ toDeepRef = false, toKind = 2, ...options } = {}, transformer = null, schemaInference = null) { 18 | return super.jsonfy({ toDeepRef, toKind, ...options }, transformer, schemaInference); 19 | } 20 | } -------------------------------------------------------------------------------- /src/lang/dql/CompleteSelectStmt.js: -------------------------------------------------------------------------------- 1 | import { BasicSelectStmt } from './BasicSelectStmt.js'; 2 | 3 | export class CompleteSelectStmt extends BasicSelectStmt { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { return this.buildSyntaxRules(); } 8 | 9 | static get syntaxPriority() { return 99; } 10 | 11 | /* AST API */ 12 | 13 | orderByClause() { return this._get('order_by_clause'); } 14 | 15 | offsetClause() { return this._get('offset_clause'); } 16 | 17 | limitClause() { return this._get('limit_clause'); } 18 | 19 | forClause() { return this._get('for_clause'); } 20 | 21 | // -- Postgres 22 | 23 | pgFetchClause() { return this._get('pg_fetch_clause'); } 24 | } -------------------------------------------------------------------------------- /src/lang/expr/etc/PredicateExpr.js: -------------------------------------------------------------------------------- 1 | import { registry } from '../../registry.js'; 2 | import { AbstractClassicExpr } from '../AbstractClassicExpr.js'; 3 | 4 | export class PredicateExpr extends AbstractClassicExpr { 5 | 6 | /* DEFS */ 7 | 8 | static get syntaxRules() { 9 | return [ 10 | { type: 'keyword', as: 'predicate', value: ['EXISTS'] }, 11 | { type: 'ScalarSubquery', as: 'expr' }, 12 | ]; 13 | } 14 | 15 | /* AST API */ 16 | 17 | predicate() { return this._get('predicate'); } 18 | 19 | expr() { return this._get('expr'); } 20 | 21 | /* TYPESYS API */ 22 | 23 | dataType() { return registry.DataType.fromJSON({ value: 'BOOLEAN' }); } 24 | } 25 | -------------------------------------------------------------------------------- /src/lang/expr/op/PGCastExpr2.js: -------------------------------------------------------------------------------- 1 | import { BinaryExpr } from './BinaryExpr.js'; 2 | 3 | export class PGCastExpr2 extends BinaryExpr { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return { 9 | dialect: 'postgres', 10 | syntax: [ 11 | { type: 'Expr', as: 'left', peek: [1, 'operator', '::'] }, 12 | { type: 'operator', as: 'operator', value: '::', autoSpacing: false }, 13 | { type: 'DataType', as: 'right', assert: true, autoSpacing: false }, 14 | ] 15 | }; 16 | } 17 | 18 | /* TYPESYS API */ 19 | 20 | expr() { return this.left(); } 21 | 22 | dataType() { return this.right(); } 23 | } -------------------------------------------------------------------------------- /src/lang/dql/TA/SRFExprDDL1.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../abstracts/AbstractNode.js'; 2 | 3 | export class SRFExprDDL1 extends AbstractNode { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | const itemSeparator = { type: 'punctuation', value: ',' }; 9 | return [ 10 | { type: 'keyword', as: 'as_kw', value: 'AS' }, 11 | { 12 | type: 'paren_block', 13 | syntax: { type: 'ColumnSchema', as: 'column_defs', arity: { min: 1 }, itemSeparator }, 14 | } 15 | ]; 16 | } 17 | 18 | /* AST API */ 19 | 20 | asKW() { return this._get('as_kw'); } 21 | 22 | columnDefs() { return this._get('column_defs'); } 23 | } -------------------------------------------------------------------------------- /src/lang/expr/etc/QuantitativeExpr.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../abstracts/AbstractNode.js'; 2 | 3 | export class QuantitativeExpr extends AbstractNode { 4 | 5 | /* DEFS */ 6 | 7 | static get syntaxRules() { 8 | return [ 9 | { type: 'keyword', as: 'quantifier', value: ['ALL', 'ANY', 'SOME'] }, 10 | { 11 | syntaxes: [ 12 | { type: 'DerivedQuery', as: 'expr' }, 13 | { type: 'paren_block', syntax: { type: 'Expr', as: 'expr' } } 14 | ], 15 | } 16 | ]; 17 | } 18 | 19 | /* AST API */ 20 | 21 | quantifier() { return this._get('quantifier'); } 22 | 23 | expr() { return this._get('expr'); } 24 | } 25 | -------------------------------------------------------------------------------- /src/lang/expr/index.js: -------------------------------------------------------------------------------- 1 | export * from './abstraction/index.js'; 2 | export * from './call/index.js'; 3 | export * from './case/index.js'; 4 | export * from './etc/index.js'; 5 | export * from './literals/index.js'; 6 | export * from './op/index.js'; 7 | export * from './ref/index.js'; 8 | export * from './abstraction/index.js'; 9 | export * from './var/index.js'; 10 | export { LQBackRefAbstraction } from './ref/LQBackRefAbstraction.js'; 11 | export { RowConstructor } from './abstraction/RowConstructor.js'; 12 | export { ScalarSubquery } from './abstraction/ScalarSubquery.js'; 13 | export { TypedRowConstructor } from './abstraction/TypedRowConstructor.js'; 14 | export { Expr } from './Expr.js'; 15 | -------------------------------------------------------------------------------- /src/lang/ddl/constraint/ColumnNullConstraint.js: -------------------------------------------------------------------------------- 1 | import { ConstraintSchema } from './ConstraintSchema.js'; 2 | 3 | export class ColumnNullConstraint extends ConstraintSchema { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return this.buildSyntaxRules([ 9 | { 10 | syntaxes: [ 11 | [ 12 | { type: 'operator', as: '.', value: 'NOT' }, 13 | { type: 'null_literal', value: 'NULL' }, 14 | ], 15 | { type: 'null_literal', as: '.', value: 'NULL' }, 16 | ] 17 | } 18 | ]); 19 | } 20 | 21 | /* AST API */ 22 | 23 | value() { return this._get('value'); } 24 | } -------------------------------------------------------------------------------- /src/entry/abstracts/Spawnable.js: -------------------------------------------------------------------------------- 1 | import { fork } from 'node:child_process'; 2 | import { fileURLToPath } from 'node:url'; 3 | import { ProxyDriver } from './driver/ProxyDriver.js'; 4 | 5 | export const Spawnable = (Base) => class extends Base { 6 | static spawn(params) { 7 | const __file__ = fileURLToPath(import.meta.url); 8 | const worker = fork(__file__, ['--linked-ql-client-autorun'], params); 9 | return worker; 10 | } 11 | } 12 | 13 | if (process.send && process.argv.includes('--linked-ql-client-autorun')) { 14 | const DB_PARAMS = process.env.DB_PARAMS; 15 | 16 | const driver = new ProxyDriver(DB_PARAMS); 17 | const instance = new Client(driver); 18 | 19 | process.on('message', () => { 20 | 21 | }); 22 | } -------------------------------------------------------------------------------- /src/lang/cte/CTEItemAlias.js: -------------------------------------------------------------------------------- 1 | import { Identifier } from '../expr/ref/Identifier.js'; 2 | 3 | export class CTEItemAlias extends Identifier { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | const itemSeparator = { type: 'punctuation', value: ',' }; 9 | return [ 10 | { ...[].concat(super.syntaxRules)[0] }, 11 | { 12 | type: 'paren_block', 13 | syntax: { type: 'Identifier', as: 'columns', arity: { min: 1 }, itemSeparator, assert: true }, 14 | if: 'value', 15 | optional: true, 16 | optionalParens: true, 17 | } 18 | ]; 19 | } 20 | 21 | /* AST API */ 22 | 23 | columns() { return this._get('columns'); } 24 | } -------------------------------------------------------------------------------- /src/lang/expr/etc/ExtractExpr.js: -------------------------------------------------------------------------------- 1 | import { BinaryExpr } from '../op/BinaryExpr.js'; 2 | 3 | export class ExtractExpr extends BinaryExpr { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return [ 9 | { type: 'keyword', value: 'EXTRACT' }, 10 | { 11 | type: 'paren_block', 12 | syntax: [ 13 | { type: 'Expr', as: 'left' }, 14 | { type: 'keyword', value: 'FROM' }, 15 | { type: 'Expr', as: 'right', assert: true }, 16 | ], 17 | autoSpacing: false 18 | } 19 | ]; 20 | } 21 | 22 | /* AST API */ 23 | 24 | left() { return this._get('left'); } 25 | 26 | right() { return this._get('right'); } 27 | } -------------------------------------------------------------------------------- /src/lang/dml/MYSetStmt.js: -------------------------------------------------------------------------------- 1 | import { AbstractNodeList } from '../abstracts/AbstractNodeList.js'; 2 | 3 | export class MYSetStmt extends AbstractNodeList { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | const itemSeparator = { type: 'punctuation', value: ',' }; 9 | return { 10 | dialect: 'mysql', 11 | syntax: [ 12 | { type: 'keyword', value: 'SET' }, 13 | { type: 'MYVarAssignmentExpr', as: 'entries', arity: { min: 1 }, itemSeparator, assert: true, autoIndent: 2 }, 14 | ] 15 | }; 16 | } 17 | 18 | /** API */ 19 | 20 | jsonfy({ deSugar, ...options } = {}, transformer = null, schemaInference = null) { 21 | return super.jsonfy(options, transformer, schemaInference); 22 | } 23 | } -------------------------------------------------------------------------------- /src/lang/dml/clauses/MYOnDuplicateKeyUpdateClause.js: -------------------------------------------------------------------------------- 1 | import { AbstractNodeList } from '../../abstracts/AbstractNodeList.js'; 2 | 3 | export class MYOnDuplicateKeyUpdateClause extends AbstractNodeList { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | const itemSeparator = { type: 'punctuation', value: ',' }; 9 | return { 10 | dialect: 'mysql', 11 | syntax: [ 12 | { type: 'keyword', value: 'ON' }, 13 | { type: 'keyword', value: 'DUPLICATE' }, 14 | { type: 'keyword', value: 'KEY' }, 15 | { type: 'keyword', value: 'UPDATE' }, 16 | { type: 'AssignmentExpr', as: 'entries', arity: { min: 1 }, itemSeparator, assert: true, autoIndent: true }, 17 | ] 18 | }; 19 | } 20 | } -------------------------------------------------------------------------------- /src/lang/expr/literals/TypedTimeLiteral.js: -------------------------------------------------------------------------------- 1 | import { TypedLiteral } from './TypedLiteral.js'; 2 | 3 | export class TypedTimeLiteral extends TypedLiteral { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return [ 9 | { type: 'data_type', as: 'data_type', value: 'TIME' }, 10 | { type: 'string_literal', as: 'value' }, 11 | { 12 | optional: true, 13 | dialect: 'postgres', 14 | syntax: [ 15 | { type: 'keyword', as: 'pg_with_tz', value: ['WITH', 'WITHOUT'] }, 16 | { type: 'keyword', value: 'TIME ZONE', assert: true }, 17 | ] 18 | }, 19 | ]; 20 | } 21 | 22 | /* AST API */ 23 | 24 | pgWithTZ() { return this._get('pg_with_tz'); } 25 | } -------------------------------------------------------------------------------- /src/lang/dml/expr/ConfigAssignmentExpr.js: -------------------------------------------------------------------------------- 1 | import { BinaryExpr } from '../../expr/op/BinaryExpr.js'; 2 | 3 | export class ConfigAssignmentExpr extends BinaryExpr { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return [ 9 | { type: 'keyword', as: 'my_default_kw', value: 'DEFAULT', booleanfy: true, dialect: 'mysql', optional: true }, 10 | { 11 | syntaxes: [ 12 | { type: 'keyword', as: 'left' }, 13 | { type: 'identifier', as: 'left' }, 14 | ], 15 | }, 16 | { type: 'operator', as: 'operator', value: '=' }, 17 | { type: ['Expr', 'KW'], as: 'right' }, 18 | ]; 19 | } 20 | 21 | /* API */ 22 | 23 | myDefaultKW() { return this._get('my_default_kw'); } 24 | } -------------------------------------------------------------------------------- /src/lang/expr/call/constructs/PGFilterClause.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../../abstracts/AbstractNode.js'; 2 | 3 | export class PGFilterClause extends AbstractNode { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return { 9 | dialect: 'postgres', 10 | syntax: [ 11 | { type: 'keyword', value: 'FILTER' }, 12 | { 13 | type: 'paren_block', 14 | syntax: { type: 'WhereClause', as: 'where_clause' }, 15 | assert: true, 16 | autoIndent: true 17 | } 18 | ] 19 | }; 20 | } 21 | 22 | static get syntaxPriority() { return -1; } 23 | 24 | /* AST API */ 25 | 26 | whereClause() { return this._get('where_clause'); } 27 | } -------------------------------------------------------------------------------- /test/00.live 2.js: -------------------------------------------------------------------------------- 1 | import { PGClient } from '../src/entry/postgres/PGClient.js'; 2 | 3 | const client1 = new PGClient; 4 | await client1.connect(); 5 | 6 | 7 | const sql = ` 8 | SELECT table_name 9 | FROM information_schema.tables 10 | WHERE table_schema = 'public' 11 | `; 12 | 13 | const result = await client1.query(sql); 14 | console.log(result.rows); 15 | 16 | //await client1.query(`SELECT pg_drop_replication_slot('linkedql_default_slot')`); 17 | //console.log((await client1.query(`SELECT * FROM pg_replication_slots`)).rows); 18 | 19 | //const result2 = await client1.query(`UPDATE rrr SET fname = 'John Doe 22' WHERE id = 3`); 20 | //const result2 = await client1.query(`DELETE FROM rrr WHERE id = 1`); 21 | const result3 = await client1.query(`INSERT INTO rrr (fname) VALUES ('John Doe 222---222')`); 22 | await client1.disconnect(); -------------------------------------------------------------------------------- /src/lang/abstracts/AbstractNodeList.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from './AbstractNode.js'; 2 | 3 | export class AbstractNodeList extends AbstractNode { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { return []; } 8 | 9 | // API 10 | 11 | get length() { return (this._get('entries') || []).length; } 12 | 13 | [Symbol.iterator]() { return (this._get('entries') || [])[Symbol.iterator](); } 14 | 15 | ['entries']() { return (this._get('entries') || []).slice(0); } 16 | 17 | delete(index) { return this._delete('entries', index); } 18 | 19 | get(index) { return this._get('entries', index); } 20 | 21 | set(index, value) { return this._set('entries', index, value); } 22 | 23 | has(index) { return this._has('entries', index); } 24 | 25 | add(...args) { return this._add('entries', ...args); } 26 | } -------------------------------------------------------------------------------- /src/lang/dml/expr/ConfigAssignmentExprAlt1.js: -------------------------------------------------------------------------------- 1 | import { BinaryExpr } from '../../expr/op/BinaryExpr.js'; 2 | 3 | export class ConfigAssignmentExprAlt1 extends BinaryExpr { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return [ 9 | { type: 'keyword', as: 'my_default_kw', value: 'DEFAULT', booleanfy: true, dialect: 'mysql', optional: true }, 10 | { 11 | syntaxes: [ 12 | { type: 'keyword', as: 'left' }, 13 | { type: 'identifier', as: 'left' }, 14 | ], 15 | }, 16 | { type: 'operator', as: 'operator', value: '=', optional: true }, 17 | { type: ['Expr', 'KW'], as: 'right' }, 18 | ]; 19 | } 20 | 21 | /* API */ 22 | 23 | myDefaultKW() { return this._get('my_default_kw'); } 24 | } -------------------------------------------------------------------------------- /src/lang/expr/abstraction/ParenExpr.js: -------------------------------------------------------------------------------- 1 | import { AbstractClassicExpr } from '../AbstractClassicExpr.js'; 2 | 3 | export class ParenExpr extends AbstractClassicExpr { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return { 9 | type: 'paren_block', 10 | syntax: { type: 'Expr', as: 'expr' }, 11 | autoIndent: true, 12 | }; 13 | } 14 | 15 | static get syntaxPriority() { return -1; } 16 | 17 | /* AST API */ 18 | 19 | expr() { return this._get('expr'); } 20 | 21 | exprUnwrapped() { 22 | const expr = this._get('expr'); 23 | if (expr instanceof ParenExpr) { 24 | return expr.exprUnwrapped(); 25 | } 26 | return expr; 27 | } 28 | 29 | /* TYPESYS */ 30 | 31 | dataType() { return this.expr()?.dataType(); } 32 | } -------------------------------------------------------------------------------- /src/lang/expr/etc/CastExpr.js: -------------------------------------------------------------------------------- 1 | import { AbstractClassicExpr } from '../AbstractClassicExpr.js'; 2 | 3 | export class CastExpr extends AbstractClassicExpr { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return [ 9 | { type: 'keyword', value: 'CAST' }, 10 | { 11 | type: 'paren_block', 12 | syntax: [ 13 | { type: 'Expr', as: 'expr' }, 14 | { type: 'keyword', value: 'AS' }, 15 | { type: 'DataType', as: 'data_type', assert: true }, 16 | ], 17 | assert: true, 18 | autoSpacing: false, 19 | } 20 | ]; 21 | } 22 | 23 | /* AST API */ 24 | 25 | expr() { return this._get('expr'); } 26 | 27 | dataType() { return this._get('data_type'); } 28 | } -------------------------------------------------------------------------------- /src/lang/ddl/constraint/MYColumnAutoIncrementModifier.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../abstracts/AbstractNode.js'; 2 | import { ColumnIdentityConstraint } from './ColumnIdentityConstraint.js'; 3 | 4 | export class MYColumnAutoIncrementModifier extends AbstractNode { 5 | 6 | /* SYNTAX RULES */ 7 | 8 | static get syntaxRules() { 9 | return { 10 | dialect: 'mysql', 11 | syntax: { type: 'keyword', as: '.', value: 'AUTO_INCREMENT' }, 12 | }; 13 | } 14 | 15 | /* JSON RULES */ 16 | 17 | jsonfy(options = {}, transformer = null, schemaInference = null) { 18 | return (options.toDialect || this.options.dialect) === 'postgres' 19 | ? (new ColumnIdentityConstraint).jsonfy(options, transformer, schemaInference) 20 | : super.jsonfy(options, transformer, schemaInference); 21 | } 22 | } -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: ox-harris # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: webqit # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 13 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 14 | -------------------------------------------------------------------------------- /site/.vitepress/dist/vp-icons.css: -------------------------------------------------------------------------------- 1 | .vpi-social-github{--icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='24' height='24'%3E%3Cpath fill='black' d='M12 .297c-6.63 0-12 5.373-12 12c0 5.303 3.438 9.8 8.205 11.385c.6.113.82-.258.82-.577c0-.285-.01-1.04-.015-2.04c-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729c1.205.084 1.838 1.236 1.838 1.236c1.07 1.835 2.809 1.305 3.495.998c.108-.776.417-1.305.76-1.605c-2.665-.3-5.466-1.332-5.466-5.93c0-1.31.465-2.38 1.235-3.22c-.135-.303-.54-1.523.105-3.176c0 0 1.005-.322 3.3 1.23c.96-.267 1.98-.399 3-.405c1.02.006 2.04.138 3 .405c2.28-1.552 3.285-1.23 3.285-1.23c.645 1.653.24 2.873.12 3.176c.765.84 1.23 1.91 1.23 3.22c0 4.61-2.805 5.625-5.475 5.92c.42.36.81 1.096.81 2.22c0 1.606-.015 2.896-.015 3.286c0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E")} -------------------------------------------------------------------------------- /src/lang/expr/ref/abstracts/AbstractMagicRef.js: -------------------------------------------------------------------------------- 1 | import { ErrorFKInvalid } from './ErrorFKInvalid.js'; 2 | import { SugarMixin } from '../../../abstracts/SugarMixin.js'; 3 | import { BinaryExpr } from '../../op/BinaryExpr.js'; 4 | 5 | export class AbstractMagicRef extends SugarMixin(BinaryExpr) { 6 | 7 | rhsTable(transformer, schemaInference) { 8 | const resolveOperand = this.operand()?.resolve(transformer, schemaInference); 9 | const fk = resolveOperand.resultSchema()/* ColumnSchema */?.fkConstraint(true); 10 | if (!fk) { 11 | throw new ErrorFKInvalid(`[${this.parentNode || this}] Column ${this.operand()} is not a foreign key.`); 12 | } 13 | return fk.targetTable()?.resolve(null/*transformer*/, schemaInference); 14 | } 15 | 16 | rhsSchema(transformer, schemaInference) { return this.rhsTable(transformer, schemaInference)?.resultSchema(); } 17 | } -------------------------------------------------------------------------------- /src/lang/expr/call/constructs/PGWithinGroupClause.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../../abstracts/AbstractNode.js'; 2 | 3 | export class PGWithinGroupClause extends AbstractNode { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return { 9 | dialect: 'postgres', 10 | syntax: [ 11 | { type: 'keyword', value: 'WITHIN' }, 12 | { type: 'keyword', value: 'GROUP' }, 13 | { 14 | type: 'paren_block', 15 | syntax: { type: 'OrderByClause', as: 'order_by_clause' }, 16 | assert: true, 17 | autoIndent: true, 18 | }, 19 | ] 20 | }; 21 | } 22 | 23 | static get syntaxPriority() { return -1; } 24 | 25 | /* AST API */ 26 | 27 | orderByClause() { return this._get('order_by_clause'); } 28 | } -------------------------------------------------------------------------------- /src/lang/expr/ref/Identifier.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../abstracts/AbstractNode.js'; 2 | import { _eq } from '../../abstracts/util.js'; 3 | 4 | export class Identifier extends AbstractNode { 5 | 6 | /* SYNTAX RULES */ 7 | 8 | static get syntaxRules() { return { type: 'identifier', as: '.' }; } 9 | 10 | static get syntaxPriority() { return -1; } 11 | 12 | /* AST API */ 13 | 14 | value() { return this._get('value'); } 15 | 16 | /* API */ 17 | 18 | identifiesAs(ident, cs = undefined) { 19 | if (ident instanceof Identifier) { 20 | return _eq(this.value(), ident.value(), cs === undefined ? (this._has('delim') || ident._has('delim')) : cs); 21 | } 22 | if (typeof ident === 'string') { 23 | return _eq(this._get('value'), ident, cs === undefined ? this._has('delim') : cs); 24 | } 25 | return super.identifiesAs(ident, cs); 26 | } 27 | } -------------------------------------------------------------------------------- /src/lang/expr/ref/index.js: -------------------------------------------------------------------------------- 1 | export { ColumnRef0 } from './ColumnRef0.js'; 2 | export { ColumnRef1 } from './ColumnRef1.js'; 3 | export { ColumnRef2 } from './ColumnRef2.js'; 4 | export { Identifier } from './Identifier.js'; 5 | export { LQBackBackRef } from './LQBackBackRef.js'; 6 | export { LQBackRef } from './LQBackRef.js'; 7 | export { LQBackRefAbstraction } from './LQBackRefAbstraction.js'; 8 | export { LQBackRefEndpoint } from './LQBackRefEndpoint.js'; 9 | export { LQDeepDeepRef1 } from './LQDeepDeepRef1.js'; 10 | export { LQDeepDeepRef2 } from './LQDeepDeepRef2.js'; 11 | export { LQDeepRef1 } from './LQDeepRef1.js'; 12 | export { LQDeepRef2 } from './LQDeepRef2.js'; 13 | export { NamespaceRef } from './NamespaceRef.js'; 14 | export { TableRef0 } from './TableRef0.js'; 15 | export { TableRef1 } from './TableRef1.js'; 16 | export { TableRef2 } from './TableRef2.js'; 17 | export { WindowRef } from './WindowRef.js'; 18 | -------------------------------------------------------------------------------- /src/lang/dql/clauses/UsingClause.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../abstracts/AbstractNode.js'; 2 | 3 | export class UsingClause extends AbstractNode { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | const itemSeparator = { type: 'punctuation', value: ',' }; 9 | return [ 10 | { type: 'keyword', value: 'USING' }, 11 | { 12 | syntaxes: [ 13 | { type: 'Identifier', as: 'column' }, 14 | { 15 | type: 'paren_block', 16 | syntax: { type: 'Identifier', as: 'columns', arity: { min: 1 }, itemSeparator, assert: true } 17 | } 18 | ], assert: true 19 | }, 20 | ]; 21 | } 22 | 23 | /* AST API */ 24 | 25 | column() { return this._get('column'); } 26 | 27 | columns() { return this._get('columns'); } 28 | } -------------------------------------------------------------------------------- /src/lang/expr/Expr.js: -------------------------------------------------------------------------------- 1 | import { AbstractClassicExpr } from './AbstractClassicExpr.js'; 2 | import * as exprs from './index.js'; 3 | 4 | export class Expr extends AbstractClassicExpr { 5 | 6 | /* SYNTAX RULES */ 7 | 8 | static get syntaxRules() { 9 | return { type: ExprNamesInOrder, expression: 1 }; 10 | } 11 | 12 | /* API */ 13 | 14 | static [Symbol.hasInstance](instance) { 15 | return instance instanceof AbstractClassicExpr || instance.constructor.name in exprs; 16 | } 17 | } 18 | 19 | const ExprNames = Object.keys(exprs); 20 | const ExprNamesInOrder = ExprNames.filter((k) => { 21 | return exprs[k] !== Expr && exprs[k].syntaxPriority !== -1; 22 | }).sort((a, b) => { 23 | const comp = (exprs[b].syntaxPriority ?? 100) - (exprs[a].syntaxPriority ?? 100); 24 | if (comp === 0) return exprs[b].prototype.isPrototypeOf(exprs[a].prototype) ? -1 : 1; 25 | return comp; 26 | }); 27 | -------------------------------------------------------------------------------- /src/lang/dml/expr/ConfigAssignmentExprAlt2.js: -------------------------------------------------------------------------------- 1 | import { BinaryExpr } from '../../expr/op/BinaryExpr.js'; 2 | 3 | export class ConfigAssignmentExprAlt2 extends BinaryExpr { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return [ 9 | { type: 'keyword', as: 'default_kw', value: 'DEFAULT', booleanfy: true, optional: true }, 10 | { 11 | syntaxes: [ 12 | { type: 'keyword', as: 'left' }, 13 | { type: 'identifier', as: 'left' }, 14 | ], 15 | }, 16 | { 17 | optional: true, 18 | syntax: [ 19 | { type: 'operator', as: 'operator', value: '=' }, 20 | { type: ['Expr', 'KW'], as: 'right' }, 21 | ], 22 | } 23 | ]; 24 | } 25 | 26 | /* API */ 27 | 28 | myDefaultKW() { return this._get('my_default_kw'); } 29 | } -------------------------------------------------------------------------------- /src/lang/expr/op/UnaryExpr.js: -------------------------------------------------------------------------------- 1 | import { AbstractClassicExpr } from '../AbstractClassicExpr.js'; 2 | import { registry } from '../../registry.js'; 3 | 4 | export class UnaryExpr extends AbstractClassicExpr { 5 | 6 | /* DEFS */ 7 | 8 | static get syntaxRules() { 9 | return [ 10 | { type: 'operator', as: 'operator', value: ['-', '+', 'NOT'] }, 11 | { type: 'Expr', as: 'operand', autoSpacing: ['NOT'] }, 12 | ]; 13 | } 14 | 15 | static get syntaxPriority() { return 1;/* higher than BinaryExpr */ } 16 | 17 | /* AST API */ 18 | 19 | operator() { return this._get('operator'); } 20 | 21 | operand() { return this._get('operand'); } 22 | 23 | /* TYPESYS API */ 24 | 25 | dataType() { 26 | const operator = this.operator(); 27 | if (!operator) return super.dataType(); 28 | return registry.DataType.fromJSON({ value: operator === 'NOT' ? 'BOOLEAN' : 'NUMBER' }); 29 | } 30 | } -------------------------------------------------------------------------------- /src/lang/expr/literals/TypedTimestampLiteral.js: -------------------------------------------------------------------------------- 1 | import { TypedLiteral } from './TypedLiteral.js'; 2 | 3 | export class TypedTimestampLiteral extends TypedLiteral { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return [ 9 | { type: 'data_type', as: 'data_type', value: 'TIMESTAMP', dialect: 'postgres' }, 10 | { type: 'data_type', as: 'data_type', value: ['TIMESTAMP', 'DATETIME'], dialect: 'mysql' }, 11 | { type: 'string_literal', as: 'value' }, 12 | { 13 | optional: true, 14 | dialect: 'postgres', 15 | syntax: [ 16 | { type: 'keyword', as: 'pg_with_tz', value: ['WITH', 'WITHOUT'] }, 17 | { type: 'keyword', value: 'TIME ZONE', assert: true }, 18 | ] 19 | } 20 | ]; 21 | } 22 | 23 | /* AST API */ 24 | 25 | pgWithTZ() { return this._get('pg_with_tz'); } 26 | } -------------------------------------------------------------------------------- /src/lang/ddl/namespace/NamespaceSchema.js: -------------------------------------------------------------------------------- 1 | import { AbstractSchema } from '../../abstracts/AbstractSchema.js'; 2 | import { registry } from '../../registry.js'; 3 | 4 | export class NamespaceSchema extends AbstractSchema { 5 | 6 | /* SYNTAX RULES */ 7 | 8 | static get syntaxRules() { 9 | const itemSeparator = { type: 'punctuation', value: ',' }; 10 | return [ 11 | { type: 'NamespaceIdent', as: 'name', assert: true }, 12 | { 13 | type: 'paren_block', 14 | syntax: { type: 'TableSchema', as: 'entries', arity: Infinity, itemSeparator, singletons: 'BY_KEY', autoIndent: true }, 15 | }, 16 | ]; 17 | } 18 | 19 | /* API */ 20 | 21 | tables() { 22 | const result = []; 23 | for (const entry of this) { 24 | if (!(entry instanceof registry.TableSchema)) continue; 25 | result.push(entry); 26 | } 27 | return result; 28 | } 29 | } -------------------------------------------------------------------------------- /src/lang/expr/op/AtTimeZoneExpr.js: -------------------------------------------------------------------------------- 1 | import { BinaryExpr } from './BinaryExpr.js'; 2 | import { registry } from '../../registry.js'; 3 | 4 | export class AtTimeZoneExpr extends BinaryExpr { 5 | 6 | /* DEFS */ 7 | 8 | static get syntaxRules() { 9 | return [ 10 | { type: 'Expr', as: 'left', peek: [1, 'operator', 'AT'] }, 11 | { type: 'operator', as: 'operator', value: 'AT' }, 12 | { 13 | syntaxes: [ 14 | { type: 'TypedTimeZoneLiteral', as: 'right' }, 15 | { type: 'keyword', as: 'right', value: 'LOCAL' } 16 | ] 17 | } 18 | ]; 19 | } 20 | 21 | static get syntaxPriority() { return 0; } 22 | 23 | /* AST API */ 24 | 25 | left() { return this._get('left'); } 26 | 27 | right() { return this._get('right'); } 28 | 29 | /* TYPESYS API */ 30 | 31 | dataType() { return registry.DataType.fromJSON({ value: 'TIME ZONE' }); } 32 | } -------------------------------------------------------------------------------- /src/lang/ddl/constraint/ColumnPKConstraint.js: -------------------------------------------------------------------------------- 1 | import { ConstraintSchema } from './ConstraintSchema.js'; 2 | import { registry } from '../../registry.js'; 3 | 4 | export class ColumnPKConstraint extends ConstraintSchema { 5 | 6 | /* SYNTAX RULES */ 7 | 8 | static get syntaxRules() { 9 | return this.buildSyntaxRules([ 10 | { type: 'keyword', value: 'PRIMARY' }, 11 | { type: 'keyword', as: '.', value: 'KEY', assert: true }, 12 | { type: 'PGIndexParameters', as: 'pg_index_parameters', optional: true, dialect: 'postgres' }, 13 | ]); 14 | } 15 | 16 | /* AST API */ 17 | 18 | primaryKW() { return this._get('primary_kw'); } 19 | 20 | pgIndexParameters() { return this._get('pg_index_parameters'); } 21 | 22 | /* API */ 23 | 24 | columns() { 25 | return this.parentNode instanceof registry.ColumnSchema 26 | ? [registry.ColumnRef2.fromJSON({ value: this.parentNode.name().value() })] 27 | : []; 28 | } 29 | } -------------------------------------------------------------------------------- /src/lang/dql/clauses/OrderByClause.js: -------------------------------------------------------------------------------- 1 | import { AbstractNodeList } from '../../abstracts/AbstractNodeList.js'; 2 | 3 | export class OrderByClause extends AbstractNodeList { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | const itemSeparator = { type: 'punctuation', value: ',' }; 9 | return [ 10 | { type: 'keyword', value: 'ORDER' }, 11 | { type: 'keyword', value: 'BY', assert: true }, 12 | { type: 'OrderElement', as: 'entries', arity: { min: 1 }, itemSeparator, assert: true, autoIndent: 2 }, 13 | { 14 | optional: true, 15 | autoIndent: true, 16 | syntax: [ 17 | { type: 'keyword', as: 'with_rollup', value: 'WITH', booleanfy: true }, 18 | { type: 'keyword', value: 'ROLLUP', assert: true }, 19 | ] 20 | }, 21 | ]; 22 | } 23 | 24 | /* AST API */ 25 | 26 | withRollup() { return this._get('with_rollup'); } 27 | } -------------------------------------------------------------------------------- /src/lang/ddl/constraint/TablePKConstraint.js: -------------------------------------------------------------------------------- 1 | import { ConstraintSchema } from './ConstraintSchema.js'; 2 | 3 | export class TablePKConstraint extends ConstraintSchema { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | const itemSeparator = { type: 'punctuation', value: ',' }; 9 | return this.buildSyntaxRules([ 10 | { type: 'keyword', value: 'PRIMARY' }, 11 | { type: 'keyword', as: '.', value: 'KEY', assert: true }, 12 | { 13 | type: 'paren_block', 14 | syntax: { type: 'ColumnRef2', as: 'columns', arity: { min: 1 }, itemSeparator, singletons: 'BY_KEY', assert: true }, 15 | assert: true, 16 | }, 17 | { type: 'PGIndexParameters', as: 'pg_index_parameters', optional: true, dialect: 'postgres' }, 18 | ]); 19 | } 20 | 21 | /* AST API */ 22 | 23 | columns() { return this._get('columns'); } 24 | 25 | pgIndexParameters() { return this._get('pg_index_parameters'); } 26 | } -------------------------------------------------------------------------------- /src/flashql/fetch/AbstractFetchClient.js: -------------------------------------------------------------------------------- 1 | import { normalizeQueryArgs } from '../../entry/abstracts/util.js'; 2 | import { AbstractClient } from '../../entry/abstracts/AbstractClient.js'; 3 | 4 | export class AbstractFetchClient extends AbstractClient { 5 | 6 | async parse(requestSpec, { alias = null, dynamicWhereMode = false, ...options } = {}) { 7 | } 8 | 9 | async resolve(request, options = {}) { 10 | } 11 | 12 | async request(...args) { 13 | const [_request, options] = normalizeQueryArgs(...args); 14 | const request = await this.parse(_request, options); 15 | return await this._request(request, options); 16 | } 17 | 18 | async stream(...args) { 19 | const [_request, options] = normalizeQueryArgs(...args); 20 | const request = await this.parse(_request, options); 21 | return await this._stream(request, options); 22 | } 23 | 24 | async showCreate(selector, structured = false) { 25 | return await this._showCreate(selector, structured); 26 | } 27 | } -------------------------------------------------------------------------------- /site/.vitepress/theme/custom.css: -------------------------------------------------------------------------------- 1 | :root { 2 | /* Logo */ 3 | --vp-nav-logo-height: 40px; 4 | 5 | /* Dark background for code blocks */ 6 | --vp-code-block-bg: #212327; 7 | 8 | --vp-button-brand-text: black; 9 | --vp-button-brand-hover-text: black; 10 | --vp-button-brand-active-text: black; 11 | 12 | --vp-c-brand-1: #e9c80d; 13 | --vp-c-brand-2: gold; 14 | --vp-c-brand-3: #ffbf00; 15 | } 16 | 17 | .nowrap { 18 | white-space: nowrap; 19 | } 20 | 21 | h1 { counter-reset: h2_c; } 22 | 23 | h2 { 24 | counter-increment: h2_c; 25 | counter-reset: h3_c; 26 | } 27 | h2:not(.title, .text, :has(em)):before { content: counter(h2_c) ". "; } 28 | 29 | h3 { 30 | counter-increment: h3_c; 31 | counter-reset: h4_c; 32 | } 33 | h3:not(.text):before { content: counter(h2_c) "." counter(h3_c) ". "; } 34 | 35 | h4 { 36 | counter-increment: h4_c; 37 | } 38 | h4:not(.text):before { content: counter(h2_c) "." counter(h3_c) "." counter(h4_c) ". "; } 39 | 40 | :is(h2, h3, h4)::before { 41 | font-family: "Roboto Mono", monospace; 42 | } -------------------------------------------------------------------------------- /src/lang/dql/clauses/OrderElement.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../abstracts/AbstractNode.js'; 2 | 3 | export class OrderElement extends AbstractNode { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return [ 9 | { type: 'Expr', as: 'expr' }, 10 | { 11 | optional: true, 12 | syntaxes: [ 13 | { type: 'keyword', value: ['ASC', 'DESC'], as: 'dir' }, 14 | { type: 'PGOrderOperator', as: 'dir' }, 15 | ] 16 | }, 17 | { 18 | optional: true, 19 | syntax: [ 20 | { type: 'keyword', value: 'NULLS' }, 21 | { type: 'keyword', as: 'nulls_spec', value: ['FIRST', 'LAST'], assert: true }, 22 | ] 23 | }, 24 | ]; 25 | } 26 | 27 | /* AST API */ 28 | 29 | expr() { return this._get('expr'); } 30 | 31 | dir() { return this._get('dir'); } 32 | 33 | nullsSpec() { return this._get('nulls_spec'); } 34 | } -------------------------------------------------------------------------------- /src/lang/expr/literals/index.js: -------------------------------------------------------------------------------- 1 | export { BitLiteral } from './BitLiteral.js'; 2 | export { BoolLiteral } from './BoolLiteral.js'; 3 | export { DefaultLiteral } from './DefaultLiteral.js'; 4 | export { HexLiteral } from './HexLiteral.js'; 5 | export { NullLiteral } from './NullLiteral.js'; 6 | export { NumberLiteral } from './NumberLiteral.js'; 7 | export { StringLiteral } from './StringLiteral.js'; 8 | export { TypedDateLiteral } from './TypedDateLiteral.js'; 9 | export { TypedIntervalLiteral } from './TypedIntervalLiteral.js'; 10 | export { TypedLiteral } from './TypedLiteral.js'; 11 | export { TypedTimeLiteral } from './TypedTimeLiteral.js'; 12 | export { TypedTimestampLiteral } from './TypedTimestampLiteral.js'; 13 | export { TypedTimeZoneLiteral } from './TypedTimeZoneLiteral.js'; 14 | export { UnknownLiteral } from './UnknownLiteral.js'; 15 | export { LQArrayLiteral } from './LQArrayLiteral.js'; 16 | export { LQObjectLiteral } from './LQObjectLiteral.js'; 17 | export { LQObjectProperty } from './LQObjectProperty.js'; 18 | export { PGTypedArrayLiteral } from './PGTypedArrayLiteral.js'; 19 | -------------------------------------------------------------------------------- /src/lang/ddl/constraint/constructs/ReferentialAction.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../../abstracts/AbstractNode.js'; 2 | 3 | export class ReferentialAction extends AbstractNode { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | const itemSeparator = { type: 'punctuation', value: ',' }; 9 | return { 10 | syntaxes: [ 11 | { type: 'keyword', as: 'value', value: ['NO ACTION', 'RESTRICT', 'CASCADE'] }, 12 | [ 13 | { type: 'keyword', as: 'value', value: ['SET NULL', 'SET DEFAULT'] }, 14 | { 15 | optional: true, 16 | dialect: 'postgres', 17 | type: 'paren_block', 18 | syntax: { type: 'Identifier', as: 'columns', arity: { min: 1 }, itemSeparator }, 19 | } 20 | ], 21 | ], 22 | }; 23 | } 24 | 25 | /*. AST API */ 26 | 27 | value() { return this._get('value'); } 28 | 29 | columns() { return this._get('columns'); } 30 | } -------------------------------------------------------------------------------- /test/00.live.js: -------------------------------------------------------------------------------- 1 | import { PGClient } from '../src/entry/postgres/PGClient.js'; 2 | import { Script } from '../src/lang/Script.js'; 3 | 4 | //const r = await Script.parse(`SELECdT INTO`); 5 | //console.log(r.entries()[0], r+'', r.jsonfy()); 6 | //process.exit(); 7 | 8 | const client1 = new PGClient; 9 | await client1.connect(); 10 | 11 | 12 | const sql = ` 13 | SELECT table_name 14 | FROM information_schema.tables 15 | WHERE table_schema = 'public' 16 | `; 17 | 18 | const result = await client1.query(sql); 19 | console.log(result.rows); 20 | 21 | //await client1.query(`ALTER TABLE rrr RENAME COLUMN full_name TO fname`); 22 | 23 | //await client1.query(`SELECT pg_drop_replication_slot('linkedql_default_slot')`); 24 | //console.log((await client1.query(`SELECT * FROM pg_replication_slots`)).rows); 25 | 26 | //const result2 = await client1.query(`UPDATE rrr SET fname = 'John Doe 22' WHERE id = 3`); 27 | //const result2 = await client1.query(`DELETE FROM rrr WHERE id = 1`); 28 | const result3 = await client1.query(`INSERT INTO rrr (fname) VALUES ('John Doe 222---222')`); 29 | await client1.disconnect(); -------------------------------------------------------------------------------- /src/lang/dql/clauses/WindowSpec.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../abstracts/AbstractNode.js'; 2 | 3 | export class WindowSpec extends AbstractNode { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return { 9 | type: 'paren_block', 10 | syntax: [ 11 | { type: 'WindowRef', as: 'super_window', optional: true }, 12 | { type: 'PartitionByClause', as: 'partition_by_clause', optional: true, autoIndent: true }, 13 | { type: 'OrderByClause', as: 'order_by_clause', optional: true, autoIndent: true }, 14 | { type: 'WindowFrameSpec', as: 'frame_spec', optional: true, autoIndent: true }, 15 | ], 16 | autoIndent: true, 17 | autoIndentAdjust: -1 18 | }; 19 | } 20 | 21 | /* AST API */ 22 | 23 | superWindow() { return this._get('super_window'); } 24 | 25 | partitionByClause() { return this._get('partition_by_clause'); } 26 | 27 | orderByClause() { return this._get('order_by_clause'); } 28 | 29 | frameSpec() { return this._get('frame_spec'); } 30 | } -------------------------------------------------------------------------------- /src/lang/abstracts/AbstractStmt.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from './AbstractNode.js'; 2 | 3 | export class AbstractStmt extends AbstractNode { 4 | 5 | get statementNode() { return this; } 6 | 7 | /* JSON API */ 8 | 9 | #uuid; 10 | 11 | get uuid() { 12 | if (!this.#uuid) { 13 | this.#uuid = `$query${(0 | Math.random() * 9e6).toString(36)}`; 14 | } 15 | return this.#uuid; 16 | } 17 | 18 | static fromJSON(inputJson, options = {}, callback = null) { 19 | if (inputJson instanceof AbstractNode) { 20 | return super.fromJSON(inputJson, options, callback); 21 | } 22 | const { uuid, ...restJson } = inputJson; 23 | const instance = super.fromJSON(restJson, options, callback); 24 | if (instance) { 25 | instance.#uuid = uuid; 26 | } 27 | return instance; 28 | } 29 | 30 | jsonfy(options = {}, transformer = null, schemaInference = null) { 31 | let resultJson = super.jsonfy(options, transformer, schemaInference); 32 | if (this.#uuid) { 33 | resultJson = { 34 | uuid: this.#uuid, 35 | ...resultJson, 36 | }; 37 | } 38 | return resultJson; 39 | } 40 | } -------------------------------------------------------------------------------- /src/lang/dql/TA/SRFExprDDL2.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../abstracts/AbstractNode.js'; 2 | 3 | export class SRFExprDDL2 extends AbstractNode { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | const itemSeparator = { type: 'punctuation', value: ',' }; 9 | return [ 10 | { 11 | syntaxes: [ 12 | { type: 'Identifier', as: 'alias', peek: [1, 'paren_block'] }, 13 | [ 14 | { type: 'keyword', as: 'as_kw', value: 'AS', peek: [2, 'paren_block'] }, 15 | { type: 'Identifier', as: 'alias', assert: true } 16 | ] 17 | ] 18 | }, 19 | { 20 | type: 'paren_block', 21 | syntax: { type: 'ColumnSchema', as: 'column_defs', arity: { min: 1 }, itemSeparator }, 22 | } 23 | ]; 24 | } 25 | 26 | /* AST API */ 27 | 28 | asKW() { return this._get('as_kw'); } 29 | 30 | alias() { return this._get('alias'); } 31 | 32 | columnDefs() { return this._get('column_defs'); } 33 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Linked DB 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/lang/expr/case/CaseExpr.js: -------------------------------------------------------------------------------- 1 | import { TypeSysMixin } from '../../abstracts/TypeSysMixin.js'; 2 | import { AbstractNodeList } from '../../abstracts/AbstractNodeList.js'; 3 | 4 | export class CaseExpr extends TypeSysMixin(AbstractNodeList) { 5 | 6 | /* DEFS */ 7 | 8 | static get syntaxRules() { 9 | return [ 10 | { type: 'keyword', value: 'CASE' }, 11 | { type: 'Expr', as: 'subject', optional: true }, 12 | { type: 'CaseBranch', as: 'entries', arity: { min: 1 }, assert: true, autoIndent: 2 }, 13 | { 14 | optional: true, 15 | syntax: [ 16 | { type: 'keyword', value: 'ELSE' }, 17 | { type: 'Expr', as: 'alternate', autoIndent: true }, 18 | ], 19 | autoSpacing: '\n', 20 | }, 21 | { type: 'keyword', value: 'END', autoSpacing: '\n' }, 22 | ]; 23 | } 24 | 25 | /* AST API */ 26 | 27 | subject() { return this._get('subject'); } 28 | 29 | branches() { return this.entries(); } 30 | 31 | alternate() { return this._get('alternate'); } 32 | } -------------------------------------------------------------------------------- /src/lang/dql/clauses/WindowFrameBound.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../abstracts/AbstractNode.js'; 2 | 3 | export class WindowFrameBound extends AbstractNode { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return { 9 | syntaxes: [ 10 | { type: 'keyword', as: 'specifier', value: 'CURRENT ROW' }, 11 | [ 12 | { type: 'keyword', as: 'specifier', value: 'UNBOUNDED' }, 13 | { type: 'keyword', as: 'dir', value: ['PRECEDING', 'FOLLOWING'] }, 14 | ], 15 | [ 16 | { type: 'number_literal', as: 'specifier' }, 17 | { type: 'keyword', as: 'dir', value: ['PRECEDING', 'FOLLOWING'] }, 18 | ], 19 | [ 20 | { type: 'Expr'/* Ideally, Temporal types */, as: 'specifier' }, 21 | { type: 'keyword', as: 'dir', value: ['PRECEDING', 'FOLLOWING'] }, 22 | ], 23 | ] 24 | }; 25 | } 26 | 27 | /* AST API */ 28 | 29 | specifier() { return this._get('specifier'); } 30 | 31 | dir() { return this._get('dir'); } 32 | } -------------------------------------------------------------------------------- /src/lang/ddl/constraint/CheckConstraint.js: -------------------------------------------------------------------------------- 1 | import { registry } from '../../registry.js'; 2 | import { ConstraintSchema } from './ConstraintSchema.js'; 3 | 4 | export class CheckConstraint extends ConstraintSchema { 5 | 6 | /* SYNTAX RULES */ 7 | 8 | static get syntaxRules() { 9 | return this.buildSyntaxRules([ 10 | { type: 'keyword', value: 'CHECK' }, 11 | { 12 | type: 'paren_block', 13 | syntax: { type: 'Expr', as: 'expr', assert: true }, 14 | assert: true, 15 | }, 16 | { type: 'keyword', as: 'no_inherit_kw', value: 'NO INHERIT', optional: true } 17 | ]); 18 | } 19 | 20 | /* AST API */ 21 | 22 | expr() { return this._get('expr'); } 23 | 24 | noInheritKW() { return this._get('no_inherit_kw'); } 25 | 26 | /* API */ 27 | 28 | columns() { 29 | const columns = []; 30 | this.expr()?.walkTree((node) => { 31 | if (node instanceof registry.ColumnRef1) { 32 | columns.push(registry.ColumnRef2.fromJSON({ value: node.value() })) 33 | } else return node; 34 | }); 35 | return columns; 36 | } 37 | } -------------------------------------------------------------------------------- /src/lang/dql/clauses/GroupByClause.js: -------------------------------------------------------------------------------- 1 | import { AbstractNodeList } from '../../abstracts/AbstractNodeList.js'; 2 | 3 | export class GroupByClause extends AbstractNodeList { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | const itemSeparator = { type: 'punctuation', value: ',' }; 9 | return [ 10 | { type: 'keyword', value: 'GROUP' }, 11 | { type: 'keyword', value: 'BY', assert: true }, 12 | { type: 'keyword', as: 'all_or_distinct', value: ['ALL', 'DISTINCT'], optional: true }, 13 | { type: 'GroupingElement', as: 'entries', arity: { min: 1 }, itemSeparator, assert: true, autoIndent: 2 }, 14 | { 15 | optional: true, 16 | autoIndent: true, 17 | syntax: [ 18 | { type: 'keyword', as: 'with_rollup', value: 'WITH', booleanfy: true }, 19 | { type: 'keyword', value: 'ROLLUP', assert: true }, 20 | ] 21 | }, 22 | ]; 23 | } 24 | 25 | /* AST API */ 26 | 27 | allOrDistinct() { return this._get('all_or_distinct'); } 28 | 29 | withRollup() { return this._get('with_rollup'); } 30 | } -------------------------------------------------------------------------------- /src/lang/abstracts/ResultSchemaMixin.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from './AbstractNode.js'; 2 | 3 | export const ResultSchemaMixin = (Class) => class extends Class { 4 | 5 | #result_schema; 6 | 7 | resultSchema() { return this.#result_schema; } 8 | 9 | static fromJSON(inputJson, options = {}, callback = null) { 10 | if (!inputJson || inputJson instanceof AbstractNode) { 11 | return super.fromJSON(inputJson, options, callback); 12 | } 13 | const { result_schema, ...restJson } = inputJson; 14 | const instance = super.fromJSON(restJson, options, callback); 15 | if (instance && result_schema) { 16 | if (!(result_schema instanceof AbstractNode)) { 17 | throw new Error(`Invalid Schema object passed at inputJson.result_schema`); 18 | } 19 | instance.#result_schema = result_schema; 20 | } 21 | return instance; 22 | } 23 | 24 | jsonfy(options = {}, transformer = null, schemaInference = null) { 25 | let resultJson = super.jsonfy(options, transformer, schemaInference); 26 | if (this.#result_schema && options.resultSchemas !== false) { 27 | resultJson = { 28 | ...resultJson, 29 | result_schema: this.#result_schema, 30 | }; 31 | } 32 | return resultJson; 33 | } 34 | } -------------------------------------------------------------------------------- /src/entry/abstracts/SimpleEmitter.js: -------------------------------------------------------------------------------- 1 | export class SimpleEmitter { 2 | 3 | #listeners = new Map; 4 | #closeCallbacks = new Set; 5 | 6 | on(event, fn) { 7 | if (!this.#listeners.has(event)) { 8 | this.#listeners.set(event, new Set); 9 | } 10 | this.#listeners.get(event).add(fn); 11 | return () => { 12 | this.#listeners.get(event).delete(fn); 13 | if (!this.#listeners.get(event).size) { 14 | this.#listeners.delete(event); 15 | if (!this.#listeners.size) { 16 | for (const fn of this.#closeCallbacks) fn(); 17 | this.#closeCallbacks.clear(); 18 | } 19 | } 20 | }; 21 | } 22 | 23 | onClose(fn) { this.#closeCallbacks.add(fn); } 24 | 25 | emit(event, payload) { 26 | const s = this.#listeners.get(event); 27 | if (!s) return; 28 | for (const fn of s) { 29 | fn(payload); 30 | try { 31 | } catch (err) { 32 | // eslint-disable-next-line no-console 33 | console.error('emitter handler error', err); 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/lang/dql/clauses/DistinctClause.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../abstracts/AbstractNode.js'; 2 | 3 | export class DistinctClause extends AbstractNode { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | const itemSeparator = { type: 'punctuation', value: ',' }; 9 | return { 10 | syntaxes: [ 11 | { 12 | dialect: 'postgres', 13 | syntax: [ 14 | { type: 'keyword', value: 'DISTINCT' }, 15 | { type: 'keyword', value: 'ON' }, 16 | { 17 | type: 'paren_block', 18 | syntax: { type: 'Expr', as: 'pg_distinct_on_list', arity: { min: 1 }, itemSeparator, assert: true } 19 | }, 20 | ], 21 | }, 22 | { type: 'keyword', as: 'all_or_distinct', value: ['ALL', 'DISTINCT'] }, 23 | ] 24 | }; 25 | } 26 | 27 | /* AST API */ 28 | 29 | allOrDistinct() { return this._get('all_or_distinct'); } 30 | 31 | // -- Postgres 32 | 33 | pgDistinctOnList() { return this._get('pg_distinct_on_list'); } 34 | } -------------------------------------------------------------------------------- /src/lang/ddl/constraint/index.js: -------------------------------------------------------------------------------- 1 | export * from './constructs/index.js'; 2 | export { CheckConstraint } from './CheckConstraint.js'; 3 | export { ColumnDefaultConstraint } from './ColumnDefaultConstraint.js'; 4 | export { ColumnExpressionConstraint } from './ColumnExpressionConstraint.js'; 5 | export { ColumnFKConstraint } from './ColumnFKConstraint.js'; 6 | export { ColumnIdentityConstraint } from './ColumnIdentityConstraint.js'; 7 | export { ColumnNullConstraint } from './ColumnNullConstraint.js'; 8 | export { ColumnPKConstraint } from './ColumnPKConstraint.js'; 9 | export { ColumnUKConstraint } from './ColumnUKConstraint.js'; 10 | export { ConstraintSchema } from './ConstraintSchema.js'; 11 | export { MYColumnAutoIncrementModifier } from './MYColumnAutoIncrementModifier.js'; 12 | export { MYColumnCommentModifier } from './MYColumnCommentModifier.js'; 13 | export { MYColumnOnUpdateModifier } from './MYColumnOnUpdateModifier.js'; 14 | export { MYColumnVisibilityModifier } from './MYColumnVisibilityModifier.js'; 15 | export { PGTableEXConstraint } from './PGTableEXConstraint.js'; 16 | export { TableFKConstraint } from './TableFKConstraint.js'; 17 | export { TablePKConstraint } from './TablePKConstraint.js'; 18 | export { TableUKConstraint } from './TableUKConstraint.js'; 19 | -------------------------------------------------------------------------------- /src/lang/dml/clauses/PGConflictTargetIndexSpec.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../abstracts/AbstractNode.js'; 2 | 3 | export class PGConflictTargetIndexSpec extends AbstractNode { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return [ 9 | { 10 | syntaxes: [ 11 | { type: 'ColumnRef2', as: 'column_name' }, 12 | { type: 'paren_block', syntax: { type: 'Expr', as: 'expr', assert: true }, autoIndent: true }, 13 | { type: 'CallExpr', as: 'expr' }, // Must come after the parens option 14 | ], 15 | }, 16 | { 17 | optional: true, 18 | syntax: [ 19 | { type: 'operator', value: 'COLLATE' }, 20 | { type: 'string_literal', as: 'collation', assert: true }, 21 | ], 22 | }, 23 | { type: 'Identifier', as: 'opclass', optional: true }, 24 | ]; 25 | } 26 | 27 | /* AST API */ 28 | 29 | columnName() { return this._get('column_name'); } 30 | 31 | expr() { return this._get('expr'); } 32 | 33 | collation() { return this._get('collation'); } 34 | 35 | opclass() { return this._get('opclass'); } 36 | } -------------------------------------------------------------------------------- /src/lang/dql/TA/SelectItemAlias.js: -------------------------------------------------------------------------------- 1 | import { Identifier } from '../../expr/ref/Identifier.js'; 2 | 3 | export class SelectItemAlias extends Identifier { 4 | static get syntaxRules() { 5 | return [ 6 | { 7 | syntaxes: [ 8 | { ...[].concat(super.syntaxRules)[0] }, 9 | [ 10 | { type: 'keyword', as: 'as_kw', value: 'AS', booleanfy: true }, 11 | { ...[].concat(super.syntaxRules)[0], assert: true }, 12 | ] 13 | ] 14 | }, 15 | { type: 'AggrNotation', as: 'is_aggr', autoSpacing: false, optional: true }, 16 | ]; 17 | } 18 | 19 | /* AST API */ 20 | 21 | asKW() { return this._get('as_kw'); } 22 | 23 | isAggr() { return this._get('is_aggr'); } 24 | 25 | // -------------- 26 | 27 | jsonfy(options = {}, transformer = null, schemaInference = null) { 28 | let resultJson = super.jsonfy(options, transformer, schemaInference); 29 | if ((options.deSugar === true || options.deSugar?.normalizeCasing) && !resultJson.delim) { 30 | resultJson = { ...resultJson, value: resultJson.value.toLowerCase(), }; 31 | } 32 | return resultJson; 33 | } 34 | } -------------------------------------------------------------------------------- /src/lang/dql/clauses/index.js: -------------------------------------------------------------------------------- 1 | export { DistinctClause } from './DistinctClause.js'; 2 | export { ForClause } from './ForClause.js'; 3 | export { FromClause } from './FromClause.js'; 4 | export { GroupByClause } from './GroupByClause.js'; 5 | export { GroupingElement } from './GroupingElement.js'; 6 | export { HavingClause } from './HavingClause.js'; 7 | export { JoinClause } from './JoinClause.js'; 8 | export { LimitClause } from './LimitClause.js'; 9 | export { OffsetClause } from './OffsetClause.js'; 10 | export { OnClause } from './OnClause.js'; 11 | export { OrderByClause } from './OrderByClause.js'; 12 | export { OrderElement } from './OrderElement.js'; 13 | export { PartitionByClause } from './PartitionByClause.js'; 14 | export { PGFetchClause } from './PGFetchClause.js'; 15 | export { PGOrderOperator } from './PGOrderOperator.js'; 16 | export { SelectList } from './SelectList.js'; 17 | export { UsingClause } from './UsingClause.js'; 18 | export { WhereClause } from './WhereClause.js'; 19 | export { WindowClause } from './WindowClause.js'; 20 | export { WindowDeclaration } from './WindowDeclaration.js'; 21 | export { WindowFrameSpec } from './WindowFrameSpec.js'; 22 | export { WindowFrameBound } from './WindowFrameBound.js'; 23 | export { WindowSpec } from './WindowSpec.js'; 24 | -------------------------------------------------------------------------------- /src/lang/dql/clauses/PGFetchClause.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../abstracts/AbstractNode.js'; 2 | 3 | export class PGFetchClause extends AbstractNode { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return { 9 | dialect: 'postgres', 10 | syntax: [ 11 | { type: 'keyword', value: 'FETCH' }, 12 | { type: 'keyword', as: 'rel_kw', value: ['FIRST', 'NEXT'] }, 13 | { type: 'Expr', as: 'expr', optional: true }, 14 | { type: 'keyword', as: 'row_kw', value: ['ROW', 'ROWS'], assert: true }, 15 | { 16 | syntaxes: [ 17 | { type: 'keyword', value: 'ONLY' }, 18 | [ 19 | { type: 'keyword', as: 'with_ties', value: 'WITH' }, 20 | { type: 'keyword', value: 'TIES', assert: true }, 21 | ] 22 | ] 23 | } 24 | ] 25 | }; 26 | } 27 | 28 | /* AST API */ 29 | 30 | relKW() { return this._get('rel_kw'); } 31 | 32 | expr() { return this._get('expr'); } 33 | 34 | rowKW() { return this._get('row_kw'); } 35 | 36 | withTies() { return this._get('with_ties'); } 37 | } -------------------------------------------------------------------------------- /src/lang/dml/clauses/PGConflictTarget.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../abstracts/AbstractNode.js'; 2 | 3 | export class PGConflictTarget extends AbstractNode { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | const itemSeparator = { type: 'punctuation', value: ',' }; 9 | return { 10 | syntaxes: [ 11 | [ 12 | { type: 'keyword', value: 'ON' }, 13 | { type: 'keyword', value: 'CONSTRAINT' }, 14 | { type: 'Identifier', as: 'constraint_name', assert: true } 15 | ], 16 | [ 17 | { 18 | type: 'paren_block', 19 | syntax: { type: 'PGConflictTargetIndexSpec', as: 'index_list', arity: { min: 1 }, itemSeparator, assert: true }, 20 | autoIndent: true, 21 | }, 22 | { type: 'WhereClause', as: 'where_clause', optional: true, autoIndent: true }, 23 | ], 24 | ], 25 | }; 26 | } 27 | 28 | /* AST API */ 29 | 30 | constraintName() { return this._get('constraint_name'); } 31 | 32 | indexList() { return this._get('index_list'); } 33 | 34 | whereClause() { return this._get('where_clause'); } 35 | } -------------------------------------------------------------------------------- /src/lang/ddl/DropTableStmt.js: -------------------------------------------------------------------------------- 1 | import { DDLStmt } from './DDLStmt.js'; 2 | 3 | export class DropTableStmt extends DDLStmt { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | const itemSeparator = { type: 'punctuation', value: ',' }; 9 | return [ 10 | { type: 'keyword', value: 'DROP' }, 11 | { type: 'keyword', as: 'my_temporary_kw', value: 'TEMPORARY', booleanfy: true, optional: true, dialect: 'mysql' }, 12 | { type: 'keyword', value: 'TABLE' }, 13 | { 14 | optional: true, 15 | syntax: [ 16 | { type: 'keyword', as: 'if_exists', value: 'IF', booleanfy: true }, 17 | { type: 'keyword', value: 'EXISTS' }, 18 | ] 19 | }, 20 | { type: ['TableIdent', 'Identifier'/* to support mock names */], as: 'names', arity: { min: 1 }, itemSeparator }, 21 | { type: 'keyword', as: 'cascade_rule', value: ['CASCADE', 'RESTRICT'], optional: true }, 22 | ]; 23 | } 24 | 25 | /* AST API */ 26 | 27 | myTemporaryKW() { return this._get('my_temporary_kw'); } 28 | 29 | ifExists() { return this._get('if_exists'); } 30 | 31 | names() { return this._get('names'); } 32 | 33 | cascadeRule() { return this._get('cascade_rule'); } 34 | } -------------------------------------------------------------------------------- /site/.vitepress/dist/assets/app.Ds4M_nwI.js: -------------------------------------------------------------------------------- 1 | import{R as p}from"./chunks/theme.CAZbyQ2r.js";import{R as s,a2 as i,a3 as u,a4 as c,a5 as l,a6 as f,a7 as d,a8 as m,a9 as h,aa as g,ab as A,d as v,u as R,v as w,s as y,ac as C,ad as P,ae as b,af as E}from"./chunks/framework.B-XtCDNB.js";function r(e){if(e.extends){const a=r(e.extends);return{...a,...e,async enhanceApp(t){a.enhanceApp&&await a.enhanceApp(t),e.enhanceApp&&await e.enhanceApp(t)}}}return e}const n=r(p),S=v({name:"VitePressApp",setup(){const{site:e,lang:a,dir:t}=R();return w(()=>{y(()=>{document.documentElement.lang=a.value,document.documentElement.dir=t.value})}),e.value.router.prefetchLinks&&C(),P(),b(),n.setup&&n.setup(),()=>E(n.Layout)}});async function T(){globalThis.__VITEPRESS__=!0;const e=_(),a=D();a.provide(u,e);const t=c(e.route);return a.provide(l,t),a.component("Content",f),a.component("ClientOnly",d),Object.defineProperties(a.config.globalProperties,{$frontmatter:{get(){return t.frontmatter.value}},$params:{get(){return t.page.value.params}}}),n.enhanceApp&&await n.enhanceApp({app:a,router:e,siteData:m}),{app:a,router:e,data:t}}function D(){return A(S)}function _(){let e=s;return h(a=>{let t=g(a),o=null;return t&&(e&&(t=t.replace(/\.js$/,".lean.js")),o=import(t)),s&&(e=!1),o},n.NotFound)}s&&T().then(({app:e,router:a,data:t})=>{a.go().then(()=>{i(a.route,t.site),e.mount("#app")})});export{T as createApp}; 2 | -------------------------------------------------------------------------------- /src/lang/dql/clauses/LimitClause.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../abstracts/AbstractNode.js'; 2 | 3 | export class LimitClause extends AbstractNode { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return [ 9 | { type: 'keyword', value: 'LIMIT' }, 10 | { 11 | dialect: 'mysql', 12 | syntax: [ 13 | { 14 | optional: true, 15 | syntax: [ 16 | { type: 'Expr', as: 'my_offset' }, 17 | { type: 'punctuation', value: ',', autoSpacing: false }, 18 | ] 19 | }, 20 | { type: 'Expr', as: 'expr', assert: true, }, 21 | ] 22 | }, 23 | { 24 | dialect: 'postgres', 25 | syntaxes: [ 26 | { type: 'keyword', as: 'pg_all_kw', value: 'ALL' }, 27 | { type: 'Expr', as: 'expr', assert: true }, 28 | ], 29 | }, 30 | ]; 31 | } 32 | 33 | /* AST API */ 34 | 35 | expr() { return this._get('expr'); } 36 | 37 | // -- Postgres 38 | 39 | pgAllKW() { return this._get('pg_all_kw'); } 40 | 41 | // -- MySQL 42 | 43 | myOffset() { return this._get('my_offset'); } 44 | } -------------------------------------------------------------------------------- /src/lang/cte/constructs/PGSearchClause.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../abstracts/AbstractNode.js'; 2 | 3 | export class PGSearchClause extends AbstractNode { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | const itemSeparator = { type: 'punctuation', value: ',' }; 9 | return { 10 | dialect: 'postgres', 11 | syntax: [ 12 | { type: 'keyword', value: 'SEARCH' }, 13 | { 14 | assert: true, 15 | syntax: [ 16 | { type: 'keyword', as: 'breadth_or_depth_first', value: ['BREADTH', 'DEPTH'] }, 17 | { type: 'keyword', value: 'FIRST' }, 18 | { type: 'keyword', value: 'BY' }, 19 | { type: 'ColumnRef1', as: 'column_names', arity: { min: 1 }, itemSeparator, assert: true, autoIndent: 2 }, 20 | { type: 'keyword', value: 'SET' }, 21 | { type: 'ColumnRef1', as: 'seq_col_name' }, 22 | ] 23 | } 24 | ] 25 | }; 26 | } 27 | 28 | /* AST API */ 29 | 30 | breadthOrDepthFirst() { return this._get('breadth_or_depth_first'); } 31 | 32 | columnNames() { return this._get('column_names'); } 33 | 34 | seqColName() { return this._get('seq_col_name'); } 35 | } -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish to npm 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v*' 7 | 8 | jobs: 9 | publish: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - name: Checkout repository 14 | uses: actions/checkout@v4 15 | 16 | - name: Setup Node.js 17 | uses: actions/setup-node@v4 18 | with: 19 | node-version: 20 20 | registry-url: 'https://registry.npmjs.org/' 21 | 22 | - name: Install dependencies 23 | run: npm ci 24 | 25 | - name: Build 26 | run: npm run build 27 | 28 | - name: Determine npm tag 29 | id: tag 30 | run: | 31 | # Extract tag name without "refs/tags/" 32 | TAG_REF=${GITHUB_REF#refs/tags/} 33 | echo "Detected Git tag: $TAG_REF" 34 | 35 | # Determine npm tag 36 | if [[ "$TAG_REF" == *-* ]]; then 37 | # prerelease (contains a hyphen) 38 | NPM_TAG=$(echo "$TAG_REF" | sed -E 's/^v[0-9]+\.[0-9]+\.[0-9]+-([a-zA-Z0-9]+).*/\1/') 39 | else 40 | NPM_TAG="latest" 41 | fi 42 | echo "npm publish will use tag: $NPM_TAG" 43 | echo "tag=$NPM_TAG" >> $GITHUB_OUTPUT 44 | 45 | - name: Publish to npm 46 | env: 47 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 48 | run: npm publish --tag ${{ steps.tag.outputs.tag }} 49 | -------------------------------------------------------------------------------- /src/lang/abstracts/AbstractNonDDLStmt.js: -------------------------------------------------------------------------------- 1 | import { ResultSchemaMixin } from './ResultSchemaMixin.js'; 2 | import { OriginSchemasMixin } from '../abstracts/OriginSchemasMixin.js'; 3 | import { AbstractStmt } from './AbstractStmt.js'; 4 | 5 | export class AbstractNonDDLStmt extends ResultSchemaMixin(OriginSchemasMixin(AbstractStmt)) { 6 | 7 | renderBindings(values) { 8 | if (!Array.isArray(values)) throw new Error(`Values must be an array`); 9 | const queryBindings = [...this.queryBindings()]; 10 | for (let i = 0; i < values.length; i++) { 11 | const bindings = queryBindings.filter(b => b.offset() === i+1); 12 | if (!bindings.length) throw new Error(`No bindings exists at offset #${i}`); 13 | bindings.forEach(b => b.value(values[i])); 14 | } 15 | } 16 | 17 | normalizeBindings(dedupe = false) { 18 | const queryBindings = [...this.queryBindings()]; 19 | if (!dedupe) { 20 | queryBindings.forEach((b, i) => b.offset(i+1)); 21 | return queryBindings; 22 | } 23 | let redundants = new Map, $offset = 1; 24 | for (const b of queryBindings) { 25 | if (b.offset() === 0 || !redundants.has(b.offset())) { 26 | const newOffset = $offset++; 27 | redundants.set(b.offset(), newOffset); 28 | b.offset(newOffset); 29 | } else b.offset(redundants.get(b.offset())).withDetail('redundant', true); 30 | } 31 | return queryBindings.filter(b => !b.getDetail('redundant')); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/lang/ddl/constraint/ColumnExpressionConstraint.js: -------------------------------------------------------------------------------- 1 | import { ConstraintSchema } from './ConstraintSchema.js'; 2 | 3 | export class ColumnExpressionConstraint extends ConstraintSchema { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return this.buildSyntaxRules([ 9 | { 10 | dialect: 'postgres', 11 | syntax: [ 12 | { type: 'keyword', value: 'GENERATED' }, 13 | { type: 'keyword', value: 'ALWAYS' }, 14 | { type: 'keyword', value: 'AS' }, 15 | { 16 | type: 'paren_block', 17 | syntax: { type: 'Expr', as: 'expr', assert: true }, 18 | }, 19 | { type: 'keyword', as: 'stored', value: 'STORED', assert: true }, 20 | ], 21 | }, 22 | { 23 | dialect: 'mysql', 24 | syntax: [ 25 | { 26 | optional: true, 27 | syntax: [ 28 | { type: 'keyword', as: 'my_generated_kw', value: 'GENERATED', booleanfy: true }, 29 | { type: 'keyword', value: 'ALWAYS' }, 30 | ], 31 | }, 32 | { type: 'keyword', value: 'AS' }, 33 | { 34 | type: 'paren_block', 35 | syntax: { type: 'Expr', as: 'expr', assert: true }, 36 | }, 37 | { type: 'keyword', as: 'stored', value: ['STORED', 'VIRTUAL'], optional: true }, 38 | ], 39 | }, 40 | ]); 41 | } 42 | 43 | /* AST API */ 44 | 45 | myGeneratedKW() { return this._get('my_generated_kw'); } 46 | 47 | expr() { return this._get('expr'); } 48 | 49 | stored() { return this._get('stored'); } 50 | } -------------------------------------------------------------------------------- /src/lang/ddl/DropSchemaStmt.js: -------------------------------------------------------------------------------- 1 | import { DDLStmt } from './DDLStmt.js'; 2 | 3 | export class DropSchemaStmt extends DDLStmt { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | const itemSeparator = { type: 'punctuation', value: ',' }; 9 | return [ 10 | { type: 'keyword', value: 'DROP' }, 11 | { type: 'keyword', value: 'SCHEMA', dialect: 'postgres' }, 12 | { type: 'keyword', value: ['SCHEMA', 'DATABASE'], dialect: 'mysql' }, 13 | { 14 | optional: true, 15 | syntax: [ 16 | { type: 'keyword', as: 'if_exists', value: 'IF', booleanfy: true }, 17 | { type: 'keyword', value: 'EXISTS' }, 18 | ] 19 | }, 20 | { type: ['NamespaceIdent', 'Identifier'/* to support mock names */], as: 'pg_names', arity: { min: 1 }, itemSeparator, dialect: 'postgres' }, 21 | { type: ['NamespaceIdent', 'Identifier'/* to support mock names */], as: 'my_name', dialect: 'mysql' }, 22 | { type: 'keyword', as: 'pg_cascade_rule', value: ['CASCADE', 'RESTRICT'], optional: true, dialect: 'postgres' }, 23 | ]; 24 | } 25 | 26 | /* AST API */ 27 | 28 | ifExists() { return this._get('if_exists'); } 29 | 30 | pgNames() { return this._get('pg_names'); } 31 | 32 | myName() { return this._get('my_name'); } 33 | 34 | pgCascadeRule() { return this._get('pg_cascade_rule'); } 35 | } -------------------------------------------------------------------------------- /src/lang/expr/abstraction/ScalarSubquery.js: -------------------------------------------------------------------------------- 1 | import { DerivedQuery } from '../../dql/TA/DerivedQuery.js'; 2 | import { registry } from '../../registry.js'; 3 | 4 | export class ScalarSubquery extends DerivedQuery { 5 | 6 | /* SYNTAX RULES */ 7 | 8 | static get syntaxRules() { 9 | return { 10 | type: 'paren_block', 11 | syntax: { type: ['SelectStmt', 'CTE'], as: 'expr' }, 12 | autoIndent: true, 13 | }; 14 | } 15 | 16 | static get syntaxPriority() { return 48; } // Below RowConstructor 17 | 18 | /* TYPESYS API */ 19 | 20 | dataType() { 21 | if (this.resultSchema()) { 22 | return this.resultSchema().dataType(); 23 | } 24 | return registry.DataType.fromJSON({ value: 'TEXT' }); 25 | } 26 | 27 | /* JSON API */ 28 | 29 | jsonfy(options = {}, transformer = null, schemaInference = null) { 30 | let resultJson = super.jsonfy(options, transformer, schemaInference); 31 | if (options.deSugar) { 32 | let resultSchema = resultJson.expr?.result_schema; 33 | if (resultSchema?.length !== 1) { 34 | throw new Error(`Scalar subqueries must return a scalar value.`); 35 | } 36 | resultSchema = resultSchema.entries()[0]; 37 | resultJson = { 38 | ...resultJson, 39 | result_schema: resultSchema, 40 | }; 41 | } 42 | return resultJson; 43 | } 44 | } -------------------------------------------------------------------------------- /src/lang/dql/clauses/GroupingElement.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../abstracts/AbstractNode.js'; 2 | 3 | export class GroupingElement extends AbstractNode { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | const itemSeparator = { type: 'punctuation', value: ',' }; 9 | return { 10 | syntaxes: [ 11 | [ 12 | { type: 'keyword', value: 'GROUPING SETS' }, 13 | { 14 | type: 'paren_block', syntax: 15 | { type: 'GroupingElement', as: 'grouping_sets', arity: { min: 1 }, itemSeparator, assert: true, autoIndent: 2 }, 16 | autoIndent: true 17 | } 18 | ], 19 | [ 20 | { type: 'keyword', value: 'ROLLUP' }, 21 | { type: 'RowConstructor', as: 'rollup_set', assert: true }, 22 | ], 23 | [ 24 | { type: 'keyword', value: 'CUBE' }, 25 | { type: 'RowConstructor', as: 'cube_set', assert: true }, 26 | ], 27 | { type: 'Expr', as: 'expr' }, 28 | ] 29 | }; 30 | } 31 | 32 | /* AST API */ 33 | 34 | groupingSets() { return this._get('grouping_sets'); } 35 | 36 | rollupSet() { return this._get('rollup_set'); } 37 | 38 | cubeSet() { return this._get('cube_set'); } 39 | 40 | expr() { return this._get('expr'); } 41 | } -------------------------------------------------------------------------------- /src/lang/dml/PGSetStmt.js: -------------------------------------------------------------------------------- 1 | import { BinaryExpr } from '../expr/op/BinaryExpr.js'; 2 | 3 | export class PGSetStmt extends BinaryExpr { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | const itemSeparator = { type: 'punctuation', value: ',' }; 9 | return { 10 | dialect: 'postgres', 11 | syntax: [ 12 | { type: 'keyword', value: 'SET' }, 13 | { type: 'identifier', as: 'scope_kw', value: ['LOCAL', 'SESSION'], optional: true }, 14 | { 15 | syntaxes: [ 16 | { type: 'keyword', as: 'left' }, 17 | { type: 'identifier', as: 'left' }, 18 | ], 19 | }, 20 | { 21 | optional: true, 22 | syntaxes: [ 23 | { type: 'operator', as: 'operator', value: '=' }, 24 | { type: 'keyword', as: 'operator', value: 'TO' } 25 | ], 26 | }, 27 | { type: ['Expr', 'KW'], as: 'right', arity: { min: 1 }, itemSeparator, assert: true, autoIndent: 2 }, 28 | ] 29 | }; 30 | } 31 | 32 | /* API */ 33 | 34 | scopeKW() { return this._get('scope_kw'); } 35 | 36 | /** API */ 37 | 38 | jsonfy({ deSugar, ...options } = {}, transformer = null, schemaInference = null) { 39 | return super.jsonfy(options, transformer, schemaInference); 40 | } 41 | } -------------------------------------------------------------------------------- /src/lang/expr/literals/PGTypedArrayLiteral.js: -------------------------------------------------------------------------------- 1 | import { AbstractNodeList } from '../../abstracts/AbstractNodeList.js'; 2 | import { registry } from '../../registry.js'; 3 | 4 | export class PGTypedArrayLiteral extends AbstractNodeList { 5 | 6 | /* SYNTAX RULES */ 7 | 8 | static get syntaxRules() { 9 | const itemSeparator = { type: 'punctuation', value: ',' }; 10 | return { 11 | dialect: 'postgres', 12 | syntax: [ 13 | { type: 'keyword', value: 'ARRAY' }, 14 | { 15 | type: 'bracket_block', 16 | syntax: { type: 'Expr', as: 'entries', arity: Infinity, itemSeparator, autoIndent: 2 }, 17 | autoSpacing: false, 18 | }, 19 | ], 20 | }; 21 | } 22 | 23 | static morphsTo() { return registry.CallExpr; } 24 | 25 | /* TYPESYS API */ 26 | 27 | dataType() { return registry.DataType.fromJSON({ value: 'JSON' }); } 28 | 29 | /* JSON API */ 30 | 31 | jsonfy(options = {}, transformer = null, schemaInference = null) { 32 | let resultJson = super.jsonfy(options, transformer, schemaInference); 33 | if ((options.toDialect || this.options.dialect) === 'mysql') { 34 | resultJson = { 35 | nodeName: registry.CallExpr.NODE_NAME, 36 | name: 'JSON_ARRAY', 37 | arguments: resultJson.entries, 38 | }; 39 | } 40 | return resultJson; 41 | } 42 | } -------------------------------------------------------------------------------- /src/lang/dql/clauses/WindowFrameSpec.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../abstracts/AbstractNode.js'; 2 | 3 | export class WindowFrameSpec extends AbstractNode { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | const itemSeparator = { type: 'operator', value: 'AND' }; 9 | return [ 10 | { type: 'keyword', as: 'specifier', value: ['ROWS', 'RANGE', 'GROUPS'] }, 11 | { 12 | syntaxes: [ 13 | [ 14 | { type: 'operator', as: 'with_between_clause', value: 'BETWEEN', booleanfy: true }, 15 | { type: 'WindowFrameBound', as: 'bounds', arity: 2, itemSeparator, assert: true }, 16 | ], 17 | { type: 'WindowFrameBound', as: 'bounds', arity: 1, itemSeparator, assert: true }, 18 | 19 | ] 20 | }, 21 | { 22 | optional: true, 23 | syntax: [ 24 | { type: 'keyword', value: 'EXCLUDE' }, 25 | { type: 'keyword', as: 'exclusion', value: ['CURRENT ROW', 'GROUP', 'TIES', 'NO OTHERS'], assert: true }, 26 | ] 27 | }, 28 | ]; 29 | } 30 | 31 | /* AST API */ 32 | 33 | specifier() { return this._get('specifier'); } 34 | 35 | withBetweenClause() { return this._get('with_between_clause'); } 36 | 37 | bounds() { return this._get('bounds'); } 38 | 39 | exclusion() { return this._get('exclusion'); } 40 | } -------------------------------------------------------------------------------- /src/lang/dml/DMLStmt.js: -------------------------------------------------------------------------------- 1 | import { AbstractNonDDLStmt } from '../abstracts/AbstractNonDDLStmt.js'; 2 | import { registry } from '../registry.js'; 3 | 4 | export class DMLStmt extends AbstractNonDDLStmt { 5 | 6 | /* SYNTAX RULES */ 7 | 8 | static get syntaxRules() { return { type: ['InsertStmt', 'UpsertStmt', 'UpdateStmt', 'DeleteStmt'] }; } 9 | 10 | finalizeOutputJSON(resultJson, transformer, schemaInference, options) { 11 | 12 | if (resultJson.returning_clause) { 13 | // 1. Re-resolve output list for cases of just-added deep refs in returning_clause 14 | // wherein schemas wouldn't have been resolvable at the time 15 | // 2. Finalize output list for the last time, honouring given deSugaring level with regards to star selects "*" 16 | // and ofcos finalize output schemas 17 | const returningClauseJson = this.returningClause().finalizeJSON(resultJson.returning_clause, transformer, schemaInference, options); 18 | // Apply now 19 | resultJson = { 20 | ...resultJson, 21 | returning_clause: returningClauseJson, 22 | result_schema: returningClauseJson.result_schema, 23 | }; 24 | } else { 25 | resultJson = { 26 | ...resultJson, 27 | result_schema: registry.JSONSchema.fromJSON({ entries: [] }, this.options), 28 | }; 29 | } 30 | 31 | return resultJson; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/lang/ddl/CreateTableStmt.js: -------------------------------------------------------------------------------- 1 | import { DDLStmt } from './DDLStmt.js'; 2 | 3 | export class CreateTableStmt extends DDLStmt { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | return [ 9 | { type: 'keyword', value: 'CREATE' }, 10 | { 11 | optional: true, 12 | syntaxes: [ 13 | { type: 'keyword', as: 'temporary_kw', value: 'TEMPORARY', booleanfy: true }, 14 | { type: 'keyword', as: 'temporary_kw', value: 'TEMP', booleanfy: true, dialect: 'postgres' }, 15 | ], 16 | }, 17 | { type: 'keyword', value: 'TABLE' }, 18 | { 19 | optional: true, 20 | syntax: [ 21 | { type: 'keyword', as: 'if_not_exists', value: 'IF', booleanfy: true }, 22 | { type: 'operator', value: 'NOT' }, 23 | { type: 'keyword', value: 'EXISTS' }, 24 | ], 25 | }, 26 | { type: 'TableSchema', as: 'argument' }, 27 | { type: ['ConfigAssignmentExprAlt1', 'ConfigAssignmentExprAlt2'], as: 'my_create_options', arity: Infinity, dialect: 'mysql' } 28 | ]; 29 | } 30 | 31 | /* AST API */ 32 | 33 | temporaryKW() { return this._get('temporary_kw'); } 34 | 35 | ifNotExists() { return this._get('if_not_exists'); } 36 | 37 | argument() { return this._get('argument'); } 38 | 39 | myCreateOptions() { return this._get('my_create_options'); } 40 | } -------------------------------------------------------------------------------- /src/lang/ddl/constraint/ColumnIdentityConstraint.js: -------------------------------------------------------------------------------- 1 | import { MYColumnAutoIncrementModifier } from './MYColumnAutoIncrementModifier.js'; 2 | import { ConstraintSchema } from './ConstraintSchema.js'; 3 | 4 | export class ColumnIdentityConstraint extends ConstraintSchema { 5 | 6 | /* SYNTAX RULES */ 7 | 8 | static get syntaxRules() { 9 | return this.buildSyntaxRules([ 10 | { type: 'keyword', value: 'GENERATED' }, 11 | { 12 | syntaxes: [ 13 | { type: 'keyword', as: 'always_kw', value: 'ALWAYS', booleanfy: true }, 14 | { 15 | syntax: [ 16 | { type: 'keyword', as: 'by_default_kw', value: 'BY', booleanfy: true }, 17 | { type: 'keyword', value: 'DEFAULT', assert: true }, 18 | ], 19 | }, 20 | ], 21 | }, 22 | { 23 | optional: true, 24 | syntax: [ 25 | { type: 'keyword', as: 'as_identity_kw', value: 'AS', booleanfy: true }, 26 | { type: 'keyword', value: 'IDENTITY', assert: true }, 27 | ] 28 | } 29 | ]); 30 | } 31 | 32 | /* AST API */ 33 | 34 | alwaysKW() { return this._get('always_kw'); } 35 | 36 | byDefaultKW() { return this._get('by_default_kw'); } 37 | 38 | asIdentityKW() { return this._get('as_identity_kw'); } 39 | 40 | /* JSON API */ 41 | 42 | jsonfy(options = {}, transformer = null, schemaInference = null) { 43 | return (options.toDialect || this.options.dialect) === 'mysql' 44 | ? (new MYColumnAutoIncrementModifier).jsonfy(options, transformer, schemaInference) 45 | : super.jsonfy(options, transformer, schemaInference); 46 | } 47 | } -------------------------------------------------------------------------------- /src/lang/dql/TableStmt.js: -------------------------------------------------------------------------------- 1 | import { AbstractNonDDLStmt } from '../abstracts/AbstractNonDDLStmt.js'; 2 | import { registry } from '../registry.js'; 3 | 4 | export class TableStmt extends AbstractNonDDLStmt { 5 | 6 | /* SYNTAX RULES */ 7 | 8 | static get syntaxRules() { 9 | return [ 10 | { type: 'keyword', value: 'TABLE' }, 11 | { type: 'keyword', as: 'pg_only_kw', value: 'ONLY', optional: true, dialect: 'postgres' }, 12 | { type: 'TableRef2', as: 'table_ref', assert: true }, 13 | { type: 'operator', as: 'pg_star_ref', value: '*', booleanfy: true, optional: true, dialect: 'postgres' }, 14 | ]; 15 | } 16 | 17 | /* AST API */ 18 | 19 | tableRef() { return this._get('table_ref'); } 20 | 21 | // -- Postgres 22 | 23 | pgOnlyKW() { return this._get('pg_only_kw'); } 24 | 25 | pgStarRef() { return this._get('pg_star_ref'); } 26 | 27 | /* JSON API */ 28 | 29 | jsonfy(options = {}, transformer = null, schemaInference = null) { 30 | let resultJson = super.jsonfy({ ...options, forceDeSugar: options.deSugar }, transformer, schemaInference); 31 | if (options.deSugar) { 32 | const tableSchema = resultJson.table_ref.result_schema; 33 | resultJson = { 34 | ...resultJson, 35 | result_schema: registry.JSONSchema.fromJSON({ entries: tableSchema.jsonfy().entries }), 36 | origin_schemas: [tableSchema], // or this.getOriginSchemas(transformer) 37 | }; 38 | } 39 | return resultJson; 40 | } 41 | } -------------------------------------------------------------------------------- /src/lang/dql/TA/FromItemAlias.js: -------------------------------------------------------------------------------- 1 | import { Identifier } from '../../expr/ref/Identifier.js'; 2 | 3 | export class FromItemAlias extends Identifier { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | const itemSeparator = { type: 'punctuation', value: ',' }; 9 | return [ 10 | { 11 | syntaxes: [ 12 | { ...[].concat(super.syntaxRules)[0] }, 13 | [ 14 | { type: 'keyword', as: 'as_kw', value: 'AS', booleanfy: true }, 15 | { ...[].concat(super.syntaxRules)[0], assert: true }, 16 | ] 17 | ] 18 | }, 19 | { 20 | type: 'paren_block', 21 | syntax: { type: 'Identifier', as: 'columns', arity: { min: 1 }, itemSeparator, assert: true }, 22 | if: 'value', 23 | optional: true, 24 | optionalParens: true, 25 | } 26 | ]; 27 | } 28 | 29 | /* AST API */ 30 | 31 | asKW() { return this._get('as_kw'); } 32 | 33 | columns() { return this._get('columns'); } 34 | 35 | // -------------- 36 | 37 | jsonfy(options = {}, transformer = null, schemaInference = null) { 38 | let resultJson = super.jsonfy(options, transformer, schemaInference); 39 | if ((options.deSugar === true || options.deSugar?.normalizeCasing) && !resultJson.delim) { 40 | resultJson = { ...resultJson, value: resultJson.value.toLowerCase() }; 41 | } 42 | return resultJson; 43 | } 44 | } -------------------------------------------------------------------------------- /src/lang/expr/op/BinaryExpr.js: -------------------------------------------------------------------------------- 1 | import { AbstractClassicExpr } from '../AbstractClassicExpr.js'; 2 | import { operators } from '../../toktypes.js'; 3 | import { registry } from '../../registry.js'; 4 | 5 | export class BinaryExpr extends AbstractClassicExpr { 6 | 7 | /* DEFS */ 8 | 9 | static get syntaxRules() { 10 | return [ 11 | { type: 'Expr', as: 'left', peek: [1, 'operator', ['NOT', undefined/* IMPORTANT */]] }, 12 | { type: 'operator', as: 'negation', value: 'NOT', booleanfy: true, optional: true }, 13 | { type: 'operator', as: 'operator' }, 14 | { type: 'Expr', as: 'right' }, 15 | ]; 16 | } 17 | 18 | static get syntaxPriority() { return 0; } 19 | 20 | /* AST API */ 21 | 22 | left() { return this._get('left'); } 23 | 24 | negation() { return this._get('negation'); } 25 | 26 | operator() { return this._get('operator'); } 27 | 28 | right() { return this._get('right'); } 29 | 30 | /* TYPESYS API */ 31 | 32 | dataType() { 33 | const operator = this.operator(); 34 | if (!operator) return this.left()?.dataType(); 35 | 36 | const toDialect = this.options.dialect; 37 | const operatorMap = new Map(operators.common.concat(operators[toDialect])); 38 | const resultType = operatorMap.get(operator)?.resultType; 39 | if (!resultType) return; 40 | 41 | if (resultType === ':right') { 42 | return this.right()?.dataType(); 43 | } 44 | if (resultType === ':left') { 45 | return this.left()?.dataType(); 46 | } 47 | return registry.DataType.fromJSON({ value: resultType.toUpperCase() }); 48 | } 49 | } -------------------------------------------------------------------------------- /src/lang/dql/TA/SRFExpr1.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../abstracts/AbstractNode.js'; 2 | import { ResultSchemaMixin } from '../../abstracts/ResultSchemaMixin.js'; 3 | import { registry } from '../../registry.js'; 4 | 5 | export class SRFExpr1 extends ResultSchemaMixin(AbstractNode) { 6 | 7 | /* SYNTAX RULES */ 8 | 9 | static get syntaxRules() { 10 | return [ 11 | { type: 'CallExpr', as: 'call_expr' }, 12 | { type: ['SRFExprDDL1', 'SRFExprDDL2'], as: 'qualif' }, 13 | ]; 14 | } 15 | 16 | /* AST API */ 17 | 18 | callExpr() { return this._get('call_expr'); } 19 | 20 | qualif() { return this._get('qualif'); } 21 | 22 | /* JSON API */ 23 | 24 | jsonfy(options = {}, transformer = null, schemaInference = null) { 25 | let resultJson = super.jsonfy(options, transformer, schemaInference); 26 | if (options.deSugar) { 27 | 28 | const columnDefsJson = resultJson.qualif?.column_defs || []; 29 | const resultSchema = resultJson.qualif?.alias 30 | // a. Compose from "column_defs" with explicit table alias 31 | ? registry.TableSchema.fromJSON({ 32 | name: resultJson.qualif.alias, 33 | entries: columnDefsJson, 34 | }) 35 | // b. Compose from "column_defs" without explicit table alias 36 | : registry.JSONSchema.fromJSON({ 37 | entries: columnDefsJson, 38 | }); 39 | 40 | resultJson = { 41 | ...resultJson, 42 | result_schema: resultSchema 43 | }; 44 | } 45 | 46 | return resultJson; 47 | } 48 | } -------------------------------------------------------------------------------- /src/lang/dml/constructors/ValuesConstructor.js: -------------------------------------------------------------------------------- 1 | import { ResultSchemaMixin } from '../../abstracts/ResultSchemaMixin.js'; 2 | import { AbstractNodeList } from '../../abstracts/AbstractNodeList.js'; 3 | 4 | export class ValuesConstructor extends ResultSchemaMixin(AbstractNodeList) { 5 | 6 | /* SYNTAX RULES */ 7 | 8 | static get syntaxRules() { 9 | const itemSeparator = { type: 'punctuation', value: ',' }; 10 | return { 11 | syntaxes: [ 12 | [ 13 | { type: 'keyword', value: 'VALUES' }, 14 | { type: ['TypedRowConstructor', 'RowConstructor'], as: 'entries', arity: { min: 1 }, itemSeparator, assert: true, autoIndent: 2 } 15 | ], 16 | { 17 | dialect: 'mysql', 18 | syntax: [ 19 | { type: 'keyword', value: ['VALUES', 'VALUE'] }, 20 | { type: ['TypedRowConstructor', 'RowConstructor'], as: 'entries', arity: { min: 1 }, itemSeparator, assert: true, autoIndent: 2 } 21 | ] 22 | }, 23 | ], 24 | }; 25 | } 26 | 27 | static get syntaxPriority() { return -1; } 28 | 29 | /* JSON API */ 30 | 31 | jsonfy(options = {}, transformer = null, schemaInference = null) { 32 | let resultJson = super.jsonfy({ ...options, forceDeSugar: options.deSugar }, transformer, schemaInference); 33 | if (options.deSugar) { 34 | const row1_resultSchema = resultJson.entries?.[0]?.result_schema; 35 | resultJson = { 36 | ...resultJson, 37 | result_schema: row1_resultSchema?.clone() 38 | }; 39 | } 40 | return resultJson; 41 | } 42 | } -------------------------------------------------------------------------------- /src/lang/ddl/constraint/ColumnFKConstraint.js: -------------------------------------------------------------------------------- 1 | import { ConstraintSchema } from './ConstraintSchema.js'; 2 | import { registry } from '../../registry.js'; 3 | 4 | const { 5 | ColumnSchema, 6 | ColumnRef2, 7 | } = registry; 8 | 9 | export class ColumnFKConstraint extends ConstraintSchema { 10 | 11 | /* SYNTAX RULES */ 12 | 13 | static get syntaxRules() { 14 | const itemSeparator = { type: 'punctuation', value: ',' }; 15 | return this.buildSyntaxRules([ 16 | { type: 'keyword', value: 'REFERENCES' }, 17 | { type: 'TableRef2', as: 'target_table', assert: true }, 18 | { 19 | dialect: 'postgres', 20 | optional: true, 21 | type: 'paren_block', 22 | syntax: { type: 'Identifier', as: 'target_columns', arity: 1, itemSeparator, singletons: 'BY_KEY', assert: true }, 23 | }, 24 | { 25 | dialect: 'mysql', 26 | type: 'paren_block', 27 | syntax: { type: 'Identifier', as: 'target_columns', arity: 1, itemSeparator, singletons: 'BY_KEY', assert: true }, 28 | }, 29 | { type: ['FKMatchRule', 'FKDeleteRule', 'FKUpdateRule'], as: 'referential_rules', arity: Infinity, singletons: true }, 30 | 31 | ]); 32 | } 33 | 34 | /* AST API */ 35 | 36 | targetTable() { return this._get('target_table'); } 37 | 38 | targetColumns() { return this._get('target_columns'); } 39 | 40 | referentialRules() { return this._get('referential_rules'); } 41 | 42 | /* API */ 43 | 44 | columns() { 45 | return this.parentNode instanceof ColumnSchema 46 | ? [ColumnRef2.fromJSON({ value: this.parentNode.name().value() })] 47 | : []; 48 | } 49 | } -------------------------------------------------------------------------------- /src/lang/abstracts/OriginSchemasMixin.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from './AbstractNode.js'; 2 | import { registry } from '../registry.js'; 3 | 4 | export const OriginSchemasMixin = (Class) => class extends Class { 5 | 6 | #origin_schemas; 7 | 8 | originSchemas() { return this.#origin_schemas; } 9 | 10 | static fromJSON(inputJson, options = {}, callback = null) { 11 | if (!inputJson || inputJson instanceof AbstractNode) { 12 | return super.fromJSON(inputJson, options, callback); 13 | } 14 | const { origin_schemas, ...restJson } = inputJson; 15 | const instance = super.fromJSON(restJson, options, callback); 16 | if (instance && origin_schemas) { 17 | if (!Array.isArray(origin_schemas)) { 18 | throw new Error(`Invalid list passed at inputJson.origin_schemas`); 19 | } 20 | instance.#origin_schemas = origin_schemas; 21 | } 22 | return instance; 23 | } 24 | 25 | jsonfy(options = {}, transformer = null, schemaInference = null) { 26 | let resultJson = super.jsonfy(options, transformer, schemaInference); 27 | if (this.#origin_schemas && options.originSchemas !== false) { 28 | resultJson = { 29 | ...resultJson, 30 | origin_schemas: this.#origin_schemas, 31 | }; 32 | } 33 | return resultJson; 34 | } 35 | 36 | getOriginSchemas(transformer) { 37 | const originSchemas = []; 38 | let foundJSONSchema = false; 39 | for (const { resultSchema } of transformer.statementContext.artifacts.get('tableSchemas')) { 40 | if (resultSchema instanceof registry.JSONSchema) { 41 | if (foundJSONSchema) { 42 | // Not expect; not valid SQL; but however 43 | throw new Error(`Multiple anonymous origin schemas detected`); 44 | } 45 | foundJSONSchema = true; 46 | } 47 | originSchemas.push(resultSchema); 48 | } 49 | return originSchemas; 50 | } 51 | } -------------------------------------------------------------------------------- /src/lang/dml/clauses/PGOnConflictClause.js: -------------------------------------------------------------------------------- 1 | import { AbstractNodeList } from '../../abstracts/AbstractNodeList.js'; 2 | 3 | export class PGOnConflictClause extends AbstractNodeList { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | const itemSeparator = { type: 'punctuation', value: ',' }; 9 | return { 10 | dialect: 'postgres', 11 | syntax: [ 12 | { type: 'keyword', value: 'ON' }, 13 | { type: 'keyword', value: 'CONFLICT' }, 14 | { 15 | syntaxes: [ 16 | [ 17 | { type: 'PGConflictTarget', as: 'conflict_target', optional: true }, 18 | { type: 'keyword', as: 'do_nothing_kw', value: 'DO', booleanfy: true }, 19 | { type: 'keyword', value: 'NOTHING' }, 20 | ], 21 | [ 22 | { type: 'PGConflictTarget', as: 'conflict_target' }, 23 | { type: 'keyword', value: 'DO' }, 24 | { type: 'keyword', value: 'UPDATE' }, 25 | { type: 'keyword', value: 'SET' }, 26 | { type: 'AssignmentExpr', as: 'entries', arity: { min: 1 }, itemSeparator, assert: true, autoIndent: true }, 27 | { type: 'WhereClause', as: 'where_clause', optional: true, autoIndent: true }, 28 | ], 29 | ], 30 | } 31 | ], 32 | }; 33 | } 34 | 35 | /* AST API */ 36 | 37 | conflictTarget() { return this._get('conflict_target'); } 38 | 39 | doNothingKW() { return this._get('do_nothing_kw'); } 40 | 41 | whereClause() { return this._get('where_clause'); } 42 | } -------------------------------------------------------------------------------- /site/.vitepress/cache/deps/_metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "hash": "d133ad6b", 3 | "configHash": "60d1ba4e", 4 | "lockfileHash": "f450393d", 5 | "browserHash": "37503542", 6 | "optimized": { 7 | "vue": { 8 | "src": "../../../../node_modules/vue/dist/vue.runtime.esm-bundler.js", 9 | "file": "vue.js", 10 | "fileHash": "1f9f2d58", 11 | "needsInterop": false 12 | }, 13 | "vitepress > @vue/devtools-api": { 14 | "src": "../../../../node_modules/@vue/devtools-api/dist/index.js", 15 | "file": "vitepress___@vue_devtools-api.js", 16 | "fileHash": "6ea27cdd", 17 | "needsInterop": false 18 | }, 19 | "vitepress > @vueuse/core": { 20 | "src": "../../../../node_modules/@vueuse/core/index.mjs", 21 | "file": "vitepress___@vueuse_core.js", 22 | "fileHash": "8ed43ceb", 23 | "needsInterop": false 24 | }, 25 | "vitepress > @vueuse/integrations/useFocusTrap": { 26 | "src": "../../../../node_modules/@vueuse/integrations/useFocusTrap.mjs", 27 | "file": "vitepress___@vueuse_integrations_useFocusTrap.js", 28 | "fileHash": "a735dd0e", 29 | "needsInterop": false 30 | }, 31 | "vitepress > mark.js/src/vanilla.js": { 32 | "src": "../../../../node_modules/mark.js/src/vanilla.js", 33 | "file": "vitepress___mark__js_src_vanilla__js.js", 34 | "fileHash": "05c2f6c3", 35 | "needsInterop": false 36 | }, 37 | "vitepress > minisearch": { 38 | "src": "../../../../node_modules/minisearch/dist/es/index.js", 39 | "file": "vitepress___minisearch.js", 40 | "fileHash": "84e1bfaa", 41 | "needsInterop": false 42 | } 43 | }, 44 | "chunks": { 45 | "chunk-Q2AYPHVK": { 46 | "file": "chunk-Q2AYPHVK.js" 47 | }, 48 | "chunk-QAXAIFA7": { 49 | "file": "chunk-QAXAIFA7.js" 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /src/lang/ddl/constraint/TableFKConstraint.js: -------------------------------------------------------------------------------- 1 | import { ConstraintSchema } from './ConstraintSchema.js'; 2 | 3 | export class TableFKConstraint extends ConstraintSchema { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | const itemSeparator = { type: 'punctuation', value: ',' }; 9 | return this.buildSyntaxRules([ 10 | { type: 'keyword', value: 'FOREIGN' }, 11 | { type: 'keyword', value: 'KEY', assert: true }, 12 | { 13 | type: 'paren_block', 14 | syntax: { type: 'ColumnRef2', as: 'columns', arity: { min: 1 }, itemSeparator, assert: true, singletons: 'BY_KEY' }, 15 | }, 16 | { type: 'keyword', value: 'REFERENCES' }, 17 | { type: 'TableRef2', as: 'target_table', assert: true }, 18 | { 19 | dialect: 'postgres', 20 | optional: true, 21 | type: 'paren_block', 22 | syntax: { type: 'Identifier', as: 'target_columns', arity: { min: 1 }, itemSeparator, singletons: 'BY_KEY', assert: true }, 23 | }, 24 | { 25 | dialect: 'mysql', 26 | type: 'paren_block', 27 | syntax: { type: 'Identifier', as: 'target_columns', arity: { min: 1 }, itemSeparator, singletons: 'BY_KEY', assert: true }, 28 | }, 29 | { type: ['FKMatchRule', 'FKDeleteRule', 'FKUpdateRule'], as: 'referential_rules', arity: Infinity, assert: true, singletons: true }, 30 | ]); 31 | } 32 | 33 | /* AST API */ 34 | 35 | columns() { return this._get('columns'); } 36 | 37 | targetTable() { return this._get('target_table'); } 38 | 39 | targetColumns() { return this._get('target_columns'); } 40 | 41 | referentialRules() { return this._get('referential_rules'); } 42 | } 43 | -------------------------------------------------------------------------------- /src/lang/ddl/constraint/TableUKConstraint.js: -------------------------------------------------------------------------------- 1 | import { ConstraintSchema } from './ConstraintSchema.js'; 2 | 3 | export class TableUKConstraint extends ConstraintSchema { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | const itemSeparator = { type: 'punctuation', value: ',' }; 9 | return this.buildSyntaxRules([ 10 | { type: 'keyword', value: 'UNIQUE' }, 11 | { type: 'keyword', as: 'my_key_kw', value: ['KEY', 'INDEX'], optional: true, dialect: 'mysql' }, 12 | { 13 | optional: true, 14 | dialect: 'postgres', 15 | syntaxes: [ 16 | [ 17 | { type: 'keyword', value: 'NULLS' }, 18 | { type: 'operator', as: 'pg_nulls_distinct', value: 'NOT' }, 19 | { type: 'keyword', value: 'DISTINCT', assert: true }, 20 | ], 21 | [ 22 | { type: 'keyword', value: 'NULLS' }, 23 | { type: 'keyword', as: 'pg_nulls_distinct', value: 'DISTINCT', assert: true }, 24 | ], 25 | ] 26 | }, 27 | { 28 | type: 'paren_block', 29 | syntax: { type: 'ColumnRef2', as: 'columns', arity: { min: 1 }, itemSeparator, singletons: 'BY_KEY', assert: true }, 30 | assert: true, 31 | }, 32 | { type: 'PGIndexParameters', as: 'pg_index_parameters', optional: true, dialect: 'postgres' } 33 | ]); 34 | } 35 | 36 | /* AST API */ 37 | 38 | myKeyKW() { return this._get('my_key_kw'); } 39 | 40 | pgNullsDistinct() { return this._get('pg_nulls_distinct'); } 41 | 42 | columns() { return this._get('columns'); } 43 | 44 | pgIndexParameters() { return this._get('pg_index_parameters'); } 45 | } -------------------------------------------------------------------------------- /src/lang/abstracts/AbstractSchema.js: -------------------------------------------------------------------------------- 1 | import { AbstractNodeList } from './AbstractNodeList.js'; 2 | import { AbstractNode } from './AbstractNode.js'; 3 | import { registry } from '../registry.js'; 4 | 5 | export class AbstractSchema extends AbstractNodeList { 6 | 7 | /* AST API */ 8 | 9 | name() { return this._get('name'); } 10 | 11 | /* API */ 12 | 13 | identifiesAs(value, ...args) { 14 | return this.name()?.identifiesAs( 15 | value instanceof AbstractSchema ? value.name() : value, 16 | ...args 17 | ); 18 | } 19 | 20 | /* JSON API */ 21 | 22 | static fromJSON(inputJson, options = {}, callback = null) { 23 | if (inputJson instanceof AbstractNode) { 24 | return super.fromJSON(inputJson, options, callback); 25 | } 26 | const { ddl_name, ...restJson } = inputJson; 27 | const node = super.fromJSON(restJson, options, callback); 28 | if (ddl_name && node) { 29 | const iddlNameIdent = [registry.NamespaceIdent, registry.TableIdent, registry.ColumnIdent].reduce((prev, Class) => prev || Class.fromJSON(ddl_name), null); 30 | node._set('ddl_name', iddlNameIdent); 31 | } 32 | return node; 33 | } 34 | 35 | jsonfy({ renameTo, ...options } = {}, transformer = null, schemaInference = null) { 36 | let resultJson = super.jsonfy(options, transformer, schemaInference); 37 | if (renameTo) { 38 | if (renameTo instanceof AbstractNode) { 39 | throw new Error(`options.renameTo must be a JSON value.`); 40 | } 41 | if (resultJson.name?.value && !resultJson.ddl_name) { 42 | resultJson = { ...resultJson, ddl_name: resultJson.name }; 43 | } 44 | return { ...resultJson, name: renameTo }; 45 | } 46 | return resultJson; 47 | } 48 | } -------------------------------------------------------------------------------- /src/lang/ddl/constraint/ColumnUKConstraint.js: -------------------------------------------------------------------------------- 1 | import { ConstraintSchema } from './ConstraintSchema.js'; 2 | import { registry } from '../../registry.js'; 3 | 4 | export class ColumnUKConstraint extends ConstraintSchema { 5 | 6 | /* SYNTAX RULES */ 7 | 8 | static get syntaxRules() { 9 | return this.buildSyntaxRules([ 10 | { type: 'keyword', value: 'UNIQUE' }, 11 | { type: 'keyword', as: 'my_key_kw', value: ['KEY', 'INDEX'], optional: true, dialect: 'mysql' }, 12 | { 13 | optional: true, 14 | dialect: 'postgres', 15 | syntaxes: [ 16 | [ 17 | { type: 'keyword', value: 'NULLS' }, 18 | { type: 'operator', as: 'pg_nulls_distinct', value: 'NOT' }, 19 | { type: 'keyword', value: 'DISTINCT', assert: true }, 20 | ], 21 | [ 22 | { type: 'keyword', value: 'NULLS' }, 23 | { type: 'keyword', as: 'pg_nulls_distinct', value: 'DISTINCT', assert: true }, 24 | ], 25 | ] 26 | }, 27 | { type: 'PGIndexParameters', as: 'pg_index_parameters', optional: true, dialect: 'postgres' } 28 | ]); 29 | } 30 | 31 | /* AST API */ 32 | 33 | myKeyKW() { return this._get('my_key_kw'); } 34 | 35 | pgNullsDistinct() { return this._get('pg_nulls_distinct'); } 36 | 37 | pgIndexParameters() { return this._get('pg_index_parameters'); } 38 | 39 | /* API */ 40 | 41 | columns() { 42 | const { 43 | ColumnSchema, 44 | ColumnRef2, 45 | } = registry; 46 | return this.parentNode instanceof ColumnSchema 47 | ? [ColumnRef2.fromJSON({ value: this.parentNode.name().value() })] 48 | : []; 49 | } 50 | } -------------------------------------------------------------------------------- /src/lang/expr/ref/LQBackBackRef.js: -------------------------------------------------------------------------------- 1 | import { AbstractMagicRef } from './abstracts/AbstractMagicRef.js'; 2 | import { registry } from '../../registry.js'; 3 | 4 | export class LQBackBackRef extends AbstractMagicRef { 5 | 6 | /* SYNTAX RULES */ 7 | 8 | static get _leftType() { 9 | return [ 10 | 'LQBackRefEndpoint'/* must come first to prevent left-recursion */, 11 | 'LQBackBackRef' 12 | ]; 13 | } // for inheritance 14 | 15 | static get syntaxRules() { 16 | return [ 17 | { type: this._leftType, as: 'left', peek: [1, 'operator', '<~'] }, 18 | { type: 'operator', value: '<~' }, 19 | { type: 'ColumnRef2', as: 'right', peek: [1, 'operator', '<~'] }, 20 | ]; 21 | } 22 | 23 | static get syntaxPriority() { return 1; } 24 | 25 | static morphsTo() { return [registry.LQDeepRef1, registry.LQDeepRef2, registry.LQDeepDeepRef1, registry.LQDeepDeepRef2]; } 26 | 27 | /* API */ 28 | 29 | operand() { return this.right(); } 30 | 31 | endpoint() { return this.left() instanceof LQBackBackRef ? this.left().endpoint() : this.left(); } 32 | 33 | /* JSON API */ 34 | 35 | jsonfy({ reverseRef = false, toKind = 1, ...options } = {}, transformer = null, schemaInference = null) { 36 | if (reverseRef) { 37 | return { 38 | nodeName: toKind === 2 39 | ? (reverseRef === Infinity ? registry.LQDeepDeepRef2.NODE_NAME : registry.LQDeepRef2.NODE_NAME) 40 | : (reverseRef === Infinity ? registry.LQDeepDeepRef1.NODE_NAME : registry.LQDeepRef1.NODE_NAME), 41 | left: this.right().jsonfy({ toKind: reverseRef !== Infinity ? 1 : 2, ...options }), 42 | right: this.left() instanceof registry.LQBackRefEndpoint 43 | ? { nodeName: registry.ColumnRef2.NODE_NAME, value: this.left().value(), delim: this.left()._get('delim') } 44 | : this.left().jsonfy({ reverseRef: Infinity, toKind, ...options }), 45 | }; 46 | } 47 | return super.jsonfy(options, transformer, schemaInference); 48 | } 49 | } -------------------------------------------------------------------------------- /src/lang/ddl/constraint/PGTableEXConstraint.js: -------------------------------------------------------------------------------- 1 | import { ConstraintSchema } from './ConstraintSchema.js'; 2 | 3 | export class PGTableEXConstraint extends ConstraintSchema { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | const itemSeparator = { type: 'punctuation', value: ',' }; 9 | return { 10 | dialect: 'postgres', 11 | syntax: this.buildSyntaxRules([ 12 | { type: 'keyword', value: 'EXCLUDE' }, 13 | { 14 | optional: true, 15 | syntax: [ 16 | { type: 'keyword', value: 'USING' }, 17 | { type: 'keyword', as: 'index_method', assert: true }, 18 | ], 19 | }, 20 | { 21 | type: 'paren_block', 22 | syntax: { type: 'PGTableEXConstraintItem', as: 'entries', arity: { min: 1 }, itemSeparator, assert: true }, 23 | assert: true, 24 | }, 25 | { type: 'PGIndexParameters', as: 'pg_index_parameters', optional: true }, 26 | { 27 | optional: true, 28 | syntax: [ 29 | { type: 'keyword', value: 'WHERE' }, 30 | { 31 | type: 'paren_block', 32 | syntax: { type: 'Expr', as: 'where_predicate', assert: true }, 33 | assert: true, 34 | } 35 | ], 36 | } 37 | ]) 38 | }; 39 | } 40 | 41 | /* AST API */ 42 | 43 | indexMethod() { return this._get('index_method'); } 44 | 45 | entries() { return this._get('entries'); } 46 | 47 | pgIndexParameters() { return this._get('pg_index_parameters'); } 48 | 49 | wherePredicate() { return this._get('where_predicate'); } 50 | } -------------------------------------------------------------------------------- /src/lang/cte/constructs/PGCycleClause.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../abstracts/AbstractNode.js'; 2 | 3 | export class PGCycleClause extends AbstractNode { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | const itemSeparator = { type: 'punctuation', value: ',' }; 9 | return { 10 | dialect: 'postgres', 11 | syntax: [ 12 | { type: 'keyword', value: 'CYCLE' }, 13 | { 14 | assert: true, 15 | syntax: [ 16 | { type: 'ColumnRef1', as: 'column_names', arity: { min: 1 }, itemSeparator, assert: true, autoIndent: 2 }, 17 | { type: 'keyword', value: 'SET' }, 18 | { type: 'ColumnRef1', as: 'mark_col_name' }, 19 | { 20 | optional: true, 21 | syntax: [ 22 | { type: 'keyword', value: 'TO' }, 23 | { type: 'Expr', as: 'mark_value' }, 24 | { type: 'keyword', value: 'DEFAULT' }, 25 | { type: 'Expr', as: 'mark_default' }, 26 | ] 27 | }, 28 | { type: 'keyword', value: 'USING' }, 29 | { type: 'ColumnRef1', as: 'path_col_name' }, 30 | ] 31 | }, 32 | ] 33 | }; 34 | } 35 | 36 | /* AST API */ 37 | 38 | breadthOrDepthFirst() { return this._get('breadth_or_depth_first'); } 39 | 40 | columnNames() { return this._get('column_names'); } 41 | 42 | markColName() { return this._get('mark_col_name'); } 43 | 44 | markValue() { return this._get('mark_value'); } 45 | 46 | markDefault() { return this._get('mark_default'); } 47 | 48 | pathColName() { return this._get('path_col_name'); } 49 | } -------------------------------------------------------------------------------- /src/lang/type/DataType.js: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../abstracts/AbstractNode.js'; 2 | 3 | export class DataType extends AbstractNode { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | const itemSeparator = { type: 'punctuation', value: ',' }; 9 | return [ 10 | { 11 | syntaxes: [ 12 | [ 13 | { type: 'data_type', as: '.', value: ['TIME', 'TIMESTAMP'], dialect: 'postgres' }, 14 | { type: 'data_type', as: '.', value: ['TIME', 'TIMESTAMP', 'DATETIME'], dialect: 'mysql' }, 15 | { 16 | optional: true, 17 | dialect: 'postgres', 18 | syntax: [ 19 | { type: 'keyword', as: 'pg_with_tz', value: ['WITH', 'WITHOUT'] }, 20 | { type: 'keyword', value: 'TIME ZONE', assert: true }, 21 | ] 22 | } 23 | ], 24 | { type: 'data_type', as: '.' }, 25 | { type: 'keyword', as: '.', value: ['SET'] }, 26 | ] 27 | }, 28 | { 29 | type: 'paren_block', 30 | syntax: { type: 'Expr', as: 'specificity', arity: Infinity, itemSeparator, assert: true }, 31 | optional: true, 32 | optionalParens: true, 33 | autoSpacing: false 34 | }, 35 | { type: 'AggrNotation', as: 'pg_is_aggr', autoSpacing: false, optional: true, dialect: 'postgres' }, 36 | ]; 37 | } 38 | 39 | /* AST API */ 40 | 41 | value() { return this._get('value'); } 42 | 43 | specificity() { return this._get('specificity'); } 44 | 45 | // -- Postgres 46 | 47 | pgIsAggr() { return this._get('pg_is_aggr'); } 48 | 49 | pgWithTZ() { return this._get('pg_with_tz'); } 50 | } -------------------------------------------------------------------------------- /site/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: home 3 | title: LinkedQL 4 | hero: 5 | name: LinkedQL 6 | text: A modern take on SQL and SQL databases. 7 | tagline: > 8 | Reactivity, Relationships, JSON, Schemas, Embedding, Federation & Sync, and More → SOLVED. 9 | actions: 10 | - theme: brand 11 | text: Get Started 12 | link: /docs/ 13 | - theme: alt 14 | text: Star on GitHub 15 | link: https://github.com/linked-db/linked-ql 16 | features: 17 | - title: Relationships Solved 18 | details: Traverse relationships directly in your queries — without writing a JOIN. Meet DeepRefs, the syntax shorthand that lets you follow relationships using simple arrow notation SELECT a ~> b 19 | - title: JSON Solved 20 | details: Bring JSON-like clearity to your queries. LinkedQL's first-class support for JSON notation saves you the wrangling with SQL's low-level JSON functions SELECT { a, b } 21 | - title: Schemas Solved 22 | details: Take a break from manual schema ops. LinkedQL operates with full context of your schema and automates the world for you. With Automatic Schema Inference, everything just works — without you 23 | - title: Reactivity Solved 24 | details: Turn on reactivity over arbitrary SQL with { live∶ true }. You get back a live view of your query. Live Queries in LinkedQL works directly on your database without a middleware or GraphQL servers. 25 | - title: Versioning Solved 26 | details: Get automatic database versioning as you iterate and evolve your schemas. LinkedQL makes that a reality right on your database. And that means, no more manual migration practices. 27 | - title: Embedding, Federation & Sync Solved 28 | details: Run SQL anywhere — even offline. Meet FlashQL, the in-memory engine that brings full LinkedQL semantics to the client and edge. And it comes as one query space over your entire data universe. 29 | --- 30 | -------------------------------------------------------------------------------- /src/lang/expr/ref/LQDeepDeepRef1.js: -------------------------------------------------------------------------------- 1 | import { AbstractMagicRef } from './abstracts/AbstractMagicRef.js'; 2 | import { registry } from '../../registry.js'; 3 | 4 | export class LQDeepDeepRef1 extends AbstractMagicRef { 5 | 6 | /* SYNTAX RULES */ 7 | 8 | static get _rightType() { return ['LQDeepDeepRef1', 'LQObjectLiteral', 'LQArrayLiteral', 'RowConstructor', 'ColumnRef2']; } // for inheritance 9 | 10 | static get syntaxRules() { 11 | return [ 12 | { type: ['ColumnRef2', 'LQBackRefAbstraction'], as: 'left', peek: [1, 'operator', '~>'] }, 13 | { type: 'operator', value: '~>' }, 14 | { type: this._rightType, as: 'right' }, 15 | ]; 16 | } 17 | 18 | static get syntaxPriority() { return -1; } 19 | 20 | static morphsTo() { return [registry.LQDeepRef1, registry.LQDeepRef2, registry.LQDeepDeepRef1, registry.LQDeepDeepRef2]; } 21 | 22 | /* API */ 23 | 24 | operand() { return this.left(); } 25 | 26 | endpoint() { return this.right() instanceof LQDeepDeepRef1 ? this.right().endpoint() : this.right(); } 27 | 28 | /* JSON API */ 29 | 30 | jsonfy({ toDeepRef = false, toKind = 1, ...options } = {}, transformer = null, schemaInference = null) { 31 | if (toDeepRef || toKind === 1 || toKind === 2) { 32 | const altsMap = [ 33 | registry.LQDeepRef1.NODE_NAME, registry.LQDeepRef2.NODE_NAME, 34 | registry.LQDeepDeepRef1.NODE_NAME, registry.LQDeepDeepRef2.NODE_NAME 35 | ]; 36 | 37 | let currentIndex = altsMap.indexOf(this.NODE_NAME); 38 | if (toDeepRef && currentIndex > 1) { 39 | currentIndex -= 2; 40 | } 41 | 42 | const NODE_NAME = altsMap[(currentIndex + 1) % 2 === toKind % 2 43 | ? currentIndex 44 | : (toKind % 2 // its 1 or 3 45 | ? currentIndex - 1 46 | : currentIndex + 1)]; 47 | 48 | return { 49 | nodeName: NODE_NAME, 50 | left: this.left().jsonfy({ toKind: currentIndex > 1 ? 2 : 1 }), // Left is always ColumnRef1 for DeepRef, but ColumnRef2 for DeepDeepRef 51 | right: this.right().jsonfy({ toKind: this.right() instanceof LQDeepDeepRef1 ? toKind : undefined }), 52 | }; 53 | } 54 | 55 | return super.jsonfy(options, transformer, schemaInference); 56 | } 57 | } -------------------------------------------------------------------------------- /site/.vitepress/dist/assets/index.md.BsUu5Xl8.js: -------------------------------------------------------------------------------- 1 | import{_ as e,c as t,o as a}from"./chunks/framework.B-XtCDNB.js";const h=JSON.parse(`{"title":"LinkedQL","description":"","frontmatter":{"layout":"home","title":"LinkedQL","hero":{"name":"LinkedQL","text":"A modern take on SQL and SQL databases.","tagline":"Relationships, JSON, Schema, Reactivity, Versioning, Offline → SOLVED.\\n","actions":[{"theme":"brand","text":"Get Started","link":"/docs/"},{"theme":"alt","text":"Star on GitHub","link":"https://github.com/linked-db/linked-ql"}]},"features":[{"title":"Relationships Solved","details":"Traverse relationships directly in your queries — without writing a JOIN. Meet DeepRefs, the syntax shorthand that lets you follow relationships using simple arrow notation SELECT a ~> b"},{"title":"JSON Solved","details":"Bring JSON-like clearity to your queries. LinkedQL's first-class support for JSON notation saves you the wrangling with SQL's low-level JSON functions SELECT { a, b }"},{"title":"Schema Solved","details":"Take a break from manual schema ops. LinkedQL operates with full context of your schema and automates the world for you. With Automatic Schema Inference, everything just works — without you"},{"title":"Reactivity Solved","details":"Turn on reactivity over arbitrary SQL with { live∶ true }. You get back a live view of your query. Live Queries in LinkedQL works directly on your database without a middleware or GraphQL servers."},{"title":"Versioning Solved","details":"Get automatic database versioning as you iterate and evolve your schemas. LinkedQL makes that a reality right on your database. And that means, no more manual migration practices."},{"title":"Offline Solved","details":"Run SQL anywhere — even offline. Meet FlashQL, the in-memory engine that brings full LinkedQL semantics to the client and edge. And it comes as one query space over your entire data universe."}]},"headers":[],"relativePath":"index.md","filePath":"index.md"}`),i={name:"index.md"};function n(o,s,r,l,d,c){return a(),t("div")}const m=e(i,[["render",n]]);export{h as __pageData,m as default}; 2 | -------------------------------------------------------------------------------- /site/.vitepress/dist/assets/index.md.BsUu5Xl8.lean.js: -------------------------------------------------------------------------------- 1 | import{_ as e,c as t,o as a}from"./chunks/framework.B-XtCDNB.js";const h=JSON.parse(`{"title":"LinkedQL","description":"","frontmatter":{"layout":"home","title":"LinkedQL","hero":{"name":"LinkedQL","text":"A modern take on SQL and SQL databases.","tagline":"Relationships, JSON, Schema, Reactivity, Versioning, Offline → SOLVED.\\n","actions":[{"theme":"brand","text":"Get Started","link":"/docs/"},{"theme":"alt","text":"Star on GitHub","link":"https://github.com/linked-db/linked-ql"}]},"features":[{"title":"Relationships Solved","details":"Traverse relationships directly in your queries — without writing a JOIN. Meet DeepRefs, the syntax shorthand that lets you follow relationships using simple arrow notation SELECT a ~> b"},{"title":"JSON Solved","details":"Bring JSON-like clearity to your queries. LinkedQL's first-class support for JSON notation saves you the wrangling with SQL's low-level JSON functions SELECT { a, b }"},{"title":"Schema Solved","details":"Take a break from manual schema ops. LinkedQL operates with full context of your schema and automates the world for you. With Automatic Schema Inference, everything just works — without you"},{"title":"Reactivity Solved","details":"Turn on reactivity over arbitrary SQL with { live∶ true }. You get back a live view of your query. Live Queries in LinkedQL works directly on your database without a middleware or GraphQL servers."},{"title":"Versioning Solved","details":"Get automatic database versioning as you iterate and evolve your schemas. LinkedQL makes that a reality right on your database. And that means, no more manual migration practices."},{"title":"Offline Solved","details":"Run SQL anywhere — even offline. Meet FlashQL, the in-memory engine that brings full LinkedQL semantics to the client and edge. And it comes as one query space over your entire data universe."}]},"headers":[],"relativePath":"index.md","filePath":"index.md"}`),i={name:"index.md"};function n(o,s,r,l,d,c){return a(),t("div")}const m=e(i,[["render",n]]);export{h as __pageData,m as default}; 2 | -------------------------------------------------------------------------------- /src/lang/expr/literals/LQArrayLiteral.js: -------------------------------------------------------------------------------- 1 | import { AbstractLQJsonLiteral } from './AbstractLQJsonLiteral.js'; 2 | import { registry } from '../../registry.js'; 3 | 4 | export class LQArrayLiteral extends AbstractLQJsonLiteral { 5 | 6 | /* SYNTAX RULES */ 7 | 8 | static get syntaxRules() { 9 | const itemSeparator = { type: 'punctuation', value: ',' }; 10 | return { 11 | syntax: [ 12 | { 13 | type: 'bracket_block', 14 | syntax: { type: 'Expr', as: 'entries', arity: Infinity, itemSeparator, autoIndent: 2 }, 15 | }, 16 | ], 17 | }; 18 | } 19 | 20 | static morphsTo() { return registry.CallExpr; } 21 | 22 | /* JSON API */ 23 | 24 | jsonfy(options = {}, transformer = null, schemaInference = null) { 25 | let resultJson = super.jsonfy(options, transformer, schemaInference); 26 | if (options.deSugar) { 27 | const resultSchemas = []; 28 | 29 | resultJson = { 30 | nodeName: registry.CallExpr.NODE_NAME, 31 | name: (options.toDialect || this.options.dialect) === 'mysql' ? 'JSON_ARRAY' : 'JSON_BUILD_ARRAY', 32 | arguments: resultJson.entries.map((e, i) => { 33 | 34 | let resultSchema = e.result_schema; 35 | const namespaceIdent = { value: i, nodeName: registry.Identifier.NODE_NAME }; 36 | 37 | if (resultSchema instanceof registry.ColumnSchema) { 38 | resultSchema = resultSchema.clone({ renameTo: namespaceIdent }); 39 | } else { 40 | resultSchema = registry.ColumnSchema.fromJSON({ 41 | name: namespaceIdent, 42 | data_type: this.entries()[i].dataType().jsonfy(), 43 | }); 44 | } 45 | resultSchemas.push(resultSchema); 46 | 47 | return e; 48 | }), 49 | result_schema: registry.JSONSchema.fromJSON({ entries: resultSchemas }, { assert: true }) 50 | }; 51 | } 52 | 53 | return resultJson; 54 | } 55 | } -------------------------------------------------------------------------------- /src/lang/Script.js: -------------------------------------------------------------------------------- 1 | import { AbstractNodeList } from './abstracts/AbstractNodeList.js'; 2 | import { StdStmt } from './StdStmt.js'; 3 | 4 | export class Script extends AbstractNodeList { 5 | 6 | /* SYNTAX RULES */ 7 | 8 | static get _contentTypes() { 9 | return [ 10 | 'SelectStmt', 11 | 'TableStmt', 12 | 'InsertStmt', 13 | 'UpsertStmt', 14 | 'UpdateStmt', 15 | 'DeleteStmt', 16 | 'MYSetStmt', 17 | 'PGSetStmt', 18 | 'CTE', 19 | 'CreateSchemaStmt', 20 | 'DropSchemaStmt', 21 | 'CreateTableStmt', 22 | 'DropTableStmt', 23 | 'StdStmt', 24 | ]; 25 | } 26 | 27 | static get syntaxRules() { 28 | const itemSeparator = { type: 'punctuation', value: ';' }; 29 | return { type: this._contentTypes, as: 'entries', arity: Infinity, itemSeparator, autoSpacing: '\n' }; 30 | } 31 | 32 | /* API */ 33 | 34 | static async parse(input, options = {}) { 35 | const tokenStream = await this.toStream(input, options); 36 | const result = await super.parse(tokenStream, options); 37 | if (!tokenStream.done && tokenStream.current()) { 38 | const current = tokenStream.current(); 39 | const message = `[${this.NODE_NAME}] Unexpected ${current.type} token:${typeof current.value === 'string' ? ` "${current.value}"` : ''} at `; 40 | throw new SyntaxError(message); 41 | } 42 | return result; 43 | } 44 | 45 | static async _parseFromRules(tokenStream, syntaxRules, { left, minPrecedence, trail, ...options }, resultAST = {}) { 46 | let rulesArray; 47 | if (!options.supportStdStmt && (rulesArray = [].concat(syntaxRules)).length === 1 && Array.isArray(rulesArray[0].type) && rulesArray[0].type.includes('StdStmt')) { 48 | syntaxRules = { ...rulesArray[0], type: rulesArray[0].type.filter((r) => r !== 'StdStmt') }; 49 | } 50 | return super._parseFromRules(tokenStream, syntaxRules, { left, minPrecedence, trail, ...options }, resultAST); 51 | } 52 | 53 | stringify(options = {}) { return `${super.stringify(options)};`; } 54 | } -------------------------------------------------------------------------------- /src/lang/abstracts/util.js: -------------------------------------------------------------------------------- 1 | import { _isObject } from '@webqit/util/js/index.js'; 2 | 3 | export function _eq(a, b, cs = false, ignoreList = null) { 4 | if (Array.isArray(a) && Array.isArray(b)) { 5 | return a.length === b.length && (b = b.slice(0).sort()) 6 | && a.slice(0).sort().every((x, i) => _eq(x, b[i], cs, ignoreList)); 7 | } 8 | if (typeof a?.jsonfy === 'function') a = a.jsonfy(); 9 | if (typeof b?.jsonfy === 'function') b = b.jsonfy(); 10 | if (_isObject(a) && _isObject(b)) { 11 | const temp = { 12 | indexs_a: Object.keys(a), 13 | indexs_b: Object.keys(b), 14 | }; 15 | if (ignoreList?.length) { 16 | const $ignoreList = [].concat(ignoreList); 17 | temp.indexs_a = temp.indexs_a.filter((k) => !$ignoreList.includes(k)); 18 | temp.indexs_b = temp.indexs_b.filter((k) => !$ignoreList.includes(k)); 19 | } 20 | return temp.indexs_a.length === temp.indexs_b.length 21 | && temp.indexs_a.reduce((prev, k) => prev && _eq(a[k], b[k], cs, ignoreList), true); 22 | } 23 | if (typeof a === 'string' && typeof b === 'string' && cs === false) { 24 | return a.toLowerCase() === b.toLowerCase(); 25 | } 26 | return a === b; 27 | } 28 | 29 | export function _toCapsSnake(str) { 30 | // Handle cases like "myVariableName" -> "my_Variable_Name" 31 | // This regex looks for a lowercase letter or digit followed by an uppercase letter. 32 | // It inserts an underscore between them. 33 | let result = str.replace(/([a-z0-9])([A-Z])/g, '$1_$2'); 34 | 35 | // Handle cases like "HTMLParser" -> "HTML_Parser" or "APICall" -> "API_Call" 36 | // This regex looks for an uppercase letter followed by another uppercase letter 37 | // which is then followed by a lowercase letter. This targets the transition 38 | // from an acronym to a new word. 39 | // Example: In "HTMLParser", it matches 'L' and then 'P' (uppercase) followed by 'a' (lowercase). 40 | // It inserts an underscore between the first uppercase letter and the second. 41 | result = result.replace(/([A-Z])([A-Z][a-z])/g, '$1_$2'); 42 | 43 | // Convert the entire string to uppercase. 44 | return result.toUpperCase(); 45 | } -------------------------------------------------------------------------------- /src/lang/ddl/constraint/constructs/PGTableEXConstraintItem.js: -------------------------------------------------------------------------------- 1 | import { ConstraintSchema } from '../ConstraintSchema.js'; 2 | 3 | export class PGTableEXConstraintItem extends ConstraintSchema { 4 | 5 | /* SYNTAX RULES */ 6 | 7 | static get syntaxRules() { 8 | const itemSeparator = { type: 'punctuation', value: ',' }; 9 | return [ 10 | { 11 | syntaxes: [ 12 | { type: 'ColumnRef2', as: 'expr' }, 13 | { type: 'ParenExpr', as: 'expr' }, 14 | ], 15 | }, 16 | { 17 | optional: true, 18 | syntax: [ 19 | { type: 'operator', value: 'COLLATE' }, 20 | { type: 'string_literal', as: 'collation', assert: true }, 21 | ], 22 | }, 23 | { 24 | optional: true, 25 | syntax: [ 26 | { type: 'Identifier', as: 'opclass' }, 27 | { 28 | optional: true, 29 | type: 'paren_block', 30 | syntax: { type: 'ConfigAssignmentExpr', as: 'opclass_parameters', arity: { min: 1 }, itemSeparator, assert: true }, 31 | }, 32 | ], 33 | }, 34 | { type: 'keyword', value: ['ASC', 'DESC'], as: 'dir', optional: true }, 35 | { 36 | optional: true, 37 | syntax: [ 38 | { type: 'keyword', value: 'NULLS' }, 39 | { type: 'keyword', as: 'nulls_spec', value: ['FIRST', 'LAST'], assert: true }, 40 | ] 41 | }, 42 | { type: 'keyword', value: 'WITH' }, 43 | { type: 'operator', as: 'operator' }, 44 | ]; 45 | } 46 | 47 | /* AST API */ 48 | 49 | expr() { return this._get('expr'); } 50 | 51 | collation() { return this._get('collation'); } 52 | 53 | opclass() { return this._get('opclass'); } 54 | 55 | opclassParameters() { return this._get('opclass_parameters'); } 56 | 57 | dir() { return this._get('dir'); } 58 | 59 | nullsSpec() { return this._get('nulls_spec'); } 60 | 61 | operator() { return this._get('operator'); } 62 | } -------------------------------------------------------------------------------- /src/lang/cte/CTE.js: -------------------------------------------------------------------------------- 1 | import { AbstractNonDDLStmt } from '../abstracts/AbstractNonDDLStmt.js'; 2 | import { Transformer } from '../Transformer.js'; 3 | import { registry } from '../registry.js'; 4 | 5 | export class CTE extends AbstractNonDDLStmt { 6 | 7 | /* SYNTAX RULES */ 8 | 9 | static get _bodyTypes() { 10 | return [ 11 | 'SelectStmt', 12 | 'TableStmt', 13 | 'InsertStmt', 14 | 'UpsertStmt', 15 | 'UpdateStmt', 16 | 'DeleteStmt', 17 | 'ValuesConstructor', 18 | ]; 19 | } 20 | 21 | static get syntaxRules() { 22 | const itemSeparator = { type: 'punctuation', value: ',' }; 23 | return [ 24 | { type: 'keyword', value: 'WITH' }, 25 | { type: 'keyword', as: 'recursive', value: 'RECURSIVE', booleanfy: true, optional: true }, 26 | { type: 'CTEItem', as: 'declarations', arity: { min: 1 }, itemSeparator, assert: true, autoIndent: 2 }, 27 | { type: this._bodyTypes, as: 'body', assert: true, autoSpacing: '\n' }, 28 | ]; 29 | } 30 | 31 | /* AST API */ 32 | 33 | recursive() { return this._get('recursive'); } 34 | 35 | declarations() { return this._get('declarations'); } 36 | 37 | body() { return this._get('body'); } 38 | 39 | /* JSON API */ 40 | 41 | jsonfy(options = {}, transformer = null, schemaInference = null) { 42 | if (!options.deSugar) return super.jsonfy(options, transformer, schemaInference); 43 | 44 | let outerResultSchema; 45 | 46 | transformer = new Transformer((node, defaultTransform, keyHint) => { 47 | // Process body nodes 48 | if (keyHint === 'body' && node.parentNode === this) { 49 | const bodyResultJson = defaultTransform(); 50 | 51 | outerResultSchema = bodyResultJson.result_schema; 52 | 53 | return bodyResultJson; 54 | } 55 | 56 | return defaultTransform(); 57 | }, transformer, this); 58 | 59 | // Run transform 60 | const resultJson = super.jsonfy(options, transformer, schemaInference); 61 | return { 62 | ...resultJson, 63 | result_schema: outerResultSchema, 64 | }; 65 | } 66 | } -------------------------------------------------------------------------------- /src/lang/expr/ref/abstracts/AbstractClassicRef.js: -------------------------------------------------------------------------------- 1 | import { ErrorRefUnknown } from './ErrorRefUnknown.js'; 2 | import { ErrorRefAmbiguous } from './ErrorRefAmbiguous.js'; 3 | import { AbstractNode } from '../../../abstracts/AbstractNode.js'; 4 | import { ResultSchemaMixin } from '../../../abstracts/ResultSchemaMixin.js'; 5 | import { TypeSysMixin } from '../../../abstracts/TypeSysMixin.js'; 6 | import { Identifier } from '../Identifier.js'; 7 | 8 | export class AbstractClassicRef extends ResultSchemaMixin(TypeSysMixin(Identifier)) { 9 | 10 | #resolution; 11 | 12 | resolution() { return this.#resolution; } 13 | 14 | lookup(transformer, schemaInference) { return []; } 15 | 16 | resolve(transformer, schemaInference) { 17 | const resultSet = this.lookup(null, transformer, schemaInference) || []; 18 | const objectType = this.constructor.name.match(/namespace/i) ? 'Namespace' : (this.constructor.name.match(/table/i) ? 'Table' : 'Column'); 19 | if (resultSet.length > 1) { 20 | throw new ErrorRefAmbiguous(`[${this.parentNode?.parentNode || this.parentNode || this}] ${objectType} ${this} is ambiguous. (Is it ${resultSet.join(' or ')}?)`); 21 | } else if (!resultSet.length) { 22 | throw new ErrorRefUnknown(`[${this.parentNode?.parentNode || this.parentNode || this}] ${objectType} ${this} does not exist.`); 23 | } 24 | return resultSet[0]; 25 | } 26 | 27 | static fromJSON(inputJson, options = {}, callback = null) { 28 | if (!inputJson || inputJson instanceof AbstractNode) { 29 | return super.fromJSON(inputJson, options, callback); 30 | } 31 | const { resolution, ...restJson } = inputJson; 32 | const instance = super.fromJSON(restJson, options, callback); 33 | if (instance && resolution) { 34 | if (typeof resolution !== 'string') { 35 | throw new Error(`Invalid "resolution" hint passed at inputJson.resolution`); 36 | } 37 | instance.#resolution = resolution; 38 | } 39 | return instance; 40 | } 41 | 42 | jsonfy(options = {}, transformer = null, schemaInference = null) { 43 | let resultJson = super.jsonfy(options, transformer, schemaInference); 44 | if (this.#resolution) { 45 | resultJson = { 46 | ...resultJson, 47 | resolution: this.#resolution, 48 | }; 49 | } 50 | return resultJson; 51 | } 52 | } --------------------------------------------------------------------------------