const wxString &password, const wxString &defaultDir,
const wxString &fileType, const wxString &description)
{
- wxASSERT(dsn.Length());
-
Henv = 0;
freeHenvOnDestroy = FALSE;
i_dbDataType = DB_DATA_TYPE_VARCHAR;
if (i_sqlDataType == SQL_REAL)
i_dbDataType = DB_DATA_TYPE_FLOAT;
+ if (i_sqlDataType == SQL_C_BINARY)
+ i_dbDataType = DB_DATA_TYPE_BLOB;
}
if ((i_dbDataType == DB_DATA_TYPE_INTEGER) && (i_sqlDataType == SQL_C_DOUBLE))
s_Field = wxT("%02d/%02d/%04d %02d:%02d:%02d.%03d");
}
break;
+ case DB_DATA_TYPE_BLOB:
+ s_Field.Printf(wxT("Unable to format(%d)-SQL(%d)"),dbDataType,sqlDataType); //
+ break;
default:
s_Field.Printf(wxT("Unknown Format(%d)-SQL(%d)"),dbDataType,sqlDataType); //
break;
typeInfDate.CaseSensitive = 0;
typeInfDate.MaximumScale = 0;
+ typeInfBlob.TypeName.Empty();
+ typeInfBlob.FsqlType = 0;
+ typeInfBlob.Precision = 0;
+ typeInfBlob.CaseSensitive = 0;
+ typeInfBlob.MaximumScale = 0;
+
// Error reporting is turned OFF by default
silent = TRUE;
// Query the data source regarding data type information
//
- // The way I determined which SQL data types to use was by calling SQLGetInfo
+ // The way it was determined which SQL data types to use was by calling SQLGetInfo
// for all of the possible SQL data types to see which ones were supported. If
// a type is not supported, the SQLFetch() that's called from getDataTypeInfo()
// fails with SQL_NO_DATA_FOUND. This is ugly because I'm sure the three SQL data
// Float
if (!getDataTypeInfo(SQL_DOUBLE,typeInfFloat))
-
if (!getDataTypeInfo(SQL_REAL,typeInfFloat))
if (!getDataTypeInfo(SQL_FLOAT,typeInfFloat))
if (!getDataTypeInfo(SQL_DECIMAL,typeInfFloat))
typeInfDate.FsqlType = SQL_DATE;
}
+ if (!getDataTypeInfo(SQL_LONGVARBINARY, typeInfBlob))
+ {
+ if (!getDataTypeInfo(SQL_VARBINARY,typeInfBlob))
+ return(FALSE);
+ else
+ typeInfBlob.FsqlType = SQL_VARBINARY;
+ }
+ else
+ typeInfBlob.FsqlType = SQL_LONGVARBINARY;
+
+//typeInfBlob.TypeName = "BLOB";
+
#ifdef DBDEBUG_CONSOLE
cout << wxT("VARCHAR DATA TYPE: ") << typeInfVarchar.TypeName << endl;
cout << wxT("INTEGER DATA TYPE: ") << typeInfInteger.TypeName << endl;
cout << wxT("FLOAT DATA TYPE: ") << typeInfFloat.TypeName << endl;
cout << wxT("DATE DATA TYPE: ") << typeInfDate.TypeName << endl;
+ cout << wxT("BLOB DATA TYPE: ") << typeInfBlob.TypeName << endl;
cout << endl;
#endif
typeInfDate.CaseSensitive = copyDb->typeInfDate.CaseSensitive;
typeInfDate.MaximumScale = copyDb->typeInfDate.MaximumScale;
+ // Blob
+ typeInfBlob.FsqlType = copyDb->typeInfBlob.FsqlType;
+ typeInfBlob.TypeName = copyDb->typeInfBlob.TypeName;
+ typeInfBlob.Precision = copyDb->typeInfBlob.Precision;
+ typeInfBlob.CaseSensitive = copyDb->typeInfBlob.CaseSensitive;
+ typeInfBlob.MaximumScale = copyDb->typeInfBlob.MaximumScale;
+
#ifdef DBDEBUG_CONSOLE
cout << wxT("VARCHAR DATA TYPE: ") << typeInfVarchar.TypeName << endl;
cout << wxT("INTEGER DATA TYPE: ") << typeInfInteger.TypeName << endl;
cout << wxT("FLOAT DATA TYPE: ") << typeInfFloat.TypeName << endl;
cout << wxT("DATE DATA TYPE: ") << typeInfDate.TypeName << endl;
+ cout << wxT("BLOB DATA TYPE: ") << typeInfBlob.TypeName << endl;
cout << endl;
#endif
/********** wxDb::ExecSql() **********/
bool wxDb::ExecSql(const wxString &pSqlStmt)
{
+ RETCODE retcode;
+
SQLFreeStmt(hstmt, SQL_CLOSE);
- if (SQLExecDirect(hstmt, (UCHAR FAR *) pSqlStmt.c_str(), SQL_NTS) == SQL_SUCCESS)
+
+ retcode = SQLExecDirect(hstmt, (UCHAR FAR *) pSqlStmt.c_str(), SQL_NTS);
+ if (retcode == SQL_SUCCESS ||
+ (Dbms() == dbmsDB2 && (retcode == SQL_SUCCESS_WITH_INFO || retcode == SQL_NO_DATA_FOUND)))
+ {
return(TRUE);
+ }
else
{
DispAllErrors(henv, hdbc, hstmt);
/********** wxDb::GetKeyFields() **********/
-int wxDb::GetKeyFields(const wxString &tableName, wxDbColInf* colInf, int noCols)
+int wxDb::GetKeyFields(const wxString &tableName, wxDbColInf* colInf, UWORD noCols)
{
wxChar szPkTable[DB_MAX_TABLE_NAME_LEN+1]; /* Primary key table name */
wxChar szFkTable[DB_MAX_TABLE_NAME_LEN+1]; /* Foreign key table name */
wxChar szFkCol[DB_MAX_COLUMN_NAME_LEN+1]; /* Foreign key column */
SQLRETURN retcode;
SDWORD cb;
- int i;
+ SWORD i;
wxString tempStr;
/*
* -----------------------------------------------------------------------
* to avoid undesired unbinding of columns.
*/
{
- int noCols = 0;
- int colNo = 0;
+ UWORD noCols = 0;
+ UWORD colNo = 0;
wxDbColInf *colInf = 0;
RETCODE retcode;
#endif
colInf[colNo].dbDataType = DB_DATA_TYPE_VARCHAR;
}
- else if (!wxStricmp(typeInfInteger.TypeName,colInf[colNo].typeName))
+ else if (!wxStricmp(typeInfInteger.TypeName, colInf[colNo].typeName))
colInf[colNo].dbDataType = DB_DATA_TYPE_INTEGER;
- else if (!wxStricmp(typeInfFloat.TypeName,colInf[colNo].typeName))
+ else if (!wxStricmp(typeInfFloat.TypeName, colInf[colNo].typeName))
colInf[colNo].dbDataType = DB_DATA_TYPE_FLOAT;
- else if (!wxStricmp(typeInfDate.TypeName,colInf[colNo].typeName))
+ else if (!wxStricmp(typeInfDate.TypeName, colInf[colNo].typeName))
colInf[colNo].dbDataType = DB_DATA_TYPE_DATE;
-
+ else if (!wxStricmp(typeInfBlob.TypeName, colInf[colNo].typeName))
+ colInf[colNo].dbDataType = DB_DATA_TYPE_BLOB;
colNo++;
}
}
/********** wxDb::GetColumns() **********/
-wxDbColInf *wxDb::GetColumns(const wxString &tableName, int *numCols, const wxChar *userID)
+wxDbColInf *wxDb::GetColumns(const wxString &tableName, UWORD *numCols, const wxChar *userID)
//
// Same as the above GetColumns() function except this one gets columns
// only for a single table, and if 'numCols' is not NULL, the number of
// to avoid undesired unbinding of columns.
{
- int noCols = 0;
- int colNo = 0;
+ UWORD noCols = 0;
+ UWORD colNo = 0;
wxDbColInf *colInf = 0;
RETCODE retcode;
// Determine the wxDb data type that is used to represent the native data type of this data source
colInf[colNo].dbDataType = 0;
- if (!wxStricmp(typeInfVarchar.TypeName,colInf[colNo].typeName))
+ if (!wxStricmp(typeInfVarchar.TypeName, colInf[colNo].typeName))
{
#ifdef _IODBC_
// IODBC does not return a correct columnSize, so we set
colInf[colNo].dbDataType = DB_DATA_TYPE_VARCHAR;
}
- else if (!wxStricmp(typeInfInteger.TypeName,colInf[colNo].typeName))
+ else if (!wxStricmp(typeInfInteger.TypeName, colInf[colNo].typeName))
colInf[colNo].dbDataType = DB_DATA_TYPE_INTEGER;
- else if (!wxStricmp(typeInfFloat.TypeName,colInf[colNo].typeName))
+ else if (!wxStricmp(typeInfFloat.TypeName, colInf[colNo].typeName))
colInf[colNo].dbDataType = DB_DATA_TYPE_FLOAT;
- else if (!wxStricmp(typeInfDate.TypeName,colInf[colNo].typeName))
+ else if (!wxStricmp(typeInfDate.TypeName, colInf[colNo].typeName))
colInf[colNo].dbDataType = DB_DATA_TYPE_DATE;
+ else if (!wxStricmp(typeInfBlob.TypeName, colInf[colNo].typeName))
+ colInf[colNo].dbDataType = DB_DATA_TYPE_BLOB;
colNo++;
}
typedef struct
{
- int noCols;
+ UWORD noCols;
wxDbColInf *colInf;
} _TableColumns;
// The last array element of the tableName[] argument must be zero (null).
// This is how the end of the array is detected.
- int noCols = 0;
+ UWORD noCols = 0;
// How many tables ?
int tbl;
// by this function. This function should use its own wxDb instance
// to avoid undesired unbinding of columns.
{
- SWORD noCols = 0;
- int colNo = 0;
+ UWORD noCols = 0;
+ UWORD colNo = 0;
wxDbColInf *colInf = 0;
RETCODE retcode;
case SQL_DATE:
colInf[colNo].dbDataType = DB_DATA_TYPE_DATE;
break;
+ case SQL_BINARY:
+ colInf[colNo].dbDataType = DB_DATA_TYPE_BLOB;
+ break;
#ifdef __WXDEBUG__
default:
wxString errMsg;
/********** wxDb::GetColumnCount() **********/
-int wxDb::GetColumnCount(const wxString &tableName, const wxChar *userID)
+UWORD wxDb::GetColumnCount(const wxString &tableName, const wxChar *userID)
/*
* Returns a count of how many columns are in a table.
* If an error occurs in computing the number of columns
* to avoid undesired unbinding of columns.
*/
{
- int noCols = 0;
+ UWORD noCols = 0;
RETCODE retcode;
if (!UserID.IsEmpty() &&
Dbms() != dbmsMY_SQL &&
Dbms() != dbmsACCESS &&
- Dbms() != dbmsMS_SQL_SERVER)
+ Dbms() != dbmsMS_SQL_SERVER &&
+ Dbms() != dbmsDB2 &&
+ Dbms() != dbmsPERVASIVE_SQL)
{
retcode = SQLTables(hstmt,
NULL, 0, // All qualifiers
wxString TableName;
- wxString UserID;
+ wxString UserID,Schema;
convertUserID(userID,UserID);
+ convertUserID(schema,Schema);
TableName = tableName;
// Oracle and Interbase table names are uppercase only, so force
SQLFreeStmt(hstmt, SQL_CLOSE);
- if (!schema)
+ // Some databases cannot accept a user name when looking up table names,
+ // so we use the call below that leaves out the user name
+ if (!Schema.IsEmpty() &&
+ Dbms() != dbmsMY_SQL &&
+ Dbms() != dbmsACCESS &&
+ Dbms() != dbmsMS_SQL_SERVER)
{
retcode = SQLTablePrivileges(hstmt,
NULL, 0, // Catalog
- NULL, 0, // Schema
+ (UCHAR FAR *)Schema.c_str(), SQL_NTS, // Schema
(UCHAR FAR *)TableName.c_str(), SQL_NTS);
}
else
{
retcode = SQLTablePrivileges(hstmt,
NULL, 0, // Catalog
- (UCHAR FAR *)schema, SQL_NTS, // Schema
+ NULL, 0, // Schema
(UCHAR FAR *)TableName.c_str(), SQL_NTS);
}
if ((retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO))
return(DispAllErrors(henv, hdbc, hstmt));
+ bool failed = FALSE;
retcode = SQLFetch(hstmt);
while (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
{
if (SQLGetData(hstmt, 1, SQL_C_CHAR, (UCHAR*) result.tableQual, sizeof(result.tableQual), &cbRetVal) != SQL_SUCCESS)
- return(DispAllErrors(henv, hdbc, hstmt));
+ failed = true;
- if (SQLGetData(hstmt, 2, SQL_C_CHAR, (UCHAR*) result.tableOwner, sizeof(result.tableOwner), &cbRetVal) != SQL_SUCCESS)
- return(DispAllErrors(henv, hdbc, hstmt));
+ if (!failed && SQLGetData(hstmt, 2, SQL_C_CHAR, (UCHAR*) result.tableOwner, sizeof(result.tableOwner), &cbRetVal) != SQL_SUCCESS)
+ failed = true;
- if (SQLGetData(hstmt, 3, SQL_C_CHAR, (UCHAR*) result.tableName, sizeof(result.tableName), &cbRetVal) != SQL_SUCCESS)
- return(DispAllErrors(henv, hdbc, hstmt));
+ if (!failed && SQLGetData(hstmt, 3, SQL_C_CHAR, (UCHAR*) result.tableName, sizeof(result.tableName), &cbRetVal) != SQL_SUCCESS)
+ failed = true;
- if (SQLGetData(hstmt, 4, SQL_C_CHAR, (UCHAR*) result.grantor, sizeof(result.grantor), &cbRetVal) != SQL_SUCCESS)
- return(DispAllErrors(henv, hdbc, hstmt));
+ if (!failed && SQLGetData(hstmt, 4, SQL_C_CHAR, (UCHAR*) result.grantor, sizeof(result.grantor), &cbRetVal) != SQL_SUCCESS)
+ failed = true;
- if (SQLGetData(hstmt, 5, SQL_C_CHAR, (UCHAR*) result.grantee, sizeof(result.grantee), &cbRetVal) != SQL_SUCCESS)
- return(DispAllErrors(henv, hdbc, hstmt));
+ if (!failed && SQLGetData(hstmt, 5, SQL_C_CHAR, (UCHAR*) result.grantee, sizeof(result.grantee), &cbRetVal) != SQL_SUCCESS)
+ failed = true;
- if (SQLGetData(hstmt, 6, SQL_C_CHAR, (UCHAR*) result.privilege, sizeof(result.privilege), &cbRetVal) != SQL_SUCCESS)
- return(DispAllErrors(henv, hdbc, hstmt));
+ if (!failed && SQLGetData(hstmt, 6, SQL_C_CHAR, (UCHAR*) result.privilege, sizeof(result.privilege), &cbRetVal) != SQL_SUCCESS)
+ failed = true;
- if (SQLGetData(hstmt, 7, SQL_C_CHAR, (UCHAR*) result.grantable, sizeof(result.grantable), &cbRetVal) != SQL_SUCCESS)
- return(DispAllErrors(henv, hdbc, hstmt));
+ if (!failed && SQLGetData(hstmt, 7, SQL_C_CHAR, (UCHAR*) result.grantable, sizeof(result.grantable), &cbRetVal) != SQL_SUCCESS)
+ failed = true;
+ if (failed)
+ {
+ return(DispAllErrors(henv, hdbc, hstmt));
+ }
#ifdef DBDEBUG_CONSOLE
fprintf(stderr,wxT("Scanning %s privilege on table %s.%s granted by %s to %s\n"),
result.privilege,result.tableOwner,result.tableName,
*
* DB2
* - Primary keys must be declared as NOT NULL
+ * - Table and index names must not be longer than 13 characters in length (technically
+ * table names can be up to 18 characters, but the primary index is created using the
+ * base table name plus "_PIDX", so the limit if the table has a primary index is 13.
+ *
+ * PERVASIVE SQL
*
*/
{
if (!wxStricmp(dbInf.dbmsName,wxT("PostgreSQL"))) // v6.5.0
return((wxDBMS)(dbmsType = dbmsPOSTGRES));
+ baseName[9] = 0;
+ if (!wxStricmp(dbInf.dbmsName,wxT("Pervasive")))
+ return((wxDBMS)(dbmsType = dbmsPERVASIVE_SQL));
+
baseName[8] = 0;
if (!wxStricmp(baseName,wxT("Informix")))
return((wxDBMS)(dbmsType = dbmsINFORMIX));
case DB_DATA_TYPE_DATE :
dataTypeName = typeInfDate.TypeName;
break;
+ case DB_DATA_TYPE_BLOB :
+ dataTypeName = typeInfBlob.TypeName;
+ break;
default:
return FALSE;
}