Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Socket
Sign inDemoInstall

objection

Package Overview
Dependencies
Maintainers
2
Versions
201
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

objection - npm Package Compare versions

Comparing version 0.8.0-rc.1 to 0.8.0-rc.2

100

lib/queryBuilder/operations/eager/RelationJoinBuilder.js

@@ -7,4 +7,4 @@ 'use strict';

const idLengthLimit = 63;
const relationRecursionLimit = 64;
const ID_LENGTH_LIMIT = 63;
const RELATION_RECURSION_LIMIT = 64;

@@ -80,3 +80,3 @@ class RelationJoinBuilder {

expr: this.expression,
builder: builder,
builder,
modelClass: builder.modelClass(),

@@ -99,3 +99,3 @@ joinOperation: this.opt.joinOperation || 'leftJoin',

expr: this.expression,
builder: builder,
builder,
modelClass: builder.modelClass(),

@@ -130,2 +130,3 @@ joinOperation: this.opt.joinOperation || 'leftJoin',

const id = pInfo.idGetter(row);
let model;

@@ -146,3 +147,3 @@ if (!id) {

let model = pInfo.getModelFromBranch(curBranch, id);
model = pInfo.getModelFromBranch(curBranch, id);

@@ -174,7 +175,3 @@ if (!model) {

if (!pInfo.omitCols[col]) {
keyInfo.push({
pInfo: pInfo,
key: key,
col: col
});
keyInfo.push({pInfo, key, col});
}

@@ -188,7 +185,3 @@ } else {

if (!pInfo.omitCols[col]) {
keyInfo.push({
pInfo,
key,
col
});
keyInfo.push({pInfo, key, col});
}

@@ -268,4 +261,4 @@ }

const filterQuery = createFilterQuery({
builder: builder,
relation: relation,
builder,
relation,
expr: childExpr

@@ -275,4 +268,4 @@ });

const relatedJoinSelectQuery = createRelatedJoinFromQuery({
filterQuery: filterQuery,
relation: relation,
filterQuery,
relation,
allRelations: this.allRelations

@@ -291,3 +284,3 @@ });

// to the createFilterQuery function because relatedJoinSelectQuery is cloned
// From the return value of that function and we don't want relation.modify
// from the return value of that function and we don't want relation.modify
// to be called twice for it.

@@ -350,13 +343,26 @@ filterQuery.modify(relation.modify);

const rootTable = this.rootModelClass.tableName;
const columns = RelationJoinBuilder.columnInfo[modelClass.tableName].columns;
RelationJoinBuilder.columnInfo[modelClass.tableName].columns.forEach(col => {
for (let i = 0, l = columns.length; i < l; ++i) {
const col = columns[i];
const filterPassed = selectFilter(col);
const isIdColumn = idCols.indexOf(col) !== -1;
// This needs to be var instead of let or const to prevent an optimization
// bailout because of "Unsupported phi use of const or let variable".
var isIdColumn = idCols.indexOf(col) !== -1;
if (filterPassed || isIdColumn) {
selects.push({
col: `${info.encPath || rootTable}.${col}`,
alias: this.joinPath(info.encPath, col)
});
const fullCol = `${info.encPath || rootTable}.${col}`;
if (!builder.hasSelection(fullCol, true)) {
const alias = this.joinPath(info.encPath, col);
if (alias.length > ID_LENGTH_LIMIT) {
throw new ValidationError({
eager: `identifier ${alias} is over ${ID_LENGTH_LIMIT} characters long and would be truncated by the database engine.`
});
}
selects.push(`${fullCol} as ${alias}`);
}
if (!filterPassed) {

@@ -366,3 +372,3 @@ info.omitCols[col] = true;

}
});
}

@@ -372,25 +378,25 @@ if (relation && relation.joinTableExtras) {

relation.joinTableExtras.forEach(extra => {
if (selectFilter(extra.joinTableCol)) {
selects.push({
col: `${joinTable}.${extra.joinTableCol}`,
alias: this.joinPath(info.encPath, extra.aliasCol)
});
}
});
}
for (let i = 0, l = relation.joinTableExtras.length; i < l; ++i) {
const extra = relation.joinTableExtras[i];
const filterPassed = selectFilter(extra.joinTableCol);
const tooLongAliases = selects.filter(select => select.alias.length > idLengthLimit);
if (filterPassed) {
const fullCol = `${joinTable}.${extra.joinTableCol}`;
if (tooLongAliases.length) {
throw new ValidationError({
eager: `identifier ${tooLongAliases[0].alias} is over ${idLengthLimit} characters long `
+ `and would be truncated by the database engine.`
});
if (!builder.hasSelection(fullCol, true)) {
const alias = this.joinPath(info.encPath, extra.aliasCol);
if (alias.length > ID_LENGTH_LIMIT) {
throw new ValidationError({
eager: `identifier ${alias} is over ${ID_LENGTH_LIMIT} characters long and would be truncated by the database engine.`
});
}
selects.push(`${fullCol} as ${alias}`);
}
}
}
}
builder.select(selects
.filter(select => !builder.hasSelection(select.col, true))
.map(select => `${select.col} as ${select.alias}`)
);
builder.select(selects);
}

@@ -506,3 +512,3 @@

if (expr.isAllRecursive() || expr.maxRecursionDepth() > relationRecursionLimit) {
if (expr.isAllRecursive() || expr.maxRecursionDepth() > RELATION_RECURSION_LIMIT) {
throw new ValidationError({

@@ -509,0 +515,0 @@ eager: `recursion depth of eager expression ${expr.toString()} too big for JoinEagerAlgorithm`

@@ -64,3 +64,6 @@ 'use strict';

const addedSelects = {};
let cols;
// Collect columns that need to be selected for the eager fetch
// to work that are not currently selected.
for (let i = 0, l = this.relationsToFetch.length; i < l; ++i) {

@@ -80,3 +83,5 @@ const relation = this.relationsToFetch[i].relation;

const cols = Object.keys(addedSelects);
// Don't move the `let` or `const` here to prevent an optimization
// bailout because of "Unsupported phi use of const or let variable".
cols = Object.keys(addedSelects);

@@ -83,0 +88,0 @@ if (cols.length) {

@@ -43,3 +43,3 @@ 'use strict';

deep: this.splitQueryPropsDeep,
json: json
json
});

@@ -46,0 +46,0 @@

@@ -6,2 +6,5 @@ 'use strict';

const ALIAS_REGEX = /\s+as\s+/i;
const COUNT_REGEX = /count/i;
class SelectOperation extends WrappingQueryBuilderOperation {

@@ -11,6 +14,10 @@

super(name, opt);
this.selections = [];
this.hasCache = Object.create(null);
}
static parseSelection(selection) {
let dotIdx;
if (typeof selection !== 'string') {

@@ -21,4 +28,7 @@ return null;

// Discard the possible alias.
selection = selection.split(/\s+as\s+/i)[0].trim();
const dotIdx = selection.lastIndexOf('.');
if (ALIAS_REGEX.test(selection)) {
selection = selection.split(ALIAS_REGEX)[0].trim();
}
dotIdx = selection.lastIndexOf('.');

@@ -43,3 +53,3 @@ if (dotIdx !== -1) {

// etc. because knex apparently supports it.
if (selections.length === 0 && !/count/i.test(this.name)) {
if (selections.length === 0 && !COUNT_REGEX.test(this.name)) {
return false;

@@ -46,0 +56,0 @@ }

@@ -36,3 +36,6 @@ 'use strict';

let sql = '(';
// Needs to be var instead of let to prevent a weird
// optimization bailout.
var sql = '(';
for (let i = 0, l = columns.length; i < l; ++i) {

@@ -45,2 +48,3 @@ sql += formatter.wrap(columns[i]);

}
sql += ')';

@@ -52,3 +56,3 @@

buildNonComposite(knexBuilder, columns, values) {
let col = (typeof columns === 'string') ? columns : columns[0];
const col = (typeof columns === 'string') ? columns : columns[0];

@@ -55,0 +59,0 @@ if (Array.isArray(values)) {

'use strict';
const memoize = require('lodash').memoize;
const QueryBuilderOperation = require('./QueryBuilderOperation');
const isKnexQueryBuilder = require('../../utils/knexUtils').isKnexQueryBuilder;
const isKnexJoinBuilder = require('../../utils/knexUtils').isKnexJoinBuilder;
const isKnexRaw = require('../../utils/knexUtils').isKnexRaw;
let QueryBuilderBase = null;
let JoinBuilder = null;
const getQueryBuilderBase = memoize(() => require('../QueryBuilderBase'));
const getJoinBuilder = memoize(() => require('../JoinBuilder'));

@@ -18,5 +20,4 @@ class WrappingQueryBuilderOperation extends QueryBuilderOperation {

call(builder, args) {
const ret = wrapArgs(this, builder, args);
this.args = args;
return ret;
this.args = wrapArgs(this, builder, args);
return this.args !== null;
}

@@ -26,7 +27,5 @@ }

function wrapArgs(op, builder, args) {
// Preventing cyclic deps.
QueryBuilderBase = QueryBuilderBase || requireQueryBuilderBase();
const skipUndefined = builder.internalOptions().skipUndefined;
const knex = builder.knex();
const out = new Array(args.length);

@@ -36,64 +35,70 @@ for (let i = 0, l = args.length; i < l; ++i) {

if (arg === undefined) {
if (skipUndefined) {
return false;
} else {
throw new Error(`undefined passed as argument #${l} for '${op.name}' operation. Call skipUndefined() method to ignore the undefined values.`);
}
} else if (arg && arg.isObjectionReferenceBuilder) {
args[i] = knex.raw.apply(knex, args[i].toRawArgs());
} else if (arg && arg.isObjectionQueryBuilderBase) {
// Convert QueryBuilderBase instances into knex query builders.
args[i] = arg.build();
} else if (Array.isArray(arg)) {
if (skipUndefined) {
args[i] = withoutUndefined(arg);
} else if (includesUndefined(arg)) {
throw new Error(`undefined passed as an item in argument #${l} for '${op.name}' operation. Call skipUndefined() method to ignore the undefined values.`);
}
// convert reference builders to knex.raw
args[i] = args[i].map(arg => {
return (arg && arg.isObjectionReferenceBuilder) ? knex.raw.apply(knex, arg.toRawArgs()) : arg;
});
} else if (typeof arg === 'function') {
// If an argument is a function, knex calls it with a query builder as
// first argument (and as `this` context). We wrap the query builder into
// a QueryBuilderBase instance.
args[i] = wrapFunctionArg(arg, knex);
if (isUndefined(arg)) {
return wrapUndefined(i, op, skipUndefined);
} else if (isObjectionReferenceBuilder(arg)) {
out[i] = wrapReferenceBuilder(arg, knex, skipUndefined);
} else if (isObjectionQueryBuilderBase(arg)) {
out[i] = wrapQueryBuilderBase(arg);
} else if (isArray(arg)) {
out[i] = wrapArray(arg, knex, i, op, skipUndefined);
} else if (isFunction(arg)) {
out[i] = wrapFunction(arg, knex);
} else if (isPlainObject(arg)) {
out[i] = wrapObject(arg, knex, i, op, skipUndefined);
} else {
out[i] = arg;
}
}
return true;
return out;
}
function wrapFunctionArg(func, knex) {
// Preventing cyclic deps.
QueryBuilderBase = QueryBuilderBase || requireQueryBuilderBase();
JoinBuilder = JoinBuilder || requireJoinBuilder();
function isUndefined(arg) {
return arg === undefined;
}
return function wrappedKnexFunctionArg() {
if (isKnexQueryBuilder(this)) {
const knexQueryBuilder = this;
const wrappedQueryBuilder = new QueryBuilderBase(knex);
function wrapUndefined(i, op, skipUndefined) {
if (skipUndefined) {
return null;
} else {
throw new Error(`undefined passed as argument #${i} for '${op.name}' operation. Call skipUndefined() method to ignore the undefined values.`);
}
}
func.call(wrappedQueryBuilder, wrappedQueryBuilder);
wrappedQueryBuilder.buildInto(knexQueryBuilder);
} else if (isKnexJoinBuilder(this)) {
const knexQueryBuilder = this;
const joinClauseBuilder = new JoinBuilder(knex);
function isObjectionReferenceBuilder(item) {
return item !== null && item.isObjectionReferenceBuilder === true;
}
func.call(joinClauseBuilder, joinClauseBuilder);
joinClauseBuilder.buildInto(knexQueryBuilder);
} else {
return func.apply(this, arguments);
}
};
function wrapReferenceBuilder(builder, knex) {
return knex.raw.apply(knex, builder.toRawArgs());
}
function withoutUndefined(arr) {
function isObjectionQueryBuilderBase(item) {
return item !== null && item.isObjectionQueryBuilderBase === true;
}
function wrapQueryBuilderBase(builder) {
return builder.build();
}
function isArray(arg) {
return Array.isArray(arg);
}
function wrapArray(arr, knex, i, op, skipUndefined) {
const out = [];
for (let i = 0, l = arr.length; i < l; ++i) {
if (arr[i] !== undefined) {
out.push(arr[i]);
for (let j = 0, l = arr.length; j < l; ++j) {
const item = arr[j];
if (item === undefined) {
if (!skipUndefined) {
throw new Error(`undefined passed as an item in argument #${i} for '${op.name}' operation. Call skipUndefined() method to ignore the undefined values.`);
}
} else if (isObjectionReferenceBuilder(item)) {
out.push(wrapReferenceBuilder(item, knex));
} else if (isObjectionQueryBuilderBase(item)) {
out.push(wrapQueryBuilderBase(item));
} else {
out.push(item);
}

@@ -105,20 +110,65 @@ }

function includesUndefined(arr) {
for (let i = 0, l = arr.length; i < l; ++i) {
if (arr[i] === undefined) {
return true;
function isFunction(arg) {
return typeof arg === 'function';
}
function wrapFunction(func, knex) {
return function wrappedKnexFunctionArg() {
if (isKnexQueryBuilder(this)) {
wrapQueryBuilderFunction(this, func, knex)
} else if (isKnexJoinBuilder(this)) {
wrapJoinBuilderFunction(this, func, knex);
} else {
return func.apply(this, arguments);
}
}
};
}
return false;
function wrapQueryBuilderFunction(knexQueryBuilder, func, knex) {
const QueryBuilderBase = getQueryBuilderBase();
const wrappedQueryBuilder = new QueryBuilderBase(knex);
func.call(wrappedQueryBuilder, wrappedQueryBuilder);
wrappedQueryBuilder.buildInto(knexQueryBuilder);
}
function requireQueryBuilderBase() {
return require('../QueryBuilderBase');
function wrapJoinBuilderFunction(knexJoinBuilder, func, knex) {
const JoinBuilder = getJoinBuilder();
const joinClauseBuilder = new JoinBuilder(knex);
func.call(joinClauseBuilder, joinClauseBuilder);
joinClauseBuilder.buildInto(knexJoinBuilder);
}
function requireJoinBuilder() {
return require('../JoinBuilder');
function isPlainObject(arg) {
return arg !== null
&& typeof arg === 'object'
&& (!arg.constructor || arg.constructor === Object)
&& (!arg.toString || arg.toString === Object.prototype.toString)
}
function wrapObject(obj, knex, i, op, skipUndefined) {
const out = {};
const keys = Object.keys(obj);
for (let j = 0, l = keys.length; j < l; ++j) {
const key = keys[j];
const item = obj[key];
if (item === undefined) {
if (!skipUndefined) {
throw new Error(`undefined passed as an item in argument #${i} for '${op.name}' operation. Call skipUndefined() method to ignore the undefined values.`);
}
} else if (isObjectionReferenceBuilder(item)) {
out[key] = wrapReferenceBuilder(item, knex);
} else if (isObjectionQueryBuilderBase(item)) {
out[key] = wrapQueryBuilderBase(item);
} else {
out[key] = item;
}
}
return out;
}
module.exports = WrappingQueryBuilderOperation;

@@ -445,3 +445,3 @@ 'use strict';

const table = this.modelClass().tableName;
const table = this._modelClass.tableName;
let noSelectStatements = true;

@@ -452,3 +452,3 @@

if (op instanceof SelectOperation) {
if (op.constructor === SelectOperation) {
noSelectStatements = false;

@@ -839,4 +839,4 @@

function build(builder) {
let context = builder.context() || {};
let internalContext = builder.internalContext();
const context = builder.context() || {};
const internalContext = builder.internalContext();
let knexBuilder = builder.knex().queryBuilder();

@@ -843,0 +843,0 @@

@@ -49,3 +49,3 @@ 'use strict';

knex(knex) {
knex() {
if (arguments.length === 0) {

@@ -62,3 +62,3 @@ const knex = this._context.knex || this._knex;

} else {
this._knex = knex;
this._knex = arguments[0];
return this;

@@ -115,5 +115,5 @@ }

if (operationSelector instanceof RegExp) {
forEachOperationRegex(this, operationSelector, callback, match);
forEachOperationRegex(this._operations, operationSelector, callback, match);
} else {
forEachOperationInstanceOf(this, operationSelector, callback, match);
forEachOperationInstanceOf(this._operations, operationSelector, callback, match);
}

@@ -232,5 +232,5 @@

function forEachOperationRegex(builder, operationSelector, callback, match) {
for (let i = 0, l = builder._operations.length; i < l; ++i) {
const op = builder._operations[i];
function forEachOperationRegex(operations, operationSelector, callback, match) {
for (let i = 0, l = operations.length; i < l; ++i) {
const op = operations[i];

@@ -245,5 +245,5 @@ if (operationSelector.test(op.name) === match) {

function forEachOperationInstanceOf(builder, operationSelector, callback, match) {
for (let i = 0, l = builder._operations.length; i < l; ++i) {
const op = builder._operations[i];
function forEachOperationInstanceOf(operations, operationSelector, callback, match) {
for (let i = 0, l = operations.length; i < l; ++i) {
const op = operations[i];

@@ -250,0 +250,0 @@ if ((op instanceof operationSelector) === match) {

@@ -35,3 +35,3 @@ 'use strict';

return expr;
} else if (!_.isString(expr) || _.isEmpty(expr.trim())) {
} else if (typeof expr !== 'string' || expr.trim().length === 0) {
return new RelationExpression();

@@ -53,5 +53,5 @@ } else {

return new RelationExpression();
} else {
return new RelationExpression(modelGraphToNode(graph, newNode()));
}
return new RelationExpression(modelGraphToNode(graph, newNode()));
}

@@ -116,2 +116,4 @@

expr = RelationExpression.parse(expr);
// Need to defined these here to prevent an optimization bailout.
let maxRecursionDepth, childNames;

@@ -130,3 +132,3 @@ if (this.isAllRecursive()) {

const maxRecursionDepth = expr.maxRecursionDepth();
maxRecursionDepth = expr.maxRecursionDepth();

@@ -137,6 +139,8 @@ if (maxRecursionDepth > 0) {

return _.every(expr.children, (child, childName) => {
var ownSubExpression = this.childExpression(childName);
var subExpression = expr.childExpression(childName);
childNames = Object.keys(expr.children);
return childNames.every(childName => {
const ownSubExpression = this.childExpression(childName);
const subExpression = expr.childExpression(childName);
return ownSubExpression && ownSubExpression.isSubExpression(subExpression);

@@ -203,4 +207,4 @@ });

addAnonymousFilterAtPath(path, filter) {
let filterNodes = this._nodesAtPath(path);
let filters = this.filters;
const filterNodes = this.rawNodesAtPath(path);
const filters = this.filters;

@@ -214,33 +218,18 @@ let idx = 0;

if (!_.isEmpty(filterNodes)) {
if (filterNodes.length !== 0) {
filters[filterName] = filter;
_.each(filterNodes, node => node.args.push(filterName));
for (let i = 0, l = filterNodes.length; i < l; ++i) {
filterNodes[i].args.push(filterName);
}
}
}
rawNodesAtPath(path) {
return findNodesAtPath(this, RelationExpression.parse(path), []);
}
toString() {
return toString(this);
}
_nodesAtPath(pathExpression) {
let path = RelationExpression.parse(pathExpression);
let nodes = [];
RelationExpression.nodesAtPath(this, path, nodes);
return nodes;
}
static nodesAtPath(target, path, expressions) {
if (path.numChildren == 0) {
expressions.push(target);
} else {
_.forOwn(path.children, child => {
const targetChild = target.children[child.name];
if (targetChild) {
this.nodesAtPath(targetChild, child, expressions);
}
});
}
}
}

@@ -279,5 +268,5 @@

function toString(node) {
let childExpr = _.values(node.children).map(toString);
let str = node.name;

@@ -290,4 +279,2 @@ if (childExpr.length > 1) {

let str = node.name;
if (node.args.length) {

@@ -355,2 +342,23 @@ str += `(${node.args.join(', ')})`;

function findNodesAtPath(target, path, results) {
if (path.numChildren == 0) {
// Path leaf reached, add target node to result set.
results.push(target);
} else {
const childNames = Object.keys(path.children);
for (let i = 0, l = childNames.length; i < l; ++i) {
const childName = childNames[i];
const child = path.children[childName];
const targetChild = target.children[childName];
if (targetChild) {
findNodesAtPath(targetChild, child, results);
}
}
}
return results;
}
module.exports = RelationExpression;
{
"name": "objection",
"version": "0.8.0-rc.1",
"version": "0.8.0-rc.2",
"description": "An SQL-friendly ORM for Node.js",

@@ -5,0 +5,0 @@ "main": "lib/objection.js",

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