Back to index

php5  5.3.10
Functions | Variables
odbc_driver.c File Reference
#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
#include "pdo/php_pdo.h"
#include "pdo/php_pdo_driver.h"
#include "php_pdo_odbc.h"
#include "php_pdo_odbc_int.h"
#include "zend_exceptions.h"

Go to the source code of this file.

Functions

static int pdo_odbc_fetch_error_func (pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info TSRMLS_DC)
void pdo_odbc_error (pdo_dbh_t *dbh, pdo_stmt_t *stmt, PDO_ODBC_HSTMT statement, char *what, const char *file, int line TSRMLS_DC)
static int odbc_handle_closer (pdo_dbh_t *dbh TSRMLS_DC)
static int odbc_handle_preparer (pdo_dbh_t *dbh, const char *sql, long sql_len, pdo_stmt_t *stmt, zval *driver_options TSRMLS_DC)
static long odbc_handle_doer (pdo_dbh_t *dbh, const char *sql, long sql_len TSRMLS_DC)
static int odbc_handle_quoter (pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen, enum pdo_param_type param_type TSRMLS_DC)
static int odbc_handle_begin (pdo_dbh_t *dbh TSRMLS_DC)
static int odbc_handle_commit (pdo_dbh_t *dbh TSRMLS_DC)
static int odbc_handle_rollback (pdo_dbh_t *dbh TSRMLS_DC)
static int odbc_handle_set_attr (pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC)
static int odbc_handle_get_attr (pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC)
static int pdo_odbc_handle_factory (pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC)

Variables

static struct pdo_dbh_methods
pdo_driver_t pdo_odbc_driver

Function Documentation

static int odbc_handle_begin ( pdo_dbh_t *dbh  TSRMLS_DC) [static]

Definition at line 271 of file odbc_driver.c.

{
       if (dbh->auto_commit) {
              /* we need to disable auto-commit now, to be able to initiate a transaction */
              RETCODE rc;
              pdo_odbc_db_handle *H = (pdo_odbc_db_handle *)dbh->driver_data;

              rc = SQLSetConnectAttr(H->dbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_OFF, SQL_IS_INTEGER);
              if (rc != SQL_SUCCESS) {
                     pdo_odbc_drv_error("SQLSetConnectAttr AUTOCOMMIT = OFF");
                     return 0;
              }
       }
       return 1;
}
static int odbc_handle_closer ( pdo_dbh_t *dbh  TSRMLS_DC) [static]

Definition at line 127 of file odbc_driver.c.

{
       pdo_odbc_db_handle *H = (pdo_odbc_db_handle*)dbh->driver_data;

       if (H->dbc != SQL_NULL_HANDLE) {
              SQLEndTran(SQL_HANDLE_DBC, H->dbc, SQL_ROLLBACK);
              SQLDisconnect(H->dbc);
              SQLFreeHandle(SQL_HANDLE_DBC, H->dbc);
              H->dbc = NULL;
       }
       SQLFreeHandle(SQL_HANDLE_ENV, H->env);
       H->env = NULL;
       pefree(H, dbh->is_persistent);
       dbh->driver_data = NULL;

       return 0;
}
static int odbc_handle_commit ( pdo_dbh_t *dbh  TSRMLS_DC) [static]

Definition at line 287 of file odbc_driver.c.

{
       pdo_odbc_db_handle *H = (pdo_odbc_db_handle *)dbh->driver_data;
       RETCODE rc;

       rc = SQLEndTran(SQL_HANDLE_DBC, H->dbc, SQL_COMMIT);

       if (rc != SQL_SUCCESS) {
              pdo_odbc_drv_error("SQLEndTran: Commit");

              if (rc != SQL_SUCCESS_WITH_INFO) {
                     return 0;
              }
       }

       if (dbh->auto_commit) {
              /* turn auto-commit back on again */
              rc = SQLSetConnectAttr(H->dbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_ON, SQL_IS_INTEGER);
              if (rc != SQL_SUCCESS) {
                     pdo_odbc_drv_error("SQLSetConnectAttr AUTOCOMMIT = ON");
                     return 0;
              }
       }
       return 1;
}
static long odbc_handle_doer ( pdo_dbh_t *  dbh,
const char *  sql,
long sql_len  TSRMLS_DC 
) [static]

