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 : * SQLFetch()
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 : SQLRETURN
37 2648 : MNDBFetch(ODBCStmt *stmt, SQLUSMALLINT *RowStatusArray)
38 : {
39 2648 : ODBCDesc *ard, *ird;
40 2648 : ODBCDescRec *rec;
41 2648 : int i;
42 2648 : SQLULEN row;
43 2648 : SQLLEN offset;
44 :
45 : /* stmt->startRow is the (0 based) index of the first row we
46 : * stmt->need to fetch */
47 :
48 2648 : ard = stmt->ApplRowDescr;
49 2648 : ird = stmt->ImplRowDescr;
50 :
51 2648 : stmt->retrieved = 0;
52 2648 : stmt->currentCol = 0;
53 :
54 2648 : stmt->rowSetSize = 0;
55 2648 : stmt->currentRow = stmt->startRow + 1;
56 2648 : if (mapi_seek_row(stmt->hdl, stmt->startRow, MAPI_SEEK_SET) != MOK) {
57 : /* Row value out of range */
58 0 : addStmtError(stmt, "HY107", mapi_error_str(stmt->Dbc->mid), 0);
59 0 : return SQL_ERROR;
60 : }
61 :
62 2648 : stmt->State = FETCHED;
63 :
64 2648 : if (stmt->retrieveData == SQL_RD_OFF) {
65 : /* don't really retrieve the data, just do as if,
66 : updating the SQL_DESC_ARRAY_STATUS_PTR */
67 0 : stmt->rowSetSize = ard->sql_desc_array_size;
68 :
69 0 : if (stmt->startRow + stmt->rowSetSize > (SQLLEN) stmt->rowcount)
70 0 : stmt->rowSetSize = stmt->rowcount - stmt->startRow;
71 :
72 0 : if (stmt->rowSetSize <= 0) {
73 0 : stmt->rowSetSize = 0;
74 0 : return SQL_NO_DATA;
75 : }
76 0 : if (RowStatusArray) {
77 0 : for (row = 0; (SQLLEN) row < stmt->rowSetSize; row++) {
78 0 : WriteValue(RowStatusArray, SQL_ROW_SUCCESS);
79 0 : RowStatusArray++;
80 : }
81 0 : for (; row < ard->sql_desc_array_size; row++) {
82 0 : WriteValue(RowStatusArray, SQL_ROW_NOROW);
83 0 : RowStatusArray++;
84 : }
85 : }
86 0 : return SQL_SUCCESS;
87 : }
88 :
89 2648 : if (ard->sql_desc_bind_offset_ptr)
90 0 : offset = *ard->sql_desc_bind_offset_ptr;
91 : else
92 : offset = 0;
93 5211 : for (row = 0; row < ard->sql_desc_array_size; row++) {
94 2648 : if (mapi_fetch_row(stmt->hdl) == 0) {
95 85 : switch (mapi_error(stmt->Dbc->mid)) {
96 85 : case MOK:
97 85 : if (row == 0)
98 : return SQL_NO_DATA;
99 : break;
100 0 : case MTIMEOUT:
101 0 : if (RowStatusArray)
102 0 : WriteValue(RowStatusArray, SQL_ROW_ERROR);
103 : /* Timeout expired / Communication
104 : * link failure */
105 0 : addStmtError(stmt, stmt->Dbc->sql_attr_connection_timeout ? "HYT00" : "08S01", mapi_error_str(stmt->Dbc->mid), 0);
106 0 : return SQL_ERROR;
107 0 : default:
108 0 : if (RowStatusArray)
109 0 : WriteValue(RowStatusArray, SQL_ROW_ERROR);
110 : /* General error */
111 0 : addStmtError(stmt, "HY000", mapi_error_str(stmt->Dbc->mid), 0);
112 0 : return SQL_ERROR;
113 : }
114 : break;
115 : }
116 2563 : if (RowStatusArray)
117 0 : WriteValue(RowStatusArray, SQL_ROW_SUCCESS);
118 :
119 2563 : stmt->rowSetSize++;
120 :
121 19139 : for (i = 1; i <= ird->sql_desc_count; i++)
122 16576 : ird->descRec[i].already_returned = -1;
123 :
124 12648 : for (i = 1; i <= ard->sql_desc_count; i++) {
125 10085 : rec = &ard->descRec[i];
126 10085 : if (rec->sql_desc_data_ptr == NULL)
127 75 : continue;
128 10010 : stmt->retrieved = 0;
129 10010 : if (ODBCFetch(stmt, i,
130 10010 : rec->sql_desc_concise_type,
131 : rec->sql_desc_data_ptr,
132 : rec->sql_desc_octet_length,
133 : rec->sql_desc_octet_length_ptr,
134 : rec->sql_desc_indicator_ptr,
135 10010 : rec->sql_desc_precision,
136 10010 : rec->sql_desc_scale,
137 : rec->sql_desc_datetime_interval_precision,
138 : offset, row) == SQL_ERROR) {
139 0 : if (RowStatusArray)
140 10085 : WriteValue(RowStatusArray, SQL_ROW_SUCCESS_WITH_INFO);
141 : }
142 : }
143 2563 : if (RowStatusArray)
144 0 : RowStatusArray++;
145 : }
146 2563 : if (ird->sql_desc_rows_processed_ptr)
147 0 : *ird->sql_desc_rows_processed_ptr = (SQLULEN) stmt->rowSetSize;
148 :
149 2563 : if (RowStatusArray)
150 0 : while (row++ < ard->sql_desc_array_size) {
151 0 : WriteValue(RowStatusArray, SQL_ROW_NOROW);
152 0 : RowStatusArray++;
153 : }
154 :
155 2563 : return stmt->Error ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
156 : }
157 :
158 : SQLRETURN SQL_API
159 : SQLFetch(SQLHSTMT StatementHandle)
160 : {
161 1647 : ODBCStmt *stmt = (ODBCStmt *) StatementHandle;
162 :
163 : #ifdef ODBCDEBUG
164 1647 : ODBCLOG("SQLFetch %p\n", StatementHandle);
165 : #endif
166 :
167 1647 : if (!isValidStmt(stmt))
168 : return SQL_INVALID_HANDLE;
169 :
170 1647 : clearStmtErrors(stmt);
171 :
172 1647 : assert(stmt->hdl);
173 :
174 : /* check statement cursor state, query should be executed */
175 1647 : if (stmt->State < EXECUTED0 || stmt->State == EXTENDEDFETCHED) {
176 : /* Function sequence error */
177 0 : addStmtError(stmt, "HY010", NULL, 0);
178 0 : return SQL_ERROR;
179 : }
180 1647 : if (stmt->State == EXECUTED0) {
181 : /* Invalid cursor state */
182 0 : addStmtError(stmt, "24000", NULL, 0);
183 0 : return SQL_ERROR;
184 : }
185 :
186 1647 : stmt->startRow += stmt->rowSetSize;
187 :
188 1647 : return MNDBFetch(stmt, stmt->ImplRowDescr->sql_desc_array_status_ptr);
189 : }
|