224 lines
4.4 KiB
JavaScript
Executable File
224 lines
4.4 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
|
|
const fs = require('fs');
|
|
const assert = require('assert');
|
|
|
|
const lines = fs.readFileSync(process.argv[2], {encoding:'utf8'}).split("\n");
|
|
|
|
function getRecordStream(lineList)
|
|
{
|
|
var recs = [];
|
|
const blankRx = /^\s*$/;
|
|
lineList.forEach(function(line) {
|
|
if (blankRx.test(line))
|
|
return;
|
|
|
|
try {
|
|
const record = JSON.parse(line);
|
|
recs.push(record);
|
|
} catch (e) {
|
|
console.error("Invalid line: ", line);
|
|
console.error(e);
|
|
}
|
|
});
|
|
|
|
return recs;
|
|
}
|
|
|
|
function parseRecordStream(recs)
|
|
{
|
|
var stk = [];
|
|
var ret = null;
|
|
|
|
recs.forEach(function(current) {
|
|
if (current.op && current.op == 'DEFINE-COL') {
|
|
var objColumn = {
|
|
name: current.name,
|
|
flags: current.flags,
|
|
attr: [],
|
|
};
|
|
while (stk.length > 0) {
|
|
const rec = stk.pop();
|
|
if ('attr' in rec)
|
|
objColumn.attr.push(rec);
|
|
else if ('type' in rec)
|
|
objColumn.type = rec.type;
|
|
else if (rec.op && rec.op == 'START-COL')
|
|
break;
|
|
else {
|
|
assert.fail('unhandled rec: ' + JSON.stringify(rec));
|
|
}
|
|
}
|
|
stk.push(objColumn);
|
|
|
|
} else if (current.op && current.op == 'CREATE-TABLE') {
|
|
var objTable = {
|
|
verb: 'CREATE_TABLE',
|
|
name: current.name,
|
|
temp: current.temp,
|
|
if_n_exists: current.if_n_exists,
|
|
columns: [],
|
|
};
|
|
var wantCols = current.n_cols;
|
|
while (wantCols-- > 0) {
|
|
const col = stk.pop();
|
|
assert(col !== undefined);
|
|
|
|
objTable.columns.push(col);
|
|
}
|
|
stk.push(objTable);
|
|
|
|
} else if (current.op && current.op == 'DROP-TABLE') {
|
|
var objTab = {
|
|
verb: 'DROP_TABLE',
|
|
temp: current.temp,
|
|
if_exists: current.if_exists,
|
|
tables: [],
|
|
};
|
|
|
|
var wantTabs = current.n_tables;
|
|
while (wantTabs-- > 0) {
|
|
const tab = stk.pop();
|
|
assert(tab !== undefined);
|
|
|
|
objTab.tables.push(tab.name);
|
|
}
|
|
|
|
stk.push(objTab);
|
|
|
|
} else if (current.op && current.op == 'INSERT') {
|
|
var objInsert = {
|
|
verb: 'INSERT',
|
|
tbl_name: current.tbl_name,
|
|
opts: current.opts,
|
|
values: [],
|
|
columns: [],
|
|
};
|
|
|
|
var wantVals = current.n_vals;
|
|
while (wantVals-- > 0) {
|
|
const val = stk.pop();
|
|
assert(val !== undefined);
|
|
|
|
objInsert.values.unshift(val.values);
|
|
}
|
|
|
|
var wantCols = current.n_cols;
|
|
assert(wantCols <= 1);
|
|
|
|
if (wantCols > 0) {
|
|
const val = stk.pop();
|
|
assert(val !== undefined);
|
|
|
|
objInsert.columns = val;
|
|
}
|
|
|
|
stk.push(objInsert);
|
|
|
|
} else if ('INSERT-COLS' in current) {
|
|
var arrCols = [];
|
|
|
|
var wantVals = current['INSERT-COLS'];
|
|
while (wantVals-- > 0) {
|
|
const val = stk.pop();
|
|
assert(val !== undefined);
|
|
|
|
arrCols.unshift(val['COLUMN']);
|
|
}
|
|
|
|
stk.push(arrCols);
|
|
|
|
} else if (current.op && current.op == 'CREATE-DB') {
|
|
var objDb = {
|
|
verb: 'CREATE_DATABASE',
|
|
name: current.name,
|
|
if_ne: current.if_ne,
|
|
};
|
|
stk.push(objDb);
|
|
|
|
} else if (current.op && current.op == 'DROP-DB') {
|
|
var objDb = {
|
|
verb: 'DROP_DATABASE',
|
|
name: current.name,
|
|
if_exists: current.if_exists,
|
|
};
|
|
stk.push(objDb);
|
|
|
|
} else if (current.op && current.op == 'SELECT') {
|
|
var objSelect = {
|
|
verb: 'SELECT',
|
|
opts: current.opts,
|
|
tables: [],
|
|
exprs: [],
|
|
};
|
|
var wantTabs = current.n_tbl_ref;
|
|
while (wantTabs-- > 0) {
|
|
const tab = stk.pop();
|
|
assert(tab !== undefined);
|
|
|
|
objSelect.tables.push(tab.name);
|
|
}
|
|
var wantExpr = current.n_expr;
|
|
while (wantExpr-- > 0) {
|
|
const an_expr = stk.pop();
|
|
assert(an_expr !== undefined);
|
|
|
|
objSelect.exprs.push(an_expr);
|
|
}
|
|
stk.push(objSelect);
|
|
|
|
} else if (current.op && current.op == 'STMT') {
|
|
const stmt = stk.pop();
|
|
assert(stk.length === 0);
|
|
|
|
ret = stmt;
|
|
|
|
} else if ('INT/NUMBER' in current) {
|
|
const objVal = {
|
|
type: 'number',
|
|
val: current['INT/NUMBER'],
|
|
};
|
|
stk.push(objVal);
|
|
|
|
} else if ('STRING' in current) {
|
|
const objVal = {
|
|
type: 'string',
|
|
val: current.STRING,
|
|
};
|
|
stk.push(objVal);
|
|
|
|
} else if ('VALUES' in current) {
|
|
const objVal = {
|
|
type: 'value_list',
|
|
values: [],
|
|
};
|
|
var wantVals = current.VALUES;
|
|
while (wantVals-- > 0) {
|
|
const val = stk.pop();
|
|
assert(val !== undefined);
|
|
|
|
objVal.values.unshift(val);
|
|
}
|
|
stk.push(objVal);
|
|
|
|
} else if ('result' in current) {
|
|
// EOF; do nothing
|
|
|
|
} else {
|
|
// console.log("PUSH", current);
|
|
stk.push(current);
|
|
}
|
|
});
|
|
|
|
return ret;
|
|
}
|
|
|
|
const recs = getRecordStream(lines);
|
|
|
|
// console.dir(recs);
|
|
|
|
const stmt = parseRecordStream(recs);
|
|
|
|
console.log(JSON.stringify(stmt, null, 2));
|
|
|