Definition at line 223 of file odbc_driver.c.

{
       pdo_odbc_db_handle *H = (pdo_odbc_db_handle *)dbh->driver_data;
       RETCODE rc;
       SQLLEN row_count = -1;
       PDO_ODBC_HSTMT       stmt;
       
       rc = SQLAllocHandle(SQL_HANDLE_STMT, H->dbc, &stmt);
       if (rc != SQL_SUCCESS) {
              pdo_odbc_drv_error("SQLAllocHandle: STMT");
              return -1;
       }

       rc = SQLExecDirect(stmt, (char *)sql, sql_len);

       if (rc == SQL_NO_DATA) {
              /* If SQLExecDirect executes a searched update or delete statement that
               * does not affect any rows at the data source, the call to
               * SQLExecDirect returns SQL_NO_DATA. */
              row_count = 0;
              goto out;
       }

       if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
              pdo_odbc_doer_error("SQLExecDirect");
              goto out;
       }

       rc = SQLRowCount(stmt, &row_count);
       if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
              pdo_odbc_doer_error("SQLRowCount");
              goto out;
       }
       if (row_count == -1) {
              row_count = 0;
       }
out:
       SQLFreeHandle(SQL_HANDLE_STMT, stmt);
       return row_count;
}

Here is the call graph for this function:

static int odbc_handle_get_attr ( pdo_dbh_t *  dbh,
long  attr,
zval *val  TSRMLS_DC 
) [static]

Definition at line 354 of file odbc_driver.c.

{
       pdo_odbc_db_handle *H = (pdo_odbc_db_handle *)dbh->driver_data;
       switch (attr) {
              case PDO_ATTR_CLIENT_VERSION:
                     ZVAL_STRING(val, "ODBC-" PDO_ODBC_TYPE, 1);
                     return 1;

              case PDO_ATTR_SERVER_VERSION:
              case PDO_ATTR_PREFETCH:
              case PDO_ATTR_TIMEOUT:
              case PDO_ATTR_SERVER_INFO:
              case PDO_ATTR_CONNECTION_STATUS:
                     break;
              case PDO_ODBC_ATTR_ASSUME_UTF8:
                     ZVAL_BOOL(val, H->assume_utf8 ? 1 : 0);
                     return 1;

       }
       return 0;
}

Here is the call graph for this function:

static int odbc_handle_preparer ( pdo_dbh_t *  dbh,
const char *  sql,
long  sql_len,
pdo_stmt_t *  stmt,
zval *driver_options  TSRMLS_DC 
) [static]

Definition at line 145 of file odbc_driver.c.

