UNPKG

6 kBJavaScriptView Raw
1// Generated by CoffeeScript 1.4.0
2/*
3Dialects are responsible for compiling an AST to a SQL string compatible with
4a particular DBMS. They are rarely used directly, instead a query is usually
5bound to an `engine <Engines>`_ that will delegate compiling to it's dialect
6instance.
7*/
8
9var BaseDialect, Delete, Insert, MySQLDialect, PostgresDialect, SQLite3Dialect, Select, Update, keywords, kwFile, read, _ref,
10 __hasProp = {}.hasOwnProperty,
11 __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
12
13read = require('fs').readFileSync;
14
15kwFile = __dirname + '/sql_keywords.txt';
16
17keywords = read(kwFile, 'ascii').split('\n').filter(Boolean);
18
19_ref = require('./nodes'), Select = _ref.Select, Update = _ref.Update, Delete = _ref.Delete, Insert = _ref.Insert;
20
21BaseDialect = (function() {
22 var Visitor, doubleQuote, needsQuote;
23
24 function BaseDialect() {}
25
26 BaseDialect.prototype.reset = function() {};
27
28 BaseDialect.prototype.compile = function(root) {
29 var text, visitor;
30 visitor = new Visitor(this);
31 text = visitor.compile(root);
32 return [text, visitor.params];
33 };
34
35 BaseDialect.prototype.renderString = function(s) {
36 var path;
37 path = this.path.map(function(p) {
38 var _ref1;
39 return (_ref1 = p.constructor) != null ? _ref1.name : void 0;
40 }).join(' > ');
41 this.path = [];
42 throw new Error("raw string compiled! " + path);
43 };
44
45 needsQuote = /\s|"|\./;
46
47 doubleQuote = /"/g;
48
49 BaseDialect.prototype.quote = function(s) {
50 if ((s != null ? s.match(needsQuote) : void 0) || this.isKeyword(s)) {
51 return '"' + s.replace(doubleQuote, '\\"') + '"';
52 } else {
53 return s;
54 }
55 };
56
57 BaseDialect.prototype.isKeyword = function(word) {
58 return keywords.indexOf(word.toUpperCase()) !== -1;
59 };
60
61 BaseDialect.prototype.operator = function(op) {
62 switch (op.toLowerCase()) {
63 case 'ne':
64 case '!=':
65 case '<>':
66 return '!=';
67 case 'eq':
68 case '=':
69 return '=';
70 case 'lt':
71 case '<':
72 return '<';
73 case 'gt':
74 case '>':
75 return '>';
76 case 'lte':
77 case '<=':
78 return '<=';
79 case 'gte':
80 case '>=':
81 return '>=';
82 case 'like':
83 return 'LIKE';
84 case 'ilike':
85 return 'ILIKE';
86 case 'in':
87 return 'IN';
88 case 'notin':
89 return 'NOT IN';
90 case 'is':
91 return 'IS';
92 default:
93 throw new Error("Unsupported comparison operator: " + op);
94 }
95 };
96
97 BaseDialect.prototype.placeholder = function(position) {
98 return "$" + position;
99 };
100
101 Visitor = (function() {
102
103 function Visitor(dialect) {
104 this.dialect = dialect;
105 this.path = [];
106 this.params = [];
107 }
108
109 Visitor.prototype.compile = function(node) {
110 var custom, name, string, _ref1, _ref2;
111 this.path.push(node);
112 name = node != null ? (_ref1 = node.__proto__) != null ? (_ref2 = _ref1.constructor) != null ? _ref2.name : void 0 : void 0 : void 0;
113 if (name && (custom = this.dialect['render' + name])) {
114 string = custom.call(this, node);
115 } else {
116 string = node.compile(this, this.path);
117 }
118 this.path.pop(node);
119 return string;
120 };
121
122 Visitor.prototype.maybeParens = function(it) {
123 if (/\s/.exec(it)) {
124 return "(" + it + ")";
125 } else {
126 return it;
127 }
128 };
129
130 Visitor.prototype.operator = function(string) {
131 return this.dialect.operator(string);
132 };
133
134 Visitor.prototype.parameter = function(val) {
135 this.params.push(val);
136 return this.dialect.placeholder(this.params.length);
137 };
138
139 Visitor.prototype.quote = function(string) {
140 return this.dialect.quote(string, this.path);
141 };
142
143 return Visitor;
144
145 })();
146
147 return BaseDialect;
148
149})();
150
151PostgresDialect = (function(_super) {
152
153 __extends(PostgresDialect, _super);
154
155 function PostgresDialect() {
156 return PostgresDialect.__super__.constructor.apply(this, arguments);
157 }
158
159 PostgresDialect.prototype.operator = function(op) {
160 switch (op.toLowerCase()) {
161 case 'hasKey':
162 return '?';
163 case '->':
164 return '->';
165 default:
166 return PostgresDialect.__super__.operator.call(this, op);
167 }
168 };
169
170 PostgresDialect.prototype.isKeyword = function(s) {
171 return (s != null) && s !== '*';
172 };
173
174 return PostgresDialect;
175
176})(BaseDialect);
177
178MySQLDialect = (function(_super) {
179
180 __extends(MySQLDialect, _super);
181
182 function MySQLDialect() {
183 return MySQLDialect.__super__.constructor.apply(this, arguments);
184 }
185
186 MySQLDialect.prototype.placeholder = function() {
187 return '?';
188 };
189
190 MySQLDialect.prototype.quote = function(s, path) {
191 /* Do not quote column names in insert column list
192 */
193 if (path.some(function(node) {
194 return node instanceof Insert.ColumnList;
195 })) {
196 return s;
197 } else {
198 return MySQLDialect.__super__.quote.apply(this, arguments);
199 }
200 };
201
202 return MySQLDialect;
203
204})(BaseDialect);
205
206SQLite3Dialect = (function(_super) {
207
208 __extends(SQLite3Dialect, _super);
209
210 function SQLite3Dialect() {
211 return SQLite3Dialect.__super__.constructor.apply(this, arguments);
212 }
213
214 SQLite3Dialect.prototype.placeholder = function() {
215 return '?';
216 };
217
218 SQLite3Dialect.prototype.renderInsertData = function(node) {
219 var string;
220 if (node.nodes.length < 2) {
221 return node.compile(this, this.path);
222 } else {
223 node.glue = ' UNION ALL SELECT ';
224 string = node.compile(this, this.path).replace('VALUES', 'SELECT').replace(/[()]/g, '');
225 node.glue = ', ';
226 return string;
227 }
228 };
229
230 return SQLite3Dialect;
231
232})(BaseDialect);
233
234module.exports = {
235 base: BaseDialect,
236 postgres: PostgresDialect,
237 mysql: MySQLDialect,
238 sqlite3: SQLite3Dialect
239};