Example #1
0
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);
}
Example #2
0
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);
}
Example #3
0
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;
}
Example #4
0
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;
}
Example #5
0
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;
}
Example #7
0
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;
}
Example #8
0
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;
}
Example #9
0
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;
}
Example #10
0
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;
}
Example #11
0
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 */
}
Example #12
0
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;
}
Example #13
0
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;
}
Example #14
0
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;
}
Example #15
0
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;
}
Example #16
0
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;
}
Example #17
0
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;
}
Example #18
0
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;
}
Example #19
0
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;
}
Example #20
0
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;
}
Example #21
0
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;
}
Example #22
0
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;
}
Example #23
0
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;
}
Example #24
0
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;
}
Example #25
0
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);
}
Example #26
0
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;
}
Example #27
0
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);
}
Example #28
0
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);
}
Example #29
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;
}
Example #30
0
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;
}