From c24caba0424541ce11b273cf725ee3c94bff86b2 Mon Sep 17 00:00:00 2001 From: danilo neves cruz Date: Mon, 23 Sep 2024 23:43:15 -0300 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20schema:=20support=20drizzle=20intro?= =?UTF-8?q?spection?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/schema/pg-catalog/index.ts | 6 +++ src/schema/pg-catalog/pg-enum-list.ts | 28 ++++++++++++ src/schema/pg-catalog/pg-sequences-list.ts | 35 +++++++++++++++ src/schema/pg-catalog/pg-user-list.ts | 34 ++++++++++++++ src/tests/drizzle-requests.spec.ts | 52 ++++++++++++++++++++++ 5 files changed, 155 insertions(+) create mode 100644 src/schema/pg-catalog/pg-enum-list.ts create mode 100644 src/schema/pg-catalog/pg-sequences-list.ts create mode 100644 src/schema/pg-catalog/pg-user-list.ts create mode 100644 src/tests/drizzle-requests.spec.ts diff --git a/src/schema/pg-catalog/index.ts b/src/schema/pg-catalog/index.ts index c996f9a..0c0bd69 100644 --- a/src/schema/pg-catalog/index.ts +++ b/src/schema/pg-catalog/index.ts @@ -3,9 +3,12 @@ import { DataType, FunctionDefinition, _IDb, _ISchema } from '../../interfaces-p import { PgAttributeTable } from './pg-attribute-list'; import { PgClassListTable } from './pg-class'; import { PgConstraintTable } from './pg-constraints-list'; +import { PgEnumTable } from './pg-enum-list'; import { PgIndexTable } from './pg-index-list'; import { PgNamespaceTable } from './pg-namespace-list'; +import { PgSequencesTable } from './pg-sequences-list'; import { PgTypeTable } from './pg-type-list'; +import { PgUserTable } from './pg-user-list'; import { allFunctions } from '../../functions'; import { PgRange } from './pg-range'; import { sqlSubstring } from '../../parser/expression-builder'; @@ -58,6 +61,9 @@ export function setupPgCatalog(db: _IDb) { new PgProc(catalog).register(); new PgDatabaseTable(catalog).register(); new PgStatioUserTables(catalog).register(); + new PgEnumTable(catalog).register(); + new PgSequencesTable(catalog).register(); + new PgUserTable(catalog).register(); // this is an ugly hack... diff --git a/src/schema/pg-catalog/pg-enum-list.ts b/src/schema/pg-catalog/pg-enum-list.ts new file mode 100644 index 0000000..a9135a7 --- /dev/null +++ b/src/schema/pg-catalog/pg-enum-list.ts @@ -0,0 +1,28 @@ +import { _ITable, _ISelection, _IIndex, _IDb, _ISchema } from '../../interfaces-private'; +import { Schema } from '../../interfaces'; +import { Types } from '../../datatypes'; +import { ReadOnlyTable } from '../readonly-table'; + +export class PgEnumTable extends ReadOnlyTable implements _ITable { + + _schema: Schema = { + name: 'pg_enum', + fields: [ + { name: 'oid', type: Types.integer } + , { name: 'enumtypid', type: Types.integer } + , { name: 'enumsortorder', type: Types.integer } + , { name: 'enumlabel', type: Types.text() } + ] + }; + + entropy(): number { + return 0; + } + + *enumerate() { + } + + hasItem(value: any): boolean { + return false; + } +} diff --git a/src/schema/pg-catalog/pg-sequences-list.ts b/src/schema/pg-catalog/pg-sequences-list.ts new file mode 100644 index 0000000..075c88f --- /dev/null +++ b/src/schema/pg-catalog/pg-sequences-list.ts @@ -0,0 +1,35 @@ +import { _ITable, _ISelection, _IIndex, _IDb, _ISchema } from '../../interfaces-private'; +import { Schema } from '../../interfaces'; +import { Types } from '../../datatypes'; +import { ReadOnlyTable } from '../readonly-table'; + +export class PgSequencesTable extends ReadOnlyTable implements _ITable { + + _schema: Schema = { + name: 'pg_sequences', + fields: [ + { name: 'schemaname', type: Types.text() } + , { name: 'sequencename', type: Types.text() } + , { name: 'sequenceowner', type: Types.integer } + , { name: 'data_type', type: Types.text() } + , { name: 'start_value', type: Types.integer } + , { name: 'min_value', type: Types.integer } + , { name: 'max_value', type: Types.integer } + , { name: 'increment_by', type: Types.integer } + , { name: 'cycle', type: Types.bool } + , { name: 'cache_size', type: Types.integer } + , { name: 'last_value', type: Types.integer } + ] + }; + + entropy(): number { + return 0; + } + + *enumerate() { + } + + hasItem(value: any): boolean { + return false; + } +} diff --git a/src/schema/pg-catalog/pg-user-list.ts b/src/schema/pg-catalog/pg-user-list.ts new file mode 100644 index 0000000..78a7367 --- /dev/null +++ b/src/schema/pg-catalog/pg-user-list.ts @@ -0,0 +1,34 @@ +import { _ITable, _ISelection, _IIndex, _IDb, _ISchema } from '../../interfaces-private'; +import { Schema } from '../../interfaces'; +import { Types } from '../../datatypes'; +import { ReadOnlyTable } from '../readonly-table'; + +export class PgUserTable extends ReadOnlyTable implements _ITable { + + _schema: Schema = { + name: 'pg_user', + fields: [ + { name: 'usename', type: Types.text() } + , { name: 'usesysid', type: Types.integer } + , { name: 'usecreatedb', type: Types.bool } + , { name: 'usesuper', type: Types.bool } + , { name: 'usecatupd', type: Types.bool } + , { name: 'userepl', type: Types.bool } + , { name: 'usebypassrls', type: Types.bool } + , { name: 'passwd', type: Types.text() } + , { name: 'valuntil', type: Types.timestamptz() } + , { name: 'useconfig', type: Types.jsonb } + ] + }; + + entropy(): number { + return 0; + } + + *enumerate() { + } + + hasItem(value: any): boolean { + return false; + } +} diff --git a/src/tests/drizzle-requests.spec.ts b/src/tests/drizzle-requests.spec.ts new file mode 100644 index 0000000..3af8fe7 --- /dev/null +++ b/src/tests/drizzle-requests.spec.ts @@ -0,0 +1,52 @@ +import { describe, it, beforeEach, expect } from 'bun:test'; + +import { newDb } from '../db'; + +import { _IDb } from '../interfaces-private'; + +describe('drizzle - requests', () => { + + let db: _IDb; + let many: (str: string) => any[]; + let none: (str: string) => void; + beforeEach(() => { + db = newDb({ + autoCreateForeignKeyIndices: true, + }) as _IDb; + many = db.public.many.bind(db.public); + none = db.public.none.bind(db.public); + }); + + function simpleDb() { + db.public.none('create table data(id text primary key, data jsonb, num integer, var varchar(10))'); + } + + it('can select pg_user', () => { + simpleDb(); + many(`select s.nspname as table_schema + from pg_catalog.pg_namespace s + join pg_catalog.pg_user u on u.usesysid = s.nspowner + where nspname not in ('information_schema', 'pg_catalog', 'public') + and nspname not like 'pg_toast%' + and nspname not like 'pg_temp_%' + order by table_schema`); + }); + + it('can select pg_sequences', () => { + simpleDb(); + many(`select schemaname, sequencename, start_value, min_value, max_value, increment_by, cycle, cache_size from pg_sequences as seq WHERE schemaname = 'public'`); + }); + + it('can select pg_enum', () => { + simpleDb(); + many(`select n.nspname as enum_schema, + t.typname as enum_name, + e.enumlabel as enum_value, + e.enumsortorder as sort_order + from pg_type t + join pg_enum e on t.oid = e.enumtypid + join pg_catalog.pg_namespace n ON n.oid = t.typnamespace + where n.nspname = 'public' + order by enum_schema, enum_name, sort_order`); + }); +});