blob: a74172d987c8b20058ffb67e235a781a61fe2644 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// ----------------------------------------------------------------------------
//
// File: KO_ALLOC.CPP
//
// Notes: Contains function for managing allocation and release
// of the three structures/handles - Environment,
// Connection and Statement. Statements r
// encapsulated inside connection while all connections
// inside environment
//
// Exported functions:
// SQLAllocEnv
// SQLAllocConnect
// SQLAllocConnect
// SQLAllocStmt
// SQLAllocHandle
// SQLFreeStmt
// SQLDisconnect
// SQLFreeConnect
// SQLFreeHandle
// SQLFreeEnv
// ----------------------------------------------------------------------------
#include "stdafx.h"
// --------------------------- local functions --------------------------------
static eGoodBad _SQLAttachStmt ( pODBCConn pConn, pODBCStmt pStmt );
static eGoodBad _SQLDetachStmt ( pODBCConn pConn, pODBCStmt pStmt );
static RETCODE SQL_API _SQLFreeStmtResult ( pODBCStmt pHandle );
static RETCODE SQL_API _SQLFreeStmtCols ( pODBCStmt pHandle );
static RETCODE SQL_API _SQLFreeStmtParams ( pODBCStmt pHandle );
static RETCODE SQL_API _SQLFreeStmtAll ( pODBCStmt pHandle );
static RETCODE SQL_API _SQLFreeStmts ( pODBCStmt pHandle );
static eGoodBad _SQLAttachConn ( pODBCEnv pEnv, pODBCConn pConn );
static eGoodBad _SQLDetachConn ( pODBCEnv pEnv, pODBCConn pConn );
static RETCODE SQL_API _SQLFreeConnect ( pODBCConn pHandle );
static RETCODE SQL_API _SQLFreeConnects ( pODBCConn pHandle );
static RETCODE SQL_API _SQLFreeEnv ( pODBCEnv pHandle );
// -----------------------------------------------------------------------
// to allocate a environment
// -----------------------------------------------------------------------
RETCODE SQL_API SQLAllocEnv ( HENV* pOutputHandlePtr ) {
__ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "SQLAllocEnv called" ) );
pODBCEnv env = NULL;
// precaution
if ( pOutputHandlePtr == 0 ) {
__ODBCPOPMSG ( _ODBCPopMsg ( "SQLAllocEnv - bad params" ) );
return SQL_ERROR;
}
// initializations
*pOutputHandlePtr = 0;
// allocate an env
env = new ODBCEnv;
// clear the env attributes
memset ( env, 0, sizeof ( ODBCEnv ) );
// set the handle signature
( ( pODBCEnv ) env )->Sign = SQL_HANDLE_ENV;
// default values
( ( pODBCEnv ) env )->AttrODBCVersion =
SQL_OV_ODBC3; // SQL_ATTR_ODBC_VERSION 200
( ( pODBCEnv ) env )->AttrConnPooling =
SQL_CP_OFF; // SQL_ATTR_CONNECTION_POOLING 201
( ( pODBCEnv ) env )->AttrCPMatch =
SQL_CP_STRICT_MATCH; // SQL_ATTR_CP_MATCH 202
( ( pODBCEnv ) env )->AttrOutputNTS = SQL_TRUE; // SQL_ATTR_OUTPUT_NTS
// pass back to caller
*pOutputHandlePtr = ( HENV ) env;
return SQL_SUCCESS;
}
// -----------------------------------------------------------------------
// to allocate a connection
// -----------------------------------------------------------------------
RETCODE SQL_API SQLAllocConnect ( HENV pEnvHandle, HDBC* pOutputHandlePtr ) {
__ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "SQLAllocConnect called" ) );
pODBCConn conn;
__CHK_HANDLE ( pEnvHandle, SQL_HANDLE_ENV, SQL_ERROR );
_SQLFreeDiag ( _DIAGENV ( pEnvHandle ) );
// precaution
if ( pOutputHandlePtr == 0 ) {
__ODBCPOPMSG ( _ODBCPopMsg ( "SQLAllocConnect - bad params" ) );
return SQL_ERROR;
}
// initializations
*pOutputHandlePtr = 0;
// allocate a conn
conn = new ODBCConn;
// clear the conn attributes
memset ( conn, 0, sizeof ( ODBCConn ) );
// set the handle signature
( ( pODBCConn ) conn )->Sign = SQL_HANDLE_DBC;
// default values
( ( pODBCConn ) conn )->AccessMode = SQL_MODE_READ_ONLY;
( ( pODBCConn ) conn )->AutoIPD = SQL_FALSE;
( ( pODBCConn ) conn )->AsyncEnable = SQL_ASYNC_ENABLE_OFF;
( ( pODBCConn ) conn )->AutoCommit = SQL_AUTOCOMMIT_ON;
( ( pODBCConn ) conn )->TimeOut = 0;
( ( pODBCConn ) conn )->LoginTimeOut = 0;
( ( pODBCConn ) conn )->MetaDataID = SQL_FALSE;
( ( pODBCConn ) conn )->ODBCCursors = SQL_CUR_USE_DRIVER;
( ( pODBCConn ) conn )->Window = NULL;
( ( pODBCConn ) conn )->TxnIsolation = 0;
( ( pODBCConn ) conn )->MaxRows = 0;
( ( pODBCConn ) conn )->QueryTimeout = 0;
// attach it to link list
_SQLAttachConn ( ( pODBCEnv ) pEnvHandle, conn );
// pass back conn to caller
*pOutputHandlePtr = ( HDBC ) conn;
return SQL_SUCCESS;
}
// -----------------------------------------------------------------------
// to allocate a statement
// -----------------------------------------------------------------------
RETCODE SQL_API SQLAllocStmt ( HDBC pConnHandle, HSTMT* pOutputHandlePtr ) {
__ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "SQLAllocStmt called" ) );
pODBCStmt stmt = NULL;
__CHK_HANDLE ( pConnHandle, SQL_HANDLE_DBC, SQL_ERROR );
_SQLFreeDiag ( _DIAGCONN ( pConnHandle ) );
// precaution
if ( pOutputHandlePtr == 0 ) {
__ODBCPOPMSG ( _ODBCPopMsg ( "SQLAllocStmt - bad params" ) );
return SQL_ERROR;
}
// initializations
*pOutputHandlePtr = 0;
// allocate a stmt
stmt = new ODBCStmt;
// clear the stmt attributes
memset ( stmt, 0, sizeof ( ODBCStmt ) );
// set the handle signature
( ( pODBCStmt ) stmt )->Sign = SQL_HANDLE_STMT;
// default values
( ( pODBCStmt ) stmt )->AsyncEnable = SQL_ASYNC_ENABLE_OFF;
( ( pODBCStmt ) stmt )->Concurrency = SQL_CONCUR_READ_ONLY;
( ( pODBCStmt ) stmt )->CursorScroll = SQL_NONSCROLLABLE;
( ( pODBCStmt ) stmt )->CursorSensitivity = SQL_UNSPECIFIED;
( ( pODBCStmt ) stmt )->CursorType = SQL_CURSOR_FORWARD_ONLY;
( ( pODBCStmt ) stmt )->AutoIPD = SQL_FALSE;
( ( pODBCStmt ) stmt )->KeysetSize = 0;
( ( pODBCStmt ) stmt )->MetaDataID = SQL_FALSE;
( ( pODBCStmt ) stmt )->NoScan = SQL_NOSCAN_OFF;
( ( pODBCStmt ) stmt )->QryTimeout = 0;
( ( pODBCStmt ) stmt )->RetrieveData = SQL_RD_DEFAULT;
// set descriptor defaults
_SQLSetARDFieldsDefault ( & ( ( ( pODBCStmt ) stmt )->ARD ), ( pODBCStmt ) stmt );
_SQLSetAPDFieldsDefault ( & ( ( ( pODBCStmt ) stmt )->APD ), ( pODBCStmt ) stmt );
_SQLSetIRDFieldsDefault ( & ( ( ( pODBCStmt ) stmt )->IRD ), ( pODBCStmt ) stmt );
_SQLSetIPDFieldsDefault ( & ( ( ( pODBCStmt ) stmt )->IPD ), ( pODBCStmt ) stmt );
// attach it to link list
_SQLAttachStmt ( ( pODBCConn ) pConnHandle, stmt );
// pass back to caller
*pOutputHandlePtr = ( HSTMT ) stmt;
// ???? debug log message
__ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "New stmt: %d", stmt ) );
return SQL_SUCCESS;
}
// -----------------------------------------------------------------------
// to allocate a handle for env, conn or stmt
// -----------------------------------------------------------------------
RETCODE SQL_API SQLAllocHandle ( SQLSMALLINT pHandleType, SQLHANDLE pInputHandle, SQLHANDLE* pOutputHandlePtr ) {
__ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "SQLAllocHandle called" ) );
switch ( pHandleType ) {
case SQL_HANDLE_ENV:
return SQLAllocEnv ( pOutputHandlePtr ); // allocate environment
case SQL_HANDLE_DBC:
return SQLAllocConnect ( pInputHandle, pOutputHandlePtr ); // allocate connection
case SQL_HANDLE_STMT:
return SQLAllocStmt ( pInputHandle, pOutputHandlePtr ); // allocate statement
case SQL_HANDLE_DESC:
__ODBCPOPMSG ( _ODBCPopMsg ( "SQLAllocHandle - Explicit descriptor requested - not supported" ) );
return SQL_ERROR; // allocate a descriptor
}
return SQL_ERROR;
}
// -----------------------------------------------------------------------
// to free an existing statement handle
// -----------------------------------------------------------------------
RETCODE SQL_API SQLFreeStmt ( SQLHSTMT pStmt, SQLUSMALLINT pOption ) {
__ODBCLOG ( _ODBCLogMsg ( LogLevel_INFO, "SQLFreeStmt called, %d with option %d", pStmt, pOption ) );
__CHK_HANDLE ( pStmt, SQL_HANDLE_STMT, SQL_ERROR );
_SQLFreeDiag ( _DIAGSTMT ( pStmt ) );
// check the operation to perform
switch ( pOption ) {
case SQL_UNBIND:
__ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "SQLFreeStmt called for Col bindings" ) );
return _SQLFreeStmtCols ( ( pODBCStmt ) pStmt );
case SQL_RESET_PARAMS:
__ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "SQLFreeStmt called for params" ) );
return _SQLFreeStmtParams ( ( pODBCStmt ) pStmt );
default: // include SQL_CLOSE:
__ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "SQLFreeStmt called for Result" ) );
return _SQLFreeStmtResult ( ( pODBCStmt ) pStmt );
}
}
// -----------------------------------------------------------------------
// to disconnect from sever is a state is maintained on a connection
// -----------------------------------------------------------------------
RETCODE SQL_API SQLDisconnect ( HDBC pHandle ) {
__ODBCLOG ( _ODBCLogMsg ( LogLevel_INFO, "SQLDisconnect called" ) );
__CHK_HANDLE ( pHandle, SQL_HANDLE_DBC, SQL_ERROR );
_SQLFreeDiag ( _DIAGCONN ( pHandle ) );
// free the connection
RETCODE code = _SQLDisconnect ( ( pODBCConn ) pHandle );
__ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "SQLDisconnect exited" ) );
return code;
}
// -----------------------------------------------------------------------
// to free an existing connection handle
// -----------------------------------------------------------------------
RETCODE SQL_API SQLFreeConnect ( HDBC pHandle ) {
__ODBCLOG ( _ODBCLogMsg ( LogLevel_INFO, "SQLFreeConnect called" ) );
__CHK_HANDLE ( pHandle, SQL_HANDLE_DBC, SQL_ERROR );
// free the connection
RETCODE code = _SQLFreeConnect ( ( pODBCConn ) pHandle );
__ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "SQLFreeConnect Exited" ) );
return code;
}
// -----------------------------------------------------------------------
// to free an existing environment handle
// -----------------------------------------------------------------------
RETCODE SQL_API SQLFreeEnv ( HENV pHandle ) {
__ODBCLOG ( _ODBCLogMsg ( LogLevel_INFO, "SQLFreeEnv called" ) );
__CHK_HANDLE ( pHandle, SQL_HANDLE_ENV, SQL_ERROR );
// free the env
return _SQLFreeEnv ( ( pODBCEnv ) pHandle );
}
// -----------------------------------------------------------------------
// to free an environment, connection or stmt
// -----------------------------------------------------------------------
RETCODE SQL_API SQLFreeHandle ( SQLSMALLINT pHandleType, SQLHANDLE pHandle ) {
__ODBCLOG ( _ODBCLogMsg ( LogLevel_INFO, "SQLFreeHandle called, Handle Type: %d, Handle: %d", pHandleType,
( Long ) pHandle ) );
__CHK_HANDLE ( pHandle, pHandleType, SQL_ERROR );
// as per the handle type
switch ( pHandleType ) {
case SQL_HANDLE_ENV:
return _SQLFreeEnv ( ( pODBCEnv ) pHandle ); // free environment
case SQL_HANDLE_DBC:
return _SQLFreeConnect ( ( pODBCConn ) pHandle ); // free conenction
case SQL_HANDLE_STMT:
return _SQLFreeStmtAll ( ( pODBCStmt ) pHandle ); // free statement
case SQL_HANDLE_DESC:
__ODBCPOPMSG ( _ODBCPopMsg ( "SQLFreeHandle called for descriptor" ) );
return SQL_ERROR; // free descriptor
}
return SQL_ERROR;
}
// -----------------------------------------------------------------------
// to attach a new stmt to STMT link list in CONN
// -----------------------------------------------------------------------
static eGoodBad _SQLAttachStmt ( pODBCConn pConn, pODBCStmt pStmt ) {
pODBCStmt l;
// precaution
if ( pConn == NULL || pStmt == NULL )
{ return BAD; }
// set conn as stmt container
pStmt->Conn = pConn;
// check if this is the first item
if ( pConn->Stmts == NULL ) {
// set as first and only item
pConn->Stmts = pStmt;
pStmt->Prev = NULL;
pStmt->Next = NULL;
return GOOD;
}
// move to tail item
for ( l = pConn->Stmts; l->Next != NULL; l = l->Next );
// attach to tail
l->Next = pStmt;
pStmt->Prev = l;
pStmt->Next = NULL;
return GOOD;
}
// -----------------------------------------------------------------------
// to detach an existing stmt from link list
// -----------------------------------------------------------------------
static eGoodBad _SQLDetachStmt ( pODBCConn pConn, pODBCStmt pStmt ) {
// precaution
if ( pConn == NULL || pStmt == NULL )
{ return BAD; }
if ( pStmt->Prev )
{ ( pStmt->Prev )->Next = pStmt->Next; } // attach prev to next
else
{ pConn->Stmts = pStmt->Next; } // set head to next if any
if ( pStmt->Next )
{ ( pStmt->Next )->Prev = pStmt->Prev; } // set next to prev if any
return GOOD;
}
// -----------------------------------------------------------------------
// free the cursor/results associated with the specified stmt
// -----------------------------------------------------------------------
static RETCODE SQL_API _SQLFreeStmtResult ( pODBCStmt pHandle ) {
// note
// assumes handle already checked
// basic stmt
if ( pHandle->Stmt ) {
delete[] pHandle->Stmt;
pHandle->Stmt = NULL;
}
// basic stmt
pHandle->StmtLen = 0;
pHandle->Prepared = FALSE;
pHandle->CurRowsetStartRow = NULL; // start of current rowset
pHandle->CurRowsetStartRowPos = 0; // absolute position
pHandle->CurRowsetEndRow = NULL; // end of current rowset
pHandle->CurRowsetEndRowPos = 0; // absolute position
pHandle->RowCount = 0;
_SQLFreeIRDContent ( & ( pHandle->IRD ) );
return SQL_SUCCESS;
}
// -----------------------------------------------------------------------
// free all the cols bound to a specified stmt
// -----------------------------------------------------------------------
static RETCODE SQL_API _SQLFreeStmtCols ( pODBCStmt pHandle ) {
// note
// assumes handle already checked
return _SQLFreeARDContent ( & ( pHandle->ARD ) );
}
// -----------------------------------------------------------------------
// free all the params bound to a particular stmt
// -----------------------------------------------------------------------
static RETCODE SQL_API _SQLFreeStmtParams ( pODBCStmt pHandle ) {
// note always called as a sub-function so no diag reset
// to be implemented along with
// other details of parms
return _SQLFreeAPDContent ( & ( pHandle->APD ) );
}
// -----------------------------------------------------------------------
// to free the stmt itself & others associated items like ARD, APD etc
// -----------------------------------------------------------------------
static RETCODE SQL_API _SQLFreeStmtAll ( pODBCStmt pHandle ) {
_SQLFreeDiag ( _DIAGSTMT ( pHandle ) );
// note always called as a sub-function so no diag reset
pODBCConn conn;
// extract the container connection
conn = pHandle->Conn;
// check if valid
if ( conn == NULL )
{ return SQL_ERROR; }
// pluck from link-list
_SQLDetachStmt ( conn, pHandle );
// clear/free results
_SQLFreeStmtResult ( pHandle );
// clear/free col bindings
_SQLFreeStmtCols ( pHandle );
// clear/free parms bindings
_SQLFreeStmtParams ( pHandle );
// now free the structure itself
delete pHandle;
return SQL_SUCCESS;
}
// -----------------------------------------------------------------------
// to all the stmts starting from the specified stmt
// -----------------------------------------------------------------------
static RETCODE SQL_API _SQLFreeStmts ( pODBCStmt pHandle ) {
pODBCStmt t, n;
// loop to iterate the list
for ( n = pHandle; n != NULL; ) {
t = n;
n = n->Next;
_SQLFreeStmtAll ( t );
}
return SQL_SUCCESS;
}
// -----------------------------------------------------------------------
// to attach a new conn to CONN link list in ENV
// -----------------------------------------------------------------------
static eGoodBad _SQLAttachConn ( pODBCEnv pEnv, pODBCConn pConn ) {
pODBCConn l;
// precaution
if ( pEnv == NULL || pConn == NULL )
{ return BAD; }
// set env as container for conn
pConn->Env = pEnv;
// check if this is the first item
if ( pEnv->Conns == NULL ) {
// set as first and only item
pEnv->Conns = pConn;
pConn->Prev = NULL;
pConn->Next = NULL;
return GOOD;
}
// move to tail item
for ( l = pEnv->Conns; l->Next != NULL; l = l->Next );
// attach to tail
l->Next = pConn;
pConn->Prev = l;
pConn->Next = NULL;
return GOOD;
}
// -----------------------------------------------------------------------
// to detach an existing item from ARD link-list
// -----------------------------------------------------------------------
static eGoodBad _SQLDetachConn ( pODBCEnv pEnv, pODBCConn pConn ) {
// precaution
if ( pEnv == NULL || pConn == NULL )
{ return BAD; }
if ( pConn->Prev )
{ ( pConn->Prev )->Next = pConn->Next; } // attach prev to next
else
{ pEnv->Conns = pConn->Next; } // set head to next if any
if ( pConn->Next )
{ ( pConn->Next )->Prev = pConn->Prev; } // set next to prev if any
return GOOD;
}
// -----------------------------------------------------------------------
// to free all info associated with a connection but not the conenction itself
// -----------------------------------------------------------------------
RETCODE SQL_API _SQLDisconnect ( pODBCConn pHandle ) {
pHandle->IsConnected = FALSE;
if ( pHandle->ConnectStr ) {
delete[] pHandle->ConnectStr;
pHandle->ConnectStr = NULL;
}
if ( pHandle->Server ) {
delete[] pHandle->Server;
pHandle->Server = NULL;
}
if ( pHandle->Project ) {
delete[] pHandle->Project;
pHandle->Project = NULL;
}
if ( pHandle->UserName ) {
delete[] pHandle->UserName;
pHandle->UserName = NULL;
}
if ( pHandle->Password ) {
delete[] pHandle->Password;
pHandle->Password = NULL;
}
// free all associated statements
if ( pHandle->Stmts ) { // all stmts within connection
_SQLFreeStmts ( pHandle->Stmts );
pHandle->Stmts = NULL;
}
//free meta
if ( pHandle->meta ) {
pHandle->meta = NULL;
}
return SQL_SUCCESS;
}
// -----------------------------------------------------------------------
// to free a specifed connection, plucks from parent/list AND FREEs it
// -----------------------------------------------------------------------
static RETCODE SQL_API _SQLFreeConnect ( pODBCConn pHandle ) {
_SQLFreeDiag ( _DIAGCONN ( pHandle ) );
pODBCEnv env;
// disconnect
_SQLDisconnect ( pHandle );
// extract the container environment
env = pHandle->Env;
// check if valid
if ( env == NULL ) { return SQL_ERROR; }
// detach from link list
_SQLDetachConn ( env, pHandle );
// now free the structure itself
delete pHandle;
// reset
pHandle = NULL;
return SQL_SUCCESS;
}
// -----------------------------------------------------------------------
// to all the connections starting from the specified connection
// -----------------------------------------------------------------------
static RETCODE SQL_API _SQLFreeConnects ( pODBCConn pHandle ) {
pODBCConn t, n;
// loop to iterate the list of connections
for ( n = pHandle; n != NULL; ) {
t = n; // save
n = n->Next; // get next
_SQLFreeConnect ( t ); // free saved
}
return SQL_SUCCESS;
}
// -----------------------------------------------------------------------
// to free the specified env
// -----------------------------------------------------------------------
static RETCODE SQL_API _SQLFreeEnv ( pODBCEnv pHandle ) {
// free diags if any
_SQLFreeDiag ( _DIAGENV ( pHandle ) );
// check if any connections are allocated
if ( pHandle->Conns ) {
//_SQLFreeConnects ( pHandle->Conns ); // relase all connections
}
delete pHandle;
return SQL_SUCCESS;
}