Skip to main content

datasources_sqlserver/
driver.rs

1use crate::connection::SqlServerConnection;
2use crate::sql_generate;
3use crate::statement_renderer::SqlServerStatementRenderer;
4use datasources::{
5    Column, Command, Connection, Driver, Information, IsolationLevel, Mapping, Result,
6    RoutineParameter,
7    StatementTextRenderer, StubTransaction, Transaction, TypeConverter, Value,
8};
9use std::collections::HashMap;
10use std::sync::{Arc, LazyLock};
11
12pub struct SqlServerDriver;
13
14impl SqlServerDriver {
15    pub const QUOTE_LEFT: &'static str = sql_generate::QUOTE_LEFT;
16    pub const QUOTE_RIGHT: &'static str = sql_generate::QUOTE_RIGHT;
17    pub const PROCEDURE_PAYLOAD_TYPE: &'static str = sql_generate::PROCEDURE_PAYLOAD_TYPE;
18
19    pub fn apply_keywords(sql: &str, keyword: &dyn Fn(&str) -> String) -> String {
20        sql_generate::apply_keywords(sql, keyword)
21    }
22
23    pub fn statement_text_renderer() -> &'static StatementTextRenderer {
24        static DRIVER: SqlServerDriver = SqlServerDriver;
25        Driver::statement_renderer(&DRIVER).expect("sqlserver")
26    }
27
28    pub fn types() -> &'static crate::type_map::TypeMap {
29        &*sql_generate::TYPES
30    }
31
32    pub fn defaults() -> &'static crate::default_value_converter::DefaultValueConverter {
33        &sql_generate::DEFAULTS
34    }
35
36    pub fn convert_type(field: &datasources::SpecField) -> Result<String> {
37        sql_generate::convert_type(field)
38    }
39
40    pub fn convert_default(spec_type: &str, text: &str) -> Result<Option<String>> {
41        sql_generate::convert_default(spec_type, text)
42    }
43
44    pub fn quote(name: &str) -> String {
45        format!("[{name}]")
46    }
47
48    pub fn native_type(column: &Column) -> String {
49        column
50            .field
51            .as_ref()
52            .and_then(|field| sql_generate::TYPES.convert_field(field).ok())
53            .unwrap_or_else(|| column.type_name.clone())
54    }
55
56    pub fn native_default(column: &Column) -> String {
57        let Some(default) = &column.default else {
58            return String::new();
59        };
60        let Some(field) = &column.field else {
61            return default.value.clone();
62        };
63        sql_generate::DEFAULTS
64            .convert(&field.type_name, &default.value)
65            .ok()
66            .flatten()
67            .unwrap_or_else(|| default.value.clone())
68    }
69
70    pub fn utc_now() -> String {
71        sql_generate::DEFAULTS
72            .convert("datetime", "UtcNow")
73            .ok()
74            .flatten()
75            .unwrap_or_default()
76    }
77
78    pub fn native_param(parameter: &RoutineParameter) -> String {
79        if parameter.r#type == "payload" {
80            return Self::PROCEDURE_PAYLOAD_TYPE.to_string();
81        }
82        parameter
83            .field
84            .as_ref()
85            .and_then(|field| sql_generate::TYPES.convert_field(field).ok())
86            .unwrap_or_else(|| parameter.r#type.clone())
87    }
88}
89
90static STATEMENTS: LazyLock<StatementTextRenderer> =
91    LazyLock::new(|| {
92        StatementTextRenderer::new(Some(Box::new(SqlServerStatementRenderer)), None)
93            .with_keyword_apply(sql_generate::apply_keywords)
94    });
95
96static INFORMATION: LazyLock<Information> = LazyLock::new(|| {
97    Information::new(
98        ["SQL Server driver."],
99        [
100            "Overrides CreateCreateStoredProcedureStatement to PROCEDURE Create{Plural}",
101            "Overrides CreateReadStoredProcedureStatement to PROCEDURE Read{Plural}By{Properties}",
102            "Overrides CreateUpdateStoredProcedureStatement to PROCEDURE Update{Plural}By{Properties}",
103            "Overrides CreateDeleteStoredProcedureStatement to PROCEDURE Delete{Plural}By{Properties}",
104            "Overrides CreateBulkCreateStoredProcedureStatement to PROCEDURE BulkCreate{Plural}",
105            "Overrides CreateBulkUpdateStoredProcedureStatement to PROCEDURE BulkUpdate{Plural}",
106            "Overrides CreateBulkDeleteStoredProcedureStatement to PROCEDURE BulkDelete{Plural}",
107        ],
108        [] as [&str; 0],
109    )
110});
111
112impl Driver for SqlServerDriver {
113    fn connection(&self, options: Option<&HashMap<String, String>>) -> Arc<dyn Connection> {
114        SqlServerConnection::from_options(options)
115    }
116
117    fn command(&self, connection: Arc<dyn Connection>) -> Arc<dyn Command> {
118        connection.create_command()
119    }
120
121    fn transaction(
122        &self,
123        connection: Arc<dyn Connection>,
124        _isolation: IsolationLevel,
125    ) -> Arc<dyn Transaction> {
126        Arc::new(StubTransaction::new("sqlserver", connection))
127    }
128
129    fn row_type_converters(
130        &self,
131    ) -> HashMap<String, Box<dyn TypeConverter<Value, Value> + Send + Sync>> {
132        HashMap::new()
133    }
134
135    fn type_converter(&self) -> Option<&dyn Mapping<String, String>> {
136        Some(&*sql_generate::TYPES)
137    }
138
139    fn statement_renderer(&self) -> Option<&StatementTextRenderer> {
140        Some(&STATEMENTS)
141    }
142
143    fn information(&self) -> Option<&Information> {
144        Some(&INFORMATION)
145    }
146}