windows porting
[csql.git] / src / odbc / odbcDbc.cxx
blob78e94e1f678847abe1fb6481c1969b52ff54466c
1 /* Class CSqlOdbcDbc
2 Description: Connection Handle manager.
4 ODBC API's:
5 CSqlOdbcDbc::SQLAllocDbc();
6 CSqlOdbcDbc::SQLFreeDbc();
7 CSqlOdbcDbc::SQLConnect();
8 */
10 #define strtok_r strtok_s
11 #include "odbcCommon.h"
12 #include <SqlNwConnection.h>
14 // Constructor
15 CSqlOdbcDbc::CSqlOdbcDbc( void ) :
16 handleType_( SQL_HANDLE_DBC ),
17 parentEnv_( 0 ),
18 state_( C1 ),
19 err_( SQL_HANDLE_DBC ),
20 mode_ (1),
21 curAccessMode_( ACCESSMODE_READ_WRITE ),
22 curIsolationLevel_( READ_REPEATABLE ),
23 accessMode_( ACCESSMODE_READ_WRITE ),
24 isolationLevel_( READ_COMMITTED ),
25 autoCommit_( SQL_AUTOCOMMIT_ON ),
26 fsqlConn_( NULL )
29 SQLRETURN SQLAllocConnect(
30 SQLHENV EnvironmentHandle,
31 SQLHDBC *ConnectionHandle)
33 return( CSqlOdbcDbc::SQLAllocHandle( EnvironmentHandle, ConnectionHandle ) );
36 // All ODBC API's below.
37 SQLRETURN CSqlOdbcDbc::SQLAllocHandle(
38 SQLHANDLE inputHandle, // IN
39 SQLHANDLE *outputHandle ) // OUT
42 CSqlOdbcEnv *inputEnv = (CSqlOdbcEnv*) inputHandle;
44 if( isValidHandle( inputEnv, SQL_HANDLE_ENV ) != SQL_SUCCESS )
45 return( SQL_INVALID_HANDLE );
47 // Stop if odbcVersion not set.
48 if( inputEnv->odbcVersion_ == 0 )
50 inputEnv->err_.set( ERROR_FUNCSEQ );
51 return( SQL_ERROR );
53 if (NULL == outputHandle)
55 globalError.set(ERROR_INVARGVAL);
56 return (SQL_ERROR);
59 // Allocate Connection object.
60 *outputHandle = (SQLHANDLE*) new CSqlOdbcDbc;
61 if( *outputHandle == NULL )
63 globalError.set( ERROR_MEMALLOC );
64 globalError.printStr( SQL_OV_ODBC3 );
65 return( SQL_ERROR );
68 inputEnv->dbcList_.append(*outputHandle);
69 inputEnv->state_ = E2;
70 ((CSqlOdbcDbc*) *outputHandle)->parentEnv_ = inputEnv;
71 ((CSqlOdbcDbc*) *outputHandle)->state_ = C2;
72 return( SQL_SUCCESS );
75 SQLRETURN SQLFreeConnect(
76 SQLHDBC ConnectionHandle)
78 return( CSqlOdbcDbc::SQLFreeHandle( ConnectionHandle ) );
81 SQLRETURN CSqlOdbcDbc::SQLFreeHandle(
82 SQLHANDLE inputHandle) // IN
84 CSqlOdbcDbc *inputDbc = (CSqlOdbcDbc*) inputHandle;
86 // Validate handle
87 if( isValidHandle( inputDbc, SQL_HANDLE_DBC ) != SQL_SUCCESS )
88 return( SQL_INVALID_HANDLE );
90 // Check whether we can proceed.
91 if( inputDbc->chkStateForSQLFreeHandle() != SQL_SUCCESS )
92 return( SQL_ERROR );
94 // Remove Dbc from Parent Env.
95 ListIterator iter = inputDbc->parentEnv_->dbcList_.getIterator();
96 CSqlOdbcDbc *dbcElem = NULL;
97 while(iter.hasElement())
99 dbcElem = (CSqlOdbcDbc *) iter.nextElement();
100 if (dbcElem == inputDbc) {
101 iter.reset();
102 inputDbc->parentEnv_->dbcList_.remove(dbcElem);
103 break;
106 if( inputDbc->parentEnv_->dbcList_.size() == 0 )
107 inputDbc->parentEnv_->state_ = E1;
109 inputDbc->handleType_ = -1; // Make object invalid.
110 delete inputDbc; // Delete Dbc.
112 return( SQL_SUCCESS );
115 SQLRETURN SQLDriverConnect(
116 SQLHDBC ConnectionHandle,
117 SQLHWND WindowHandle,
118 SQLCHAR * InConnectionString,
119 SQLSMALLINT StringLength1,
120 SQLCHAR * OutConnectionString,
121 SQLSMALLINT BufferLength,
122 SQLSMALLINT * StringLength2Ptr,
123 SQLUSMALLINT DriverCompletion)
125 #ifdef DEBUG
126 printError(ErrWarning, "SQLDriverConnect");
127 #endif
129 // Validate handle
130 if( isValidHandle( ConnectionHandle, SQL_HANDLE_DBC ) != SQL_SUCCESS )
131 return( SQL_INVALID_HANDLE );
133 return( ((CSqlOdbcDbc*) ConnectionHandle)->SQLConnect(InConnectionString,
134 SQL_NTS, (SQLCHAR*)"root", (SQLSMALLINT)strlen("root"),
135 (SQLCHAR*)"manager", (SQLSMALLINT)strlen("manager")) );
139 char * CSqlOdbcDbc::getFromUrl(char *url,char *name)
141 char *token=NULL, *subtoken=NULL;
142 char *saveptr1, *saveptr2,*str1,*str2;
143 for ( str1 = url; ; str1 = NULL) {
144 token = strtok_r(str1, ";" , &saveptr1);
145 if (token == NULL)
146 break;
147 // printf("TOKEN: %s\n",token);
148 str2 = token;
149 subtoken = strtok_r(str2, "=", &saveptr2);
150 //printf(" --> %s\n", subtoken);
151 if (subtoken != NULL){
152 if(strcasecmp(subtoken,name)==0)
154 return strtok_r(NULL,"=",&saveptr2);
158 return NULL;
161 SQLRETURN SQLConnect( // All param's are IN
162 SQLHDBC ConnectionHandle,
163 SQLCHAR *ServerName,
164 SQLSMALLINT NameLength1,
165 SQLCHAR *UserName,
166 SQLSMALLINT NameLength2,
167 SQLCHAR *Authentication,
168 SQLSMALLINT NameLength3)
170 #ifdef DEBUG
171 printError(ErrWarning, "SQLConnect");
172 #endif
174 // Validate handle
175 if( isValidHandle( ConnectionHandle, SQL_HANDLE_DBC ) != SQL_SUCCESS )
176 return( SQL_INVALID_HANDLE );
178 return( ((CSqlOdbcDbc*) ConnectionHandle)->SQLConnect( ServerName, NameLength1,
179 UserName, NameLength2, Authentication, NameLength3) );
182 SQLRETURN CSqlOdbcDbc::SQLConnect( // All param's are IN
183 SQLCHAR *serverName,
184 SQLSMALLINT len1,
185 SQLCHAR *user,
186 SQLSMALLINT len2,
187 SQLCHAR *pass,
188 SQLSMALLINT len3)
190 int rc;
191 char str[IDENTIFIER_LENGTH];
192 char *dsn=NULL;
193 char *hostName = NULL;
194 char *portNo = NULL;
195 char *connMode = NULL;
196 // Start with NO_ERR
197 err_.set( NO_ERR );
198 // Can we proceed ?
199 if( chkStateForSQLConnect() != SQL_SUCCESS )
200 return( SQL_ERROR );
202 // Invalid Buffer Length.
203 if( (len1 < 0 && len1 != SQL_NTS) || (len2 < 0 && len2 != SQL_NTS) || (len2 < 0 && len2 != SQL_NTS) )
205 err_.set( ERROR_BUFLEN );
206 return( SQL_ERROR );
208 if (fsqlConn_ != NULL)
210 err_.set( ERROR_CONNINUSE);
211 return ( SQL_ERROR );
213 if (NULL == serverName)
215 err_.set(ERROR_INVARGVAL);
216 return (SQL_ERROR);
218 if (NULL == user || NULL == pass)
220 err_.set(ERROR_INVARGVAL);
221 return (SQL_ERROR);
224 strncpy(str,(char *) serverName, IDENTIFIER_LENGTH);
225 dsn = getFromUrl(str,"DSN");
226 strncpy(str,(char *) serverName, IDENTIFIER_LENGTH);
227 connMode = getFromUrl(str,"MODE");
228 strncpy(str,(char *) serverName, IDENTIFIER_LENGTH);
229 hostName = getFromUrl(str,"SERVER");
230 strncpy(str,(char *) serverName, IDENTIFIER_LENGTH);
231 portNo = getFromUrl(str,"PORT");
232 //printf("Mode=%s , hostName=%s port=%s\n",connMode,hostName,portNo);
233 if(NULL != connMode){
234 if (hostName == NULL || strcasecmp((char*)hostName, "localhost") == 0 ){
235 if (strcasecmp((char*)connMode, "Gateway") == 0){
236 fsqlConn_ = SqlFactory::createConnection(CSqlGateway);
237 mode_ = 3;
238 }else if (strcasecmp((char*)connMode, "Adapter") == 0){
239 fsqlConn_ = SqlFactory::createConnection(CSqlAdapter);
240 mode_ = 2;
241 }else if (strcasecmp((char*)connMode, "csql") == 0){
242 fsqlConn_ = SqlFactory::createConnection(CSql);
243 mode_ = 1;
244 }else return ( SQL_ERROR );
245 } else {
246 if (portNo == NULL) {
247 err_.set(ERROR_INVARGVAL);
248 return (SQL_ERROR);
250 if (strcasecmp((char*)connMode, "Gateway") == 0){
251 fsqlConn_ = SqlFactory::createConnection(CSqlNetworkGateway);
252 SqlNwConnection *con = (SqlNwConnection *)fsqlConn_;
253 con->setHost(hostName, atoi(portNo));
254 mode_ = 6;
255 }else if (strcasecmp((char*)connMode, "Adapter") == 0){
256 fsqlConn_ = SqlFactory::createConnection(CSqlNetworkAdapter);
257 SqlNwConnection *con = (SqlNwConnection *)fsqlConn_;
258 con->setHost(hostName, atoi(portNo));
259 mode_ = 5;
260 }else if (strcasecmp((char*)connMode, "csql") == 0){
261 fsqlConn_ = SqlFactory::createConnection(CSqlNetwork);
262 SqlNwConnection *con = (SqlNwConnection *)fsqlConn_;
263 con->setHost(hostName, atoi(portNo));
264 mode_ = 4;
265 }else {
266 err_.set( ERROR_INVARGVAL );
267 return ( SQL_ERROR );
271 }else{
272 fsqlConn_ = SqlFactory::createConnection(CSql);
273 mode_ = 1;
275 rc = fsqlConn_->connect( (char*) user, (char*) pass );
276 if( rc != OK )
278 err_.set( ERROR_CONNREJCTD);
279 return( SQL_ERROR );
281 rc = fsqlConn_->beginTrans( isolationLevel_ );
282 if( rc != OK )
284 err_.set( ERROR_INVTRANSTATE );
285 return( SQL_ERROR );
287 curAccessMode_ = accessMode_;
288 curIsolationLevel_ = isolationLevel_;
290 // Update Dbc state
291 state_ = C4;
293 return( SQL_SUCCESS );
297 SQLRETURN SQLDisconnect(
298 SQLHDBC ConnectionHandle) // IN
300 #ifdef DEBUG
301 printError(ErrWarning, "SQLDisConnect");
302 #endif
303 // Validate Handle
304 if( isValidHandle( ConnectionHandle, SQL_HANDLE_DBC ) != SQL_SUCCESS )
305 return( SQL_INVALID_HANDLE );
306 SQLRETURN ret = ( ((CSqlOdbcDbc*) ConnectionHandle)->SQLDisconnect() );
307 return ret;
310 SQLRETURN CSqlOdbcDbc::SQLDisconnect( void )
312 SQLRETURN rc;
314 // Start with NO_ERR
315 err_.set( NO_ERR );
317 // Can we proceed ?
318 if( chkStateForSQLDisconnect() != SQL_SUCCESS )
319 return( SQL_ERROR );
321 ListIterator iter=stmtList_.getIterator();
322 while (iter.hasElement()) {
323 rc = CSqlOdbcStmt::SQLFreeHandle(iter.nextElement());
324 if( rc != OK )
325 return( SQL_ERROR );
328 // Rollback the transaction
329 if( fsqlConn_->rollback() != OK )
330 return( SQL_ERROR );
332 // Disconnect
333 if( fsqlConn_->disconnect() != OK )
334 return( SQL_ERROR );
336 delete fsqlConn_;
337 fsqlConn_ = NULL;
338 // Change the state of Dbc
339 state_ = C2;
341 return( SQL_SUCCESS );
344 SQLRETURN CSqlOdbcDbc::SQLEndTran(
345 SQLSMALLINT completionType) // IN
347 #ifdef DEBUG
348 printError(ErrWarning, "SQLEndTran: %hd", completionType);
349 #endif
351 SQLRETURN rc;
353 // Start with NO_ERR
354 err_.set( NO_ERR );
356 // Can we proceed ?
357 if( chkStateForSQLEndTran() != SQL_SUCCESS )
358 return( SQL_ERROR );
360 // Stop if no transaction is started.
361 if( state_ != C6 )
362 return( SQL_SUCCESS );
364 // Close cursors of all the statements
365 ListIterator iter = stmtList_.getIterator();
366 CSqlOdbcStmt *stmtElem = NULL;
367 while (iter.hasElement()) {
368 stmtElem = (CSqlOdbcStmt *) iter.nextElement();
369 stmtElem->SQLFreeHandle( SQL_CLOSE );
371 // Finish transaction
372 switch( completionType )
374 case SQL_COMMIT:
376 if( fsqlConn_->commit() != OK )
377 return( SQL_ERROR );
379 if( fsqlConn_->beginTrans( curIsolationLevel_ ) != OK )
380 return( SQL_ERROR );
382 break;
384 case SQL_ROLLBACK:
385 if( fsqlConn_->rollback() != OK )
386 return( SQL_ERROR );
388 rc = fsqlConn_->beginTrans( curIsolationLevel_ );
389 break;
391 default: err_.set( ERROR_OPTRANGE );
392 return( SQL_ERROR );
395 // Had statements ?
396 if( stmtList_.size() == 0 )
397 state_ = C4;
398 else
399 state_ = C5;
401 return( SQL_SUCCESS );
404 SQLRETURN SQLSetConnectOption(
405 SQLHDBC ConnectionHandle,
406 SQLUSMALLINT Option,
407 SQLUINTEGER Value)
409 return( SQLSetConnectAttr( ConnectionHandle, Option, (SQLPOINTER) Value, 0) );
412 SQLRETURN SQLSetConnectAttr(
413 SQLHDBC ConnectionHandle,
414 SQLINTEGER Attribute,
415 SQLPOINTER Value,
416 SQLINTEGER StringLength)
418 // Validate handle
419 if( isValidHandle( ConnectionHandle, SQL_HANDLE_DBC ) != SQL_SUCCESS )
420 return( SQL_INVALID_HANDLE );
422 return( ((CSqlOdbcDbc*)ConnectionHandle)->SQLSetConnectAttr( Attribute, Value, StringLength ) );
425 SQLRETURN CSqlOdbcDbc::SQLSetConnectAttr(
426 SQLINTEGER attribute,
427 SQLPOINTER value,
428 SQLINTEGER stringLength)
430 // Start with NO_ERR
431 err_.set( NO_ERR );
433 switch( attribute )
435 case SQL_ATTR_ACCESS_MODE:
436 // validate 'value'
437 if( (SQLUINTEGER) value == SQL_MODE_READ_ONLY )
438 accessMode_ = ACCESSMODE_READ_ONLY;
439 else if( (SQLUINTEGER) value == SQL_MODE_READ_WRITE )
440 accessMode_ = ACCESSMODE_READ_WRITE;
441 else
442 return( SQL_ERROR );
444 break;
445 case SQL_DEFAULT_TXN_ISOLATION:
446 case SQL_ATTR_TXN_ISOLATION:
447 // validate 'value'
448 if( (SQLUINTEGER) value == SQL_TXN_READ_UNCOMMITTED )
449 isolationLevel_ = READ_UNCOMMITTED;
450 else if( (SQLUINTEGER) value == SQL_TXN_READ_COMMITTED )
451 isolationLevel_ = READ_COMMITTED;
452 else if( (SQLUINTEGER) value == SQL_TXN_REPEATABLE_READ )
453 isolationLevel_ = READ_REPEATABLE;
454 // else if( (SQLUINTEGER) value == SQL_TXN_SERIALIZABLE )
455 // isolationLevel_ = SERIALIZABLE;
456 else
457 return( SQL_ERROR );
459 break;
460 case SQL_ATTR_AUTOCOMMIT:
461 autoCommit_ = (SQLUINTEGER) value;
462 if( state_ == C6 )
463 SQLEndTran( SQL_COMMIT );
464 break;
466 default: err_.set( ERROR_OPTRANGE );
467 return( SQL_ERROR );
470 return( SQL_SUCCESS );
473 SQLRETURN SQLGetConnectOption(
474 SQLHDBC ConnectionHandle,
475 SQLUSMALLINT Option,
476 SQLPOINTER Value)
478 return( SQLGetConnectAttr( ConnectionHandle, Option, Value, 0, 0) );
481 SQLRETURN SQLGetConnectAttr(
482 SQLHDBC ConnectionHandle,
483 SQLINTEGER Attribute,
484 SQLPOINTER Value,
485 SQLINTEGER BufferLength,
486 SQLINTEGER *StringLength)
488 // Validate handle
489 if( isValidHandle( ConnectionHandle, SQL_HANDLE_DBC ) != SQL_SUCCESS )
490 return( SQL_INVALID_HANDLE );
492 return( ((CSqlOdbcDbc*)ConnectionHandle)->SQLGetConnectAttr( Attribute, Value, BufferLength, StringLength ) );
495 SQLRETURN CSqlOdbcDbc::SQLGetConnectAttr(
496 SQLINTEGER attribute,
497 SQLPOINTER value,
498 SQLINTEGER bufferLength,
499 SQLINTEGER *stringLength)
501 // Start with NO_ERR
502 err_.set( NO_ERR );
504 switch( attribute )
506 case SQL_ATTR_ACCESS_MODE:
507 // Get ODBC Access Mode
508 if( accessMode_ == ACCESSMODE_READ_ONLY )
509 *((SQLUINTEGER*) value) = SQL_MODE_READ_ONLY;
510 else if( accessMode_ == ACCESSMODE_READ_WRITE )
511 *((SQLUINTEGER*) value) = SQL_MODE_READ_WRITE;
512 else
513 return( SQL_ERROR );
515 break;
516 case SQL_DEFAULT_TXN_ISOLATION:
517 case SQL_ATTR_TXN_ISOLATION:
518 // validate 'value'
519 if( (SQLUINTEGER) isolationLevel_ == READ_UNCOMMITTED )
520 *((SQLUINTEGER*) value) = SQL_TXN_READ_UNCOMMITTED;
521 else if( (SQLUINTEGER) isolationLevel_ == READ_COMMITTED )
522 *((SQLUINTEGER*) value) = SQL_TXN_READ_COMMITTED;
523 else if( (SQLUINTEGER) isolationLevel_ == READ_REPEATABLE )
524 *((SQLUINTEGER*) value) = SQL_TXN_REPEATABLE_READ;
525 // else if( (SQLUINTEGER) isolationLevel_ == SERIALIZABLE )
526 // *((SQLUINTEGER*) value) = SQL_TXN_SERIALIZABLE;
527 else
528 return( SQL_ERROR );
530 break;
531 case SQL_ATTR_AUTOCOMMIT:
532 *((SQLUINTEGER*) value) = autoCommit_;
533 break;
535 default: err_.set( ERROR_OPTRANGE );
536 return( SQL_ERROR );
539 return( SQL_SUCCESS );
542 /*SQLRETURN SQLGetFunctions(
543 SQLHDBC ConnectionHandle,
544 SQLUSMALLINT FunctionId,
545 SQLUSMALLINT * SupportedPtr)
547 if( isValidHandle( ConnectionHandle, SQL_HANDLE_DBC ) != SQL_SUCCESS )
548 return( SQL_INVALID_HANDLE );
549 return( ((CSqlOdbcDbc*)ConnectionHandle)->SQLGetFunctions(FunctionId,SupportedPtr) );
552 SQLRETURN CSqlOdbcDbc::SQLGetFunctions(
553 SQLUSMALLINT FunctionId,
554 SQLUSMALLINT * SupportedPtr)
556 if (NULL == SupportedPtr)
558 err_.set(ERROR_INVARGVAL);
559 return (SQL_ERROR);
561 if(isFunctionSupports(FunctionId))
562 *SupportedPtr = SQL_TRUE ;
563 else
564 *SupportedPtr = SQL_FALSE;
565 return (SQL_SUCCESS);
570 SQLRETURN SQLGetInfo(
571 SQLHDBC ConnectionHandle,
572 SQLUSMALLINT InfoType,
573 SQLPOINTER InfoValuePtr,
574 SQLSMALLINT BufferLength,
575 SQLSMALLINT * StringLengthPtr)
577 if( isValidHandle( ConnectionHandle, SQL_HANDLE_DBC ) != SQL_SUCCESS )
578 return( SQL_INVALID_HANDLE );
580 return( ((CSqlOdbcDbc*)ConnectionHandle)->SQLGetInfo( InfoType,InfoValuePtr,BufferLength,StringLengthPtr ) );
584 SQLRETURN CSqlOdbcDbc::SQLGetInfo(
585 SQLUSMALLINT InfoType,
586 SQLPOINTER InfoValuePtr,
587 SQLSMALLINT BufferLength,
588 SQLSMALLINT * StringLengthPtr)
590 return (SQL_SUCCESS);