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.1 to 0.8.2

lib/queryBuilder/operations/DeleteByIdOperation.js

62

lib/model/Model.js

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

static get objectionModelClass() {
return Model;
}
static fromJson(json, options) {

@@ -535,12 +539,2 @@ const model = new this();

static getFullIdColumn() {
// Memoize getFullIdColumn but only for this class. The hasOwnProperty check
// will fail for subclasses and the value gets recreated.
if (!this.hasOwnProperty('$$fullIdColumn')) {
defineNonEnumerableProperty(this, '$$fullIdColumn', getFullIdColumn(this));
}
return this.$$fullIdColumn;
}
static getIdPropertyArray() {

@@ -635,6 +629,2 @@ // Memoize getIdPropertyArray but only for this class. The hasOwnProperty check

static uniqueTag() {
return this.tableName;
}
static bindKnex(knex) {

@@ -648,3 +638,3 @@ const ModelClass = this;

defineNonEnumerableProperty(knex, '$$objection', {
boundModels: Object.create(null)
boundModels: new Map()
});

@@ -654,4 +644,4 @@ }

// Check if this model class has already been bound to the given knex.
if (knex.$$objection.boundModels[ModelClass.uniqueTag()]) {
return knex.$$objection.boundModels[ModelClass.uniqueTag()];
if (knex.$$objection.boundModels.has(ModelClass)) {
return knex.$$objection.boundModels.get(ModelClass);
}

@@ -671,3 +661,3 @@

BoundModelClass.knex(knex);
knex.$$objection.boundModels[ModelClass.uniqueTag()] = BoundModelClass;
knex.$$objection.boundModels.set(ModelClass, BoundModelClass);

@@ -732,3 +722,3 @@ relations = ModelClass.getRelationArray();

if (!relation) {
throw new Error(`A model class (tableName = ${this.tableName}) doesn't have relation ${name}`);
throw new Error(`A model class ${this.name} doesn't have relation ${name}`);
}

@@ -845,2 +835,3 @@

Model.defaultEagerOptions = null;
Model.namedFilters = null;

@@ -898,10 +889,2 @@ function setId(model, id) {

function getFullIdColumn(ModelClass) {
if (Array.isArray(ModelClass.idColumn)) {
return ModelClass.idColumn.map(col => `${ModelClass.tableName}.${col}`);
} else {
return `${ModelClass.tableName}.${ModelClass.idColumn}`;
}
}
function getIdPropertyArray(ModelClass) {

@@ -1211,2 +1194,3 @@ return ModelClass.getIdColumnArray().map(col => idColumnToIdProperty(ModelClass, col));

}
return false;

@@ -1241,10 +1225,10 @@ }

function columnNameToPropertyName(ModelClass, columnName) {
let model = new ModelClass();
let addedProps = Object.keys(model.$parseDatabaseJson({}));
const model = new ModelClass();
const addedProps = Object.keys(model.$parseDatabaseJson({}));
let row = {};
const row = {};
row[columnName] = null;
let props = Object.keys(model.$parseDatabaseJson(row));
let propertyName = difference(props, addedProps)[0];
const props = Object.keys(model.$parseDatabaseJson(row));
const propertyName = difference(props, addedProps)[0];

@@ -1255,10 +1239,10 @@ return propertyName || null;

function propertyNameToColumnName(ModelClass, propertyName) {
let model = new ModelClass();
let addedCols = Object.keys(model.$formatDatabaseJson({}));
const model = new ModelClass();
const addedCols = Object.keys(model.$formatDatabaseJson({}));
let obj = {};
const obj = {};
obj[propertyName] = null;
let cols = Object.keys(model.$formatDatabaseJson(obj));
let columnName = difference(cols, addedCols)[0];
const cols = Object.keys(model.$formatDatabaseJson(obj));
const columnName = difference(cols, addedCols)[0];

@@ -1269,6 +1253,6 @@ return columnName || null;

function idColumnToIdProperty(ModelClass, idColumn) {
let idProperty = ModelClass.columnNameToPropertyName(idColumn);
const idProperty = ModelClass.columnNameToPropertyName(idColumn);
if (!idProperty) {
throw new Error(ModelClass.tableName + '.$parseDatabaseJson probably changes the value of the id column `' + idColumn + '` which is a no-no.');
throw new Error(ModelClass.name + '.$parseDatabaseJson probably changes the value of the id column `' + idColumn + '` which is a no-no.');
}

@@ -1275,0 +1259,0 @@

@@ -9,3 +9,2 @@ 'use strict';

super(node);
this.relation = relation;

@@ -12,0 +11,0 @@ }

@@ -65,24 +65,27 @@ 'use strict';

if (rel instanceof HasManyRelation) {
if (rel) {
if (rel instanceof HasManyRelation) {
node.needs.push(new HasManyDependency(parentNode, rel));
parentNode.isNeededBy.push(new HasManyDependency(node, rel));
node.needs.push(new HasManyDependency(parentNode, rel));
parentNode.isNeededBy.push(new HasManyDependency(node, rel));
} else if (rel instanceof BelongsToOneRelation) {
} else if (rel instanceof BelongsToOneRelation) {
node.isNeededBy.push(new BelongsToOneDependency(parentNode, rel));
parentNode.needs.push(new BelongsToOneDependency(node, rel));
node.isNeededBy.push(new BelongsToOneDependency(parentNode, rel));
parentNode.needs.push(new BelongsToOneDependency(node, rel));
} else if (rel instanceof ManyToManyRelation) {
} else if (rel instanceof ManyToManyRelation) {
// ManyToManyRelations create no dependencies since we can create the
// join table rows after everything else has been inserted.
parentNode.manyToManyConnections.push(new ManyToManyConnection(node, rel));
// ManyToManyRelations create no dependencies since we can create the
// join table rows after everything else has been inserted.
parentNode.manyToManyConnections.push(new ManyToManyConnection(node, rel));
}
}
this.buildForRelations(modelClass, model, node, allowedRelations);
this.buildForRelations(modelClass, node, allowedRelations);
}
buildForRelations(modelClass, model, node, allowedRelations) {
buildForRelations(modelClass, node, allowedRelations) {
const model = node.model;
const relations = modelClass.getRelationArray();

@@ -92,4 +95,3 @@

const rel = relations[i];
const relName = rel.name;
const relModels = model[relName];
const relModels = model[rel.name];

@@ -99,3 +101,3 @@ let nextAllowed = null;

if (relModels && allowedRelations instanceof RelationExpression) {
nextAllowed = allowedRelations.childExpression(relName);
nextAllowed = allowedRelations.childExpression(rel.name);

@@ -134,3 +136,3 @@ if (!nextAllowed) {

solveReferences() {
let refMap = Object.create(null);
const refMap = Object.create(null);

@@ -146,3 +148,3 @@ // First merge all reference nodes into the actual node.

for (let n = 0, ln = this.nodes.length; n < ln; ++n) {
let refNode = this.nodes[n];
const refNode = this.nodes[n];
let ref;

@@ -157,3 +159,3 @@

if (ref) {
let actualNode = this.nodesById[ref];
const actualNode = this.nodesById[ref];
let d, ld;

@@ -185,3 +187,3 @@

for (let n = 0, ln = this.nodes.length; n < ln; ++n) {
let node = this.nodes[n];
const node = this.nodes[n];
let d, ld, dep, actualNode;

@@ -208,3 +210,3 @@

for (let m = 0, lm = node.manyToManyConnections.length; m < lm; ++m) {
let conn = node.manyToManyConnections[m];
const conn = node.manyToManyConnections[m];
actualNode = refMap[conn.node.id];

@@ -222,3 +224,3 @@

for (let n = 0, ln = this.nodes.length; n < ln; ++n) {
let node = this.nodes[n];
const node = this.nodes[n];

@@ -250,6 +252,6 @@ if (!node.handled) {

allMatches(propRefRegex, value, matchResult => {
let match = matchResult[0];
let refId = matchResult[1];
let refProp = matchResult[2];
let refNode = this.nodesById[refId];
const match = matchResult[0];
const refId = matchResult[1];
const refProp = matchResult[2];
const refNode = this.nodesById[refId];

@@ -256,0 +258,0 @@ if (!refNode) {

@@ -19,4 +19,16 @@ 'use strict';

get hasUnresolvedDependencies() {
return this.numHandledNeeds < this.needs.length;
}
markAsHandled() {
for (let nb = 0, lnb = this.isNeededBy.length; nb < lnb; ++nb) {
const dependency = this.isNeededBy[nb];
dependency.node.numHandledNeeds++;
}
this.handled = true;
}
}
module.exports = DependencyNode;
'use strict';
const _ = require('lodash');
const uniqBy = require('lodash/uniqBy');
const Promise = require('bluebird');

@@ -12,46 +12,50 @@

constructor(args) {
this.allowedRelations = args.allowedRelations || null;
this.modelClass = args.modelClass;
this.models = args.models;
this.allowedRelations = args.allowedRelations || null;
this.done = false;
this.knex = args.knex;
this.graph = this._buildDependencyGraph();
this.knex = args.knex;
}
execute(inserter) {
return this._executeNextBatch(inserter);
return Promise.try(() => {
return this._executeNormalBatches(inserter);
}).then(() => {
return this._executeJoinRowBatch(inserter);
}).then(() => {
return this._finalize();
});
}
_buildDependencyGraph() {
let graph = new DependencyGraph(this.allowedRelations);
const graph = new DependencyGraph(this.allowedRelations);
graph.build(this.modelClass, this.models);
return graph;
}
_executeNormalBatches(inserter) {
return this._executeNextBatch(inserter);
}
_executeNextBatch(inserter) {
let batch = this._nextBatch();
const batch = this._nextBatch();
if (!batch) {
// If we get here, we are done. All we need to do now is to finalize the object graph
// and return it as the final output.
return this._finalize();
// No more normal batches to execute.
return null;
}
// Insert the batch using the `inserter` function.
// Insert the batch one table at a time.
return Promise.all(Object.keys(batch).map(tableName => {
const tableInsertion = batch[tableName];
let uids;
// We need to omit the uid properties so that they don't get inserted
// into the database.
const uids = this._omitUids(tableInsertion);
if (!tableInsertion.isJoinTableInsertion) {
// We need to omit the uid properties so that they don't get inserted
// into the database. Join table insertions never have uids.
uids = this._omitUids(tableInsertion);
}
return inserter(tableInsertion).then(() => {
if (!tableInsertion.isJoinTableInsertion) {
// Resolve dependencies to the inserted objects. Join table insertions
// never resolve any dependencies.
this._resolveDepsForInsertion(tableInsertion, uids);
}
// Resolve dependencies to the inserted objects.
return this._resolveDepsForInsertion(tableInsertion, uids);
});

@@ -64,25 +68,20 @@ })).then(() => {

_nextBatch() {
if (this.done) {
return null;
}
const batch = this._createBatch();
let batch = this._createBatch();
if (_.isEmpty(batch)) {
this.done = true;
return this._createManyToManyRelationJoinRowBatch();
} else {
if (batch) {
this._markBatchHandled(batch);
return batch;
}
return batch;
}
_createBatch() {
let batch = Object.create(null);
let nodes = this.graph.nodes;
const batch = Object.create(null);
const nodes = this.graph.nodes;
let empty = true;
for (let n = 0, ln = nodes.length; n < ln; ++n) {
let node = nodes[n];
const node = nodes[n];
if (!node.handled && node.needs.length === node.numHandledNeeds) {
if (!node.handled && !node.hasUnresolvedDependencies) {
let tableInsertion = batch[node.modelClass.tableName];

@@ -97,38 +96,49 @@

tableInsertion.isInputModel.push(!!this.graph.inputNodesById[node.id]);
empty = false;
}
}
return batch;
if (empty) {
return null;
} else {
return batch;
}
}
_markBatchHandled(batch) {
let models = _.flatten(_.map(batch, 'models'));
let nodes = this.graph.nodesById;
const tableNames = Object.keys(batch);
const nodes = this.graph.nodesById;
for (let m = 0, lm = models.length; m < lm; ++m) {
let id = models[m][models[m].constructor.uidProp];
let node = nodes[id];
for (let t = 0, lt = tableNames.length; t < lt; ++t) {
const tableInsertion = batch[tableNames[t]];
const modelClass = tableInsertion.modelClass;
const models = tableInsertion.models;
for (let nb = 0, lnb = node.isNeededBy.length; nb < lnb; ++nb) {
let dep = node.isNeededBy[nb];
dep.node.numHandledNeeds++;
for (let m = 0, lm = models.length; m < lm; ++m) {
nodes[models[m][modelClass.uidProp]].markAsHandled();
}
node.handled = true;
}
}
_createManyToManyRelationJoinRowBatch() {
let batch = Object.create(null);
let modelNames;
_executeJoinRowBatch(inserter) {
const batch = this._createJoinRowBatch();
// Insert the batch one table at a time.
return Promise.all(Object.keys(batch).map(tableName => {
return inserter(batch[tableName]);
}));
}
_createJoinRowBatch() {
const batch = Object.create(null);
for (let n = 0, ln = this.graph.nodes.length; n < ln; ++n) {
let node = this.graph.nodes[n];
const node = this.graph.nodes[n];
for (let m = 0, lm = node.manyToManyConnections.length; m < lm; ++m) {
let conn = node.manyToManyConnections[m];
const conn = node.manyToManyConnections[m];
let tableInsertion = batch[conn.relation.joinTable];
let ownerProp = node.model.$values(conn.relation.ownerProp);
let modelClass = conn.relation.joinTableModelClass(this.knex);
const ownerProp = node.model.$values(conn.relation.ownerProp);
const modelClass = conn.relation.joinTableModelClass(this.knex);
let joinModel = conn.relation.createJoinModels(ownerProp, [conn.node.model])[0];

@@ -139,5 +149,5 @@

for (let k = 0, lk = conn.relation.joinTableExtras.length; k < lk; ++k) {
let extra = conn.relation.joinTableExtras[k];
const extra = conn.relation.joinTableExtras[k];
if (!_.isUndefined(conn.refNode.model[extra.aliasProp])) {
if (conn.refNode.model[extra.aliasProp] !== undefined) {
joinModel[extra.joinTableProp] = conn.refNode.model[extra.aliasProp];

@@ -160,13 +170,34 @@ }

modelNames = Object.keys(batch);
// Remove duplicates.
for (let i = 0, l = modelNames.length; i < l; ++i) {
const modelName = modelNames[i];
const tableInsertion = batch[modelName];
return this._removeJoinRowDuplicatesFromBatch(batch);
}
_removeJoinRowDuplicatesFromBatch(batch) {
const tableNames = Object.keys(batch);
for (let t = 0, lt = tableNames.length; t < lt; ++t) {
const tableName = tableNames[t];
const tableInsertion = batch[tableName];
if (tableInsertion.models.length) {
const keys = _.uniq(_.flatMap(tableInsertion.models, _.keys));
const models = tableInsertion.models;
const keyHash = Object.create(null);
const keys = [];
tableInsertion.models = _.uniqBy(tableInsertion.models, model => model.$propKey(keys));
tableInsertion.isInputModel = _.times(tableInsertion.models.length, _.constant(false));
for (let m = 0, lm = models.length; m < lm; ++m) {
const model = models[m];
const modelKeys = Object.keys(model);
for (let k = 0, lk = modelKeys.length; k < lk; ++k) {
const key = modelKeys[k];
if (!keyHash[key]) {
keyHash[modelKeys[k]] = true;
keys.push(key);
}
}
}
tableInsertion.models = uniqBy(models, model => model.$propKey(keys));
tableInsertion.isInputModel = new Array(tableInsertion.models.length);
tableInsertion.isInputModel.fill(false);
}

@@ -179,6 +210,11 @@ }

_omitUids(tableInsertion) {
let ids = _.map(tableInsertion.models, tableInsertion.modelClass.uidProp);
const ids = new Array(tableInsertion.models.length);
const modelClass = tableInsertion.modelClass;
const uidProp = modelClass.uidProp;
for (let m = 0, lm = tableInsertion.models.length; m < lm; ++m) {
tableInsertion.models[m].$omit(tableInsertion.modelClass.uidProp);
const model = tableInsertion.models[m];
ids[m] = model[uidProp];
modelClass.omitImpl(model, uidProp);
}

@@ -191,4 +227,4 @@

for (let m = 0, lm = tableInsertion.models.length; m < lm; ++m) {
let node = this.graph.nodesById[uids[m]];
let model = tableInsertion.models[m];
const node = this.graph.nodesById[uids[m]];
const model = tableInsertion.models[m];

@@ -203,4 +239,5 @@ for (let d = 0, ld = node.isNeededBy.length; d < ld; ++d) {

for (let n = 0, ln = this.graph.nodes.length; n < ln; ++n) {
let refNode = this.graph.nodes[n];
let ref = refNode.model[refNode.modelClass.uidRefProp];
const refNode = this.graph.nodes[n];
const modelClass = refNode.modelClass;
const ref = refNode.model[modelClass.uidRefProp];

@@ -217,3 +254,3 @@ if (ref) {

if (!relations[key] && !_.isFunction(value)) {
if (!relations[key] && typeof value !== 'function') {
refNode.model[key] = value;

@@ -223,3 +260,7 @@ }

refNode.model.$omit(refNode.modelClass.uidProp, refNode.modelClass.uidRefProp);
modelClass.omitImpl(refNode.model, modelClass.uidProp);
modelClass.omitImpl(refNode.model, modelClass.uidRefProp);
} else if (refNode.model[modelClass.uidProp]) {
// Make sure the model no longer has an uid.
modelClass.omitImpl(refNode.model, modelClass.uidProp);
}

@@ -226,0 +267,0 @@ }

@@ -12,5 +12,4 @@ 'use strict';

}
}
module.exports = ManyToManyConnection;

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

onBeforeInternal(builder) {
return this.joinBuilder.fetchColumnInfo(builder.knex());
return this.joinBuilder.fetchColumnInfo(builder);
}

@@ -45,0 +45,0 @@

'use strict';
const _ = require('lodash');
const uniq = require('lodash/uniq');
const uniqBy = require('lodash/uniqBy');
const values = require('lodash/values');
const groupBy = require('lodash/groupBy');
const uniqWith = require('lodash/uniqWith');
const Promise = require('bluebird');

@@ -21,7 +25,7 @@

this.opt = _.defaults(args.opt, {
this.opt = Object.assign({
minimize: false,
separator: ':',
aliases: {}
});
}, args.opt);
}

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

*/
fetchColumnInfo(knex) {
fetchColumnInfo(builder) {
const knex = builder.knex();
const columnInfo = RelationJoinBuilder.columnInfo;

@@ -58,3 +63,3 @@ const allModelClasses = findAllModels(this.expression, this.rootModelClass);

return Promise.all(allModelClasses.map(ModelClass => {
const table = ModelClass.tableName;
const table = builder.tableNameFor(ModelClass);

@@ -93,4 +98,6 @@ if (columnInfo[table]) {

const builderClone = builder.clone();
const tableName = builder.tableNameFor(this.rootModelClass);
const tableAlias = builder.tableRefFor(this.rootModelClass);
builder.table(`${this.rootModelClass.tableName} as ${this.rootModelClass.tableName}`);
builder.table(`${tableName} as ${tableAlias}`);

@@ -112,3 +119,3 @@ this.doBuild({

rowsToTree(rows) {
if (_.isEmpty(rows)) {
if (!Array.isArray(rows) || rows.length === 0) {
return rows;

@@ -118,3 +125,3 @@ }

const keyInfoByPath = this.createKeyInfo(rows);
const pathInfo = _.values(this.pathInfo);
const pathInfo = values(this.pathInfo);

@@ -158,3 +165,3 @@ const tree = Object.create(null);

return this.finalize(pathInfo[0], _.values(tree));
return this.finalize(pathInfo[0], values(tree));
}

@@ -189,3 +196,3 @@

return _.groupBy(keyInfo, kInfo => kInfo.pInfo.encPath);
return groupBy(keyInfo, kInfo => kInfo.pInfo.encPath);
}

@@ -339,4 +346,5 @@

const idCols = modelClass.getIdColumnArray();
const rootTable = this.rootModelClass.tableName;
const columns = RelationJoinBuilder.columnInfo[modelClass.tableName].columns;
const rootTable = builder.tableRefFor(this.rootModelClass);
const table = builder.tableNameFor(modelClass);
const columns = RelationJoinBuilder.columnInfo[table].columns;

@@ -477,3 +485,3 @@ for (let i = 0, l = columns.length; i < l; ++i) {

return _.uniqBy(models, 'tableName');
return uniqBy(models, 'tableName');
}

@@ -494,3 +502,3 @@

return _.uniqWith(relations, (lhs, rhs) => lhs === rhs);
return uniqWith(relations, (lhs, rhs) => lhs === rhs);
}

@@ -596,2 +604,3 @@

const relation = args.relation;
const modelNamedFilters = relation.relatedModelClass.namedFilters || {};
const filterQuery = relation.relatedModelClass

@@ -603,3 +612,3 @@ .query()

const filterName = expr.args[i];
const filter = expr.filters[filterName];
const filter = expr.filters[filterName] || modelNamedFilters[filterName];

@@ -638,7 +647,7 @@ if (typeof filter !== 'function') {

allRelations.forEach(rel => {
if (rel.relatedModelClass.tableName === modelClass.tableName) {
if (rel.relatedModelClass === modelClass) {
rel.relatedCol.forEach(col => foreignKeys.push(col));
}
if (rel.ownerModelClass.tableName === modelClass.tableName) {
if (rel.ownerModelClass === modelClass) {
rel.ownerCol.forEach(col => foreignKeys.push(col));

@@ -648,3 +657,3 @@ }

return _.uniq(foreignKeys);
return uniq(foreignKeys);
}

@@ -700,3 +709,3 @@

finalizeBranch(branch, parentModel) {
const relModels = _.values(branch);
const relModels = values(branch);
parentModel[this.relation.name] = relModels;

@@ -703,0 +712,0 @@ return relModels;

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

const relation = this.relationsToFetch[i].relation;
const cols = relation.fullOwnerCol;
const cols = relation.fullOwnerCol(builder);

@@ -153,2 +153,3 @@ for (let c = 0, lc = cols.length; c < lc; ++c) {

const findOperation = relation.find(queryBuilder, models);
const modelNamedFilters = relation.relatedModelClass.namedFilters || {};

@@ -160,3 +161,3 @@ findOperation.alwaysReturnArray = true;

const filterName = childExpression.args[i];
const filter = childExpression.filters[filterName];
const filter = childExpression.filters[filterName] || modelNamedFilters[filterName];

@@ -163,0 +164,0 @@ if (typeof filter !== 'function') {

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

.childQueryOf(builder)
.whereInComposite(builder.modelClass().getFullIdColumn(), insertedModelArray.map(model => model.$id()))
.whereInComposite(builder.fullIdColumnFor(builder.modelClass()), insertedModelArray.map(model => model.$id()))
.then(fetchedModels => {

@@ -31,0 +31,0 @@ fetchedModels = keyBy(fetchedModels, model => model.$propKey(idProps));

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

.childQueryOf(builder)
.whereIn(modelClass.getFullIdColumn(), ids)
.whereIn(builder.fullIdColumnFor(modelClass), ids)
.eager(eager)

@@ -40,0 +40,0 @@ .then(models => {

'use strict';
const QueryBuilderOperation = require('./QueryBuilderOperation');
const fromJson = require('../../model/modelFactory').fromJson;
const mapAfterAllReturn = require('../../utils/promiseUtils').mapAfterAllReturn;
const toDatabaseJson = require('../../model/modelFactory').toDatabaseJson;
const mapAfterAllReturn = require('../../utils/promiseUtils').mapAfterAllReturn;
const isPostgres = require('../../utils/knexUtils').isPostgres;
const fromJson = require('../../model/modelFactory').fromJson;

@@ -9,0 +9,0 @@ class InsertOperation extends QueryBuilderOperation {

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

super.onBeforeBuild(builder);
builder.whereComposite(builder.modelClass().getFullIdColumn(), this.instance.$id());
builder.whereComposite(builder.fullIdColumnFor(builder.modelClass()), this.instance.$id());
}

@@ -23,0 +23,0 @@

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

onBeforeBuild(builder) {
builder.whereComposite(builder.modelClass().getFullIdColumn(), this.instance.$id()).first()
builder.whereComposite(builder.fullIdColumnFor(builder.modelClass()), this.instance.$id()).first()
}

@@ -16,0 +16,0 @@ }

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

super.onBeforeBuild(builder);
builder.whereComposite(builder.modelClass().getFullIdColumn(), this.instance.$id());
builder.whereComposite(builder.fullIdColumnFor(builder.modelClass()), this.instance.$id());
}

@@ -30,0 +30,0 @@

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

if (opt.alias === false) {
alias = relation.relatedModelClass.tableName;
alias = builder.tableRefFor(relation.relatedModelClass);
} else if (opt.alias === true || !opt.alias) {

@@ -45,0 +45,0 @@ alias = relation.name;

'use strict';
const _ = require('lodash');
const jsonFieldExpressionParser = require('../../parsers/jsonFieldExpressionParser');

@@ -47,3 +46,3 @@

let parsed = jsonFieldExpressionParser.parse(expression);
let jsonRefs = _(parsed.access).map('ref').value().join(",");
let jsonRefs = parsed.access.map(it => it.ref).join(",");
let extractor = extractAsText ? '#>>' : '#>';

@@ -62,3 +61,3 @@ let middleQuotedColumnName = parsed.columnName.split('.').join('"."');

if (_.isString(jsonObjectOrFieldExpression)) {
if (typeof jsonObjectOrFieldExpression === 'string') {
let rightHandReference = parseFieldExpression(jsonObjectOrFieldExpression);

@@ -70,3 +69,3 @@ let refRefQuery = ["(", fieldReference, ")::jsonb", operator, "(", rightHandReference, ")::jsonb"];

return [refRefQuery.join(" ")];
} else if (_.isObject(jsonObjectOrFieldExpression)) {
} else if (jsonObjectOrFieldExpression && typeof jsonObjectOrFieldExpression === 'object') {
let refValQuery = ["(", fieldReference, ")::jsonb", operator, "?::jsonb"];

@@ -85,6 +84,6 @@ if (queryPrefix) {

let fieldReference = parseFieldExpression(fieldExpression);
keys = _.isArray(keys) ? keys : [keys];
keys = Array.isArray(keys) ? keys : [keys];
let questionMarksArray = _.map(keys, function (key) {
if (!_.isString(key)) {
let questionMarksArray = keys.map(key => {
if (typeof key !== 'string') {
throw new Error("All keys to find must be strings.");

@@ -108,9 +107,11 @@ }

let escapedValue = knex.raw(" ?", [value]);
if (_.isNumber(value)) {
let type = typeof value;
if (type === 'number') {
cast = "::NUMERIC";
} else if (_.isBoolean(value)) {
} else if (type === 'boolean') {
cast = "::BOOLEAN";
} else if (_.isString(value)) {
} else if (type === 'string') {
cast = "::TEXT";
} else if (_.isNull(value)) {
} else if (value === null) {
cast = "::TEXT";

@@ -117,0 +118,0 @@ escapedValue = 'NULL';

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

super.onBeforeBuild(builder);
builder.whereComposite(builder.modelClass().getFullIdColumn(), this.id);
builder.whereComposite(builder.fullIdColumnFor(builder.modelClass()), this.id);
}

@@ -43,3 +43,3 @@

.childQueryOf(builder)
.whereComposite(builder.modelClass().getFullIdColumn(), this.id)
.whereComposite(builder.fullIdColumnFor(builder.modelClass()), this.id)
.first()

@@ -46,0 +46,0 @@ .then(fetched => {

@@ -21,4 +21,6 @@ 'use strict';

const InsertGraphOperation = require('./operations/InsertGraphOperation');
const DeleteByIdOperation = require('./operations/DeleteByIdOperation');
const RunBeforeOperation = require('./operations/RunBeforeOperation');
const RunAfterOperation = require('./operations/RunAfterOperation');
const FindByIdOperation = require('./operations/FindByIdOperation');
const OnBuildOperation = require('./operations/OnBuildOperation');

@@ -28,2 +30,3 @@ const SelectOperation = require('./operations/SelectOperation');

const RangeOperation = require('./operations/RangeOperation');
const FromOperation = require('./operations/FromOperation');

@@ -65,2 +68,42 @@ class QueryBuilder extends QueryBuilderBase {

tableRefFor(modelClass) {
const ctx = this.internalContext();
const aliasMap = ctx.aliasMap;
return (aliasMap && aliasMap[modelClass.tableName]) || this.tableNameFor(modelClass);
}
tableNameFor(modelClass) {
const ctx = this.internalContext();
const tableMap = ctx.tableMap;
return (tableMap && tableMap[modelClass.tableName]) || modelClass.tableName;
}
alias(alias) {
const ctx = this.internalContext();
ctx.aliasMap = ctx.aliasMap || Object.create(null);
ctx.aliasMap[this._modelClass.tableName] = alias;
return this;
}
fullIdColumnFor(modelClass) {
const tableName = this.tableRefFor(modelClass);
const idColumn = modelClass.idColumn;
if (Array.isArray(idColumn)) {
const id = new Array(idColumn.length);
for (let i = 0, l = idColumn.length; i < l; ++i) {
id[i] = `${tableName}.${idColumn[i]}`;
}
return id;
} else {
return `${tableName}.${idColumn}`;
}
}
childQueryOf(query) {

@@ -243,2 +286,6 @@ if (query) {

isEagerQuery() {
return !!this._eagerExpression;
}
toString() {

@@ -357,3 +404,3 @@ return this.build().toString();

if (builder._eagerExpression) {
if (builder.isEagerQuery()) {
callEagerFetchOperation(builder);

@@ -389,3 +436,3 @@ }

if (builder._eagerExpression) {
if (builder.isEagerQuery()) {
callEagerFetchOperation(builder);

@@ -466,3 +513,3 @@ }

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

@@ -540,6 +587,2 @@

findById(id) {
return this.whereComposite(this._modelClass.getFullIdColumn(), id).first();
}
withSchema(schema) {

@@ -668,6 +711,2 @@ this.internalContext().onBuild.push(builder => {

deleteById(id) {
return this.delete().whereComposite(this._modelClass.getFullIdColumn(), id);
}
relate(ids) {

@@ -708,2 +747,4 @@ const relateOperation = this._relateOperationFactory(this);

fullOuterJoinRelation(relationName) {}
deleteById(id) {}
findById(id) {}
runBefore(runBefore) {}

@@ -770,2 +811,11 @@ onBuild(onBuild) {}

properties: ['runAfter']
}, {
decorator: queryBuilderOperation(FindByIdOperation),
properties: ['findById']
}, {
decorator: queryBuilderOperation(DeleteByIdOperation),
properties: ['deleteById']
}, {
decorator: queryBuilderOperation(FromOperation),
properties: ['from', 'table']
}]);

@@ -884,13 +934,25 @@

if (!builder.has(QueryBuilderBase.FromSelector)) {
const table = builder.modelClass().tableName;
const fromOperation = builder.findLastOperation(QueryBuilderBase.FromSelector);
const hasSelects = builder.has(QueryBuilderBase.SelectSelector);
if (!fromOperation) {
const table = builder.tableNameFor(builder.modelClass());
const tableRef = builder.tableRefFor(builder.modelClass());
// Set the table only if it hasn't been explicitly set yet.
knexBuilder.table(table);
if (!builder.has(QueryBuilderBase.SelectSelector)) {
knexBuilder.select(`${table}.*`);
if (table === tableRef) {
knexBuilder.table(table);
} else {
knexBuilder.table(`${table} as ${tableRef}`);
}
}
if (!hasSelects && (!fromOperation || fromOperation.table)) {
const tableRef = builder.tableRefFor(builder.modelClass());
// Only add `table.*` select if there are no explicit selects
// and `from` is a table name and not a subquery.
knexBuilder.select(`${tableRef}.*`);
}
return knexBuilder;

@@ -897,0 +959,0 @@ }

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

this.onBuild = [];
this.aliasMap = null;
this.tableMap = null;
}

@@ -23,2 +26,5 @@

ctx.aliasMap = this.aliasMap;
ctx.tableMap = this.tableMap;
return ctx;

@@ -25,0 +31,0 @@ }

@@ -109,2 +109,22 @@ 'use strict';

indexOfLastOperation(operationSelector) {
let idx = -1;
this.forEachOperation(operationSelector, (op, i) => {
idx = i;
});
return idx;
}
findLastOperation(operationSelector) {
const idx = this.indexOfLastOperation(operationSelector);
if (idx !== -1) {
return this._operations[idx];
} else {
return null;
}
}
forEachOperation(operationSelector, callback, match) {

@@ -111,0 +131,0 @@ match = (match == null) ? true : match;

'use strict';
const _ = require('lodash');
const merge = require('lodash/merge');
const clone = require('lodash/clone');
const values = require('lodash/values');
const cloneDeep = require('lodash/cloneDeep');
const parser = require('./parsers/relationExpressionParser');

@@ -62,5 +65,5 @@

merged.numChildren += expr.numChildren;
merged.children = _.merge(merged.children, expr.children);
merged.args = _.merge(merged.args, expr.args);
merged.filters = _.merge(merged.filters, expr.filters);
merged.children = merge(merged.children, expr.children);
merged.args = merge(merged.args, expr.args);
merged.filters = merge(merged.filters, expr.filters);

@@ -173,6 +176,6 @@ // Handle recursive and all recursive nodes.

numChildren: this.numChildren,
children: _.cloneDeep(this.children)
children: cloneDeep(this.children)
};
const filters = _.clone(this._filters);
const filters = clone(this._filters);
return new RelationExpression(node, this._recursionDepth, filters);

@@ -256,3 +259,3 @@ }

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

@@ -259,0 +262,0 @@

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

.patch(patch)
.whereComposite(this.relation.ownerModelClass.getFullIdColumn(), this.owner.$id())
.whereComposite(builder.fullIdColumnFor(this.relation.ownerModelClass), this.owner.$id())
.return(inserted);

@@ -48,0 +48,0 @@ });

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

.patch(patch)
.whereComposite(this.relation.ownerModelClass.getFullIdColumn(), this.owner.$id());
.whereComposite(builder.fullIdColumnFor(this.relation.ownerModelClass), this.owner.$id());
}

@@ -47,0 +47,0 @@ }

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

.copyFrom(builder, /where/i)
.whereInComposite(this.relation.relatedModelClass.getFullIdColumn(), this.ids)
.whereInComposite(builder.fullIdColumnFor(this.relation.relatedModelClass), this.ids)
.modify(this.relation.modify);

@@ -42,0 +42,0 @@ }

'use strict';
const Relation = require('../Relation');
const HasManyInsertOperation = require('./HasManyInsertOperation');

@@ -6,0 +5,0 @@ const HasManyRelateOperation = require('./HasManyRelateOperation');

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

.copyFrom(builder, /where/i)
.whereComposite(this.relation.fullRelatedCol, this.owner.$values(this.relation.ownerProp))
.whereComposite(this.relation.fullRelatedCol(builder), this.owner.$values(this.relation.ownerProp))
.modify(this.relation.modify);

@@ -31,0 +31,0 @@ }

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

const RelationFindOperation = require('../RelationFindOperation');
const OWNER_JOIN_COLUMN_ALIAS_PREFIX = 'objectiontmpjoin';
const ownerJoinColumnAliasPrefix = 'objectiontmpjoin';
class ManyToManyFindOperation extends RelationFindOperation {

@@ -17,3 +16,3 @@

for (let i = 0, l = this.relation.joinTableOwnerCol.length; i < l; ++i) {
this.ownerJoinColumnAlias[i] = ownerJoinColumnAliasPrefix + i;
this.ownerJoinColumnAlias[i] = OWNER_JOIN_COLUMN_ALIAS_PREFIX + i;
}

@@ -39,5 +38,7 @@ }

if (!builder.has(builder.constructor.SelectSelector)) {
const table = builder.tableRefFor(relatedModelClass);
// If the user hasn't specified a select clause, select the related model's columns.
// If we don't do this we also get the join table's columns.
builder.select(relatedModelClass.tableName + '.*');
builder.select(`${table}.*`);

@@ -57,7 +58,7 @@ // Also select all extra columns.

const fullJoinTableOwnerCol = this.relation.fullJoinTableOwnerCol;
const fullJoinTableOwnerCol = this.relation.fullJoinTableOwnerCol(builder);
// We must select the owner join columns so that we know for which owner model the related
// models belong to after the requests.
for (let i = 0, l = fullJoinTableOwnerCol.length; i < l; ++i) {
builder.select(fullJoinTableOwnerCol[i] + ' as ' + this.ownerJoinColumnAlias[i]);
builder.select(`${fullJoinTableOwnerCol[i]} as ${this.ownerJoinColumnAlias[i]}`);

@@ -64,0 +65,0 @@ // Mark them to be omitted later.

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

const inheritModel = require('../../model/inheritModel');
const resolveModel = require('../../utils/resolveModel').resolveModel
const isSqlite = require('../../utils/knexUtils').isSqlite;
const getModel = () => require('../../model/Model');

@@ -18,3 +20,3 @@ const ManyToManyFindOperation = require('./ManyToManyFindOperation');

const sqliteBuiltInRowId = '_rowid_';
const SQLITE_BUILTIN_ROW_ID = '_rowid_';

@@ -25,12 +27,10 @@ class ManyToManyRelation extends Relation {

let retVal = super.setMapping(mapping);
let Model = getModel();
// Avoid require loop and import here.
let Model = require(__dirname + '/../../model/Model');
if (!mapping.join.through || typeof mapping.join.through !== 'object') {
this.throwError('join must have the `through` that describes the join table.');
throw this.createError('join must have a `through` object that describes the join table.');
}
if (!mapping.join.through.from || !mapping.join.through.to) {
this.throwError('join.through must be an object that describes the join table. For example: {from: "JoinTable.someId", to: "JoinTable.someOtherId"}');
throw this.createError('join.through must be an object that describes the join table. For example: {from: "JoinTable.someId", to: "JoinTable.someOtherId"}');
}

@@ -44,11 +44,11 @@

if (!joinTableFrom.table || !joinTableFrom.columns.length) {
this.throwError('join.through.from must have format JoinTable.columnName. For example "JoinTable.someId" or in case of composite key ["JoinTable.a", "JoinTable.b"].');
throw this.createError('join.through.from must have format JoinTable.columnName. For example "JoinTable.someId" or in case of composite key ["JoinTable.a", "JoinTable.b"].');
}
if (!joinTableTo.table || !joinTableTo.columns.length) {
this.throwError('join.through.to must have format JoinTable.columnName. For example "JoinTable.someId" or in case of composite key ["JoinTable.a", "JoinTable.b"].');
throw this.createError('join.through.to must have format JoinTable.columnName. For example "JoinTable.someId" or in case of composite key ["JoinTable.a", "JoinTable.b"].');
}
if (joinTableFrom.table !== joinTableTo.table) {
this.throwError('join.through `from` and `to` must point to the same join table.');
throw this.createError('join.through `from` and `to` must point to the same join table.');
}

@@ -67,3 +67,7 @@

if (mapping.join.through.modelClass) {
this._joinTableModelClass = this.resolveModel(Model, mapping.join.through.modelClass, 'join.through.modelClass');
try {
this._joinTableModelClass = resolveModel(mapping.join.through.modelClass, this.ownerModelClass.modelPaths, 'join.through.modelClass');
} catch (err) {
throw this.createError(err.message);
}
} else {

@@ -81,12 +85,32 @@ this._joinTableModelClass = inheritModel(Model);

this.fullJoinTableOwnerCol = this.joinTableOwnerCol.map(col => `${this.joinTable}.${col}`);
this.fullJoinTableRelatedCol = this.joinTableRelatedCol.map(col => `${this.joinTable}.${col}`);
return retVal;
}
joinTableAlias() {
return this.joinTable + '_rel_' + this.name;
joinTableAlias(builder) {
const table = builder.tableRefFor(this._joinTableModelClass);
return `${table}_rel_${this.name}`;
}
fullJoinTableRelatedCol(builder) {
const table = builder.tableRefFor(this._joinTableModelClass);
const col = new Array(this.joinTableRelatedCol.length);
for (let i = 0, l = col.length; i < l; ++i) {
col[i] = `${table}.${this.joinTableRelatedCol[i]}`;
}
return col;
}
fullJoinTableOwnerCol(builder) {
const table = builder.tableRefFor(this._joinTableModelClass);
const col = new Array(this.joinTableOwnerCol.length);
for (let i = 0, l = col.length; i < l; ++i) {
col[i] = `${table}.${this.joinTableOwnerCol[i]}`;
}
return col;
}
bindKnex(knex) {

@@ -100,4 +124,4 @@ let bound = super.bindKnex(knex);

builder.join(this.joinTable, join => {
const fullRelatedCol = this.fullRelatedCol;
const fullJoinTableRelatedCol = this.fullJoinTableRelatedCol;
const fullRelatedCol = this.fullRelatedCol(builder);
const fullJoinTableRelatedCol = this.fullJoinTableRelatedCol(builder);

@@ -110,3 +134,3 @@ for (let i = 0, l = fullJoinTableRelatedCol.length; i < l; ++i) {

if (opt.isColumnRef) {
const fullJoinTableOwnerCol = this.fullJoinTableOwnerCol;
const fullJoinTableOwnerCol = this.fullJoinTableOwnerCol(builder);

@@ -129,3 +153,3 @@ for (let i = 0, l = fullJoinTableOwnerCol.length; i < l; ++i) {

if (hasIds) {
builder.whereInComposite(this.fullJoinTableOwnerCol, opt.ownerIds);
builder.whereInComposite(this.fullJoinTableOwnerCol(builder), opt.ownerIds);
} else {

@@ -143,15 +167,9 @@ builder.resolve([]);

opt.joinOperation = opt.joinOperation || 'join';
opt.relatedTableAlias = opt.relatedTableAlias || this.relatedTableAlias;
opt.relatedTableAlias = opt.relatedTableAlias || this.relatedTableAlias(builder);
opt.relatedJoinSelectQuery = opt.relatedJoinSelectQuery || this.relatedModelClass.query().childQueryOf(builder);
opt.relatedTable = opt.relatedTable || this.relatedModelClass.tableName;
opt.ownerTable = opt.ownerTable || this.ownerModelClass.tableName;
opt.relatedTable = opt.relatedTable || builder.tableNameFor(this.relatedModelClass);
opt.ownerTable = opt.ownerTable || builder.tableRefFor(this.ownerModelClass);
opt.joinTableAlias = opt.joinTableAlias || `${opt.relatedTableAlias}_join`;
const joinTableAsAlias = `${this.joinTable} as ${opt.joinTableAlias}`;
const joinTableOwnerCol = this.joinTableOwnerCol.map(col => `${opt.joinTableAlias}.${col}`);
const joinTableRelatedCol = this.joinTableRelatedCol.map(col => `${opt.joinTableAlias}.${col}`);
const relatedCol = this.relatedCol.map(col => `${opt.relatedTableAlias}.${col}`);
const ownerCol = this.ownerCol.map(col => `${opt.ownerTable}.${col}`);
let relatedJoinSelect = opt.relatedJoinSelectQuery

@@ -163,3 +181,3 @@ .modify(this.modify)

// No need to join a subquery if the query is `select * from "RelatedTable"`.
relatedJoinSelect = `${this.relatedModelClass.tableName} as ${opt.relatedTableAlias}`
relatedJoinSelect = `${opt.relatedTable} as ${opt.relatedTableAlias}`;
}

@@ -169,9 +187,13 @@

[opt.joinOperation](joinTableAsAlias, join => {
for (let i = 0, l = joinTableOwnerCol.length; i < l; ++i) {
join.on(joinTableOwnerCol[i], ownerCol[i]);
for (let i = 0, l = this.joinTableOwnerCol.length; i < l; ++i) {
const joinTableOwnerCol = `${opt.joinTableAlias}.${this.joinTableOwnerCol[i]}`;
const ownerCol = `${opt.ownerTable}.${this.ownerCol[i]}`;
join.on(joinTableOwnerCol, ownerCol);
}
})
[opt.joinOperation](relatedJoinSelect, join => {
for (let i = 0, l = joinTableRelatedCol.length; i < l; ++i) {
join.on(joinTableRelatedCol[i], relatedCol[i]);
for (let i = 0, l = this.joinTableRelatedCol.length; i < l; ++i) {
const joinTableRelatedCol = `${opt.joinTableAlias}.${this.joinTableRelatedCol[i]}`;
const relatedCol = `${opt.relatedTableAlias}.${this.relatedCol[i]}`;
join.on(joinTableRelatedCol, relatedCol);
}

@@ -266,14 +288,14 @@ });

.childQueryOf(builder)
.select(this.fullJoinTableRelatedCol)
.whereComposite(this.fullJoinTableOwnerCol, ownerId);
.select(this.fullJoinTableRelatedCol(builder))
.whereComposite(this.fullJoinTableOwnerCol(builder), ownerId);
return builder.whereInComposite(this.fullRelatedCol, idQuery);
return builder.whereInComposite(this.fullRelatedCol(builder), idQuery);
}
selectForModifySqlite(builder, owner) {
const relatedTable = this.relatedModelClass.tableName;
const relatedTableAlias = this.relatedTableAlias;
const relatedTableAsAlias = relatedTable + ' as ' + relatedTableAlias;
const relatedTableAliasRowId = relatedTableAlias + '.' + sqliteBuiltInRowId;
const relatedTableRowId = relatedTable + '.' + sqliteBuiltInRowId;
const relatedTable = builder.tableNameFor(this.relatedModelClass);
const relatedTableAlias = this.relatedTableAlias(builder);
const relatedTableAsAlias = `${relatedTable} as ${relatedTableAlias}`;
const relatedTableAliasRowId = `${relatedTableAlias}.${SQLITE_BUILTIN_ROW_ID}`;
const relatedTableRowId = `${relatedTable}.${SQLITE_BUILTIN_ROW_ID}`;

@@ -284,6 +306,6 @@ const selectRelatedQuery = this.joinTableModelClass(builder.knex())

.select(relatedTableAliasRowId)
.whereComposite(this.fullJoinTableOwnerCol, owner.$values(this.ownerProp))
.whereComposite(this.fullJoinTableOwnerCol(builder), owner.$values(this.ownerProp))
.join(relatedTableAsAlias, join => {
const fullJoinTableRelatedCols = this.fullJoinTableRelatedCol;
const fullRelatedCol = this.fullRelatedCol;
const fullJoinTableRelatedCols = this.fullJoinTableRelatedCol(builder);
const fullRelatedCol = this.fullRelatedCol(builder);

@@ -290,0 +312,0 @@ for (let i = 0, l = fullJoinTableRelatedCols.length; i < l; ++i) {

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

.copyFrom(builder, /where/i)
.select(this.relation.fullRelatedCol)
.select(this.relation.fullRelatedCol(builder))
.modify(this.relation.modify);

@@ -28,4 +28,4 @@

.delete()
.whereComposite(this.relation.fullJoinTableOwnerCol, this.owner.$values(this.relation.ownerProp))
.whereInComposite(this.relation.fullJoinTableRelatedCol, selectRelatedColQuery);
.whereComposite(this.relation.fullJoinTableOwnerCol(builder), this.owner.$values(this.relation.ownerProp))
.whereInComposite(this.relation.fullJoinTableRelatedCol(builder), selectRelatedColQuery);
}

@@ -32,0 +32,0 @@ }

'use strict';
const QueryBuilderOperation = require('../../queryBuilder/operations/QueryBuilderOperation');
const sqliteBuiltInRowId = '_rowid_';
const SQLITE_BUILTIN_ROW_ID = '_rowid_';

@@ -17,9 +17,9 @@ class ManyToManyUnrelateSqliteOperation extends QueryBuilderOperation {

queryExecutor(builder) {
let joinTableAlias = this.relation.joinTableAlias();
let joinTableAlias = this.relation.joinTableAlias(builder);
let joinTableAsAlias = this.relation.joinTable + ' as ' + joinTableAlias;
let joinTableAliasRowId = joinTableAlias + '.' + sqliteBuiltInRowId;
let joinTableRowId = this.relation.joinTable + '.' + sqliteBuiltInRowId;
let joinTableAliasRowId = joinTableAlias + '.' + SQLITE_BUILTIN_ROW_ID;
let joinTableRowId = this.relation.joinTable + '.' + SQLITE_BUILTIN_ROW_ID;
let ownerId = this.owner.$values(this.relation.ownerProp);
let fullRelatedCol = this.relation.fullRelatedCol;
let fullRelatedCol = this.relation.fullRelatedCol(builder);

@@ -32,5 +32,5 @@ let selectRelatedQuery = this.relation.relatedModelClass

.modify(this.relation.modify)
.whereComposite(this.relation.fullJoinTableOwnerCol, ownerId)
.whereComposite(this.relation.fullJoinTableOwnerCol(builder), ownerId)
.join(joinTableAsAlias, join => {
const fullJoinTableRelatedCol = this.relation.fullJoinTableRelatedCol;
const fullJoinTableRelatedCol = this.relation.fullJoinTableRelatedCol(builder);

@@ -37,0 +37,0 @@ for (let i = 0, l = fullJoinTableRelatedCol.length; i < l; ++i) {

'use strict';
const _ = require('lodash');
const path = require('path');
const sortBy = require('lodash/sortBy');
const values = require('lodash/values');
const compact = require('lodash/compact');
const isEmpty = require('lodash/isEmpty');
const isSubclassOf = require('../utils/classUtils').isSubclassOf;
const resolveModel = require('../utils/resolveModel').resolveModel
const QueryBuilder = require('../queryBuilder/QueryBuilder');
const getModel = () => require('../model/Model');

@@ -24,5 +29,2 @@ const RelationFindOperation = require('./RelationFindOperation');

this.relatedProp = null;
this.fullRelatedCol = null;
this.fullOwnerCol = null;
this.relatedTableAlias = null;

@@ -35,4 +37,2 @@ this.joinTable = null;

this.joinTableExtras = [];
this.fullJoinTableOwnerCol = null;
this.fullJoinTableRelatedCol = null;

@@ -43,25 +43,28 @@ this.modify = null;

setMapping(mapping) {
// Avoid require loop and import here.
let Model = require(__dirname + '/../model/Model');
const Model = getModel();
if (!isSubclassOf(this.ownerModelClass, Model)) {
this.throwError('Relation\'s owner is not a subclass of Model');
throw this.createError('Relation\'s owner is not a subclass of Model');
}
if (!mapping.modelClass) {
this.throwError('modelClass is not defined');
throw this.createError('modelClass is not defined');
}
this.relatedModelClass = this.resolveModel(Model, mapping.modelClass, 'modelClass');
try {
this.relatedModelClass = resolveModel(mapping.modelClass, this.ownerModelClass.modelPaths, 'modelClass');
} catch (err) {
throw this.createError(err.message);
}
if (!mapping.relation) {
this.throwError('relation is not defined');
throw this.createError('relation is not defined');
}
if (!isSubclassOf(mapping.relation, Relation)) {
this.throwError('relation is not a subclass of Relation');
throw this.createError('relation is not a subclass of Relation');
}
if (!mapping.join || !mapping.join.from || !mapping.join.to) {
this.throwError('join must be an object that maps the columns of the related models together. For example: {from: "SomeTable.id", to: "SomeOtherTable.someModelId"}');
throw this.createError('join must be an object that maps the columns of the related models together. For example: {from: "SomeTable.id", to: "SomeOtherTable.someModelId"}');
}

@@ -75,8 +78,8 @@

if (!joinFrom.table || _.isEmpty(joinFrom.columns)) {
this.throwError('join.from must have format TableName.columnName. For example "SomeTable.id" or in case of composite key ["SomeTable.a", "SomeTable.b"].');
if (!joinFrom.table || isEmpty(joinFrom.columns)) {
throw this.createError('join.from must have format TableName.columnName. For example "SomeTable.id" or in case of composite key ["SomeTable.a", "SomeTable.b"].');
}
if (!joinTo.table || _.isEmpty(joinTo.columns)) {
this.throwError('join.to must have format TableName.columnName. For example "SomeTable.id" or in case of composite key ["SomeTable.a", "SomeTable.b"].');
if (!joinTo.table || isEmpty(joinTo.columns)) {
throw this.createError('join.to must have format TableName.columnName. For example "SomeTable.id" or in case of composite key ["SomeTable.a", "SomeTable.b"].');
}

@@ -91,7 +94,7 @@

} else {
this.throwError('join: either `from` or `to` must point to the owner model table.');
throw this.createError('join: either `from` or `to` must point to the owner model table.');
}
if (joinRelated.table !== this.relatedModelClass.tableName) {
this.throwError('join: either `from` or `to` must point to the related model table.');
throw this.createError('join: either `from` or `to` must point to the related model table.');
}

@@ -104,8 +107,31 @@

this.modify = this.parseModify(mapping);
}
this.fullRelatedCol = this.relatedCol.map(col => this.relatedModelClass.tableName + '.' + col);
this.fullOwnerCol = this.ownerCol.map(col => this.ownerModelClass.tableName + '.' + col);
this.relatedTableAlias = this.relatedModelClass.tableName + '_rel_' + this.name;
fullRelatedCol(builder) {
const table = builder.tableRefFor(this.relatedModelClass);
const col = new Array(this.relatedCol.length);
for (let i = 0, l = col.length; i < l; ++i) {
col[i] = `${table}.${this.relatedCol[i]}`;
}
return col;
}
fullOwnerCol(builder) {
const table = builder.tableRefFor(this.ownerModelClass);
const col = new Array(this.ownerCol.length);
for (let i = 0, l = col.length; i < l; ++i) {
col[i] = `${table}.${this.ownerCol[i]}`;
}
return col;
}
relatedTableAlias(builder) {
const tableRef = builder.tableRefFor(this.relatedModelClass);
return `${tableRef}_rel_${this.name}`;
}
isOneToOne() {

@@ -131,5 +157,2 @@ return false;

relation.relatedProp = this.relatedProp;
relation.fullRelatedCol = this.fullRelatedCol;
relation.fullOwnerCol = this.fullOwnerCol;
relation.relatedTableAlias = this.relatedTableAlias;
relation.modify = this.modify;

@@ -144,4 +167,2 @@

relation.joinTableExtras = this.joinTableExtras;
relation.fullJoinTableOwnerCol = this.fullJoinTableOwnerCol;
relation.fullJoinTableRelatedCol = this.fullJoinTableRelatedCol;

@@ -161,3 +182,3 @@ return relation;

findQuery(builder, opt) {
const fullRelatedCol = this.fullRelatedCol;
const fullRelatedCol = this.fullRelatedCol(builder);

@@ -181,10 +202,7 @@ if (opt.isColumnRef) {

opt.joinOperation = opt.joinOperation || 'join';
opt.relatedTableAlias = opt.relatedTableAlias || this.relatedTableAlias;
opt.relatedTableAlias = opt.relatedTableAlias || this.relatedTableAlias(builder);
opt.relatedJoinSelectQuery = opt.relatedJoinSelectQuery || this.relatedModelClass.query().childQueryOf(builder);
opt.relatedTable = opt.relatedTable || this.relatedModelClass.tableName;
opt.ownerTable = opt.ownerTable || this.ownerModelClass.tableName;
opt.relatedTable = opt.relatedTable || builder.tableNameFor(this.relatedModelClass);
opt.ownerTable = opt.ownerTable || builder.tableRefFor(this.ownerModelClass);
const relatedCol = this.relatedCol.map(col => `${opt.relatedTableAlias}.${col}`);
const ownerCol = this.ownerCol.map(col => `${opt.ownerTable}.${col}`);
let relatedSelect = opt.relatedJoinSelectQuery

@@ -196,3 +214,3 @@ .modify(this.modify)

// No need to join a subquery if the query is `select * from "RelatedTable"`.
relatedSelect = `${this.relatedModelClass.tableName} as ${opt.relatedTableAlias}`
relatedSelect = `${opt.relatedTable} as ${opt.relatedTableAlias}`;
}

@@ -202,4 +220,6 @@

[opt.joinOperation](relatedSelect, join => {
for (let i = 0, l = relatedCol.length; i < l; ++i) {
join.on(relatedCol[i], '=', ownerCol[i]);
for (let i = 0, l = this.relatedCol.length; i < l; ++i) {
const relatedCol = `${opt.relatedTableAlias}.${this.relatedCol[i]}`;
const ownerCol = `${opt.ownerTable}.${this.ownerCol[i]}`;
join.on(relatedCol, '=', ownerCol);
}

@@ -211,3 +231,3 @@ });

insert(builder, owner) {
this.throwError('not implemented');
throw this.createError('not implemented');
}

@@ -246,3 +266,3 @@

relate(builder, owner) {
this.throwError('not implemented');
throw this.createError('not implemented');
}

@@ -252,3 +272,3 @@

unrelate(builder, owner) {
this.throwError('not implemented');
throw this.createError('not implemented');
}

@@ -264,3 +284,3 @@

' This is a no-no because ' + column +
' is needed in the relation ' + this.ownerModelClass.tableName + '.' + this.name);
' is needed in the relation ' + this.ownerModelClass.name + '.' + this.name);
}

@@ -274,11 +294,12 @@

let modify = mapping.modify || mapping.filter;
let type = typeof modify;
if (_.isFunction(modify)) {
if (type === 'function') {
return modify;
} else if (_.isObject(modify)) {
return function (queryBuilder) {
} else if (modify && type === 'object') {
return (queryBuilder) => {
queryBuilder.where(modify);
};
} else {
return _.noop;
return () => {};
}

@@ -288,3 +309,3 @@ }

parseReference(ref) {
if (!_.isArray(ref)) {
if (!Array.isArray(ref)) {
ref = [ref];

@@ -324,10 +345,10 @@ }

models1 = _.compact(models1);
models2 = _.compact(models2);
models1 = compact(models1);
models2 = compact(models2);
if (_.isEmpty(models1) && _.isEmpty(models2)) {
if (isEmpty(models1) && isEmpty(models2)) {
return [];
}
if (!_.isEmpty(models1)) {
if (!isEmpty(models1)) {
modelClass = models1[0].constructor;

@@ -355,63 +376,10 @@ } else {

return _.sortBy(_.values(modelsById), idProperty);
return sortBy(values(modelsById), idProperty);
}
resolveModel(Model, modelClass, logPrefix) {
const requireModel = (path) => {
let ModelClass;
try {
// babel 6 style of exposing es6 exports to commonjs https://github.com/babel/babel/issues/2683
let module = require(path);
ModelClass = isSubclassOf(module.default, Model)
? module.default
: module;
} catch (err) {
return null;
}
if (!isSubclassOf(ModelClass, Model)) {
return null;
}
return ModelClass;
};
if (_.isString(modelClass)) {
let ModelClass = null;
if (isAbsolutePath(modelClass)) {
ModelClass = requireModel(modelClass);
} else {
// If the path is not a absolute, try the modelPaths of the owner model class.
_.each(this.ownerModelClass.modelPaths, modelPath => {
ModelClass = requireModel(path.join(modelPath, modelClass));
if (isSubclassOf(ModelClass, Model)) {
// Break the loop.
return false;
}
});
}
if (!isSubclassOf(ModelClass, Model)) {
this.throwError(`${logPrefix}: ${modelClass} is an invalid file path to a model class`);
}
return ModelClass;
} else {
if (!isSubclassOf(modelClass, Model)) {
this.throwError(`${logPrefix} is not a subclass of Model or a file path to a module that exports one.`);
}
return modelClass;
}
}
throwError(message) {
createError(message) {
if (this.ownerModelClass && this.ownerModelClass.name && this.name) {
throw new Error(`${this.ownerModelClass.name}.relationMappings.${this.name}: ${message}`);
return new Error(`${this.ownerModelClass.name}.relationMappings.${this.name}: ${message}`);
} else {
throw new Error(`${this.constructor.name}: ${message}`);
return new Error(`${this.constructor.name}: ${message}`);
}

@@ -421,6 +389,2 @@ }

function isAbsolutePath(pth) {
return path.normalize(pth + '/') === path.normalize(path.resolve(pth) + '/');
}
function containsNonNull(arr) {

@@ -427,0 +391,0 @@ for (let i = 0, l = arr.length; i < l; ++i) {

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

const addedSelects = {};
const cols = this.relation.fullRelatedCol;
const cols = this.relation.fullRelatedCol(builder);
let selects;

@@ -89,0 +89,0 @@

'use strict';
const _ = require('lodash');
const Promise = require('bluebird');

@@ -20,4 +19,4 @@ const Model = require('./model/Model');

if (!isSubclassOf(args[0], Model) && _.isFunction(args[0].transaction)) {
let knex = _.first(args);
if (!isSubclassOf(args[0], Model) && typeof args[0].transaction === 'function') {
let knex = args[0];
args = args.slice(1);

@@ -33,4 +32,4 @@

// The last argument should be the callback and all other Model subclasses.
let callback = _.last(args);
let modelClasses = _.take(args, args.length - 1);
let callback = args[args.length - 1];
let modelClasses = args.slice(0, args.length - 1);
let i;

@@ -44,3 +43,3 @@

let knex = _.first(modelClasses).knex();
let knex = modelClasses[0].knex();
for (i = 0; i < modelClasses.length; ++i) {

@@ -80,3 +79,3 @@ if (modelClasses[i].knex() !== knex) {

if (!knex || !_.isFunction(knex.transaction)) {
if (!knex || typeof knex.transaction !== 'function') {
return Promise.reject(new Error('objection.transaction.start: first argument must be a model class or a knex instance'));

@@ -83,0 +82,0 @@ }

'use strict';
const _ = require('lodash');
const isObject = require('lodash/isObject');
const zipObject = require('lodash/zipObject');

@@ -35,3 +36,3 @@ module.exports = (ids, expectedProperties, opt) => {

}
} else if (_.isObject(ids[0])) {
} else if (isObject(ids[0])) {
ret = new Array(ids.length);

@@ -47,3 +48,3 @@

}
} else if (_.isObject(ids)) {
} else if (isObject(ids)) {
// 2.

@@ -63,3 +64,3 @@ ret = [ids];

if (Array.isArray(ids)) {
if (_.isObject(ids[0])) {
if (isObject(ids[0])) {
ret = new Array(ids.length);

@@ -79,3 +80,3 @@

}
} else if (_.isObject(ids)) {
} else if (isObject(ids)) {
// 2.

@@ -109,7 +110,7 @@ ret = [ids];

return _.zipObject(expectedProperties, ids);
return zipObject(expectedProperties, ids);
}
function ensureObject(ids) {
if (_.isObject(ids)) {
if (isObject(ids)) {
return ids;

@@ -116,0 +117,0 @@ } else {

{
"name": "objection",
"version": "0.8.1",
"version": "0.8.2",
"description": "An SQL-friendly ORM for Node.js",

@@ -32,3 +32,3 @@ "main": "lib/objection.js",

"engines": {
"node" : ">=4.0.0"
"node": ">=4.0.0"
},

@@ -35,0 +35,0 @@ "keywords": [

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