Line data Source code
1 : /*
2 : * SPDX-License-Identifier: MPL-2.0
3 : *
4 : * This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 : *
8 : * Copyright 2024 MonetDB Foundation;
9 : * Copyright August 2008 - 2023 MonetDB B.V.;
10 : * Copyright 1997 - July 2008 CWI.
11 : */
12 :
13 : /*
14 : * This code was created by Peter Harvey (mostly during Christmas 98/99).
15 : * This code is LGPL. Please ensure that this message remains in future
16 : * distributions and uses of this code (thats about all I get out of it).
17 : * - Peter Harvey pharvey@codebydesign.com
18 : *
19 : * This file has been modified for the MonetDB project. See the file
20 : * Copyright in this directory for more information.
21 : */
22 :
23 : /**********************************************************************
24 : * SQLDescribeCol()
25 : * CLI Compliance: ISO 92
26 : *
27 : * Author: Martin van Dinther, Sjoerd Mullender
28 : * Date : 30 aug 2002
29 : *
30 : **********************************************************************/
31 :
32 : #include "ODBCGlobal.h"
33 : #include "ODBCStmt.h"
34 : #include "ODBCUtil.h"
35 :
36 :
37 : static SQLRETURN
38 1660 : MNDBDescribeCol(ODBCStmt *stmt,
39 : SQLUSMALLINT ColumnNumber,
40 : SQLCHAR *ColumnName,
41 : SQLSMALLINT BufferLength,
42 : SQLSMALLINT *NameLengthPtr,
43 : SQLSMALLINT *DataTypePtr,
44 : SQLULEN *ColumnSizePtr,
45 : SQLSMALLINT *DecimalDigitsPtr,
46 : SQLSMALLINT *NullablePtr)
47 : {
48 1660 : ODBCDescRec *rec = NULL;
49 :
50 : /* check statement cursor state, query should be executed */
51 1660 : if (stmt->State == INITED) {
52 : /* Function sequence error */
53 0 : addStmtError(stmt, "HY010", NULL, 0);
54 0 : return SQL_ERROR;
55 : }
56 1660 : if (stmt->State == PREPARED0) {
57 : /* Prepared statement not a cursor-specification */
58 0 : addStmtError(stmt, "07005", NULL, 0);
59 0 : return SQL_ERROR;
60 : }
61 1660 : if (stmt->State == EXECUTED0) {
62 : /* Invalid cursor state */
63 0 : addStmtError(stmt, "24000", NULL, 0);
64 0 : return SQL_ERROR;
65 : }
66 :
67 1660 : if (ColumnNumber < 1 ||
68 1660 : ColumnNumber > stmt->ImplRowDescr->sql_desc_count) {
69 : /* Invalid descriptor index */
70 0 : addStmtError(stmt, "07009", NULL, 0);
71 0 : return SQL_ERROR;
72 : }
73 :
74 1660 : rec = stmt->ImplRowDescr->descRec + ColumnNumber;
75 :
76 : /* now copy the data */
77 3280 : copyString(rec->sql_desc_name, strlen((char *) rec->sql_desc_name),
78 : ColumnName, BufferLength, NameLengthPtr, SQLSMALLINT,
79 : addStmtError, stmt, return SQL_ERROR);
80 :
81 1660 : if (DataTypePtr)
82 870 : *DataTypePtr = rec->sql_desc_concise_type;
83 :
84 : /* also see SQLDescribeParam */
85 1660 : if (ColumnSizePtr) {
86 870 : *ColumnSizePtr = ODBCLength(rec, SQL_DESC_LENGTH);
87 870 : if (*ColumnSizePtr == (SQLULEN) SQL_NO_TOTAL)
88 4 : *ColumnSizePtr = 0;
89 : }
90 :
91 : /* also see SQLDescribeParam */
92 1660 : if (DecimalDigitsPtr) {
93 870 : switch (rec->sql_desc_concise_type) {
94 2 : case SQL_DECIMAL:
95 : case SQL_NUMERIC:
96 2 : *DecimalDigitsPtr = rec->sql_desc_scale;
97 2 : break;
98 354 : case SQL_BIT:
99 : case SQL_TINYINT:
100 : case SQL_SMALLINT:
101 : case SQL_INTEGER:
102 : case SQL_BIGINT:
103 : case SQL_HUGEINT:
104 354 : *DecimalDigitsPtr = 0;
105 354 : break;
106 0 : case SQL_TYPE_TIME:
107 : case SQL_TYPE_TIMESTAMP:
108 : case SQL_INTERVAL_SECOND:
109 : case SQL_INTERVAL_DAY_TO_SECOND:
110 : case SQL_INTERVAL_HOUR_TO_SECOND:
111 : case SQL_INTERVAL_MINUTE_TO_SECOND:
112 0 : *DecimalDigitsPtr = rec->sql_desc_precision;
113 0 : break;
114 514 : default:
115 514 : *DecimalDigitsPtr = 0;
116 514 : break;
117 : }
118 : }
119 :
120 1660 : if (NullablePtr)
121 80 : *NullablePtr = rec->sql_desc_nullable;
122 :
123 1660 : return stmt->Error ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
124 : }
125 :
126 : SQLRETURN SQL_API
127 : SQLDescribeCol(SQLHSTMT StatementHandle,
128 : SQLUSMALLINT ColumnNumber,
129 : SQLCHAR *ColumnName,
130 : SQLSMALLINT BufferLength,
131 : SQLSMALLINT *NameLengthPtr,
132 : SQLSMALLINT *DataTypePtr,
133 : SQLULEN *ColumnSizePtr,
134 : SQLSMALLINT *DecimalDigitsPtr,
135 : SQLSMALLINT *NullablePtr)
136 : {
137 1580 : ODBCStmt *stmt = (ODBCStmt *) StatementHandle;
138 :
139 : #ifdef ODBCDEBUG
140 1580 : ODBCLOG("SQLDescribeCol %p %u %p %d %p %p %p %p %p\n",
141 : StatementHandle, (unsigned int) ColumnNumber,
142 : ColumnName, (int) BufferLength,
143 : NameLengthPtr, DataTypePtr,
144 : ColumnSizePtr, DecimalDigitsPtr,
145 : NullablePtr);
146 : #endif
147 :
148 1580 : if (!isValidStmt(stmt))
149 : return SQL_INVALID_HANDLE;
150 :
151 1580 : clearStmtErrors(stmt);
152 :
153 1580 : return MNDBDescribeCol(stmt,
154 : ColumnNumber,
155 : ColumnName,
156 : BufferLength,
157 : NameLengthPtr,
158 : DataTypePtr,
159 : ColumnSizePtr,
160 : DecimalDigitsPtr,
161 : NullablePtr);
162 : }
163 :
164 : SQLRETURN SQL_API
165 : SQLDescribeColA(SQLHSTMT StatementHandle,
166 : SQLUSMALLINT ColumnNumber,
167 : SQLCHAR *ColumnName,
168 : SQLSMALLINT BufferLength,
169 : SQLSMALLINT *NameLengthPtr,
170 : SQLSMALLINT *DataTypePtr,
171 : SQLULEN *ColumnSizePtr,
172 : SQLSMALLINT *DecimalDigitsPtr,
173 : SQLSMALLINT *NullablePtr)
174 : {
175 0 : return SQLDescribeCol(StatementHandle,
176 : ColumnNumber,
177 : ColumnName,
178 : BufferLength,
179 : NameLengthPtr,
180 : DataTypePtr,
181 : ColumnSizePtr,
182 : DecimalDigitsPtr,
183 : NullablePtr);
184 : }
185 :
186 : SQLRETURN SQL_API
187 : SQLDescribeColW(SQLHSTMT StatementHandle,
188 : SQLUSMALLINT ColumnNumber,
189 : SQLWCHAR *ColumnName,
190 : SQLSMALLINT BufferLength,
191 : SQLSMALLINT *NameLengthPtr,
192 : SQLSMALLINT *DataTypePtr,
193 : SQLULEN *ColumnSizePtr,
194 : SQLSMALLINT *DecimalDigitsPtr,
195 : SQLSMALLINT *NullablePtr)
196 : {
197 40 : ODBCStmt *stmt = (ODBCStmt *) StatementHandle;
198 40 : SQLCHAR *colname;
199 40 : SQLSMALLINT n;
200 40 : SQLRETURN rc = SQL_ERROR;
201 :
202 : #ifdef ODBCDEBUG
203 40 : ODBCLOG("SQLDescribeColW %p %u %p %d %p %p %p %p %p\n",
204 : StatementHandle, (unsigned int) ColumnNumber,
205 : ColumnName, (int) BufferLength,
206 : NameLengthPtr, DataTypePtr,
207 : ColumnSizePtr, DecimalDigitsPtr,
208 : NullablePtr);
209 : #endif
210 :
211 40 : if (!isValidStmt(stmt))
212 : return SQL_INVALID_HANDLE;
213 :
214 40 : clearStmtErrors(stmt);
215 :
216 40 : rc = MNDBDescribeCol(stmt, ColumnNumber, NULL, 0, &n, DataTypePtr,
217 : ColumnSizePtr, DecimalDigitsPtr, NullablePtr);
218 40 : if (!SQL_SUCCEEDED(rc))
219 : return rc;
220 40 : clearStmtErrors(stmt);
221 40 : n++; /* account for NUL byte */
222 40 : colname = malloc(n);
223 40 : if (colname == NULL) {
224 : /* Memory allocation error */
225 0 : addStmtError(stmt, "HY001", NULL, 0);
226 0 : return SQL_ERROR;
227 : }
228 40 : rc = MNDBDescribeCol(stmt,
229 : ColumnNumber,
230 : colname,
231 : n,
232 : &n,
233 : DataTypePtr,
234 : ColumnSizePtr,
235 : DecimalDigitsPtr,
236 : NullablePtr);
237 40 : if (SQL_SUCCEEDED(rc)) {
238 40 : fixWcharOut(rc, colname, n, ColumnName, BufferLength,
239 : NameLengthPtr, 1, addStmtError, stmt);
240 : }
241 40 : free(colname);
242 :
243 40 : return rc;
244 : }
|