📄 php_odbc.c
字号:
RETURN_FALSE; } if (result->values[field_ind].vallen == SQL_NULL_DATA) { efree(field); RETURN_NULL(); } /* chop the trailing \0 by outputing only 4095 bytes */ PHPWRITE(field,(rc == SQL_SUCCESS_WITH_INFO) ? 4095 : result->values[field_ind].vallen); if (rc == SQL_SUCCESS) { /* no more data avail */ efree(field); RETURN_TRUE; } } RETURN_TRUE;}/* }}} *//* {{{ proto int odbc_result_all(resource result_id [, string format]) Print result as HTML table */PHP_FUNCTION(odbc_result_all){ char *buf = NULL; int i, numArgs; odbc_result *result; RETCODE rc; pval **pv_res, **pv_format; SWORD sql_c_type;#ifdef HAVE_SQL_EXTENDED_FETCH UDWORD crow; UWORD RowStatus[1];#endif numArgs = ZEND_NUM_ARGS(); if (numArgs == 1) { if (zend_get_parameters_ex(1, &pv_res) == FAILURE) WRONG_PARAM_COUNT; } else { if (zend_get_parameters_ex(2, &pv_res, &pv_format) == FAILURE) WRONG_PARAM_COUNT; } 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; }#ifdef HAVE_SQL_EXTENDED_FETCH if (result->fetch_abs) rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus); else#endif rc = SQLFetch(result->stmt); if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { php_printf("<h2>No rows found</h2>\n"); RETURN_LONG(0); } /* Start table tag */ if (numArgs == 1) { php_printf("<table><tr>"); } else { convert_to_string_ex(pv_format); php_printf("<table %s ><tr>",Z_STRVAL_PP(pv_format)); } for(i = 0; i < result->numcols; i++) php_printf("<th>%s</th>", result->values[i].name); php_printf("</tr>\n"); while(rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { result->fetched++; php_printf("<tr>"); for(i = 0; i < result->numcols; i++) { sql_c_type = SQL_C_CHAR; switch(result->values[i].coltype) { case SQL_BINARY: case SQL_VARBINARY: case SQL_LONGVARBINARY: if (result->binmode <= 0) { php_printf("<td>Not printable</td>"); break; } if (result->binmode <= 1) sql_c_type = SQL_C_BINARY; case SQL_LONGVARCHAR: if (IS_SQL_LONG(result->values[i].coltype) && result->longreadlen <= 0) { php_printf("<td>Not printable</td>"); break; } if (buf == NULL) buf = emalloc(result->longreadlen); rc = SQLGetData(result->stmt, (UWORD)(i + 1),sql_c_type, buf, result->longreadlen, &result->values[i].vallen); php_printf("<td>"); if (rc == SQL_ERROR) { odbc_sql_error(result->conn_ptr, result->stmt, "SQLGetData"); php_printf("</td></tr></table>"); efree(buf); RETURN_FALSE; } if (rc == SQL_SUCCESS_WITH_INFO) PHPWRITE(buf, result->longreadlen); else if (result->values[i].vallen == SQL_NULL_DATA) { php_printf("<td>NULL</td>"); break; } else { PHPWRITE(buf, result->values[i].vallen); } php_printf("</td>"); break; default: if (result->values[i].vallen == SQL_NULL_DATA) { php_printf("<td>NULL</td>"); } else { php_printf("<td>%s</td>", result->values[i].value); } break; } } php_printf("</tr>\n");#ifdef HAVE_SQL_EXTENDED_FETCH if (result->fetch_abs) rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus); else#endif rc = SQLFetch(result->stmt); } php_printf("</table>\n"); if (buf) efree(buf); RETURN_LONG(result->fetched);}/* }}} *//* {{{ proto bool odbc_free_result(resource result_id) Free resources associated with a result */PHP_FUNCTION(odbc_free_result){ pval **pv_res; odbc_result *result; int i; if (zend_get_parameters_ex(1, &pv_res) == FAILURE) { WRONG_PARAM_COUNT; } ZEND_FETCH_RESOURCE(result, odbc_result *, pv_res, -1, "ODBC result", le_result); if (result->values) { for (i = 0; i < result->numcols; i++) { if (result->values[i].value) { efree(result->values[i].value); } } efree(result->values); result->values = NULL; } zend_list_delete(result->id); RETURN_TRUE;}/* }}} *//* {{{ proto resource odbc_connect(string DSN, string user, string password [, int cursor_option]) Connect to a datasource */PHP_FUNCTION(odbc_connect){ odbc_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);}/* }}} *//* {{{ proto resource odbc_pconnect(string DSN, string user, string password [, int cursor_option]) Establish a persistent connection to a datasource */PHP_FUNCTION(odbc_pconnect){ odbc_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);}/* }}} *//* {{{ odbc_sqlconnect */int odbc_sqlconnect(odbc_connection **conn, char *db, char *uid, char *pwd, int cur_opt, int persistent TSRMLS_DC){ RETCODE rc; *conn = (odbc_connection *)pemalloc(sizeof(odbc_connection), persistent); (*conn)->persistent = persistent; SQLAllocEnv(&((*conn)->henv)); SQLAllocConnect((*conn)->henv, &((*conn)->hdbc)); #if defined(HAVE_SOLID) || defined(HAVE_SOLID_30) SQLSetConnectOption((*conn)->hdbc, SQL_TRANSLATE_OPTION, SQL_SOLID_XLATOPT_NOCNV);#endif#ifdef HAVE_OPENLINK { char dsnbuf[1024]; short dsnbuflen; rc = SQLDriverConnect((*conn)->hdbc, NULL, db, SQL_NTS, dsnbuf, sizeof(dsnbuf) - 1, &dsnbuflen, SQL_DRIVER_NOPROMPT); }#else if (cur_opt != SQL_CUR_DEFAULT) { rc = SQLSetConnectOption((*conn)->hdbc, SQL_ODBC_CURSORS, cur_opt); if (rc != SQL_SUCCESS) { /* && rc != SQL_SUCCESS_WITH_INFO ? */ odbc_sql_error(*conn, SQL_NULL_HSTMT, "SQLSetConnectOption"); SQLFreeConnect((*conn)->hdbc); pefree(*conn, persistent); return FALSE; } }/* Possible fix for bug #10250 * Needs testing on UnixODBC < 2.0.5 though. */#if defined(HAVE_EMPRESS) || defined(HAVE_UNIXODBC) || defined(PHP_WIN32)/* * Uncomment the line above, and comment line below to fully test * #ifdef HAVE_EMPRESS */ { int direct = 0; char dsnbuf[1024]; short dsnbuflen; char *ldb = 0; int ldb_len = 0; if (strstr((char*)db, ";")) { direct = 1; if (uid && !strstr ((char*)db, "uid") && !strstr((char*)db, "UID")) { ldb = (char*) emalloc(strlen(db) + strlen(uid) + strlen(pwd) + 12); sprintf(ldb, "%s;UID=%s;PWD=%s", db, uid, pwd); } else { ldb_len = strlen(db)+1; ldb = (char*) emalloc(ldb_len); memcpy(ldb, db, ldb_len); } } if (direct) { rc = SQLDriverConnect((*conn)->hdbc, NULL, ldb, strlen(ldb), dsnbuf, sizeof(dsnbuf) - 1, &dsnbuflen, SQL_DRIVER_NOPROMPT); } else { rc = SQLConnect((*conn)->hdbc, db, SQL_NTS, uid, SQL_NTS, pwd, SQL_NTS); } if (ldb) { efree(ldb); } }#else rc = SQLConnect((*conn)->hdbc, db, SQL_NTS, uid, SQL_NTS, pwd, SQL_NTS);#endif#endif if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { odbc_sql_error(*conn, SQL_NULL_HSTMT, "SQLConnect"); SQLFreeConnect((*conn)->hdbc); pefree((*conn), persistent); return FALSE; }/* (*conn)->open = 1;*/ return TRUE;}/* }}} *//* Persistent connections: two list-types le_pconn, le_conn and a plist * where hashed connection info is stored together with index pointer to * the actual link of type le_pconn in the list. Only persistent * connections get hashed up. Normal connections use existing pconnections. * Maybe this has to change with regard to transactions on pconnections? * Possibly set autocommit to on on request shutdown. * * We do have to hash non-persistent connections, and reuse connections. * In the case where two connects were being made, without closing the first * connect, access violations were occuring. This is because some of the * "globals" in this module should actualy be per-connection variables. I * simply fixed things to get them working for now. Shane *//* {{{ odbc_do_connect */void odbc_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent){ char *db = NULL; char *uid = NULL; char *pwd = NULL; pval **pv_db, **pv_uid, **pv_pwd, **pv_opt; odbc_connection *db_conn; char *hashed_details; int hashed_len, cur_opt; /* Now an optional 4th parameter specifying the cursor type * defaulting to the cursors default */ switch(ZEND_NUM_ARGS()) { case 3: if (zend_get_parameters_ex(3, &pv_db, &pv_uid, &pv_pwd) == FAILURE) { WRONG_PARAM_COUNT; } /* Use Default: Probably a better way to do this */ cur_opt = SQL_CUR_DEFAULT; break; case 4: if (zend_get_parameters_ex(4, &pv_db, &pv_uid, &pv_pwd, &pv_opt) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_long_ex(pv_opt); cur_opt = Z_LVAL_PP(pv_opt); /* Confirm the cur_opt range */ if (! (cur_opt == SQL_CUR_USE_IF_NEEDED || cur_opt == SQL_CUR_USE_ODBC || cur_opt == SQL_CUR_USE_DRIVER || cur_opt == SQL_CUR_DEFAULT) ) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Cursor type (%d)", cur_opt); RETURN_FALSE; } break; default: WRONG_PARAM_COUNT; break; } convert_to_string_ex(pv_db); convert_to_string_ex(pv_uid); convert_to_string_ex(pv_pwd); db = Z_STRVAL_PP(pv_db); uid = Z_STRVAL_PP(pv_uid); pwd = Z_STRVAL_PP(pv_pwd); if (ODBCG(allow_persistent) <= 0) { persistent = 0; } hashed_len = spprintf(&hashed_details, 0, "%s_%s_%s_%s_%d", ODBC_TYPE, db, uid, pwd, cur_opt); /* FIXME the idea of checking to see if our connection is already persistent is good, but it adds a lot of overhead to non-persistent connections. We should look and see if we can fix that somehow */ /* try to find if we already have this link in our persistent list, * no matter if it is to be persistent or not */try_and_get_another_connection: if (persistent) { list_entry *le; if (zend_hash_find(&EG(persistent_list), hashed_details, hashed_len + 1, (void **) &le) == FAILURE) { /* the link is not in the persistent list */ list_entry new_le; if (ODBCG(max_links) != -1 && ODBCG(num_links) >= ODBCG(max_links)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many open links (%ld)", ODBCG(num_links)); efree(hashed_details); RETURN_FALSE; } if (ODBCG(max_persistent) != -1 && ODBCG(num_persistent) >= ODBCG(max_persistent)) { php_error_docref(NULL TSRMLS_CC, E_WARNING,"Too many open persistent links (%ld)", ODBCG(num_persistent)); efree(hashed_details); RETURN_FALSE; } if (!odbc_sqlconnect(&db_conn, db, uid, pwd, cur_opt, 1 TSRMLS_CC)) { efree(hashed_details); RETURN_FALSE; } Z_TYPE(new_le) = le_pconn; new_le.ptr = db_conn; if (zend_hash_update(&EG(persistent_list), hashed_details, hashed_len + 1, &new_le, sizeof(list_entry), NULL) == FAILURE) { free(db_conn); efree(hashed_details); RETURN_FALSE; } ODBCG(num_persistent)++; ODBCG(num_links)++; db_conn->id = ZEND_REGISTER_RESOURCE(return_value, db_conn, le_pconn); } else { /* found connection */ if (Z_TYPE_P(le) != le_pconn) { RETURN_FALSE; } /* * check to see if the connection is still valid */ db_conn = (odbc_connection *)le->ptr; /* * check to see if the connection is still in place (lurcher) */ if(ODBCG(check_persistent)){ RETCODE ret; UCHAR d_name[32]; SWORD len; ret = SQLGetInfo(db_conn->hdbc, SQL_DATA_SOURCE_READ_ONLY, d_name, sizeof(d_name), &len); if(ret != SQL_SUCCESS || len == 0) { zend_hash_del(&EG(persistent_list), hashed_details, hashed_len + 1); /* Commented out to fix a possible double closure error * when working with persistent connections as submitted by * bug #15758 * * safe_odbc_disconnect(db_conn->hdbc); * SQLFreeConnect(db_conn->hdbc); */ goto try_and_get_another_connection; } } } db_conn->id = ZEND_REGISTER_RESOURCE(return_value, db_conn, le_pconn); } else { /* non persistent */ list_entry *index_ptr, new_index_ptr; if (zend_hash_find(&EG(regular_list), hashed_details, hashed_len + 1, (void **) &index_ptr) == SUCCESS) { int type, conn_id; void *ptr; if (Z_TYPE_P(index_ptr) != le_index_ptr) { RETURN_FALSE; } conn_id = (int)index_ptr->ptr; ptr = zend_list_find(conn_id, &type); /* check if the connection is still there */ if (ptr && (type == le_conn || type == le_pconn)) { zend_list_addref(conn_id); Z_LVAL_P(return_value) = conn_id; Z_TYPE_P(return_value) = IS_RESOURCE; efree(hashed_details); return; } else { zend_hash_del(&EG(regular_list), hashed_details, hashed_len + 1); } } if (ODBCG(max_links) != -1 && ODBCG(num_links) >= ODBCG(max_links)) { php_error_docref(NULL TSRMLS_CC, E_WARNING,"Too many open connections (%ld)",ODBCG(num_links)); efree(hashed_details); RETURN_FALSE; } if (!odbc_sqlconnect(&db_conn, db, uid, pwd, cur_opt, 0 TSRMLS_CC)) { efree(hashed_details); RETURN_FALSE; } db_conn->id = ZEND_REGISTER_RESOURCE(return_value, db_conn, le_conn); new_index_ptr.ptr = (void *) Z_LVAL_P(return_value); Z_TYPE(new_index_ptr) = le_index_ptr; if (zend_hash_update(&EG(regular_list), hashed_details, hashed_len + 1, (void *) &new_index_ptr, sizeof(list_entry), NULL) == FAILURE) { efree(hashed_details); RETURN_FALSE; /* XXX Free Connection */ } ODBCG(num_links)++; } efree(hashed_details);}/* }}} *//* {{{ proto void odbc_close(resource connection_id) Close an ODBC con
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -