1
0
mirror of https://github.com/php/php-src.git synced 2026-04-03 14:12:38 +02:00

Merge branch 'PHP-7.0' of git.php.net:/php-src into PHP-7.0

* 'PHP-7.0' of git.php.net:/php-src:
  Remove __halt_compiler from semi-reserved tokens
  Fixed Bug #71974 Trans sid will always be send, even if cookies are available
  Optimized array_fill(). This is a perfect function for fast creation of packed arrays.
  Fixed build
  fix merge mistake
  fix tests
  PostgreSQL's PDOStatement::getColumnMeta() fills in table's name.
  fix indent
  Fixed bug #71978 (Existence of return type hint affects other compatibility rules)
  fix test
  fix bug #71667 (emulate how mssql extension names "computed" columns)
  update NEWS
  add 32-bit specific variont for #62498
  skip test on 32-bit
  make opcache lockfile path configurable
  return zvals instead of strings, cast or not based on stringify attribute
  fix test
  add skip slow test
This commit is contained in:
Xinchen Hui
2016-04-07 13:58:00 +08:00
26 changed files with 804 additions and 193 deletions

View File

@@ -80,7 +80,6 @@ class Obj
function __FILE__(){ echo __METHOD__, PHP_EOL; }
function __DIR__(){ echo __METHOD__, PHP_EOL; }
function __NAMESPACE__(){ echo __METHOD__, PHP_EOL; }
function __halt_compiler(){ echo __METHOD__, PHP_EOL; }
}
$obj = new Obj;
@@ -160,7 +159,6 @@ $obj->__LINE__();
$obj->__FILE__();
$obj->__DIR__();
$obj->__NAMESPACE__();
$obj->__halt_compiler();
echo "\nDone\n";
@@ -240,6 +238,5 @@ Obj::__LINE__
Obj::__FILE__
Obj::__DIR__
Obj::__NAMESPACE__
Obj::__halt_compiler
Done

View File

@@ -80,7 +80,6 @@ class Obj
static function __FILE__(){ echo __METHOD__, PHP_EOL; }
static function __DIR__(){ echo __METHOD__, PHP_EOL; }
static function __NAMESPACE__(){ echo __METHOD__, PHP_EOL; }
static function __halt_compiler(){ echo __METHOD__, PHP_EOL; }
}
Obj::empty();
@@ -158,7 +157,6 @@ Obj::__LINE__();
Obj::__FILE__();
Obj::__DIR__();
Obj::__NAMESPACE__();
Obj::__halt_compiler();
echo "\nDone\n";
@@ -238,6 +236,5 @@ Obj::__LINE__
Obj::__FILE__
Obj::__DIR__
Obj::__NAMESPACE__
Obj::__halt_compiler
Done

View File

@@ -79,7 +79,6 @@ class Obj
const __FILE__ = '__FILE__';
const __DIR__ = '__DIR__';
const __NAMESPACE__ = '__NAMESPACE__';
const __HALT_COMPILER = '__halt_compiler';
}
echo Obj::EMPTY, PHP_EOL;
@@ -156,7 +155,6 @@ echo Obj::__LINE__, PHP_EOL;
echo Obj::__FILE__, PHP_EOL;
echo Obj::__DIR__, PHP_EOL;
echo Obj::__NAMESPACE__, PHP_EOL;
echo Obj::__HALT_COMPILER, PHP_EOL;
echo "\nDone\n";
@@ -235,6 +233,5 @@ __LINE__
__FILE__
__DIR__
__NAMESPACE__
__halt_compiler
Done

View File

@@ -0,0 +1,21 @@
--TEST--
Bug #71978 (Existence of return type hint affects other compatibility rules)
--FILE--
<?php
class A {
function foo(int $a) {}
}
class B extends A {
function foo(string $a) {}
}
class A1 {
function foo(int $a): int {}
}
class B1 extends A1 {
function foo(string $a): int {}
}
?>
--EXPECTF--
Warning: Declaration of B::foo(string $a) should be compatible with A::foo(int $a) in %s on line %d
Warning: Declaration of B1::foo(string $a): int should be compatible with A1::foo(int $a): int in %s on line %d

View File

