DefPixel-PostgreSQL 0.1.5__83-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.5.dist-info/METADATA +180 -0
  65. defpixel_postgresql-0.1.5.dist-info/RECORD +68 -0
  66. defpixel_postgresql-0.1.5.dist-info/WHEEL +6 -0
  67. defpixel_postgresql-0.1.5.dist-info/licenses/LICENSE +674 -0
  68. defpixel_postgresql-0.1.5.dist-info/top_level.txt +1 -0
@@ -0,0 +1,53 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from typing import Optional
4
+
5
+ from ..Column import Column
6
+ from ..Compiler import (
7
+ Compilable,
8
+ Compiler,
9
+ typename,
10
+ )
11
+ from ..Expr import Expr
12
+
13
+ __all__ = (
14
+ 'Of',
15
+ )
16
+
17
+
18
+ class Of(Expr):
19
+ """(json -> key)[::type]; str keys select object members and int keys select array elements."""
20
+
21
+ def __init__(
22
+ self,
23
+ col,
24
+ arg,
25
+ type=None,
26
+ ):
27
+ if isinstance(col, str):
28
+ col = Column(col)
29
+ if not isinstance(col, Compilable):
30
+ raise TypeError('Of requires a column or SQL expression')
31
+ if isinstance(arg, bool) or not isinstance(arg, (str, int, Compilable)):
32
+ raise TypeError('Of keys must be str, int, or SQL expressions')
33
+ self.col = col
34
+ self.arg = arg
35
+ self.type: Optional[str] = None
36
+ if type is not None:
37
+ self.cast(type)
38
+ return
39
+
40
+ def cast(self, type) -> 'Of':
41
+ self.type = typename(type)
42
+ return self
43
+
44
+ def compile(self, compiler: Compiler) -> str:
45
+ if isinstance(self.arg, Compilable):
46
+ arg = compiler.compile(self.arg)
47
+ else:
48
+ arg = compiler.bind(self.arg, 'TEXT' if isinstance(self.arg, str) else 'INTEGER')
49
+ return '({}->{}){}'.format(
50
+ compiler.compile(self.col),
51
+ arg,
52
+ '::{}'.format(self.type) if self.type else '',
53
+ )
@@ -0,0 +1,42 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from ..Compiler import (
4
+ Compilable,
5
+ Compiler,
6
+ )
7
+ from ..Expr import Expr
8
+
9
+ __all__ = (
10
+ 'And',
11
+ 'Or',
12
+ 'conditions',
13
+ )
14
+
15
+
16
+ def conditions(args, name: str = 'Conditions') -> tuple:
17
+ """Validate that every condition is a SQL expression."""
18
+ for arg in args:
19
+ if not isinstance(arg, Compilable):
20
+ raise TypeError('{} must be SQL expressions'.format(name))
21
+ return tuple(args)
22
+
23
+
24
+ class Logical(Expr):
25
+ operator = ''
26
+
27
+ def __init__(self, *args):
28
+ if not args:
29
+ raise ValueError('{} requires at least one condition'.format(self.__class__.__name__))
30
+ self.args = conditions(args)
31
+ return
32
+
33
+ def compile(self, compiler: Compiler) -> str:
34
+ return '({})'.format(' {} '.format(self.operator).join(compiler.compile(arg) for arg in self.args))
35
+
36
+
37
+ class And(Logical):
38
+ operator = 'AND'
39
+
40
+
41
+ class Or(Logical):
42
+ operator = 'OR'
@@ -0,0 +1,48 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from ..Compiler import Compiler
4
+ from ..Expr import Expr
5
+
6
+ __all__ = (
7
+ 'Like',
8
+ 'LikeStartWith',
9
+ 'LikeEndWith',
10
+ )
11
+
12
+
13
+ class Pattern(Expr):
14
+ prefix = ''
15
+ suffix = ''
16
+
17
+ def __init__(
18
+ self,
19
+ col,
20
+ other: str,
21
+ ):
22
+ if not isinstance(other, str):
23
+ raise TypeError('LIKE patterns must be strings')
24
+ self.col = col
25
+ self.other = other
26
+ return
27
+
28
+ def compile(self, compiler: Compiler) -> str:
29
+ return '{} LIKE {}'.format(
30
+ compiler.compile(self.col),
31
+ compiler.bind('{}{}{}'.format(self.prefix, self.other, self.suffix)),
32
+ )
33
+
34
+
35
+ class Like(Pattern):
36
+ """col LIKE '%other%'; wildcard characters in other keep their LIKE meaning."""
37
+ prefix = '%'
38
+ suffix = '%'
39
+
40
+
41
+ class LikeStartWith(Pattern):
42
+ """col LIKE 'other%'."""
43
+ suffix = '%'
44
+
45
+
46
+ class LikeEndWith(Pattern):
47
+ """col LIKE '%other'."""
48
+ prefix = '%'
@@ -0,0 +1,75 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from .Common import (
4
+ Alias,
5
+ TypeTo,
6
+ If,
7
+ IfNull,
8
+ IfNotNull,
9
+ Switch,
10
+ Query,
11
+ )
12
+ from .Condition import (
13
+ In,
14
+ NotIn,
15
+ Is,
16
+ IsNull,
17
+ IsNotNull,
18
+ IsTrue,
19
+ IsNotTrue,
20
+ IsFalse,
21
+ IsNotFalse,
22
+ IsUnknown,
23
+ IsNotUnknown,
24
+ )
25
+ from .Operator import (
26
+ And,
27
+ Or,
28
+ )
29
+ from .Compare import (
30
+ EqualTo,
31
+ NotEqualTo,
32
+ GreaterThan,
33
+ GreaterEqualTo,
34
+ LessThan,
35
+ LessEqualTo,
36
+ )
37
+ from .String import (
38
+ Like,
39
+ LikeStartWith,
40
+ LikeEndWith,
41
+ )
42
+ from .JavaScriptObjectNotation import Of
43
+
44
+ __all__ = (
45
+ 'Alias',
46
+ 'TypeTo',
47
+ 'If',
48
+ 'IfNull',
49
+ 'IfNotNull',
50
+ 'Switch',
51
+ 'Query',
52
+ 'In',
53
+ 'NotIn',
54
+ 'Is',
55
+ 'IsNull',
56
+ 'IsNotNull',
57
+ 'IsTrue',
58
+ 'IsNotTrue',
59
+ 'IsFalse',
60
+ 'IsNotFalse',
61
+ 'IsUnknown',
62
+ 'IsNotUnknown',
63
+ 'And',
64
+ 'Or',
65
+ 'EqualTo',
66
+ 'NotEqualTo',
67
+ 'GreaterThan',
68
+ 'GreaterEqualTo',
69
+ 'LessThan',
70
+ 'LessEqualTo',
71
+ 'Like',
72
+ 'LikeStartWith',
73
+ 'LikeEndWith',
74
+ 'Of',
75
+ )
@@ -0,0 +1,11 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from .Compiler import Compilable
4
+
5
+ __all__ = (
6
+ 'Function',
7
+ )
8
+
9
+
10
+ class Function(Compilable):
11
+ """SQL function that compiles into a fragment and bound parameters."""
@@ -0,0 +1,142 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from ..Column import Column
4
+ from ..Compiler import (
5
+ Compilable,
6
+ Compiler,
7
+ )
8
+ from ..Exprs.Operator import conditions
9
+ from ..Function import Function
10
+
11
+ __all__ = (
12
+ 'Count',
13
+ 'Sum',
14
+ 'Average',
15
+ 'Min',
16
+ 'Max',
17
+ 'AggregateToArray',
18
+ 'RowNumber',
19
+ 'Rank',
20
+ 'DenseRank',
21
+ )
22
+
23
+
24
+ def argument(col):
25
+ if isinstance(col, str):
26
+ return Column(col)
27
+ if not isinstance(col, Compilable):
28
+ raise TypeError('Function arguments must be column names or SQL expressions')
29
+ return col
30
+
31
+
32
+ def where(compiler: Compiler, conds) -> str:
33
+ if not conds:
34
+ return ''
35
+ return ' FILTER (WHERE {})'.format(' AND '.join(compiler.compile(cond) for cond in conds))
36
+
37
+
38
+ class Aggregate(Function):
39
+ name = ''
40
+
41
+ def __init__(
42
+ self,
43
+ col,
44
+ distinct: bool = False,
45
+ ):
46
+ self.col = argument(col)
47
+ self.distinct = bool(distinct)
48
+ self.conds = ()
49
+ return
50
+
51
+ def where(self, *args):
52
+ self.conds = conditions(args)
53
+ return self
54
+
55
+ def compile(self, compiler: Compiler) -> str:
56
+ return '{}({}{}){}'.format(
57
+ self.name,
58
+ 'DISTINCT ' if self.distinct else '',
59
+ compiler.compile(self.col),
60
+ where(compiler, self.conds),
61
+ )
62
+
63
+
64
+ class Count(Aggregate):
65
+ name = 'COUNT'
66
+
67
+
68
+ class Sum(Aggregate):
69
+ name = 'SUM'
70
+
71
+
72
+ class Average(Aggregate):
73
+ name = 'AVG'
74
+
75
+
76
+ class Min(Function):
77
+ name = 'MIN'
78
+
79
+ def __init__(self, col):
80
+ self.col = argument(col)
81
+ return
82
+
83
+ def compile(self, compiler: Compiler) -> str:
84
+ return '{}({})'.format(self.name, compiler.compile(self.col))
85
+
86
+
87
+ class Max(Min):
88
+ name = 'MAX'
89
+
90
+
91
+ class AggregateToArray(Function):
92
+ def __init__(
93
+ self,
94
+ col,
95
+ distinct: bool = False,
96
+ ):
97
+ self.col = argument(col)
98
+ self.distinct = bool(distinct)
99
+ return
100
+
101
+ def compile(self, compiler: Compiler) -> str:
102
+ return 'ARRAY_AGG({}{})'.format(
103
+ 'DISTINCT ' if self.distinct else '',
104
+ compiler.compile(self.col),
105
+ )
106
+
107
+
108
+ class Window(Function):
109
+ name = ''
110
+
111
+ def __init__(self, *args):
112
+ self.orders = conditions(args, 'Orders')
113
+ self.partitions = ()
114
+ return
115
+
116
+ def order(self, *args):
117
+ self.orders = conditions(args, 'Orders')
118
+ return self
119
+
120
+ def partition(self, *args):
121
+ self.partitions = tuple(argument(arg) for arg in args)
122
+ return self
123
+
124
+ def compile(self, compiler: Compiler) -> str:
125
+ clauses = []
126
+ if self.partitions:
127
+ clauses.append('PARTITION BY {}'.format(', '.join(compiler.compile(arg) for arg in self.partitions)))
128
+ if self.orders:
129
+ clauses.append('ORDER BY {}'.format(', '.join(compiler.compile(arg) for arg in self.orders)))
130
+ return '{}() OVER({})'.format(self.name, ' '.join(clauses))
131
+
132
+
133
+ class RowNumber(Window):
134
+ name = 'ROW_NUMBER'
135
+
136
+
137
+ class Rank(Window):
138
+ name = 'RANK'
139
+
140
+
141
+ class DenseRank(Window):
142
+ name = 'DENSE_RANK'
@@ -0,0 +1,219 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from enum import Enum
4
+
5
+ from ..Column import Column
6
+ from ..Compiler import (
7
+ Compilable,
8
+ Compiler,
9
+ )
10
+ from ..Function import Function
11
+
12
+ __all__ = (
13
+ 'Now',
14
+ 'DatePartType',
15
+ 'DatePart',
16
+ 'Year',
17
+ 'Month',
18
+ 'Day',
19
+ 'Hour',
20
+ 'Minute',
21
+ 'Second',
22
+ 'MilliSecond',
23
+ 'MicroSecond',
24
+ 'Quarter',
25
+ 'Week',
26
+ 'DayOfWeek',
27
+ 'DayOfWeekISO',
28
+ 'DayOfYear',
29
+ 'Timezone',
30
+ 'TimezoneHour',
31
+ 'TimezoneMinute',
32
+ 'TimezoneHourMinute',
33
+ 'Millennium',
34
+ 'Century',
35
+ 'Decade',
36
+ 'Epoch',
37
+ )
38
+
39
+
40
+ class Now(Function):
41
+ def compile(self, compiler: Compiler) -> str:
42
+ return 'NOW()'
43
+
44
+
45
+ class DatePartType(str, Enum):
46
+ Year = 'YEAR'
47
+ Month = 'MONTH'
48
+ Day = 'DAY'
49
+ Hour = 'HOUR'
50
+ Minute = 'MINUTE'
51
+ Second = 'SECOND'
52
+ MilliSecond = 'MILLISECOND'
53
+ MicroSecond = 'MICROSECOND'
54
+ Quarter = 'QUARTER'
55
+ Week = 'WEEK'
56
+ DayOfWeek = 'DOW'
57
+ DayOfWeekISO = 'ISODOW'
58
+ DayOfYear = 'DOY'
59
+ Timezone = 'TIMEZONE'
60
+ TimezoneHour = 'TIMEZONE_HOUR'
61
+ TimezoneMinute = 'TIMEZONE_MINUTE'
62
+ TimezoneHourMinute = 'TIMEZONE_HOUR_MINUTE'
63
+ Millennium = 'MILLENNIUM'
64
+ Century = 'CENTURY'
65
+ Decade = 'DECADE'
66
+ Epoch = 'EPOCH'
67
+
68
+ def __str__(self) -> str:
69
+ return self.value
70
+
71
+
72
+ class DatePart(Function):
73
+ """DATE_PART('part', expr)."""
74
+
75
+ def __init__(
76
+ self,
77
+ part,
78
+ expr,
79
+ ):
80
+ if isinstance(part, str) and not isinstance(part, DatePartType):
81
+ part = DatePartType(part.upper())
82
+ if not isinstance(part, DatePartType):
83
+ raise TypeError('part must be a DatePartType or its name')
84
+ if isinstance(expr, str):
85
+ expr = Column(expr)
86
+ if not isinstance(expr, Compilable):
87
+ raise TypeError('DatePart requires a column name or SQL expression')
88
+ self.part = part
89
+ self.expr = expr
90
+ return
91
+
92
+ def compile(self, compiler: Compiler) -> str:
93
+ return "DATE_PART('{}', {})".format(self.part.value, compiler.compile(self.expr))
94
+
95
+
96
+ class Year(DatePart):
97
+ def __init__(self, expr):
98
+ super().__init__(DatePartType.Year, expr)
99
+ return
100
+
101
+
102
+ class Month(DatePart):
103
+ def __init__(self, expr):
104
+ super().__init__(DatePartType.Month, expr)
105
+ return
106
+
107
+
108
+ class Day(DatePart):
109
+ def __init__(self, expr):
110
+ super().__init__(DatePartType.Day, expr)
111
+ return
112
+
113
+
114
+ class Hour(DatePart):
115
+ def __init__(self, expr):
116
+ super().__init__(DatePartType.Hour, expr)
117
+ return
118
+
119
+
120
+ class Minute(DatePart):
121
+ def __init__(self, expr):
122
+ super().__init__(DatePartType.Minute, expr)
123
+ return
124
+
125
+
126
+ class Second(DatePart):
127
+ def __init__(self, expr):
128
+ super().__init__(DatePartType.Second, expr)
129
+ return
130
+
131
+
132
+ class MilliSecond(DatePart):
133
+ def __init__(self, expr):
134
+ super().__init__(DatePartType.MilliSecond, expr)
135
+ return
136
+
137
+
138
+ class MicroSecond(DatePart):
139
+ def __init__(self, expr):
140
+ super().__init__(DatePartType.MicroSecond, expr)
141
+ return
142
+
143
+
144
+ class Quarter(DatePart):
145
+ def __init__(self, expr):
146
+ super().__init__(DatePartType.Quarter, expr)
147
+ return
148
+
149
+
150
+ class Week(DatePart):
151
+ def __init__(self, expr):
152
+ super().__init__(DatePartType.Week, expr)
153
+ return
154
+
155
+
156
+ class DayOfWeek(DatePart):
157
+ def __init__(self, expr):
158
+ super().__init__(DatePartType.DayOfWeek, expr)
159
+ return
160
+
161
+
162
+ class DayOfWeekISO(DatePart):
163
+ def __init__(self, expr):
164
+ super().__init__(DatePartType.DayOfWeekISO, expr)
165
+ return
166
+
167
+
168
+ class DayOfYear(DatePart):
169
+ def __init__(self, expr):
170
+ super().__init__(DatePartType.DayOfYear, expr)
171
+ return
172
+
173
+
174
+ class Timezone(DatePart):
175
+ def __init__(self, expr):
176
+ super().__init__(DatePartType.Timezone, expr)
177
+ return
178
+
179
+
180
+ class TimezoneHour(DatePart):
181
+ def __init__(self, expr):
182
+ super().__init__(DatePartType.TimezoneHour, expr)
183
+ return
184
+
185
+
186
+ class TimezoneMinute(DatePart):
187
+ def __init__(self, expr):
188
+ super().__init__(DatePartType.TimezoneMinute, expr)
189
+ return
190
+
191
+
192
+ class TimezoneHourMinute(DatePart):
193
+ def __init__(self, expr):
194
+ super().__init__(DatePartType.TimezoneHourMinute, expr)
195
+ return
196
+
197
+
198
+ class Millennium(DatePart):
199
+ def __init__(self, expr):
200
+ super().__init__(DatePartType.Millennium, expr)
201
+ return
202
+
203
+
204
+ class Century(DatePart):
205
+ def __init__(self, expr):
206
+ super().__init__(DatePartType.Century, expr)
207
+ return
208
+
209
+
210
+ class Decade(DatePart):
211
+ def __init__(self, expr):
212
+ super().__init__(DatePartType.Decade, expr)
213
+ return
214
+
215
+
216
+ class Epoch(DatePart):
217
+ def __init__(self, expr):
218
+ super().__init__(DatePartType.Epoch, expr)
219
+ return
@@ -0,0 +1,100 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from collections.abc import Mapping
4
+
5
+ from ..Compiler import (
6
+ Compilable,
7
+ Compiler,
8
+ )
9
+ from ..Exprs.Operator import conditions
10
+ from ..Function import Function
11
+ from .Common import where
12
+
13
+ __all__ = (
14
+ 'AggregateToJSON',
15
+ 'AggregateToJSONB',
16
+ 'ToJSON',
17
+ 'ToJSONB',
18
+ )
19
+
20
+
21
+ def value(compiler: Compiler, value) -> str:
22
+ """Compile a JSON object value with a type PostgreSQL can resolve in variadic arguments."""
23
+ if value is None:
24
+ return 'NULL'
25
+ if isinstance(value, Compilable):
26
+ return compiler.compile(value)
27
+ if isinstance(value, str):
28
+ return compiler.bind(value, 'TEXT')
29
+ if isinstance(value, Mapping):
30
+ return compiler.bind(dict(value), 'JSONB')
31
+ return compiler.bind(value)
32
+
33
+
34
+ class BuildObject(Function):
35
+ function = ''
36
+
37
+ def __init__(self, format):
38
+ if not isinstance(format, Mapping) or not format:
39
+ raise TypeError('format must be a nonempty mapping')
40
+ for key in format:
41
+ if not isinstance(key, str):
42
+ raise TypeError('JSON object keys must be strings')
43
+ self.kwargs = dict(format)
44
+ return
45
+
46
+ def build(self, compiler: Compiler) -> str:
47
+ return '{}({})'.format(
48
+ self.function,
49
+ ', '.join(
50
+ '{}, {}'.format(compiler.bind(key, 'TEXT'), value(compiler, item))
51
+ for key, item in self.kwargs.items()
52
+ ),
53
+ )
54
+
55
+ def compile(self, compiler: Compiler) -> str:
56
+ return self.build(compiler)
57
+
58
+
59
+ class ToJSON(BuildObject):
60
+ """JSON_BUILD_OBJECT(key, value, ...)."""
61
+ function = 'JSON_BUILD_OBJECT'
62
+
63
+
64
+ class ToJSONB(BuildObject):
65
+ """JSONB_BUILD_OBJECT(key, value, ...)."""
66
+ function = 'JSONB_BUILD_OBJECT'
67
+
68
+
69
+ class AggregateToJSON(BuildObject):
70
+ """JSON_AGG(JSONB_BUILD_OBJECT(...)) with an optional FILTER."""
71
+
72
+ function = 'JSONB_BUILD_OBJECT'
73
+ aggregate = 'JSON_AGG'
74
+
75
+ def __init__(
76
+ self,
77
+ format,
78
+ distinct: bool = False,
79
+ ):
80
+ super().__init__(format)
81
+ self.distinct = bool(distinct)
82
+ self.conds = ()
83
+ return
84
+
85
+ def where(self, *args):
86
+ self.conds = conditions(args)
87
+ return self
88
+
89
+ def compile(self, compiler: Compiler) -> str:
90
+ return '{}({}{}){}'.format(
91
+ self.aggregate,
92
+ 'DISTINCT ' if self.distinct else '',
93
+ self.build(compiler),
94
+ where(compiler, self.conds),
95
+ )
96
+
97
+
98
+ class AggregateToJSONB(AggregateToJSON):
99
+ """JSONB_AGG([DISTINCT] JSONB_BUILD_OBJECT(...)) with an optional FILTER."""
100
+ aggregate = 'JSONB_AGG'