New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@balena/abstract-sql-compiler

Package Overview
Dependencies
Maintainers
3
Versions
478
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@balena/abstract-sql-compiler - npm Package Compare versions

Comparing version 7.10.0 to 7.10.1-separate-referenced-fields-7ca7b5cfad4e8833293426235667cc59245f427a

out/referenced-fields.d.ts

4

CHANGELOG.md

@@ -7,2 +7,6 @@ # Change Log

## 7.10.1 - 2021-01-29
* Separate code relating to referenced fields out of the main file [Pagan Gazzard]
## 7.10.0 - 2021-01-29

@@ -9,0 +13,0 @@

17

out/AbstractSQLCompiler.d.ts

@@ -9,2 +9,4 @@ export declare const enum Engines {

import * as _ from 'lodash';
import { ReferencedFields, RuleReferencedFields, ModifiedFields } from './referenced-fields';
export type { ReferencedFields, RuleReferencedFields, ModifiedFields };
export declare type NullNode = ['Null'];

@@ -173,5 +175,2 @@ export declare type DateNode = ['Date', Date];

}
export interface ReferencedFields {
[alias: string]: string[];
}
export interface SqlRule {

@@ -223,7 +222,2 @@ sql: string;

}
export interface ModifiedFields {
table: string;
action: keyof RuleReferencedFields[string];
fields?: string[];
}
export interface EngineInstance {

@@ -240,9 +234,2 @@ compileSchema: (abstractSqlModel: AbstractSqlModel) => SqlModel;

export declare const isResourceNode: (n: AbstractSqlType) => n is ResourceNode;
export interface RuleReferencedFields {
[alias: string]: {
create: string[];
update: string[];
delete: string[];
};
}
export declare function compileRule(abstractSQL: UpsertQueryNode, engine: Engines, noBinds: true): [string, string];

@@ -249,0 +236,0 @@ export declare function compileRule(abstractSQL: AbstractSqlQuery, engine: Engines, noBinds: true): string;

@@ -15,2 +15,3 @@ "use strict";

const AbstractSQLSchemaOptimiser_1 = require("./AbstractSQLSchemaOptimiser");
const referenced_fields_1 = require("./referenced-fields");
const validateTypes = _.mapValues(sbvrTypes, ({ validate }) => validate);

@@ -85,170 +86,2 @@ const dataTypeValidate = async (value, field) => {

};
const getScope = (rulePart, scope) => {
scope = { ...scope };
const fromNodes = rulePart.filter(exports.isFromNode);
fromNodes.forEach((node) => {
const nested = node[1];
if (nested[0] === 'Alias') {
const [, from, alias] = nested;
if (typeof alias !== 'string') {
throw new Error('Cannot handle non-string aliases');
}
switch (from[0]) {
case 'Table':
scope[alias] = from[1];
break;
case 'SelectQuery':
scope[alias] = '';
break;
default:
throw new Error(`Cannot handle aliased ${from[0]} nodes`);
}
}
else if (nested[0] === 'Table') {
scope[nested[1]] = nested[1];
}
else {
throw Error(`Unsupported FromNode for scoping: ${nested[0]}`);
}
});
return scope;
};
const $getReferencedFields = (referencedFields, rulePart, scope = {}) => {
if (!Array.isArray(rulePart)) {
return;
}
switch (rulePart[0]) {
case 'SelectQuery':
scope = getScope(rulePart, scope);
rulePart.forEach((node) => {
$getReferencedFields(referencedFields, node, scope);
});
break;
case 'ReferencedField':
let tableName = rulePart[1];
const fieldName = rulePart[2];
if (typeof tableName !== 'string' || typeof fieldName !== 'string') {
throw new Error(`Invalid ReferencedField: ${rulePart}`);
}
tableName = scope[tableName];
if (tableName !== '') {
if (referencedFields[tableName] == null) {
referencedFields[tableName] = [];
}
referencedFields[tableName].push(fieldName);
}
return;
case 'Field':
throw new Error('Cannot find queried fields for unreferenced fields');
default:
rulePart.forEach((node) => {
$getReferencedFields(referencedFields, node, scope);
});
}
};
const getReferencedFields = (ruleBody) => {
ruleBody = AbstractSQLOptimiser_1.AbstractSQLOptimiser(ruleBody);
const referencedFields = {};
$getReferencedFields(referencedFields, ruleBody);
return _.mapValues(referencedFields, _.uniq);
};
const dealiasTableNode = (n) => {
if (exports.isTableNode(n)) {
return n;
}
if (n[0] === 'Alias' && exports.isTableNode(n[1])) {
return n[1];
}
};
const getRuleReferencedFields = (ruleBody) => {
ruleBody = AbstractSQLOptimiser_1.AbstractSQLOptimiser(ruleBody);
let referencedFields = {};
const deletable = new Set();
if (ruleBody[0] === 'NotExists') {
const s = ruleBody[1];
if (s[0] === 'SelectQuery') {
s.forEach((m) => {
if (!exports.isFromNode(m)) {
return;
}
const table = dealiasTableNode(m[1]);
if (table == null) {
return;
}
deletable.add(table[1]);
});
}
}
$getReferencedFields(referencedFields, ruleBody);
referencedFields = _.mapValues(referencedFields, _.uniq);
const refFields = {};
for (const f of Object.keys(referencedFields)) {
refFields[f] = {
create: referencedFields[f],
update: referencedFields[f],
delete: referencedFields[f],
};
if (deletable.has(f)) {
const countFroms = (n) => {
let count = 0;
n.forEach((p) => {
var _a;
if (Array.isArray(p)) {
if (exports.isFromNode(p) && ((_a = dealiasTableNode(p[1])) === null || _a === void 0 ? void 0 : _a[1]) === f) {
count++;
}
else {
count += countFroms(p);
}
}
});
return count;
};
if (countFroms(ruleBody) === 1) {
refFields[f].delete = [];
}
}
}
return refFields;
};
const checkQuery = (query) => {
const queryType = query[0];
if (!['InsertQuery', 'UpdateQuery', 'DeleteQuery'].includes(queryType)) {
return;
}
const froms = query.filter(exports.isFromNode);
if (froms.length !== 1) {
return;
}
const table = froms[0][1];
let tableName;
if (table[0] === 'Table') {
tableName = table[1];
}
else if (typeof table === 'string') {
tableName = table;
}
else {
return;
}
if (queryType === 'InsertQuery') {
return { table: tableName, action: 'create' };
}
if (queryType === 'DeleteQuery') {
return { table: tableName, action: 'delete' };
}
const fields = _(query)
.filter((v) => v != null && v[0] === 'Fields')
.flatMap((v) => v[1])
.value();
return { table: tableName, action: 'update', fields };
};
const getModifiedFields = (abstractSqlQuery) => {
if (Array.isArray(abstractSqlQuery[0])) {
return abstractSqlQuery.map(checkQuery);
}
else {
return checkQuery(abstractSqlQuery);
}
};
function compileRule(abstractSQL, engine, noBinds = false) {

@@ -493,3 +326,3 @@ abstractSQL = AbstractSQLOptimiser_1.AbstractSQLOptimiser(abstractSQL, noBinds);

try {
referencedFields = getReferencedFields(ruleBody);
referencedFields = referenced_fields_1.getReferencedFields(ruleBody);
}

@@ -501,3 +334,3 @@ catch (e) {

try {
ruleReferencedFields = getRuleReferencedFields(ruleBody);
ruleReferencedFields = referenced_fields_1.getRuleReferencedFields(ruleBody);
}

@@ -530,5 +363,5 @@ catch (e) {

dataTypeValidate,
getReferencedFields,
getRuleReferencedFields,
getModifiedFields,
getReferencedFields: referenced_fields_1.getReferencedFields,
getRuleReferencedFields: referenced_fields_1.getRuleReferencedFields,
getModifiedFields: referenced_fields_1.getModifiedFields,
};

@@ -535,0 +368,0 @@ };

{
"name": "@balena/abstract-sql-compiler",
"version": "7.10.0",
"version": "7.10.1-separate-referenced-fields-7ca7b5cfad4e8833293426235667cc59245f427a",
"description": "A translator for abstract sql into sql.",

@@ -5,0 +5,0 @@ "main": "out/AbstractSQLCompiler.js",

@@ -17,3 +17,13 @@ export const enum Engines {

import { optimizeSchema } from './AbstractSQLSchemaOptimiser';
import {
getReferencedFields,
getRuleReferencedFields,
getModifiedFields,
ReferencedFields,
RuleReferencedFields,
ModifiedFields,
} from './referenced-fields';
export type { ReferencedFields, RuleReferencedFields, ModifiedFields };
export type NullNode = ['Null'];

@@ -277,5 +287,2 @@ export type DateNode = ['Date', Date];

}
export interface ReferencedFields {
[alias: string]: string[];
}
export interface SqlRule {

@@ -341,8 +348,2 @@ sql: string;

export interface ModifiedFields {
table: string;
action: keyof RuleReferencedFields[string];
fields?: string[];
}
export interface EngineInstance {

@@ -456,202 +457,2 @@ compileSchema: (abstractSqlModel: AbstractSqlModel) => SqlModel;

type Scope = _.Dictionary<string>;
const getScope = (rulePart: AbstractSqlQuery, scope: Scope): Scope => {
scope = { ...scope };
const fromNodes = rulePart.filter(isFromNode);
fromNodes.forEach((node) => {
const nested = node[1];
if (nested[0] === 'Alias') {
const [, from, alias] = nested;
if (typeof alias !== 'string') {
throw new Error('Cannot handle non-string aliases');
}
switch (from[0]) {
case 'Table':
scope[alias] = from[1];
break;
case 'SelectQuery':
// Ignore SelectQuery in the From as we'll handle any fields it selects
// when we recurse in. With true scope handling however we could prune
// fields that don't affect the end result and avoid false positives
scope[alias] = '';
break;
default:
throw new Error(`Cannot handle aliased ${from[0]} nodes`);
}
} else if (nested[0] === 'Table') {
scope[nested[1]] = nested[1];
} else {
throw Error(`Unsupported FromNode for scoping: ${nested[0]}`);
}
});
return scope;
};
const $getReferencedFields = (
referencedFields: ReferencedFields,
rulePart: AbstractSqlQuery,
scope: Scope = {},
) => {
if (!Array.isArray(rulePart)) {
return;
}
switch (rulePart[0]) {
case 'SelectQuery':
// Update the current scope before trying to resolve field references
scope = getScope(rulePart, scope);
rulePart.forEach((node: AbstractSqlQuery) => {
$getReferencedFields(referencedFields, node, scope);
});
break;
case 'ReferencedField':
let tableName = rulePart[1];
const fieldName = rulePart[2];
if (typeof tableName !== 'string' || typeof fieldName !== 'string') {
throw new Error(`Invalid ReferencedField: ${rulePart}`);
}
tableName = scope[tableName];
// The scoped tableName is empty in the case of an aliased from query
// and those fields will be covered when we recurse into them
if (tableName !== '') {
if (referencedFields[tableName] == null) {
referencedFields[tableName] = [];
}
referencedFields[tableName].push(fieldName);
}
return;
case 'Field':
throw new Error('Cannot find queried fields for unreferenced fields');
default:
rulePart.forEach((node: AbstractSqlQuery) => {
$getReferencedFields(referencedFields, node, scope);
});
}
};
const getReferencedFields: EngineInstance['getReferencedFields'] = (
ruleBody,
) => {
ruleBody = AbstractSQLOptimiser(ruleBody);
const referencedFields: ReferencedFields = {};
$getReferencedFields(referencedFields, ruleBody);
return _.mapValues(referencedFields, _.uniq);
};
const dealiasTableNode = (n: AbstractSqlQuery): TableNode | undefined => {
if (isTableNode(n)) {
return n;
}
if (n[0] === 'Alias' && isTableNode(n[1])) {
return n[1];
}
};
export interface RuleReferencedFields {
[alias: string]: {
create: string[];
update: string[];
delete: string[];
};
}
const getRuleReferencedFields: EngineInstance['getRuleReferencedFields'] = (
ruleBody,
) => {
ruleBody = AbstractSQLOptimiser(ruleBody);
let referencedFields: ReferencedFields = {};
const deletable = new Set<string>();
if (ruleBody[0] === 'NotExists') {
const s = ruleBody[1] as SelectQueryNode;
if (s[0] === 'SelectQuery') {
s.forEach((m) => {
if (!isFromNode(m)) {
return;
}
const table = dealiasTableNode(m[1]);
if (table == null) {
// keep this from node for later checking if we didn't optimize out
return;
}
deletable.add(table[1]);
});
}
}
$getReferencedFields(referencedFields, ruleBody);
referencedFields = _.mapValues(referencedFields, _.uniq);
const refFields: RuleReferencedFields = {};
for (const f of Object.keys(referencedFields)) {
refFields[f] = {
create: referencedFields[f],
update: referencedFields[f],
delete: referencedFields[f],
};
if (deletable.has(f)) {
const countFroms = (n: AbstractSqlType[]) => {
let count = 0;
n.forEach((p) => {
if (Array.isArray(p)) {
if (isFromNode(p) && dealiasTableNode(p[1])?.[1] === f) {
count++;
} else {
count += countFroms(p as AbstractSqlType[]);
}
}
});
return count;
};
// It's only deletable if there's just a single ref
if (countFroms(ruleBody) === 1) {
refFields[f].delete = [];
}
}
}
return refFields;
};
const checkQuery = (query: AbstractSqlQuery): ModifiedFields | undefined => {
const queryType = query[0];
if (!['InsertQuery', 'UpdateQuery', 'DeleteQuery'].includes(queryType)) {
return;
}
const froms = query.filter(isFromNode);
if (froms.length !== 1) {
return;
}
const table = froms[0][1];
let tableName: string;
if (table[0] === 'Table') {
tableName = table[1];
} else if (typeof table === 'string') {
// Deprecated: Remove this when we drop implicit tables
tableName = table;
} else {
return;
}
if (queryType === 'InsertQuery') {
return { table: tableName, action: 'create' };
}
if (queryType === 'DeleteQuery') {
return { table: tableName, action: 'delete' };
}
const fields = _<FieldsNode | AbstractSqlType>(query)
.filter((v): v is FieldsNode => v != null && v[0] === 'Fields')
.flatMap((v) => v[1])
.value();
return { table: tableName, action: 'update', fields };
};
const getModifiedFields: EngineInstance['getModifiedFields'] = (
abstractSqlQuery: AbstractSqlQuery,
) => {
if (Array.isArray(abstractSqlQuery[0])) {
return abstractSqlQuery.map(checkQuery);
} else {
return checkQuery(abstractSqlQuery);
}
};
export function compileRule(

@@ -658,0 +459,0 @@ abstractSQL: UpsertQueryNode,

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc