fxsql
Version:
Functional query builder based on fxjs
699 lines (590 loc) • 24.6 kB
JavaScript
"use strict";
var _mapInstanceProperty2 = require("@babel/runtime-corejs3/core-js-stable/instance/map");
var _reduceInstanceProperty2 = require("@babel/runtime-corejs3/core-js-stable/instance/reduce");
var _flatInstanceProperty = require("@babel/runtime-corejs3/core-js-stable/instance/flat");
var _filterInstanceProperty2 = require("@babel/runtime-corejs3/core-js-stable/instance/filter");
var _Object$defineProperty = require("@babel/runtime-corejs3/core-js-stable/object/define-property");
var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault");
_Object$defineProperty(exports, "__esModule", {
value: true
});
exports.MySQL = exports.PostgreSQL = exports.FxSQL_DEBUG = void 0;
var _symbol = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/symbol"));
var _isArray = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/array/is-array"));
var _reduce = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/reduce"));
var _assign = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/object/assign"));
var _concat = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/concat"));
var _map = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/map"));
var _slice = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/slice"));
var _filter = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/filter"));
var _trim = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/trim"));
var _some = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/some"));
var _splice = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/splice"));
var _includes = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/includes"));
var _entries = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/object/entries"));
var _find = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/find"));
var _values = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/values"));
var _keys = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/object/keys"));
var _values2 = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/object/values"));
var _stringify = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/json/stringify"));
var _promise = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/promise"));
var _bind = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/bind"));
var _dumper = _interopRequireDefault(require("dumper.js"));
var _fxjs = require("fxjs");
var _mysql = _interopRequireDefault(require("mysql"));
var _pgPool = _interopRequireDefault(require("pg-pool"));
var _pluralize = _interopRequireDefault(require("pluralize"));
var _ljoin = _interopRequireDefault(require("./ljoin.js"));
const {
dump
} = _dumper.default;
const {
plural,
singular
} = _pluralize.default;
const FxSQL_DEBUG = {
DUMP: false,
LOG: false,
ERROR_WITH_SQL: false
};
exports.FxSQL_DEBUG = FxSQL_DEBUG;
const SymbolColumn = (0, _symbol.default)('COLUMN');
const SymbolTag = (0, _symbol.default)('TAG');
const SymbolInjection = (0, _symbol.default)('INJECTION');
const SymbolDefault = (0, _symbol.default)('DEFAULT');
const wrap_arr = a => (0, _isArray.default)(a) ? a : [a];
const mix = (arr1, arr2) => (0, _reduce.default)(arr1).call(arr1, (res, item, i) => {
res.push(item);
i < arr2.length && res.push(arr2[i]);
return res;
}, []);
const uniq_index_by = (0, _fxjs.curry)((f, coll) => (0, _fxjs.indexBy)(f, (0, _fxjs.uniqueBy)(f, coll)));
const first = a => a && a[0];
const last = a => a && a[a.length - 1];
const is_plain_object = obj => !!obj && typeof obj == 'object' && obj.constructor == Object;
const is_column = f => !!(f && f[SymbolColumn]);
const is_tag = f => !!(f && f[SymbolTag]);
const is_injection = query => query == SymbolInjection;
const tag = f => typeof f == 'function' ? (0, _assign.default)(f, {
[SymbolTag]: true
}) : tag(_ => f);
function BASE({
create_pool,
end_pool,
query_fn,
get_connection = pool => pool.connect(),
BEGIN = client => client.query('BEGIN'),
COMMIT = async client => {
await client.query('COMMIT');
return await client.release();
},
ROLLBACK = async client => {
await client.query('ROLLBACK');
return await client.release();
},
reg_q = /\?\?/g,
to_q = () => '??',
escape_dq = idtf => `"${('' + idtf).replace(/\\/g, '\\\\').replace(/"/g, '""')}"`,
replace_q = query => {
if (is_injection(query)) return SymbolInjection;
let i = 0;
query.text = query.text.replace(reg_q, _ => `$${++i}`);
return query;
},
use_ljoin
}) {
const add_column = me => {
var _context;
return me.column == '*' ? COLUMN(me.as + '.*') : is_column(me.column) ? COLUMN(...(0, _fxjs.go)((0, _concat.default)(_context = me.column.originals).call(_context, (0, _fxjs.pluck)('left_key', me.rels)), (0, _mapInstanceProperty2(_fxjs))(c => (0, _fxjs.isString)(c) ? me.as + '.' + c : c), _fxjs.uniq)) : is_tag(me.column) ? CL(me.column) : tag(SymbolInjection);
};
const columnize = v => {
var _context2;
return v == '*' ? '*' : v.match(/\s*\sas\s\s*/i) ? (0, _map.default)(_context2 = v.split(/\s*\sas\s\s*/i)).call(_context2, dq).join(' AS ') : dq(v);
};
const dq = str => {
var _context3;
return (0, _map.default)(_context3 = ('' + str).split('.')).call(_context3, s => s == '*' ? s : escape_dq(s)).join('.');
};
function ASSOCIATE_MODULE(strs, ...tails) {
var _context4, _context5;
strs = (0, _slice.default)(strs).call(strs);
strs.push(strs.pop() + '\n');
var [strs2, tails2] = import_module(strs, tails);
const splited = (0, _filter.default)(_context4 = (0, _filter.default)(_context5 = (0, _fxjs.deepFlat)((0, _map.default)(strs).call(strs, str => str.split('\n')))).call(_context5, str => str.match(/^\s*/)[0])).call(_context4, str => (0, _trim.default)(str).call(str));
const min = (0, _fxjs.minBy)(str => str.match(/^\s*/)[0].length, splited) || '';
const a = '\n' + min.match(/^\s*/)[0];
return [(0, _map.default)(strs2).call(strs2, str => str.split(a).join('\n')), tails2];
}
function import_module(strs, tails) {
var _context6, _context7;
if (!(0, _some.default)(tails).call(tails, tail => typeof tail == 'function' && !is_tag(tail))) return [strs, tails];
var strs2 = [...strs];
var j = 0;
var tails2 = (0, _map.default)(tails).call(tails, function (tail, i) {
if (typeof tail != 'function' || is_tag(tail)) return tail;
var k = i + j++;
var spaces = last(strs2[k].split('\n')).match(/^\s*/)[0];
var [strs3, tails3] = tail();
(0, _splice.default)(strs2).call(strs2, k + 1, 0, (0, _map.default)(strs3).call(strs3, str => str.replace(/\n/g, '\n' + spaces)));
return tails3;
});
return [(0, _reduce.default)(_context6 = (0, _filter.default)(_context7 = (0, _fxjs.deepFlat)(strs2)).call(_context7, str => (0, _trim.default)(str).call(str))).call(_context6, (strs, str, i) => {
var _context8;
if (i == 0) return strs.push(str), strs;
const splited = last(strs).split('\n');
if (!(0, _trim.default)(_context8 = last(splited)).call(_context8)) {
splited[splited.length - 1] = str.substr(1);
strs[strs.length - 1] = splited.join('\n');
} else {
strs.push(str);
}
return strs;
}, []), (0, _fxjs.deepFlat)(tails2)];
}
function ready_sqls(strs, tails) {
const [strs2, tails2] = import_module(strs, tails);
const options = (0, _map.default)(strs2).call(strs2, s => {
var _context9;
return (0, _map.default)(_context9 = s.replace(/\s*\n/, '').split('\n')).call(_context9, s => {
var _context10;
var depth = s.match(/^\s*/)[0].length,
as = (0, _trim.default)(s).call(s),
rel_type;
var prefix = as.substr(0, 2);
if ((0, _includes.default)(_context10 = ['- ', '< ', 'x ']).call(_context10, prefix)) {
var _context11;
rel_type = (0, _trim.default)(prefix).call(prefix);
as = (0, _trim.default)(_context11 = as.substr(1)).call(_context11);
return {
depth,
as,
rel_type
};
} else if (prefix == 'p ') {
var _context12;
rel_type = as[2];
as = (0, _trim.default)(_context12 = as.substr(3)).call(_context12);
return {
depth,
as,
rel_type,
is_poly: true
};
} else {
return {
depth,
as
};
}
});
});
(0, _fxjs.go)(tails2, (0, _mapInstanceProperty2(_fxjs))(tail => is_tag(tail) ? {
query: tail
} : (0, _assign.default)({}, tail, {
query: tail.query || tag()
})), _entries.default, (0, _fxjs.each)(([i, t]) => (0, _fxjs.go)(options[i], last, _ => (0, _assign.default)(_, t))));
return options;
}
function merge_query(queries, sep = ' ') {
var _context13;
if ((0, _find.default)(queries).call(queries, is_injection)) return SymbolInjection;
var query = (0, _reduceInstanceProperty2(_fxjs))((res, query) => {
if (!query) return res;
if (query.text) res.text += sep + query.text;
if ((0, _values.default)(query)) (0, _values.default)(res).push(...(0, _values.default)(query));
return res;
}, {
text: '',
values: []
}, queries);
query.text = (0, _trim.default)(_context13 = query.text.replace(/\n/g, ' ').replace(/\s\s*/g, ' ')).call(_context13);
return query;
}
function VALUES(values) {
return tag(function () {
var _context14;
values = (0, _isArray.default)(values) ? values : [values];
const columns = (0, _fxjs.go)(values, (0, _mapInstanceProperty2(_fxjs))(_keys.default), _flatInstanceProperty(_fxjs), _fxjs.uniq);
const DEFAULTS = (0, _fxjs.go)(columns, (0, _mapInstanceProperty2(_fxjs))(k => [k, SymbolDefault]), _fxjs.object);
values = (0, _map.default)(_context14 = (0, _map.default)(values).call(values, v => (0, _assign.default)({}, DEFAULTS, v))).call(_context14, v => (0, _values2.default)(v));
return {
text: `(${COLUMN(...columns)().text}) VALUES (${(0, _map.default)(values).call(values, v => (0, _map.default)(v).call(v, v => v == SymbolDefault ? 'DEFAULT' : to_q()).join(', ')).join('), (')})`,
values: (0, _flatInstanceProperty(_fxjs))((0, _map.default)(values).call(values, v => (0, _filter.default)(v).call(v, v => v != SymbolDefault)))
};
});
}
function COLUMN(...originals) {
return (0, _assign.default)(tag(function () {
let sqls = (0, _flatInstanceProperty(_fxjs))((0, _map.default)(originals).call(originals, v => {
var _context15;
return (0, _fxjs.isString)(v) ? [{
text: columnize(v)
}, {
text: ', '
}] : is_tag(v) ? [v(), {
text: ', '
}] : [{
text: (0, _map.default)(_context15 = (0, _entries.default)(v)).call(_context15, v => (0, _map.default)(v).call(v, dq).join(' AS ')).join(', ')
}, {
text: ', '
}];
}));
sqls.pop();
return merge_query(sqls, '');
}), {
[SymbolColumn]: true,
originals: originals
});
}
const CL = COLUMN,
TABLE = COLUMN,
TB = TABLE;
function PARAMS(obj, sep) {
return tag(function () {
var _context16;
let i = 0;
const text = (0, _map.default)(_context16 = (0, _keys.default)(obj)).call(_context16, k => `${columnize(k)} = ${to_q()}`).join(sep);
const values = (0, _values2.default)(obj);
return {
text: text.replace(reg_q, function () {
const value = values[i++];
return is_column(value) ? value().text : to_q();
}),
values: (0, _fxjs.reject)(is_column, values)
};
});
}
function EQ(obj, sep = 'AND') {
return PARAMS(obj, ' ' + sep + ' ');
}
function SET(obj) {
return tag(function () {
const query = PARAMS(obj, ', ')();
query.text = 'SET ' + query.text;
return query;
});
}
function BASE_IN(key, operator, values) {
values = (0, _fxjs.uniq)(values);
var keys_text = COLUMN(...wrap_arr(key))().text;
return {
text: `${(0, _isArray.default)(key) ? `(${keys_text})` : keys_text} ${operator} (${(0, _map.default)(values).call(values, (0, _isArray.default)(key) ? v => `(${(0, _map.default)(v).call(v, to_q).join(', ')})` : to_q).join(', ')})`,
values: (0, _fxjs.deepFlat)(values)
};
}
function IN(key, values) {
return tag(function () {
if (!values || !values.length) return {
text: `1=??`,
values: [0]
};
return BASE_IN(key, 'IN', values);
});
}
function NOT_IN(key, values) {
return tag(function () {
if (!values || !values.length) return {
text: `1=??`,
values: [0]
};
return BASE_IN(key, 'NOT IN', values);
});
}
function _SQL(texts, values) {
return (0, _fxjs.go)(mix((0, _map.default)(texts).call(texts, text => ({
text
})), (0, _map.default)(values).call(values, value => is_tag(value) ? value() : (0, _fxjs.isFunction)(value) ? SymbolInjection : {
text: to_q(),
values: [value]
})), merge_query);
}
function SQL(texts, ...values) {
return tag(function () {
return _SQL(texts, values);
});
}
function SQLS(sqls) {
return tag(function () {
return (0, _find.default)(sqls).call(sqls, sql => !is_tag(sql)) ? SymbolInjection : merge_query((0, _map.default)(sqls).call(sqls, sql => sql()));
});
}
function baseAssociate(QUERY) {
return async function (strs, ...tails) {
return (0, _fxjs.go)(ready_sqls(strs, tails), _fxjs.deepFlat, (0, _filterInstanceProperty2(_fxjs))(t => t.as), (0, _fxjs.each)(option => {
option.column = option.column || '*';
option.join = option.join || SQL``;
option.query = option.query || tag();
option.table = option.table || (option.rel_type == '-' ? plural(option.as) : option.as);
option.rels = [];
option.row_number = option.row_number || [];
}), function setting([left, ...rest]) {
const cur = [left];
(0, _fxjs.each)(me => {
while (!(last(cur).depth < me.depth)) cur.pop();
const left = last(cur);
left.rels.push(me);
if (me.rel_type == '-') {
me.left_key = me.left_key || (me.is_poly ? 'id' : singular(me.table) + '_id');
me.where_key = me.key || (me.is_poly ? 'attached_id' : 'id');
me.xjoin = tag();
} else if (me.rel_type == '<') {
me.left_key = me.left_key || 'id';
me.where_key = me.key || (me.is_poly ? 'attached_id' : singular(left.table) + '_id');
me.xjoin = tag();
} else if (me.rel_type == 'x') {
me.left_key = me.left_key || 'id';
const xtable = me.xtable || left.table + '_' + me.table;
const xtable_as = me.xtable_as || xtable;
me.where_key = `${xtable_as}.${me.left_xkey || singular(left.table) + '_id'}`;
me.xjoin = SQL`INNER JOIN ${TB(xtable)} AS ${TB(xtable_as)} ON ${EQ({
[`${xtable_as}.${me.xkey || singular(me.table) + '_id'}`]: COLUMN(me.as + '.' + (me.key || 'id'))
})}`;
}
me.poly_type = me.is_poly ? SQL`AND ${EQ(is_plain_object(me.poly_type) ? me.poly_type : {
attached_type: me.poly_type || left.table
})}` : tag();
cur.push(me);
}, rest);
return left;
}, async function (me) {
const lefts = await QUERY`
SELECT ${add_column(me)}
FROM ${TB(me.table)} AS ${TB(me.as)} ${me.query}`;
return (0, _fxjs.go)([lefts, me], function recur([lefts, option]) {
return lefts.length && option.rels.length && (0, _fxjs.go)(option.rels, (0, _fxjs.mapC)(async function (me) {
var _context17;
const query = me.query();
if (query && query.text) query.text = query.text.replace(/^\s*WHERE/i, 'AND');
var fold_key = me.rel_type == 'x' ? `_#_${me.where_key.split('.')[1]}_#_` : me.where_key;
const colums = (0, _fxjs.uniq)((0, _concat.default)(_context17 = add_column(me).originals).call(_context17, me.rel_type != 'x' ? me.as + '.' + me.where_key : me.where_key + ' AS ' + fold_key));
const in_vals = (0, _filterInstanceProperty2(_fxjs))(a => a != null, (0, _fxjs.pluck)(me.left_key, lefts));
const is_row_num = me.row_number.length == 2;
const from_sql = SQL`
FROM ${TB(me.table)} AS ${TB(me.as)}
${me.join}
${me.xjoin}
WHERE
${IN((me.rel_type == 'x' ? '' : me.as + '.') + me.where_key, in_vals)}
${me.poly_type}
${tag(query)}`;
const rights = !in_vals.length ? [] : await (is_row_num ? QUERY`
SELECT *
FROM (
SELECT
${COLUMN(...colums)},
ROW_NUMBER() OVER (PARTITION BY ${CL(me.where_key)} ORDER BY ${me.row_number[1]}) as "--row_number--"
${from_sql}
) AS "--row_number_table--"
WHERE "--row_number_table--"."--row_number--"<=${me.row_number[0]}` : QUERY`SELECT ${COLUMN(...colums)} ${from_sql}`);
const [folder, default_value] = me.rel_type == '-' ? [uniq_index_by, () => ({})] : [_fxjs.groupBy, () => []];
return (0, _fxjs.go)(rights, is_row_num ? (0, _mapInstanceProperty2(_fxjs))(r => delete r['--row_number--'] && r) : r => r, folder(a => a[fold_key]), folded => (0, _fxjs.each)(function (left) {
left._ = left._ || {};
left._[me.as] = folded[left[me.left_key]] || default_value();
if (me.rel_type == 'x') (0, _fxjs.each)(a => delete a[fold_key], left._[me.as]);
}, lefts), _ => recur([rights, me]), _ => me.hook && (0, _fxjs.each)(left => (0, _fxjs.go)(me.hook(left._[me.as]), right => left._[me.as] = right), lefts));
}));
}, _ => me.hook ? me.hook(lefts) : lefts);
});
};
}
function CONNECT(connection_info) {
const pool = create_pool(connection_info);
const pool_query = query_fn(pool);
const _on2_obj = {
error: function () {}
};
pool.queryError = cb => {
_on2_obj['error'] = cb;
};
async function base_query(excute_query, texts, values, transaction_querys) {
const error_for_stack = new Error();
try {
var query = replace_q(_SQL(texts, values));
if ((0, _isArray.default)(transaction_querys)) transaction_querys.push({
text: query.text,
values: (0, _stringify.default)((0, _values.default)(query)),
stack: FxSQL_DEBUG.LOG && new Error().stack
});
return await (0, _fxjs.go)(is_injection(query) ? _promise.default.reject('INJECTION ERROR') : query, (0, _fxjs.tap)(function (query) {
if (FxSQL_DEBUG.DUMP) dump(query);
typeof FxSQL_DEBUG.LOG == 'function' ? FxSQL_DEBUG.LOG(query) : FxSQL_DEBUG.LOG && console.log(query.text, '\n', (0, _values.default)(query));
}), excute_query);
} catch (e) {
FxSQL_DEBUG.ERROR_WITH_SQL && (e.stack = `\nFxSQL_DEBUG.ERROR_WITH_SQL:\n text: ${query.text}\n values: ${(0, _stringify.default)((0, _values.default)(query))}\n${e.stack}`);
error_for_stack.message = e.message;
_on2_obj.error(query, error_for_stack);
throw e;
}
}
function QUERY(texts, ...values) {
return base_query(pool_query, texts, values);
}
function END() {
return end_pool(pool);
}
const QUERY1 = (0, _fxjs.pipe)(QUERY, first),
ASSOCIATE = baseAssociate(QUERY),
ASSOCIATE1 = (0, _fxjs.pipe)(ASSOCIATE, first);
var ljoin = null;
async function LOAD_LJOIN(QUERY) {
if (!ljoin) ljoin = await (0, _ljoin.default)({
ready_sqls,
add_column,
tag,
FxSQL_DEBUG,
connection_info,
QUERY,
VALUES,
IN,
NOT_IN,
EQ,
SET,
COLUMN,
CL,
TABLE,
TB,
SQL,
SQLS
});
return ljoin(QUERY);
}
let baseTransactionQuery = function () {};
let transactionErrorHandler = function (err) {
throw err;
};
return {
POOL: pool,
VALUES,
IN,
NOT_IN,
EQ,
SET,
COLUMN,
CL,
TABLE,
TB,
SQL,
SQLS,
FxSQL_DEBUG,
QUERY,
QUERY1,
ASSOCIATE,
ASSOCIATE1,
ASSOCIATE_MODULE,
END,
LOAD_LJOIN: use_ljoin ? LOAD_LJOIN : null,
config: {
setBaseTransactionQuery(func) {
baseTransactionQuery = func;
},
setTransactionErrorHandler(func) {
transactionErrorHandler = func;
}
},
async TRANSACTION() {
const stack = Error('Transaction start stacktrace');
try {
const client = await get_connection(pool);
const client_query = query_fn(client);
const transaction_querys = [];
await BEGIN(client);
const QUERY = function QUERY(texts, ...values) {
return base_query(client_query, texts, values, transaction_querys);
};
const QUERY1 = (0, _fxjs.pipe)(QUERY, first),
ASSOCIATE = baseAssociate(QUERY),
ASSOCIATE1 = (0, _fxjs.pipe)(ASSOCIATE, first);
await baseTransactionQuery(QUERY, QUERY1);
client.on('error', err => {
transactionErrorHandler(err, client, transaction_querys, stack);
});
return {
client,
VALUES,
IN,
NOT_IN,
EQ,
SET,
COLUMN,
CL,
TABLE,
TB,
SQL,
QUERY,
QUERY1,
ASSOCIATE,
ASSOCIATE1,
LJOIN: use_ljoin && ljoin ? await ljoin(QUERY) : null,
COMMIT: _ => {
const {
stack
} = new Error();
transaction_querys.push({
query: 'COMMIT',
VALUES: [],
stack
});
return COMMIT(client);
},
ROLLBACK: _ => {
const {
stack
} = new Error();
transaction_querys.push({
query: 'ROLLBACK',
VALUES: [],
stack
});
return ROLLBACK(client);
}
};
} catch (e) {
throw e;
}
}
};
}
return {
CONNECT,
VALUES,
IN,
NOT_IN,
EQ,
SET,
COLUMN,
CL,
TABLE,
TB,
SQL,
SQLS,
FxSQL_DEBUG
};
}
const method_promise = (0, _fxjs.curry)((name, obj) => new _promise.default((resolve, reject) => obj[name]((err, res) => err ? reject(err) : resolve(res))));
const PostgreSQL = BASE({
create_pool: connection_info => new _pgPool.default(connection_info),
end_pool: pool => pool.end(),
query_fn: pool => {
var _context18;
return (0, _fxjs.pipe)((0, _bind.default)(_context18 = pool.query).call(_context18, pool), res => res.rows);
},
use_ljoin: true
}),
MySQL = BASE({
create_pool: connection_info => _mysql.default.createPool(connection_info),
end_pool: pool => new _promise.default((resolve, reject) => pool.end(err => err ? reject(err) : resolve())),
query_fn: pool => ({
text,
values
}) => new _promise.default((resolve, reject) => pool.query(text, values, (err, results) => err ? reject(err) : resolve(results))),
get_connection: method_promise('getConnection'),
BEGIN: method_promise('beginTransaction'),
COMMIT: method_promise('commit'),
ROLLBACK: method_promise('rollback'),
reg_q: /\?/g,
to_q: () => '?',
escape_dq: _mysql.default.escapeId,
replace_q: _ => _
});
exports.MySQL = MySQL;
exports.PostgreSQL = PostgreSQL;