Comparing version 1.2.0 to 1.3.0
{ | ||
"name": "sqltyper", | ||
"version": "1.2.0", | ||
"version": "1.3.0", | ||
"description": "Typed SQL queries in PostgreSQL", | ||
@@ -33,4 +33,4 @@ "main": "dist/src/index.js", | ||
"devDependencies": { | ||
"@types/jest": "^26.0.10", | ||
"@types/node": "^15.0.1", | ||
"@types/jest": "^27.0.1", | ||
"@types/node": "^16.3.1", | ||
"@types/ramda": "^0.27.3", | ||
@@ -42,7 +42,7 @@ "@types/wrap-ansi": "^3.0.0", | ||
"eslint": "^7.17.0", | ||
"eslint-plugin-prettier": "^3.1.3", | ||
"jest": "^26.0.1", | ||
"jest-cli": "^26.0.1", | ||
"eslint-plugin-prettier": "^4.0.0", | ||
"jest": "^27.2.0", | ||
"jest-cli": "^27.2.0", | ||
"prettier": "^2.0.2", | ||
"ts-jest": "^26.2.0", | ||
"ts-jest": "^27.0.3", | ||
"ts-node": "^10.0.0" | ||
@@ -49,0 +49,0 @@ }, |
@@ -171,3 +171,3 @@ "use strict"; | ||
return ((equals(a.lhs, b.lhs) && equals(a.rhs, b.rhs)) || | ||
(const_utils_1.isOperatorCommutative(a.op) && | ||
((0, const_utils_1.isOperatorCommutative)(a.op) && | ||
equals(a.lhs, b.rhs) && | ||
@@ -174,0 +174,0 @@ equals(a.rhs, b.lhs))); |
@@ -26,3 +26,2 @@ #!/usr/bin/env node | ||
const function_1 = require("fp-ts/lib/function"); | ||
const pipeable_1 = require("fp-ts/lib/pipeable"); | ||
const yargs = require("yargs"); | ||
@@ -63,3 +62,3 @@ const clients_1 = require("./clients"); | ||
const fileExtensions = extensions(args.ext); | ||
const clients = yield clients_1.connect(args.database); | ||
const clients = yield (0, clients_1.connect)(args.database); | ||
if (Either.isLeft(clients)) { | ||
@@ -86,3 +85,3 @@ console.error(clients.left); | ||
} | ||
yield clients_1.disconnect(clients.right); | ||
yield (0, clients_1.disconnect)(clients.right); | ||
return status; | ||
@@ -132,3 +131,3 @@ }); | ||
alias: 'm', | ||
description: 'Where to import node-postgres or postgres.js from.', | ||
description: 'Where to import node-postgres, postgres.js, or pg-promise from.', | ||
type: 'string', | ||
@@ -175,3 +174,3 @@ }) | ||
const eventHandler = makeWatchEventHandler(clients, options); | ||
dirPaths.forEach((dirPath) => node_watch_1.default(dirPath, { filter: (fileName) => hasOneOfExtensions(fileExtensions, fileName) }, (event, filePath) => __awaiter(this, void 0, void 0, function* () { | ||
dirPaths.forEach((dirPath) => (0, node_watch_1.default)(dirPath, { filter: (fileName) => hasOneOfExtensions(fileExtensions, fileName) }, (event, filePath) => __awaiter(this, void 0, void 0, function* () { | ||
if (!event || !filePath) | ||
@@ -203,3 +202,3 @@ return; | ||
const newModules = yield eventHandler(moduleDir.nestedDirs, moduleDir.modules, type, dirPath, fileName); | ||
moduleDirs = pipeable_1.pipe(modifyWhere((moduleDir) => moduleDir.dirPath === dirPath, (moduleDir) => ({ | ||
moduleDirs = (0, function_1.pipe)(modifyWhere((moduleDir) => moduleDir.dirPath === dirPath, (moduleDir) => ({ | ||
dirPath: moduleDir.dirPath, | ||
@@ -220,7 +219,7 @@ nestedDirs: moduleDir.nestedDirs, | ||
case 'update': | ||
result = pipeable_1.pipe(processSQLFile(clients, sqlFilePath, false, options), Task.map((tsModuleOption) => pipeable_1.pipe(tsModuleOption, Option.map((tsModule) => replaceOrAddTsModule(tsModule, tsModules)), Option.getOrElse(() => removeTsModule(sqlFileName, tsModules))))); | ||
result = (0, function_1.pipe)(processSQLFile(clients, sqlFilePath, false, options), Task.map((tsModuleOption) => (0, function_1.pipe)(tsModuleOption, Option.map((tsModule) => replaceOrAddTsModule(tsModule, tsModules)), Option.getOrElse(() => removeTsModule(sqlFileName, tsModules))))); | ||
break; | ||
case 'remove': | ||
yield removeOutputFile(sqlFilePath); | ||
result = pipeable_1.pipe(Task.of(removeTsModule(sqlFileName, tsModules))); | ||
result = (0, function_1.pipe)(Task.of(removeTsModule(sqlFileName, tsModules))); | ||
break; | ||
@@ -230,3 +229,3 @@ default: | ||
} | ||
result = pipeable_1.pipe(result, Task.chain((newModules) => maybeWriteIndexModule(options.index, dirPath, nestedDirs, newModules, options.prettify))); | ||
result = (0, function_1.pipe)(result, Task.chain((newModules) => maybeWriteIndexModule(options.index, dirPath, nestedDirs, newModules, options.prettify))); | ||
return yield result(); | ||
@@ -236,6 +235,6 @@ }); | ||
function replaceOrAddTsModule(tsModule, tsModules) { | ||
return pipeable_1.pipe(modifyWhere((mod) => mod.sqlFileName === tsModule.sqlFileName, () => tsModule, tsModules), Option.getOrElse(() => Array.snoc(tsModules, tsModule))); | ||
return (0, function_1.pipe)(modifyWhere((mod) => mod.sqlFileName === tsModule.sqlFileName, () => tsModule, tsModules), Option.getOrElse(() => Array.snoc(tsModules, tsModule))); | ||
} | ||
function modifyWhere(pred, replacer, where) { | ||
return pipeable_1.pipe(where.findIndex(pred), Option.fromNullable, Option.chain((index) => pipeable_1.pipe(where, Array.modifyAt(index, () => replacer(where[index]))))); | ||
return (0, function_1.pipe)(where.findIndex(pred), Option.fromNullable, Option.chain((index) => (0, function_1.pipe)(where, Array.modifyAt(index, () => replacer(where[index]))))); | ||
} | ||
@@ -246,3 +245,3 @@ function removeTsModule(sqlFileName, tsModules) { | ||
function processDirectories(clients, fileExtensions, dirPaths, options) { | ||
return pipeable_1.pipe(() => __awaiter(this, void 0, void 0, function* () { | ||
return (0, function_1.pipe)(() => __awaiter(this, void 0, void 0, function* () { | ||
console.log('Starting compilation...'); | ||
@@ -266,6 +265,6 @@ }), Task.chain(() => mapDirectories(dirPaths, fileExtensions, (filePath) => processSQLFile(clients, filePath, false, options), (dirPath, nestedDirs, tsModules) => processSQLDirectory(dirPath, nestedDirs, tsModules, options))), Task.map((moduleDirs) => { | ||
function mapDirectories(dirPaths, fileExtensions, fileProcessor, dirProcessor) { | ||
return fp_utils_1.traverseATs(dirPaths, (dirPath) => mapDirectory(dirPath, fileExtensions, fileProcessor, dirProcessor)); | ||
return (0, fp_utils_1.traverseATs)(dirPaths, (dirPath) => mapDirectory(dirPath, fileExtensions, fileProcessor, dirProcessor)); | ||
} | ||
function mapDirectory(dirPath, fileExtensions, fileProcessor, dirProcessor) { | ||
return pipeable_1.pipe(findSQLFilePaths(dirPath, fileExtensions), Task.chain((res) => pipeable_1.pipe(fp_utils_1.traverseATs(res.nestedDirs, (dirPath) => mapDirectory(dirPath, fileExtensions, fileProcessor, dirProcessor)), Task.chain((processedDirs) => pipeable_1.pipe(fp_utils_1.traverseATs(res.sqlFiles, fileProcessor), Task.chain((processedFiles) => dirProcessor(dirPath, processedDirs, processedFiles))))))); | ||
return (0, function_1.pipe)(findSQLFilePaths(dirPath, fileExtensions), Task.chain((res) => (0, function_1.pipe)((0, fp_utils_1.traverseATs)(res.nestedDirs, (dirPath) => mapDirectory(dirPath, fileExtensions, fileProcessor, dirProcessor)), Task.chain((processedDirs) => (0, function_1.pipe)((0, fp_utils_1.traverseATs)(res.sqlFiles, fileProcessor), Task.chain((processedFiles) => dirProcessor(dirPath, processedDirs, processedFiles))))))); | ||
} | ||
@@ -275,3 +274,3 @@ function processSQLFile(clients, filePath, checkOnly, options) { | ||
const fnName = funcName(filePath); | ||
return pipeable_1.pipe(() => fs_1.promises.readFile(filePath, 'utf-8'), Task.chain((sql) => index_1.sqlToStatementDescription(clients, sql)), TaskEither.map((stmtWithWarnings) => { | ||
return (0, function_1.pipe)(() => fs_1.promises.readFile(filePath, 'utf-8'), Task.chain((sql) => (0, index_1.sqlToStatementDescription)(clients, sql)), TaskEither.map((stmtWithWarnings) => { | ||
const [stmt, warnings] = Warn.split(stmtWithWarnings); | ||
@@ -282,3 +281,3 @@ if (warnings.length > 0) { | ||
return stmt; | ||
}), TaskEither.chain((source) => index_1.generateTSCode(clients, path.basename(filePath), source, fnName, { | ||
}), TaskEither.chain((source) => (0, index_1.generateTSCode)(clients, path.basename(filePath), source, fnName, { | ||
prettierFileName: options.prettify ? tsPath : undefined, | ||
@@ -310,5 +309,5 @@ target: options.target, | ||
function processSQLDirectory(dirPath, nestedDirs, modules, options) { | ||
const successfulModules = pipeable_1.pipe(modules, Array.filterMap(function_1.identity)); | ||
const successfulModules = (0, function_1.pipe)(modules, Array.filterMap(function_1.identity)); | ||
const hasErrors = modules.some(Option.isNone); | ||
return pipeable_1.pipe(maybeWriteIndexModule(options.index, dirPath, nestedDirs, successfulModules, options.prettify), Task.map((modules) => ({ hasErrors, dirPath, modules, nestedDirs }))); | ||
return (0, function_1.pipe)(maybeWriteIndexModule(options.index, dirPath, nestedDirs, successfulModules, options.prettify), Task.map((modules) => ({ hasErrors, dirPath, modules, nestedDirs }))); | ||
} | ||
@@ -322,3 +321,3 @@ function moduleDirContainsSqlFiles(dir) { | ||
(tsModules.length > 0 || nestedDirs.some(moduleDirContainsSqlFiles))) { | ||
return pipeable_1.pipe(Task.of(tsModules), Task.map((modules) => pipeable_1.pipe(modules, Array.sort(Ord.fromCompare((a, b) => Ordering.sign(a.tsFileName.localeCompare(b.tsFileName)))))), Task.chain((sortedModules) => index_1.indexModuleTS(dirPath, nestedDirs.filter(moduleDirContainsSqlFiles), sortedModules, { | ||
return (0, function_1.pipe)(Task.of(tsModules), Task.map((modules) => (0, function_1.pipe)(modules, Array.sort(Ord.fromCompare((a, b) => Ordering.sign(a.tsFileName.localeCompare(b.tsFileName)))))), Task.chain((sortedModules) => (0, index_1.indexModuleTS)(dirPath, nestedDirs.filter(moduleDirContainsSqlFiles), sortedModules, { | ||
prettierFileName: prettify ? tsPath : null, | ||
@@ -379,6 +378,6 @@ })), Task.chain((tsCode) => () => __awaiter(this, void 0, void 0, function* () { | ||
function findSQLFilePaths(dirPath, fileExtensions) { | ||
return pipeable_1.pipe(() => fs_1.promises.readdir(dirPath, { | ||
return (0, function_1.pipe)(() => fs_1.promises.readdir(dirPath, { | ||
encoding: 'utf-8', | ||
withFileTypes: true, | ||
}), Task.chain((dirents) => pipeable_1.pipe(fp_utils_1.traverseATs(dirents, (dirent) => pipeable_1.pipe(categoriseDirEnt(fileExtensions, dirPath, dirent.name), Task.map((typ) => [typ, dirent]))), Task.map((dirents) => ({ | ||
}), Task.chain((dirents) => (0, function_1.pipe)((0, fp_utils_1.traverseATs)(dirents, (dirent) => (0, function_1.pipe)(categoriseDirEnt(fileExtensions, dirPath, dirent.name), Task.map((typ) => [typ, dirent]))), Task.map((dirents) => ({ | ||
sqlFiles: mapPartial(dirents, ([typ, dirent]) => typ === 'sqlfile' ? path.join(dirPath, dirent.name) : null), | ||
@@ -385,0 +384,0 @@ nestedDirs: mapPartial(dirents, ([typ, dirent]) => typ === 'dir' ? path.join(dirPath, dirent.name) : null), |
@@ -28,4 +28,4 @@ "use strict"; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const schema = schema_1.schemaClient(postgresClient); | ||
const types = yield tstype_1.typeClient(postgresClient); | ||
const schema = (0, schema_1.schemaClient)(postgresClient); | ||
const types = yield (0, tstype_1.typeClient)(postgresClient); | ||
return { postgres: postgresClient, schema, types }; | ||
@@ -45,3 +45,3 @@ }); | ||
// Recreate it to clear the cache. | ||
const types = yield tstype_1.typeClient(clients.postgres); | ||
const types = yield (0, tstype_1.typeClient)(clients.postgres); | ||
return Object.assign(Object.assign({}, clients), { types }); | ||
@@ -48,0 +48,0 @@ }); |
@@ -7,6 +7,10 @@ "use strict"; | ||
const Task = require("fp-ts/lib/Task"); | ||
const pipeable_1 = require("fp-ts/lib/pipeable"); | ||
const function_1 = require("fp-ts/lib/function"); | ||
const fp_utils_1 = require("./fp-utils"); | ||
const pkginfo = require("./pkginfo"); | ||
exports.codegenTargets = ['pg', 'postgres']; | ||
exports.codegenTargets = [ | ||
'pg', | ||
'postgres', | ||
'pg-promise', | ||
]; | ||
//////////////////////////////////////////////////////////////////////// | ||
@@ -34,3 +38,3 @@ function validateStatement(stmt) { | ||
const positionalOnly = hasOnlyPositionalParams(stmt); | ||
return pipeable_1.pipe(Task.of(typeScriptString(sourceFileName, target, module, funcName, stmt.sql)), Task.ap(funcParams(types, stmt, positionalOnly)), Task.ap(funcReturnType(types, stmt)), Task.ap(Task.of(queryValues(stmt, positionalOnly))), Task.ap(Task.of(outputValue(target, stmt)))); | ||
return (0, function_1.pipe)(Task.of(typeScriptString(sourceFileName, target, module, funcName, stmt.sql)), Task.ap(funcParams(types, stmt, positionalOnly)), Task.ap(funcReturnType(types, stmt)), Task.ap(Task.of(queryValues(stmt, positionalOnly))), Task.ap(Task.of(outputValue(target, stmt)))); | ||
} | ||
@@ -82,2 +86,17 @@ exports.generateTypeScript = generateTypeScript; | ||
}, | ||
'pg-promise'({ sourceFileName, module, funcName, params, returnType, sql, queryValues, outputValue, }) { | ||
return `\ | ||
${topComment(sourceFileName)} | ||
import * as pgp from '${module}' | ||
export async function ${funcName}( | ||
client: pgp.IDatabase<any, any>${params} | ||
): Promise<${returnType}> { | ||
const result = await client.query(\`\\ | ||
${sql}\`${queryValues}) | ||
return ${outputValue} | ||
} | ||
`; | ||
}, | ||
}; | ||
@@ -88,3 +107,3 @@ function hasOnlyPositionalParams(stmt) { | ||
function funcReturnType(types, stmt) { | ||
return pipeable_1.pipe(fp_utils_1.traverseATs(stmt.columns, columnType(types)), Task.map((columnTypes) => { | ||
return (0, function_1.pipe)((0, fp_utils_1.traverseATs)(stmt.columns, columnType(types)), Task.map((columnTypes) => { | ||
const rowType = '{ ' + columnTypes.join('; ') + ' }'; | ||
@@ -104,3 +123,3 @@ switch (stmt.rowCount) { | ||
const columnType = (types) => (column) => { | ||
return pipeable_1.pipe(types.columnType(column), Task.map(({ name, type }) => `${stringLiteral(name)}: ${type}`)); | ||
return (0, function_1.pipe)(types.columnType(column), Task.map(({ name, type }) => `${stringLiteral(name)}: ${type}`)); | ||
}; | ||
@@ -118,2 +137,5 @@ function outputValue(target, stmt) { | ||
break; | ||
case 'pg-promise': | ||
rows = 'result'; | ||
count = 'result.length'; | ||
} | ||
@@ -138,3 +160,3 @@ switch (stmt.rowCount) { | ||
} | ||
return pipeable_1.pipe(positionalOnly | ||
return (0, function_1.pipe)(positionalOnly | ||
? positionalFuncParams(types, stmt) | ||
@@ -144,6 +166,6 @@ : namedFuncParams(types, stmt), Task.map((params) => `, ${params}`)); | ||
function positionalFuncParams(types, stmt) { | ||
return pipeable_1.pipe(fp_utils_1.traverseATs(stmt.params, (param) => pipeable_1.pipe(types.tsType(param.type, param.nullable), Task.map((tsType) => `${param.name}: ${tsType}`))), Task.map((params) => params.join(', '))); | ||
return (0, function_1.pipe)((0, fp_utils_1.traverseATs)(stmt.params, (param) => (0, function_1.pipe)(types.tsType(param.type, param.nullable), Task.map((tsType) => `${param.name}: ${tsType}`))), Task.map((params) => params.join(', '))); | ||
} | ||
function namedFuncParams(types, stmt) { | ||
return pipeable_1.pipe(positionalFuncParams(types, stmt), Task.map((params) => `params: { ${params} }`)); | ||
return (0, function_1.pipe)(positionalFuncParams(types, stmt), Task.map((params) => `params: { ${params} }`)); | ||
} | ||
@@ -150,0 +172,0 @@ function queryValues(stmt, positionalOnly) { |
@@ -5,3 +5,3 @@ "use strict"; | ||
const Option = require("fp-ts/lib/Option"); | ||
const pipeable_1 = require("fp-ts/lib/pipeable"); | ||
const function_1 = require("fp-ts/lib/function"); | ||
const constants_1 = require("./constants"); | ||
@@ -14,7 +14,7 @@ function findOperator(name) { | ||
function isOperatorCommutative(name) { | ||
return pipeable_1.pipe(findOperator(name), Option.map((op) => op.commutative || false), Option.getOrElse(() => false)); | ||
return (0, function_1.pipe)(findOperator(name), Option.map((op) => op.commutative || false), Option.getOrElse(() => false)); | ||
} | ||
exports.isOperatorCommutative = isOperatorCommutative; | ||
function operatorNullSafety(name) { | ||
return pipeable_1.pipe(findOperator(name), Option.map((op) => op.nullSafety), Option.toNullable); | ||
return (0, function_1.pipe)(findOperator(name), Option.map((op) => op.nullSafety), Option.toNullable); | ||
} | ||
@@ -28,4 +28,4 @@ exports.operatorNullSafety = operatorNullSafety; | ||
function builtinFunctionNullSafety(name) { | ||
return pipeable_1.pipe(findBuiltinFunction(name), Option.map((func) => func.nullSafety), Option.toNullable); | ||
return (0, function_1.pipe)(findBuiltinFunction(name), Option.map((func) => func.nullSafety), Option.toNullable); | ||
} | ||
exports.builtinFunctionNullSafety = builtinFunctionNullSafety; |
@@ -5,7 +5,7 @@ "use strict"; | ||
const TaskEither = require("fp-ts/lib/TaskEither"); | ||
const pipeable_1 = require("fp-ts/lib/pipeable"); | ||
const function_1 = require("fp-ts/lib/function"); | ||
const R = require("ramda"); | ||
const types_1 = require("./types"); | ||
function describeStatement(postgresClient, sql, paramNames) { | ||
return pipeable_1.pipe(TaskEither.tryCatch(() => postgresClient.describe(sql), (error) => error instanceof postgresClient.PostgresError | ||
return (0, function_1.pipe)(TaskEither.tryCatch(() => postgresClient.describe(sql), (error) => error instanceof postgresClient.PostgresError | ||
? errorToString(error, sql) | ||
@@ -12,0 +12,0 @@ : error.message || ''), TaskEither.map((result) => describeResult(sql, paramNames, result))); |
@@ -8,3 +8,3 @@ "use strict"; | ||
const TaskEither = require("fp-ts/lib/TaskEither"); | ||
const pipeable_1 = require("fp-ts/lib/pipeable"); | ||
const function_1 = require("fp-ts/lib/function"); | ||
const Warn = require("./Warn"); | ||
@@ -15,3 +15,3 @@ exports.traverseATs = Array.array.traverse(Task.taskSeq); | ||
function traverseAIM(ta, f) { | ||
return pipeable_1.pipe(exports.traverseATE(ta, f), TaskEither.map(exports.sequenceAW)); | ||
return (0, function_1.pipe)((0, exports.traverseATE)(ta, f), TaskEither.map(exports.sequenceAW)); | ||
} | ||
@@ -22,3 +22,3 @@ exports.traverseAIM = traverseAIM; | ||
function sequenceAIM(ta) { | ||
return pipeable_1.pipe(exports.sequenceATE(ta), TaskEither.map(exports.sequenceAW)); | ||
return (0, function_1.pipe)((0, exports.sequenceATE)(ta), TaskEither.map(exports.sequenceAW)); | ||
} | ||
@@ -25,0 +25,0 @@ exports.sequenceAIM = sequenceAIM; |
@@ -6,3 +6,3 @@ "use strict"; | ||
const TaskEither = require("fp-ts/lib/TaskEither"); | ||
const pipeable_1 = require("fp-ts/lib/pipeable"); | ||
const function_1 = require("fp-ts/lib/function"); | ||
const codegen_1 = require("./codegen"); | ||
@@ -14,3 +14,3 @@ const describe_1 = require("./describe"); | ||
function sqlToStatementDescription(clients, sql) { | ||
return pipeable_1.pipe(Task.of(sql), Task.map(preprocess_1.preprocessSQL), TaskEither.chain((processed) => describe_1.describeStatement(clients.postgres, processed.sql, processed.paramNames)), TaskEither.chain((stmt) => Task.of(codegen_1.validateStatement(stmt))), TaskEither.chain((stmt) => TaskEither.rightTask(infer_1.inferStatementNullability(clients.schema, stmt)))); | ||
return (0, function_1.pipe)(Task.of(sql), Task.map(preprocess_1.preprocessSQL), TaskEither.chain((processed) => (0, describe_1.describeStatement)(clients.postgres, processed.sql, processed.paramNames)), TaskEither.chain((stmt) => Task.of((0, codegen_1.validateStatement)(stmt))), TaskEither.chain((stmt) => TaskEither.rightTask((0, infer_1.inferStatementNullability)(clients.schema, stmt)))); | ||
} | ||
@@ -20,4 +20,4 @@ exports.sqlToStatementDescription = sqlToStatementDescription; | ||
const { prettierFileName = null, target = 'pg', module = 'pg', } = options || {}; | ||
return pipeable_1.pipe(TaskEither.right(stmt), TaskEither.chain((stmt) => TaskEither.rightTask(codegen_1.generateTypeScript(clients.types, sourceFileName, target, module, funcName, stmt))), TaskEither.chain((tsCode) => prettierFileName != null | ||
? TaskEither.rightTask(() => prettify_1.runPrettier(prettierFileName, tsCode)) | ||
return (0, function_1.pipe)(TaskEither.right(stmt), TaskEither.chain((stmt) => TaskEither.rightTask((0, codegen_1.generateTypeScript)(clients.types, sourceFileName, target, module, funcName, stmt))), TaskEither.chain((tsCode) => prettierFileName != null | ||
? TaskEither.rightTask(() => (0, prettify_1.runPrettier)(prettierFileName, tsCode)) | ||
: TaskEither.right(tsCode))); | ||
@@ -28,6 +28,6 @@ } | ||
const { prettierFileName = null } = options || {}; | ||
return pipeable_1.pipe(Task.of(codegen_1.generateIndexModule(dirPath, nestedDirs, tsModules)), Task.chain((tsCode) => prettierFileName != null | ||
? () => prettify_1.runPrettier(prettierFileName, tsCode) | ||
return (0, function_1.pipe)(Task.of((0, codegen_1.generateIndexModule)(dirPath, nestedDirs, tsModules)), Task.chain((tsCode) => prettierFileName != null | ||
? () => (0, prettify_1.runPrettier)(prettierFileName, tsCode) | ||
: Task.of(tsCode))); | ||
} | ||
exports.indexModuleTS = indexModuleTS; |
@@ -20,3 +20,2 @@ "use strict"; | ||
const function_1 = require("fp-ts/lib/function"); | ||
const pipeable_1 = require("fp-ts/lib/pipeable"); | ||
const ast = require("./ast"); | ||
@@ -34,7 +33,7 @@ const fp_utils_1 = require("./fp-utils"); | ||
function inferStatementNullability(client, statement) { | ||
return pipeable_1.pipe(TaskEither.fromEither(parser_1.parse(statement.sql)), TaskEither.chain((astNode) => pipeable_1.pipe(InferM.fromTaskEither(getParamNullability(client, astNode)), InferM.chain((paramNullability) => pipeable_1.pipe(inferColumnNullability(client, statement, paramNullability, astNode), InferM.map((stmt) => applyParamNullability(stmt, paramNullability)))), InferM.map((stmt) => inferRowCount(stmt, astNode)))), TaskEither.getOrElse((parseErrorStr) => Task.of(Warn.warning(statement, 'The internal SQL parser failed to parse the SQL statement.', `Parse error: ${parseErrorStr}`)))); | ||
return (0, function_1.pipe)(TaskEither.fromEither((0, parser_1.parse)(statement.sql)), TaskEither.chain((astNode) => (0, function_1.pipe)(InferM.fromTaskEither(getParamNullability(client, astNode)), InferM.chain((paramNullability) => (0, function_1.pipe)(inferColumnNullability(client, statement, paramNullability, astNode), InferM.map((stmt) => applyParamNullability(stmt, paramNullability)))), InferM.map((stmt) => inferRowCount(stmt, astNode)))), TaskEither.getOrElse((parseErrorStr) => Task.of(Warn.warning(statement, 'The internal SQL parser failed to parse the SQL statement.', `Parse error: ${parseErrorStr}`)))); | ||
} | ||
exports.inferStatementNullability = inferStatementNullability; | ||
function inferColumnNullability(client, statement, paramNullability, tree) { | ||
return pipeable_1.pipe(getOutputColumns(client, [], paramNullability, tree), InferM.chain((outputColumns) => InferM.fromEither(applyColumnNullability(statement, outputColumns)))); | ||
return (0, function_1.pipe)(getOutputColumns(client, [], paramNullability, tree), InferM.chain((outputColumns) => InferM.fromEither(applyColumnNullability(statement, outputColumns)))); | ||
} | ||
@@ -44,6 +43,6 @@ exports.inferColumnNullability = inferColumnNullability; | ||
return ast.walk(tree, { | ||
select: ({ ctes, body, setOps }) => pipeable_1.pipe(combineVirtualTables(outsideCTEs, getVirtualTablesForWithQueries(client, paramNullability, ctes)), InferM.chain((combinedCTEs) => inferSetOpsOutput(client, combinedCTEs, paramNullability, body, setOps))), | ||
insert: ({ table, as, returning }) => pipeable_1.pipe(getSourceColumnsForTable(client, outsideCTEs, table, as), InferM.chain((sourceColumns) => inferSelectListOutput(client, outsideCTEs, sourceColumns, paramNullability, [], returning))), | ||
update: ({ ctes, table, as, from, where, returning }) => pipeable_1.pipe(combineVirtualTables(outsideCTEs, getVirtualTablesForWithQueries(client, paramNullability, ctes)), InferM.chain((combinedCTEs) => combineSourceColumns(getSourceColumnsForTableExpr(client, combinedCTEs, paramNullability, from), getSourceColumnsForTable(client, combinedCTEs, table, as))), InferM.chain((sourceColumns) => inferSelectListOutput(client, outsideCTEs, sourceColumns, paramNullability, [where], returning))), | ||
delete: ({ table, as, where, returning }) => pipeable_1.pipe(getSourceColumnsForTable(client, outsideCTEs, table, as), InferM.chain((sourceColumns) => inferSelectListOutput(client, outsideCTEs, sourceColumns, paramNullability, [where], returning))), | ||
select: ({ ctes, body, setOps }) => (0, function_1.pipe)(combineVirtualTables(outsideCTEs, getVirtualTablesForWithQueries(client, paramNullability, ctes)), InferM.chain((combinedCTEs) => inferSetOpsOutput(client, combinedCTEs, paramNullability, body, setOps))), | ||
insert: ({ table, as, returning }) => (0, function_1.pipe)(getSourceColumnsForTable(client, outsideCTEs, table, as), InferM.chain((sourceColumns) => inferSelectListOutput(client, outsideCTEs, sourceColumns, paramNullability, [], returning))), | ||
update: ({ ctes, table, as, from, where, returning }) => (0, function_1.pipe)(combineVirtualTables(outsideCTEs, getVirtualTablesForWithQueries(client, paramNullability, ctes)), InferM.chain((combinedCTEs) => combineSourceColumns(getSourceColumnsForTableExpr(client, combinedCTEs, paramNullability, from), getSourceColumnsForTable(client, combinedCTEs, table, as))), InferM.chain((sourceColumns) => inferSelectListOutput(client, outsideCTEs, sourceColumns, paramNullability, [where], returning))), | ||
delete: ({ table, as, where, returning }) => (0, function_1.pipe)(getSourceColumnsForTable(client, outsideCTEs, table, as), InferM.chain((sourceColumns) => inferSelectListOutput(client, outsideCTEs, sourceColumns, paramNullability, [where], returning))), | ||
}); | ||
@@ -92,3 +91,3 @@ } | ||
if (setOp.op !== 'EXCEPT') { | ||
result = pipeable_1.pipe(Warn.of((aa) => (bb) => pipeable_1.pipe(Array.zip(aa, bb), Array.map(([a, b]) => ({ | ||
result = (0, function_1.pipe)(Warn.of((aa) => (bb) => (0, function_1.pipe)(Array.zip(aa, bb), Array.map(([a, b]) => ({ | ||
// Column names are determined by the first SELECT | ||
@@ -104,10 +103,10 @@ name: a.name, | ||
function inferSelectBodyOutput(client, outsideCTEs, paramNullability, body) { | ||
return pipeable_1.pipe(getSourceColumnsForTableExpr(client, outsideCTEs, paramNullability, body.from), InferM.chain((sourceColumns) => inferSelectListOutput(client, outsideCTEs, sourceColumns, paramNullability, [body.where, body.having], body.selectList))); | ||
return (0, function_1.pipe)(getSourceColumnsForTableExpr(client, outsideCTEs, paramNullability, body.from), InferM.chain((sourceColumns) => inferSelectListOutput(client, outsideCTEs, sourceColumns, paramNullability, [body.where, body.having], body.selectList))); | ||
} | ||
function inferSelectListOutput(client, outsideCTEs, sourceColumns, paramNullability, conditions, selectList) { | ||
return pipeable_1.pipe(InferM.right(pipeable_1.pipe(conditions.map((cond) => getNonNullSubExpressionsFromRowCond(cond)), Array.flatten)), InferM.chain((nonNullExpressions) => pipeable_1.pipe(fp_utils_1.traverseAIM(selectList, (item) => inferSelectListItemOutput(client, outsideCTEs, sourceColumns, paramNullability, nonNullExpressions, item)), InferM.map(R.flatten)))); | ||
return (0, function_1.pipe)(InferM.right((0, function_1.pipe)(conditions.map((cond) => getNonNullSubExpressionsFromRowCond(cond)), Array.flatten)), InferM.chain((nonNullExpressions) => (0, function_1.pipe)((0, fp_utils_1.traverseAIM)(selectList, (item) => inferSelectListItemOutput(client, outsideCTEs, sourceColumns, paramNullability, nonNullExpressions, item)), InferM.map(R.flatten)))); | ||
} | ||
function inferSelectListItemOutput(client, outsideCTEs, sourceColumns, paramNullability, nonNullExpressions, selectListItem) { | ||
return ast.SelectListItem.walk(selectListItem, { | ||
allFields: () => InferM.fromEither(pipeable_1.pipe( | ||
allFields: () => InferM.fromEither((0, function_1.pipe)( | ||
// hidden columns aren't selected by SELECT * | ||
@@ -118,7 +117,7 @@ findNonHiddenSourceColumns(sourceColumns), Either.map((columns) => applyExpressionNonNullability(nonNullExpressions, columns)), Either.map((columns) => columns.map((column) => ({ | ||
}))))), | ||
allTableFields: ({ tableName }) => InferM.fromEither(pipeable_1.pipe(findNonHiddenSourceTableColumns(tableName, sourceColumns), Either.map((columns) => applyExpressionNonNullability(nonNullExpressions, columns)), Either.map((columns) => columns.map((column) => ({ | ||
allTableFields: ({ tableName }) => InferM.fromEither((0, function_1.pipe)(findNonHiddenSourceTableColumns(tableName, sourceColumns), Either.map((columns) => applyExpressionNonNullability(nonNullExpressions, columns)), Either.map((columns) => columns.map((column) => ({ | ||
name: column.columnName, | ||
nullability: column.nullability, | ||
}))))), | ||
selectListExpression: ({ expression, as }) => pipeable_1.pipe(inferExpressionNullability(client, outsideCTEs, sourceColumns, paramNullability, nonNullExpressions, expression), InferM.map((exprNullability) => [ | ||
selectListExpression: ({ expression, as }) => (0, function_1.pipe)(inferExpressionNullability(client, outsideCTEs, sourceColumns, paramNullability, nonNullExpressions, expression), InferM.map((exprNullability) => [ | ||
virtualField(as || inferExpressionName(expression), exprNullability), | ||
@@ -134,3 +133,3 @@ ])), | ||
function applyExpressionNonNullability(nonNullableExpressions, sourceColumns) { | ||
const nonNullableColumns = pipeable_1.pipe(nonNullableExpressions, R.map((expr) => ast.Expression.walkSome(expr, Option.none, { | ||
const nonNullableColumns = (0, function_1.pipe)(nonNullableExpressions, R.map((expr) => ast.Expression.walkSome(expr, Option.none, { | ||
columnRef: ({ column }) => Option.some({ tableName: null, columnName: column }), | ||
@@ -151,4 +150,4 @@ tableColumnRef: ({ table, column }) => Option.some({ tableName: table, columnName: column }), | ||
function inferExpressionNullability(client, outsideCTEs, sourceColumns, paramNullability, nonNullExprs, expression) { | ||
const anyTE = function_1.flow(field_nullability_1.FieldNullability.any, Warn.of, TaskEither.right); | ||
const arrayTE = function_1.flow(field_nullability_1.FieldNullability.array, Warn.of, TaskEither.right); | ||
const anyTE = (0, function_1.flow)(field_nullability_1.FieldNullability.any, Warn.of, TaskEither.right); | ||
const arrayTE = (0, function_1.flow)(field_nullability_1.FieldNullability.array, Warn.of, TaskEither.right); | ||
if (nonNullExprs.some((nonNull) => ast.Expression.equals(expression, nonNull))) { | ||
@@ -162,6 +161,6 @@ // This expression is guaranteed to be not NULL by a | ||
// have a NOT NULL constraint | ||
tableColumnRef: ({ table, column }) => pipeable_1.pipe(InferM.fromEither(findSourceTableColumn(table, column, sourceColumns)), InferM.map((column) => column.nullability)), | ||
tableColumnRef: ({ table, column }) => (0, function_1.pipe)(InferM.fromEither(findSourceTableColumn(table, column, sourceColumns)), InferM.map((column) => column.nullability)), | ||
// A column reference may evaluate to NULL if the column doesn't | ||
// have a NOT NULL constraint | ||
columnRef: ({ column }) => pipeable_1.pipe(InferM.fromEither(findSourceColumn(column, sourceColumns)), InferM.map((column) => column.nullability)), | ||
columnRef: ({ column }) => (0, function_1.pipe)(InferM.fromEither(findSourceColumn(column, sourceColumns)), InferM.map((column) => column.nullability)), | ||
// A unary operator has two options: | ||
@@ -175,3 +174,3 @@ // | ||
unaryOp: ({ op, operand }) => { | ||
switch (const_utils_1.operatorNullSafety(op)) { | ||
switch ((0, const_utils_1.operatorNullSafety)(op)) { | ||
case 'safe': | ||
@@ -198,6 +197,6 @@ return inferExpressionNullability(client, outsideCTEs, sourceColumns, paramNullability, nonNullExprs, operand); | ||
// result is also guaranteed to be non-null. | ||
const nullSafety = op == 'AND' || op == 'OR' ? 'safe' : const_utils_1.operatorNullSafety(op); | ||
const nullSafety = op == 'AND' || op == 'OR' ? 'safe' : (0, const_utils_1.operatorNullSafety)(op); | ||
switch (nullSafety) { | ||
case 'safe': | ||
return pipeable_1.pipe(InferM.right(field_nullability_1.FieldNullability.disjunction), InferM.ap(pipeable_1.pipe(inferExpressionNullability(client, outsideCTEs, sourceColumns, paramNullability, nonNullExprs, lhs))), InferM.ap(pipeable_1.pipe(inferExpressionNullability(client, outsideCTEs, sourceColumns, paramNullability, nonNullExprs, rhs)))); | ||
return (0, function_1.pipe)(InferM.right(field_nullability_1.FieldNullability.disjunction), InferM.ap((0, function_1.pipe)(inferExpressionNullability(client, outsideCTEs, sourceColumns, paramNullability, nonNullExprs, lhs))), InferM.ap((0, function_1.pipe)(inferExpressionNullability(client, outsideCTEs, sourceColumns, paramNullability, nonNullExprs, rhs)))); | ||
case 'unsafe': | ||
@@ -212,5 +211,5 @@ return anyTE(true); | ||
ternaryOp: ({ lhs, op, rhs1, rhs2 }) => { | ||
switch (const_utils_1.operatorNullSafety(op)) { | ||
switch ((0, const_utils_1.operatorNullSafety)(op)) { | ||
case 'safe': | ||
return pipeable_1.pipe(InferM.right((a) => (b) => (c) => field_nullability_1.FieldNullability.disjunction(field_nullability_1.FieldNullability.disjunction(a)(b))(c)), InferM.ap(inferExpressionNullability(client, outsideCTEs, sourceColumns, paramNullability, nonNullExprs, lhs)), InferM.ap(inferExpressionNullability(client, outsideCTEs, sourceColumns, paramNullability, nonNullExprs, rhs1)), InferM.ap(inferExpressionNullability(client, outsideCTEs, sourceColumns, paramNullability, nonNullExprs, rhs2))); | ||
return (0, function_1.pipe)(InferM.right((a) => (b) => (c) => field_nullability_1.FieldNullability.disjunction(field_nullability_1.FieldNullability.disjunction(a)(b))(c)), InferM.ap(inferExpressionNullability(client, outsideCTEs, sourceColumns, paramNullability, nonNullExprs, lhs)), InferM.ap(inferExpressionNullability(client, outsideCTEs, sourceColumns, paramNullability, nonNullExprs, rhs1)), InferM.ap(inferExpressionNullability(client, outsideCTEs, sourceColumns, paramNullability, nonNullExprs, rhs2))); | ||
case 'unsafe': | ||
@@ -234,6 +233,6 @@ return anyTE(true); | ||
// | ||
functionCall: ({ schema, funcName, argList }) => pipeable_1.pipe(client.functionNullSafety(schema, funcName), Task.chain((nullSafety) => { | ||
functionCall: ({ schema, funcName, argList }) => (0, function_1.pipe)(client.functionNullSafety(schema, funcName), Task.chain((nullSafety) => { | ||
switch (nullSafety) { | ||
case 'safe': | ||
return pipeable_1.pipe(fp_utils_1.traverseATE(argList, (arg) => inferExpressionNullability(client, outsideCTEs, sourceColumns, paramNullability, nonNullExprs, arg)), TaskEither.map((argNullability) => pipeable_1.pipe(fp_utils_1.sequenceAW(argNullability), Warn.map((an) => field_nullability_1.FieldNullability.any(an.some((nullability) => nullability.nullable)))))); | ||
return (0, function_1.pipe)((0, fp_utils_1.traverseATE)(argList, (arg) => inferExpressionNullability(client, outsideCTEs, sourceColumns, paramNullability, nonNullExprs, arg)), TaskEither.map((argNullability) => (0, function_1.pipe)((0, fp_utils_1.sequenceAW)(argNullability), Warn.map((an) => field_nullability_1.FieldNullability.any(an.some((nullability) => nullability.nullable)))))); | ||
case 'unsafe': | ||
@@ -251,3 +250,3 @@ return anyTE(true); | ||
// the inside depends on the inside select list expression | ||
arraySubQuery: ({ subquery }) => pipeable_1.pipe(getOutputColumns(client, outsideCTEs, paramNullability, subquery), InferM.chain((columns) => { | ||
arraySubQuery: ({ subquery }) => (0, function_1.pipe)(getOutputColumns(client, outsideCTEs, paramNullability, subquery), InferM.chain((columns) => { | ||
if (columns.length != 1) | ||
@@ -267,3 +266,3 @@ return TaskEither.left('subquery must return only one column'); | ||
} | ||
return pipeable_1.pipe(InferM.right((branchNullabilities) => (elseNullability) => branchNullabilities.reduce((a, b) => field_nullability_1.FieldNullability.disjunction(a)(b), elseNullability)), InferM.ap(pipeable_1.pipe(branches.map(({ condition, result }) => { | ||
return (0, function_1.pipe)(InferM.right((branchNullabilities) => (elseNullability) => branchNullabilities.reduce((a, b) => field_nullability_1.FieldNullability.disjunction(a)(b), elseNullability)), InferM.ap((0, function_1.pipe)(branches.map(({ condition, result }) => { | ||
const nonNullExprsByCond = getNonNullSubExpressionsFromRowCond(condition); | ||
@@ -308,3 +307,3 @@ return inferExpressionNullability(client, outsideCTEs, sourceColumns, paramNullability, [...nonNullExprsByCond, ...nonNullExprs], result); | ||
} | ||
if (const_utils_1.operatorNullSafety(op) === 'safe') { | ||
if ((0, const_utils_1.operatorNullSafety)(op) === 'safe') { | ||
// For safe operators, the operator must non-nullable for the | ||
@@ -334,3 +333,3 @@ // result to evaluate to non-null | ||
} | ||
if (op === 'AND' || const_utils_1.operatorNullSafety(op) === 'safe') { | ||
if (op === 'AND' || (0, const_utils_1.operatorNullSafety)(op) === 'safe') { | ||
// For safe operators, both sides must be non-nullable for the | ||
@@ -348,3 +347,3 @@ // result to be non-nullable. | ||
ternaryOp: ({ lhs, op, rhs1, rhs2 }) => { | ||
if (const_utils_1.operatorNullSafety(op) === 'safe') { | ||
if ((0, const_utils_1.operatorNullSafety)(op) === 'safe') { | ||
// For safe operators, all operands must be non-nullable for the | ||
@@ -364,4 +363,4 @@ // result to be non-nullable. | ||
// It's enough to check builtin functions because non-builtins are never null safe | ||
if (const_utils_1.builtinFunctionNullSafety(funcName) === 'safe') { | ||
return pipeable_1.pipe(argList, Array.map((arg) => getNonNullSubExpressionsFromRowCond(arg, logicalNegation)), Array.flatten); | ||
if ((0, const_utils_1.builtinFunctionNullSafety)(funcName) === 'safe') { | ||
return (0, function_1.pipe)(argList, Array.map((arg) => getNonNullSubExpressionsFromRowCond(arg, logicalNegation)), Array.flatten); | ||
} | ||
@@ -379,5 +378,5 @@ return [expression]; | ||
} | ||
const valuesParamNullability = pipeable_1.pipe(TaskEither.right(combineParamNullability), TaskEither.ap(TaskEither.right(findParamsFromValues(valuesOrSelect, columns.length))), TaskEither.ap(findInsertColumns(client, table, columns))); | ||
const valuesParamNullability = (0, function_1.pipe)(TaskEither.right(combineParamNullability), TaskEither.ap(TaskEither.right(findParamsFromValues(valuesOrSelect, columns.length))), TaskEither.ap(findInsertColumns(client, table, columns))); | ||
const onConflictParamNullability = findParamNullabilityFromUpdates(client, table, onConflict); | ||
return pipeable_1.pipe(TaskEither.right(fp_utils_1.concat2()), TaskEither.ap(valuesParamNullability), TaskEither.ap(onConflictParamNullability)); | ||
return (0, function_1.pipe)(TaskEither.right((0, fp_utils_1.concat2)()), TaskEither.ap(valuesParamNullability), TaskEither.ap(onConflictParamNullability)); | ||
}, | ||
@@ -395,6 +394,6 @@ update: ({ table, updates }) => findParamNullabilityFromUpdates(client, table, updates), | ||
function findParamNullabilityFromUpdates(client, table, updates) { | ||
return pipeable_1.pipe(client.getTable(table.schema, table.table), TaskEither.chain((dbTable) => TaskEither.fromEither(fp_utils_1.traverseAE(updates, (update) => updateToParamNullability(dbTable, update)))), TaskEither.map((paramNullabilities) => pipeable_1.pipe(paramNullabilities, Array.filterMap(function_1.identity)))); | ||
return (0, function_1.pipe)(client.getTable(table.schema, table.table), TaskEither.chain((dbTable) => TaskEither.fromEither((0, fp_utils_1.traverseAE)(updates, (update) => updateToParamNullability(dbTable, update)))), TaskEither.map((paramNullabilities) => (0, function_1.pipe)(paramNullabilities, Array.filterMap(function_1.identity)))); | ||
} | ||
function paramIndexFromExpr(expression) { | ||
return pipeable_1.pipe(Option.fromNullable(expression), Option.chain((nonNullExpr) => ast.Expression.walkSome(nonNullExpr, Option.none, { | ||
return (0, function_1.pipe)(Option.fromNullable(expression), Option.chain((nonNullExpr) => ast.Expression.walkSome(nonNullExpr, Option.none, { | ||
parameter: (paramExpr) => Option.some(paramExpr.index - 1), | ||
@@ -404,10 +403,10 @@ }))); | ||
function updateToParamNullability(dbTable, update) { | ||
return pipeable_1.pipe(Either.right(makeParamNullability), Either.ap(Either.right(paramIndexFromExpr(update.value))), Either.ap(findTableColumn(update.columnName, dbTable))); | ||
return (0, function_1.pipe)(Either.right(makeParamNullability), Either.ap(Either.right(paramIndexFromExpr(update.value))), Either.ap(findTableColumn(update.columnName, dbTable))); | ||
} | ||
const makeParamNullability = (index) => (column) => pipeable_1.pipe(index, Option.map((index) => ({ index, nullable: column.nullable }))); | ||
const makeParamNullability = (index) => (column) => (0, function_1.pipe)(index, Option.map((index) => ({ index, nullable: column.nullable }))); | ||
function findInsertColumns(client, table, columnNames) { | ||
return pipeable_1.pipe(client.getTable(table.schema, table.table), TaskEither.chain((dbTable) => TaskEither.fromEither(fp_utils_1.traverseAE(columnNames, (columnName) => findTableColumn(columnName, dbTable))))); | ||
return (0, function_1.pipe)(client.getTable(table.schema, table.table), TaskEither.chain((dbTable) => TaskEither.fromEither((0, fp_utils_1.traverseAE)(columnNames, (columnName) => findTableColumn(columnName, dbTable))))); | ||
} | ||
const combineParamNullability = (valuesListParams) => (targetColumns) => { | ||
return pipeable_1.pipe(valuesListParams.map((valuesParams) => R.zip(targetColumns, valuesParams).map(([column, param]) => pipeable_1.pipe(param, Option.map((index) => ({ index, nullable: column.nullable }))))), R.flatten, Array.filterMap(function_1.identity)); | ||
return (0, function_1.pipe)(valuesListParams.map((valuesParams) => R.zip(targetColumns, valuesParams).map(([column, param]) => (0, function_1.pipe)(param, Option.map((index) => ({ index, nullable: column.nullable }))))), R.flatten, Array.filterMap(function_1.identity)); | ||
}; | ||
@@ -466,3 +465,3 @@ function applyParamNullability(stmt, paramNullability) { | ||
// "Virtual tables" from previous WITH queries are available | ||
const virtualTable = pipeable_1.pipe(yield getOutputColumns(client, virtualTables, paramNullability, withQuery.query)(), Either.map((columnsWithWarnings) => pipeable_1.pipe(columnsWithWarnings, Warn.map((columns) => ({ name: withQuery.as, columns }))))); | ||
const virtualTable = (0, function_1.pipe)(yield getOutputColumns(client, virtualTables, paramNullability, withQuery.query)(), Either.map((columnsWithWarnings) => (0, function_1.pipe)(columnsWithWarnings, Warn.map((columns) => ({ name: withQuery.as, columns }))))); | ||
if (Either.isLeft(virtualTable)) { | ||
@@ -478,3 +477,3 @@ return virtualTable; | ||
function combineVirtualTables(outsideCTEs, ctes) { | ||
return pipeable_1.pipe(ctes, InferM.map((virtualTables) => [...outsideCTEs, ...virtualTables])); | ||
return (0, function_1.pipe)(ctes, InferM.map((virtualTables) => [...outsideCTEs, ...virtualTables])); | ||
} | ||
@@ -494,3 +493,3 @@ function getSourceColumnsForTable(client, ctes, table, as) { | ||
// No matching CTE, try to find a database table | ||
return pipeable_1.pipe(client.getTable(table.schema, table.table), TaskEither.map((table) => table.columns.map((col) => ({ | ||
return (0, function_1.pipe)(client.getTable(table.schema, table.table), TaskEither.map((table) => table.columns.map((col) => ({ | ||
tableAlias: as || table.name, | ||
@@ -506,3 +505,3 @@ columnName: col.name, | ||
} | ||
return pipeable_1.pipe(ast.TableExpression.walk(tableExpr, { | ||
return (0, function_1.pipe)(ast.TableExpression.walk(tableExpr, { | ||
table: ({ table, as }) => getSourceColumnsForTable(client, ctes, table, as), | ||
@@ -519,3 +518,3 @@ subQuery: ({ query, as }) => getSourceColumnsForSubQuery(client, ctes, paramNullability, query, as), | ||
function getSourceColumnsForSubQuery(client, outsideCTEs, paramNullability, subquery, as) { | ||
return pipeable_1.pipe(getOutputColumns(client, outsideCTEs, paramNullability, subquery), InferM.map((columns) => columns.map((column) => ({ | ||
return (0, function_1.pipe)(getOutputColumns(client, outsideCTEs, paramNullability, subquery), InferM.map((columns) => columns.map((column) => ({ | ||
tableAlias: as, | ||
@@ -531,3 +530,3 @@ columnName: column.name, | ||
function combineSourceColumns(...sourceColumns) { | ||
return pipeable_1.pipe(sourceColumns, fp_utils_1.sequenceAIM, InferM.map(R.flatten)); | ||
return (0, function_1.pipe)(sourceColumns, fp_utils_1.sequenceAIM, InferM.map(R.flatten)); | ||
} | ||
@@ -540,6 +539,6 @@ function isConstantExprOf(expectedValue, expr) { | ||
function findNonHiddenSourceColumns(sourceColumns) { | ||
return pipeable_1.pipe(sourceColumns.filter((col) => !col.hidden), Either.fromPredicate((result) => result.length > 0, () => `No columns`)); | ||
return (0, function_1.pipe)(sourceColumns.filter((col) => !col.hidden), Either.fromPredicate((result) => result.length > 0, () => `No columns`)); | ||
} | ||
function findNonHiddenSourceTableColumns(tableName, sourceColumns) { | ||
return pipeable_1.pipe(findNonHiddenSourceColumns(sourceColumns), Either.map((sourceColumns) => sourceColumns.filter((col) => col.tableAlias === tableName)), Either.chain((result) => result.length > 0 | ||
return (0, function_1.pipe)(findNonHiddenSourceColumns(sourceColumns), Either.map((sourceColumns) => sourceColumns.filter((col) => col.tableAlias === tableName)), Either.chain((result) => result.length > 0 | ||
? Either.right(result) | ||
@@ -549,9 +548,9 @@ : Either.left(`No visible columns for table ${tableName}`))); | ||
function findSourceTableColumn(tableName, columnName, sourceColumns) { | ||
return pipeable_1.pipe(sourceColumns.find((source) => source.tableAlias === tableName && source.columnName === columnName), Either.fromNullable(`Unknown column ${tableName}.${columnName}`)); | ||
return (0, function_1.pipe)(sourceColumns.find((source) => source.tableAlias === tableName && source.columnName === columnName), Either.fromNullable(`Unknown column ${tableName}.${columnName}`)); | ||
} | ||
function findSourceColumn(columnName, sourceColumns) { | ||
return pipeable_1.pipe(sourceColumns.find((col) => col.columnName === columnName), Either.fromNullable(`Unknown column ${columnName}`)); | ||
return (0, function_1.pipe)(sourceColumns.find((col) => col.columnName === columnName), Either.fromNullable(`Unknown column ${columnName}`)); | ||
} | ||
function findTableColumn(columnName, table) { | ||
return pipeable_1.pipe(table.columns.find((column) => column.name === columnName), Either.fromNullable(`Unknown column ${columnName}`)); | ||
return (0, function_1.pipe)(table.columns.find((column) => column.name === columnName), Either.fromNullable(`Unknown column ${columnName}`)); | ||
} |
@@ -7,17 +7,16 @@ "use strict"; | ||
const function_1 = require("fp-ts/lib/function"); | ||
const pipeable_1 = require("fp-ts/lib/pipeable"); | ||
const Warn = require("./Warn"); | ||
exports.fromEither = function_1.flow(Either.map(Warn.of), TaskEither.fromEither); | ||
exports.fromEither = (0, function_1.flow)(Either.map(Warn.of), TaskEither.fromEither); | ||
exports.fromTaskEither = TaskEither.map(Warn.of); | ||
exports.right = function_1.flow(Warn.of, TaskEither.right); | ||
exports.right = (0, function_1.flow)(Warn.of, TaskEither.right); | ||
exports.payload = TaskEither.map((warn) => warn.payload); | ||
exports.warnings = TaskEither.map((warn) => warn.warnings); | ||
exports.map = function_1.flow(Warn.map, TaskEither.map); | ||
exports.map = (0, function_1.flow)(Warn.map, TaskEither.map); | ||
function chain(f) { | ||
return (ma) => pipeable_1.pipe(TaskEither.right((p) => (w) => Warn.make(p.payload, p.warnings.concat(w))), TaskEither.ap(pipeable_1.pipe(ma, TaskEither.chain((w) => f(w.payload)))), TaskEither.ap(exports.warnings(ma))); | ||
return (ma) => (0, function_1.pipe)(TaskEither.right((p) => (w) => Warn.make(p.payload, p.warnings.concat(w))), TaskEither.ap((0, function_1.pipe)(ma, TaskEither.chain((w) => f(w.payload)))), TaskEither.ap((0, exports.warnings)(ma))); | ||
} | ||
exports.chain = chain; | ||
function ap(fa) { | ||
return (fab) => pipeable_1.pipe(TaskEither.right((p) => (w1) => (w2) => Warn.make(p, w1.concat(w2))), TaskEither.ap(pipeable_1.pipe(exports.payload(fab), TaskEither.ap(exports.payload(fa)))), TaskEither.ap(exports.warnings(fa)), TaskEither.ap(exports.warnings(fab))); | ||
return (fab) => (0, function_1.pipe)(TaskEither.right((p) => (w1) => (w2) => Warn.make(p, w1.concat(w2))), TaskEither.ap((0, function_1.pipe)((0, exports.payload)(fab), TaskEither.ap((0, exports.payload)(fa)))), TaskEither.ap((0, exports.warnings)(fa)), TaskEither.ap((0, exports.warnings)(fab))); | ||
} | ||
exports.ap = ap; |
@@ -12,24 +12,24 @@ "use strict"; | ||
function parenthesized(parser) { | ||
return typed_parser_1.seq2(token_1.symbol('('), parser, token_1.symbol(')')); | ||
return (0, typed_parser_1.seq2)((0, token_1.symbol)('('), parser, (0, token_1.symbol)(')')); | ||
} | ||
exports.parenthesized = parenthesized; | ||
// [ AS ] identifier | ||
const as = typed_parser_1.seq2(utils_1.optional(token_1.reservedWord('AS')), token_1.identifier); | ||
const as = (0, typed_parser_1.seq2)((0, utils_1.optional)((0, token_1.reservedWord)('AS')), token_1.identifier); | ||
// AS identifier | ||
const reqAs = typed_parser_1.seq2(token_1.reservedWord('AS'), token_1.identifier); | ||
const reqAs = (0, typed_parser_1.seq2)((0, token_1.reservedWord)('AS'), token_1.identifier); | ||
// [ schema . ] table | ||
const tableRef = typed_parser_1.seq(token_1.identifier, utils_1.optional(typed_parser_1.seq2(token_1.symbol('.'), token_1.identifier)))((id1, id2) => (id2 ? ast_1.TableRef.create(id1, id2) : ast_1.TableRef.create(null, id1))); | ||
const tableRef = (0, typed_parser_1.seq)(token_1.identifier, (0, utils_1.optional)((0, typed_parser_1.seq2)((0, token_1.symbol)('.'), token_1.identifier)))((id1, id2) => (id2 ? ast_1.TableRef.create(id1, id2) : ast_1.TableRef.create(null, id1))); | ||
// Expressions | ||
const arraySubQueryExpr = typed_parser_1.seq(token_1.reservedWord('ARRAY'), parenthesized(typed_parser_1.lazy(() => select)))((_arr, subquery) => ast_1.Expression.createArraySubQuery(subquery)); | ||
const caseBranch = typed_parser_1.seq(token_1.reservedWord('WHEN'), typed_parser_1.lazy(() => expression), token_1.reservedWord('THEN'), typed_parser_1.lazy(() => expression))((_when, condition, _then, result) => ({ condition, result })); | ||
const caseElse = typed_parser_1.seq2(token_1.reservedWord('ELSE'), typed_parser_1.lazy(() => expression)); | ||
const caseExpr = typed_parser_1.seq(token_1.reservedWord('CASE'), caseBranch, typed_parser_1.many(caseBranch), utils_1.optional(caseElse), token_1.reservedWord('END'))((_case, branch1, branches, else_, _end) => ast_1.Expression.createCase([branch1, ...branches], else_)); | ||
const functionArguments = parenthesized(typed_parser_1.oneOf( | ||
const arraySubQueryExpr = (0, typed_parser_1.seq)((0, token_1.reservedWord)('ARRAY'), parenthesized((0, typed_parser_1.lazy)(() => select)))((_arr, subquery) => ast_1.Expression.createArraySubQuery(subquery)); | ||
const caseBranch = (0, typed_parser_1.seq)((0, token_1.reservedWord)('WHEN'), (0, typed_parser_1.lazy)(() => expression), (0, token_1.reservedWord)('THEN'), (0, typed_parser_1.lazy)(() => expression))((_when, condition, _then, result) => ({ condition, result })); | ||
const caseElse = (0, typed_parser_1.seq2)((0, token_1.reservedWord)('ELSE'), (0, typed_parser_1.lazy)(() => expression)); | ||
const caseExpr = (0, typed_parser_1.seq)((0, token_1.reservedWord)('CASE'), caseBranch, (0, typed_parser_1.many)(caseBranch), (0, utils_1.optional)(caseElse), (0, token_1.reservedWord)('END'))((_case, branch1, branches, else_, _end) => ast_1.Expression.createCase([branch1, ...branches], else_)); | ||
const functionArguments = parenthesized((0, typed_parser_1.oneOf)( | ||
// func(*) means no arguments | ||
typed_parser_1.seqConst([], token_1.symbol('*')), typed_parser_1.sepBy(token_1.symbol(','), typed_parser_1.lazy(() => expression)))); | ||
const windowDefinition = typed_parser_1.oneOf(token_1.identifier, typed_parser_1.seq(utils_1.optional(typed_parser_1.seq3(token_1.reservedWord('PARTITION'), token_1.reservedWord('BY'), typed_parser_1.lazy(() => expression))), utils_1.optional(typed_parser_1.lazy(() => orderBy)))((partition, order) => ({ | ||
(0, typed_parser_1.seqConst)([], (0, token_1.symbol)('*')), (0, typed_parser_1.sepBy)((0, token_1.symbol)(','), (0, typed_parser_1.lazy)(() => expression)))); | ||
const windowDefinition = (0, typed_parser_1.oneOf)(token_1.identifier, (0, typed_parser_1.seq)((0, utils_1.optional)((0, typed_parser_1.seq3)((0, token_1.reservedWord)('PARTITION'), (0, token_1.reservedWord)('BY'), (0, typed_parser_1.lazy)(() => expression))), (0, utils_1.optional)((0, typed_parser_1.lazy)(() => orderBy)))((partition, order) => ({ | ||
partitionBy: partition, | ||
orderBy: order, | ||
}))); | ||
const columnRefOrFunctionCallExpr = typed_parser_1.seq(token_1.identifier, utils_1.optional(typed_parser_1.seq2(token_1.symbol('.'), token_1.identifier)), utils_1.optional(typed_parser_1.seq(functionArguments, utils_1.optional(typed_parser_1.seq2(token_1.reservedWord('FILTER'), parenthesized(typed_parser_1.seq2(token_1.reservedWord('WHERE'), typed_parser_1.lazy(() => expression))))), utils_1.optional(typed_parser_1.seq2(token_1.reservedWord('OVER'), typed_parser_1.oneOf(token_1.identifier, parenthesized(windowDefinition)))))((argList, filter, window) => [argList, filter, window])))((ident, ident2, fnCall) => { | ||
const columnRefOrFunctionCallExpr = (0, typed_parser_1.seq)(token_1.identifier, (0, utils_1.optional)((0, typed_parser_1.seq2)((0, token_1.symbol)('.'), token_1.identifier)), (0, utils_1.optional)((0, typed_parser_1.seq)(functionArguments, (0, utils_1.optional)((0, typed_parser_1.seq2)((0, token_1.reservedWord)('FILTER'), parenthesized((0, typed_parser_1.seq2)((0, token_1.reservedWord)('WHERE'), (0, typed_parser_1.lazy)(() => expression))))), (0, utils_1.optional)((0, typed_parser_1.seq2)((0, token_1.reservedWord)('OVER'), (0, typed_parser_1.oneOf)(token_1.identifier, parenthesized(windowDefinition)))))((argList, filter, window) => [argList, filter, window])))((ident, ident2, fnCall) => { | ||
if (fnCall) { | ||
@@ -46,12 +46,12 @@ const [argList, filter, window] = fnCall; | ||
}); | ||
const strEscape = typed_parser_1.seq2(token_1.symbolKeepWS('\\'), typed_parser_1.oneOf(typed_parser_1.keyword("'", "'"), typed_parser_1.keyword('\\', '\\'), typed_parser_1.keyword('/', '/'), typed_parser_1.keyword('b', '\b'), typed_parser_1.keyword('f', '\f'), typed_parser_1.keyword('n', '\n'), typed_parser_1.keyword('r', '\r'), typed_parser_1.keyword('t', '\t'))); | ||
const strInner = typed_parser_1.seq(typed_parser_1.stringBefore("[\\']"), typed_parser_1.oneOf(typed_parser_1.seq(strEscape, typed_parser_1.lazy(() => strInner))((e, t) => e + t), typed_parser_1.constant('')))((s, tail) => s + tail); | ||
const stringConstant = typed_parser_1.seq2(token_1.symbolKeepWS("'"), strInner, token_1.symbol("'")); | ||
const constantExpr = typed_parser_1.seq(typed_parser_1.oneOf(token_1.expectIdentifier('TRUE'), token_1.expectIdentifier('FALSE'), token_1.expectIdentifier('NULL'), typed_parser_1.match('[0-9]+(\\.[0-9]+)?([eE]-?[0-9]+)?'), typed_parser_1.match('\\.[0-9]+'), stringConstant), token_1._)((val, _ws) => ast_1.Expression.createConstant(val)); | ||
const parameterExpr = typed_parser_1.seq(token_1.symbolKeepWS('$'), typed_parser_1.int('[0-9]+'), token_1._)((_$, index, _ws) => ast_1.Expression.createParameter(index)); | ||
const parenthesizedExpr = parenthesized(typed_parser_1.lazy(() => expression)); | ||
const typeName = typed_parser_1.seq(token_1.identifier, typed_parser_1.oneOf(typed_parser_1.seqConst('[]', token_1.symbol('['), token_1.symbol(']')), typed_parser_1.seqConst('', token_1._)))((id, arraySuffix) => id + arraySuffix); | ||
const primaryExpr = typed_parser_1.seq(typed_parser_1.oneOf(arraySubQueryExpr, caseExpr, typed_parser_1.attempt(special_functions_1.specialFunctionCall(typed_parser_1.lazy(() => primaryExpr))), columnRefOrFunctionCallExpr, constantExpr, parameterExpr, parenthesizedExpr), utils_1.optional(typed_parser_1.seq2(token_1.symbol('::'), typeName)))((expr, typeCast) => typeCast != null ? ast_1.Expression.createTypeCast(expr, typeCast) : expr); | ||
const strEscape = (0, typed_parser_1.seq2)((0, token_1.symbolKeepWS)('\\'), (0, typed_parser_1.oneOf)((0, typed_parser_1.keyword)("'", "'"), (0, typed_parser_1.keyword)('\\', '\\'), (0, typed_parser_1.keyword)('/', '/'), (0, typed_parser_1.keyword)('b', '\b'), (0, typed_parser_1.keyword)('f', '\f'), (0, typed_parser_1.keyword)('n', '\n'), (0, typed_parser_1.keyword)('r', '\r'), (0, typed_parser_1.keyword)('t', '\t'))); | ||
const strInner = (0, typed_parser_1.seq)((0, typed_parser_1.stringBefore)("[\\']"), (0, typed_parser_1.oneOf)((0, typed_parser_1.seq)(strEscape, (0, typed_parser_1.lazy)(() => strInner))((e, t) => e + t), (0, typed_parser_1.constant)('')))((s, tail) => s + tail); | ||
const stringConstant = (0, typed_parser_1.seq2)((0, token_1.symbolKeepWS)("'"), strInner, (0, token_1.symbol)("'")); | ||
const constantExpr = (0, typed_parser_1.seq)((0, typed_parser_1.oneOf)((0, token_1.expectIdentifier)('TRUE'), (0, token_1.expectIdentifier)('FALSE'), (0, token_1.expectIdentifier)('NULL'), (0, typed_parser_1.match)('[0-9]+(\\.[0-9]+)?([eE]-?[0-9]+)?'), (0, typed_parser_1.match)('\\.[0-9]+'), stringConstant), token_1._)((val, _ws) => ast_1.Expression.createConstant(val)); | ||
const parameterExpr = (0, typed_parser_1.seq)((0, token_1.symbolKeepWS)('$'), (0, typed_parser_1.int)('[0-9]+'), token_1._)((_$, index, _ws) => ast_1.Expression.createParameter(index)); | ||
const parenthesizedExpr = parenthesized((0, typed_parser_1.lazy)(() => expression)); | ||
const typeName = (0, typed_parser_1.seq)(token_1.identifier, (0, typed_parser_1.oneOf)((0, typed_parser_1.seqConst)('[]', (0, token_1.symbol)('['), (0, token_1.symbol)(']')), (0, typed_parser_1.seqConst)('', token_1._)))((id, arraySuffix) => id + arraySuffix); | ||
const primaryExpr = (0, typed_parser_1.seq)((0, typed_parser_1.oneOf)(arraySubQueryExpr, caseExpr, (0, typed_parser_1.attempt)((0, special_functions_1.specialFunctionCall)((0, typed_parser_1.lazy)(() => primaryExpr))), columnRefOrFunctionCallExpr, constantExpr, parameterExpr, parenthesizedExpr), (0, utils_1.optional)((0, typed_parser_1.seq2)((0, token_1.symbol)('::'), typeName)))((expr, typeCast) => typeCast != null ? ast_1.Expression.createTypeCast(expr, typeCast) : expr); | ||
function makeUnaryOp(oper, nextExpr) { | ||
return typed_parser_1.seq(typed_parser_1.many(oper), nextExpr)((ops, next) => ops.length > 0 | ||
return (0, typed_parser_1.seq)((0, typed_parser_1.many)(oper), nextExpr)((ops, next) => ops.length > 0 | ||
? ops.reduceRight((acc, op) => ast_1.Expression.createUnaryOp(op, acc), next) | ||
@@ -61,17 +61,17 @@ : next); | ||
function makeBinaryOp(oper, nextExpr) { | ||
return typed_parser_1.seq(nextExpr, typed_parser_1.many(typed_parser_1.seq(oper, nextExpr)((op, next) => ({ op, next }))))((first, rest) => rest.reduce((acc, val) => ast_1.Expression.createBinaryOp(acc, val.op, val.next), first)); | ||
return (0, typed_parser_1.seq)(nextExpr, (0, typed_parser_1.many)((0, typed_parser_1.seq)(oper, nextExpr)((op, next) => ({ op, next }))))((first, rest) => rest.reduce((acc, val) => ast_1.Expression.createBinaryOp(acc, val.op, val.next), first)); | ||
} | ||
const oneOfOperators = (...ops) => typed_parser_1.oneOf(...ops.map(token_1.operator)); | ||
const subscriptExpr = typed_parser_1.seq(primaryExpr, typed_parser_1.many(typed_parser_1.seq2(token_1.symbol('['), typed_parser_1.lazy(() => expression), token_1.symbol(']'))))((next, subs) => subs.reduce((acc, val) => ast_1.Expression.createBinaryOp(acc, '[]', val), next)); | ||
const oneOfOperators = (...ops) => (0, typed_parser_1.oneOf)(...ops.map(token_1.operator)); | ||
const subscriptExpr = (0, typed_parser_1.seq)(primaryExpr, (0, typed_parser_1.many)((0, typed_parser_1.seq2)((0, token_1.symbol)('['), (0, typed_parser_1.lazy)(() => expression), (0, token_1.symbol)(']'))))((next, subs) => subs.reduce((acc, val) => ast_1.Expression.createBinaryOp(acc, '[]', val), next)); | ||
const unaryPlusMinus = makeUnaryOp(oneOfOperators('+', '-'), subscriptExpr); | ||
const expExpr = makeBinaryOp(token_1.operator('^'), unaryPlusMinus); | ||
const expExpr = makeBinaryOp((0, token_1.operator)('^'), unaryPlusMinus); | ||
const mulDivModExpr = makeBinaryOp(oneOfOperators('*', '/', '%'), expExpr); | ||
const addSubExpr = makeBinaryOp(oneOfOperators('+', '-'), mulDivModExpr); | ||
const existsExpr = typed_parser_1.seq(token_1.reservedWord('EXISTS'), parenthesized(typed_parser_1.lazy(() => select)))((_exists, subquery) => ast_1.Expression.createExistsOp(subquery)); | ||
const existsExpr = (0, typed_parser_1.seq)((0, token_1.reservedWord)('EXISTS'), parenthesized((0, typed_parser_1.lazy)(() => select)))((_exists, subquery) => ast_1.Expression.createExistsOp(subquery)); | ||
var OtherExprRhs; | ||
(function (OtherExprRhs) { | ||
const in_ = typed_parser_1.seq(typed_parser_1.attempt(typed_parser_1.oneOf(token_1.reservedWord('IN'), typed_parser_1.seqConst('NOT IN', token_1.reservedWord('NOT'), token_1.reservedWord('IN')))), parenthesized(typed_parser_1.lazy(() => select)))((op, rhs) => ({ kind: 'InExprRhs', op, rhs })); | ||
const ternary = typed_parser_1.seq(typed_parser_1.oneOf(typed_parser_1.attempt(token_1.sepReserveds('NOT BETWEEN SYMMETRIC')), typed_parser_1.attempt(token_1.sepReserveds('BETWEEN SYMMETRIC')), typed_parser_1.attempt(token_1.sepReserveds('NOT BETWEEN')), typed_parser_1.attempt(token_1.reservedWord('BETWEEN'))), addSubExpr, token_1.reservedWord('AND'), addSubExpr)((op, rhs1, _and, rhs2) => ({ kind: 'TernaryExprRhs', op, rhs1, rhs2 })); | ||
const unarySuffix = typed_parser_1.seqConst({ kind: 'UnarySuffix', op: '!' }, token_1.operator('!')); | ||
const otherOp = typed_parser_1.seq(typed_parser_1.oneOf(token_1.anyOperatorExcept([ | ||
const in_ = (0, typed_parser_1.seq)((0, typed_parser_1.attempt)((0, typed_parser_1.oneOf)((0, token_1.reservedWord)('IN'), (0, typed_parser_1.seqConst)('NOT IN', (0, token_1.reservedWord)('NOT'), (0, token_1.reservedWord)('IN')))), parenthesized((0, typed_parser_1.lazy)(() => select)))((op, rhs) => ({ kind: 'InExprRhs', op, rhs })); | ||
const ternary = (0, typed_parser_1.seq)((0, typed_parser_1.oneOf)((0, typed_parser_1.attempt)((0, token_1.sepReserveds)('NOT BETWEEN SYMMETRIC')), (0, typed_parser_1.attempt)((0, token_1.sepReserveds)('BETWEEN SYMMETRIC')), (0, typed_parser_1.attempt)((0, token_1.sepReserveds)('NOT BETWEEN')), (0, typed_parser_1.attempt)((0, token_1.reservedWord)('BETWEEN'))), addSubExpr, (0, token_1.reservedWord)('AND'), addSubExpr)((op, rhs1, _and, rhs2) => ({ kind: 'TernaryExprRhs', op, rhs1, rhs2 })); | ||
const unarySuffix = (0, typed_parser_1.seqConst)({ kind: 'UnarySuffix', op: '!' }, (0, token_1.operator)('!')); | ||
const otherOp = (0, typed_parser_1.seq)((0, typed_parser_1.oneOf)((0, token_1.anyOperatorExcept)([ | ||
'<', | ||
@@ -89,4 +89,4 @@ '>', | ||
'^', | ||
]), token_1.sepReserveds('IS DISTINCT FROM'), token_1.sepReserveds('IS NOT DISTINCT FROM'), token_1.reservedWord('LIKE')), addSubExpr)((op, rhs) => ({ kind: 'OtherOpExprRhs', op, rhs })); | ||
OtherExprRhs.parser = typed_parser_1.oneOf(in_, ternary, unarySuffix, otherOp); | ||
]), (0, token_1.sepReserveds)('IS DISTINCT FROM'), (0, token_1.sepReserveds)('IS NOT DISTINCT FROM'), (0, token_1.reservedWord)('LIKE')), addSubExpr)((op, rhs) => ({ kind: 'OtherOpExprRhs', op, rhs })); | ||
OtherExprRhs.parser = (0, typed_parser_1.oneOf)(in_, ternary, unarySuffix, otherOp); | ||
function createExpression(lhs, rhs) { | ||
@@ -106,23 +106,23 @@ switch (rhs.kind) { | ||
})(OtherExprRhs || (OtherExprRhs = {})); | ||
const otherExpr = typed_parser_1.seq(addSubExpr, typed_parser_1.many(OtherExprRhs.parser))((first, rest) => rest.reduce((acc, val) => OtherExprRhs.createExpression(acc, val), first)); | ||
const existsOrOtherExpr = typed_parser_1.oneOf(existsExpr, otherExpr); | ||
const otherExpr = (0, typed_parser_1.seq)(addSubExpr, (0, typed_parser_1.many)(OtherExprRhs.parser))((first, rest) => rest.reduce((acc, val) => OtherExprRhs.createExpression(acc, val), first)); | ||
const existsOrOtherExpr = (0, typed_parser_1.oneOf)(existsExpr, otherExpr); | ||
const comparisonExpr = makeBinaryOp(oneOfOperators('<', '>', '=', '<=', '>=', '<>'), existsOrOtherExpr); | ||
const isExpr = typed_parser_1.seq(comparisonExpr, utils_1.optional(typed_parser_1.oneOf(token_1.sepReserveds('IS NULL'), token_1.sepReserveds('IS NOT NULL'), token_1.reservedWord('ISNULL'), token_1.reservedWord('NOTNULL'), token_1.sepReserveds('IS TRUE'), token_1.sepReserveds('IS NOT TRUE'), token_1.sepReserveds('IS FALSE'), token_1.sepReserveds('IS NOT FALSE'), token_1.sepReserveds('IS UNKNOWN'), token_1.sepReserveds('IS NOT UNKNOWN'))))((next, op) => (op ? ast_1.Expression.createUnaryOp(op, next) : next)); | ||
const notExpr = makeUnaryOp(token_1.reservedWord('NOT'), isExpr); | ||
const andExpr = makeBinaryOp(token_1.reservedWord('AND'), notExpr); | ||
const orExpr = makeBinaryOp(token_1.reservedWord('OR'), andExpr); | ||
const isExpr = (0, typed_parser_1.seq)(comparisonExpr, (0, utils_1.optional)((0, typed_parser_1.oneOf)((0, token_1.sepReserveds)('IS NULL'), (0, token_1.sepReserveds)('IS NOT NULL'), (0, token_1.reservedWord)('ISNULL'), (0, token_1.reservedWord)('NOTNULL'), (0, token_1.sepReserveds)('IS TRUE'), (0, token_1.sepReserveds)('IS NOT TRUE'), (0, token_1.sepReserveds)('IS FALSE'), (0, token_1.sepReserveds)('IS NOT FALSE'), (0, token_1.sepReserveds)('IS UNKNOWN'), (0, token_1.sepReserveds)('IS NOT UNKNOWN'))))((next, op) => (op ? ast_1.Expression.createUnaryOp(op, next) : next)); | ||
const notExpr = makeUnaryOp((0, token_1.reservedWord)('NOT'), isExpr); | ||
const andExpr = makeBinaryOp((0, token_1.reservedWord)('AND'), notExpr); | ||
const orExpr = makeBinaryOp((0, token_1.reservedWord)('OR'), andExpr); | ||
const expression = orExpr; | ||
// (name1, name2, ...) | ||
const identifierList = parenthesized(typed_parser_1.sepBy1(token_1.symbol(','), token_1.identifier)); | ||
const identifierList = parenthesized((0, typed_parser_1.sepBy1)((0, token_1.symbol)(','), token_1.identifier)); | ||
// WITH | ||
const withQueries = typed_parser_1.seq2(token_1.reservedWord('WITH'), typed_parser_1.sepBy1(token_1.symbol(','), typed_parser_1.seq(token_1.identifier, utils_1.optional(identifierList), token_1.reservedWord('AS'), parenthesized(typed_parser_1.lazy(() => statementParser)))((as, columns, _as, stmt) => ast_1.WithQuery.create(as, columns, stmt)))); | ||
const crossJoin = typed_parser_1.seq(token_1.sepReserveds('CROSS JOIN'), typed_parser_1.lazy(() => tableExpression))((_cj, tableExpr) => ({ join: { kind: 'Cross' }, tableExpr })); | ||
const qualifiedJoinType = typed_parser_1.seq(utils_1.optional(typed_parser_1.oneOf(token_1.reservedWord('INNER'), typed_parser_1.seq1(typed_parser_1.oneOf(token_1.reservedWord('LEFT'), token_1.reservedWord('RIGHT'), token_1.reservedWord('FULL')), utils_1.optional(token_1.reservedWord('OUTER'))))), token_1.reservedWord('JOIN'))((joinType, _join) => joinType || 'INNER'); | ||
const qualifiedJoin = typed_parser_1.seq(qualifiedJoinType, typed_parser_1.lazy(() => tableExpression), typed_parser_1.oneOf(typed_parser_1.seq(token_1.reservedWord('ON'), expression)((_on, expr) => ast_1.TableExpression.createJoinOn(expr)), typed_parser_1.seq(token_1.reservedWord('USING'), identifierList)((_using, columns) => ast_1.TableExpression.createJoinUsing(columns))))((type, tableExpr, condition) => ({ | ||
const withQueries = (0, typed_parser_1.seq2)((0, token_1.reservedWord)('WITH'), (0, typed_parser_1.sepBy1)((0, token_1.symbol)(','), (0, typed_parser_1.seq)(token_1.identifier, (0, utils_1.optional)(identifierList), (0, token_1.reservedWord)('AS'), parenthesized((0, typed_parser_1.lazy)(() => statementParser)))((as, columns, _as, stmt) => ast_1.WithQuery.create(as, columns, stmt)))); | ||
const crossJoin = (0, typed_parser_1.seq)((0, token_1.sepReserveds)('CROSS JOIN'), (0, typed_parser_1.lazy)(() => tableExpression))((_cj, tableExpr) => ({ join: { kind: 'Cross' }, tableExpr })); | ||
const qualifiedJoinType = (0, typed_parser_1.seq)((0, utils_1.optional)((0, typed_parser_1.oneOf)((0, token_1.reservedWord)('INNER'), (0, typed_parser_1.seq1)((0, typed_parser_1.oneOf)((0, token_1.reservedWord)('LEFT'), (0, token_1.reservedWord)('RIGHT'), (0, token_1.reservedWord)('FULL')), (0, utils_1.optional)((0, token_1.reservedWord)('OUTER'))))), (0, token_1.reservedWord)('JOIN'))((joinType, _join) => joinType || 'INNER'); | ||
const qualifiedJoin = (0, typed_parser_1.seq)(qualifiedJoinType, (0, typed_parser_1.lazy)(() => tableExpression), (0, typed_parser_1.oneOf)((0, typed_parser_1.seq)((0, token_1.reservedWord)('ON'), expression)((_on, expr) => ast_1.TableExpression.createJoinOn(expr)), (0, typed_parser_1.seq)((0, token_1.reservedWord)('USING'), identifierList)((_using, columns) => ast_1.TableExpression.createJoinUsing(columns))))((type, tableExpr, condition) => ({ | ||
join: { kind: 'Qualified', type, condition }, | ||
tableExpr, | ||
})); | ||
const naturalJoinType = typed_parser_1.seq2(token_1.reservedWord('NATURAL'), qualifiedJoinType); | ||
const naturalJoin = typed_parser_1.seq(naturalJoinType, typed_parser_1.lazy(() => tableExpression))((type, tableExpr) => ({ join: { kind: 'Natural', type }, tableExpr })); | ||
const table = typed_parser_1.seq(tableRef, utils_1.optional(as))(ast_1.TableExpression.createTable); | ||
const naturalJoinType = (0, typed_parser_1.seq2)((0, token_1.reservedWord)('NATURAL'), qualifiedJoinType); | ||
const naturalJoin = (0, typed_parser_1.seq)(naturalJoinType, (0, typed_parser_1.lazy)(() => tableExpression))((type, tableExpr) => ({ join: { kind: 'Natural', type }, tableExpr })); | ||
const table = (0, typed_parser_1.seq)(tableRef, (0, utils_1.optional)(as))(ast_1.TableExpression.createTable); | ||
function tableExprReducer(acc, joinSpec) { | ||
@@ -138,4 +138,4 @@ switch (joinSpec.join.kind) { | ||
} | ||
const tableExpression = typed_parser_1.seq(typed_parser_1.oneOf(typed_parser_1.attempt(typed_parser_1.seq2(token_1.symbol('('), typed_parser_1.lazy(() => tableExpression), token_1.symbol(')'))), typed_parser_1.attempt(typed_parser_1.seq(parenthesized(typed_parser_1.lazy(() => statementParser)), as)((stmt, as) => ast_1.TableExpression.createSubQuery(stmt, as))), table), typed_parser_1.many(typed_parser_1.oneOf(crossJoin, qualifiedJoin, naturalJoin)))((lhs, rest) => (rest.length === 0 ? lhs : rest.reduce(tableExprReducer, lhs))); | ||
const from = typed_parser_1.seq(token_1.reservedWord('FROM'), tableExpression, typed_parser_1.many(typed_parser_1.seq2(token_1.symbol(','), tableExpression)))((_from, tableExpr, rest) => rest.length === 0 | ||
const tableExpression = (0, typed_parser_1.seq)((0, typed_parser_1.oneOf)((0, typed_parser_1.attempt)((0, typed_parser_1.seq2)((0, token_1.symbol)('('), (0, typed_parser_1.lazy)(() => tableExpression), (0, token_1.symbol)(')'))), (0, typed_parser_1.attempt)((0, typed_parser_1.seq)(parenthesized((0, typed_parser_1.lazy)(() => statementParser)), as)((stmt, as) => ast_1.TableExpression.createSubQuery(stmt, as))), table), (0, typed_parser_1.many)((0, typed_parser_1.oneOf)(crossJoin, qualifiedJoin, naturalJoin)))((lhs, rest) => (rest.length === 0 ? lhs : rest.reduce(tableExprReducer, lhs))); | ||
const from = (0, typed_parser_1.seq)((0, token_1.reservedWord)('FROM'), tableExpression, (0, typed_parser_1.many)((0, typed_parser_1.seq2)((0, token_1.symbol)(','), tableExpression)))((_from, tableExpr, rest) => rest.length === 0 | ||
? tableExpr | ||
@@ -145,49 +145,49 @@ : // Implicit join equals to CROSS JOIN | ||
// WHERE | ||
const where = typed_parser_1.seq2(token_1.reservedWord('WHERE'), expression); | ||
const where = (0, typed_parser_1.seq2)((0, token_1.reservedWord)('WHERE'), expression); | ||
// GROUP BY & HAVING | ||
const groupBy = typed_parser_1.seq3(token_1.reservedWord('GROUP'), token_1.reservedWord('BY'), typed_parser_1.sepBy1(token_1.symbol(','), expression)); | ||
const having = typed_parser_1.seq2(token_1.reservedWord('HAVING'), expression); | ||
const groupBy = (0, typed_parser_1.seq3)((0, token_1.reservedWord)('GROUP'), (0, token_1.reservedWord)('BY'), (0, typed_parser_1.sepBy1)((0, token_1.symbol)(','), expression)); | ||
const having = (0, typed_parser_1.seq2)((0, token_1.reservedWord)('HAVING'), expression); | ||
// WINDOW | ||
const window = typed_parser_1.seq2(token_1.reservedWord('WINDOW'), typed_parser_1.sepBy1(token_1.symbol(','), typed_parser_1.seq(token_1.identifier, token_1.reservedWord('AS'), parenthesized(windowDefinition))((name, _as, window) => ast_1.NamedWindowDefinition.create(name, window)))); | ||
const window = (0, typed_parser_1.seq2)((0, token_1.reservedWord)('WINDOW'), (0, typed_parser_1.sepBy1)((0, token_1.symbol)(','), (0, typed_parser_1.seq)(token_1.identifier, (0, token_1.reservedWord)('AS'), parenthesized(windowDefinition))((name, _as, window) => ast_1.NamedWindowDefinition.create(name, window)))); | ||
// ORDER BY | ||
const orderByOrder = typed_parser_1.oneOf(token_1.reservedWord('ASC'), token_1.reservedWord('DESC'), typed_parser_1.seq(token_1.reservedWord('USING'), token_1.anyOperator)((_using, op) => ['USING', op])); | ||
const orderByNulls = typed_parser_1.seq2(token_1.reservedWord('NULLS'), typed_parser_1.oneOf(token_1.reservedWord('FIRST'), token_1.reservedWord('LAST'))); | ||
const orderByItem = typed_parser_1.seq(expression, utils_1.optional(orderByOrder), utils_1.optional(orderByNulls))((expr, order, nulls) => ast_1.OrderBy.create(expr, order, nulls)); | ||
const orderBy = typed_parser_1.seq(token_1.reservedWord('ORDER'), token_1.reservedWord('BY'), typed_parser_1.sepBy1(token_1.symbol(','), orderByItem))((_order, _by, list) => list); | ||
const orderByOrder = (0, typed_parser_1.oneOf)((0, token_1.reservedWord)('ASC'), (0, token_1.reservedWord)('DESC'), (0, typed_parser_1.seq)((0, token_1.reservedWord)('USING'), token_1.anyOperator)((_using, op) => ['USING', op])); | ||
const orderByNulls = (0, typed_parser_1.seq2)((0, token_1.reservedWord)('NULLS'), (0, typed_parser_1.oneOf)((0, token_1.reservedWord)('FIRST'), (0, token_1.reservedWord)('LAST'))); | ||
const orderByItem = (0, typed_parser_1.seq)(expression, (0, utils_1.optional)(orderByOrder), (0, utils_1.optional)(orderByNulls))((expr, order, nulls) => ast_1.OrderBy.create(expr, order, nulls)); | ||
const orderBy = (0, typed_parser_1.seq)((0, token_1.reservedWord)('ORDER'), (0, token_1.reservedWord)('BY'), (0, typed_parser_1.sepBy1)((0, token_1.symbol)(','), orderByItem))((_order, _by, list) => list); | ||
// LIMIT | ||
const limit = typed_parser_1.seq(token_1.reservedWord('LIMIT'), typed_parser_1.oneOf(typed_parser_1.seqNull(token_1.reservedWord('ALL')), expression), utils_1.optional(typed_parser_1.seq2(token_1.reservedWord('OFFSET'), expression)))((_l, count, offset) => ast_1.Limit.create(count, offset)); | ||
const limit = (0, typed_parser_1.seq)((0, token_1.reservedWord)('LIMIT'), (0, typed_parser_1.oneOf)((0, typed_parser_1.seqNull)((0, token_1.reservedWord)('ALL')), expression), (0, utils_1.optional)((0, typed_parser_1.seq2)((0, token_1.reservedWord)('OFFSET'), expression)))((_l, count, offset) => ast_1.Limit.create(count, offset)); | ||
// SELECT | ||
const distinct = typed_parser_1.oneOf(token_1.reservedWord('ALL'), typed_parser_1.seq(token_1.reservedWord('DISTINCT'), utils_1.optional(typed_parser_1.seq2(token_1.reservedWord('ON'), parenthesized(typed_parser_1.sepBy1(token_1.symbol(','), expression)))))((_distinct, on) => (on ? on : 'DISTINCT'))); | ||
const allFields = typed_parser_1.seqConst(ast_1.SelectListItem.createAllFields(), token_1.symbol('*')); | ||
const allTableFields = typed_parser_1.seq(token_1.identifier, token_1.symbol('.'), token_1.symbol('*'))((table, _p, _a) => ast_1.SelectListItem.createAllTableFields(table)); | ||
const selectListExpression = typed_parser_1.seq(expression, utils_1.optional(as))((expr, as) => ast_1.SelectListItem.createSelectListExpression(expr, as)); | ||
const selectListItem = typed_parser_1.oneOf(allFields, typed_parser_1.attempt(allTableFields), selectListExpression); | ||
const selectList = typed_parser_1.sepBy1(token_1.symbol(','), selectListItem); | ||
const selectBody = typed_parser_1.seq(token_1.reservedWord('SELECT'), utils_1.optional(distinct), selectList, utils_1.optional(from), utils_1.optional(where), utils_1.optional(groupBy), utils_1.optional(having), utils_1.optional(window))((_sel, distinct, list, from, where, groupBy, having, window) => ast_1.SelectBody.create(distinct || 'ALL', list, from, where, groupBy || [], having, window || [])); | ||
const selectSetOps = typed_parser_1.many(typed_parser_1.seq(typed_parser_1.oneOf(token_1.reservedWord('UNION'), token_1.reservedWord('INTERSECT'), token_1.reservedWord('EXCEPT')), utils_1.optional(typed_parser_1.oneOf(token_1.reservedWord('ALL'), token_1.reservedWord('DISTINCT'))), selectBody)((op, duplicates, body) => ast_1.SelectOp.create(op, duplicates || 'DISTINCT', body))); | ||
const select = typed_parser_1.seq(utils_1.optional(withQueries), selectBody, selectSetOps, utils_1.optional(orderBy), utils_1.optional(limit))((withQueries, body, setOps, orderBy, limit) => ast_1.Select.create(withQueries || [], body, setOps, orderBy || [], limit)); | ||
const distinct = (0, typed_parser_1.oneOf)((0, token_1.reservedWord)('ALL'), (0, typed_parser_1.seq)((0, token_1.reservedWord)('DISTINCT'), (0, utils_1.optional)((0, typed_parser_1.seq2)((0, token_1.reservedWord)('ON'), parenthesized((0, typed_parser_1.sepBy1)((0, token_1.symbol)(','), expression)))))((_distinct, on) => (on ? on : 'DISTINCT'))); | ||
const allFields = (0, typed_parser_1.seqConst)(ast_1.SelectListItem.createAllFields(), (0, token_1.symbol)('*')); | ||
const allTableFields = (0, typed_parser_1.seq)(token_1.identifier, (0, token_1.symbol)('.'), (0, token_1.symbol)('*'))((table, _p, _a) => ast_1.SelectListItem.createAllTableFields(table)); | ||
const selectListExpression = (0, typed_parser_1.seq)(expression, (0, utils_1.optional)(as))((expr, as) => ast_1.SelectListItem.createSelectListExpression(expr, as)); | ||
const selectListItem = (0, typed_parser_1.oneOf)(allFields, (0, typed_parser_1.attempt)(allTableFields), selectListExpression); | ||
const selectList = (0, typed_parser_1.sepBy1)((0, token_1.symbol)(','), selectListItem); | ||
const selectBody = (0, typed_parser_1.seq)((0, token_1.reservedWord)('SELECT'), (0, utils_1.optional)(distinct), selectList, (0, utils_1.optional)(from), (0, utils_1.optional)(where), (0, utils_1.optional)(groupBy), (0, utils_1.optional)(having), (0, utils_1.optional)(window))((_sel, distinct, list, from, where, groupBy, having, window) => ast_1.SelectBody.create(distinct || 'ALL', list, from, where, groupBy || [], having, window || [])); | ||
const selectSetOps = (0, typed_parser_1.many)((0, typed_parser_1.seq)((0, typed_parser_1.oneOf)((0, token_1.reservedWord)('UNION'), (0, token_1.reservedWord)('INTERSECT'), (0, token_1.reservedWord)('EXCEPT')), (0, utils_1.optional)((0, typed_parser_1.oneOf)((0, token_1.reservedWord)('ALL'), (0, token_1.reservedWord)('DISTINCT'))), selectBody)((op, duplicates, body) => ast_1.SelectOp.create(op, duplicates || 'DISTINCT', body))); | ||
const select = (0, typed_parser_1.seq)((0, utils_1.optional)(withQueries), selectBody, selectSetOps, (0, utils_1.optional)(orderBy), (0, utils_1.optional)(limit))((withQueries, body, setOps, orderBy, limit) => ast_1.Select.create(withQueries || [], body, setOps, orderBy || [], limit)); | ||
// INSERT | ||
const defaultValues = typed_parser_1.seq(token_1.reservedWord('DEFAULT'), token_1.reservedWord('VALUES'))((_def, _val) => ast_1.Values.defaultValues); | ||
const expressionValues = typed_parser_1.seq(token_1.reservedWord('VALUES'), typed_parser_1.sepBy(token_1.symbol(','), parenthesized(typed_parser_1.sepBy1(token_1.symbol(','), typed_parser_1.oneOf(typed_parser_1.seqNull(token_1.reservedWord('DEFAULT')), expression)))))((_val, values) => ast_1.Values.createExpressionValues(values)); | ||
const values = typed_parser_1.oneOf(defaultValues, expressionValues); | ||
const onConstraint = typed_parser_1.seqNull(token_1.reservedWord('ON'), token_1.reservedWord('CONSTRAINT'), token_1.identifier); | ||
const conflictTarget = typed_parser_1.oneOf(typed_parser_1.seqNull(identifierList), onConstraint); | ||
const conflictAction = typed_parser_1.seq2(token_1.reservedWord('DO'), typed_parser_1.oneOf(typed_parser_1.seqNull(token_1.reservedWord('NOTHING')), typed_parser_1.seq2(token_1.reservedWord('UPDATE'), typed_parser_1.lazy(() => updateAssignments)))); | ||
const onConflict = typed_parser_1.seq(token_1.reservedWord('ON'), token_1.reservedWord('CONFLICT'), utils_1.optional(conflictTarget), conflictAction)((_on, _conflict, _target, action) => action); | ||
const returning = typed_parser_1.seq2(token_1.reservedWord('RETURNING'), selectList); | ||
const insertInto = typed_parser_1.seq3(token_1.reservedWord('INSERT'), token_1.reservedWord('INTO'), tableRef); | ||
const insert = typed_parser_1.seq(utils_1.optional(withQueries), insertInto, utils_1.optional(reqAs), utils_1.optional(identifierList), typed_parser_1.oneOf(values, typed_parser_1.lazy(() => select)), utils_1.optional(onConflict), utils_1.optional(returning))((withQueries, table, as, columns, values, onConflict, returning) => ast_1.Insert.create(withQueries || [], table, as, columns || [], values, onConflict || [], returning || [])); | ||
const defaultValues = (0, typed_parser_1.seq)((0, token_1.reservedWord)('DEFAULT'), (0, token_1.reservedWord)('VALUES'))((_def, _val) => ast_1.Values.defaultValues); | ||
const expressionValues = (0, typed_parser_1.seq)((0, token_1.reservedWord)('VALUES'), (0, typed_parser_1.sepBy)((0, token_1.symbol)(','), parenthesized((0, typed_parser_1.sepBy1)((0, token_1.symbol)(','), (0, typed_parser_1.oneOf)((0, typed_parser_1.seqNull)((0, token_1.reservedWord)('DEFAULT')), expression)))))((_val, values) => ast_1.Values.createExpressionValues(values)); | ||
const values = (0, typed_parser_1.oneOf)(defaultValues, expressionValues); | ||
const onConstraint = (0, typed_parser_1.seqNull)((0, token_1.reservedWord)('ON'), (0, token_1.reservedWord)('CONSTRAINT'), token_1.identifier); | ||
const conflictTarget = (0, typed_parser_1.oneOf)((0, typed_parser_1.seqNull)(identifierList), onConstraint); | ||
const conflictAction = (0, typed_parser_1.seq2)((0, token_1.reservedWord)('DO'), (0, typed_parser_1.oneOf)((0, typed_parser_1.seqNull)((0, token_1.reservedWord)('NOTHING')), (0, typed_parser_1.seq2)((0, token_1.reservedWord)('UPDATE'), (0, typed_parser_1.lazy)(() => updateAssignments)))); | ||
const onConflict = (0, typed_parser_1.seq)((0, token_1.reservedWord)('ON'), (0, token_1.reservedWord)('CONFLICT'), (0, utils_1.optional)(conflictTarget), conflictAction)((_on, _conflict, _target, action) => action); | ||
const returning = (0, typed_parser_1.seq2)((0, token_1.reservedWord)('RETURNING'), selectList); | ||
const insertInto = (0, typed_parser_1.seq3)((0, token_1.reservedWord)('INSERT'), (0, token_1.reservedWord)('INTO'), tableRef); | ||
const insert = (0, typed_parser_1.seq)((0, utils_1.optional)(withQueries), insertInto, (0, utils_1.optional)(reqAs), (0, utils_1.optional)(identifierList), (0, typed_parser_1.oneOf)(values, (0, typed_parser_1.lazy)(() => select)), (0, utils_1.optional)(onConflict), (0, utils_1.optional)(returning))((withQueries, table, as, columns, values, onConflict, returning) => ast_1.Insert.create(withQueries || [], table, as, columns || [], values, onConflict || [], returning || [])); | ||
// UPDATE | ||
const updateAssignments = typed_parser_1.seq2(token_1.reservedWord('SET'), typed_parser_1.sepBy1(token_1.symbol(','), typed_parser_1.seq(token_1.identifier, token_1.symbol('='), expression)((columnName, _eq, value) => ({ columnName, value })))); | ||
const updateTable = typed_parser_1.seq2(token_1.reservedWord('UPDATE'), tableRef); | ||
const update = typed_parser_1.seq(utils_1.optional(withQueries), updateTable, utils_1.optional(reqAs), updateAssignments, utils_1.optional(from), utils_1.optional(where), utils_1.optional(returning))((withQueries, table, as, updates, from, where, returning) => ast_1.Update.create(withQueries || [], table, as, updates, from, where, returning || [])); | ||
const updateAssignments = (0, typed_parser_1.seq2)((0, token_1.reservedWord)('SET'), (0, typed_parser_1.sepBy1)((0, token_1.symbol)(','), (0, typed_parser_1.seq)(token_1.identifier, (0, token_1.symbol)('='), expression)((columnName, _eq, value) => ({ columnName, value })))); | ||
const updateTable = (0, typed_parser_1.seq2)((0, token_1.reservedWord)('UPDATE'), tableRef); | ||
const update = (0, typed_parser_1.seq)((0, utils_1.optional)(withQueries), updateTable, (0, utils_1.optional)(reqAs), updateAssignments, (0, utils_1.optional)(from), (0, utils_1.optional)(where), (0, utils_1.optional)(returning))((withQueries, table, as, updates, from, where, returning) => ast_1.Update.create(withQueries || [], table, as, updates, from, where, returning || [])); | ||
// DELETE | ||
const deleteFrom = typed_parser_1.seq3(token_1.reservedWord('DELETE'), token_1.reservedWord('FROM'), tableRef); | ||
const delete_ = typed_parser_1.seq(deleteFrom, utils_1.optional(reqAs), utils_1.optional(where), utils_1.optional(returning))((table, as, where, returning) => ast_1.Delete.create(table, as, where, returning || [])); | ||
const deleteFrom = (0, typed_parser_1.seq3)((0, token_1.reservedWord)('DELETE'), (0, token_1.reservedWord)('FROM'), tableRef); | ||
const delete_ = (0, typed_parser_1.seq)(deleteFrom, (0, utils_1.optional)(reqAs), (0, utils_1.optional)(where), (0, utils_1.optional)(returning))((table, as, where, returning) => ast_1.Delete.create(table, as, where, returning || [])); | ||
// parse | ||
const statementParser = typed_parser_1.seq1(typed_parser_1.oneOf(select, insert, update, delete_), utils_1.optional(token_1.symbol(';'))); | ||
const topLevelParser = typed_parser_1.seq2(token_1._, statementParser, typed_parser_1.end); | ||
const statementParser = (0, typed_parser_1.seq1)((0, typed_parser_1.oneOf)(select, insert, update, delete_), (0, utils_1.optional)((0, token_1.symbol)(';'))); | ||
const topLevelParser = (0, typed_parser_1.seq2)(token_1._, statementParser, typed_parser_1.end); | ||
function parse(source) { | ||
return Either_1.tryCatch(() => typed_parser_1.run(topLevelParser, source), (e) => e.explain()); | ||
return (0, Either_1.tryCatch)(() => (0, typed_parser_1.run)(topLevelParser, source), (e) => e.explain()); | ||
} | ||
exports.parse = parse; |
@@ -12,8 +12,8 @@ "use strict"; | ||
function specialFunctionParser(funcName, argsParser) { | ||
return typed_parser_1.seq(token_1.expectIdentifier(funcName), utils_1.parenthesized(argsParser))((_, argList) => ast_1.Expression.createFunctionCall(null, funcName, argList, null, null)); | ||
return (0, typed_parser_1.seq)((0, token_1.expectIdentifier)(funcName), (0, utils_1.parenthesized)(argsParser))((_, argList) => ast_1.Expression.createFunctionCall(null, funcName, argList, null, null)); | ||
} | ||
const overlayFunction = specialFunctionParser('overlay', typed_parser_1.seq(primaryExpr, token_1.expectIdentifier('placing'), primaryExpr, token_1.expectIdentifier('from'), primaryExpr, token_1.expectIdentifier('for'), primaryExpr)((a1, _placing, a2, _from, a3, _for, a4) => [a1, a2, a3, a4])); | ||
const positionFunction = specialFunctionParser('position', typed_parser_1.seq(primaryExpr, token_1.expectIdentifier('in'), primaryExpr)((a1, _in, a2) => [a1, a2])); | ||
const substringFunction = specialFunctionParser('substring', typed_parser_1.seq(primaryExpr, token_1.expectIdentifier('from'), primaryExpr, utils_1.optional(typed_parser_1.seq2(token_1.expectIdentifier('for'), primaryExpr)))((a1, _from, a2, a3) => (a3 ? [a1, a2, a3] : [a1, a2]))); | ||
const trimDirection = typed_parser_1.oneOf(token_1.expectIdentifier('leading'), token_1.expectIdentifier('trailing'), token_1.expectIdentifier('both')); | ||
const overlayFunction = specialFunctionParser('overlay', (0, typed_parser_1.seq)(primaryExpr, (0, token_1.expectIdentifier)('placing'), primaryExpr, (0, token_1.expectIdentifier)('from'), primaryExpr, (0, token_1.expectIdentifier)('for'), primaryExpr)((a1, _placing, a2, _from, a3, _for, a4) => [a1, a2, a3, a4])); | ||
const positionFunction = specialFunctionParser('position', (0, typed_parser_1.seq)(primaryExpr, (0, token_1.expectIdentifier)('in'), primaryExpr)((a1, _in, a2) => [a1, a2])); | ||
const substringFunction = specialFunctionParser('substring', (0, typed_parser_1.seq)(primaryExpr, (0, token_1.expectIdentifier)('from'), primaryExpr, (0, utils_1.optional)((0, typed_parser_1.seq2)((0, token_1.expectIdentifier)('for'), primaryExpr)))((a1, _from, a2, a3) => (a3 ? [a1, a2, a3] : [a1, a2]))); | ||
const trimDirection = (0, typed_parser_1.oneOf)((0, token_1.expectIdentifier)('leading'), (0, token_1.expectIdentifier)('trailing'), (0, token_1.expectIdentifier)('both')); | ||
function trimArgs(dir, chrs, str) { | ||
@@ -29,5 +29,5 @@ return [ | ||
// trim([leading | trailing | both] string [, characters] ) | ||
const trimFunction = specialFunctionParser('trim', typed_parser_1.seq(utils_1.optional(trimDirection), typed_parser_1.oneOf(typed_parser_1.seq(token_1.expectIdentifier('from'), primaryExpr, utils_1.optional(typed_parser_1.seq2(token_1.symbol(','), primaryExpr)))((_from, str, chars) => [str, chars]), typed_parser_1.oneOf(typed_parser_1.attempt(typed_parser_1.seq(primaryExpr, token_1.expectIdentifier('from'), primaryExpr)((chrs, _from, str) => [str, chrs])), typed_parser_1.seq(primaryExpr, utils_1.optional(typed_parser_1.seq2(token_1.symbol(','), primaryExpr)))((str, chrs) => [str, chrs]))))((dir, [str, chrs]) => trimArgs(dir, chrs, str))); | ||
return typed_parser_1.oneOf(overlayFunction, positionFunction, substringFunction, trimFunction); | ||
const trimFunction = specialFunctionParser('trim', (0, typed_parser_1.seq)((0, utils_1.optional)(trimDirection), (0, typed_parser_1.oneOf)((0, typed_parser_1.seq)((0, token_1.expectIdentifier)('from'), primaryExpr, (0, utils_1.optional)((0, typed_parser_1.seq2)((0, token_1.symbol)(','), primaryExpr)))((_from, str, chars) => [str, chars]), (0, typed_parser_1.oneOf)((0, typed_parser_1.attempt)((0, typed_parser_1.seq)(primaryExpr, (0, token_1.expectIdentifier)('from'), primaryExpr)((chrs, _from, str) => [str, chrs])), (0, typed_parser_1.seq)(primaryExpr, (0, utils_1.optional)((0, typed_parser_1.seq2)((0, token_1.symbol)(','), primaryExpr)))((str, chrs) => [str, chrs]))))((dir, [str, chrs]) => trimArgs(dir, chrs, str))); | ||
return (0, typed_parser_1.oneOf)(overlayFunction, positionFunction, substringFunction, trimFunction); | ||
} | ||
exports.specialFunctionCall = specialFunctionCall; |
@@ -8,5 +8,5 @@ "use strict"; | ||
// whitespace and comments | ||
exports._ = typed_parser_1.seqNull(typed_parser_1.skip('\\s*'), typed_parser_1.many(typed_parser_1.oneOf(typed_parser_1.seqNull(typed_parser_1.expectString('--'), typed_parser_1.stringBeforeEndOr('\n'), typed_parser_1.skip('\\s*')), typed_parser_1.seqNull(typed_parser_1.expectString('/*'), typed_parser_1.stringUntil('\\*/'), typed_parser_1.skip('\\s*'))))); | ||
exports._ = (0, typed_parser_1.seqNull)((0, typed_parser_1.skip)('\\s*'), (0, typed_parser_1.many)((0, typed_parser_1.oneOf)((0, typed_parser_1.seqNull)((0, typed_parser_1.expectString)('--'), (0, typed_parser_1.stringBeforeEndOr)('\n'), (0, typed_parser_1.skip)('\\s*')), (0, typed_parser_1.seqNull)((0, typed_parser_1.expectString)('/*'), (0, typed_parser_1.stringUntil)('\\*/'), (0, typed_parser_1.skip)('\\s*'))))); | ||
function symbol(s) { | ||
return typed_parser_1.seqNull(typed_parser_1.expectString(s, 'symbol'), exports._); | ||
return (0, typed_parser_1.seqNull)((0, typed_parser_1.expectString)(s, 'symbol'), exports._); | ||
} | ||
@@ -16,14 +16,14 @@ exports.symbol = symbol; | ||
function symbolKeepWS(s) { | ||
return typed_parser_1.expectString(s, 'symbol'); | ||
return (0, typed_parser_1.expectString)(s, 'symbol'); | ||
} | ||
exports.symbolKeepWS = symbolKeepWS; | ||
exports.matchIdentifier = typed_parser_1.match('[a-zA-Z_][a-zA-Z0-9_]*'); | ||
exports.quotedEscape = typed_parser_1.seq2(symbolKeepWS('\\'), typed_parser_1.oneOf(typed_parser_1.keyword('"', '"'), typed_parser_1.keyword('\\', '\\'))); | ||
exports.quotedInner = typed_parser_1.seq(typed_parser_1.stringBefore('[\\"]'), typed_parser_1.oneOf(typed_parser_1.seq(exports.quotedEscape, typed_parser_1.lazy(() => exports.quotedInner))((e, t) => e + t), typed_parser_1.constant('')))((s, tail) => s + tail); | ||
exports.quotedIdentifier = typed_parser_1.seq2(symbolKeepWS('"'), exports.quotedInner, symbol('"')); | ||
exports.identifier = typed_parser_1.seq1(typed_parser_1.attempt(typed_parser_1.oneOf(typed_parser_1.map((identifier, toError) => constants_1.sqlReservedWords.includes(identifier.toUpperCase()) | ||
exports.matchIdentifier = (0, typed_parser_1.match)('[a-zA-Z_][a-zA-Z0-9_]*'); | ||
exports.quotedEscape = (0, typed_parser_1.seq2)(symbolKeepWS('\\'), (0, typed_parser_1.oneOf)((0, typed_parser_1.keyword)('"', '"'), (0, typed_parser_1.keyword)('\\', '\\'))); | ||
exports.quotedInner = (0, typed_parser_1.seq)((0, typed_parser_1.stringBefore)('[\\"]'), (0, typed_parser_1.oneOf)((0, typed_parser_1.seq)(exports.quotedEscape, (0, typed_parser_1.lazy)(() => exports.quotedInner))((e, t) => e + t), (0, typed_parser_1.constant)('')))((s, tail) => s + tail); | ||
exports.quotedIdentifier = (0, typed_parser_1.seq2)(symbolKeepWS('"'), exports.quotedInner, symbol('"')); | ||
exports.identifier = (0, typed_parser_1.seq1)((0, typed_parser_1.attempt)((0, typed_parser_1.oneOf)((0, typed_parser_1.map)((identifier, toError) => constants_1.sqlReservedWords.includes(identifier.toUpperCase()) | ||
? toError(`Expected an identifier, got reserved word ${identifier}`) | ||
: identifier, exports.matchIdentifier), exports.quotedIdentifier)), exports._); | ||
function expectIdentifier(ident) { | ||
return typed_parser_1.seqConst(ident, typed_parser_1.attempt(typed_parser_1.map((match, toError) => match.toLowerCase() !== ident.toLowerCase() | ||
return (0, typed_parser_1.seqConst)(ident, (0, typed_parser_1.attempt)((0, typed_parser_1.map)((match, toError) => match.toLowerCase() !== ident.toLowerCase() | ||
? toError(`Expected ${ident}, got ${match}`) | ||
@@ -36,3 +36,3 @@ : ident, exports.matchIdentifier)), exports._); | ||
throw new Error(`INTERNAL ERROR: ${word} is not included in reservedWords`); | ||
return typed_parser_1.seq1(typed_parser_1.attempt(typed_parser_1.map((match, toError) => match.toUpperCase() !== word | ||
return (0, typed_parser_1.seq1)((0, typed_parser_1.attempt)((0, typed_parser_1.map)((match, toError) => match.toUpperCase() !== word | ||
? toError(`Expected ${word}, got ${match}`) | ||
@@ -42,10 +42,10 @@ : word, exports.matchIdentifier)), exports._); | ||
exports.reservedWord = reservedWord; | ||
const sepReserveds = (words) => typed_parser_1.attempt(typed_parser_1.seqConst(words, ...words.split(/\s+/).map((word) => typed_parser_1.seqNull(exports.reservedWord(word), exports._)), exports._)); | ||
const sepReserveds = (words) => (0, typed_parser_1.attempt)((0, typed_parser_1.seqConst)(words, ...words.split(/\s+/).map((word) => (0, typed_parser_1.seqNull)((0, exports.reservedWord)(word), exports._)), exports._)); | ||
exports.sepReserveds = sepReserveds; | ||
exports.anyOperator = typed_parser_1.seq1(typed_parser_1.match('[-+*/<>=~!@#%^&|`?]{1,63}'), exports._); | ||
const operator = (op) => typed_parser_1.attempt(typed_parser_1.map((match, toError) => match != op ? toError(`Operator ${op} expected`) : match, exports.anyOperator)); | ||
exports.anyOperator = (0, typed_parser_1.seq1)((0, typed_parser_1.match)('[-+*/<>=~!@#%^&|`?]{1,63}'), exports._); | ||
const operator = (op) => (0, typed_parser_1.attempt)((0, typed_parser_1.map)((match, toError) => match != op ? toError(`Operator ${op} expected`) : match, exports.anyOperator)); | ||
exports.operator = operator; | ||
const anyOperatorExcept = (exclude) => typed_parser_1.attempt(typed_parser_1.map((match, toError) => exclude.includes(match) | ||
const anyOperatorExcept = (exclude) => (0, typed_parser_1.attempt)((0, typed_parser_1.map)((match, toError) => exclude.includes(match) | ||
? toError(`Operator other than ${exclude.join(' ')} expected`) | ||
: match, exports.anyOperator)); | ||
exports.anyOperatorExcept = anyOperatorExcept; |
@@ -7,3 +7,3 @@ "use strict"; | ||
function optional(parser) { | ||
return typed_parser_1.oneOf(parser, typed_parser_1.seqNull(typed_parser_1.constant(''))); | ||
return (0, typed_parser_1.oneOf)(parser, (0, typed_parser_1.seqNull)((0, typed_parser_1.constant)(''))); | ||
} | ||
@@ -13,4 +13,4 @@ exports.optional = optional; | ||
function parenthesized(parser) { | ||
return typed_parser_1.seq2(token_1.symbol('('), parser, token_1.symbol(')')); | ||
return (0, typed_parser_1.seq2)((0, token_1.symbol)('('), parser, (0, token_1.symbol)(')')); | ||
} | ||
exports.parenthesized = parenthesized; |
@@ -12,15 +12,15 @@ "use strict"; | ||
const firstNumberedParam = numberedParamMatch[0]; | ||
return Either_1.left(`Cannot mix named parameters (${firstNamedParam}) and numbered \ | ||
return (0, Either_1.left)(`Cannot mix named parameters (${firstNamedParam}) and numbered \ | ||
parameters (${firstNumberedParam}) in the same statement`); | ||
} | ||
else if (namedParamMatch == null && numberedParamMatch == null) { | ||
return Either_1.right({ sql, paramNames: [] }); | ||
return (0, Either_1.right)({ sql, paramNames: [] }); | ||
} | ||
else if (namedParamMatch != null) { | ||
// Only named params | ||
return Either_1.right(handleNamedParams(sql, namedParamMatch)); | ||
return (0, Either_1.right)(handleNamedParams(sql, namedParamMatch)); | ||
} | ||
else if (numberedParamMatch != null) { | ||
// Only numbered params | ||
return Either_1.right(handleNumberedParams(sql, numberedParamMatch)); | ||
return (0, Either_1.right)(handleNumberedParams(sql, numberedParamMatch)); | ||
} | ||
@@ -27,0 +27,0 @@ else { |
@@ -15,3 +15,3 @@ "use strict"; | ||
const Task = require("fp-ts/lib/Task"); | ||
const pipeable_1 = require("fp-ts/lib/pipeable"); | ||
const function_1 = require("fp-ts/lib/function"); | ||
const sql = require("./sql"); | ||
@@ -41,3 +41,3 @@ const const_utils_1 = require("./const-utils"); | ||
}); | ||
const getEnums = func_utils_1.asyncCached(() => __awaiter(this, void 0, void 0, function* () { | ||
const getEnums = (0, func_utils_1.asyncCached)(() => __awaiter(this, void 0, void 0, function* () { | ||
return (yield sql.enums(postgresClient)).map((row) => ({ | ||
@@ -49,3 +49,3 @@ oid: row.oid, | ||
})); | ||
const getArrayTypes = func_utils_1.asyncCached(() => __awaiter(this, void 0, void 0, function* () { | ||
const getArrayTypes = (0, func_utils_1.asyncCached)(() => __awaiter(this, void 0, void 0, function* () { | ||
return (yield sql.arrayTypes(postgresClient)).map((row) => ({ | ||
@@ -56,3 +56,3 @@ oid: row.oid, | ||
})); | ||
const getFunctions = func_utils_1.asyncCached(() => __awaiter(this, void 0, void 0, function* () { | ||
const getFunctions = (0, func_utils_1.asyncCached)(() => __awaiter(this, void 0, void 0, function* () { | ||
return (yield sql.functions(postgresClient)).map((row) => ({ | ||
@@ -65,6 +65,6 @@ schema: row.nspname, | ||
const functionNullSafety = (schemaName, functionName) => { | ||
const builtin = schemaName === null ? const_utils_1.builtinFunctionNullSafety(functionName) : null; | ||
const builtin = schemaName === null ? (0, const_utils_1.builtinFunctionNullSafety)(functionName) : null; | ||
if (builtin !== null) | ||
return Task.of(builtin); | ||
return pipeable_1.pipe(getFunctions, Task.map((functions) => { | ||
return (0, function_1.pipe)(getFunctions, Task.map((functions) => { | ||
const fn = functions.find((fn) => fn.name === functionName && | ||
@@ -71,0 +71,0 @@ (schemaName === null || fn.schema === schemaName)); |
@@ -16,3 +16,3 @@ "use strict"; | ||
const Task = require("fp-ts/lib/Task"); | ||
const pipeable_1 = require("fp-ts/lib/pipeable"); | ||
const function_1 = require("fp-ts/lib/function"); | ||
const types_1 = require("./types"); | ||
@@ -48,4 +48,4 @@ const schema_1 = require("./schema"); | ||
const result = types_1.ValueType.walk(valueType, { | ||
array: ({ oid, elemNullable }) => pipeable_1.pipe(arrayTsType(oid, elemNullable), Option.getOrElse(() => exports.defaultType)), | ||
any: ({ oid }) => pipeable_1.pipe( | ||
array: ({ oid, elemNullable }) => (0, function_1.pipe)(arrayTsType(oid, elemNullable), Option.getOrElse(() => exports.defaultType)), | ||
any: ({ oid }) => (0, function_1.pipe)( | ||
// If it's an array type its items can be NULL, unless we | ||
@@ -60,3 +60,3 @@ // know how the array was constructed (see the array handler | ||
function columnType(column) { | ||
return pipeable_1.pipe(tsType(column.type, column.nullable), Task.map((type) => ({ | ||
return (0, function_1.pipe)(tsType(column.type, column.nullable), Task.map((type) => ({ | ||
name: column.name, | ||
@@ -132,3 +132,3 @@ type, | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const arrayTypes = yield schema_1.schemaClient(postgresClient).getArrayTypes(); | ||
const arrayTypes = yield (0, schema_1.schemaClient)(postgresClient).getArrayTypes(); | ||
return new Map(arrayTypes.map(({ oid, elemType }) => [oid, elemType])); | ||
@@ -139,3 +139,3 @@ }); | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const enums = yield schema_1.schemaClient(postgresClient).getEnums(); | ||
const enums = yield (0, schema_1.schemaClient)(postgresClient).getEnums(); | ||
return new Map(enums.map((enumType) => [ | ||
@@ -142,0 +142,0 @@ enumType.oid, |
{ | ||
"name": "sqltyper", | ||
"version": "1.2.0", | ||
"version": "1.3.0", | ||
"description": "Typed SQL queries in PostgreSQL", | ||
@@ -33,4 +33,4 @@ "main": "dist/src/index.js", | ||
"devDependencies": { | ||
"@types/jest": "^26.0.10", | ||
"@types/node": "^15.0.1", | ||
"@types/jest": "^27.0.1", | ||
"@types/node": "^16.3.1", | ||
"@types/ramda": "^0.27.3", | ||
@@ -42,7 +42,7 @@ "@types/wrap-ansi": "^3.0.0", | ||
"eslint": "^7.17.0", | ||
"eslint-plugin-prettier": "^3.1.3", | ||
"jest": "^26.0.1", | ||
"jest-cli": "^26.0.1", | ||
"eslint-plugin-prettier": "^4.0.0", | ||
"jest": "^27.2.0", | ||
"jest-cli": "^27.2.0", | ||
"prettier": "^2.0.2", | ||
"ts-jest": "^26.2.0", | ||
"ts-jest": "^27.0.3", | ||
"ts-node": "^10.0.0" | ||
@@ -49,0 +49,0 @@ }, |
@@ -71,4 +71,5 @@ # sqltyper - Type your SQL queries! | ||
The generated TypeScript code uses [node-postgres] or [postgres.js] to execute | ||
the queries, so either `pg` or `postgres` is a required runtime dependency: | ||
The generated TypeScript code uses [node-postgres], [postgres.js], or | ||
[pg-promise] to execute the queries, so either `pg`, `postgres`, or `pg-promise` | ||
is a required runtime dependency: | ||
@@ -79,2 +80,4 @@ ``` | ||
npm install --save postgres@beta | ||
# or | ||
npm install --save pg-promise | ||
``` | ||
@@ -197,4 +200,4 @@ | ||
Whether to generate code for `pg` ([node-postgres]) or `postgres` | ||
([postgres.js]). Default: `pg`. | ||
Whether to generate code for `pg` ([node-postgres]), `postgres` ([postgres.js]), | ||
or `pg-promise` ([pg-promise]). Default: `pg`. | ||
@@ -283,2 +286,3 @@ `--module`, `-m` | ||
[postgres.js]: https://github.com/porsager/postgres | ||
[pg-promise]: http://vitaly-t.github.io/pg-promise/ | ||
[sqlτyped]: https://github.com/jonifreeman/sqltyped |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
223840
4955
285