{
       RETCODE rc;
       pdo_odbc_db_handle *H = (pdo_odbc_db_handle *)dbh->driver_data;
       pdo_odbc_stmt *S = ecalloc(1, sizeof(*S));
       enum pdo_cursor_type cursor_type = PDO_CURSOR_FWDONLY;
       int ret;
       char *nsql = NULL;
       int nsql_len = 0;

       S->H = H;
       S->assume_utf8 = H->assume_utf8;

       /* before we prepare, we need to peek at the query; if it uses named parameters,
        * we want PDO to rewrite them for us */
       stmt->supports_placeholders = PDO_PLACEHOLDER_POSITIONAL;
       ret = pdo_parse_params(stmt, (char*)sql, sql_len, &nsql, &nsql_len TSRMLS_CC);
       
       if (ret == 1) {
              /* query was re-written */
              sql = nsql;
       } else if (ret == -1) {
              /* couldn't grok it */
              strcpy(dbh->error_code, stmt->error_code);
              efree(S);
              return 0;
       }
       
       rc = SQLAllocHandle(SQL_HANDLE_STMT, H->dbc, &S->stmt);

       if (rc == SQL_INVALID_HANDLE || rc == SQL_ERROR) {
              efree(S);
              if (nsql) {
                     efree(nsql);
              }
              pdo_odbc_drv_error("SQLAllocStmt");
              return 0;
       }

       cursor_type = pdo_attr_lval(driver_options, PDO_ATTR_CURSOR, PDO_CURSOR_FWDONLY TSRMLS_CC);
       if (cursor_type != PDO_CURSOR_FWDONLY) {
              rc = SQLSetStmtAttr(S->stmt, SQL_ATTR_CURSOR_SCROLLABLE, (void*)SQL_SCROLLABLE, 0);
              if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
                     pdo_odbc_stmt_error("SQLSetStmtAttr: SQL_ATTR_CURSOR_SCROLLABLE");
                     SQLFreeHandle(SQL_HANDLE_STMT, S->stmt);
                     if (nsql) {
                            efree(nsql);
                     }
                     return 0;
              }
       }
       
       rc = SQLPrepare(S->stmt, (char*)sql, SQL_NTS);
       if (nsql) {
              efree(nsql);
       }

       stmt->driver_data = S;
       stmt->methods = &odbc_stmt_methods;

       if (rc != SQL_SUCCESS) {
              pdo_odbc_stmt_error("SQLPrepare");
        if (rc != SQL_SUCCESS_WITH_INFO) {
            /* clone error information into the db handle */
            strcpy(H->einfo.last_err_msg, S->einfo.last_err_msg);
            H->einfo.file = S->einfo.file;
            H->einfo.line = S->einfo.line;
            H->einfo.what = S->einfo.what;
            strcpy(dbh->error_code, stmt->error_code);
        }
       }

       if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
              return 0;
       }
       return 1;
}

Here is the call graph for this function:

static int odbc_handle_quoter ( pdo_dbh_t *  dbh,
const char *  unquoted,
int  unquotedlen,
char **  quoted,
int quotedlen,
enum pdo_param_type param_type  TSRMLS_DC 
) [static]

Definition at line 264 of file odbc_driver.c.

{
       pdo_odbc_db_handle *H = (pdo_odbc_db_handle *)dbh->driver_data;
       /* TODO: figure it out */
       return 0;
}
static int odbc_handle_rollback ( pdo_dbh_t *dbh  TSRMLS_DC) [static]

Definition at line 313 of file odbc_driver.c.

{
       pdo_odbc_db_handle *H = (pdo_odbc_db_handle *)dbh->driver_data;
       RETCODE rc;

       rc = SQLEndTran(SQL_HANDLE_DBC, H->dbc, SQL_ROLLBACK);

       if (rc != SQL_SUCCESS) {
              pdo_odbc_drv_error("SQLEndTran: Rollback");

              if (rc != SQL_SUCCESS_WITH_INFO) {
                     return 0;
              }
       }
       if (dbh->auto_commit && H->dbc) {
              /* turn auto-commit back on again */
              rc = SQLSetConnectAttr(H->dbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_ON, SQL_IS_INTEGER);
              if (rc != SQL_SUCCESS) {
                     pdo_odbc_drv_error("SQLSetConnectAttr AUTOCOMMIT = ON");
                     return 0;
              }
       }

       return 1;
}
static int odbc_handle_set_attr ( pdo_dbh_t *  dbh,
long  attr,
zval *val  TSRMLS_DC 
) [static]

Definition at line 339 of file odbc_driver.c.

{
       pdo_odbc_db_handle *H = (pdo_odbc_db_handle *)dbh->driver_data;
       switch (attr) {
              case PDO_ODBC_ATTR_ASSUME_UTF8:
                     H->assume_utf8 = zval_is_true(val);
                     return 1;
              default:
                     strcpy(H->einfo.last_err_msg, "Unknown Attribute");
                     H->einfo.what = "setAttribute";
                     strcpy(H->einfo.last_state, "IM001");
                     return -1;
       }
}

