Merge remote-tracking branch 'origin/PHP-5.6' into str_size_and_int64_56_backport

* origin/PHP-5.6: (41 commits)
  fix crash in MINFO when no mysqlnd plugins are loaded
  backported some ext/intl tests from 5.6 into 5.4
  test fixes for ICU 53.1
  Fixed bug #67033 Remove reference to Windows 95
  fix NEWS
  Fixed bug #64604
  Fix #66562: Consistency bug where curl_multi_getcontent behaves different from curl_exec
  Fix bug #66482, replace wrong item name 'priority' with 'process.priority' in php-fpm.conf
  Fix windows build
  Fix bug #66721
  fix apr_psprintf format string from e0df4e3dba
  Fixed bug #67024 - getimagesize should recognize BMP files with negative height
  Bug #66840: Fix broken build when extension built separately
  Reverted to 5a0da281e5 Discussion: http://news.php.net/php.cvs/76836
  Forgot title in phpt for bug #67064
  Updated NEWS
  Fix bug #67064 in a BC safe way You can use an optional parameter now when implementing the Countable interface to get the $mode passed to count().
  Added UPGRAING notice for bug #66015 in BC break section
  Add new zend_hash_* APIs to UPGRADING.INTERNALS
  Add str_* macros to UPGRADING.INTERNALS
  ...

Conflicts:
	Zend/zend_compile.c
	Zend/zend_execute_API.c
	Zend/zend_language_parser.y
	ext/mysqli/mysqli.c
	ext/mysqlnd/mysqlnd.c
	ext/mysqlnd/mysqlnd.h
	ext/mysqlnd/mysqlnd_ps.c
	ext/mysqlnd/mysqlnd_result.c
	ext/mysqlnd/mysqlnd_result.h
	ext/mysqlnd/mysqlnd_structs.h
	ext/mysqlnd/mysqlnd_wireprotocol.c
	ext/mysqlnd/mysqlnd_wireprotocol.h
	ext/opcache/zend_accelerator_util_funcs.c
	ext/spl/spl_observer.c
	ext/standard/array.c
This commit is contained in:
Anatol Belski committed 2014-04-15 09:53:02 +02:00
commit f166237626
139 files changed
+5520 -2701

No files matched your search

