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.
Files changed (18) hide show
  1. {sqlalchemy-risingwave-1.1.0 → sqlalchemy_risingwave-1.4.0}/PKG-INFO +15 -8
  2. {sqlalchemy-risingwave-1.1.0 → sqlalchemy_risingwave-1.4.0}/README.md +1 -5
  3. {sqlalchemy-risingwave-1.1.0 → sqlalchemy_risingwave-1.4.0}/setup.py +1 -1
  4. {sqlalchemy-risingwave-1.1.0 → sqlalchemy_risingwave-1.4.0}/sqlalchemy_risingwave/__init__.py +1 -1
  5. {sqlalchemy-risingwave-1.1.0 → sqlalchemy_risingwave-1.4.0}/sqlalchemy_risingwave/base.py +48 -24
  6. {sqlalchemy-risingwave-1.1.0 → sqlalchemy_risingwave-1.4.0}/sqlalchemy_risingwave.egg-info/PKG-INFO +15 -8
  7. sqlalchemy_risingwave-1.4.0/sqlalchemy_risingwave.egg-info/requires.txt +1 -0
  8. {sqlalchemy-risingwave-1.1.0 → sqlalchemy_risingwave-1.4.0}/test/test_schema.py +26 -12
  9. sqlalchemy-risingwave-1.1.0/sqlalchemy_risingwave.egg-info/requires.txt +0 -1
  10. {sqlalchemy-risingwave-1.1.0 → sqlalchemy_risingwave-1.4.0}/LICENSE +0 -0
  11. {sqlalchemy-risingwave-1.1.0 → sqlalchemy_risingwave-1.4.0}/setup.cfg +0 -0
  12. {sqlalchemy-risingwave-1.1.0 → sqlalchemy_risingwave-1.4.0}/sqlalchemy_risingwave/psycopg2.py +0 -0
  13. {sqlalchemy-risingwave-1.1.0 → sqlalchemy_risingwave-1.4.0}/sqlalchemy_risingwave/requirements.py +0 -0
  14. {sqlalchemy-risingwave-1.1.0 → sqlalchemy_risingwave-1.4.0}/sqlalchemy_risingwave.egg-info/SOURCES.txt +0 -0
  15. {sqlalchemy-risingwave-1.1.0 → sqlalchemy_risingwave-1.4.0}/sqlalchemy_risingwave.egg-info/dependency_links.txt +0 -0
  16. {sqlalchemy-risingwave-1.1.0 → sqlalchemy_risingwave-1.4.0}/sqlalchemy_risingwave.egg-info/entry_points.txt +0 -0
  17. {sqlalchemy-risingwave-1.1.0 → sqlalchemy_risingwave-1.4.0}/sqlalchemy_risingwave.egg-info/not-zip-safe +0 -0
  18. {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
1
+ Metadata-Version: 2.2
2
2
  Name: sqlalchemy-risingwave
3
- Version: 1.1.0
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,>=2.0
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>=2.0,<2.1"],
39
+ install_requires=["SQLAlchemy>=1.4,<2.0"],
40
40
  zip_safe=False,
41
41
  # # Do not support dialects now.
42
42
  entry_points={
@@ -1,6 +1,6 @@
1
1
  from sqlalchemy.dialects import registry as _registry
2
2
 
3
- __version__ = "1.1.0"
3
+ __version__ = "1.4.0"
4
4
 
5
5
  _registry.register(
6
6
  "risingwave.psycopg2",
@@ -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
- sql = "SELECT viewname FROM pg_views"
74
- if schema is not None:
75
- sql += f" WHERE schemaname = '{schema or self.default_schema_name}'"
76
- else:
77
- sql += " WHERE schemaname <> 'rw_catalog' and schemaname <> 'pg_catalog' and schemaname <> 'information_schema'"
78
- views = conn.execute(text(sql))
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
- return [view.viewname for view in views] + [source.source_name for source in sources]
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
- {"table_schema": schema or self.default_schema_name, "table_name": table_name},
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
- query = (
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
- % schema_where_clause
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
- raise []
232
+ return []
214
233
 
215
234
  def get_foreign_keys(
216
- self, connection, table_name, schema=None, postgresql_ignore_search_path=False, **kw
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
 
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: sqlalchemy-risingwave
3
- Version: 1.1.0
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,>=2.0
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 three_columns (id1 INT, id2 INT, id3 INT)"))
30
- conn.execute(text("CREATE INDEX three_columns_idx ON three_columns(id2) INCLUDE(id1)"))
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("three_columns")
33
+ indexes = insp.get_indexes("t")
34
34
 
35
35
  assert len(indexes) == 1
36
- assert indexes[0]["name"] == "three_columns_idx"
37
- # pg will return `"id2", "id1"`
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 three_columns"))
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 three_columns (id1 INT, id2 INT, id3 INT)"))
45
- conn.execute(text("CREATE VIEW three_view AS SELECT * from three_columns"))
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 views[0] == "three_view"
64
+ assert "mv" in views
52
65
 
53
- conn.execute(text("DROP VIEW three_view"))
54
- conn.execute(text("DROP TABLE three_columns"))
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