Here is the call graph for this function:

void pdo_odbc_error ( pdo_dbh_t *  dbh,
pdo_stmt_t *  stmt,
PDO_ODBC_HSTMT  statement,
char *  what,
const char *  file,
int line  TSRMLS_DC 
)

Definition at line 59 of file odbc_driver.c.

{
       SQLRETURN rc;
       SQLSMALLINT   errmsgsize = 0;
       SQLHANDLE eh;
       SQLSMALLINT htype, recno = 1;
       pdo_odbc_db_handle *H = (pdo_odbc_db_handle*)dbh->driver_data;
       pdo_odbc_errinfo *einfo = &H->einfo;
       pdo_odbc_stmt *S = NULL;
       pdo_error_type *pdo_err = &dbh->error_code;

       if (stmt) {
              S = (pdo_odbc_stmt*)stmt->driver_data;

              einfo = &S->einfo;
              pdo_err = &stmt->error_code;
       }

       if (statement == SQL_NULL_HSTMT && S) {
              statement = S->stmt;
       }

       if (statement) {
              htype = SQL_HANDLE_STMT;
              eh = statement;
       } else if (H->dbc) {
              htype = SQL_HANDLE_DBC;
              eh = H->dbc;
       } else {
              htype = SQL_HANDLE_ENV;
              eh = H->env;
       }

       rc = SQLGetDiagRec(htype, eh, recno++, einfo->last_state, &einfo->last_error,
                     einfo->last_err_msg, sizeof(einfo->last_err_msg)-1, &errmsgsize);

       if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
              errmsgsize = 0;
       }

       einfo->last_err_msg[errmsgsize] = '\0';
       einfo->file = file;
       einfo->line = line;
       einfo->what = what;

       strcpy(*pdo_err, einfo->last_state);
/* printf("@@ SQLSTATE[%s] %s\n", *pdo_err, einfo->last_err_msg); */
       if (!dbh->methods) {
              zend_throw_exception_ex(php_pdo_get_exception(), einfo->last_error TSRMLS_CC, "SQLSTATE[%s] %s: %d %s",
                            *pdo_err, what, einfo->last_error, einfo->last_err_msg);
       }

       /* just like a cursor, once you start pulling, you need to keep
        * going until the end; SQL Server (at least) will mess with the
        * actual cursor state if you don't finish retrieving all the
        * diagnostic records (which can be generated by PRINT statements
        * in the query, for instance). */
       while (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) {
              char discard_state[5];
              char discard_buf[1024];
              SQLINTEGER code;
              rc = SQLGetDiagRec(htype, eh, recno++, discard_state, &code,
                            discard_buf, sizeof(discard_buf)-1, &errmsgsize);
       }

}

Here is the call graph for this function:

static int pdo_odbc_fetch_error_func ( pdo_dbh_t *  dbh,
pdo_stmt_t *  stmt,
zval *info  TSRMLS_DC 
) [static]

Definition at line 34 of file odbc_driver.c.

{
       pdo_odbc_db_handle *H = (pdo_odbc_db_handle *)dbh->driver_data;
       pdo_odbc_errinfo *einfo = &H->einfo;
       pdo_odbc_stmt *S = NULL;
       char *message = NULL;

       if (stmt) {
              S = (pdo_odbc_stmt*)stmt->driver_data;
              einfo = &S->einfo;
       }

       spprintf(&message, 0, "%s (%s[%ld] at %s:%d)",
                            einfo->last_err_msg,
                            einfo->what, einfo->last_error,
                            einfo->file, einfo->line);

       add_next_index_long(info, einfo->last_error);
       add_next_index_string(info, message, 0);
       add_next_index_string(info, einfo->last_state, 1);

       return 1;
}

Here is the call graph for this function:

static int pdo_odbc_handle_factory ( pdo_dbh_t *  dbh,
zval *driver_options  TSRMLS_DC 
) [static]

