From 98ab1444a57c2d42b58b1706a74b60f02315cb04 Mon Sep 17 00:00:00 2001 From: Chris Rudd Date: Tue, 7 Oct 2025 16:19:35 -0500 Subject: [PATCH 1/3] Fix README.md test failure --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d30ecb6..91e6090 100644 --- a/README.md +++ b/README.md @@ -97,12 +97,12 @@ CREATE TYPE "orders_status" AS ENUM ( 'created', 'running', 'done', - 'failure', + 'failure' ); CREATE TYPE "product status" AS ENUM ( 'Out of Stock', - 'In Stock', + 'In Stock' ); CREATE TABLE "orders" ( From 976f60a9d5e6421b9cf0de68855357c5b86fe93a Mon Sep 17 00:00:00 2001 From: Chris Rudd Date: Tue, 7 Oct 2025 16:21:49 -0500 Subject: [PATCH 2/3] fix: sql generation of varchar columns with defaults --- pydbml/renderer/sql/default/column.py | 16 +++++++++----- test/conftest.py | 22 +++++++++++++++++++ test/test_renderer/test_dbml/test_column.py | 10 +++++++++ .../test_sql/test_default/test_column.py | 9 ++++++++ 4 files changed, 52 insertions(+), 5 deletions(-) diff --git a/pydbml/renderer/sql/default/column.py b/pydbml/renderer/sql/default/column.py index d04b061..4211ae8 100644 --- a/pydbml/renderer/sql/default/column.py +++ b/pydbml/renderer/sql/default/column.py @@ -1,8 +1,18 @@ +from typing import Union + from pydbml.classes import Column, Enum, Expression from pydbml.renderer.sql.default.renderer import DefaultSQLRenderer from .utils import comment_to_sql from .enum import get_full_name_for_sql as get_full_name_for_sql_enum +def default_to_str(val: Union[Expression, str, int, float, bool]) -> str: + if isinstance(val, Expression): + return DefaultSQLRenderer.render(val) + elif isinstance(val, str): + val = val.replace("'", "''") + return f"'{val}'" + else: + return str(val) @DefaultSQLRenderer.renderer_for(Column) def render_column(model: Column) -> str: @@ -28,11 +38,7 @@ def render_column(model: Column) -> str: if model.not_null: components.append('NOT NULL') if model.default is not None: - if isinstance(model.default, Expression): - default = DefaultSQLRenderer.render(model.default) - else: - default = model.default # type: ignore - components.append(f'DEFAULT {default}') + components.append(f'DEFAULT {default_to_str(model.default)}') result = comment_to_sql(model.comment) if model.comment else '' result += ' '.join(components) diff --git a/test/conftest.py b/test/conftest.py index 8ef74aa..2de957b 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -65,6 +65,28 @@ def complex_column_with_table(db: Database, table1: Table, complex_column: Colum db.add(table1) return complex_column +@pytest.fixture +def string_column() -> Column: + return Column( + name='name', + type='varchar(255)', + pk=False, + autoinc=False, + unique=True, + not_null=True, + default='value\'s', + comment='This is a defaulted string column', + note=Note('This is a note for the column'), + properties={'foo': 'bar', 'baz': "qux\nqux"} + ) + + +@pytest.fixture +def string_column_with_table(db: Database, table1: Table, string_column: Column) -> Column: + table1.add_column(string_column) + db.add(table1) + return string_column + @pytest.fixture def table1() -> Table: diff --git a/test/test_renderer/test_dbml/test_column.py b/test/test_renderer/test_dbml/test_column.py index b2cf3b8..8261a8c 100644 --- a/test/test_renderer/test_dbml/test_column.py +++ b/test/test_renderer/test_dbml/test_column.py @@ -137,3 +137,13 @@ def test_complex(complex_column_with_table: Column) -> None: "a note for the column']" ) assert render_column(complex_column_with_table) == expected + + @staticmethod + def test_string(string_column_with_table: Column) -> None: + expected = ( + "// This is a defaulted string column\n" + '"name" varchar(255) [default: \'value\\\'s\', unique, not null, note: \'This is ' + "a note for the column']" + ) + assert render_column(string_column_with_table) == expected + diff --git a/test/test_renderer/test_sql/test_default/test_column.py b/test/test_renderer/test_sql/test_default/test_column.py index 05f9c20..85d5dfb 100644 --- a/test/test_renderer/test_sql/test_default/test_column.py +++ b/test/test_renderer/test_sql/test_default/test_column.py @@ -17,3 +17,12 @@ def test_complex(complex_column: Column) -> None: "0" ) assert render_column(complex_column) == expected + + @staticmethod + def test_string(string_column: Column) -> None: + expected = ( + "-- This is a defaulted string column\n" + '"name" varchar(255) UNIQUE NOT NULL DEFAULT ' + "'value''s'" + ) + assert render_column(string_column) == expected From 48ffac544ea2ed1b7aaf9748ed6ec5713166606f Mon Sep 17 00:00:00 2001 From: Chris Rudd Date: Tue, 7 Oct 2025 16:31:22 -0500 Subject: [PATCH 3/3] =?UTF-8?q?fix=20=20=E2=80=98falsey=E2=80=99=20default?= =?UTF-8?q?=20value=20generation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pydbml/renderer/dbml/default/column.py | 2 +- test/conftest.py | 22 +++++++++++++++++++ test/test_data/integration1.dbml | 2 +- test/test_renderer/test_dbml/test_column.py | 10 ++++++++- .../test_sql/test_default/test_column.py | 9 ++++++++ 5 files changed, 42 insertions(+), 3 deletions(-) diff --git a/pydbml/renderer/dbml/default/column.py b/pydbml/renderer/dbml/default/column.py index 3ec037a..bac43a6 100644 --- a/pydbml/renderer/dbml/default/column.py +++ b/pydbml/renderer/dbml/default/column.py @@ -24,7 +24,7 @@ def render_options(model: Column) -> str: options.append('pk') if model.autoinc: options.append('increment') - if model.default: + if model.default is not None: options.append(f'default: {default_to_str(model.default)}') if model.unique: options.append('unique') diff --git a/test/conftest.py b/test/conftest.py index 2de957b..3f596a1 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -87,6 +87,28 @@ def string_column_with_table(db: Database, table1: Table, string_column: Column) db.add(table1) return string_column +@pytest.fixture +def boolean_column() -> Column: + return Column( + name='enabled', + type='boolean', + pk=False, + autoinc=False, + unique=False, + not_null=True, + default=False, + comment='This is a defaulted boolean column', + note=Note('This is a note for the column'), + properties={'foo': 'bar', 'baz': "qux\nqux"} + ) + + +@pytest.fixture +def boolean_column_with_table(db: Database, table1: Table, boolean_column: Column) -> Column: + table1.add_column(boolean_column) + db.add(table1) + return boolean_column + @pytest.fixture def table1() -> Table: diff --git a/test/test_data/integration1.dbml b/test/test_data/integration1.dbml index b24c9d7..5838edf 100644 --- a/test/test_data/integration1.dbml +++ b/test/test_data/integration1.dbml @@ -12,7 +12,7 @@ Enum "level" { Table "Employees" as "emp" { "id" integer [pk, increment] "name" varchar [note: 'Full employee name'] - "age" number + "age" number [default: 0] "level" level "favorite_book_id" integer } diff --git a/test/test_renderer/test_dbml/test_column.py b/test/test_renderer/test_dbml/test_column.py index 8261a8c..33a9e70 100644 --- a/test/test_renderer/test_dbml/test_column.py +++ b/test/test_renderer/test_dbml/test_column.py @@ -133,7 +133,7 @@ def test_enum(simple_column_with_table: Column, enum1: Enum) -> None: def test_complex(complex_column_with_table: Column) -> None: expected = ( "// This is a counter column\n" - '"counter" "product status" [pk, increment, unique, not null, note: \'This is ' + '"counter" "product status" [pk, increment, default: 0, unique, not null, note: \'This is ' "a note for the column']" ) assert render_column(complex_column_with_table) == expected @@ -147,3 +147,11 @@ def test_string(string_column_with_table: Column) -> None: ) assert render_column(string_column_with_table) == expected + @staticmethod + def test_boolean(boolean_column_with_table: Column) -> None: + expected = ( + "// This is a defaulted boolean column\n" + '"enabled" boolean [default: False, not null, note: \'This is ' + "a note for the column']" + ) + assert render_column(boolean_column_with_table) == expected diff --git a/test/test_renderer/test_sql/test_default/test_column.py b/test/test_renderer/test_sql/test_default/test_column.py index 85d5dfb..f8a49ee 100644 --- a/test/test_renderer/test_sql/test_default/test_column.py +++ b/test/test_renderer/test_sql/test_default/test_column.py @@ -26,3 +26,12 @@ def test_string(string_column: Column) -> None: "'value''s'" ) assert render_column(string_column) == expected + + @staticmethod + def test_string(boolean_column: Column) -> None: + expected = ( + "-- This is a defaulted boolean column\n" + '"enabled" boolean NOT NULL DEFAULT ' + "False" + ) + assert render_column(boolean_column) == expected