📄 php_odbc.c
字号:
REGISTER_LONG_CONSTANT("SQL_SMALLINT", SQL_SMALLINT, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("SQL_INTEGER", SQL_INTEGER, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("SQL_BIGINT", SQL_BIGINT, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("SQL_REAL", SQL_REAL, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("SQL_FLOAT", SQL_FLOAT, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("SQL_DOUBLE", SQL_DOUBLE, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("SQL_BINARY", SQL_BINARY, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("SQL_VARBINARY", SQL_VARBINARY, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("SQL_LONGVARBINARY", SQL_LONGVARBINARY, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("SQL_DATE", SQL_DATE, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("SQL_TIME", SQL_TIME, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("SQL_TIMESTAMP", SQL_TIMESTAMP, CONST_PERSISTENT | CONST_CS);#if defined(ODBCVER) && (ODBCVER >= 0x0300) REGISTER_LONG_CONSTANT("SQL_TYPE_DATE", SQL_TYPE_DATE, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("SQL_TYPE_TIME", SQL_TYPE_TIME, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("SQL_TYPE_TIMESTAMP", SQL_TYPE_TIMESTAMP, CONST_PERSISTENT | CONST_CS); /* * SQLSpecialColumns values */ REGISTER_LONG_CONSTANT("SQL_BEST_ROWID", SQL_BEST_ROWID, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("SQL_ROWVER", SQL_ROWVER, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("SQL_SCOPE_CURROW", SQL_SCOPE_CURROW, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("SQL_SCOPE_TRANSACTION", SQL_SCOPE_TRANSACTION, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("SQL_SCOPE_SESSION", SQL_SCOPE_SESSION, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("SQL_NO_NULLS", SQL_NO_NULLS, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("SQL_NULLABLE", SQL_NULLABLE, CONST_PERSISTENT | CONST_CS); /* * SQLStatistics values */ REGISTER_LONG_CONSTANT("SQL_INDEX_UNIQUE", SQL_INDEX_UNIQUE, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("SQL_INDEX_ALL", SQL_INDEX_ALL, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("SQL_ENSURE", SQL_ENSURE, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("SQL_QUICK", SQL_QUICK, CONST_PERSISTENT | CONST_CS);#endif return SUCCESS;}/* }}} *//* {{{ PHP_RINIT_FUNCTION */PHP_RINIT_FUNCTION(odbc){ ODBCG(defConn) = -1; ODBCG(num_links) = ODBCG(num_persistent); memset(ODBCG(laststate), '\0', 6); memset(ODBCG(lasterrormsg), '\0', SQL_MAX_MESSAGE_LENGTH); return SUCCESS;}/* }}} *//* {{{ PHP_RSHUTDOWN_FUNCTION */PHP_RSHUTDOWN_FUNCTION(odbc){ return SUCCESS;}/* }}} *//* {{{ PHP_MSHUTDOWN_FUNCTION */PHP_MSHUTDOWN_FUNCTION(odbc){ UNREGISTER_INI_ENTRIES(); return SUCCESS;}/* }}} *//* {{{ PHP_MINFO_FUNCTION */PHP_MINFO_FUNCTION(odbc){ char buf[32]; php_info_print_table_start(); php_info_print_table_header(2, "ODBC Support", "enabled"); sprintf(buf, "%ld", ODBCG(num_persistent)); php_info_print_table_row(2, "Active Persistent Links", buf); sprintf(buf, "%ld", ODBCG(num_links)); php_info_print_table_row(2, "Active Links", buf); php_info_print_table_row(2, "ODBC library", PHP_ODBC_TYPE);#ifndef PHP_WIN32 php_info_print_table_row(2, "ODBC_INCLUDE", PHP_ODBC_INCLUDE); php_info_print_table_row(2, "ODBC_LFLAGS", PHP_ODBC_LFLAGS); php_info_print_table_row(2, "ODBC_LIBS", PHP_ODBC_LIBS);#endif php_info_print_table_end(); DISPLAY_INI_ENTRIES();} /* }}} *//* {{{ odbc_sql_error */void odbc_sql_error(ODBC_SQL_ERROR_PARAMS){ char state[6]; SDWORD error; /* Not used */ char errormsg[SQL_MAX_MESSAGE_LENGTH]; SWORD errormsgsize; /* Not used */ RETCODE rc; ODBC_SQL_ENV_T henv; ODBC_SQL_CONN_T conn; TSRMLS_FETCH(); if (conn_resource) { henv = conn_resource->henv; conn = conn_resource->hdbc; } else { henv = SQL_NULL_HENV; conn = SQL_NULL_HDBC; } /* This leads to an endless loop in many drivers! * while(henv != SQL_NULL_HENV){ do { */ rc = SQLError(henv, conn, stmt, state, &error, errormsg, sizeof(errormsg)-1, &errormsgsize); if (conn_resource) { memcpy(conn_resource->laststate, state, sizeof(state)); memcpy(conn_resource->lasterrormsg, errormsg, sizeof(errormsg)); } memcpy(ODBCG(laststate), state, sizeof(state)); memcpy(ODBCG(lasterrormsg), errormsg, sizeof(errormsg)); if (func) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQL error: %s, SQL state %s in %s", errormsg, state, func); } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQL error: %s, SQL state %s", errormsg, state); } /* } while (SQL_SUCCEEDED(rc)); } */}/* }}} *//* {{{ php_odbc_fetch_attribs */void php_odbc_fetch_attribs(INTERNAL_FUNCTION_PARAMETERS, int mode){ odbc_result *result; pval **pv_res, **pv_flag; if (zend_get_parameters_ex(2, &pv_res, &pv_flag) == FAILURE) WRONG_PARAM_COUNT; convert_to_long_ex(pv_flag); if (Z_LVAL_PP(pv_res)) { ZEND_FETCH_RESOURCE(result, odbc_result *, pv_res, -1, "ODBC result", le_result); if (mode) result->longreadlen = Z_LVAL_PP(pv_flag); else result->binmode = Z_LVAL_PP(pv_flag); } else { if (mode) ODBCG(defaultlrl) = Z_LVAL_PP(pv_flag); else ODBCG(defaultbinmode) = Z_LVAL_PP(pv_flag); } RETURN_TRUE;}/* }}} *//* {{{ odbc_bindcols */int odbc_bindcols(odbc_result *result TSRMLS_DC){ RETCODE rc; int i; SWORD colnamelen; /* Not used */ SDWORD displaysize; result->values = (odbc_result_value *) emalloc(sizeof(odbc_result_value)*result->numcols); result->longreadlen = ODBCG(defaultlrl); result->binmode = ODBCG(defaultbinmode); for(i = 0; i < result->numcols; i++) { rc = SQLColAttributes(result->stmt, (UWORD)(i+1), SQL_COLUMN_NAME, result->values[i].name, sizeof(result->values[i].name), &colnamelen, 0); rc = SQLColAttributes(result->stmt, (UWORD)(i+1), SQL_COLUMN_TYPE, NULL, 0, NULL, &result->values[i].coltype); /* Don't bind LONG / BINARY columns, so that fetch behaviour can * be controlled by odbc_binmode() / odbc_longreadlen() */ switch(result->values[i].coltype) { case SQL_BINARY: case SQL_VARBINARY: case SQL_LONGVARBINARY: case SQL_LONGVARCHAR: result->values[i].value = NULL; break; #ifdef HAVE_ADABAS case SQL_TIMESTAMP: result->values[i].value = (char *)emalloc(27); SQLBindCol(result->stmt, (UWORD)(i+1), SQL_C_CHAR, result->values[i].value, 27, &result->values[i].vallen); break;#endif /* HAVE_ADABAS */ default: rc = SQLColAttributes(result->stmt, (UWORD)(i+1), SQL_COLUMN_DISPLAY_SIZE, NULL, 0, NULL, &displaysize); displaysize = displaysize <= result->longreadlen ? displaysize : result->longreadlen; result->values[i].value = (char *)emalloc(displaysize + 1); rc = SQLBindCol(result->stmt, (UWORD)(i+1), SQL_C_CHAR, result->values[i].value, displaysize + 1, &result->values[i].vallen); break; } } return 1;}/* }}} *//* {{{ odbc_transact */void odbc_transact(INTERNAL_FUNCTION_PARAMETERS, int type){ odbc_connection *conn; RETCODE rc; pval **pv_conn; if (zend_get_parameters_ex(1, &pv_conn) == FAILURE) { WRONG_PARAM_COUNT; } ZEND_FETCH_RESOURCE2(conn, odbc_connection *, pv_conn, -1, "ODBC-Link", le_conn, le_pconn); rc = SQLTransact(conn->henv, conn->hdbc, (UWORD)((type)?SQL_COMMIT:SQL_ROLLBACK)); if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLTransact"); RETURN_FALSE; } RETURN_TRUE;}/* }}} *//* {{{ _close_pconn_with_id */static int _close_pconn_with_id(list_entry *le, int *id TSRMLS_DC){ if(Z_TYPE_P(le) == le_pconn && (((odbc_connection *)(le->ptr))->id == *id)){ return 1; }else{ return 0; }}/* }}} *//* {{{ odbc_column_lengths */void odbc_column_lengths(INTERNAL_FUNCTION_PARAMETERS, int type){ odbc_result *result;#if defined(HAVE_SOLID) || defined(HAVE_SOLID_30) || defined(HAVE_OPENLINK) /* this seems to be necessary for Solid2.3 ( tested by * tammy@synchronis.com) and Solid 3.0 (tested by eric@terra.telemediair.nl) * Solid does not seem to declare a SQLINTEGER, but it does declare a * SQL_INTEGER which does not work (despite being the same type as a SDWORD. * Solid 3.5 does not have this issue. */ SDWORD len;#else SQLINTEGER len;#endif pval **pv_res, **pv_num; if (zend_get_parameters_ex(2, &pv_res, &pv_num) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_long_ex(pv_num); ZEND_FETCH_RESOURCE(result, odbc_result *, pv_res, -1, "ODBC result", le_result); if (result->numcols == 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "No tuples available at this result index"); RETURN_FALSE; } if (Z_LVAL_PP(pv_num) > result->numcols) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Field index larger than number of fields"); RETURN_FALSE; } if (Z_LVAL_PP(pv_num) < 1) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Field numbering starts at 1"); RETURN_FALSE; } SQLColAttributes(result->stmt, (UWORD)Z_LVAL_PP(pv_num), (SQLUSMALLINT) (type?SQL_COLUMN_SCALE:SQL_COLUMN_PRECISION), NULL, 0, NULL, &len); RETURN_LONG(len);}/* }}} *//* Main User Functions *//* {{{ proto void odbc_close_all(void) Close all ODBC connections */PHP_FUNCTION(odbc_close_all){ void *ptr; int type; int i; int nument; if (ZEND_NUM_ARGS() != 0) { WRONG_PARAM_COUNT; } nument = zend_hash_next_free_element(&EG(regular_list)); /* Loop through list and close all statements */ for(i = 1; i < nument; i++) { ptr = zend_list_find(i, &type); if (ptr && (type == le_result)){ zend_list_delete(i); } } /* Second loop through list, now close all connections */ nument = zend_hash_next_free_element(&EG(regular_list)); for(i = 1; i < nument; i++) { ptr = zend_list_find(i, &type); if (ptr){ if(type == le_conn){ zend_list_delete(i); }else if(type == le_pconn){ zend_list_delete(i); /* Delete the persistent connection */ zend_hash_apply_with_argument(&EG(persistent_list), (apply_func_arg_t) _close_pconn_with_id, (void *) &i TSRMLS_CC); } } }}/* }}} *//* {{{ proto bool odbc_binmode(int result_id, int mode) Handle binary column data */PHP_FUNCTION(odbc_binmode){ php_odbc_fetch_attribs(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);}/* }}} *//* {{{ proto bool odbc_longreadlen(int result_id, int length) Handle LONG columns */PHP_FUNCTION(odbc_longreadlen){ php_odbc_fetch_attribs(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);}/* }}} *//* {{{ proto resource odbc_prepare(resource connection_id, string query) Prepares a statement for execution */PHP_FUNCTION(odbc_prepare){ pval **pv_conn, **pv_query; char *query; odbc_result *result = NULL; odbc_connection *conn; RETCODE rc;#ifdef HAVE_SQL_EXTENDED_FETCH UDWORD scrollopts;#endif if (zend_get_parameters_ex(2, &pv_conn, &pv_query) == FAILURE) { WRONG_PARAM_COUNT; } ZEND_FETCH_RESOURCE2(conn, odbc_connection *, pv_conn, -1, "ODBC-Link", le_conn, le_pconn); convert_to_string_ex(pv_query); query = Z_STRVAL_PP(pv_query); result = (odbc_result *)emalloc(sizeof(odbc_result)); result->numparams = 0; rc = SQLAllocStmt(conn->hdbc, &(result->stmt)); if (rc == SQL_INVALID_HANDLE) { efree(result); php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'"); RETURN_FALSE; } if (rc == SQL_ERROR) { odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt"); efree(result); RETURN_FALSE; }#ifdef HAVE_SQL_EXTENDED_FETCH /* Solid doesn't have ExtendedFetch, if DriverManager is used, get Info, whether Driver supports ExtendedFetch */ rc = SQLGetInfo(conn->hdbc, SQL_FETCH_DIRECTION, (void *) &scrollopts, sizeof(scrollopts), NULL); if (rc == SQL_SUCCESS) { if ((result->fetch_abs = (scrollopts & SQL_FD_FETCH_ABSOLUTE))) { /* Try to set CURSOR_TYPE to dynamic. Driver will replace this with other type if not possible. */ if (SQLSetStmtOption(result->stmt, SQL_CURSOR_TYPE, SQL_CURSOR_DYNAMIC) == SQL_ERROR) { odbc_sql_error(conn, result->stmt, " SQLSetStmtOption"); SQLFreeStmt(result->stmt, SQL_DROP); efree(result); RETURN_FALSE; } } } else { result->fetch_abs = 0; }#endif rc = SQLPrepare(result->stmt, query, SQL_NTS); switch (rc) { case SQL_SUCCESS: break; case SQL_SUCCESS_WITH_INFO: odbc_sql_error(conn, result->stmt, "SQLPrepare"); break; default: odbc_sql_error(conn, result->stmt, "SQLPrepare"); RETURN_FALSE; } SQLNumParams(result->stmt, &(result->numparams)); SQLNumResultCols(result->stmt, &(result->numcols)); if (result->numcols > 0) { if (!odbc_bindcols(result TSRMLS_CC)) { efree(result); RETURN_FALSE; } } else { result->values = NULL; } result->id = zend_list_insert(result, le_result); zend_list_addref(conn->id); result->conn_ptr = conn; result->fetched = 0; RETURN_RESOURCE(result->id);}/* }}} *//* * Execute prepared SQL statement. Supports only input parameters. *//* {{{ proto bool odbc_execute(resource result_id [, array parameters_array]) Execute a prepared statement */PHP_FUNCTION(odbc_execute){ pval **pv_res, **pv_param_arr, **tmp; typedef struct params_t { SDWORD vallen; int fp; } params_t; params_t *params = NULL; char *filename; unsigned char otype; SWORD sqltype, ctype, scale; SWORD nullable; UDWORD precision;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -