Skip to content

Commit

Permalink
Fix miscellaneous issues with Microsoft SQL Server
Browse files Browse the repository at this point in the history
  • Loading branch information
hunyadi committed Sep 10, 2024
1 parent d72a9b2 commit 68ad831
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 40 deletions.
2 changes: 2 additions & 0 deletions pysqlsync/dialect/mssql/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ def open(self) -> BaseContext:
"PWD": self.params.password,
"TrustServerCertificate": "yes",
}
if self.params.database is not None:
params["DATABASE"] = self.params.database
conn_string = ";".join(
f"{key}={value}" for key, value in params.items() if value is not None
)
Expand Down
6 changes: 4 additions & 2 deletions pysqlsync/dialect/mssql/mutation.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import typing
from typing import Optional

from pysqlsync.formation.mutation import Mutator
Expand All @@ -8,7 +9,8 @@
Table,
join_or_none,
)
from pysqlsync.model.id_types import LocalId

from .object_types import MSSQLColumn


class MSSQLMutator(Mutator):
Expand Down Expand Up @@ -37,7 +39,7 @@ def mutate_table_stmt(self, source: Table, target: Table) -> Optional[str]:
if source_def == target_def:
continue

name = LocalId(f"df_{source_column.name.local_id}")
name = typing.cast(MSSQLColumn, source_column).default_constraint_name()
if source_def is not None:
constraints.append(f"DROP CONSTRAINT {name}")
if target_def is not None:
Expand Down
50 changes: 26 additions & 24 deletions pysqlsync/dialect/mssql/object_types.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import typing
from typing import Optional

from pysqlsync.formation.object_types import (
Expand All @@ -10,14 +11,38 @@
)
from pysqlsync.model.data_types import quote
from pysqlsync.model.id_types import LocalId
from pysqlsync.util.typing import override


class MSSQLColumn(Column):
def default_constraint_name(self) -> LocalId:
"The name of the constraint for DEFAULT."

return LocalId(f"df_{self.name.local_id}")

@property
def data_spec(self) -> str:
nullable = " NOT NULL" if not self.nullable else ""
name = self.default_constraint_name()
default = (
f" CONSTRAINT {name} DEFAULT {self.default}"
if self.default is not None
else ""
)
identity = " IDENTITY" if self.identity else ""
return f"{self.data_type}{nullable}{identity}"
return f"{self.data_type}{nullable}{default}{identity}"

@override
def create_stmt(self) -> str:
return f"ADD {self.column_spec}"

@override
def drop_stmt(self) -> str:
if self.default is not None:
name = self.default_constraint_name()
return f"DROP CONSTRAINT {name}, COLUMN {self.name}"
else:
return f"DROP COLUMN {self.name}"


class MSSQLTable(Table):
Expand All @@ -28,39 +53,16 @@ def alter_table_stmt(self, statements: list[str]) -> str:

def add_constraints_stmt(self) -> Optional[str]:
statements: list[str] = []

constraints: list[str] = []
for column in self.columns.values():
if column.default is None:
continue
name = LocalId(f"df_{column.name.local_id}")
constraints.append(
f"ADD CONSTRAINT {name} DEFAULT {column.default} FOR {column.name}"
)
if constraints:
statements.append(self.alter_table_stmt(constraints))

if self.table_constraints:
statements.append(
f"ALTER TABLE {self.name} ADD\n"
+ ",\n".join(f"CONSTRAINT {c.spec}" for c in self.table_constraints)
+ ";"
)

return join_or_none(statements)

def drop_constraints_stmt(self) -> Optional[str]:
statements: list[str] = []

constraints: list[str] = []
for column in self.columns.values():
if column.default is None:
continue
name = LocalId(f"df_{column.name.local_id}")
constraints.append(f"DROP CONSTRAINT {name}")
if constraints:
statements.append(self.alter_table_stmt(constraints))

if self.table_constraints:
statements.append(
f"ALTER TABLE {self.name} DROP\n"
Expand Down
4 changes: 4 additions & 0 deletions pysqlsync/formation/object_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,9 +203,13 @@ def data_spec(self) -> str:
return f"{self.data_type}{nullable}{default}{identity}"

def create_stmt(self) -> str:
"Creates a column as part of an ALTER TABLE statement."

return f"ADD COLUMN {self.column_spec}"

def drop_stmt(self) -> str:
"Removes a column as part of an ALTER TABLE statement."

return f"DROP COLUMN {self.name}"

def soft_drop_stmt(self) -> str:
Expand Down
22 changes: 8 additions & 14 deletions tests/test_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,18 +130,13 @@ def test_create_default_numeric_table(self) -> None:
tables.DefaultNumericTable,
'CREATE TABLE "DefaultNumericTable" (\n'
'"id" bigint NOT NULL,\n'
'"integer_8" smallint NOT NULL,\n'
'"integer_16" smallint NOT NULL,\n'
'"integer_32" integer NOT NULL,\n'
'"integer_64" bigint NOT NULL,\n'
'"integer" bigint NOT NULL,\n'
'"integer_8" smallint NOT NULL CONSTRAINT "df_integer_8" DEFAULT 127,\n'
'"integer_16" smallint NOT NULL CONSTRAINT "df_integer_16" DEFAULT 32767,\n'
'"integer_32" integer NOT NULL CONSTRAINT "df_integer_32" DEFAULT 2147483647,\n'
'"integer_64" bigint NOT NULL CONSTRAINT "df_integer_64" DEFAULT 0,\n'
'"integer" bigint NOT NULL CONSTRAINT "df_integer" DEFAULT 23,\n'
'CONSTRAINT "pk_DefaultNumericTable" PRIMARY KEY ("id")\n'
");\n"
'ALTER TABLE "DefaultNumericTable" ADD CONSTRAINT "df_integer_8" DEFAULT 127 FOR "integer_8";\n'
'ALTER TABLE "DefaultNumericTable" ADD CONSTRAINT "df_integer_16" DEFAULT 32767 FOR "integer_16";\n'
'ALTER TABLE "DefaultNumericTable" ADD CONSTRAINT "df_integer_32" DEFAULT 2147483647 FOR "integer_32";\n'
'ALTER TABLE "DefaultNumericTable" ADD CONSTRAINT "df_integer_64" DEFAULT 0 FOR "integer_64";\n'
'ALTER TABLE "DefaultNumericTable" ADD CONSTRAINT "df_integer" DEFAULT 23 FOR "integer";',
");",
)

def test_create_fixed_precision_float_table(self) -> None:
Expand Down Expand Up @@ -291,10 +286,9 @@ def test_create_default_datetime_table(self) -> None:
tables.DefaultDateTimeTable,
'CREATE TABLE "DefaultDateTimeTable" (\n'
'"id" bigint NOT NULL,\n'
""""iso_date_time" datetime2 NOT NULL,\n"""
""""iso_date_time" datetime2 NOT NULL CONSTRAINT "df_iso_date_time" DEFAULT '1989-10-24 23:59:59',\n"""
'CONSTRAINT "pk_DefaultDateTimeTable" PRIMARY KEY ("id")\n'
");\n"
"""ALTER TABLE "DefaultDateTimeTable" ADD CONSTRAINT "df_iso_date_time" DEFAULT '1989-10-24 23:59:59' FOR "iso_date_time";""",
");",
)

def test_create_enum_table(self) -> None:
Expand Down

0 comments on commit 68ad831

Please sign in to comment.