1 | // |
2 | // ODBCMetaColumn.cpp |
3 | // |
4 | // Library: Data/ODBC |
5 | // Package: ODBC |
6 | // Module: ODBCMetaColumn |
7 | // |
8 | // Copyright (c) 2006, Applied Informatics Software Engineering GmbH. |
9 | // and Contributors. |
10 | // |
11 | // SPDX-License-Identifier: BSL-1.0 |
12 | // |
13 | |
14 | |
15 | #include "Poco/Data/ODBC/ODBCMetaColumn.h" |
16 | #include "Poco/Data/ODBC/Utility.h" |
17 | |
18 | |
19 | namespace Poco { |
20 | namespace Data { |
21 | namespace ODBC { |
22 | |
23 | |
24 | ODBCMetaColumn::ODBCMetaColumn(const StatementHandle& rStmt, std::size_t position) : |
25 | MetaColumn(position), |
26 | _rStmt(rStmt) |
27 | { |
28 | init(); |
29 | } |
30 | |
31 | |
32 | ODBCMetaColumn::~ODBCMetaColumn() |
33 | { |
34 | } |
35 | |
36 | |
37 | void ODBCMetaColumn::getDescription() |
38 | { |
39 | std::memset(_columnDesc.name, 0, NAME_BUFFER_LENGTH); |
40 | _columnDesc.nameBufferLength = 0; |
41 | _columnDesc.dataType = 0; |
42 | _columnDesc.size = 0; |
43 | _columnDesc.decimalDigits = 0; |
44 | _columnDesc.isNullable = 0; |
45 | |
46 | if (Utility::isError(Poco::Data::ODBC::SQLDescribeCol(_rStmt, |
47 | (SQLUSMALLINT) position() + 1, // ODBC columns are 1-based |
48 | _columnDesc.name, |
49 | NAME_BUFFER_LENGTH, |
50 | &_columnDesc.nameBufferLength, |
51 | &_columnDesc.dataType, |
52 | &_columnDesc.size, |
53 | &_columnDesc.decimalDigits, |
54 | &_columnDesc.isNullable))) |
55 | { |
56 | throw StatementException(_rStmt); |
57 | } |
58 | } |
59 | |
60 | |
61 | bool ODBCMetaColumn::isUnsigned() const |
62 | { |
63 | SQLLEN val = 0; |
64 | if (Utility::isError(Poco::Data::ODBC::SQLColAttribute(_rStmt, |
65 | (SQLUSMALLINT)position() + 1, // ODBC columns are 1-based |
66 | SQL_DESC_UNSIGNED, |
67 | 0, |
68 | 0, |
69 | 0, |
70 | &val))) |
71 | { |
72 | throw StatementException(_rStmt); |
73 | } |
74 | return (val == SQL_TRUE); |
75 | } |
76 | |
77 | |
78 | void ODBCMetaColumn::init() |
79 | { |
80 | getDescription(); |
81 | |
82 | if (Utility::isError(Poco::Data::ODBC::SQLColAttribute(_rStmt, |
83 | (SQLUSMALLINT) position() + 1, // ODBC columns are 1-based |
84 | SQL_DESC_LENGTH, |
85 | 0, |
86 | 0, |
87 | 0, |
88 | &_dataLength))) |
89 | { |
90 | throw StatementException(_rStmt); |
91 | } |
92 | |
93 | setName(std::string((char*) _columnDesc.name)); |
94 | setLength(_columnDesc.size); |
95 | setPrecision(_columnDesc.decimalDigits); |
96 | setNullable(SQL_NULLABLE == _columnDesc.isNullable); |
97 | switch(_columnDesc.dataType) |
98 | { |
99 | case SQL_BIT: |
100 | setType(MetaColumn::FDT_BOOL); break; |
101 | |
102 | case SQL_CHAR: |
103 | case SQL_VARCHAR: |
104 | case SQL_LONGVARCHAR: |
105 | #ifdef SQL_GUID |
106 | case SQL_GUID: |
107 | #endif |
108 | setType(MetaColumn::FDT_STRING); break; |
109 | |
110 | case SQL_WCHAR: |
111 | case SQL_WVARCHAR: |
112 | case SQL_WLONGVARCHAR: |
113 | case -350: // IBM DB2 CLOB, which long unicode string |
114 | setType(MetaColumn::FDT_WSTRING); break; |
115 | |
116 | case SQL_TINYINT: |
117 | setType(isUnsigned() ? MetaColumn::FDT_UINT8 : MetaColumn::FDT_INT8); |
118 | break; |
119 | |
120 | case SQL_SMALLINT: |
121 | setType(isUnsigned() ? MetaColumn::FDT_UINT16 : MetaColumn::FDT_INT16); |
122 | break; |
123 | |
124 | case SQL_INTEGER: |
125 | setType(isUnsigned() ? MetaColumn::FDT_UINT32 : MetaColumn::FDT_INT32); |
126 | break; |
127 | |
128 | case SQL_BIGINT: |
129 | setType(isUnsigned() ? MetaColumn::FDT_UINT64 : MetaColumn::FDT_INT64); |
130 | break; |
131 | |
132 | case SQL_DOUBLE: |
133 | case SQL_FLOAT: |
134 | setType(MetaColumn::FDT_DOUBLE); break; |
135 | |
136 | case SQL_NUMERIC: |
137 | case SQL_DECIMAL: |
138 | // Oracle has no INTEGER type - it's essentially NUMBER with 38 whole and |
139 | // 0 fractional digits. It also does not recognize SQL_BIGINT type, |
140 | // so the workaround here is to hardcode it to 32 bit integer |
141 | if (0 == _columnDesc.decimalDigits) setType(MetaColumn::FDT_INT32); |
142 | else setType(MetaColumn::FDT_DOUBLE); |
143 | break; |
144 | |
145 | case SQL_REAL: |
146 | setType(MetaColumn::FDT_FLOAT); break; |
147 | |
148 | case SQL_BINARY: |
149 | case SQL_VARBINARY: |
150 | case SQL_LONGVARBINARY: |
151 | case -98:// IBM DB2 non-standard type |
152 | case -370: // IBM DB2 XML, documentation advises to bind it as BLOB, not CLOB |
153 | setType(MetaColumn::FDT_BLOB); break; |
154 | |
155 | case -99: // IBM DB2 CLOB |
156 | setType(MetaColumn::FDT_CLOB); break; |
157 | |
158 | case SQL_TYPE_DATE: |
159 | setType(MetaColumn::FDT_DATE); break; |
160 | |
161 | case SQL_TYPE_TIME: |
162 | setType(MetaColumn::FDT_TIME); break; |
163 | |
164 | case SQL_TYPE_TIMESTAMP: |
165 | setType(MetaColumn::FDT_TIMESTAMP); break; |
166 | |
167 | default: |
168 | throw DataFormatException("Unsupported data type." ); |
169 | } |
170 | } |
171 | |
172 | |
173 | } } } // namespace Poco::Data::ODBC |
174 | |