New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More

flora-sql-parser

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

flora-sql-parser - npm Package Compare versions

Comparing version

to
1.0.0

@@ -18,13 +18,6 @@ 'use strict';

function escape(str) {
const res = [];
let char;
for (let i = 0, l = str.length; i < l; ++i) {
char = str[i];
const escaped = escapeMap[char];
if (escaped) char = escaped;
res.push(char);
}
return res.join('');
return str
.split('')
.map((char) => (!has(escapeMap, char) ? char : escapeMap[char]))
.join('');
}

@@ -48,2 +41,6 @@

else if (type === 'param') value = ':' + value;
else if (type === 'interval') {
const sign = literal.sign ? literal.sign + ' ' : '';
value = `INTERVAL ${sign}'${escape(value)}' ${literal.qualifier}`;
}

@@ -53,21 +50,6 @@ return !literal.parentheses ? value : '(' + value + ')';

let exprToSQLConvertFn = {};
function exprToSQL(expr) {
return exprToSQLConvertFn[expr.type] ? exprToSQLConvertFn[expr.type](expr) : literalToSQL(expr);
function aggrToSQL({ name: fnName, quantifier, args }) {
return fnName + '(' + (quantifier ? quantifier + ' ' : '') + exprToSQL(args.expr) + ')';
}
function aggrToSQL(expr) {
/** @type {Object} */
const args = expr.args;
let str = exprToSQL(args.expr);
const fnName = expr.name;
if (fnName === 'COUNT') {
if (has(args, 'distinct') && args.distinct !== null) str = 'DISTINCT ' + str;
}
return fnName + '(' + str + ')';
}
function binaryToSQL(expr) {

@@ -141,3 +123,3 @@ let operator = expr.operator;

return columns
.map(column => {
.map((column) => {
let str = exprToSQL(column.expr);

@@ -166,4 +148,7 @@

if (baseTable.db && baseTable.db !== null) str = baseTable.db + '.' + str;
if (baseTable.db) str = baseTable.db + '.' + str;
if (baseTable.as !== null) str += ' AS ' + identifierToSql(baseTable.as);
if (Array.isArray(baseTable.columns) && baseTable.columns.length) {
str += ' (' + baseTable.columns.map(identifierToSql).join(', ') + ')';
}

@@ -175,3 +160,3 @@ clauses.push(str);

str = joinExpr.join && joinExpr.join !== null ? ' ' + joinExpr.join + ' ' : (str = ', ');
str = joinExpr.join ? ' ' + joinExpr.join + (joinExpr.lateral ? ' LATERAL' : '') + ' ' : (str = ', ');

@@ -186,2 +171,5 @@ if (joinExpr.table) {

if (joinExpr.as !== null) str += ' AS ' + identifierToSql(joinExpr.as);
if (has(joinExpr, 'columns') && Array.isArray(joinExpr.columns) && joinExpr.columns.length) {
str += ' (' + joinExpr.columns.map(identifierToSql).join(', ') + ')';
}
if (has(joinExpr, 'on') && joinExpr.on !== null) str += ' ON ' + exprToSQL(joinExpr.on);

@@ -197,3 +185,3 @@ if (has(joinExpr, 'using')) str += ' USING (' + joinExpr.using.map(identifierToSql).join(', ') + ')';

/**
* @param {Array<Object>} withExpr
* @param {Object} withExpr
*/

@@ -203,5 +191,5 @@ function withToSql(withExpr) {

'WITH ' +
(withExpr[0].recursive ? 'RECURSIVE ' : '') +
withExpr
.map(cte => {
(withExpr.recursive ? 'RECURSIVE ' : '') +
withExpr.value
.map((cte) => {
const name = `"${cte.name}"`;

@@ -220,3 +208,3 @@ const columns = Array.isArray(cte.columns) ? '(' + cte.columns.join(', ') + ')' : '';

* @param {?Array} stmt.options
* @param {?string} stmt.distinct
* @param {string|null} stmt.distinct
* @param {?Array|string} stmt.columns

@@ -234,8 +222,7 @@ * @param {?Array} stmt.from

if (has(stmt, 'with') && Array.isArray(stmt.with)) clauses.unshift(withToSql(stmt.with));
if (has(stmt, 'with') && stmt.with !== null) clauses.unshift(withToSql(stmt.with));
if (has(stmt, 'options') && Array.isArray(stmt.options)) clauses.push(stmt.options.join(' '));
if (has(stmt, 'distinct') && stmt.distinct !== null) clauses.push(stmt.distinct);
if (stmt.columns !== '*') clauses.push(columnsToSQL(stmt.columns));
else clauses.push('*');
clauses.push(stmt.columns !== '*' ? columnsToSQL(stmt.columns) : '*');

@@ -251,3 +238,3 @@ // FROM + joins

if (Array.isArray(stmt.orderby) && stmt.orderby.length > 0) {
const orderExpressions = stmt.orderby.map(expr => exprToSQL(expr.expr) + ' ' + expr.type);
const orderExpressions = stmt.orderby.map((expr) => exprToSQL(expr.expr) + ' ' + expr.type);
clauses.push('ORDER BY', orderExpressions.join(', '));

@@ -266,2 +253,12 @@ }

function rowValueToSQL(expr) {
const needsKeyword = expr.keyword === true;
return (needsKeyword ? 'ROW' : '') + '(' + expr.value.map(exprToSQL) + ')';
}
function valuesToSQL(expr) {
const str = 'VALUES ' + expr.value.map(exprToSQL).join(', ');
return `(${str})`;
}
function unionToSQL(stmt) {

@@ -278,3 +275,3 @@ const res = [selectToSQL(stmt)];

exprToSQLConvertFn = {
const exprToSQLConvertFn = {
aggr_func: aggrToSQL,

@@ -285,3 +282,3 @@ binary_expr: binaryToSQL,

column_ref: columnRefToSQL,
expr_list: expr => {
expr_list: (expr) => {
const str = getExprListSQL(expr.value);

@@ -291,9 +288,15 @@ return !expr.parentheses ? str : `(${str})`;

function: funcToSQL,
select: expr => {
select: (expr) => {
const str = typeof expr._next !== 'object' ? selectToSQL(expr) : unionToSQL(expr);
return !expr.parentheses ? str : `(${str})`;
},
unary_expr: unaryToSQL
unary_expr: unaryToSQL,
values: valuesToSQL,
row_value: rowValueToSQL
};
function exprToSQL(expr) {
return exprToSQLConvertFn[expr.type] ? exprToSQLConvertFn[expr.type](expr) : literalToSQL(expr);
}
module.exports = function toSQL(ast) {

@@ -300,0 +303,0 @@ if (ast.type !== 'select') throw new Error('Only SELECT statements supported at the moment');

@@ -12,13 +12,11 @@ 'use strict';

function createValueExpr(value) {
let expr;
const type = typeof value;
if (Array.isArray(value)) expr = { type: 'expr_list', value: value.map(createValueExpr) };
else if (type === 'boolean') expr = { type: 'bool', value };
else if (type === 'string') expr = { type: 'string', value };
else if (type === 'number') expr = { type: 'number', value };
else if (value === null) expr = { type: 'null', value: null };
else throw new ImplementationError('Cannot convert value "' + value + '" to SQL');
if (Array.isArray(value)) return { type: 'expr_list', value: value.map(createValueExpr) };
if (type === 'boolean') return { type: 'bool', value };
if (type === 'string') return { type: 'string', value };
if (type === 'number') return { type: 'number', value };
if (value === null) return { type: 'null', value };
return expr;
throw new ImplementationError(`Cannot convert value "${value}" to SQL`);
}

@@ -33,6 +31,8 @@

function createBinaryExpr(operator, left, right) {
const expr = { operator, type: 'binary_expr' };
const expr = {
operator,
type: 'binary_expr',
left: left && left.type ? left : createValueExpr(left)
};
expr.left = left && left.type ? (expr.left = left) : createValueExpr(left);
if (operator === 'BETWEEN' || operator === 'NOT BETWEEN') {

@@ -44,3 +44,3 @@ expr.right = {

} else {
expr.right = right && right.type ? (expr.right = right) : (expr.right = createValueExpr(right));
expr.right = right && right.type ? right : createValueExpr(right);
}

@@ -60,7 +60,7 @@

Object.keys(ast)
.filter(key => {
.filter((key) => {
const value = ast[key];
return Array.isArray(value) || (typeof value === 'object' && value !== null);
})
.forEach(key => {
.forEach((key) => {
const expr = ast[key];

@@ -67,0 +67,0 @@

{
"name": "flora-sql-parser",
"version": "0.9.4",
"version": "1.0.0",
"description": "Parse SQL (select) statements into abstract syntax tree (AST) and convert ASTs back to SQL.",

@@ -9,4 +9,5 @@ "main": "index.js",

"pretest": "npm run build",
"test": "mocha",
"test": "mocha --recursive",
"lint": "eslint .",
"lint-fix": "eslint --fix .",
"prepack": "npm run build"

@@ -49,3 +50,3 @@ },

"engines": {
"node": ">=10"
"node": ">=12"
},

@@ -57,13 +58,11 @@ "dependencies": {

"devDependencies": {
"@types/chai": "^4.1.7",
"@types/mocha": "^5.2.7",
"chai": "^4.2.0",
"eslint": "^6.0.1",
"eslint-config-prettier": "^6.0.0",
"eslint-plugin-prettier": "^3.1.0",
"mocha": "^6.1.4",
"chai": "^4.3.4",
"eslint": "^8.3.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.0.0",
"mocha": "^9.1.3",
"pegjs": "^0.10.0",
"pre-commit": "^1.2.2",
"prettier": "^1.18.2"
"prettier": "^2.4.1"
}
}
# Flora SQL Parser
[![Build Status](https://travis-ci.org/godmodelabs/flora-sql-parser.svg?branch=master)](https://travis-ci.org/godmodelabs/flora-sql-parser)
[![NPM version](https://badge.fury.io/js/flora-sql-parser.svg)](https://www.npmjs.com/package/flora-sql-parser)
[![Dependencies](https://img.shields.io/david/godmodelabs/flora-sql-parser.svg)](https://david-dm.org/godmodelabs/flora-sql-parser)
![](https://github.com/godmodelabs/flora-sql-parser/workflows/ci/badge.svg)
[![NPM version](https://img.shields.io/npm/v/flora-sql-parser.svg?style=flat)](https://www.npmjs.com/package/flora-sql-parser)
[![NPM downloads](https://img.shields.io/npm/dm/flora-sql-parser.svg?style=flat)](https://www.npmjs.com/package/flora-sql-parser)

@@ -7,0 +7,0 @@ Parse simple SQL statements into an abstract syntax tree (AST) and convert it back to SQL.

Sorry, the diff of this file is too big to display