@@ -243,11 +243,6 @@ static int zend_do_perform_type_hint_check(const zend_function *fe, zend_arg_inf
return 0;
}
if (proto_arg_info->type_hint && proto_arg_info->allow_null && !fe_arg_info->allow_null) {
/* incompatible nullability */
return 0;
}
return 1;
}
/* }}} */
@@ -324,6 +319,11 @@ static zend_bool zend_do_perform_implementation_check(const zend_function *fe, c
return 0;
}
if (proto_arg_info->type_hint && proto_arg_info->allow_null && !fe_arg_info->allow_null) {
/* incompatible nullability */
return 0;
}
/* by-ref constraints on arguments are invariant */
if (fe_arg_info->pass_by_reference != proto_arg_info->pass_by_reference) {
return 0;
@@ -570,17 +570,31 @@ static void do_inheritance_check_on_method(zend_function *child, zend_function *
}
if (child->common.prototype && (
child->common.prototype->common.fn_flags & (ZEND_ACC_ABSTRACT | ZEND_ACC_HAS_RETURN_TYPE)
child->common.prototype->common.fn_flags & ZEND_ACC_ABSTRACT
)) {
if (UNEXPECTED(!zend_do_perform_implementation_check(child, child->common.prototype))) {
zend_string *method_prototype = zend_get_function_declaration(child->common.prototype);
zend_string *child_prototype = zend_get_function_declaration(child);
zend_error_noreturn(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s", ZSTR_VAL(child_prototype), ZSTR_VAL(method_prototype));
}
} else if (UNEXPECTED(!zend_do_perform_implementation_check(child, parent))) {
parent = child->common.prototype;
}
if (UNEXPECTED(!zend_do_perform_implementation_check(child, parent))) {
int error_level;
const char *error_verb;
zend_string *method_prototype = zend_get_function_declaration(parent);
zend_string *child_prototype = zend_get_function_declaration(child);
zend_error(E_WARNING, "Declaration of %s should be compatible with %s", ZSTR_VAL(child_prototype), ZSTR_VAL(method_prototype));
if (child->common.prototype && (
child->common.prototype->common.fn_flags & ZEND_ACC_ABSTRACT
)) {
error_level = E_COMPILE_ERROR;
error_verb = "must";
} else if ((parent->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) &&
(!(child->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
!zend_do_perform_type_hint_check(child, child->common.arg_info - 1, parent, parent->common.arg_info - 1))) {
error_level = E_COMPILE_ERROR;
error_verb = "must";
} else {
error_level = E_WARNING;
error_verb = "should";
}
zend_error(error_level, "Declaration of %s %s be compatible with %s", ZSTR_VAL(child_prototype), error_verb, ZSTR_VAL(method_prototype));
zend_string_free(child_prototype);
zend_string_free(method_prototype);
}

View File

@@ -272,7 +272,7 @@ reserved_non_modifiers:
| T_THROW | T_USE | T_INSTEADOF | T_GLOBAL | T_VAR | T_UNSET | T_ISSET | T_EMPTY | T_CONTINUE | T_GOTO
| T_FUNCTION | T_CONST | T_RETURN | T_PRINT | T_YIELD | T_LIST | T_SWITCH | T_ENDSWITCH | T_CASE | T_DEFAULT | T_BREAK
| T_ARRAY | T_CALLABLE | T_EXTENDS | T_IMPLEMENTS | T_NAMESPACE | T_TRAIT | T_INTERFACE | T_CLASS
| T_CLASS_C | T_TRAIT_C | T_FUNC_C | T_METHOD_C | T_LINE | T_FILE | T_DIR | T_NS_C | T_HALT_COMPILER
| T_CLASS_C | T_TRAIT_C | T_FUNC_C | T_METHOD_C | T_LINE | T_FILE | T_DIR | T_NS_C
;
semi_reserved:

View File

@@ -213,3 +213,6 @@ opcache.mmap_base
processes have to map shared memory into the same address space. This
directive allows to manually fix the "Unable to reattach to base address"
errors.
opcache.lockfile_path (default "/tmp")
Absolute path used to store shared lockfiles.

View File

@@ -217,6 +217,7 @@ typedef struct _zend_accel_directives {
zend_long max_file_size;
zend_long interned_strings_buffer;
char *restrict_api;
char *lockfile_path;
#ifdef HAVE_OPCACHE_FILE_CACHE
char *file_cache;
zend_bool file_cache_only;

View File

@@ -298,6 +298,7 @@ ZEND_INI_BEGIN()
STD_PHP_INI_BOOLEAN("opcache.enable_cli" , "0" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.enable_cli, zend_accel_globals, accel_globals)
STD_PHP_INI_ENTRY("opcache.error_log" , "" , PHP_INI_SYSTEM, OnUpdateString, accel_directives.error_log, zend_accel_globals, accel_globals)
STD_PHP_INI_ENTRY("opcache.restrict_api" , "" , PHP_INI_SYSTEM, OnUpdateString, accel_directives.restrict_api, zend_accel_globals, accel_globals)
STD_PHP_INI_ENTRY("opcache.lockfile_path" , "/tmp" , PHP_INI_SYSTEM, OnUpdateString, accel_directives.lockfile_path, zend_accel_globals, accel_globals)
#ifdef ZEND_WIN32
STD_PHP_INI_ENTRY("opcache.mmap_base", NULL, PHP_INI_SYSTEM, OnUpdateString, accel_directives.mmap_base, zend_accel_globals, accel_globals)
@@ -710,6 +711,7 @@ static ZEND_FUNCTION(opcache_get_configuration)
add_assoc_bool(&directives, "opcache.fast_shutdown", ZCG(accel_directives).fast_shutdown);
add_assoc_bool(&directives, "opcache.enable_file_override", ZCG(accel_directives).file_override_enabled);
add_assoc_long(&directives, "opcache.optimization_level", ZCG(accel_directives).optimization_level);
add_assoc_string(&directives, "opcache.lockfile_path", STRING_NOT_NULL(ZCG(accel_directives).lockfile_path));
#ifdef HAVE_OPCACHE_FILE_CACHE
add_assoc_string(&directives, "opcache.file_cache", ZCG(accel_directives).file_cache ? ZCG(accel_directives).file_cache : "");

View File

@@ -38,7 +38,6 @@
# include "sys/mman.h"
#endif
#define TMP_DIR "/tmp"
#define SEM_FILENAME_PREFIX ".ZendSem."
#define S_H(s) g_shared_alloc_handler->s
@@ -55,7 +54,7 @@ zend_smm_shared_globals *smm_shared_globals;
static MUTEX_T zts_lock;
#endif
int lock_file;
static char lockfile_name[sizeof(TMP_DIR) + sizeof(SEM_FILENAME_PREFIX) + 8];
static char lockfile_name[MAXPATHLEN];
#endif
static const zend_shared_memory_handler_entry handler_table[] = {
@@ -75,7 +74,7 @@ static const zend_shared_memory_handler_entry handler_table[] = {
};
#ifndef ZEND_WIN32
void zend_shared_alloc_create_lock(void)
void zend_shared_alloc_create_lock(char *lockfile_path)
{
int val;
@@ -83,7 +82,7 @@ void zend_shared_alloc_create_lock(void)
zts_lock = tsrm_mutex_alloc();
#endif
sprintf(lockfile_name, "%s/%sXXXXXX", TMP_DIR, SEM_FILENAME_PREFIX);
snprintf(lockfile_name, sizeof(lockfile_name), "%s/%sXXXXXX", lockfile_path, SEM_FILENAME_PREFIX);
lock_file = mkstemp(lockfile_name);
fchmod(lock_file, 0666);
@@ -163,7 +162,11 @@ int zend_shared_alloc_startup(size_t requested_size)
smm_shared_globals = &tmp_shared_globals;
ZSMMG(shared_free) = requested_size; /* goes to tmp_shared_globals.shared_free */
#ifndef ZEND_WIN32
zend_shared_alloc_create_lock(ZCG(accel_directives).lockfile_path);
#else
zend_shared_alloc_create_lock();
#endif
if (ZCG(accel_directives).memory_model && ZCG(accel_directives).memory_model[0]) {
char *model = ZCG(accel_directives).memory_model;

View File

@@ -101,6 +101,7 @@ static int dblib_handle_preparer(pdo_dbh_t *dbh, const char *sql, size_t sql_len
stmt->driver_data = S;
stmt->methods = &dblib_stmt_methods;
stmt->supports_placeholders = PDO_PLACEHOLDER_NONE;
S->computed_column_name_count = 0;
S->err.sqlstate = stmt->error_code;
return 1;

View File

@@ -218,21 +218,31 @@ static int pdo_dblib_stmt_describe(pdo_stmt_t *stmt, int colno)
return FAILURE;
}
if (colno == 0) {
S->computed_column_name_count = 0;
}
col = &stmt->columns[colno];
fname = (char*)dbcolname(H->link, colno+1);
if (fname && *fname) {
col->name = zend_string_init(fname, strlen(fname), 0);
} else {
char buf[16];
int len;
len = snprintf(buf, sizeof(buf), "computed%d", colno);
col->name = zend_string_init(buf, len, 0);
if (S->computed_column_name_count > 0) {
char buf[16];
int len;
len = snprintf(buf, sizeof(buf), "computed%d", S->computed_column_name_count);
col->name = zend_string_init(buf, len, 0);
} else {
col->name = zend_string_init("computed", strlen("computed"), 0);
}
S->computed_column_name_count++;
}
col->maxlen = dbcollen(H->link, colno+1);
col->param_type = PDO_PARAM_STR;
col->param_type = PDO_PARAM_ZVAL;
return 1;
}
@@ -245,78 +255,161 @@ static int pdo_dblib_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr,
pdo_dblib_db_handle *H = S->H;
int coltype;
unsigned int tmp_len;
char *tmp_ptr = NULL;
char *data, *tmp_data;
unsigned int data_len, tmp_data_len;
zval *zv = NULL;
coltype = dbcoltype(H->link, colno+1);
data = dbdata(H->link, colno+1);
data_len = dbdatlen(H->link, colno+1);
*len = dbdatlen(H->link, colno+1);
*ptr = dbdata(H->link, colno+1);
if (data_len != 0 || data != NULL) {
if (stmt->dbh->stringify) {
switch (coltype) {
case SQLFLT4:
case SQLFLT8:
case SQLINT4:
case SQLINT2:
case SQLINT1:
case SQLBIT: {
if (dbwillconvert(coltype, SQLCHAR)) {
tmp_data_len = 32 + (2 * (data_len)); /* FIXME: We allocate more than we need here */
tmp_data = emalloc(tmp_data_len);
data_len = dbconvert(NULL, coltype, data, data_len, SQLCHAR, tmp_data, -1);
if (*len == 0 && *ptr == NULL) {
return 1;
zv = emalloc(sizeof(zval));
ZVAL_STRING(zv, tmp_data);
efree(tmp_data);
}
break;
}
}
}
if (!zv) {
switch (coltype) {
case SQLCHAR:
case SQLVARCHAR:
case SQLTEXT: {
#if ilia_0
while (data_len>0 && data[data_len-1] == ' ') { /* nuke trailing whitespace */
data_len--;
}
#endif
}
case SQLVARBINARY:
case SQLBINARY:
case SQLIMAGE: {
zv = emalloc(sizeof(zval));
ZVAL_STRINGL(zv, data, data_len);
break;
}
case SQLDATETIME:
case SQLDATETIM4: {
int dl;
DBDATEREC di;
DBDATEREC dt;
dbconvert(H->link, coltype, data, -1, SQLDATETIME, (LPBYTE) &dt, -1);
dbdatecrack(H->link, &di, (DBDATETIME *) &dt);
dl = spprintf(&tmp_data, 20, "%d-%02d-%02d %02d:%02d:%02d",
#if defined(PHP_DBLIB_IS_MSSQL) || defined(MSDBLIB)
di.year, di.month, di.day, di.hour, di.minute, di.second
#else
di.dateyear, di.datemonth+1, di.datedmonth, di.datehour, di.dateminute, di.datesecond
#endif
);
zv = emalloc(sizeof(zval));
ZVAL_STRINGL(zv, tmp_data, dl);
efree(tmp_data);
break;
}
case SQLFLT4: {
zv = emalloc(sizeof(zval));
ZVAL_DOUBLE(zv, (double) (*(DBFLT4 *) data));
break;
}
case SQLFLT8: {
zv = emalloc(sizeof(zval));
ZVAL_DOUBLE(zv, (double) (*(DBFLT8 *) data));
break;
}
case SQLINT4: {
zv = emalloc(sizeof(zval));
ZVAL_LONG(zv, (long) ((int) *(DBINT *) data));
break;
}
case SQLINT2: {
zv = emalloc(sizeof(zval));
ZVAL_LONG(zv, (long) ((int) *(DBSMALLINT *) data));
break;
}
case SQLINT1:
case SQLBIT: {
zv = emalloc(sizeof(zval));
ZVAL_LONG(zv, (long) ((int) *(DBTINYINT *) data));
break;
}
case SQLMONEY:
case SQLMONEY4:
case SQLMONEYN: {
DBFLT8 money_value;
dbconvert(NULL, coltype, data, 8, SQLFLT8, (LPBYTE)&money_value, -1);
zv = emalloc(sizeof(zval));
ZVAL_DOUBLE(zv, money_value);
if (stmt->dbh->stringify) {
convert_to_string(zv);
}
break;
}
#ifdef SQLUNIQUE
case SQLUNIQUE: {
#else
case 36: { /* FreeTDS hack */
#endif
zv = emalloc(sizeof(zval));
ZVAL_STRINGL(zv, data, 16); /* uniqueidentifier is a 16-byte binary number */
break;
}
default: {
if (dbwillconvert(coltype, SQLCHAR)) {
tmp_data_len = 32 + (2 * (data_len)); /* FIXME: We allocate more than we need here */
tmp_data = emalloc(tmp_data_len);
data_len = dbconvert(NULL, coltype, data, data_len, SQLCHAR, tmp_data, -1);
zv = emalloc(sizeof(zval));
ZVAL_STRING(zv, tmp_data);
efree(tmp_data);
}
break;
}
}
}
}
switch (coltype) {
case SQLVARBINARY:
case SQLBINARY:
case SQLIMAGE:
case SQLTEXT:
/* FIXME: Above types should be returned as a stream as they can be VERY large */
case SQLCHAR:
case SQLVARCHAR:
tmp_ptr = emalloc(*len + 1);
memcpy(tmp_ptr, *ptr, *len);
tmp_ptr[*len] = '\0';
*ptr = tmp_ptr;
break;
case SQLMONEY:
case SQLMONEY4:
case SQLMONEYN: {
DBFLT8 money_value;
dbconvert(NULL, coltype, *ptr, *len, SQLFLT8, (LPBYTE)&money_value, 8);
*len = spprintf(&tmp_ptr, 0, "%.4f", money_value);
*ptr = tmp_ptr;
break;
}
case SQLUNIQUE: {
*len = 37;
tmp_ptr = emalloc(*len + 1);
*len = dbconvert(NULL, SQLUNIQUE, *ptr, *len, SQLCHAR, tmp_ptr, *len);
php_strtoupper(tmp_ptr, *len);
tmp_ptr[36] = '\0';
*ptr = tmp_ptr;
break;
}
case SQLDATETIM4:
case SQLDATETIME: {
DBDATETIME dt;
DBDATEREC di;
dbconvert(H->link, coltype, (BYTE*) *ptr, -1, SQLDATETIME, (LPBYTE) &dt, -1);
dbdatecrack(H->link, &di, &dt);
*len = spprintf((char**) &tmp_ptr, 20, "%d-%02d-%02d %02d:%02d:%02d",
#if defined(PHP_DBLIB_IS_MSSQL) || defined(MSDBLIB)
di.year, di.month, di.day, di.hour, di.minute, di.second
#else
di.dateyear, di.datemonth+1, di.datedmonth, di.datehour, di.dateminute, di.datesecond
#endif
);
*ptr = (char*) tmp_ptr;
break;
}
default:
if (dbwillconvert(coltype, SQLCHAR)) {
tmp_len = 32 + (2 * (*len)); /* FIXME: We allocate more than we need here */
tmp_ptr = emalloc(tmp_len);
*len = dbconvert(NULL, coltype, *ptr, *len, SQLCHAR, tmp_ptr, -1);
*ptr = tmp_ptr;
} else {
*len = 0; /* FIXME: Silently fails and returns null on conversion errors */
*ptr = NULL;
}
if (zv != NULL) {
*ptr = (char*)zv;
*len = sizeof(zval);
} else {
*ptr = NULL;
*len = 0;
}
*caller_frees = 1;
@@ -335,6 +428,7 @@ static int pdo_dblib_stmt_get_column_meta(pdo_stmt_t *stmt, zend_long colno, zva
pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
pdo_dblib_db_handle *H = S->H;
DBTYPEINFO* dbtypeinfo;
int coltype;
if(colno >= stmt->column_count || colno < 0) {
return FAILURE;
@@ -346,14 +440,28 @@ static int pdo_dblib_stmt_get_column_meta(pdo_stmt_t *stmt, zend_long colno, zva
if(!dbtypeinfo) return FAILURE;
coltype = dbcoltype(H->link, colno+1);
add_assoc_long(return_value, "max_length", dbcollen(H->link, colno+1) );
add_assoc_long(return_value, "precision", (int) dbtypeinfo->precision );
add_assoc_long(return_value, "scale", (int) dbtypeinfo->scale );
add_assoc_string(return_value, "column_source", dbcolsource(H->link, colno+1));
add_assoc_string(return_value, "native_type", pdo_dblib_get_field_name(dbcoltype(H->link, colno+1)));
add_assoc_long(return_value, "native_type_id", dbcoltype(H->link, colno+1));
add_assoc_string(return_value, "native_type", pdo_dblib_get_field_name(coltype));
add_assoc_long(return_value, "native_type_id", coltype);
add_assoc_long(return_value, "native_usertype_id", dbcolutype(H->link, colno+1));
switch (coltype) {
case SQLBIT:
case SQLINT1:
case SQLINT2:
case SQLINT4:
add_assoc_long(return_value, "pdo_type", PDO_PARAM_INT);
break;
default:
add_assoc_long(return_value, "pdo_type", PDO_PARAM_STR);
break;
}
return 1;
}

View File

@@ -118,6 +118,7 @@ typedef struct {
typedef struct {
pdo_dblib_db_handle *H;
pdo_dblib_err err;
unsigned int computed_column_name_count;
} pdo_dblib_stmt;
typedef struct {

View File

@@ -37,21 +37,21 @@ array(4) {
[0]=>
array(1) {
["val"]=>
string(1) "1"
int(1)
}
[1]=>
array(1) {
["val"]=>
string(1) "2"
int(2)
}
[2]=>
array(1) {
["val"]=>
string(1) "3"
int(3)
}
[3]=>
array(1) {
["val"]=>
string(1) "4"
int(4)
}
}

View File

@@ -14,8 +14,8 @@ $stmt->execute();
var_dump($stmt->getColumnMeta(0));
$stmt = null;
?>
--EXPECT--
array(8) {
--EXPECTF--
array(10) {
["max_length"]=>
int(255)
["precision"]=>
@@ -26,10 +26,14 @@ array(8) {
string(13) "TABLE_CATALOG"
["native_type"]=>
string(4) "char"
["native_type_id"]=>
int(%d)
["native_usertype_id"]=>
int(%d)
["pdo_type"]=>
int(2)
["name"]=>
string(13) "TABLE_CATALOG"
["len"]=>
int(255)
["pdo_type"]=>
int(2)
}

View File

@@ -23,21 +23,21 @@ array(3) {
[0]=>
array(2) {
["My Field"]=>
string(1) "1"
int(1)
["Another Field"]=>
string(11) "test_string"
}
[1]=>
array(2) {
["My Field"]=>
string(1) "2"
int(2)
["Another Field"]=>
string(11) "test_string"
}
[2]=>
array(2) {
["My Field"]=>
string(1) "3"
int(3)
["Another Field"]=>
string(11) "test_string"
}

View File

@@ -21,7 +21,7 @@ Array
(
[0] => Array
(
[computed0] => 1
[computed] => 1
[0] => 1
)

View File

@@ -0,0 +1,34 @@
--TEST--
PDO_DBLIB: Emulate how mssql extension names "computed" columns
--SKIPIF--
<?php
if (!extension_loaded('pdo_dblib')) die('skip not loaded');
require dirname(__FILE__) . '/config.inc';
?>
--FILE--
<?php
require dirname(__FILE__) . '/config.inc';
$stmt = $db->prepare("SELECT 1, 2 AS named, 3");
$stmt->execute();
var_dump($stmt->fetchAll());
?>
--EXPECT--
array(1) {
[0]=>
array(6) {
["computed"]=>
string(1) "1"
[0]=>
string(1) "1"
["named"]=>
string(1) "2"
[1]=>
string(1) "2"
["computed1"]=>
string(1) "3"
[2]=>
string(1) "3"
}
}

View File

@@ -3,6 +3,7 @@ PDO_DBLIB: Set query timeouts
--SKIPIF--
<?php
if (!extension_loaded('pdo_dblib')) die('skip not loaded');
if (getenv("SKIP_SLOW_TESTS")) die("skip slow test");
require dirname(__FILE__) . '/config.inc';
?>
--FILE--

View File

@@ -0,0 +1,66 @@
--TEST--
PDO_DBLIB: Column data types, with or without stringifying
--SKIPIF--
<?php
if (!extension_loaded('pdo_dblib')) die('skip not loaded');
require __DIR__ . '/config.inc';
?>
--FILE--
<?php
require __DIR__ . '/config.inc';
$sql = "
SELECT
'foo' AS [char],
CAST('2030-01-01 23:59:59' AS DATETIME) AS [datetime],
CAST(0 AS BIT) AS [false],
10.5 AS [float],
1000 AS [int],
CAST(10.5 AS MONEY) AS [money],
CAST('1950-01-18 23:00:00' AS SMALLDATETIME) as [smalldatetime],
CAST(1 AS BIT) AS [true]
";
$stmt = $db->query($sql);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
var_dump($row['char'] === 'foo');
var_dump($row['datetime'] === '2030-01-01 23:59:59');
var_dump($row['false'] === 0);
var_dump($row['float'] === 10.5);
var_dump($row['int'] === 1000);
var_dump($row['money'] === 10.5);
var_dump($row['smalldatetime'] === '1950-01-18 23:00:00');
var_dump($row['true'] === 1);
$db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true);
$stmt = $db->query($sql);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
var_dump($row['char'] === 'foo');
var_dump($row['datetime'] === '2030-01-01 23:59:59');
var_dump($row['false'] === '0');
var_dump($row['float'] === '10.5');
var_dump($row['int'] === '1000');
var_dump($row['money'] === '10.5');
var_dump($row['smalldatetime'] === '1950-01-18 23:00:00');
var_dump($row['true'] === '1');
?>
--EXPECT--
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)

View File

@@ -587,12 +587,40 @@ static int pgsql_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, zend_ulon
return 1;
}
static zend_always_inline char * pdo_pgsql_translate_oid_to_table(Oid oid, PGconn *conn)
{
char *table_name = NULL;
PGresult *tmp_res;
char *querystr = NULL;
spprintf(&querystr, 0, "SELECT RELNAME FROM PG_CLASS WHERE OID=%d", oid);
if ((tmp_res = PQexec(conn, querystr)) == NULL || PQresultStatus(tmp_res) != PGRES_TUPLES_OK) {
if (tmp_res) {
PQclear(tmp_res);
}
efree(querystr);
return 0;
}
efree(querystr);
if ((table_name = PQgetvalue(tmp_res, 0, 0)) == NULL) {
PQclear(tmp_res);
return 0;
}
PQclear(tmp_res);
return table_name;
}
static int pgsql_stmt_get_column_meta(pdo_stmt_t *stmt, zend_long colno, zval *return_value)
{
pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data;
PGresult *res;
char *q=NULL;
ExecStatusType status;
Oid table_oid;
char *table_name=NULL;
if (!S->result) {
return FAILURE;
@@ -605,46 +633,53 @@ static int pgsql_stmt_get_column_meta(pdo_stmt_t *stmt, zend_long colno, zval *r
array_init(return_value);
add_assoc_long(return_value, "pgsql:oid", S->cols[colno].pgsql_type);
switch (S->cols[colno].pgsql_type) {
case BOOLOID:
add_assoc_string(return_value, "native_type", BOOLLABEL);
break;
case BYTEAOID:
add_assoc_string(return_value, "native_type", BYTEALABEL);
break;
case INT8OID:
add_assoc_string(return_value, "native_type", INT8LABEL);
break;
case INT2OID:
add_assoc_string(return_value, "native_type", INT2LABEL);
break;
case INT4OID:
add_assoc_string(return_value, "native_type", INT4LABEL);
break;
case TEXTOID:
add_assoc_string(return_value, "native_type", TEXTLABEL);
break;
case VARCHAROID:
add_assoc_string(return_value, "native_type", VARCHARLABEL);
break;
case DATEOID:
add_assoc_string(return_value, "native_type", DATELABEL);
break;
case TIMESTAMPOID:
add_assoc_string(return_value, "native_type", TIMESTAMPLABEL);
break;
default:
/* Fetch metadata from Postgres system catalogue */
spprintf(&q, 0, "SELECT TYPNAME FROM PG_TYPE WHERE OID=%u", S->cols[colno].pgsql_type);
res = PQexec(S->H->server, q);
efree(q);
status = PQresultStatus(res);
if (status == PGRES_TUPLES_OK && 1 == PQntuples(res)) {
add_assoc_string(return_value, "native_type", PQgetvalue(res, 0, 0));
}
PQclear(res);
}
return 1;
table_oid = PQftable(S->result, colno);
add_assoc_long(return_value, "pgsql:table_oid", table_oid);
table_name = pdo_pgsql_translate_oid_to_table(table_oid, S->H->server);
if (table_name) {
add_assoc_string(return_value, "table", table_name);
}
switch (S->cols[colno].pgsql_type) {
case BOOLOID:
add_assoc_string(return_value, "native_type", BOOLLABEL);
break;
case BYTEAOID:
add_assoc_string(return_value, "native_type", BYTEALABEL);
break;
case INT8OID:
add_assoc_string(return_value, "native_type", INT8LABEL);
break;
case INT2OID:
add_assoc_string(return_value, "native_type", INT2LABEL);
break;
case INT4OID:
add_assoc_string(return_value, "native_type", INT4LABEL);
break;
case TEXTOID:
add_assoc_string(return_value, "native_type", TEXTLABEL);
break;
case VARCHAROID:
add_assoc_string(return_value, "native_type", VARCHARLABEL);
break;
case DATEOID:
add_assoc_string(return_value, "native_type", DATELABEL);
break;
case TIMESTAMPOID:
add_assoc_string(return_value, "native_type", TIMESTAMPLABEL);
break;
default:
/* Fetch metadata from Postgres system catalogue */
spprintf(&q, 0, "SELECT TYPNAME FROM PG_TYPE WHERE OID=%u", S->cols[colno].pgsql_type);
res = PQexec(S->H->server, q);
efree(q);
status = PQresultStatus(res);
if (status == PGRES_TUPLES_OK && 1 == PQntuples(res)) {
add_assoc_string(return_value, "native_type", PQgetvalue(res, 0, 0));
}
PQclear(res);
}
return 1;
}
static int pdo_pgsql_stmt_cursor_closer(pdo_stmt_t *stmt)

View File

@@ -0,0 +1,221 @@
--TEST--
PDO PgSQL Bug #62498 (pdo_pgsql inefficient when getColumnMeta() is used), 32-bit
--SKIPIF--
<?php
if (!extension_loaded('pdo') || !extension_loaded('pdo_pgsql')) die('skip not loaded');
require dirname(__FILE__) . '/config.inc';
require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
PDOTest::skip();
if (PHP_INT_SIZE > 4) die("skip relevant for 32-bit only");
?>
--FILE--
<?php
echo "Begin test...\n";
require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
$db->setAttribute (\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
// create the table
$db->exec("CREATE TEMPORARY TABLE bugtest_62498 (int2col INT2, int4col INT4, int8col INT8, stringcol VARCHAR(255), boolcol BOOLEAN, datecol DATE, textcol TEXT, tscol TIMESTAMP, byteacol BYTEA)");
// insert some data
$statement = $db->prepare("INSERT INTO bugtest_62498 (int2col, int4col, int8col, stringcol, boolcol, datecol, textcol, tscol, byteacol) VALUES (:int2val, :int4val, :int8val, :stringval, :boolval, :dateval, :textval, :tsval, :byteaval)");
$vals = array(
"int2val" => "42",
"int4val" => "42",
"int8val" => "42",
"stringval" => "The Answer",
"boolval" => true,
"dateval" => '2015-12-14',
"textval" => "some text",
"tsval" => 19990108,
"byteaval" => 0,
);
$statement->execute($vals);
$select = $db->query('SELECT int2col, int4col, int8col, stringcol, boolcol, datecol, textcol, tscol, byteacol FROM bugtest_62498');
$meta = [];
for ($i=0; $i < count($vals); $i++) {
$meta[] = $select->getColumnMeta($i);
}
var_dump($meta);
?>
Done
--EXPECTF--
Begin test...
array(9) {
[0]=>
array(8) {
["pgsql:oid"]=>
int(21)
["pgsql:table_oid"]=>
int(%d)
["table"]=>
string(13) "bugtest_62498"
["native_type"]=>
string(4) "int2"
["name"]=>
string(7) "int2col"
["len"]=>
int(2)
["precision"]=>
int(-1)
["pdo_type"]=>
int(1)
}
[1]=>
array(8) {
["pgsql:oid"]=>
int(23)
["pgsql:table_oid"]=>
int(%d)
["table"]=>
string(13) "bugtest_62498"
["native_type"]=>
string(4) "int4"
["name"]=>
string(7) "int4col"
["len"]=>
int(4)
["precision"]=>
int(-1)
["pdo_type"]=>
int(1)
}
[2]=>
array(8) {
["pgsql:oid"]=>
int(20)
["pgsql:table_oid"]=>
int(%d)
["table"]=>
string(13) "bugtest_62498"
["native_type"]=>
string(4) "int8"
["name"]=>
string(7) "int8col"
["len"]=>
int(8)
["precision"]=>
int(-1)
["pdo_type"]=>
int(2)
}
[3]=>
array(8) {
["pgsql:oid"]=>
int(1043)
["pgsql:table_oid"]=>
int(%d)
["table"]=>
string(13) "bugtest_62498"
["native_type"]=>
string(7) "varchar"
["name"]=>
string(9) "stringcol"
["len"]=>
int(-1)
["precision"]=>
int(259)
["pdo_type"]=>
int(2)
}
[4]=>
array(8) {
["pgsql:oid"]=>
int(16)
["pgsql:table_oid"]=>
int(%d)
["table"]=>
string(13) "bugtest_62498"
["native_type"]=>
string(4) "bool"
["name"]=>
string(7) "boolcol"
["len"]=>
int(1)
["precision"]=>
int(-1)
["pdo_type"]=>
int(5)
}
[5]=>
array(8) {
["pgsql:oid"]=>
int(1082)
["pgsql:table_oid"]=>
int(%d)
["table"]=>
string(13) "bugtest_62498"
["native_type"]=>
string(4) "date"
["name"]=>
string(7) "datecol"
["len"]=>
int(4)
["precision"]=>
int(-1)
["pdo_type"]=>
int(2)
}
[6]=>
array(8) {
["pgsql:oid"]=>
int(25)
["pgsql:table_oid"]=>
int(%d)
["table"]=>
string(13) "bugtest_62498"
["native_type"]=>
string(4) "text"
["name"]=>
string(7) "textcol"
["len"]=>
int(-1)
["precision"]=>
int(-1)
["pdo_type"]=>
int(2)
}
[7]=>
array(8) {
["pgsql:oid"]=>
int(1114)
["pgsql:table_oid"]=>
int(%d)
["table"]=>
string(13) "bugtest_62498"
["native_type"]=>
string(9) "timestamp"
["name"]=>
string(5) "tscol"
["len"]=>
int(8)
["precision"]=>
int(-1)
["pdo_type"]=>
int(2)
}
[8]=>
array(8) {
["pgsql:oid"]=>
int(17)
["pgsql:table_oid"]=>
int(%d)
["table"]=>
string(13) "bugtest_62498"
["native_type"]=>
string(5) "bytea"
["name"]=>
string(8) "byteacol"
["len"]=>
int(-1)
["precision"]=>
int(-1)
["pdo_type"]=>
int(3)
}
}
Done

View File

@@ -1,11 +1,12 @@
--TEST--
PDO PgSQL Bug #62498 (pdo_pgsql inefficient when getColumnMeta() is used)
PDO PgSQL Bug #62498 (pdo_pgsql inefficient when getColumnMeta() is used), 64-bit
--SKIPIF--
<?php
if (!extension_loaded('pdo') || !extension_loaded('pdo_pgsql')) die('skip not loaded');
require dirname(__FILE__) . '/config.inc';
require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
PDOTest::skip();
if (PHP_INT_SIZE < 8) die("skip valid for 64-bit only");
?>
--FILE--
<?php
@@ -42,13 +43,17 @@ var_dump($meta);
?>
Done
--EXPECT--
--EXPECTF--
Begin test...
array(9) {
[0]=>
array(6) {
array(8) {
["pgsql:oid"]=>
int(21)
["pgsql:table_oid"]=>
int(%d)
["table"]=>
string(13) "bugtest_62498"
["native_type"]=>
string(4) "int2"
["name"]=>
@@ -61,9 +66,13 @@ array(9) {
int(1)
}
[1]=>
array(6) {
array(8) {
["pgsql:oid"]=>
int(23)
["pgsql:table_oid"]=>
int(%d)
["table"]=>
string(13) "bugtest_62498"
["native_type"]=>
string(4) "int4"
["name"]=>
@@ -76,9 +85,13 @@ array(9) {
int(1)
}
[2]=>
array(6) {
array(8) {
["pgsql:oid"]=>
int(20)
["pgsql:table_oid"]=>
int(%d)
["table"]=>
string(13) "bugtest_62498"
["native_type"]=>
string(4) "int8"
["name"]=>
@@ -91,9 +104,13 @@ array(9) {
int(1)
}
[3]=>
array(6) {
array(8) {
["pgsql:oid"]=>
int(1043)
["pgsql:table_oid"]=>
int(%d)
["table"]=>
string(13) "bugtest_62498"
["native_type"]=>
string(7) "varchar"
["name"]=>
@@ -106,9 +123,13 @@ array(9) {
int(2)
}
[4]=>
array(6) {
array(8) {
["pgsql:oid"]=>
int(16)
["pgsql:table_oid"]=>
int(%d)
["table"]=>
string(13) "bugtest_62498"
["native_type"]=>
string(4) "bool"
["name"]=>
@@ -121,9 +142,13 @@ array(9) {
int(5)
}
[5]=>
array(6) {
array(8) {
["pgsql:oid"]=>
int(1082)
["pgsql:table_oid"]=>
int(%d)
["table"]=>
string(13) "bugtest_62498"
["native_type"]=>
string(4) "date"
["name"]=>
@@ -136,9 +161,13 @@ array(9) {
int(2)
}
[6]=>
array(6) {
array(8) {
["pgsql:oid"]=>
int(25)
["pgsql:table_oid"]=>
int(%d)
["table"]=>
string(13) "bugtest_62498"
["native_type"]=>
string(4) "text"
["name"]=>
@@ -151,9 +180,13 @@ array(9) {
int(2)
}
[7]=>
array(6) {
array(8) {
["pgsql:oid"]=>
int(1114)
["pgsql:table_oid"]=>
int(%d)
["table"]=>
string(13) "bugtest_62498"
["native_type"]=>
string(9) "timestamp"
["name"]=>
@@ -166,9 +199,13 @@ array(9) {
int(2)
}
[8]=>
array(6) {
array(8) {
["pgsql:oid"]=>
int(17)
["pgsql:table_oid"]=>
int(%d)
["table"]=>
string(13) "bugtest_62498"
["native_type"]=>
string(5) "bytea"
["name"]=>

View File

@@ -1483,7 +1483,7 @@ static void ppid2sid(zval *ppid) {
PHPAPI void php_session_reset_id(void) /* {{{ */
{
int module_number = PS(module_number);
zval *sid;
zval *sid, *data, *ppid;
if (!PS(id)) {
php_error_docref(NULL, E_WARNING, "Cannot set session ID - session ID is not initialized");
@@ -1523,13 +1523,20 @@ PHPAPI void php_session_reset_id(void) /* {{{ */
}
}
if (APPLY_TRANS_SID) {
/* FIXME: Resetting vars are required when
session is stop/start/regenerated. However,
php_url_scanner_reset_vars() resets all vars
including other URL rewrites set by elsewhere. */
/* php_url_scanner_reset_vars(); */
php_url_scanner_add_var(PS(session_name), strlen(PS(session_name)), ZSTR_VAL(PS(id)), ZSTR_LEN(PS(id)), 1);
/* Apply trans sid if sid cookie is not set */
if (APPLY_TRANS_SID
&& (data = zend_hash_str_find(&EG(symbol_table), "_COOKIE", sizeof("_COOKIE") - 1))) {
ZVAL_DEREF(data);
if (Z_TYPE_P(data) == IS_ARRAY && (ppid = zend_hash_str_find(Z_ARRVAL_P(data), PS(session_name), strlen(PS(session_name))))) {
ZVAL_DEREF(ppid);
} else {
/* FIXME: Resetting vars are required when
session is stop/start/regenerated. However,
php_url_scanner_reset_vars() resets all vars
including other URL rewrites set by elsewhere. */
/* php_url_scanner_reset_vars(); */
php_url_scanner_add_var(PS(session_name), strlen(PS(session_name)), ZSTR_VAL(PS(id)), ZSTR_LEN(PS(id)), 1);
}
}
}
/* }}} */

View File

@@ -0,0 +1,23 @@
--TEST--
Bug #71974 Trans sid will always be send, even if cookies are available
--SKIPIF--
<?php include('skipif.inc'); ?>
--INI--
session.save_handler=files
session.auto_start=0
session.use_cookies=1
session.use_only_cookies=0
session.use_trans_sid=1
session.use_strict_mode=0
--COOKIE--
PHPSESSID=1234567890123456789012345678901234567890
--FILE--
<?php
ob_start();
session_start()
?>
<a href="some.php">abc</a>
--EXPECTF--
<a href="some.php">abc</a>

View File

@@ -2000,34 +2000,72 @@ PHP_FUNCTION(array_fill)
zval *val;
zend_long start_key, num;
#ifndef FAST_ZPP
if (zend_parse_parameters(ZEND_NUM_ARGS(), "llz", &start_key, &num, &val) == FAILURE) {
return;
}
#else
ZEND_PARSE_PARAMETERS_START(3, 3)
Z_PARAM_LONG(start_key)
Z_PARAM_LONG(num)
Z_PARAM_ZVAL(val)
ZEND_PARSE_PARAMETERS_END();
#endif
if (num < 0) {
php_error_docref(NULL, E_WARNING, "Number of elements can't be negative");
RETURN_FALSE;
}
/* allocate an array for return */
array_init_size(return_value, (uint32_t)num);
if (num == 0) {
return;
}
num--;
zend_hash_index_update(Z_ARRVAL_P(return_value), start_key, val);
Z_TRY_ADDREF_P(val);
while (num--) {
if (zend_hash_next_index_insert(Z_ARRVAL_P(return_value), val) != NULL) {
Z_TRY_ADDREF_P(val);
} else {
zval_dtor(return_value);
if (EXPECTED(num > 0)) {
if (sizeof(num) > 4 && UNEXPECTED(EXPECTED(num > 0x7fffffff))) {
php_error_docref(NULL, E_WARNING, "Too many elements");
RETURN_FALSE;
} else if (UNEXPECTED(start_key > ZEND_LONG_MAX - num + 1)) {
php_error_docref(NULL, E_WARNING, "Cannot add element to the array as the next element is already occupied");
RETURN_FALSE;
} else if (EXPECTED(start_key >= 0) && EXPECTED(start_key < num)) {
/* create packed array */
Bucket *p;
zend_long n;
array_init_size(return_value, (uint32_t)(start_key + num));
zend_hash_real_init(Z_ARRVAL_P(return_value), 1);
Z_ARRVAL_P(return_value)->nNumUsed = start_key + num;
Z_ARRVAL_P(return_value)->nNumOfElements = num;
Z_ARRVAL_P(return_value)->nInternalPointer = start_key;
if (Z_REFCOUNTED_P(val)) {
GC_REFCOUNT(Z_COUNTED_P(val)) += num;
}
p = Z_ARRVAL_P(return_value)->arData;
n = start_key;
while (start_key--) {
ZVAL_UNDEF(&p->val);
p++;
}
while (num--) {
ZVAL_COPY_VALUE(&p->val, val);
p->h = n++;
p->key = NULL;
p++;
}
} else {
/* create hash */
array_init_size(return_value, (uint32_t)num);
zend_hash_real_init(Z_ARRVAL_P(return_value), 0);
if (Z_REFCOUNTED_P(val)) {
GC_REFCOUNT(Z_COUNTED_P(val)) += num;
}
zend_hash_index_add_new(Z_ARRVAL_P(return_value), start_key, val);
while (--num) {
zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), val);
start_key++;
}
}
} else if (EXPECTED(num == 0)) {
array_init(return_value);
return;
} else {
php_error_docref(NULL, E_WARNING, "Number of elements can't be negative");
RETURN_FALSE;
}
}
/* }}} */