Back to index

openldap  2.4.31
Defines | Functions | Variables
sql-wrap.c File Reference
#include "portable.h"
#include <stdio.h>
#include "ac/string.h"
#include <sys/types.h>
#include "slap.h"
#include "proto-sql.h"

Go to the source code of this file.

Defines

#define MAX_ATTR_LEN   16384

Functions

void backsql_PrintErrors (SQLHENV henv, SQLHDBC hdbc, SQLHSTMT sth, int rc)
RETCODE backsql_Prepare (SQLHDBC dbh, SQLHSTMT *sth, const char *query, int timeout)
RETCODE backsql_BindRowAsStrings_x (SQLHSTMT sth, BACKSQL_ROW_NTS *row, void *ctx)
RETCODE backsql_BindRowAsStrings (SQLHSTMT sth, BACKSQL_ROW_NTS *row)
RETCODE backsql_FreeRow_x (BACKSQL_ROW_NTS *row, void *ctx)
RETCODE backsql_FreeRow (BACKSQL_ROW_NTS *row)
static void backsql_close_db_handle (SQLHDBC dbh)
int backsql_conn_destroy (backsql_info *bi)
int backsql_init_db_env (backsql_info *bi)
int backsql_free_db_env (backsql_info *bi)
static int backsql_open_db_handle (backsql_info *bi, SQLHDBC *dbhp)
static void backsql_db_conn_keyfree (void *key, void *data)
int backsql_free_db_conn (Operation *op, SQLHDBC dbh)
int backsql_get_db_conn (Operation *op, SQLHDBC *dbhp)

Variables

static voidbacksql_db_conn_dummy

Define Documentation

#define MAX_ATTR_LEN   16384

Definition at line 33 of file sql-wrap.c.


Function Documentation

RETCODE backsql_BindRowAsStrings ( SQLHSTMT  sth,
BACKSQL_ROW_NTS row 
)

Definition at line 280 of file sql-wrap.c.

{
       return backsql_BindRowAsStrings_x( sth, row, NULL );
}

Here is the call graph for this function:

Here is the caller graph for this function:

RETCODE backsql_BindRowAsStrings_x ( SQLHSTMT  sth,
BACKSQL_ROW_NTS row,
void ctx 
)

Definition at line 127 of file sql-wrap.c.

