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.
- DefPixel/DataAccessObject/Implements/PostgreSQL/Adapters/Array.py +16 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Adapters/JavaScriptObjectNotation.py +74 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Adapters/__init__.py +51 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Column.py +34 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Compiler.py +161 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Configuration.py +116 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Connection.py +138 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Constraint.py +18 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Constraints/Check.py +23 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Constraints/Columns.py +24 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Constraints/ForeignKey.py +56 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Constraints/PrimaryKey.py +21 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Constraints/Unique.py +25 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Constraints/__init__.py +13 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Context.py +48 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Cursor.py +123 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Executors/Create.py +181 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Executors/Delete.py +31 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Executors/Drop.py +53 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Executors/Get.py +24 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Executors/Insert.py +98 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Executors/Query.py +37 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Executors/Select.py +122 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Executors/Update.py +57 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Executors/__init__.py +19 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Expr.py +11 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Exprs/Common.py +180 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Exprs/Compare.py +87 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Exprs/Condition.py +155 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Exprs/JavaScriptObjectNotation.py +53 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Exprs/Operator.py +42 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Exprs/String.py +48 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Exprs/__init__.py +75 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Function.py +11 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Functions/Common.py +142 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Functions/DateTime.py +219 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Functions/JavaScriptObjectNotation.py +100 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Functions/Sequence.py +55 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Functions/__init__.py +91 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Index.py +135 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Joins/FullOuter.py +15 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Joins/Inner.py +15 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Joins/Join.py +41 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Joins/LeftOuter.py +15 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Joins/RightOuter.py +15 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Joins/__init__.py +15 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Mapping.py +359 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Orders.py +59 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Pool.py +84 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Schema.py +28 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Sequence.py +55 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Session.py +84 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Type.py +113 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Types/Array.py +61 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Types/Binary.py +34 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Types/Bool.py +29 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Types/DateTime.py +120 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Types/JavaScriptObjectNotation.py +52 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Types/Numeric.py +151 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Types/Size.py +13 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Types/String.py +80 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/Types/__init__.py +76 -0
- DefPixel/DataAccessObject/Implements/PostgreSQL/__init__.py +85 -0
- defpixel_postgresql-0.1.5.dist-info/METADATA +180 -0
- defpixel_postgresql-0.1.5.dist-info/RECORD +68 -0
- defpixel_postgresql-0.1.5.dist-info/WHEEL +6 -0
- defpixel_postgresql-0.1.5.dist-info/licenses/LICENSE +674 -0
- 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,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'
|