+44
View File
@@ -2,6 +2,50 @@ PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? ??? 2014, PHP 5.6.0 Beta 2
- Core:
. Fixed bug #64604 (parse_url is inconsistent with specified port).
(Ingo Walz)
. Fixed bug #66015 (Unexpected array indexing in class's static property). (Bob)
. Added (constant) string/array dereferencing to static scalar expressions
to complete the set; now possible thanks to bug #66015 being fixed. (Bob)
. Fixed bug #66568 (Update reflection information for unserialize() function).
(Ferenc)
. Fixed bug #66660 (Composer.phar install/update fails). (Ferenc)
. Fixed bug #67024 (getimagesize should recognize BMP files with negative
height). (Gabor Buella)
. Fixed bug #67064 (Countable interface prevents using 2nd parameter
($mode) of count() function). (Bob)
- cURL:
. Fixed bug #66562 (curl_exec returns differently than curl_multi_getcontent).
(Freek Lijten)
- Date:
. Fixed bug #66721 (__wakeup of DateTime segfaults when invalid object data is
supplied). (Boro Sitnikovski)
- FPM:
. Fixed bug #66482 (unknown entry 'priority' in php-fpm.conf).
- JSON:
. Fixed bug #66021 (Blank line inside empty array/object when
JSON_PRETTY_PRINT is set). (Kevin Israel)
- mysqlnd:
. Added a new fetching mode to mysqlnd. (Andrey)
- PDO:
. Fixed bug #66604 ('pdo/php_pdo_error.h' not copied to the include dir).
(Matteo)
- SQLite:
. Fixed bug #66967 (Updated bundled libsqlite to 3.8.4.3). (Anatol)
- Apache2 Handler SAPI:
. Fixed Apache log issue caused by APR's lack of support for %zu
(APR issue https://issues.apache.org/bugzilla/show_bug.cgi?id=56120).
(Jeff Trawick)
10 Apr 2014, PHP 5.6.0 Beta 1
- Core:
+15
View File
@@ -20,6 +20,21 @@ PHP 5.6 UPGRADE NOTES
1. Backward Incompatible Changes
========================================
- Core:
By fixing bug #66015 it is no longer possible to overwrite keys in static scalar
arrays. Quick example to illustrate:
class Test {
const FIRST = 1;
public $array = array(
self::FIRST => 'first',
'second',
'third'
);
}
Test::$array will have as expected three array keys (1, 2, 3) and no longer
two (0, 1). self::FIRST will no longer overwrite 'third' having key 1 then,
but will mark the beginning of indexing.
- JSON:
json_decode() no longer accepts non-lowercase variants of lone JSON true,
false or null values. For example, True or FALSE will now cause json_decode to
+67 -1
View File
@@ -9,6 +9,9 @@ UPGRADE NOTES - PHP X.Y
d. Arginfo changes
e. tsrm_virtual_cwd.h moved to zend_virtual_cwd.h
f. empty strings are interned
g. Additional str_* APIs
h. Addition of zend_hash_reindex
i. Addition of zend_hash_splice
2. Build system changes
a. Unix build system changes
@@ -120,8 +123,71 @@ UPGRADE NOTES - PHP X.Y
String created using STR_EMPTY_ALLOC() are now interned.
convert_to_string use STR_EMPTY_ALLOC() for zval when IS_NULL.
STR_FREE() shoud be prefered as efree on such strings can raise memory corruption.
str_efree() shoud be preferred as efree() on such strings can cause memory
corruption.
g. Additional str_* APIs
In addition to the previously existing str_free() and str_efree() macros, the
following macros have been introduced to simplify dealing with potentially
interned strings:
str_efree_rel(str) - efree_rel() if not interned
str_erealloc(str, new_len) - erealloc() or emalloc+memcpy if interned
str_estrndup(str, len) - estrndup() if not interned
str_strndup(str, len) - zend_strndup() if not interned
str_hash(str, len) - INTERNED_HASH(str) if interned,
zend_hash_func(str, len+1) otherwise
h. Addition of zend_hash_reindex
A zend_hash_reindex() function with the following prototype has been added:
void zend_hash_reindex(HashTable *ht, zend_bool only_integer_keys);
If only_integer_keys==0, this function will change all keys to be continuous,
zero-based integers in hash order. If only_integer_keys==1 the same will be
done only for keys that were already integers previously, while leaving
string keys alone.
i. Addition of zend_hash_splice
A zend_hash_splice() macro with the following prototype has been added:
void zend_hash_splice(
HashTable *ht, uint nDataSize, copy_ctor_func_t pCopyConstructor,
uint offset, uint length,
void **list, uint list_count, HashTable *removed
);
This function performs an in-place splice operation on a hashtable:
The elements between offset and offset+length are removed and the elements in
list[list_count] are inserted in their place. The removed elements can be
optionally collected into a hashtable.
This operation reindexes the hashtable, i.e. integer keys will be zero-based
and sequential, while string keys stay intact. The same applies to the
elements inserted into the removed HT.
As a side-effect of this addition the signature of the php_splice() function
changed:
void php_splice(
HashTable *ht, zend_uint offset, zend_uint length,
zval ***list, zend_uint list_count, HashTable *removed TSRMLS_DC
)
This function now directly forwards to zend_hash_splice(), resets the
IAP of ht (for compatibility with the previous implementation) and resets
CVs if the passed hashtable is the global symbol table.
j. An additional parameter is sent to Countable::count()
That parameter denotes the $mode passed to count; it shouldn't affect any
userland code, but any zend_parse_parameters() used with no arguments should
fail. Extensions which implement Countable internally, need to accept one
optional long as parameter.
========================
2. Build system changes
+30
View File
@@ -0,0 +1,30 @@
--TEST--
Bug #66015 (wrong array indexing in class's static property)
--FILE--
<?php
class Test
{
const FIRST = 1;
const SECOND = 2;
const THIRD = 3;
protected static $array = [
self::FIRST => 'first',
'second',
'third'
];
public function __construct()
{
var_export(self::$array);
}
}
$test = new Test();
?>
--EXPECTF--
array (
1 => 'first',
2 => 'second',
3 => 'third',
)
+13
View File
@@ -0,0 +1,13 @@
--TEST--
Bug #66660 (Composer.phar install/update fails)
--STDIN--
<?php __CLASS__ ?>
--FILE--
<?php
file_put_contents(__DIR__."/bug66660.tmp.php", "<?php __CLASS__ ?>");
echo php_strip_whitespace(__DIR__."/bug66660.tmp.php");
?>
--CLEAN--
<?php unlink(__DIR__."/bug66660.tmp.php"); ?>
--EXPECT--
<?php __CLASS__ ?>
+3 -1
View File
@@ -7,7 +7,9 @@ class test {
const TEST = array(1,2,3);
}
var_dump(test::TEST);
echo "Done\n";
?>
--EXPECTF--
Fatal error: Arrays are not allowed in class constants in %s on line %d
Fatal error: Arrays are not allowed in constants at run-time in %s on line %d
+4 -1
View File
@@ -3,6 +3,9 @@
--FILE--
<?php
const C = array();
var_dump(C);
?>
--EXPECTF--
Fatal error: Arrays are not allowed as constants in %sns_059.php on line 2
Fatal error: Arrays are not allowed in constants at run-time in %sns_059.php on line 4
+2 -5
View File
@@ -589,14 +589,11 @@ typedef int (*zend_write_func_t)(const char *str, zend_size_t str_length);
#define IS_STRING 6
#define IS_RESOURCE 7
#define IS_CONSTANT 8
#define IS_CONSTANT_ARRAY 9
#define IS_CONSTANT_AST 10
#define IS_CALLABLE 11
#define IS_CONSTANT_AST 9
#define IS_CALLABLE 10
/* Ugly hack to support constants as static array indices */
#define IS_CONSTANT_TYPE_MASK 0x00f
#define IS_CONSTANT_UNQUALIFIED 0x010
#define IS_CONSTANT_INDEX 0x080
#define IS_LEXICAL_VAR 0x020
#define IS_LEXICAL_REF 0x040
#define IS_CONSTANT_IN_NAMESPACE 0x100
+3 -4
View File
@@ -1077,7 +1077,7 @@ static int zval_update_class_constant(zval **pp, int is_static, int offset TSRML
int ret;
zend_class_entry *old_scope = *scope;
*scope = prop_info->ce;
ret = zval_update_constant(pp, (void*)1 TSRMLS_CC);
ret = zval_update_constant(pp, 1 TSRMLS_CC);
*scope = old_scope;
return ret;
}
@@ -1086,7 +1086,7 @@ static int zval_update_class_constant(zval **pp, int is_static, int offset TSRML
} while (ce);
}
return zval_update_constant(pp, (void*)1 TSRMLS_CC);
return zval_update_constant(pp, 1 TSRMLS_CC);
}
return 0;
}
@@ -1100,7 +1100,7 @@ ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC
int i;
*scope = class_type;
zend_hash_apply_with_argument(&class_type->constants_table, (apply_func_arg_t) zval_update_constant, (void*)1 TSRMLS_CC);
zend_hash_apply_with_argument(&class_type->constants_table, (apply_func_arg_t) zval_update_constant, (void *)1 TSRMLS_CC);
for (i = 0; i < class_type->default_properties_count; i++) {
if (class_type->default_properties_table[i]) {
@@ -3470,7 +3470,6 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, const char *name, ze
if (ce->type & ZEND_INTERNAL_CLASS) {
switch(Z_TYPE_P(property)) {
case IS_ARRAY:
case IS_CONSTANT_ARRAY:
case IS_OBJECT:
case IS_RESOURCE:
zend_error(E_CORE_ERROR, "Internal zval's can't be arrays, objects or resources");
+60 -19
View File
@@ -63,6 +63,27 @@ ZEND_API zend_ast* zend_ast_create_ternary(uint kind, zend_ast *op0, zend_ast *o
return ast;
}
ZEND_API zend_ast* zend_ast_create_dynamic(uint kind)
{
zend_ast *ast = emalloc(sizeof(zend_ast) + sizeof(zend_ast*) * 3); /* use 4 children as deafult */
ast->kind = kind;
ast->children = 0;
return ast;
}
ZEND_API void zend_ast_dynamic_add(zend_ast **ast, zend_ast *op)
{
if ((*ast)->children >= 4 && (*ast)->children == ((*ast)->children & -(*ast)->children)) {
*ast = erealloc(*ast, sizeof(zend_ast) + sizeof(zend_ast*) * ((*ast)->children * 2 + 1));
}
(&(*ast)->u.child)[(*ast)->children++] = op;
}
ZEND_API void zend_ast_dynamic_shrink(zend_ast **ast)
{
*ast = erealloc(*ast, sizeof(zend_ast) + sizeof(zend_ast*) * ((*ast)->children - 1));
}
ZEND_API int zend_ast_is_ct_constant(zend_ast *ast)
{
int i;
@@ -233,7 +254,7 @@ ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *s
*result = *ast->u.val;
zval_copy_ctor(result);
if (IS_CONSTANT_TYPE(Z_TYPE_P(result))) {
zval_update_constant_ex(&result, (void *) 1, scope TSRMLS_CC);
zval_update_constant_ex(&result, 1, scope TSRMLS_CC);
}
break;
case ZEND_BOOL_AND:
@@ -284,6 +305,35 @@ ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *s
sub_function(result, &op1, &op2 TSRMLS_CC);
zval_dtor(&op2);
break;
case ZEND_INIT_ARRAY:
INIT_PZVAL(result);
array_init(result);
{
int i;
zend_bool has_key;
for (i = 0; i < ast->children; i+=2) {
zval *expr;
MAKE_STD_ZVAL(expr);
if ((has_key = !!(&ast->u.child)[i])) {
zend_ast_evaluate(&op1, (&ast->u.child)[i], scope TSRMLS_CC);
}
zend_ast_evaluate(expr, (&ast->u.child)[i+1], scope TSRMLS_CC);
zend_do_add_static_array_element(result, has_key?&op1:NULL, expr);
}
}
break;
case ZEND_FETCH_DIM_R:
zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
{
zval *tmp;
zend_fetch_dimension_by_zval(&tmp, &op1, &op2 TSRMLS_CC);
*result = *tmp;
efree(tmp);
}
zval_dtor(&op1);
zval_dtor(&op2);
break;
default:
zend_error(E_ERROR, "Unsupported constant expression");
}
@@ -297,26 +347,17 @@ ZEND_API zend_ast *zend_ast_copy(zend_ast *ast)
zend_ast *copy = zend_ast_create_constant(ast->u.val);
zval_copy_ctor(copy->u.val);
return copy;
} else {
switch (ast->children) {
case 1:
return zend_ast_create_unary(
ast->kind,
zend_ast_copy((&ast->u.child)[0]));
case 2:
return zend_ast_create_binary(
ast->kind,
zend_ast_copy((&ast->u.child)[0]),
zend_ast_copy((&ast->u.child)[1]));
case 3:
return zend_ast_create_ternary(
ast->kind,
zend_ast_copy((&ast->u.child)[0]),
zend_ast_copy((&ast->u.child)[1]),
zend_ast_copy((&ast->u.child)[2]));
} else if (ast->children) {
zend_ast *new = emalloc(sizeof(zend_ast) + sizeof(zend_ast*) * (ast->children - 1));
int i;
new->kind = ast->kind;
new->children = ast->children;
for (i = 0; i < ast->children; i++) {
(&new->u.child)[i] = zend_ast_copy((&ast->u.child)[i]);
}
return new;
}
return NULL;
return zend_ast_create_dynamic(ast->kind);
}
ZEND_API void zend_ast_destroy(zend_ast *ast)
+3
View File
@@ -50,6 +50,9 @@ ZEND_API zend_ast *zend_ast_create_constant(zval *zv);
ZEND_API zend_ast *zend_ast_create_unary(uint kind, zend_ast *op0);
ZEND_API zend_ast *zend_ast_create_binary(uint kind, zend_ast *op0, zend_ast *op1);
ZEND_API zend_ast *zend_ast_create_ternary(uint kind, zend_ast *op0, zend_ast *op1, zend_ast *op2);
ZEND_API zend_ast* zend_ast_create_dynamic(uint kind);
ZEND_API void zend_ast_dynamic_add(zend_ast **ast, zend_ast *op);
ZEND_API void zend_ast_dynamic_shrink(zend_ast **ast);
ZEND_API int zend_ast_is_ct_constant(zend_ast *ast);
+11 -46
View File
@@ -1933,7 +1933,7 @@ void zend_do_receive_param(zend_uchar op, znode *varname, const znode *initializ
if (op == ZEND_RECV_INIT) {
if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL")) || Z_TYPE(initialization->u.constant) == IS_CONSTANT_AST) {
cur_arg_info->allow_null = 1;
} else if (Z_TYPE(initialization->u.constant) != IS_ARRAY && Z_TYPE(initialization->u.constant) != IS_CONSTANT_ARRAY) {
} else if (Z_TYPE(initialization->u.constant) != IS_ARRAY) {
zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters with array type hint can only be an array or NULL");
}
}
@@ -3461,7 +3461,7 @@ static char * zend_get_function_declaration(zend_function *fptr TSRMLS_DC) /* {{
*zv = *precv->op2.zv;
zval_copy_ctor(zv);
INIT_PZVAL(zv);
zval_update_constant_ex(&zv, (void*)1, fptr->common.scope TSRMLS_CC);
zval_update_constant_ex(&zv, 1, fptr->common.scope TSRMLS_CC);
if (Z_TYPE_P(zv) == IS_BOOL) {
if (Z_IVAL_P(zv)) {
memcpy(offset, "true", 4);
@@ -5442,10 +5442,6 @@ void zend_do_declare_class_constant(znode *var_name, const znode *value TSRMLS_D
const char *cname = NULL;
zend_uint_t hash;
if(Z_TYPE(value->u.constant) == IS_CONSTANT_ARRAY) {
zend_error_noreturn(E_COMPILE_ERROR, "Arrays are not allowed in class constants");
return;
}
if ((CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
zend_error_noreturn(E_COMPILE_ERROR, "Traits cannot have constants");
return;
@@ -5887,57 +5883,30 @@ void zend_do_add_array_element(znode *result, const znode *expr, const znode *of
}
/* }}} */
void zend_do_add_static_array_element(znode *result, znode *offset, const znode *expr) /* {{{ */
void zend_do_add_static_array_element(zval *result, zval *offset, const zval *expr) /* {{{ */
{
zval *element;
ALLOC_ZVAL(element);
*element = expr->u.constant;
if (offset) {
switch (Z_TYPE(offset->u.constant) & IS_CONSTANT_TYPE_MASK) {
case IS_CONSTANT:
/* Ugly hack to denote that this value has a constant index */
Z_TYPE_P(element) |= IS_CONSTANT_INDEX;
Z_STRVAL(offset->u.constant) = erealloc(Z_STRVAL(offset->u.constant), Z_STRSIZE(offset->u.constant)+3);
Z_STRVAL(offset->u.constant)[Z_STRSIZE(offset->u.constant)+1] = Z_TYPE(offset->u.constant);
Z_STRVAL(offset->u.constant)[Z_STRSIZE(offset->u.constant)+2] = 0;
zend_symtable_update(Z_ARRVAL(result->u.constant), Z_STRVAL(offset->u.constant), Z_STRSIZE(offset->u.constant)+3, &element, sizeof(zval *), NULL);
zval_dtor(&offset->u.constant);
break;
case IS_CONSTANT_AST: {
/* Another ugly hack to store the data about the AST in the array */
char* key;
int len = sizeof(zend_ast *);
Z_TYPE_P(element) |= IS_CONSTANT_INDEX;
key = emalloc(len + 2);
*(zend_ast **)key = Z_AST(offset->u.constant);
key[len] = Z_TYPE(offset->u.constant);
key[len + 1] = 0;
zend_symtable_update(Z_ARRVAL(result->u.constant), key, len + 2, &element, sizeof(zval *), NULL);
efree(key);
break;
}
switch (Z_TYPE_P(offset)) {
case IS_STRING:
zend_symtable_update(Z_ARRVAL(result->u.constant), Z_STRVAL(offset->u.constant), Z_STRSIZE(offset->u.constant)+1, &element, sizeof(zval *), NULL);
zval_dtor(&offset->u.constant);
zend_symtable_update(Z_ARRVAL_P(result), Z_STRVAL_P(offset), Z_STRSIZE_P(offset)+1, &expr, sizeof(zval *), NULL);
zval_dtor(offset);
break;
case IS_NULL:
zend_symtable_update(Z_ARRVAL(result->u.constant), "", 1, &element, sizeof(zval *), NULL);
zend_symtable_update(Z_ARRVAL_P(result), "", 1, &expr, sizeof(zval *), NULL);
break;
case IS_INT:
case IS_BOOL:
zend_hash_index_update(Z_ARRVAL(result->u.constant), Z_IVAL(offset->u.constant), &element, sizeof(zval *), NULL);
zend_hash_index_update(Z_ARRVAL_P(result), Z_IVAL_P(offset), &expr, sizeof(zval *), NULL);
break;
case IS_DOUBLE:
zend_hash_index_update(Z_ARRVAL(result->u.constant), zend_dval_to_ival(Z_DVAL(offset->u.constant)), &element, sizeof(zval *), NULL);
zend_hash_index_update(Z_ARRVAL_P(result), zend_dval_to_ival(Z_DVAL_P(offset)), &expr, sizeof(zval *), NULL);
break;
case IS_CONSTANT_ARRAY:
case IS_ARRAY:
zend_error(E_ERROR, "Illegal offset type");
break;
}
} else {
zend_hash_next_index_insert(Z_ARRVAL(result->u.constant), &element, sizeof(zval *), NULL);
zend_hash_next_index_insert(Z_ARRVAL_P(result), &expr, sizeof(zval *), NULL);
}
}
/* }}} */
@@ -7318,10 +7287,6 @@ void zend_do_declare_constant(znode *name, znode *value TSRMLS_DC) /* {{{ */
zend_op *opline;
zval **ns_name;
if(Z_TYPE(value->u.constant) == IS_CONSTANT_ARRAY) {
zend_error_noreturn(E_COMPILE_ERROR, "Arrays are not allowed as constants");
}
if (zend_get_ct_const(&name->u.constant, 0 TSRMLS_CC)) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare constant '%s'", Z_STRVAL(name->u.constant));
}
+1 -1
View File
@@ -602,7 +602,7 @@ void zend_do_shell_exec(znode *result, const znode *cmd TSRMLS_DC);
void zend_do_init_array(znode *result, const znode *expr, const znode *offset, zend_bool is_ref TSRMLS_DC);
void zend_do_add_array_element(znode *result, const znode *expr, const znode *offset, zend_bool is_ref TSRMLS_DC);
void zend_do_add_static_array_element(znode *result, znode *offset, const znode *expr);
void zend_do_add_static_array_element(zval *result, zval *offset, const zval *expr);
void zend_do_list_init(TSRMLS_D);
void zend_do_list_end(znode *result, znode *expr TSRMLS_DC);
void zend_do_add_list_element(const znode *element TSRMLS_DC);
+2 -2
View File
@@ -408,7 +408,7 @@ ZEND_API int zend_get_constant_ex(const char *name, zend_size_t name_len, zval *
efree(lcname);
if(found_const) {
*result = c->value;
zval_update_constant_ex(&result, (void*)1, NULL TSRMLS_CC);
zval_update_constant_ex(&result, 1, NULL TSRMLS_CC);
zval_copy_ctor(result);
Z_SET_REFCOUNT_P(result, 1);
Z_UNSET_ISREF_P(result);
@@ -423,7 +423,7 @@ ZEND_API int zend_get_constant_ex(const char *name, zend_size_t name_len, zval *
retval = 0;
finish:
if (retval) {
zval_update_constant_ex(ret_constant, (void*)1, ce TSRMLS_CC);
zval_update_constant_ex(ret_constant, 1, ce TSRMLS_CC);
*result = **ret_constant;
zval_copy_ctor(result);
INIT_PZVAL(result);
+7 -1
View File
@@ -1352,9 +1352,15 @@ static void zend_fetch_dimension_address_read(temp_variable *result, zval *conta
}
}
ZEND_API void zend_fetch_dimension_by_zval(zval **result, zval *container, zval *dim TSRMLS_DC) {
temp_variable tmp;
zend_fetch_dimension_address_read(&tmp, container, dim, IS_TMP_VAR, BP_VAR_R TSRMLS_CC);
*result = tmp.var.ptr;
}
static void zend_fetch_property_address(temp_variable *result, zval **container_ptr, zval *prop_ptr, const zend_literal *key, int type TSRMLS_DC)
{
zval *container = *container_ptr;;
zval *container = *container_ptr;
if (Z_TYPE_P(container) != IS_OBJECT) {
if (container == &EG(error_zval)) {
+6 -4
View File
@@ -158,10 +158,10 @@ static zend_always_inline int i_zend_is_true(zval *op)
return result;
}
ZEND_API int zval_update_constant(zval **pp, void *arg TSRMLS_DC);
ZEND_API int zval_update_constant_inline_change(zval **pp, void *arg TSRMLS_DC);
ZEND_API int zval_update_constant_no_inline_change(zval **pp, void *arg TSRMLS_DC);
ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *scope TSRMLS_DC);
ZEND_API int zval_update_constant(zval **pp, zend_bool inline_change TSRMLS_DC);
ZEND_API int zval_update_constant_inline_change(zval **pp, zend_class_entry *scope TSRMLS_DC);
ZEND_API int zval_update_constant_no_inline_change(zval **pp, zend_class_entry *scope TSRMLS_DC);
ZEND_API int zval_update_constant_ex(zval **pp, zend_bool inline_change, zend_class_entry *scope TSRMLS_DC);
/* dedicated Zend executor functions - do not use! */
#define ZEND_VM_STACK_PAGE_SIZE ((16 * 1024) - 16)
@@ -362,6 +362,8 @@ ZEND_API zend_class_entry *zend_fetch_class(const char *class_name, zend_size_t
ZEND_API zend_class_entry *zend_fetch_class_by_name(const char *class_name, zend_size_t class_name_len, const zend_literal *key, int fetch_type TSRMLS_DC);
void zend_verify_abstract_class(zend_class_entry *ce TSRMLS_DC);
ZEND_API void zend_fetch_dimension_by_zval(zval **result, zval *container, zval *dim TSRMLS_DC);
#ifdef ZEND_WIN32
void zend_init_timeout_thread(void);
void zend_shutdown_timeout_thread(void);
+8 -126
View File
@@ -451,28 +451,14 @@ ZEND_API int zend_is_true(zval *op) /* {{{ */
#include "../TSRM/tsrm_strtok_r.h"
#define IS_VISITED_CONSTANT IS_CONSTANT_INDEX
#define IS_VISITED_CONSTANT 0x80
#define IS_CONSTANT_VISITED(p) (Z_TYPE_P(p) & IS_VISITED_CONSTANT)
#define Z_REAL_TYPE_P(p) (Z_TYPE_P(p) & ~IS_VISITED_CONSTANT)
#define MARK_CONSTANT_VISITED(p) Z_TYPE_P(p) |= IS_VISITED_CONSTANT
static void zval_deep_copy(zval **p)
{
zval *value;
ALLOC_ZVAL(value);
*value = **p;
Z_TYPE_P(value) &= ~IS_CONSTANT_INDEX;
zval_copy_ctor(value);
Z_TYPE_P(value) = Z_TYPE_PP(p);
INIT_PZVAL(value);
*p = value;
}
ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *scope TSRMLS_DC) /* {{{ */
ZEND_API int zval_update_constant_ex(zval **pp, zend_bool inline_change, zend_class_entry *scope TSRMLS_DC) /* {{{ */
{
zval *p = *pp;
zend_bool inline_change = (zend_bool) (zend_uintptr_t) arg;
zval const_value;
char *colon;
@@ -559,110 +545,6 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco
Z_SET_REFCOUNT_P(p, refcount);
Z_SET_ISREF_TO_P(p, is_ref);
} else if (Z_TYPE_P(p) == IS_CONSTANT_ARRAY) {
zval **element, *new_val;
char *str_index;
zend_size_t str_index_len;
zend_uint_t num_index;
int ret;
SEPARATE_ZVAL_IF_NOT_REF(pp);
p = *pp;
Z_TYPE_P(p) = IS_ARRAY;
if (!inline_change) {
zval *tmp;
HashTable *tmp_ht = NULL;
ALLOC_HASHTABLE(tmp_ht);
zend_hash_init(tmp_ht, zend_hash_num_elements(Z_ARRVAL_P(p)), NULL, ZVAL_PTR_DTOR, 0);
zend_hash_copy(tmp_ht, Z_ARRVAL_P(p), (copy_ctor_func_t) zval_deep_copy, (void *) &tmp, sizeof(zval *));
Z_ARRVAL_P(p) = tmp_ht;
}
/* First go over the array and see if there are any constant indices */
zend_hash_internal_pointer_reset(Z_ARRVAL_P(p));
while (zend_hash_get_current_data(Z_ARRVAL_P(p), (void **) &element) == SUCCESS) {
if (!(Z_TYPE_PP(element) & IS_CONSTANT_INDEX)) {
zend_hash_move_forward(Z_ARRVAL_P(p));
continue;
}
Z_TYPE_PP(element) &= ~IS_CONSTANT_INDEX;
if (zend_hash_get_current_key_ex(Z_ARRVAL_P(p), &str_index, &str_index_len, &num_index, 0, NULL) != HASH_KEY_IS_STRING) {
zend_hash_move_forward(Z_ARRVAL_P(p));
continue;
}
if (str_index[str_index_len - 2] == IS_CONSTANT_AST) {
zend_ast_evaluate(&const_value, *(zend_ast **)str_index, scope TSRMLS_CC);
zend_ast_destroy(*(zend_ast **)str_index);
} else if (!zend_get_constant_ex(str_index, str_index_len - 3, &const_value, scope, str_index[str_index_len - 2] TSRMLS_CC)) {
char *actual;
const char *save = str_index;
if ((colon = (char*)zend_memrchr(str_index, ':', str_index_len - 3))) {
zend_error(E_ERROR, "Undefined class constant '%s'", str_index);
str_index_len -= ((colon - str_index) + 1);
str_index = colon;
} else {
if (str_index[str_index_len - 2] & IS_CONSTANT_UNQUALIFIED) {
if ((actual = (char *)zend_memrchr(str_index, '\\', str_index_len - 3))) {
actual++;
str_index_len -= (actual - str_index);
str_index = actual;
}
}
if (str_index[0] == '\\') {
++str_index;
--str_index_len;
}
if (save[0] == '\\') {
++save;
}
if ((str_index[str_index_len - 2] & IS_CONSTANT_UNQUALIFIED) == 0) {
zend_error(E_ERROR, "Undefined constant '%s'", save);
}
zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", str_index, str_index);
}
ZVAL_STRINGL(&const_value, str_index, str_index_len-3, 1);
}
if (Z_REFCOUNT_PP(element) > 1) {
ALLOC_ZVAL(new_val);
*new_val = **element;
zval_copy_ctor(new_val);
Z_SET_REFCOUNT_P(new_val, 1);
Z_UNSET_ISREF_P(new_val);
/* preserve this bit for inheritance */
Z_TYPE_PP(element) |= IS_CONSTANT_INDEX;
zval_ptr_dtor(element);
*element = new_val;
}
switch (Z_TYPE(const_value)) {
case IS_STRING:
ret = zend_symtable_update_current_key(Z_ARRVAL_P(p), Z_STRVAL(const_value), Z_STRSIZE(const_value) + 1, HASH_UPDATE_KEY_IF_BEFORE);
break;
case IS_BOOL:
case IS_INT:
ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_INT, NULL, 0, Z_IVAL(const_value), HASH_UPDATE_KEY_IF_BEFORE, NULL);
break;
case IS_DOUBLE:
ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_INT, NULL, 0, zend_dval_to_ival(Z_DVAL(const_value)), HASH_UPDATE_KEY_IF_BEFORE, NULL);
break;
case IS_NULL:
ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_STRING, "", 1, 0, HASH_UPDATE_KEY_IF_BEFORE, NULL);
break;
default:
ret = SUCCESS;
break;
}
if (ret == SUCCESS) {
zend_hash_move_forward(Z_ARRVAL_P(p));
}
zval_dtor(&const_value);
}
zend_hash_apply_with_argument(Z_ARRVAL_P(p), (apply_func_arg_t) zval_update_constant_inline_change, (void *) scope TSRMLS_CC);
zend_hash_internal_pointer_reset(Z_ARRVAL_P(p));
} else if (Z_TYPE_P(p) == IS_CONSTANT_AST) {
SEPARATE_ZVAL_IF_NOT_REF(pp);
p = *pp;
@@ -677,21 +559,21 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco
}
/* }}} */
ZEND_API int zval_update_constant_inline_change(zval **pp, void *scope TSRMLS_DC) /* {{{ */
ZEND_API int zval_update_constant_inline_change(zval **pp, zend_class_entry *scope TSRMLS_DC) /* {{{ */
{
return zval_update_constant_ex(pp, (void*)1, scope TSRMLS_CC);
return zval_update_constant_ex(pp, 1, scope TSRMLS_CC);
}
/* }}} */
ZEND_API int zval_update_constant_no_inline_change(zval **pp, void *scope TSRMLS_DC) /* {{{ */
ZEND_API int zval_update_constant_no_inline_change(zval **pp, zend_class_entry *scope TSRMLS_DC) /* {{{ */
{
return zval_update_constant_ex(pp, (void*)0, scope TSRMLS_CC);
return zval_update_constant_ex(pp, 0, scope TSRMLS_CC);
}
/* }}} */
ZEND_API int zval_update_constant(zval **pp, void *arg TSRMLS_DC) /* {{{ */
ZEND_API int zval_update_constant(zval **pp, zend_bool inline_change TSRMLS_DC) /* {{{ */
{
return zval_update_constant_ex(pp, arg, NULL TSRMLS_CC);
return zval_update_constant_ex(pp, inline_change, NULL TSRMLS_CC);
}
/* }}} */
+1 -1
View File
@@ -211,7 +211,7 @@ ZEND_API void zend_strip(TSRMLS_D)
break;
default:
efree(token.value.str.val);
STR_FREE(token.value.str.val);
break;
}
}
+11 -10
View File
@@ -986,9 +986,7 @@ static_class_constant:
;
static_scalar: /* compile-time evaluated scalars */
static_scalar_value { zend_do_constant_expression(&$$, $1.u.ast TSRMLS_CC); }
| T_ARRAY '(' static_array_pair_list ')' { $$ = $3; Z_TYPE($$.u.constant) = IS_CONSTANT_ARRAY; }
| '[' static_array_pair_list ']' { $$ = $2; Z_TYPE($$.u.constant) = IS_CONSTANT_ARRAY; }
static_scalar_value { zend_do_constant_expression(&$$, $1.u.ast TSRMLS_CC); }
;
static_scalar_value:
@@ -997,13 +995,16 @@ static_scalar_value:
| namespace_name { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_CT, 1 TSRMLS_CC); $$.u.ast = zend_ast_create_constant(&$$.u.constant); }
| T_NAMESPACE T_NS_SEPARATOR namespace_name { $$.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$$.u.constant); zend_do_build_namespace_name(&$$, &$$, &$3 TSRMLS_CC); $3 = $$; zend_do_fetch_constant(&$$, NULL, &$3, ZEND_CT, 0 TSRMLS_CC); $$.u.ast = zend_ast_create_constant(&$$.u.constant); }
| T_NS_SEPARATOR namespace_name { char *tmp = estrndup(Z_STRVAL($2.u.constant), Z_STRSIZE($2.u.constant)+1); memcpy(&(tmp[1]), Z_STRVAL($2.u.constant), Z_STRSIZE($2.u.constant)+1); tmp[0] = '\\'; efree(Z_STRVAL($2.u.constant)); Z_STRVAL($2.u.constant) = tmp; ++Z_STRSIZE($2.u.constant); zend_do_fetch_constant(&$$, NULL, &$2, ZEND_CT, 0 TSRMLS_CC); $$.u.ast = zend_ast_create_constant(&$$.u.constant); }
| T_ARRAY '(' static_array_pair_list ')' { $$ = $3; }
| '[' static_array_pair_list ']' { $$ = $2; }
| static_class_constant { $$.u.ast = zend_ast_create_constant(&$1.u.constant); }
| T_CLASS_C { $$.u.ast = zend_ast_create_constant(&$1.u.constant); }
| static_operation { $$ = $1; }
;
static_operation:
static_scalar_value '+' static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_ADD, $1.u.ast, $3.u.ast); }
static_scalar_value '[' static_scalar_value ']' { $$.u.ast = zend_ast_create_binary(ZEND_FETCH_DIM_R, $1.u.ast, $3.u.ast); }
| static_scalar_value '+' static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_ADD, $1.u.ast, $3.u.ast); }
| static_scalar_value '-' static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_SUB, $1.u.ast, $3.u.ast); }
| static_scalar_value '*' static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_MUL, $1.u.ast, $3.u.ast); }
| static_scalar_value T_POW static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_POW, $1.u.ast, $3.u.ast); }
@@ -1053,8 +1054,8 @@ scalar:
static_array_pair_list:
/* empty */ { $$.op_type = IS_CONST; INIT_PZVAL(&$$.u.constant); array_init(&$$.u.constant); }
| non_empty_static_array_pair_list possible_comma { $$ = $1; }
/* empty */ { $$.op_type = IS_CONST; INIT_PZVAL(&$$.u.constant); array_init(&$$.u.constant); $$.u.ast = zend_ast_create_constant(&$$.u.constant); }
| non_empty_static_array_pair_list possible_comma { zend_ast_dynamic_shrink(&$1.u.ast); $$ = $1; }
;
possible_comma:
@@ -1063,10 +1064,10 @@ possible_comma:
;
non_empty_static_array_pair_list:
non_empty_static_array_pair_list ',' static_scalar T_DOUBLE_ARROW static_scalar { zend_do_add_static_array_element(&$$, &$3, &$5); }
| non_empty_static_array_pair_list ',' static_scalar { zend_do_add_static_array_element(&$$, NULL, &$3); }
| static_scalar T_DOUBLE_ARROW static_scalar { $$.op_type = IS_CONST; INIT_PZVAL(&$$.u.constant); array_init(&$$.u.constant); zend_do_add_static_array_element(&$$, &$1, &$3); }
| static_scalar { $$.op_type = IS_CONST; INIT_PZVAL(&$$.u.constant); array_init(&$$.u.constant); zend_do_add_static_array_element(&$$, NULL, &$1); }
non_empty_static_array_pair_list ',' static_scalar_value T_DOUBLE_ARROW static_scalar_value { zend_ast_dynamic_add(&$$.u.ast, $3.u.ast); zend_ast_dynamic_add(&$$.u.ast, $5.u.ast); }
| non_empty_static_array_pair_list ',' static_scalar_value { zend_ast_dynamic_add(&$$.u.ast, NULL); zend_ast_dynamic_add(&$$.u.ast, $3.u.ast); }
| static_scalar_value T_DOUBLE_ARROW static_scalar_value { $$.u.ast = zend_ast_create_dynamic(ZEND_INIT_ARRAY); zend_ast_dynamic_add(&$$.u.ast, $1.u.ast); zend_ast_dynamic_add(&$$.u.ast, $3.u.ast); }
| static_scalar_value { $$.u.ast = zend_ast_create_dynamic(ZEND_INIT_ARRAY); zend_ast_dynamic_add(&$$.u.ast, NULL); zend_ast_dynamic_add(&$$.u.ast, $1.u.ast); }
;
expr:
+2
View File
@@ -170,6 +170,8 @@ ZEND_API HashTable *zend_std_get_debug_info(zval *object, int *is_temp TSRMLS_DC
}
zend_error_noreturn(E_ERROR, ZEND_DEBUGINFO_FUNC_NAME "() must return an array");
return NULL; /* Compilers are dumb and don't understand that noreturn means that the function does NOT need a return value... */
}
/* }}} */
+2 -5
View File
@@ -36,8 +36,7 @@ ZEND_API void _zval_dtor_func(zval *zvalue ZEND_FILE_LINE_DC)
CHECK_ZVAL_STRING_REL(zvalue);
str_efree_rel(zvalue->value.str.val);
break;
case IS_ARRAY:
case IS_CONSTANT_ARRAY: {
case IS_ARRAY: {
TSRMLS_FETCH();
if (zvalue->value.ht && (zvalue->value.ht != &EG(symbol_table))) {
@@ -86,7 +85,6 @@ ZEND_API void _zval_internal_dtor(zval *zvalue ZEND_FILE_LINE_DC)
str_free(zvalue->value.str.val);
break;
case IS_ARRAY:
case IS_CONSTANT_ARRAY:
case IS_CONSTANT_AST:
case IS_OBJECT:
case IS_RESOURCE:
@@ -128,8 +126,7 @@ ZEND_API void _zval_copy_ctor_func(zval *zvalue ZEND_FILE_LINE_DC)
zvalue->value.str.val = (char *) estrndup_rel(zvalue->value.str.val, zvalue->value.str.len);
}
break;
case IS_ARRAY:
case IS_CONSTANT_ARRAY: {
case IS_ARRAY: {
zval *tmp;
HashTable *original_ht = zvalue->value.ht;
HashTable *tmp_ht = NULL;
+11 -15
View File
@@ -1081,7 +1081,7 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMP|VAR|CV, UNUSED|CONST|
FREE_OP1();
break;
case ZEND_FETCH_STATIC:
zval_update_constant(retval, (void*) 1 TSRMLS_CC);
zval_update_constant(retval, 1 TSRMLS_CC);
break;
case ZEND_FETCH_GLOBAL_LOCK:
if (OP1_TYPE == IS_VAR && !free_op1.var) {
@@ -3710,8 +3710,6 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
retval = &EX_T(opline->result.var).tmp_var;
ZVAL_COPY_VALUE(retval, &c->value);
zval_copy_ctor(retval);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
} else {
/* class constant */
zend_class_entry *ce;
@@ -3722,8 +3720,7 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
value = CACHED_PTR(opline->op2.literal->cache_slot);
ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, *value);
zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
goto constant_fetch_end;
} else if (CACHED_PTR(opline->op1.literal->cache_slot)) {
ce = CACHED_PTR(opline->op1.literal->cache_slot);
} else {
@@ -3741,8 +3738,7 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
if ((value = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce)) != NULL) {
ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, *value);
zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
goto constant_fetch_end;
}
}
@@ -3751,7 +3747,7 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
zend_class_entry *old_scope = EG(scope);
EG(scope) = ce;
zval_update_constant(value, (void *) 1 TSRMLS_CC);
zval_update_constant(value, 1 TSRMLS_CC);
EG(scope) = old_scope;
}
if (OP1_TYPE == IS_CONST) {
@@ -3767,10 +3763,13 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
} else {
zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(opline->op2.zv));
}
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
constant_fetch_end:
if (Z_TYPE(EX_T(opline->result.var).tmp_var) == IS_ARRAY) {
zend_error_noreturn(E_ERROR, "Arrays are not allowed in constants at run-time");
}
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMP|VAR|UNUSED|CV)
@@ -5376,11 +5375,8 @@ ZEND_VM_HANDLER(143, ZEND_DECLARE_CONST, CONST, CONST)
zval *tmp_ptr = &tmp;
ZVAL_COPY_VALUE(&tmp, val);
if (Z_TYPE_P(val) == IS_CONSTANT_ARRAY) {
zval_copy_ctor(&tmp);
}
INIT_PZVAL(&tmp);
zval_update_constant(&tmp_ptr, NULL TSRMLS_CC);
zval_update_constant(&tmp_ptr, 0 TSRMLS_CC);
c.value = *tmp_ptr;
} else {
INIT_PZVAL_COPY(&c.value, val);
+40 -46
View File
@@ -3684,7 +3684,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_CONST(int type
break;
case ZEND_FETCH_STATIC:
zval_update_constant(retval, (void*) 1 TSRMLS_CC);
zval_update_constant(retval, 1 TSRMLS_CC);
break;
case ZEND_FETCH_GLOBAL_LOCK:
if (IS_CONST == IS_VAR && !free_op1.var) {
@@ -3971,8 +3971,6 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCO
retval = &EX_T(opline->result.var).tmp_var;
ZVAL_COPY_VALUE(retval, &c->value);
zval_copy_ctor(retval);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
} else {
/* class constant */
zend_class_entry *ce;
@@ -3983,8 +3981,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCO
value = CACHED_PTR(opline->op2.literal->cache_slot);
ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, *value);
zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
goto constant_fetch_end;
} else if (CACHED_PTR(opline->op1.literal->cache_slot)) {
ce = CACHED_PTR(opline->op1.literal->cache_slot);
} else {
@@ -4002,8 +3999,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCO
if ((value = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce)) != NULL) {
ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, *value);
zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
goto constant_fetch_end;
}
}
@@ -4012,7 +4008,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCO
zend_class_entry *old_scope = EG(scope);
EG(scope) = ce;
zval_update_constant(value, (void *) 1 TSRMLS_CC);
zval_update_constant(value, 1 TSRMLS_CC);
EG(scope) = old_scope;
}
if (IS_CONST == IS_CONST) {
@@ -4028,10 +4024,13 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCO
} else {
zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(opline->op2.zv));
}
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
constant_fetch_end:
if (Z_TYPE(EX_T(opline->result.var).tmp_var) == IS_ARRAY) {
zend_error_noreturn(E_ERROR, "Arrays are not allowed in constants at run-time");
}
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -4309,11 +4308,8 @@ static int ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCOD
zval *tmp_ptr = &tmp;
ZVAL_COPY_VALUE(&tmp, val);
if (Z_TYPE_P(val) == IS_CONSTANT_ARRAY) {
zval_copy_ctor(&tmp);
}
INIT_PZVAL(&tmp);
zval_update_constant(&tmp_ptr, NULL TSRMLS_CC);
zval_update_constant(&tmp_ptr, 0 TSRMLS_CC);
c.value = *tmp_ptr;
} else {
INIT_PZVAL_COPY(&c.value, val);
@@ -5572,7 +5568,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_VAR(int type,
break;
case ZEND_FETCH_STATIC:
zval_update_constant(retval, (void*) 1 TSRMLS_CC);
zval_update_constant(retval, 1 TSRMLS_CC);
break;
case ZEND_FETCH_GLOBAL_LOCK:
if (IS_CONST == IS_VAR && !free_op1.var) {
@@ -6324,7 +6320,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_UNUSED(int typ
break;
case ZEND_FETCH_STATIC:
zval_update_constant(retval, (void*) 1 TSRMLS_CC);
zval_update_constant(retval, 1 TSRMLS_CC);
break;
case ZEND_FETCH_GLOBAL_LOCK:
if (IS_CONST == IS_VAR && !free_op1.var) {
@@ -9094,7 +9090,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_CONST(int type,
zval_dtor(free_op1.var);
break;
case ZEND_FETCH_STATIC:
zval_update_constant(retval, (void*) 1 TSRMLS_CC);
zval_update_constant(retval, 1 TSRMLS_CC);
break;
case ZEND_FETCH_GLOBAL_LOCK:
if (IS_TMP_VAR == IS_VAR && !free_op1.var) {
@@ -10850,7 +10846,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_VAR(int type, ZE
zval_dtor(free_op1.var);
break;
case ZEND_FETCH_STATIC:
zval_update_constant(retval, (void*) 1 TSRMLS_CC);
zval_update_constant(retval, 1 TSRMLS_CC);
break;
case ZEND_FETCH_GLOBAL_LOCK:
if (IS_TMP_VAR == IS_VAR && !free_op1.var) {
@@ -11604,7 +11600,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_UNUSED(int type,
zval_dtor(free_op1.var);
break;
case ZEND_FETCH_STATIC:
zval_update_constant(retval, (void*) 1 TSRMLS_CC);
zval_update_constant(retval, 1 TSRMLS_CC);
break;
case ZEND_FETCH_GLOBAL_LOCK:
if (IS_TMP_VAR == IS_VAR && !free_op1.var) {
@@ -15024,7 +15020,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_CONST(int type,
zval_ptr_dtor_nogc(&free_op1.var);
break;
case ZEND_FETCH_STATIC:
zval_update_constant(retval, (void*) 1 TSRMLS_CC);
zval_update_constant(retval, 1 TSRMLS_CC);
break;
case ZEND_FETCH_GLOBAL_LOCK:
if (IS_VAR == IS_VAR && !free_op1.var) {
@@ -15924,8 +15920,6 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE
retval = &EX_T(opline->result.var).tmp_var;
ZVAL_COPY_VALUE(retval, &c->value);
zval_copy_ctor(retval);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
} else {
/* class constant */
zend_class_entry *ce;
@@ -15936,8 +15930,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE
value = CACHED_PTR(opline->op2.literal->cache_slot);
ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, *value);
zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
goto constant_fetch_end;
} else if (CACHED_PTR(opline->op1.literal->cache_slot)) {
ce = CACHED_PTR(opline->op1.literal->cache_slot);
} else {
@@ -15955,8 +15948,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE
if ((value = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce)) != NULL) {
ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, *value);
zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
goto constant_fetch_end;
}
}
@@ -15965,7 +15957,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE
zend_class_entry *old_scope = EG(scope);
EG(scope) = ce;
zval_update_constant(value, (void *) 1 TSRMLS_CC);
zval_update_constant(value, 1 TSRMLS_CC);
EG(scope) = old_scope;
}
if (IS_VAR == IS_CONST) {
@@ -15981,10 +15973,13 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE
} else {
zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(opline->op2.zv));
}
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
constant_fetch_end:
if (Z_TYPE(EX_T(opline->result.var).tmp_var) == IS_ARRAY) {
zend_error_noreturn(E_ERROR, "Arrays are not allowed in constants at run-time");
}
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -19622,7 +19617,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_VAR(int type, ZE
zval_ptr_dtor_nogc(&free_op1.var);
break;
case ZEND_FETCH_STATIC:
zval_update_constant(retval, (void*) 1 TSRMLS_CC);
zval_update_constant(retval, 1 TSRMLS_CC);
break;
case ZEND_FETCH_GLOBAL_LOCK:
if (IS_VAR == IS_VAR && !free_op1.var) {
@@ -21610,7 +21605,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_UNUSED(int type,
zval_ptr_dtor_nogc(&free_op1.var);
break;
case ZEND_FETCH_STATIC:
zval_update_constant(retval, (void*) 1 TSRMLS_CC);
zval_update_constant(retval, 1 TSRMLS_CC);
break;
case ZEND_FETCH_GLOBAL_LOCK:
if (IS_VAR == IS_VAR && !free_op1.var) {
@@ -25537,8 +25532,6 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPC
retval = &EX_T(opline->result.var).tmp_var;
ZVAL_COPY_VALUE(retval, &c->value);
zval_copy_ctor(retval);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
} else {
/* class constant */
zend_class_entry *ce;
@@ -25549,8 +25542,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPC
value = CACHED_PTR(opline->op2.literal->cache_slot);
ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, *value);
zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
goto constant_fetch_end;
} else if (CACHED_PTR(opline->op1.literal->cache_slot)) {
ce = CACHED_PTR(opline->op1.literal->cache_slot);
} else {
@@ -25568,8 +25560,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPC
if ((value = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce)) != NULL) {
ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, *value);
zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
goto constant_fetch_end;
}
}
@@ -25578,7 +25569,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPC
zend_class_entry *old_scope = EG(scope);
EG(scope) = ce;
zval_update_constant(value, (void *) 1 TSRMLS_CC);
zval_update_constant(value, 1 TSRMLS_CC);
EG(scope) = old_scope;
}
if (IS_UNUSED == IS_CONST) {
@@ -25594,10 +25585,13 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPC
} else {
zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(opline->op2.zv));
}
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
constant_fetch_end:
if (Z_TYPE(EX_T(opline->result.var).tmp_var) == IS_ARRAY) {
zend_error_noreturn(E_ERROR, "Arrays are not allowed in constants at run-time");
}
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -32488,7 +32482,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_CONST(int type, Z
break;
case ZEND_FETCH_STATIC:
zval_update_constant(retval, (void*) 1 TSRMLS_CC);
zval_update_constant(retval, 1 TSRMLS_CC);
break;
case ZEND_FETCH_GLOBAL_LOCK:
if (IS_CV == IS_VAR && !free_op1.var) {
@@ -36712,7 +36706,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_VAR(int type, ZEN
break;
case ZEND_FETCH_STATIC:
zval_update_constant(retval, (void*) 1 TSRMLS_CC);
zval_update_constant(retval, 1 TSRMLS_CC);
break;
case ZEND_FETCH_GLOBAL_LOCK:
if (IS_CV == IS_VAR && !free_op1.var) {
@@ -38560,7 +38554,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_UNUSED(int type,
break;
case ZEND_FETCH_STATIC:
zval_update_constant(retval, (void*) 1 TSRMLS_CC);
zval_update_constant(retval, 1 TSRMLS_CC);
break;
case ZEND_FETCH_GLOBAL_LOCK:
if (IS_CV == IS_VAR && !free_op1.var) {
+1 -1
View File
@@ -160,7 +160,7 @@ PHP_COM_DOTNET_API void php_com_variant_from_zval(VARIANT *v, zval *z, php_int_t
case IS_RESOURCE:
case IS_CONSTANT:
case IS_CONSTANT_ARRAY:
case IS_CONSTANT_AST:
default:
V_VT(v) = VT_NULL;
break;
+2
View File
@@ -248,6 +248,8 @@ PHP_FUNCTION(curl_multi_getcontent)
smart_str_0(&ch->handlers->write->buf);
RETURN_STRINGL(ch->handlers->write->buf.c, ch->handlers->write->buf.len, 1);
}
RETURN_EMPTY_STRING();
}
/* }}} */
+4
View File
@@ -2801,6 +2801,10 @@ static int php_date_initialize_from_hash(zval **return_value, php_date_obj **dat
tzi = php_date_parse_tzfile(Z_STRVAL_PP(z_timezone), DATE_TIMEZONEDB TSRMLS_CC);
if (tzi == NULL) {
return 0;
}
ALLOC_INIT_ZVAL(tmp_obj);
tzobj = zend_object_store_get_object(php_date_instantiate(date_ce_timezone, tmp_obj TSRMLS_CC) TSRMLS_CC);
tzobj->type = TIMELIB_ZONETYPE_ID;
+11
View File
@@ -0,0 +1,11 @@
--TEST--
Test for bug #66721: __wakeup of DateTime segfaults when invalid object data is supplied
--CREDITS--
Boro Sitnikovski <buritomath@yahoo.com>
--FILE--
<?php
$y = 'O:8:"DateTime":3:{s:4:"date";s:19:"2014-02-15 02:00:51";s:13:"timezone_type";i:3;s:8:"timezone";s:10:"1234567890";}';
var_dump(unserialize($y));
?>
--EXPECTF--
Fatal error: Invalid serialization data for DateTime object in %s on line %d
-4
View File
@@ -1,7 +1,3 @@
dnl
dnl $Id$
dnl
PHP_ARG_WITH(interbase,for InterBase support,
[ --with-interbase[=DIR] Include InterBase support. DIR is the InterBase base
install directory [/usr/interbase]])
-1
View File
@@ -1,4 +1,3 @@
// $Id$
// vim:ft=javascript
ARG_WITH("interbase", "InterBase support", "no");
-2
View File
@@ -16,8 +16,6 @@
+----------------------------------------------------------------------+
*/
/* $Id$ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
-2
View File
@@ -16,8 +16,6 @@
+----------------------------------------------------------------------+
*/
/* $Id$ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
-2
View File
@@ -16,8 +16,6 @@
+----------------------------------------------------------------------+
*/
/* $Id$ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
-2
View File
@@ -16,8 +16,6 @@
+----------------------------------------------------------------------+
*/
/* $Id$ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
-2
View File
@@ -18,8 +18,6 @@
+----------------------------------------------------------------------+
*/
/* $Id$ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
-2
View File
@@ -18,8 +18,6 @@
+----------------------------------------------------------------------+
*/
/* $Id$ */
#ifndef PHP_IBASE_INCLUDES_H
#define PHP_IBASE_INCLUDES_H
-2
View File
@@ -16,8 +16,6 @@
+----------------------------------------------------------------------+
*/
/* $Id$ */
/**
* This UDF library adds the ability to call PHP functions from SQL
* statements. Because of SQL's strong typing, you will have to declare
-2
View File
@@ -18,8 +18,6 @@
+----------------------------------------------------------------------+
*/
/* $Id$ */
#ifndef PHP_INTERBASE_H
#define PHP_INTERBASE_H
+1 -1
View File
@@ -1,4 +1,4 @@
<?php /* $Id$ */
<?php
srand((double)microtime()*1000000);
+1 -1
View File
@@ -1,4 +1,4 @@
<?php /* $Id$ */
<?php
if (!extension_loaded("interbase")) print "skip interbase extension not available";
require("interbase.inc");
@@ -1,9 +1,8 @@
--TEST--
IntlBreakIterator::getLocale(): basic test
--SKIPIF--
<?php
if (!extension_loaded('intl'))
die('skip intl extension not enabled');
<?php if (!extension_loaded('intl')) die('skip intl extension not enabled'); ?>
<?php if (version_compare(INTL_ICU_VERSION, '53.1') >= 0) die('skip for ICU < 53.1'); ?>
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
@@ -18,4 +17,4 @@ var_dump($bi->getLocale(1));
--EXPECT--
string(4) "root"
string(4) "root"
==DONE==
==DONE==
@@ -0,0 +1,20 @@
--TEST--
IntlBreakIterator::getLocale(): basic test
--SKIPIF--
<?php if (!extension_loaded('intl')) die('skip intl extension not enabled'); ?>
<?php if (version_compare(INTL_ICU_VERSION, '53.1') < 0) die('skip for ICU >= 53.1'); ?>
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
ini_set("intl.default_locale", "pt_PT");
$bi = IntlBreakIterator::createSentenceInstance('pt');
var_dump($bi->getLocale(0));
var_dump($bi->getLocale(1));
?>
==DONE==
--EXPECT--
string(4) "root"
string(2) "pt"
==DONE==
+3 -5
View File
@@ -1,11 +1,9 @@
--TEST--
Bug #62070: Collator::getSortKey() returns garbage
--SKIPIF--
<?php
if (!extension_loaded('intl'))
die('skip intl extension not enabled');
if (version_compare(INTL_ICU_VERSION, '49') < 0)
die('skip ICU >= 49 only');
<?php if (!extension_loaded('intl')) die('skip intl extension not enabled'); ?>
<?php if (version_compare(INTL_ICU_VERSION, '49') < 0) die('skip for ICU >= 49'); ?>
<?php if (version_compare(INTL_ICU_VERSION, '53.1') >= 0) die('skip for ICU < 53.1'); ?>
--FILE--
<?php
$s1 = 'Hello';
+15
View File
@@ -0,0 +1,15 @@
--TEST--
Bug #62070: Collator::getSortKey() returns garbage
--SKIPIF--
<?php if (!extension_loaded('intl')) die('skip intl extension not enabled'); ?>
<?php if (version_compare(INTL_ICU_VERSION, '53.1') < 0) die('skip for ICU >= 53.1'); ?>
--FILE--
<?php
$s1 = 'Hello';
$coll = collator_create('en_US');
$res = collator_get_sort_key($coll, $s1);
echo urlencode($res);
--EXPECT--
71%3F%3FE%01%09%01%DC%08
+3 -2
View File
@@ -1,8 +1,9 @@
--TEST--
create() icu >= 4.8
create() icu >= 4.8 && icu < 53.1
--SKIPIF--
<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
<?php if(version_compare(INTL_ICU_VERSION, '4.8') < 0) print 'skip'; ?>
<?php if(version_compare(INTL_ICU_VERSION, '4.8') < 0) print 'skip for ICU >= 4.8'; ?>
<?php if (version_compare(INTL_ICU_VERSION, '53.1') >= 0) die('skip for ICU < 53.1'); ?>
--FILE--
<?php
+82
View File
@@ -0,0 +1,82 @@
--TEST--
create() icu >= 53.1
--SKIPIF--
<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
<?php if (version_compare(INTL_ICU_VERSION, '53.1') < 0) die('skip for ICU >= 53.1'); ?>
--FILE--
<?php
/*
* Try creating collator with different locales
* with Procedural and Object methods.
*/
function ut_main()
{
$res_str = '';
$locales = array(
'EN-US-ODESSA',
'UK_UA_ODESSA',
'uk-ua_CALIFORNIA@currency=;currency=GRN',
'',
'root',
'uk@currency=EURO',
'1234567891113151719212325272931333537394143454749515357596163656769717375777981838587899193959799'
);
foreach( $locales as $locale )
{
// Create Collator with the current locale.
$coll = ut_coll_create( $locale );
if( !is_object($coll) )
{
$res_str .= "Error creating collator with '$locale' locale: " .
intl_get_error_message() . "\n";
continue;
}
// Get the requested, valid and actual locales.
$vloc = ut_coll_get_locale( $coll, Locale::VALID_LOCALE );
$aloc = ut_coll_get_locale( $coll, Locale::ACTUAL_LOCALE );
// Show them.
$res_str .= "Locale: '$locale'\n" .
" ULOC_REQUESTED_LOCALE = '$locale'\n" .
" ULOC_VALID_LOCALE = '$vloc'\n" .
" ULOC_ACTUAL_LOCALE = '$aloc'\n";
}
return $res_str;
}
include_once( 'ut_common.inc' );
ut_run();
?>
--EXPECTF--
Locale: 'EN-US-ODESSA'
ULOC_REQUESTED_LOCALE = 'EN-US-ODESSA'
ULOC_VALID_LOCALE = 'en_US'
ULOC_ACTUAL_LOCALE = 'root'
Locale: 'UK_UA_ODESSA'
ULOC_REQUESTED_LOCALE = 'UK_UA_ODESSA'
ULOC_VALID_LOCALE = 'uk'
ULOC_ACTUAL_LOCALE = 'uk'
Locale: 'uk-ua_CALIFORNIA@currency=;currency=GRN'
ULOC_REQUESTED_LOCALE = 'uk-ua_CALIFORNIA@currency=;currency=GRN'
ULOC_VALID_LOCALE = 'root'
ULOC_ACTUAL_LOCALE = 'root'
Locale: ''
ULOC_REQUESTED_LOCALE = ''
ULOC_VALID_LOCALE = '%s'
ULOC_ACTUAL_LOCALE = '%s'
Locale: 'root'
ULOC_REQUESTED_LOCALE = 'root'
ULOC_VALID_LOCALE = 'root'
ULOC_ACTUAL_LOCALE = 'root'
Locale: 'uk@currency=EURO'
ULOC_REQUESTED_LOCALE = 'uk@currency=EURO'
ULOC_VALID_LOCALE = 'uk'
ULOC_ACTUAL_LOCALE = 'uk'
Error creating collator with '1234567891113151719212325272931333537394143454749515357596163656769717375777981838587899193959799' locale: Locale string too long, should be no longer than 80 characters: U_ILLEGAL_ARGUMENT_ERROR
@@ -3,6 +3,7 @@ collator_get_sort_key()
--SKIPIF--
<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
<?php if (version_compare(INTL_ICU_VERSION, '51.2') < 0) die('skip for ICU >= 51.2'); ?>
<?php if (version_compare(INTL_ICU_VERSION, '53.1') >= 0) die('skip for ICU < 53.1'); ?>
--FILE--
<?php
@@ -0,0 +1,98 @@
--TEST--
collator_get_sort_key()
--SKIPIF--
<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
<?php if (version_compare(INTL_ICU_VERSION, '53.1') < 0) die('skip for ICU >= 53.1'); ?>
--FILE--
<?php
/*
* Get sort keys using various locales
*/
function sort_arrays( $locale, $data )
{
$res_str = '';
$coll = ut_coll_create( $locale );
foreach($data as $value) {
$res_val = ut_coll_get_sort_key( $coll, $value );
$res_str .= "source: ".$value."\n".
"key: ".bin2hex($res_val)."\n";
}
return $res_str;
}
function ut_main()
{
$res_str = '';
// Regular strings keys
$test_params = array(
'abc', 'abd', 'aaa',
'аа', 'а', 'z',
'', null , '3',
'y' , 'i' , 'k'
);
$res_str .= sort_arrays( 'en_US', $test_params );
// Sort a non-ASCII array using ru_RU locale.
$test_params = array(
'абг', 'абв', 'жжж', 'эюя'
);
$res_str .= sort_arrays( 'ru_RU', $test_params );
// Sort an array using Lithuanian locale.
$res_str .= sort_arrays( 'lt_LT', $test_params );
return $res_str . "\n";
}
include_once( 'ut_common.inc' );
ut_run();
?>
--EXPECT--
source: abc
key: 292b2d01070107
source: abd
key: 292b2f01070107
source: aaa
key: 29292901070107
source: аа
key: 5e090901060106
source: а
key: 5e0901050105
source: z
key: 5b01050105
source:
key: 0101
source:
key: 0101
source: 3
key: 1a01050105
source: y
key: 5901050105
source: i
key: 3901050105
source: k
key: 3d01050105
source: абг
key: 2809131701070107
source: абв
key: 2809131501070107
source: жжж
key: 2833333301070107
source: эюя
key: 28cdd1d501070107
source: абг
key: 5e09131701070107
source: абв
key: 5e09131501070107
source: жжж
key: 5e33333301070107
source: эюя
key: 5ecdd1d501070107
+3 -2
View File
@@ -1,8 +1,9 @@
--TEST--
numfmt_format() icu >= 52.1
numfmt_format() icu >= 52.1 && icu < 53.1
--SKIPIF--
<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
<?php if(version_compare(INTL_ICU_VERSION, '52.1') < 0) print 'skip'; ?>
<?php if(version_compare(INTL_ICU_VERSION, '52.1') < 0) print 'skip for ICU >= 52.1'; ?>
<?php if (version_compare(INTL_ICU_VERSION, '53.1') >= 0) die('skip for ICU < 53.1'); ?>
--FILE--
<?php
+130
View File
@@ -0,0 +1,130 @@
--TEST--
numfmt_format() icu >= 53.1
--SKIPIF--
<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
<?php if (version_compare(INTL_ICU_VERSION, '53.1') < 0) die('skip for ICU >= 53.1'); ?>
--FILE--
<?php
/*
* Format a number using misc locales/patterns.
*/
/*
* TODO: doesn't pass on ICU 3.6 because 'ru' and 'de' locales changed
* currency and percent formatting.
*/
function ut_main()
{
$styles = array(
NumberFormatter::PATTERN_DECIMAL => '##.#####################',
NumberFormatter::DECIMAL => '',
NumberFormatter::CURRENCY => '',
NumberFormatter::PERCENT => '',
NumberFormatter::SCIENTIFIC => '',
NumberFormatter::SPELLOUT => '@@@@@@@',
NumberFormatter::ORDINAL => '',
NumberFormatter::DURATION => '',
NumberFormatter::PATTERN_RULEBASED => '#####.###',
1234999, // bad one
);
$integer = array(
NumberFormatter::ORDINAL => '',
NumberFormatter::DURATION => '',
);
$locales = array(
'en_US',
'ru_UA',
'de',
'fr',
'en_UK'
);
$str_res = '';
$number = 1234567.891234567890000;
foreach( $locales as $locale )
{
$str_res .= "\nLocale is: $locale\n";
foreach( $styles as $style => $pattern )
{
$fmt = ut_nfmt_create( $locale, $style, $pattern );
if(!$fmt) {
$str_res .= "Bad formatter!\n";
continue;
}
$str_res .= dump( isset($integer[$style])?ut_nfmt_format( $fmt, $number, NumberFormatter::TYPE_INT32):ut_nfmt_format( $fmt, $number ) ) . "\n";
}
}
return $str_res;
}
include_once( 'ut_common.inc' );
// Run the test
ut_run();
?>
--EXPECTREGEX--
Locale is: en_US
'1234567.89123457'
'1,234,567.891'
'\$1,234,567.89'
'123,456,789%'
'1.23456789123457E6'
'one million,? two hundred (and )?thirty-four thousand,? five hundred (and )?sixty-seven point eight nine one two three four five seven'
'1,234,567(th|ᵗʰ)'
'342:56:07'
'#####.###'
'USD1,234,567.89'
Locale is: ru_UA
'1234567,89123457'
'1 234 567,891'
'1 234 567,89 ?(грн\.|₴)'
'123 456 789 ?%'
'1,23456789123457E6'
'один миллион двести тридцать четыре тысяч пятьсот шестьдесят семь запятая восемь девять один два три четыре пять семь'
'1 234 567.?'
'1 234 567'
'#####.###'
'1 234 567,89 UAH'
Locale is: de
'1234567,89123457'
'1.234.567,891'
'(¤ )?1.234.567,89( ¤)?'
'123\.456\.789 %'
'1,23456789123457E6'
'eine Million zwei­hundert­vier­und­dreißig­tausend­fünf­hundert­sieben­und­sechzig Komma acht neun eins zwei drei vier fünf sieben'
'1.234.567.?'
'1.234.567'
'#####.###'
'1.234.567,89 ¤¤'
Locale is: fr
'1234567,89123457'
'1 234 567,891'
'1 234 567,89 ¤'
'123 456 789 ?%'
'1,23456789123457E6'
'un million deux cent trente-quatre mille cinq cent soixante-sept virgule huit neuf un deux trois quatre cinq sept'
'1 234 567e'
'1 234 567'
'#####.###'
'1 234 567,89 ¤¤'
Locale is: en_UK
'1234567.89123457'
'1,234,567.891'
'¤1,234,567.89'
'123,456,789%'
'1.23456789123457E6'
'one million,? two hundred (and )?thirty-four thousand,? five hundred (and )?sixty-seven point eight nine one two three four five seven'
'1,234,567(th|ᵗʰ)'
'342:56:07'
'#####.###'
'¤¤1,234,567.89'
+2 -1
View File
@@ -1,8 +1,9 @@
--TEST--
locale_get_display_name() icu >= 52.1
locale_get_display_name() icu >= 52.1 && icu < 53.1
--SKIPIF--
<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
<?php if (version_compare(INTL_ICU_VERSION, '52.1') < 0) die('skip for ICU >= 52.1'); ?>
<?php if (version_compare(INTL_ICU_VERSION, '53.1') >= 0) die('skip for ICU < 53.1'); ?>
--FILE--
<?php
@@ -0,0 +1,342 @@
--TEST--
locale_get_display_name() icu >= 53.1
--SKIPIF--
<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
<?php if (version_compare(INTL_ICU_VERSION, '53.1') < 0) die('skip for ICU >= 53.1'); ?>
--FILE--
<?php
/*
* Try getting the display_name for different locales
* with Procedural and Object methods.
*/
function ut_main()
{
$res_str='';
$disp_locales=array('en','fr','de');
$locales = array(
'sl_IT_nedis_KIRTI',
'sl_IT_nedis-a-kirti-x-xyz',
'sl_IT_rozaj',
'sl_IT_NEDIS_ROJAZ_1901',
'i-enochian',
'zh-hakka',
'zh-wuu',
'i-tay',
'sgn-BE-nl',
'sgn-CH-de',
'sl_IT_rozaj@currency=EUR',
'uk-ua_CALIFORNIA@currency=;currency=GRN',
'root',
'uk@currency=EURO',
'Hindi',
//Simple language subtag
'de',
'fr',
'ja',
'i-enochian', //(example of a grandfathered tag)
//Language subtag plus Script subtag:
'zh-Hant',
'zh-Hans',
'sr-Cyrl',
'sr-Latn',
//Language-Script-Region
'zh-Hans-CN',
'sr-Latn-CS',
//Language-Variant
'sl-rozaj',
'sl-nedis',
//Language-Region-Variant
'de-CH-1901',
'sl-IT-nedis',
//Language-Script-Region-Variant
'sl-Latn-IT-nedis',
//Language-Region:
'de-DE',
'en-US',
'es-419',
//Private use subtags:
'de-CH-x-phonebk',
'az-Arab-x-AZE-derbend',
//Extended language subtags
'zh-min',
'zh-min-nan-Hant-CN',
//Private use registry values
'x-whatever',
'qaa-Qaaa-QM-x-southern',
'sr-Latn-QM',
'sr-Qaaa-CS',
/*Tags that use extensions (examples ONLY: extensions MUST be defined
by revision or update to this document or by RFC): */
'en-US-u-islamCal',
'zh-CN-a-myExt-x-private',
'en-a-myExt-b-another',
//Some Invalid Tags:
'de-419-DE',
'a-DE',
'ar-a-aaa-b-bbb-a-ccc'
);
$res_str = '';
foreach( $locales as $locale )
{
$res_str .= "locale='$locale'\n";
foreach( $disp_locales as $disp_locale )
{
$scr = ut_loc_get_display_name( $locale ,$disp_locale );
$scr = str_replace(array('(', ')'), '#', $scr);
$res_str .= "disp_locale=$disp_locale : display_name=$scr";
$res_str .= "\n";
}
$res_str .= "-----------------\n";
}
return $res_str;
}
include_once( 'ut_common.inc' );
ut_run();
?>
--EXPECTREGEX--
locale='sl_IT_nedis_KIRTI'
disp_locale=en : display_name=Slovenian #Italy, NEDIS_KIRTI#
disp_locale=fr : display_name=slovène #Italie, NEDIS_KIRTI#
disp_locale=de : display_name=Slowenisch #Italien, NEDIS_KIRTI#
-----------------
locale='sl_IT_nedis-a-kirti-x-xyz'
disp_locale=en : display_name=Slovenian #Italy, NEDIS_A_KIRTI_X_XYZ#
disp_locale=fr : display_name=slovène #Italie, NEDIS_A_KIRTI_X_XYZ#
disp_locale=de : display_name=Slowenisch #Italien, NEDIS_A_KIRTI_X_XYZ#
-----------------
locale='sl_IT_rozaj'
disp_locale=en : display_name=Slovenian #Italy, Resian#
disp_locale=fr : display_name=slovène #Italie, dialecte de Resia#
disp_locale=de : display_name=Slowenisch #Italien, (ROZAJ|Resianisch)#
-----------------
locale='sl_IT_NEDIS_ROJAZ_1901'
disp_locale=en : display_name=Slovenian #Italy, NEDIS_ROJAZ_1901#
disp_locale=fr : display_name=slovène #Italie, NEDIS_ROJAZ_1901#
disp_locale=de : display_name=Slowenisch #Italien, NEDIS_ROJAZ_1901#
-----------------
locale='i-enochian'
disp_locale=en : display_name=i-enochian #Private-Use=i-enochian#
disp_locale=fr : display_name=i-enochian #Usage privé=i-enochian#
disp_locale=de : display_name=i-enochian #Privatnutzung=i-enochian#
-----------------
locale='zh-hakka'
disp_locale=en : display_name=Chinese( #HAKKA#)?
disp_locale=fr : display_name=chinois( #HAKKA#)?
disp_locale=de : display_name=Chinesisch( #HAKKA#)?
-----------------
locale='zh-wuu'
disp_locale=en : display_name=Chinese #WUU#
disp_locale=fr : display_name=chinois #WUU#
disp_locale=de : display_name=Chinesisch #WUU#
-----------------
locale='i-tay'
disp_locale=en : display_name=i-tay
disp_locale=fr : display_name=i-tay
disp_locale=de : display_name=i-tay
-----------------
locale='sgn-BE-nl'
disp_locale=en : display_name=sgn #Belgium, NL#
disp_locale=fr : display_name=sgn #Belgique, NL#
disp_locale=de : display_name=sgn #Belgien, NL#
-----------------
locale='sgn-CH-de'
disp_locale=en : display_name=sgn #Switzerland, DE#
disp_locale=fr : display_name=sgn #Suisse, DE#
disp_locale=de : display_name=sgn #Schweiz, DE#
-----------------
locale='sl_IT_rozaj@currency=EUR'
disp_locale=en : display_name=Slovenian #Italy, Resian, [Cc]urrency=Euro#
disp_locale=fr : display_name=slovène #Italie, dialecte de Resia, [Dd]evise=euro#
disp_locale=de : display_name=Slowenisch #Italien, (ROZAJ|Resianisch), Währung=Euro#
-----------------
locale='uk-ua_CALIFORNIA@currency=;currency=GRN'
disp_locale=en : display_name=
disp_locale=fr : display_name=
disp_locale=de : display_name=
-----------------
locale='root'
disp_locale=en : display_name=Root
disp_locale=fr : display_name=racine
disp_locale=de : display_name=[Rr]oot
-----------------
locale='uk@currency=EURO'
disp_locale=en : display_name=Ukrainian #[Cc]urrency=EURO#
disp_locale=fr : display_name=ukrainien #[Dd]evise=EURO#
disp_locale=de : display_name=Ukrainisch #Währung=EURO#
-----------------
locale='Hindi'
disp_locale=en : display_name=hindi
disp_locale=fr : display_name=hindi
disp_locale=de : display_name=hindi
-----------------
locale='de'
disp_locale=en : display_name=German
disp_locale=fr : display_name=allemand
disp_locale=de : display_name=Deutsch
-----------------
locale='fr'
disp_locale=en : display_name=French
disp_locale=fr : display_name=français
disp_locale=de : display_name=Französisch
-----------------
locale='ja'
disp_locale=en : display_name=Japanese
disp_locale=fr : display_name=japonais
disp_locale=de : display_name=Japanisch
-----------------
locale='i-enochian'
disp_locale=en : display_name=i-enochian #Private-Use=i-enochian#
disp_locale=fr : display_name=i-enochian #Usage privé=i-enochian#
disp_locale=de : display_name=i-enochian #Privatnutzung=i-enochian#
-----------------
locale='zh-Hant'
disp_locale=en : display_name=Chinese #Traditional#
disp_locale=fr : display_name=chinois #traditionnel#
disp_locale=de : display_name=Chinesisch #Traditionell#
-----------------
locale='zh-Hans'
disp_locale=en : display_name=Chinese #Simplified#
disp_locale=fr : display_name=chinois #simplifié#
disp_locale=de : display_name=Chinesisch #Vereinfacht#
-----------------
locale='sr-Cyrl'
disp_locale=en : display_name=Serbian #Cyrillic#
disp_locale=fr : display_name=serbe #cyrillique#
disp_locale=de : display_name=Serbisch #Kyrillisch#
-----------------
locale='sr-Latn'
disp_locale=en : display_name=Serbian #Latin#
disp_locale=fr : display_name=serbe #latin#
disp_locale=de : display_name=Serbisch #Lateinisch#
-----------------
locale='zh-Hans-CN'
disp_locale=en : display_name=Chinese #Simplified, China#
disp_locale=fr : display_name=chinois #simplifié, Chine#
disp_locale=de : display_name=Chinesisch #Vereinfacht, China#
-----------------
locale='sr-Latn-CS'
disp_locale=en : display_name=Serbian #Latin, Serbia#
disp_locale=fr : display_name=serbe #latin, Serbie#
disp_locale=de : display_name=Serbisch #Lateinisch, Serbien#
-----------------
locale='sl-rozaj'
disp_locale=en : display_name=Slovenian #Resian#
disp_locale=fr : display_name=slovène #dialecte de Resia#
disp_locale=de : display_name=Slowenisch( #(ROZAJ|Resianisch)#)?
-----------------
locale='sl-nedis'
disp_locale=en : display_name=Slovenian #Natisone dialect#
disp_locale=fr : display_name=slovène #dialecte de Natisone#
disp_locale=de : display_name=Slowenisch #Natisone-Dialekt#
-----------------
locale='de-CH-1901'
disp_locale=en : display_name=German #Switzerland, Traditional German orthography#
disp_locale=fr : display_name=allemand #Suisse, orthographe allemande traditionnelle#
disp_locale=de : display_name=Deutsch #Schweiz, (1901|[aA]lte deutsche Rechtschreibung)#
-----------------
locale='sl-IT-nedis'
disp_locale=en : display_name=Slovenian #Italy, Natisone dialect#
disp_locale=fr : display_name=slovène #Italie, dialecte de Natisone#
disp_locale=de : display_name=Slowenisch #Italien, (NEDIS|Natisone-Dialekt)#
-----------------
locale='sl-Latn-IT-nedis'
disp_locale=en : display_name=Slovenian #Latin, Italy, Natisone dialect#
disp_locale=fr : display_name=slovène #latin, Italie, dialecte de Natisone#
disp_locale=de : display_name=Slowenisch #Lateinisch, Italien, (NEDIS|Natisone-Dialekt)#
-----------------
locale='de-DE'
disp_locale=en : display_name=German #Germany#
disp_locale=fr : display_name=allemand #Allemagne#
disp_locale=de : display_name=Deutsch #Deutschland#
-----------------
locale='en-US'
disp_locale=en : display_name=English #United States#
disp_locale=fr : display_name=anglais #États-Unis#
disp_locale=de : display_name=Englisch #Vereinigte Staaten#
-----------------
locale='es-419'
disp_locale=en : display_name=Spanish #Latin America#
disp_locale=fr : display_name=espagnol #Amérique latine#
disp_locale=de : display_name=Spanisch #Lateinamerika#
-----------------
locale='de-CH-x-phonebk'
disp_locale=en : display_name=German #Switzerland, Private-Use=phonebk#
disp_locale=fr : display_name=allemand #Suisse, Usage privé=phonebk#
disp_locale=de : display_name=Deutsch #Schweiz, Privatnutzung=phonebk#
-----------------
locale='az-Arab-x-AZE-derbend'
disp_locale=en : display_name=Azerbaijani #Arabic, Private-Use=aze-derbend#
disp_locale=fr : display_name=azéri #arabe, Usage privé=aze-derbend#
disp_locale=de : display_name=Aserbaidschanisch #Arabisch, Privatnutzung=aze-derbend#
-----------------
locale='zh-min'
disp_locale=en : display_name=Chinese #MIN#
disp_locale=fr : display_name=chinois #MIN#
disp_locale=de : display_name=Chinesisch #MIN#
-----------------
locale='zh-min-nan-Hant-CN'
disp_locale=en : display_name=Chinese #MIN, NAN_HANT_CN#
disp_locale=fr : display_name=chinois #MIN, NAN_HANT_CN#
disp_locale=de : display_name=Chinesisch #MIN, NAN_HANT_CN#
-----------------
locale='x-whatever'
disp_locale=en : display_name=x-whatever #Private-Use=whatever#
disp_locale=fr : display_name=x-whatever #Usage privé=whatever#
disp_locale=de : display_name=x-whatever #Privatnutzung=whatever#
-----------------
locale='qaa-Qaaa-QM-x-southern'
disp_locale=en : display_name=qaa #Qaaa, QM, Private-Use=southern#
disp_locale=fr : display_name=qaa #Qaaa, QM, Usage privé=southern#
disp_locale=de : display_name=qaa #Qaaa, QM, Privatnutzung=southern#
-----------------
locale='sr-Latn-QM'
disp_locale=en : display_name=Serbian #Latin, QM#
disp_locale=fr : display_name=serbe #latin, QM#
disp_locale=de : display_name=Serbisch #Lateinisch, QM#
-----------------
locale='sr-Qaaa-CS'
disp_locale=en : display_name=Serbian #Qaaa, Serbia#
disp_locale=fr : display_name=serbe #Qaaa, Serbie#
disp_locale=de : display_name=Serbisch #Qaaa, Serbien#
-----------------
locale='en-US-u-islamCal'
disp_locale=en : display_name=English #United States, attribute=islamcal#
disp_locale=fr : display_name=anglais #États-Unis, attribute=islamcal#
disp_locale=de : display_name=Englisch #Vereinigte Staaten, attribute=islamcal#
-----------------
locale='zh-CN-a-myExt-x-private'
disp_locale=en : display_name=Chinese #China, a=myext, Private-Use=private#
disp_locale=fr : display_name=chinois #Chine, a=myext, Usage privé=private#
disp_locale=de : display_name=Chinesisch #China, a=myext, Privatnutzung=private#
-----------------
locale='en-a-myExt-b-another'
disp_locale=en : display_name=English #a=myext, b=another#
disp_locale=fr : display_name=anglais #a=myext, b=another#
disp_locale=de : display_name=Englisch #a=myext, b=another#
-----------------
locale='de-419-DE'
disp_locale=en : display_name=German #Latin America, DE#
disp_locale=fr : display_name=allemand #Amérique latine, DE#
disp_locale=de : display_name=Deutsch #Lateinamerika, DE#
-----------------
locale='a-DE'
disp_locale=en : display_name=a #Germany#
disp_locale=fr : display_name=a #Allemagne#
disp_locale=de : display_name=a #Deutschland#
-----------------
locale='ar-a-aaa-b-bbb-a-ccc'
disp_locale=en : display_name=Arabic #a=aaa, b=bbb#
disp_locale=fr : display_name=arabe #a=aaa, b=bbb#
disp_locale=de : display_name=Arabisch #a=aaa, b=bbb#
-----------------
@@ -1,9 +1,8 @@
--TEST--
IntlTimeZone::getCanonicalID(): second argument
--SKIPIF--
<?php
if (!extension_loaded('intl'))
die('skip intl extension not enabled');
<?php if (!extension_loaded('intl')) die('skip intl extension not enabled'); ?>
<?php if (version_compare(INTL_ICU_VERSION, '53.1') >= 0) die('skip for ICU < 53.1'); ?>
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
@@ -21,4 +20,4 @@ string(13) "Europe/Lisbon"
bool(true)
string(0) ""
bool(false)
==DONE==
==DONE==
@@ -0,0 +1,26 @@
--TEST--
IntlTimeZone::getCanonicalID(): second argument
--SKIPIF--
<?php if (!extension_loaded('intl')) die('skip intl extension not enabled'); ?>
<?php if (version_compare(INTL_ICU_VERSION, '53.1') < 0) die('skip for ICU >= 53.1'); ?>
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
var_dump(IntlTimeZone::getCanonicalID('Portugal', $isSystemId));
var_dump($isSystemId);
/* A valid custom time zone ID has the following syntax: GMT[+|-]hh[[:]mm] */
var_dump(IntlTimeZone::getCanonicalID('GMT +01:25', $isSystemId));
var_dump($isSystemId);
?>
==DONE==
--EXPECTF--
string(13) "Europe/Lisbon"
bool(true)
Warning: IntlTimeZone::getCanonicalID(): intltz_get_canonical_id: error obtaining canonical ID in %stimezone_getCanonicalID_variant1_2.php on line %d
bool(false)
bool(true)
==DONE==
+10 -8
View File
@@ -230,7 +230,7 @@ static inline void json_pretty_print_indent(smart_str *buf, php_int_t options TS
static void json_encode_array(smart_str *buf, zval **val, php_int_t options TSRMLS_DC) /* {{{ */
{
int i, r;
int i, r, need_comma = 0;
HashTable *myht;
if (Z_TYPE_PP(val) == IS_ARRAY) {
@@ -253,7 +253,6 @@ static void json_encode_array(smart_str *buf, zval **val, php_int_t options TSRM
smart_str_appendc(buf, '{');
}
json_pretty_print_char(buf, options, '\n' TSRMLS_CC);
++JSON_G(encoder_depth);
i = myht ? zend_hash_num_elements(myht) : 0;
@@ -266,7 +265,6 @@ static void json_encode_array(smart_str *buf, zval **val, php_int_t options TSRM
php_size_t key_len;
HashPosition pos;
HashTable *tmp_ht;
int need_comma = 0;
zend_hash_internal_pointer_reset_ex(myht, &pos);
for (;; zend_hash_move_forward_ex(myht, &pos)) {
@@ -283,11 +281,11 @@ static void json_encode_array(smart_str *buf, zval **val, php_int_t options TSRM
if (r == PHP_JSON_OUTPUT_ARRAY) {
if (need_comma) {
smart_str_appendc(buf, ',');
json_pretty_print_char(buf, options, '\n' TSRMLS_CC);
} else {
need_comma = 1;
}
json_pretty_print_char(buf, options, '\n' TSRMLS_CC);
json_pretty_print_indent(buf, options TSRMLS_CC);
php_json_encode(buf, *data, options TSRMLS_CC);
} else if (r == PHP_JSON_OUTPUT_OBJECT) {
@@ -302,11 +300,11 @@ static void json_encode_array(smart_str *buf, zval **val, php_int_t options TSRM
if (need_comma) {
smart_str_appendc(buf, ',');
json_pretty_print_char(buf, options, '\n' TSRMLS_CC);
} else {
need_comma = 1;
}
json_pretty_print_char(buf, options, '\n' TSRMLS_CC);
json_pretty_print_indent(buf, options TSRMLS_CC);
json_escape_string(buf, key, key_len - 1, options & ~PHP_JSON_NUMERIC_CHECK TSRMLS_CC);
@@ -318,11 +316,11 @@ static void json_encode_array(smart_str *buf, zval **val, php_int_t options TSRM
} else {
if (need_comma) {
smart_str_appendc(buf, ',');
json_pretty_print_char(buf, options, '\n' TSRMLS_CC);
} else {
need_comma = 1;
}
json_pretty_print_char(buf, options, '\n' TSRMLS_CC);
json_pretty_print_indent(buf, options TSRMLS_CC);
smart_str_appendc(buf, '"');
@@ -347,8 +345,12 @@ static void json_encode_array(smart_str *buf, zval **val, php_int_t options TSRM
JSON_G(error_code) = PHP_JSON_ERROR_DEPTH;
}
--JSON_G(encoder_depth);
json_pretty_print_char(buf, options, '\n' TSRMLS_CC);
json_pretty_print_indent(buf, options TSRMLS_CC);
/* Only keep closing bracket on same line for empty arrays/objects */
if (need_comma) {
json_pretty_print_char(buf, options, '\n' TSRMLS_CC);
json_pretty_print_indent(buf, options TSRMLS_CC);
}
if (r == PHP_JSON_OUTPUT_ARRAY) {
smart_str_appendc(buf, ']');
+20
View File
@@ -0,0 +1,20 @@
--TEST--
Bug #66021 (Blank line inside empty array/object when JSON_PRETTY_PRINT is set)
--SKIPIF--
<?php if (!extension_loaded("json")) print "skip"; ?>
--FILE--
<?php
class Foo {
private $bar = 'baz';
}
echo json_encode([[], (object)[], new Foo], JSON_PRETTY_PRINT), "\n";
?>
--EXPECT--
[
[],
{},
{}
]
+5 -5
View File
@@ -878,7 +878,7 @@ static void php_mysql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
#ifndef MYSQL_USE_MYSQLND
mysql->conn = mysql_init(NULL);
#else
mysql->conn = mysql_init(persistent);
mysql->conn = mysqlnd_init(MYSQLND_CLIENT_KNOWS_RSET_COPY_DATA, persistent);
#endif
if (connect_timeout != -1) {
@@ -887,7 +887,7 @@ static void php_mysql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
#ifndef MYSQL_USE_MYSQLND
if (mysql_real_connect(mysql->conn, host, user, passwd, NULL, port, socket, client_flags)==NULL)
#else
if (mysqlnd_connect(mysql->conn, host, user, passwd, passwd_len, NULL, 0, port, socket, client_flags TSRMLS_CC) == NULL)
if (mysqlnd_connect(mysql->conn, host, user, passwd, passwd_len, NULL, 0, port, socket, client_flags, MYSQLND_CLIENT_KNOWS_RSET_COPY_DATA TSRMLS_CC) == NULL)
#endif
{
/* Populate connect error globals so that the error functions can read them */
@@ -935,7 +935,7 @@ static void php_mysql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
#ifndef MYSQL_USE_MYSQLND
if (mysql_real_connect(mysql->conn, host, user, passwd, NULL, port, socket, client_flags)==NULL)
#else
if (mysqlnd_connect(mysql->conn, host, user, passwd, passwd_len, NULL, 0, port, socket, client_flags TSRMLS_CC) == NULL)
if (mysqlnd_connect(mysql->conn, host, user, passwd, passwd_len, NULL, 0, port, socket, client_flags, MYSQLND_CLIENT_KNOWS_RSET_COPY_DATA TSRMLS_CC) == NULL)
#endif
{
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Link to server lost, unable to reconnect");
@@ -997,7 +997,7 @@ static void php_mysql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
#ifndef MYSQL_USE_MYSQLND
mysql->conn = mysql_init(NULL);
#else
mysql->conn = mysql_init(persistent);
mysql->conn = mysqlnd_init(MYSQLND_CLIENT_KNOWS_RSET_COPY_DATA, persistent);
#endif
if (!mysql->conn) {
MySG(connect_error) = estrdup("OOM");
@@ -1014,7 +1014,7 @@ static void php_mysql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
#ifndef MYSQL_USE_MYSQLND
if (mysql_real_connect(mysql->conn, host, user, passwd, NULL, port, socket, client_flags)==NULL)
#else
if (mysqlnd_connect(mysql->conn, host, user, passwd, passwd_len, NULL, 0, port, socket, client_flags TSRMLS_CC) == NULL)
if (mysqlnd_connect(mysql->conn, host, user, passwd, passwd_len, NULL, 0, port, socket, client_flags, MYSQLND_CLIENT_KNOWS_RSET_COPY_DATA TSRMLS_CC) == NULL)
#endif
{
/* Populate connect error globals so that the error functions can read them */
+1
View File
@@ -721,6 +721,7 @@ PHP_MINIT_FUNCTION(mysqli)
REGISTER_INT_CONSTANT("MYSQLI_USE_RESULT", MYSQLI_USE_RESULT, CONST_CS | CONST_PERSISTENT);
#if defined (MYSQLI_USE_MYSQLND)
REGISTER_INT_CONSTANT("MYSQLI_ASYNC", MYSQLI_ASYNC, CONST_CS | CONST_PERSISTENT);
REGISTER_INT_CONSTANT("MYSQLI_STORE_RESULT_COPY_DATA", MYSQLI_STORE_RESULT_COPY_DATA, CONST_CS | CONST_PERSISTENT);
#endif
/* for mysqli_fetch_assoc */
+11 -5
View File
@@ -1525,7 +1525,7 @@ void php_mysqli_init(INTERNAL_FUNCTION_PARAMETERS)
We create always persistent, as if the user want to connecto
to p:somehost, we can't convert the handle then
*/
if (!(mysql->mysql = mysql_init(TRUE)))
if (!(mysql->mysql = mysqlnd_init(MYSQLND_CLIENT_KNOWS_RSET_COPY_DATA, TRUE)))
#endif
{
efree(mysql);
@@ -2617,7 +2617,7 @@ PHP_FUNCTION(mysqli_stmt_sqlstate)
}
/* }}} */
/* {{{ proto object mysqli_store_result(object link)
/* {{{ proto object mysqli_store_result(object link [, flags])
Buffer result set on client */
PHP_FUNCTION(mysqli_store_result)
{
@@ -2625,13 +2625,19 @@ PHP_FUNCTION(mysqli_store_result)
MYSQL_RES *result;
zval *mysql_link;
MYSQLI_RESOURCE *mysqli_resource;
long flags = 0;
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O|l", &mysql_link, mysqli_link_class_entry, &flags) == FAILURE) {
return;
}
MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
if (!(result = mysql_store_result(mysql->mysql))) {
#if MYSQLI_USE_MYSQLND
result = flags & MYSQLI_STORE_RESULT_COPY_DATA? mysqlnd_store_result_ofs(mysql->mysql) : mysqlnd_store_result(mysql->mysql);
#else
result = mysql_store_result(mysql->mysql);
#endif
if (!result) {
MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
RETURN_FALSE;
}
+13 -2
View File
@@ -142,6 +142,17 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_mysqli_rollback, 0, 0, 0)
ZEND_ARG_INFO(0, name)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_mysqli_store_result, 0, 0, 1)
MYSQLI_ZEND_ARG_OBJ_INFO_LINK()
ZEND_ARG_INFO(0, flags)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_store_result, 0, 0, 0)
ZEND_ARG_INFO(0, flags)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_mysqli_change_user, 0, 0, 4)
MYSQLI_ZEND_ARG_OBJ_INFO_LINK()
ZEND_ARG_INFO(0, user)
@@ -498,7 +509,7 @@ const zend_function_entry mysqli_functions[] = {
PHP_FE(mysqli_sqlstate, arginfo_mysqli_only_link)
PHP_FE(mysqli_ssl_set, arginfo_mysqli_ssl_set)
PHP_FE(mysqli_stat, arginfo_mysqli_only_link)
PHP_FE(mysqli_store_result, arginfo_mysqli_only_link)
PHP_FE(mysqli_store_result, arginfo_mysqli_store_result)
PHP_FE(mysqli_thread_id, arginfo_mysqli_only_link)
PHP_FE(mysqli_thread_safe, arginfo_mysqli_no_params)
PHP_FE(mysqli_use_result, arginfo_mysqli_only_link)
@@ -568,7 +579,7 @@ const zend_function_entry mysqli_link_methods[] = {
PHP_FALIAS(ssl_set, mysqli_ssl_set, arginfo_class_mysqli_ssl_set)
PHP_FALIAS(stat, mysqli_stat, arginfo_mysqli_no_params)
PHP_FALIAS(stmt_init, mysqli_stmt_init, arginfo_mysqli_no_params)
PHP_FALIAS(store_result, mysqli_store_result, arginfo_mysqli_no_params)
PHP_FALIAS(store_result, mysqli_store_result, arginfo_class_store_result)
PHP_FALIAS(thread_safe, mysqli_thread_safe, arginfo_mysqli_no_params)
PHP_FALIAS(use_result, mysqli_use_result, arginfo_mysqli_no_params)
PHP_FALIAS(refresh,mysqli_refresh, arginfo_class_mysqli_refresh)
+10 -5
View File
@@ -217,7 +217,7 @@ void mysqli_common_connect(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_real_conne
#if !defined(MYSQLI_USE_MYSQLND)
if (!(mysql->mysql = mysql_init(NULL))) {
#else
if (!(mysql->mysql = mysqlnd_init(persistent))) {
if (!(mysql->mysql = mysqlnd_init(MYSQLND_CLIENT_KNOWS_RSET_COPY_DATA, persistent))) {
#endif
goto err;
}
@@ -240,7 +240,7 @@ void mysqli_common_connect(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_real_conne
if (mysql_real_connect(mysql->mysql, hostname, username, passwd, dbname, port, socket, flags) == NULL)
#else
if (mysqlnd_connect(mysql->mysql, hostname, username, passwd, passwd_len, dbname, dbname_len,
port, socket, flags TSRMLS_CC) == NULL)
port, socket, flags, MYSQLND_CLIENT_KNOWS_RSET_COPY_DATA TSRMLS_CC) == NULL)
#endif
{
/* Save error messages - for mysqli_connect_error() & mysqli_connect_errno() */
@@ -575,7 +575,7 @@ PHP_FUNCTION(mysqli_query)
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty query");
RETURN_FALSE;
}
if ((resultmode & ~MYSQLI_ASYNC) != MYSQLI_USE_RESULT && (resultmode & ~MYSQLI_ASYNC) != MYSQLI_STORE_RESULT) {
if ((resultmode & ~MYSQLI_ASYNC) != MYSQLI_USE_RESULT && (resultmode & ~(MYSQLI_ASYNC | MYSQLI_STORE_RESULT_COPY_DATA)) != MYSQLI_STORE_RESULT) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid value for resultmode");
RETURN_FALSE;
}
@@ -609,9 +609,14 @@ PHP_FUNCTION(mysqli_query)
RETURN_TRUE;
}
switch (resultmode) {
switch (resultmode & ~(MYSQLI_ASYNC | MYSQLI_STORE_RESULT_COPY_DATA)) {
case MYSQLI_STORE_RESULT:
result = mysql_store_result(mysql->mysql);
#ifdef MYSQLI_USE_MYSQLND
if (resultmode & MYSQLI_STORE_RESULT_COPY_DATA) {
result = mysqlnd_store_result_ofs(mysql->mysql);
} else
#endif
result = mysql_store_result(mysql->mysql);
break;
case MYSQLI_USE_RESULT:
result = mysql_use_result(mysql->mysql);
+2
View File
@@ -114,9 +114,11 @@ PHP_MYSQLI_EXPORT(zend_object_value) mysqli_objects_new(zend_class_entry * TSRML
#define MYSQLI_USE_RESULT 1
#ifdef MYSQLI_USE_MYSQLND
#define MYSQLI_ASYNC 8
#define MYSQLI_STORE_RESULT_COPY_DATA 16
#else
/* libmysql */
#define MYSQLI_ASYNC 0
#define MYSQLI_STORE_RESULT_OFS 0
#endif
/* for mysqli_fetch_assoc */
+3 -1
View File
@@ -12,7 +12,9 @@ require_once('skipifconnectfailure.inc');
--FILE--
<?php
require 'connect.inc';
$db = new mysqli($host, $user, $passwd, 'mysql');
if (!$db = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
printf("[001] Connect failed, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
}
$stmt = $db->stmt_init();
$stmt->prepare("SELECT User FROM user WHERE password=\"\"");
+3 -2
View File
@@ -9,7 +9,9 @@ require_once('skipifconnectfailure.inc');
<?php
require_once("connect.inc");
$mysqli = new mysqli($host, $user, $passwd, $db);
if (!$mysqli = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
printf("[001] Connect failed, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
}
$read_stmt = $mysqli->prepare("SELECT 1");
@@ -17,7 +19,6 @@ require_once('skipifconnectfailure.inc');
unset($mysqli);
var_dump($read_stmt->bind_result($data));
?>
done!
--EXPECT--
+54 -42
View File
@@ -32,65 +32,73 @@ require_once('skipifconnectfailure.inc');
printf("[006] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
$host, $user, $db, $port, $socket);
if (false !== ($tmp = mysqli_change_user($link, $user . '_unknown_really', $passwd . 'non_empty', $db)))
if (false !== ($tmp = @mysqli_change_user($link, $user . '_unknown_really', $passwd . 'non_empty', $db)))
printf("[007] Expecting false, got %s/%s\n", gettype($tmp), $tmp);
if (false !== ($tmp = mysqli_change_user($link, $user, $passwd . '_unknown_really', $db)))
printf("[008] Expecting false, got %s/%s\n", gettype($tmp), $tmp);
if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
printf("[008] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
$host, $user, $db, $port, $socket);
if (false !== ($tmp = mysqli_change_user($link, $user, $passwd, $db . '_unknown_really')))
if (false !== ($tmp = @mysqli_change_user($link, $user, $passwd . '_unknown_really', $db)))
printf("[009] Expecting false, got %s/%s\n", gettype($tmp), $tmp);
if (!mysqli_query($link, 'SET @mysqli_change_user_test_var=1'))
printf("[010] Failed to set test variable: [%d] %s\n", mysqli_errno($link), mysqli_error($link));
if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
printf("[010] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
$host, $user, $db, $port, $socket);
if (!$res = mysqli_query($link, 'SELECT @mysqli_change_user_test_var AS test_var'))
printf("[011] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
$tmp = mysqli_fetch_assoc($res);
mysqli_free_result($res);
if (1 != $tmp['test_var'])
printf("[012] Cannot set test variable\n");
if (true !== ($tmp = mysqli_change_user($link, $user, $passwd, $db)))
printf("[013] Expecting true, got %s/%s\n", gettype($tmp), $tmp);
if (!$res = mysqli_query($link, 'SELECT database() AS dbname, user() AS user'))
printf("[014] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
$tmp = mysqli_fetch_assoc($res);
mysqli_free_result($res);
if (substr($tmp['user'], 0, strlen($user)) !== $user)
printf("[015] Expecting user %s, got user() %s\n", $user, $tmp['user']);
if ($tmp['dbname'] != $db)
printf("[016] Expecting database %s, got database() %s\n", $db, $tmp['dbname']);
if (!$res = mysqli_query($link, 'SELECT @mysqli_change_user_test_var AS test_var'))
printf("[017] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
$tmp = mysqli_fetch_assoc($res);
mysqli_free_result($res);
if (NULL !== $tmp['test_var'])
printf("[019] Test variable is still set!\n");
if (false !== ($tmp = @mysqli_change_user($link, $user, $passwd, $db . '_unknown_really')))
printf("[011] Expecting false, got %s/%s\n", gettype($tmp), $tmp);
mysqli_close($link);
if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
printf("[020] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
printf("[012] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
$host, $user, $db, $port, $socket);
}
if (false !== ($tmp = mysqli_change_user($link, str_repeat('user', 16384), str_repeat('pass', 16384), str_repeat('dbase', 16384))))
printf("[021] Expecting false, got %s/%s\n", gettype($tmp), $tmp);
if (false !== ($tmp = @mysqli_change_user($link, str_repeat('user', 16384), str_repeat('pass', 16384), str_repeat('dbase', 16384))))
printf("[013] Expecting false, got %s/%s\n", gettype($tmp), $tmp);
mysqli_close($link);
if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
printf("[022] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
printf("[014] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
$host, $user, $db, $port, $socket);
}
/* silent protocol change if no db which requires workaround in mysqlnd/libmysql
(empty db = no db send with COM_CHANGE_USER) */
if (true !== ($tmp = mysqli_change_user($link, $user, $passwd, "")))
printf("[015] Expecting true, got %s/%s\n", gettype($tmp), $tmp);
if (!$res = mysqli_query($link, 'SELECT database() AS dbname, user() AS user'))
printf("[016] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
$tmp = mysqli_fetch_assoc($res);
mysqli_free_result($res);
if ($tmp['dbname'] != "")
printf("[017] Expecting database '', got database() '%s'\n", $tmp['dbname']);
mysqli_close($link);
if (NULL !== ($tmp = @mysqli_change_user($link, $user, $passwd, $db)))
printf("[018] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
printf("[019] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
$host, $user, $db, $port, $socket);
if (!mysqli_query($link, 'SET @mysqli_change_user_test_var=1'))
printf("[020] Failed to set test variable: [%d] %s\n", mysqli_errno($link), mysqli_error($link));
if (!$res = mysqli_query($link, 'SELECT @mysqli_change_user_test_var AS test_var'))
printf("[021] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
$tmp = mysqli_fetch_assoc($res);
mysqli_free_result($res);
if (1 != $tmp['test_var'])
printf("[022] Cannot set test variable\n");
if (true !== ($tmp = mysqli_change_user($link, $user, $passwd, $db)))
printf("[023] Expecting true, got %s/%s\n", gettype($tmp), $tmp);
if (!$res = mysqli_query($link, 'SELECT database() AS dbname, user() AS user'))
@@ -98,13 +106,17 @@ require_once('skipifconnectfailure.inc');
$tmp = mysqli_fetch_assoc($res);
mysqli_free_result($res);
if ($tmp['dbname'] != "")
printf("[025] Expecting database '', got database() '%s'\n", $tmp['dbname']);
if (substr($tmp['user'], 0, strlen($user)) !== $user)
printf("[025] Expecting user %s, got user() %s\n", $user, $tmp['user']);
if ($tmp['dbname'] != $db)
printf("[026] Expecting database %s, got database() %s\n", $db, $tmp['dbname']);
mysqli_close($link);
if (NULL !== ($tmp = @mysqli_change_user($link, $user, $passwd, $db)))
printf("[026] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
if (!$res = mysqli_query($link, 'SELECT @mysqli_change_user_test_var AS test_var'))
printf("[027] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
$tmp = mysqli_fetch_assoc($res);
mysqli_free_result($res);
if (NULL !== $tmp['test_var'])
printf("[028] Test variable is still set!\n");
print "done!";
?>
@@ -0,0 +1,44 @@
--TEST--
mysqli_change_user(), MySQL 5.6+
--SKIPIF--
<?php
require_once('skipif.inc');
require_once('skipifemb.inc');
require_once('skipifconnectfailure.inc');
if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
die(sprintf("SKIP Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
$host, $user, $db, $port, $socket));
if (mysqli_get_server_version($link) < 50600)
die("SKIP For MySQL >= 5.6.0");
?>
--FILE--
<?php
require_once("connect.inc");
$tmp = NULL;
$link = NULL;
if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
$host, $user, $db, $port, $socket);
/* Pre 5.6: link remains useable */
if (false !== ($tmp = @mysqli_change_user($link, $user . '_unknown_really', $passwd . 'non_empty', $db)))
printf("[002] Expecting false, got %s/%s\n", gettype($tmp), $tmp);
if (!$res = mysqli_query($link, 'SELECT 1 AS _one'))
printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
var_dump($res->fetch_assoc());
print "done!";
?>
--EXPECTF--
Warning: mysqli_query(): MySQL server has gone away in %s on line %d
Warning: mysqli_query(): Error reading result set's header in %s on line %d
[003] [2006] MySQL server has gone away
Fatal error: Call to a member function fetch_assoc() on a non-object in %s on line %d
@@ -0,0 +1,39 @@
--TEST--
mysqli_change_user(), MySQL < 5.6
--SKIPIF--
<?php
require_once('skipif.inc');
require_once('skipifemb.inc');
require_once('skipifconnectfailure.inc');
if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
die(sprintf("SKIP Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
$host, $user, $db, $port, $socket));
if (mysqli_get_server_version($link) >= 50600)
die("SKIP For MySQL < 5.6.0");
?>
--FILE--
<?php
require_once("connect.inc");
$tmp = NULL;
$link = NULL;
if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
$host, $user, $db, $port, $socket);
/* Pre 5.6: link remains useable */
if (false !== ($tmp = mysqli_change_user($link, $user . '_unknown_really', $passwd . 'non_empty', $db)))
printf("[011] Expecting false, got %s/%s\n", gettype($tmp), $tmp);
if (!$res = mysqli_query($link, 'SELECT 1 AS _one'))
printf("[012] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
var_dump($res->fetch_assoc());
print "done!";
?>
--EXPECTF--
done!
@@ -10,6 +10,9 @@ require_once('table.inc');
if (!$IS_MYSQLND && (mysqli_get_server_version($link) < 50118 && mysqli_get_server_version($link) > 50100)) {
die("skip Your MySQL Server version has a known bug that will cause a crash");
}
if (mysqli_get_server_version($link) >= 50600)
die("SKIP For MySQL < 5.6.0");
?>
--FILE--
<?php
@@ -1140,9 +1140,16 @@ isInternal: yes
isUserDefined: no
returnsReference: no
Modifiers: 256
Number of Parameters: 0
Number of Parameters: 1
Number of Required Parameters: 0
Inspecting parameter 'flags' of method 'store_result'
isArray: no
allowsNull: no
isPassedByReference: no
isOptional: yes
isDefaultValueAvailable: no
Inspecting method 'thread_safe'
isFinal: no
isAbstract: no
+4
View File
@@ -108,6 +108,10 @@ require_once('skipifconnectfailure.inc');
$expected_constants['MYSQLI_OPT_INT_AND_FLOAT_NATIVE'] = true;
}
if ($IS_MYSQLND && defined('MYSQLI_STORE_RESULT_COPY_DATA')) {
$expected_constants['MYSQLI_STORE_RESULT_COPY_DATA'] = true;
}
if ($IS_MYSQLND || defined('MYSQLI_REFRESH_BACKUP_LOG')) {
$expected_constants['MYSQLI_REFRESH_BACKUP_LOG'] = true;
}
+20
View File
@@ -299,6 +299,26 @@ if (!function_exists('mysqli_fetch_all'))
if (null !== ($tmp = mysqli_fetch_array($res, MYSQLI_ASSOC)))
printf("[015] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
printf("[016] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
$host, $user, $db, $port, $socket);
}
if (!$res = mysqli_real_query($link, "SELECT 1 AS _one"))
printf("[017] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
/* on mysqlnd level this would not be allowed */
if (!is_object($res = mysqli_use_result($link)))
printf("[018] Expecting object, got %s/%s. [%d] %s\n",
gettype($res), $res, mysqli_errno($link), mysqli_error($link));
$rows = mysqli_fetch_all($res, MYSQLI_ASSOC);
if (!is_array($rows) || (count($rows) > 1) || !isset($rows[0]['_one']) || ($rows[0]['_one'] != 1)) {
printf("[019] Results seem wrong, dumping\n");
var_dump($rows);
}
print "done!";
?>
--CLEAN--
+4 -2
View File
@@ -10,8 +10,10 @@ require_once('skipifconnectfailure.inc');
<?php
require_once("connect.inc");
if (!$mysqli = new mysqli($host, $user, $passwd, $db, $port, $socket))
printf("[001] Cannot connect\n");
if (!$mysqli = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
$host, $user, $db, $port, $socket);
}
if (!is_null($tmp = @mysqli_fetch_lengths()))
printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+21 -10
View File
@@ -52,6 +52,13 @@ if (!$IS_MYSQLND)
if (0 !== ($tmp = (mysqli_poll($read, $error, $reject, 0, 1))))
printf("[009] Expecting int/0 got %s/%s\n", gettype($tmp), var_export($tmp, true));
$read = $error = $reject = array($link);
if (false !== ($tmp = (mysqli_poll($read, $error, $reject, -1, 1))))
printf("[010] Expecting false got %s/%s\n", gettype($tmp), var_export($tmp, true));
$read = $error = $reject = array($link);
if (false !== ($tmp = (mysqli_poll($read, $error, $reject, 0, -1))))
printf("[011] Expecting false got %s/%s\n", gettype($tmp), var_export($tmp, true));
function poll_async($offset, $link, $links, $errors, $reject, $exp_ready, $use_oo_syntax) {
@@ -90,14 +97,14 @@ if (!$IS_MYSQLND)
$links = array($link);
$errors = array($link);
$reject = array($link);
poll_async(10, $link, $links, $errors, $reject, 0, false);
poll_async(12, $link, $links, $errors, $reject, 0, false);
mysqli_close($link);
$link = get_connection();
$links = array($link);
$errors = array($link);
$reject = array($link);
poll_async(11, $link, $links, $errors, $reject, 0, true);
poll_async(13, $link, $links, $errors, $reject, 0, true);
mysqli_close($link);
// Connections on which no query has been send - 2
@@ -106,7 +113,7 @@ if (!$IS_MYSQLND)
$links = array($link, $link);
$errors = array($link, $link);
$reject = array();
poll_async(12, $link, $links, $errors, $reject, 0, false);
poll_async(14, $link, $links, $errors, $reject, 0, false);
// Connections on which no query has been send - 3
// Difference: pass two connections
@@ -114,7 +121,7 @@ if (!$IS_MYSQLND)
$links = array($link, get_connection());
$errors = array($link, $link);
$reject = array();
poll_async(13, $link, $links, $errors, $reject, 0, false);
poll_async(15, $link, $links, $errors, $reject, 0, false);
// Reference mess...
$link = get_connection();
@@ -122,16 +129,20 @@ if (!$IS_MYSQLND)
$errors = array($link);
$ref_errors =& $errors;
$reject = array();
poll_async(14, $link, $links, $ref_errors, $reject, 0, false);
poll_async(16, $link, $links, $ref_errors, $reject, 0, false);
print "done!";
?>
--EXPECTF--
[010 + 6] Rejecting thread %d: 0/
[011 + 6] Rejecting thread %d: 0/
Warning: mysqli_poll(): Negative values passed for sec and/or usec in %s on line %d
Warning: mysqli_poll(): Negative values passed for sec and/or usec in %s on line %d
[012 + 6] Rejecting thread %d: 0/
[012 + 6] Rejecting thread %d: 0/
[013 + 6] Rejecting thread %d: 0/
[013 + 6] Rejecting thread %d: 0/
[014 + 6] Rejecting thread %d: 0/
done!
[014 + 6] Rejecting thread %d: 0/
[015 + 6] Rejecting thread %d: 0/
[015 + 6] Rejecting thread %d: 0/
[016 + 6] Rejecting thread %d: 0/
done!
+19 -8
View File
@@ -90,6 +90,7 @@ if (!$IS_MYSQLND)
// Yes, 1 - fetch OK packet of kill!
$processed = 0;
$begin = microtime(true);
do {
$links = array($link, $link);
$errors = array($link, $link);
@@ -106,9 +107,14 @@ if (!$IS_MYSQLND)
break;
}
if (FALSE === $ready) {
printf("[013] MySQLi indicates some error\n");
break;
}
if (!empty($reject)) {
foreach ($reject as $mysqli) {
printf("[013] Rejecting thread %d: %s/%s\n",
printf("[014] Rejecting thread %d: %s/%s\n",
mysqli_thread_id($mysqli),
mysqli_errno($mysqli),
mysqli_error($mysqli));
@@ -121,11 +127,16 @@ if (!$IS_MYSQLND)
printf("Fetching from thread %d...\n", mysqli_thread_id($mysqli));
var_dump(mysqli_fetch_assoc($res));
} else if (mysqli_errno($mysqli) > 0) {
printf("[014] %d/%s\n", mysqli_errno($mysqli), mysqli_error($mysqli));
printf("[015] %d/%s\n", mysqli_errno($mysqli), mysqli_error($mysqli));
}
$processed++;
}
if ((microtime(true) - $begin) > 5) {
printf("[016] Pulling the emergency break after 5s, something is wrong...\n");
break;
}
} while ($processed < 2);
@@ -137,17 +148,17 @@ if (!$IS_MYSQLND)
// Sleep 0.1s to ensure the KILL gets recognized
usleep(100000);
if (false !== ($tmp = mysqli_query($link, "SELECT 1 AS 'processed before killed'", MYSQLI_ASYNC | MYSQLI_USE_RESULT)))
printf("[015] Expecting boolean/false got %s/%s\n", gettype($tmp), var_export($tmp, true));
printf("[017] Expecting boolean/false got %s/%s\n", gettype($tmp), var_export($tmp, true));
$links = array($link);
$errors = array($link);
$reject = array($link);
if (0 !== ($tmp = (mysqli_poll($links, $errors, $reject, 0, 10000))))
printf("[016] Expecting int/0 got %s/%s\n", gettype($tmp), var_export($tmp, true));
printf("[018] Expecting int/0 got %s/%s\n", gettype($tmp), var_export($tmp, true));
if (!is_array($links) || empty($links))
printf("[017] Expecting non-empty array got %s/%s\n", gettype($links), var_export($links, true));
printf("[019] Expecting non-empty array got %s/%s\n", gettype($links), var_export($links, true));
else
foreach ($links as $link) {
if (is_object($res = mysqli_reap_async_query($link))) {
@@ -156,16 +167,16 @@ if (!$IS_MYSQLND)
mysqli_free_result($res);
} else if ($link->errno > 0) {
// But you are supposed to handle the error the way its shown here!
printf("[018] Error: %d/%s\n", $link->errno, $link->error);
printf("[020] Error: %d/%s\n", $link->errno, $link->error);
}
}
// None of these will indicate an error, check errno on the list of returned connections!
if (!is_array($errors) || !empty($errors))
printf("[019] Expecting non-empty array got %s/%s\n", gettype($errors), var_export($errors, true));
printf("[021] Expecting non-empty array got %s/%s\n", gettype($errors), var_export($errors, true));
if (!is_array($reject) || !empty($reject))
printf("[020] Expecting empty array got %s/%s\n", gettype($reject), var_export($reject, true));
printf("[021] Expecting empty array got %s/%s\n", gettype($reject), var_export($reject, true));
mysqli_close($link);
@@ -80,13 +80,17 @@ if (!$IS_MYSQLND)
if (0 == count($poll_links))
break;
if (0 == ($num_ready = mysqli_poll($poll_links, $poll_errors, $poll_reject, 0, 200000)))
if (0 === ($num_ready = mysqli_poll($poll_links, $poll_errors, $poll_reject, 0, 200000)))
continue;
if (!empty($poll_errors)) {
die(var_dump($poll_errors));
}
if (FALSE === $num_ready) {
die("Some mysqli indicated error");
}
foreach ($poll_links as $link) {
$thread_id = mysqli_thread_id($link);
$links[$thread_id]['processed'] = true;
@@ -0,0 +1,97 @@
--TEST--
mysqli_reap_async_query()
--SKIPIF--
<?php
require_once('skipif.inc');
require_once('skipifemb.inc');
require_once('connect.inc');
require_once('skipifconnectfailure.inc');
if (!$IS_MYSQLND)
die("skip mysqlnd only feature, compile PHP using --with-mysqli=mysqlnd");
?>
--FILE--
<?php
require_once('connect.inc');
function get_connection() {
global $host, $user, $passwd, $db, $port, $socket;
if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
return $link;
}
if (!$link = get_connection())
printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
if (NULL !== ($tmp = @mysqli_reap_async_query()))
printf("[002] Expecting NULL got %s\n", var_export($tmp, true));
$l = array($link);
if (NULL !== ($tmp = @mysqli_reap_async_query($l)))
printf("[003] Expecting NULL got %s\n", var_export($tmp, true));
if (NULL !== ($tmp = @mysqli_reap_async_query($link, $link)))
printf("[004] Expecting NULL got %s\n", var_export($tmp, true));
function poll_async($offset, $link, $links, $errors, $reject, $exp_ready, $use_oo_syntax) {
if ($exp_ready !== ($tmp = mysqli_poll($links, $errors, $reject, 0, 1000)))
printf("[%03d + 1] There should be %d links ready to read from, %d ready\n",
$offset, $exp_ready, $tmp);
foreach ($links as $mysqli) {
if ($use_oo_syntax) {
$res = $mysqli->reap_async_query();
} else {
$res = mysqli_reap_async_query($mysqli);
}
if (is_object($res)) {
printf("[%03d + 2] %s\n", $offset, var_export($res->fetch_assoc(), true));
} else if (mysqli_errno($mysqli) > 0) {
printf("[%03d + 3] Error indicated through links array: %d/%s",
$offset, mysqli_errno($mysqli), mysqli_error($mysqli));
} else {
printf("[%03d + 4] Cannot fetch and no error set - non resultset query (no SELECT)!\n", $offset);
}
}
foreach ($errors as $mysqli)
printf("[%03d + 5] Error on %d: %d/%s\n",
$offset, mysqli_thread_id($mysqli), mysqli_errno($mysqli), mysqli_error($mysqli));
foreach ($reject as $mysqli)
printf("[%03d + 6] Rejecting thread %d: %d/%s\n",
$offset, mysqli_thread_id($mysqli), mysqli_errno($mysqli), mysqli_error($mysqli));
}
// Connections on which no query has been send - 1
$link = get_connection();
$link->query("SELECT 1 AS _one", MYSQLI_ASYNC | MYSQLI_STORE_RESULT);
$links = array($link);
$errors = array($link);
$reject = array($link);
poll_async(12, $link, $links, $errors, $reject, 1, false);
mysqli_close($link);
$link = get_connection();
$link->query("SELECT 2 AS _two", MYSQLI_ASYNC | MYSQLI_USE_RESULT);
$links = array($link);
$errors = array($link);
$reject = array($link);
poll_async(13, $link, $links, $errors, $reject, 1, true);
mysqli_close($link);
print "done!";
?>
--EXPECTF--
[012 + 2] array (
'_one' => '1',
)
[013 + 2] array (
'_two' => '2',
)
done!
@@ -0,0 +1,84 @@
--TEST--
mysqli_release_savepoint()
--SKIPIF--
<?php
require_once('skipif.inc');
require_once('skipifemb.inc');
require_once('skipifconnectfailure.inc');
require_once('connect.inc');
if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
die(sprintf("Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error()));
if (!have_innodb($link))
die(sprintf("Needs InnoDB support, [%d] %s", $link->errno, $link->error));
?>
--FILE--
<?php
require_once("connect.inc");
/* {{{ proto bool mysqli_release_savepoint(object link, string name) */
$tmp = NULL;
$link = NULL;
if (!is_null($tmp = @mysqli_release_savepoint()))
printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
if (!is_null($tmp = @mysqli_release_savepoint($link)))
printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
printf("[003] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
$host, $user, $db, $port, $socket);
$name = array();
if (!is_null($tmp = @mysqli_release_savepoint($link, $name)))
printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
if (!is_null($tmp = @mysqli_release_savepoint($link, 'foo', $link)))
printf("[005] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
if (false !== ($tmp = mysqli_release_savepoint($link, '')))
printf("[006] Expecting false, got %s/%s\n", gettype($tmp), $tmp);
if (!mysqli_query($link, 'DROP TABLE IF EXISTS test'))
printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
if (!mysqli_query($link, 'CREATE TABLE test(id INT) ENGINE = InnoDB'))
printf("[008] Cannot create test table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
if (true !== ($tmp = mysqli_autocommit($link, false)))
printf("[009] Cannot turn off autocommit, expecting true, got %s/%s\n", gettype($tmp), $tmp);
/* note that there is no savepoint my... */
if (true !== ($tmp = mysqli_release_savepoint($link, 'my')))
printf("[010] Got %s - [%d] %s\n", var_dump($tmp, true), mysqli_errno($link), mysqli_error($link));
if (!mysqli_query($link, 'INSERT INTO test(id) VALUES (1)'))
printf("[011] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
$tmp = mysqli_commit($link);
if ($tmp !== true)
printf("[012] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
if (true !== ($tmp = mysqli_savepoint($link, 'my')))
printf("[013] Got %s - [%d] %s\n", var_dump($tmp, true), mysqli_errno($link), mysqli_error($link));
$res = mysqli_query($link, "SELECT * FROM test");
var_dump($res->fetch_assoc());
if (true !== ($tmp = mysqli_release_savepoint($link, 'my')))
printf("[014] Got %s - [%d] %s\n", var_dump($tmp, true), mysqli_errno($link), mysqli_error($link));
print "done!";
?>
--CLEAN--
<?php
require_once("clean_table.inc");
?>
--EXPECTF--
Warning: mysqli_release_savepoint(): Savepoint name cannot be empty in %s on line %d
array(1) {
["id"]=>
string(1) "1"
}
done!
-5
View File
@@ -43,8 +43,6 @@ require_once('skipifconnectfailure.inc');
mysqli_multi_query($link, "BAR; FOO;");
mysqli_query($link, "FOO");
/* This might work if you accept anonymous users in your setup */
mysqli_change_user($link, "0123456789-10-456789-20-456789-30-456789-40-456789-50-456789-60-456789-70-456789-80-456789-90-456789", "password", $db);
mysqli_kill($link, -1);
// mysqli_ping() cannot be tested, because one would need to cause an error inside the C function to test it
@@ -61,7 +59,6 @@ require_once('skipifconnectfailure.inc');
mysqli_multi_query($link, "BAR; FOO;");
mysqli_query($link, "FOO");
mysqli_change_user($link, "This might work if you accept anonymous users in your setup", "password", $db);
mysqli_kill($link, -1);
mysqli_prepare($link, "FOO");
mysqli_real_query($link, "FOO");
@@ -291,8 +288,6 @@ Warning: mysqli_multi_query(): (%d/%d): You have an error in your SQL syntax; ch
Warning: mysqli_query(): (%d/%d): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FOO' at line 1 in %s on line %d
Warning: mysqli_change_user(): (%d/%d): Access denied for user '%s'@'%s' (using password: %s) in %s on line %d
Warning: mysqli_kill(): processid should have positive value in %s on line %d
Warning: mysqli_prepare(): (%d/%d): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FOO' at line 1 in %s on line %d
+50
View File
@@ -0,0 +1,50 @@
--TEST--
mysqli_report(), change user, MySQL 5.6+
--SKIPIF--
<?php
require_once('skipif.inc');
require_once('skipifemb.inc');
require_once('skipifconnectfailure.inc');
if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
die(sprintf("SKIP Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
$host, $user, $db, $port, $socket));
if (mysqli_get_server_version($link) < 50600)
die("SKIP For MySQL >= 5.6.0");
?>
--FILE--
<?php
require_once("connect.inc");
$tmp = NULL;
$link = NULL;
require('table.inc');
/*
Internal macro MYSQL_REPORT_ERROR
*/
mysqli_report(MYSQLI_REPORT_ERROR);
mysqli_change_user($link, "0123456789-10-456789-20-456789-30-456789-40-456789-50-456789-60-456789-70-456789-80-456789-90-456789", "password", $db);
mysqli_report(MYSQLI_REPORT_OFF);
if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
$host, $user, $db, $port, $socket);
mysqli_change_user($link, "This might work if you accept anonymous users in your setup", "password", $db);
print "done!";
?>
--CLEAN--
<?php
require_once("clean_table.inc");
?>
--EXPECTF--
Warning: mysqli_change_user(): (%d/%d): Access denied for user '%s'@'%s' (using password: %s) in %s on line %d
done!
+8 -1
View File
@@ -1,10 +1,17 @@
--TEST--
mysqli_report()
mysqli_report(), MySQL < 5.6
--SKIPIF--
<?php
require_once('skipif.inc');
require_once('skipifemb.inc');
require_once('skipifconnectfailure.inc');
if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
die(sprintf("SKIP Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
$host, $user, $db, $port, $socket));
if (mysqli_get_server_version($link) >= 50600)
die("SKIP For MySQL < 5.6.0");
?>
--FILE--
<?php
+72
View File
@@ -0,0 +1,72 @@
--TEST--
mysqli_savepoint()
--SKIPIF--
<?php
require_once('skipif.inc');
require_once('skipifemb.inc');
require_once('skipifconnectfailure.inc');
require_once('connect.inc');
if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
die(sprintf("Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error()));
if (!have_innodb($link))
die(sprintf("Needs InnoDB support, [%d] %s", $link->errno, $link->error));
?>
--FILE--
<?php
require_once("connect.inc");
/* {{{ proto bool mysqli_savepoint(object link, string name) */
$tmp = NULL;
$link = NULL;
if (!is_null($tmp = @mysqli_savepoint()))
printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
if (!is_null($tmp = @mysqli_savepoint($link)))
printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
printf("[003] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
$host, $user, $db, $port, $socket);
$name = array();
if (!is_null($tmp = @mysqli_savepoint($link, $name)))
printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
if (!is_null($tmp = @mysqli_savepoint($link, 'foo', $link)))
printf("[005] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
if (false !== ($tmp = mysqli_savepoint($link, '')))
printf("[006] Expecting false, got %s/%s\n", gettype($tmp), $tmp);
if (!mysqli_query($link, 'DROP TABLE IF EXISTS test'))
printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
if (!mysqli_query($link, 'CREATE TABLE test(id INT) ENGINE = InnoDB'))
printf("[008] Cannot create test table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
if (true !== ($tmp = mysqli_autocommit($link, false)))
printf("[009] Cannot turn off autocommit, expecting true, got %s/%s\n", gettype($tmp), $tmp);
/* overrule autocommit */
if (true !== ($tmp = mysqli_savepoint($link, 'my')))
printf("[010] Got %s - [%d] %s\n", var_dump($tmp, true), mysqli_errno($link), mysqli_error($link));
if (!mysqli_query($link, 'INSERT INTO test(id) VALUES (1)'))
printf("[011] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
$tmp = mysqli_rollback($link);
if ($tmp !== true)
printf("[012] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
print "done!";
?>
--CLEAN--
<?php
require_once("clean_table.inc");
?>
--EXPECTF--
Warning: mysqli_savepoint(): Savepoint name cannot be empty in %s on line %d
done!
+17 -14
View File
@@ -17,7 +17,7 @@ if (!mysqli_query($link, "DROP TABLE IF EXISTS test") ||
!mysqli_query($link, "CREATE TABLE test(id SMALLINT)"))
die(sprintf("skip [%d] %s\n", $link->errno, $link->error));
if (!@mysqli_query("INSERT INTO test(id) VALUES (100001)"))
if (!@mysqli_query($link, "SET sql_mode=''") || !@mysqli_query($link, "INSERT INTO test(id) VALUES (100001)"))
die("skip Strict sql mode seems to be active. We won't get a warning to check for.");
mysqli_query($link, "DROP TABLE IF EXISTS test");
@@ -43,54 +43,57 @@ mysqli_query($link, "DROP TABLE IF EXISTS test");
if (NULL !== ($tmp = mysqli_stmt_get_warnings($stmt)))
printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
if (!mysqli_stmt_prepare($stmt, "DROP TABLE IF EXISTS test") || !mysqli_stmt_execute($stmt))
if (!mysqli_stmt_prepare($stmt, "SET sql_mode=''") || !mysqli_stmt_execute($stmt))
printf("[005] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
if (!mysqli_stmt_prepare($stmt, "DROP TABLE IF EXISTS test") || !mysqli_stmt_execute($stmt))
printf("[006] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
if (false !== ($tmp = mysqli_stmt_get_warnings($stmt)))
printf("[006] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
printf("[007] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
if (!mysqli_stmt_prepare($stmt, "CREATE TABLE test(id SMALLINT, label CHAR(1))") || !mysqli_stmt_execute($stmt))
printf("[007] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
printf("[008] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
if (false !== ($tmp = mysqli_stmt_get_warnings($stmt)))
printf("[008] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
printf("[009] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (100000, 'a'), (100001, 'b')") ||
!mysqli_stmt_execute($stmt))
printf("[009] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
printf("[010] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
if (!is_object($warning = mysqli_stmt_get_warnings($stmt)))
printf("[010] Expecting mysqli_warning object, got %s/%s\n", gettype($warning), $warning);
printf("[011] Expecting mysqli_warning object, got %s/%s\n", gettype($warning), $warning);
if ('mysqli_warning' !== get_class($warning))
printf("[011] Expecting object of type mysqli_warning got type '%s'", get_class($warning));
printf("[012] Expecting object of type mysqli_warning got type '%s'", get_class($warning));
if (!method_exists($warning, 'next'))
printf("[012] Object mysqli_warning seems to lack method next()\n");
printf("[013] Object mysqli_warning seems to lack method next()\n");
$i = 0;
do {
if ('' == $warning->message)
printf("[013 - %d] Message should not be empty\n", $i);
printf("[014 - %d] Message should not be empty\n", $i);
if ('' == $warning->sqlstate)
printf("[014 - %d] SQL State should not be empty\n", $i);
printf("[015 - %d] SQL State should not be empty\n", $i);
if (0 == $warning->errno)
printf("[015 - %d] Error number should not be zero\n", $i);
printf("[016 - %d] Error number should not be zero\n", $i);
$i++;
} while ($warning->next());
if (2 != $i)
printf("[016] Expected 2 warnings, got %d warnings\n", $i);
printf("[017] Expected 2 warnings, got %d warnings\n", $i);
mysqli_stmt_close($stmt);
if (NULL !== ($tmp = mysqli_stmt_get_warnings($stmt)))
printf("[015] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
printf("[018] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
mysqli_close($link);
print "done!";
@@ -0,0 +1,42 @@
--TEST--
mysqli_store_result()
--SKIPIF--
<?php
require_once('skipif.inc');
require_once('skipifemb.inc');
require_once('skipifconnectfailure.inc');
?>
--INI--
mysqlnd.debug=d:t:O,/tmp/mysqlnd.trace
--FILE--
<?php
require_once("connect.inc");
$tmp = NULL;
$link = NULL;
require('table.inc');
if (!$res = mysqli_real_query($link, "SELECT id, label FROM test ORDER BY id"))
printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
if (!is_object($res = mysqli_store_result($link, MYSQLI_STORE_RESULT_COPY_DATA)))
printf("[004] Expecting object, got %s/%s. [%d] %s\n",
gettype($res), $res, mysqli_errno($link), mysqli_error($link));
if (true !== ($tmp = mysqli_data_seek($res, 2)))
printf("[005] Expecting boolean/true, got %s/%s. [%d] %s\n",
gettype($tmp), $tmp, mysqli_errno($link), mysqli_error($link));
mysqli_free_result($res);
print "done!";
?>
--CLEAN--
<?php
require_once("clean_table.inc");
?>
--EXPECTF--
Warning: mysqli_store_result(): Couldn't fetch mysqli in %s on line %d
done!
@@ -0,0 +1,285 @@
--TEST--
mysqli_store_result()
--SKIPIF--
<?php
require_once('skipif.inc');
require_once('skipifemb.inc');
require_once('skipifconnectfailure.inc');
if (!$IS_MYSQLND) {
die("SKIP mysqlnd only test");
}
?>
--INI--
mysqlnd.debug=d:t:O,/tmp/mysqlnd.trace
mysqlnd.net_read_buffer_size=1
mysqlnd.mempool_default_size=1
mysqlnd.fetch_data_copy=0
--FILE--
<?php
require_once("connect.inc");
$tmp = NULL;
$link = NULL;
require('table.inc');
if (!$res = mysqli_real_query($link, "SELECT id, label FROM test ORDER BY id"))
printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
if (!is_object($res = mysqli_store_result($link, MYSQLI_STORE_RESULT_COPY_DATA)))
printf("[004] Expecting object, got %s/%s. [%d] %s\n",
gettype($res), $res, mysqli_errno($link), mysqli_error($link));
if (true !== ($tmp = mysqli_data_seek($res, 2)))
printf("[005] Expecting boolean/true, got %s/%s. [%d] %s\n",
gettype($tmp), $tmp, mysqli_errno($link), mysqli_error($link));
var_dump($res->fetch_assoc());
if (true !== ($tmp = mysqli_data_seek($res, 0)))
printf("[006] Expecting boolean/true, got %s/%s. [%d] %s\n",
gettype($tmp), $tmp, mysqli_errno($link), mysqli_error($link));
while ($row = $res->fetch_assoc()) {
printf("id = %d, label = %s\n", $row['id'], $row['label']);
}
mysqli_free_result($res);
mysqli_close($link);
if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
printf("[007] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
$host, $user, $db, $port, $socket);
}
if (!$res = mysqli_real_query($link, "SELECT id, label FROM test ORDER BY id"))
printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
if (!is_object($res = mysqli_store_result($link, MYSQLI_STORE_RESULT_COPY_DATA)))
printf("[009] Expecting object, got %s/%s. [%d] %s\n",
gettype($res), $res, mysqli_errno($link), mysqli_error($link));
$no_result = 0;
for ($i = 0; $i < 1000; $i++) {
$idx = mt_rand(-100, 100);
if (true === @mysqli_data_seek($res, $idx)) {
$row = $res->fetch_assoc();
if (!isset($row['id']) || !isset($row['label'])) {
printf("[010] Brute force seek %d returned %d\n", $idx, var_export($row, true));
}
} else {
$no_result++;
}
}
printf("No result: %d\n", $no_result);
/* implicit free, implicit store */
/* meta and fetch lenghts code */
if (!$res = mysqli_query($link, "SELECT CONCAT(id, id) AS _c, label FROM test ORDER BY id DESC LIMIT 2"))
printf("[011] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
printf("Default\n");
var_dump(mysqli_fetch_lengths($res));
$fields = $res->fetch_fields();
while ($row = $res->fetch_assoc()) {
var_dump(mysqli_fetch_lengths($res));
}
var_dump(mysqli_fetch_lengths($res));
if (!$res = mysqli_real_query($link, "SELECT CONCAT(id, id) AS _c, label FROM test ORDER BY id DESC LIMIT 2"))
printf("[012] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
if (!is_object($res = mysqli_store_result($link, MYSQLI_STORE_RESULT_COPY_DATA)))
printf("[013] Expecting object, got %s/%s. [%d] %s\n",
gettype($res), $res, mysqli_errno($link), mysqli_error($link));
printf("Copy\n");
var_dump(mysqli_fetch_lengths($res));
$fields_copy = $res->fetch_fields();
while ($row = $res->fetch_assoc()) {
var_dump(mysqli_fetch_lengths($res));
}
var_dump(mysqli_fetch_lengths($res));
/* There's no need for in-depth testing here. If you want in-depth switch mysqlnd
globally to copy mode and run all the tests */
foreach ($fields as $k => $field_info) {
if ($fields_copy[$k] != $field_info) {
printf("[014] Metadata seems to differ, dumping\n");
var_dump($field_info);
var_dump($fields_copy[$k]);
}
}
/* fetch all */
if (!$res = mysqli_real_query($link, "SELECT id, label FROM test ORDER BY id DESC LIMIT 2"))
printf("[015] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
if (!is_object($res = mysqli_store_result($link, MYSQLI_STORE_RESULT_COPY_DATA)))
printf("[016] Expecting object, got %s/%s. [%d] %s\n",
gettype($res), $res, mysqli_errno($link), mysqli_error($link));
foreach (mysqli_fetch_all($res, MYSQLI_ASSOC) as $row) {
printf("id = %d label = %s\n", $row['id'], $row['label']);
}
if (!$res = mysqli_real_query($link, "SELECT id, label FROM test ORDER BY id DESC LIMIT 2"))
printf("[017] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
if (!is_object($res = mysqli_store_result($link, MYSQLI_STORE_RESULT_COPY_DATA)))
printf("[018] Expecting object, got %s/%s. [%d] %s\n",
gettype($res), $res, mysqli_errno($link), mysqli_error($link));
/* provoke out of sync */
if (!mysqli_real_query($link, "SELECT id, label FROM test ORDER BY id DESC LIMIT 2"))
printf("[019] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
var_dump($res->fetch_assoc());
if (!$res = mysqli_real_query($link, "SELECT id, label FROM test ORDER BY id ASC LIMIT 2"))
printf("[020] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
if (!is_object($res = mysqli_store_result($link, MYSQLI_STORE_RESULT_COPY_DATA)))
printf("[021] Expecting object, got %s/%s. [%d] %s\n",
gettype($res), $res, mysqli_errno($link), mysqli_error($link));
/* user conn killed, res associated with conn, fetch from res */
unset($link);
var_dump($res->fetch_assoc());
if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
printf("[022] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
$host, $user, $db, $port, $socket);
}
if (!$res = mysqli_real_query($link, "INSERT INTO test(id, label) VALUES (100, 'z')"))
printf("[023] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
mysqli_store_result($link, MYSQLI_STORE_RESULT_COPY_DATA);
if (mysqli_get_server_version($link) > 50000) {
// let's try to play with stored procedures
mysqli_real_query($link, 'DROP PROCEDURE IF EXISTS p');
if (mysqli_real_query($link, 'CREATE PROCEDURE p(OUT ver_param VARCHAR(25)) READS SQL DATA BEGIN SELECT id FROM test WHERE id >= 100 ORDER BY id; SELECT id + 1, label FROM test WHERE id > 0 AND id < 3 ORDER BY id; SELECT VERSION() INTO ver_param;
END;')) {
mysqli_multi_query($link, "CALL p(@version)");
do {
if ($res = $link->store_result(MYSQLI_STORE_RESULT_COPY_DATA)) {
printf("---\n");
var_dump($res->fetch_all());
$res->free();
} else {
if ($link->errno) {
echo "Store failed: (" . $link->errno . ") " . $link->error;
}
}
} while ($link->more_results() && $link->next_result());
mysqli_real_query($link, 'SELECT @version AS p_version');
$res = mysqli_store_result($link, MYSQLI_STORE_RESULT_COPY_DATA);
$tmp = mysqli_fetch_assoc($res);
if (!is_array($tmp) || empty($tmp) || !isset($tmp['p_version']) || ('' == $tmp['p_version'])) {
printf("[024] Expecting array [%d] %s\n", mysqli_errno($link), mysqli_error($link));
var_dump($tmp);
}
mysqli_free_result($res);
} else {
printf("[025] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
}
}
print "done!";
?>
--CLEAN--
<?php
require_once("clean_table.inc");
?>
--EXPECTF--
array(2) {
["id"]=>
string(1) "3"
["label"]=>
string(1) "c"
}
id = 1, label = a
id = 2, label = b
id = 3, label = c
id = 4, label = d
id = 5, label = e
id = 6, label = f
No result: %d
Default
bool(false)
array(2) {
[0]=>
int(2)
[1]=>
int(1)
}
array(2) {
[0]=>
int(2)
[1]=>
int(1)
}
bool(false)
Copy
bool(false)
array(2) {
[0]=>
int(2)
[1]=>
int(1)
}
array(2) {
[0]=>
int(2)
[1]=>
int(1)
}
bool(false)
id = 6 label = f
id = 5 label = e
array(2) {
["id"]=>
string(1) "6"
["label"]=>
string(1) "f"
}
[020] [2014] %s
array(2) {
["id"]=>
string(1) "6"
["label"]=>
string(1) "f"
}
---
array(1) {
[0]=>
array(1) {
[0]=>
string(3) "100"
}
}
---
array(2) {
[0]=>
array(2) {
[0]=>
string(1) "2"
[1]=>
string(1) "a"
}
[1]=>
array(2) {
[0]=>
string(1) "3"
[1]=>
string(1) "b"
}
}
done!
+56 -5
View File
@@ -1111,7 +1111,8 @@ PHPAPI MYSQLND * mysqlnd_connect(MYSQLND * conn_handle,
const char * db, php_size_t db_len,
php_uint_t port,
const char * socket_or_pipe,
php_uint_t mysql_flags
php_uint_t mysql_flags,
php_uint_t client_api_flags
TSRMLS_DC)
{
enum_func_status ret = FAIL;
@@ -1122,7 +1123,7 @@ PHPAPI MYSQLND * mysqlnd_connect(MYSQLND * conn_handle,
if (!conn_handle) {
self_alloced = TRUE;
if (!(conn_handle = mysqlnd_init(FALSE))) {
if (!(conn_handle = mysqlnd_init(client_api_flags, FALSE))) {
/* OOM */
DBG_RETURN(NULL);
}
@@ -2570,6 +2571,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, store_result)(MYSQLND_CONN_DATA * const conn,
if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
do {
unsigned int f = flags;
if (!conn->current_result) {
break;
}
@@ -2583,7 +2585,24 @@ MYSQLND_METHOD(mysqlnd_conn_data, store_result)(MYSQLND_CONN_DATA * const conn,
MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_BUFFERED_SETS);
result = conn->current_result->m.store_result(conn->current_result, conn, 0 TSRMLS_CC);
/* overwrite */
if ((conn->m->get_client_api_capabilities(conn TSRMLS_CC) & MYSQLND_CLIENT_KNOWS_RSET_COPY_DATA)) {
if (MYSQLND_G(fetch_data_copy)) {
f &= ~MYSQLND_STORE_NO_COPY;
f |= MYSQLND_STORE_COPY;
}
} else {
/* if for some reason PDO borks something */
if (!(f & (MYSQLND_STORE_NO_COPY | MYSQLND_STORE_COPY))) {
f |= MYSQLND_STORE_COPY;
}
}
if (!(f & (MYSQLND_STORE_NO_COPY | MYSQLND_STORE_COPY))) {
SET_CLIENT_ERROR(*conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "Unknown fetch mode");
DBG_ERR("Unknown fetch mode");
break;
}
result = conn->current_result->m.store_result(conn->current_result, conn, f TSRMLS_CC);
if (!result) {
conn->current_result->m.free_result(conn->current_result, TRUE TSRMLS_CC);
}
@@ -2890,6 +2909,32 @@ MYSQLND_METHOD(mysqlnd_conn_data, tx_savepoint_release)(MYSQLND_CONN_DATA * conn
/* }}} */
/* {{{ mysqlnd_conn_data::negotiate_client_api_capabilities */
static unsigned int
MYSQLND_METHOD(mysqlnd_conn_data, negotiate_client_api_capabilities)(MYSQLND_CONN_DATA * const conn, const unsigned int flags TSRMLS_DC)
{
unsigned int ret = 0;
DBG_ENTER("mysqlnd_conn_data::negotiate_client_api_capabilities");
if (conn) {
ret = conn->client_api_capabilities;
conn->client_api_capabilities = flags;
}
DBG_RETURN(ret);
}
/* }}} */
/* {{{ mysqlnd_conn_data::get_client_api_capabilities */
static unsigned int
MYSQLND_METHOD(mysqlnd_conn_data, get_client_api_capabilities)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
DBG_ENTER("mysqlnd_conn_data::get_client_api_capabilities");
DBG_RETURN(conn? conn->client_api_capabilities : 0);
}
/* }}} */
/* {{{ mysqlnd_conn_data::local_tx_start */
static enum_func_status
MYSQLND_METHOD(mysqlnd_conn_data, local_tx_start)(MYSQLND_CONN_DATA * conn, size_t this_func TSRMLS_DC)
@@ -3018,7 +3063,10 @@ MYSQLND_CLASS_METHODS_START(mysqlnd_conn_data)
MYSQLND_METHOD(mysqlnd_conn_data, simple_command_send_request),
MYSQLND_METHOD(mysqlnd_conn_data, fetch_auth_plugin_by_name),
MYSQLND_METHOD(mysqlnd_conn_data, set_client_option_2d)
MYSQLND_METHOD(mysqlnd_conn_data, set_client_option_2d),
MYSQLND_METHOD(mysqlnd_conn_data, negotiate_client_api_capabilities),
MYSQLND_METHOD(mysqlnd_conn_data, get_client_api_capabilities)
MYSQLND_CLASS_METHODS_END;
@@ -3097,11 +3145,14 @@ MYSQLND_CLASS_METHODS_END;
/* {{{ _mysqlnd_init */
PHPAPI MYSQLND *
_mysqlnd_init(zend_bool persistent TSRMLS_DC)
_mysqlnd_init(unsigned int flags, zend_bool persistent TSRMLS_DC)
{
MYSQLND * ret;
DBG_ENTER("mysqlnd_init");
ret = MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_object_factory).get_connection(persistent TSRMLS_CC);
if (ret && ret->data) {
ret->data->m->negotiate_client_api_capabilities(ret->data, flags TSRMLS_CC);
}
DBG_RETURN(ret);
}
/* }}} */
+5 -3
View File
@@ -85,15 +85,16 @@ PHPAPI const MYSQLND_CHARSET * mysqlnd_find_charset_name(const char * const char
/* Connect */
#define mysqlnd_init(persistent) _mysqlnd_init((persistent) TSRMLS_CC)
PHPAPI MYSQLND * _mysqlnd_init(zend_bool persistent TSRMLS_DC);
#define mysqlnd_init(client_flags, persistent) _mysqlnd_init((client_flags), (persistent) TSRMLS_CC)
PHPAPI MYSQLND * _mysqlnd_init(unsigned int client_flags, zend_bool persistent TSRMLS_DC);
PHPAPI MYSQLND * mysqlnd_connect(MYSQLND * conn,
const char * host, const char * user,
const char * passwd, php_size_t passwd_len,
const char * db, php_size_t db_len,
php_uint_t port,
const char * socket_or_pipe,
php_uint_t mysql_flags
php_uint_t mysql_flags,
php_uint_t client_api_flags
TSRMLS_DC);
#define mysqlnd_change_user(conn, user, passwd, db, silent) ((conn)->data)->m->change_user((conn)->data, (user), (passwd), (db), (silent), strlen((passwd)) TSRMLS_CC)
@@ -282,6 +283,7 @@ ZEND_BEGIN_MODULE_GLOBALS(mysqlnd)
php_int_t debug_calloc_fail_threshold;
php_int_t debug_realloc_fail_threshold;
char * sha256_server_public_key;
zend_bool fetch_data_copy;
ZEND_END_MODULE_GLOBALS(mysqlnd)
PHPAPI ZEND_EXTERN_MODULE_GLOBALS(mysqlnd)
+10
View File
@@ -620,6 +620,16 @@ enum php_mysqlnd_server_command
#define MYSQLND_STORE_NO_COPY 2
#define MYSQLND_STORE_COPY 4
enum mysqlnd_buffered_type
{
MYSQLND_BUFFERED_TYPE_ZVAL = 1,
MYSQLND_BUFFERED_TYPE_C
};
#define MYSQLND_CLIENT_NO_FLAG 0
#define MYSQLND_CLIENT_KNOWS_RSET_COPY_DATA 1
#endif /* MYSQLND_ENUM_N_DEF_H */
+14 -2
View File
@@ -84,14 +84,26 @@ PHPAPI void ** _mysqlnd_plugin_get_plugin_result_unbuffered_data(const MYSQLND_R
/* {{{ _mysqlnd_plugin_get_plugin_result_buffered_data */
PHPAPI void ** _mysqlnd_plugin_get_plugin_result_buffered_data(const MYSQLND_RES_BUFFERED * result, unsigned int plugin_id TSRMLS_DC)
PHPAPI void ** _mysqlnd_plugin_get_plugin_result_buffered_data_zval(const MYSQLND_RES_BUFFERED_ZVAL * result, unsigned int plugin_id TSRMLS_DC)
{
DBG_ENTER("_mysqlnd_plugin_get_plugin_result_data");
DBG_INF_FMT("plugin_id=%u", plugin_id);
if (!result || plugin_id >= mysqlnd_plugin_count()) {
return NULL;
}
DBG_RETURN((void *)((char *)result + sizeof(MYSQLND_RES_BUFFERED) + plugin_id * sizeof(void *)));
DBG_RETURN((void *)((char *)result + sizeof(MYSQLND_RES_BUFFERED_ZVAL) + plugin_id * sizeof(void *)));
}
/* }}} */
/* {{{ _mysqlnd_plugin_get_plugin_result_buffered_data */
PHPAPI void ** _mysqlnd_plugin_get_plugin_result_buffered_data_c(const MYSQLND_RES_BUFFERED_C * result, unsigned int plugin_id TSRMLS_DC)
{
DBG_ENTER("_mysqlnd_plugin_get_plugin_result_data");
DBG_INF_FMT("plugin_id=%u", plugin_id);
if (!result || plugin_id >= mysqlnd_plugin_count()) {
return NULL;
}
DBG_RETURN((void *)((char *)result + sizeof(MYSQLND_RES_BUFFERED_C) + plugin_id * sizeof(void *)));
}
/* }}} */
+4 -2
View File
@@ -34,9 +34,11 @@ PHPAPI void ** _mysqlnd_plugin_get_plugin_result_data(const MYSQLND_RES * result
PHPAPI void ** _mysqlnd_plugin_get_plugin_result_unbuffered_data(const MYSQLND_RES_UNBUFFERED * result, unsigned int plugin_id TSRMLS_DC);
#define mysqlnd_plugin_get_plugin_result_unbuffered_data(r, p_id) _mysqlnd_plugin_get_plugin_result_unbuffered_data((r), (p_id) TSRMLS_CC)
PHPAPI void ** _mysqlnd_plugin_get_plugin_result_buffered_data(const MYSQLND_RES_BUFFERED * result, unsigned int plugin_id TSRMLS_DC);
#define mysqlnd_plugin_get_plugin_result_buffered_data(r, p_id) _mysqlnd_plugin_get_plugin_result_buffered_data((r), (p_id) TSRMLS_CC)
PHPAPI void ** _mysqlnd_plugin_get_plugin_result_buffered_data_zval(const MYSQLND_RES_BUFFERED_ZVAL * result, unsigned int plugin_id TSRMLS_DC);
#define mysqlnd_plugin_get_plugin_result_buffered_data_zval(r, p_id) _mysqlnd_plugin_get_plugin_result_buffered_data_zval((r), (p_id) TSRMLS_CC)
PHPAPI void ** _mysqlnd_plugin_get_plugin_result_buffered_data_c(const MYSQLND_RES_BUFFERED_C * result, unsigned int plugin_id TSRMLS_DC);
#define mysqlnd_plugin_get_plugin_result_buffered_data_c(r, p_id) _mysqlnd_plugin_get_plugin_result_buffered_data_c((r), (p_id) TSRMLS_CC)
PHPAPI void ** _mysqlnd_plugin_get_plugin_stmt_data(const MYSQLND_STMT * stmt, unsigned int plugin_id TSRMLS_DC);
#define mysqlnd_plugin_get_plugin_stmt_data(s, p_id) _mysqlnd_plugin_get_plugin_stmt_data((s), (p_id) TSRMLS_CC)
+87 -80
View File
@@ -89,36 +89,39 @@ MYSQLND_METHOD(mysqlnd_stmt, store_result)(MYSQLND_STMT * const s TSRMLS_DC)
result->type = MYSQLND_RES_PS_BUF;
/* result->m.row_decoder = php_mysqlnd_rowp_read_binary_protocol; */
result->stored_data = mysqlnd_result_buffered_init(result->field_count, TRUE, result->persistent TSRMLS_CC);
result->stored_data = (MYSQLND_RES_BUFFERED *) mysqlnd_result_buffered_zval_init(result->field_count, TRUE, result->persistent TSRMLS_CC);
if (!result->stored_data) {
SET_OOM_ERROR(*conn->error_info);
DBG_RETURN(NULL);
}
ret = result->m.store_result_fetch_data(conn, result, result->meta, TRUE TSRMLS_CC);
ret = result->m.store_result_fetch_data(conn, result, result->meta, &result->stored_data->row_buffers, TRUE TSRMLS_CC);
result->stored_data->m.fetch_row = mysqlnd_stmt_fetch_row_buffered;
if (PASS == ret) {
/* Overflow ? */
MYSQLND_RES_BUFFERED * set = result->stored_data;
if (set->row_count) {
/* don't try to allocate more than possible - mnd_XXalloc expects size_t, and it can have narrower range than uint64_t */
if (set->row_count * result->meta->field_count * sizeof(zval *) > SIZE_MAX) {
SET_OOM_ERROR(*conn->error_info);
DBG_RETURN(NULL);
if (result->stored_data->type == MYSQLND_BUFFERED_TYPE_ZVAL) {
MYSQLND_RES_BUFFERED_ZVAL * set = (MYSQLND_RES_BUFFERED_ZVAL *) result->stored_data;
if (result->stored_data->row_count) {
/* don't try to allocate more than possible - mnd_XXalloc expects size_t, and it can have narrower range than uint64_t */
if (result->stored_data->row_count * result->meta->field_count * sizeof(zval *) > SIZE_MAX) {
SET_OOM_ERROR(*conn->error_info);
DBG_RETURN(NULL);
}
/* if pecalloc is used valgrind barks gcc version 4.3.1 20080507 (prerelease) [gcc-4_3-branch revision 135036] (SUSE Linux) */
set->data = mnd_emalloc((size_t)(result->stored_data->row_count * result->meta->field_count * sizeof(zval *)));
if (!set->data) {
SET_OOM_ERROR(*conn->error_info);
DBG_RETURN(NULL);
}
memset(set->data, 0, (size_t)(result->stored_data->row_count * result->meta->field_count * sizeof(zval *)));
}
/* if pecalloc is used valgrind barks gcc version 4.3.1 20080507 (prerelease) [gcc-4_3-branch revision 135036] (SUSE Linux) */
set->data = mnd_emalloc((size_t)(set->row_count * result->meta->field_count * sizeof(zval *)));
if (!set->data) {
SET_OOM_ERROR(*conn->error_info);
DBG_RETURN(NULL);
}
memset(set->data, 0, (size_t)(set->row_count * result->meta->field_count * sizeof(zval *)));
/* Position at the first row */
set->data_cursor = set->data;
} else if (result->stored_data->type == MYSQLND_BUFFERED_TYPE_ZVAL) {
/*TODO*/
}
/* Position at the first row */
set->data_cursor = set->data;
/* libmysql API docs say it should be so for SELECT statements */
stmt->upsert_status->affected_rows = stmt->result->stored_data->row_count;
@@ -187,7 +190,7 @@ MYSQLND_METHOD(mysqlnd_stmt, get_result)(MYSQLND_STMT * const s TSRMLS_DC)
break;
}
if ((result = result->m.store_result(result, conn, TRUE TSRMLS_CC))) {
if ((result = result->m.store_result(result, conn, MYSQLND_STORE_PS | MYSQLND_STORE_NO_COPY TSRMLS_CC))) {
stmt->upsert_status->affected_rows = result->stored_data->row_count;
stmt->state = MYSQLND_STMT_PREPARED;
result->type = MYSQLND_RES_PS_BUF;
@@ -733,7 +736,6 @@ mysqlnd_stmt_fetch_row_buffered(MYSQLND_RES * result, void * param, php_uint_t f
{
MYSQLND_STMT * s = (MYSQLND_STMT *) param;
MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
MYSQLND_RES_BUFFERED *set = result->stored_data;
const MYSQLND_RES_METADATA * const meta = result->meta;
php_uint_t field_count = meta->field_count;
@@ -742,81 +744,86 @@ mysqlnd_stmt_fetch_row_buffered(MYSQLND_RES * result, void * param, php_uint_t f
DBG_INF_FMT("stmt=%lu", stmt != NULL ? stmt->stmt_id : 0L);
/* If we haven't read everything */
if (set->data_cursor &&
(set->data_cursor - set->data) < (set->row_count * field_count))
{
/* The user could have skipped binding - don't crash*/
if (stmt->result_bind) {
php_uint_t i;
zval **current_row = set->data_cursor;
if (result->stored_data->type == MYSQLND_BUFFERED_TYPE_ZVAL) {
MYSQLND_RES_BUFFERED_ZVAL * set = (MYSQLND_RES_BUFFERED_ZVAL *) result->stored_data;
if (set->data_cursor &&
(set->data_cursor - set->data) < (result->stored_data->row_count * field_count))
{
/* The user could have skipped binding - don't crash*/
if (stmt->result_bind) {
php_uint_t i;
zval **current_row = set->data_cursor;
if (NULL == current_row[0]) {
uint64_t row_num = (set->data_cursor - set->data) / field_count;
enum_func_status rc = result->stored_data->m.row_decoder(set->row_buffers[row_num],
current_row,
meta->field_count,
meta->fields,
result->conn->options->int_and_float_native,
result->conn->stats TSRMLS_CC);
if (PASS != rc) {
DBG_RETURN(FAIL);
}
set->initialized_rows++;
if (stmt->update_max_length) {
for (i = 0; i < result->field_count; i++) {
/*
NULL fields are 0 length, 0 is not more than 0
String of zero size, definitely can't be the next max_length.
Thus for NULL and zero-length we are quite efficient.
*/
if (Z_TYPE_P(current_row[i]) >= IS_STRING) {
php_uint_t len = Z_STRSIZE_P(current_row[i]);
if (meta->fields[i].max_length < len) {
meta->fields[i].max_length = len;
if (NULL == current_row[0]) {
uint64_t row_num = (set->data_cursor - set->data) / field_count;
enum_func_status rc = result->stored_data->m.row_decoder(result->stored_data->row_buffers[row_num],
current_row,
meta->field_count,
meta->fields,
result->conn->options->int_and_float_native,
result->conn->stats TSRMLS_CC);
if (PASS != rc) {
DBG_RETURN(FAIL);
}
result->stored_data->initialized_rows++;
if (stmt->update_max_length) {
for (i = 0; i < result->field_count; i++) {
/*
NULL fields are 0 length, 0 is not more than 0
String of zero size, definitely can't be the next max_length.
Thus for NULL and zero-length we are quite efficient.
*/
if (Z_TYPE_P(current_row[i]) >= IS_STRING) {
php_size_t len = Z_STRSIZE_P(current_row[i]);
if (meta->fields[i].max_length < len) {
meta->fields[i].max_length = len;
}
}
}
}
}
}
for (i = 0; i < result->field_count; i++) {
/* Clean what we copied last time */
for (i = 0; i < result->field_count; i++) {
/* Clean what we copied last time */
#ifndef WE_DONT_COPY_IN_BUFFERED_AND_UNBUFFERED_BECAUSEOF_IS_REF
if (stmt->result_bind[i].zv) {
zval_dtor(stmt->result_bind[i].zv);
}
if (stmt->result_bind[i].zv) {
zval_dtor(stmt->result_bind[i].zv);
}
#endif
/* copy the type */
if (stmt->result_bind[i].bound == TRUE) {
DBG_INF_FMT("i=%u type=%u", i, Z_TYPE_P(current_row[i]));
if (Z_TYPE_P(current_row[i]) != IS_NULL) {
/*
Copy the value.
Pre-condition is that the zvals in the result_bind buffer
have been ZVAL_NULL()-ed or to another simple type
(int, double, bool but not string). Because of the reference
counting the user can't delete the strings the variables point to.
*/
/* copy the type */
if (stmt->result_bind[i].bound == TRUE) {
DBG_INF_FMT("i=%u type=%u", i, Z_TYPE_P(current_row[i]));
if (Z_TYPE_P(current_row[i]) != IS_NULL) {
/*
Copy the value.
Pre-condition is that the zvals in the result_bind buffer
have been ZVAL_NULL()-ed or to another simple type
(int, double, bool but not string). Because of the reference
counting the user can't delete the strings the variables point to.
*/
Z_TYPE_P(stmt->result_bind[i].zv) = Z_TYPE_P(current_row[i]);
stmt->result_bind[i].zv->value = current_row[i]->value;
Z_TYPE_P(stmt->result_bind[i].zv) = Z_TYPE_P(current_row[i]);
stmt->result_bind[i].zv->value = current_row[i]->value;
#ifndef WE_DONT_COPY_IN_BUFFERED_AND_UNBUFFERED_BECAUSEOF_IS_REF
zval_copy_ctor(stmt->result_bind[i].zv);
zval_copy_ctor(stmt->result_bind[i].zv);
#endif
} else {
ZVAL_NULL(stmt->result_bind[i].zv);
} else {
ZVAL_NULL(stmt->result_bind[i].zv);
}
}
}
}
set->data_cursor += field_count;
*fetched_anything = TRUE;
/* buffered result sets don't have a connection */
MYSQLND_INC_GLOBAL_STATISTIC(STAT_ROWS_FETCHED_FROM_CLIENT_PS_BUF);
DBG_INF("row fetched");
} else {
set->data_cursor = NULL;
DBG_INF("no more data");
}
set->data_cursor += field_count;
*fetched_anything = TRUE;
/* buffered result sets don't have a connection */
MYSQLND_INC_GLOBAL_STATISTIC(STAT_ROWS_FETCHED_FROM_CLIENT_PS_BUF);
DBG_INF("row fetched");
} else {
set->data_cursor = NULL;
DBG_INF("no more data");
} else if (result->stored_data->type == MYSQLND_BUFFERED_TYPE_C) {
/*TODO*/
}
DBG_INF("PASS");
DBG_RETURN(PASS);
+473 -157
View File
@@ -32,29 +32,30 @@
#define MYSQLND_SILENT
/* {{{ mysqlnd_result_buffered::initialize_result_set_rest */
/* {{{ mysqlnd_result_buffered_zval::initialize_result_set_rest */
static enum_func_status
MYSQLND_METHOD(mysqlnd_result_buffered, initialize_result_set_rest)(MYSQLND_RES_BUFFERED * const result, MYSQLND_RES_METADATA * const meta,
MYSQLND_STATS * stats, zend_bool int_and_float_native TSRMLS_DC)
MYSQLND_METHOD(mysqlnd_result_buffered_zval, initialize_result_set_rest)(MYSQLND_RES_BUFFERED * const result, MYSQLND_RES_METADATA * const meta,
MYSQLND_STATS * stats, zend_bool int_and_float_native TSRMLS_DC)
{
php_uint_t i;
zval **data_cursor = result->data;
zval **data_begin = result->data;
php_uint_t field_count = meta->field_count;
uint64_t row_count = result->row_count;
enum_func_status ret = PASS;
DBG_ENTER("mysqlnd_result_buffered::initialize_result_set_rest");
const unsigned int field_count = meta->field_count;
const uint64_t row_count = result->row_count;
enum_func_status rc;
zval **data_begin = ((MYSQLND_RES_BUFFERED_ZVAL *) result)->data;
zval **data_cursor = data_begin;
DBG_ENTER("mysqlnd_result_buffered_zval::initialize_result_set_rest");
if (!data_cursor || row_count == result->initialized_rows) {
DBG_RETURN(ret);
}
while ((data_cursor - data_begin) < (ptrdiff_t)(row_count * field_count)) {
if (NULL == data_cursor[0]) {
enum_func_status rc = result->m.row_decoder(
result->row_buffers[(data_cursor - data_begin) / field_count],
rc = result->m.row_decoder(result->row_buffers[(data_cursor - data_begin) / field_count],
data_cursor,
meta->field_count,
field_count,
meta->fields,
int_and_float_native,
stats TSRMLS_CC);
@@ -63,7 +64,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered, initialize_result_set_rest)(MYSQLND_RES_
break;
}
result->initialized_rows++;
for (i = 0; i < meta->field_count; i++) {
for (i = 0; i < field_count; i++) {
/*
NULL fields are 0 length, 0 is not more than 0
String of zero size, definitely can't be the next max_length.
@@ -84,6 +85,62 @@ MYSQLND_METHOD(mysqlnd_result_buffered, initialize_result_set_rest)(MYSQLND_RES_
/* }}} */
/* {{{ mysqlnd_result_buffered_c::initialize_result_set_rest */
static enum_func_status
MYSQLND_METHOD(mysqlnd_result_buffered_c, initialize_result_set_rest)(MYSQLND_RES_BUFFERED * const result, MYSQLND_RES_METADATA * const meta,
MYSQLND_STATS * stats, zend_bool int_and_float_native TSRMLS_DC)
{
unsigned int i;
enum_func_status ret = PASS;
const unsigned int field_count = meta->field_count;
const uint64_t row_count = result->row_count;
enum_func_status rc;
DBG_ENTER("mysqlnd_result_buffered_c::initialize_result_set_rest");
if (result->initialized_rows < row_count) {
zend_uchar * initialized = ((MYSQLND_RES_BUFFERED_C *) result)->initialized;
zval ** current_row = mnd_emalloc(field_count * sizeof(zval *));
if (!current_row) {
DBG_RETURN(FAIL);
}
for (i = 0; i < result->row_count; i++) {
/* (i / 8) & the_bit_for_i*/
if (initialized[i >> 3] & (1 << (i & 7))) {
continue;
}
rc = result->m.row_decoder(result->row_buffers[i], current_row, field_count, meta->fields, int_and_float_native, stats TSRMLS_CC);
if (rc != PASS) {
ret = FAIL;
break;
}
result->initialized_rows++;
initialized[i >> 3] |= (1 << (i & 7));
for (i = 0; i < field_count; i++) {
/*
NULL fields are 0 length, 0 is not more than 0
String of zero size, definitely can't be the next max_length.
Thus for NULL and zero-length we are quite efficient.
*/
if (Z_TYPE_P(current_row[i]) >= IS_STRING) {
unsigned long len = Z_STRSIZE_P(current_row[i]);
if (meta->fields[i].max_length < len) {
meta->fields[i].max_length = len;
}
}
zval_ptr_dtor(&current_row[i]);
}
}
mnd_efree(current_row);
}
DBG_RETURN(ret);
}
/* }}} */
/* {{{ mysqlnd_rset_zval_ptr_dtor */
static void
mysqlnd_rset_zval_ptr_dtor(zval **zv, enum_mysqlnd_res_type type, zend_bool * copy_ctor_called TSRMLS_DC)
@@ -205,25 +262,23 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, free_result)(MYSQLND_RES_UNBUFFERED *
/* }}} */
/* {{{ mysqlnd_result_buffered::free_result */
/* {{{ mysqlnd_result_buffered_zval::free_result */
static void
MYSQLND_METHOD(mysqlnd_result_buffered, free_result)(MYSQLND_RES_BUFFERED * const set TSRMLS_DC)
MYSQLND_METHOD(mysqlnd_result_buffered_zval, free_result)(MYSQLND_RES_BUFFERED_ZVAL * const set TSRMLS_DC)
{
php_uint_t field_count = set->field_count;
int64_t row;
zval ** data = set->data;
DBG_ENTER("mysqlnd_res::free_buffered_data");
DBG_INF_FMT("Freeing "MYSQLND_LLU_SPEC" row(s)", set->row_count);
DBG_ENTER("mysqlnd_result_buffered_zval::free_result");
if (set->data) {
set->data = NULL; /* prevent double free if following loop is interrupted */
if (data) {
php_uint_t copy_on_write_performed = 0;
php_uint_t copy_on_write_saved = 0;
zval **data = set->data;
set->data = NULL; /* prevent double free if following loop is interrupted */
php_uint_t field_count = set->field_count;
int64_t row;
for (row = set->row_count - 1; row >= 0; row--) {
zval **current_row = data + row * field_count;
MYSQLND_MEMORY_POOL_CHUNK *current_buffer = set->row_buffers[row];
int64_t col;
if (current_row != NULL) {
@@ -239,13 +294,48 @@ MYSQLND_METHOD(mysqlnd_result_buffered, free_result)(MYSQLND_RES_BUFFERED * cons
}
}
}
current_buffer->free_chunk(current_buffer TSRMLS_CC);
}
MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_COPY_ON_WRITE_PERFORMED, copy_on_write_performed,
STAT_COPY_ON_WRITE_SAVED, copy_on_write_saved);
mnd_efree(data);
}
set->data_cursor = NULL;
DBG_VOID_RETURN;
}
/* }}} */
/* {{{ mysqlnd_result_buffered_c::free_result */
static void
MYSQLND_METHOD(mysqlnd_result_buffered_c, free_result)(MYSQLND_RES_BUFFERED_C * const set TSRMLS_DC)
{
DBG_ENTER("mysqlnd_result_buffered_c::free_result");
mnd_pefree(set->initialized, set->persistent);
set->initialized = NULL;
DBG_VOID_RETURN;
}
/* }}} */
/* {{{ mysqlnd_result_buffered::free_result */
static void
MYSQLND_METHOD(mysqlnd_result_buffered, free_result)(MYSQLND_RES_BUFFERED * const set TSRMLS_DC)
{
int64_t row;
DBG_ENTER("mysqlnd_result_buffered::free_result");
DBG_INF_FMT("Freeing "MYSQLND_LLU_SPEC" row(s)", set->row_count);
if (set->type == MYSQLND_BUFFERED_TYPE_ZVAL) {
MYSQLND_METHOD(mysqlnd_result_buffered_zval, free_result)((MYSQLND_RES_BUFFERED_ZVAL *) set TSRMLS_CC);
} if (set->type == MYSQLND_BUFFERED_TYPE_C) {
MYSQLND_METHOD(mysqlnd_result_buffered_c, free_result)((MYSQLND_RES_BUFFERED_C *) set TSRMLS_CC);
}
for (row = set->row_count - 1; row >= 0; row--) {
MYSQLND_MEMORY_POOL_CHUNK *current_buffer = set->row_buffers[row];
current_buffer->free_chunk(current_buffer TSRMLS_CC);
}
if (set->lengths) {
mnd_pefree(set->lengths, set->persistent);
@@ -253,8 +343,8 @@ MYSQLND_METHOD(mysqlnd_result_buffered, free_result)(MYSQLND_RES_BUFFERED * cons
}
if (set->row_buffers) {
mnd_efree(set->row_buffers);
set->row_buffers = NULL;
mnd_pefree(set->row_buffers, 0);
set->row_buffers = NULL;
}
if (set->result_set_memory_pool) {
@@ -263,7 +353,6 @@ MYSQLND_METHOD(mysqlnd_result_buffered, free_result)(MYSQLND_RES_BUFFERED * cons
}
set->data_cursor = NULL;
set->row_count = 0;
mnd_pefree(set, set->persistent);
@@ -590,31 +679,49 @@ mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s
completeness.
*/
static php_uint_t *
MYSQLND_METHOD(mysqlnd_result_buffered, fetch_lengths)(MYSQLND_RES_BUFFERED * const result TSRMLS_DC)
MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_lengths)(MYSQLND_RES_BUFFERED * const result TSRMLS_DC)
{
php_uint_t i;
zval **previous_row;
MYSQLND_RES_BUFFERED *set = result;
const MYSQLND_RES_BUFFERED_ZVAL * set = (MYSQLND_RES_BUFFERED_ZVAL *) result;
/*
If:
- unbuffered result
- first row has not been read
- last_row has been read
*/
DBG_ENTER("mysqlnd_result_buffered_zval::fetch_lengths");
if (set->data_cursor == NULL ||
set->data_cursor == set->data ||
((set->data_cursor - set->data) > (set->row_count * result->field_count) ))
((set->data_cursor - set->data) > (result->row_count * result->field_count) ))
{
return NULL;/* No rows or no more rows */
DBG_INF("EOF");
DBG_RETURN(NULL);/* No rows or no more rows */
}
DBG_INF("non NULL");
DBG_RETURN(result->lengths);
}
/* }}} */
previous_row = set->data_cursor - result->field_count;
for (i = 0; i < result->field_count; i++) {
result->lengths[i] = (Z_TYPE_P(previous_row[i]) == IS_NULL)? 0:Z_STRSIZE_P(previous_row[i]);
/* {{{ mysqlnd_result_buffered_c::fetch_lengths */
/*
Do lazy initialization for buffered results. As PHP strings have
length inside, this function makes not much sense in the context
of PHP, to be called as separate function. But let's have it for
completeness.
*/
static unsigned long *
MYSQLND_METHOD(mysqlnd_result_buffered_c, fetch_lengths)(MYSQLND_RES_BUFFERED * const result TSRMLS_DC)
{
const MYSQLND_RES_BUFFERED_C * set = (MYSQLND_RES_BUFFERED_C *) result;
DBG_ENTER("mysqlnd_result_buffered_c::fetch_lengths");
if (set->current_row > set->row_count || set->current_row == 0) {
DBG_INF("EOF");
DBG_RETURN(NULL); /* No more rows, or no fetched row */
}
return result->lengths;
DBG_INF("non NULL");
DBG_RETURN(result->lengths);
}
/* }}} */
@@ -767,7 +874,7 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row_c)(MYSQLND_RES * result, voi
/* {{{ mysqlnd_result_unbuffered::fetch_row */
static enum_func_status
MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row)(MYSQLND_RES * result, void * param, php_uint_t flags, zend_bool * fetched_anything TSRMLS_DC)
MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row)(MYSQLND_RES * result, void * param, const php_uint_t flags, zend_bool * fetched_anything TSRMLS_DC)
{
enum_func_status ret;
zval *row = (zval *) param;
@@ -944,74 +1051,86 @@ static enum_func_status
MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row_c)(MYSQLND_RES * result, void * param, php_uint_t flags, zend_bool * fetched_anything TSRMLS_DC)
{
MYSQLND_ROW_C * row = (MYSQLND_ROW_C *) param;
MYSQLND_RES_BUFFERED * set = result->stored_data;
const MYSQLND_RES_METADATA * const meta = result->meta;
php_uint_t field_count = meta->field_count;
enum_func_status ret = FAIL;
DBG_ENTER("mysqlnd_result_buffered::fetch_row_c");
/* If we haven't read everything */
if (set->data_cursor &&
(set->data_cursor - set->data) < (set->row_count * field_count))
{
zval **current_row = set->data_cursor;
MYSQLND_FIELD * field = meta->fields;
php_uint_t i;
if (result->stored_data->type == MYSQLND_BUFFERED_TYPE_ZVAL) {
MYSQLND_RES_BUFFERED_ZVAL * set = (MYSQLND_RES_BUFFERED_ZVAL *) result->stored_data;
if (NULL == current_row[0]) {
uint64_t row_num = (set->data_cursor - set->data) / field_count;
enum_func_status rc = set->m.row_decoder(set->row_buffers[row_num],
current_row,
field_count,
meta->fields,
result->conn->options->int_and_float_native,
result->conn->stats TSRMLS_CC);
if (rc != PASS) {
DBG_RETURN(FAIL);
}
set->initialized_rows++;
for (i = 0; i < field_count; i++) {
/*
NULL fields are 0 length, 0 is not more than 0
String of zero size, definitely can't be the next max_length.
Thus for NULL and zero-length we are quite efficient.
*/
if (Z_TYPE_P(current_row[i]) >= IS_STRING) {
php_uint_t len = Z_STRSIZE_P(current_row[i]);
if (field->max_length < len) {
field->max_length = len;
/* If we haven't read everything */
if (set->data_cursor &&
(set->data_cursor - set->data) < (result->stored_data->row_count * field_count))
{
zval **current_row = set->data_cursor;
unsigned int i;
if (NULL == current_row[0]) {
uint64_t row_num = (set->data_cursor - set->data) / field_count;
enum_func_status rc = set->m.row_decoder(set->row_buffers[row_num],
current_row,
field_count,
meta->fields,
result->conn->options->int_and_float_native,
result->conn->stats TSRMLS_CC);
if (rc != PASS) {
DBG_RETURN(FAIL);
}
set->initialized_rows++;
for (i = 0; i < field_count; i++) {
/*
NULL fields are 0 length, 0 is not more than 0
String of zero size, definitely can't be the next max_length.
Thus for NULL and zero-length we are quite efficient.
*/
if (Z_TYPE_P(current_row[i]) >= IS_STRING) {
unsigned long len = Z_STRSIZE_P(current_row[i]);
if (meta->fields[i].max_length < len) {
meta->fields[i].max_length = len;
}
}
}
}
}
/* BEGIN difference between normal normal fetch and _c */
/* there is no conn handle in this function thus we can't set OOM in error_info */
*row = mnd_malloc(field_count * sizeof(char *));
if (ret) {
for (i = 0; i < field_count; i++) {
zval * data = current_row[i];
/* there is no conn handle in this function thus we can't set OOM in error_info */
*row = mnd_malloc(field_count * sizeof(char *));
if (*row) {
for (i = 0; i < field_count; i++) {
zval * data = current_row[i];
if (Z_TYPE_P(data) != IS_NULL) {
convert_to_string(data);
(*row)[i] = Z_STRVAL_P(data);
} else {
(*row)[i] = NULL;
set->lengths[i] = (Z_TYPE_P(data) == IS_NULL)? 0:Z_STRSIZE_P(data);
if (Z_TYPE_P(data) != IS_NULL) {
convert_to_string(data);
(*row)[i] = Z_STRVAL_P(data);
} else {
(*row)[i] = NULL;
}
}
set->data_cursor += field_count;
MYSQLND_INC_GLOBAL_STATISTIC(STAT_ROWS_FETCHED_FROM_CLIENT_NORMAL_BUF);
} else {
SET_OOM_ERROR(*result->conn->error_info);
}
}
/* END difference between normal normal fetch and _c */
set->data_cursor += field_count;
MYSQLND_INC_GLOBAL_STATISTIC(STAT_ROWS_FETCHED_FROM_CLIENT_NORMAL_BUF);
*fetched_anything = TRUE;
ret = PASS;
} else {
set->data_cursor = NULL;
DBG_INF("EOF reached");
*fetched_anything = *row? TRUE:FALSE;
ret = *row? PASS:FAIL;
} else {
set->data_cursor = NULL;
DBG_INF("EOF reached");
*fetched_anything = FALSE;
ret = PASS;
}
} else if (result->stored_data->type == MYSQLND_BUFFERED_TYPE_C) {
/*
We don't support _C with pdo because it uses the data in a different way - just references it.
We will either leak or give nirvana pointers
*/
*fetched_anything = FALSE;
ret = PASS;
DBG_RETURN(FAIL);
}
DBG_INF_FMT("ret=PASS fetched=%u", *fetched_anything);
DBG_RETURN(ret);
@@ -1019,25 +1138,24 @@ MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row_c)(MYSQLND_RES * result, void
/* }}} */
/* {{{ mysqlnd_result_buffered::fetch_row */
/* {{{ mysqlnd_result_buffered_zval::fetch_row */
static enum_func_status
MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row)(MYSQLND_RES * result, void * param, php_uint_t flags, zend_bool * fetched_anything TSRMLS_DC)
MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_row)(MYSQLND_RES * result, void * param, const unsigned int flags, zend_bool * fetched_anything TSRMLS_DC)
{
zval * row = (zval *) param;
MYSQLND_RES_BUFFERED * set = result->stored_data;
const MYSQLND_RES_METADATA * const meta = result->meta;
php_uint_t field_count = meta->field_count;
enum_func_status ret = FAIL;
MYSQLND_RES_BUFFERED_ZVAL * set = (MYSQLND_RES_BUFFERED_ZVAL *) result->stored_data;
DBG_ENTER("mysqlnd_result_buffered::fetch_row");
DBG_ENTER("mysqlnd_result_buffered_zval::fetch_row");
/* If we haven't read everything */
if (set->data_cursor &&
(set->data_cursor - set->data) < (set->row_count * field_count))
{
zval **current_row = set->data_cursor;
MYSQLND_FIELD * field = meta->fields;
php_uint_t i;
zval **current_row = set->data_cursor;
if (NULL == current_row[0]) {
uint64_t row_num = (set->data_cursor - set->data) / field_count;
@@ -1058,17 +1176,19 @@ MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row)(MYSQLND_RES * result, void *
Thus for NULL and zero-length we are quite efficient.
*/
if (Z_TYPE_P(current_row[i]) >= IS_STRING) {
php_uint_t len = Z_STRSIZE_P(current_row[i]);
if (field->max_length < len) {
field->max_length = len;
php_size_t len = Z_STRSIZE_P(current_row[i]);
if (meta->fields[i].max_length < len) {
meta->fields[i].max_length = len;
}
}
}
}
for (i = 0; i < field_count; i++, field++) {
for (i = 0; i < field_count; i++) {
zval * data = current_row[i];
set->lengths[i] = (Z_TYPE_P(data) == IS_NULL)? 0:Z_STRSIZE_P(data);
if (flags & MYSQLND_FETCH_NUM) {
Z_ADDREF_P(data);
zend_hash_next_index_insert(Z_ARRVAL_P(row), &data, sizeof(zval *), NULL);
@@ -1084,12 +1204,12 @@ MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row)(MYSQLND_RES * result, void *
Z_ADDREF_P(data);
if (meta->zend_hash_keys[i].is_numeric == FALSE) {
zend_hash_quick_update(Z_ARRVAL_P(row),
field->name,
field->name_length + 1,
meta->fields[i].name,
meta->fields[i].name_length + 1,
meta->zend_hash_keys[i].key,
(void *) &data, sizeof(zval *), NULL);
} else {
zend_hash_index_update(Z_ARRVAL_P(row),
zend_hash_index_update(Z_ARRVAL_P(row),
meta->zend_hash_keys[i].key,
(void *) &data, sizeof(zval *), NULL);
}
@@ -1111,9 +1231,121 @@ MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row)(MYSQLND_RES * result, void *
/* }}} */
/* {{{ mysqlnd_result_buffered_c::fetch_row */
static enum_func_status
MYSQLND_METHOD(mysqlnd_result_buffered_c, fetch_row)(MYSQLND_RES * result, void * param, const php_uint_t flags, zend_bool * fetched_anything TSRMLS_DC)
{
zval * row = (zval *) param;
const MYSQLND_RES_METADATA * const meta = result->meta;
php_uint_t field_count = meta->field_count;
enum_func_status ret = FAIL;
MYSQLND_RES_BUFFERED_C * set = (MYSQLND_RES_BUFFERED_C *) result->stored_data;
DBG_ENTER("mysqlnd_result_buffered_c::fetch_row");
/* If we haven't read everything */
if (set->current_row < set->row_count) {
zval **current_row;
enum_func_status rc;
php_uint_t i;
current_row = mnd_emalloc(field_count * sizeof(zval *));
if (!current_row) {
SET_OOM_ERROR(*result->conn->error_info);
DBG_RETURN(FAIL);
}
rc = result->stored_data->m.row_decoder(result->stored_data->row_buffers[set->current_row],
current_row,
field_count,
meta->fields,
result->conn->options->int_and_float_native,
result->conn->stats TSRMLS_CC);
if (rc != PASS) {
DBG_RETURN(FAIL);
}
if (!(set->initialized[set->current_row >> 3] & (1 << (set->current_row & 7)))) {
set->initialized[set->current_row >> 3] |= (1 << (set->current_row & 7)); /* mark initialized */
set->initialized_rows++;
for (i = 0; i < field_count; i++) {
/*
NULL fields are 0 length, 0 is not more than 0
String of zero size, definitely can't be the next max_length.
Thus for NULL and zero-length we are quite efficient.
*/
if (Z_TYPE_P(current_row[i]) >= IS_STRING) {
php_size_t len = Z_STRSIZE_P(current_row[i]);
if (meta->fields[i].max_length < len) {
meta->fields[i].max_length = len;
}
}
}
}
for (i = 0; i < field_count; i++) {
zval * data = current_row[i];
set->lengths[i] = (Z_TYPE_P(data) == IS_NULL)? 0:Z_STRSIZE_P(data);
if (flags & MYSQLND_FETCH_NUM) {
Z_ADDREF_P(data);
zend_hash_next_index_insert(Z_ARRVAL_P(row), &data, sizeof(zval *), NULL);
}
if (flags & MYSQLND_FETCH_ASSOC) {
/* zend_hash_quick_update needs length + trailing zero */
/* QQ: Error handling ? */
/*
zend_hash_quick_update does not check, as add_assoc_zval_ex do, whether
the index is a numeric and convert it to it. This however means constant
hashing of the column name, which is not needed as it can be precomputed.
*/
Z_ADDREF_P(data);
if (meta->zend_hash_keys[i].is_numeric == FALSE) {
zend_hash_quick_update(Z_ARRVAL_P(row),
meta->fields[i].name,
meta->fields[i].name_length + 1,
meta->zend_hash_keys[i].key,
(void *) &data, sizeof(zval *), NULL);
} else {
zend_hash_index_update(Z_ARRVAL_P(row),
meta->zend_hash_keys[i].key,
(void *) &data, sizeof(zval *), NULL);
}
}
/*
This will usually not destroy anything but decref.
However, if neither NUM nor ASSOC is set we will free memory cleanly and won't leak.
It also simplifies the handling of Z_ADDREF_P because we don't need to check if only
either NUM or ASSOC is set but not both.
*/
zval_ptr_dtor(&data);
}
mnd_efree(current_row);
set->current_row++;
MYSQLND_INC_GLOBAL_STATISTIC(STAT_ROWS_FETCHED_FROM_CLIENT_NORMAL_BUF);
*fetched_anything = TRUE;
ret = PASS;
} else {
if (set->current_row == set->row_count) {
set->current_row = set->row_count + 1;
}
DBG_INF_FMT("EOF reached. current_row=%llu", (unsigned long long) set->current_row);
*fetched_anything = FALSE;
ret = PASS;
}
DBG_INF_FMT("ret=PASS fetched=%u", *fetched_anything);
DBG_RETURN(ret);
}
/* }}} */
/* {{{ mysqlnd_res::fetch_row */
static enum_func_status
MYSQLND_METHOD(mysqlnd_res, fetch_row)(MYSQLND_RES * result, void * param, php_uint_t flags, zend_bool *fetched_anything TSRMLS_DC)
MYSQLND_METHOD(mysqlnd_res, fetch_row)(MYSQLND_RES * result, void * param, const php_uint_t flags, zend_bool *fetched_anything TSRMLS_DC)
{
const mysqlnd_fetch_row_func f = result->stored_data? result->stored_data->m.fetch_row:(result->unbuf? result->unbuf->m.fetch_row:NULL);
if (f) {
@@ -1131,6 +1363,7 @@ MYSQLND_METHOD(mysqlnd_res, fetch_row)(MYSQLND_RES * result, void * param, php_u
enum_func_status
MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const conn, MYSQLND_RES * result,
MYSQLND_RES_METADATA * meta,
MYSQLND_MEMORY_POOL_CHUNK ***row_buffers,
zend_bool binary_protocol TSRMLS_DC)
{
enum_func_status ret;
@@ -1142,13 +1375,13 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const c
set = result->stored_data;
if (!set) {
if (!set || !row_buffers) {
ret = FAIL;
goto end;
}
if (free_rows) {
set->row_buffers = mnd_emalloc((size_t)(free_rows * sizeof(MYSQLND_MEMORY_POOL_CHUNK *)));
if (!set->row_buffers) {
*row_buffers = mnd_pemalloc((size_t)(free_rows * sizeof(MYSQLND_MEMORY_POOL_CHUNK *)), 0);
if (!*row_buffers) {
SET_OOM_ERROR(*conn->error_info);
ret = FAIL;
goto end;
@@ -1184,16 +1417,16 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const c
ret = FAIL;
goto end;
}
new_row_buffers = mnd_erealloc(set->row_buffers, (size_t)(total_allocated_rows * sizeof(MYSQLND_MEMORY_POOL_CHUNK *)));
new_row_buffers = mnd_perealloc(*row_buffers, (size_t)(total_allocated_rows * sizeof(MYSQLND_MEMORY_POOL_CHUNK *)), 0);
if (!new_row_buffers) {
SET_OOM_ERROR(*conn->error_info);
ret = FAIL;
goto end;
}
set->row_buffers = new_row_buffers;
*row_buffers = new_row_buffers;
}
free_rows--;
set->row_buffers[set->row_count] = row_packet->row_buffer;
(*row_buffers)[set->row_count] = row_packet->row_buffer;
set->row_count++;
@@ -1228,7 +1461,7 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const c
ret = FAIL;
goto end;
}
set->row_buffers = mnd_erealloc(set->row_buffers, (size_t) (set->row_count * sizeof(MYSQLND_MEMORY_POOL_CHUNK *)));
*row_buffers = mnd_perealloc(*row_buffers, (size_t) (set->row_count * sizeof(MYSQLND_MEMORY_POOL_CHUNK *)), 0);
}
if (conn->upsert_status->server_status & SERVER_MORE_RESULTS_EXISTS) {
@@ -1247,7 +1480,7 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const c
ret == PASS? "PASS":"FAIL", (uint) set->row_count, conn->upsert_status->warning_count, conn->upsert_status->server_status);
end:
PACKET_FREE(row_packet);
DBG_INF_FMT("rows=%llu", (unsigned long long)result->stored_data->row_count);
DBG_RETURN(ret);
}
/* }}} */
@@ -1260,6 +1493,7 @@ MYSQLND_METHOD(mysqlnd_res, store_result)(MYSQLND_RES * result,
const unsigned int flags TSRMLS_DC)
{
enum_func_status ret;
MYSQLND_MEMORY_POOL_CHUNK ***row_buffers = NULL;
DBG_ENTER("mysqlnd_res::store_result");
@@ -1270,13 +1504,23 @@ MYSQLND_METHOD(mysqlnd_res, store_result)(MYSQLND_RES * result,
CONN_SET_STATE(conn, CONN_FETCHING_DATA);
result->stored_data = mysqlnd_result_buffered_init(result->field_count, flags & MYSQLND_STORE_PS, result->persistent TSRMLS_CC);
if (!result->stored_data) {
SET_OOM_ERROR(*conn->error_info);
DBG_RETURN(NULL);
if (flags & MYSQLND_STORE_NO_COPY) {
result->stored_data = (MYSQLND_RES_BUFFERED *) mysqlnd_result_buffered_zval_init(result->field_count, flags & MYSQLND_STORE_PS, result->persistent TSRMLS_CC);
if (!result->stored_data) {
SET_OOM_ERROR(*conn->error_info);
DBG_RETURN(NULL);
}
row_buffers = &result->stored_data->row_buffers;
} else if (flags & MYSQLND_STORE_COPY) {
result->stored_data = (MYSQLND_RES_BUFFERED *) mysqlnd_result_buffered_c_init(result->field_count, flags & MYSQLND_STORE_PS, result->persistent TSRMLS_CC);
if (!result->stored_data) {
SET_OOM_ERROR(*conn->error_info);
DBG_RETURN(NULL);
}
row_buffers = &result->stored_data->row_buffers;
}
ret = result->m.store_result_fetch_data(conn, result, result->meta, row_buffers, flags & MYSQLND_STORE_PS TSRMLS_CC);
ret = result->m.store_result_fetch_data(conn, result, result->meta, flags & MYSQLND_STORE_PS TSRMLS_CC);
if (FAIL == ret) {
if (result->stored_data) {
COPY_CLIENT_ERROR(*conn->error_info, result->stored_data->error_info);
@@ -1286,24 +1530,30 @@ MYSQLND_METHOD(mysqlnd_res, store_result)(MYSQLND_RES * result,
DBG_RETURN(NULL);
} else {
/* Overflow ? */
MYSQLND_RES_METADATA * meta = result->meta;
MYSQLND_RES_BUFFERED * set = result->stored_data;
if (set->row_count) {
/* don't try to allocate more than possible - mnd_XXalloc expects size_t, and it can have narrower range than uint64_t */
if (set->row_count * meta->field_count * sizeof(zval *) > SIZE_MAX) {
SET_OOM_ERROR(*conn->error_info);
DBG_RETURN(NULL);
if (flags & MYSQLND_STORE_NO_COPY) {
MYSQLND_RES_METADATA * meta = result->meta;
MYSQLND_RES_BUFFERED_ZVAL * set = (MYSQLND_RES_BUFFERED_ZVAL *) result->stored_data;
if (set->row_count) {
/* don't try to allocate more than possible - mnd_XXalloc expects size_t, and it can have narrower range than uint64_t */
if (set->row_count * meta->field_count * sizeof(zval *) > SIZE_MAX) {
SET_OOM_ERROR(*conn->error_info);
DBG_RETURN(NULL);
}
/* if pecalloc is used valgrind barks gcc version 4.3.1 20080507 (prerelease) [gcc-4_3-branch revision 135036] (SUSE Linux) */
set->data = mnd_emalloc((size_t)(set->row_count * meta->field_count * sizeof(zval *)));
if (!set->data) {
SET_OOM_ERROR(*conn->error_info);
DBG_RETURN(NULL);
}
memset(set->data, 0, (size_t)(set->row_count * meta->field_count * sizeof(zval *)));
}
/* if pecalloc is used valgrind barks gcc version 4.3.1 20080507 (prerelease) [gcc-4_3-branch revision 135036] (SUSE Linux) */
set->data = mnd_emalloc((size_t)(set->row_count * meta->field_count * sizeof(zval *)));
if (!set->data) {
SET_OOM_ERROR(*conn->error_info);
DBG_RETURN(NULL);
}
memset(set->data, 0, (size_t)(set->row_count * meta->field_count * sizeof(zval *)));
/* Position at the first row */
set->data_cursor = set->data;
} else if (flags & MYSQLND_STORE_COPY) {
MYSQLND_RES_BUFFERED_C * set = (MYSQLND_RES_BUFFERED_C *) result->stored_data;
set->current_row = 0;
set->initialized = mnd_pecalloc((set->row_count / 8) + 1, sizeof(zend_uchar), set->persistent); /* +1 for safety */
}
/* Position at the first row */
set->data_cursor = set->data;
}
/* libmysql's documentation says it should be so for SELECT statements */
@@ -1370,19 +1620,37 @@ MYSQLND_METHOD(mysqlnd_res, data_seek)(MYSQLND_RES * const result, const uint64_
/* }}} */
/* {{{ mysqlnd_result_buffered::data_seek */
/* {{{ mysqlnd_result_buffered_zval::data_seek */
static enum_func_status
MYSQLND_METHOD(mysqlnd_result_buffered, data_seek)(MYSQLND_RES_BUFFERED * const result, const uint64_t row TSRMLS_DC)
MYSQLND_METHOD(mysqlnd_result_buffered_zval, data_seek)(MYSQLND_RES_BUFFERED * const result, const uint64_t row TSRMLS_DC)
{
DBG_ENTER("mysqlnd_result_buffered::data_seek");
MYSQLND_RES_BUFFERED_ZVAL * set = (MYSQLND_RES_BUFFERED_ZVAL *) result;
DBG_ENTER("mysqlnd_result_buffered_zval::data_seek");
/* libmysql just moves to the end, it does traversing of a linked list */
if (row >= result->row_count) {
result->data_cursor = NULL;
if (row >= set->row_count) {
set->data_cursor = NULL;
} else {
result->data_cursor = result->data + row * result->field_count;
set->data_cursor = set->data + row * result->field_count;
}
DBG_RETURN(PASS);
}
/* }}} */
/* {{{ mysqlnd_result_buffered_c::data_seek */
static enum_func_status
MYSQLND_METHOD(mysqlnd_result_buffered_c, data_seek)(MYSQLND_RES_BUFFERED * const result, const uint64_t row TSRMLS_DC)
{
MYSQLND_RES_BUFFERED_C * set = (MYSQLND_RES_BUFFERED_C *) result;
DBG_ENTER("mysqlnd_result_buffered_c::data_seek");
/* libmysql just moves to the end, it does traversing of a linked list */
if (row >= set->row_count) {
set->current_row = set->row_count;
} else {
set->current_row = row;
}
DBG_RETURN(PASS);
}
/* }}} */
@@ -1539,7 +1807,7 @@ MYSQLND_METHOD(mysqlnd_res, field_tell)(const MYSQLND_RES * const result TSRMLS_
/* {{{ mysqlnd_res::fetch_into */
static void
MYSQLND_METHOD(mysqlnd_res, fetch_into)(MYSQLND_RES * result, php_uint_t flags,
MYSQLND_METHOD(mysqlnd_res, fetch_into)(MYSQLND_RES * result, const php_uint_t flags,
zval *return_value,
enum_mysqlnd_extension extension TSRMLS_DC ZEND_FILE_LINE_DC)
{
@@ -1585,7 +1853,7 @@ MYSQLND_METHOD(mysqlnd_res, fetch_row_c)(MYSQLND_RES * result TSRMLS_DC)
MYSQLND_ROW_C ret = NULL;
DBG_ENTER("mysqlnd_res::fetch_row_c");
if (result->stored_data && result->stored_data->m.fetch_row == MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row)) {
if (result->stored_data && result->stored_data->m.fetch_row == MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_row)) {
MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row_c)(result, (void *) &ret, 0, &fetched_anything TSRMLS_CC);
} else if (result->unbuf && result->unbuf->m.fetch_row == MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row)) {
MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row_c)(result, (void *) &ret, 0, &fetched_anything TSRMLS_CC);
@@ -1600,7 +1868,7 @@ MYSQLND_METHOD(mysqlnd_res, fetch_row_c)(MYSQLND_RES * result TSRMLS_DC)
/* {{{ mysqlnd_res::fetch_all */
static void
MYSQLND_METHOD(mysqlnd_res, fetch_all)(MYSQLND_RES * result, php_uint_t flags, zval *return_value TSRMLS_DC ZEND_FILE_LINE_DC)
MYSQLND_METHOD(mysqlnd_res, fetch_all)(MYSQLND_RES * result, const php_uint_t flags, zval *return_value TSRMLS_DC ZEND_FILE_LINE_DC)
{
zval *row;
php_uint_t i = 0;
@@ -1713,12 +1981,12 @@ MYSQLND_CLASS_METHODS_END;
MYSQLND_CLASS_METHODS_START(mysqlnd_result_buffered)
MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row),
NULL, /* fetch_row */
NULL, /* row_decoder */
MYSQLND_METHOD(mysqlnd_result_buffered, num_rows),
MYSQLND_METHOD(mysqlnd_result_buffered, fetch_lengths),
MYSQLND_METHOD(mysqlnd_result_buffered, data_seek),
MYSQLND_METHOD(mysqlnd_result_buffered, initialize_result_set_rest),
NULL, /* fetch_lengths */
NULL, /* data_seek */
NULL, /* initialize_result_set_rest */
MYSQLND_METHOD(mysqlnd_result_buffered, free_result)
MYSQLND_CLASS_METHODS_END;
@@ -1778,7 +2046,7 @@ mysqlnd_result_unbuffered_init(php_uint_t field_count, zend_bool ps, zend_bool p
ret->m.fetch_lengths = NULL; /* makes no sense */
ret->m.row_decoder = php_mysqlnd_rowp_read_binary_protocol;
} else {
ret->m.row_decoder = php_mysqlnd_rowp_read_text_protocol;
ret->m.row_decoder = php_mysqlnd_rowp_read_text_protocol_zval;
}
DBG_RETURN(ret);
@@ -1786,14 +2054,14 @@ mysqlnd_result_unbuffered_init(php_uint_t field_count, zend_bool ps, zend_bool p
/* }}} */
/* {{{ mysqlnd_result_buffered_init */
PHPAPI MYSQLND_RES_BUFFERED *
mysqlnd_result_buffered_init(php_uint_t field_count, zend_bool ps, zend_bool persistent TSRMLS_DC)
/* {{{ mysqlnd_result_buffered_zval_init */
PHPAPI MYSQLND_RES_BUFFERED_ZVAL *
mysqlnd_result_buffered_zval_init(php_uint_t field_count, zend_bool ps, zend_bool persistent TSRMLS_DC)
{
size_t alloc_size = sizeof(MYSQLND_RES_BUFFERED) + mysqlnd_plugin_count() * sizeof(void *);
MYSQLND_RES_BUFFERED * ret = mnd_pecalloc(1, alloc_size, persistent);
size_t alloc_size = sizeof(MYSQLND_RES_BUFFERED_ZVAL) + mysqlnd_plugin_count() * sizeof(void *);
MYSQLND_RES_BUFFERED_ZVAL * ret = mnd_pecalloc(1, alloc_size, persistent);
DBG_ENTER("mysqlnd_result_buffered_init");
DBG_ENTER("mysqlnd_result_buffered_zval_init");
if (!ret) {
DBG_RETURN(NULL);
@@ -1812,13 +2080,61 @@ mysqlnd_result_buffered_init(php_uint_t field_count, zend_bool ps, zend_bool per
ret->field_count= field_count;
ret->ps = ps;
ret->m = *mysqlnd_result_buffered_get_methods();
ret->type = MYSQLND_BUFFERED_TYPE_ZVAL;
if (ps) {
ret->m.fetch_lengths = NULL; /* makes no sense */
ret->m.row_decoder = php_mysqlnd_rowp_read_binary_protocol;
} else {
ret->m.row_decoder = php_mysqlnd_rowp_read_text_protocol;
ret->m.row_decoder = php_mysqlnd_rowp_read_text_protocol_zval;
}
ret->m.fetch_row = MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_row);
ret->m.fetch_lengths = MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_lengths);
ret->m.data_seek = MYSQLND_METHOD(mysqlnd_result_buffered_zval, data_seek);
ret->m.initialize_result_set_rest = MYSQLND_METHOD(mysqlnd_result_buffered_zval, initialize_result_set_rest);
DBG_RETURN(ret);
}
/* }}} */
/* {{{ mysqlnd_result_buffered_c_init */
PHPAPI MYSQLND_RES_BUFFERED_C *
mysqlnd_result_buffered_c_init(php_uint_t field_count, zend_bool ps, zend_bool persistent TSRMLS_DC)
{
size_t alloc_size = sizeof(MYSQLND_RES_BUFFERED_C) + mysqlnd_plugin_count() * sizeof(void *);
MYSQLND_RES_BUFFERED_C * ret = mnd_pecalloc(1, alloc_size, persistent);
DBG_ENTER("mysqlnd_result_buffered_c_init");
if (!ret) {
DBG_RETURN(NULL);
}
if (!(ret->lengths = mnd_pecalloc(field_count, sizeof(php_uint_t), persistent))) {
mnd_pefree(ret, persistent);
DBG_RETURN(NULL);
}
if (!(ret->result_set_memory_pool = mysqlnd_mempool_create(MYSQLND_G(mempool_default_size) TSRMLS_CC))) {
mnd_efree(ret->lengths);
mnd_pefree(ret, persistent);
DBG_RETURN(NULL);
}
ret->persistent = persistent;
ret->field_count= field_count;
ret->ps = ps;
ret->m = *mysqlnd_result_buffered_get_methods();
ret->type = MYSQLND_BUFFERED_TYPE_C;
if (ps) {
ret->m.fetch_lengths = NULL; /* makes no sense */
ret->m.row_decoder = php_mysqlnd_rowp_read_binary_protocol;
} else {
ret->m.row_decoder = php_mysqlnd_rowp_read_text_protocol_c;
}
ret->m.fetch_row = MYSQLND_METHOD(mysqlnd_result_buffered_c, fetch_row);
ret->m.fetch_lengths = MYSQLND_METHOD(mysqlnd_result_buffered_c, fetch_lengths);
ret->m.data_seek = MYSQLND_METHOD(mysqlnd_result_buffered_c, data_seek);
ret->m.initialize_result_set_rest = MYSQLND_METHOD(mysqlnd_result_buffered_c, initialize_result_set_rest);
DBG_RETURN(ret);
}
+2 -1
View File
@@ -25,7 +25,8 @@
PHPAPI MYSQLND_RES * mysqlnd_result_init(php_uint_t field_count, zend_bool persistent TSRMLS_DC);
PHPAPI MYSQLND_RES_UNBUFFERED * mysqlnd_result_unbuffered_init(php_uint_t field_count, zend_bool ps, zend_bool persistent TSRMLS_DC);
PHPAPI MYSQLND_RES_BUFFERED * mysqlnd_result_buffered_init(php_uint_t field_count, zend_bool ps, zend_bool persistent TSRMLS_DC);
PHPAPI MYSQLND_RES_BUFFERED_ZVAL * mysqlnd_result_buffered_zval_init(php_uint_t field_count, zend_bool ps, zend_bool persistent TSRMLS_DC);
PHPAPI MYSQLND_RES_BUFFERED_C * mysqlnd_result_buffered_c_init(php_uint_t field_count, zend_bool ps, zend_bool persistent TSRMLS_DC);
enum_func_status mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * stmt TSRMLS_DC);
+4 -1
View File
@@ -68,7 +68,7 @@ mysqlnd_reverse_api_register_api(MYSQLND_REVERSE_API * apiext TSRMLS_DC)
/* {{{ zval_to_mysqlnd */
PHPAPI MYSQLND *
zval_to_mysqlnd(zval * zv TSRMLS_DC)
zval_to_mysqlnd(zval * zv, const unsigned int client_api_capabilities, unsigned int * save_client_api_capabilities TSRMLS_DC)
{
MYSQLND * retval;
MYSQLND_REVERSE_API ** elem;
@@ -80,6 +80,9 @@ zval_to_mysqlnd(zval * zv TSRMLS_DC)
if ((*elem)->conversion_cb) {
retval = (*elem)->conversion_cb(zv TSRMLS_CC);
if (retval) {
if (retval->data) {
*save_client_api_capabilities = retval->data->m->negotiate_client_api_capabilities(retval->data, client_api_capabilities TSRMLS_CC);
}
return retval;
}
}
+1 -2
View File
@@ -34,8 +34,7 @@ PHPAPI void mysqlnd_reverse_api_end(TSRMLS_D);
PHPAPI HashTable * mysqlnd_reverse_api_get_api_list(TSRMLS_D);
PHPAPI void mysqlnd_reverse_api_register_api(MYSQLND_REVERSE_API * apiext TSRMLS_DC);
PHPAPI MYSQLND * zval_to_mysqlnd(zval * zv TSRMLS_DC);
PHPAPI MYSQLND * zval_to_mysqlnd(zval * zv, const unsigned int client_api_capabilities, unsigned int * save_client_api_capabilities TSRMLS_DC);
#endif /* MYSQLND_REVERSE_API_H */
+58 -27
View File
@@ -235,7 +235,9 @@ typedef struct st_mysqlnd_param_bind MYSQLND_PARAM_BIND;
typedef struct st_mysqlnd_result_bind MYSQLND_RESULT_BIND;
typedef struct st_mysqlnd_result_metadata MYSQLND_RES_METADATA;
typedef struct st_mysqlnd_buffered_result MYSQLND_RES_BUFFERED;
typedef struct st_mysqlnd_buffered_result_parent MYSQLND_RES_BUFFERED;
typedef struct st_mysqlnd_buffered_result_zval MYSQLND_RES_BUFFERED_ZVAL;
typedef struct st_mysqlnd_buffered_result_c MYSQLND_RES_BUFFERED_C;
typedef struct st_mysqlnd_unbuffered_result MYSQLND_RES_UNBUFFERED;
typedef struct st_mysqlnd_debug MYSQLND_DEBUG;
@@ -244,7 +246,7 @@ typedef struct st_mysqlnd_debug MYSQLND_DEBUG;
typedef MYSQLND_RES* (*mysqlnd_stmt_use_or_store_func)(MYSQLND_STMT * const TSRMLS_DC);
typedef enum_func_status (*mysqlnd_fetch_row_func)(MYSQLND_RES *result,
void * param,
php_uint_t flags,
const php_uint_t flags,
zend_bool * fetched_anything
TSRMLS_DC);
@@ -500,6 +502,11 @@ typedef struct st_mysqlnd_authentication_plugin * (*func_mysqlnd_conn_data__fetc
typedef enum_func_status (*func_mysqlnd_conn_data__set_client_option_2d)(MYSQLND_CONN_DATA * const conn, enum mysqlnd_option option, const char * const key, const char * const value TSRMLS_DC);
typedef unsigned int (*func_mysqlnd_conn_data__negotiate_client_api_capabilities)(MYSQLND_CONN_DATA * const conn, const unsigned int flags TSRMLS_DC);
typedef unsigned int (*func_mysqlnd_conn_data__get_client_api_capabilities)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC);
struct st_mysqlnd_conn_data_methods
{
func_mysqlnd_conn_data__init init;
@@ -591,6 +598,9 @@ struct st_mysqlnd_conn_data_methods
func_mysqlnd_conn_data__fetch_auth_plugin_by_name fetch_auth_plugin_by_name;
func_mysqlnd_conn_data__set_client_option_2d set_client_option_2d;
func_mysqlnd_conn_data__negotiate_client_api_capabilities negotiate_client_api_capabilities;
func_mysqlnd_conn_data__get_client_api_capabilities get_client_api_capabilities;
};
@@ -615,9 +625,9 @@ typedef enum_func_status (*func_mysqlnd_res__row_decoder)(MYSQLND_MEMORY_POOL_CH
typedef MYSQLND_RES * (*func_mysqlnd_res__use_result)(MYSQLND_RES * const result, zend_bool ps_protocol TSRMLS_DC);
typedef MYSQLND_RES * (*func_mysqlnd_res__store_result)(MYSQLND_RES * result, MYSQLND_CONN_DATA * const conn, const php_uint_t flags TSRMLS_DC);
typedef void (*func_mysqlnd_res__fetch_into)(MYSQLND_RES *result, php_uint_t flags, zval *return_value, enum_mysqlnd_extension ext TSRMLS_DC ZEND_FILE_LINE_DC);
typedef void (*func_mysqlnd_res__fetch_into)(MYSQLND_RES *result, const php_uint_t flags, zval *return_value, enum_mysqlnd_extension ext TSRMLS_DC ZEND_FILE_LINE_DC);
typedef MYSQLND_ROW_C (*func_mysqlnd_res__fetch_row_c)(MYSQLND_RES *result TSRMLS_DC);
typedef void (*func_mysqlnd_res__fetch_all)(MYSQLND_RES *result, php_uint_t flags, zval *return_value TSRMLS_DC ZEND_FILE_LINE_DC);
typedef void (*func_mysqlnd_res__fetch_all)(MYSQLND_RES *result, const php_uint_t flags, zval *return_value TSRMLS_DC ZEND_FILE_LINE_DC);
typedef void (*func_mysqlnd_res__fetch_field_data)(MYSQLND_RES *result, php_uint_t offset, zval *return_value TSRMLS_DC);
typedef uint64_t (*func_mysqlnd_res__num_rows)(const MYSQLND_RES * const result TSRMLS_DC);
typedef php_uint_t (*func_mysqlnd_res__num_fields)(const MYSQLND_RES * const result TSRMLS_DC);
@@ -631,7 +641,7 @@ typedef const MYSQLND_FIELD *(*func_mysqlnd_res__fetch_fields)(MYSQLND_RES * con
typedef enum_func_status (*func_mysqlnd_res__read_result_metadata)(MYSQLND_RES * result, MYSQLND_CONN_DATA * conn TSRMLS_DC);
typedef php_uint_t * (*func_mysqlnd_res__fetch_lengths)(MYSQLND_RES * const result TSRMLS_DC);
typedef enum_func_status (*func_mysqlnd_res__store_result_fetch_data)(MYSQLND_CONN_DATA * const conn, MYSQLND_RES * result, MYSQLND_RES_METADATA *meta, zend_bool binary_protocol TSRMLS_DC);
typedef enum_func_status (*func_mysqlnd_res__store_result_fetch_data)(MYSQLND_CONN_DATA * const conn, MYSQLND_RES * result, MYSQLND_RES_METADATA * meta, MYSQLND_MEMORY_POOL_CHUNK *** row_buffers, zend_bool binary_protocol TSRMLS_DC);
typedef void (*func_mysqlnd_res__free_result_buffers)(MYSQLND_RES * result TSRMLS_DC); /* private */
typedef enum_func_status (*func_mysqlnd_res__free_result)(MYSQLND_RES * result, zend_bool implicit TSRMLS_DC);
@@ -947,9 +957,6 @@ struct st_mysqlnd_connection_data
/* Temporal storage for mysql_query */
php_uint_t field_count;
/* persistent connection */
zend_bool persistent;
/* options */
MYSQLND_OPTIONS * options;
MYSQLND_OPTIONS options_impl;
@@ -957,7 +964,12 @@ struct st_mysqlnd_connection_data
/* stats */
MYSQLND_STATS * stats;
unsigned int client_api_capabilities;
struct st_mysqlnd_conn_data_methods * m;
/* persistent connection */
zend_bool persistent;
};
@@ -991,31 +1003,50 @@ struct st_mysqlnd_result_metadata
};
struct st_mysqlnd_buffered_result
#define def_mysqlnd_buffered_result_parent \
MYSQLND_MEMORY_POOL_CHUNK **row_buffers; \
uint64_t row_count; \
uint64_t initialized_rows; \
\
/* Column lengths of current row - both buffered and unbuffered. For buffered results it duplicates the data found in **data */ \
unsigned long *lengths; \
\
MYSQLND_MEMORY_POOL *result_set_memory_pool; \
\
unsigned int references; \
\
MYSQLND_ERROR_INFO error_info; \
\
unsigned int field_count; \
zend_bool ps; \
zend_bool persistent; \
struct st_mysqlnd_result_buffered_methods m; \
enum mysqlnd_buffered_type type; \
void * unused1; \
void * unused2; \
void * unused3
struct st_mysqlnd_buffered_result_parent
{
zval **data;
zval **data_cursor;
MYSQLND_MEMORY_POOL_CHUNK **row_buffers;
uint64_t row_count;
uint64_t initialized_rows;
def_mysqlnd_buffered_result_parent;
};
/*
Column lengths of current row - both buffered and unbuffered.
For buffered results it duplicates the data found in **data
*/
php_uint_t *lengths;
struct st_mysqlnd_buffered_result_zval
{
def_mysqlnd_buffered_result_parent;
MYSQLND_MEMORY_POOL *result_set_memory_pool;
zval **data;
zval **data_cursor;
};
php_uint_t references;
MYSQLND_ERROR_INFO error_info;
struct st_mysqlnd_buffered_result_c
{
def_mysqlnd_buffered_result_parent;
php_uint_t field_count;
zend_bool ps;
zend_bool persistent;
struct st_mysqlnd_result_buffered_methods m;
zend_uchar *initialized; /* every row is a single bit */
uint64_t current_row;
};
+39 -9
View File
@@ -1572,13 +1572,13 @@ php_mysqlnd_rowp_read_binary_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zv
}
/* }}} */
/* {{{ php_mysqlnd_rowp_read_text_protocol */
enum_func_status
php_mysqlnd_rowp_read_text_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields,
php_mysqlnd_rowp_read_text_protocol_aux(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields,
php_uint_t field_count, const MYSQLND_FIELD * fields_metadata,
zend_bool as_int_or_float, MYSQLND_STATS * stats TSRMLS_DC)
zend_bool as_int_or_float, zend_bool copy_data, MYSQLND_STATS * stats TSRMLS_DC)
{
php_uint_t i;
zend_bool last_field_was_string = FALSE;
zval **current_field, **end_field, **start_field;
@@ -1586,7 +1586,7 @@ php_mysqlnd_rowp_read_text_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval
size_t data_size = row_buffer->app;
zend_uchar * bit_area = (zend_uchar*) row_buffer->ptr + data_size + 1; /* we allocate from here */
DBG_ENTER("php_mysqlnd_rowp_read_text_protocol");
DBG_ENTER("php_mysqlnd_rowp_read_text_protocol_aux");
if (!fields) {
DBG_RETURN(FAIL);
@@ -1608,7 +1608,7 @@ php_mysqlnd_rowp_read_text_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval
/* php_mysqlnd_net_field_length() call should be after *this_field_len_pos = p; */
php_uint_t len = php_mysqlnd_net_field_length(&p);
if (current_field > start_field && last_field_was_string) {
if (copy_data == FALSE && current_field > start_field && last_field_was_string) {
/*
Normal queries:
We have to put \0 now to the end of the previous field, if it was
@@ -1733,22 +1733,22 @@ php_mysqlnd_rowp_read_text_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval
p -= len;
if (Z_TYPE_PP(current_field) == IS_INT) {
bit_area += 1 + sprintf((char *)start, ZEND_INT_FMT, Z_IVAL_PP(current_field));
ZVAL_STRINGL(*current_field, (char *) start, bit_area - start - 1, 0);
ZVAL_STRINGL(*current_field, (char *) start, bit_area - start - 1, copy_data);
} else if (Z_TYPE_PP(current_field) == IS_STRING){
memcpy(bit_area, Z_STRVAL_PP(current_field), Z_STRSIZE_PP(current_field));
bit_area += Z_STRSIZE_PP(current_field);
*bit_area++ = '\0';
zval_dtor(*current_field);
ZVAL_STRINGL(*current_field, (char *) start, bit_area - start - 1, 0);
ZVAL_STRINGL(*current_field, (char *) start, bit_area - start - 1, copy_data);
}
} else {
ZVAL_STRINGL(*current_field, (char *)p, len, 0);
ZVAL_STRINGL(*current_field, (char *)p, len, copy_data);
}
p += len;
last_field_was_string = TRUE;
}
}
if (last_field_was_string) {
if (copy_data == FALSE && last_field_was_string) {
/* Normal queries: The buffer has one more byte at the end, because we need it */
row_buffer->ptr[data_size] = '\0';
}
@@ -1758,6 +1758,36 @@ php_mysqlnd_rowp_read_text_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval
/* }}} */
/* {{{ php_mysqlnd_rowp_read_text_protocol_zval */
enum_func_status
php_mysqlnd_rowp_read_text_protocol_zval(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields,
unsigned int field_count, const MYSQLND_FIELD * fields_metadata,
zend_bool as_int_or_float, MYSQLND_STATS * stats TSRMLS_DC)
{
enum_func_status ret;
DBG_ENTER("php_mysqlnd_rowp_read_text_protocol_zval");
ret = php_mysqlnd_rowp_read_text_protocol_aux(row_buffer, fields, field_count, fields_metadata, as_int_or_float, FALSE, stats TSRMLS_CC);
DBG_RETURN(ret);
}
/* }}} */
/* {{{ php_mysqlnd_rowp_read_text_protocol_c */
enum_func_status
php_mysqlnd_rowp_read_text_protocol_c(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields,
unsigned int field_count, const MYSQLND_FIELD * fields_metadata,
zend_bool as_int_or_float, MYSQLND_STATS * stats TSRMLS_DC)
{
enum_func_status ret;
DBG_ENTER("php_mysqlnd_rowp_read_text_protocol_c");
ret = php_mysqlnd_rowp_read_text_protocol_aux(row_buffer, fields, field_count, fields_metadata, as_int_or_float, TRUE, stats TSRMLS_CC);
DBG_RETURN(ret);
}
/* }}} */
/* {{{ php_mysqlnd_rowp_read */
/*
if normal statements => packet->fields is created by this function,
+5 -1
View File
@@ -312,7 +312,11 @@ enum_func_status php_mysqlnd_rowp_read_binary_protocol(MYSQLND_MEMORY_POOL_CHUNK
zend_bool as_int_or_float, MYSQLND_STATS * stats TSRMLS_DC);
enum_func_status php_mysqlnd_rowp_read_text_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields,
enum_func_status php_mysqlnd_rowp_read_text_protocol_zval(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields,
php_uint_t field_count, const MYSQLND_FIELD * fields_metadata,
zend_bool as_int_or_float, MYSQLND_STATS * stats TSRMLS_DC);
enum_func_status php_mysqlnd_rowp_read_text_protocol_c(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields,
php_uint_t field_count, const MYSQLND_FIELD * fields_metadata,
zend_bool as_int_or_float, MYSQLND_STATS * stats TSRMLS_DC);
+5 -4
View File
@@ -111,7 +111,7 @@ mysqlnd_minfo_dump_api_plugins(smart_str * buffer TSRMLS_DC)
MYSQLND_REVERSE_API **ext;
for (zend_hash_internal_pointer_reset_ex(ht, &pos);
zend_hash_get_current_data_ex(ht, (void **) &ext, &pos);
zend_hash_get_current_data_ex(ht, (void **) &ext, &pos) == SUCCESS;
zend_hash_move_forward_ex(ht, &pos)
) {
if (buffer->len) {
@@ -209,6 +209,7 @@ static PHP_GINIT_FUNCTION(mysqlnd)
mysqlnd_globals->debug_calloc_fail_threshold = -1;
mysqlnd_globals->debug_realloc_fail_threshold = -1;
mysqlnd_globals->sha256_server_public_key = NULL;
mysqlnd_globals->fetch_data_copy = FALSE;
}
/* }}} */
@@ -229,8 +230,8 @@ static PHP_INI_MH(OnUpdateNetCmdBufferSize)
/* {{{ PHP_INI_BEGIN
*/
PHP_INI_BEGIN()
STD_PHP_INI_BOOLEAN("mysqlnd.collect_statistics", "1", PHP_INI_ALL, OnUpdateBool, collect_statistics, zend_mysqlnd_globals, mysqlnd_globals)
STD_PHP_INI_BOOLEAN("mysqlnd.collect_memory_statistics", "0", PHP_INI_SYSTEM, OnUpdateBool, collect_memory_statistics, zend_mysqlnd_globals, mysqlnd_globals)
STD_PHP_INI_BOOLEAN("mysqlnd.collect_statistics", "1", PHP_INI_ALL, OnUpdateBool, collect_statistics, zend_mysqlnd_globals, mysqlnd_globals)
STD_PHP_INI_BOOLEAN("mysqlnd.collect_memory_statistics","0",PHP_INI_SYSTEM, OnUpdateBool, collect_memory_statistics, zend_mysqlnd_globals, mysqlnd_globals)
STD_PHP_INI_ENTRY("mysqlnd.debug", NULL, PHP_INI_SYSTEM, OnUpdateString, debug, zend_mysqlnd_globals, mysqlnd_globals)
STD_PHP_INI_ENTRY("mysqlnd.trace_alloc", NULL, PHP_INI_SYSTEM, OnUpdateString, trace_alloc_settings, zend_mysqlnd_globals, mysqlnd_globals)
STD_PHP_INI_ENTRY("mysqlnd.net_cmd_buffer_size", MYSQLND_NET_CMD_BUFFER_MIN_SIZE_STR, PHP_INI_ALL, OnUpdateNetCmdBufferSize, net_cmd_buffer_size, zend_mysqlnd_globals, mysqlnd_globals)
@@ -239,7 +240,7 @@ PHP_INI_BEGIN()
STD_PHP_INI_ENTRY("mysqlnd.log_mask", "0", PHP_INI_ALL, OnUpdateLong, log_mask, zend_mysqlnd_globals, mysqlnd_globals)
STD_PHP_INI_ENTRY("mysqlnd.mempool_default_size","16000", PHP_INI_ALL, OnUpdateLong, mempool_default_size, zend_mysqlnd_globals, mysqlnd_globals)
STD_PHP_INI_ENTRY("mysqlnd.sha256_server_public_key",NULL, PHP_INI_PERDIR, OnUpdateString, sha256_server_public_key, zend_mysqlnd_globals, mysqlnd_globals)
STD_PHP_INI_BOOLEAN("mysqlnd.fetch_data_copy", "0", PHP_INI_ALL, OnUpdateBool, fetch_data_copy, zend_mysqlnd_globals, mysqlnd_globals)
#if PHP_DEBUG
STD_PHP_INI_ENTRY("mysqlnd.debug_emalloc_fail_threshold","-1", PHP_INI_SYSTEM, OnUpdateLong, debug_emalloc_fail_threshold, zend_mysqlnd_globals, mysqlnd_globals)
STD_PHP_INI_ENTRY("mysqlnd.debug_ecalloc_fail_threshold","-1", PHP_INI_SYSTEM, OnUpdateLong, debug_ecalloc_fail_threshold, zend_mysqlnd_globals, mysqlnd_globals)
+4 -2
View File
@@ -2211,8 +2211,10 @@ static void accel_fast_zval_ptr_dtor(zval **zval_ptr)
#else
switch (Z_TYPE_P(zvalue) & ~IS_CONSTANT_INDEX) {
#endif
case IS_ARRAY:
case IS_CONSTANT_ARRAY: {
#if ZEND_EXTENSION_API_NO <= PHP_5_5_API_NO
case IS_CONSTANT_ARRAY:
#endif
case IS_ARRAY: {
TSRMLS_FETCH();
#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
+1 -1
View File
@@ -779,7 +779,7 @@ static ZEND_FUNCTION(opcache_compile_file)
op_array = persistent_compile_file(&handle, ZEND_INCLUDE TSRMLS_CC);
} zend_catch {
EG(current_execute_data) = orig_execute_data;
zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME " could not compile file %s" TSRMLS_CC, handle.filename);
zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME " could not compile file %s", handle.filename);
} zend_end_try();
if(op_array != NULL) {
+21 -15
View File
@@ -237,19 +237,21 @@ static zend_ast *zend_ast_clone(zend_ast *ast TSRMLS_DC)
if ((Z_TYPE_P(ast->u.val) & IS_CONSTANT_TYPE_MASK) >= IS_ARRAY) {
switch ((Z_TYPE_P(ast->u.val) & IS_CONSTANT_TYPE_MASK)) {
case IS_STRING:
case IS_CONSTANT:
case IS_CONSTANT:
Z_STRVAL_P(node->u.val) = (char *) interned_estrndup(Z_STRVAL_P(ast->u.val), Z_STRSIZE_P(ast->u.val));
break;
case IS_ARRAY:
case IS_CONSTANT_ARRAY:
#if ZEND_EXTENSION_API_NO <= PHP_5_5_API_NO
case IS_CONSTANT_ARRAY:
#endif
if (ast->u.val->value.ht && ast->u.val->value.ht != &EG(symbol_table)) {
ALLOC_HASHTABLE(node->u.val->value.ht);
zend_hash_clone_zval(node->u.val->value.ht, ast->u.val->value.ht, 0);
}
break;
case IS_CONSTANT_AST:
Z_AST_P(node->u.val) = zend_ast_clone(Z_AST_P(ast->u.val) TSRMLS_CC);
break;
case IS_CONSTANT_AST:
Z_AST_P(node->u.val) = zend_ast_clone(Z_AST_P(ast->u.val) TSRMLS_CC);
break;
}
}
} else {
@@ -295,20 +297,22 @@ static inline zval* zend_clone_zval(zval *src, int bind TSRMLS_DC)
switch ((Z_TYPE_P(ret) & ~IS_CONSTANT_INDEX)) {
#endif
case IS_STRING:
case IS_CONSTANT:
case IS_CONSTANT:
Z_STRVAL_P(ret) = (char *) interned_estrndup(Z_STRVAL_P(ret), Z_STRSIZE_P(ret));
break;
case IS_ARRAY:
case IS_CONSTANT_ARRAY:
#if ZEND_EXTENSION_API_NO <= PHP_5_5_API_NO
case IS_CONSTANT_ARRAY:
#endif
if (ret->value.ht && ret->value.ht != &EG(symbol_table)) {
ALLOC_HASHTABLE(ret->value.ht);
zend_hash_clone_zval(ret->value.ht, src->value.ht, 0);
}
break;
#if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO
case IS_CONSTANT_AST:
Z_AST_P(ret) = zend_ast_clone(Z_AST_P(ret) TSRMLS_CC);
break;
case IS_CONSTANT_AST:
Z_AST_P(ret) = zend_ast_clone(Z_AST_P(ret) TSRMLS_CC);
break;
#endif
}
}
@@ -417,20 +421,22 @@ static void zend_hash_clone_zval(HashTable *ht, HashTable *source, int bind)
switch ((Z_TYPE_P((zval*)p->pDataPtr) & ~IS_CONSTANT_INDEX)) {
#endif
case IS_STRING:
case IS_CONSTANT:
case IS_CONSTANT:
Z_STRVAL_P(ppz) = (char *) interned_estrndup(Z_STRVAL_P((zval*)p->pDataPtr), Z_STRSIZE_P((zval*)p->pDataPtr));
break;
case IS_ARRAY:
case IS_CONSTANT_ARRAY:
#if ZEND_EXTENSION_API_NO <= PHP_5_5_API_NO
case IS_CONSTANT_ARRAY:
#endif
if (((zval*)p->pDataPtr)->value.ht && ((zval*)p->pDataPtr)->value.ht != &EG(symbol_table)) {
ALLOC_HASHTABLE(ppz->value.ht);
zend_hash_clone_zval(ppz->value.ht, ((zval*)p->pDataPtr)->value.ht, 0);
}
break;
#if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO
case IS_CONSTANT_AST:
Z_AST_P(ppz) = zend_ast_clone(Z_AST_P(ppz) TSRMLS_CC);
break;
case IS_CONSTANT_AST:
Z_AST_P(ppz) = zend_ast_clone(Z_AST_P(ppz) TSRMLS_CC);
break;
#endif
}
}
Loaded 100 of 139 files, more files were not shown because too many files have changed in this diff. Show more