export declare const enum Engines { postgres = "postgres", mysql = "mysql", websql = "websql" } import type { Binding, SqlResult } from './abstract-sql-rules-to-sql.js'; export { Binding, SqlResult } from './abstract-sql-rules-to-sql.js'; import { optimizeSchema } from './abstract-sql-schema-optimizer.js'; import type { ReferencedFields, RuleReferencedFields, ModifiedFields } from './referenced-fields.js'; export type { ReferencedFields, RuleReferencedFields, ModifiedFields }; export type NullNode = ['Null']; export type DateNode = ['Date', Date | number | string]; export type DurationNode = [ 'Duration', { negative?: boolean | undefined; day?: number | undefined; hour?: number | undefined; minute?: number | undefined; second?: number | undefined; } ]; export type StrictDurationTypeNodes = DurationNode; export type DurationTypeNodes = StrictDurationTypeNodes | UnknownTypeNodes; export type BooleanNode = ['Boolean', boolean]; export type EqualsNode = ['Equals', AnyTypeNodes, AnyTypeNodes]; export type EqualsAnyNode = ['EqualsAny', AnyTypeNodes, BindNode]; export type NotEqualsNode = ['NotEquals', AnyTypeNodes, AnyTypeNodes]; export type IsDistinctFromNode = ['IsDistinctFrom', AnyTypeNodes, AnyTypeNodes]; export type IsNotDistinctFromNode = [ 'IsNotDistinctFrom', AnyTypeNodes, AnyTypeNodes ]; export type GreaterThanNode = ['GreaterThan', AnyTypeNodes, AnyTypeNodes]; export type GreaterThanOrEqualNode = [ 'GreaterThanOrEqual', AnyTypeNodes, AnyTypeNodes ]; export type LessThanNode = ['LessThan', AnyTypeNodes, AnyTypeNodes]; export type LessThanOrEqualNode = [ 'LessThanOrEqual', AnyTypeNodes, AnyTypeNodes ]; export type BetweenNode = ['Between', AnyTypeNodes, AnyTypeNodes, AnyTypeNodes]; export type LikeNode = ['Like', AnyTypeNodes, AnyTypeNodes]; export type InNode = [ 'In', FieldNode | ReferencedFieldNode, AnyTypeNodes, ...AnyTypeNodes[] ]; export type NotInNode = [ 'NotIn', FieldNode | ReferencedFieldNode, AnyTypeNodes, ...AnyTypeNodes[] ]; export type NotExistsNode = ['NotExists', AnyTypeNodes]; export type ExistsNode = ['Exists', AnyTypeNodes]; export type NotNode = ['Not', BooleanTypeNodes]; export type AndNode = ['And', ...BooleanTypeNodes[]]; export type OrNode = ['Or', ...BooleanTypeNodes[]]; export type StartsWithNode = ['StartsWith', TextTypeNodes, TextTypeNodes]; export type EndsWithNode = ['EndsWith', TextTypeNodes, TextTypeNodes]; export type ContainsNode = ['Contains', TextTypeNodes, TextTypeNodes]; export type StrictBooleanTypeNodes = BooleanNode | EqualsNode | EqualsAnyNode | NotEqualsNode | IsDistinctFromNode | IsNotDistinctFromNode | GreaterThanNode | GreaterThanOrEqualNode | LessThanNode | LessThanOrEqualNode | BetweenNode | LikeNode | InNode | NotInNode | ExistsNode | NotExistsNode | NotNode | AndNode | OrNode | StartsWithNode | EndsWithNode | ContainsNode; export type BooleanTypeNodes = StrictBooleanTypeNodes | UnknownTypeNodes; export type YearNode = ['Year', DateTypeNodes]; export type MonthNode = ['Month', DateTypeNodes]; export type DayNode = ['Day', DateTypeNodes]; export type HourNode = ['Hour', DateTypeNodes]; export type MinuteNode = ['Minute', DateTypeNodes]; export type SecondNode = ['Second', DateTypeNodes]; export type FractionalsecondsNode = ['Fractionalseconds', DateTypeNodes]; export type ExtractNumericDateTypeNodes = YearNode | MonthNode | DayNode | HourNode | MinuteNode | SecondNode | FractionalsecondsNode; export type TotalsecondsNode = ['Totalseconds', DurationTypeNodes]; export type IntegerNode = ['Integer', number]; export type RealNode = ['Real', number]; export type NumberNode = ['Number', number]; export type AddNode = ['Add', NumberTypeNodes, NumberTypeNodes]; export type SubtractNode = ['Subtract', NumberTypeNodes, NumberTypeNodes]; export type MultiplyNode = ['Multiply', NumberTypeNodes, NumberTypeNodes]; export type DivideNode = ['Divide', NumberTypeNodes, NumberTypeNodes]; export type StrPosNode = ['StrPos', TextTypeNodes, TextTypeNodes]; export type RoundNode = ['Round', NumberTypeNodes]; export type FloorNode = ['Floor', NumberTypeNodes]; export type CeilingNode = ['Ceiling', NumberTypeNodes]; export type CountNode = ['Count', '*']; export type AverageNode = ['Average', NumberTypeNodes]; export type SumNode = ['Sum', NumberTypeNodes]; export type CharacterLengthNode = ['CharacterLength', TextTypeNodes]; export type BitwiseAndNode = ['BitwiseAnd', NumberTypeNodes, NumberTypeNodes]; export type BitwiseShiftRightNode = [ 'BitwiseShiftRight', NumberTypeNodes, NumberTypeNodes ]; export type StrictNumberTypeNodes = NumberNode | IntegerNode | RealNode | AddNode | SubtractNode | MultiplyNode | DivideNode | StrPosNode | ExtractNumericDateTypeNodes | TotalsecondsNode | RoundNode | FloorNode | CeilingNode | CountNode | AverageNode | SumNode | BitwiseAndNode | BitwiseShiftRightNode | CharacterLengthNode | SubtractDateDateNode; export type NumberTypeNodes = StrictNumberTypeNodes | UnknownTypeNodes; export type FieldNode = ['Field', string]; export type ReferencedFieldNode = ['ReferencedField', string, string]; export type DateTruncNode = ['DateTrunc', TextTypeNodes, DateTypeNodes] | ['DateTrunc', TextTypeNodes, DateTypeNodes, TextTypeNodes]; export type ToDateNode = ['ToDate', DateTypeNodes]; export type ToTimeNode = ['ToTime', DateTypeNodes]; export type CurrentTimestampNode = ['CurrentTimestamp']; export type CurrentDateNode = ['CurrentDate']; export type RangeLowerNode = ['RangeLower', RangeTypeNodes]; export type RangeUpperNode = ['RangeUpper', RangeTypeNodes]; export type RangeTypeNodes = UnknownTypeNodes; export type StrictDateTypeNodes = DateNode | ToDateNode | ToTimeNode | CurrentTimestampNode | CurrentDateNode | DateTruncNode | SubtractDateNumberNode | SubtractDateDurationNode | AddDateTypeNodes; export type DateTypeNodes = StrictDateTypeNodes | UnknownTypeNodes; export type SubtractDateDateNode = [ 'SubtractDateDate', DateTypeNodes, DateTypeNodes ]; export type SubtractDateNumberNode = [ 'SubtractDateNumber', DateTypeNodes, NumberTypeNodes ]; export type SubtractDateDurationNode = [ 'SubtractDateDuration', DateTypeNodes, DurationNode ]; export type AddDateTypeNodes = AddDateNumberNode | AddDateDurationNode; export type AddDateNumberNode = [ 'AddDateNumber', DateTypeNodes, NumberTypeNodes ]; export type AddDateDurationNode = [ 'AddDateDuration', DateTypeNodes, DurationNode ]; export type WhenNode = ['When', BooleanTypeNodes, AnyTypeNodes]; export type ElseNode = ['Else', AnyTypeNodes]; export type CaseNode = ['Case', ...WhenNode[]] | ['Case', ...WhenNode[], ElseNode]; export type BindNode = ['Bind', number | string] | ['Bind', [string, string]]; export type CastNode = ['Cast', AnyTypeNodes, type: string | TableNode]; export type CoalesceNode = [ 'Coalesce', AnyTypeNodes, AnyTypeNodes, ...AnyTypeNodes[] ]; export type AnyNode = ['Any', AnyTypeNodes, string]; export type FnCallNode = ['FnCall', string, ...AnyTypeNodes[]]; export type UnknownTypeNodes = SelectQueryNode | JSONPopulateRecordNode | UnionQueryNode | NullNode | FieldNode | ReferencedFieldNode | BindNode | CastNode | CaseNode | CoalesceNode | AnyNode | FnCallNode | RangeLowerNode | RangeUpperNode; /** * This converts a row that looks like a specific table row based upon column names to the actual row type * of that table using the column names and avoiding issues due to the positional order of the columns. * Note: this only takes effect on postgres */ export type ConvertRowNode = ['ConvertRow', SelectQueryNode, TableNode]; export type JSONPopulateRecordNode = [ 'JSONPopulateRecord', CastNode, JSONTypeNodes ]; export type ToJSONNode = ['ToJSON', AnyTypeNodes]; /** * The referenced field node should be like `table.*` */ export type RowToJSONNode = ['RowToJSON', ReferencedFieldNode]; export type AggregateJSONNode = [ 'AggregateJSON', FieldNode | ReferencedFieldNode ]; export type StrictJSONTypeNodes = AggregateJSONNode | ToJSONNode | RowToJSONNode; export type JSONTypeNodes = StrictJSONTypeNodes | UnknownTypeNodes; export type EmbeddedTextNode = ['EmbeddedText', string]; export type TextNode = ['Text', string]; export type ConcatenateNode = [ 'Concatenate', TextTypeNodes, ...TextTypeNodes[] ]; export type ConcatenateWithSeparatorNode = [ 'ConcatenateWithSeparator', TextTypeNodes, TextTypeNodes, ...TextTypeNodes[] ]; export type LowerNode = ['Lower', TextTypeNodes]; export type UpperNode = ['Upper', TextTypeNodes]; export type TrimNode = ['Trim', TextTypeNodes]; export type SubstringNode = [ 'Substring', TextTypeNodes, NumberTypeNodes, NumberTypeNodes? ]; export type RightNode = ['Right', TextTypeNodes, NumberTypeNodes]; export type ReplaceNode = [ 'Replace', TextTypeNodes, TextTypeNodes, TextTypeNodes ]; export type ExtractJSONPathAsTextNode = [ 'ExtractJSONPathAsText', JSONTypeNodes, TextArrayTypeNodes ]; export type EscapeForLikeNode = ['EscapeForLike', TextTypeNodes]; export type StrictTextArrayTypeNodes = TextArrayNode; export type TextArrayTypeNodes = StrictTextArrayTypeNodes | UnknownTypeNodes; export type TextArrayNode = ['TextArray', ...TextTypeNodes[]]; export type StrictTextTypeNodes = TextNode | EmbeddedTextNode | ConcatenateNode | ConcatenateWithSeparatorNode | LowerNode | UpperNode | TrimNode | SubstringNode | RightNode | ReplaceNode | ExtractJSONPathAsTextNode | EscapeForLikeNode; export type TextTypeNodes = StrictTextTypeNodes | UnknownTypeNodes; export type JoinTypeNodes = InnerJoinNode | LeftJoinNode | RightJoinNode | FullJoinNode | CrossJoinNode; export type SelectQueryStatementNode = SelectNode | FromNode | JoinTypeNodes | WhereNode | GroupByNode | HavingNode | OrderByNode | LimitNode | OffsetNode; export type SelectQueryNode = ['SelectQuery', ...SelectQueryStatementNode[]]; export type UnionQueryNode = [ 'UnionQuery', ...(UnionQueryNode | SelectQueryNode)[] ]; export type InsertQueryNode = [ 'InsertQuery', ...Array ]; export type UpdateQueryNode = [ 'UpdateQuery', ...Array ]; export type DeleteQueryNode = ['DeleteQuery', ...Array]; export type UpsertQueryNode = ['UpsertQuery', InsertQueryNode, UpdateQueryNode]; /** * This interface allows adding to the valid set of FromTypeNodes using interface merging, eg * declare module '@balena/abstract-sql-compiler' { * interface FromTypeNode { * MyNode: MyNode; * } * } */ export interface FromTypeNode { SelectQueryNode: SelectQueryNode; UnionQueryNode: UnionQueryNode; TableNode: TableNode; ResourceNode: ResourceNode; JSONPopulateRecordNode: JSONPopulateRecordNode; ConvertRowNode: ConvertRowNode; } /** * This is not currently understood by the abstract-sql-compiler but is a placeholder for future support */ export type ResourceNode = ['Resource', string]; export type FromTypeNodes = FromTypeNode[keyof FromTypeNode] | AliasNode; export type SelectNode = ['Select', AnyTypeNodes[]]; export type FromNode = ['From', FromTypeNodes]; export type InnerJoinNode = ['Join', FromTypeNodes, OnNode?]; export type LeftJoinNode = ['LeftJoin', FromTypeNodes, OnNode?]; export type RightJoinNode = ['RightJoin', FromTypeNodes, OnNode?]; export type FullJoinNode = ['FullJoin', FromTypeNodes, OnNode?]; export type CrossJoinNode = ['CrossJoin', FromTypeNodes]; export type OnNode = ['On', BooleanTypeNodes]; export type TableNode = ['Table', string]; export type WhereNode = ['Where', BooleanTypeNodes]; export type GroupByNode = ['GroupBy', Array]; export type HavingNode = ['Having', BooleanTypeNodes]; type OrderBy = ['ASC' | 'DESC', AnyTypeNodes]; export type OrderByNode = ['OrderBy', ...OrderBy[]]; export type LimitNode = ['Limit', NumberTypeNodes]; export type OffsetNode = ['Offset', NumberTypeNodes]; export type FieldsNode = ['Fields', string[]]; export type ValuesNode = [ 'Values', SelectQueryNode | UnionQueryNode | ValuesNodeTypes[] ]; export type ValuesNodeTypes = 'Default' | NullNode | BindNode | TextNode | EmbeddedTextNode | NumberNode | IntegerNode | RealNode | BooleanNode; export type AliasNode = ['Alias', T, string]; export type AnyTypeNodes = DateTypeNodes | BooleanTypeNodes | NumberTypeNodes | TextTypeNodes | JSONTypeNodes | TextArrayTypeNodes | UnknownTypeNodes | DurationNode | InsertQueryNode | UpdateQueryNode | DeleteQueryNode | UpsertQueryNode | ValuesNode | SelectQueryStatementNode | FromTypeNodes | UnknownNode; export type AbstractSqlType = string | string[] | AnyTypeNodes; export type UnknownNode = AbstractSqlQuery; export interface AbstractSqlQuery extends Array { 0: string; } export interface AbstractSqlField { fieldName: string; dataType: string; required?: boolean; index?: string; references?: { resourceName: string; fieldName: string; type?: string; }; defaultValue?: string; computed?: AnyTypeNodes | true | { parallel: 'UNSAFE' | 'RESTRICTED' | 'SAFE'; volatility: 'STABLE' | 'IMMUTABLE' | 'VOLATILE'; definition: AnyTypeNodes; fnName?: string; }; checks?: BooleanTypeNodes[]; } export interface Trigger { operation: 'INSERT' | 'UPDATE' | 'DELETE' | 'TRUNCATE'; fnName: string; level: 'ROW' | 'STATEMENT'; when: 'BEFORE' | 'AFTER' | 'INSTEAD OF'; } export interface Index { type: string; fields: string[]; name?: string; /** For rules converted to partial unique indexes this holds the actual rule expression */ description?: string; distinctNulls?: boolean; predicate?: BooleanTypeNodes; } export interface Check { description?: string; name?: string; abstractSql: BooleanTypeNodes; } export interface BindVars extends Array { [key: string]: any; } export interface Definition { binds?: BindVars; abstractSql: FromTypeNodes; } export interface AbstractSqlTable { name: string; resourceName: string; idField: string; fields: AbstractSqlField[]; indexes: Index[]; primitive: false | string; triggers?: Trigger[]; checks?: Check[]; viewDefinition?: Omit; definition?: Definition; modifyFields?: AbstractSqlTable['fields']; modifyName?: AbstractSqlTable['name']; } export interface SqlRule { sql: string; bindings: Binding[]; structuredEnglish: string; referencedFields?: ReferencedFields | undefined; ruleReferencedFields?: RuleReferencedFields | undefined; } /** * The RelationshipMapping can either describe a relationship to another term, or * a relationship to a local term (since simple terms are also defined and referenced). * A local term basically describes the fields of the term that are available. * * - RelationshipMapping[0] is the local field * * If this relationship points to a foreign term (a different table) * * - RelationshipMapping[1] is the reference to the other resource, that joins this resource * - RelationshipMapping[1][0] is the name of the other resource (or the other table) * - RelationshipMapping[1][1] is the name of the field on the other resource */ export type RelationshipMapping = [string, [string, string]?]; export interface RelationshipLeafNode { $: RelationshipMapping; } export interface RelationshipInternalNode { [resourceName: string]: Relationship; } export type Relationship = RelationshipLeafNode | RelationshipInternalNode; export interface AbstractSqlModel { synonyms: { [synonym: string]: string; }; relationships: { [resourceName: string]: RelationshipInternalNode; }; tables: { [resourceName: string]: AbstractSqlTable; }; rules: Array<[ 'Rule', ['Body', AbstractSqlQuery], ['StructuredEnglish', string] ]>; functions?: Record; lfInfo: { rules: { [key: string]: LfRuleInfo; }; }; } export interface LfRuleInfo { root: { table: string; alias: string; }; } export interface SqlModel { synonyms: { [synonym: string]: string; }; relationships: { [resourceName: string]: Relationship; }; tables: { [resourceName: string]: AbstractSqlTable; }; rules: SqlRule[]; createSchema: string[]; dropSchema: string[]; } export interface EngineInstance { compileSchema: (abstractSqlModel: AbstractSqlModel) => SqlModel; compileRule: (abstractSQL: AbstractSqlQuery) => SqlResult | [SqlResult, SqlResult]; dataTypeValidate: (value: any, field: Pick) => Promise; getReferencedFields: (ruleBody: AbstractSqlQuery) => ReferencedFields; /** * This gets referenced fields for a query that is expected to always return true and only return fields that could change it to false */ getRuleReferencedFields: (ruleBody: AbstractSqlQuery) => RuleReferencedFields; getModifiedFields: (abstractSqlQuery: AbstractSqlQuery) => undefined | ModifiedFields | Array; } export declare const isAliasNode: (n: AliasNode | AbstractSqlType) => n is AliasNode; export declare const isFromNode: (n: AbstractSqlType) => n is FromNode; export declare const isTableNode: (n: AbstractSqlType) => n is TableNode; export declare const isResourceNode: (n: AbstractSqlType) => n is ResourceNode; export declare const isSelectQueryNode: (n: AbstractSqlType) => n is SelectQueryNode; export declare const isSelectNode: (n: AbstractSqlType) => n is SelectNode; export declare const isWhereNode: (n: AbstractSqlType) => n is WhereNode; export declare const isReferencedFieldNode: (n: AbstractSqlType) => n is ReferencedFieldNode; export declare const isFieldNode: (n: AbstractSqlType) => n is FieldNode; export declare const isFieldTypeNode: (n: AbstractSqlType) => n is FieldNode | ReferencedFieldNode; /** * * @param n The abstract sql to check * @param checkNodeTypeFn A function that checks if a given node is the correct type */ export declare const abstractSqlContainsNode: (n: AnyTypeNodes, checkNodeTypeFn: (n: AnyTypeNodes) => boolean) => boolean; export declare function compileRule(abstractSQL: UpsertQueryNode, engine: Engines, noBinds: true): [string, string]; export declare function compileRule(abstractSQL: AbstractSqlQuery, engine: Engines, noBinds: true): string; export declare function compileRule(abstractSQL: UpsertQueryNode, engine: Engines, noBinds?: false): [SqlResult, SqlResult]; export declare function compileRule(abstractSQL: SelectQueryNode | UnionQueryNode | InsertQueryNode | UpdateQueryNode | DeleteQueryNode, engine: Engines, noBinds?: false): SqlResult; export declare function compileRule(abstractSQL: AbstractSqlQuery, engine: Engines, noBinds?: false): SqlResult | [SqlResult, SqlResult]; export declare function compileRule(abstractSQL: AbstractSqlQuery, engine: Engines, noBinds?: boolean): SqlResult | [SqlResult, SqlResult] | string; export { optimizeSchema }; export declare const postgres: { optimizeSchema: (abstractSqlModel: AbstractSqlModel, { createCheckConstraints }?: { createCheckConstraints?: boolean | undefined; }) => AbstractSqlModel; generateRuleSlug: (tableName: string, ruleBody: AbstractSqlType) => string; compileSchema: (abstractSqlModel: AbstractSqlModel) => SqlModel; compileRule: (abstractSQL: AbstractSqlQuery) => SqlResult | [SqlResult, SqlResult]; dataTypeValidate: (value: any, field: Pick) => Promise; getReferencedFields: (ruleBody: AbstractSqlQuery) => ReferencedFields; getRuleReferencedFields: (ruleBody: AbstractSqlQuery) => RuleReferencedFields; getModifiedFields: (abstractSqlQuery: AbstractSqlQuery) => undefined | ModifiedFields | Array; }; export declare const mysql: { optimizeSchema: (abstractSqlModel: AbstractSqlModel, { createCheckConstraints }?: { createCheckConstraints?: boolean | undefined; }) => AbstractSqlModel; generateRuleSlug: (tableName: string, ruleBody: AbstractSqlType) => string; compileSchema: (abstractSqlModel: AbstractSqlModel) => SqlModel; compileRule: (abstractSQL: AbstractSqlQuery) => SqlResult | [SqlResult, SqlResult]; dataTypeValidate: (value: any, field: Pick) => Promise; getReferencedFields: (ruleBody: AbstractSqlQuery) => ReferencedFields; getRuleReferencedFields: (ruleBody: AbstractSqlQuery) => RuleReferencedFields; getModifiedFields: (abstractSqlQuery: AbstractSqlQuery) => undefined | ModifiedFields | Array; }; export declare const websql: { optimizeSchema: (abstractSqlModel: AbstractSqlModel, { createCheckConstraints }?: { createCheckConstraints?: boolean | undefined; }) => AbstractSqlModel; generateRuleSlug: (tableName: string, ruleBody: AbstractSqlType) => string; compileSchema: (abstractSqlModel: AbstractSqlModel) => SqlModel; compileRule: (abstractSQL: AbstractSqlQuery) => SqlResult | [SqlResult, SqlResult]; dataTypeValidate: (value: any, field: Pick) => Promise; getReferencedFields: (ruleBody: AbstractSqlQuery) => ReferencedFields; getRuleReferencedFields: (ruleBody: AbstractSqlQuery) => RuleReferencedFields; getModifiedFields: (abstractSqlQuery: AbstractSqlQuery) => undefined | ModifiedFields | Array; };