HandleStmt.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:24k
- /* Copyright (C) 2003 MySQL AB
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
- #include <common/OdbcData.hpp>
- #include <codegen/CodeGen.hpp>
- #include "HandleRoot.hpp"
- #include "HandleDbc.hpp"
- #include "HandleStmt.hpp"
- #include "HandleDesc.hpp"
- HandleStmt::HandleStmt(HandleDbc* pDbc) :
- StmtArea(*pDbc),
- m_dbc(pDbc),
- m_attrArea(m_attrSpec)
- {
- m_attrArea.setHandle(this);
- for (unsigned i = 0; i <= 1; i++) {
- for (unsigned u = 0; u <= 4; u++) {
- m_handleDesc[i][u] = 0;
- }
- }
- }
- HandleStmt::~HandleStmt()
- {
- }
- void
- HandleStmt::ctor(Ctx& ctx)
- {
- for (unsigned u = 1; u <= 4; u++) {
- HandleDesc** ppDesc = &m_handleDesc[0][u];
- m_dbc->sqlAllocDesc(ctx, ppDesc);
- if (! ctx.ok())
- return;
- m_descArea[u] = &(*ppDesc)->descArea();
- m_descArea[u]->setAlloc(Desc_alloc_auto);
- m_descArea[u]->setUsage((DescUsage)u);
- }
- }
- void
- HandleStmt::dtor(Ctx& ctx)
- {
- free(ctx);
- for (unsigned u = 1; u <= 4; u++) {
- HandleDesc** ppDesc = &m_handleDesc[0][u];
- if (*ppDesc != 0)
- m_dbc->sqlFreeDesc(ctx, *ppDesc);
- *ppDesc = 0;
- }
- }
- // descriptor handles
- HandleDesc*
- HandleStmt::getHandleDesc(Ctx& ctx, DescUsage u) const
- {
- ctx_assert(1 <= u && u <= 4);
- if (m_handleDesc[1][u] != 0)
- return m_handleDesc[1][u];
- return m_handleDesc[0][u];
- }
- void
- HandleStmt::setHandleDesc(Ctx& ctx, DescUsage u, SQLPOINTER handle)
- {
- ctx_assert(1 <= u && u <= 4);
- if (handle == SQL_NULL_HDESC) {
- m_handleDesc[1][u] = 0; // revert to implicit
- m_descArea[u] = &m_handleDesc[0][u]->descArea();
- return;
- }
- HandleDesc* pDesc = getRoot()->findDesc(handle);
- if (pDesc == 0) {
- ctx.pushStatus(Sqlstate::_HY024, Error::Gen, "cannot set %s handle to invalid descriptor handle %x", DescArea::nameUsage(u), (unsigned)handle);
- return;
- }
- if (pDesc == m_handleDesc[0][u]) {
- m_handleDesc[1][u] = 0; // revert to implicit
- m_descArea[u] = &m_handleDesc[0][u]->descArea();
- return;
- }
- // XXX should check implicit handles on all statements
- for (unsigned v = 1; v <= 4; v++) {
- if (pDesc == m_handleDesc[0][v]) {
- ctx.pushStatus(Sqlstate::_HY024, Error::Gen, "cannot set %s handle to implicitly allocated %s handle", DescArea::nameUsage(u), DescArea::nameUsage((DescUsage)v));
- return;
- }
- }
- m_handleDesc[1][u] = pDesc;
- m_descArea[u] = &m_handleDesc[1][u]->descArea();
- }
- // allocate and free handles (no valid case)
- void
- HandleStmt::sqlAllocHandle(Ctx& ctx, SQLSMALLINT childType, HandleBase** ppChild)
- {
- ctx.pushStatus(Sqlstate::_HY092, Error::Gen, "inappropriate handle type");
- }
- void
- HandleStmt::sqlFreeHandle(Ctx& ctx, SQLSMALLINT childType, HandleBase* ppChild)
- {
- ctx.pushStatus(Sqlstate::_HY092, Error::Gen, "inappropriate handle type");
- }
- // attributes and info
- static bool
- ignore_attr(Ctx& ctx, SQLINTEGER attribute)
- {
- switch (attribute) {
- case 1211:
- case 1227:
- case 1228:
- ctx_log2(("ignore unknown ADO.NET stmt attribute %d", (int)attribute));
- return true;
- }
- return false;
- }
- void
- HandleStmt::sqlSetStmtAttr(Ctx& ctx, SQLINTEGER attribute, SQLPOINTER value, SQLINTEGER stringLength)
- {
- if (ignore_attr(ctx, attribute))
- return;
- baseSetHandleAttr(ctx, m_attrArea, attribute, value, stringLength);
- }
- void
- HandleStmt::sqlGetStmtAttr(Ctx& ctx, SQLINTEGER attribute, SQLPOINTER value, SQLINTEGER bufferLength, SQLINTEGER* stringLength)
- {
- if (ignore_attr(ctx, attribute))
- return;
- baseGetHandleAttr(ctx, m_attrArea, attribute, value, bufferLength, stringLength);
- }
- void
- HandleStmt::sqlSetStmtOption(Ctx& ctx, SQLUSMALLINT option, SQLUINTEGER value)
- {
- if (ignore_attr(ctx, option))
- return;
- baseSetHandleOption(ctx, m_attrArea, option, value);
- }
- void
- HandleStmt::sqlGetStmtOption(Ctx& ctx, SQLUSMALLINT option, SQLPOINTER value)
- {
- if (ignore_attr(ctx, option))
- return;
- baseGetHandleOption(ctx, m_attrArea, option, value);
- }
- void
- HandleStmt::sqlGetTypeInfo(Ctx& ctx, SQLSMALLINT dataType)
- {
- BaseString text;
- // odbc$typeinfo is a (possible unordered) view matching SQLGetTypeInfo result set
- text.append("SELECT * FROM odbc$typeinfo");
- if (dataType != SQL_ALL_TYPES) {
- switch (dataType) {
- case SQL_CHAR:
- case SQL_VARCHAR:
- case SQL_BINARY:
- case SQL_VARBINARY:
- case SQL_SMALLINT:
- case SQL_INTEGER:
- case SQL_BIGINT:
- case SQL_REAL:
- case SQL_DOUBLE:
- break;
- default:
- // XXX unsupported vs illegal
- ctx_log1(("sqlGetTypeInfo: unknown data type %d", (int)dataType));
- break;
- }
- text.appfmt(" WHERE data_type = %d", (int)dataType);
- }
- // sort signed before unsigned
- text.append(" ORDER BY data_type, unsigned_attribute, type_name");
- sqlExecDirect(ctx, (SQLCHAR*)text.c_str(), text.length());
- }
- void
- HandleStmt::sqlTables(Ctx& ctx, SQLCHAR* catalogName, SQLSMALLINT nameLength1, SQLCHAR* schemaName, SQLSMALLINT nameLength2, SQLCHAR* tableName, SQLSMALLINT nameLength3, SQLCHAR* tableType, SQLSMALLINT nameLength4)
- {
- BaseString text;
- // odbc$tables is a (possibly unordered) view matching SQLTables result set
- text.append("SELECT * FROM odbc$tables");
- SQLUINTEGER metadata_id = SQL_FALSE;
- sqlGetStmtAttr(ctx, SQL_ATTR_METADATA_ID, (SQLPOINTER)&metadata_id, SQL_IS_POINTER, 0);
- if (! ctx.ok())
- return;
- unsigned count = 0;
- if (catalogName != 0) {
- OdbcData data;
- data.copyin(ctx, OdbcData::Sqlchar, (SQLPOINTER)catalogName, nameLength1);
- if (! ctx.ok())
- return;
- text.append(++count == 1 ? " WHERE" : " AND");
- if (getOdbcVersion(ctx) == 2)
- text.appfmt(" table_cat = '%s'", data.sqlchar());
- else if (metadata_id == SQL_TRUE)
- text.appfmt(" table_cat = '%s'", data.sqlchar()); // XXX UPPER
- else
- text.appfmt(" table_cat LIKE '%s'", data.sqlchar());
- }
- if (schemaName != 0) {
- OdbcData data;
- data.copyin(ctx, OdbcData::Sqlchar, (SQLPOINTER)schemaName, nameLength2);
- if (! ctx.ok())
- return;
- text.append(++count == 1 ? " WHERE" : " AND");
- if (metadata_id == SQL_TRUE)
- text.appfmt(" table_schem = '%s'", data.sqlchar()); // XXX UPPER
- else
- text.appfmt(" table_schem LIKE '%s'", data.sqlchar());
- }
- if (tableName != 0) {
- OdbcData data;
- data.copyin(ctx, OdbcData::Sqlchar, (SQLPOINTER)tableName, nameLength3);
- if (! ctx.ok())
- return;
- text.append(++count == 1 ? " WHERE" : " AND");
- if (metadata_id == SQL_TRUE)
- text.appfmt(" table_name = '%s'", data.sqlchar()); // XXX UPPER
- else
- text.appfmt(" table_name LIKE '%s'", data.sqlchar());
- }
- if (tableType != 0) {
- OdbcData data;
- data.copyin(ctx, OdbcData::Sqlchar, (SQLPOINTER)tableType, nameLength4);
- if (! ctx.ok())
- return;
- text.append(++count == 1 ? " WHERE" : " AND");
- text.appfmt(" table_type IN (%s)", data.sqlchar()); // XXX UPPER, quotes
- }
- text.append(" ORDER BY table_type, table_cat, table_schem, table_name");
- sqlExecDirect(ctx, (SQLCHAR*)text.c_str(), text.length());
- }
- void
- HandleStmt::sqlColumns(Ctx& ctx, SQLCHAR* catalogName, SQLSMALLINT nameLength1, SQLCHAR* schemaName, SQLSMALLINT nameLength2, SQLCHAR* tableName, SQLSMALLINT nameLength3, SQLCHAR* columnName, SQLSMALLINT nameLength4)
- {
- BaseString text;
- // odbc$columns is a (possibly unordered) view matching SQLColumns result set
- text.append("SELECT * FROM odbc$columns");
- SQLUINTEGER metadata_id = SQL_FALSE;
- sqlGetStmtAttr(ctx, SQL_ATTR_METADATA_ID, (SQLPOINTER)&metadata_id, SQL_IS_POINTER, 0);
- if (! ctx.ok())
- return;
- unsigned count = 0;
- if (catalogName != 0) {
- OdbcData data;
- data.copyin(ctx, OdbcData::Sqlchar, (SQLPOINTER)catalogName, nameLength1);
- if (! ctx.ok())
- return;
- text.append(++count == 1 ? " WHERE" : " AND");
- if (getOdbcVersion(ctx) == 2)
- text.appfmt(" table_cat = '%s'", data.sqlchar());
- else if (metadata_id == SQL_TRUE)
- text.appfmt(" table_cat = '%s'", data.sqlchar()); // XXX UPPER
- else
- text.appfmt(" table_cat LIKE '%s'", data.sqlchar());
- }
- if (schemaName != 0) {
- OdbcData data;
- data.copyin(ctx, OdbcData::Sqlchar, (SQLPOINTER)schemaName, nameLength2);
- if (! ctx.ok())
- return;
- text.append(++count == 1 ? " WHERE" : " AND");
- if (metadata_id == SQL_TRUE)
- text.appfmt(" table_schem = '%s'", data.sqlchar()); // XXX UPPER
- else
- text.appfmt(" table_schem LIKE '%s'", data.sqlchar());
- }
- if (tableName != 0) {
- OdbcData data;
- data.copyin(ctx, OdbcData::Sqlchar, (SQLPOINTER)tableName, nameLength3);
- if (! ctx.ok())
- return;
- text.append(++count == 1 ? " WHERE" : " AND");
- if (metadata_id == SQL_TRUE)
- text.appfmt(" table_name = '%s'", data.sqlchar()); // XXX UPPER
- else
- text.appfmt(" table_name LIKE '%s'", data.sqlchar());
- }
- if (columnName != 0) {
- OdbcData data;
- data.copyin(ctx, OdbcData::Sqlchar, (SQLPOINTER)columnName, nameLength4);
- if (! ctx.ok())
- return;
- text.append(++count == 1 ? " WHERE" : " AND");
- if (metadata_id == SQL_TRUE)
- text.appfmt(" column_name = '%s'", data.sqlchar()); // XXX UPPER
- else
- text.appfmt(" column_name LIKE '%s'", data.sqlchar());
- }
- text.append(" ORDER BY table_cat, table_schem, table_name, ordinal_position");
- sqlExecDirect(ctx, (SQLCHAR*)text.c_str(), text.length());
- }
- void
- HandleStmt::sqlPrimaryKeys(Ctx& ctx, SQLCHAR* szCatalogName, SQLSMALLINT cbCatalogName, SQLCHAR* szSchemaName, SQLSMALLINT cbSchemaName, SQLCHAR* szTableName, SQLSMALLINT cbTableName)
- {
- BaseString text;
- // odbc$primarykeys is a (possible unordered) view matching SQLPrimaryKeys result set
- text.append("SELECT * FROM odbc$primarykeys");
- SQLUINTEGER metadata_id = SQL_FALSE;
- sqlGetStmtAttr(ctx, SQL_ATTR_METADATA_ID, (SQLPOINTER)&metadata_id, SQL_IS_POINTER, 0);
- if (! ctx.ok())
- return;
- unsigned count = 0;
- if (szCatalogName != 0) {
- OdbcData data;
- data.copyin(ctx, OdbcData::Sqlchar, (SQLPOINTER)szCatalogName, cbCatalogName);
- if (! ctx.ok())
- return;
- text.append(++count == 1 ? " WHERE" : " AND");
- if (getOdbcVersion(ctx) == 2)
- text.appfmt(" table_cat = '%s'", data.sqlchar());
- else if (metadata_id == SQL_TRUE)
- text.appfmt(" table_cat = '%s'", data.sqlchar()); // XXX UPPER
- else
- text.appfmt(" table_cat = '%s'", data.sqlchar()); // no pattern
- }
- if (szSchemaName != 0) {
- OdbcData data;
- data.copyin(ctx, OdbcData::Sqlchar, (SQLPOINTER)szSchemaName, cbSchemaName);
- if (! ctx.ok())
- return;
- text.append(++count == 1 ? " WHERE" : " AND");
- if (metadata_id == SQL_TRUE)
- text.appfmt(" table_schem = '%s'", data.sqlchar()); // XXX UPPER
- else
- text.appfmt(" table_schem = '%s'", data.sqlchar()); // no pattern
- }
- if (szTableName != 0) {
- OdbcData data;
- data.copyin(ctx, OdbcData::Sqlchar, (SQLPOINTER)szTableName, cbTableName);
- if (! ctx.ok())
- return;
- text.append(++count == 1 ? " WHERE" : " AND");
- if (metadata_id == SQL_TRUE)
- text.appfmt(" table_name = '%s'", data.sqlchar()); // XXX UPPER
- else
- text.appfmt(" table_name = '%s'", data.sqlchar()); // no pattern
- } else { // no null
- ctx.pushStatus(Sqlstate::_HY009, Error::Gen, "null table name");
- return;
- }
- text.append(" ORDER BY table_cat, table_schem, table_name, key_seq");
- sqlExecDirect(ctx, (SQLCHAR*)text.c_str(), text.length());
- }
- int
- HandleStmt::getOdbcVersion(Ctx& ctx)
- {
- return m_dbc->getOdbcVersion(ctx);
- }
- // prepare and execute
- void
- HandleStmt::sqlPrepare(Ctx& ctx, SQLCHAR* statementText, SQLINTEGER textLength)
- {
- if (m_state == Open) {
- ctx.pushStatus(Sqlstate::_24000, Error::Gen, "cursor is open");
- return;
- }
- free(ctx);
- const char* text = reinterpret_cast<char*>(statementText);
- if (textLength == SQL_NTS) {
- m_sqlText.assign(text);
- } else if (textLength >= 0) {
- m_sqlText.assign(text, textLength);
- } else {
- ctx.pushStatus(Sqlstate::_HY090, Error::Gen, "missing SQL text");
- return;
- }
- if (! useSchemaCon(ctx, true))
- return;
- CodeGen codegen(*this);
- codegen.prepare(ctx);
- useSchemaCon(ctx, false);
- if (! ctx.ok()) {
- free(ctx);
- return;
- }
- ctx_log2(("prepared %s statement", m_stmtInfo.getDesc()));
- m_state = Prepared;
- }
- void
- HandleStmt::sqlExecute(Ctx& ctx)
- {
- if (m_state == Open) {
- ctx.pushStatus(Sqlstate::_24000, Error::Gen, "cursor is open");
- return;
- }
- StmtType stmtType = m_stmtInfo.getType();
- switch (stmtType) {
- case Stmt_type_DDL:
- if (! useSchemaCon(ctx, true))
- return;
- break;
- case Stmt_type_query:
- case Stmt_type_DML:
- if (! useConnection(ctx, true))
- return;
- break;
- default:
- ctx_assert(false);
- break;
- }
- CodeGen codegen(*this);
- codegen.execute(ctx);
- // valid only after execute says M$ XXX create this diag only on demand
- setFunction(ctx);
- if (ctx.getCode() == SQL_NEED_DATA) {
- m_state = NeedData;
- return;
- }
- ctx_log2(("execute: fetched %u tuples from NDB", (unsigned)m_tuplesFetched));
- switch (stmtType) {
- case Stmt_type_DDL:
- codegen.close(ctx);
- useSchemaCon(ctx, false);
- m_state = Prepared;
- break;
- case Stmt_type_query:
- if (! ctx.ok()) {
- codegen.close(ctx);
- useConnection(ctx, false);
- m_state = Prepared;
- } else {
- m_state = Open;
- }
- break;
- case Stmt_type_DML:
- codegen.close(ctx);
- if (m_dbc->autocommit()) {
- // even if error
- m_dbc->sqlEndTran(ctx, SQL_COMMIT);
- } else {
- m_dbc->uncommitted(true); // uncommitted changes possible
- }
- useConnection(ctx, false);
- m_state = Prepared;
- break;
- default:
- ctx_assert(false);
- break;
- }
- }
- void
- HandleStmt::sqlExecDirect(Ctx& ctx, SQLCHAR* statementText, SQLINTEGER textLength)
- {
- sqlPrepare(ctx, statementText, textLength);
- if (! ctx.ok())
- return;
- sqlExecute(ctx);
- }
- void
- HandleStmt::sqlFetch(Ctx& ctx)
- {
- if (m_state != Open) {
- ctx.pushStatus(Sqlstate::_24000, Error::Gen, "cursor is not open");
- return;
- }
- StmtType stmtType = m_stmtInfo.getType();
- switch (stmtType) {
- case Stmt_type_query: {
- CodeGen codegen(*this);
- codegen.fetch(ctx);
- if (! ctx.ok()) {
- codegen.close(ctx);
- useConnection(ctx, false);
- }
- break;
- }
- default:
- ctx_assert(false);
- break;
- }
- }
- void
- HandleStmt::sqlRowCount(Ctx& ctx, SQLINTEGER* rowCount)
- {
- *rowCount = m_rowCount;
- }
- void
- HandleStmt::sqlMoreResults(Ctx& ctx)
- {
- if (m_state == Open) {
- sqlCloseCursor(ctx);
- if (! ctx.ok())
- return;
- }
- ctx.setCode(SQL_NO_DATA);
- }
- void
- HandleStmt::sqlCancel(Ctx& ctx)
- {
- if (m_state == NeedData) {
- CodeGen codegen(*this);
- codegen.close(ctx);
- m_state = Prepared;
- }
- }
- void
- HandleStmt::sqlCloseCursor(Ctx& ctx)
- {
- if (m_state != Open) {
- ctx.pushStatus(Sqlstate::_24000, Error::Gen, "cursor is not open");
- return;
- }
- ctx_log2(("execute: fetched %u tuples from NDB", (unsigned)m_tuplesFetched));
- StmtType stmtType = m_stmtInfo.getType();
- switch (stmtType) {
- case Stmt_type_query: {
- CodeGen codegen(*this);
- codegen.close(ctx);
- useConnection(ctx, false);
- m_state = Prepared;
- m_rowCount = 0;
- m_tuplesFetched = 0;
- break;
- }
- default:
- ctx_assert(false);
- break;
- }
- }
- void
- HandleStmt::sqlGetCursorName(Ctx& ctx, SQLCHAR* cursorName, SQLSMALLINT bufferLength, SQLSMALLINT* nameLength)
- {
- OdbcData name("SQL_CUR_DUMMY");
- name.copyout(ctx, cursorName, bufferLength, 0, nameLength);
- }
- void
- HandleStmt::sqlSetCursorName(Ctx& ctx, SQLCHAR* cursorName, SQLSMALLINT nameLength)
- {
- }
- // special data access
- void
- HandleStmt::sqlGetData(Ctx& ctx, SQLUSMALLINT columnNumber, SQLSMALLINT targetType, SQLPOINTER targetValue, SQLINTEGER bufferLength, SQLINTEGER* strlen_or_Ind)
- {
- if (m_state != Open) {
- ctx.pushStatus(Sqlstate::_24000, Error::Gen, "cursor is not open");
- return;
- }
- if (bufferLength < 0) {
- ctx.pushStatus(Sqlstate::_HY090, Error::Gen, "invalid buffer length %d", (int)bufferLength);
- return;
- }
- CodeGen codegen(*this);
- codegen.sqlGetData(ctx, columnNumber, targetType, targetValue, bufferLength, strlen_or_Ind);
- }
- void
- HandleStmt::sqlParamData(Ctx& ctx, SQLPOINTER* value)
- {
- if (m_state != NeedData) {
- ctx.pushStatus(Sqlstate::_HY010, Error::Gen, "not expecting data-at-exec");
- return;
- }
- CodeGen codegen(*this);
- codegen.sqlParamData(ctx, value);
- if (! ctx.ok())
- return;
- sqlExecute(ctx);
- }
- void
- HandleStmt::sqlPutData(Ctx& ctx, SQLPOINTER data, SQLINTEGER strlen_or_Ind)
- {
- if (m_state != NeedData) {
- ctx.pushStatus(Sqlstate::_HY010, Error::Gen, "not expecting data-at-exec");
- return;
- }
- CodeGen codegen(*this);
- codegen.sqlPutData(ctx, data, strlen_or_Ind);
- }
- // describe statement
- void
- HandleStmt::sqlNumParams(Ctx& ctx, SQLSMALLINT* parameterCountPtr)
- {
- if (m_state == Free) {
- ctx.pushStatus(Sqlstate::_HY010, Error::Gen, "statement is not prepared");
- return;
- }
- HandleDesc* ipd = getHandleDesc(ctx, Desc_usage_IPD);
- ipd->sqlGetDescField(ctx, 0, SQL_DESC_COUNT, static_cast<SQLPOINTER>(parameterCountPtr), -1, 0);
- }
- void
- HandleStmt::sqlDescribeParam(Ctx& ctx, SQLUSMALLINT ipar, SQLSMALLINT* pfSqlType, SQLUINTEGER* pcbParamDef, SQLSMALLINT* pibScale, SQLSMALLINT* pfNullable)
- {
- if (m_state == Free) {
- ctx.pushStatus(Sqlstate::_HY010, Error::Gen, "statement is not prepared");
- return;
- }
- HandleDesc* ipd = getHandleDesc(ctx, Desc_usage_IPD);
- ipd->sqlGetDescField(ctx, ipar, SQL_DESC_CONCISE_TYPE, static_cast<SQLPOINTER>(pfSqlType), -1, 0);
- { // XXX fix it
- OdbcData data((SQLUINTEGER)0);
- data.copyout(ctx, (SQLPOINTER)pcbParamDef, -1, 0);
- }
- { // XXX fix it
- OdbcData data((SQLSMALLINT)0);
- data.copyout(ctx, (SQLPOINTER)pibScale, -1, 0);
- }
- ipd->sqlGetDescField(ctx, ipar, SQL_DESC_NULLABLE, static_cast<SQLPOINTER>(pfNullable), -1, 0);
- }
- void
- HandleStmt::sqlNumResultCols(Ctx& ctx, SQLSMALLINT* columnCount)
- {
- if (m_state == Free) {
- ctx.pushStatus(Sqlstate::_HY010, Error::Gen, "statement is not prepared");
- return;
- }
- HandleDesc* const ird = getHandleDesc(ctx, Desc_usage_IRD);
- ird->sqlGetDescField(ctx, 0, SQL_DESC_COUNT, static_cast<SQLPOINTER>(columnCount), -1, 0);
- setFunction(ctx); // unixODBC workaround
- }
- void
- HandleStmt::sqlDescribeCol(Ctx& ctx, SQLUSMALLINT columnNumber, SQLCHAR* columnName, SQLSMALLINT bufferLength, SQLSMALLINT* nameLength, SQLSMALLINT* dataType, SQLUINTEGER* columnSize, SQLSMALLINT* decimalDigits, SQLSMALLINT* nullable)
- {
- if (m_state == Free) {
- ctx.pushStatus(Sqlstate::_HY010, Error::Gen, "statement is not prepared");
- return;
- }
- HandleDesc* const ird = getHandleDesc(ctx, Desc_usage_IRD);
- ird->sqlGetDescField(ctx, columnNumber, SQL_DESC_NAME, static_cast<SQLPOINTER>(columnName), bufferLength, 0, nameLength);
- ird->sqlGetDescField(ctx, columnNumber, SQL_DESC_CONCISE_TYPE, static_cast<SQLPOINTER>(dataType), -1, 0);
- if (! ctx.ok())
- return;
- if (columnSize != 0) {
- switch (*dataType) {
- case SQL_CHAR:
- case SQL_VARCHAR:
- case SQL_BINARY:
- case SQL_VARBINARY:
- ird->sqlGetDescField(ctx, columnNumber, SQL_DESC_LENGTH, static_cast<SQLPOINTER>(columnSize), -1, 0);
- break;
- case SQL_SMALLINT:
- *columnSize = 5;
- break;
- case SQL_INTEGER:
- *columnSize = 10;
- break;
- case SQL_BIGINT:
- *columnSize = 20; // XXX 19 for signed
- break;
- case SQL_REAL:
- *columnSize = 7;
- break;
- case SQL_DOUBLE:
- *columnSize = 15;
- break;
- case SQL_TYPE_TIMESTAMP:
- *columnSize = 30;
- break;
- default:
- *columnSize = 0;
- break;
- }
- }
- if (decimalDigits != 0) {
- switch (*dataType) {
- case SQL_SMALLINT:
- case SQL_INTEGER:
- case SQL_BIGINT:
- *decimalDigits = 0;
- break;
- case SQL_TYPE_TIMESTAMP:
- *decimalDigits = 10;
- break;
- default:
- *decimalDigits = 0;
- break;
- }
- }
- ird->sqlGetDescField(ctx, columnNumber, SQL_DESC_NULLABLE, static_cast<SQLPOINTER>(nullable), -1, 0);
- }
- void
- HandleStmt::sqlColAttribute(Ctx& ctx, SQLUSMALLINT columnNumber, SQLUSMALLINT fieldIdentifier, SQLPOINTER characterAttribute, SQLSMALLINT bufferLength, SQLSMALLINT* stringLength, SQLPOINTER numericAttribute)
- {
- if (m_state == Free) {
- ctx.pushStatus(Sqlstate::_HY010, Error::Gen, "statement is not prepared");
- return;
- }
- HandleDesc* const ird = getHandleDesc(ctx, Desc_usage_IRD);
- ird->sqlColAttribute(ctx, columnNumber, fieldIdentifier, characterAttribute, bufferLength, stringLength, numericAttribute);
- }
- void
- HandleStmt::sqlColAttributes(Ctx& ctx, SQLUSMALLINT icol, SQLUSMALLINT fdescType, SQLPOINTER rgbDesc, SQLSMALLINT cbDescMax, SQLSMALLINT* pcbDesc, SQLINTEGER* pfDesc)
- {
- if (m_state == Free) {
- ctx.pushStatus(Sqlstate::_HY010, Error::Gen, "statement is nor prepared");
- return;
- }
- HandleDesc* const ird = getHandleDesc(ctx, Desc_usage_IRD);
- ird->sqlColAttributes(ctx, icol, fdescType, rgbDesc, cbDescMax, pcbDesc, pfDesc);
- }
- // descriptor manipulation
- void
- HandleStmt::sqlBindCol(Ctx& ctx, SQLUSMALLINT columnNumber, SQLSMALLINT targetType, SQLPOINTER targetValue, SQLINTEGER bufferLength, SQLINTEGER* strlen_or_Ind)
- {
- HandleDesc* const ard = getHandleDesc(ctx, Desc_usage_ARD);
- DescArea& desc = ard->descArea();
- if (desc.getCount() < columnNumber) {
- desc.setCount(ctx, columnNumber);
- }
- DescRec& rec = desc.getRecord(columnNumber);
- rec.setField(ctx, SQL_DESC_TYPE, targetType);
- rec.setField(ctx, SQL_DESC_CONCISE_TYPE, targetType);
- rec.setField(ctx, SQL_DESC_DATA_PTR, targetValue);
- rec.setField(ctx, SQL_DESC_OCTET_LENGTH, bufferLength);
- rec.setField(ctx, SQL_DESC_OCTET_LENGTH_PTR, strlen_or_Ind);
- rec.setField(ctx, SQL_DESC_INDICATOR_PTR, strlen_or_Ind);
- }
- void
- HandleStmt::sqlBindParameter(Ctx& ctx, SQLUSMALLINT ipar, SQLSMALLINT fParamType, SQLSMALLINT fCType, SQLSMALLINT fSqlType, SQLUINTEGER cbColDef, SQLSMALLINT ibScale, SQLPOINTER rgbValue, SQLINTEGER cbValueMax, SQLINTEGER* pcbValue)
- {
- HandleDesc* const ipd = getHandleDesc(ctx, Desc_usage_IPD);
- HandleDesc* const apd = getHandleDesc(ctx, Desc_usage_APD);
- DescArea& descIPD = ipd->descArea();
- DescArea& descAPD = apd->descArea();
- if (ipar < 1) {
- ctx.pushStatus(Sqlstate::_07009, Error::Gen, "invalid parameter index %u", (unsigned)ipar);
- return;
- }
- if (descIPD.getCount() < ipar) {
- descIPD.setCount(ctx, ipar);
- }
- if (descAPD.getCount() < ipar) {
- descAPD.setCount(ctx, ipar);
- }
- DescRec& recIPD = descIPD.getRecord(ipar);
- DescRec& recAPD = descAPD.getRecord(ipar);
- recIPD.setField(ctx, SQL_DESC_PARAMETER_TYPE, fParamType);
- recAPD.setField(ctx, SQL_DESC_TYPE, fCType);
- recAPD.setField(ctx, SQL_DESC_CONCISE_TYPE, fCType);
- recIPD.setField(ctx, SQL_DESC_TYPE, fSqlType);
- recIPD.setField(ctx, SQL_DESC_CONCISE_TYPE, fSqlType);
- switch (fSqlType) {
- case SQL_CHAR: // XXX not complete
- case SQL_VARCHAR:
- case SQL_BINARY:
- case SQL_VARBINARY:
- recIPD.setField(ctx, SQL_DESC_LENGTH, cbColDef);
- break;
- case SQL_DECIMAL:
- case SQL_NUMERIC:
- case SQL_FLOAT:
- case SQL_REAL:
- case SQL_DOUBLE:
- recIPD.setField(ctx, SQL_DESC_PRECISION, cbColDef);
- break;
- }
- switch (fSqlType) {
- case SQL_TYPE_TIME: // XXX not complete
- case SQL_TYPE_TIMESTAMP:
- recIPD.setField(ctx, SQL_DESC_PRECISION, ibScale);
- break;
- case SQL_NUMERIC:
- case SQL_DECIMAL:
- recIPD.setField(ctx, SQL_DESC_SCALE, ibScale);
- break;
- }
- recAPD.setField(ctx, SQL_DESC_DATA_PTR, rgbValue);
- recAPD.setField(ctx, SQL_DESC_OCTET_LENGTH, cbValueMax);
- recAPD.setField(ctx, SQL_DESC_OCTET_LENGTH_PTR, pcbValue);
- recAPD.setField(ctx, SQL_DESC_INDICATOR_PTR, pcbValue);
- }
- void
- HandleStmt::sqlBindParam(Ctx& ctx, SQLUSMALLINT parameterNumber, SQLSMALLINT valueType, SQLSMALLINT parameterType, SQLUINTEGER lengthPrecision, SQLSMALLINT parameterScale, SQLPOINTER parameterValue, SQLINTEGER* strLen_or_Ind)
- {
- sqlBindParameter(ctx, parameterNumber, SQL_PARAM_INPUT_OUTPUT, valueType, parameterType, lengthPrecision, parameterScale, parameterValue, SQL_SETPARAM_VALUE_MAX, strLen_or_Ind);
- }
- void
- HandleStmt::sqlSetParam(Ctx& ctx, SQLUSMALLINT parameterNumber, SQLSMALLINT valueType, SQLSMALLINT parameterType, SQLUINTEGER lengthPrecision, SQLSMALLINT parameterScale, SQLPOINTER parameterValue, SQLINTEGER* strLen_or_Ind)
- {
- sqlBindParameter(ctx, parameterNumber, SQL_PARAM_INPUT_OUTPUT, valueType, parameterType, lengthPrecision, parameterScale, parameterValue, SQL_SETPARAM_VALUE_MAX, strLen_or_Ind);
- }