Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 21 additions & 7 deletions src/AbstractSQLCompiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -455,16 +455,19 @@ export function compileRule(
abstractSQL: UpsertQueryNode,
engine: Engines,
noBinds: true,
abstractSqlModel?: AbstractSqlModel,
): [string, string];
export function compileRule(
abstractSQL: AbstractSqlQuery,
engine: Engines,
noBinds: true,
abstractSqlModel?: AbstractSqlModel,
): string;
export function compileRule(
abstractSQL: UpsertQueryNode,
engine: Engines,
noBinds?: false,
abstractSqlModel?: AbstractSqlModel,
): [SqlResult, SqlResult];
export function compileRule(
abstractSQL:
Expand All @@ -475,23 +478,27 @@ export function compileRule(
| DeleteQueryNode,
engine: Engines,
noBinds?: false,
abstractSqlModel?: AbstractSqlModel,
): SqlResult;
export function compileRule(
abstractSQL: AbstractSqlQuery,
engine: Engines,
noBinds?: false,
abstractSqlModel?: AbstractSqlModel,
): SqlResult | [SqlResult, SqlResult];
export function compileRule(
abstractSQL: AbstractSqlQuery,
engine: Engines,
noBinds?: boolean,
abstractSqlModel?: AbstractSqlModel,
): SqlResult | [SqlResult, SqlResult] | string;
export function compileRule(
abstractSQL: AbstractSqlQuery,
engine: Engines,
noBinds = false,
abstractSqlModel?: AbstractSqlModel,
): SqlResult | [SqlResult, SqlResult] | string | [string, string] {
abstractSQL = AbstractSQLOptimiser(abstractSQL, noBinds);
abstractSQL = AbstractSQLOptimiser(abstractSQL, noBinds, abstractSqlModel);
return AbstractSQLRules2SQL(abstractSQL, engine, noBinds);
}

Expand Down Expand Up @@ -586,10 +593,12 @@ $$;`);
createSQL: [
`\
CREATE ${orReplaceStr}VIEW "${table.name}" AS (
${compileRule(definitionAbstractSql as AbstractSqlQuery, engine, true).replace(
/^/gm,
' ',
)}
${compileRule(
definitionAbstractSql as AbstractSqlQuery,
engine,
true,
abstractSqlModel,
).replace(/^/gm, ' ')}
);`,
],
dropSQL: [`DROP VIEW "${table.name}";`],
Expand Down Expand Up @@ -671,6 +680,7 @@ $$;`);
check.abstractSql as AbstractSqlQuery,
engine,
true,
abstractSqlModel,
);
createSqlElements.push(`\
${comment}${constraintName}CHECK (${sql})`);
Expand Down Expand Up @@ -796,6 +806,8 @@ CREATE TABLE ${ifNotExistsStr}"${table.name}" (
const { query: ruleSQL, bindings: ruleBindings } = compileRule(
ruleBody,
engine,
undefined,
abstractSqlModel,
) as SqlResult;
let referencedFields: ReferencedFields | undefined;
try {
Expand Down Expand Up @@ -835,8 +847,10 @@ const generateExport = (engine: Engines, ifNotExists: boolean) => {
optimizeSchema,
compileSchema: (abstractSqlModel: AbstractSqlModel) =>
compileSchema(abstractSqlModel, engine, ifNotExists),
compileRule: (abstractSQL: AbstractSqlQuery) =>
compileRule(abstractSQL, engine, false),
compileRule: (
abstractSQL: AbstractSqlQuery,
abstractSqlModel?: AbstractSqlModel,
) => compileRule(abstractSQL, engine, false, abstractSqlModel),
dataTypeValidate,
getReferencedFields,
getRuleReferencedFields,
Expand Down
30 changes: 29 additions & 1 deletion src/AbstractSQLOptimiser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@ import * as _ from 'lodash';

import { Dictionary } from 'lodash';
import {
AbstractSqlModel,
AbstractSqlQuery,
AbstractSqlType,
AliasNode,
DurationNode,
ReferencedFieldNode,
ReplaceNode,
TableNode,
} from './AbstractSQLCompiler';
import * as AbstractSQLRules2SQL from './AbstractSQLRules2SQL';

Expand All @@ -14,7 +18,6 @@ const {
getAbstractSqlQuery,
checkArgs,
checkMinArgs,
isNotNullable,
} = AbstractSQLRules2SQL;

type OptimisationMatchFn = (
Expand All @@ -36,7 +39,9 @@ const escapeForLike = (str: AbstractSqlType): ReplaceNode => [
];

let helped = false;
let aliases: { [alias: string]: string } = {};
let noBinds = false;
let abstractSqlModel: AbstractSqlModel | undefined;
const Helper = <F extends (...args: any[]) => any>(fn: F) => {
return (...args: Parameters<F>): ReturnType<F> => {
const result = fn(...args);
Expand Down Expand Up @@ -65,6 +70,22 @@ const isEmptySelectQuery = (query: AbstractSqlQuery): boolean => {
return false;
};

const isNotNullable = (node: AbstractSqlQuery): boolean => {
switch (node[0]) {
case 'ReferencedField':
if (abstractSqlModel != null) {
const [, aliasName, fieldName] = node as ReferencedFieldNode;
const tableName = aliases[aliasName] ?? aliasName;
const table = abstractSqlModel.tables[tableName];
const field = table?.fields.find((f) => f.fieldName === fieldName);
if (field?.required === true) {
return true;
}
}
}
return AbstractSQLRules2SQL.isNotNullable(node);
};

const rewriteMatch = (
name: string,
matchers: Array<(args: AbstractSqlType) => AbstractSqlType>,
Expand Down Expand Up @@ -455,6 +476,10 @@ const typeRules: Dictionary<MatchFn> = {
},
From: (args) => {
checkArgs('From', args, 1);
const maybeAlias = args[0] as AliasNode<TableNode>;
if (maybeAlias[0] === 'Alias' && maybeAlias[1][0] === 'Table') {
aliases[maybeAlias[2]] = maybeAlias[1][1];
}
return ['From', MaybeAlias(args[0] as AbstractSqlQuery, FromMatch)];
},
Join: JoinMatch('Join'),
Expand Down Expand Up @@ -1311,10 +1336,13 @@ const typeRules: Dictionary<MatchFn> = {
export const AbstractSQLOptimiser = (
abstractSQL: AbstractSqlQuery,
$noBinds = false,
$abstractSqlModel?: AbstractSqlModel,
): AbstractSqlQuery => {
noBinds = $noBinds;
abstractSqlModel = $abstractSqlModel;
do {
helped = false;
aliases = {};
const [type, ...rest] = abstractSQL;
switch (type) {
case 'SelectQuery':
Expand Down
6 changes: 5 additions & 1 deletion src/AbstractSQLSchemaOptimiser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,11 @@ export const optimizeSchema = (
}

// Optimize the rule body, this also normalizes it making the check constraint check easier
ruleBodyNode[1] = ruleBody = AbstractSQLOptimiser(ruleBody, true);
ruleBodyNode[1] = ruleBody = AbstractSQLOptimiser(
ruleBody,
true,
abstractSqlModel,
);

const count = countFroms(ruleBody);
if (
Expand Down
Loading