diff --git a/ext/pdo_oci/oci_driver.c b/ext/pdo_oci/oci_driver.c index 367f478e12482..49c75cc81154e 100644 --- a/ext/pdo_oci/oci_driver.c +++ b/ext/pdo_oci/oci_driver.c @@ -699,6 +699,13 @@ static int pdo_oci_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ * goto cleanup; } + /* Get max character width */ + H->last_err = OCINlsNumericInfoGet(H->env, H->err, &H->max_char_width, OCI_NLS_CHARSET_MAXBYTESZ); + if (H->last_err) { + oci_drv_error("OCINlsNumericInfoGet: OCI_NLS_CHARSET_MAXBYTESZ"); + goto cleanup; + } + dbh->methods = &oci_methods; dbh->alloc_own_columns = 1; dbh->native_case = PDO_CASE_UPPER; diff --git a/ext/pdo_oci/oci_statement.c b/ext/pdo_oci/oci_statement.c index 5d34957885256..bf360f0dba8ce 100644 --- a/ext/pdo_oci/oci_statement.c +++ b/ext/pdo_oci/oci_statement.c @@ -602,9 +602,8 @@ static int oci_stmt_describe(pdo_stmt_t *stmt, int colno) /* {{{ */ } else { S->cols[colno].datalen = (ub4) col->maxlen; } - if (dtype == SQLT_BIN) { - S->cols[colno].datalen *= 3; - } + + S->cols[colno].datalen *= S->H->max_char_width; S->cols[colno].data = emalloc(S->cols[colno].datalen + 1); dtype = SQLT_CHR; diff --git a/ext/pdo_oci/php_pdo_oci_int.h b/ext/pdo_oci/php_pdo_oci_int.h index ab437c14a8174..2e8b0c0db8fec 100644 --- a/ext/pdo_oci/php_pdo_oci_int.h +++ b/ext/pdo_oci/php_pdo_oci_int.h @@ -38,6 +38,7 @@ typedef struct { ub4 prefetch; ub2 charset; sword last_err; + sb4 max_char_width; unsigned attached:1; unsigned _reserved:31; diff --git a/ext/pdo_oci/tests/bug54379.phpt b/ext/pdo_oci/tests/bug54379.phpt new file mode 100644 index 0000000000000..1eb70e30904ae --- /dev/null +++ b/ext/pdo_oci/tests/bug54379.phpt @@ -0,0 +1,47 @@ +--TEST-- +Bug #54379 (PDO_OCI: UTF-8 output gets truncated) +--SKIPIF-- + +--FILE-- +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + +try { + $db->exec("DROP TABLE test"); +} catch (Exception $e) { +} + +$db->exec("CREATE TABLE test (col1 NVARCHAR2(100))"); +$db->exec("INSERT INTO test VALUES('12345678901234567890')"); +$db->exec("INSERT INTO test VALUES('Русские символы по три байта')"); + +$stmt = $db->prepare("SELECT * FROM test"); + +$stmt->execute(); +var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + +$db->exec("DROP TABLE test"); + +?> +--EXPECTF-- +array(2) { + [0]=> + array(1) { + ["col1"]=> + string(20) "12345678901234567890" + } + [1]=> + array(1) { + ["col1"]=> + string(52) "Русские символы по три байта" + } +}