Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1715 lines
40 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name :
  4. odbcconn.cxx
  5. Abstract:
  6. This module defines member functions for ODBC_CONNECTION object.
  7. Author:
  8. Murali R. Krishnan ( MuraliK ) 16-Feb-1995
  9. Environment:
  10. User Mode - Win32.
  11. Project:
  12. Internet Services Common DLL
  13. Functions Exported:
  14. ODBC_PARAMETER::CopyValue( IN LPCWSTR pwszValue);
  15. ODBC_PARAMETER::Bind( IN HSTMT hstmt);
  16. ODBC_STATEMENT::~ODBC_STATEMENT()
  17. ODBC_STATEMENT::PrepareStatement( IN LPCSTR pszStatement)
  18. ODBC_STATEMENT::PrepareStatement( IN LPCWSTR pwszStatement)
  19. ODBC_STATEMENT::BindParameter( IN PODBC_PARAMETER pOdbcParam)
  20. ODBC_STATEMENT::ExecuteStatement( VOID)
  21. ODBC_STATEMENT::ExecDirect( IN LPCSTR pwszSqlCommand, IN DWORD cch)
  22. ODBC_STATEMENT::ExecDirect( IN LPCWSTR pwszSqlCommand, IN DWORD cch)
  23. ODBC_STATEMENT::QueryColNames( OUT STR * * apstrCols,
  24. OUT DWORD * cCols,
  25. IN DWORD cchMaxFieldSize = 0 );
  26. ODBC_STATEMENT::QueryValuesAsStr( OUT STR * * apstrValues,
  27. OUT DWORD * * apcbValues,
  28. OUT BOOL * pfLast );
  29. ODBC_CONNECTION::~ODBC_CONNECTION();
  30. ODBC_CONNECTION::Open();
  31. ODBC_CONNECTION::Close();
  32. ODBC_CONNECTION::GetLastErrorCode();
  33. ODBC_CONNECTION::AllocStatement();
  34. Revision History:
  35. --*/
  36. /************************************************************
  37. * Include Headers
  38. ************************************************************/
  39. # include <tcpdllp.hxx> // for debugging macros & Unicode functions
  40. # include "odbcconn.hxx"
  41. //
  42. // Since the ODBC does not support UNICODE APIs, we convert unicode to ANSI
  43. // to call the APIs. This will have to go away once we find some other
  44. // better way to do manage the same.
  45. //
  46. //
  47. // Constants for display widths
  48. //
  49. #define MAX_NUM_PRECISION 15
  50. //
  51. // Constant for all non string and non binary data. 40 is chosen to account
  52. // for things such as Oracle's numeric types, which can have up to 38 digits
  53. // of precision
  54. //
  55. #define MAX_NONCHAR_DATA_LEN 40
  56. //
  57. // If no default maximum field size is specified, then use this value
  58. // as the maximum
  59. //
  60. #define DEFAULT_MAX_FIELD_SIZE 8192
  61. /************************************************************
  62. * Local Functions
  63. ************************************************************/
  64. static inline VOID
  65. CheckAndPrintErrorMessage( IN ODBC_CONNECTION * poc,
  66. IN RETCODE rc)
  67. {
  68. # if DBG
  69. if ( !ODBC_CONNECTION::Success( rc)) {
  70. STR str;
  71. poc->GetLastErrorText( &str, NULL, rc );
  72. DBGPRINTF( ( DBG_CONTEXT,
  73. "ODBC Error Code( %d). Text: %s\n",
  74. rc,
  75. str.QueryStr() ));
  76. }
  77. # endif // DBG
  78. return;
  79. } // CheckAndPrintErrorMessage()
  80. static inline VOID
  81. CheckAndPrintErrorMessage( IN ODBC_STATEMENT * pos,
  82. IN RETCODE rc)
  83. {
  84. # if DBG
  85. if ( !ODBC_CONNECTION::Success( rc)) {
  86. STR str;
  87. pos->GetLastErrorText( &str );
  88. DBGPRINTF( ( DBG_CONTEXT,
  89. "ODBC Error Code( %d). Text: %s\n",
  90. rc,
  91. str.QueryStr() ));
  92. }
  93. # endif // DBG
  94. return;
  95. } // CheckAndPrintErrorMessage()
  96. //
  97. // 64BIT
  98. // Not 64 Bit Compatible
  99. //
  100. // SQLPOINTER is treated here as a 32 bit value. To make this work for
  101. // sundown this needs to be reconciled.
  102. //
  103. # if 0
  104. static VOID
  105. PrintMultiString( IN char * pszMsg, IN DWORD cbLen, IN char * pmsz)
  106. {
  107. DBGPRINTF( ( DBG_CONTEXT,
  108. "Values of %s. %d bytes.\n", pszMsg, cbLen));
  109. for( char * psz = pmsz; *psz != '\0'; psz += (strlen( psz) + 1)) {
  110. DBGPRINTF( ( DBG_CONTEXT, "%s\n", psz));
  111. }
  112. return;
  113. } // PrintMultiString()
  114. static VOID
  115. AuxOdbcFunctions( IN HENV henv, IN HDBC hdbc)
  116. /*++
  117. Function useful in walking throug a few additional ODBC functions
  118. to find out the ODBC setup information.
  119. Not to be part of the shipped code. Useful for development purposes.
  120. - MuraliK
  121. --*/
  122. {
  123. RETCODE rc;
  124. //
  125. // Set the trace file to a standard file.
  126. //
  127. rc = pSQLSetConnectOption( hdbc, SQL_OPT_TRACE, SQL_OPT_TRACE_ON);
  128. DBG_ASSERT( ODBC_CONNECTION::Success( rc));
  129. rc = pSQLSetConnectOption( hdbc, SQL_OPT_TRACEFILE,
  130. (unsigned long ) //64BIT
  131. "%systemroot%\\system32\\gophsql.log");
  132. DBG_ASSERT( ODBC_CONNECTION::Success( rc));
  133. UCHAR szDriverDesc[ 300];
  134. UCHAR szDriverAttrib[ 300];
  135. SWORD cbDD = 300;
  136. SWORD cbDA = 300;
  137. SWORD cbDDCur = 0;
  138. SWORD cbDACur = 0;
  139. szDriverDesc[0] = szDriverAttrib[0] = '\0';
  140. rc = pSQLDrivers( henv, SQL_FETCH_FIRST,
  141. szDriverDesc, cbDD, &cbDDCur,
  142. szDriverAttrib, cbDA, &cbDACur);
  143. DBG_ASSERT( ODBC_CONNECTION::Success( rc));
  144. DBGPRINTF( ( DBG_CONTEXT,
  145. " SQLDrivers( %08x) ==> RetCode = %d."
  146. " Driver Desc. = ( %d bytes) %s. ",
  147. henv, rc, cbDDCur, szDriverDesc));
  148. PrintMultiString( " Driver Attributes", cbDACur, (char *) szDriverAttrib);
  149. szDriverDesc[0] = szDriverAttrib[0] = '\0';
  150. cbDDCur = cbDACur = 0;
  151. rc = pSQLDataSources( henv, SQL_FETCH_FIRST,
  152. szDriverDesc, cbDD, &cbDDCur,
  153. szDriverAttrib, cbDA, &cbDACur);
  154. DBG_ASSERT( ODBC_CONNECTION::Success( rc));
  155. DBGPRINTF( ( DBG_CONTEXT,
  156. " SQLDataSources( %08x) ==> RetCode = %d."
  157. " Data Sources. = ( %d bytes) %s. ",
  158. henv, rc, cbDDCur, szDriverDesc));
  159. PrintMultiString( " Data Source Description", cbDACur,
  160. (char *) szDriverAttrib);
  161. return;
  162. } // AuxOdbcFunctions()
  163. # endif // 0
  164. /************************************************************
  165. * Member Functions of ODBC_PARAMETER
  166. ************************************************************/
  167. BOOL
  168. ODBC_PARAMETER::CopyValue( IN LPCWSTR pwszValue)
  169. /*++
  170. Description:
  171. This function copies the given Unicode string as the value into
  172. current parameter marker to be used for future insertion.
  173. Arguments:
  174. pwszValue pointer to null-terminated string containing Unicode value to
  175. be copied into the parameter marker.
  176. Returns:
  177. TRUE on success and FALSE if there is any error.
  178. Note:
  179. Since ODBC does not support Unicode directly right now, we convert
  180. string value to be ANSI before copying the value over.
  181. --*/
  182. {
  183. BOOL fReturn = FALSE;
  184. CHAR * pszValue = ConvertUnicodeToAnsi( pwszValue, NULL, 0 );
  185. //
  186. // If successful then Copy ASCII value to buffer in the parameter block.
  187. //
  188. if ( pszValue != NULL) {
  189. fReturn = this->CopyValue( pszValue);
  190. TCP_FREE( pszValue);
  191. }
  192. return ( fReturn);
  193. } // ODBC_PARAMETER::CopyValue()
  194. BOOL
  195. ODBC_PARAMETER::CopyValue( IN LPSYSTEMTIME lpst)
  196. /*++
  197. Description:
  198. This function copies the given system time into the ODBC timestamp
  199. structure for the current parameter marker to be used for
  200. future insertion.
  201. Arguments:
  202. lpSystemTime pointer to System Time structure containing current time.
  203. Returns:
  204. TRUE on success and FALSE if there is any error.
  205. --*/
  206. {
  207. TIMESTAMP_STRUCT * ptsOdbc;
  208. DBG_ASSERT( lpst != NULL);
  209. DBG_ASSERT( m_CType == SQL_C_TIMESTAMP);
  210. DBG_ASSERT( m_SqlType == SQL_TIMESTAMP);
  211. DBG_ASSERT( m_cbValueMax >= sizeof(TIMESTAMP_STRUCT));
  212. ptsOdbc = (TIMESTAMP_STRUCT * ) m_pValue;
  213. DBG_ASSERT( m_pValue != NULL);
  214. //
  215. // Copy the individual fields over properly
  216. // The types used in ODBC/Win32 are different
  217. // So do a type specific copy of the values.
  218. //
  219. ptsOdbc->year = (SWORD ) lpst->wYear;
  220. ptsOdbc->month = (UWORD ) lpst->wMonth;
  221. ptsOdbc->day = (UWORD ) lpst->wDay;
  222. ptsOdbc->hour = (UWORD ) lpst->wHour;
  223. ptsOdbc->minute = (UWORD ) lpst->wMinute;
  224. ptsOdbc->second = (UWORD ) lpst->wSecond;
  225. ptsOdbc->fraction = (UDWORD ) lpst->wMilliseconds;
  226. return ( TRUE);
  227. } // ODBC_PARAMETER::CopyValue()
  228. RETCODE
  229. ODBC_PARAMETER::Bind( IN HSTMT hStmt)
  230. /*++
  231. Description:
  232. This functions binds the data about the parameter marker 'this'
  233. ( this object) represents to the statement provided.
  234. Arguments:
  235. hStmt HANDLE for the statement to which this parameter
  236. is to be bound.
  237. Returns:
  238. RETCODE value returned by SQLBindParamater().
  239. --*/
  240. {
  241. RETCODE rc;
  242. DBG_ASSERT( hStmt != SQL_NULL_HSTMT);
  243. rc = pSQLBindParameter( hStmt, // statement
  244. QueryParamNumber(),
  245. QueryParamType(),
  246. QueryCType(),
  247. QuerySqlType(),
  248. QueryPrecision(),
  249. QueryScale(),
  250. QueryValue(),
  251. QueryMaxCbValue(),
  252. &(QueryCbValueRef())
  253. );
  254. return ( rc);
  255. } // ODBC_STATEMENT::BindParameter()
  256. # if DBG
  257. VOID
  258. ODBC_PARAMETER::Print( VOID) const
  259. {
  260. DBGPRINTF( ( DBG_CONTEXT,
  261. "Printing ODBC_PARAMETER ( %08x).\n"
  262. " Num=%u; Type=%d; CType=%d; SqlType=%d; Prec=%u; Scale=%d;"
  263. " CbMax=%d; Cb=%d.\n",
  264. this,
  265. QueryParamNumber(),
  266. QueryParamType(),
  267. QueryCType(),
  268. QuerySqlType(),
  269. QueryPrecision(),
  270. QueryScale(),
  271. QueryMaxCbValue(),
  272. QueryCbValue()));
  273. switch ( QuerySqlType()) {
  274. case SQL_INTEGER:
  275. {
  276. DWORD dwValue = *(DWORD *) QueryValue();
  277. DBGPRINTF( ( DBG_CONTEXT, " Integer Value = %u\n", dwValue));
  278. break;
  279. }
  280. case SQL_CHAR:
  281. {
  282. LPCSTR pszValue = (LPCSTR ) QueryValue();
  283. DBGPRINTF( ( DBG_CONTEXT, " String Value( %08x) = %s\n",
  284. pszValue, pszValue));
  285. break;
  286. }
  287. default:
  288. {
  289. DBGPRINTF( ( DBG_CONTEXT, " Type=%d. Unknown value at %08x\n",
  290. QuerySqlType(), QueryValue()));
  291. break;
  292. }
  293. } // switch
  294. return;
  295. } // ODBC_PARAMETER::Print()
  296. # endif // DBG
  297. /************************************************************
  298. * ODBC_STATEMENT member functions
  299. ************************************************************/
  300. ODBC_STATEMENT::~ODBC_STATEMENT( VOID)
  301. {
  302. //
  303. // Free the statement handle
  304. //
  305. if ( m_hStmt != SQL_NULL_HSTMT) {
  306. m_rc = pSQLFreeStmt( m_hStmt, SQL_DROP);
  307. m_hStmt = SQL_NULL_HSTMT;
  308. // Ignore the error code here.
  309. DBG_ASSERT( ODBC_CONNECTION::Success( m_rc));
  310. IF_DEBUG( ODBC) {
  311. DBGPRINTF( ( DBG_CONTEXT,
  312. "SqlFreeStmt() return code %d.\n",
  313. m_rc));
  314. CheckAndPrintErrorMessage( this, m_rc);
  315. }
  316. }
  317. FreeColumnMemory();
  318. } // ODBC_STATEMENT::~ODBC_STATEMENT()
  319. BOOL
  320. ODBC_STATEMENT::ExecDirect(
  321. IN LPCSTR pszSqlCommand,
  322. IN DWORD cchSqlCommand)
  323. {
  324. BOOL fReturn;
  325. IF_DEBUG( ODBC) {
  326. DBGPRINTF( ( DBG_CONTEXT,
  327. " Executing the SQL command (%d bytes) %s.\n",
  328. cchSqlCommand * sizeof( CHAR),
  329. pszSqlCommand));
  330. }
  331. //
  332. // SQLExecDirect only likes Unsigned chars !
  333. //
  334. m_rc = pSQLExecDirect( m_hStmt, (UCHAR FAR *) pszSqlCommand, cchSqlCommand);
  335. fReturn = ODBC_CONNECTION::Success( m_rc);
  336. IF_DEBUG( ODBC) {
  337. DBGPRINTF( ( DBG_CONTEXT,
  338. " SQLExecDirect() returns code %d\n",
  339. m_rc));
  340. CheckAndPrintErrorMessage( this, m_rc);
  341. }
  342. return ( fReturn);
  343. } // ODBC_STATEMENT::ExecDirect()
  344. BOOL
  345. ODBC_STATEMENT::ExecDirect(
  346. IN LPCWSTR pszSqlCommand,
  347. IN DWORD cchSqlCommand)
  348. {
  349. BOOL fReturn = FALSE;
  350. char * pszCommand;
  351. if ( ( pszCommand = ConvertUnicodeToAnsi( pszSqlCommand, NULL, 0))
  352. != NULL ) {
  353. fReturn = ExecDirect( pszCommand, strlen( pszCommand));
  354. TCP_FREE( pszCommand);
  355. }
  356. return ( fReturn);
  357. } // ODBC_STATEMENT::ExecDirect()
  358. BOOL
  359. ODBC_STATEMENT::PrepareStatement(IN LPCSTR pszStatement)
  360. /*++
  361. This function prepares the SQL statement for future execution.
  362. Arguments:
  363. pszStatement pointer to null terminated string containing the
  364. statement.
  365. Returns:
  366. TRUE on success and FALSE if there is any failure.
  367. --*/
  368. {
  369. BOOL fReturn;
  370. DBG_ASSERT( QueryErrorCode() == SQL_SUCCESS && pszStatement != NULL);
  371. m_rc = pSQLPrepare( m_hStmt, (UCHAR FAR *) pszStatement, SQL_NTS);
  372. IF_DEBUG( ODBC) {
  373. DBGPRINTF( ( DBG_CONTEXT,
  374. " SQLPrepare( %s) returns ErrorCode = %d.\n",
  375. pszStatement, m_rc));
  376. CheckAndPrintErrorMessage( this, m_rc);
  377. }
  378. return ( m_fPreparedStmt = ODBC_CONNECTION::Success( m_rc));
  379. } // ODBC_STATEMENT::PrepareStatment()
  380. BOOL
  381. ODBC_STATEMENT::PrepareStatement( IN LPCWSTR pwszCommand)
  382. /*++
  383. This function prepares an ODBC statement for execution.
  384. Since ODBC does not support UNICODE, we convert the statement into ANSI
  385. before calling the APIs.
  386. Arguments:
  387. pwszCommand pointer to null-terminated string containing the
  388. statement to be prepared.
  389. Returns:
  390. TRUE on success and FALSE if there is any failure.
  391. --*/
  392. {
  393. BOOL fReturn = FALSE;
  394. CHAR * pszCommand = NULL;
  395. DBG_ASSERT( pwszCommand != NULL);
  396. pszCommand = ConvertUnicodeToAnsi( pwszCommand, NULL, 0);
  397. if ( pszCommand != NULL) {
  398. fReturn = PrepareStatement( pszCommand);
  399. TCP_FREE( pszCommand);
  400. } // pszCommand != NULL
  401. return ( fReturn);
  402. } // ODBC_STATEMENT::PrepareStatement()
  403. BOOL
  404. ODBC_STATEMENT::BindParameter( IN PODBC_PARAMETER pOdbcParameter)
  405. {
  406. DBG_ASSERT( ODBC_CONNECTION::Success( m_rc) && pOdbcParameter != NULL);
  407. m_rc = pOdbcParameter->Bind( m_hStmt);
  408. IF_DEBUG( ODBC) {
  409. CheckAndPrintErrorMessage( this, m_rc);
  410. }
  411. return ( ODBC_CONNECTION::Success( m_rc));
  412. } // ODBC_STATEMENT::BindParameter()
  413. BOOL
  414. ODBC_STATEMENT::ExecuteStatement( VOID)
  415. /*++
  416. This function executes a prepared ODBC statement. At the end of execution,
  417. the transaction is also committed to ensure that the record is automatically
  418. written to the database.
  419. Arguments:
  420. None
  421. Returns:
  422. TRUE on success and FALSE if there is any failure.
  423. --*/
  424. {
  425. DBG_ASSERT( m_fPreparedStmt != FALSE);
  426. if ( !ODBC_CONNECTION::Success( QueryErrorCode()) ) {
  427. DBGPRINTF(( DBG_CONTEXT,
  428. "!!WARNING!! - Attempting to use Invalid ODBC Connection!\n" ));
  429. }
  430. m_rc = pSQLExecute( m_hStmt);
  431. IF_DEBUG( ODBC) {
  432. CheckAndPrintErrorMessage( this, m_rc);
  433. }
  434. return ( ODBC_CONNECTION::Success( m_rc));
  435. } // ODBC_STATEMENT::ExecuteStatement()
  436. BOOL
  437. ODBC_STATEMENT::QueryRowCount(
  438. OUT DWORD * pcRows
  439. )
  440. /*++
  441. Calls SQLRowCount on the current result set.
  442. NOTE: Not all database implementations support this!!
  443. Arguments:
  444. pcRows - Receives count of rows
  445. Returns:
  446. TRUE on success and FALSE if there are any failures.
  447. Note:
  448. --*/
  449. {
  450. m_rc = pSQLRowCount( m_hStmt,
  451. (SDWORD *) pcRows );
  452. return ( ODBC_CONNECTION::Success( m_rc));
  453. }
  454. BOOL
  455. ODBC_STATEMENT::QueryColNames(
  456. STR * * pastrCols,
  457. DWORD * cCols,
  458. DWORD cchMaxFieldSize,
  459. BOOL * pfHaveResultSet
  460. )
  461. /*++
  462. This method returns the list of column names from the result table
  463. Arguments:
  464. pastrCols - Receives an array of STRs containing the column names
  465. cCols - Count of columns returned (zero for no result set)
  466. cchMaxFieldSize - Maximum buffer size to allocate for any data fields,
  467. zero means use the default value.
  468. pfHaveResultSet - Set to TRUE if the current query was a SELECT and thus has
  469. rows that can be enumerated
  470. Returns:
  471. TRUE on success and FALSE if there are any failures.
  472. Note:
  473. --*/
  474. {
  475. SWORD nresultcols;
  476. SWORD i;
  477. CHAR achColName[64];
  478. SWORD cchColName;
  479. SWORD ColType;
  480. DWORD cchColLength;
  481. SWORD scale;
  482. SWORD nullable;
  483. *pastrCols = NULL;
  484. *cCols = 0;
  485. *pfHaveResultSet = TRUE;
  486. //
  487. // Return the old binding info if we already have it
  488. //
  489. if ( m_astrColNames )
  490. {
  491. *pastrCols = m_astrColNames;
  492. *cCols = m_cCols;
  493. return TRUE;
  494. }
  495. //
  496. // Provide a default maximum field size if none was specified
  497. //
  498. if ( !cchMaxFieldSize )
  499. cchMaxFieldSize = DEFAULT_MAX_FIELD_SIZE;
  500. //
  501. // See what kind of statement it was. If there are no result
  502. // columns, the statement is not a SELECT statement.
  503. //
  504. m_rc = pSQLNumResultCols( m_hStmt,
  505. &nresultcols);
  506. if ( !ODBC_CONNECTION::Success( m_rc ))
  507. return FALSE;
  508. if ( nresultcols > 0 )
  509. {
  510. //
  511. // Allocate an array of strings for the column names and the column
  512. // values
  513. //
  514. m_cCols = nresultcols;
  515. *cCols = m_cCols;
  516. m_astrColNames = new STR[m_cCols];
  517. m_astrValues = new STR[m_cCols];
  518. m_acbValue = new LONG[m_cCols];
  519. //
  520. // Otherwise, get the column names of the result set and use the
  521. // display_size() function to compute the length needed by each data
  522. // type. Next, bind the columns and specify all data will be
  523. // converted to char.
  524. //
  525. for (i = 0; i < m_cCols; i++)
  526. {
  527. m_rc = pSQLDescribeCol( m_hStmt,
  528. i + 1,
  529. (UCHAR *) achColName,
  530. (SWORD)sizeof(achColName),
  531. &cchColName,
  532. &ColType,
  533. &cchColLength,
  534. &scale,
  535. &nullable);
  536. if ( !ODBC_CONNECTION::Success( m_rc ))
  537. return FALSE;
  538. //
  539. // Select the buffer size for the retrieved data for this column
  540. //
  541. cchColLength = ODBC_CONNECTION::DisplaySize( ColType,
  542. min( cchColLength, cchMaxFieldSize) );
  543. //
  544. // Copy the column name and set the column data size
  545. //
  546. if ( !m_astrColNames[i].Copy( achColName ) ||
  547. !m_astrValues[i].Resize( cchColLength + 1 ))
  548. {
  549. return FALSE;
  550. }
  551. m_rc = pSQLBindCol( m_hStmt,
  552. i + 1,
  553. SQL_C_CHAR,
  554. m_astrValues[i].QueryPtr(),
  555. cchColLength,
  556. &m_acbValue[i] );
  557. if ( !ODBC_CONNECTION::Success( m_rc ))
  558. return FALSE;
  559. }
  560. *pastrCols = m_astrColNames;
  561. *cCols = m_cCols;
  562. }
  563. else
  564. {
  565. *pfHaveResultSet = FALSE;
  566. }
  567. return TRUE;
  568. }
  569. BOOL
  570. ODBC_STATEMENT::QueryValuesAsStr(
  571. STR * * pastrValues,
  572. OUT DWORD * * pacbValues,
  573. BOOL * pfLast
  574. )
  575. /*++
  576. This method gets the data at the current position.
  577. Arguments:
  578. pastrValues - Receives a pointer to an array of strings that contains
  579. the alphanumeric representation of that field
  580. pacbValues - Receives pointer to array of DWORDs that contain the length
  581. of the field
  582. pfLast - Set to TRUE if there are no more values to retrieve
  583. Returns:
  584. TRUE on success and FALSE if there are any failures.
  585. Note:
  586. --*/
  587. {
  588. *pastrValues = NULL;
  589. //
  590. // Build the bindings if we haven't already
  591. //
  592. if ( !m_astrColNames )
  593. {
  594. STR * astrCols;
  595. DWORD cCols;
  596. BOOL fHaveResultSet;
  597. if ( !QueryColNames( &astrCols,
  598. &cCols,
  599. 0,
  600. &fHaveResultSet ))
  601. {
  602. return FALSE;
  603. }
  604. }
  605. //
  606. // If there are columns to enumerate, get them now
  607. //
  608. if ( m_astrColNames )
  609. {
  610. DWORD i;
  611. //
  612. // Zero terminate the columns as some drivers don't write anything
  613. // for NULL fields
  614. //
  615. for ( i = 0; i < m_cCols; i++ )
  616. {
  617. *((CHAR *) m_astrValues[i].QueryPtr()) = '\0';
  618. m_acbValue[i] = 0;
  619. }
  620. //
  621. // Fill in the binding values
  622. //
  623. m_rc = pSQLFetch( m_hStmt );
  624. if ( m_rc == SQL_NO_DATA_FOUND )
  625. {
  626. *pfLast = TRUE;
  627. }
  628. else
  629. {
  630. if ( !ODBC_CONNECTION::Success( m_rc ))
  631. return FALSE;
  632. *pfLast = FALSE;
  633. }
  634. *pastrValues = m_astrValues;
  635. *pacbValues = (DWORD *) m_acbValue;
  636. }
  637. else
  638. {
  639. *pfLast = TRUE;
  640. }
  641. return TRUE;
  642. }
  643. BOOL
  644. ODBC_STATEMENT::MoreResults(
  645. BOOL * pfMoreResults
  646. )
  647. /*++
  648. Determines if there are any more results sets to return to the user
  649. pfMoreResults - Set to TRUE if there are more results in the result set
  650. --*/
  651. {
  652. *pfMoreResults = TRUE;
  653. m_rc = pSQLMoreResults( m_hStmt );
  654. if ( m_rc == SQL_NO_DATA_FOUND )
  655. {
  656. *pfMoreResults = FALSE;
  657. return TRUE;
  658. }
  659. if ( !ODBC_CONNECTION::Success( m_rc ))
  660. return FALSE;
  661. return TRUE;
  662. }
  663. VOID
  664. ODBC_STATEMENT::FreeColumnMemory(
  665. VOID
  666. )
  667. /*++
  668. This method frees memory allocated by the QueryColNames and
  669. QueryValuesAsStr methods.
  670. --*/
  671. {
  672. if ( m_astrColNames ) delete [] m_astrColNames;
  673. if ( m_astrValues ) delete [] m_astrValues;
  674. if ( m_acbValue ) delete [] m_acbValue;
  675. m_astrColNames = NULL;
  676. m_astrValues = NULL;
  677. m_acbValue = NULL;
  678. }
  679. # if DBG
  680. VOID
  681. ODBC_STATEMENT::Print( VOID) const
  682. {
  683. DBGPRINTF( ( DBG_CONTEXT,
  684. " Printing ODBC_STATEMENT( %08x)."
  685. " HStmt = %08x. OdbcConn=%08x. RetCode = %d\n",
  686. m_hStmt, m_pOdbcConnection, m_rc));
  687. } // ODBC_STATEMENT::Print()
  688. # endif // DBG
  689. /**************************************************
  690. * Member Functions of class ODBC_CONNECTION
  691. **************************************************/
  692. ODBC_CONNECTION::~ODBC_CONNECTION( VOID)
  693. /*++
  694. This function closes the odbc connection ( if open) and cleans up.
  695. --*/
  696. {
  697. DBG_REQUIRE( Close());
  698. return;
  699. } // ODBC_CONNECTION::~ODBC_CONNECTION()
  700. BOOL
  701. ODBC_CONNECTION::Open(
  702. IN LPCSTR pszDataSource,
  703. IN LPCSTR pszUserName,
  704. IN LPCSTR pszPassword)
  705. /*++
  706. This function opens a new odbc connection to given data source
  707. using the user name and password supplied.
  708. Arguments:
  709. pszDataSource pointer to null-terminated string containing ODBC
  710. data source name
  711. pszUserName pointer to null-terminated string containing UserName
  712. pszPassword pointer to null-terminated string containing Password
  713. Returns:
  714. TRUE on success and FALSE if there is an error.
  715. --*/
  716. {
  717. BOOL fReturn = FALSE;
  718. DBG_ASSERT( pszDataSource != NULL &&
  719. pszUserName != NULL &&
  720. pszPassword != NULL);
  721. //
  722. // Allocate an ODBC environment
  723. //
  724. m_rc = pSQLAllocEnv( &m_henv);
  725. fReturn = Success( m_rc);
  726. IF_DEBUG( ODBC) {
  727. DBGPRINTF( ( DBG_CONTEXT,
  728. "SQLAllocEnv() returned ErrorCode %d. henv = %08x\n",
  729. m_rc, m_henv));
  730. CheckAndPrintErrorMessage( this, m_rc);
  731. }
  732. if ( fReturn) {
  733. //
  734. // Establish memory for connection handle within the environment
  735. //
  736. m_rc = pSQLAllocConnect( m_henv, &m_hdbc);
  737. fReturn = Success( m_rc);
  738. IF_DEBUG( ODBC) {
  739. DBGPRINTF( ( DBG_CONTEXT,
  740. "SQLAllocConnect() returns code %d. hdbc = %08x\n",
  741. m_rc, m_hdbc));
  742. CheckAndPrintErrorMessage( this, m_rc);
  743. }
  744. }
  745. if ( fReturn) {
  746. //
  747. // Use Following call to just printout the dynamic values for ODBC
  748. //
  749. // AuxOdbcFunctions( m_henv, m_hdbc);
  750. #if 0
  751. {
  752. STR str;
  753. STR strOut;
  754. SWORD swStrOut;
  755. if ( !str.Append( pszDataSource ) ||
  756. !str.Append( ";UID=" ) ||
  757. !str.Append( pszUserName ) ||
  758. !str.Append( ";PWD=" ) ||
  759. !str.Append( pszPassword ) ||
  760. !str.Append( ";APP=Internet Services") ||
  761. !strOut.Resize( 255 ))
  762. {
  763. return FALSE;
  764. }
  765. m_rc = pSQLDriverConnect( m_hdbc,
  766. NULL,
  767. (UCHAR *) str.QueryStr(),
  768. SQL_NTS,
  769. (UCHAR *) strOut.QueryStr(),
  770. strOut.QuerySize(),
  771. &swStrOut,
  772. SQL_DRIVER_NOPROMPT );
  773. }
  774. #else
  775. {
  776. m_rc = pSQLConnect( m_hdbc,
  777. (UCHAR FAR *) pszDataSource, SQL_NTS,
  778. (UCHAR FAR *) pszUserName, SQL_NTS,
  779. (UCHAR FAR *) pszPassword, SQL_NTS);
  780. }
  781. #endif
  782. fReturn = Success( m_rc);
  783. IF_DEBUG( ODBC) {
  784. DBGPRINTF( ( DBG_CONTEXT,
  785. "SQLConnect( %s, %s, %s) returns code %d.\n",
  786. pszDataSource,
  787. pszUserName,
  788. pszPassword,
  789. m_rc));
  790. CheckAndPrintErrorMessage( this, m_rc);
  791. }
  792. }
  793. m_fValid = fReturn;
  794. if ( !fReturn) {
  795. SetLastError( ERROR_GEN_FAILURE );
  796. }
  797. return ( fReturn);
  798. } // ODBC_CONNECTION::Open()
  799. BOOL
  800. ODBC_CONNECTION::Open(
  801. IN LPCWSTR pwszDataSource,
  802. IN LPCWSTR pwszUserName,
  803. IN LPCWSTR pwszPassword)
  804. /*++
  805. This function opens a new odbc connection to given data source
  806. using the user name and password supplied.
  807. Arguments:
  808. pwszDataSource pointer to null-terminated string containing ODBC
  809. data source name
  810. pwszUserName pointer to null-terminated string containing UserName
  811. pwszPassword pointer to null-terminated string containing Password
  812. Returns:
  813. TRUE on success and FALSE if there is an error.
  814. Note:
  815. Poor me. ODBC Does not take UNICODE strings :(. 2/15/95
  816. So we will explicitly convert parameters to ANSI on stack.
  817. --*/
  818. {
  819. BOOL fReturn;
  820. DWORD dwError = NO_ERROR;
  821. CHAR * pszDataSource;
  822. CHAR * pszUserName;
  823. CHAR * pszPassword;
  824. //
  825. // Convert all parameters from UNICODE to ANSI
  826. //
  827. pszDataSource = ConvertUnicodeToAnsi( pwszDataSource, NULL, 0);
  828. pszUserName = ConvertUnicodeToAnsi( pwszUserName, NULL, 0);
  829. pszPassword = ConvertUnicodeToAnsi( pwszPassword, NULL, 0);
  830. //
  831. // Make an ANSI open call.
  832. //
  833. fReturn = Open( pszDataSource, pszUserName, pszPassword);
  834. if ( !fReturn) {
  835. dwError = GetLastError();
  836. }
  837. //
  838. // Freeup the space allocated.
  839. //
  840. if ( pszDataSource != NULL) {
  841. TCP_FREE( pszDataSource);
  842. pszDataSource = NULL;
  843. }
  844. if ( pszUserName != NULL) {
  845. TCP_FREE( pszUserName);
  846. pszUserName = NULL;
  847. }
  848. if ( pszPassword != NULL) {
  849. //
  850. // Zero the password for security reasons.
  851. //
  852. memset( pszPassword, 0, strlen( pszPassword));
  853. TCP_FREE( pszPassword);
  854. pszPassword = NULL;
  855. }
  856. if ( !fReturn) {
  857. SetLastError( dwError);
  858. }
  859. return ( fReturn);
  860. } // ODBC_CONNECTION::Open()
  861. BOOL
  862. ODBC_CONNECTION::Close( VOID)
  863. /*++
  864. This function closes the connection established with the ODBC
  865. and frees up and dynamic memory used.
  866. Returns:
  867. TRUE on success and FALSE if there are any failures.
  868. Note:
  869. Intermediate failures are ignored. Normally they should not occur.
  870. --*/
  871. {
  872. BOOL fReturn = TRUE;
  873. //
  874. // Disconnect and free the connection.
  875. //
  876. if ( m_hdbc != SQL_NULL_HDBC) {
  877. m_rc = pSQLDisconnect( m_hdbc );
  878. //
  879. // Disconnect is allowed to fail w/o being fatal so don't set
  880. // fReturn
  881. //
  882. IF_DEBUG( ODBC) {
  883. DBGPRINTF( ( DBG_CONTEXT,
  884. "Warning: SQLDisconnect() returns code %d.\n",
  885. m_rc));
  886. CheckAndPrintErrorMessage( this, m_rc);
  887. }
  888. m_rc = pSQLFreeConnect( m_hdbc);
  889. m_hdbc = SQL_NULL_HDBC;
  890. fReturn = fReturn && Success( m_rc);
  891. IF_DEBUG( ODBC) {
  892. DBGPRINTF( ( DBG_CONTEXT,
  893. "SQLFreeConnect() returns code %d.\n",
  894. m_rc));
  895. CheckAndPrintErrorMessage( this, m_rc);
  896. }
  897. }
  898. //
  899. // Free the ODBC environment handle.
  900. //
  901. if ( m_henv != SQL_NULL_HENV) {
  902. m_rc = pSQLFreeEnv( m_henv);
  903. m_henv = SQL_NULL_HENV;
  904. fReturn = fReturn && Success( m_rc);
  905. IF_DEBUG( ODBC) {
  906. DBGPRINTF( ( DBG_CONTEXT,
  907. "SQLFreeEnv() returns code %d.\n",
  908. m_rc));
  909. CheckAndPrintErrorMessage( this, m_rc);
  910. }
  911. }
  912. return ( fReturn);
  913. } // ODBC_CONNECTION::Close()
  914. PODBC_STATEMENT
  915. ODBC_CONNECTION::AllocStatement( VOID)
  916. /*++
  917. Description:
  918. This function allocates a new ODBC statement object and also calls
  919. SQLAllocStatement to create the state required for establishing the
  920. statement in the ODBC Manager.
  921. Arguments:
  922. None
  923. Returns:
  924. TRUE on success and FALSE if there is any failure.
  925. --*/
  926. {
  927. PODBC_STATEMENT pOdbcStmt = NULL;
  928. HSTMT hstmt = SQL_NULL_HSTMT;
  929. DBG_ASSERT( Success( m_rc));
  930. //
  931. // Allocate a statement handle and associate it with the connection.
  932. //
  933. m_rc = pSQLAllocStmt( m_hdbc, &hstmt);
  934. IF_DEBUG( ODBC) {
  935. DBGPRINTF( ( DBG_CONTEXT,
  936. "SqlAllocStmt() returns code %d."
  937. " New Hstmt is : %08x\n",
  938. m_rc, hstmt));
  939. CheckAndPrintErrorMessage( this, m_rc);
  940. }
  941. if ( ODBC_CONNECTION::Success( m_rc)) {
  942. pOdbcStmt = new ODBC_STATEMENT( this, hstmt);
  943. }
  944. return ( pOdbcStmt);
  945. } // ODBC_CONNECTION::AllocStatement()
  946. BOOL
  947. ODBC_CONNECTION::SetConnectOption(
  948. IN UWORD Option,
  949. IN SQLPOINTER Param
  950. )
  951. /*++
  952. Sets various options on this connection
  953. Arguments:
  954. Option - Option to set
  955. Param - Option value (32 bit dword or pointer to null terminated string)
  956. Returns:
  957. TRUE on success and FALSE if there are any failures. Failures are
  958. considered to be soft errors as the problem may be the driver doesn't
  959. support the option etc.
  960. Note:
  961. --*/
  962. {
  963. BOOL fReturn = TRUE;
  964. RETCODE rc;
  965. if ( m_hdbc != SQL_NULL_HDBC)
  966. {
  967. rc = pSQLSetConnectOption( m_hdbc, Option, Param);
  968. fReturn = Success( rc);
  969. IF_DEBUG( ODBC) {
  970. DBGPRINTF( ( DBG_CONTEXT,
  971. "SQLSetConnectOption( %d, %d ) returns code %d.\n",
  972. Option,
  973. Param,
  974. rc));
  975. CheckAndPrintErrorMessage( this, rc);
  976. }
  977. }
  978. else
  979. {
  980. DBGPRINTF( ( DBG_CONTEXT,
  981. "[SetConnectOption] Warning: Setting option on closed connection\n" ));
  982. }
  983. return fReturn;
  984. }
  985. BOOL
  986. ODBC_CONNECTION::GetLastErrorText(
  987. OUT STR * pstrError,
  988. IN HSTMT hstmt,
  989. IN RETCODE rc
  990. ) const
  991. /*++
  992. This method returns the textual representation of the last ODBC or windows
  993. error that occurred. Even though the ODBC methods return FALSE on failure,
  994. if it was an ODBC call that failed, then GetLastError won't return the
  995. needed error code. Clients of this class should call this method to get
  996. a descriptive text string of the failure.
  997. Returns:
  998. TRUE on success and FALSE if there are any failures.
  999. Note:
  1000. If this function returns FALSE, then a client should call GetLastError
  1001. for the error code.
  1002. --*/
  1003. {
  1004. BOOL fReturn = TRUE;
  1005. if ( ODBC_CONNECTION::Success( rc)) {
  1006. fReturn = pstrError->LoadString( GetLastError());
  1007. } else {
  1008. CHAR rgchMsg[ SQL_MAX_MESSAGE_LENGTH + 10];
  1009. CHAR achState[30];
  1010. CHAR rgchFullMsg[ sizeof(rgchMsg) + sizeof(achState) + 60];
  1011. SWORD cbMsg;
  1012. LONG lError;
  1013. DWORD dwError;
  1014. //
  1015. // If we're formatting as HTML, we bullet list the items
  1016. //
  1017. pstrError->Reset();
  1018. //
  1019. // Loop to pick up all of the errors
  1020. //
  1021. do {
  1022. cbMsg = SQL_MAX_MESSAGE_LENGTH;
  1023. rc = pSQLError( m_henv,
  1024. m_hdbc,
  1025. hstmt,
  1026. (UCHAR *) achState,
  1027. &lError,
  1028. (UCHAR *) rgchMsg,
  1029. cbMsg,
  1030. &cbMsg );
  1031. if ( ODBC_CONNECTION::Success( rc)) {
  1032. wsprintf( rgchFullMsg,
  1033. "[State=%s][Error=%d]%s\n",
  1034. achState, lError, rgchMsg);
  1035. if ( !pstrError->Append( rgchFullMsg )) {
  1036. fReturn = FALSE;
  1037. break;
  1038. }
  1039. } else {
  1040. //
  1041. // This is indicates there are no more error strings
  1042. // to pick up so we should get out
  1043. //
  1044. if ( rc == SQL_NO_DATA_FOUND ) {
  1045. //
  1046. // Append the end of unorder list marker
  1047. //
  1048. rc = SQL_SUCCESS;
  1049. break;
  1050. }
  1051. }
  1052. } while ( ODBC_CONNECTION::Success( rc) );
  1053. if ( !ODBC_CONNECTION::Success( rc) )
  1054. {
  1055. DBGPRINTF( ( DBG_CONTEXT,
  1056. "[GetLastErrorText] SqlError() returned error %d.\n",
  1057. rc));
  1058. SetLastError( ERROR_GEN_FAILURE );
  1059. fReturn = FALSE;
  1060. }
  1061. }
  1062. return ( fReturn);
  1063. } // ODBC_CONNECTION::GetLastErrorText()
  1064. BOOL
  1065. ODBC_CONNECTION::GetLastErrorTextAsHtml(
  1066. OUT STR * pstrError,
  1067. IN HSTMT hstmt,
  1068. IN RETCODE rc
  1069. ) const
  1070. /*++
  1071. This method returns the textual representation of the last ODBC or windows
  1072. error that occurred. Even though the ODBC methods return FALSE on failure,
  1073. if it was an ODBC call that failed, then GetLastError won't return the
  1074. needed error code. Clients of this class should call this method to get
  1075. a descriptive text string of the failure.
  1076. Returns:
  1077. TRUE on success and FALSE if there are any failures.
  1078. Note:
  1079. If this function returns FALSE, then a client should call GetLastError
  1080. for the error code.
  1081. --*/
  1082. {
  1083. BOOL fReturn = TRUE;
  1084. if ( ODBC_CONNECTION::Success( rc)) {
  1085. fReturn = pstrError->LoadString( GetLastError());
  1086. } else {
  1087. CHAR rgchMsg[ SQL_MAX_MESSAGE_LENGTH + 10];
  1088. CHAR achState[30];
  1089. CHAR rgchFullMsg[ sizeof(rgchMsg) + sizeof(achState) + 60];
  1090. SWORD cbMsg;
  1091. LONG lError;
  1092. DWORD dwError;
  1093. //
  1094. // If we're formatting as HTML, we bullet list the items
  1095. //
  1096. if ( !pstrError->Copy( "<UL>" ))
  1097. {
  1098. return FALSE;
  1099. }
  1100. //
  1101. // Loop to pick up all of the errors
  1102. //
  1103. do {
  1104. cbMsg = SQL_MAX_MESSAGE_LENGTH;
  1105. rc = pSQLError( m_henv,
  1106. m_hdbc,
  1107. hstmt,
  1108. (UCHAR *) achState,
  1109. &lError,
  1110. (UCHAR *) rgchMsg,
  1111. cbMsg,
  1112. &cbMsg );
  1113. if ( ODBC_CONNECTION::Success( rc)) {
  1114. wsprintf( rgchFullMsg,
  1115. "<LI>[State=%s][Error=%d]%s\n",
  1116. achState, lError, rgchMsg);
  1117. if ( !pstrError->Append( rgchFullMsg )) {
  1118. fReturn = FALSE;
  1119. break;
  1120. }
  1121. } else {
  1122. //
  1123. // This is indicates there are no more error strings
  1124. // to pick up so we should get out
  1125. //
  1126. if ( rc == SQL_NO_DATA_FOUND ) {
  1127. //
  1128. // Append the end of unorder list marker
  1129. //
  1130. if ( !pstrError->Append( "</UL>" )) {
  1131. return FALSE;
  1132. }
  1133. rc = SQL_SUCCESS;
  1134. break;
  1135. }
  1136. }
  1137. } while ( ODBC_CONNECTION::Success( rc) );
  1138. if ( !ODBC_CONNECTION::Success( rc) )
  1139. {
  1140. DBGPRINTF( ( DBG_CONTEXT,
  1141. "[GetLastErrorText] SqlError() returned error %d.\n",
  1142. rc));
  1143. SetLastError( ERROR_GEN_FAILURE );
  1144. fReturn = FALSE;
  1145. }
  1146. }
  1147. return ( fReturn);
  1148. } // ODBC_CONNECTION::GetLastErrorTextAsHtml()
  1149. BOOL
  1150. ODBC_CONNECTION::GetInfo(IN DWORD fInfoType,
  1151. IN PVOID rgbInfoValue,
  1152. IN DWORD cbInfoValueMax,
  1153. IN OUT DWORD * pcbInfoValue)
  1154. /*++
  1155. This function obtains the value of the fInfoType for a specific
  1156. ODBC Connection. It mimicks the SQLGetInfo() and uses it to obtain
  1157. this value. On successful return the pointer rgbInfoValue contains
  1158. the requested value and pcbInfoValue contains the size in bytes of
  1159. data.
  1160. Arguments:
  1161. fInfoType - flag containing the Information Type (name) to be fetched.
  1162. rgbInfoValue - pointer to buffer which will contain the return data.
  1163. cbInfoValue - size of rgbInfoValue in bytes.
  1164. pcbInfoValue - pointer to location that will contain the size of
  1165. information stored in rgbInfoValue, on successful return.
  1166. If buffer is insufficient, this location will contain the
  1167. required number of bytes.
  1168. Returns:
  1169. TRUE on success and FALSE if there is any failure.
  1170. --*/
  1171. {
  1172. BOOL fReturn = FALSE;
  1173. if ( m_hdbc != SQL_NULL_HDBC) {
  1174. RETCODE rc;
  1175. rc = pSQLGetInfo( m_hdbc, (UWORD ) fInfoType,
  1176. (PTR) rgbInfoValue,
  1177. (SWORD) cbInfoValueMax,
  1178. (SWORD FAR *) pcbInfoValue);
  1179. fReturn = Success( rc);
  1180. IF_DEBUG( ODBC) {
  1181. DBGPRINTF( ( DBG_CONTEXT,
  1182. "SQLGetInfo( %08x, %d, %08x, %d, %08x) returns %d.\n",
  1183. m_hdbc, fInfoType, rgbInfoValue, cbInfoValueMax,
  1184. pcbInfoValue, rc));
  1185. CheckAndPrintErrorMessage( this, rc);
  1186. }
  1187. } else {
  1188. DBGPRINTF( ( DBG_CONTEXT,
  1189. "[SQLGetInfo] Invalid Connection to ODBC\n"));
  1190. }
  1191. return (fReturn);
  1192. } // ODBC_CONNECTION::GetInfo()
  1193. DWORD
  1194. ODBC_CONNECTION::DisplaySize(
  1195. SWORD coltype,
  1196. DWORD collen
  1197. )
  1198. {
  1199. DWORD cbSize = MAX_NONCHAR_DATA_LEN;
  1200. //
  1201. // Note that we always set the size to at least four bytes. This prevents
  1202. // any possible problems if the column to be bound is NULLable, which can
  1203. // cause a NULL to be written for the data during a fetch
  1204. //
  1205. switch (coltype)
  1206. {
  1207. case SQL_CHAR:
  1208. case SQL_VARCHAR:
  1209. case SQL_LONGVARCHAR:
  1210. case SQL_BINARY:
  1211. case SQL_VARBINARY:
  1212. case SQL_LONGVARBINARY:
  1213. cbSize = max(collen + sizeof(CHAR), sizeof(PVOID));
  1214. break;
  1215. default:
  1216. break;
  1217. }
  1218. return ( cbSize);
  1219. } // ODBC_CONNECTION::DisplaySize()
  1220. # if DBG
  1221. VOID
  1222. ODBC_CONNECTION::Print( VOID) const
  1223. {
  1224. DBGPRINTF( ( DBG_CONTEXT,
  1225. "Printing ODBC_CONNECTION ( %08x). fValid = %d\n"
  1226. " HENV = %08x. HDBC = %08x. ReturnCode =%d\n",
  1227. this, m_fValid,
  1228. m_henv, m_hdbc, m_rc));
  1229. return;
  1230. } // ODBC_CONNECTION::Print()
  1231. # endif // DBG
  1232. /************************ End of File ***********************/