UNPKG

sql-from-mongo

Version:

Simple conversion from MongoDB-like syntax to SQL WHERE clauses

263 lines (258 loc) 10.3 kB
// Generated by CoffeeScript 1.9.3 (function() { var sqlFromMongo; sqlFromMongo = function(mongoQueryObject, collectionName, fields) { var JOIN_LOOKUP, field, fieldStringParts, fieldsString, key, keys, parseSingleKeyValuePair, parts, prefix, sql, subObject, type, value; if ((fields != null) && (collectionName == null)) { throw new Error("Must provide a collectionName if fields is provided."); } JOIN_LOOKUP = { $and: " AND ", $or: " OR ", $nor: " OR " }; type = (function() { var classToType, i, len, name, ref; classToType = {}; ref = "Boolean Number String Function Array Date RegExp Undefined Null".split(" "); for (i = 0, len = ref.length; i < len; i++) { name = ref[i]; classToType["[object " + name + "]"] = name.toLowerCase(); } return function(obj) { var strType; strType = Object.prototype.toString.call(obj); return classToType[strType] || "object"; }; })(); if (type(mongoQueryObject) === 'string' && mongoQueryObject.toUpperCase().indexOf('SELECT') === 0) { return mongoQueryObject; } parseSingleKeyValuePair = function(key, value, collectionName) { var i, joinOperator, key2, keys, len, maxDistance, minDistance, o, parts, s, value2, valueKey, valueValue; switch (key) { case "$not": s = sqlFromMongo(value, collectionName); if (s.indexOf("(") === 0) { return "NOT " + s; } else { return "NOT (" + s + ")"; } break; case "$and": case "$or": case "$nor": if (type(value) !== "array") { throw new Error("Use of $and, $or, or $nor operator requires an array as its parameter."); } parts = []; for (i = 0, len = value.length; i < len; i++) { o = value[i]; parts.push(sqlFromMongo(o, collectionName)); } joinOperator = JOIN_LOOKUP[key]; s = "(" + parts.join(joinOperator) + ")"; if (key === "$nor") { return "NOT " + s; } else { return s; } break; default: if (type(value) === "object") { parts = []; s = (prefix + key) + " "; for (valueKey in value) { valueValue = value[valueKey]; switch (valueKey) { case "$lt": parts.push(s + ("< " + (JSON.stringify(valueValue)))); break; case "$gt": parts.push(s + ("> " + (JSON.stringify(valueValue)))); break; case "$lte": parts.push(s + ("<= " + (JSON.stringify(valueValue)))); break; case "$gte": parts.push(s + (">= " + (JSON.stringify(valueValue)))); break; case "$ne": parts.push(s + ("<> " + (JSON.stringify(valueValue)))); break; case "$eq": parts.push(s + ("= " + (JSON.stringify(valueValue)))); break; case "$in": if (type(valueValue) === 'array') { if (valueValue.length > 100) { throw new Error("In DocumentDB the maximum number of values per IN expression is 100"); } s = JSON.stringify(valueValue); s = s.substr(1, s.length - 2); return (prefix + key) + " IN (" + s + ")"; } else { return "ARRAY_CONTAINS(" + (prefix + valueValue) + ", " + key + ")"; } break; case "$nin": if (type(valueValue) === 'array') { if (valueValue.length > 100) { throw new Error("In DocumentDB the maximum number of values per IN expression is 100"); } s = JSON.stringify(valueValue); s = s.substr(1, s.length - 2); return "NOT " + (prefix + key) + " IN (" + s + ")"; } else { return "NOT ARRAY_CONTAINS(" + (prefix + valueValue) + ", " + key + ")"; } break; case "$size": return "ARRAY_LENGTH(" + (prefix + key) + ") = " + valueValue; case "$exists": if (valueValue) { return "IS_DEFINED(" + (prefix + key) + ")"; } else { return "NOT IS_DEFINED(" + (prefix + key) + ")"; } break; case "$isArray": if (valueValue) { return "IS_ARRAY(" + (prefix + key) + ")"; } else { return "NOT IS_ARRAY(" + (prefix + key) + ")"; } break; case "$isBool": if (valueValue) { return "IS_BOOL(" + (prefix + key) + ")"; } else { return "NOT IS_BOOL(" + (prefix + key) + ")"; } break; case "$isNull": if (valueValue) { return "IS_NULL(" + (prefix + key) + ")"; } else { return "NOT IS_NULL(" + (prefix + key) + ")"; } break; case "$isNumber": if (valueValue) { return "IS_NUMBER(" + (prefix + key) + ")"; } else { return "NOT IS_NUMBER(" + (prefix + key) + ")"; } break; case "$isObject": if (valueValue) { return "IS_OBJECT(" + (prefix + key) + ")"; } else { return "NOT IS_OBJECT(" + (prefix + key) + ")"; } break; case "$isString": if (valueValue) { return "IS_STRING(" + (prefix + key) + ")"; } else { return "NOT IS_STRING(" + (prefix + key) + ")"; } break; case "$isPrimitive": if (valueValue) { return "IS_PRIMITIVE(" + (prefix + key) + ")"; } else { return "NOT IS_PRIMITIVE(" + (prefix + key) + ")"; } break; case "$startsWith": return "STARTSWITH(" + (prefix + key) + ", " + (JSON.stringify(valueValue)) + ")"; case "$endsWith": return "ENDSWITH(" + (prefix + key) + ", " + (JSON.stringify(valueValue)) + ")"; case "$contains": return "CONTAINS(" + (prefix + key) + ", " + (JSON.stringify(valueValue)) + ")"; case "$geoWithin": return "ST_WITHIN(" + (prefix + key) + ", " + (JSON.stringify(valueValue)) + ")"; case "$near": maxDistance = valueValue.$maxDistance; minDistance = valueValue.$minDistance; if (maxDistance != null) { if (minDistance != null) { return "(ST_DISTANCE(" + (prefix + key) + ", " + (JSON.stringify(valueValue.$geometry)) + ") <= " + maxDistance + " AND ST_DISTANCE(" + (prefix + key) + ", " + (JSON.stringify(valueValue.$geometry)) + ") >= " + minDistance + ")"; } else { return "ST_DISTANCE(" + (prefix + key) + ", " + (JSON.stringify(valueValue.$geometry)) + ") <= " + maxDistance; } } if (minDistance != null) { return "ST_DISTANCE(" + (prefix + key) + ", " + (JSON.stringify(valueValue.$geometry)) + ") >= " + minDistance; } else { throw new Error("No minDistance nor maxDistance found in {" + (prefix + key) + ": " + (JSON.stringify(value)) + "}"); } break; default: throw new Error("sql-from-mongo does not recognize {" + (prefix + key) + ": " + (JSON.stringify(value)) + "}"); } } keys = []; for (key2 in value) { value2 = value[key2]; keys.push(key2); } if (keys.length === 1) { return parts[0]; } else { return "(" + parts.join(" AND ") + ")"; } } else { return (prefix + key) + " = " + (JSON.stringify(value)); } } }; if ((collectionName != null) && collectionName.length > 0) { prefix = collectionName + "."; } else { prefix = ""; } keys = []; for (key in mongoQueryObject) { value = mongoQueryObject[key]; keys.push(key); } if (keys.length === 1) { parts = [parseSingleKeyValuePair(keys[0], mongoQueryObject[keys[0]], collectionName)]; } else { parts = []; for (key in mongoQueryObject) { value = mongoQueryObject[key]; subObject = {}; subObject[key] = value; parts.push(sqlFromMongo(subObject, collectionName)); } } if (parts.length === 1) { sql = parts[0]; } else { sql = "(" + parts.join(" AND ") + ")"; } if (fields != null) { if (fields === '*' || (fields[0] === '*') || fields === true) { fieldsString = '*'; } else { fieldStringParts = (function() { var i, len, results; results = []; for (i = 0, len = fields.length; i < len; i++) { field = fields[i]; results.push(prefix + field); } return results; })(); fieldsString = fieldStringParts.join(", "); } sql = ("SELECT " + fieldsString + " FROM " + collectionName + " WHERE ") + sql; } return sql; }; exports.sqlFromMongo = sqlFromMongo; }).call(this); //# sourceMappingURL=sql-from-mongo.js.map