diff --git a/src/sqlacodegen/cli.py b/src/sqlacodegen/cli.py index ce18d7a..8e39b80 100644 --- a/src/sqlacodegen/cli.py +++ b/src/sqlacodegen/cli.py @@ -32,6 +32,7 @@ parse_policy_row, parse_publication_row, parse_trigger_row, + parse_sequence_row, ) from sqlacodegen.seed_export import export_pgdata_py @@ -253,6 +254,14 @@ class ExportDict(TypedDict, total=False): "parse_row_func": parse_publication_row, "file": "pg_publications.py", }, + { + "title": "Sequences", + "entities_varname": "all_sequences", + "template": "ALEMBIC_SEQUENCE_TEMPLATE", + "statement": "ALEMBIC_STANDALONE_SEQUENCE_STATEMENT", + "parse_row_func": parse_sequence_row, + "file": "pg_sequence.py", + }, ] # ----------- Export-Loop ------------ @@ -283,8 +292,9 @@ class ExportDict(TypedDict, total=False): orm_views, pg_alembic = gen_func(generator_views) # type: ignore[operator] with open(dest_orm_path, "w", encoding="utf-8") as f: f.write(orm_views) - with open(dest_pg_path, "w", encoding="utf-8") as f: - f.write("\n".join(pg_alembic)) + if pg_alembic: + with open(dest_pg_path, "w", encoding="utf-8") as f: + f.write("\n".join(pg_alembic)) print(f"{title} geschrieben nach: {dest_orm_path.as_posix()}") else: generator_views = generator_class(metadata_views, engine, options) diff --git a/src/sqlacodegen/risclog_generators.py b/src/sqlacodegen/risclog_generators.py index 2d758cb..d394b32 100644 --- a/src/sqlacodegen/risclog_generators.py +++ b/src/sqlacodegen/risclog_generators.py @@ -239,34 +239,47 @@ class {classname}(PortalObject): # type: ignore[misc] ORDER BY extname; """ -ALEMBIC_SEQUENCE_STATEMENT = """ +ALEMBIC_STANDALONE_SEQUENCE_STATEMENT = """ +WITH seqs AS ( + SELECT c.oid AS seq_oid, + n.nspname AS schema, + c.relname AS sequence_name + FROM pg_class c + JOIN pg_namespace n ON n.oid = c.relnamespace + WHERE c.relkind = 'S' + AND n.nspname NOT IN ('pg_catalog','information_schema') + AND n.nspname NOT LIKE 'pg_toast%' + AND n.nspname NOT LIKE 'pg_temp_%' +) SELECT - s.sequence_schema AS schema, - s.sequence_name, - s.data_type, - s.start_value, - s.minimum_value, - s.maximum_value, - s.increment, - s.cycle_option AS cycle, - ps.cache_size -FROM information_schema.sequences s + s.schema, + s.sequence_name, + ps.data_type, + ps.start_value, + ps.min_value AS minimum_value, + ps.max_value AS maximum_value, + ps.increment_by AS increment, + ps.cycle, + ps.cache_size +FROM seqs s JOIN pg_catalog.pg_sequences ps - ON s.sequence_schema = ps.schemaname - AND s.sequence_name = ps.sequencename -JOIN pg_class t - ON t.relkind = 'r' AND t.relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = s.sequence_schema) -JOIN pg_attribute a - ON a.attrelid = t.oid -JOIN pg_attrdef d - ON d.adrelid = t.oid AND d.adnum = a.attnum -WHERE - s.sequence_schema NOT IN ('pg_catalog', 'information_schema') - AND pg_get_expr(d.adbin, d.adrelid) LIKE '%nextval(%' || s.sequence_name || '%' -ORDER BY s.sequence_schema, s.sequence_name; + ON ps.schemaname = s.schema + AND ps.sequencename = s.sequence_name +LEFT JOIN pg_depend owned + ON owned.classid = 'pg_class'::regclass + AND owned.objid = s.seq_oid + AND owned.deptype IN ('a','i') -- serial/identity ownership +LEFT JOIN pg_depend used + ON used.refclassid = 'pg_class'::regclass + AND used.refobjid = s.seq_oid + AND used.classid = 'pg_attrdef'::regclass -- used in a column DEFAULT +WHERE owned.objid IS NULL + AND used.objid IS NULL +ORDER BY s.schema, s.sequence_name; """ + def parse_publication_row( row: dict[str, Any], template_def: str,