Lightweight 0.20261105.1
Loading...
Searching...
No Matches
SqlColumnTypeDefinitions.hpp
1// SPDX-License-Identifier: Apache-2.0
2
3#pragma once
4
5// See SqlOdbcPrelude.hpp's header comment for why this replaces a direct <Windows.h> include.
6#include "SqlOdbcPrelude.hpp"
7
8#include <cstdint>
9#include <optional>
10#include <variant>
11
12#include <sql.h>
13#include <sqlext.h>
14
15// Microsoft SQL Server extension for TIME(7) with fractional seconds.
16// This is supported by SQL Server 2008 and later, MariaDB and MySQL ODBC drivers.
17// clang-format off
18#if !defined(SQL_SS_TIME2)
19 #define SQL_SS_TIME2 (-154)
20
21 struct SQL_SS_TIME2_STRUCT
22 {
23 SQLUSMALLINT hour;
24 SQLUSMALLINT minute;
25 SQLUSMALLINT second;
26 SQLUINTEGER fraction;
27 };
28
29 static_assert(
30 sizeof(SQL_SS_TIME2_STRUCT) == 12,
31 "SQL_SS_TIME2_STRUCT size must be padded 12 bytes, as per ODBC extension spec."
32 );
33#endif
34// clang-format on
35
36namespace Lightweight
37{
38
39/// @brief Represents if a column is nullable or not.
40enum class SqlNullable : uint8_t
41{
42 NotNull,
43 Null,
44};
45
46namespace SqlColumnTypeDefinitions
47{
48
49 // `legacyLob` on Varchar, NVarchar and VarBinary declares SQL Server's TEXT, NTEXT and IMAGE, and is what
50 // SqlSchema reports for such a column. Other databases ignore it. It takes part in comparisons, so a live
51 // TEXT column differs from a declared Varchar of the same size.
52 // clang-format off
53struct Bigint { auto operator<=>(Bigint const&) const = default; };
54struct Binary { std::size_t size = 255; auto operator<=>(Binary const&) const = default; };
55struct Bool { auto operator<=>(Bool const&) const = default; };
56struct Char { std::size_t size = 1; auto operator<=>(Char const&) const = default; };
57struct Date { auto operator<=>(Date const&) const = default; };
58struct DateTime { auto operator<=>(DateTime const&) const = default; };
59struct Decimal { std::size_t precision {}; std::size_t scale {}; auto operator<=>(Decimal const&) const = default; };
60struct Guid { auto operator<=>(Guid const&) const = default; };
61struct Integer { auto operator<=>(Integer const&) const = default; };
62struct NChar { std::size_t size = 1; auto operator<=>(NChar const&) const = default; };
63struct NVarchar { std::size_t size = 255; bool legacyLob = false; auto operator<=>(NVarchar const&) const = default; };
64struct Real { std::size_t precision = {}; auto operator<=>(Real const&) const = default; };
65struct Smallint { auto operator<=>(Smallint const&) const = default; };
66struct Text { std::size_t size {}; auto operator<=>(Text const&) const = default; };
67struct Time { auto operator<=>(Time const&) const = default; };
68struct Timestamp { auto operator<=>(Timestamp const&) const = default; };
69struct Tinyint { auto operator<=>(Tinyint const&) const = default; };
70struct VarBinary { std::size_t size = 255; bool legacyLob = false; auto operator<=>(VarBinary const&) const = default; };
71struct Varchar { std::size_t size = 255; bool legacyLob = false; auto operator<=>(Varchar const&) const = default; };
72 // clang-format on
73
74} // namespace SqlColumnTypeDefinitions
75
76using SqlColumnTypeDefinition = std::variant<SqlColumnTypeDefinitions::Bigint,
77 SqlColumnTypeDefinitions::Binary,
78 SqlColumnTypeDefinitions::Bool,
79 SqlColumnTypeDefinitions::Char,
80 SqlColumnTypeDefinitions::Date,
81 SqlColumnTypeDefinitions::DateTime,
82 SqlColumnTypeDefinitions::Decimal,
83 SqlColumnTypeDefinitions::Guid,
84 SqlColumnTypeDefinitions::Integer,
85 SqlColumnTypeDefinitions::NChar,
86 SqlColumnTypeDefinitions::NVarchar,
87 SqlColumnTypeDefinitions::Real,
88 SqlColumnTypeDefinitions::Tinyint,
89 SqlColumnTypeDefinitions::Smallint,
90 SqlColumnTypeDefinitions::Text,
91 SqlColumnTypeDefinitions::Time,
92 SqlColumnTypeDefinitions::Timestamp,
93 SqlColumnTypeDefinitions::VarBinary,
94 SqlColumnTypeDefinitions::Varchar>;
95
96/// Maps ODBC data type (with given @p size and @p precision) to SqlColumnTypeDefinition
97///
98/// @return SqlColumnTypeDefinition if the data type is supported, otherwise std::nullopt
99constexpr std::optional<SqlColumnTypeDefinition> MakeColumnTypeFromNative(int value, std::size_t size, std::size_t precision)
100{
101 // Maps ODBC data types to SqlColumnTypeDefinition
102 // See: https://learn.microsoft.com/en-us/sql/odbc/reference/appendixes/sql-data-types?view=sql-server-ver16
103 using namespace SqlColumnTypeDefinitions;
104 // clang-format off
105 switch (value)
106 {
107 case SQL_BIGINT: return Bigint {};
108 case SQL_BINARY: return Binary { size };
109 case SQL_BIT: return Bool {};
110 case SQL_CHAR: return Char { size };
111 case SQL_DATE: return Date {};
112 case SQL_DECIMAL: return Decimal { .precision = size, .scale = precision };
113 case SQL_DOUBLE: return Real { .precision = 53 };
114 case SQL_FLOAT: return Real { . precision = precision };
115 case SQL_GUID: return Guid {};
116 case SQL_INTEGER: return Integer {};
117 case SQL_LONGVARBINARY: return VarBinary { .size = size };
118 case SQL_LONGVARCHAR: return Varchar { .size = size };
119 case SQL_NUMERIC: return Decimal { .precision = size, .scale = precision };
120 case SQL_REAL: return Real { .precision = 24 };
121 case SQL_SMALLINT: return Smallint {};
122 case SQL_TIME: return Time {};
123 case SQL_TIMESTAMP: return DateTime {};
124 case SQL_TINYINT: return Tinyint {};
125 case SQL_TYPE_DATE: return Date {};
126 case SQL_TYPE_TIME: return Time {};
127 case SQL_SS_TIME2: return Time {}; // Microsoft SQL Server extension
128 case SQL_TYPE_TIMESTAMP: return DateTime {};
129 case SQL_VARBINARY: return VarBinary { .size = size };
130 case SQL_VARCHAR: return Varchar { .size = size };
131 case SQL_WCHAR: return NChar { size };
132 case SQL_WLONGVARCHAR: return NVarchar { .size = size };
133 case SQL_WVARCHAR: return NVarchar { .size = size };
134 case SQL_UNKNOWN_TYPE: return std::nullopt;
135 default: return std::nullopt;
136 }
137 // clang-format on
138}
139
140} // namespace Lightweight