selectForUpdate = FALSE; // SELECT ... FOR UPDATE; Indicates whether to include the FOR UPDATE phrase
queryOnly = qryOnly;
insertable = TRUE;
+ wxStrcpy(tablePath,"");
+ wxStrcpy(tableName,"");
+ wxStrcpy(queryTableName,"");
assert (tblName);
wxStrcpy(tableName, tblName); // Table Name
if (tblPath)
wxStrcpy(tablePath, tblPath); // Table Path - used for dBase files
+ else
+ tablePath[0] = 0;
if (qryTblName) // Name of the table/view to query
wxStrcpy(queryTableName, qryTblName);
fSqlType = pDb->GetTypeInfVarchar().FsqlType;
precision = colDefs[i].SzDataObj;
scale = 0;
- colDefs[i].CbValue = SQL_NTS;
+ if (colDefs[i].Null)
+ colDefs[i].CbValue = SQL_NULL_DATA;
+ else
+ colDefs[i].CbValue = SQL_NTS;
break;
case DB_DATA_TYPE_INTEGER:
fSqlType = pDb->GetTypeInfInteger().FsqlType;
precision = pDb->GetTypeInfInteger().Precision;
scale = 0;
- colDefs[i].CbValue = 0;
+ if (colDefs[i].Null)
+ colDefs[i].CbValue = SQL_NULL_DATA;
+ else
+ colDefs[i].CbValue = 0;
break;
case DB_DATA_TYPE_FLOAT:
fSqlType = pDb->GetTypeInfFloat().FsqlType;
// I check for this here and set the scale = precision.
//if (scale < 0)
// scale = (short) precision;
- colDefs[i].CbValue = 0;
+ if (colDefs[i].Null)
+ colDefs[i].CbValue = SQL_NULL_DATA;
+ else
+ colDefs[i].CbValue = 0;
break;
case DB_DATA_TYPE_DATE:
fSqlType = pDb->GetTypeInfDate().FsqlType;
precision = pDb->GetTypeInfDate().Precision;
scale = 0;
- colDefs[i].CbValue = 0;
+ if (colDefs[i].Null)
+ colDefs[i].CbValue = SQL_NULL_DATA;
+ else
+ colDefs[i].CbValue = 0;
break;
}
// Null values
- if (colDefs[i].Null)
- {
- colDefs[i].CbValue = SQL_NULL_DATA;
- colDefs[i].Null = FALSE;
- }
+//RG-NULL
+//RG-NULL if (colDefs[i].Null)
+//RG-NULL {
+//RG-NULL colDefs[i].CbValue = SQL_NULL_DATA;
+//RG-NULL colDefs[i].Null = FALSE;
+//RG-NULL }
if (SQLBindParameter(hstmtInsert, colNo++, SQL_PARAM_INPUT, colDefs[i].SqlCtype,
fSqlType, precision, scale, (UCHAR*) colDefs[i].PtrDataObj,
fSqlType = pDb->GetTypeInfVarchar().FsqlType;
precision = colDefs[i].SzDataObj;
scale = 0;
- colDefs[i].CbValue = SQL_NTS;
+ if (colDefs[i].Null)
+ colDefs[i].CbValue = SQL_NULL_DATA;
+ else
+ colDefs[i].CbValue = SQL_NTS;
break;
case DB_DATA_TYPE_INTEGER:
fSqlType = pDb->GetTypeInfInteger().FsqlType;
precision = pDb->GetTypeInfInteger().Precision;
scale = 0;
- colDefs[i].CbValue = 0;
+ if (colDefs[i].Null)
+ colDefs[i].CbValue = SQL_NULL_DATA;
+ else
+ colDefs[i].CbValue = 0;
break;
case DB_DATA_TYPE_FLOAT:
fSqlType = pDb->GetTypeInfFloat().FsqlType;
// I check for this here and set the scale = precision.
//if (scale < 0)
// scale = (short) precision;
- colDefs[i].CbValue = 0;
+ if (colDefs[i].Null)
+ colDefs[i].CbValue = SQL_NULL_DATA;
+ else
+ colDefs[i].CbValue = 0;
break;
case DB_DATA_TYPE_DATE:
fSqlType = pDb->GetTypeInfDate().FsqlType;
precision = pDb->GetTypeInfDate().Precision;
scale = 0;
- colDefs[i].CbValue = 0;
+ if (colDefs[i].Null)
+ colDefs[i].CbValue = SQL_NULL_DATA;
+ else
+ colDefs[i].CbValue = 0;
break;
}
/********** wxDbTable::bindCols() **********/
bool wxDbTable::bindCols(HSTMT cursor)
{
- static SDWORD cb;
+//RG-NULL static SDWORD cb;
// Bind each column of the table to a memory address for fetching data
int i;
for (i = 0; i < noCols; i++)
{
if (SQLBindCol(cursor, i+1, colDefs[i].SqlCtype, (UCHAR*) colDefs[i].PtrDataObj,
- colDefs[i].SzDataObj, &cb) != SQL_SUCCESS)
+//RG-NULL colDefs[i].SzDataObj, &cb) != SQL_SUCCESS)
+ colDefs[i].SzDataObj, &colDefs[i].CbValue ) != SQL_SUCCESS)
{
return (pDb->DispAllErrors(henv, hdbc, cursor));
}
else
return(pDb->DispAllErrors(henv, hdbc, hstmt));
}
+ else
+ {
+ // Set the Null member variable to indicate the Null state
+ // of each column just read in.
+ int i;
+ for (i = 0; i < noCols; i++)
+ colDefs[i].Null = (colDefs[i].CbValue == SQL_NULL_DATA);
+ }
}
else
{
else
return(pDb->DispAllErrors(henv, hdbc, hstmt));
}
+ else
+ {
+ // Set the Null member variable to indicate the Null state
+ // of each column just read in.
+ int i;
+ for (i = 0; i < noCols; i++)
+ colDefs[i].Null = (colDefs[i].CbValue == SQL_NULL_DATA);
+ }
}
// Completed successfully
{
char sqlStmt[DB_MAX_STATEMENT_LEN];
- // Set the selectForUpdate member variable
if (forUpdate)
// The user may wish to select for update, but the DBMS may not be capable
selectForUpdate = CanSelectForUpdate();
BuildSelectStmt(sqlStmt, queryType, distinct);
pDb->WriteSqlLog(sqlStmt);
}
+/*
+ This is the block of code that got added during the 2.2.1 merge with
+ the 2.2 main branch that somehow got added here when it should not have. - gt
+
else
wxStrcpy(sqlStmt, pSqlStmt);
pDb->DispAllErrors(henv, hdbc, hstmt);
return(FALSE);
}
-
+*/
// Make sure the cursor is closed first
- if (! CloseCursor(hstmt))
+ if (!CloseCursor(hstmt))
return(FALSE);
// Execute the SQL SELECT statement
/********** wxDbTable::Open() **********/
-bool wxDbTable::Open(void)
+bool wxDbTable::Open(bool checkPrivileges)
{
if (!pDb)
return FALSE;
int i;
wxString sqlStmt;
+ wxString s;
+ s = "";
// Verify that the table exists in the database
- if (!pDb->TableExists(tableName,pDb->GetUsername(),tablePath))
+ if (!pDb->TableExists(tableName,/*pDb->GetUsername()*/NULL,tablePath))
{
- wxString s;
- if (wxStrcmp(tablePath,""))
- s.sprintf(wxT("Error opening '%s/%s'.\n"),tablePath,tableName);
+ s = "Table/view does not exist in the database";
+ if ( *(pDb->dbInf.accessibleTables) == 'Y')
+ s += ", or you have no permissions.\n";
else
- s.sprintf(wxT("Error opening '%s'.\n"), tableName);
- if (!pDb->TableExists(tableName,NULL,tablePath))
- s += wxT("Table/view does not exist in the database.\n");
+ s += ".\n";
+ }
+ else if (checkPrivileges)
+ {
+ // Verify the user has rights to access the table.
+ // Shortcut boolean evaluation to optimize out call to
+ // TablePrivileges
+ //
+ // Unfortunately this optimization doesn't seem to be
+ // reliable!
+ if (// *(pDb->dbInf.accessibleTables) == 'N' &&
+ !pDb->TablePrivileges(tableName,"SELECT",NULL,pDb->GetUsername(),tablePath))
+ s = "Current logged in user does not have sufficient privileges to access this table.\n";
+ }
+
+ if (!s.IsEmpty())
+ {
+ wxString p;
+
+ if (wxStrcmp(tablePath,""))
+ p.sprintf("Error opening '%s/%s'.\n",tablePath,tableName);
else
- s += wxT("Current logged in user does not have sufficient privileges to access this table.\n");
- pDb->LogError(s.c_str());
+ p.sprintf("Error opening '%s'.\n", tableName);
+
+ p += s;
+ pDb->LogError(p.GetData());
+
return(FALSE);
}
if (!bindCols(hstmtInternal)) // Internal use only
return(FALSE);
-
- /*
+
+ /*
* Do NOT bind the hstmtCount cursor!!!
*/
sqlStmt += s.c_str();
}
- if (pDb->Dbms() == dbmsSYBASE_ASE || pDb->Dbms() == dbmsMY_SQL)
+ if (pDb->Dbms() == dbmsDB2 ||
+ pDb->Dbms() == dbmsMY_SQL ||
+ pDb->Dbms() == dbmsSYBASE_ASE ||
+ pDb->Dbms() == dbmsMS_SQL_SERVER)
{
if (colDefs[i].KeyField)
{
if (pDb->Dbms() == dbmsACCESS || pDb->Dbms() == dbmsMY_SQL)
sqlStmt.sprintf("DROP INDEX %s ON %s",idxName,tableName);
- else if (pDb->Dbms() == dbmsSYBASE_ASE)
+ else if ((pDb->Dbms() == dbmsMS_SQL_SERVER) ||
+ (pDb->Dbms() == dbmsSYBASE_ASE))
sqlStmt.sprintf("DROP INDEX %s.%s",tableName,idxName);
else
sqlStmt.sprintf("DROP INDEX %s",idxName);
} // wxDbTable::DropIndex()
+/********** wxDbTable::SetOrderByColNums() **********/
+bool wxDbTable::SetOrderByColNums(int first, ... )
+{
+ int colNo = first;
+ va_list argptr;
+
+ bool abort = FALSE;
+ wxString tempStr;
+
+ va_start(argptr, first); /* Initialize variable arguments. */
+ while (!abort && (colNo != wxDB_NO_MORE_COLUMN_NUMBERS))
+ {
+ // Make sure the passed in column number
+ // is within the valid range of columns
+ //
+ // Valid columns are 0 thru noCols-1
+ if (colNo >= noCols || colNo < 0)
+ {
+ abort = TRUE;
+ continue;
+ }
+
+ if (colNo != first)
+ tempStr += ",";
+
+ tempStr += colDefs[colNo].ColName;
+ colNo = va_arg (argptr, int);
+ }
+ va_end (argptr); /* Reset variable arguments. */
+
+ SetOrderByClause(tempStr.c_str());
+
+ return (!abort);
+} // wxDbTable::SetOrderByColNums()
+
+
/********** wxDbTable::Insert() **********/
int wxDbTable::Insert(void)
{
{
// Determine if this column should be included in the WHERE clause
if ((typeOfWhere == DB_WHERE_KEYFIELDS && colDefs[i].KeyField) ||
- (typeOfWhere == DB_WHERE_MATCHING && (! IsColNull(i))))
+ (typeOfWhere == DB_WHERE_MATCHING && (!IsColNull(i))))
{
// Skip over timestamp columns
if (colDefs[i].SqlCtype == SQL_C_TIMESTAMP)
/********** wxDbTable::IsColNull() **********/
bool wxDbTable::IsColNull(int colNo)
{
+/*
+ This logic is just not right. It would indicate TRUE
+ if a numeric field were set to a value of 0.
+
switch(colDefs[colNo].SqlCtype)
{
case SQL_C_CHAR:
default:
return(TRUE);
}
+*/
+ return (colDefs[colNo].Null);
} // wxDbTable::IsColNull()
/********** wxDbTable::CanSelectForUpdate() **********/
bool wxDbTable::CanSelectForUpdate(void)
{
+ if (queryOnly)
+ return FALSE;
+
if (pDb->Dbms() == dbmsMY_SQL)
return FALSE;
- if (pDb->dbInf.posStmts & SQL_PS_SELECT_FOR_UPDATE)
+ if ((pDb->Dbms() == dbmsORACLE) ||
+ (pDb->dbInf.posStmts & SQL_PS_SELECT_FOR_UPDATE))
return(TRUE);
else
return(FALSE);
} // wxDbTable::IsCursorClosedOnCommit()
-/********** wxDbTable::ClearMemberVars() **********/
-void wxDbTable::ClearMemberVars(void)
+
+/********** wxDbTable::ClearMemberVar() **********/
+void wxDbTable::ClearMemberVar(int colNo, bool setToNull)
{
- // Loop through the columns setting each member variable to zero
- int i;
- for (i = 0; i < noCols; i++)
+ assert(colNo < noCols);
+
+ switch(colDefs[colNo].SqlCtype)
{
- switch(colDefs[i].SqlCtype)
- {
- case SQL_C_CHAR:
- ((UCHAR FAR *) colDefs[i].PtrDataObj)[0] = 0;
- break;
- case SQL_C_SSHORT:
- *((SWORD *) colDefs[i].PtrDataObj) = 0;
- break;
- case SQL_C_USHORT:
- *((UWORD*) colDefs[i].PtrDataObj) = 0;
- break;
- case SQL_C_SLONG:
- *((SDWORD *) colDefs[i].PtrDataObj) = 0;
- break;
- case SQL_C_ULONG:
- *((UDWORD *) colDefs[i].PtrDataObj) = 0;
- break;
- case SQL_C_FLOAT:
- *((SFLOAT *) colDefs[i].PtrDataObj) = 0.0f;
- break;
- case SQL_C_DOUBLE:
- *((SDOUBLE *) colDefs[i].PtrDataObj) = 0.0f;
- break;
- case SQL_C_TIMESTAMP:
- TIMESTAMP_STRUCT *pDt;
- pDt = (TIMESTAMP_STRUCT *) colDefs[i].PtrDataObj;
- pDt->year = 0;
- pDt->month = 0;
- pDt->day = 0;
- pDt->hour = 0;
- pDt->minute = 0;
- pDt->second = 0;
- pDt->fraction = 0;
- break;
- }
+ case SQL_C_CHAR:
+ ((UCHAR FAR *) colDefs[colNo].PtrDataObj)[0] = 0;
+ break;
+ case SQL_C_SSHORT:
+ *((SWORD *) colDefs[colNo].PtrDataObj) = 0;
+ break;
+ case SQL_C_USHORT:
+ *((UWORD*) colDefs[colNo].PtrDataObj) = 0;
+ break;
+ case SQL_C_SLONG:
+ *((SDWORD *) colDefs[colNo].PtrDataObj) = 0;
+ break;
+ case SQL_C_ULONG:
+ *((UDWORD *) colDefs[colNo].PtrDataObj) = 0;
+ break;
+ case SQL_C_FLOAT:
+ *((SFLOAT *) colDefs[colNo].PtrDataObj) = 0.0f;
+ break;
+ case SQL_C_DOUBLE:
+ *((SDOUBLE *) colDefs[colNo].PtrDataObj) = 0.0f;
+ break;
+ case SQL_C_TIMESTAMP:
+ TIMESTAMP_STRUCT *pDt;
+ pDt = (TIMESTAMP_STRUCT *) colDefs[colNo].PtrDataObj;
+ pDt->year = 0;
+ pDt->month = 0;
+ pDt->day = 0;
+ pDt->hour = 0;
+ pDt->minute = 0;
+ pDt->second = 0;
+ pDt->fraction = 0;
+ break;
}
+ if (setToNull)
+ SetColNull(colNo);
+} // wxDbTable::ClearMemberVar()
+
+
+/********** wxDbTable::ClearMemberVars() **********/
+void wxDbTable::ClearMemberVars(bool setToNull)
+{
+ int i;
+
+ // Loop through the columns setting each member variable to zero
+ for (i=0; i < noCols; i++)
+ ClearMemberVar(i,setToNull);
+
} // wxDbTable::ClearMemberVars()
/********** wxDbTable::SetColDefs() **********/
-void wxDbTable::SetColDefs (int index, const char *fieldName, int dataType, void *pData,
- int cType, int size, bool keyField, bool upd,
- bool insAllow, bool derivedCol)
+void wxDbTable::SetColDefs(int index, const char *fieldName, int dataType, void *pData,
+ int cType, int size, bool keyField, bool upd,
+ bool insAllow, bool derivedCol)
{
if (!colDefs) // May happen if the database connection fails
return;
} // wxDbTable::SetColDefs()
-/********** wxDbTable::SetColDef() **********/
-wxDbColDataPtr* wxDbTable::SetColDefs (wxDbColInf *pColInfs, ULONG numCols)
+/********** wxDbTable::SetColDefs() **********/
+wxDbColDataPtr* wxDbTable::SetColDefs(wxDbColInf *pColInfs, ULONG numCols)
{
assert(pColInfs);
wxDbColDataPtr *pColDataPtrs = NULL;
return (pColDataPtrs);
-} // wxDbTable::SetColDef()
+} // wxDbTable::SetColDefs()
/********** wxDbTable::SetCursor() **********/
} // wxDbTable::Refresh()
-/********** wxDbTable::SetNull(int colNo) **********/
-bool wxDbTable::SetNull(int colNo)
+/********** wxDbTable::SetColNull(int colNo, bool set) **********/
+bool wxDbTable::SetColNull(int colNo, bool set)
{
if (colNo < noCols)
- return(colDefs[colNo].Null = TRUE);
+ {
+ colDefs[colNo].Null = set;
+ if (set) // Blank out the values in the member variable
+ ClearMemberVar(colNo,FALSE); // Must call with FALSE, or infinite recursion will happen
+ return(TRUE);
+ }
else
return(FALSE);
-} // wxDbTable::SetNull(int colNo)
+} // wxDbTable::SetColNull(int colNo)
-/********** wxDbTable::SetNull(char *colName) **********/
-bool wxDbTable::SetNull(const char *colName)
+/********** wxDbTable::SetColNull(char *colName, bool set) **********/
+bool wxDbTable::SetColNull(const char *colName, bool set)
{
int i;
for (i = 0; i < noCols; i++)
}
if (i < noCols)
- return(colDefs[i].Null = TRUE);
+ {
+ colDefs[i].Null = set;
+ if (set) // Blank out the values in the member variable
+ ClearMemberVar(i,FALSE); // Must call with FALSE, or infinite recursion will happen
+ return(TRUE);
+ }
else
return(FALSE);
-} // wxDbTable::SetNull(char *colName)
+} // wxDbTable::SetColNull(char *colName)
/********** wxDbTable::GetNewCursor() **********/