sandwich 0.2.0__py3-none-any.whl → 0.2.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sandwich/__init__.py +3 -0
- sandwich/dialects/__init__.py +12 -0
- sandwich/dialects/base.py +166 -0
- sandwich/dialects/ddl_mssql.py +148 -0
- sandwich/dialects/ddl_postgres.py +132 -0
- sandwich/dialects/factory.py +27 -0
- sandwich/dialects/mssql.py +271 -0
- sandwich/dialects/postgres.py +108 -0
- sandwich/dialects/utils.py +149 -0
- sandwich/dv2_helper.py +98 -0
- sandwich/errors.py +25 -0
- sandwich/main.py +0 -0
- sandwich/modeling/__init__.py +103 -0
- sandwich/strategies/__init__.py +15 -0
- sandwich/strategies/base.py +44 -0
- sandwich/strategies/factory.py +38 -0
- sandwich/strategies/link2fact.py +91 -0
- sandwich/strategies/scd2dim.py +246 -0
- {sandwich-0.2.0.dist-info → sandwich-0.2.2.dist-info}/METADATA +169 -136
- sandwich-0.2.2.dist-info/RECORD +23 -0
- sandwich-0.2.2.dist-info/WHEEL +4 -0
- sandwich-0.2.2.dist-info/entry_points.txt +3 -0
- sandwich-0.2.0.dist-info/RECORD +0 -5
- sandwich-0.2.0.dist-info/WHEEL +0 -4
- sandwich-0.2.0.dist-info/licenses/LICENSE +0 -9
sandwich/__init__.py
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"""Dialects package for SQL code generation."""
|
|
2
|
+
from src.sandwich.dialects.base import DialectHandler
|
|
3
|
+
from src.sandwich.dialects.factory import DialectHandlerFactory
|
|
4
|
+
from src.sandwich.dialects.mssql import MssqlDialectHandler
|
|
5
|
+
from src.sandwich.dialects.postgres import PostgresDialectHandler
|
|
6
|
+
|
|
7
|
+
__all__ = [
|
|
8
|
+
"DialectHandler",
|
|
9
|
+
"DialectHandlerFactory",
|
|
10
|
+
"MssqlDialectHandler",
|
|
11
|
+
"PostgresDialectHandler",
|
|
12
|
+
]
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from typing import Tuple
|
|
3
|
+
|
|
4
|
+
from sqlalchemy import Table
|
|
5
|
+
|
|
6
|
+
class DialectHandler(ABC):
|
|
7
|
+
@abstractmethod
|
|
8
|
+
def get_boolean_type(self): ...
|
|
9
|
+
|
|
10
|
+
@abstractmethod
|
|
11
|
+
def get_proc_name_format(self, schema: str, operation: str, entity_name: str) -> str:
|
|
12
|
+
pass
|
|
13
|
+
|
|
14
|
+
@abstractmethod
|
|
15
|
+
def apply_proc_template(self, proc_name: str, sql_body: str, header: str) -> str:
|
|
16
|
+
"""Wrap SQL body in procedure template with error handling and logging.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
proc_name: Name of the procedure
|
|
20
|
+
sql_body: The main SQL logic to execute
|
|
21
|
+
header: Auto-generated header comment
|
|
22
|
+
|
|
23
|
+
Returns:
|
|
24
|
+
Complete procedure definition
|
|
25
|
+
"""
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
@abstractmethod
|
|
29
|
+
def make_stg_materialization_proc(
|
|
30
|
+
self,
|
|
31
|
+
entity_name: str,
|
|
32
|
+
header: str
|
|
33
|
+
) -> Tuple[str, str, str]:
|
|
34
|
+
"""Generate staging table materialization procedure.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
entity_name: Entity name
|
|
38
|
+
columns_list: Comma-separated list of columns
|
|
39
|
+
header: Auto-generated header comment
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
Tuple of (procedure_code, procedure_name)
|
|
43
|
+
"""
|
|
44
|
+
pass
|
|
45
|
+
|
|
46
|
+
@abstractmethod
|
|
47
|
+
def make_hub_proc(
|
|
48
|
+
self,
|
|
49
|
+
hub_table: Table,
|
|
50
|
+
bk_keys: list,
|
|
51
|
+
header: str
|
|
52
|
+
) -> Tuple[str, str, str]:
|
|
53
|
+
"""Generate hub population procedure.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
hub_table: SQLAlchemy Table object for hub
|
|
57
|
+
bk_keys: List of business key tuples (name, type)
|
|
58
|
+
columns_list: Comma-separated list of columns
|
|
59
|
+
header: Auto-generated header comment
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
Tuple of (procedure_code, procedure_name)
|
|
63
|
+
"""
|
|
64
|
+
pass
|
|
65
|
+
|
|
66
|
+
@abstractmethod
|
|
67
|
+
def make_sat_proc(
|
|
68
|
+
self,
|
|
69
|
+
sat_table: Table,
|
|
70
|
+
hk_name: str,
|
|
71
|
+
hashdiff_col: str,
|
|
72
|
+
is_available_col: str,
|
|
73
|
+
loaddate_col: str,
|
|
74
|
+
stg_schema: str,
|
|
75
|
+
header: str
|
|
76
|
+
) -> Tuple[str, str, str]:
|
|
77
|
+
"""Generate satellite population procedure.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
sat_table: SQLAlchemy Table object for satellite
|
|
81
|
+
hk_name: Hash key column name
|
|
82
|
+
hashdiff_col: Hash diff column name
|
|
83
|
+
is_available_col: Is available column name
|
|
84
|
+
loaddate_col: Load date column name
|
|
85
|
+
columns_list: Comma-separated list of columns
|
|
86
|
+
stg_schema: Staging schema name ('stg' or 'proxy')
|
|
87
|
+
header: Auto-generated header comment
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
Tuple of (procedure_code, procedure_name)
|
|
91
|
+
"""
|
|
92
|
+
pass
|
|
93
|
+
|
|
94
|
+
@abstractmethod
|
|
95
|
+
def make_dim_scd2_proc(
|
|
96
|
+
self,
|
|
97
|
+
dim_table: Table,
|
|
98
|
+
bk_keys: list,
|
|
99
|
+
header: str
|
|
100
|
+
) -> Tuple[str, str, str]:
|
|
101
|
+
"""Generate dimension SCD2 recalculation procedure.
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
dim_table: SQLAlchemy Table object for dimension
|
|
105
|
+
bk_keys: List of business key tuples (name, type)
|
|
106
|
+
columns_list: Comma-separated list of columns
|
|
107
|
+
header: Auto-generated header comment
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
Tuple of (procedure_code, procedure_name)
|
|
111
|
+
"""
|
|
112
|
+
pass
|
|
113
|
+
|
|
114
|
+
@abstractmethod
|
|
115
|
+
def make_job_proc(
|
|
116
|
+
self,
|
|
117
|
+
entity_name: str,
|
|
118
|
+
hub_proc_name: str,
|
|
119
|
+
sat_proc_name: str,
|
|
120
|
+
dim_proc_name: str,
|
|
121
|
+
stg_proc_name: str | None,
|
|
122
|
+
header: str
|
|
123
|
+
) -> Tuple[str, str, str]:
|
|
124
|
+
"""Generate main job orchestration procedure.
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
entity_name: Entity name
|
|
128
|
+
hub_proc_name: Name of hub population procedure
|
|
129
|
+
sat_proc_name: Name of satellite population procedure
|
|
130
|
+
dim_proc_name: Name of dimension recalculation procedure
|
|
131
|
+
stg_proc_name: Name of staging materialization procedure (optional)
|
|
132
|
+
header: Auto-generated header comment
|
|
133
|
+
|
|
134
|
+
Returns:
|
|
135
|
+
Tuple of (procedure_code, procedure_name)
|
|
136
|
+
"""
|
|
137
|
+
pass
|
|
138
|
+
|
|
139
|
+
@abstractmethod
|
|
140
|
+
def make_drop_proc(
|
|
141
|
+
self,
|
|
142
|
+
entity_name: str,
|
|
143
|
+
stg_schema: str,
|
|
144
|
+
job_proc_name: str,
|
|
145
|
+
stg_proc_name: str | None,
|
|
146
|
+
hub_proc_name: str,
|
|
147
|
+
sat_proc_name: str,
|
|
148
|
+
dim_proc_name: str,
|
|
149
|
+
header: str
|
|
150
|
+
) -> Tuple[str, str, str]:
|
|
151
|
+
"""Generate cleanup/drop procedure for all entity objects.
|
|
152
|
+
|
|
153
|
+
Args:
|
|
154
|
+
entity_name: Entity name
|
|
155
|
+
stg_schema: Staging schema name ('stg' or 'proxy')
|
|
156
|
+
job_proc_name: Name of job orchestration procedure
|
|
157
|
+
stg_proc_name: Name of staging materialization procedure (optional)
|
|
158
|
+
hub_proc_name: Name of hub population procedure
|
|
159
|
+
sat_proc_name: Name of satellite population procedure
|
|
160
|
+
dim_proc_name: Name of dimension recalculation procedure
|
|
161
|
+
header: Auto-generated header comment
|
|
162
|
+
|
|
163
|
+
Returns:
|
|
164
|
+
Tuple of (procedure_code, procedure_name)
|
|
165
|
+
"""
|
|
166
|
+
pass
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# language=sql
|
|
2
|
+
create_entities_table = """
|
|
3
|
+
if object_id('core.entities') is null
|
|
4
|
+
begin
|
|
5
|
+
create table core.entities (
|
|
6
|
+
[entity_id] bigint primary key identity,
|
|
7
|
+
[entity_name] varchar(100) not null,
|
|
8
|
+
[template] varchar(50) not null,
|
|
9
|
+
[created] datetime2(7) not null default sysdatetime(),
|
|
10
|
+
[updated] datetime2(7) not null default sysdatetime(),
|
|
11
|
+
[is_deleted] bit not null default 0,
|
|
12
|
+
[deleted] datetime2(7) default null,
|
|
13
|
+
unique ([entity_name])
|
|
14
|
+
);
|
|
15
|
+
end
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
# language=sql
|
|
19
|
+
create_proc_register_entity = """
|
|
20
|
+
create or alter proc core.register_entity (
|
|
21
|
+
@entity_name varchar(100),
|
|
22
|
+
@template varchar(50)
|
|
23
|
+
) as
|
|
24
|
+
begin
|
|
25
|
+
set nocount on;
|
|
26
|
+
|
|
27
|
+
if exists (
|
|
28
|
+
select *
|
|
29
|
+
from core.[entities]
|
|
30
|
+
where [entity_name] = @entity_name
|
|
31
|
+
)
|
|
32
|
+
begin
|
|
33
|
+
update core.[entities]
|
|
34
|
+
set [updated] = sysdatetime(), [is_deleted] = 0
|
|
35
|
+
where [entity_name] = @entity_name
|
|
36
|
+
end
|
|
37
|
+
else begin
|
|
38
|
+
insert into core.[entities]
|
|
39
|
+
([entity_name], [template])
|
|
40
|
+
values (@entity_name, @template)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
# language=sql
|
|
46
|
+
create_table_ExecutionLog = """
|
|
47
|
+
if object_id('core.ExecutionLog') is null
|
|
48
|
+
begin
|
|
49
|
+
create table [core].[ExecutionLog](
|
|
50
|
+
[executionID] [bigint] identity(1,1) primary key NOT NULL,
|
|
51
|
+
[procid] [int] NOT NULL,
|
|
52
|
+
[begin_timestamp] [datetime2](7) NOT NULL default (getdate()),
|
|
53
|
+
[end_timestamp] [datetime2](7) NULL default (NULL),
|
|
54
|
+
[errorID] [int] NULL,
|
|
55
|
+
[procname] [varchar](200) NULL,
|
|
56
|
+
[parent_executionID] [bigint] NULL
|
|
57
|
+
)
|
|
58
|
+
end
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
# language=sql
|
|
62
|
+
create_table_ErrorLog = """
|
|
63
|
+
if object_id('core.ErrorLog') is null
|
|
64
|
+
begin
|
|
65
|
+
create table [core].[ErrorLog](
|
|
66
|
+
[ErrorID] [int] IDENTITY(1,1) NOT NULL,
|
|
67
|
+
[UserName] [varchar](100) NULL,
|
|
68
|
+
[ErrorNumber] [int] NULL,
|
|
69
|
+
[ErrorState] [int] NULL,
|
|
70
|
+
[ErrorSeverity] [int] NULL,
|
|
71
|
+
[ErrorLine] [int] NULL,
|
|
72
|
+
[ErrorProcedure] [varchar](max) NULL,
|
|
73
|
+
[ErrorMessage] [varchar](max) NULL,
|
|
74
|
+
[ErrorDateTime] [datetime] NULL
|
|
75
|
+
);
|
|
76
|
+
end
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
# language=sql
|
|
80
|
+
create_func_StringToHash = """
|
|
81
|
+
create or alter function [core].[StringToHash1]
|
|
82
|
+
(
|
|
83
|
+
@StrValue1 nvarchar(1000)
|
|
84
|
+
) returns char(40) as
|
|
85
|
+
begin
|
|
86
|
+
declare @result char(40);
|
|
87
|
+
set @result = upper(convert(char(40), hashbytes('sha1',
|
|
88
|
+
upper(rtrim(ltrim(isnull(@StrValue1, ''))))
|
|
89
|
+
), 2));
|
|
90
|
+
return @result;
|
|
91
|
+
end
|
|
92
|
+
"""
|
|
93
|
+
|
|
94
|
+
# language=sql
|
|
95
|
+
create_schemas = """
|
|
96
|
+
if schema_id('core') is null
|
|
97
|
+
exec ('create schema core')
|
|
98
|
+
if schema_id('stg') is null
|
|
99
|
+
exec ('create schema stg')
|
|
100
|
+
if schema_id('hub') is null
|
|
101
|
+
exec ('create schema hub')
|
|
102
|
+
if schema_id('sat') is null
|
|
103
|
+
exec ('create schema sat')
|
|
104
|
+
if schema_id('dim') is null
|
|
105
|
+
exec ('create schema dim')
|
|
106
|
+
if schema_id('fact') is null
|
|
107
|
+
exec ('create schema fact')
|
|
108
|
+
if schema_id('elt') is null
|
|
109
|
+
exec ('create schema elt')
|
|
110
|
+
if schema_id('job') is null
|
|
111
|
+
exec ('create schema job')
|
|
112
|
+
if schema_id('meta') is null
|
|
113
|
+
exec ('create schema meta')
|
|
114
|
+
if schema_id('proxy') is null
|
|
115
|
+
exec ('create schema proxy')
|
|
116
|
+
"""
|
|
117
|
+
|
|
118
|
+
# language=sql
|
|
119
|
+
create_proc_LogExecution = """
|
|
120
|
+
create or alter proc [core].[LogExecution]
|
|
121
|
+
(
|
|
122
|
+
@procid int,
|
|
123
|
+
@executionID_in bigint,
|
|
124
|
+
@executionID_out bigint out,
|
|
125
|
+
@parent_executionID bigint = null
|
|
126
|
+
) as
|
|
127
|
+
begin
|
|
128
|
+
set nocount on;
|
|
129
|
+
|
|
130
|
+
if @executionID_in is not null
|
|
131
|
+
begin
|
|
132
|
+
update [core].[ExecutionLog]
|
|
133
|
+
set [end_timestamp] = getdate()
|
|
134
|
+
where executionID = @executionID_in;
|
|
135
|
+
|
|
136
|
+
set @executionID_out = @executionID_in;
|
|
137
|
+
end else
|
|
138
|
+
begin
|
|
139
|
+
|
|
140
|
+
declare @out table (executionID int);
|
|
141
|
+
insert into [core].[ExecutionLog] (procid, procname, parent_executionID) output inserted.executionID
|
|
142
|
+
into @out
|
|
143
|
+
values (@procid, object_name(@procid), @parent_executionID);
|
|
144
|
+
|
|
145
|
+
set @executionID_out = (select executionID from @out);
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
"""
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# language=sql
|
|
2
|
+
create_extensions = """
|
|
3
|
+
create extension if not exists pgcrypto;
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
# language=sql
|
|
7
|
+
create_entities_table = """
|
|
8
|
+
CREATE TABLE IF NOT EXISTS core.entities (
|
|
9
|
+
entity_id BIGSERIAL PRIMARY KEY,
|
|
10
|
+
entity_name VARCHAR(100) NOT NULL,
|
|
11
|
+
template VARCHAR(50) NOT NULL,
|
|
12
|
+
created TIMESTAMP NOT NULL DEFAULT NOW(),
|
|
13
|
+
updated TIMESTAMP NOT NULL DEFAULT NOW(),
|
|
14
|
+
is_deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
|
15
|
+
deleted TIMESTAMP DEFAULT NULL,
|
|
16
|
+
UNIQUE (entity_name)
|
|
17
|
+
);
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
# language=sql
|
|
21
|
+
create_proc_register_entity = """
|
|
22
|
+
CREATE OR REPLACE PROCEDURE core.register_entity(
|
|
23
|
+
p_entity_name VARCHAR(100),
|
|
24
|
+
p_gen_path VARCHAR(50)
|
|
25
|
+
)
|
|
26
|
+
LANGUAGE plpgsql
|
|
27
|
+
AS $$
|
|
28
|
+
BEGIN
|
|
29
|
+
INSERT INTO core.entities (entity_name, template)
|
|
30
|
+
VALUES (p_entity_name, p_gen_path)
|
|
31
|
+
ON CONFLICT (entity_name) DO UPDATE
|
|
32
|
+
SET updated = NOW(),
|
|
33
|
+
is_deleted = FALSE;
|
|
34
|
+
END;
|
|
35
|
+
$$;
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
# language=sql
|
|
39
|
+
create_func_StringToHash= """
|
|
40
|
+
create or replace function core.string_to_hash1(str_value text)
|
|
41
|
+
returns char(40)
|
|
42
|
+
language plpgsql
|
|
43
|
+
as $$
|
|
44
|
+
declare
|
|
45
|
+
result char(40);
|
|
46
|
+
begin
|
|
47
|
+
if str_value is null
|
|
48
|
+
or str_value in ('(unknown)', 'empty')
|
|
49
|
+
then
|
|
50
|
+
result := repeat('0', 40);
|
|
51
|
+
else
|
|
52
|
+
result :=
|
|
53
|
+
upper(
|
|
54
|
+
encode(
|
|
55
|
+
digest(upper(trim(str_value)), 'sha1'),
|
|
56
|
+
'hex'
|
|
57
|
+
)
|
|
58
|
+
);
|
|
59
|
+
end if;
|
|
60
|
+
|
|
61
|
+
return cast(result as char(40));
|
|
62
|
+
end;
|
|
63
|
+
$$;
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
# language=sql
|
|
67
|
+
create_table_ExecutionLog = """
|
|
68
|
+
CREATE TABLE IF NOT EXISTS core.ExecutionLog (
|
|
69
|
+
executionID BIGSERIAL PRIMARY KEY,
|
|
70
|
+
procid INT NOT NULL,
|
|
71
|
+
begin_timestamp TIMESTAMP NOT NULL DEFAULT NOW(),
|
|
72
|
+
end_timestamp TIMESTAMP DEFAULT NULL,
|
|
73
|
+
errorID INT DEFAULT NULL,
|
|
74
|
+
procname VARCHAR(200) DEFAULT NULL,
|
|
75
|
+
parent_executionID BIGINT DEFAULT NULL
|
|
76
|
+
);
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
# language=sql
|
|
80
|
+
create_table_ErrorLog = """
|
|
81
|
+
CREATE TABLE IF NOT EXISTS core.ErrorLog (
|
|
82
|
+
ErrorID SERIAL PRIMARY KEY,
|
|
83
|
+
UserName VARCHAR(100) DEFAULT NULL,
|
|
84
|
+
ErrorNumber INT DEFAULT NULL,
|
|
85
|
+
ErrorState INT DEFAULT NULL,
|
|
86
|
+
ErrorSeverity INT DEFAULT NULL,
|
|
87
|
+
ErrorLine INT DEFAULT NULL,
|
|
88
|
+
ErrorProcedure TEXT DEFAULT NULL,
|
|
89
|
+
ErrorMessage TEXT DEFAULT NULL,
|
|
90
|
+
ErrorDateTime TIMESTAMP DEFAULT NULL
|
|
91
|
+
);
|
|
92
|
+
"""
|
|
93
|
+
|
|
94
|
+
# language=sql
|
|
95
|
+
create_proc_LogExecution = """
|
|
96
|
+
CREATE OR REPLACE PROCEDURE core.LogExecution(
|
|
97
|
+
p_procid INT,
|
|
98
|
+
p_executionID_in BIGINT,
|
|
99
|
+
INOUT p_executionID_out BIGINT,
|
|
100
|
+
p_parent_executionID BIGINT DEFAULT NULL
|
|
101
|
+
)
|
|
102
|
+
LANGUAGE plpgsql
|
|
103
|
+
AS $$
|
|
104
|
+
BEGIN
|
|
105
|
+
IF p_executionID_in IS NOT NULL THEN
|
|
106
|
+
UPDATE core.ExecutionLog
|
|
107
|
+
SET end_timestamp = NOW()
|
|
108
|
+
WHERE executionID = p_executionID_in;
|
|
109
|
+
|
|
110
|
+
p_executionID_out := p_executionID_in;
|
|
111
|
+
ELSE
|
|
112
|
+
INSERT INTO core.ExecutionLog (procid, procname, parent_executionID)
|
|
113
|
+
VALUES (p_procid, NULL, p_parent_executionID)
|
|
114
|
+
RETURNING executionID INTO p_executionID_out;
|
|
115
|
+
END IF;
|
|
116
|
+
END;
|
|
117
|
+
$$;
|
|
118
|
+
"""
|
|
119
|
+
|
|
120
|
+
# language=sql
|
|
121
|
+
create_schemas = f"""
|
|
122
|
+
CREATE SCHEMA IF NOT EXISTS core;
|
|
123
|
+
CREATE SCHEMA IF NOT EXISTS stg;
|
|
124
|
+
CREATE SCHEMA IF NOT EXISTS hub;
|
|
125
|
+
CREATE SCHEMA IF NOT EXISTS sat;
|
|
126
|
+
CREATE SCHEMA IF NOT EXISTS dim;
|
|
127
|
+
CREATE SCHEMA IF NOT EXISTS fact;
|
|
128
|
+
CREATE SCHEMA IF NOT EXISTS elt;
|
|
129
|
+
CREATE SCHEMA IF NOT EXISTS job;
|
|
130
|
+
CREATE SCHEMA IF NOT EXISTS meta;
|
|
131
|
+
CREATE SCHEMA IF NOT EXISTS proxy;
|
|
132
|
+
"""
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from src.sandwich.dialects.base import DialectHandler
|
|
2
|
+
from src.sandwich.dialects.mssql import MssqlDialectHandler
|
|
3
|
+
from src.sandwich.dialects.postgres import PostgresDialectHandler
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class DialectHandlerFactory:
|
|
7
|
+
_handlers = {
|
|
8
|
+
"mssql": MssqlDialectHandler,
|
|
9
|
+
"postgres": PostgresDialectHandler,
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
@classmethod
|
|
13
|
+
def register_dialect(cls, dialect_name: str, handler_class):
|
|
14
|
+
cls._handlers[dialect_name] = handler_class
|
|
15
|
+
|
|
16
|
+
@classmethod
|
|
17
|
+
def create_handler(cls, dialect: str) -> DialectHandler:
|
|
18
|
+
if dialect not in cls._handlers:
|
|
19
|
+
available = ", ".join(cls._handlers.keys())
|
|
20
|
+
raise ValueError(f"Unknown dialect '{dialect}'. Available dialects: {available}")
|
|
21
|
+
|
|
22
|
+
handler_class = cls._handlers[dialect]
|
|
23
|
+
return handler_class()
|
|
24
|
+
|
|
25
|
+
@classmethod
|
|
26
|
+
def get_available_dialects(cls) -> list[str]:
|
|
27
|
+
return list(cls._handlers.keys())
|