From 0f25c66ec9e58b0ff3bb57f1bfb832ed2d7d34f4 Mon Sep 17 00:00:00 2001 From: Cody Stoltman Date: Fri, 18 Mar 2016 11:43:46 -0500 Subject: [PATCH 1/4] add jshintrc file --- .jshintrc | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 .jshintrc diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 0000000..059786a --- /dev/null +++ b/.jshintrc @@ -0,0 +1,122 @@ +{ + // ┬┌─┐╦ ╦╦╔╗╔╔╦╗┬─┐┌─┐ + // │└─┐╠═╣║║║║ ║ ├┬┘│ + // o└┘└─┘╩ ╩╩╝╚╝ ╩ ┴└─└─┘ + // + // This file (`.jshintrc`) exists to help with consistency of code + // throughout this package, and throughout Sails and the Node-Machine project. + // + // To review what each of these options mean, see: + // http://jshint.com/docs/options + // + // (or: https://github.com/jshint/jshint/blob/master/examples/.jshintrc) + + + + ////////////////////////////////////////////////////////////////////// + // NOT SUPPORTED IN SOME JSHINT VERSIONS SO LEAVING COMMENTED OUT: + ////////////////////////////////////////////////////////////////////// + // Prevent overwriting prototypes of native classes like `Array`. + // (doing this is _never_ ok in any of our packages that are intended + // to be used as dependencies of other developers' modules and apps) + // "freeze": true, + ////////////////////////////////////////////////////////////////////// + + + ////////////////////////////////////////////////////////////////////// + // EVERYTHING ELSE: + ////////////////////////////////////////////////////////////////////// + + // Allow the use of `eval` and `new Function()` + // (we sometimes actually need to use these things) + "evil": true, + + // Tolerate funny-looking dashes in RegExp literals. + // (see https://github.com/jshint/jshint/issues/159#issue-903547) + "regexdash": true, + + // The potential runtime "Environments" (as defined by jshint) + // that the _style_ of code written in this package should be + // compatible with (not the code itself, of course). + "browser": true, + "node": true, + "wsh": true, + + // Tolerate the use `[]` notation when dot notation would be possible. + // (this is sometimes preferable for readability) + "sub": true, + + // Do NOT suppress warnings about mixed tabs and spaces + // (two spaces always, please; see `.editorconfig`) + "smarttabs": false, + + // Suppress warnings about trailing whitespace + // (this is already enforced by the .editorconfig, so no need to warn as well) + "trailing": false, + + // Suppress warnings about the use of expressions where fn calls or assignments + // are expected, and about using assignments where conditionals are expected. + // (while generally a good idea, without this setting, JSHint needlessly lights up warnings + // in existing, working code that really shouldn't be tampered with. Pandora's box and all.) + "expr": true, + "boss": true, + + // Do NOT suppress warnings about using functions inside loops + // (in the general case, we should be using iteratee functions with `_.each()` + // or `Array.prototype.forEach()` instead of `for` or `while` statements + // anyway. This warning serves as a helpful reminder.) + "loopfunc": false, + + // Suppress warnings about "weird constructions" + // i.e. allow code like: + // ``` + // (new (function OneTimeUsePrototype () { } )) + // ``` + // + // (sometimes order of operations in JavaScript can be scary. There is + // nothing wrong with using an extra set of parantheses when the mood + // strikes or you get "that special feeling".) + "supernew": true, + + // Do NOT allow backwards, node-dependency-style commas. + // (while this code style choice was used by the project in the past, + // we have since standardized these practices to make code easier to + // read, albeit a bit less exciting) + "laxcomma": false, + + // Strictly enforce the consistent use of single quotes. + // (this is a convention that was established primarily to make it easier + // to grep [or FIND+REPLACE in Sublime] particular string literals in + // JavaScript [.js] files. Note that JSON [.json] files are, of course, + // still written exclusively using double quotes around key names and + // around string literals.) + "quotmark": "single", + + // Do NOT suppress warnings about the use of `==null` comparisons. + // (please be explicit-- use Lodash or `require('util')` and call + // either `.isNull()` or `.isUndefined()`) + "eqnull": false, + + // Strictly enforce the use of curly braces with `if`, `else`, and `switch` + // as well as, much less commonly, `for` and `while` statements. + // (this is just so that all of our code is consistent, and to avoid bugs) + "curly": true, + + // Strictly enforce the use of `===` and `!==`. + // (this is always a good idea. Check out "Truth, Equality, and JavaScript" + // by Angus Croll [the author of "If Hemmingway Wrote JavaScript"] for more + // explanation as to why.) + "eqeqeq": true, + + // Allow initializing variables to `undefined`. + // For more information, see: + // • https://jslinterrors.com/it-is-not-necessary-to-initialize-a-to-undefined + // • https://github.com/jshint/jshint/issues/1484 + // + // (it is often very helpful to explicitly clarify the initial value of + // a local variable-- especially for folks new to more advanced JavaScript + // and who might not recognize the subtle, yet critically important differences between our seemingly + // between `null` and `undefined`, and the impact on `typeof` checks) + "-W080": true + +} From 03f58f27d46ef5cf4eee59f6cf066efd37472295 Mon Sep 17 00:00:00 2001 From: Cody Stoltman Date: Fri, 18 Mar 2016 11:48:26 -0500 Subject: [PATCH 2/4] add editorconfig and npmignore --- .editorconfig | 10 ++++++++++ .npmignore | 21 +++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 .editorconfig create mode 100644 .npmignore diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..0f09989 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,10 @@ +# editorconfig.org +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..5e87615 --- /dev/null +++ b/.npmignore @@ -0,0 +1,21 @@ +*# +node_modules +ssl +.DS_STORE +*.swo +*.swp +*.swn +*.swm +*~ +.git +.gitignore +.dockerignore +.jshintrc +.travis.yml +.editorconfig +docker-compose.yml +Dockerfile +Makefile +*.md +**/*.md +test From 9048d94ff9c495ad299501af6e16c4130fae543c Mon Sep 17 00:00:00 2001 From: Cody Stoltman Date: Fri, 18 Mar 2016 11:48:48 -0500 Subject: [PATCH 3/4] update formatting to pass jshint style guide --- lib/adapter.js | 403 ++++++++++++++++++++++++++++++++--------------- lib/processor.js | 13 +- lib/utils.js | 23 +-- 3 files changed, 287 insertions(+), 152 deletions(-) diff --git a/lib/adapter.js b/lib/adapter.js index 8ce7744..e568932 100644 --- a/lib/adapter.js +++ b/lib/adapter.js @@ -13,7 +13,6 @@ var Sequel = require('waterline-sequel'); var utils = require('./utils'); var Processor = require('./processor'); var Cursor = require('waterline-cursor'); -var hop = utils.object.hasOwnProperty; module.exports = (function() { @@ -58,14 +57,19 @@ module.exports = (function() { var self = this; - if(!connection.identity) return cb(Errors.IdentityMissing); - if(connections[connection.identity]) return cb(Errors.IdentityDuplicate); + if(!connection.identity) { + return cb(Errors.IdentityMissing); + } + + if(connections[connection.identity]) { + return cb(Errors.IdentityDuplicate); + } // Store any connection overrides connectionOverrides[connection.identity] = {}; // Look for the WL Next key - if(hop(connection, 'wlNext')) { + if(_.has(connection, 'wlNext')) { connectionOverrides[connection.identity].wlNext = _.cloneDeep(connection.wlNext); } @@ -103,10 +107,10 @@ module.exports = (function() { // If this collection has a schema name set, make sure that it's passed // through to the options for waterline-sequel. - if(hop(collection, 'meta') && hop(collection.meta, 'schemaName')) { + if(_.has(collection, 'meta') && _.has(collection.meta, 'schemaName')) { sqlOptions.schemaName[_schema.tableName] = collection.meta.schemaName; } else { - sqlOptions.schemaName[_schema.tableName] = "public"; + sqlOptions.schemaName[_schema.tableName] = 'public'; } // If the tableName is different from the identity, store the tableName @@ -134,7 +138,7 @@ module.exports = (function() { // Teardown teardown: function (conn, cb) { - if (typeof conn == 'function') { + if (typeof conn === 'function') { cb = conn; conn = null; } @@ -142,7 +146,10 @@ module.exports = (function() { connections = {}; return cb(); } - if(!connections[conn]) return cb(); + if(!connections[conn]) { + return cb(); + } + delete connections[conn]; cb(); }, @@ -158,8 +165,12 @@ module.exports = (function() { spawnConnection(connectionName, function __QUERY__(client, cb) { // Run query - if (data) client.query(query, data, cb); - else client.query(query, cb); + if (data) { + client.query(query, data, cb); + } + else { + client.query(query, cb); + } }, cb); }, @@ -176,56 +187,70 @@ module.exports = (function() { // Build query to get a bunch of info from the information_schema // It's not super important to understand it only that it returns the following fields: // [Table, #, Column, Type, Null, Constraint, C, consrc, F Key, Default] - var query = "SELECT x.nspname || '.' || x.relname as \"Table\", x.attnum as \"#\", x.attname as \"Column\", x.\"Type\"," + - " case x.attnotnull when true then 'NOT NULL' else '' end as \"NULL\", r.conname as \"Constraint\", r.contype as \"C\", " + - "r.consrc, fn.nspname || '.' || f.relname as \"F Key\", d.adsrc as \"Default\" FROM (" + - "SELECT c.oid, a.attrelid, a.attnum, n.nspname, c.relname, a.attname, pg_catalog.format_type(a.atttypid, a.atttypmod) as \"Type\", " + - "a.attnotnull FROM pg_catalog.pg_attribute a, pg_namespace n, pg_class c WHERE a.attnum > 0 AND NOT a.attisdropped AND a.attrelid = c.oid " + - "and c.relkind not in ('S','v') and c.relnamespace = n.oid and n.nspname not in ('pg_catalog','pg_toast','information_schema')) x " + - "left join pg_attrdef d on d.adrelid = x.attrelid and d.adnum = x.attnum " + - "left join pg_constraint r on r.conrelid = x.oid and r.conkey[1] = x.attnum " + - "left join pg_class f on r.confrelid = f.oid " + - "left join pg_namespace fn on f.relnamespace = fn.oid " + - "where x.relname = '" + tableName + "' and x.nspname = '" + schemaName + "' order by 1,2;"; + var query = 'SELECT x.nspname || \'.\' || x.relname as \"Table\", x.attnum as \"#\", x.attname as \"Column\", x.\"Type\",' + + ' case x.attnotnull when true then \'NOT NULL\' else \'\' end as \"NULL\", r.conname as \"Constraint\", r.contype as \"C\", ' + + 'r.consrc, fn.nspname || \'.\' || f.relname as \"F Key\", d.adsrc as \"Default\" FROM (' + + 'SELECT c.oid, a.attrelid, a.attnum, n.nspname, c.relname, a.attname, pg_catalog.format_type(a.atttypid, a.atttypmod) as \"Type\", ' + + 'a.attnotnull FROM pg_catalog.pg_attribute a, pg_namespace n, pg_class c WHERE a.attnum > 0 AND NOT a.attisdropped AND a.attrelid = c.oid ' + + 'and c.relkind not in (\'S\',\'v\') and c.relnamespace = n.oid and n.nspname not in (\'pg_catalog\',\'pg_toast\',\'information_schema\')) x ' + + 'left join pg_attrdef d on d.adrelid = x.attrelid and d.adnum = x.attnum ' + + 'left join pg_constraint r on r.conrelid = x.oid and r.conkey[1] = x.attnum ' + + 'left join pg_class f on r.confrelid = f.oid ' + + 'left join pg_namespace fn on f.relnamespace = fn.oid ' + + 'where x.relname = \'' + tableName + '\' and x.nspname = \'' + schemaName + '\' order by 1,2;'; // Get Sequences to test if column auto-increments - var autoIncrementQuery = "SELECT t.relname as related_table, a.attname as related_column, s.relname as sequence_name " + - "FROM pg_class s JOIN pg_depend d ON d.objid = s.oid JOIN pg_class t ON d.objid = s.oid AND d.refobjid = t.oid " + - "JOIN pg_attribute a ON (d.refobjid, d.refobjsubid) = (a.attrelid, a.attnum) JOIN pg_namespace n ON n.oid = s.relnamespace " + - "WHERE s.relkind = 'S' AND n.nspname = '" + schemaName + "';"; + var autoIncrementQuery = 'SELECT t.relname as related_table, a.attname as related_column, s.relname as sequence_name ' + + 'FROM pg_class s JOIN pg_depend d ON d.objid = s.oid JOIN pg_class t ON d.objid = s.oid AND d.refobjid = t.oid ' + + 'JOIN pg_attribute a ON (d.refobjid, d.refobjsubid) = (a.attrelid, a.attnum) JOIN pg_namespace n ON n.oid = s.relnamespace ' + + 'WHERE s.relkind = \'S\' AND n.nspname = \'' + schemaName + '\';'; // Get Indexes - var indiciesQuery = "SELECT n.nspname as \"Schema\", c.relname as \"Name\", CASE c.relkind WHEN 'r' THEN 'table' " + - "WHEN 'v' THEN 'view' WHEN 'i' THEN 'index' WHEN 'S' THEN 'sequence' WHEN 's' THEN 'special' WHEN 'f' THEN " + - "'foreign table' END as \"Type\", pg_catalog.pg_get_userbyid(c.relowner) as \"Owner\", c2.relname as \"Table\" " + - "FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace " + - "LEFT JOIN pg_catalog.pg_index i ON i.indexrelid = c.oid " + - "LEFT JOIN pg_catalog.pg_class c2 ON i.indrelid = c2.oid " + - "WHERE c.relkind IN ('i','') AND n.nspname <> 'pg_catalog' AND n.nspname <> 'information_schema' " + - "AND n.nspname !~ '^pg_toast' AND pg_catalog.pg_table_is_visible(c.oid) ORDER BY 1,2;"; + var indiciesQuery = 'SELECT n.nspname as \"Schema\", c.relname as \"Name\", CASE c.relkind WHEN \'r\' THEN \'table\' ' + + 'WHEN \'v\' THEN \'view\' WHEN \'i\' THEN \'index\' WHEN \'S\' THEN \'sequence\' WHEN \'s\' THEN \'special\' WHEN \'f\' THEN ' + + '\'foreign table\' END as \"Type\", pg_catalog.pg_get_userbyid(c.relowner) as \"Owner\", c2.relname as \"Table\" ' + + 'FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace ' + + 'LEFT JOIN pg_catalog.pg_index i ON i.indexrelid = c.oid ' + + 'LEFT JOIN pg_catalog.pg_class c2 ON i.indrelid = c2.oid ' + + 'WHERE c.relkind IN (\'i\',\'\') AND n.nspname <> \'pg_catalog\' AND n.nspname <> \'information_schema\' ' + + 'AND n.nspname !~ \'^pg_toast\' AND pg_catalog.pg_table_is_visible(c.oid) ORDER BY 1,2;'; // Run Info Query client.query(query, function(err, result) { - if(err) return cb(handleQueryError(err)); - if(result.rows.length === 0) return cb(); + if(err) { + return cb(handleQueryError(err)); + } + + if(result.rows.length === 0) { + return cb(); + } // Run Query to get Auto Incrementing sequences client.query(autoIncrementQuery, function(err, aResult) { - if(err) return cb(handleQueryError(err)); + if(err) { + return cb(handleQueryError(err)); + } aResult.rows.forEach(function(row) { - if(row.related_table !== table) return; + if(row.related_table !== table) { + return; + } // Look through query results and see if related_column exists result.rows.forEach(function(column) { - if(column.Column !== row.related_column) return; + if(column.Column !== row.related_column) { + return; + } + column.autoIncrement = true; }); }); // Run Query to get Indexed values client.query(indiciesQuery, function(err, iResult) { - if(err) return cb(handleQueryError(err)); + if(err) { + return cb(handleQueryError(err)); + } // Loop through indicies and see if any match iResult.rows.forEach(function(column) { @@ -233,7 +258,10 @@ module.exports = (function() { // Look through query results and see if key exists result.rows.forEach(function(column) { - if(column.Column !== key) return; + if(column.Column !== key) { + return; + } + column.indexed = true; }); }); @@ -259,10 +287,12 @@ module.exports = (function() { // Create a describe method to run after the define. // Ensures the define connection is properly closed. var describe = function(err, result) { - if(err) return cb(err); + if(err) { + return cb(err); + } // Describe (sets schema) - adapter.describe(connectionName, table.replace(/["']/g, ""), cb); + adapter.describe(connectionName, table.replace(/["']/g, ''), cb); }; var connectionObject = connections[connectionName]; @@ -274,17 +304,21 @@ module.exports = (function() { // If we're being told NOT to create schemas, then skip right to // creating the table. - if (connectionObject.config.createSchemas === false) {return _define();} + if (connectionObject.config.createSchemas === false) { + return _define(); + } // If the schema name is "public", just finish creating the table - if (schemaName == 'public') {return _define();} + if (schemaName === 'public') { + return _define(); + } - // If not, attempt to create the schema first. This will succeed if + // If not, attempt to create the schema first. This will succeed if // the schema already exists. adapter.createSchema(connectionName, table, schemaName, _define); function _define(errCreatingSchema) { - + if (errCreatingSchema) { cb(handleQueryError(errCreatingSchema)); } @@ -305,7 +339,7 @@ module.exports = (function() { client.query(query, function __DEFINE__(err, result) { if(err) { - if (err.code == '3F000') { + if (err.code === '3F000') { err.table = table; err.schemaName = schemaName; } @@ -322,7 +356,10 @@ module.exports = (function() { var query = 'CREATE INDEX ' + utils.escapeName(cleanTable + '_' + name) + ' on ' + tableName + ' (' + utils.escapeName(name) + ');'; // Run Query client.query(query, function(err, result) { - if(err) return cb(handleQueryError(err)); + if(err) { + return cb(handleQueryError(err)); + } + cb(); }); } @@ -339,22 +376,25 @@ module.exports = (function() { // Create a schema createSchema: function(connectionName, table, schemaName, cb) { - if ('function' == typeof schemaName) { + if ('function' === typeof schemaName) { cb = schemaName; schemaName = getSchema(connectionName, table); } if (!schemaName) { - throw new Error("No schemaName specified, and could not determined schemaname for table `" + table + "`"); + throw new Error('No schemaName specified, and could not determined schemaname for table `' + table + '`'); } - // Build Query + // Build Query var query = 'CREATE SCHEMA "' + schemaName + '"'; spawnConnection(connectionName, function (client, cb) { // Run Query client.query(query, function (err, result) { // If we get a "duplicate schema" error, just silently ignore it - if (err && err.code == '42P06') {return cb();} + if (err && err.code === '42P06') { + return cb(); + } + // If we get any other type of error, return it if (err) { err.type = 'CREATING_SCHEMA'; @@ -388,13 +428,19 @@ module.exports = (function() { // Run Query client.query(query, function __DROP__(err, result) { - if(err) result = null; + if(err) { + result = null; + } + next(null, result); }); } async.eachSeries(relations, dropTable, function(err) { - if(err) return cb(err); + if(err) { + return cb(err); + } + dropTable(table, cb); }); @@ -419,7 +465,10 @@ module.exports = (function() { // Run Query client.query(query, function __ADD_ATTRIBUTE__(err, result) { - if(err) return cb(handleQueryError(err)); + if(err) { + return cb(handleQueryError(err)); + } + cb(null, result.rows); }); @@ -438,7 +487,10 @@ module.exports = (function() { // Run Query client.query(query, function __REMOVE_ATTRIBUTE__(err, result) { - if(err) return cb(handleQueryError(err)); + if(err) { + return cb(handleQueryError(err)); + } + cb(null, result.rows); }); @@ -461,7 +513,7 @@ module.exports = (function() { // Mixin WL Next connection overrides to sqlOptions var overrides = connectionOverrides[connectionName] || {}; var options = _.cloneDeep(sqlOptions); - if(hop(overrides, 'wlNext')) { + if(_.has(overrides, 'wlNext')) { options.wlNext = overrides.wlNext; } @@ -479,34 +531,50 @@ module.exports = (function() { // Loop through all the attributes being inserted and check if a sequence was used Object.keys(collection.schema).forEach(function(schemaKey) { - if(!utils.object.hasOwnProperty(collection.schema[schemaKey], 'autoIncrement')) return; - if(Object.keys(data).indexOf(schemaKey) < 0) return; + if(!_.has(collection.schema[schemaKey], 'autoIncrement')) { + return; + } + + if(Object.keys(data).indexOf(schemaKey) < 0) { + return; + } + incrementSequences.push(schemaKey); }); // Run Query client.query(query.query, query.values, function __CREATE__(err, result) { - if(err) return cb(handleQueryError(err)); + if(err) { + return cb(handleQueryError(err)); + } // Cast special values var values = processor.cast(tableName, result.rows[0]); // Set Sequence value to defined value if needed - if(incrementSequences.length === 0) return cb(null, values); + if(incrementSequences.length === 0) { + return cb(null, values); + } function setSequence(item, next) { - var sequenceName = "'\"" + schemaName + '\".\"' + tableName + '_' + item + '_seq' + "\"'"; + var sequenceName = '\'\"' + schemaName + '\".\"' + tableName + '_' + item + '_seq' + '\"\''; var sequenceValue = values[item]; var sequenceQuery = 'SELECT setval(' + sequenceName + ', ' + sequenceValue + ', true)'; client.query(sequenceQuery, function(err, result) { - if(err) return next(err); + if(err) { + return next(err); + } + next(); }); } async.each(incrementSequences, setSequence, function(err) { - if(err) return cb(err); + if(err) { + return cb(err); + } + cb(null, values); }); @@ -537,7 +605,7 @@ module.exports = (function() { // Mixin WL Next connection overrides to sqlOptions var overrides = connectionOverrides[connectionName] || {}; var options = _.cloneDeep(sqlOptions); - if(hop(overrides, 'wlNext')) { + if(_.has(overrides, 'wlNext')) { options.wlNext = overrides.wlNext; } @@ -546,7 +614,10 @@ module.exports = (function() { // Loop through all the attributes being inserted and check if a sequence was used Object.keys(collection.schema).forEach(function(schemaKey) { - if(!utils.object.hasOwnProperty(collection.schema[schemaKey], 'autoIncrement')) return; + if(!_.has(collection.schema[schemaKey], 'autoIncrement')) { + return; + } + incrementSequences.push({ key: schemaKey, value: 0 @@ -570,13 +641,17 @@ module.exports = (function() { // Run Query client.query(query.query, query.values, function __CREATE_EACH__(err, result) { - if(err) return cb(handleQueryError(err)); + if(err) { + return cb(handleQueryError(err)); + } // Cast special values var values = processor.cast(tableName, result.rows[0]); results.push(values); - if(incrementSequences.length === 0) return cb(null, values); + if(incrementSequences.length === 0) { + return cb(null, values); + } function checkSequence(item, next) { var currentValue = item.value; @@ -589,29 +664,46 @@ module.exports = (function() { } async.each(incrementSequences, checkSequence, function(err) { - if(err) return cb(err); + if(err) { + return cb(err); + } + cb(null, values); }); }); }, function(err) { - if(err) return cb(err); - if(incrementSequences.length === 0) return cb(null, results); + if(err) { + return cb(err); + } + + if(incrementSequences.length === 0) { + return cb(null, results); + } function setSequence(item, next) { - if (sequenceValue === 0) {return next();} - var sequenceName = "'\"" + schemaName + '\".\"' + tableName + '_' + item.key + '_seq' + "\"'"; + if (sequenceValue === 0) { + return next(); + } + + var sequenceName = '\'\"' + schemaName + '\".\"' + tableName + '_' + item.key + '_seq' + '\"\''; var sequenceValue = item.value; var sequenceQuery = 'SELECT setval(' + sequenceName + ', ' + sequenceValue + ', true)'; client.query(sequenceQuery, function(err, result) { - if(err) return next(err); + if(err) { + return next(err); + } + next(); }); } async.each(incrementSequences, setSequence, function(err) { - if(err) return cb(err); + if(err) { + return cb(err); + } + cb(null, results); }); }); @@ -620,8 +712,7 @@ module.exports = (function() { }, // Native Join Support - join: function(connectionName, table, options, cb) { - + join: function(connectionName, table, options, cb, metaContainer) { spawnConnection(connectionName, function __FIND__(client, done) { // Populate associated records for each parent result @@ -651,7 +742,10 @@ module.exports = (function() { * @return {String} */ $getPK: function (collectionName) { - if (!collectionName) return; + if (!collectionName) { + return; + } + return _getPK(connectionName, collectionName); }, @@ -687,13 +781,12 @@ module.exports = (function() { // Mixin WL Next connection overrides to sqlOptions var overrides = connectionOverrides[connectionName] || {}; var _options = _.cloneDeep(sqlOptions); - if(hop(overrides, 'wlNext')) { + if(_.has(overrides, 'wlNext')) { _options.wlNext = overrides.wlNext; } var sequel = new Sequel(_schema, _options); var _query; - // Build a query for the specific query strategy try { _query = sequel.find(tableName, instructions); @@ -706,7 +799,9 @@ module.exports = (function() { processParent: function(next) { client.query(_query.query[0], _query.values[0], function __FIND__(err, result) { - if(err) return next(handleQueryError(err)); + if(err) { + return next(handleQueryError(err)); + } parentRecords = result.rows; @@ -718,9 +813,14 @@ module.exports = (function() { // Check if we can split this on our special alias identifier '___' and if // so put the result in the cache var split = key.split('___'); - if(split.length < 2) return; + if(split.length < 2) { + return; + } + + if(!_.has(cache, split[0])) { + cache[split[0]] = {}; + } - if(!hop(cache, split[0])) cache[split[0]] = {}; cache[split[0]][split[1]] = parent[key]; delete parent[key]; }); @@ -728,7 +828,10 @@ module.exports = (function() { // Combine the local cache into the cachedChildren if(_.keys(cache).length > 0) { _.keys(cache).forEach(function(pop) { - if(!hop(cachedChildren, pop)) cachedChildren[pop] = []; + if(!_.has(cachedChildren, pop)) { + cachedChildren[pop] = []; + } + cachedChildren[pop] = cachedChildren[pop].concat(cache[pop]); }); } @@ -739,7 +842,10 @@ module.exports = (function() { // Pull out any aliased child records that have come from a hasFK association async.eachSeries(parentRecords, splitChildren, function(err) { - if(err) return next(err); + if(err) { + return next(err); + } + buffers.parents = parentRecords; next(); }); @@ -771,7 +877,7 @@ module.exports = (function() { var recordsMap = {}; // Check for any cached parent records - if(hop(cachedChildren, alias)) { + if(_.has(cachedChildren, alias)) { cachedChildren[alias].forEach(function(cachedChild) { var childVal = popInstructions[0].childKey; var parentVal = popInstructions[0].parentKey; @@ -781,7 +887,10 @@ module.exports = (function() { } // If null value for the parentVal, ignore it - if(parent[parentVal] === null) return; + if(parent[parentVal] === null) { + return; + } + // If the same record is alreay there, ignore it if (!recordsMap[cachedChild[childVal]]) { records.push(cachedChild); @@ -822,31 +931,31 @@ module.exports = (function() { if(_.isNumber(parent[pk])) { qs += q.qs.replace('^?^', parent[pk]) + ' UNION ALL '; } else { - qs += q.qs.replace('^?^', "'" + parent[pk] + "'") + ' UNION ALL '; + qs += q.qs.replace('^?^', '\'' + parent[pk] + '\'') + ' UNION ALL '; } }); // Remove the last UNION ALL qs = qs.slice(0, -11); - // Add a final sort to the Union clause for integration - if(parentRecords.length > 1) { - var addedOrder; + var addedOrder; + function addSort(sortKey, sorts) { + // ID sorts are ambiguous + if(sortKey === 'id') { + return; + } - function addSort(sortKey, sorts) { - // ID sorts are ambiguous - if(sortKey === 'id') { - return; - } + if (!addedOrder) { + addedOrder = true; + qs += ' ORDER BY '; + } - if (!addedOrder) { - addedOrder = true; - qs += ' ORDER BY '; - } + var direction = sorts[sortKey] === 1 ? 'ASC' : 'DESC'; + qs += '"' + sortKey + '"' + ' ' + direction + ', '; + } - var direction = sorts[sortKey] === 1 ? 'ASC' : 'DESC'; - qs += '"' + sortKey + '"' + ' ' + direction + ', '; - } + // Add a final sort to the Union clause for integration + if(parentRecords.length > 1) { if(!Array.isArray(q.instructions)) { _.keys(q.instructions.criteria.sort).forEach(function(sortKey) { @@ -867,14 +976,16 @@ module.exports = (function() { } client.query(qs, q.values, function __FIND__(err, result) { - if(err) return next(handleQueryError(err)); + if(err) { + return next(handleQueryError(err)); + } var groupedRecords = {}; result.rows.forEach(function(row) { if(!Array.isArray(q.instructions)) { - if(!hop(groupedRecords, row[q.instructions.childKey])) { + if(!_.has(groupedRecords, row[q.instructions.childKey])) { groupedRecords[row[q.instructions.childKey]] = []; } @@ -885,7 +996,7 @@ module.exports = (function() { // Grab the special "foreign key" we attach and make sure to remove it var fk = '___' + q.instructions[0].childKey; - if(!hop(groupedRecords, row[fk])) { + if(!_.has(groupedRecords, row[fk])) { groupedRecords[row[fk]] = []; } @@ -899,10 +1010,19 @@ module.exports = (function() { }); buffers.store.forEach(function(buffer) { - if(buffer.attrName !== q.attrName) return; + if(buffer.attrName !== q.attrName) { + return; + } + var records = groupedRecords[buffer.belongsToPKValue]; - if(!records) return; - if(!buffer.records) buffer.records = []; + if(!records) { + return; + } + + if(!buffer.records) { + buffer.records = []; + } + buffer.records = buffer.records.concat(records); }); @@ -916,7 +1036,10 @@ module.exports = (function() { }, function(err) { - if(err) return next(err); + if(err) { + return next(err); + } + next(); }); @@ -929,7 +1052,11 @@ module.exports = (function() { }, // Select Query Logic - find: function(connectionName, table, options, cb) { + find: function(connectionName, table, options, cb, metaContainer) { + + // if(metaContainer) { + // console.log(metaContainer()); + // } spawnConnection(connectionName, function __FIND__(client, cb) { // Grab Connection Schema @@ -949,7 +1076,7 @@ module.exports = (function() { // Mixin WL Next connection overrides to sqlOptions var overrides = connectionOverrides[connectionName] || {}; var _options = _.cloneDeep(sqlOptions); - if(hop(overrides, 'wlNext')) { + if(_.has(overrides, 'wlNext')) { _options.wlNext = overrides.wlNext; } @@ -962,8 +1089,11 @@ module.exports = (function() { } catch(e) { return cb(e); } + client.query(_query.query[0], _query.values[0], function __FIND__(err, result) { - if(err) return cb(handleQueryError(err)); + if(err) { + return cb(handleQueryError(err)); + } // Cast special values var values = []; @@ -999,7 +1129,7 @@ module.exports = (function() { // Mixin WL Next connection overrides to sqlOptions var overrides = connectionOverrides[connectionName] || {}; var _options = _.cloneDeep(sqlOptions); - if(hop(overrides, 'wlNext')) { + if(_.has(overrides, 'wlNext')) { _options.wlNext = overrides.wlNext; } @@ -1014,7 +1144,10 @@ module.exports = (function() { } client.query(_query.query[0], _query.values[0], function __COUNT__(err, result) { - if(err) return cb(handleQueryError(err)); + if(err) { + return cb(handleQueryError(err)); + } + if(!_.isArray(result.rows) || !result.rows.length) { return cb(new Error('Invalid query, no results returned.')); } @@ -1069,7 +1202,7 @@ module.exports = (function() { // Update one or more models in the collection update: function(connectionName, table, options, data, cb) { //LIMIT in a postgresql UPDATE command is not valid - if (hop(options, 'limit')) { + if (_.has(options, 'limit')) { return cb(new Error('Your \'LIMIT ' + options.limit + '\' is not allowed in the PostgreSQL UPDATE query.')); } spawnConnection(connectionName, function __UPDATE__(client, cb) { @@ -1084,7 +1217,7 @@ module.exports = (function() { // Mixin WL Next connection overrides to sqlOptions var overrides = connectionOverrides[connectionName] || {}; var _options = _.cloneDeep(sqlOptions); - if(hop(overrides, 'wlNext')) { + if(_.has(overrides, 'wlNext')) { _options.wlNext = overrides.wlNext; } @@ -1100,7 +1233,9 @@ module.exports = (function() { // Run Query client.query(query.query, query.values, function __UPDATE__(err, result) { - if(err) return cb(handleQueryError(err)); + if(err) { + return cb(handleQueryError(err)); + } // Cast special values var values = []; @@ -1128,7 +1263,7 @@ module.exports = (function() { // Mixin WL Next connection overrides to sqlOptions var overrides = connectionOverrides[connectionName] || {}; var _options = _.cloneDeep(sqlOptions); - if(hop(overrides, 'wlNext')) { + if(_.has(overrides, 'wlNext')) { _options.wlNext = overrides.wlNext; } @@ -1144,7 +1279,10 @@ module.exports = (function() { // Run Query client.query(query.query, query.values, function __DELETE__(err, result) { - if(err) return cb(handleQueryError(err)); + if(err) { + return cb(handleQueryError(err)); + } + cb(null, result.rows); }); @@ -1175,11 +1313,18 @@ module.exports = (function() { pk = _.find(Object.keys(collectionDefinition), function _findPK(key) { var attrDef = collectionDefinition[key]; - if(attrDef && attrDef.primaryKey) return key; - else return false; + if(attrDef && attrDef.primaryKey) { + return key; + } + else { + return false; + } }); - if(!pk) pk = 'id'; + if(!pk) { + pk = 'id'; + } + return pk; } catch (e) { @@ -1195,7 +1340,9 @@ module.exports = (function() { function spawnConnection(connectionName, logic, cb) { var connectionObject = connections[connectionName]; - if(!connectionObject) return cb(Errors.InvalidConnection); + if(!connectionObject) { + return cb(Errors.InvalidConnection); + } // If the connection details were supplied as a URL use that. Otherwise, // connect using the configuration object as is. @@ -1357,17 +1504,17 @@ module.exports = (function() { rule: 'unique' }]; } - } + } - else if (err.code === '3F000') { + else if (err.code === '3F000') { formattedErr = {}; formattedErr.message = 'Attempted to create a table `' + err.table + '` in a schema `' + err.schemaName + '` that does not exist. Either create the schema manually or make sure that the `createSchemas` flag in your connection configuration is not set to `false`.'; delete err.table; delete err.schemaName; formattedErr.originalError = err; - } + } - else if (err.type == 'CREATING_SCHEMA') { + else if (err.type === 'CREATING_SCHEMA') { formattedErr = {}; formattedErr.code = 'CREATING_SCHEMA'; formattedErr.message = 'An error occurred creating the schema "' + err.schemaName + '"; perhaps it contains invalid characters?'; diff --git a/lib/processor.js b/lib/processor.js index 846fe72..70fd34b 100644 --- a/lib/processor.js +++ b/lib/processor.js @@ -56,10 +56,15 @@ Processor.prototype.cast = function(table, values) { } }); - if(!attr) attr = key; + if(!attr) { + attr = key; + } // Lookup Schema "Type" - if(!this.schema[identity] || !this.schema[identity].attributes[attr]) return; + if(!this.schema[identity] || !this.schema[identity].attributes[attr]) { + return; + } + var type; if(!_.isPlainObject(this.schema[identity].attributes[attr])) { @@ -69,7 +74,9 @@ Processor.prototype.cast = function(table, values) { } - if(!type) return; + if(!type) { + return; + } // Attempt to parse Array if(type === 'array') { diff --git a/lib/utils.js b/lib/utils.js index 576f359..95af19e 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -23,25 +23,6 @@ utils.marshalConfig = function(config) { }); }; -/** - * Safe hasOwnProperty - */ - -utils.object = {}; - -/** - * Safer helper for hasOwnProperty checks - * - * @param {Object} obj - * @param {String} prop - * @return {Boolean} - * @api public - */ - -var hop = Object.prototype.hasOwnProperty; -utils.object.hasOwnProperty = function(obj, prop) { - return hop.call(obj, prop); -}; /** * Escape Name @@ -272,7 +253,7 @@ utils.sqlTypeCast = function(type) { return 'BYTEA'; default: - console.error("Unregistered type given: " + type); - return "TEXT"; + console.error('Unregistered type given: ' + type); + return 'TEXT'; } }; From 29d8200b5581c8035bc6d6397b0c527e303737e0 Mon Sep 17 00:00:00 2001 From: Cody Stoltman Date: Fri, 18 Mar 2016 11:49:57 -0500 Subject: [PATCH 4/4] remove leftover testing --- lib/adapter.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/lib/adapter.js b/lib/adapter.js index e568932..f9b31e6 100644 --- a/lib/adapter.js +++ b/lib/adapter.js @@ -712,7 +712,7 @@ module.exports = (function() { }, // Native Join Support - join: function(connectionName, table, options, cb, metaContainer) { + join: function(connectionName, table, options, cb) { spawnConnection(connectionName, function __FIND__(client, done) { // Populate associated records for each parent result @@ -1052,11 +1052,7 @@ module.exports = (function() { }, // Select Query Logic - find: function(connectionName, table, options, cb, metaContainer) { - - // if(metaContainer) { - // console.log(metaContainer()); - // } + find: function(connectionName, table, options, cb) { spawnConnection(connectionName, function __FIND__(client, cb) { // Grab Connection Schema