Skip to content

Commit 9c6d374

Browse files
authored
Add client tests for dbeaver introspection queries (#266)
* Add initial dbt test. * Fix some runner issues, rename some queries to avoi confusion. * Add stub flag for queries that return something, rather than nothing at all. * Bump jdbc to avoid security warning. * Added the tests that debeaver uses to introspect into postgres, based on the cockroachdb work.
1 parent 173c25d commit 9c6d374

File tree

2 files changed

+252
-2
lines changed

2 files changed

+252
-2
lines changed

scripts/client-compat/CLAUDE.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,7 @@ scripts/client-compat/
2525
│ ├── tokio-postgres/
2626
│ ├── node-postgres/
2727
│ ├── sqlalchemy/
28-
│ ├── dbt/
29-
│ └── harlequin/
28+
│ └── dbt/
3029
└── results/ # output volume (.gitignored)
3130
```
3231

@@ -190,8 +189,17 @@ Duckgres auto-generates a self-signed cert. Clients must accept it:
190189
Group related tests under a suite name. Common conventions:
191190
- `connection` — TLS, auth, server version, driver info
192191
- `ddl_dml` / `core_ddl_dml` — CREATE, INSERT, UPDATE, DELETE, DROP
192+
- `dbeaver_introspection` — DBeaver CE metadata queries (see below)
193193
- Library-specific features get their own suite (`batch`, `copy`, `orm`, `prepared`, etc.)
194194
195+
### DBeaver introspection suite
196+
197+
DBeaver CE cannot run headlessly in Docker (GTK3 SWT bug freezes the event loop under Xvfb).
198+
Instead, the `dbeaver_introspection` suite in `queries.yaml` contains the exact catalog queries
199+
DBeaver fires on connect, sourced from [cockroachdb/cockroach#28309](https://github.com/cockroachdb/cockroach/issues/28309).
200+
These queries are executed by every client, testing the same catalog surface a real DBeaver
201+
connection would exercise.
202+
195203
## Results Database
196204
197205
Exported to `results/results_<timestamp>.duckdb` with:

scripts/client-compat/queries.yaml

Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,3 +340,245 @@
340340
- suite: catalog_stubs
341341
name: pg_statio_user_tables
342342
sql: SELECT * FROM pg_statio_user_tables LIMIT 5
343+
344+
# --- DBeaver introspection queries ---
345+
# Queries that DBeaver CE fires on connect for metadata discovery.
346+
# Sourced from https://github.com/cockroachdb/cockroach/issues/28309
347+
# which catalogued every introspection query DBeaver sends.
348+
#
349+
# These test the same catalog surface that a real DBeaver connection
350+
# would exercise. We cannot run DBeaver headlessly (GTK3 SWT bug
351+
# freezes the event loop under Xvfb) so we test the queries directly.
352+
353+
# Database list
354+
- suite: dbeaver_introspection
355+
name: database_list
356+
stub: true
357+
sql: SELECT db.datname FROM pg_catalog.pg_database AS db WHERE datallowconn
358+
359+
# Role list
360+
- suite: dbeaver_introspection
361+
name: role_list
362+
stub: true
363+
sql: SELECT a.oid, a.* FROM pg_catalog.pg_roles AS a
364+
365+
# Access methods
366+
- suite: dbeaver_introspection
367+
name: pg_am
368+
stub: true
369+
sql: SELECT am.oid, am.* FROM pg_catalog.pg_am AS am
370+
371+
# Collations
372+
- suite: dbeaver_introspection
373+
name: pg_collation
374+
stub: true
375+
sql: SELECT c.oid, c.* FROM pg_catalog.pg_collation AS c
376+
377+
# Tablespaces
378+
- suite: dbeaver_introspection
379+
name: pg_tablespace
380+
stub: true
381+
sql: SELECT t.oid, t.* FROM pg_catalog.pg_tablespace AS t
382+
383+
# Schemas with descriptions
384+
- suite: dbeaver_introspection
385+
name: schemas_with_desc
386+
stub: true
387+
sql: >-
388+
SELECT n.oid, n.*, d.description
389+
FROM pg_catalog.pg_namespace AS n
390+
LEFT JOIN pg_catalog.pg_description AS d ON d.objoid = n.oid
391+
392+
# Sequences
393+
- suite: dbeaver_introspection
394+
name: pg_sequences
395+
stub: true
396+
sql: SELECT * FROM pg_catalog.pg_sequences LIMIT 5
397+
398+
# Enums
399+
- suite: dbeaver_introspection
400+
name: pg_enum
401+
stub: true
402+
sql: SELECT e.enumlabel FROM pg_catalog.pg_enum AS e LIMIT 5
403+
404+
# Classes (tables/views) with descriptions — DBeaver's main catalog query
405+
- suite: dbeaver_introspection
406+
name: classes_with_desc
407+
stub: true
408+
sql: >-
409+
SELECT c.oid, c.relname, c.relkind, c.relnamespace, d.description
410+
FROM pg_catalog.pg_class AS c
411+
LEFT JOIN pg_catalog.pg_description AS d ON d.objoid = c.oid AND d.objsubid = 0
412+
WHERE c.relkind NOT IN ('i', 'c')
413+
LIMIT 20
414+
415+
# Attributes (columns) with defaults and descriptions
416+
- suite: dbeaver_introspection
417+
name: attributes_with_defaults
418+
sql: >-
419+
SELECT c.relname, a.attname, a.atttypid, a.attnum,
420+
pg_catalog.pg_get_expr(ad.adbin, ad.adrelid, true) AS def_value,
421+
dsc.description
422+
FROM pg_catalog.pg_attribute AS a
423+
INNER JOIN pg_catalog.pg_class AS c ON a.attrelid = c.oid
424+
LEFT JOIN pg_catalog.pg_attrdef AS ad ON a.attrelid = ad.adrelid AND a.attnum = ad.adnum
425+
LEFT JOIN pg_catalog.pg_description AS dsc ON c.oid = dsc.objoid AND a.attnum = dsc.objsubid
426+
WHERE a.attnum > 0 AND NOT a.attisdropped
427+
LIMIT 20
428+
429+
# Constraints with table names
430+
- suite: dbeaver_introspection
431+
name: constraints_with_tables
432+
stub: true
433+
sql: >-
434+
SELECT c.oid, c.conname, c.contype, t.relname AS tabrelname,
435+
rt.relnamespace AS refnamespace, d.description
436+
FROM pg_catalog.pg_constraint AS c
437+
INNER JOIN pg_catalog.pg_class AS t ON t.oid = c.conrelid
438+
LEFT JOIN pg_catalog.pg_class AS rt ON rt.oid = c.confrelid
439+
LEFT JOIN pg_catalog.pg_description AS d ON d.objoid = c.oid AND d.objsubid = 0
440+
LIMIT 20
441+
442+
# Indexes with descriptions
443+
- suite: dbeaver_introspection
444+
name: indexes_with_desc
445+
stub: true
446+
sql: >-
447+
SELECT i.indexrelid, i.indrelid, i.indisunique, i.indisprimary,
448+
c.relname, tc.relname AS tabrelname, dsc.description
449+
FROM pg_catalog.pg_index AS i
450+
INNER JOIN pg_catalog.pg_class AS c ON c.oid = i.indexrelid
451+
INNER JOIN pg_catalog.pg_class AS tc ON tc.oid = i.indrelid
452+
LEFT JOIN pg_catalog.pg_description AS dsc ON i.indexrelid = dsc.objoid
453+
LIMIT 20
454+
455+
# Procedures (functions)
456+
- suite: dbeaver_introspection
457+
name: pg_proc
458+
sql: >-
459+
SELECT p.oid, p.proname, p.pronamespace, p.prorettype
460+
FROM pg_catalog.pg_proc AS p
461+
LIMIT 20
462+
463+
# Data types (filtered)
464+
- suite: dbeaver_introspection
465+
name: pg_type_filtered
466+
sql: >-
467+
SELECT t.oid, t.typname, t.typnamespace, t.typtype, t.typcategory
468+
FROM pg_catalog.pg_type AS t
469+
WHERE t.typcategory NOT IN ('A', 'C')
470+
LIMIT 20
471+
472+
# Inheritance
473+
- suite: dbeaver_introspection
474+
name: pg_inherits
475+
stub: true
476+
sql: >-
477+
SELECT i.*, c.relnamespace
478+
FROM pg_catalog.pg_inherits AS i, pg_catalog.pg_class AS c
479+
WHERE c.oid = i.inhparent
480+
LIMIT 5
481+
482+
# Activity
483+
- suite: dbeaver_introspection
484+
name: pg_stat_activity
485+
stub: true
486+
sql: SELECT sa.* FROM pg_catalog.pg_stat_activity AS sa LIMIT 5
487+
488+
# Object comments
489+
- suite: dbeaver_introspection
490+
name: object_comments
491+
stub: true
492+
sql: >-
493+
SELECT description
494+
FROM pg_catalog.pg_description
495+
JOIN pg_catalog.pg_class ON pg_description.objoid = pg_class.oid
496+
JOIN pg_catalog.pg_namespace ON pg_class.relnamespace = pg_namespace.oid
497+
LIMIT 5
498+
499+
# View definition function
500+
- suite: dbeaver_introspection
501+
name: pg_get_viewdef
502+
stub: true
503+
sql: SELECT pg_get_viewdef(0)
504+
505+
# View definition function (pretty-print overload)
506+
- suite: dbeaver_introspection
507+
name: pg_get_viewdef_pretty
508+
stub: true
509+
sql: SELECT pg_get_viewdef(0, true)
510+
511+
# --- Missing tables: DBeaver queries these but duckgres doesn't have them yet ---
512+
# These will fail until stubs are added to catalog.go.
513+
514+
# Role membership
515+
- suite: dbeaver_introspection
516+
name: pg_auth_members
517+
stub: true
518+
sql: SELECT * FROM pg_catalog.pg_auth_members LIMIT 5
519+
520+
# Operator classes
521+
- suite: dbeaver_introspection
522+
name: pg_opclass
523+
stub: true
524+
sql: SELECT oc.oid, oc.* FROM pg_catalog.pg_opclass AS oc LIMIT 5
525+
526+
# Encoding conversions
527+
- suite: dbeaver_introspection
528+
name: pg_conversion
529+
stub: true
530+
sql: SELECT * FROM pg_catalog.pg_conversion AS c LIMIT 5
531+
532+
# Procedural languages
533+
- suite: dbeaver_introspection
534+
name: pg_language
535+
stub: true
536+
sql: SELECT l.oid, l.* FROM pg_catalog.pg_language AS l
537+
538+
# Extensions
539+
- suite: dbeaver_introspection
540+
name: pg_extension
541+
stub: true
542+
sql: SELECT e.oid, e.* FROM pg_catalog.pg_extension AS e
543+
544+
# Foreign servers
545+
- suite: dbeaver_introspection
546+
name: pg_foreign_server
547+
stub: true
548+
sql: SELECT l.oid, l.* FROM pg_catalog.pg_foreign_server AS l
549+
550+
# Foreign data wrappers (with handler proc join)
551+
- suite: dbeaver_introspection
552+
name: pg_foreign_data_wrapper
553+
stub: true
554+
sql: >-
555+
SELECT l.oid, l.*, p.pronamespace AS handler_schema_id
556+
FROM pg_catalog.pg_foreign_data_wrapper AS l
557+
LEFT JOIN pg_catalog.pg_proc AS p ON p.oid = l.fdwhandler
558+
ORDER BY l.fdwname
559+
560+
# Foreign tables
561+
- suite: dbeaver_introspection
562+
name: pg_foreign_table
563+
stub: true
564+
sql: SELECT * FROM pg_catalog.pg_foreign_table LIMIT 5
565+
566+
# Triggers (with proc join)
567+
- suite: dbeaver_introspection
568+
name: pg_trigger
569+
stub: true
570+
sql: >-
571+
SELECT x.oid, x.*, p.pronamespace AS func_schema_id
572+
FROM pg_catalog.pg_trigger AS x
573+
LEFT JOIN pg_catalog.pg_proc AS p ON p.oid = x.tgfoid
574+
LIMIT 5
575+
576+
# Transaction locks
577+
- suite: dbeaver_introspection
578+
name: pg_locks
579+
stub: true
580+
sql: >-
581+
SELECT COALESCE(lock.locktype, '') AS locktype,
582+
lock.pid, lock.granted
583+
FROM pg_catalog.pg_locks AS lock
584+
LIMIT 5

0 commit comments

Comments
 (0)