Skip to content
This repository has been archived by the owner on Aug 13, 2021. It is now read-only.

Commit

Permalink
Add support for ANSI_QUOTES
Browse files Browse the repository at this point in the history
  • Loading branch information
rkt2spc committed Nov 16, 2018
1 parent 35c23bf commit 951af8f
Show file tree
Hide file tree
Showing 22 changed files with 211 additions and 109 deletions.
29 changes: 16 additions & 13 deletions sequel/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,11 @@ var Sequel = module.exports = function(schema, options) {
// should use lower or regex logic for querying.
this.caseSensitive = options && utils.object.hasOwnProperty(options, 'caseSensitive') ? options.caseSensitive : true;

// Set the escape character, default is "
this.escapeCharacter = options && utils.object.hasOwnProperty(options, 'escapeCharacter') ? options.escapeCharacter : '"';
// Set the identifier character, default is `
this.identifierCharacter = options && utils.object.hasOwnProperty(options, 'identifierCharacter') ? options.identifierCharacter : '`';

// Set the escape character, default is '
this.escapeCharacter = options && utils.object.hasOwnProperty(options, 'escapeCharacter') ? options.escapeCharacter : '\'';

// Set if the database can return values from things such as an insert
this.canReturnValues = options && utils.object.hasOwnProperty(options, 'canReturnValues') ? options.canReturnValues : false;
Expand All @@ -46,7 +49,7 @@ var Sequel = module.exports = function(schema, options) {
this.escapeInserts = options && utils.object.hasOwnProperty(options, 'escapeInserts') ? options.escapeInserts : false;

// Determine if aliased tablenames in DELETE queries need to be referenced before the FROM, e.g.
// DELETE `tableName` FROM `tableName` as `otherTableName` WHERE `otherTableName`.`foo` = "bar"
// DELETE `tableName` FROM `tableName` as `otherTableName` WHERE `otherTableName`.`foo` = 'bar'
// MySQL and Oracle require this, but it doesn't work in Postgresql.
this.declareDeleteAlias = options && utils.object.hasOwnProperty(options, 'declareDeleteAlias') ? options.declareDeleteAlias : true;

Expand Down Expand Up @@ -116,8 +119,8 @@ Sequel.prototype.find = function find(currentTable, queryObject) {
Sequel.prototype.count = function count(currentTable, queryObject) {

// Escape table name
var tableName = utils.escapeName(this.schema[currentTable].tableName, this.escapeCharacter, this.schemaName);
var alias = utils.escapeName(this.schema[currentTable].tableName, this.escapeCharacter);
var tableName = utils.escapeName(this.schema[currentTable].tableName, this.identifierCharacter, this.schemaName);
var alias = utils.escapeName(this.schema[currentTable].tableName, this.identifierCharacter);

// Step 1:
// Build out the Count statements
Expand Down Expand Up @@ -164,7 +167,7 @@ Sequel.prototype.create = function create(currentTable, data) {

var options = {
parameterized: this.parameterized,
escapeCharacter: this.escapeCharacter,
identifierCharacter: this.identifierCharacter,
escapeInserts: this.escapeInserts,
schemaName: this.schemaName
};
Expand All @@ -175,7 +178,7 @@ Sequel.prototype.create = function create(currentTable, data) {
var paramValues = attributes.params.join(', ');

// Build Query
var query = 'INSERT INTO ' + utils.escapeName(currentTable, this.escapeCharacter, this.schemaName) + ' (' + columnNames + ') values (' + paramValues + ')';
var query = 'INSERT INTO ' + utils.escapeName(currentTable, this.identifierCharacter, this.schemaName) + ' (' + columnNames + ') values (' + paramValues + ')';

if(this.canReturnValues) {
query += ' RETURNING *';
Expand All @@ -192,15 +195,15 @@ Sequel.prototype.update = function update(currentTable, queryObject, data) {

var options = {
parameterized: this.parameterized,
escapeCharacter: this.escapeCharacter,
identifierCharacter: this.identifierCharacter,
escapeInserts: this.escapeInserts,
schemaName: this.schemaName
};

// Get the attribute identity (as opposed to the table name)
var identity = currentTable;
// Create the query with the tablename aliased as the identity (in case they are different)
var query = 'UPDATE ' + utils.escapeName(currentTable, this.escapeCharacter, this.schemaName) + ' AS ' + utils.escapeName(identity, this.escapeCharacter) + ' ';
var query = 'UPDATE ' + utils.escapeName(currentTable, this.identifierCharacter, this.schemaName) + ' AS ' + utils.escapeName(identity, this.identifierCharacter) + ' ';

// Transform the Data object into arrays used in a parameterized query
var attributes = utils.mapAttributes(data, options);
Expand Down Expand Up @@ -248,7 +251,7 @@ Sequel.prototype.destroy = function destroy(currentTable, queryObject) {
// Get the attribute identity (as opposed to the table name)
var identity = currentTable;

var query = 'DELETE ' + (this.declareDeleteAlias ? utils.escapeName(identity, this.escapeCharacter) : '') + ' FROM ' + utils.escapeName(currentTable, this.escapeCharacter, this.schemaName) + ' AS ' + utils.escapeName(identity, this.escapeCharacter) + ' ';
var query = 'DELETE ' + (this.declareDeleteAlias ? utils.escapeName(identity, this.identifierCharacter) : '') + ' FROM ' + utils.escapeName(currentTable, this.identifierCharacter, this.schemaName) + ' AS ' + utils.escapeName(identity, this.identifierCharacter) + ' ';

// Build Criteria clause
var whereObject = this.simpleWhere(currentTable, queryObject);
Expand All @@ -273,7 +276,7 @@ Sequel.prototype.destroy = function destroy(currentTable, queryObject) {

Sequel.prototype.select = function select(currentTable, queryObject) {
var options = {
escapeCharacter: this.escapeCharacter,
identifierCharacter: this.identifierCharacter,
caseSensitive: this.caseSensitive,
cast: this.cast,
wlNext: this.wlNext,
Expand All @@ -291,7 +294,7 @@ Sequel.prototype.simpleWhere = function simpleWhere(currentTable, queryObject, o
var _options = {
parameterized: this.parameterized,
caseSensitive: this.caseSensitive,
escapeCharacter: this.escapeCharacter,
identifierCharacter: this.identifierCharacter,
wlNext: this.wlNext,
schemaName: this.schemaName
};
Expand All @@ -304,7 +307,7 @@ Sequel.prototype.complexWhere = function complexWhere(currentTable, queryObject,
var _options = {
parameterized: this.parameterized,
caseSensitive: this.caseSensitive,
escapeCharacter: this.escapeCharacter,
identifierCharacter: this.identifierCharacter,
schemaName: this.schemaName
};

Expand Down
6 changes: 3 additions & 3 deletions sequel/lib/cast.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* Cast special values to proper types.
*
* Ex: Array is stored as "[0,1,2,3]" and should be cast to proper
* Ex: Array is stored as '[0,1,2,3]' and should be cast to proper
* array for return values.
*/

Expand All @@ -27,7 +27,7 @@ Query.prototype.cast = function(values) {

Query.prototype.castValue = function(key, value, attributes, schema, joinKey) {

// Check if key is a special "join" key, identified with a '__' split
// Check if key is a special 'join' key, identified with a '__' split
var attr = key.split('__');
if(attr.length === 2) {

Expand All @@ -38,7 +38,7 @@ Query.prototype.castValue = function(key, value, attributes, schema, joinKey) {
}
}

// Lookup Schema "Type"
// Lookup Schema 'Type'
if(!schema[key]) return;
var type = schema[key].type;
if(!type) return;
Expand Down
52 changes: 29 additions & 23 deletions sequel/lib/criteriaProcessor.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ var CriteriaProcessor = module.exports = function CriteriaProcessor(currentTable
this.paramCount = 1;
this.parameterized = true;
this.caseSensitive = true;
this.escapeCharacter = '"';
this.identifierCharacter = '`';
this.escapeCharacter = '\'';
this.wlNext = {};

if(options && utils.object.hasOwnProperty(options, 'parameterized')) {
Expand All @@ -54,8 +55,8 @@ var CriteriaProcessor = module.exports = function CriteriaProcessor(currentTable
this.caseSensitive = options.caseSensitive;
}

if(options && utils.object.hasOwnProperty(options, 'escapeCharacter')) {
this.escapeCharacter = options.escapeCharacter;
if(options && utils.object.hasOwnProperty(options, 'identifierCharacter')) {
this.identifierCharacter = options.identifierCharacter;
}

if(options && utils.object.hasOwnProperty(options, 'paramCount')) {
Expand Down Expand Up @@ -325,13 +326,13 @@ CriteriaProcessor.prototype._in = function _in(key, val) {
// Check case sensitivity to decide if LOWER logic is used
if(!caseSensitivity) {
if(lower) {
key = 'LOWER(' + utils.escapeName(self.getTableAlias(), self.escapeCharacter, self.schemaName) + '.' + utils.escapeName(key, self.escapeCharacter) + ')';
key = 'LOWER(' + utils.escapeName(self.getTableAlias(), self.identifierCharacter, self.schemaName) + '.' + utils.escapeName(key, self.identifierCharacter) + ')';
} else {
key = utils.escapeName(self.getTableAlias(), self.escapeCharacter, self.schemaName) + '.' + utils.escapeName(key, self.escapeCharacter);
key = utils.escapeName(self.getTableAlias(), self.identifierCharacter, self.schemaName) + '.' + utils.escapeName(key, self.identifierCharacter);
}
self.queryString += key + ' IN (';
} else {
self.queryString += utils.escapeName(self.getTableAlias(), self.escapeCharacter, self.schemaName) + '.' + utils.escapeName(key, self.escapeCharacter) + ' IN (';
self.queryString += utils.escapeName(self.getTableAlias(), self.identifierCharacter, self.schemaName) + '.' + utils.escapeName(key, self.identifierCharacter) + ' IN (';
}

// Append each value to query
Expand All @@ -349,7 +350,7 @@ CriteriaProcessor.prototype._in = function _in(key, val) {
}
else {
if(_.isString(value)) {
value = '"' + utils.escapeString(value) + '"';
value = utils.wrapValue(utils.escapeString(value), self.escapeCharacter);
}

self.queryString += value + ',';
Expand Down Expand Up @@ -377,7 +378,7 @@ CriteriaProcessor.prototype.buildParam = function buildParam (tableName, propert
var escape = utils.escapeName,
param;

param = escape(tableName, this.escapeCharacter, this.schemaName) + '.' + escape(property, this.escapeCharacter);
param = escape(tableName, this.identifierCharacter, this.schemaName) + '.' + escape(property, this.identifierCharacter);

if (caseSensitive) {
param = 'LOWER(' + param + ')';
Expand Down Expand Up @@ -483,7 +484,7 @@ CriteriaProcessor.prototype.processSimple = function processSimple (tableName, p
}

if (_.isString(value)) {
value = '"' + utils.escapeString(value) +'"';
value = utils.wrapValue(utils.escapeString(value), self.escapeCharacter);
}

this.queryString += parent + ' ' + combinator + ' ' + value;
Expand Down Expand Up @@ -511,7 +512,7 @@ CriteriaProcessor.prototype.processObject = function processObject (tableName, p
// Expand criteria object
function expandCriteria (obj) {
var child = self.findChild(parent),
sensitiveTypes = ['text', 'string'], // haha, "sensitive types". "I'll watch 'the notebook' with you, babe."
sensitiveTypes = ['text', 'string'], // haha, 'sensitive types'. 'I'll watch \'the notebook\' with you, babe.'
lower;

_.keys(obj).forEach(function(key) {
Expand Down Expand Up @@ -606,7 +607,7 @@ CriteriaProcessor.prototype.prepareCriterion = function prepareCriterion(key, va
('00' + value.getMinutes()).slice(-2) + ':' +
('00' + value.getSeconds()).slice(-2);

value = '"' + value + '"';
value = utils.wrapValue(value, self.escapeCharacter);
escapedDate = true;
}

Expand All @@ -621,7 +622,7 @@ CriteriaProcessor.prototype.prepareCriterion = function prepareCriterion(key, va
}
else {
if(_.isString(value) && !escapedDate) {
value = '"' + utils.escapeString(value) + '"';
value = utils.wrapValue(utils.escapeString(value), self.escapeCharacter);
}
str = '< ' + value;
}
Expand All @@ -637,7 +638,7 @@ CriteriaProcessor.prototype.prepareCriterion = function prepareCriterion(key, va
}
else {
if(_.isString(value) && !escapedDate) {
value = '"' + utils.escapeString(value) + '"';
value = utils.wrapValue(utils.escapeString(value), self.escapeCharacter);
}
str = '<= ' + value;
}
Expand All @@ -653,7 +654,7 @@ CriteriaProcessor.prototype.prepareCriterion = function prepareCriterion(key, va
}
else {
if(_.isString(value) && !escapedDate) {
value = '"' + utils.escapeString(value) + '"';
value = utils.wrapValue(utils.escapeString(value), self.escapeCharacter);
}
str = '> ' + value;
}
Expand All @@ -669,7 +670,7 @@ CriteriaProcessor.prototype.prepareCriterion = function prepareCriterion(key, va
}
else {
if(_.isString(value) && !escapedDate) {
value = '"' + utils.escapeString(value) + '"';
value = utils.wrapValue(utils.escapeString(value), self.escapeCharacter);;
}
str = '>= ' + value;
}
Expand Down Expand Up @@ -706,7 +707,7 @@ CriteriaProcessor.prototype.prepareCriterion = function prepareCriterion(key, va
value.forEach(function(val) {

if(_.isString(val)) {
val = '"' + utils.escapeString(val) + '"';
val = utils.wrapValue(utils.escapeString(val), self.escapeCharacter);
}

str += val + ',';
Expand All @@ -724,7 +725,7 @@ CriteriaProcessor.prototype.prepareCriterion = function prepareCriterion(key, va
}
else {
if(_.isString(value)) {
value = '"' + utils.escapeString(value) + '"';
value = utils.wrapValue(utils.escapeString(value), self.escapeCharacter);;
}

str = '<> ' + value;
Expand Down Expand Up @@ -754,7 +755,7 @@ CriteriaProcessor.prototype.prepareCriterion = function prepareCriterion(key, va
}
else {
// Note that wildcards are not escaped out of like criterion intentionally
str = comparator + ' "' + utils.escapeString(value) + '"';
str = comparator + ' ' + utils.wrapValue(utils.escapeString(value), self.escapeCharacter);
}

break;
Expand All @@ -778,7 +779,7 @@ CriteriaProcessor.prototype.prepareCriterion = function prepareCriterion(key, va
str = comparator + ' ' + '$' + this.paramCount;
}
else {
str = comparator + ' "%' + utils.escapeString(value, true) + '%"';
str = comparator + ' ' + utils.wrapValue('%' + utils.escapeString(value, true) + '%', self.escapeCharacter);
}

break;
Expand All @@ -802,7 +803,7 @@ CriteriaProcessor.prototype.prepareCriterion = function prepareCriterion(key, va
str = comparator + ' ' + '$' + this.paramCount;
}
else {
str = comparator + ' "' + utils.escapeString(value, true) + '%"';
str = comparator + ' ' + utils.wrapValue(utils.escapeString(value, true) + '%', self.escapeCharacter);
}

break;
Expand All @@ -826,10 +827,15 @@ CriteriaProcessor.prototype.prepareCriterion = function prepareCriterion(key, va
str = comparator + ' ' + '$' + this.paramCount;
}
else {
str = comparator + ' "%' + utils.escapeString(value, true) + '"';
str = comparator + ' ' + utils.wrapValue('%' + utils.escapeString(value, true), self.escapeCharacter);
}

break;

default:
var err = new Error('Unknown filtering operator: \'' + key + '\'. Should be \'startsWith\', \'>\', \'contains\' or similar');
err.operator = key;
throw err;
}

// Bump paramCount
Expand Down Expand Up @@ -877,7 +883,7 @@ CriteriaProcessor.prototype.sort = function(options) {

keys.forEach(function(key) {
var direction = options[key] === 1 ? 'ASC' : 'DESC';
self.queryString += utils.escapeName(self.currentTable, self.escapeCharacter, self.schemaName) + '.' + utils.escapeName(key, self.escapeCharacter) + ' ' + direction + ', ';
self.queryString += utils.escapeName(self.currentTable, self.identifierCharacter, self.schemaName) + '.' + utils.escapeName(key, self.identifierCharacter) + ' ' + direction + ', ';
});

// Remove trailing comma
Expand All @@ -899,7 +905,7 @@ CriteriaProcessor.prototype.group = function(options) {
options.forEach(function(key) {
// Check whether we are grouping by a column or an expression.
if (_.includes(_.keys(self.currentSchema), key)) {
self.queryString += utils.escapeName(self.currentTable, self.escapeCharacter, self.schemaName) + '.' + utils.escapeName(key, self.escapeCharacter) + ', ';
self.queryString += utils.escapeName(self.currentTable, self.identifierCharacter, self.schemaName) + '.' + utils.escapeName(key, self.identifierCharacter) + ', ';
} else {
self.queryString += key + ', ';
}
Expand Down
Loading

0 comments on commit 951af8f

Please sign in to comment.