forked from felixfbecker/node-sql-template-strings
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
162 lines (154 loc) · 8.55 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
'use strict'
let pgKeywords = new Set(['A', 'ABORT', 'ABS', 'ABSENT', 'ABSOLUTE', 'ACCESS',
'ACCORDING', 'ACTION', 'ADA', 'ADD', 'ADMIN', 'AFTER', 'AGGREGATE', 'ALL',
'ALLOCATE', 'ALSO', 'ALTER', 'ALWAYS', 'ANALYSE', 'ANALYZE', 'AND', 'ANY',
'ARE', 'ARRAY', 'ARRAYAGG', 'ARRAYMAXCARDINALITY', 'AS', 'ASC', 'ASENSITIVE',
'ASSERTION', 'ASSIGNMENT', 'ASYMMETRIC', 'AT', 'ATOMIC', 'ATTRIBUTE',
'ATTRIBUTES', 'AUTHORIZATION', 'AVG', 'BACKWARD', 'BASE', 'BEFORE', 'BEGIN',
'BEGINFRAME', 'BEGINPARTITION', 'BERNOULLI', 'BETWEEN', 'BIGINT', 'BINARY',
'BIT', 'BITLENGTH', 'BLOB', 'BLOCKED', 'BOM', 'BOOLEAN', 'BOTH', 'BREADTH',
'BY', 'C', 'CACHE', 'CALL', 'CALLED', 'CARDINALITY', 'CASCADE', 'CASCADED',
'CASE', 'CAST', 'CATALOG', 'CATALOGNAME', 'CEIL', 'CEILING', 'CHAIN', 'CHAR',
'CHARACTER', 'CHARACTERISTICS', 'CHARACTERS', 'CHARACTERLENGTH',
'CHARACTERSETCATALOG', 'CHARACTERSETNAME', 'CHARACTERSETSCHEMA', 'CHARLENGTH',
'CHECK', 'CHECKPOINT', 'CLASS', 'CLASSORIGIN', 'CLOB', 'CLOSE', 'CLUSTER',
'COALESCE', 'COBOL', 'COLLATE', 'COLLATION', 'COLLATIONCATALOG',
'COLLATIONNAME', 'COLLATIONSCHEMA', 'COLLECT', 'COLUMN', 'COLUMNS',
'COLUMNNAME', 'COMMANDFUNCTION', 'COMMANDFUNCTIONCODE', 'COMMENT', 'COMMENTS',
'COMMIT', 'COMMITTED', 'CONCURRENTLY', 'CONDITION', 'CONDITIONNUMBER',
'CONFIGURATION', 'CONFLICT', 'CONNECT', 'CONNECTION', 'CONNECTIONNAME',
'CONSTRAINT', 'CONSTRAINTS', 'CONSTRAINTCATALOG', 'CONSTRAINTNAME',
'CONSTRAINTSCHEMA', 'CONSTRUCTOR', 'CONTAINS', 'CONTENT', 'CONTINUE',
'CONTROL', 'CONVERSION', 'CONVERT', 'COPY', 'CORR', 'CORRESPONDING', 'COST',
'COUNT', 'COVARPOP', 'COVARSAMP', 'CREATE', 'CROSS', 'CSV', 'CUBE',
'CUMEDIST', 'CURRENT', 'CURRENTCATALOG', 'CURRENTDATE',
'CURRENTDEFAULTTRANSFORMGROUP', 'CURRENTPATH', 'CURRENTROLE', 'CURRENTROW',
'CURRENTSCHEMA', 'CURRENTTIME', 'CURRENTTIMESTAMP',
'CURRENTTRANSFORMGROUPFORTYPE', 'CURRENTUSER', 'CURSOR', 'CURSORNAME',
'CYCLE', 'DATA', 'DATABASE', 'DATALINK', 'DATE', 'DATETIMEINTERVALCODE',
'DATETIMEINTERVALPRECISION', 'DAY', 'DB', 'DEALLOCATE', 'DEC', 'DECIMAL',
'DECLARE', 'DEFAULT', 'DEFAULTS', 'DEFERRABLE', 'DEFERRED', 'DEFINED',
'DEFINER', 'DEGREE', 'DELETE', 'DELIMITER', 'DELIMITERS', 'DENSERANK',
'DEPTH', 'DEREF', 'DERIVED', 'DESC', 'DESCRIBE', 'DESCRIPTOR',
'DETERMINISTIC', 'DIAGNOSTICS', 'DICTIONARY', 'DISABLE', 'DISCARD',
'DISCONNECT', 'DISPATCH', 'DISTINCT', 'DLNEWCOPY', 'DLPREVIOUSCOPY',
'DLURLCOMPLETE', 'DLURLCOMPLETEONLY', 'DLURLCOMPLETEWRITE', 'DLURLPATH',
'DLURLPATHONLY', 'DLURLPATHWRITE', 'DLURLSCHEME', 'DLURLSERVER', 'DLVALUE',
'DO', 'DOCUMENT', 'DOMAIN', 'DOUBLE', 'DROP', 'DYNAMIC', 'DYNAMICFUNCTION',
'DYNAMICFUNCTIONCODE', 'EACH', 'ELEMENT', 'ELSE', 'EMPTY', 'ENABLE',
'ENCODING', 'ENCRYPTED', 'END', 'ENDEXEC', 'ENDFRAME', 'ENDPARTITION',
'ENFORCED', 'ENUM', 'EQUALS', 'ESCAPE', 'EVENT', 'EVERY', 'EXCEPT',
'EXCEPTION', 'EXCLUDE', 'EXCLUDING', 'EXCLUSIVE', 'EXEC', 'EXECUTE', 'EXISTS',
'EXP', 'EXPLAIN', 'EXPRESSION', 'EXTENSION', 'EXTERNAL', 'EXTRACT', 'FALSE',
'FAMILY', 'FETCH', 'FILE', 'FILTER', 'FINAL', 'FIRST', 'FIRSTVALUE', 'FLAG',
'FLOAT', 'FLOOR', 'FOLLOWING', 'FOR', 'FORCE', 'FOREIGN', 'FORTRAN',
'FORWARD', 'FOUND', 'FRAMEROW', 'FREE', 'FREEZE', 'FROM', 'FS', 'FULL',
'FUNCTION', 'FUNCTIONS', 'FUSION', 'G', 'GENERAL', 'GENERATED', 'GET',
'GLOBAL', 'GO', 'GOTO', 'GRANT', 'GRANTED', 'GREATEST', 'GROUP', 'GROUPING',
'GROUPS', 'HANDLER', 'HAVING', 'HEADER', 'HEX', 'HIERARCHY', 'HOLD', 'HOUR',
'ID', 'IDENTITY', 'IF', 'IGNORE', 'ILIKE', 'IMMEDIATE', 'IMMEDIATELY',
'IMMUTABLE', 'IMPLEMENTATION', 'IMPLICIT', 'IMPORT', 'IN', 'INCLUDING',
'INCREMENT', 'INDENT', 'INDEX', 'INDEXES', 'INDICATOR', 'INHERIT', 'INHERITS',
'INITIALLY', 'INLINE', 'INNER', 'INOUT', 'INPUT', 'INSENSITIVE', 'INSERT',
'INSTANCE', 'INSTANTIABLE', 'INSTEAD', 'INT', 'INTEGER', 'INTEGRITY',
'INTERSECT', 'INTERSECTION', 'INTERVAL', 'INTO', 'INVOKER', 'IS', 'ISNULL',
'ISOLATION', 'JOIN', 'K', 'KEY', 'KEYMEMBER', 'KEYTYPE', 'LABEL', 'LAG',
'LANGUAGE', 'LARGE', 'LAST', 'LASTVALUE', 'LATERAL', 'LCCOLLATE', 'LCCTYPE',
'LEAD', 'LEADING', 'LEAKPROOF', 'LEAST', 'LEFT', 'LENGTH', 'LEVEL', 'LIBRARY',
'LIKE', 'LIKEREGEX', 'LIMIT', 'LINK', 'LISTEN', 'LN', 'LOAD', 'LOCAL',
'LOCALTIME', 'LOCALTIMESTAMP', 'LOCATION', 'LOCATOR', 'LOCK', 'LOWER', 'M',
'MAP', 'MAPPING', 'MATCH', 'MATCHED', 'MATERIALIZED', 'MAX', 'MAXVALUE',
'MAXCARDINALITY', 'MEMBER', 'MERGE', 'MESSAGELENGTH', 'MESSAGEOCTETLENGTH',
'MESSAGETEXT', 'METHOD', 'MIN', 'MINUTE', 'MINVALUE', 'MOD', 'MODE',
'MODIFIES', 'MODULE', 'MONTH', 'MORE', 'MOVE', 'MULTISET', 'MUMPS', 'NAME',
'NAMES', 'NAMESPACE', 'NATIONAL', 'NATURAL', 'NCHAR', 'NCLOB', 'NESTING',
'NEW', 'NEXT', 'NFC', 'NFD', 'NFKC', 'NFKD', 'NIL', 'NO', 'NONE', 'NORMALIZE',
'NORMALIZED', 'NOT', 'NOTHING', 'NOTIFY', 'NOTNULL', 'NOWAIT', 'NTHVALUE',
'NTILE', 'NULL', 'NULLABLE', 'NULLIF', 'NULLS', 'NUMBER', 'NUMERIC', 'OBJECT',
'OCCURRENCESREGEX', 'OCTETS', 'OCTETLENGTH', 'OF', 'OFF', 'OFFSET', 'OIDS',
'OLD', 'ON', 'ONLY', 'OPEN', 'OPERATOR', 'OPTION', 'OPTIONS', 'OR', 'ORDER',
'ORDERING', 'ORDINALITY', 'OTHERS', 'OUT', 'OUTER', 'OUTPUT', 'OVER',
'OVERLAPS', 'OVERLAY', 'OVERRIDING', 'OWNED', 'OWNER', 'P', 'PAD',
'PARAMETER', 'PARAMETERMODE', 'PARAMETERNAME', 'PARAMETERORDINALPOSITION',
'PARAMETERSPECIFICCATALOG', 'PARAMETERSPECIFICNAME',
'PARAMETERSPECIFICSCHEMA', 'PARSER', 'PARTIAL', 'PARTITION', 'PASCAL',
'PASSING', 'PASSTHROUGH', 'PASSWORD', 'PATH', 'PERCENT', 'PERCENTILECONT',
'PERCENTILEDISC', 'PERCENTRANK', 'PERIOD', 'PERMISSION', 'PLACING', 'PLANS',
'PLI', 'POLICY', 'PORTION', 'POSITION', 'POSITIONREGEX', 'POWER', 'PRECEDES',
'PRECEDING', 'PRECISION', 'PREPARE', 'PREPARED', 'PRESERVE', 'PRIMARY',
'PRIOR', 'PRIVILEGES', 'PROCEDURAL', 'PROCEDURE', 'PROGRAM', 'PUBLIC',
'QUOTE', 'RANGE', 'RANK', 'READ', 'READS', 'REAL', 'REASSIGN', 'RECHECK',
'RECOVERY', 'RECURSIVE', 'REF', 'REFERENCES', 'REFERENCING', 'REFRESH',
'REGRAVGX', 'REGRAVGY', 'REGRCOUNT', 'REGRINTERCEPT', 'REGRR', 'REGRSLOPE',
'REGRSXX', 'REGRSXY', 'REGRSYY', 'REINDEX', 'RELATIVE', 'RELEASE', 'RENAME',
'REPEATABLE', 'REPLACE', 'REPLICA', 'REQUIRING', 'RESET', 'RESPECT',
'RESTART', 'RESTORE', 'RESTRICT', 'RESULT', 'RETURN', 'RETURNEDCARDINALITY',
'RETURNEDLENGTH', 'RETURNEDOCTETLENGTH', 'RETURNEDSQLSTATE', 'RETURNING',
'RETURNS', 'REVOKE', 'RIGHT', 'ROLE', 'ROLLBACK', 'ROLLUP', 'ROUTINE',
'ROUTINECATALOG', 'ROUTINENAME', 'ROUTINESCHEMA', 'ROW', 'ROWS', 'ROWCOUNT',
'ROWNUMBER', 'RULE', 'SAVEPOINT', 'SCALE', 'SCHEMA', 'SCHEMANAME', 'SCOPE',
'SCOPECATALOG', 'SCOPENAME', 'SCOPESCHEMA', 'SCROLL', 'SEARCH', 'SECOND',
'SECTION', 'SECURITY', 'SELECT', 'SELECTIVE', 'SELF', 'SENSITIVE', 'SEQUENCE',
'SEQUENCES', 'SERIALIZABLE', 'SERVER', 'SERVERNAME', 'SESSION', 'SESSIONUSER',
'SET', 'SETOF', 'SETS', 'SHARE', 'SHOW', 'SIMILAR', 'SIMPLE', 'SIZE',
'SMALLINT', 'SNAPSHOT', 'SOME', 'SOURCE', 'SPACE', 'SPECIFIC', 'SPECIFICTYPE',
'SPECIFICNAME', 'SQL', 'SQLCODE', 'SQLERROR', 'SQLEXCEPTION', 'SQLSTATE',
'SQLWARNING', 'SQRT', 'STABLE', 'STANDALONE', 'START', 'STATE', 'STATEMENT',
'STATIC', 'STATISTICS', 'STDDEVPOP', 'STDDEVSAMP', 'STDIN', 'STDOUT',
'STORAGE', 'STRICT', 'STRIP'])
let pgIdentReg = /^[A-zÀ-ÿ_$]+$/
function SQL (strings) {
let args = Array.from(arguments).slice(1)
let sql = '' // for mysql/mysql2
let text = '' // for postgres
let values = []
for (let i = 0, stringsLength = strings.length, argsLength = args.length; i < stringsLength; i++) {
sql += strings[i]
text += strings[i]
if (typeof args[i] === 'object' && args[i] !== null && args[i].raw) {
sql += args[i].value
text += args[i].value
} else if (i < argsLength) {
values.push(args[i])
sql += '?'
text += '$' + values.length
}
}
return {sql, text, values}
}
SQL.raw = function (value) {
return {value, raw: true}
}
SQL.InvalidValue = function (msg) {
Error.call(this, msg)
this.name = 'SQLTemplateInvalidValue'
}
SQL.InvalidValue.prototoype = Object.create(Error.prototype)
SQL.PG = {
keyword: function (value, subset) {
value = value.toUpperCase()
if (subset) {
subset = new Set(subset)
if (!subset.has(value)) {
throw new SQL.InvalidValue()
}
}
if (!pgKeywords.has(value)) {
throw new SQL.InvalidValue()
}
return {value, raw: true}
},
identifier: function (value, subset) {
if (subset) {
subset = new Set(subset)
if (!subset.has(value.toLowerCase())) {
throw new SQL.InvalidValue()
}
}
if (!pgIdentReg.test(value)) {
throw new SQL.InvalidValue()
}
return {value: `"${value}"`, raw: true}
}
}
module.exports = SQL