SQLRETURN SQL_API SQLFetchScroll(SQLHSTMT StatementHandle, SQLSMALLINT FetchOrientation, SQLLEN FetchOffset) { ODBCStmt *stmt = (ODBCStmt *) StatementHandle; #ifdef ODBCDEBUG ODBCLOG("SQLFetchScroll %p %s " LENFMT "\n", StatementHandle, translateFetchOrientation(FetchOrientation), LENCAST FetchOffset); #endif if (!isValidStmt(stmt)) return SQL_INVALID_HANDLE; clearStmtErrors(stmt); /* check statement cursor state, query should be executed */ if (stmt->State < EXECUTED0 || stmt->State == EXTENDEDFETCHED) { /* Function sequence error */ addStmtError(stmt, "HY010", NULL, 0); return SQL_ERROR; } if (stmt->State == EXECUTED0) { /* Invalid cursor state */ addStmtError(stmt, "24000", NULL, 0); return SQL_ERROR; } return MNDBFetchScroll(stmt, FetchOrientation, FetchOffset, stmt->ImplRowDescr->sql_desc_array_status_ptr); }
SQLRETURN SQL_API SQLFetch(SQLHSTMT StatementHandle) { ODBCStmt *stmt = (ODBCStmt *) StatementHandle; #ifdef ODBCDEBUG ODBCLOG("SQLFetch " PTRFMT "\n", PTRFMTCAST StatementHandle); #endif if (!isValidStmt(stmt)) return SQL_INVALID_HANDLE; clearStmtErrors(stmt); assert(stmt->hdl); /* check statement cursor state, query should be executed */ if (stmt->State < EXECUTED0 || stmt->State == EXTENDEDFETCHED) { /* Function sequence error */ addStmtError(stmt, "HY010", NULL, 0); return SQL_ERROR; } if (stmt->State == EXECUTED0) { /* Invalid cursor state */ addStmtError(stmt, "24000", NULL, 0); return SQL_ERROR; } stmt->startRow += stmt->rowSetSize; return MNDBFetch(stmt, stmt->ImplRowDescr->sql_desc_array_status_ptr); }
SQLRETURN SQL_API SQLNumResultCols(SQLHSTMT StatementHandle, SQLSMALLINT *ColumnCountPtr) { ODBCStmt *stmt = (ODBCStmt *) StatementHandle; #ifdef ODBCDEBUG ODBCLOG("SQLNumResultCols " PTRFMT "\n", PTRFMTCAST StatementHandle); #endif if (!isValidStmt(stmt)) return SQL_INVALID_HANDLE; clearStmtErrors(stmt); /* check statement cursor state, query should be prepared or executed */ if (stmt->State == INITED) { /* Function sequence error */ addStmtError(stmt, "HY010", NULL, 0); return SQL_ERROR; } /* check output parameter */ if (ColumnCountPtr == NULL) { /* Invalid use of null pointer */ addStmtError(stmt, "HY009", NULL, 0); return SQL_ERROR; } /* We can now set the "number of output columns" value */ /* Note: row count can be 0 (for non SELECT queries) */ *ColumnCountPtr = stmt->ImplRowDescr->sql_desc_count; return SQL_SUCCESS; }
SQLRETURN SQL_API SQLRowCount(SQLHSTMT StatementHandle, SQLLEN *RowCountPtr) { ODBCStmt *stmt = (ODBCStmt *) StatementHandle; #ifdef ODBCDEBUG ODBCLOG("SQLRowCount %p\n", StatementHandle); #endif if (!isValidStmt(stmt)) return SQL_INVALID_HANDLE; clearStmtErrors(stmt); /* check statement cursor state, query should be executed */ if (stmt->State < EXECUTED0) { /* Function sequence error */ addStmtError(stmt, "HY010", NULL, 0); return SQL_ERROR; } /* check output parameter */ if (RowCountPtr == NULL) { /* Invalid use of null pointer */ addStmtError(stmt, "HY009", NULL, 0); return SQL_ERROR; } /* We can now set the "number of result set rows" value */ *RowCountPtr = (SQLLEN) stmt->rowcount; return SQL_SUCCESS; }
SQLRETURN SQL_API SQLExtendedFetch(SQLHSTMT StatementHandle, SQLUSMALLINT FetchOrientation, SQLLEN FetchOffset, #ifdef BUILD_REAL_64_BIT_MODE /* note: only defined on Debian Lenny */ SQLUINTEGER *RowCountPtr, #else SQLULEN *RowCountPtr, #endif SQLUSMALLINT *RowStatusArray) { ODBCStmt *stmt = (ODBCStmt *) StatementHandle; SQLRETURN rc; #ifdef ODBCDEBUG ODBCLOG("SQLExtendedFetch " PTRFMT " %s " LENFMT " " PTRFMT " " PTRFMT "\n", PTRFMTCAST StatementHandle, translateFetchOrientation(FetchOrientation), LENCAST FetchOffset, PTRFMTCAST RowCountPtr, PTRFMTCAST RowStatusArray); #endif if (!isValidStmt(stmt)) return SQL_INVALID_HANDLE; clearStmtErrors(stmt); /* check statement cursor state, query should be executed */ if (stmt->State < EXECUTED0 || stmt->State == FETCHED) { /* Function sequence error */ addStmtError(stmt, "HY010", NULL, 0); return SQL_ERROR; } if (stmt->State == EXECUTED0) { /* Invalid cursor state */ addStmtError(stmt, "24000", NULL, 0); return SQL_ERROR; } rc = MNDBFetchScroll(stmt, FetchOrientation, FetchOffset, RowStatusArray); if (SQL_SUCCEEDED(rc) || rc == SQL_NO_DATA) stmt->State = EXTENDEDFETCHED; if (SQL_SUCCEEDED(rc) && RowCountPtr) { #ifdef BUILD_REAL_64_BIT_MODE /* note: only defined on Debian Lenny */ WriteValue(RowCountPtr, (SQLUINTEGER) stmt->rowSetSize); #else WriteValue(RowCountPtr, (SQLULEN) stmt->rowSetSize); #endif } return rc; }
SQLRETURN SQL_API SQLSetScrollOptions(SQLHSTMT StatementHandle, SQLUSMALLINT fConcurrency, SQLLEN crowKeyset, SQLUSMALLINT crowRowset) { #ifdef ODBCDEBUG ODBCLOG("SQLSetScrollOptions " PTRFMT " %u " LENFMT " %u\n", PTRFMTCAST StatementHandle, (unsigned int) fConcurrency, LENCAST crowKeyset, (unsigned int) crowRowset); #endif (void) fConcurrency; /* Stefan: unused!? */ (void) crowKeyset; /* Stefan: unused!? */ (void) crowRowset; /* Stefan: unused!? */ if (!isValidStmt((ODBCStmt *) StatementHandle)) return SQL_INVALID_HANDLE; clearStmtErrors((ODBCStmt *) StatementHandle); /* TODO: implement the mapping to multiple SQLSetStmtAttr() calls */ /* See ODBC 3.5 SDK Help file for details */ /* for now return error */ /* Driver does not support this function */ addStmtError((ODBCStmt *) StatementHandle, "IM001", NULL, 0); return SQL_ERROR; }
SQLRETURN SQL_API SQLDescribeColW(SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber, SQLWCHAR *ColumnName, SQLSMALLINT BufferLength, SQLSMALLINT *NameLengthPtr, SQLSMALLINT *DataTypePtr, SQLULEN *ColumnSizePtr, SQLSMALLINT *DecimalDigitsPtr, SQLSMALLINT *NullablePtr) { ODBCStmt *stmt = (ODBCStmt *) StatementHandle; SQLCHAR *colname; SQLSMALLINT n; SQLRETURN rc = SQL_ERROR; #ifdef ODBCDEBUG ODBCLOG("SQLDescribeColW " PTRFMT " %u " PTRFMT " %d " PTRFMT " " PTRFMT " " PTRFMT " " PTRFMT " " PTRFMT "\n", PTRFMTCAST StatementHandle, (unsigned int) ColumnNumber, PTRFMTCAST ColumnName, (int) BufferLength, PTRFMTCAST NameLengthPtr, PTRFMTCAST DataTypePtr, PTRFMTCAST ColumnSizePtr, PTRFMTCAST DecimalDigitsPtr, PTRFMTCAST NullablePtr); #endif if (!isValidStmt(stmt)) return SQL_INVALID_HANDLE; clearStmtErrors(stmt); rc = MNDBDescribeCol(stmt, ColumnNumber, NULL, 0, &n, DataTypePtr, ColumnSizePtr, DecimalDigitsPtr, NullablePtr); if (!SQL_SUCCEEDED(rc)) return rc; clearStmtErrors(stmt); n++; /* account for NUL byte */ colname = malloc(n); if (colname == NULL) { /* Memory allocation error */ addStmtError(stmt, "HY001", NULL, 0); return SQL_ERROR; } rc = MNDBDescribeCol(stmt, ColumnNumber, colname, n, &n, DataTypePtr, ColumnSizePtr, DecimalDigitsPtr, NullablePtr); if (SQL_SUCCEEDED(rc)) { fixWcharOut(rc, colname, n, ColumnName, BufferLength, NameLengthPtr, 1, addStmtError, stmt); } free(colname); return rc; }
SQLRETURN SQL_API SQLBulkOperations(SQLHSTMT StatementHandle, SQLSMALLINT Operation) { ODBCStmt *stmt = (ODBCStmt *) StatementHandle; #ifdef ODBCDEBUG ODBCLOG("SQLBulkOperations " PTRFMT " %s\n", PTRFMTCAST StatementHandle, translateOperation(Operation)); #endif if (!isValidStmt(stmt)) return SQL_INVALID_HANDLE; clearStmtErrors(stmt); if (stmt->State < EXECUTED0 || stmt->State == EXTENDEDFETCHED) { /* Function sequence error */ addStmtError(stmt, "HY010", NULL, 0); return SQL_ERROR; } if (stmt->State == EXECUTED0) { /* Invalid cursor state */ addStmtError(stmt, "24000", NULL, 0); return SQL_ERROR; } /* check Operation code */ switch (Operation) { case SQL_ADD: case SQL_UPDATE_BY_BOOKMARK: case SQL_DELETE_BY_BOOKMARK: case SQL_FETCH_BY_BOOKMARK: break; default: /* Invalid attribute/option identifier */ addStmtError(stmt, "HY092", NULL, 0); return SQL_ERROR; } /* TODO: finish implementation */ /* Driver does not support this function */ addStmtError(stmt, "IM001", NULL, 0); return SQL_ERROR; }
SQLRETURN SQL_API SQLGetStmtOption(SQLHSTMT StatementHandle, SQLUSMALLINT Option, SQLPOINTER ValuePtr) { ODBCStmt *stmt = (ODBCStmt *) StatementHandle; SQLULEN v; SQLRETURN r; #ifdef ODBCDEBUG ODBCLOG("SQLGetStmtOption " PTRFMT " %s " PTRFMT "\n", PTRFMTCAST StatementHandle, translateStmtOption(Option), PTRFMTCAST ValuePtr); #endif if (!isValidStmt(stmt)) return SQL_INVALID_HANDLE; clearStmtErrors(stmt); /* only the ODBC 1.0 and ODBC 2.0 options */ switch (Option) { case SQL_ASYNC_ENABLE: case SQL_CONCURRENCY: case SQL_CURSOR_TYPE: case SQL_NOSCAN: case SQL_QUERY_TIMEOUT: case SQL_RETRIEVE_DATA: case SQL_SIMULATE_CURSOR: case SQL_USE_BOOKMARKS: case SQL_ROW_NUMBER: /* SQLGetStmtAttr returns 64 bit value, but we need to * return 32 bit value */ r = MNDBGetStmtAttr(stmt, Option, &v, 0, NULL); if (SQL_SUCCEEDED(r)) WriteData(ValuePtr, (SQLUINTEGER) v, SQLUINTEGER); return r; case SQL_BIND_TYPE: case SQL_KEYSET_SIZE: case SQL_MAX_LENGTH: case SQL_MAX_ROWS: case SQL_ROWSET_SIZE: /* case SQL_GET_BOOKMARKS: is deprecated in ODBC 3.0+ */ /* use mapping as described in ODBC 3.0 SDK Help */ return MNDBGetStmtAttr(stmt, Option, ValuePtr, 0, NULL); default: /* Invalid attribute/option identifier */ addStmtError(stmt, "HY092", NULL, 0); break; } return SQL_ERROR; }
SQLRETURN SQL_API SQLSetStmtOption(SQLHSTMT StatementHandle, SQLUSMALLINT Option, SQLULEN ValuePtr) { ODBCStmt *stmt = (ODBCStmt *) StatementHandle; #ifdef ODBCDEBUG ODBCLOG("SQLSetStmtOption " PTRFMT " %s " ULENFMT "\n", PTRFMTCAST StatementHandle, translateStmtOption(Option), ULENCAST ValuePtr); #endif if (!isValidStmt(stmt)) return SQL_INVALID_HANDLE; clearStmtErrors(stmt); switch (Option) { /* only the ODBC 1.0 and ODBC 2.0 options */ case SQL_ROWSET_SIZE: Option = SQL_ATTR_ROW_ARRAY_SIZE; /* fall through */ case SQL_QUERY_TIMEOUT: case SQL_MAX_ROWS: case SQL_NOSCAN: case SQL_MAX_LENGTH: case SQL_ASYNC_ENABLE: case SQL_BIND_TYPE: case SQL_CURSOR_TYPE: case SQL_CONCURRENCY: case SQL_KEYSET_SIZE: case SQL_SIMULATE_CURSOR: case SQL_RETRIEVE_DATA: case SQL_USE_BOOKMARKS: /* use mapping as described in ODBC 3.0 SDK Help */ return MNDBSetStmtAttr(stmt, Option, (SQLPOINTER) (uintptr_t) ValuePtr, SQL_NTS); default: /* Invalid attribute/option identifier */ addStmtError(stmt, "HY092", NULL, 0); break; } return SQL_ERROR; }
SQLRETURN SQLFreeStmt_(ODBCStmt *stmt, SQLUSMALLINT Option) { switch (Option) { case SQL_CLOSE: /* Note: this option is also called from SQLCancel() * and SQLCloseCursor(), so be careful when changing * the code */ /* close cursor, discard result set, set to prepared */ setODBCDescRecCount(stmt->ImplRowDescr, 0); stmt->currentRow = 0; stmt->startRow = 0; stmt->rowSetSize = 0; if (stmt->State == EXECUTED0) stmt->State = stmt->queryid >= 0 ? PREPARED0 : INITED; else if (stmt->State >= EXECUTED1) stmt->State = stmt->queryid >= 0 ? PREPARED1 : INITED; /* Important: do not destroy the bind parameters and columns! */ return SQL_SUCCESS; case SQL_DROP: return ODBCFreeStmt_(stmt); case SQL_UNBIND: setODBCDescRecCount(stmt->ApplRowDescr, 0); return SQL_SUCCESS; case SQL_RESET_PARAMS: setODBCDescRecCount(stmt->ApplParamDescr, 0); setODBCDescRecCount(stmt->ImplParamDescr, 0); mapi_clear_params(stmt->hdl); return SQL_SUCCESS; default: /* Invalid attribute/option identifier */ addStmtError(stmt, "HY092", NULL, 0); return SQL_ERROR; } /* not reached */ }
SQLRETURN SQL_API SQLParamData(SQLHSTMT StatementHandle, SQLPOINTER *ValuePtrPtr) { ODBCStmt *stmt = (ODBCStmt *) StatementHandle; #ifdef ODBCDEBUG ODBCLOG("SQLParamData " PTRFMT "\n", PTRFMTCAST StatementHandle); #endif (void) ValuePtrPtr; /* Stefan: unused!? */ if (!isValidStmt(stmt)) return SQL_INVALID_HANDLE; clearStmtErrors(stmt); /* TODO: implement this function and corresponding behavior */ /* Function sequence error */ addStmtError(stmt, "HY010", NULL, 0); return SQL_ERROR; }
static SQLRETURN MNDBTablePrivileges(ODBCStmt *stmt, SQLCHAR *CatalogName, SQLSMALLINT NameLength1, SQLCHAR *SchemaName, SQLSMALLINT NameLength2, SQLCHAR *TableName, SQLSMALLINT NameLength3) { RETCODE rc; char *query = NULL; char *query_end = NULL; char *cat = NULL, *sch = NULL, *tab = NULL; fixODBCstring(CatalogName, NameLength1, SQLSMALLINT, addStmtError, stmt, return SQL_ERROR); fixODBCstring(SchemaName, NameLength2, SQLSMALLINT, addStmtError, stmt, return SQL_ERROR); fixODBCstring(TableName, NameLength3, SQLSMALLINT, addStmtError, stmt, return SQL_ERROR); #ifdef ODBCDEBUG ODBCLOG("\"%.*s\" \"%.*s\" \"%.*s\"\n", (int) NameLength1, (char *) CatalogName, (int) NameLength2, (char *) SchemaName, (int) NameLength3, (char *) TableName); #endif if (stmt->Dbc->sql_attr_metadata_id == SQL_FALSE) { if (NameLength1 > 0) { cat = ODBCParseOA("e", "value", (const char *) CatalogName, (size_t) NameLength1); if (cat == NULL) goto nomem; } if (NameLength2 > 0) { sch = ODBCParsePV("s", "name", (const char *) SchemaName, (size_t) NameLength2); if (sch == NULL) goto nomem; } if (NameLength3 > 0) { tab = ODBCParsePV("t", "name", (const char *) TableName, (size_t) NameLength3); if (tab == NULL) goto nomem; } } else { if (NameLength1 > 0) { cat = ODBCParseID("e", "value", (const char *) CatalogName, (size_t) NameLength1); if (cat == NULL) goto nomem; } if (NameLength2 > 0) { sch = ODBCParseID("s", "name", (const char *) SchemaName, (size_t) NameLength2); if (sch == NULL) goto nomem; } if (NameLength3 > 0) { tab = ODBCParseID("t", "name", (const char *) TableName, (size_t) NameLength3); if (tab == NULL) goto nomem; } } /* construct the query now */ query = malloc(1200 + (cat ? strlen(cat) : 0) + (sch ? strlen(sch) : 0) + (tab ? strlen(tab) : 0)); if (query == NULL) goto nomem; query_end = query; /* SQLTablePrivileges returns a table with the following columns: table_cat VARCHAR table_schem VARCHAR table_name VARCHAR NOT NULL grantor VARCHAR grantee VARCHAR NOT NULL privilege VARCHAR NOT NULL is_grantable VARCHAR */ sprintf(query_end, "select e.value as table_cat, " "s.name as table_schem, " "t.name as table_name, " "case a.id " "when s.owner then '_SYSTEM' " "else g.name " "end as grantor, " "case a.name " "when 'public' then 'PUBLIC' " "else a.name " "end as grantee, " "case p.privileges " "when 1 then 'SELECT' " "when 2 then 'UPDATE' " "when 4 then 'INSERT' " "when 8 then 'DELETE' " "when 16 then 'EXECUTE' " "when 32 then 'GRANT' " "end as privilege, " "case p.grantable " "when 1 then 'YES' " "when 0 then 'NO' " "end as is_grantable " "from sys.schemas s, " "sys._tables t, " "sys.auths a, " "sys.privileges p, " "sys.auths g, " "sys.env() e " "where p.obj_id = t.id " "and p.auth_id = a.id " "and t.schema_id = s.id " "and t.system = false " "and p.grantor = g.id " "and e.name = 'gdk_dbname'"); assert(strlen(query) < 1000); query_end += strlen(query_end); /* Construct the selection condition query part */ if (cat) { /* filtering requested on catalog name */ sprintf(query_end, " and %s", cat); query_end += strlen(query_end); free(cat); } if (sch) { /* filtering requested on schema name */ sprintf(query_end, " and %s", sch); query_end += strlen(query_end); free(sch); } if (tab) { /* filtering requested on table name */ sprintf(query_end, " and %s", tab); query_end += strlen(query_end); free(tab); } /* add the ordering */ strcpy(query_end, " order by table_cat, table_schem, table_name, privilege, grantee"); query_end += strlen(query_end); /* query the MonetDB data dictionary tables */ rc = MNDBExecDirect(stmt, (SQLCHAR *) query, (SQLINTEGER) (query_end - query)); free(query); return rc; nomem: /* note that query must be NULL when we get here */ if (cat) free(cat); if (sch) free(sch); if (tab) free(tab); /* Memory allocation error */ addStmtError(stmt, "HY001", NULL, 0); return SQL_ERROR; }
static SQLRETURN MNDBForeignKeys(ODBCStmt *stmt, SQLCHAR *PKCatalogName, SQLSMALLINT NameLength1, SQLCHAR *PKSchemaName, SQLSMALLINT NameLength2, SQLCHAR *PKTableName, SQLSMALLINT NameLength3, SQLCHAR *FKCatalogName, SQLSMALLINT NameLength4, SQLCHAR *FKSchemaName, SQLSMALLINT NameLength5, SQLCHAR *FKTableName, SQLSMALLINT NameLength6) { RETCODE rc; /* buffer for the constructed query to do meta data retrieval */ char *query = NULL; char *query_end = NULL; /* pointer to end of built-up query */ char *pcat = NULL, *psch = NULL, *ptab = NULL; char *fcat = NULL, *fsch = NULL, *ftab = NULL; /* deal with SQL_NTS and SQL_NULL_DATA */ fixODBCstring(PKCatalogName, NameLength1, SQLSMALLINT, addStmtError, stmt, return SQL_ERROR); fixODBCstring(PKSchemaName, NameLength2, SQLSMALLINT, addStmtError, stmt, return SQL_ERROR); fixODBCstring(PKTableName, NameLength3, SQLSMALLINT, addStmtError, stmt, return SQL_ERROR); fixODBCstring(FKCatalogName, NameLength4, SQLSMALLINT, addStmtError, stmt, return SQL_ERROR); fixODBCstring(FKSchemaName, NameLength5, SQLSMALLINT, addStmtError, stmt, return SQL_ERROR); fixODBCstring(FKTableName, NameLength6, SQLSMALLINT, addStmtError, stmt, return SQL_ERROR); #ifdef ODCBDEBUG ODBCLOG("\"%.*s\" \"%.*s\" \"%.*s\" \"%.*s\" \"%.*s\" \"%.*s\"\n", (int) NameLength1, PKCatalogName, (int) NameLength2, PKSchemaName, (int) NameLength3, PKTableName, (int) NameLength4, FKCatalogName, (int) NameLength5, FKSchemaName, (int) NameLength6, FKTableName); #endif /* dependent on the input parameter values we must add a variable selection condition dynamically */ if (stmt->Dbc->sql_attr_metadata_id == SQL_FALSE) { if (NameLength1 > 0) { pcat = ODBCParseOA("e", "value", (const char *) PKCatalogName, (size_t) NameLength1); if (pcat == NULL) goto nomem; } if (NameLength2 > 0) { psch = ODBCParseOA("pks", "name", (const char *) PKSchemaName, (size_t) NameLength2); if (psch == NULL) goto nomem; } if (NameLength3 > 0) { ptab = ODBCParseOA("pkt", "name", (const char *) PKTableName, (size_t) NameLength3); if (ptab == NULL) goto nomem; } if (NameLength4 > 0) { fcat = ODBCParseOA("e", "value", (const char *) FKCatalogName, (size_t) NameLength4); if (fcat == NULL) goto nomem; } if (NameLength5 > 0) { fsch = ODBCParseOA("fks", "name", (const char *) FKSchemaName, (size_t) NameLength5); if (fsch == NULL) goto nomem; } if (NameLength6 > 0) { ftab = ODBCParseOA("fkt", "name", (const char *) FKTableName, (size_t) NameLength6); if (ftab == NULL) goto nomem; } } else { if (NameLength1 > 0) { pcat = ODBCParseID("e", "value", (const char *) PKCatalogName, (size_t) NameLength1); if (pcat == NULL) goto nomem; } if (NameLength2 > 0) { psch = ODBCParseID("pks", "name", (const char *) PKSchemaName, (size_t) NameLength2); if (psch == NULL) goto nomem; } if (NameLength3 > 0) { ptab = ODBCParseID("pkt", "name", (const char *) PKTableName, (size_t) NameLength3); if (ptab == NULL) goto nomem; } if (NameLength4 > 0) { fcat = ODBCParseID("e", "value", (const char *) FKCatalogName, (size_t) NameLength4); if (fcat == NULL) goto nomem; } if (NameLength5 > 0) { fsch = ODBCParseID("fks", "name", (const char *) FKSchemaName, (size_t) NameLength5); if (fsch == NULL) goto nomem; } if (NameLength6 > 0) { ftab = ODBCParseID("fkt", "name", (const char *) FKTableName, (size_t) NameLength6); if (ftab == NULL) goto nomem; } } /* first create a string buffer (1200 extra bytes is plenty: we actually need just over 1000) */ query = malloc(1200 + (pcat ? strlen(pcat) : 0) + (psch ? strlen(psch) : 0) + (ptab ? strlen(ptab) : 0) + (fcat ? strlen(fcat) : 0) + (fsch ? strlen(fsch) : 0) + (ftab ? strlen(ftab) : 0)); if (query == NULL) goto nomem; query_end = query; /* SQLForeignKeys returns a table with the following columns: VARCHAR pktable_cat VARCHAR pktable_schem VARCHAR pktable_name NOT NULL VARCHAR pkcolumn_name NOT NULL VARCHAR fktable_cat VARCHAR fktable_schem VARCHAR fktable_name NOT NULL VARCHAR fkcolumn_name NOT NULL SMALLINT key_seq NOT NULL SMALLINT update_rule SMALLINT delete_rule VARCHAR fk_name VARCHAR pk_name SMALLINT deferrability */ sprintf(query_end, "select e.value as pktable_cat, " "pks.name as pktable_schem, " "pkt.name as pktable_name, " "pkkc.name as pkcolumn_name, " "e.value as fktable_cat, " "fks.name as fktable_schem, " "fkt.name as fktable_name, " "fkkc.name as fkcolumn_name, " "cast(fkkc.nr + 1 as smallint) as key_seq, " "cast(%d as smallint) as update_rule, " "cast(%d as smallint) as delete_rule, " "fkk.name as fk_name, " "pkk.name as pk_name, " "cast(%d as smallint) as deferrability " "from sys.schemas fks, sys.tables fkt, " "sys.objects fkkc, sys.keys as fkk, " "sys.schemas pks, sys.tables pkt, " "sys.objects pkkc, sys.keys as pkk, " "sys.env() e " "where fkt.id = fkk.table_id and " "pkt.id = pkk.table_id and " "fkk.id = fkkc.id and " "pkk.id = pkkc.id and " "fks.id = fkt.schema_id and " "pks.id = pkt.schema_id and " "fkk.rkey = pkk.id and " "fkkc.nr = pkkc.nr and " "e.name = 'gdk_dbname'", SQL_NO_ACTION, SQL_NO_ACTION, SQL_NOT_DEFERRABLE); assert(strlen(query) < 1100); query_end += strlen(query_end); /* Construct the selection condition query part */ if (pcat) { /* filtering requested on catalog name */ sprintf(query_end, " and %s", pcat); query_end += strlen(query_end); free(pcat); } if (psch) { /* filtering requested on schema name */ sprintf(query_end, " and %s", psch); query_end += strlen(query_end); free(psch); } if (ptab) { /* filtering requested on table name */ sprintf(query_end, " and %s", ptab); query_end += strlen(query_end); free(ptab); } if (fcat) { /* filtering requested on catalog name */ sprintf(query_end, " and %s", fcat); query_end += strlen(query_end); free(fcat); } if (fsch) { /* filtering requested on schema name */ sprintf(query_end, " and %s", fsch); query_end += strlen(query_end); free(fsch); } if (ftab) { /* filtering requested on table name */ sprintf(query_end, " and %s", ftab); query_end += strlen(query_end); free(ftab); } /* TODO finish the FROM and WHERE clauses */ /* add the ordering */ /* if PKTableName != NULL, selection on primary key, order on FK output columns, else order on PK output columns */ sprintf(query_end, " order by %stable_schem, %stable_name, key_seq", PKTableName != NULL ? "fk" : "pk", PKTableName != NULL ? "fk" : "pk"); query_end += strlen(query_end); /* query the MonetDB data dictionary tables */ rc = MNDBExecDirect(stmt, (SQLCHAR *) query, (SQLINTEGER) (query_end - query)); free(query); return rc; nomem: if (pcat) free(pcat); if (psch) free(psch); if (ptab) free(ptab); if (fcat) free(fcat); if (fsch) free(fsch); if (ftab) free(ftab); if (query) free(query); /* Memory allocation error */ addStmtError(stmt, "HY001", NULL, 0); return SQL_ERROR; }
SQLRETURN SQL_API SQLBindCol(SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType, SQLPOINTER TargetValuePtr, SQLLEN BufferLength, SQLLEN *StrLen_or_Ind) { ODBCStmt *stmt = (ODBCStmt *) StatementHandle; ODBCDesc *desc; /* Application Row Descriptor */ #ifdef ODBCDEBUG ODBCLOG("SQLBindCol " PTRFMT " %u %s " LENFMT "\n", PTRFMTCAST StatementHandle, (unsigned int) ColumnNumber, translateCType(TargetType), LENCAST BufferLength); #endif if (!isValidStmt(stmt)) return SQL_INVALID_HANDLE; assert(stmt->Dbc); clearStmtErrors(stmt); /* check input parameters */ /* column number 0 (Bookmark column) is not supported */ if (ColumnNumber == 0) { if (TargetType == SQL_C_BOOKMARK || TargetType == SQL_C_VARBOOKMARK) { /* Optional feature not implemented */ addStmtError(stmt, "HYC00", NULL, 0); } else { /* Restricted data type attribute violation */ addStmtError(stmt, "07006", NULL, 0); } return SQL_ERROR; } if (stmt->State >= EXECUTED1 && ColumnNumber > stmt->ImplRowDescr->sql_desc_count) { /* Invalid descriptor index */ addStmtError(stmt, "07009", NULL, 0); return SQL_ERROR; } /* For safety: limit the maximum number of columns to bind */ if (ColumnNumber > MONETDB_MAX_BIND_COLS) { /* General error */ addStmtError(stmt, "HY000", "Maximum number of bind columns (8192) exceeded", 0); return SQL_ERROR; } /* can't let SQLSetDescField below do this check since it returns the wrong error code if the type is incorrect */ switch (TargetType) { case SQL_C_CHAR: case SQL_C_WCHAR: case SQL_C_BINARY: case SQL_C_BIT: case SQL_C_STINYINT: case SQL_C_UTINYINT: case SQL_C_TINYINT: case SQL_C_SSHORT: case SQL_C_USHORT: case SQL_C_SHORT: case SQL_C_SLONG: case SQL_C_ULONG: case SQL_C_LONG: case SQL_C_SBIGINT: case SQL_C_UBIGINT: case SQL_C_NUMERIC: case SQL_C_FLOAT: case SQL_C_DOUBLE: case SQL_C_TYPE_DATE: case SQL_C_TYPE_TIME: case SQL_C_TYPE_TIMESTAMP: case SQL_C_INTERVAL_YEAR: case SQL_C_INTERVAL_MONTH: case SQL_C_INTERVAL_YEAR_TO_MONTH: case SQL_C_INTERVAL_DAY: case SQL_C_INTERVAL_HOUR: case SQL_C_INTERVAL_MINUTE: case SQL_C_INTERVAL_SECOND: case SQL_C_INTERVAL_DAY_TO_HOUR: case SQL_C_INTERVAL_DAY_TO_MINUTE: case SQL_C_INTERVAL_DAY_TO_SECOND: case SQL_C_INTERVAL_HOUR_TO_MINUTE: case SQL_C_INTERVAL_HOUR_TO_SECOND: case SQL_C_INTERVAL_MINUTE_TO_SECOND: case SQL_C_GUID: case SQL_C_DEFAULT: break; default: /* Invalid application buffer type */ addStmtError(stmt, "HY003", NULL, 0); return SQL_ERROR; } if (BufferLength < 0) { /* Invalid string or buffer length */ addStmtError(stmt, "HY090", NULL, 0); return SQL_ERROR; } desc = stmt->ApplRowDescr; if (TargetValuePtr == NULL && ColumnNumber == desc->sql_desc_count) { int i = desc->sql_desc_count - 1; while (i > 0 && desc->descRec[i].sql_desc_data_ptr == NULL) i--; setODBCDescRecCount(desc, i); } else { ODBCDescRec *rec; SQLRETURN rc; if (ColumnNumber > desc->sql_desc_count) setODBCDescRecCount(desc, ColumnNumber); rc = SQLSetDescField_(desc, ColumnNumber, SQL_DESC_CONCISE_TYPE, (SQLPOINTER) (ssize_t) TargetType, 0); if (!SQL_SUCCEEDED(rc)) return rc; rec = &desc->descRec[ColumnNumber]; rec->sql_desc_octet_length = BufferLength; rec->sql_desc_data_ptr = TargetValuePtr; rec->sql_desc_indicator_ptr = StrLen_or_Ind; rec->sql_desc_octet_length_ptr = StrLen_or_Ind; } return SQL_SUCCESS; }
static SQLRETURN SQLColumns_(ODBCStmt *stmt, SQLCHAR *CatalogName, SQLSMALLINT NameLength1, SQLCHAR *SchemaName, SQLSMALLINT NameLength2, SQLCHAR *TableName, SQLSMALLINT NameLength3, SQLCHAR *ColumnName, SQLSMALLINT NameLength4) { RETCODE rc; /* buffer for the constructed query to do meta data retrieval */ char *query = NULL; char *query_end = NULL; char *cat = NULL, *sch = NULL, *tab = NULL, *col = NULL; /* null pointers not allowed if arguments are identifiers */ if (stmt->Dbc->sql_attr_metadata_id == SQL_TRUE && (SchemaName == NULL || TableName == NULL || ColumnName == NULL)) { addStmtError(stmt, "HY090", NULL, 0); return SQL_ERROR; } fixODBCstring(CatalogName, NameLength1, SQLSMALLINT, addStmtError, stmt, return SQL_ERROR); fixODBCstring(SchemaName, NameLength2, SQLSMALLINT, addStmtError, stmt, return SQL_ERROR); fixODBCstring(TableName, NameLength3, SQLSMALLINT, addStmtError, stmt, return SQL_ERROR); fixODBCstring(ColumnName, NameLength4, SQLSMALLINT, addStmtError, stmt, return SQL_ERROR); #ifdef ODBCDEBUG ODBCLOG(" \"%.*s\" \"%.*s\" \"%.*s\" \"%.*s\"\n", (int) NameLength1, (char *) CatalogName, (int) NameLength2, (char *) SchemaName, (int) NameLength3, (char *) TableName, (int) NameLength4, (char *) ColumnName); #endif if (stmt->Dbc->sql_attr_metadata_id == SQL_FALSE) { if (NameLength1 > 0) { cat = ODBCParseOA("e", "value", (const char *) CatalogName, (size_t) NameLength1); } if (NameLength2 > 0) { sch = ODBCParsePV("s", "name", (const char *) SchemaName, (size_t) NameLength2); } if (NameLength3 > 0) { tab = ODBCParsePV("t", "name", (const char *) TableName, (size_t) NameLength3); } if (NameLength4 > 0) { col = ODBCParsePV("c", "name", (const char *) ColumnName, (size_t) NameLength4); } } else { if (NameLength1 > 0) { cat = ODBCParseID("e", "value", (const char *) CatalogName, (size_t) NameLength1); } if (NameLength2 > 0) { sch = ODBCParseID("s", "name", (const char *) SchemaName, (size_t) NameLength2); } if (NameLength3 > 0) { tab = ODBCParseID("t", "name", (const char *) TableName, (size_t) NameLength3); } if (NameLength4 > 0) { col = ODBCParseID("c", "name", (const char *) ColumnName, (size_t) NameLength4); } } /* construct the query now */ query = malloc(6500 + (cat ? strlen(cat) : 0) + (sch ? strlen(sch) : 0) + (tab ? strlen(tab) : 0) + (col ? strlen(col) : 0)); assert(query); query_end = query; /* SQLColumns returns a table with the following columns: VARCHAR table_cat VARCHAR table_schem VARCHAR table_name NOT NULL VARCHAR column_name NOT NULL SMALLINT data_type NOT NULL VARCHAR type_name NOT NULL INTEGER column_size INTEGER buffer_length SMALLINT decimal_digits SMALLINT num_prec_radix SMALLINT nullable NOT NULL VARCHAR remarks VARCHAR column_def SMALLINT sql_data_type NOT NULL SMALLINT sql_datetime_sub INTEGER char_octet_length INTEGER ordinal_position NOT NULL VARCHAR is_nullable */ sprintf(query_end, "select e.\"value\" as table_cat," " s.\"name\" as table_schem," " t.\"name\" as table_name," " c.\"name\" as column_name," " case c.\"type\"" " when 'bigint' then %d" " when 'blob' then %d" " when 'boolean' then %d" " when 'char' then %d" " when 'clob' then %d" " when 'date' then %d" " when 'decimal' then %d" " when 'double' then %d" " when 'int' then %d" " when 'month_interval' then" " case c.type_digits" " when 1 then %d" " when 2 then %d" " when 3 then %d" " end" " when 'real' then %d" " when 'sec_interval' then" " case c.type_digits" " when 4 then %d" " when 5 then %d" " when 6 then %d" " when 7 then %d" " when 8 then %d" " when 9 then %d" " when 10 then %d" " when 11 then %d" " when 12 then %d" " when 13 then %d" " end" " when 'smallint' then %d" " when 'time' then %d" " when 'timestamp' then %d" " when 'timestamptz' then %d" " when 'timetz' then %d" " when 'tinyint' then %d" " when 'varchar' then %d" " when 'wrd' then" " case c.type_digits" " when 32 then %d" " when 64 then %d" " end" " end as data_type," " case c.\"type\"" " when 'bigint' then 'BIGINT'" " when 'blob' then 'BINARY LARGE OBJECT'" " when 'boolean' then 'BOOLEAN'" " when 'char' then 'CHARACTER'" " when 'clob' then 'CHARACTER LARGE OBJECT'" " when 'date' then 'DATE'" " when 'decimal' then 'DECIMAL'" " when 'double' then 'DOUBLE'" " when 'int' then 'INTEGER'" " when 'month_interval' then" " case c.type_digits" " when 1 then 'INTERVAL YEAR'" " when 2 then 'INTERVAL YEAR TO MONTH'" " when 3 then 'INTERVAL MONTH'" " end" " when 'real' then 'REAL'" " when 'sec_interval' then" " case c.type_digits" " when 4 then 'INTERVAL DAY'" " when 5 then 'INTERVAL DAY TO HOUR'" " when 6 then 'INTERVAL DAY TO MINUTE'" " when 7 then 'INTERVAL DAY TO SECOND'" " when 8 then 'INTERVAL HOUR'" " when 9 then 'INTERVAL HOUR TO MINUTE'" " when 10 then 'INTERVAL HOUR TO SECOND'" " when 11 then 'INTERVAL MINUTE'" " when 12 then 'INTERVAL MINUTE TO SECOND'" " when 13 then 'INTERVAL SECOND'" " end" " when 'smallint' then 'SMALLINT'" " when 'time' then 'TIME'" " when 'timestamp' then 'TIMESTAMP'" " when 'timestamptz' then 'TIMESTAMP'" " when 'timetz' then 'TIME'" " when 'tinyint' then 'TINYINT'" " when 'varchar' then 'VARCHAR'" " when 'wrd' then" " case c.type_digits" " when 32 then 'INTEGER'" " when 64 then 'BIGINT'" " end" " end as type_name," " case c.\"type\"" " when 'date' then 10" " when 'month_interval' then" " case c.type_digits" " when 1 then 26" " when 2 then 38" " when 3 then 27" " end" " when 'sec_interval' then" " case c.type_digits" " when 4 then 25" " when 5 then 36" " when 6 then 41" " when 7 then 47" " when 8 then 26" " when 9 then 39" " when 10 then 45" " when 11 then 28" " when 12 then 44" " when 13 then 30" " end" " when 'time' then 12" " when 'timestamp' then 23" " when 'timestamptz' then 23" " when 'timetz' then 12" " else c.type_digits" " end as column_size," " case c.\"type\"" " when 'bigint' then 20" " when 'char' then 2 * c.type_digits" " when 'clob' then 2 * c.type_digits" " when 'date' then 10" " when 'double' then 24" " when 'int' then 11" " when 'month_interval' then" " case c.type_digits" " when 1 then 26" " when 2 then 38" " when 3 then 27" " end" " when 'real' then 14" " when 'sec_interval' then" " case c.type_digits" " when 4 then 25" " when 5 then 36" " when 6 then 41" " when 7 then 47" " when 8 then 26" " when 9 then 39" " when 10 then 45" " when 11 then 28" " when 12 then 44" " when 13 then 30" " end" " when 'smallint' then 6" " when 'time' then 12" " when 'timestamp' then 23" " when 'timestamptz' then 23" " when 'timetz' then 12" " when 'tinyint' then 4" " when 'varchar' then 2 * c.type_digits" " when 'wrd' then" " case c.type_digits" " when 32 then 11" " when 64 then 20" " end" " else c.type_digits" " end as buffer_length," " case c.\"type\"" " when 'bigint' then 19" " when 'decimal' then c.type_scale" " when 'double' then" " case when c.type_digits = 53 and c.type_scale = 0 then 15" " else c.type_digits" " end" " when 'int' then 10" " when 'month_interval' then 0" " when 'real' then" " case when c.type_digits = 24 and c.type_scale = 0 then 7" " else c.type_digits" " end" " when 'sec_interval' then 0" " when 'smallint' then 5" " when 'time' then c.type_digits - 1" " when 'timestamp' then c.type_digits - 1" " when 'timestamptz' then c.type_digits - 1" " when 'timetz' then c.type_digits - 1" " when 'tinyint' then 3" " when 'wrd' then" " case c.type_digits" " when 32 then 10" " when 64 then 19" " end" " else cast(null as smallint)" " end as decimal_digits," " case c.\"type\"" " when 'bigint' then 2" " when 'decimal' then 10" " when 'double' then" " case when c.type_digits = 53 and c.type_scale = 0 then 2" " else 10" " end" " when 'int' then 2" " when 'real' then" " case when c.type_digits = 24 and c.type_scale = 0 then 2" " else 10" " end" " when 'smallint' then 2" " when 'tinyint' then 2" " when 'wrd' then 2" " else cast(null as smallint)" " end as num_prec_radix," " case c.\"null\"" " when true then cast(%d as smallint)" " when false then cast(%d as smallint)" " end as nullable," " cast('' as varchar(1)) as remarks," " c.\"default\" as column_def," " case c.\"type\"" " when 'bigint' then %d" " when 'blob' then %d" " when 'boolean' then %d" " when 'char' then %d" " when 'clob' then %d" " when 'date' then %d" " when 'decimal' then %d" " when 'double' then %d" " when 'int' then %d" " when 'month_interval' then %d" " when 'real' then %d" " when 'sec_interval' then %d" " when 'smallint' then %d" " when 'time' then %d" " when 'timestamp' then %d" " when 'timestamptz' then %d" " when 'timetz' then %d" " when 'tinyint' then %d" " when 'varchar' then %d" " when 'wrd' then" " case c.type_digits" " when 32 then %d" " when 64 then %d" " end" " end as sql_data_type," " case c.\"type\"" " when 'date' then %d" " when 'month_interval' then" " case c.type_digits" " when 1 then %d" " when 2 then %d" " when 3 then %d" " end" " when 'sec_interval' then" " case c.type_digits" " when 4 then %d" " when 5 then %d" " when 6 then %d" " when 7 then %d" " when 8 then %d" " when 9 then %d" " when 10 then %d" " when 11 then %d" " when 12 then %d" " when 13 then %d" " end" " when 'time' then %d" " when 'timestamp' then %d" " when 'timestamptz' then %d" " when 'timetz' then %d" " else cast(null as smallint)" " end as sql_datetime_sub," " case c.\"type\"" " when 'char' then 2 * c.type_digits" " when 'varchar' then 2 * c.type_digits" " when 'clob' then 2 * c.type_digits" " when 'blob' then c.type_digits" " else cast(null as integer)" " end as char_octet_length," " cast(c.\"number\" + 1 as integer) as ordinal_position," " case c.\"null\"" " when true then cast('YES' as varchar(3))" " when false then cast('NO' as varchar(3))" " end as is_nullable" " from sys.\"schemas\" s," " sys.\"tables\" t," " sys.\"columns\" c," " sys.\"env\"() e" " where s.\"id\" = t.\"schema_id\" and" " t.\"id\" = c.\"table_id\" and" " e.\"name\" = 'gdk_dbname'", /* data_type: */ SQL_BIGINT, SQL_LONGVARBINARY, SQL_BIT, SQL_WCHAR, SQL_WLONGVARCHAR, SQL_TYPE_DATE, SQL_DECIMAL, SQL_DOUBLE, SQL_INTEGER, SQL_INTERVAL_YEAR, SQL_INTERVAL_YEAR_TO_MONTH, SQL_INTERVAL_MONTH, SQL_REAL, SQL_INTERVAL_DAY, SQL_INTERVAL_DAY_TO_HOUR, SQL_INTERVAL_DAY_TO_MINUTE, SQL_INTERVAL_DAY_TO_SECOND, SQL_INTERVAL_HOUR, SQL_INTERVAL_HOUR_TO_MINUTE, SQL_INTERVAL_HOUR_TO_SECOND, SQL_INTERVAL_MINUTE, SQL_INTERVAL_MINUTE_TO_SECOND, SQL_INTERVAL_SECOND, SQL_SMALLINT, SQL_TYPE_TIME, SQL_TYPE_TIMESTAMP, SQL_TYPE_TIMESTAMP, SQL_TYPE_TIME, SQL_TINYINT, SQL_WVARCHAR, SQL_INTEGER, SQL_BIGINT, /* nullable: */ SQL_NULLABLE, SQL_NO_NULLS, /* sql_data_type: */ SQL_BIGINT, SQL_LONGVARBINARY, SQL_BIT, SQL_WCHAR, SQL_WLONGVARCHAR, SQL_DATETIME, SQL_DECIMAL, SQL_DOUBLE, SQL_INTEGER, SQL_INTERVAL, SQL_REAL, SQL_INTERVAL, SQL_SMALLINT, SQL_DATETIME, SQL_DATETIME, SQL_DATETIME, SQL_DATETIME, SQL_TINYINT, SQL_WVARCHAR, SQL_INTEGER, SQL_BIGINT, /* sql_datetime_sub: */ SQL_CODE_DATE, SQL_CODE_YEAR, SQL_CODE_YEAR_TO_MONTH, SQL_CODE_MONTH, SQL_CODE_DAY, SQL_CODE_DAY_TO_HOUR, SQL_CODE_DAY_TO_MINUTE, SQL_CODE_DAY_TO_SECOND, SQL_CODE_HOUR, SQL_CODE_HOUR_TO_MINUTE, SQL_CODE_HOUR_TO_SECOND, SQL_CODE_MINUTE, SQL_CODE_MINUTE_TO_SECOND, SQL_CODE_SECOND, SQL_CODE_TIME, SQL_CODE_TIMESTAMP, SQL_CODE_TIMESTAMP, SQL_CODE_TIME); assert(strlen(query) < 6300); query_end += strlen(query_end); /* depending on the input parameter values we must add a variable selection condition dynamically */ /* Construct the selection condition query part */ if (cat) { /* filtering requested on catalog name */ sprintf(query_end, " and %s", cat); query_end += strlen(query_end); free(cat); } if (sch) { /* filtering requested on schema name */ sprintf(query_end, " and %s", sch); query_end += strlen(query_end); free(sch); } if (tab) { /* filtering requested on table name */ sprintf(query_end, " and %s", tab); query_end += strlen(query_end); free(tab); } if (col) { /* filtering requested on column name */ sprintf(query_end, " and %s", col); query_end += strlen(query_end); free(col); } /* add the ordering */ strcpy(query_end, " order by table_cat, table_schem, " "table_name, ordinal_position"); query_end += strlen(query_end); /* query the MonetDB data dictionary tables */ rc = SQLExecDirect_(stmt, (SQLCHAR *) query, (SQLINTEGER) (query_end - query)); free(query); return rc; }
static SQLRETURN MNDBSpecialColumns(ODBCStmt *stmt, SQLUSMALLINT IdentifierType, SQLCHAR *CatalogName, SQLSMALLINT NameLength1, SQLCHAR *SchemaName, SQLSMALLINT NameLength2, SQLCHAR *TableName, SQLSMALLINT NameLength3, SQLUSMALLINT Scope, SQLUSMALLINT Nullable) { RETCODE rc; /* buffer for the constructed query to do meta data retrieval */ char *query = NULL; char *query_end = NULL; char *cat = NULL, *sch = NULL, *tab = NULL; fixODBCstring(CatalogName, NameLength1, SQLSMALLINT, addStmtError, stmt, return SQL_ERROR); fixODBCstring(SchemaName, NameLength2, SQLSMALLINT, addStmtError, stmt, return SQL_ERROR); fixODBCstring(TableName, NameLength3, SQLSMALLINT, addStmtError, stmt, return SQL_ERROR); #ifdef ODBCDEBUG ODBCLOG("\"%.*s\" \"%.*s\" \"%.*s\" %s %s\n", (int) NameLength1, (char *) CatalogName, (int) NameLength2, (char *) SchemaName, (int) NameLength3, (char *) TableName, translateScope(Scope), translateNullable(Nullable)); #endif /* check for valid IdentifierType argument */ switch (IdentifierType) { case SQL_BEST_ROWID: case SQL_ROWVER: break; default: /* Column type out of range */ addStmtError(stmt, "HY097", NULL, 0); return SQL_ERROR; } /* check for valid Scope argument */ switch (Scope) { case SQL_SCOPE_CURROW: case SQL_SCOPE_TRANSACTION: case SQL_SCOPE_SESSION: break; default: /* Scope type out of range */ addStmtError(stmt, "HY098", NULL, 0); return SQL_ERROR; } /* check for valid Nullable argument */ switch (Nullable) { case SQL_NO_NULLS: case SQL_NULLABLE: break; default: /* Nullable type out of range */ addStmtError(stmt, "HY099", NULL, 0); return SQL_ERROR; } /* check if a valid (non null, not empty) table name is supplied */ if (TableName == NULL) { /* Invalid use of null pointer */ addStmtError(stmt, "HY009", NULL, 0); return SQL_ERROR; } if (NameLength3 == 0) { /* Invalid string or buffer length */ addStmtError(stmt, "HY090", NULL, 0); return SQL_ERROR; } /* SQLSpecialColumns returns a table with the following columns: SMALLINT scope VARCHAR column_name NOT NULL SMALLINT data_type NOT NULL VARCHAR type_name NOT NULL INTEGER column_size INTEGER buffer_length SMALLINT decimal_digits SMALLINT pseudo_column */ if (IdentifierType == SQL_BEST_ROWID) { /* Select from the key table the (smallest) primary/unique key */ if (stmt->Dbc->sql_attr_metadata_id == SQL_FALSE) { if (NameLength1 > 0) { cat = ODBCParseOA("e", "value", (const char *) CatalogName, (size_t) NameLength1); if (cat == NULL) goto nomem; } if (NameLength2 > 0) { sch = ODBCParseOA("s", "name", (const char *) SchemaName, (size_t) NameLength2); if (sch == NULL) goto nomem; } if (NameLength3 > 0) { tab = ODBCParseOA("t", "name", (const char *) TableName, (size_t) NameLength3); if (tab == NULL) goto nomem; } } else { if (NameLength1 > 0) { cat = ODBCParseID("e", "value", (const char *) CatalogName, (size_t) NameLength1); if (cat == NULL) goto nomem; } if (NameLength2 > 0) { sch = ODBCParseID("s", "name", (const char *) SchemaName, (size_t) NameLength2); if (sch == NULL) goto nomem; } if (NameLength3 > 0) { tab = ODBCParseID("t", "name", (const char *) TableName, (size_t) NameLength3); if (tab == NULL) goto nomem; } } /* first create a string buffer (1000 extra bytes is plenty */ query = (char *) malloc(5000 + NameLength1 + NameLength2 + NameLength3); if (query == NULL) goto nomem; query_end = query; /* Note: SCOPE is SQL_SCOPE_TRANSACTION */ /* Note: PSEUDO_COLUMN is SQL_PC_NOT_PSEUDO */ sprintf(query_end, "with sc as (" "select t.id as table_id, k.type as type, " "cast(%d as smallint) as scope, " "c.name as column_name, " DATA_TYPE(c) ", " TYPE_NAME(c) ", " COLUMN_SIZE(c) ", " BUFFER_LENGTH(c) ", " DECIMAL_DIGITS(c) ", " "cast(%d as smallint) as pseudo_column " "from sys.schemas s, " "sys.tables t, " "sys.columns c, " "sys.keys k, " "sys.objects kc, " "sys.env() e " "where s.id = t.schema_id and " "t.id = c.table_id and " "t.id = k.table_id and " "c.name = kc.name and " "kc.id = k.id and " "k.type = 0 and " "e.name = 'gdk_dbname'", /* scope: */ SQL_SCOPE_TRANSACTION, #ifdef DATA_TYPE_ARGS DATA_TYPE_ARGS, #endif #ifdef TYPE_NAME_ARGS TYPE_NAME_ARGS, #endif #ifdef COLUMN_SIZE_ARGS COLUMN_SIZE_ARGS, #endif #ifdef BUFFER_SIZE_ARGS BUFFER_SIZE_ARGS, #endif #ifdef DECIMAL_DIGITS_ARGS DECIMAL_DIGITS_ARGS, #endif /* pseudo_column: */ SQL_PC_NOT_PSEUDO); assert(strlen(query) < 4300); query_end += strlen(query_end); /* TODO: improve the SQL to get the correct result: - only one set of columns should be returned, also when multiple primary keys are available for this table. - when the table has NO primary key it should return the columns of a unique key (only from ONE unique key which is also the best/smallest key) TODO: optimize SQL: - when no SchemaName is set (see above) also no filtering on SCHEMA NAME and join with table SCHEMAS is needed! */ /* add the selection condition */ if (cat) { /* filtering requested on catalog name */ sprintf(query_end, " and %s", cat); query_end += strlen(query_end); free(cat); } if (sch) { /* filtering requested on schema name */ sprintf(query_end, " and %s", sch); query_end += strlen(query_end); free(sch); } if (tab) { /* filtering requested on table name */ sprintf(query_end, " and %s", tab); query_end += strlen(query_end); free(tab); } /* add an extra selection when SQL_NO_NULLS is requested */ if (Nullable == SQL_NO_NULLS) { strcpy(query_end, " and c.\"null\" = false"); query_end += strlen(query_end); } strcpy(query_end, "), " "tid as (" "select t.id as tid " "from sys._tables t, sys.keys k " "where t.id = k.table_id and k.type = 0" ") " "select sc.scope, sc.column_name, sc.data_type, " "sc.type_name, sc.column_size, " "sc.buffer_length, sc.decimal_digits, " "sc.pseudo_column " "from sc " "where (sc.type = 0 and " "sc.table_id in (select tid from tid)) or " "(sc.type = 1 and " "sc.table_id not in (select tid from tid))"); query_end += strlen(query_end); /* ordering on SCOPE not needed (since it is constant) */ } else { assert(IdentifierType == SQL_ROWVER); /* The backend does not have such info available */ /* create just a query which results in zero rows */ /* Note: pseudo_column is sql_pc_unknown is 0 */ query = strdup("select cast(null as smallint) as scope, " "cast('' as varchar(1)) as column_name, " "cast(1 as smallint) as data_type, " "cast('char' as varchar(4)) as type_name, " "cast(1 as integer) as column_size, " "cast(1 as integer) as buffer_length, " "cast(0 as smallint) as decimal_digits, " "cast(0 as smallint) as pseudo_column " "where 0 = 1"); if (query == NULL) goto nomem; query_end = query + strlen(query); } /* query the MonetDB data dictionary tables */ rc = MNDBExecDirect(stmt, (SQLCHAR *) query, (SQLINTEGER) (query_end - query)); free(query); return rc; nomem: /* note that query must be NULL when we get here */ if (cat) free(cat); if (sch) free(sch); if (tab) free(tab); /* Memory allocation error */ addStmtError(stmt, "HY001", NULL, 0); return SQL_ERROR; }
static SQLRETURN MNDBDescribeCol(ODBCStmt *stmt, SQLUSMALLINT ColumnNumber, SQLCHAR *ColumnName, SQLSMALLINT BufferLength, SQLSMALLINT *NameLengthPtr, SQLSMALLINT *DataTypePtr, SQLULEN *ColumnSizePtr, SQLSMALLINT *DecimalDigitsPtr, SQLSMALLINT *NullablePtr) { ODBCDescRec *rec = NULL; /* check statement cursor state, query should be executed */ if (stmt->State == INITED) { /* Function sequence error */ addStmtError(stmt, "HY010", NULL, 0); return SQL_ERROR; } if (stmt->State == PREPARED0) { /* Prepared statement not a cursor-specification */ addStmtError(stmt, "07005", NULL, 0); return SQL_ERROR; } if (stmt->State == EXECUTED0) { /* Invalid cursor state */ addStmtError(stmt, "24000", NULL, 0); return SQL_ERROR; } if (ColumnNumber < 1 || ColumnNumber > stmt->ImplRowDescr->sql_desc_count) { /* Invalid descriptor index */ addStmtError(stmt, "07009", NULL, 0); return SQL_ERROR; } rec = stmt->ImplRowDescr->descRec + ColumnNumber; /* now copy the data */ copyString(rec->sql_desc_name, strlen((char *) rec->sql_desc_name), ColumnName, BufferLength, NameLengthPtr, SQLSMALLINT, addStmtError, stmt, return SQL_ERROR); if (DataTypePtr) *DataTypePtr = rec->sql_desc_concise_type; /* also see SQLDescribeParam */ if (ColumnSizePtr) { *ColumnSizePtr = ODBCLength(rec, SQL_DESC_LENGTH); if (*ColumnSizePtr == (SQLULEN) SQL_NO_TOTAL) *ColumnSizePtr = 0; } /* also see SQLDescribeParam */ if (DecimalDigitsPtr) { switch (rec->sql_desc_concise_type) { case SQL_DECIMAL: case SQL_NUMERIC: *DecimalDigitsPtr = rec->sql_desc_scale; break; case SQL_BIT: case SQL_TINYINT: case SQL_SMALLINT: case SQL_INTEGER: case SQL_BIGINT: *DecimalDigitsPtr = 0; break; case SQL_TYPE_TIME: case SQL_TYPE_TIMESTAMP: case SQL_INTERVAL_SECOND: case SQL_INTERVAL_DAY_TO_SECOND: case SQL_INTERVAL_HOUR_TO_SECOND: case SQL_INTERVAL_MINUTE_TO_SECOND: *DecimalDigitsPtr = rec->sql_desc_precision; break; default: *DecimalDigitsPtr = 0; break; } } if (NullablePtr) *NullablePtr = rec->sql_desc_nullable; return stmt->Error ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS; }
SQLRETURN MNDBEndTran(SQLSMALLINT HandleType, SQLHANDLE Handle, SQLSMALLINT CompletionType) { ODBCEnv *env = NULL; ODBCDbc *dbc = NULL; SQLHANDLE StatementHandle; RETCODE rc; /* check parameters HandleType and Handle for validity */ switch (HandleType) { case SQL_HANDLE_DBC: dbc = (ODBCDbc *) Handle; if (!isValidDbc(dbc)) return SQL_INVALID_HANDLE; clearDbcErrors(dbc); if (!dbc->Connected) { /* Connection does not exist */ addDbcError(dbc, "08003", NULL, 0); return SQL_ERROR; } break; case SQL_HANDLE_ENV: env = (ODBCEnv *) Handle; if (!isValidEnv(env)) return SQL_INVALID_HANDLE; clearEnvErrors(env); if (env->sql_attr_odbc_version == 0) { /* Function sequence error */ addEnvError(env, "HY010", NULL, 0); return SQL_ERROR; } break; case SQL_HANDLE_STMT: if (isValidStmt((ODBCStmt *) Handle)) { clearStmtErrors((ODBCStmt *) Handle); /* Invalid attribute/option identifier */ addStmtError((ODBCStmt *) Handle, "HY092", NULL, 0); return SQL_ERROR; } return SQL_INVALID_HANDLE; case SQL_HANDLE_DESC: if (isValidDesc((ODBCDesc *) Handle)) { clearDescErrors((ODBCDesc *) Handle); /* Invalid attribute/option identifier */ addDescError((ODBCDesc *) Handle, "HY092", NULL, 0); return SQL_ERROR; } return SQL_INVALID_HANDLE; default: return SQL_INVALID_HANDLE; } /* check parameter CompletionType */ if (CompletionType != SQL_COMMIT && CompletionType != SQL_ROLLBACK) { /* Invalid transaction operation code */ if (HandleType == SQL_HANDLE_DBC) addDbcError(dbc, "HY012", NULL, 0); else addEnvError(env, "HY012", NULL, 0); return SQL_ERROR; } if (HandleType == SQL_HANDLE_ENV) { RETCODE rc1 = SQL_SUCCESS; for (dbc = env->FirstDbc; dbc; dbc = dbc->next) { assert(isValidDbc(dbc)); if (!dbc->Connected) continue; rc = MNDBEndTran(SQL_HANDLE_DBC, dbc, CompletionType); if (rc == SQL_ERROR) rc1 = SQL_ERROR; else if (rc == SQL_SUCCESS_WITH_INFO && rc1 != SQL_ERROR) rc1 = rc; } return rc1; } assert(HandleType == SQL_HANDLE_DBC); if (dbc->sql_attr_autocommit == SQL_AUTOCOMMIT_ON) { /* nothing to do if in autocommit mode */ return SQL_SUCCESS; } /* construct a statement object and excute a SQL COMMIT or ROLLBACK */ rc = MNDBAllocStmt(dbc, &StatementHandle); if (SQL_SUCCEEDED(rc)) { ODBCStmt *stmt = (ODBCStmt *) StatementHandle; rc = MNDBExecDirect(stmt, CompletionType == SQL_COMMIT ? (SQLCHAR *) "commit" : (SQLCHAR *) "rollback", SQL_NTS); if (rc == SQL_ERROR || rc == SQL_SUCCESS_WITH_INFO) { /* get the error/warning and post in on the * dbc handle */ SQLCHAR sqlState[SQL_SQLSTATE_SIZE + 1]; SQLINTEGER nativeErrCode; SQLCHAR msgText[SQL_MAX_MESSAGE_LENGTH + 1]; (void) MNDBGetDiagRec(SQL_HANDLE_STMT, stmt, 1, sqlState, &nativeErrCode, msgText, sizeof(msgText), NULL); addDbcError(dbc, (char *) sqlState, (char *) msgText + ODBCErrorMsgPrefixLength, nativeErrCode); } /* clean up the statement handle */ ODBCResetStmt(stmt); ODBCFreeStmt_(stmt); for (stmt = dbc->FirstStmt; stmt; stmt = stmt->next) ODBCResetStmt(stmt); } else { /* could not allocate a statement object */ /* Memory management error */ addDbcError(dbc, "HY013", NULL, 0); return SQL_ERROR; } return rc; }
SQLRETURN SQLColAttribute_(ODBCStmt *stmt, SQLUSMALLINT ColumnNumber, SQLUSMALLINT FieldIdentifier, SQLPOINTER CharacterAttributePtr, SQLSMALLINT BufferLength, SQLSMALLINT *StringLengthPtr, LENP_OR_POINTER_T NumericAttributePtr) { ODBCDescRec *rec; /* check statement cursor state, query should be prepared or executed */ if (stmt->State == INITED) { /* Function sequence error */ addStmtError(stmt, "HY010", NULL, 0); return SQL_ERROR; } if (stmt->State == EXECUTED0) { /* Invalid cursor state */ addStmtError(stmt, "24000", NULL, 0); return SQL_ERROR; } if (stmt->State == PREPARED0 && FieldIdentifier != SQL_DESC_COUNT) { /* Prepared statement not a cursor-specification */ addStmtError(stmt, "07005", NULL, 0); return SQL_ERROR; } if (stmt->ImplRowDescr->descRec == NULL) { /* General error */ addStmtError(stmt, "HY000", "Cannot return the column info. No result set is available", 0); return SQL_ERROR; } /* check input parameter */ if (ColumnNumber < 1 || ColumnNumber > stmt->ImplRowDescr->sql_desc_count) { /* Invalid descriptor index */ addStmtError(stmt, "07009", NULL, 0); return SQL_ERROR; } /* TODO: finish implementation */ rec = stmt->ImplRowDescr->descRec + ColumnNumber; switch (FieldIdentifier) { case SQL_DESC_AUTO_UNIQUE_VALUE: /* SQL_COLUMN_AUTO_INCREMENT */ if (NumericAttributePtr) *(SQLLEN *) NumericAttributePtr = rec->sql_desc_auto_unique_value; break; case SQL_DESC_BASE_COLUMN_NAME: copyString(rec->sql_desc_base_column_name, strlen((char *) rec->sql_desc_base_column_name), CharacterAttributePtr, BufferLength, StringLengthPtr, SQLSMALLINT, addStmtError, stmt, return SQL_ERROR); break; case SQL_DESC_BASE_TABLE_NAME: copyString(rec->sql_desc_base_table_name, strlen((char *) rec->sql_desc_base_table_name), CharacterAttributePtr, BufferLength, StringLengthPtr, SQLSMALLINT, addStmtError, stmt, return SQL_ERROR); break; case SQL_DESC_CASE_SENSITIVE: /* SQL_COLUMN_CASE_SENSITIVE */ if (NumericAttributePtr) *(SQLLEN *) NumericAttributePtr = rec->sql_desc_case_sensitive; break; case SQL_DESC_CATALOG_NAME: /* SQL_COLUMN_QUALIFIER_NAME */ copyString(rec->sql_desc_catalog_name, strlen((char *) rec->sql_desc_catalog_name), CharacterAttributePtr, BufferLength, StringLengthPtr, SQLSMALLINT, addStmtError, stmt, return SQL_ERROR); break; case SQL_DESC_CONCISE_TYPE: /* SQL_COLUMN_TYPE */ if (NumericAttributePtr) *(SQLLEN *) NumericAttributePtr = rec->sql_desc_concise_type; break; case SQL_DESC_COUNT: if (NumericAttributePtr) *(SQLLEN *) NumericAttributePtr = stmt->ImplRowDescr->sql_desc_count; break; case SQL_DESC_DISPLAY_SIZE: /* SQL_COLUMN_DISPLAY_SIZE */ if (NumericAttributePtr) *(SQLLEN *) NumericAttributePtr = rec->sql_desc_display_size; break; case SQL_DESC_FIXED_PREC_SCALE: /* SQL_COLUMN_MONEY */ if (NumericAttributePtr) *(SQLLEN *) NumericAttributePtr = rec->sql_desc_fixed_prec_scale; break; case SQL_DESC_LABEL: /* SQL_COLUMN_LABEL */ copyString(rec->sql_desc_label, strlen((char *) rec->sql_desc_label), CharacterAttributePtr, BufferLength, StringLengthPtr, SQLSMALLINT, addStmtError, stmt, return SQL_ERROR); break; case SQL_COLUMN_LENGTH: case SQL_DESC_LENGTH: if (NumericAttributePtr) *(SQLLEN *) NumericAttributePtr = rec->sql_desc_length; break; case SQL_DESC_LITERAL_PREFIX: copyString(rec->sql_desc_literal_prefix, strlen((char *) rec->sql_desc_literal_prefix), CharacterAttributePtr, BufferLength, StringLengthPtr, SQLSMALLINT, addStmtError, stmt, return SQL_ERROR); break; case SQL_DESC_LITERAL_SUFFIX: copyString(rec->sql_desc_literal_suffix, strlen((char *) rec->sql_desc_literal_suffix), CharacterAttributePtr, BufferLength, StringLengthPtr, SQLSMALLINT, addStmtError, stmt, return SQL_ERROR); break; case SQL_DESC_LOCAL_TYPE_NAME: copyString(rec->sql_desc_local_type_name, strlen((char *) rec->sql_desc_local_type_name), CharacterAttributePtr, BufferLength, StringLengthPtr, SQLSMALLINT, addStmtError, stmt, return SQL_ERROR); break; case SQL_DESC_NAME: copyString(rec->sql_desc_name, strlen((char *) rec->sql_desc_name), CharacterAttributePtr, BufferLength, StringLengthPtr, SQLSMALLINT, addStmtError, stmt, return SQL_ERROR); break; case SQL_DESC_NULLABLE: if (NumericAttributePtr) *(SQLLEN *) NumericAttributePtr = rec->sql_desc_nullable; break; case SQL_DESC_NUM_PREC_RADIX: if (NumericAttributePtr) *(SQLLEN *) NumericAttributePtr = rec->sql_desc_num_prec_radix; break; case SQL_DESC_OCTET_LENGTH: if (NumericAttributePtr) *(SQLLEN *) NumericAttributePtr = rec->sql_desc_octet_length; break; case SQL_COLUMN_PRECISION: case SQL_DESC_PRECISION: if (NumericAttributePtr) *(SQLLEN *) NumericAttributePtr = rec->sql_desc_precision; break; case SQL_COLUMN_SCALE: case SQL_DESC_SCALE: if (NumericAttributePtr) *(SQLLEN *) NumericAttributePtr = rec->sql_desc_scale; break; case SQL_DESC_SCHEMA_NAME: /* SQL_COLUMN_OWNER_NAME */ copyString(rec->sql_desc_schema_name, strlen((char *) rec->sql_desc_schema_name), CharacterAttributePtr, BufferLength, StringLengthPtr, SQLSMALLINT, addStmtError, stmt, return SQL_ERROR); break; case SQL_DESC_SEARCHABLE: /* SQL_COLUMN_SEARCHABLE */ if (NumericAttributePtr) *(SQLLEN *) NumericAttributePtr = rec->sql_desc_searchable; break; case SQL_DESC_TABLE_NAME: /* SQL_COLUMN_TABLE_NAME */ copyString(rec->sql_desc_table_name, strlen((char *) rec->sql_desc_table_name), CharacterAttributePtr, BufferLength, StringLengthPtr, SQLSMALLINT, addStmtError, stmt, return SQL_ERROR); break; case SQL_DESC_TYPE: if (NumericAttributePtr) *(SQLLEN *) NumericAttributePtr = rec->sql_desc_type; break; case SQL_DESC_TYPE_NAME: /* SQL_COLUMN_TYPE_NAME */ copyString(rec->sql_desc_type_name, strlen((char *) rec->sql_desc_type_name), CharacterAttributePtr, BufferLength, StringLengthPtr, SQLSMALLINT, addStmtError, stmt, return SQL_ERROR); break; case SQL_DESC_UNNAMED: if (NumericAttributePtr) *(SQLLEN *) NumericAttributePtr = rec->sql_desc_unnamed; break; case SQL_DESC_UNSIGNED: /* SQL_COLUMN_UNSIGNED */ if (NumericAttributePtr) *(SQLLEN *) NumericAttributePtr = rec->sql_desc_unsigned; break; case SQL_DESC_UPDATABLE: /* SQL_COLUMN_UPDATABLE */ if (NumericAttributePtr) *(SQLLEN *) NumericAttributePtr = rec->sql_desc_updatable; break; default: /* Invalid descriptor field identifier */ addStmtError(stmt, "HY091", NULL, 0); return SQL_ERROR; } return stmt->Error ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS; }
SQLRETURN MNDBFetch(ODBCStmt *stmt, SQLUSMALLINT *RowStatusArray) { ODBCDesc *ard, *ird; ODBCDescRec *rec; int i; SQLULEN row; SQLLEN offset; /* stmt->startRow is the (0 based) index of the first row we * stmt->need to fetch */ ard = stmt->ApplRowDescr; ird = stmt->ImplRowDescr; stmt->retrieved = 0; stmt->currentCol = 0; stmt->rowSetSize = 0; stmt->currentRow = stmt->startRow + 1; if (mapi_seek_row(stmt->hdl, stmt->startRow, MAPI_SEEK_SET) != MOK) { /* Row value out of range */ addStmtError(stmt, "HY107", mapi_error_str(stmt->Dbc->mid), 0); return SQL_ERROR; } stmt->State = FETCHED; if (stmt->retrieveData == SQL_RD_OFF) { /* don't really retrieve the data, just do as if, updating the SQL_DESC_ARRAY_STATUS_PTR */ stmt->rowSetSize = ard->sql_desc_array_size; if (stmt->startRow + stmt->rowSetSize > (SQLLEN) stmt->rowcount) stmt->rowSetSize = stmt->rowcount - stmt->startRow; if (stmt->rowSetSize <= 0) { stmt->rowSetSize = 0; return SQL_NO_DATA; } if (RowStatusArray) { for (row = 0; (SQLLEN) row < stmt->rowSetSize; row++) { WriteValue(RowStatusArray, SQL_ROW_SUCCESS); RowStatusArray++; } for (; row < ard->sql_desc_array_size; row++) { WriteValue(RowStatusArray, SQL_ROW_NOROW); RowStatusArray++; } } return SQL_SUCCESS; } if (ard->sql_desc_bind_offset_ptr) offset = *ard->sql_desc_bind_offset_ptr; else offset = 0; for (row = 0; row < ard->sql_desc_array_size; row++) { if (mapi_fetch_row(stmt->hdl) == 0) { switch (mapi_error(stmt->Dbc->mid)) { case MOK: if (row == 0) return SQL_NO_DATA; break; case MTIMEOUT: if (RowStatusArray) WriteValue(RowStatusArray, SQL_ROW_ERROR); /* Timeout expired / Communication * link failure */ addStmtError(stmt, stmt->Dbc->sql_attr_connection_timeout ? "HYT00" : "08S01", mapi_error_str(stmt->Dbc->mid), 0); return SQL_ERROR; default: if (RowStatusArray) WriteValue(RowStatusArray, SQL_ROW_ERROR); /* General error */ addStmtError(stmt, "HY000", mapi_error_str(stmt->Dbc->mid), 0); return SQL_ERROR; } break; } if (RowStatusArray) WriteValue(RowStatusArray, SQL_ROW_SUCCESS); stmt->rowSetSize++; for (i = 1; i <= ird->sql_desc_count; i++) ird->descRec[i].already_returned = 0; for (i = 1; i <= ard->sql_desc_count; i++) { rec = &ard->descRec[i]; if (rec->sql_desc_data_ptr == NULL) continue; stmt->retrieved = 0; if (ODBCFetch(stmt, i, rec->sql_desc_concise_type, rec->sql_desc_data_ptr, rec->sql_desc_octet_length, rec->sql_desc_octet_length_ptr, rec->sql_desc_indicator_ptr, rec->sql_desc_precision, rec->sql_desc_scale, rec->sql_desc_datetime_interval_precision, offset, row) == SQL_ERROR) { if (RowStatusArray) WriteValue(RowStatusArray, SQL_ROW_SUCCESS_WITH_INFO); } } if (RowStatusArray) RowStatusArray++; } if (ird->sql_desc_rows_processed_ptr) *ird->sql_desc_rows_processed_ptr = (SQLULEN) stmt->rowSetSize; if (RowStatusArray) while (row++ < ard->sql_desc_array_size) { WriteValue(RowStatusArray, SQL_ROW_NOROW); RowStatusArray++; } return stmt->Error ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS; }
SQLRETURN MNDBGetStmtAttr(ODBCStmt *stmt, SQLINTEGER Attribute, SQLPOINTER ValuePtr, SQLINTEGER BufferLength, SQLINTEGER *StringLengthPtr) { /* TODO: check parameters: ValuePtr, BufferLength and * StringLengthPtr */ switch (Attribute) { #ifndef STATIC_CODE_ANALYSIS /* Coverity doesn't like the debug print in WriteData, so we * hide this whole thing */ case SQL_ATTR_APP_PARAM_DESC: /* SQLHANDLE */ WriteData(ValuePtr, stmt->ApplParamDescr, SQLHANDLE); return SQL_SUCCESS; case SQL_ATTR_APP_ROW_DESC: /* SQLHANDLE */ WriteData(ValuePtr, stmt->ApplRowDescr, SQLHANDLE); return SQL_SUCCESS; #endif case SQL_ATTR_ASYNC_ENABLE: /* SQLULEN */ /* SQL_ASYNC_ENABLE */ WriteData(ValuePtr, SQL_ASYNC_ENABLE_OFF, SQLULEN); break; case SQL_ATTR_CONCURRENCY: /* SQLULEN */ /* SQL_CONCURRENCY */ WriteData(ValuePtr, SQL_CONCUR_READ_ONLY, SQLULEN); break; case SQL_ATTR_CURSOR_SCROLLABLE: /* SQLULEN */ WriteData(ValuePtr, stmt->cursorScrollable, SQLULEN); break; case SQL_ATTR_CURSOR_SENSITIVITY: /* SQLULEN */ WriteData(ValuePtr, SQL_INSENSITIVE, SQLULEN); break; case SQL_ATTR_CURSOR_TYPE: /* SQLULEN */ /* SQL_CURSOR_TYPE */ WriteData(ValuePtr, stmt->cursorType, SQLULEN); break; #ifndef STATIC_CODE_ANALYSIS /* Coverity doesn't like the debug print in WriteData, so we * hide this whole thing */ case SQL_ATTR_IMP_PARAM_DESC: /* SQLHANDLE */ WriteData(ValuePtr, stmt->ImplParamDescr, SQLHANDLE); return SQL_SUCCESS; case SQL_ATTR_IMP_ROW_DESC: /* SQLHANDLE */ WriteData(ValuePtr, stmt->ImplRowDescr, SQLHANDLE); return SQL_SUCCESS; #endif case SQL_ATTR_MAX_LENGTH: /* SQLULEN */ /* SQL_MAX_LENGTH */ WriteData(ValuePtr, 0, SQLULEN); break; case SQL_ATTR_MAX_ROWS: /* SQLULEN */ /* SQL_MAX_ROWS */ WriteData(ValuePtr, 0, SQLULEN); break; case SQL_ATTR_METADATA_ID: /* SQLULEN */ WriteData(ValuePtr, stmt->Dbc->sql_attr_metadata_id, SQLULEN); break; case SQL_ATTR_NOSCAN: /* SQLULEN */ /* SQL_NOSCAN */ WriteData(ValuePtr, stmt->noScan, SQLULEN); break; case SQL_ATTR_PARAM_BIND_OFFSET_PTR: /* SQLULEN* */ return MNDBGetDescField(stmt->ApplParamDescr, 0, SQL_DESC_BIND_OFFSET_PTR, ValuePtr, BufferLength, StringLengthPtr); case SQL_ATTR_PARAM_BIND_TYPE: /* SQLULEN */ /* SQL_BIND_TYPE */ WriteData(ValuePtr, stmt->ApplParamDescr->sql_desc_bind_type, SQLULEN); break; case SQL_ATTR_PARAM_OPERATION_PTR: /* SQLUSMALLINT* */ return MNDBGetDescField(stmt->ApplParamDescr, 0, SQL_DESC_ARRAY_STATUS_PTR, ValuePtr, BufferLength, StringLengthPtr); case SQL_ATTR_PARAMSET_SIZE: /* SQLULEN */ return MNDBGetDescField(stmt->ApplParamDescr, 0, SQL_DESC_ARRAY_SIZE, ValuePtr, BufferLength, StringLengthPtr); case SQL_ATTR_PARAMS_PROCESSED_PTR: /* SQLULEN* */ return MNDBGetDescField(stmt->ImplParamDescr, 0, SQL_DESC_ROWS_PROCESSED_PTR, ValuePtr, BufferLength, StringLengthPtr); case SQL_ATTR_PARAM_STATUS_PTR: /* SQLUSMALLINT* */ return MNDBGetDescField(stmt->ImplParamDescr, 0, SQL_DESC_ARRAY_STATUS_PTR, ValuePtr, BufferLength, StringLengthPtr); case SQL_ATTR_RETRIEVE_DATA: /* SQLULEN */ /* SQL_RETRIEVE_DATA */ WriteData(ValuePtr, stmt->retrieveData, SQLULEN); break; case SQL_ATTR_ROW_ARRAY_SIZE: /* SQLULEN */ case SQL_ROWSET_SIZE: return MNDBGetDescField(stmt->ApplRowDescr, 0, SQL_DESC_ARRAY_SIZE, ValuePtr, BufferLength, StringLengthPtr); case SQL_ATTR_ROW_BIND_OFFSET_PTR: /* SQLULEN* */ return MNDBGetDescField(stmt->ApplRowDescr, 0, SQL_DESC_BIND_OFFSET_PTR, ValuePtr, BufferLength, StringLengthPtr); case SQL_ATTR_ROW_BIND_TYPE: /* SQLULEN */ WriteData(ValuePtr, stmt->ApplRowDescr->sql_desc_bind_type, SQLULEN); break; case SQL_ATTR_ROW_NUMBER: /* SQLULEN */ if (stmt->State <= EXECUTED1) { /* Invalid cursor state */ addStmtError(stmt, "24000", NULL, 0); return SQL_ERROR; } WriteData(ValuePtr, (SQLULEN) stmt->currentRow, SQLULEN); break; case SQL_ATTR_ROW_OPERATION_PTR: /* SQLUSMALLINT* */ return MNDBGetDescField(stmt->ApplRowDescr, 0, SQL_DESC_ARRAY_STATUS_PTR, ValuePtr, BufferLength, StringLengthPtr); case SQL_ATTR_ROW_STATUS_PTR: /* SQLUSMALLINT* */ return MNDBGetDescField(stmt->ImplRowDescr, 0, SQL_DESC_ARRAY_STATUS_PTR, ValuePtr, BufferLength, StringLengthPtr); case SQL_ATTR_ROWS_FETCHED_PTR: /* SQLULEN* */ return MNDBGetDescField(stmt->ImplRowDescr, 0, SQL_DESC_ROWS_PROCESSED_PTR, ValuePtr, BufferLength, StringLengthPtr); /* TODO: implement requested behavior */ #ifdef SQL_ATTR_ASYNC_STMT_EVENT case SQL_ATTR_ASYNC_EVENT: /* SQLPOINTER */ #endif #ifdef SQL_ATTR_ASYNC_STMT_PCALLBACK case SQL_ATTR_ASYNC_PCALLBACK: /* SQLPOINTER */ #endif #ifdef SQL_ATTR_ASYNC_STMT_PCONTEXT case SQL_ATTR_ASYNC_PCONTEXT: /* SQLPOINTER */ #endif case SQL_ATTR_ENABLE_AUTO_IPD: /* SQLULEN */ case SQL_ATTR_FETCH_BOOKMARK_PTR: /* SQLLEN* */ case SQL_ATTR_KEYSET_SIZE: /* SQLULEN */ /* SQL_KEYSET_SIZE */ case SQL_ATTR_QUERY_TIMEOUT: /* SQLULEN */ /* SQL_QUERY_TIMEOUT */ case SQL_ATTR_SIMULATE_CURSOR: /* SQLULEN */ case SQL_ATTR_USE_BOOKMARKS: /* SQLULEN */ /* Optional feature not implemented */ addStmtError(stmt, "HYC00", NULL, 0); return SQL_ERROR; default: /* Invalid attribute/option identifier */ addStmtError(stmt, "HY092", NULL, 0); return SQL_ERROR; } return SQL_SUCCESS; }
static SQLRETURN MNDBPrimaryKeys(ODBCStmt *stmt, SQLCHAR *CatalogName, SQLSMALLINT NameLength1, SQLCHAR *SchemaName, SQLSMALLINT NameLength2, SQLCHAR *TableName, SQLSMALLINT NameLength3) { RETCODE rc; /* buffer for the constructed query to do meta data retrieval */ char *query = NULL; char *query_end = NULL; /* pointer to end of built-up query */ char *cat = NULL, *sch = NULL, *tab = NULL; /* deal with SQL_NTS and SQL_NULL_DATA */ fixODBCstring(CatalogName, NameLength1, SQLSMALLINT, addStmtError, stmt, return SQL_ERROR); fixODBCstring(SchemaName, NameLength2, SQLSMALLINT, addStmtError, stmt, return SQL_ERROR); fixODBCstring(TableName, NameLength3, SQLSMALLINT, addStmtError, stmt, return SQL_ERROR); /* check if a valid (non null, not empty) table name is supplied */ if (TableName == NULL) { /* Invalid use of null pointer */ addStmtError(stmt, "HY009", NULL, 0); return SQL_ERROR; } #ifdef ODBCDEBUG ODBCLOG("\"%.*s\" \"%.*s\" \"%.*s\"\n", (int) NameLength1, (char *) CatalogName, (int) NameLength2, (char *) SchemaName, (int) NameLength3, (char *) TableName); #endif if (stmt->Dbc->sql_attr_metadata_id == SQL_FALSE) { if (NameLength1 > 0) { cat = ODBCParseOA("e", "value", (const char *) CatalogName, (size_t) NameLength1); if (cat == NULL) goto nomem; } if (NameLength2 > 0) { sch = ODBCParseOA("s", "name", (const char *) SchemaName, (size_t) NameLength2); if (sch == NULL) goto nomem; } if (NameLength3 > 0) { tab = ODBCParseOA("t", "name", (const char *) TableName, (size_t) NameLength3); if (tab == NULL) goto nomem; } } else { if (NameLength1 > 0) { cat = ODBCParseID("e", "value", (const char *) CatalogName, (size_t) NameLength1); if (cat == NULL) goto nomem; } if (NameLength2 > 0) { sch = ODBCParseID("s", "name", (const char *) SchemaName, (size_t) NameLength2); if (sch == NULL) goto nomem; } if (NameLength3 > 0) { tab = ODBCParseID("t", "name", (const char *) TableName, (size_t) NameLength3); if (tab == NULL) goto nomem; } } /* construct the query */ query = malloc(1000 + (cat ? strlen(cat) : 0) + (sch ? strlen(sch) : 0) + (tab ? strlen(tab) : 0)); if (query == NULL) goto nomem; query_end = query; /* SQLPrimaryKeys returns a table with the following columns: VARCHAR table_cat VARCHAR table_schem VARCHAR table_name NOT NULL VARCHAR column_name NOT NULL SMALLINT key_seq NOT NULL VARCHAR pk_name */ strcpy(query_end, "select e.value as table_cat, " "s.name as table_schem, " "t.name as table_name, " "kc.name as column_name, " "cast(kc.nr + 1 as smallint) as key_seq, " "k.name as pk_name " "from sys.schemas s, sys.tables t, " "sys.keys k, sys.objects kc, " "sys.env() e " "where k.id = kc.id and " "k.table_id = t.id and " "t.schema_id = s.id and " "k.type = 0 and " "e.name = 'gdk_dbname'"); assert(strlen(query) < 800); query_end += strlen(query_end); /* Construct the selection condition query part */ if (cat) { /* filtering requested on catalog name */ sprintf(query_end, " and %s", cat); query_end += strlen(query_end); free(cat); } if (sch) { /* filtering requested on schema name */ sprintf(query_end, " and %s", sch); query_end += strlen(query_end); free(sch); } if (tab) { /* filtering requested on table name */ sprintf(query_end, " and %s", tab); query_end += strlen(query_end); free(tab); } /* add the ordering */ strcpy(query_end, " order by table_schem, table_name, key_seq"); query_end += strlen(query_end); /* query the MonetDB data dictionary tables */ rc = MNDBExecDirect(stmt, (SQLCHAR *) query, (SQLINTEGER) (query_end - query)); free(query); return rc; nomem: /* note that query must be NULL when we get here */ if (cat) free(cat); if (sch) free(sch); if (tab) free(tab); /* Memory allocation error */ addStmtError(stmt, "HY001", NULL, 0); return SQL_ERROR; }
SQLRETURN SQL_API SQLDescribeParam(SQLHSTMT StatementHandle, SQLUSMALLINT ParameterNumber, SQLSMALLINT *DataTypePtr, SQLULEN *ParameterSizePtr, SQLSMALLINT *DecimalDigitsPtr, SQLSMALLINT *NullablePtr) { ODBCStmt *stmt = (ODBCStmt *) StatementHandle; ODBCDescRec *rec; #ifdef ODBCDEBUG ODBCLOG("SQLDescribeParam " PTRFMT " %u\n", PTRFMTCAST StatementHandle, (unsigned int) ParameterNumber); #endif if (!isValidStmt(stmt)) return SQL_INVALID_HANDLE; clearStmtErrors(stmt); /* check statement cursor state, query should be prepared or executed */ if (stmt->State == INITED || stmt->State >= EXECUTED0) { /* Function sequence error */ addStmtError(stmt, "HY010", NULL, 0); return SQL_ERROR; } if (ParameterNumber < 1 || ParameterNumber > stmt->ImplParamDescr->sql_desc_count) { /* Invalid descriptor index */ addStmtError(stmt, "07009", NULL, 0); return SQL_ERROR; } rec = &stmt->ImplParamDescr->descRec[ParameterNumber]; if (DataTypePtr) *DataTypePtr = rec->sql_desc_concise_type; if (NullablePtr) *NullablePtr = rec->sql_desc_nullable; /* also see SQLDescribeCol */ if (ParameterSizePtr) *ParameterSizePtr = ODBCLength(rec, SQL_DESC_LENGTH); /* also see SQLDescribeCol */ if (DecimalDigitsPtr) { switch (rec->sql_desc_concise_type) { case SQL_DECIMAL: case SQL_NUMERIC: *DecimalDigitsPtr = rec->sql_desc_scale; break; case SQL_BIT: case SQL_TINYINT: case SQL_SMALLINT: case SQL_INTEGER: case SQL_BIGINT: *DecimalDigitsPtr = 0; break; case SQL_TYPE_TIME: case SQL_TYPE_TIMESTAMP: case SQL_INTERVAL_SECOND: case SQL_INTERVAL_DAY_TO_SECOND: case SQL_INTERVAL_HOUR_TO_SECOND: case SQL_INTERVAL_MINUTE_TO_SECOND: *DecimalDigitsPtr = rec->sql_desc_precision; break; } } return SQL_SUCCESS; }
static SQLRETURN MNDBGetTypeInfo(ODBCStmt *stmt, SQLSMALLINT DataType) { const char **tuples[sizeof(types) / sizeof(types[0])]; struct types *t; int i; switch (DataType) { case SQL_ALL_TYPES: case SQL_CHAR: case SQL_NUMERIC: case SQL_DECIMAL: case SQL_INTEGER: case SQL_SMALLINT: case SQL_FLOAT: case SQL_REAL: case SQL_DOUBLE: case SQL_DATE: case SQL_TIME: case SQL_TIMESTAMP: case SQL_VARCHAR: case SQL_TYPE_DATE: case SQL_TYPE_TIME: case SQL_TYPE_TIMESTAMP: case SQL_LONGVARCHAR: case SQL_BINARY: case SQL_VARBINARY: case SQL_LONGVARBINARY: case SQL_BIGINT: case SQL_TINYINT: case SQL_BIT: case SQL_WCHAR: case SQL_WVARCHAR: case SQL_WLONGVARCHAR: case SQL_GUID: case SQL_INTERVAL_YEAR: case SQL_INTERVAL_MONTH: case SQL_INTERVAL_DAY: case SQL_INTERVAL_HOUR: case SQL_INTERVAL_MINUTE: case SQL_INTERVAL_SECOND: case SQL_INTERVAL_YEAR_TO_MONTH: case SQL_INTERVAL_DAY_TO_HOUR: case SQL_INTERVAL_DAY_TO_MINUTE: case SQL_INTERVAL_DAY_TO_SECOND: case SQL_INTERVAL_HOUR_TO_MINUTE: case SQL_INTERVAL_HOUR_TO_SECOND: case SQL_INTERVAL_MINUTE_TO_SECOND: break; /* some pre ODBC 3.0 data types which can be mapped to ODBC * 3.0 data types */ case -80: /* SQL_INTERVAL_YEAR */ DataType = SQL_INTERVAL_YEAR; break; case -81: /* SQL_INTERVAL_YEAR_TO_MONTH */ DataType = SQL_INTERVAL_YEAR_TO_MONTH; break; case -82: /* SQL_INTERVAL_MONTH */ DataType = SQL_INTERVAL_MONTH; break; case -83: /* SQL_INTERVAL_DAY */ DataType = SQL_INTERVAL_DAY; break; case -84: /* SQL_INTERVAL_HOUR */ DataType = SQL_INTERVAL_HOUR; break; case -85: /* SQL_INTERVAL_MINUTE */ DataType = SQL_INTERVAL_MINUTE; break; case -86: /* SQL_INTERVAL_SECOND */ DataType = SQL_INTERVAL_SECOND; break; case -87: /* SQL_INTERVAL_DAY_TO_HOUR */ DataType = SQL_INTERVAL_DAY_TO_HOUR; break; case -88: /* SQL_INTERVAL_DAY_TO_MINUTE */ DataType = SQL_INTERVAL_DAY_TO_MINUTE; break; case -89: /* SQL_INTERVAL_DAY_TO_SECOND */ DataType = SQL_INTERVAL_DAY_TO_SECOND; break; case -90: /* SQL_INTERVAL_HOUR_TO_MINUTE */ DataType = SQL_INTERVAL_HOUR_TO_MINUTE; break; case -91: /* SQL_INTERVAL_HOUR_TO_SECOND */ DataType = SQL_INTERVAL_HOUR_TO_SECOND; break; case -92: /* SQL_INTERVAL_MINUTE_TO_SECOND */ DataType = SQL_INTERVAL_MINUTE_TO_SECOND; break; case -95: /* SQL_UNICODE_CHAR and SQL_UNICODE */ DataType = SQL_WCHAR; break; case -96: /* SQL_UNICODE_VARCHAR */ DataType = SQL_WVARCHAR; break; case -97: /* SQL_UNICODE_LONGVARCHAR */ DataType = SQL_WLONGVARCHAR; break; default: /* Invalid SQL data type */ addStmtError(stmt, "HY004", NULL, 0); return SQL_ERROR; } for (t = types, i = 0; t < &types[sizeof(types) / sizeof(types[0])]; t++) { assert(t == types || t->data_type >= (t-1)->data_type); if (DataType == SQL_ALL_TYPES || DataType == t->data_type) { if (t->tuple == NULL) { char buf[32]; t->tuple = malloc(NCOLUMNS * sizeof(*t->tuple)); t->tuple[0] = t->type_name; snprintf(buf, sizeof(buf), "%d", t->data_type); t->tuple[1] = strdup(buf); if (t->column_size == -1) t->tuple[2] = NULL; else { snprintf(buf, sizeof(buf), "%d", t->column_size); t->tuple[2] = strdup(buf); } t->tuple[3] = t->literal_prefix; t->tuple[4] = t->literal_suffix; t->tuple[5] = t->create_params; snprintf(buf, sizeof(buf), "%d", t->nullable); t->tuple[6] = strdup(buf); snprintf(buf, sizeof(buf), "%d", t->case_sensitive); t->tuple[7] = strdup(buf); snprintf(buf, sizeof(buf), "%d", t->searchable); t->tuple[8] = strdup(buf); if (t->unsigned_attribute == -1) t->tuple[9] = NULL; else { snprintf(buf, sizeof(buf), "%d", t->unsigned_attribute); t->tuple[9] = strdup(buf); } snprintf(buf, sizeof(buf), "%d", t->fixed_prec_scale); t->tuple[10] = strdup(buf); if (t->auto_unique_value == -1) t->tuple[11] = NULL; else { snprintf(buf, sizeof(buf), "%d", t->auto_unique_value); t->tuple[11] = strdup(buf); } t->tuple[12] = t->local_type_name; if (t->minimum_scale == -1) t->tuple[13] = NULL; else { snprintf(buf, sizeof(buf), "%d", t->minimum_scale); t->tuple[13] = strdup(buf); } if (t->maximum_scale == -1) t->tuple[14] = NULL; else { snprintf(buf, sizeof(buf), "%d", t->maximum_scale); t->tuple[14] = strdup(buf); } snprintf(buf, sizeof(buf), "%d", t->sql_data_type); t->tuple[15] = strdup(buf); if (t->sql_datetime_sub == -1) t->tuple[16] = NULL; else { snprintf(buf, sizeof(buf), "%d", t->sql_datetime_sub); t->tuple[16] = strdup(buf); } if (t->num_prec_radix == -1) t->tuple[17] = NULL; else { snprintf(buf, sizeof(buf), "%d", t->num_prec_radix); t->tuple[17] = strdup(buf); } if (t->interval_precision == -1) t->tuple[18] = NULL; else { snprintf(buf, sizeof(buf), "%d", t->interval_precision); t->tuple[18] = strdup(buf); } } tuples[i++] = t->tuple; } } mapi_virtual_result(stmt->hdl, NCOLUMNS, columnnames, columntypes, columnlengths, i, tuples); return ODBCInitResult(stmt); }
SQLRETURN SQL_API SQLSetPos(SQLHSTMT StatementHandle, SQLSETPOSIROW RowNumber, SQLUSMALLINT Operation, SQLUSMALLINT LockType) { ODBCStmt *stmt = (ODBCStmt *) StatementHandle; #ifdef ODBCDEBUG ODBCLOG("SQLSetPos " PTRFMT " " ULENFMT " %s %s\n", PTRFMTCAST StatementHandle, ULENCAST RowNumber, translateOperation(Operation), translateLockType(LockType)); #endif if (!isValidStmt(stmt)) return SQL_INVALID_HANDLE; clearStmtErrors(stmt); /* check the parameter values */ if (stmt->State < EXECUTED0) { /* Function sequence error */ addStmtError(stmt, "HY010", NULL, 0); return SQL_ERROR; } if (stmt->State <= EXECUTED1) { /* Invalid cursor state */ addStmtError(stmt, "24000", NULL, 0); return SQL_ERROR; } if (RowNumber > (SQLSETPOSIROW) stmt->rowSetSize) { /* Row value out of range */ addStmtError(stmt, "HY107", NULL, 0); return SQL_ERROR; } if (stmt->cursorType == SQL_CURSOR_FORWARD_ONLY) { /* Invalid cursor position */ addStmtError(stmt, "HY109", NULL, 0); return SQL_ERROR; } switch (LockType) { case SQL_LOCK_NO_CHANGE: /* the only value that we support */ break; case SQL_LOCK_EXCLUSIVE: case SQL_LOCK_UNLOCK: /* Optional feature not implemented */ addStmtError(stmt, "HYC00", NULL, 0); return SQL_ERROR; default: /* Invalid attribute/option identifier */ addStmtError(stmt, "HY092", NULL, 0); return SQL_ERROR; } switch (Operation) { case SQL_POSITION: if (RowNumber == 0) { /* Invalid cursor position */ addStmtError(stmt, "HY109", NULL, 0); return SQL_ERROR; } if (mapi_seek_row(stmt->hdl, stmt->startRow + RowNumber - 1, MAPI_SEEK_SET) != MOK) { /* Invalid cursor position */ addStmtError(stmt, "HY109", NULL, 0); return SQL_ERROR; } stmt->currentRow = stmt->startRow + RowNumber - 1; switch (mapi_fetch_row(stmt->hdl)) { case MOK: break; case MTIMEOUT: /* Connection timeout expired */ addStmtError(stmt, "HYT01", NULL, 0); return SQL_ERROR; default: /* Invalid cursor position */ addStmtError(stmt, "HY109", NULL, 0); return SQL_ERROR; } stmt->currentRow++; break; case SQL_REFRESH: case SQL_UPDATE: case SQL_DELETE: /* Optional feature not implemented */ addStmtError(stmt, "HYC00", NULL, 0); return SQL_ERROR; default: /* Invalid attribute/option identifier */ addStmtError(stmt, "HY092", NULL, 0); return SQL_ERROR; } return SQL_SUCCESS; }
SQLRETURN MNDBFetchScroll(ODBCStmt *stmt, SQLSMALLINT FetchOrientation, SQLLEN FetchOffset, SQLUSMALLINT *RowStatusArray) { assert(stmt->hdl); if ((stmt->cursorType == SQL_CURSOR_FORWARD_ONLY || stmt->cursorScrollable == SQL_NONSCROLLABLE) && FetchOrientation != SQL_FETCH_NEXT) { /* Fetch type out of range */ addStmtError(stmt, "HY106", NULL, 0); return SQL_ERROR; } #define RowSetSize (stmt->ApplRowDescr->sql_desc_array_size) assert(stmt->startRow >= 0); switch (FetchOrientation) { case SQL_FETCH_NEXT: stmt->startRow += stmt->rowSetSize; break; case SQL_FETCH_FIRST: stmt->startRow = 0; break; case SQL_FETCH_LAST: if (stmt->rowcount < RowSetSize) stmt->startRow = 0; else stmt->startRow = stmt->rowcount - RowSetSize; break; case SQL_FETCH_PRIOR: if (stmt->startRow == 0) { /* before start */ stmt->startRow = 0; stmt->rowSetSize = 0; stmt->State = FETCHED; return SQL_NO_DATA; } if (stmt->startRow < (SQLLEN) RowSetSize) { /* Attempt to fetch before the result set * returned the first rowset */ addStmtError(stmt, "01S06", NULL, 0); stmt->startRow = 0; } else stmt->startRow = stmt->startRow - RowSetSize; break; case SQL_FETCH_RELATIVE: if ((stmt->startRow > 0 || stmt->rowSetSize > 0 || FetchOffset <= 0) && ((SQLULEN) stmt->startRow < stmt->rowcount || FetchOffset >= 0)) { if ((stmt->startRow == 0 && stmt->rowSetSize == 0 && FetchOffset <= 0) || (stmt->startRow == 0 && stmt->rowSetSize > 0 && FetchOffset < 0) || (stmt->startRow > 0 && stmt->startRow + FetchOffset < 1 && (FetchOffset > (SQLLEN) RowSetSize || -FetchOffset > (SQLLEN) RowSetSize))) { /* before start */ stmt->startRow = 0; stmt->rowSetSize = 0; stmt->State = FETCHED; return SQL_NO_DATA; } if (stmt->startRow > 0 && stmt->startRow + FetchOffset < 1 && FetchOffset <= (SQLLEN) RowSetSize && -FetchOffset <= (SQLLEN) RowSetSize) { /* Attempt to fetch before the result * set returned the first rowset */ addStmtError(stmt, "01S06", NULL, 0); stmt->startRow = 0; break; } if (stmt->startRow + FetchOffset >= 0 && stmt->startRow + FetchOffset < (SQLLEN) stmt->rowcount) { stmt->startRow += FetchOffset; break; } if (stmt->startRow + FetchOffset >= (SQLLEN) stmt->rowcount || (stmt->startRow >= (SQLLEN) stmt->rowcount && FetchOffset >= 0)) { /* after end */ stmt->startRow = stmt->rowcount; stmt->rowSetSize = 0; stmt->State = FETCHED; return SQL_NO_DATA; } /* all bases should have been covered above */ assert(0); } /* fall through */ case SQL_FETCH_ABSOLUTE: if (FetchOffset < 0) { if ((unsigned int) -FetchOffset <= stmt->rowcount) { stmt->startRow = stmt->rowcount + FetchOffset; break; } stmt->startRow = 0; if ((unsigned int) -FetchOffset > RowSetSize) { /* before start */ stmt->State = FETCHED; stmt->rowSetSize = 0; return SQL_NO_DATA; } /* Attempt to fetch before the result set returned the first rowset */ addStmtError(stmt, "01S06", NULL, 0); break; } if (FetchOffset == 0) { /* before start */ stmt->startRow = 0; stmt->rowSetSize = 0; stmt->State = FETCHED; return SQL_NO_DATA; } if ((SQLULEN) FetchOffset > stmt->rowcount) { /* after end */ stmt->startRow = stmt->rowcount; stmt->rowSetSize = 0; stmt->State = FETCHED; return SQL_NO_DATA; } stmt->startRow = FetchOffset - 1; break; case SQL_FETCH_BOOKMARK: /* Optional feature not implemented */ addStmtError(stmt, "HYC00", NULL, 0); return SQL_ERROR; default: /* Fetch type out of range */ addStmtError(stmt, "HY106", NULL, 0); return SQL_ERROR; } return MNDBFetch(stmt, RowStatusArray); }
SQLRETURN SQL_API SQLGetData(SQLHSTMT StatementHandle, SQLUSMALLINT Col_or_Param_Num, SQLSMALLINT TargetType, SQLPOINTER TargetValuePtr, SQLLEN BufferLength, SQLLEN *StrLen_or_IndPtr) { ODBCStmt *stmt = (ODBCStmt *) StatementHandle; #ifdef ODBCDEBUG ODBCLOG("SQLGetData %p %u %s %p " LENFMT " %p\n", StatementHandle, (unsigned int) Col_or_Param_Num, translateCType(TargetType), TargetValuePtr, LENCAST BufferLength, StrLen_or_IndPtr); #endif if (!isValidStmt(stmt)) return SQL_INVALID_HANDLE; assert(stmt->Dbc); assert(stmt->Dbc->mid); assert(stmt->hdl); clearStmtErrors(stmt); /* check statement cursor state, query should be executed */ if (stmt->State < EXECUTED0) { /* Function sequence error */ addStmtError(stmt, "HY010", NULL, 0); return SQL_ERROR; } if (stmt->State <= EXECUTED1) { /* Invalid cursor state */ addStmtError(stmt, "24000", NULL, 0); return SQL_ERROR; } if (stmt->rowSetSize == 0) { /* SQLFetch failed */ /* General error */ addStmtError(stmt, "HY000", NULL, 0); return SQL_ERROR; } if (stmt->rowSetSize > 1 && stmt->cursorType == SQL_CURSOR_FORWARD_ONLY) { /* Invalid cursor position */ addStmtError(stmt, "HY109", NULL, 0); return SQL_ERROR; } if (Col_or_Param_Num <= 0 || Col_or_Param_Num > stmt->ImplRowDescr->sql_desc_count) { /* Invalid descriptor index */ addStmtError(stmt, "07009", NULL, 0); return SQL_ERROR; } if (TargetValuePtr == NULL) { /* Invalid use of null pointer */ addStmtError(stmt, "HY009", NULL, 0); return SQL_ERROR; } if (Col_or_Param_Num != stmt->currentCol) stmt->retrieved = 0; stmt->currentCol = Col_or_Param_Num; if (TargetType == SQL_ARD_TYPE) { ODBCDesc *desc = stmt->ApplRowDescr; if (Col_or_Param_Num > desc->sql_desc_count) { /* Invalid descriptor index */ addStmtError(stmt, "07009", NULL, 0); return SQL_ERROR; } TargetType = desc->descRec[Col_or_Param_Num].sql_desc_concise_type; } return ODBCFetch(stmt, Col_or_Param_Num, TargetType, TargetValuePtr, BufferLength, StrLen_or_IndPtr, StrLen_or_IndPtr, UNAFFECTED, UNAFFECTED, UNAFFECTED, 0, 0); }
static SQLRETURN MNDBProcedures(ODBCStmt *stmt, SQLCHAR *CatalogName, SQLSMALLINT NameLength1, SQLCHAR *SchemaName, SQLSMALLINT NameLength2, SQLCHAR *ProcName, SQLSMALLINT NameLength3) { RETCODE rc; /* buffer for the constructed query to do meta data retrieval */ char *query = NULL; char *query_end; char *cat = NULL, *sch = NULL, *pro = NULL; /* convert input string parameters to normal null terminated C strings */ fixODBCstring(CatalogName, NameLength1, SQLSMALLINT, addStmtError, stmt, return SQL_ERROR); fixODBCstring(SchemaName, NameLength2, SQLSMALLINT, addStmtError, stmt, return SQL_ERROR); fixODBCstring(ProcName, NameLength3, SQLSMALLINT, addStmtError, stmt, return SQL_ERROR); #ifdef ODBCDEBUG ODBCLOG("\"%.*s\" \"%.*s\" \"%.*s\"\n", (int) NameLength1, (char *) CatalogName, (int) NameLength2, (char *) SchemaName, (int) NameLength3, (char *) ProcName); #endif /* SQLProcedures returns a table with the following columns: VARCHAR procedure_cat VARCHAR procedure_schem VARCHAR procedure_name NOT NULL n/a num_input_params (reserved for future use) n/a num_output_params (reserved for future use) n/a num_result_sets (reserved for future use) VARCHAR remarks SMALLINT procedure_type */ if (stmt->Dbc->sql_attr_metadata_id == SQL_FALSE) { if (NameLength1 > 0) { cat = ODBCParseOA("e", "value", (const char *) CatalogName, (size_t) NameLength1); if (cat == NULL) goto nomem; } if (NameLength2 > 0) { sch = ODBCParsePV("s", "name", (const char *) SchemaName, (size_t) NameLength2); if (sch == NULL) goto nomem; } if (NameLength3 > 0) { pro = ODBCParsePV("p", "name", (const char *) ProcName, (size_t) NameLength3); if (pro == NULL) goto nomem; } } else { if (NameLength1 > 0) { cat = ODBCParseID("e", "value", (const char *) CatalogName, (size_t) NameLength1); if (cat == NULL) goto nomem; } if (NameLength2 > 0) { sch = ODBCParseID("s", "name", (const char *) SchemaName, (size_t) NameLength2); if (sch == NULL) goto nomem; } if (NameLength3 > 0) { pro = ODBCParseID("p", "name", (const char *) ProcName, (size_t) NameLength3); if (pro == NULL) goto nomem; } } query = malloc(1000 + (cat ? strlen(cat) : 0) + (sch ? strlen(sch) : 0) + (pro ? strlen(pro) : 0)); if (query == NULL) goto nomem; query_end = query; /* see sql_catalog.h */ #define F_FUNC 1 #define F_PROC 2 #define F_UNION 5 snprintf(query_end, 1000, "select e.value as procedure_cat, " "s.name as procedure_schem, " "p.name as procedure_name, " "0 as num_input_params, " "0 as num_output_params, " "0 as num_result_sets, " "cast('' as varchar(1)) as remarks, " "cast(case when p.type = %d then %d else %d end as smallint) as procedure_type " "from sys.schemas as s, " "sys.env() as e, " "sys.functions as p " "where p.schema_id = s.id and " "p.sql = true and " "p.type in (%d, %d, %d) and " "e.name = 'gdk_dbname'", F_PROC, SQL_PT_PROCEDURE, SQL_PT_FUNCTION, F_FUNC, F_PROC, F_UNION); assert(strlen(query) < 800); query_end += strlen(query_end); /* Construct the selection condition query part */ if (cat) { /* filtering requested on catalog name */ sprintf(query_end, " and %s", cat); query_end += strlen(query_end); free(cat); } if (sch) { /* filtering requested on schema name */ sprintf(query_end, " and %s", sch); query_end += strlen(query_end); free(sch); } if (pro) { /* filtering requested on procedure name */ sprintf(query_end, " and %s", pro); query_end += strlen(query_end); free(pro); } /* add the ordering */ strcpy(query_end, " order by procedure_cat, procedure_schem, procedure_name"); query_end += strlen(query_end); /* query the MonetDB data dictionary tables */ rc = MNDBExecDirect(stmt, (SQLCHAR *) query, SQL_NTS); free(query); return rc; nomem: /* note that query must be NULL when we get here */ if (cat) free(cat); if (sch) free(sch); if (pro) free(pro); /* Memory allocation error */ addStmtError(stmt, "HY001", NULL, 0); return SQL_ERROR; }
SQLRETURN SQL_API SQLColAttributeW(SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber, SQLUSMALLINT FieldIdentifier, SQLPOINTER CharacterAttributePtr, SQLSMALLINT BufferLength, SQLSMALLINT *StringLengthPtr, LENP_OR_POINTER_T NumericAttributePtr) { ODBCStmt *stmt = (ODBCStmt *) StatementHandle; SQLPOINTER ptr; SQLRETURN rc; SQLSMALLINT n; #ifdef ODBCDEBUG ODBCLOG("SQLColAttributeW " PTRFMT " %s\n", PTRFMTCAST StatementHandle, translateFieldIdentifier(FieldIdentifier)); #endif if (!isValidStmt(stmt)) return SQL_INVALID_HANDLE; clearStmtErrors(stmt); switch (FieldIdentifier) { /* all string atributes */ case SQL_DESC_BASE_COLUMN_NAME: case SQL_DESC_BASE_TABLE_NAME: case SQL_DESC_CATALOG_NAME: /* SQL_COLUMN_QUALIFIER_NAME */ case SQL_DESC_LABEL: /* SQL_COLUMN_LABEL */ case SQL_DESC_LITERAL_PREFIX: case SQL_DESC_LITERAL_SUFFIX: case SQL_DESC_LOCAL_TYPE_NAME: case SQL_DESC_NAME: case SQL_DESC_SCHEMA_NAME: /* SQL_COLUMN_OWNER_NAME */ case SQL_DESC_TABLE_NAME: /* SQL_COLUMN_TABLE_NAME */ case SQL_DESC_TYPE_NAME: /* SQL_COLUMN_TYPE_NAME */ rc = SQLColAttribute_(stmt, ColumnNumber, FieldIdentifier, NULL, 0, &n, NumericAttributePtr); if (!SQL_SUCCEEDED(rc)) return rc; clearStmtErrors(stmt); n++; /* account for NUL byte */ ptr = (SQLPOINTER) malloc(n); if (ptr == NULL) { /* Memory allocation error */ addStmtError(stmt, "HY001", NULL, 0); return SQL_ERROR; } break; default: n = BufferLength; ptr = CharacterAttributePtr; break; } rc = SQLColAttribute_(stmt, ColumnNumber, FieldIdentifier, ptr, n, &n, NumericAttributePtr); if (ptr != CharacterAttributePtr) { if (SQL_SUCCEEDED(rc)) { fixWcharOut(rc, ptr, n, CharacterAttributePtr, BufferLength, StringLengthPtr, 2, addStmtError, stmt); } free(ptr); } else if (StringLengthPtr) *StringLengthPtr = n; return rc; }