harlequin-postgres 1.2.0__tar.gz → 1.2.2__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.
- {harlequin_postgres-1.2.0 → harlequin_postgres-1.2.2}/PKG-INFO +1 -1
- {harlequin_postgres-1.2.0 → harlequin_postgres-1.2.2}/pyproject.toml +1 -1
- {harlequin_postgres-1.2.0 → harlequin_postgres-1.2.2}/src/harlequin_postgres/adapter.py +70 -16
- {harlequin_postgres-1.2.0 → harlequin_postgres-1.2.2}/src/harlequin_postgres/catalog.py +40 -0
- {harlequin_postgres-1.2.0 → harlequin_postgres-1.2.2}/LICENSE +0 -0
- {harlequin_postgres-1.2.0 → harlequin_postgres-1.2.2}/README.md +0 -0
- {harlequin_postgres-1.2.0 → harlequin_postgres-1.2.2}/src/harlequin_postgres/__init__.py +0 -0
- {harlequin_postgres-1.2.0 → harlequin_postgres-1.2.2}/src/harlequin_postgres/cli_options.py +0 -0
- {harlequin_postgres-1.2.0 → harlequin_postgres-1.2.2}/src/harlequin_postgres/completions.py +0 -0
- {harlequin_postgres-1.2.0 → harlequin_postgres-1.2.2}/src/harlequin_postgres/interactions.py +0 -0
- {harlequin_postgres-1.2.0 → harlequin_postgres-1.2.2}/src/harlequin_postgres/keywords.tsv +0 -0
- {harlequin_postgres-1.2.0 → harlequin_postgres-1.2.2}/src/harlequin_postgres/loaders.py +0 -0
- {harlequin_postgres-1.2.0 → harlequin_postgres-1.2.2}/src/harlequin_postgres/py.typed +0 -0
|
@@ -136,10 +136,19 @@ class HarlequinPostgresConnection(HarlequinConnection):
|
|
|
136
136
|
cur.close()
|
|
137
137
|
return None
|
|
138
138
|
except Exception as e:
|
|
139
|
-
|
|
140
|
-
|
|
139
|
+
msg_suffix = ""
|
|
140
|
+
try:
|
|
141
|
+
cur.close()
|
|
142
|
+
self.rollback()
|
|
143
|
+
except Exception:
|
|
144
|
+
# likely connection is closed; error messages
|
|
145
|
+
# can be cryptic, so help the user.
|
|
146
|
+
msg_suffix = (
|
|
147
|
+
"\n\nYou may need to restart Harlequin to reconnect to the "
|
|
148
|
+
"database."
|
|
149
|
+
)
|
|
141
150
|
raise HarlequinQueryError(
|
|
142
|
-
msg=
|
|
151
|
+
msg=f"{e}{msg_suffix}",
|
|
143
152
|
title="Harlequin encountered an error while executing your query.",
|
|
144
153
|
) from e
|
|
145
154
|
else:
|
|
@@ -217,15 +226,16 @@ class HarlequinPostgresConnection(HarlequinConnection):
|
|
|
217
226
|
conn: Connection = self.pool.getconn()
|
|
218
227
|
with conn.cursor() as cur:
|
|
219
228
|
cur.execute(
|
|
220
|
-
|
|
229
|
+
"""
|
|
221
230
|
select schema_name
|
|
222
231
|
from information_schema.schemata
|
|
223
232
|
where
|
|
224
|
-
catalog_name =
|
|
233
|
+
catalog_name = %s
|
|
225
234
|
and schema_name != 'information_schema'
|
|
226
|
-
and schema_name not like 'pg_
|
|
235
|
+
and schema_name not like 'pg_%%'
|
|
227
236
|
order by schema_name asc
|
|
228
|
-
;"""
|
|
237
|
+
;""",
|
|
238
|
+
(dbname,),
|
|
229
239
|
)
|
|
230
240
|
results: list[tuple[str]] = cur.fetchall()
|
|
231
241
|
self.pool.putconn(conn)
|
|
@@ -235,34 +245,78 @@ class HarlequinPostgresConnection(HarlequinConnection):
|
|
|
235
245
|
conn: Connection = self.pool.getconn()
|
|
236
246
|
with conn.cursor() as cur:
|
|
237
247
|
cur.execute(
|
|
238
|
-
|
|
248
|
+
"""
|
|
239
249
|
select table_name, table_type
|
|
240
250
|
from information_schema.tables
|
|
241
251
|
where
|
|
242
|
-
table_catalog =
|
|
243
|
-
and table_schema =
|
|
252
|
+
table_catalog = %s
|
|
253
|
+
and table_schema = %s
|
|
244
254
|
order by table_name asc
|
|
245
|
-
;"""
|
|
255
|
+
;""",
|
|
256
|
+
(dbname, schema),
|
|
246
257
|
)
|
|
247
258
|
results: list[tuple[str, str]] = cur.fetchall()
|
|
248
259
|
self.pool.putconn(conn)
|
|
249
260
|
return results
|
|
250
261
|
|
|
262
|
+
# only works for the currently-connected db
|
|
263
|
+
def _get_mvs(self, schema: str) -> list[tuple[str]]:
|
|
264
|
+
conn: Connection = self.pool.getconn()
|
|
265
|
+
with conn.cursor() as cur:
|
|
266
|
+
cur.execute(
|
|
267
|
+
"""
|
|
268
|
+
select matviewname
|
|
269
|
+
from pg_matviews
|
|
270
|
+
where
|
|
271
|
+
schemaname = %s
|
|
272
|
+
order by matviewname asc
|
|
273
|
+
;""",
|
|
274
|
+
(schema,),
|
|
275
|
+
)
|
|
276
|
+
results: list[tuple[str]] = cur.fetchall()
|
|
277
|
+
self.pool.putconn(conn)
|
|
278
|
+
return results
|
|
279
|
+
|
|
251
280
|
def _get_columns(
|
|
252
281
|
self, dbname: str, schema: str, relation: str
|
|
253
282
|
) -> list[tuple[str, str]]:
|
|
254
283
|
conn: Connection = self.pool.getconn()
|
|
255
284
|
with conn.cursor() as cur:
|
|
256
285
|
cur.execute(
|
|
257
|
-
|
|
286
|
+
"""
|
|
258
287
|
select column_name, data_type
|
|
259
288
|
from information_schema.columns
|
|
260
289
|
where
|
|
261
|
-
table_catalog =
|
|
262
|
-
and table_schema =
|
|
263
|
-
and table_name =
|
|
290
|
+
table_catalog = %s
|
|
291
|
+
and table_schema = %s
|
|
292
|
+
and table_name = %s
|
|
264
293
|
order by ordinal_position asc
|
|
265
|
-
;"""
|
|
294
|
+
;""",
|
|
295
|
+
(dbname, schema, relation),
|
|
296
|
+
)
|
|
297
|
+
results: list[tuple[str, str]] = cur.fetchall()
|
|
298
|
+
self.pool.putconn(conn)
|
|
299
|
+
return results
|
|
300
|
+
|
|
301
|
+
def _get_mv_cols(self, schema: str, mv: str) -> list[tuple[str, str]]:
|
|
302
|
+
conn: Connection = self.pool.getconn()
|
|
303
|
+
with conn.cursor() as cur:
|
|
304
|
+
cur.execute(
|
|
305
|
+
"""
|
|
306
|
+
select
|
|
307
|
+
a.attname,
|
|
308
|
+
pg_catalog.format_type(a.atttypid, a.atttypmod)
|
|
309
|
+
from pg_attribute a
|
|
310
|
+
join pg_class t on a.attrelid = t.oid
|
|
311
|
+
join pg_namespace s on t.relnamespace = s.oid
|
|
312
|
+
where
|
|
313
|
+
a.attnum > 0
|
|
314
|
+
and not a.attisdropped
|
|
315
|
+
and s.nspname = %s
|
|
316
|
+
and t.relname = %s
|
|
317
|
+
order by a.attnum;
|
|
318
|
+
;""",
|
|
319
|
+
(schema, mv),
|
|
266
320
|
)
|
|
267
321
|
results: list[tuple[str, str]] = cur.fetchall()
|
|
268
322
|
self.pool.putconn(conn)
|
|
@@ -166,6 +166,38 @@ class ForeignCatalogItem(TableCatalogItem):
|
|
|
166
166
|
)
|
|
167
167
|
|
|
168
168
|
|
|
169
|
+
class MaterializedViewCatalogItem(RelationCatalogItem):
|
|
170
|
+
@classmethod
|
|
171
|
+
def from_parent(
|
|
172
|
+
cls,
|
|
173
|
+
parent: "SchemaCatalogItem",
|
|
174
|
+
label: str,
|
|
175
|
+
) -> "MaterializedViewCatalogItem":
|
|
176
|
+
relation_query_name = f'"{parent.label}"."{label}"'
|
|
177
|
+
relation_qualified_identifier = f'{parent.qualified_identifier}."{label}"'
|
|
178
|
+
return cls(
|
|
179
|
+
qualified_identifier=relation_qualified_identifier,
|
|
180
|
+
query_name=relation_query_name,
|
|
181
|
+
label=label,
|
|
182
|
+
type_label="mv",
|
|
183
|
+
connection=parent.connection,
|
|
184
|
+
parent=parent,
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
def fetch_children(self) -> list[ColumnCatalogItem]:
|
|
188
|
+
if self.parent is None or self.parent.parent is None or self.connection is None:
|
|
189
|
+
return []
|
|
190
|
+
result = self.connection._get_mv_cols(self.parent.label, self.label)
|
|
191
|
+
return [
|
|
192
|
+
ColumnCatalogItem.from_parent(
|
|
193
|
+
parent=self,
|
|
194
|
+
label=column_name,
|
|
195
|
+
type_label=self.connection._short_column_type(column_type),
|
|
196
|
+
)
|
|
197
|
+
for column_name, column_type in result
|
|
198
|
+
]
|
|
199
|
+
|
|
200
|
+
|
|
169
201
|
@dataclass
|
|
170
202
|
class SchemaCatalogItem(InteractiveCatalogItem["HarlequinPostgresConnection"]):
|
|
171
203
|
INTERACTIONS = [
|
|
@@ -227,6 +259,14 @@ class SchemaCatalogItem(InteractiveCatalogItem["HarlequinPostgresConnection"]):
|
|
|
227
259
|
)
|
|
228
260
|
)
|
|
229
261
|
|
|
262
|
+
for (mv_label,) in self.connection._get_mvs(self.label):
|
|
263
|
+
children.append(
|
|
264
|
+
MaterializedViewCatalogItem.from_parent(
|
|
265
|
+
parent=self,
|
|
266
|
+
label=mv_label,
|
|
267
|
+
)
|
|
268
|
+
)
|
|
269
|
+
|
|
230
270
|
return children
|
|
231
271
|
|
|
232
272
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{harlequin_postgres-1.2.0 → harlequin_postgres-1.2.2}/src/harlequin_postgres/interactions.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|