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 : * SQLBindCol() 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 : 35 : 36 : SQLRETURN SQL_API 37 : SQLBindCol(SQLHSTMT StatementHandle, 38 : SQLUSMALLINT ColumnNumber, 39 : SQLSMALLINT TargetType, 40 : SQLPOINTER TargetValuePtr, 41 : SQLLEN BufferLength, 42 : SQLLEN *StrLen_or_Ind) 43 : { 44 12 : ODBCStmt *stmt = (ODBCStmt *) StatementHandle; 45 12 : ODBCDesc *desc; /* Application Row Descriptor */ 46 : 47 : #ifdef ODBCDEBUG 48 12 : ODBCLOG("SQLBindCol %p %u %s %p " LENFMT "\n", 49 : StatementHandle, (unsigned int) ColumnNumber, 50 : translateCType(TargetType), TargetValuePtr, 51 : LENCAST BufferLength); 52 : #endif 53 : 54 12 : if (!isValidStmt(stmt)) 55 : return SQL_INVALID_HANDLE; 56 : 57 12 : assert(stmt->Dbc); 58 : 59 12 : clearStmtErrors(stmt); 60 : 61 : /* check input parameters */ 62 : /* column number 0 (Bookmark column) is not supported */ 63 12 : if (ColumnNumber == 0) { 64 0 : if (TargetType == SQL_C_BOOKMARK || TargetType == SQL_C_VARBOOKMARK) { 65 : /* Optional feature not implemented */ 66 0 : addStmtError(stmt, "HYC00", NULL, 0); 67 : } else { 68 : /* Restricted data type attribute violation */ 69 0 : addStmtError(stmt, "07006", NULL, 0); 70 : } 71 0 : return SQL_ERROR; 72 : } 73 12 : if (stmt->State >= EXECUTED1 && ColumnNumber > stmt->ImplRowDescr->sql_desc_count) { 74 : /* Invalid descriptor index */ 75 0 : addStmtError(stmt, "07009", NULL, 0); 76 0 : return SQL_ERROR; 77 : } 78 : 79 : /* For safety: limit the maximum number of columns to bind */ 80 12 : if (ColumnNumber > MONETDB_MAX_BIND_COLS) { 81 : /* General error */ 82 0 : addStmtError(stmt, "HY000", "Maximum number of bind columns (8192) exceeded", 0); 83 0 : return SQL_ERROR; 84 : } 85 : 86 : /* can't let SQLSetDescField below do this check since it 87 : returns the wrong error code if the type is incorrect */ 88 12 : switch (TargetType) { 89 : case SQL_C_CHAR: 90 : case SQL_C_WCHAR: 91 : case SQL_C_BINARY: 92 : case SQL_C_BIT: 93 : case SQL_C_STINYINT: 94 : case SQL_C_UTINYINT: 95 : case SQL_C_TINYINT: 96 : case SQL_C_SSHORT: 97 : case SQL_C_USHORT: 98 : case SQL_C_SHORT: 99 : case SQL_C_SLONG: 100 : case SQL_C_ULONG: 101 : case SQL_C_LONG: 102 : case SQL_C_SBIGINT: 103 : case SQL_C_UBIGINT: 104 : case SQL_C_NUMERIC: 105 : case SQL_C_FLOAT: 106 : case SQL_C_DOUBLE: 107 : case SQL_C_TYPE_DATE: 108 : case SQL_C_TYPE_TIME: 109 : case SQL_C_TYPE_TIMESTAMP: 110 : case SQL_C_INTERVAL_YEAR: 111 : case SQL_C_INTERVAL_MONTH: 112 : case SQL_C_INTERVAL_YEAR_TO_MONTH: 113 : case SQL_C_INTERVAL_DAY: 114 : case SQL_C_INTERVAL_HOUR: 115 : case SQL_C_INTERVAL_MINUTE: 116 : case SQL_C_INTERVAL_SECOND: 117 : case SQL_C_INTERVAL_DAY_TO_HOUR: 118 : case SQL_C_INTERVAL_DAY_TO_MINUTE: 119 : case SQL_C_INTERVAL_DAY_TO_SECOND: 120 : case SQL_C_INTERVAL_HOUR_TO_MINUTE: 121 : case SQL_C_INTERVAL_HOUR_TO_SECOND: 122 : case SQL_C_INTERVAL_MINUTE_TO_SECOND: 123 : case SQL_C_GUID: 124 : case SQL_C_DEFAULT: 125 12 : break; 126 0 : default: 127 : /* Invalid application buffer type */ 128 0 : addStmtError(stmt, "HY003", NULL, 0); 129 0 : return SQL_ERROR; 130 : } 131 : 132 12 : if (BufferLength < 0) { 133 : /* Invalid string or buffer length */ 134 0 : addStmtError(stmt, "HY090", NULL, 0); 135 0 : return SQL_ERROR; 136 : } 137 : 138 12 : desc = stmt->ApplRowDescr; 139 : 140 12 : if (TargetValuePtr == NULL && ColumnNumber == desc->sql_desc_count) { 141 0 : int i = desc->sql_desc_count - 1; 142 : 143 0 : while (i > 0 && desc->descRec[i].sql_desc_data_ptr == NULL) 144 0 : i--; 145 0 : setODBCDescRecCount(desc, i); 146 : } else { 147 12 : ODBCDescRec *rec; 148 12 : SQLRETURN rc; 149 : 150 12 : if (ColumnNumber > desc->sql_desc_count) 151 12 : setODBCDescRecCount(desc, ColumnNumber); 152 12 : rc = MNDBSetDescField(desc, ColumnNumber, SQL_DESC_CONCISE_TYPE, (SQLPOINTER) (intptr_t) TargetType, 0); 153 12 : if (!SQL_SUCCEEDED(rc)) 154 : return rc; 155 12 : rec = &desc->descRec[ColumnNumber]; 156 12 : rec->sql_desc_octet_length = BufferLength; 157 12 : rec->sql_desc_data_ptr = TargetValuePtr; 158 12 : rec->sql_desc_indicator_ptr = StrLen_or_Ind; 159 12 : rec->sql_desc_octet_length_ptr = StrLen_or_Ind; 160 : } 161 : 162 : return SQL_SUCCESS; 163 : }