omlish 0.0.0.dev73__py3-none-any.whl → 0.0.0.dev74__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.
- omlish/__about__.py +2 -2
- omlish/dataclasses/impl/fields.py +4 -0
- omlish/dataclasses/impl/metaclass.py +7 -1
- omlish/marshal/enums.py +1 -1
- omlish/sql/queries/__init__.py +24 -6
- omlish/sql/queries/binary.py +55 -17
- omlish/sql/queries/exprs.py +34 -0
- omlish/sql/queries/marshal.py +74 -0
- omlish/sql/queries/multi.py +10 -13
- omlish/sql/queries/ops.py +8 -0
- omlish/sql/queries/relations.py +5 -0
- omlish/sql/queries/rendering.py +180 -0
- omlish/sql/queries/unary.py +24 -1
- omlish/sql/tabledefs/marshal.py +1 -4
- {omlish-0.0.0.dev73.dist-info → omlish-0.0.0.dev74.dist-info}/METADATA +1 -1
- {omlish-0.0.0.dev73.dist-info → omlish-0.0.0.dev74.dist-info}/RECORD +21 -18
- /omlish/sql/queries/{std.py → building.py} +0 -0
- {omlish-0.0.0.dev73.dist-info → omlish-0.0.0.dev74.dist-info}/LICENSE +0 -0
- {omlish-0.0.0.dev73.dist-info → omlish-0.0.0.dev74.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev73.dist-info → omlish-0.0.0.dev74.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev73.dist-info → omlish-0.0.0.dev74.dist-info}/top_level.txt +0 -0
omlish/__about__.py
CHANGED
@@ -108,7 +108,11 @@ class DataMeta(abc.ABCMeta):
|
|
108
108
|
|
109
109
|
|
110
110
|
# @ta.dataclass_transform(field_specifiers=(field,)) # FIXME: ctor
|
111
|
-
class Data(
|
111
|
+
class Data(
|
112
|
+
eq=False,
|
113
|
+
order=False,
|
114
|
+
metaclass=DataMeta,
|
115
|
+
):
|
112
116
|
def __init__(self, *args, **kwargs):
|
113
117
|
super().__init__(*args, **kwargs)
|
114
118
|
|
@@ -125,6 +129,8 @@ class Data(metaclass=DataMeta):
|
|
125
129
|
class Frozen(
|
126
130
|
Data,
|
127
131
|
frozen=True,
|
132
|
+
eq=False,
|
133
|
+
order=False,
|
128
134
|
confer=frozenset([
|
129
135
|
'frozen',
|
130
136
|
'cache_hash',
|
omlish/marshal/enums.py
CHANGED
@@ -28,7 +28,7 @@ class EnumMarshalerFactory(MarshalerFactory):
|
|
28
28
|
def fn(self, ctx: MarshalContext, rty: rfl.Type) -> Marshaler:
|
29
29
|
ty = check.isinstance(rty, type)
|
30
30
|
check.state(issubclass(ty, enum.Enum))
|
31
|
-
return EnumMarshaler(ty)
|
31
|
+
return EnumMarshaler(ty) # noqa
|
32
32
|
|
33
33
|
|
34
34
|
@dc.dataclass(frozen=True)
|
omlish/sql/queries/__init__.py
CHANGED
@@ -11,6 +11,10 @@ from .binary import ( # noqa
|
|
11
11
|
BinaryOps,
|
12
12
|
)
|
13
13
|
|
14
|
+
from .building import ( # noqa
|
15
|
+
StdBuilder,
|
16
|
+
)
|
17
|
+
|
14
18
|
from .exprs import ( # noqa
|
15
19
|
CanExpr,
|
16
20
|
CanLiteral,
|
@@ -18,6 +22,7 @@ from .exprs import ( # noqa
|
|
18
22
|
ExprBuilder,
|
19
23
|
Literal,
|
20
24
|
NameExpr,
|
25
|
+
Param,
|
21
26
|
)
|
22
27
|
|
23
28
|
from .idents import ( # noqa
|
@@ -29,8 +34,7 @@ from .idents import ( # noqa
|
|
29
34
|
from .multi import ( # noqa
|
30
35
|
Multi,
|
31
36
|
MultiBuilder,
|
32
|
-
|
33
|
-
MultiOps,
|
37
|
+
MultiKind,
|
34
38
|
)
|
35
39
|
|
36
40
|
from .names import ( # noqa
|
@@ -39,6 +43,10 @@ from .names import ( # noqa
|
|
39
43
|
NameBuilder,
|
40
44
|
)
|
41
45
|
|
46
|
+
from .ops import ( # noqa
|
47
|
+
OpKind,
|
48
|
+
)
|
49
|
+
|
42
50
|
from .relations import ( # noqa
|
43
51
|
CanRelation,
|
44
52
|
CanTable,
|
@@ -47,6 +55,12 @@ from .relations import ( # noqa
|
|
47
55
|
Table,
|
48
56
|
)
|
49
57
|
|
58
|
+
from .rendering import ( # noqa
|
59
|
+
Renderer,
|
60
|
+
StdRenderer,
|
61
|
+
render,
|
62
|
+
)
|
63
|
+
|
50
64
|
from .selects import ( # noqa
|
51
65
|
CanRelation,
|
52
66
|
Select,
|
@@ -54,10 +68,6 @@ from .selects import ( # noqa
|
|
54
68
|
SelectItem,
|
55
69
|
)
|
56
70
|
|
57
|
-
from .std import ( # noqa
|
58
|
-
StdBuilder,
|
59
|
-
)
|
60
|
-
|
61
71
|
from .stmts import ( # noqa
|
62
72
|
CanExpr,
|
63
73
|
ExprStmt,
|
@@ -77,3 +87,11 @@ from .unary import ( # noqa
|
|
77
87
|
|
78
88
|
|
79
89
|
Q = StdBuilder()
|
90
|
+
|
91
|
+
|
92
|
+
##
|
93
|
+
|
94
|
+
|
95
|
+
from ...lang.imports import _register_conditional_import # noqa
|
96
|
+
|
97
|
+
_register_conditional_import('...marshal', '.marshal', __package__)
|
omlish/sql/queries/binary.py
CHANGED
@@ -1,33 +1,41 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
"""
|
2
|
+
TODO:
|
3
|
+
- in_
|
4
|
+
- like
|
5
|
+
- no this is a dedicated node, escape / negation in grammar
|
6
|
+
"""
|
3
7
|
from ... import check
|
4
8
|
from ... import dataclasses as dc
|
5
9
|
from ... import lang
|
6
10
|
from .exprs import CanExpr
|
7
11
|
from .exprs import Expr
|
8
12
|
from .exprs import ExprBuilder
|
13
|
+
from .ops import OpKind
|
9
14
|
|
10
15
|
|
11
16
|
##
|
12
17
|
|
13
18
|
|
14
|
-
class BinaryOpKind(enum.Enum):
|
15
|
-
ARITH = enum.auto()
|
16
|
-
BIT = enum.auto()
|
17
|
-
CMP = enum.auto()
|
18
|
-
|
19
|
-
|
20
19
|
class BinaryOp(dc.Frozen, lang.Final, eq=False):
|
21
20
|
name: str
|
22
|
-
kind:
|
21
|
+
kind: OpKind
|
23
22
|
|
24
23
|
|
25
24
|
class BinaryOps(lang.Namespace):
|
26
|
-
|
27
|
-
|
25
|
+
EQ = BinaryOp('eq', OpKind.CMP)
|
26
|
+
NE = BinaryOp('ne', OpKind.CMP)
|
27
|
+
LT = BinaryOp('lt', OpKind.CMP)
|
28
|
+
LE = BinaryOp('le', OpKind.CMP)
|
29
|
+
GT = BinaryOp('gt', OpKind.CMP)
|
30
|
+
GE = BinaryOp('ge', OpKind.CMP)
|
28
31
|
|
29
|
-
|
30
|
-
|
32
|
+
ADD = BinaryOp('add', OpKind.ARITH)
|
33
|
+
SUB = BinaryOp('sub', OpKind.ARITH)
|
34
|
+
MUL = BinaryOp('mul', OpKind.ARITH)
|
35
|
+
DIV = BinaryOp('div', OpKind.ARITH)
|
36
|
+
MOD = BinaryOp('mod', OpKind.ARITH)
|
37
|
+
|
38
|
+
CONCAT = BinaryOp('concat', OpKind.STR)
|
31
39
|
|
32
40
|
|
33
41
|
class Binary(Expr, lang.Final):
|
@@ -44,14 +52,44 @@ class BinaryBuilder(ExprBuilder):
|
|
44
52
|
l = Binary(op, l, self.expr(r))
|
45
53
|
return l
|
46
54
|
|
55
|
+
#
|
56
|
+
|
57
|
+
def eq(self, *es: CanExpr) -> Expr:
|
58
|
+
return self.binary(BinaryOps.EQ, *es)
|
59
|
+
|
60
|
+
def ne(self, *es: CanExpr) -> Expr:
|
61
|
+
return self.binary(BinaryOps.NE, *es)
|
62
|
+
|
63
|
+
def lt(self, *es: CanExpr) -> Expr:
|
64
|
+
return self.binary(BinaryOps.LT, *es)
|
65
|
+
|
66
|
+
def le(self, *es: CanExpr) -> Expr:
|
67
|
+
return self.binary(BinaryOps.LE, *es)
|
68
|
+
|
69
|
+
def gt(self, *es: CanExpr) -> Expr:
|
70
|
+
return self.binary(BinaryOps.GT, *es)
|
71
|
+
|
72
|
+
def ge(self, *es: CanExpr) -> Expr:
|
73
|
+
return self.binary(BinaryOps.GE, *es)
|
74
|
+
|
75
|
+
#
|
76
|
+
|
47
77
|
def add(self, *es: CanExpr) -> Expr:
|
48
78
|
return self.binary(BinaryOps.ADD, *es)
|
49
79
|
|
50
80
|
def sub(self, *es: CanExpr) -> Expr:
|
51
81
|
return self.binary(BinaryOps.SUB, *es)
|
52
82
|
|
53
|
-
def
|
54
|
-
return self.binary(BinaryOps.
|
83
|
+
def mul(self, *es: CanExpr) -> Expr:
|
84
|
+
return self.binary(BinaryOps.MUL, *es)
|
55
85
|
|
56
|
-
def
|
57
|
-
return self.binary(BinaryOps.
|
86
|
+
def div(self, *es: CanExpr) -> Expr:
|
87
|
+
return self.binary(BinaryOps.DIV, *es)
|
88
|
+
|
89
|
+
def mod(self, *es: CanExpr) -> Expr:
|
90
|
+
return self.binary(BinaryOps.MOD, *es)
|
91
|
+
|
92
|
+
#
|
93
|
+
|
94
|
+
def concat(self, *es: CanExpr) -> Expr:
|
95
|
+
return self.binary(BinaryOps.CONCAT, *es)
|
omlish/sql/queries/exprs.py
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
"""
|
2
|
+
TODO:
|
3
|
+
- case
|
4
|
+
- cast / ::
|
5
|
+
"""
|
1
6
|
import typing as ta
|
2
7
|
|
3
8
|
from ... import lang
|
@@ -24,6 +29,24 @@ class NameExpr(Expr, lang.Final):
|
|
24
29
|
n: Name
|
25
30
|
|
26
31
|
|
32
|
+
class Param(Expr, lang.Final):
|
33
|
+
n: str | None = None
|
34
|
+
|
35
|
+
def __repr__(self) -> str:
|
36
|
+
if self.n is not None:
|
37
|
+
return f'{self.__class__.__name__}({self.n!r})'
|
38
|
+
else:
|
39
|
+
return f'{self.__class__.__name__}(@{hex(id(self))[2:]})'
|
40
|
+
|
41
|
+
def __eq__(self, other):
|
42
|
+
if not isinstance(other, Param):
|
43
|
+
return False
|
44
|
+
if self.n is None and other.n is None:
|
45
|
+
return self is other
|
46
|
+
else:
|
47
|
+
return self.n == other.n
|
48
|
+
|
49
|
+
|
27
50
|
CanLiteral: ta.TypeAlias = Literal | Value
|
28
51
|
CanExpr: ta.TypeAlias = Expr | CanName | CanLiteral
|
29
52
|
|
@@ -41,6 +64,8 @@ class ExprBuilder(NameBuilder):
|
|
41
64
|
def l(self, o: CanLiteral) -> Literal: # noqa
|
42
65
|
return self.literal(o)
|
43
66
|
|
67
|
+
#
|
68
|
+
|
44
69
|
def expr(self, o: CanExpr) -> Expr:
|
45
70
|
if isinstance(o, Expr):
|
46
71
|
return o
|
@@ -52,3 +77,12 @@ class ExprBuilder(NameBuilder):
|
|
52
77
|
@ta.final
|
53
78
|
def e(self, o: CanExpr) -> Expr:
|
54
79
|
return self.expr(o)
|
80
|
+
|
81
|
+
#
|
82
|
+
|
83
|
+
def param(self, n: str | None = None) -> Param:
|
84
|
+
return Param(n)
|
85
|
+
|
86
|
+
@ta.final
|
87
|
+
def p(self, n: str | None = None) -> Param:
|
88
|
+
return self.param(n)
|
@@ -0,0 +1,74 @@
|
|
1
|
+
import enum
|
2
|
+
import typing as ta
|
3
|
+
|
4
|
+
from ... import cached
|
5
|
+
from ... import check
|
6
|
+
from ... import collections as col
|
7
|
+
from ... import dataclasses as dc
|
8
|
+
from ... import lang
|
9
|
+
from ... import marshal as msh
|
10
|
+
from .base import Node
|
11
|
+
from .binary import BinaryOp
|
12
|
+
from .binary import BinaryOps
|
13
|
+
from .exprs import Expr
|
14
|
+
from .multi import MultiKind
|
15
|
+
from .relations import Relation
|
16
|
+
from .stmts import Stmt
|
17
|
+
from .unary import UnaryOp
|
18
|
+
from .unary import UnaryOps
|
19
|
+
|
20
|
+
|
21
|
+
@dc.dataclass(frozen=True)
|
22
|
+
class OpMarshalerUnmarshaler(msh.Marshaler, msh.Unmarshaler):
|
23
|
+
ty: type
|
24
|
+
ns: type[lang.Namespace]
|
25
|
+
|
26
|
+
@cached.property
|
27
|
+
@dc.init
|
28
|
+
def by_name(self) -> ta.Mapping[str, ta.Any]:
|
29
|
+
return col.make_map(((o.name, o) for _, o in self.ns), strict=True)
|
30
|
+
|
31
|
+
def marshal(self, ctx: msh.MarshalContext, o: ta.Any) -> msh.Value:
|
32
|
+
return check.isinstance(o, self.ty).name # type: ignore # noqa
|
33
|
+
|
34
|
+
def unmarshal(self, ctx: msh.UnmarshalContext, v: msh.Value) -> ta.Any:
|
35
|
+
return self.by_name[check.isinstance(v, str)]
|
36
|
+
|
37
|
+
|
38
|
+
@dc.dataclass(frozen=True)
|
39
|
+
class LowerEnumMarshaler(msh.Marshaler, msh.Unmarshaler):
|
40
|
+
ty: type[enum.Enum]
|
41
|
+
|
42
|
+
@cached.property
|
43
|
+
@dc.init
|
44
|
+
def by_name(self) -> ta.Mapping[str, ta.Any]:
|
45
|
+
return col.make_map(((o.name.lower(), o) for o in self.ty), strict=True)
|
46
|
+
|
47
|
+
def marshal(self, ctx: msh.MarshalContext, o: ta.Any) -> msh.Value:
|
48
|
+
return o.name.lower()
|
49
|
+
|
50
|
+
def unmarshal(self, ctx: msh.UnmarshalContext, v: msh.Value) -> ta.Any:
|
51
|
+
return self.by_name[check.isinstance(v, str).lower()]
|
52
|
+
|
53
|
+
|
54
|
+
@lang.static_init
|
55
|
+
def _install_standard_marshalling() -> None:
|
56
|
+
for ty, ns in [
|
57
|
+
(BinaryOp, BinaryOps),
|
58
|
+
(UnaryOp, UnaryOps),
|
59
|
+
]:
|
60
|
+
msh.STANDARD_MARSHALER_FACTORIES[0:0] = [msh.TypeMapMarshalerFactory({ty: OpMarshalerUnmarshaler(ty, ns)})]
|
61
|
+
msh.STANDARD_UNMARSHALER_FACTORIES[0:0] = [msh.TypeMapUnmarshalerFactory({ty: OpMarshalerUnmarshaler(ty, ns)})]
|
62
|
+
|
63
|
+
msh.STANDARD_MARSHALER_FACTORIES[0:0] = [msh.TypeMapMarshalerFactory({MultiKind: LowerEnumMarshaler(MultiKind)})]
|
64
|
+
msh.STANDARD_UNMARSHALER_FACTORIES[0:0] = [msh.TypeMapUnmarshalerFactory({MultiKind: LowerEnumMarshaler(MultiKind)})] # noqa
|
65
|
+
|
66
|
+
for cls in [
|
67
|
+
Expr,
|
68
|
+
Node,
|
69
|
+
Relation,
|
70
|
+
Stmt,
|
71
|
+
]:
|
72
|
+
p = msh.polymorphism_from_subclasses(cls, naming=msh.Naming.SNAKE)
|
73
|
+
msh.STANDARD_MARSHALER_FACTORIES[0:0] = [msh.PolymorphismMarshalerFactory(p)]
|
74
|
+
msh.STANDARD_UNMARSHALER_FACTORIES[0:0] = [msh.PolymorphismUnmarshalerFactory(p)]
|
omlish/sql/queries/multi.py
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
import enum
|
1
2
|
import typing as ta
|
2
3
|
|
3
4
|
from ... import check
|
@@ -11,30 +12,26 @@ from .exprs import ExprBuilder
|
|
11
12
|
##
|
12
13
|
|
13
14
|
|
14
|
-
class
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
class MultiOps(lang.Namespace):
|
19
|
-
AND = MultiOp('and')
|
20
|
-
OR = MultiOp('or')
|
15
|
+
class MultiKind(enum.Enum):
|
16
|
+
AND = enum.auto()
|
17
|
+
OR = enum.auto()
|
21
18
|
|
22
19
|
|
23
20
|
class Multi(Expr, lang.Final):
|
24
|
-
|
25
|
-
es: ta.Sequence[Expr] = dc.xfield(coerce=tuple)
|
21
|
+
k: MultiKind
|
22
|
+
es: ta.Sequence[Expr] = dc.xfield(coerce=tuple, validate=lambda es: len(es) > 1)
|
26
23
|
|
27
24
|
|
28
25
|
class MultiBuilder(ExprBuilder):
|
29
|
-
def multi(self,
|
26
|
+
def multi(self, k: MultiKind, *es: CanExpr) -> Expr:
|
30
27
|
check.not_empty(es)
|
31
28
|
if len(es) == 1:
|
32
29
|
return self.expr(es[0])
|
33
30
|
else:
|
34
|
-
return Multi(
|
31
|
+
return Multi(k, [self.expr(e) for e in es])
|
35
32
|
|
36
33
|
def and_(self, *es: CanExpr) -> Expr:
|
37
|
-
return self.multi(
|
34
|
+
return self.multi(MultiKind.AND, *es)
|
38
35
|
|
39
36
|
def or_(self, *es: CanExpr) -> Expr:
|
40
|
-
return self.multi(
|
37
|
+
return self.multi(MultiKind.OR, *es)
|
omlish/sql/queries/relations.py
CHANGED
@@ -0,0 +1,180 @@
|
|
1
|
+
"""
|
2
|
+
TODO:
|
3
|
+
- minimal parens
|
4
|
+
- text.parts
|
5
|
+
- QuoteStyle
|
6
|
+
- ParamStyle
|
7
|
+
|
8
|
+
==
|
9
|
+
|
10
|
+
def needs_parens(self, e: Expr) -> bool:
|
11
|
+
if isinstance(e, (Literal, Ident, Name)):
|
12
|
+
return True
|
13
|
+
elif isinstance(e, Expr):
|
14
|
+
return False
|
15
|
+
else:
|
16
|
+
raise TypeError(e)
|
17
|
+
"""
|
18
|
+
import io
|
19
|
+
import typing as ta
|
20
|
+
|
21
|
+
from ... import dispatch
|
22
|
+
from ... import lang
|
23
|
+
from .base import Node
|
24
|
+
from .binary import Binary
|
25
|
+
from .binary import BinaryOp
|
26
|
+
from .binary import BinaryOps
|
27
|
+
from .exprs import Literal
|
28
|
+
from .exprs import NameExpr
|
29
|
+
from .idents import Ident
|
30
|
+
from .multi import Multi
|
31
|
+
from .multi import MultiKind
|
32
|
+
from .names import Name
|
33
|
+
from .relations import Table
|
34
|
+
from .selects import Select
|
35
|
+
from .selects import SelectItem
|
36
|
+
from .unary import Unary
|
37
|
+
from .unary import UnaryOp
|
38
|
+
from .unary import UnaryOps
|
39
|
+
|
40
|
+
|
41
|
+
class Renderer(lang.Abstract):
|
42
|
+
def __init__(self, out: ta.TextIO) -> None:
|
43
|
+
super().__init__()
|
44
|
+
self._out = out
|
45
|
+
|
46
|
+
@dispatch.method
|
47
|
+
def render(self, o: ta.Any) -> None:
|
48
|
+
raise TypeError(o)
|
49
|
+
|
50
|
+
@classmethod
|
51
|
+
def render_str(cls, o: ta.Any, *args: ta.Any, **kwargs: ta.Any) -> str:
|
52
|
+
out = io.StringIO()
|
53
|
+
cls(out, *args, **kwargs).render(o)
|
54
|
+
return out.getvalue()
|
55
|
+
|
56
|
+
|
57
|
+
class StdRenderer(Renderer):
|
58
|
+
# binary
|
59
|
+
|
60
|
+
BINARY_OP_TO_STR: ta.ClassVar[ta.Mapping[BinaryOp, str]] = {
|
61
|
+
BinaryOps.EQ: '=',
|
62
|
+
BinaryOps.NE: '!=',
|
63
|
+
BinaryOps.LT: '<',
|
64
|
+
BinaryOps.LE: '<=',
|
65
|
+
BinaryOps.GT: '>',
|
66
|
+
BinaryOps.GE: '>=',
|
67
|
+
|
68
|
+
BinaryOps.ADD: '+',
|
69
|
+
BinaryOps.SUB: '-',
|
70
|
+
BinaryOps.MUL: '*',
|
71
|
+
BinaryOps.DIV: '/',
|
72
|
+
BinaryOps.MOD: '%',
|
73
|
+
|
74
|
+
BinaryOps.CONCAT: '||',
|
75
|
+
}
|
76
|
+
|
77
|
+
@Renderer.render.register
|
78
|
+
def render_binary(self, o: Binary) -> None:
|
79
|
+
self._out.write('(')
|
80
|
+
self.render(o.l)
|
81
|
+
self._out.write(f' {self.BINARY_OP_TO_STR[o.op]} ')
|
82
|
+
self.render(o.r)
|
83
|
+
self._out.write(')')
|
84
|
+
|
85
|
+
# exprs
|
86
|
+
|
87
|
+
@Renderer.render.register
|
88
|
+
def render_literal(self, o: Literal) -> None:
|
89
|
+
self._out.write(repr(o.v))
|
90
|
+
|
91
|
+
@Renderer.render.register
|
92
|
+
def render_name_expr(self, o: NameExpr) -> None:
|
93
|
+
self.render(o.n)
|
94
|
+
|
95
|
+
# idents
|
96
|
+
|
97
|
+
@Renderer.render.register
|
98
|
+
def render_ident(self, o: Ident) -> None:
|
99
|
+
self._out.write(f'"{o.s}"')
|
100
|
+
|
101
|
+
# multis
|
102
|
+
|
103
|
+
MULTI_KIND_TO_STR: ta.ClassVar[ta.Mapping[MultiKind, str]] = {
|
104
|
+
MultiKind.AND: 'and',
|
105
|
+
MultiKind.OR: 'or',
|
106
|
+
|
107
|
+
}
|
108
|
+
|
109
|
+
@Renderer.render.register
|
110
|
+
def render_multi(self, o: Multi) -> None:
|
111
|
+
d = f' {self.MULTI_KIND_TO_STR[o.k]} '
|
112
|
+
self._out.write('(')
|
113
|
+
for i, e in enumerate(o.es):
|
114
|
+
if i:
|
115
|
+
self._out.write(d)
|
116
|
+
self.render(e)
|
117
|
+
self._out.write(')')
|
118
|
+
|
119
|
+
# names
|
120
|
+
|
121
|
+
@Renderer.render.register
|
122
|
+
def render_name(self, o: Name) -> None:
|
123
|
+
for n, i in enumerate(o.ps):
|
124
|
+
if n:
|
125
|
+
self._out.write('.')
|
126
|
+
self.render(i)
|
127
|
+
|
128
|
+
# relations
|
129
|
+
|
130
|
+
@Renderer.render.register
|
131
|
+
def render_table(self, o: Table) -> None:
|
132
|
+
self.render(o.n)
|
133
|
+
if o.a is not None:
|
134
|
+
self._out.write(' as ')
|
135
|
+
self.render(o.a)
|
136
|
+
|
137
|
+
# selects
|
138
|
+
|
139
|
+
@Renderer.render.register
|
140
|
+
def render_select_item(self, o: SelectItem) -> None:
|
141
|
+
self.render(o.v)
|
142
|
+
if o.a is not None:
|
143
|
+
self._out.write(' as ')
|
144
|
+
self.render(o.a)
|
145
|
+
|
146
|
+
@Renderer.render.register
|
147
|
+
def render_select(self, o: Select) -> None:
|
148
|
+
self._out.write('select ')
|
149
|
+
for i, it in enumerate(o.items):
|
150
|
+
if i:
|
151
|
+
self._out.write(', ')
|
152
|
+
self.render(it)
|
153
|
+
if o.from_ is not None:
|
154
|
+
self._out.write(' from ')
|
155
|
+
self.render(o.from_)
|
156
|
+
if o.where:
|
157
|
+
self._out.write(' where ')
|
158
|
+
self.render(o.where)
|
159
|
+
|
160
|
+
# unary
|
161
|
+
|
162
|
+
UNARY_OP_TO_STR: ta.ClassVar[ta.Mapping[UnaryOp, tuple[str, str]]] = {
|
163
|
+
UnaryOps.NOT: ('not ', ''),
|
164
|
+
UnaryOps.IS_NULL: ('', ' is null'),
|
165
|
+
UnaryOps.IS_NOT_NULL: ('', ' is not null'),
|
166
|
+
|
167
|
+
UnaryOps.POS: ('+', ''),
|
168
|
+
UnaryOps.NEG: ('-', ''),
|
169
|
+
}
|
170
|
+
|
171
|
+
@Renderer.render.register
|
172
|
+
def render_unary(self, o: Unary) -> None:
|
173
|
+
pfx, sfx = self.UNARY_OP_TO_STR[o.op]
|
174
|
+
self._out.write(pfx)
|
175
|
+
self.render(o.v)
|
176
|
+
self._out.write(sfx)
|
177
|
+
|
178
|
+
|
179
|
+
def render(n: Node) -> str:
|
180
|
+
return StdRenderer.render_str(n)
|
omlish/sql/queries/unary.py
CHANGED
@@ -3,6 +3,7 @@ from ... import lang
|
|
3
3
|
from .exprs import CanExpr
|
4
4
|
from .exprs import Expr
|
5
5
|
from .exprs import ExprBuilder
|
6
|
+
from .ops import OpKind
|
6
7
|
|
7
8
|
|
8
9
|
##
|
@@ -10,10 +11,16 @@ from .exprs import ExprBuilder
|
|
10
11
|
|
11
12
|
class UnaryOp(dc.Frozen, lang.Final, eq=False):
|
12
13
|
name: str
|
14
|
+
kind: OpKind
|
13
15
|
|
14
16
|
|
15
17
|
class UnaryOps(lang.Namespace):
|
16
|
-
NOT = UnaryOp('not')
|
18
|
+
NOT = UnaryOp('not', OpKind.CMP)
|
19
|
+
IS_NULL = UnaryOp('is_null', OpKind.CMP)
|
20
|
+
IS_NOT_NULL = UnaryOp('is_not_null', OpKind.CMP)
|
21
|
+
|
22
|
+
POS = UnaryOp('pos', OpKind.ARITH)
|
23
|
+
NEG = UnaryOp('neg', OpKind.ARITH)
|
17
24
|
|
18
25
|
|
19
26
|
class Unary(Expr, lang.Final):
|
@@ -25,5 +32,21 @@ class UnaryBuilder(ExprBuilder):
|
|
25
32
|
def unary(self, op: UnaryOp, v: CanExpr) -> Unary:
|
26
33
|
return Unary(op, self.expr(v))
|
27
34
|
|
35
|
+
#
|
36
|
+
|
28
37
|
def not_(self, v: CanExpr) -> Unary:
|
29
38
|
return self.unary(UnaryOps.NOT, v)
|
39
|
+
|
40
|
+
def is_null(self, v: CanExpr) -> Unary:
|
41
|
+
return self.unary(UnaryOps.IS_NULL, v)
|
42
|
+
|
43
|
+
def is_not_null(self, v: CanExpr) -> Unary:
|
44
|
+
return self.unary(UnaryOps.IS_NOT_NULL, v)
|
45
|
+
|
46
|
+
#
|
47
|
+
|
48
|
+
def pos(self, v: CanExpr) -> Unary:
|
49
|
+
return self.unary(UnaryOps.POS, v)
|
50
|
+
|
51
|
+
def neg(self, v: CanExpr) -> Unary:
|
52
|
+
return self.unary(UnaryOps.NEG, v)
|
omlish/sql/tabledefs/marshal.py
CHANGED
@@ -10,10 +10,7 @@ def _install_poly(cls: type) -> None:
|
|
10
10
|
msh.STANDARD_UNMARSHALER_FACTORIES[0:0] = [msh.PolymorphismUnmarshalerFactory(p)]
|
11
11
|
|
12
12
|
|
13
|
-
@lang.
|
13
|
+
@lang.static_init
|
14
14
|
def _install_standard_marshalling() -> None:
|
15
15
|
_install_poly(Dtype)
|
16
16
|
_install_poly(Element)
|
17
|
-
|
18
|
-
|
19
|
-
_install_standard_marshalling()
|
@@ -1,5 +1,5 @@
|
|
1
1
|
omlish/.manifests.json,sha256=TXvFdkAU0Zr2FKdo7fyvt9nr3UjCtrnAZ0diZXSAteE,1430
|
2
|
-
omlish/__about__.py,sha256=
|
2
|
+
omlish/__about__.py,sha256=6L5yBogPnXXOqNId_oVRZJ4kjVB68VskkdZvIJ7NlE0,3420
|
3
3
|
omlish/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
4
|
omlish/argparse.py,sha256=Dc73G8lyoQBLvXhMYUbzQUh4SJu_OTvKUXjSUxq_ang,7499
|
5
5
|
omlish/c3.py,sha256=4vogWgwPb8TbNS2KkZxpoWbwjj7MuHG2lQG-hdtkvjI,8062
|
@@ -132,13 +132,13 @@ omlish/dataclasses/impl/as_.py,sha256=CD-t7hkC1EP2F_jvZKIA_cVoDuwZ-Ln_xC4fJumPYX
|
|
132
132
|
omlish/dataclasses/impl/copy.py,sha256=Tn8_n6Vohs-w4otbGdubBEvhd3TsSTaM3EfNGdS2LYo,591
|
133
133
|
omlish/dataclasses/impl/descriptors.py,sha256=rEYE1Len99agTQCC25hSPMnM19BgPr0ZChABGi58Fdk,2476
|
134
134
|
omlish/dataclasses/impl/exceptions.py,sha256=DeiM6rcjgncudn-XVuph9TDbVDEwBtyYb1bcbO3FFcA,193
|
135
|
-
omlish/dataclasses/impl/fields.py,sha256=
|
135
|
+
omlish/dataclasses/impl/fields.py,sha256=mr8tnSDceHGZ6VBbeegt-iCzQJbtCXoWOUwltjRULy4,6521
|
136
136
|
omlish/dataclasses/impl/frozen.py,sha256=x87DSM8FIMZ3c_BIUE8NooCkExFjPsabeqIueEP5qKs,2988
|
137
137
|
omlish/dataclasses/impl/hashing.py,sha256=FKnHuXCg9ylrzK2TLGqO5yfRN4HX3F415CSLlVYXtYE,3190
|
138
138
|
omlish/dataclasses/impl/init.py,sha256=IgxO9nwHaHF8jGrUAk-Y5xke9uV2OwzfEe-88McE1Wg,6161
|
139
139
|
omlish/dataclasses/impl/internals.py,sha256=UvZYjrLT1S8ntyxJ_vRPIkPOF00K8HatGAygErgoXTU,2990
|
140
140
|
omlish/dataclasses/impl/main.py,sha256=Ti0PKbFKraKvfmoPuR-G7nLVNzRC8mvEuXhCuC-M2kc,2574
|
141
|
-
omlish/dataclasses/impl/metaclass.py,sha256=
|
141
|
+
omlish/dataclasses/impl/metaclass.py,sha256=Fb0ExFiyYdOpvck4ayXMr_vEVDvHLhe28Ns3F4aduM8,3222
|
142
142
|
omlish/dataclasses/impl/metadata.py,sha256=4veWwTr-aA0KP-Y1cPEeOcXHup9EKJTYNJ0ozIxtzD4,1401
|
143
143
|
omlish/dataclasses/impl/order.py,sha256=zWvWDkSTym8cc7vO1cLHqcBhhjOlucHOCUVJcdh4jt0,1369
|
144
144
|
omlish/dataclasses/impl/params.py,sha256=zsobAD6QvMAZeMsohP8nKFyv_w6Q4buocARQG1y1etA,2768
|
@@ -299,7 +299,7 @@ omlish/marshal/base.py,sha256=_ZKSSuv6p9r86sja_jaxI09WYpjCBFi0KTsOiZCYyk0,6587
|
|
299
299
|
omlish/marshal/base64.py,sha256=F-3ogJdcFCtWINRgJgWT0rErqgx6f4qahhcg8OrkqhE,1089
|
300
300
|
omlish/marshal/dataclasses.py,sha256=G6Uh8t4vvNBAx2BhzH8ksj8Hq_bo6npFphQhyF298VU,6892
|
301
301
|
omlish/marshal/datetimes.py,sha256=0ffg8cEvx9SMKIXZGD9b7MqpLfmgw0uKKdn6YTfoqok,3714
|
302
|
-
omlish/marshal/enums.py,sha256
|
302
|
+
omlish/marshal/enums.py,sha256=CMAbx6RI2EcQoo7SoD-5q2l-3DFKreWMiOxs6mFpl_4,1472
|
303
303
|
omlish/marshal/exceptions.py,sha256=jwQWn4LcPnadT2KRI_1JJCOSkwWh0yHnYK9BmSkNN4U,302
|
304
304
|
omlish/marshal/factories.py,sha256=UV2Svjok-lTWsRqKGh-CeuAhvlohw9uJe7ZLyoKMvTM,2968
|
305
305
|
omlish/marshal/forbidden.py,sha256=BNshzm4lN5O8sUZ1YvxrSYq3WPklq9NMQCRZ7RC3DLM,865
|
@@ -388,24 +388,27 @@ omlish/sql/alchemy/duckdb.py,sha256=kr7pIhiBLNAuZrcigHDtFg9zHkVcrRW3LfryO9VJ4mk,
|
|
388
388
|
omlish/sql/alchemy/exprs.py,sha256=gO4Fj4xEY-PuDgV-N8hBMy55glZz7O-4H7v1LWabfZY,323
|
389
389
|
omlish/sql/alchemy/secrets.py,sha256=EMfy4EfTbEvrlv_41oOhn8qsoF-eTkY7HciPenIE6rI,178
|
390
390
|
omlish/sql/alchemy/sqlean.py,sha256=RbkuOuFIfM4fowwKk8-sQ6Dxk-tTUwxS94nY5Kxt52s,403
|
391
|
-
omlish/sql/queries/__init__.py,sha256=
|
391
|
+
omlish/sql/queries/__init__.py,sha256=BdhONMw2JebX-jEgYb1WrM5L3vkJOzQRm0nt04IYKgQ,1229
|
392
392
|
omlish/sql/queries/base.py,sha256=_8O3MbH_OEjBnhp2oIJUZ3ClaQ8l4Sj9BdPdsP0Ie-g,224
|
393
|
-
omlish/sql/queries/binary.py,sha256=
|
394
|
-
omlish/sql/queries/
|
393
|
+
omlish/sql/queries/binary.py,sha256=dcEzeEn104AMPuQ7QrJU2O-YCN3SUdxB5S4jaWKOUqY,2253
|
394
|
+
omlish/sql/queries/building.py,sha256=pddD8-WDDGwX97OW7MLahaZTLsO_0NLxxIIAXXq1N40,537
|
395
|
+
omlish/sql/queries/exprs.py,sha256=kAI5PmvfJ-TqEzzc9H4_womFShT1eA0jWSZH2j2Wg-c,1802
|
395
396
|
omlish/sql/queries/idents.py,sha256=erW6fE9UapuvW1ZeLfGFz7yuW6zzktWIWmOuAHeF8_g,496
|
396
|
-
omlish/sql/queries/
|
397
|
+
omlish/sql/queries/marshal.py,sha256=MKZ3CVcr7mpnmg25twVgErWk1SpRBEkE1mu2fE8QwUA,2508
|
398
|
+
omlish/sql/queries/multi.py,sha256=KKHf8uS3Akk-YACPUwaqQO20NlDdrB3gbauOAejZzgU,832
|
397
399
|
omlish/sql/queries/names.py,sha256=YiIyS6ehYMYrdLlUxMawV_Xf2zdi7RwVO9Qsxr_W4_4,772
|
398
|
-
omlish/sql/queries/
|
400
|
+
omlish/sql/queries/ops.py,sha256=B7IDfjr2DW5LJhWoNaY1WW90BJhe5ZtmxIELhWXbW-0,129
|
401
|
+
omlish/sql/queries/relations.py,sha256=-d3n-dN17c3TPMZmzSplhWawllUzdq12XPDAuzoeMEQ,838
|
402
|
+
omlish/sql/queries/rendering.py,sha256=AC2PSGFCLXYk38mnH7EAMV7hQOKp5x6O-ZYV8FXgnAM,4360
|
399
403
|
omlish/sql/queries/selects.py,sha256=EcHlyKl5kGSY1d3GVxnImhGCTB6WvwQnlSA9eZanBqU,1364
|
400
|
-
omlish/sql/queries/std.py,sha256=pddD8-WDDGwX97OW7MLahaZTLsO_0NLxxIIAXXq1N40,537
|
401
404
|
omlish/sql/queries/stmts.py,sha256=pBqwD7dRlqMu6uh6vR3xaWOEgbZCcFWbOQ9ryYd17T4,441
|
402
|
-
omlish/sql/queries/unary.py,sha256=
|
405
|
+
omlish/sql/queries/unary.py,sha256=MEYBDZn_H0bexmUrJeONOv5-gIpYowUaXOsEHeQM4ks,1144
|
403
406
|
omlish/sql/tabledefs/__init__.py,sha256=TvtQsp-jJu6_ZahyCOFAaElSSBcRftNyJpdiDPGYCDk,190
|
404
407
|
omlish/sql/tabledefs/alchemy.py,sha256=MiNfVSgX_Ka6PmVTgAcCmS3ULK5mfVRXD_VC2-9TidU,485
|
405
408
|
omlish/sql/tabledefs/dtypes.py,sha256=egZDi-A17MC-4R_ZKR_3uQf1a6mGm91Gmh0b72O85bQ,362
|
406
409
|
omlish/sql/tabledefs/elements.py,sha256=lP_Ch19hKmiGYPQVeC8HpFaKdTYnXi2FfpfwKMxZOck,1674
|
407
410
|
omlish/sql/tabledefs/lower.py,sha256=YQf8gl1kxD5Fm-vOxV6G0Feh_D9PP1pYwz_vz6XjTPQ,1405
|
408
|
-
omlish/sql/tabledefs/marshal.py,sha256=
|
411
|
+
omlish/sql/tabledefs/marshal.py,sha256=j-Rz1HsiXmABv39-2VoJdzSSB3kbxqaVevbdkZWMyG8,504
|
409
412
|
omlish/sql/tabledefs/tabledefs.py,sha256=lIhvlt0pk6G7RZAtDFsFXm5j0l9BvRfnP7vNGeydHtE,816
|
410
413
|
omlish/testing/__init__.py,sha256=M_BQrcCHkoL-ZvE-UpQ8XxXNYRRawhjUz4rCJnAqM2A,152
|
411
414
|
omlish/testing/testing.py,sha256=TT2wwSzPZ_KhIvKxpM1qc1yHKD-LHDNgGrcr_h8vs7c,2895
|
@@ -433,9 +436,9 @@ omlish/text/delimit.py,sha256=ubPXcXQmtbOVrUsNh5gH1mDq5H-n1y2R4cPL5_DQf68,4928
|
|
433
436
|
omlish/text/glyphsplit.py,sha256=Ug-dPRO7x-OrNNr8g1y6DotSZ2KH0S-VcOmUobwa4B0,3296
|
434
437
|
omlish/text/indent.py,sha256=6Jj6TFY9unaPa4xPzrnZemJ-fHsV53IamP93XGjSUHs,1274
|
435
438
|
omlish/text/parts.py,sha256=7vPF1aTZdvLVYJ4EwBZVzRSy8XB3YqPd7JwEnNGGAOo,6495
|
436
|
-
omlish-0.0.0.
|
437
|
-
omlish-0.0.0.
|
438
|
-
omlish-0.0.0.
|
439
|
-
omlish-0.0.0.
|
440
|
-
omlish-0.0.0.
|
441
|
-
omlish-0.0.0.
|
439
|
+
omlish-0.0.0.dev74.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
|
440
|
+
omlish-0.0.0.dev74.dist-info/METADATA,sha256=fnVoKX28JDI8_XtMIkZGO22Po_cPDkZIi8nGwf6A_84,4167
|
441
|
+
omlish-0.0.0.dev74.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
|
442
|
+
omlish-0.0.0.dev74.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
|
443
|
+
omlish-0.0.0.dev74.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
|
444
|
+
omlish-0.0.0.dev74.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|