{
       RETCODE              rc;

       if ( row == NULL ) {
              return SQL_ERROR;
       }

#ifdef BACKSQL_TRACE
       Debug( LDAP_DEBUG_TRACE, "==> backsql_BindRowAsStrings()\n", 0, 0, 0 );
#endif /* BACKSQL_TRACE */
       
       rc = SQLNumResultCols( sth, &row->ncols );
       if ( rc != SQL_SUCCESS ) {
#ifdef BACKSQL_TRACE
              Debug( LDAP_DEBUG_TRACE, "backsql_BindRowAsStrings(): "
                     "SQLNumResultCols() failed:\n", 0, 0, 0 );
#endif /* BACKSQL_TRACE */
              
              backsql_PrintErrors( SQL_NULL_HENV, SQL_NULL_HDBC, sth, rc );

       } else {
              SQLCHAR              colname[ 64 ];
              SQLSMALLINT   name_len, col_type, col_scale, col_null;
              SQLLEN        col_prec;
              int           i;

#ifdef BACKSQL_TRACE
              Debug( LDAP_DEBUG_TRACE, "backsql_BindRowAsStrings: "
                     "ncols=%d\n", (int)row->ncols, 0, 0 );
#endif /* BACKSQL_TRACE */

              row->col_names = (BerVarray)ber_memcalloc_x( row->ncols + 1, 
                            sizeof( struct berval ), ctx );
              if ( row->col_names == NULL ) {
                     goto nomem;
              }

              row->col_prec = (UDWORD *)ber_memcalloc_x( row->ncols,
                            sizeof( UDWORD ), ctx );
              if ( row->col_prec == NULL ) {
                     goto nomem;
              }

              row->col_type = (SQLSMALLINT *)ber_memcalloc_x( row->ncols,
                            sizeof( SQLSMALLINT ), ctx );
              if ( row->col_type == NULL ) {
                     goto nomem;
              }

              row->cols = (char **)ber_memcalloc_x( row->ncols + 1, 
                            sizeof( char * ), ctx );
              if ( row->cols == NULL ) {
                     goto nomem;
              }

              row->value_len = (SQLLEN *)ber_memcalloc_x( row->ncols,
                            sizeof( SQLLEN ), ctx );
              if ( row->value_len == NULL ) {
                     goto nomem;
              }

              if ( 0 ) {
nomem:
                     ber_memfree_x( row->col_names, ctx );
                     row->col_names = NULL;
                     ber_memfree_x( row->col_prec, ctx );
                     row->col_prec = NULL;
                     ber_memfree_x( row->col_type, ctx );
                     row->col_type = NULL;
                     ber_memfree_x( row->cols, ctx );
                     row->cols = NULL;
                     ber_memfree_x( row->value_len, ctx );
                     row->value_len = NULL;

                     Debug( LDAP_DEBUG_ANY, "backsql_BindRowAsStrings: "
                            "out of memory\n", 0, 0, 0 );

                     return LDAP_NO_MEMORY;
              }

              for ( i = 0; i < row->ncols; i++ ) {
                     SQLSMALLINT   TargetType;

                     rc = SQLDescribeCol( sth, (SQLSMALLINT)(i + 1), &colname[ 0 ],
                                   (SQLUINTEGER)( sizeof( colname ) - 1 ),
                                   &name_len, &col_type,
                                   &col_prec, &col_scale, &col_null );
                     /* FIXME: test rc? */

                     ber_str2bv_x( (char *)colname, 0, 1,
                                   &row->col_names[ i ], ctx );
#ifdef BACKSQL_TRACE
                     Debug( LDAP_DEBUG_TRACE, "backsql_BindRowAsStrings: "
                            "col_name=%s, col_prec[%d]=%d\n",
                            colname, (int)(i + 1), (int)col_prec );
#endif /* BACKSQL_TRACE */
                     if ( col_type != SQL_CHAR && col_type != SQL_VARCHAR )
                     {
                            col_prec = MAX_ATTR_LEN;
                     }

                     row->cols[ i ] = (char *)ber_memcalloc_x( col_prec + 1,
                                   sizeof( char ), ctx );
                     row->col_prec[ i ] = col_prec;
                     row->col_type[ i ] = col_type;

                     /*
                      * ITS#3386, ITS#3113 - 20070308
                      * Note: there are many differences between various DPMS and ODBC
                      * Systems; some support SQL_C_BLOB, SQL_C_BLOB_LOCATOR.  YMMV:
                      * This has only been tested on Linux/MySQL/UnixODBC
                      * For BINARY-type Fields (BLOB, etc), read the data as BINARY
                      */
                     if ( BACKSQL_IS_BINARY( col_type ) ) {
#ifdef BACKSQL_TRACE
                            Debug( LDAP_DEBUG_TRACE, "backsql_BindRowAsStrings: "
                                   "col_name=%s, col_type[%d]=%d: reading binary data\n",
                                   colname, (int)(i + 1), (int)col_type);
#endif /* BACKSQL_TRACE */
                            TargetType = SQL_C_BINARY;

                     } else {
                            /* Otherwise read it as Character data */
#ifdef BACKSQL_TRACE
                            Debug( LDAP_DEBUG_TRACE, "backsql_BindRowAsStrings: "
                                   "col_name=%s, col_type[%d]=%d: reading character data\n",
                                   colname, (int)(i + 1), (int)col_type);
#endif /* BACKSQL_TRACE */
                            TargetType = SQL_C_CHAR;
                     }

                     rc = SQLBindCol( sth, (SQLUSMALLINT)(i + 1),
                             TargetType,
                             (SQLPOINTER)row->cols[ i ],
                             col_prec + 1,
                             &row->value_len[ i ] );

                     /* FIXME: test rc? */
              }

              BER_BVZERO( &row->col_names[ i ] );
              row->cols[ i ] = NULL;
       }

#ifdef BACKSQL_TRACE
       Debug( LDAP_DEBUG_TRACE, "<== backsql_BindRowAsStrings()\n", 0, 0, 0 );
#endif /* BACKSQL_TRACE */

       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void backsql_close_db_handle ( SQLHDBC  dbh) [static]

Definition at line 309 of file sql-wrap.c.

{
       if ( dbh == SQL_NULL_HDBC ) {
              return;
       }

       Debug( LDAP_DEBUG_TRACE, "==>backsql_close_db_handle(%p)\n",
              (void *)dbh, 0, 0 );

       /*
        * Default transact is SQL_ROLLBACK; commit is required only
        * by write operations, and it is explicitly performed after
        * each atomic operation succeeds.
        */

       /* TimesTen */
       SQLTransact( SQL_NULL_HENV, dbh, SQL_ROLLBACK );
       SQLDisconnect( dbh );
       SQLFreeConnect( dbh );

       Debug( LDAP_DEBUG_TRACE, "<==backsql_close_db_handle(%p)\n",
              (void *)dbh, 0, 0 );
}

Here is the caller graph for this function:

Definition at line 334 of file sql-wrap.c.

{
       return 0;
}

Here is the caller graph for this function:

static void backsql_db_conn_keyfree ( void key,
void data 
) [static]

Definition at line 469 of file sql-wrap.c.

{
       (void)backsql_close_db_handle( (SQLHDBC)data );
}

Here is the call graph for this function:

Here is the caller graph for this function:

int backsql_free_db_conn ( Operation op,
SQLHDBC  dbh 
)

Definition at line 477 of file sql-wrap.c.

{
       Debug( LDAP_DEBUG_TRACE, "==>backsql_free_db_conn()\n", 0, 0, 0 );

       (void)backsql_close_db_handle( dbh );
       ldap_pvt_thread_pool_setkey( op->o_threadctx,
              &backsql_db_conn_dummy, (void *)SQL_NULL_HDBC,
              backsql_db_conn_keyfree, NULL, NULL );

       Debug( LDAP_DEBUG_TRACE, "<==backsql_free_db_conn()\n", 0, 0, 0 );

       return LDAP_SUCCESS;
}

Here is the call graph for this function:

Definition at line 363 of file sql-wrap.c.

{
       Debug( LDAP_DEBUG_TRACE, "==>backsql_free_db_env()\n", 0, 0, 0 );

       (void)SQLFreeEnv( bi->sql_db_env );
       bi->sql_db_env = SQL_NULL_HENV;

       /*
        * stop, if frontend waits for all threads to shutdown 
        * before calling this -- then what are we going to delete?? 
        * everything is already deleted...
        */
       Debug( LDAP_DEBUG_TRACE, "<==backsql_free_db_env()\n", 0, 0, 0 );

       return SQL_SUCCESS;
}

Here is the call graph for this function:

Here is the caller graph for this function:

RETCODE backsql_FreeRow ( BACKSQL_ROW_NTS row)

Definition at line 303 of file sql-wrap.c.

{
       return backsql_FreeRow_x( row, NULL );
}

Here is the call graph for this function:

Here is the caller graph for this function:

RETCODE backsql_FreeRow_x ( BACKSQL_ROW_NTS row,
void ctx 
)

Definition at line 286 of file sql-wrap.c.

{
       if ( row->cols == NULL ) {
              return SQL_ERROR;
       }

       ber_bvarray_free_x( row->col_names, ctx );
       ber_memfree_x( row->col_prec, ctx );
       ber_memfree_x( row->col_type, ctx );
       ber_memvfree_x( (void **)row->cols, ctx );
       ber_memfree_x( row->value_len, ctx );

       return SQL_SUCCESS;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int backsql_get_db_conn ( Operation op,
SQLHDBC *  dbhp 
)

Definition at line 492 of file sql-wrap.c.

{
       backsql_info  *bi = (backsql_info *)op->o_bd->be_private;
       int           rc = LDAP_SUCCESS;
       SQLHDBC              dbh = SQL_NULL_HDBC;

       Debug( LDAP_DEBUG_TRACE, "==>backsql_get_db_conn()\n", 0, 0, 0 );

       assert( dbhp != NULL );
       *dbhp = SQL_NULL_HDBC;

       if ( op->o_threadctx ) {
              void          *data = NULL;

              ldap_pvt_thread_pool_getkey( op->o_threadctx,
                            &backsql_db_conn_dummy, &data, NULL );
              dbh = (SQLHDBC)data;

       } else {
              dbh = bi->sql_dbh;
       }

       if ( dbh == SQL_NULL_HDBC ) {
              rc = backsql_open_db_handle( bi, &dbh );
              if ( rc != LDAP_SUCCESS ) {
                     return rc;
              }

              if ( op->o_threadctx ) {
                     void          *data = (void *)dbh;

                     ldap_pvt_thread_pool_setkey( op->o_threadctx,
                                   &backsql_db_conn_dummy, data,
                                   backsql_db_conn_keyfree, NULL, NULL );

              } else {
                     bi->sql_dbh = dbh;
              }
       }

       *dbhp = dbh;

       Debug( LDAP_DEBUG_TRACE, "<==backsql_get_db_conn()\n", 0, 0, 0 );

       return LDAP_SUCCESS;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 341 of file sql-wrap.c.

{
       RETCODE              rc;
       int           ret = SQL_SUCCESS;
       
       Debug( LDAP_DEBUG_TRACE, "==>backsql_init_db_env()\n", 0, 0, 0 );

       rc = SQLAllocEnv( &bi->sql_db_env );
       if ( rc != SQL_SUCCESS ) {
              Debug( LDAP_DEBUG_TRACE, "init_db_env: SQLAllocEnv failed:\n",
                            0, 0, 0 );
              backsql_PrintErrors( SQL_NULL_HENV, SQL_NULL_HDBC,
                            SQL_NULL_HENV, rc );
              ret = SQL_ERROR;
       }

       Debug( LDAP_DEBUG_TRACE, "<==backsql_init_db_env()=%d\n", ret, 0, 0 );

       return ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int backsql_open_db_handle ( backsql_info bi,
SQLHDBC *  dbhp 
) [static]

Definition at line 381 of file sql-wrap.c.

{
       /* TimesTen */
       char                 DBMSName[ 32 ];
       int                  rc;

       assert( dbhp != NULL );
       *dbhp = SQL_NULL_HDBC;
 
       Debug( LDAP_DEBUG_TRACE, "==>backsql_open_db_handle()\n",
              0, 0, 0 );

       rc = SQLAllocConnect( bi->sql_db_env, dbhp );
       if ( !BACKSQL_SUCCESS( rc ) ) {
              Debug( LDAP_DEBUG_TRACE, "backsql_open_db_handle(): "
                     "SQLAllocConnect() failed:\n",
                     0, 0, 0 );
              backsql_PrintErrors( bi->sql_db_env, SQL_NULL_HDBC,
                     SQL_NULL_HENV, rc );
              return LDAP_UNAVAILABLE;
       }

       rc = SQLConnect( *dbhp,
              (SQLCHAR*)bi->sql_dbname, SQL_NTS,
              (SQLCHAR*)bi->sql_dbuser, SQL_NTS,
              (SQLCHAR*)bi->sql_dbpasswd, SQL_NTS );
       if ( rc != SQL_SUCCESS ) {
              Debug( LDAP_DEBUG_TRACE, "backsql_open_db_handle(): "
                     "SQLConnect() to database \"%s\" %s.\n",
                     bi->sql_dbname,
                     rc == SQL_SUCCESS_WITH_INFO ?
                            "succeeded with info" : "failed",
                     0 );
              backsql_PrintErrors( bi->sql_db_env, *dbhp, SQL_NULL_HENV, rc );
              if ( rc != SQL_SUCCESS_WITH_INFO ) {
                     SQLFreeConnect( *dbhp );
                     return LDAP_UNAVAILABLE;
              }
       }

       /* 
        * TimesTen : Turn off autocommit.  We must explicitly
        * commit any transactions. 
        */
       SQLSetConnectOption( *dbhp, SQL_AUTOCOMMIT,
              BACKSQL_AUTOCOMMIT_ON( bi ) ?  SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF );

       /* 
        * See if this connection is to TimesTen.  If it is,
        * remember that fact for later use.
        */
       /* Assume until proven otherwise */
       bi->sql_flags &= ~BSQLF_USE_REVERSE_DN;
       DBMSName[ 0 ] = '\0';
       rc = SQLGetInfo( *dbhp, SQL_DBMS_NAME, (PTR)&DBMSName,
                     sizeof( DBMSName ), NULL );
       if ( rc == SQL_SUCCESS ) {
              if ( strcmp( DBMSName, "TimesTen" ) == 0 ||
                     strcmp( DBMSName, "Front-Tier" ) == 0 )
              {
                     Debug( LDAP_DEBUG_TRACE, "backsql_open_db_handle(): "
                            "TimesTen database!\n",
                            0, 0, 0 );
                     bi->sql_flags |= BSQLF_USE_REVERSE_DN;
              }

       } else {
              Debug( LDAP_DEBUG_TRACE, "backsql_open_db_handle(): "
                     "SQLGetInfo() failed.\n",
                     0, 0, 0 );
              backsql_PrintErrors( bi->sql_db_env, *dbhp, SQL_NULL_HENV, rc );
              SQLDisconnect( *dbhp );
              SQLFreeConnect( *dbhp );
              return LDAP_UNAVAILABLE;
       }
       /* end TimesTen */

       Debug( LDAP_DEBUG_TRACE, "<==backsql_open_db_handle()\n",
              0, 0, 0 );

       return LDAP_SUCCESS;
}

Here is the call graph for this function:

Here is the caller graph for this function:

RETCODE backsql_Prepare ( SQLHDBC  dbh,
SQLHSTMT *  sth,
const char *  query,
int  timeout 
)

Definition at line 55 of file sql-wrap.c.

{
       RETCODE              rc;

       rc = SQLAllocStmt( dbh, sth );
       if ( rc != SQL_SUCCESS ) {
              return rc;
       }

#ifdef BACKSQL_TRACE
       Debug( LDAP_DEBUG_TRACE, "==>backsql_Prepare()\n", 0, 0, 0 );
#endif /* BACKSQL_TRACE */

#ifdef BACKSQL_MSSQL_WORKAROUND
       {
              char          drv_name[ 30 ];
              SWORD         len;

              SQLGetInfo( dbh, SQL_DRIVER_NAME, drv_name, sizeof( drv_name ), &len );

#ifdef BACKSQL_TRACE
              Debug( LDAP_DEBUG_TRACE, "backsql_Prepare(): driver name=\"%s\"\n",
                            drv_name, 0, 0 );
#endif /* BACKSQL_TRACE */

              ldap_pvt_str2upper( drv_name );
              if ( !strncmp( drv_name, "SQLSRV32.DLL", STRLENOF( "SQLSRV32.DLL" ) ) ) {
                     /*
                      * stupid default result set in MS SQL Server
                      * does not support multiple active statements
                      * on the same connection -- so we are trying 
                      * to make it not to use default result set...
                      */
                     Debug( LDAP_DEBUG_TRACE, "_SQLprepare(): "
                            "enabling MS SQL Server default result "
                            "set workaround\n", 0, 0, 0 );
                     rc = SQLSetStmtOption( *sth, SQL_CONCURRENCY, 
                                   SQL_CONCUR_ROWVER );
                     if ( rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO ) {
                            Debug( LDAP_DEBUG_TRACE, "backsql_Prepare(): "
                                   "SQLSetStmtOption(SQL_CONCURRENCY,"
                                   "SQL_CONCUR_ROWVER) failed:\n", 
                                   0, 0, 0 );
                            backsql_PrintErrors( SQL_NULL_HENV, dbh, *sth, rc );
                            SQLFreeStmt( *sth, SQL_DROP );
                            return rc;
                     }
              }
       }
#endif /* BACKSQL_MSSQL_WORKAROUND */

       if ( timeout > 0 ) {
              Debug( LDAP_DEBUG_TRACE, "_SQLprepare(): "
                     "setting query timeout to %d sec.\n", 
                     timeout, 0, 0 );
              rc = SQLSetStmtOption( *sth, SQL_QUERY_TIMEOUT, timeout );
              if ( rc != SQL_SUCCESS ) {
                     backsql_PrintErrors( SQL_NULL_HENV, dbh, *sth, rc );
                     SQLFreeStmt( *sth, SQL_DROP );
                     return rc;
              }
       }

#ifdef BACKSQL_TRACE
       Debug( LDAP_DEBUG_TRACE, "<==backsql_Prepare() calling SQLPrepare()\n",
                     0, 0, 0 );
#endif /* BACKSQL_TRACE */

       return SQLPrepare( *sth, (SQLCHAR *)query, SQL_NTS );
}

Here is the call graph for this function:

Here is the caller graph for this function:

void backsql_PrintErrors ( SQLHENV  henv,
SQLHDBC  hdbc,
SQLHSTMT  sth,
int  rc 
)

Definition at line 36 of file sql-wrap.c.

{
       SQLCHAR       msg[SQL_MAX_MESSAGE_LENGTH];              /* msg. buffer    */
       SQLCHAR       state[SQL_SQLSTATE_SIZE];          /* statement buf. */
       SDWORD iSqlCode;                          /* return code    */
       SWORD  len = SQL_MAX_MESSAGE_LENGTH - 1;  /* return length  */ 

       Debug( LDAP_DEBUG_TRACE, "Return code: %d\n", rc, 0, 0 );

       for ( ; rc = SQLError( henv, hdbc, sth, state, &iSqlCode, msg,
              SQL_MAX_MESSAGE_LENGTH - 1, &len ), BACKSQL_SUCCESS( rc ); )
       {
              Debug( LDAP_DEBUG_TRACE,
                     "   nativeErrCode=%d SQLengineState=%s msg=\"%s\"\n",
                     (int)iSqlCode, state, msg );
       }
}

Here is the caller graph for this function:


Variable Documentation

Definition at line 466 of file sql-wrap.c.