|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
[2007-07-03 00:10 UTC] christopher dot jones at oracle dot com
[2021-02-10 06:09 UTC] gracejonesatzt at gmail dot com
[2021-11-09 17:15 UTC] harshkhanwani at gmail dot com
[2021-11-09 17:17 UTC] harshkhanwani at gmail dot com
[2021-11-09 17:18 UTC] harshkhanwani at gmail dot com
[2022-02-10 17:36 UTC] prepaidgiftbalanceblog at gmail dot com
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Mon Nov 03 06:00:01 2025 UTC |
Description: ------------ Ben Ramsey & Maggie Nelson reported a problem caused by PDO_OCI failing because it did not have access to Oracle NLS data. Here is a patch to report errors (i) when the character set name is invalid (ii) when the NLS environment can't be initialized. Reproduce code: --------------- For (i): $dbh = new PDO('oci:dbname=localhost/XE;charset=XYZ', 'hr', 'hrpwd'); For (ii) when on Linux using Oracle Instant Client 10.2.0.3 libraries: $dbh = new PDO('oci:dbname=localhost/XE;charset=TR8MACTURKISH', 'hr', 'hrpwd'); The proposed patch is: --- oci_driver.c.orig 2007-06-17 20:02:31.000000000 -0700 +++ oci_driver.c 2007-06-17 23:59:46.000000000 -0700 @@ -55,7 +55,7 @@ } /* }}} */ -ub4 _oci_error(OCIError *err, pdo_dbh_t *dbh, pdo_stmt_t *stmt, char *what, sword status, const char *file, int line TSRMLS_DC) /* {{{ */ +ub4 _oci_error(OCIError *err, pdo_dbh_t *dbh, pdo_stmt_t *stmt, char *what, sword status, int init, const char *file, int line TSRMLS_DC) /* {{{ */ { text errbuf[1024] = "<<Unknown>>"; char tmp_buf[2048]; @@ -84,6 +84,11 @@ einfo->file = file; einfo->line = line; + if (init) { /* Initialization error */ + strcpy(*pdo_err, "HY000"); + slprintf(tmp_buf, sizeof(tmp_buf), "%s (%s:%d)", what, file, line); + einfo->errmsg = pestrdup(tmp_buf, dbh->is_persistent); + } else { switch (status) { case OCI_SUCCESS: strcpy(*pdo_err, "00000"); @@ -163,6 +168,7 @@ H->einfo.errmsg = einfo->errmsg ? pestrdup(einfo->errmsg, dbh->is_persistent) : NULL; strcpy(dbh->error_code, stmt->error_code); } + } /* little mini hack so that we can use this code from the dbh ctor */ if (!dbh->methods) { @@ -446,8 +452,14 @@ #if HAVE_OCIENVNLSCREATE if (vars[0].optval) { H->charset = OCINlsCharSetNameToId(pdo_oci_Env, vars[0].optval); - if (H->charset) { - OCIEnvNlsCreate(&H->env, PDO_OCI_INIT_MODE, 0, NULL, NULL, NULL, 0, NULL, H->charset, H->charset); + if (!H->charset) { + oci_init_error("OCINlsCharSetNameToId: unknown character set name"); + goto cleanup; + } else { + if (OCIEnvNlsCreate(&H->env, PDO_OCI_INIT_MODE, 0, NULL, NULL, NULL, 0, NULL, H->charset, H->charset) != OCI_SUCCESS) { + oci_init_error("OCIEnvNlsCreate: Check the character set is valid and that PHP has access to Oracle libraries and NLS data"); + goto cleanup; + } } } #endif @@ -517,14 +529,14 @@ /* Now fire up the session */ H->last_err = OCISessionBegin(H->svc, H->err, H->session, OCI_CRED_RDBMS, OCI_DEFAULT); if (H->last_err) { - oci_drv_error("OCISessionBegin:"); + oci_drv_error("OCISessionBegin"); goto cleanup; } /* set the server handle into service handle */ H->last_err = OCIAttrSet(H->svc, OCI_HTYPE_SVCCTX, H->session, 0, OCI_ATTR_SESSION, H->err); if (H->last_err) { - oci_drv_error("OCIAttrSet: OCI_ATTR_SESSION:"); + oci_drv_error("OCIAttrSet: OCI_ATTR_SESSION"); goto cleanup; } --- oci_statement.c.orig 2007-01-26 07:07:45.000000000 -0800 +++ oci_statement.c 2007-06-17 23:59:46.000000000 -0700 @@ -33,14 +33,14 @@ #define STMT_CALL(name, params) \ S->last_err = name params; \ - S->last_err = _oci_error(S->err, stmt->dbh, stmt, #name, S->last_err, __FILE__, __LINE__ TSRMLS_CC); \ + S->last_err = _oci_error(S->err, stmt->dbh, stmt, #name, S->last_err, 0, __FILE__, __LINE__ TSRMLS_CC); \ if (S->last_err) { \ return 0; \ } #define STMT_CALL_MSG(name, msg, params) \ S->last_err = name params; \ - S->last_err = _oci_error(S->err, stmt->dbh, stmt, #name ": " #msg, S->last_err, __FILE__, __LINE__ TSRMLS_CC); \ + S->last_err = _oci_error(S->err, stmt->dbh, stmt, #name ": " #msg, S->last_err, 0, __FILE__, __LINE__ TSRMLS_CC); \ if (S->last_err) { \ return 0; \ } --- php_pdo_oci_int.h.orig 2007-01-01 01:36:05.000000000 -0800 +++ php_pdo_oci_int.h 2007-06-17 23:53:06.000000000 -0700 @@ -86,9 +86,10 @@ extern pdo_driver_t pdo_oci_driver; extern OCIEnv *pdo_oci_Env; -ub4 _oci_error(OCIError *err, pdo_dbh_t *dbh, pdo_stmt_t *stmt, char *what, sword status, const char *file, int line TSRMLS_DC); -#define oci_drv_error(w) _oci_error(H->err, dbh, NULL, w, H->last_err, __FILE__, __LINE__ TSRMLS_CC) -#define oci_stmt_error(w) _oci_error(S->err, stmt->dbh, stmt, w, S->last_err, __FILE__, __LINE__ TSRMLS_CC) +ub4 _oci_error(OCIError *err, pdo_dbh_t *dbh, pdo_stmt_t *stmt, char *what, sword status, int init, const char *file, int line TSRMLS_DC); +#define oci_init_error(w) _oci_error(H->err, dbh, NULL, w, H->last_err, 1, __FILE__, __LINE__ TSRMLS_CC) +#define oci_drv_error(w) _oci_error(H->err, dbh, NULL, w, H->last_err, 0, __FILE__, __LINE__ TSRMLS_CC) +#define oci_stmt_error(w) _oci_error(S->err, stmt->dbh, stmt, w, S->last_err, 0, __FILE__, __LINE__ TSRMLS_CC) extern struct pdo_stmt_methods oci_stmt_methods; Expected result: ---------------- For (i) the message should be: Connection failed: SQLSTATE[HY000]: OCINlsCharSetNameToId: unknown character set name (/home/cjones/phpsrc/php5/ext/pdo_oci/oci_driver.c:456) For (ii) the message should be: Connection failed: SQLSTATE[HY000]: OCIEnvNlsCreate: Check the character set is valid and that PHP has access to Oracle libraries and NLS data (/home/cjones/phpsrc/php5/ext/pdo_oci/oci_driver.c:461) Actual result: -------------- For (i) the invalid character set is ignored For (ii) Segmentation fault (core dumped)