source: OpenRLabs-Git/deploy/rlabs-docker/web2py-rlabs/gluon/packages/dal/pydal/dialects/postgre.py

main
Last change on this file was 42bd667, checked in by David Fuertes <dfuertes@…>, 4 years ago

Historial Limpio

  • Property mode set to 100755
File size: 14.0 KB
Line 
1from ..adapters.postgres import Postgre, PostgreNew, PostgreBoolean
2from .._compat import integer_types, basestring
3from ..helpers.methods import varquote_aux
4from ..objects import Expression
5from .base import SQLDialect
6from . import dialects, sqltype_for, register_expression
7
8
9@dialects.register_for(Postgre)
10class PostgreDialect(SQLDialect):
11    true_exp = "TRUE"
12    false_exp = "FALSE"
13
14    @sqltype_for("blob")
15    def type_blob(self):
16        return "BYTEA"
17
18    @sqltype_for("bigint")
19    def type_bigint(self):
20        return "BIGINT"
21
22    @sqltype_for("double")
23    def type_double(self):
24        return "FLOAT8"
25
26    @sqltype_for("id")
27    def type_id(self):
28        return "SERIAL PRIMARY KEY"
29
30    @sqltype_for("big-id")
31    def type_big_id(self):
32        return "BIGSERIAL PRIMARY KEY"
33
34    @sqltype_for("big-reference")
35    def type_big_reference(self):
36        return (
37            "BIGINT REFERENCES %(foreign_key)s "
38            + "ON DELETE %(on_delete_action)s %(null)s %(unique)s"
39        )
40
41    @sqltype_for("reference TFK")
42    def type_reference_tfk(self):
43        return (
44            ' CONSTRAINT "FK_%(constraint_name)s_PK" FOREIGN KEY '
45            + "(%(field_name)s) REFERENCES %(foreign_table)s"
46            + "(%(foreign_key)s) ON DELETE %(on_delete_action)s"
47        )
48
49    @sqltype_for("geometry")
50    def type_geometry(self):
51        return "GEOMETRY"
52
53    @sqltype_for("geography")
54    def type_geography(self):
55        return "GEOGRAPHY"
56
57    def varquote(self, val):
58        return varquote_aux(val, '"%s"')
59
60    def sequence_name(self, tablename):
61        return self.quote("%s_id_seq" % tablename)
62
63    def insert(self, table, fields, values, returning=None):
64        ret = ""
65        if returning:
66            ret = "RETURNING %s" % returning
67        return "INSERT INTO %s(%s) VALUES (%s)%s;" % (table, fields, values, ret)
68
69    @property
70    def random(self):
71        return "RANDOM()"
72
73    def add(self, first, second, query_env={}):
74        t = first.type
75        if t in ("text", "string", "password", "json", "jsonb", "upload", "blob"):
76            return "(%s || %s)" % (
77                self.expand(first, query_env=query_env),
78                self.expand(second, first.type, query_env=query_env),
79            )
80        else:
81            return "(%s + %s)" % (
82                self.expand(first, query_env=query_env),
83                self.expand(second, first.type, query_env=query_env),
84            )
85
86    def regexp(self, first, second, query_env={}):
87        return "(%s ~ %s)" % (
88            self.expand(first, query_env=query_env),
89            self.expand(second, "string", query_env=query_env),
90        )
91
92    def like(self, first, second, escape=None, query_env={}):
93        if isinstance(second, Expression):
94            second = self.expand(second, "string", query_env=query_env)
95        else:
96            second = self.expand(second, "string", query_env=query_env)
97            if escape is None:
98                escape = "\\"
99                second = second.replace(escape, escape * 2)
100        if first.type not in ("string", "text", "json", "jsonb"):
101            return "(%s LIKE %s ESCAPE '%s')" % (
102                self.cast(
103                    self.expand(first, query_env=query_env), "CHAR(%s)" % first.length
104                ),
105                second,
106                escape,
107            )
108        return "(%s LIKE %s ESCAPE '%s')" % (
109            self.expand(first, query_env=query_env),
110            second,
111            escape,
112        )
113
114    def ilike(self, first, second, escape=None, query_env={}):
115        if isinstance(second, Expression):
116            second = self.expand(second, "string", query_env=query_env)
117        else:
118            second = self.expand(second, "string", query_env=query_env)
119            if escape is None:
120                escape = "\\"
121                second = second.replace(escape, escape * 2)
122        if first.type not in ("string", "text", "json", "jsonb", "list:string"):
123            return "(%s ILIKE %s ESCAPE '%s')" % (
124                self.cast(
125                    self.expand(first, query_env=query_env), "CHAR(%s)" % first.length
126                ),
127                second,
128                escape,
129            )
130        return "(%s ILIKE %s ESCAPE '%s')" % (
131            self.expand(first, query_env=query_env),
132            second,
133            escape,
134        )
135
136    def drop_table(self, table, mode):
137        if mode not in ["restrict", "cascade", ""]:
138            raise ValueError("Invalid mode: %s" % mode)
139        return ["DROP TABLE " + table._rname + " " + mode + ";"]
140
141    def create_index(self, name, table, expressions, unique=False, where=None):
142        uniq = " UNIQUE" if unique else ""
143        whr = ""
144        if where:
145            whr = " %s" % self.where(where)
146        with self.adapter.index_expander():
147            rv = "CREATE%s INDEX %s ON %s (%s)%s;" % (
148                uniq,
149                self.quote(name),
150                table._rname,
151                ",".join(self.expand(field) for field in expressions),
152                whr,
153            )
154        return rv
155
156    def st_asgeojson(self, first, second, query_env={}):
157        return "ST_AsGeoJSON(%s,%s,%s)" % (
158            self.expand(first, query_env=query_env),
159            second["precision"],
160            second["options"],
161        )
162
163    def st_astext(self, first, query_env={}):
164        return "ST_AsText(%s)" % self.expand(first, query_env=query_env)
165
166    def st_aswkb(self, first, query_env={}):
167        return "%s" % self.expand(first, query_env=query_env)
168
169    def st_x(self, first, query_env={}):
170        return "ST_X(%s)" % (self.expand(first, query_env=query_env))
171
172    def st_y(self, first, query_env={}):
173        return "ST_Y(%s)" % (self.expand(first, query_env=query_env))
174
175    def st_contains(self, first, second, query_env={}):
176        return "ST_Contains(%s,%s)" % (
177            self.expand(first, query_env=query_env),
178            self.expand(second, first.type, query_env=query_env),
179        )
180
181    def st_distance(self, first, second, query_env={}):
182        return "ST_Distance(%s,%s)" % (
183            self.expand(first, query_env=query_env),
184            self.expand(second, first.type, query_env=query_env),
185        )
186
187    def st_equals(self, first, second, query_env={}):
188        return "ST_Equals(%s,%s)" % (
189            self.expand(first, query_env=query_env),
190            self.expand(second, first.type, query_env=query_env),
191        )
192
193    def st_intersects(self, first, second, query_env={}):
194        return "ST_Intersects(%s,%s)" % (
195            self.expand(first, query_env=query_env),
196            self.expand(second, first.type, query_env=query_env),
197        )
198
199    def st_overlaps(self, first, second, query_env={}):
200        return "ST_Overlaps(%s,%s)" % (
201            self.expand(first, query_env=query_env),
202            self.expand(second, first.type, query_env=query_env),
203        )
204
205    def st_simplify(self, first, second, query_env={}):
206        return "ST_Simplify(%s,%s)" % (
207            self.expand(first, query_env=query_env),
208            self.expand(second, "double", query_env=query_env),
209        )
210
211    def st_simplifypreservetopology(self, first, second, query_env={}):
212        return "ST_SimplifyPreserveTopology(%s,%s)" % (
213            self.expand(first, query_env=query_env),
214            self.expand(second, "double", query_env=query_env),
215        )
216
217    def st_touches(self, first, second, query_env={}):
218        return "ST_Touches(%s,%s)" % (
219            self.expand(first, query_env=query_env),
220            self.expand(second, first.type, query_env=query_env),
221        )
222
223    def st_within(self, first, second, query_env={}):
224        return "ST_Within(%s,%s)" % (
225            self.expand(first, query_env=query_env),
226            self.expand(second, first.type, query_env=query_env),
227        )
228
229    def st_dwithin(self, first, tup, query_env={}):
230        return "ST_DWithin(%s,%s,%s)" % (
231            self.expand(first, query_env=query_env),
232            self.expand(tup[0], first.type, query_env=query_env),
233            self.expand(tup[1], "double", query_env=query_env),
234        )
235
236    def st_transform(self, first, second, query_env={}):
237        # The SRID argument can be provided as an integer SRID or a Proj4 string
238        if isinstance(second, int):
239            return "ST_Transform(%s,%s)" % (
240                self.expand(first, query_env=query_env),
241                self.expand(second, "integer", query_env=query_env),
242            )
243        else:
244            return "ST_Transform(%s,%s)" % (
245                self.expand(first, query_env=query_env),
246                self.expand(second, "string", query_env=query_env),
247            )
248
249    @register_expression("doy")
250    def extract_doy(self, expr):
251        return Expression(expr.db, self.extract, expr, "doy", "integer")
252
253    @register_expression("dow")
254    def extract_dow(self, expr):
255        return Expression(expr.db, self.extract, expr, "dow", "integer")
256
257    @register_expression("isodow")
258    def extract_isodow(self, expr):
259        return Expression(expr.db, self.extract, expr, "isodow", "integer")
260
261    @register_expression("isoyear")
262    def extract_isoyear(self, expr):
263        return Expression(expr.db, self.extract, expr, "isoyear", "integer")
264
265    @register_expression("quarter")
266    def extract_quarter(self, expr):
267        return Expression(expr.db, self.extract, expr, "quarter", "integer")
268
269    @register_expression("week")
270    def extract_week(self, expr):
271        return Expression(expr.db, self.extract, expr, "week", "integer")
272
273    @register_expression("decade")
274    def extract_decade(self, expr):
275        return Expression(expr.db, self.extract, expr, "decade", "integer")
276
277    @register_expression("century")
278    def extract_century(self, expr):
279        return Expression(expr.db, self.extract, expr, "century", "integer")
280
281    @register_expression("millenium")
282    def extract_millenium(self, expr):
283        return Expression(expr.db, self.extract, expr, "millenium", "integer")
284
285
286class PostgreDialectJSON(PostgreDialect):
287    @sqltype_for("json")
288    def type_json(self):
289        return "JSON"
290
291    @sqltype_for("jsonb")
292    def type_jsonb(self):
293        return "JSONB"
294
295    def st_astext(self, first, query_env={}):
296        return "ST_AsText(%s)" % self.expand(first, query_env=query_env)
297
298    def st_asgeojson(self, first, second, query_env={}):
299        return "ST_AsGeoJSON(%s,%s,%s)" % (
300            self.expand(first, query_env=query_env),
301            second["precision"],
302            second["options"],
303        )
304
305    def json_key(self, first, key, query_env=None):
306        """ Get the json in key which you can use for more queries """
307        if isinstance(key, basestring):
308            key = self.expand(key, "string", query_env=query_env)
309        elif not isinstance(key, integer_types):
310            raise TypeError("Key must be a string or int")
311        return "%s->%s" % (self.expand(first, query_env=query_env or {}), key)
312
313    def json_key_value(self, first, key, query_env=None):
314        """ Get the value int or text in key """
315        if isinstance(key, basestring):
316            key = self.expand(key, "string", query_env=query_env)
317        elif isinstance(key, integer_types):
318            key = self.expand(key, "integer", query_env=query_env)
319        else:
320            raise TypeError("Key must be a string or int")
321        return "%s->>%s" % (self.expand(first, query_env=query_env or {}), key)
322
323    def json_path(self, first, path, query_env=None):
324        """ Get the json in path which you can use for more queries """
325        return "%s#>'%s'" % (self.expand(first, query_env=query_env or {}), path)
326
327    def json_path_value(self, first, path, query_env=None):
328        """ Get the json in path which you can use for more queries """
329        return "%s#>>'%s'" % (self.expand(first, query_env=query_env or {}), path)
330
331    # JSON Queries
332    def json_contains(self, first, jsonvalue, query_env=None):
333        # requires jsonb, value is json e.g. '{"country": "Peru"}'
334        return "%s::jsonb@>'%s'::jsonb" % (
335            self.expand(first, query_env=query_env or {}),
336            jsonvalue,
337        )
338
339
340@dialects.register_for(PostgreNew)
341class PostgreDialectArrays(PostgreDialect):
342    @sqltype_for("list:integer")
343    def type_list_integer(self):
344        return "BIGINT[]"
345
346    @sqltype_for("list:string")
347    def type_list_string(self):
348        return "TEXT[]"
349
350    @sqltype_for("list:reference")
351    def type_list_reference(self):
352        return "BIGINT[]"
353
354    def any(self, val, query_env={}):
355        return "ANY(%s)" % self.expand(val, query_env=query_env)
356
357    def contains(self, first, second, case_sensitive=True, query_env={}):
358        if first.type.startswith("list:"):
359            f = self.expand(second, "string", query_env=query_env)
360            s = self.any(first, query_env)
361            if case_sensitive is True:
362                return self.eq(f, s)
363            return self.ilike(f, s, escape="\\", query_env=query_env)
364        return super(PostgreDialectArrays, self).contains(
365            first, second, case_sensitive=case_sensitive, query_env=query_env
366        )
367
368    def ilike(self, first, second, escape=None, query_env={}):
369        if first and "type" not in first:
370            args = (first, self.expand(second, query_env=query_env))
371            return "(%s ILIKE %s)" % args
372        return super(PostgreDialectArrays, self).ilike(
373            first, second, escape=escape, query_env=query_env
374        )
375
376    def eq(self, first, second=None, query_env={}):
377        if first and "type" not in first:
378            return "(%s = %s)" % (first, self.expand(second, query_env=query_env))
379        return super(PostgreDialectArrays, self).eq(first, second, query_env)
380
381
382class PostgreDialectArraysJSON(PostgreDialectArrays):
383    @sqltype_for("json")
384    def type_json(self):
385        return "JSON"
386
387    @sqltype_for("jsonb")
388    def type_jsonb(self):
389        return "JSONB"
390
391
392@dialects.register_for(PostgreBoolean)
393class PostgreDialectBoolean(PostgreDialectArrays):
394    @sqltype_for("boolean")
395    def type_boolean(self):
396        return "BOOLEAN"
397
398
399class PostgreDialectBooleanJSON(PostgreDialectBoolean):
400    @sqltype_for("json")
401    def type_json(self):
402        return "JSON"
403
404    @sqltype_for("jsonb")
405    def type_jsonb(self):
406        return "JSONB"
Note: See TracBrowser for help on using the repository browser.