sqlalchemy-risingwave 1.1.0__tar.gz → 1.4.0__tar.gz
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.
- {sqlalchemy-risingwave-1.1.0 → sqlalchemy_risingwave-1.4.0}/PKG-INFO +15 -8
- {sqlalchemy-risingwave-1.1.0 → sqlalchemy_risingwave-1.4.0}/README.md +1 -5
- {sqlalchemy-risingwave-1.1.0 → sqlalchemy_risingwave-1.4.0}/setup.py +1 -1
- {sqlalchemy-risingwave-1.1.0 → sqlalchemy_risingwave-1.4.0}/sqlalchemy_risingwave/__init__.py +1 -1
- {sqlalchemy-risingwave-1.1.0 → sqlalchemy_risingwave-1.4.0}/sqlalchemy_risingwave/base.py +48 -24
- {sqlalchemy-risingwave-1.1.0 → sqlalchemy_risingwave-1.4.0}/sqlalchemy_risingwave.egg-info/PKG-INFO +15 -8
- sqlalchemy_risingwave-1.4.0/sqlalchemy_risingwave.egg-info/requires.txt +1 -0
- {sqlalchemy-risingwave-1.1.0 → sqlalchemy_risingwave-1.4.0}/test/test_schema.py +26 -12
- sqlalchemy-risingwave-1.1.0/sqlalchemy_risingwave.egg-info/requires.txt +0 -1
- {sqlalchemy-risingwave-1.1.0 → sqlalchemy_risingwave-1.4.0}/LICENSE +0 -0
- {sqlalchemy-risingwave-1.1.0 → sqlalchemy_risingwave-1.4.0}/setup.cfg +0 -0
- {sqlalchemy-risingwave-1.1.0 → sqlalchemy_risingwave-1.4.0}/sqlalchemy_risingwave/psycopg2.py +0 -0
- {sqlalchemy-risingwave-1.1.0 → sqlalchemy_risingwave-1.4.0}/sqlalchemy_risingwave/requirements.py +0 -0
- {sqlalchemy-risingwave-1.1.0 → sqlalchemy_risingwave-1.4.0}/sqlalchemy_risingwave.egg-info/SOURCES.txt +0 -0
- {sqlalchemy-risingwave-1.1.0 → sqlalchemy_risingwave-1.4.0}/sqlalchemy_risingwave.egg-info/dependency_links.txt +0 -0
- {sqlalchemy-risingwave-1.1.0 → sqlalchemy_risingwave-1.4.0}/sqlalchemy_risingwave.egg-info/entry_points.txt +0 -0
- {sqlalchemy-risingwave-1.1.0 → sqlalchemy_risingwave-1.4.0}/sqlalchemy_risingwave.egg-info/not-zip-safe +0 -0
- {sqlalchemy-risingwave-1.1.0 → sqlalchemy_risingwave-1.4.0}/sqlalchemy_risingwave.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: sqlalchemy-risingwave
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.0
|
|
4
4
|
Summary: RisingWave dialect for SQLAlchemy
|
|
5
5
|
Home-page: https://github.com/risingwavelabs/risingwave
|
|
6
6
|
Author: RisingWave Labs
|
|
@@ -19,7 +19,18 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.12
|
|
20
20
|
Description-Content-Type: text/markdown
|
|
21
21
|
License-File: LICENSE
|
|
22
|
-
Requires-Dist: SQLAlchemy<2.1
|
|
22
|
+
Requires-Dist: SQLAlchemy<2.0,>=1.4
|
|
23
|
+
Dynamic: author
|
|
24
|
+
Dynamic: author-email
|
|
25
|
+
Dynamic: classifier
|
|
26
|
+
Dynamic: description
|
|
27
|
+
Dynamic: description-content-type
|
|
28
|
+
Dynamic: home-page
|
|
29
|
+
Dynamic: keywords
|
|
30
|
+
Dynamic: license
|
|
31
|
+
Dynamic: project-url
|
|
32
|
+
Dynamic: requires-dist
|
|
33
|
+
Dynamic: summary
|
|
23
34
|
|
|
24
35
|
# RisingWave dialect for SQLAlchemy
|
|
25
36
|
|
|
@@ -39,7 +50,7 @@ For psycopg2 support you must install either:
|
|
|
39
50
|
|
|
40
51
|
(The binary package is a practical choice for development and testing but in
|
|
41
52
|
production it is advised to use the package built from sources.)
|
|
42
|
-
|
|
53
|
+
|
|
43
54
|
## Install
|
|
44
55
|
Install via [PyPI](https://pypi.org/project/sqlalchemy-risingwave/)
|
|
45
56
|
```
|
|
@@ -73,11 +84,7 @@ pytest # to run the test
|
|
|
73
84
|
## Ref
|
|
74
85
|
|
|
75
86
|
- [Sqlalchemy dialects doc](https://github.com/sqlalchemy/sqlalchemy/blob/main/README.dialects.rst)
|
|
76
|
-
|
|
77
87
|
- [CocoroachDB sqlalchemy](https://github.com/cockroachdb/sqlalchemy-cockroachdb)
|
|
78
|
-
|
|
79
88
|
- [RisingWave: Open-Source Streaming Database](https://www.risingwave.com/database/)
|
|
80
|
-
|
|
81
89
|
- [RisingWave Cloud](https://www.risingwave.com/cloud/)
|
|
82
|
-
|
|
83
90
|
- [What is RisingWave?](https://docs.risingwave.com/docs/current/intro/)
|
|
@@ -16,7 +16,7 @@ For psycopg2 support you must install either:
|
|
|
16
16
|
|
|
17
17
|
(The binary package is a practical choice for development and testing but in
|
|
18
18
|
production it is advised to use the package built from sources.)
|
|
19
|
-
|
|
19
|
+
|
|
20
20
|
## Install
|
|
21
21
|
Install via [PyPI](https://pypi.org/project/sqlalchemy-risingwave/)
|
|
22
22
|
```
|
|
@@ -50,11 +50,7 @@ pytest # to run the test
|
|
|
50
50
|
## Ref
|
|
51
51
|
|
|
52
52
|
- [Sqlalchemy dialects doc](https://github.com/sqlalchemy/sqlalchemy/blob/main/README.dialects.rst)
|
|
53
|
-
|
|
54
53
|
- [CocoroachDB sqlalchemy](https://github.com/cockroachdb/sqlalchemy-cockroachdb)
|
|
55
|
-
|
|
56
54
|
- [RisingWave: Open-Source Streaming Database](https://www.risingwave.com/database/)
|
|
57
|
-
|
|
58
55
|
- [RisingWave Cloud](https://www.risingwave.com/cloud/)
|
|
59
|
-
|
|
60
56
|
- [What is RisingWave?](https://docs.risingwave.com/docs/current/intro/)
|
|
@@ -36,7 +36,7 @@ setup(
|
|
|
36
36
|
},
|
|
37
37
|
packages=find_packages(include=["sqlalchemy_risingwave"]),
|
|
38
38
|
include_package_data=True,
|
|
39
|
-
install_requires=["SQLAlchemy>=
|
|
39
|
+
install_requires=["SQLAlchemy>=1.4,<2.0"],
|
|
40
40
|
zip_safe=False,
|
|
41
41
|
# # Do not support dialects now.
|
|
42
42
|
entry_points={
|
|
@@ -7,6 +7,7 @@ from sqlalchemy.util import warn
|
|
|
7
7
|
|
|
8
8
|
from sqlalchemy import util
|
|
9
9
|
import sqlalchemy.types as sqltypes
|
|
10
|
+
import sqlalchemy.exc as exc
|
|
10
11
|
|
|
11
12
|
_type_map = {
|
|
12
13
|
"bool": sqltypes.BOOLEAN, # DataType::Boolean
|
|
@@ -69,13 +70,30 @@ class RisingWaveDialect(PGDialect_psycopg2):
|
|
|
69
70
|
rows = conn.execute(text(sql))
|
|
70
71
|
return [row.tablename for row in rows]
|
|
71
72
|
|
|
72
|
-
def get_view_names(self, conn, schema=None, **kw):
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
73
|
+
def get_view_names(self, conn, schema=None, include=("plain", "materialized"), **kw):
|
|
74
|
+
base_queries = [
|
|
75
|
+
"SELECT viewname FROM pg_views",
|
|
76
|
+
"SELECT matviewname as viewname FROM pg_matviews",
|
|
77
|
+
]
|
|
78
|
+
if not include:
|
|
79
|
+
raise ValueError(
|
|
80
|
+
"empty include, needs to be a sequence containing "
|
|
81
|
+
"one or both of 'plain' and 'materialized'"
|
|
82
|
+
)
|
|
83
|
+
include_queries = []
|
|
84
|
+
if "plain" in include:
|
|
85
|
+
include_queries.append(base_queries[0])
|
|
86
|
+
if "materialized" in include:
|
|
87
|
+
include_queries.append(base_queries[1])
|
|
88
|
+
|
|
89
|
+
queries = []
|
|
90
|
+
for sql in include_queries:
|
|
91
|
+
if schema is not None:
|
|
92
|
+
sql += f" WHERE schemaname = '{schema or self.default_schema_name}'"
|
|
93
|
+
else:
|
|
94
|
+
sql += " WHERE schemaname <> 'rw_catalog' and schemaname <> 'pg_catalog' and schemaname <> 'information_schema'"
|
|
95
|
+
queries.append(sql)
|
|
96
|
+
views = conn.execute(text(" UNION ".join(queries)))
|
|
79
97
|
|
|
80
98
|
# As sqlalchmey has no support for Sources, we categorize as view temporarily.
|
|
81
99
|
source_sql = f"SELECT rw_catalog.rw_sources.name as source_name FROM rw_catalog.rw_sources JOIN rw_catalog.rw_schemas ON rw_catalog.rw_sources.schema_id = rw_catalog.rw_schemas.id"
|
|
@@ -84,7 +102,10 @@ class RisingWaveDialect(PGDialect_psycopg2):
|
|
|
84
102
|
else:
|
|
85
103
|
source_sql += " WHERE rw_catalog.rw_schemas.name <> 'rw_catalog' and rw_catalog.rw_schemas.name <> 'pg_catalog' and rw_catalog.rw_schemas.name <> 'information_schema'"
|
|
86
104
|
sources = conn.execute(text(source_sql))
|
|
87
|
-
|
|
105
|
+
|
|
106
|
+
return [view.viewname for view in views] + [
|
|
107
|
+
source.source_name for source in sources
|
|
108
|
+
]
|
|
88
109
|
|
|
89
110
|
def has_table(self, conn, table, schema=None, **kw):
|
|
90
111
|
return any(t == table for t in self.get_table_names(conn, schema=schema))
|
|
@@ -96,7 +117,10 @@ class RisingWaveDialect(PGDialect_psycopg2):
|
|
|
96
117
|
)
|
|
97
118
|
rows = conn.execute(
|
|
98
119
|
text(sql),
|
|
99
|
-
{
|
|
120
|
+
{
|
|
121
|
+
"table_schema": schema or self.default_schema_name,
|
|
122
|
+
"table_name": table_name,
|
|
123
|
+
},
|
|
100
124
|
)
|
|
101
125
|
|
|
102
126
|
res = []
|
|
@@ -138,6 +162,7 @@ class RisingWaveDialect(PGDialect_psycopg2):
|
|
|
138
162
|
column_info = dict(
|
|
139
163
|
name=name,
|
|
140
164
|
type=type_class,
|
|
165
|
+
nullable = True,
|
|
141
166
|
)
|
|
142
167
|
|
|
143
168
|
res.append(column_info)
|
|
@@ -149,8 +174,8 @@ class RisingWaveDialect(PGDialect_psycopg2):
|
|
|
149
174
|
schema_where_clause = "n.nspname = :schema"
|
|
150
175
|
else:
|
|
151
176
|
schema_where_clause = "pg_catalog.pg_table_is_visible(r.id)"
|
|
152
|
-
|
|
153
|
-
|
|
177
|
+
sql = (
|
|
178
|
+
"""
|
|
154
179
|
SELECT r.id as oid
|
|
155
180
|
FROM rw_catalog.rw_relations r
|
|
156
181
|
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = r.schema_id
|
|
@@ -158,18 +183,12 @@ class RisingWaveDialect(PGDialect_psycopg2):
|
|
|
158
183
|
AND r.name = :table_name AND r.relation_type in
|
|
159
184
|
('table', 'system table', 'view', 'materialized view', 'source', 'sink')
|
|
160
185
|
"""
|
|
161
|
-
|
|
186
|
+
% schema_where_clause
|
|
187
|
+
)
|
|
188
|
+
s = text(sql).columns(oid=sqltypes.Integer)
|
|
189
|
+
c = connection.execute(
|
|
190
|
+
s, {"table_name": str(table_name), "schema": str(schema)}
|
|
162
191
|
)
|
|
163
|
-
# Since we're binding to unicode, table_name and schema_name must be
|
|
164
|
-
# unicode.
|
|
165
|
-
table_name = util.text_type(table_name)
|
|
166
|
-
if schema is not None:
|
|
167
|
-
schema = util.text_type(schema)
|
|
168
|
-
s = text(query).bindparams(table_name=sqltypes.Unicode)
|
|
169
|
-
s = s.columns(oid=sqltypes.Integer)
|
|
170
|
-
if schema:
|
|
171
|
-
s = s.bindparams(sql.bindparam("schema", type_=sqltypes.Unicode))
|
|
172
|
-
c = connection.execute(s, dict(table_name=table_name, schema=schema))
|
|
173
192
|
table_oid = c.scalar()
|
|
174
193
|
if table_oid is None:
|
|
175
194
|
raise exc.NoSuchTableError(table_name)
|
|
@@ -210,10 +229,15 @@ class RisingWaveDialect(PGDialect_psycopg2):
|
|
|
210
229
|
return res
|
|
211
230
|
|
|
212
231
|
def get_foreign_keys_v1(self, conn, table_name, schema=None, **kw):
|
|
213
|
-
|
|
232
|
+
return []
|
|
214
233
|
|
|
215
234
|
def get_foreign_keys(
|
|
216
|
-
|
|
235
|
+
self,
|
|
236
|
+
connection,
|
|
237
|
+
table_name,
|
|
238
|
+
schema=None,
|
|
239
|
+
postgresql_ignore_search_path=False,
|
|
240
|
+
**kw,
|
|
217
241
|
):
|
|
218
242
|
return []
|
|
219
243
|
|
{sqlalchemy-risingwave-1.1.0 → sqlalchemy_risingwave-1.4.0}/sqlalchemy_risingwave.egg-info/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: sqlalchemy-risingwave
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.0
|
|
4
4
|
Summary: RisingWave dialect for SQLAlchemy
|
|
5
5
|
Home-page: https://github.com/risingwavelabs/risingwave
|
|
6
6
|
Author: RisingWave Labs
|
|
@@ -19,7 +19,18 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.12
|
|
20
20
|
Description-Content-Type: text/markdown
|
|
21
21
|
License-File: LICENSE
|
|
22
|
-
Requires-Dist: SQLAlchemy<2.1
|
|
22
|
+
Requires-Dist: SQLAlchemy<2.0,>=1.4
|
|
23
|
+
Dynamic: author
|
|
24
|
+
Dynamic: author-email
|
|
25
|
+
Dynamic: classifier
|
|
26
|
+
Dynamic: description
|
|
27
|
+
Dynamic: description-content-type
|
|
28
|
+
Dynamic: home-page
|
|
29
|
+
Dynamic: keywords
|
|
30
|
+
Dynamic: license
|
|
31
|
+
Dynamic: project-url
|
|
32
|
+
Dynamic: requires-dist
|
|
33
|
+
Dynamic: summary
|
|
23
34
|
|
|
24
35
|
# RisingWave dialect for SQLAlchemy
|
|
25
36
|
|
|
@@ -39,7 +50,7 @@ For psycopg2 support you must install either:
|
|
|
39
50
|
|
|
40
51
|
(The binary package is a practical choice for development and testing but in
|
|
41
52
|
production it is advised to use the package built from sources.)
|
|
42
|
-
|
|
53
|
+
|
|
43
54
|
## Install
|
|
44
55
|
Install via [PyPI](https://pypi.org/project/sqlalchemy-risingwave/)
|
|
45
56
|
```
|
|
@@ -73,11 +84,7 @@ pytest # to run the test
|
|
|
73
84
|
## Ref
|
|
74
85
|
|
|
75
86
|
- [Sqlalchemy dialects doc](https://github.com/sqlalchemy/sqlalchemy/blob/main/README.dialects.rst)
|
|
76
|
-
|
|
77
87
|
- [CocoroachDB sqlalchemy](https://github.com/cockroachdb/sqlalchemy-cockroachdb)
|
|
78
|
-
|
|
79
88
|
- [RisingWave: Open-Source Streaming Database](https://www.risingwave.com/database/)
|
|
80
|
-
|
|
81
89
|
- [RisingWave Cloud](https://www.risingwave.com/cloud/)
|
|
82
|
-
|
|
83
90
|
- [What is RisingWave?](https://docs.risingwave.com/docs/current/intro/)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
SQLAlchemy<2.0,>=1.4
|
|
@@ -26,29 +26,43 @@ class SchemaTest(fixtures.TestBase):
|
|
|
26
26
|
|
|
27
27
|
def test_get_indexes(self):
|
|
28
28
|
with testing.db.begin() as conn:
|
|
29
|
-
conn.execute(text("CREATE TABLE
|
|
30
|
-
conn.execute(text("CREATE INDEX
|
|
29
|
+
conn.execute(text("CREATE TABLE t (id1 INT, id2 INT, id3 INT)"))
|
|
30
|
+
conn.execute(text("CREATE INDEX idx ON t(id2) INCLUDE(id1)"))
|
|
31
31
|
|
|
32
32
|
insp = inspect(testing.db)
|
|
33
|
-
indexes = insp.get_indexes("
|
|
33
|
+
indexes = insp.get_indexes("t")
|
|
34
34
|
|
|
35
35
|
assert len(indexes) == 1
|
|
36
|
-
assert indexes[0]["name"] == "
|
|
37
|
-
|
|
38
|
-
assert indexes[0]["column_names"] == ["id2"]
|
|
36
|
+
assert indexes[0]["name"] == "idx"
|
|
37
|
+
assert indexes[0]["column_names"] == ["id2", "id1"]
|
|
39
38
|
|
|
40
|
-
conn.execute(text("DROP TABLE
|
|
39
|
+
conn.execute(text("DROP TABLE t"))
|
|
41
40
|
|
|
42
41
|
def test_get_view_names(self):
|
|
43
42
|
with testing.db.begin() as conn:
|
|
44
|
-
conn.execute(text("CREATE TABLE
|
|
45
|
-
conn.execute(text("CREATE VIEW
|
|
43
|
+
conn.execute(text("CREATE TABLE t (id1 INT, id2 INT, id3 INT)"))
|
|
44
|
+
conn.execute(text("CREATE VIEW v AS SELECT * from t"))
|
|
45
|
+
conn.execute(text("CREATE MATERIALIZED VIEW mv AS SELECT * FROM t"))
|
|
46
46
|
|
|
47
47
|
insp = inspect(testing.db)
|
|
48
48
|
views = insp.get_view_names()
|
|
49
49
|
|
|
50
|
+
assert len(views) == 2
|
|
51
|
+
assert "v" in views
|
|
52
|
+
assert "mv" in views
|
|
53
|
+
|
|
54
|
+
insp = inspect(testing.db)
|
|
55
|
+
views = insp.get_view_names(include = ("plain"))
|
|
56
|
+
|
|
57
|
+
assert len(views) == 1
|
|
58
|
+
assert "v" in views
|
|
59
|
+
|
|
60
|
+
insp = inspect(testing.db)
|
|
61
|
+
views = insp.get_view_names(include = ("materialized"))
|
|
62
|
+
|
|
50
63
|
assert len(views) == 1
|
|
51
|
-
assert
|
|
64
|
+
assert "mv" in views
|
|
52
65
|
|
|
53
|
-
conn.execute(text("DROP VIEW
|
|
54
|
-
conn.execute(text("DROP
|
|
66
|
+
conn.execute(text("DROP MATERIALIZED VIEW mv"))
|
|
67
|
+
conn.execute(text("DROP VIEW v"))
|
|
68
|
+
conn.execute(text("DROP TABLE t"))
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
SQLAlchemy<2.1,>=2.0
|
|
File without changes
|
|
File without changes
|
{sqlalchemy-risingwave-1.1.0 → sqlalchemy_risingwave-1.4.0}/sqlalchemy_risingwave/psycopg2.py
RENAMED
|
File without changes
|
{sqlalchemy-risingwave-1.1.0 → sqlalchemy_risingwave-1.4.0}/sqlalchemy_risingwave/requirements.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|