DefPixel-PostgreSQL 0.1.6__91-py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. DefPixel/DataAccessObject/Implements/PostgreSQL/Adapters/Array.py +16 -0
  2. DefPixel/DataAccessObject/Implements/PostgreSQL/Adapters/JavaScriptObjectNotation.py +74 -0
  3. DefPixel/DataAccessObject/Implements/PostgreSQL/Adapters/__init__.py +51 -0
  4. DefPixel/DataAccessObject/Implements/PostgreSQL/Column.py +34 -0
  5. DefPixel/DataAccessObject/Implements/PostgreSQL/Compiler.py +161 -0
  6. DefPixel/DataAccessObject/Implements/PostgreSQL/Configuration.py +116 -0
  7. DefPixel/DataAccessObject/Implements/PostgreSQL/Connection.py +138 -0
  8. DefPixel/DataAccessObject/Implements/PostgreSQL/Constraint.py +18 -0
  9. DefPixel/DataAccessObject/Implements/PostgreSQL/Constraints/Check.py +23 -0
  10. DefPixel/DataAccessObject/Implements/PostgreSQL/Constraints/Columns.py +24 -0
  11. DefPixel/DataAccessObject/Implements/PostgreSQL/Constraints/ForeignKey.py +56 -0
  12. DefPixel/DataAccessObject/Implements/PostgreSQL/Constraints/PrimaryKey.py +21 -0
  13. DefPixel/DataAccessObject/Implements/PostgreSQL/Constraints/Unique.py +25 -0
  14. DefPixel/DataAccessObject/Implements/PostgreSQL/Constraints/__init__.py +13 -0
  15. DefPixel/DataAccessObject/Implements/PostgreSQL/Context.py +48 -0
  16. DefPixel/DataAccessObject/Implements/PostgreSQL/Cursor.py +123 -0
  17. DefPixel/DataAccessObject/Implements/PostgreSQL/Executors/Create.py +181 -0
  18. DefPixel/DataAccessObject/Implements/PostgreSQL/Executors/Delete.py +31 -0
  19. DefPixel/DataAccessObject/Implements/PostgreSQL/Executors/Drop.py +53 -0
  20. DefPixel/DataAccessObject/Implements/PostgreSQL/Executors/Get.py +24 -0
  21. DefPixel/DataAccessObject/Implements/PostgreSQL/Executors/Insert.py +98 -0
  22. DefPixel/DataAccessObject/Implements/PostgreSQL/Executors/Query.py +37 -0
  23. DefPixel/DataAccessObject/Implements/PostgreSQL/Executors/Select.py +122 -0
  24. DefPixel/DataAccessObject/Implements/PostgreSQL/Executors/Update.py +57 -0
  25. DefPixel/DataAccessObject/Implements/PostgreSQL/Executors/__init__.py +19 -0
  26. DefPixel/DataAccessObject/Implements/PostgreSQL/Expr.py +11 -0
  27. DefPixel/DataAccessObject/Implements/PostgreSQL/Exprs/Common.py +180 -0
  28. DefPixel/DataAccessObject/Implements/PostgreSQL/Exprs/Compare.py +87 -0
  29. DefPixel/DataAccessObject/Implements/PostgreSQL/Exprs/Condition.py +155 -0
  30. DefPixel/DataAccessObject/Implements/PostgreSQL/Exprs/JavaScriptObjectNotation.py +53 -0
  31. DefPixel/DataAccessObject/Implements/PostgreSQL/Exprs/Operator.py +42 -0
  32. DefPixel/DataAccessObject/Implements/PostgreSQL/Exprs/String.py +48 -0
  33. DefPixel/DataAccessObject/Implements/PostgreSQL/Exprs/__init__.py +75 -0
  34. DefPixel/DataAccessObject/Implements/PostgreSQL/Function.py +11 -0
  35. DefPixel/DataAccessObject/Implements/PostgreSQL/Functions/Common.py +142 -0
  36. DefPixel/DataAccessObject/Implements/PostgreSQL/Functions/DateTime.py +219 -0
  37. DefPixel/DataAccessObject/Implements/PostgreSQL/Functions/JavaScriptObjectNotation.py +100 -0
  38. DefPixel/DataAccessObject/Implements/PostgreSQL/Functions/Sequence.py +55 -0
  39. DefPixel/DataAccessObject/Implements/PostgreSQL/Functions/__init__.py +91 -0
  40. DefPixel/DataAccessObject/Implements/PostgreSQL/Index.py +135 -0
  41. DefPixel/DataAccessObject/Implements/PostgreSQL/Joins/FullOuter.py +15 -0
  42. DefPixel/DataAccessObject/Implements/PostgreSQL/Joins/Inner.py +15 -0
  43. DefPixel/DataAccessObject/Implements/PostgreSQL/Joins/Join.py +41 -0
  44. DefPixel/DataAccessObject/Implements/PostgreSQL/Joins/LeftOuter.py +15 -0
  45. DefPixel/DataAccessObject/Implements/PostgreSQL/Joins/RightOuter.py +15 -0
  46. DefPixel/DataAccessObject/Implements/PostgreSQL/Joins/__init__.py +15 -0
  47. DefPixel/DataAccessObject/Implements/PostgreSQL/Mapping.py +359 -0
  48. DefPixel/DataAccessObject/Implements/PostgreSQL/Orders.py +59 -0
  49. DefPixel/DataAccessObject/Implements/PostgreSQL/Pool.py +84 -0
  50. DefPixel/DataAccessObject/Implements/PostgreSQL/Schema.py +28 -0
  51. DefPixel/DataAccessObject/Implements/PostgreSQL/Sequence.py +55 -0
  52. DefPixel/DataAccessObject/Implements/PostgreSQL/Session.py +84 -0
  53. DefPixel/DataAccessObject/Implements/PostgreSQL/Type.py +113 -0
  54. DefPixel/DataAccessObject/Implements/PostgreSQL/Types/Array.py +61 -0
  55. DefPixel/DataAccessObject/Implements/PostgreSQL/Types/Binary.py +34 -0
  56. DefPixel/DataAccessObject/Implements/PostgreSQL/Types/Bool.py +29 -0
  57. DefPixel/DataAccessObject/Implements/PostgreSQL/Types/DateTime.py +120 -0
  58. DefPixel/DataAccessObject/Implements/PostgreSQL/Types/JavaScriptObjectNotation.py +52 -0
  59. DefPixel/DataAccessObject/Implements/PostgreSQL/Types/Numeric.py +151 -0
  60. DefPixel/DataAccessObject/Implements/PostgreSQL/Types/Size.py +13 -0
  61. DefPixel/DataAccessObject/Implements/PostgreSQL/Types/String.py +80 -0
  62. DefPixel/DataAccessObject/Implements/PostgreSQL/Types/__init__.py +76 -0
  63. DefPixel/DataAccessObject/Implements/PostgreSQL/__init__.py +85 -0
  64. defpixel_postgresql-0.1.6.dist-info/METADATA +184 -0
  65. defpixel_postgresql-0.1.6.dist-info/RECORD +68 -0
  66. defpixel_postgresql-0.1.6.dist-info/WHEEL +6 -0
  67. defpixel_postgresql-0.1.6.dist-info/licenses/LICENSE +674 -0
  68. defpixel_postgresql-0.1.6.dist-info/top_level.txt +1 -0
