Coverage for python/felis/db/sqltypes.py: 61%
66 statements
« prev ^ index » next coverage.py v6.5.0, created at 2022-10-22 01:55 -0700
« prev ^ index » next coverage.py v6.5.0, created at 2022-10-22 01:55 -0700
1# This file is part of felis.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (https://www.lsst.org).
6# See the COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
8#
9# This program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program. If not, see <https://www.gnu.org/licenses/>.
22import builtins
23from collections.abc import Mapping, MutableMapping
24from typing import Any
26from sqlalchemy import Float, SmallInteger, types
27from sqlalchemy.dialects import mysql, oracle, postgresql
28from sqlalchemy.ext.compiler import compiles
30MYSQL = "mysql"
31ORACLE = "oracle"
32POSTGRES = "postgresql"
33SQLITE = "sqlite"
36class TINYINT(SmallInteger):
37 """The non-standard TINYINT type."""
39 __visit_name__ = "TINYINT"
42class DOUBLE(Float):
43 """The non-standard DOUBLE type."""
45 __visit_name__ = "DOUBLE"
48@compiles(TINYINT)
49def compile_tinyint(type_: Any, compiler: Any, **kw: Any) -> str:
50 return "TINYINT"
53@compiles(DOUBLE)
54def compile_double(type_: Any, compiler: Any, **kw: Any) -> str:
55 return "DOUBLE"
58boolean_map = {MYSQL: mysql.BIT(1), ORACLE: oracle.NUMBER(1), POSTGRES: postgresql.BOOLEAN()}
60byte_map = {
61 MYSQL: mysql.TINYINT(),
62 ORACLE: oracle.NUMBER(3),
63 POSTGRES: postgresql.SMALLINT(),
64}
66short_map = {
67 MYSQL: mysql.SMALLINT(),
68 ORACLE: oracle.NUMBER(5),
69 POSTGRES: postgresql.SMALLINT(),
70}
72# Skip Oracle
73int_map = {
74 MYSQL: mysql.INTEGER(),
75 POSTGRES: postgresql.INTEGER(),
76}
78long_map = {
79 MYSQL: mysql.BIGINT(),
80 ORACLE: oracle.NUMBER(38, 0),
81 POSTGRES: postgresql.BIGINT(),
82}
84float_map = {
85 MYSQL: mysql.FLOAT(),
86 ORACLE: oracle.BINARY_FLOAT(),
87 POSTGRES: postgresql.FLOAT(),
88}
90double_map = {
91 MYSQL: mysql.DOUBLE(),
92 ORACLE: oracle.BINARY_DOUBLE(),
93 POSTGRES: postgresql.DOUBLE_PRECISION(),
94}
96char_map = {
97 MYSQL: mysql.CHAR,
98 ORACLE: oracle.CHAR,
99 POSTGRES: postgresql.CHAR,
100}
102string_map = {
103 MYSQL: mysql.VARCHAR,
104 ORACLE: oracle.VARCHAR2,
105 POSTGRES: postgresql.VARCHAR,
106}
108unicode_map = {
109 MYSQL: mysql.NVARCHAR,
110 ORACLE: oracle.NVARCHAR2,
111 POSTGRES: postgresql.VARCHAR,
112}
114text_map = {
115 MYSQL: mysql.LONGTEXT,
116 ORACLE: oracle.CLOB,
117 POSTGRES: postgresql.TEXT,
118}
120binary_map = {
121 MYSQL: mysql.LONGBLOB,
122 ORACLE: oracle.BLOB,
123 POSTGRES: postgresql.BYTEA,
124}
127def boolean(**kwargs: Any) -> types.TypeEngine:
128 return _vary(types.BOOLEAN(), boolean_map.copy(), kwargs)
131def byte(**kwargs: Any) -> types.TypeEngine:
132 return _vary(TINYINT(), byte_map.copy(), kwargs)
135def short(**kwargs: Any) -> types.TypeEngine:
136 return _vary(types.SMALLINT(), short_map.copy(), kwargs)
139def int(**kwargs: Any) -> types.TypeEngine:
140 return _vary(types.INTEGER(), int_map.copy(), kwargs)
143def long(**kwargs: Any) -> types.TypeEngine:
144 return _vary(types.BIGINT(), long_map.copy(), kwargs)
147def float(**kwargs: Any) -> types.TypeEngine:
148 return _vary(types.FLOAT(), float_map.copy(), kwargs)
151def double(**kwargs: Any) -> types.TypeEngine:
152 return _vary(DOUBLE(), double_map.copy(), kwargs)
155def char(length: builtins.int, **kwargs: Any) -> types.TypeEngine:
156 return _vary(types.CHAR(length), char_map.copy(), kwargs, length)
159def string(length: builtins.int, **kwargs: Any) -> types.TypeEngine:
160 return _vary(types.VARCHAR(length), string_map.copy(), kwargs, length)
163def unicode(length: builtins.int, **kwargs: Any) -> types.TypeEngine:
164 return _vary(types.NVARCHAR(length), unicode_map.copy(), kwargs, length)
167def text(length: builtins.int, **kwargs: Any) -> types.TypeEngine:
168 return _vary(types.CLOB(length), text_map.copy(), kwargs, length)
171def binary(length: builtins.int, **kwargs: Any) -> types.TypeEngine:
172 return _vary(types.BLOB(length), binary_map.copy(), kwargs, length)
175def timestamp(**kwargs: Any) -> types.TypeEngine:
176 return types.TIMESTAMP()
179def _vary(
180 type_: types.TypeEngine,
181 variant_map: MutableMapping[str, types.TypeEngine],
182 overrides: Mapping[str, types.TypeEngine],
183 *args: Any,
184) -> types.TypeEngine:
185 for dialect, variant in overrides.items():
186 variant_map[dialect] = variant
187 for dialect, variant in variant_map.items():
188 # If this is a class and not an instance, instantiate
189 if isinstance(variant, type):
190 variant = variant(*args)
191 type_ = type_.with_variant(variant, dialect)
192 return type_