Definition at line 391 of file odbc_driver.c.

{
       pdo_odbc_db_handle *H;
       RETCODE rc;
       int use_direct = 0;
       SQLUINTEGER cursor_lib;

       H = pecalloc(1, sizeof(*H), dbh->is_persistent);

       dbh->driver_data = H;
       
       SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &H->env);
       rc = SQLSetEnvAttr(H->env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);

       if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
              pdo_odbc_drv_error("SQLSetEnvAttr: ODBC3");
              goto fail;
       }

#ifdef SQL_ATTR_CONNECTION_POOLING
       if (pdo_odbc_pool_on != SQL_CP_OFF) {
              rc = SQLSetEnvAttr(H->env, SQL_ATTR_CP_MATCH, (void*)pdo_odbc_pool_mode, 0);
              if (rc != SQL_SUCCESS) {
                     pdo_odbc_drv_error("SQLSetEnvAttr: SQL_ATTR_CP_MATCH");
                     goto fail;
              }
       }
#endif
       
       rc = SQLAllocHandle(SQL_HANDLE_DBC, H->env, &H->dbc);
       if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
              pdo_odbc_drv_error("SQLAllocHandle (DBC)");
              goto fail;
       }

       rc = SQLSetConnectAttr(H->dbc, SQL_ATTR_AUTOCOMMIT,
              (SQLPOINTER)(dbh->auto_commit ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF), SQL_IS_INTEGER);
       if (rc != SQL_SUCCESS) {
              pdo_odbc_drv_error("SQLSetConnectAttr AUTOCOMMIT");
              goto fail;
       }

       /* set up the cursor library, if needed, or if configured explicitly */
       cursor_lib = pdo_attr_lval(driver_options, PDO_ODBC_ATTR_USE_CURSOR_LIBRARY, SQL_CUR_USE_IF_NEEDED TSRMLS_CC);
       rc = SQLSetConnectAttr(H->dbc, SQL_ODBC_CURSORS, (void*)cursor_lib, SQL_IS_INTEGER);
       if (rc != SQL_SUCCESS && cursor_lib != SQL_CUR_USE_IF_NEEDED) {
              pdo_odbc_drv_error("SQLSetConnectAttr SQL_ODBC_CURSORS");
              goto fail;
       }

       if (strchr(dbh->data_source, ';')) {
              char dsnbuf[1024];
              short dsnbuflen;

              use_direct = 1;

              /* Force UID and PWD to be set in the DSN */
              if (dbh->username && *dbh->username && !strstr(dbh->data_source, "uid")
                            && !strstr(dbh->data_source, "UID")) {
                     char *dsn;
                     spprintf(&dsn, 0, "%s;UID=%s;PWD=%s", dbh->data_source, dbh->username, dbh->password);
                     pefree((char*)dbh->data_source, dbh->is_persistent);
                     dbh->data_source = dsn;
              }

              rc = SQLDriverConnect(H->dbc, NULL, (char*)dbh->data_source, strlen(dbh->data_source),
                            dsnbuf, sizeof(dsnbuf)-1, &dsnbuflen, SQL_DRIVER_NOPROMPT);
       }
       if (!use_direct) {
              rc = SQLConnect(H->dbc, (char*)dbh->data_source, SQL_NTS, dbh->username, SQL_NTS, dbh->password, SQL_NTS);
       }

       if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
              pdo_odbc_drv_error(use_direct ? "SQLDriverConnect" : "SQLConnect");
              goto fail;
       }

       /* TODO: if we want to play nicely, we should check to see if the driver really supports ODBC v3 or not */

       dbh->methods = &odbc_methods;
       dbh->alloc_own_columns = 1;
       
       return 1;

fail:
       dbh->methods = &odbc_methods;
       return 0;
}

Here is the call graph for this function:


Variable Documentation

struct pdo_dbh_methods [static]
Initial value:

Definition at line 481 of file odbc_driver.c.