@@ -0,0 +1,37 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from abc import abstractmethod
4
+ from typing import (
5
+ Any,
6
+ Dict,
7
+ )
8
+
9
+ from ..Compiler import (
10
+ Compilable,
11
+ Compiler,
12
+ )
13
+
14
+ __all__ = (
15
+ 'Query',
16
+ )
17
+
18
+
19
+ class Query(Compilable):
20
+ """Executor base whose query and args come from one deterministic compilation."""
21
+
22
+ @abstractmethod
23
+ def compile(self, compiler: Compiler) -> str:
24
+ raise NotImplementedError('{} must be implemented compile'.format(self.__class__.__name__))
25
+
26
+ def statement(self):
27
+ compiler = Compiler()
28
+ query = self.compile(compiler)
29
+ return query, compiler.args
30
+
31
+ @property
32
+ def query(self) -> str:
33
+ return self.statement()[0]
34
+
35
+ @property
36
+ def args(self) -> Dict[str, Any]:
37
+ return self.statement()[1]
@@ -0,0 +1,122 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from DefPixel.DataAccessObject.Properties.Database import (
4
+ Executor,
5
+ Fetch,
6
+ )
7
+ from ..Column import Column
8
+ from ..Compiler import (
9
+ Compilable,
10
+ Compiler,
11
+ )
12
+ from ..Exprs.Operator import conditions
13
+ from ..Joins import Join
14
+ from ..Mapping import inspect_model
15
+ from .Query import Query
16
+
17
+ __all__ = (
18
+ 'Select',
19
+ )
20
+
21
+
22
+ def expressions(args, name: str) -> tuple:
23
+ result = []
24
+ for arg in args:
25
+ if isinstance(arg, str):
26
+ arg = Column(arg)
27
+ if not isinstance(arg, Compilable):
28
+ raise TypeError('{} must be column names or SQL expressions'.format(name))
29
+ result.append(arg)
30
+ return tuple(result)
31
+
32
+
33
+ class Select(Query, Executor, Fetch):
34
+ """SELECT query for a mapped table or view."""
35
+
36
+ def __init__(self, o):
37
+ self.mapping = inspect_model(o)
38
+ self.joins = ()
39
+ self.conds = ()
40
+ self.grps = ()
41
+ self.havs = ()
42
+ self.ords = ()
43
+ self.vals = ()
44
+ self.offset = 0
45
+ self.size = None
46
+ return
47
+
48
+ def join(self, *args):
49
+ for arg in args:
50
+ if not isinstance(arg, Join):
51
+ raise TypeError('join requires Join objects')
52
+ self.joins = args
53
+ return self
54
+
55
+ def where(self, *args):
56
+ self.conds = conditions(args)
57
+ return self
58
+
59
+ def group(self, *args):
60
+ self.grps = expressions(args, 'Groups')
61
+ return self
62
+
63
+ def having(self, *args):
64
+ self.havs = conditions(args)
65
+ return self
66
+
67
+ def order(self, *args):
68
+ self.ords = expressions(args, 'Orders')
69
+ return self
70
+
71
+ def limit(
72
+ self,
73
+ size=None,
74
+ offset=0,
75
+ ):
76
+ if size is not None and (type(size) is not int or size < 0):
77
+ raise ValueError('size must be a nonnegative integer')
78
+ if type(offset) is not int or offset < 0:
79
+ raise ValueError('offset must be a nonnegative integer')
80
+ self.size = size
81
+ self.offset = offset
82
+ return self
83
+
84
+ def values(self, *args):
85
+ self.vals = expressions(args, 'Values')
86
+ return self
87
+
88
+ def compile(self, compiler: Compiler) -> str:
89
+ columns = self.vals or tuple(self.mapping.columns.values())
90
+ sql = 'SELECT {} FROM {}'.format(
91
+ ', '.join(compiler.compile(value) for value in columns),
92
+ self.mapping.target,
93
+ )
94
+ for join in self.joins:
95
+ sql += ' ' + compiler.compile(join)
96
+ for keyword, values, separator in (
97
+ ('WHERE', self.conds, ' AND '),
98
+ ('GROUP BY', self.grps, ', '),
99
+ ('HAVING', self.havs, ' AND '),
100
+ ('ORDER BY', self.ords, ', '),
101
+ ):
102
+ if values:
103
+ sql += ' {} {}'.format(keyword, separator.join(compiler.compile(value) for value in values))
104
+ if self.size is not None:
105
+ sql += ' LIMIT {}'.format(self.size)
106
+ if self.offset:
107
+ sql += ' OFFSET {}'.format(self.offset)
108
+ return sql
109
+
110
+ def fetch(
111
+ self,
112
+ cursor,
113
+ filter=None,
114
+ fetch=None,
115
+ ):
116
+ mapping = inspect_model(fetch) if fetch is not None else None
117
+ result = []
118
+ for row in cursor.rows():
119
+ if filter is not None:
120
+ row = filter(row)
121
+ result.append(mapping.restore(row) if mapping is not None else row)
122
+ return result if result else None
@@ -0,0 +1,57 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from DefPixel.DataAccessObject.Properties.Database import (
4
+ Executor,
5
+ Fetch,
6
+ )
7
+ from ..Compiler import (
8
+ Compiler,
9
+ identifier,
10
+ valuetype,
11
+ )
12
+ from ..Exprs.Operator import conditions
13
+ from ..Mapping import inspect_model
14
+ from .Insert import first
15
+ from .Query import Query
16
+
17
+ __all__ = (
18
+ 'Update',
19
+ )
20
+
21
+
22
+ class Update(Query, Executor, Fetch):
23
+ """UPDATE ... SET ... [WHERE ...] RETURNING *; fetch returns the first updated row."""
24
+
25
+ def __init__(self, o):
26
+ self.mapping = inspect_model(o, 'table')
27
+ self.kwargs = {}
28
+ self.conds = ()
29
+ return
30
+
31
+ def set(self, **kwargs):
32
+ self.kwargs.update(self.mapping.values(kwargs))
33
+ return self
34
+
35
+ def where(self, *args):
36
+ self.conds = conditions(args)
37
+ return self
38
+
39
+ def compile(self, compiler: Compiler) -> str:
40
+ if not self.kwargs:
41
+ raise ValueError('No columns are specified for update')
42
+ return 'UPDATE {} SET {}{} RETURNING *'.format(
43
+ self.mapping.target,
44
+ ', '.join(
45
+ '{}={}'.format(identifier(key), compiler.bind(value, valuetype(spec)))
46
+ for key, (spec, value) in self.kwargs.items()
47
+ ),
48
+ ' WHERE {}'.format(' AND '.join(compiler.compile(cond) for cond in self.conds)) if self.conds else '',
49
+ )
50
+
51
+ def fetch(
52
+ self,
53
+ cursor,
54
+ filter=None,
55
+ fetch=None,
56
+ ):
57
+ return first(cursor, filter, fetch)
@@ -0,0 +1,19 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from .Create import Create
4
+ from .Drop import Drop
5
+ from .Insert import Insert
6
+ from .Update import Update
7
+ from .Delete import Delete
8
+ from .Select import Select
9
+ from .Get import Get
10
+
11
+ __all__ = (
12
+ 'Create',
13
+ 'Drop',
14
+ 'Insert',
15
+ 'Update',
16
+ 'Delete',
17
+ 'Select',
18
+ 'Get',
19
+ )
@@ -0,0 +1,11 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from .Compiler import Compilable
4
+
5
+ __all__ = (
6
+ 'Expr',
7
+ )
8
+
9
+
10
+ class Expr(Compilable):
11
+ """SQL expression that compiles into a fragment and bound parameters."""
@@ -0,0 +1,180 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from dataclasses import MISSING
4
+
5
+ from ..Compiler import (
6
+ Compilable,
7
+ Compiler,
8
+ identifier,
9
+ typename,
10
+ )
11
+ from ..Expr import Expr
12
+
13
+ __all__ = (
14
+ 'Alias',
15
+ 'TypeTo',
16
+ 'If',
17
+ 'IfNull',
18
+ 'IfNotNull',
19
+ 'Switch',
20
+ 'Query',
21
+ )
22
+
23
+
24
+ def term(compiler: Compiler, value) -> str:
25
+ """Compile a value, rendering None as the NULL keyword."""
26
+ if value is None:
27
+ return 'NULL'
28
+ return compiler.compile(value)
29
+
30
+
31
+ class Alias(Expr):
32
+ """expr AS "name"."""
33
+
34
+ def __init__(
35
+ self,
36
+ col,
37
+ name: str,
38
+ ):
39
+ identifier(name)
40
+ self.col = col
41
+ self.name = name
42
+ return
43
+
44
+ def compile(self, compiler: Compiler) -> str:
45
+ return '{} AS {}'.format(term(compiler, self.col), identifier(self.name))
46
+
47
+
48
+ class TypeTo(Expr):
49
+ """expr::type."""
50
+
51
+ def __init__(
52
+ self,
53
+ col,
54
+ type,
55
+ ):
56
+ typename(type)
57
+ self.col = col
58
+ self.type = type
59
+ return
60
+
61
+ def compile(self, compiler: Compiler) -> str:
62
+ if isinstance(self.col, Compilable):
63
+ return '({})::{}'.format(compiler.compile(self.col), typename(self.type))
64
+ if self.col is None:
65
+ return 'NULL::{}'.format(typename(self.type))
66
+ return compiler.bind(self.col, self.type)
67
+
68
+
69
+ class Conditional(Expr):
70
+ def __init__(
71
+ self,
72
+ cond,
73
+ thenexpr=None,
74
+ elseexpr=MISSING,
75
+ ):
76
+ self.cond = cond
77
+ self.thenexpr = thenexpr
78
+ self.elseexpr = elseexpr
79
+ return
80
+
81
+ def then_(self, expr):
82
+ self.thenexpr = expr
83
+ return self
84
+
85
+ def else_(self, expr):
86
+ self.elseexpr = expr
87
+ return self
88
+
89
+
90
+ class If(Conditional):
91
+ """CASE WHEN cond THEN then [ELSE else] END."""
92
+
93
+ def __init__(
94
+ self,
95
+ cond,
96
+ thenexpr=None,
97
+ elseexpr=MISSING,
98
+ ):
99
+ if not isinstance(cond, Compilable):
100
+ raise TypeError('If requires a SQL condition')
101
+ super().__init__(cond, thenexpr, elseexpr)
102
+ return
103
+
104
+ def compile(self, compiler: Compiler) -> str:
105
+ return 'CASE WHEN {} THEN {}{} END'.format(
106
+ compiler.compile(self.cond),
107
+ term(compiler, self.thenexpr),
108
+ '' if self.elseexpr is MISSING else ' ELSE {}'.format(term(compiler, self.elseexpr)),
109
+ )
110
+
111
+
112
+ class IfNull(Conditional):
113
+ """CASE WHEN expr IS NULL THEN then ELSE else-or-expr END."""
114
+
115
+ predicate = 'IS NULL'
116
+
117
+ def compile(self, compiler: Compiler) -> str:
118
+ return 'CASE WHEN {} {} THEN {} ELSE {} END'.format(
119
+ compiler.compile(self.cond),
120
+ self.predicate,
121
+ term(compiler, self.thenexpr),
122
+ compiler.compile(self.cond) if self.elseexpr is MISSING else term(compiler, self.elseexpr),
123
+ )
124
+
125
+
126
+ class IfNotNull(IfNull):
127
+ """CASE WHEN expr IS NOT NULL THEN then ELSE else-or-expr END."""
128
+
129
+ predicate = 'IS NOT NULL'
130
+
131
+
132
+ class Switch(Expr):
133
+ """CASE WHEN cond THEN value ... [ELSE other] END built from (cond, value) pairs."""
134
+
135
+ def __init__(self, *args):
136
+ self.args = []
137
+ self.elseexpr = MISSING
138
+ for arg in args:
139
+ if not isinstance(arg, (tuple, list)) or len(arg) != 2:
140
+ raise TypeError('Switch arguments must be (condition, value) pairs')
141
+ self.case(*arg)
142
+ return
143
+
144
+ def case(
145
+ self,
146
+ cond,
147
+ thenexpr=None,
148
+ ):
149
+ if not isinstance(cond, Compilable):
150
+ raise TypeError('Switch cases require SQL conditions')
151
+ self.args.append((cond, thenexpr))
152
+ return self
153
+
154
+ def other(self, elseexpr=None):
155
+ self.elseexpr = elseexpr
156
+ return self
157
+
158
+ def compile(self, compiler: Compiler) -> str:
159
+ if not self.args:
160
+ return 'NULL'
161
+ return 'CASE {}{} END'.format(
162
+ ' '.join(
163
+ 'WHEN {} THEN {}'.format(compiler.compile(cond), term(compiler, value))
164
+ for cond, value in self.args
165
+ ),
166
+ '' if self.elseexpr is MISSING else ' ELSE {}'.format(term(compiler, self.elseexpr)),
167
+ )
168
+
169
+
170
+ class Query(Expr):
171
+ """Parenthesized subquery whose parameters join the outer query."""
172
+
173
+ def __init__(self, executor):
174
+ if not isinstance(executor, Compilable):
175
+ raise TypeError('Query requires a PostgreSQL Select executor')
176
+ self.executor = executor
177
+ return
178
+
179
+ def compile(self, compiler: Compiler) -> str:
180
+ return '({})'.format(self.executor.compile(compiler))
@@ -0,0 +1,87 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from ..Compiler import Compiler
4
+ from ..Expr import Expr
5
+ from ..Types.JavaScriptObjectNotation import JavaScriptObjectNotation
6
+ from .JavaScriptObjectNotation import Of
7
+
8
+ __all__ = (
9
+ 'EqualTo',
10
+ 'NotEqualTo',
11
+ 'GreaterThan',
12
+ 'GreaterEqualTo',
13
+ 'LessThan',
14
+ 'LessEqualTo',
15
+ )
16
+
17
+
18
+ def is_json_type(expr):
19
+ if isinstance(expr, JavaScriptObjectNotation):
20
+ return expr
21
+ if isinstance(expr, Of) and expr.type is None:
22
+ return is_json_type(expr.col)
23
+ return None
24
+
25
+
26
+ class Compare(Expr):
27
+ operator = ''
28
+ null = None
29
+
30
+ def __init__(
31
+ self,
32
+ col,
33
+ other,
34
+ ):
35
+ self.col = col
36
+ self.other = other
37
+ return
38
+
39
+ def compile(self, compiler: Compiler) -> str:
40
+ json_type = is_json_type(self.col) or is_json_type(self.other)
41
+ if json_type is not None and isinstance(self.col, list):
42
+ col = compiler.bind(json_type.adapt(self.col))
43
+ else:
44
+ col = compiler.compile(self.col)
45
+ if isinstance(self.col, Expr):
46
+ col = '({})'.format(col)
47
+ if self.other is None and self.null is not None:
48
+ return '{} {}'.format(col, self.null)
49
+ if json_type is not None and isinstance(self.other, list):
50
+ other = compiler.bind(json_type.adapt(self.other))
51
+ else:
52
+ other = compiler.compile(self.other)
53
+ if isinstance(self.other, Expr):
54
+ other = '({})'.format(other)
55
+ return '{} {} {}'.format(
56
+ col,
57
+ self.operator,
58
+ other,
59
+ )
60
+
61
+
62
+ class EqualTo(Compare):
63
+ """col = other; None compiles to IS NULL."""
64
+ operator = '='
65
+ null = 'IS NULL'
66
+
67
+
68
+ class NotEqualTo(Compare):
69
+ """col != other; None compiles to IS NOT NULL."""
70
+ operator = '!='
71
+ null = 'IS NOT NULL'
72
+
73
+
74
+ class GreaterThan(Compare):
75
+ operator = '>'
76
+
77
+
78
+ class GreaterEqualTo(Compare):
79
+ operator = '>='
80
+
81
+
82
+ class LessThan(Compare):
83
+ operator = '<'
84
+
85
+
86
+ class LessEqualTo(Compare):
87
+ operator = '<='
@@ -0,0 +1,155 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from collections.abc import Sequence
4
+
5
+ from ..Compiler import (
6
+ Compilable,
7
+ Compiler,
8
+ typename,
9
+ valuetype,
10
+ )
11
+ from ..Expr import Expr
12
+ from ..Type import Type
13
+
14
+ __all__ = (
15
+ 'In',
16
+ 'NotIn',
17
+ 'Is',
18
+ 'IsNull',
19
+ 'IsNotNull',
20
+ 'IsTrue',
21
+ 'IsNotTrue',
22
+ 'IsFalse',
23
+ 'IsNotFalse',
24
+ 'IsUnknown',
25
+ 'IsNotUnknown',
26
+ )
27
+
28
+
29
+ class Membership(Expr):
30
+ operator = ''
31
+ array = ''
32
+
33
+ def __init__(
34
+ self,
35
+ col,
36
+ args=None,
37
+ ):
38
+ self.col = col
39
+ if args is None:
40
+ self.args = []
41
+ elif isinstance(args, Sequence) and not isinstance(args, (str, bytes, bytearray)):
42
+ self.args = list(args)
43
+ else:
44
+ self.args = [args]
45
+ return
46
+
47
+ def where(self, arg):
48
+ self.args.append(arg)
49
+ return self
50
+
51
+ def compile(self, compiler: Compiler) -> str:
52
+ col = compiler.compile(self.col)
53
+ if isinstance(self.col, Expr):
54
+ col = '({})'.format(col)
55
+ from .Common import Query
56
+ if len(self.args) == 1 and isinstance(self.args[0], Query):
57
+ return '{} {} {}'.format(col, self.operator, compiler.compile(self.args[0]))
58
+ if any(isinstance(arg, Compilable) for arg in self.args):
59
+ return '{} {} ({})'.format(
60
+ col,
61
+ self.operator,
62
+ ', '.join(compiler.compile(arg) for arg in self.args),
63
+ )
64
+ cast = None
65
+ if isinstance(self.col, Type):
66
+ if typename(self.col, escape=False).endswith(']'):
67
+ if not self.args:
68
+ return 'FALSE' if self.operator == 'IN' else 'TRUE'
69
+ return '{} {} ({})'.format(
70
+ col,
71
+ self.operator,
72
+ ', '.join(compiler.bind(arg, valuetype(self.col)) for arg in self.args),
73
+ )
74
+ cast = '{}[]'.format(valuetype(self.col))
75
+ return '{} {}({})'.format(col, self.array, compiler.bind(list(self.args), cast))
76
+
77
+
78
+ class In(Membership):
79
+ """col IN values; plain values are bound as one array parameter (= ANY)."""
80
+ operator = 'IN'
81
+ array = '= ANY'
82
+
83
+
84
+ class NotIn(Membership):
85
+ """col NOT IN values; plain values are bound as one array parameter (<> ALL)."""
86
+ operator = 'NOT IN'
87
+ array = '<> ALL'
88
+
89
+
90
+ KEYWORDS = {
91
+ None: 'NULL',
92
+ True: 'TRUE',
93
+ False: 'FALSE',
94
+ }
95
+
96
+
97
+ class Is(Expr):
98
+ """col IS other, where other is None, True, or False."""
99
+
100
+ def __init__(
101
+ self,
102
+ col,
103
+ other,
104
+ ):
105
+ if not any(other is key for key in KEYWORDS):
106
+ raise TypeError('Is requires None, True, or False')
107
+ self.col = col
108
+ self.other = other
109
+ return
110
+
111
+ def compile(self, compiler: Compiler) -> str:
112
+ return '{} IS {}'.format(compiler.compile(self.col), KEYWORDS[self.other])
113
+
114
+
115
+ class Predicate(Expr):
116
+ predicate = ''
117
+
118
+ def __init__(self, col):
119
+ self.col = col
120
+ return
121
+
122
+ def compile(self, compiler: Compiler) -> str:
123
+ return '{} {}'.format(compiler.compile(self.col), self.predicate)
124
+
125
+
126
+ class IsNull(Predicate):
127
+ predicate = 'IS NULL'
128
+
129
+
130
+ class IsNotNull(Predicate):
131
+ predicate = 'IS NOT NULL'
132
+
133
+
134
+ class IsTrue(Predicate):
135
+ predicate = 'IS TRUE'
136
+
137
+
138
+ class IsNotTrue(Predicate):
139
+ predicate = 'IS NOT TRUE'
140
+
141
+
142
+ class IsFalse(Predicate):
143
+ predicate = 'IS FALSE'
144
+
145
+
146
+ class IsNotFalse(Predicate):
147
+ predicate = 'IS NOT FALSE'
148
+
149
+
150
+ class IsUnknown(Predicate):
151
+ predicate = 'IS UNKNOWN'
152
+
153
+
154
+ class IsNotUnknown(Predicate):
155
+ predicate = 'IS NOT UNKNOWN'