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 (that's 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 : * SQLExecDirect()
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 : static SQLRETURN
37 108 : ODBCExecDirect(ODBCStmt *stmt, const SQLCHAR *StatementText, SQLINTEGER TextLength)
38 : {
39 108 : char *query;
40 108 : const char *err;
41 108 : MapiMsg ret;
42 108 : MapiHdl hdl;
43 108 : long timeout;
44 :
45 108 : hdl = stmt->hdl;
46 :
47 108 : if (stmt->State >= EXECUTED1 ||
48 8 : (stmt->State == EXECUTED0 && mapi_more_results(hdl))) {
49 : /* Invalid cursor state */
50 0 : addStmtError(stmt, "24000", NULL, 0);
51 0 : return SQL_ERROR;
52 : }
53 :
54 108 : if (stmt->qtimeout != stmt->Dbc->qtimeout) {
55 0 : char buf[48];
56 0 : snprintf(buf, sizeof(buf), "call sys.%s(%" PRIu64 ")",
57 0 : (stmt->Dbc->major == 11 && stmt->Dbc->minor >= 37)
58 : ? "setquerytimeout" : "settimeout",
59 : (uint64_t) stmt->qtimeout);
60 0 : if (mapi_query_handle(hdl, buf) == MOK)
61 0 : stmt->Dbc->qtimeout = stmt->qtimeout;
62 : }
63 :
64 108 : query = ODBCTranslateSQL(stmt->Dbc, StatementText, (size_t) TextLength,
65 : stmt->noScan);
66 108 : if (query == NULL) {
67 : /* Memory allocation error */
68 0 : addStmtError(stmt, "HY001", NULL, 0);
69 0 : return SQL_ERROR;
70 : }
71 :
72 108 : ODBCResetStmt(stmt);
73 :
74 : #ifdef ODBCDEBUG
75 108 : ODBCLOG("SQLExecDirect: \"%s\"\n", query);
76 : #endif
77 :
78 108 : if (stmt->next == NULL &&
79 107 : stmt->Dbc->FirstStmt == stmt &&
80 98 : stmt->cursorType == SQL_CURSOR_FORWARD_ONLY) {
81 : /* we're the only Stmt handle, and we're only going forward */
82 98 : if (stmt->Dbc->cachelimit != 10000)
83 13 : mapi_cache_limit(stmt->Dbc->mid, 10000);
84 98 : stmt->Dbc->cachelimit = 10000;
85 : } else {
86 10 : if (stmt->Dbc->cachelimit != 100)
87 1 : mapi_cache_limit(stmt->Dbc->mid, 100);
88 10 : stmt->Dbc->cachelimit = 100;
89 : }
90 108 : ret = mapi_query_handle(hdl, query);
91 108 : free(query);
92 108 : switch (ret) {
93 : case MOK:
94 105 : break;
95 0 : case MTIMEOUT:
96 : /* Connection timeout expired / Communication link failure */
97 0 : timeout = msetting_long(stmt->Dbc->settings, MP_REPLY_TIMEOUT);
98 0 : addStmtError(stmt, timeout > 0 ? "HYT01" : "08S01", mapi_error_str(stmt->Dbc->mid), 0);
99 0 : return SQL_ERROR;
100 3 : default:
101 3 : err = mapi_result_error(hdl);
102 3 : if (err == NULL)
103 0 : err = mapi_error_str(stmt->Dbc->mid);
104 0 : if (err != NULL) {
105 3 : const char *e = mapi_result_errorcode(hdl);
106 :
107 3 : if (e) {
108 3 : addStmtError(stmt, e, err, 0);
109 3 : return SQL_ERROR;
110 : }
111 : }
112 : /* General error */
113 0 : addStmtError(stmt, "HY000", err, 0);
114 0 : return SQL_ERROR;
115 : }
116 :
117 : /* now get the result data and store it to our internal data
118 : * structure */
119 :
120 105 : return ODBCInitResult(stmt);
121 : }
122 :
123 : SQLRETURN
124 108 : MNDBExecDirect(ODBCStmt *stmt,
125 : const SQLCHAR *StatementText,
126 : SQLINTEGER TextLength)
127 : {
128 108 : SQLRETURN ret;
129 108 : SQLINTEGER i;
130 :
131 : /* check input parameter */
132 108 : if (StatementText == NULL) {
133 : /* Invalid use of null pointer */
134 0 : addStmtError(stmt, "HY009", NULL, 0);
135 0 : return SQL_ERROR;
136 : }
137 :
138 108 : fixODBCstring(StatementText, TextLength, SQLINTEGER,
139 : addStmtError, stmt, return SQL_ERROR);
140 174448 : for (i = 0; i < TextLength; i++)
141 : /* TODO FIX: only when the statement starts with PREPARE the
142 : questions marks have a special meaning */
143 174340 : if (StatementText[i] == '?') {
144 : /* query may have parameters, take the long route */
145 0 : ret = MNDBPrepare(stmt, StatementText, TextLength);
146 0 : if (ret == SQL_SUCCESS)
147 0 : ret = MNDBExecute(stmt);
148 0 : return ret;
149 : }
150 :
151 : /* no parameters, take the direct route */
152 108 : return ODBCExecDirect(stmt, StatementText, TextLength);
153 : }
154 :
155 : SQLRETURN SQL_API
156 : SQLExecDirect(SQLHSTMT StatementHandle,
157 : SQLCHAR *StatementText,
158 : SQLINTEGER TextLength)
159 : {
160 : #ifdef ODBCDEBUG
161 25 : ODBCLOG("SQLExecDirect %p\n", StatementHandle);
162 : #endif
163 :
164 25 : if (!isValidStmt((ODBCStmt *) StatementHandle))
165 : return SQL_INVALID_HANDLE;
166 :
167 25 : clearStmtErrors((ODBCStmt *) StatementHandle);
168 :
169 25 : return MNDBExecDirect((ODBCStmt *) StatementHandle,
170 : StatementText,
171 : TextLength);
172 : }
173 :
174 : SQLRETURN SQL_API
175 : SQLExecDirectA(SQLHSTMT StatementHandle,
176 : SQLCHAR *StatementText,
177 : SQLINTEGER TextLength)
178 : {
179 0 : return SQLExecDirect(StatementHandle, StatementText, TextLength);
180 : }
181 :
182 : SQLRETURN SQL_API
183 : SQLExecDirectW(SQLHSTMT StatementHandle,
184 : SQLWCHAR *StatementText,
185 : SQLINTEGER TextLength)
186 : {
187 1 : ODBCStmt *stmt = (ODBCStmt *) StatementHandle;
188 1 : SQLRETURN rc;
189 1 : SQLCHAR *sql;
190 :
191 : #ifdef ODBCDEBUG
192 1 : ODBCLOG("SQLExecDirectW %p\n", StatementHandle);
193 : #endif
194 :
195 1 : if (!isValidStmt(stmt))
196 : return SQL_INVALID_HANDLE;
197 :
198 1 : clearStmtErrors(stmt);
199 :
200 1 : fixWcharIn(StatementText, TextLength, SQLCHAR, sql,
201 : addStmtError, stmt, return SQL_ERROR);
202 :
203 1 : rc = MNDBExecDirect((ODBCStmt *) StatementHandle, sql, SQL_NTS);
204 :
205 1 : if (sql)
206 1 : free(sql);
207 :
208 : return rc;
209 : }
|