[prev in list] [next in list] [prev in thread] [next in thread]
List: pecl-cvs
Subject: [PECL-CVS] com =?UTF-8?Q?pecl/database/mysql=5Fxdevapi=3A=20orabug=20=23=33=30=31=33?= =?UTF-8?Q?=34
From: hery ramilison <mysqlre () php ! net>
Date: 2020-08-25 18:35:01
Message-ID: php-mail-cc8ecffb37ffe0291453bdaff90304c61824838774 () git ! php ! net
[Download RAW message or body]
Commit: 273abde1fe5b539d64784bc193fe162da6a149ff
Author: Darek Slusarczyk <dariusz.slusarczyk@oracle.com> Tue, 25 Aug 2020 \
20:35:01 +0200
Parents: 134a8f816d6b862cb05f0cb0bd6f8ee58ca671dd
Branches: release/8.0.23
Link: http://git.php.net/?p=pecl/database/mysql_xdevapi.git;a=commitdiff;h=273abde1fe5b539d64784bc193fe162da6a149ff
Log:
orabug #30134451: mysqlndx replace raw zval with improved zvalue where possible
refactorings in:
- converters zval vs google protobuf types (Any, Scalar, Object, Array)
- bind functions / methods
- client attributes
- collection add
- util::zvalue accepts PHP HashTable in constructor and operator=
Bugs:
https://bugs.php.net/30134451
Changed paths:
M mysqlx_collection__add.cc
M mysqlx_collection__add.h
M mysqlx_collection__find.cc
M mysqlx_collection__modify.cc
M mysqlx_collection__remove.cc
M mysqlx_result_iterator.cc
M mysqlx_table__delete.cc
M mysqlx_table__select.cc
M mysqlx_table__update.cc
M util/pb_utils.cc
M util/value.cc
M util/value.h
M xmysqlnd/xmysqlnd_crud_collection_commands.cc
M xmysqlnd/xmysqlnd_crud_collection_commands.h
M xmysqlnd/xmysqlnd_crud_table_commands.cc
M xmysqlnd/xmysqlnd_crud_table_commands.h
M xmysqlnd/xmysqlnd_session.cc
M xmysqlnd/xmysqlnd_stmt.cc
M xmysqlnd/xmysqlnd_wireprotocol.cc
M xmysqlnd/xmysqlnd_wireprotocol.h
M xmysqlnd/xmysqlnd_zval2any.cc
M xmysqlnd/xmysqlnd_zval2any.h
["diff_273abde1fe5b539d64784bc193fe162da6a149ff.txt" (text/plain)]
diff --git a/mysqlx_collection__add.cc b/mysqlx_collection__add.cc
index f748bf14..d9d1ff33 100644
--- a/mysqlx_collection__add.cc
+++ b/mysqlx_collection__add.cc
@@ -84,7 +84,7 @@ collection_add_string(
st_xmysqlnd_crud_collection_op__add* add_op,
util::zvalue& doc)
{
- if( PASS == xmysqlnd_crud_collection_add__add_doc(add_op, doc.ptr()) ) {
+ if( PASS == xmysqlnd_crud_collection_add__add_doc(add_op, doc) ) {
return Add_op_status::success;
}
return Add_op_status::fail;
@@ -97,7 +97,7 @@ collection_add_object(
{
Add_op_status ret = Add_op_status::fail;
util::zvalue new_doc(util::json::encode_document(doc));
- if( PASS == xmysqlnd_crud_collection_add__add_doc(add_op, new_doc.ptr()) ) {
+ if( PASS == xmysqlnd_crud_collection_add__add_doc(add_op, new_doc) ) {
ret = Add_op_status::success;
}
return ret;
diff --git a/mysqlx_collection__add.h b/mysqlx_collection__add.h
index ab47afe1..4c68e668 100644
--- a/mysqlx_collection__add.h
+++ b/mysqlx_collection__add.h
@@ -59,7 +59,7 @@ public:
private:
drv::xmysqlnd_collection* collection{nullptr};
drv::st_xmysqlnd_crud_collection_op__add* add_op{nullptr};
- std::vector<util::zvalue> docs;
+ util::zvalues docs;
};
util::zvalue create_collection_add(
diff --git a/mysqlx_collection__find.cc b/mysqlx_collection__find.cc
index c778a626..f9935c57 100644
--- a/mysqlx_collection__find.cc
+++ b/mysqlx_collection__find.cc
@@ -297,14 +297,12 @@ bool Collection_find::bind(const util::zvalue& bind_variables)
{
DBG_ENTER("mysqlx_collection__find::bind");
- for (const auto& variable_value : bind_variables) {
- const util::zvalue& var_name{ variable_value.first };
+ for (const auto& [var_name, var_value] : bind_variables) {
if (!var_name.is_string()) {
RAISE_EXCEPTION(err_msg_bind_fail);
DBG_RETURN(false);
}
- const util::zvalue& var_value{ variable_value.second };
- if (FAIL == xmysqlnd_crud_collection_find__bind_value(find_op, \
var_name.to_string(), var_value.ptr())) { + if (FAIL == \
xmysqlnd_crud_collection_find__bind_value(find_op, var_name.to_string(), var_value)) \
{ RAISE_EXCEPTION(err_msg_bind_fail);
DBG_RETURN(false);
}
diff --git a/mysqlx_collection__modify.cc b/mysqlx_collection__modify.cc
index 06d471a8..17a50f6c 100644
--- a/mysqlx_collection__modify.cc
+++ b/mysqlx_collection__modify.cc
@@ -205,14 +205,12 @@ bool Collection_modify::bind(const util::zvalue& \
bind_variables) {
DBG_ENTER("Collection_modify::bind");
- for (const auto& variable_value : bind_variables) {
- const util::zvalue& var_name{ variable_value.first };
+ for (const auto& [var_name, var_value] : bind_variables) {
if (!var_name.is_string()) {
RAISE_EXCEPTION(err_msg_bind_fail);
DBG_RETURN(false);
}
- const util::zvalue& var_value{ variable_value.second };
- if (!xmysqlnd_crud_collection_modify__bind_value(modify_op, var_name.to_string(), \
var_value.ptr())) { + if (!xmysqlnd_crud_collection_modify__bind_value(modify_op, \
var_name.to_string(), var_value)) { RAISE_EXCEPTION(err_msg_bind_fail);
DBG_RETURN(false);
}
diff --git a/mysqlx_collection__remove.cc b/mysqlx_collection__remove.cc
index 6d47c4f7..71671432 100644
--- a/mysqlx_collection__remove.cc
+++ b/mysqlx_collection__remove.cc
@@ -153,15 +153,13 @@ bool Collection_remove::bind(const util::zvalue& \
bind_variables) {
DBG_ENTER("Collection_remove::bind");
- for (const auto& variable_value : bind_variables) {
- const util::zvalue& var_name{ variable_value.first };
+ for (const auto& [var_name, var_value] : bind_variables) {
if (!var_name.is_string()) {
RAISE_EXCEPTION(err_msg_bind_fail);
DBG_RETURN(false);
}
- const util::zvalue& var_value{ variable_value.second };
if (FAIL == xmysqlnd_crud_collection_remove__bind_value(
- remove_op, var_name.to_string(), var_value.ptr())) {
+ remove_op, var_name.to_string(), var_value)) {
RAISE_EXCEPTION(err_msg_bind_fail);
DBG_RETURN(false);
}
diff --git a/mysqlx_result_iterator.cc b/mysqlx_result_iterator.cc
index efe5470d..d0bc7b78 100644
--- a/mysqlx_result_iterator.cc
+++ b/mysqlx_result_iterator.cc
@@ -55,7 +55,6 @@ XMYSQLND_METHOD(mysqlx__result_iterator, dtor)(zend_object_iterator \
* iter)
/* cleanup handled in sxe_object_dtor as we dont always have an iterator wrapper */
zval_ptr_dtor(&iterator->intern.data);
- delete iterator;
DBG_VOID_RETURN;
}
diff --git a/mysqlx_table__delete.cc b/mysqlx_table__delete.cc
index 5d10c436..81735a5e 100644
--- a/mysqlx_table__delete.cc
+++ b/mysqlx_table__delete.cc
@@ -210,32 +210,27 @@ MYSQL_XDEVAPI_PHP_METHOD(mysqlx_table__delete, bind)
DBG_ENTER("mysqlx_table__delete::bind");
util::raw_zval* object_zv{nullptr};
- HashTable * bind_variables;
+ HashTable* bind_variables_ht;
if (FAILURE == util::get_method_arguments(execute_data, getThis(), "Oh",
&object_zv, mysqlx_table__delete_class_entry,
- &bind_variables))
+ &bind_variables_ht))
{
DBG_VOID_RETURN;
}
- RETVAL_FALSE;
+ RETVAL_NULL();
auto& data_object{ util::fetch_data_object<st_mysqlx_table__delete>(object_zv) };
if (data_object.crud_op) {
- zend_string* key;
- zval* val{nullptr};
- MYSQLX_HASH_FOREACH_STR_KEY_VAL(bind_variables, key, val)
- {
- if (key)
- {
- const util::string_view variable{ZSTR_VAL(key), ZSTR_LEN(key)};
- if (FAIL == xmysqlnd_crud_table_delete__bind_value(data_object.crud_op, \
variable, val))
- {
+ util::zvalue bind_variables(bind_variables_ht);
+ for (const auto& [key, value] : bind_variables) {
+ if (key.is_string()) {
+ if (FAIL == xmysqlnd_crud_table_delete__bind_value(data_object.crud_op, \
key.to_string_view(), value)) { RAISE_EXCEPTION(err_msg_bind_fail);
DBG_VOID_RETURN;
}
}
- } ZEND_HASH_FOREACH_END();
+ }
util::zvalue::copy_from_to(object_zv, return_value);
}
DBG_VOID_RETURN;
diff --git a/mysqlx_table__select.cc b/mysqlx_table__select.cc
index 2e9f6307..35af8bc6 100644
--- a/mysqlx_table__select.cc
+++ b/mysqlx_table__select.cc
@@ -331,30 +331,27 @@ MYSQL_XDEVAPI_PHP_METHOD(mysqlx_table__select, bind)
DBG_ENTER("mysqlx_table__select::bind");
util::raw_zval* object_zv{nullptr};
- HashTable * bind_variables;
+ HashTable* bind_variables_ht;
if (FAILURE == util::get_method_arguments(execute_data, getThis(), "Oh",
&object_zv, mysqlx_table__select_class_entry,
- &bind_variables))
+ &bind_variables_ht))
{
DBG_VOID_RETURN;
}
- auto& data_object{ util::fetch_data_object<st_mysqlx_table__select>(object_zv) };
-
- RETVAL_FALSE;
+ RETVAL_NULL();
+ auto& data_object{ util::fetch_data_object<st_mysqlx_table__select>(object_zv) };
if (data_object.crud_op && data_object.table) {
- zend_string * key;
- zval* val{nullptr};
- MYSQLX_HASH_FOREACH_STR_KEY_VAL(bind_variables, key, val) {
- if (key) {
- const util::string_view variable{ ZSTR_VAL(key), ZSTR_LEN(key) };
- if (FAIL == xmysqlnd_crud_table_select__bind_value(data_object.crud_op, \
variable, val)) { + util::zvalue bind_variables(bind_variables_ht);
+ for (const auto& [key, value] : bind_variables) {
+ if (key.is_string()) {
+ if (FAIL == xmysqlnd_crud_table_select__bind_value(data_object.crud_op, \
key.to_string_view(), value)) { RAISE_EXCEPTION(err_msg_bind_fail);
DBG_VOID_RETURN;
}
}
- } ZEND_HASH_FOREACH_END();
+ }
util::zvalue::copy_from_to(object_zv, return_value);
}
DBG_VOID_RETURN;
diff --git a/mysqlx_table__update.cc b/mysqlx_table__update.cc
index 1c5840c4..924a4d95 100644
--- a/mysqlx_table__update.cc
+++ b/mysqlx_table__update.cc
@@ -289,35 +289,28 @@ MYSQL_XDEVAPI_PHP_METHOD(mysqlx_table__update, bind)
DBG_ENTER("mysqlx_table__update::bind");
util::raw_zval* object_zv{nullptr};
- HashTable * bind_variables;
+ HashTable * bind_variables_ht;
if (FAILURE == util::get_method_arguments(execute_data, getThis(), "Oh",
&object_zv, mysqlx_table__update_class_entry,
- &bind_variables))
+ &bind_variables_ht))
{
DBG_VOID_RETURN;
}
- auto& data_object{ util::fetch_data_object<st_mysqlx_table__update>(object_zv) };
-
- RETVAL_FALSE;
+ RETVAL_NULL();
+ auto& data_object{ util::fetch_data_object<st_mysqlx_table__update>(object_zv) };
if (data_object.crud_op) {
- zend_string * key;
- zval* val{nullptr};
- zend_bool op_success{TRUE};
- MYSQLX_HASH_FOREACH_STR_KEY_VAL(bind_variables, key, val) {
- if (key) {
- const util::string_view variable{ ZSTR_VAL(key), ZSTR_LEN(key) };
- if (FAIL == xmysqlnd_crud_table_update__bind_value(data_object.crud_op, \
variable, val)) { + util::zvalue bind_variables(bind_variables_ht);
+ for (const auto& [key, value] : bind_variables) {
+ if (key.is_string()) {
+ if (FAIL == xmysqlnd_crud_table_update__bind_value(data_object.crud_op, \
key.to_string_view(), value)) { RAISE_EXCEPTION(err_msg_bind_fail);
- op_success = FALSE;
- break;
+ DBG_VOID_RETURN;
}
}
- } ZEND_HASH_FOREACH_END();
- if( op_success ) {
- util::zvalue::copy_from_to(object_zv, return_value);
}
+ util::zvalue::copy_from_to(object_zv, return_value);
}
DBG_VOID_RETURN;
}
diff --git a/util/pb_utils.cc b/util/pb_utils.cc
index 5a5a87ca..3e1f45ff 100644
--- a/util/pb_utils.cc
+++ b/util/pb_utils.cc
@@ -191,7 +191,7 @@ void to_any(
const util::zvalue& zv,
Any& any)
{
- drv::zval2any(zv.c_ptr(), any);
+ drv::zval2any(zv, any);
}
void to_any(
diff --git a/util/value.cc b/util/value.cc
index 57175aea..970757b1 100644
--- a/util/value.cc
+++ b/util/value.cc
@@ -122,6 +122,16 @@ zvalue::zvalue(const zval* rhs)
}
}
+zvalue::zvalue(const HashTable* ht)
+{
+ if (ht) {
+ ZVAL_ARR(&zv, const_cast<HashTable*>(ht));
+ inc_ref();
+ } else {
+ ZVAL_UNDEF(&zv);
+ }
+}
+
zvalue::zvalue(std::nullptr_t /*value*/)
{
ZVAL_NULL(&zv);
@@ -269,6 +279,18 @@ zvalue& zvalue::operator=(const zval* rhs)
return *this;
}
+zvalue& zvalue::operator=(const HashTable* ht)
+{
+ zval_ptr_dtor(&zv);
+ if (ht) {
+ ZVAL_ARR(&zv, const_cast<HashTable*>(ht));
+ inc_ref();
+ } else {
+ ZVAL_UNDEF(&zv);
+ }
+ return *this;
+}
+
zvalue& zvalue::operator=(std::nullptr_t /*value*/)
{
zval_ptr_dtor(&zv);
@@ -893,7 +915,7 @@ namespace {
class Serializer
{
public:
- Serializer(util::ostringstream& os);
+ Serializer(util::ostringstream& os, bool decorate);
public:
void store(const zvalue& zv);
@@ -903,10 +925,12 @@ private:
private:
util::ostringstream& os;
+ const bool decorate;
};
-Serializer::Serializer(util::ostringstream& os)
+Serializer::Serializer(util::ostringstream& os, bool decorate)
: os(os)
+ , decorate(decorate)
{
}
@@ -938,7 +962,9 @@ void Serializer::store(const zvalue& zv)
break;
case zvalue::Type::String:
- os << "'" << zv.to_string() << "'";
+ if (decorate) os << "'";
+ os << zv.to_string();
+ if (decorate) os << "'";
break;
case zvalue::Type::Array:
@@ -974,10 +1000,10 @@ void Serializer::store_composite(const zvalue& zv, const char* \
opening_tag, cons
} // anonymous namespace
-util::string zvalue::serialize() const
+util::string zvalue::serialize(bool decorate) const
{
util::ostringstream os;
- Serializer serializer(os);
+ Serializer serializer(os, decorate);
serializer.store(*this);
return os.str();
}
diff --git a/util/value.h b/util/value.h
index 34cde5f9..c010b39a 100644
--- a/util/value.h
+++ b/util/value.h
@@ -56,6 +56,8 @@ class zvalue
zvalue(zval&& zv);
zvalue(const zval* zv);
+ zvalue(const HashTable* ht);
+
zvalue(std::nullptr_t value);
zvalue(bool value);
zvalue(int32_t value);
@@ -102,6 +104,8 @@ class zvalue
zvalue& operator=(zval&& rhs);
zvalue& operator=(const zval* rhs);
+ zvalue& operator=(const HashTable* ht);
+
zvalue& operator=(std::nullptr_t value);
zvalue& operator=(bool value);
zvalue& operator=(int32_t value);
@@ -458,8 +462,7 @@ class zvalue
zval* ptr() const;
public:
- // diagnostics
- util::string serialize() const;
+ util::string serialize(bool decorate = true) const;
private:
zval zv;
diff --git a/xmysqlnd/xmysqlnd_crud_collection_commands.cc \
b/xmysqlnd/xmysqlnd_crud_collection_commands.cc index 8986b0e0..2c6b818e 100644
--- a/xmysqlnd/xmysqlnd_crud_collection_commands.cc
+++ b/xmysqlnd/xmysqlnd_crud_collection_commands.cc
@@ -78,7 +78,7 @@ util::std_strings Bindings::get_placeholders() const
return placeholders;
}
-bool Bindings::bind(const util::string& var_name, zval* var_value)
+bool Bindings::bind(const util::string& var_name, const util::zvalue& var_value)
{
DBG_ENTER("Bindings::bind");
DBG_INF_FMT("name=%*s", var_name.length(), var_name.c_str());
@@ -90,10 +90,7 @@ bool Bindings::bind(const util::string& var_name, zval* var_value)
}
Mysqlx::Datatypes::Any any;
- if (FAIL == zval2any(var_value, any)) {
- DBG_ERR("Error converting the zvalue to scalar");
- DBG_RETURN(false);
- }
+ zval2any(var_value, any);
any2log(any);
auto& bound_value = it->second;
@@ -235,34 +232,31 @@ struct st_xmysqlnd_pb_message_shell
}
enum_func_status
-xmysqlnd_crud_collection_add__add_doc(XMYSQLND_CRUD_COLLECTION_OP__ADD * obj,
- zval * values_zv)
+xmysqlnd_crud_collection_add__add_doc(
+ XMYSQLND_CRUD_COLLECTION_OP__ADD * obj,
+ const util::zvalue& doc)
{
DBG_ENTER("xmysqlnd_crud_collection_add__add_doc");
enum_func_status ret{PASS};
- obj->add_document(values_zv);
+ obj->add_document(doc);
DBG_RETURN(ret);
}
-void st_xmysqlnd_crud_collection_op__add::add_document(zval* doc)
+void st_xmysqlnd_crud_collection_op__add::add_document(const util::zvalue& doc)
{
- zval new_doc;
- ZVAL_DUP(&new_doc, doc);
- docs_zv.push_back(new_doc);
+ docs.push_back(doc.clone());
}
void st_xmysqlnd_crud_collection_op__add::bind_docs()
{
- for (auto& values_zv : docs_zv)
- {
+ for (auto& doc : docs) {
::Mysqlx::Crud::Insert_TypedRow* row = message.add_row();
Mysqlx::Expr::Expr * field = row->add_field();
field->set_type(Mysqlx::Expr::Expr::LITERAL);
Mysqlx::Datatypes::Scalar * literal = field->mutable_literal();
literal->set_type(Mysqlx::Datatypes::Scalar::V_STRING);
- literal->mutable_v_string()->set_value(Z_STRVAL(values_zv),
- Z_STRLEN(values_zv));
+ literal->mutable_v_string()->set_value(doc.c_str(), doc.length());
}
}
@@ -322,7 +316,7 @@ enum_func_status
xmysqlnd_crud_collection_remove__bind_value(
XMYSQLND_CRUD_COLLECTION_OP__REMOVE* obj,
const util::string& name,
- zval* value)
+ const util::zvalue& value)
{
DBG_ENTER("xmysqlnd_crud_collection_remove__bind_value");
DBG_RETURN(obj->bindings.bind(name, value) ? PASS : FAIL);
@@ -415,7 +409,7 @@ bool
xmysqlnd_crud_collection_modify__bind_value(
XMYSQLND_CRUD_COLLECTION_OP__MODIFY* obj,
const util::string& name,
- zval* value)
+ const util::zvalue& value)
{
DBG_ENTER("xmysqlnd_crud_collection_modify__bind_value");
DBG_RETURN(obj->bindings.bind(name, value));
@@ -516,10 +510,7 @@ xmysqlnd_crud_collection_modify__add_operation(
}
} else {
Mysqlx::Datatypes::Any any;
- if (FAIL == zval2any(value.ptr(), any)) {
- DBG_ERR("Error converting the zvalue to scalar");
- DBG_RETURN(false);
- }
+ zval2any(value, any);
any2log(any);
operation->mutable_value()->set_type(Mysqlx::Expr::Expr::LITERAL);
@@ -674,7 +665,7 @@ enum_func_status
xmysqlnd_crud_collection_find__bind_value(
XMYSQLND_CRUD_COLLECTION_OP__FIND* obj,
const util::string& name,
- zval* value)
+ const util::zvalue& value)
{
DBG_ENTER("xmysqlnd_crud_collection_find__bind_value");
DBG_RETURN(obj->bindings.bind(name, value) ? PASS : FAIL);
@@ -871,11 +862,7 @@ st_xmysqlnd_stmt_op__execute::finalize_bind()
DBG_ENTER("st_xmysqlnd_stmt_op__execute::finalize_bind");
for (const auto& param : params) {
Mysqlx::Datatypes::Any * arg = message.add_args();
- ret = zval2any(param, *arg);
- if (FAIL == ret) {
- break;
- }
-
+ zval2any(param, *arg);
}
DBG_RETURN(ret);
}
@@ -921,12 +908,12 @@ xmysqlnd_stmt_execute__bind_one_param(XMYSQLND_STMT_OP__EXECUTE \
* obj, const uti }
enum_func_status
-xmysqlnd_stmt_execute__bind_value(XMYSQLND_STMT_OP__EXECUTE * obj, const \
util::zvalue& value) +xmysqlnd_stmt_execute__bind_value(XMYSQLND_STMT_OP__EXECUTE* \
obj, const util::zvalue& value) {
DBG_ENTER("xmysqlnd_stmt_execute__bind_value");
Mysqlx::Datatypes::Any * arg = obj->message.add_args();
- const enum_func_status ret = zval2any(value, *arg);
- DBG_RETURN(ret);
+ zval2any(value, *arg);
+ DBG_RETURN(PASS);
}
enum_func_status
diff --git a/xmysqlnd/xmysqlnd_crud_collection_commands.h \
b/xmysqlnd/xmysqlnd_crud_collection_commands.h index 2ca1a3f2..d3aa3cf3 100644
--- a/xmysqlnd/xmysqlnd_crud_collection_commands.h
+++ b/xmysqlnd/xmysqlnd_crud_collection_commands.h
@@ -40,7 +40,7 @@ typedef struct st_xmysqlnd_crud_collection_op__add \
XMYSQLND_CRUD_COLLECTION_OP__ XMYSQLND_CRUD_COLLECTION_OP__ADD * \
xmysqlnd_crud_collection_add__create(const util::string_view& schema, const \
util::string_view& collection); void \
xmysqlnd_crud_collection_add__destroy(XMYSQLND_CRUD_COLLECTION_OP__ADD * obj); \
enum_func_status \
xmysqlnd_crud_collection_add__set_upsert(XMYSQLND_CRUD_COLLECTION_OP__ADD \
* obj);
-enum_func_status \
xmysqlnd_crud_collection_add__add_doc(XMYSQLND_CRUD_COLLECTION_OP__ADD * obj, zval * \
doc); +enum_func_status \
xmysqlnd_crud_collection_add__add_doc(XMYSQLND_CRUD_COLLECTION_OP__ADD * obj, const \
util::zvalue& doc); enum_func_status \
xmysqlnd_crud_collection_add__finalize_bind(XMYSQLND_CRUD_COLLECTION_OP__ADD * obj); \
struct st_xmysqlnd_pb_message_shell \
xmysqlnd_crud_collection_add__get_protobuf_message(XMYSQLND_CRUD_COLLECTION_OP__ADD * \
obj);
@@ -54,7 +54,7 @@ enum_func_status \
xmysqlnd_crud_collection_remove__set_skip(XMYSQLND_CRUD_COLLECT enum_func_status \
xmysqlnd_crud_collection_remove__bind_value( XMYSQLND_CRUD_COLLECTION_OP__REMOVE* \
obj, const util::string& name,
- zval* value);
+ const util::zvalue& value);
enum_func_status xmysqlnd_crud_collection_remove__add_sort(XMYSQLND_CRUD_COLLECTION_OP__REMOVE \
* obj, const util::string_view& sort); enum_func_status \
xmysqlnd_crud_collection_remove__finalize_bind(XMYSQLND_CRUD_COLLECTION_OP__REMOVE * \
obj); st_xmysqlnd_pb_message_shell \
xmysqlnd_crud_collection_remove__get_protobuf_message(XMYSQLND_CRUD_COLLECTION_OP__REMOVE \
* obj); @@ -79,7 +79,7 @@ bool \
xmysqlnd_crud_collection_modify__set_skip(XMYSQLND_CRUD_COLLECTION_OP__MODI bool \
xmysqlnd_crud_collection_modify__bind_value( XMYSQLND_CRUD_COLLECTION_OP__MODIFY* \
obj, const util::string& name,
- zval* value);
+ const util::zvalue& value);
bool xmysqlnd_crud_collection_modify__add_sort(XMYSQLND_CRUD_COLLECTION_OP__MODIFY* \
obj, const util::string_view& sort);
bool xmysqlnd_crud_collection_modify__unset(
@@ -117,7 +117,7 @@ enum_func_status \
xmysqlnd_crud_collection_find__set_offset(XMYSQLND_CRUD_COLLECT enum_func_status \
xmysqlnd_crud_collection_find__bind_value( XMYSQLND_CRUD_COLLECTION_OP__FIND* obj,
const util::string& name,
- zval* value);
+ const util::zvalue& value);
enum_func_status xmysqlnd_crud_collection_find__add_sort(XMYSQLND_CRUD_COLLECTION_OP__FIND \
* obj, const util::string_view& sort); enum_func_status \
xmysqlnd_crud_collection_find__add_grouping(XMYSQLND_CRUD_COLLECTION_OP__FIND * obj, \
const util::string_view& search_field); enum_func_status \
xmysqlnd_crud_collection_find__set_having(XMYSQLND_CRUD_COLLECTION_OP__FIND * obj, \
const util::string_view& criteria); @@ -162,7 +162,7 @@ public:
void add_placeholder(const util::string& placeholder);
void add_placeholders(const util::std_strings& placeholders);
util::std_strings get_placeholders() const;
- bool bind(const util::string& placeholder, zval* value);
+ bool bind(const util::string& placeholder, const util::zvalue& value);
bool finalize(google::protobuf::RepeatedPtrField< ::Mysqlx::Datatypes::Scalar >* \
mutable_args); Bound_values get_bound_values() const;
@@ -195,7 +195,7 @@ struct st_xmysqlnd_crud_collection_op__add
{
Mysqlx::Crud::Insert message;
- std::vector<zval> docs_zv;
+ util::zvalues docs;
st_xmysqlnd_crud_collection_op__add(
const util::string_view& schema,
@@ -206,15 +206,8 @@ struct st_xmysqlnd_crud_collection_op__add
message.set_data_model(Mysqlx::Crud::DOCUMENT);
}
- void add_document(zval* doc);
+ void add_document(const util::zvalue& doc);
void bind_docs();
-
- ~st_xmysqlnd_crud_collection_op__add() {
- for( auto& values_zv : docs_zv ) {
- zval_dtor(&values_zv);
- }
- docs_zv.clear();
- }
};
struct st_xmysqlnd_crud_collection_op__modify
@@ -255,7 +248,7 @@ struct st_xmysqlnd_crud_collection_op__remove
struct st_xmysqlnd_stmt_op__execute
{
- util::vector<util::zvalue> params;
+ util::zvalues params;
Mysqlx::Sql::StmtExecute message;
uint32_t ps_message_id;
diff --git a/xmysqlnd/xmysqlnd_crud_table_commands.cc \
b/xmysqlnd/xmysqlnd_crud_table_commands.cc index fdeefec6..bd17ad4a 100644
--- a/xmysqlnd/xmysqlnd_crud_table_commands.cc
+++ b/xmysqlnd/xmysqlnd_crud_table_commands.cc
@@ -43,7 +43,7 @@ enum_func_status
xmysqlnd_crud_table__bind_value(std::vector<std::string> & placeholders,
std::vector<Mysqlx::Datatypes::Scalar*> & bound_values,
const util::string_view& name,
- zval * value)
+ const util::zvalue& value)
{
DBG_ENTER("xmysqlnd_crud_table__bind_value");
DBG_INF_FMT("name=%*s", name.length(), name.data());
@@ -58,19 +58,18 @@ xmysqlnd_crud_table__bind_value(std::vector<std::string> & \
placeholders, }
Mysqlx::Datatypes::Any any;
- if (FAIL == zval2any(value, any)) {
- DBG_ERR("Error converting the zval to scalar");
- DBG_RETURN(FAIL);
- }
+ zval2any(value, any);
any2log(any);
- DBG_INF_FMT("offset=%u", index - begin);
- if (bound_values[index - begin]) {
- delete bound_values[index - begin];
+ const auto offset = index - begin;
+ DBG_INF_FMT("offset=%u", offset);
+ auto& bound_value = bound_values[offset];
+ if (bound_value) {
+ delete bound_value;
}
- bound_values[index - begin] = any.release_scalar();
+ bound_value = any.release_scalar();
- scalar2log(*bound_values[index - begin]);
+ scalar2log(*bound_value);
DBG_INF("PASS");
DBG_RETURN(PASS);
@@ -225,11 +224,7 @@ void st_xmysqlnd_crud_table_op__insert::bind_row(zval* \
values_zv, ::Mysqlx::Crud void \
st_xmysqlnd_crud_table_op__insert::bind_row_field(zval* value_zv, \
::Mysqlx::Crud::Insert_TypedRow* row) {
Mysqlx::Datatypes::Any any;
- if (FAIL == zval2any(value_zv, any)) {
- //TODO throw
-// DBG_ERR("Error converting the zval to scalar");
- //DBG_RETURN(FAIL);
- }
+ zval2any(value_zv, any);
any2log(any);
Mysqlx::Expr::Expr * field = row->add_field();
@@ -348,7 +343,7 @@ xmysqlnd_crud_table_delete__set_limit(XMYSQLND_CRUD_TABLE_OP__DELETE \
* obj, cons }
enum_func_status
-xmysqlnd_crud_table_delete__bind_value(XMYSQLND_CRUD_TABLE_OP__DELETE * obj, const \
util::string_view& name, zval * value) \
+xmysqlnd_crud_table_delete__bind_value(XMYSQLND_CRUD_TABLE_OP__DELETE * obj, const \
util::string_view& name, const util::zvalue& value) {
DBG_ENTER("xmysqlnd_crud_table_delete__bind_value");
if (obj->placeholders.size() && !obj->message.has_criteria()) {
@@ -456,7 +451,7 @@ xmysqlnd_crud_table_update__set_offset(XMYSQLND_CRUD_TABLE_OP__UPDATE \
* obj, con }
enum_func_status
-xmysqlnd_crud_table_update__bind_value(XMYSQLND_CRUD_TABLE_OP__UPDATE * obj, const \
util::string_view& name, zval * value) \
+xmysqlnd_crud_table_update__bind_value(XMYSQLND_CRUD_TABLE_OP__UPDATE * obj, const \
util::string_view& name, const util::zvalue& value) {
DBG_ENTER("xmysqlnd_crud_table_update__bind_value");
if (obj->placeholders.size() && !obj->message.has_criteria()) {
@@ -535,10 +530,7 @@ \
xmysqlnd_crud_table_update__add_operation(XMYSQLND_CRUD_TABLE_OP__UPDATE * obj, }
} else {
Mysqlx::Datatypes::Any any;
- if (FAIL == zval2any(value, any)) {
- DBG_ERR("Error converting the zval to scalar");
- DBG_RETURN(FAIL);
- }
+ zval2any(value, any);
any2log(any);
operation->mutable_value()->set_type(Mysqlx::Expr::Expr::LITERAL);
@@ -701,7 +693,7 @@ xmysqlnd_crud_table_select__set_offset(XMYSQLND_CRUD_TABLE_OP__SELECT \
* obj, con }
enum_func_status
-xmysqlnd_crud_table_select__bind_value(XMYSQLND_CRUD_TABLE_OP__SELECT * obj, const \
util::string_view& name, zval * value) \
+xmysqlnd_crud_table_select__bind_value(XMYSQLND_CRUD_TABLE_OP__SELECT * obj, const \
util::string_view& name, const util::zvalue& value) {
DBG_ENTER("xmysqlnd_crud_table_select__bind_value");
if (obj->placeholders.size() && !obj->message.has_criteria()) {
diff --git a/xmysqlnd/xmysqlnd_crud_table_commands.h \
b/xmysqlnd/xmysqlnd_crud_table_commands.h index f7027fdf..f16785a8 100644
--- a/xmysqlnd/xmysqlnd_crud_table_commands.h
+++ b/xmysqlnd/xmysqlnd_crud_table_commands.h
@@ -44,7 +44,7 @@ XMYSQLND_CRUD_TABLE_OP__DELETE * \
xmysqlnd_crud_table_delete__create( void \
xmysqlnd_crud_table_delete__destroy(XMYSQLND_CRUD_TABLE_OP__DELETE * obj); \
enum_func_status xmysqlnd_crud_table_delete__set_criteria(XMYSQLND_CRUD_TABLE_OP__DELETE \
* obj, const util::string_view& criteria); enum_func_status \
xmysqlnd_crud_table_delete__set_limit(XMYSQLND_CRUD_TABLE_OP__DELETE * obj, const \
size_t limit);
-enum_func_status xmysqlnd_crud_table_delete__bind_value(XMYSQLND_CRUD_TABLE_OP__DELETE \
* obj, const util::string_view& name, zval * value); +enum_func_status \
xmysqlnd_crud_table_delete__bind_value(XMYSQLND_CRUD_TABLE_OP__DELETE * obj, const \
util::string_view& name, const util::zvalue& value); enum_func_status \
xmysqlnd_crud_table_delete__add_orderby(XMYSQLND_CRUD_TABLE_OP__DELETE * obj, const \
util::string_view& orderby); enum_func_status \
xmysqlnd_crud_table_delete__finalize_bind(XMYSQLND_CRUD_TABLE_OP__DELETE * obj); \
struct st_xmysqlnd_pb_message_shell \
xmysqlnd_crud_table_delete__get_protobuf_message(XMYSQLND_CRUD_TABLE_OP__DELETE * \
obj); @@ -57,7 +57,7 @@ void \
xmysqlnd_crud_table_update__destroy(XMYSQLND_CRUD_TABLE_OP__UPDATE * obj); \
enum_func_status xmysqlnd_crud_table_update__set_criteria(XMYSQLND_CRUD_TABLE_OP__UPDATE \
* obj, const util::string_view& criteria); enum_func_status \
xmysqlnd_crud_table_update__set_limit(XMYSQLND_CRUD_TABLE_OP__UPDATE * obj, const \
size_t limit); enum_func_status \
xmysqlnd_crud_table_update__set_offset(XMYSQLND_CRUD_TABLE_OP__UPDATE * obj, const \
size_t offset);
-enum_func_status xmysqlnd_crud_table_update__bind_value(XMYSQLND_CRUD_TABLE_OP__UPDATE \
* obj, const util::string_view& name, zval * value); +enum_func_status \
xmysqlnd_crud_table_update__bind_value(XMYSQLND_CRUD_TABLE_OP__UPDATE * obj, const \
util::string_view& name, const util::zvalue& value); enum_func_status \
xmysqlnd_crud_table_update__add_orderby(XMYSQLND_CRUD_TABLE_OP__UPDATE * obj, const \
util::string_view& orderby);
//enum_func_status xmysqlnd_crud_table_update__unset(XMYSQLND_CRUD_TABLE_OP__UPDATE \
* obj, const util::string_view& path); @@ -77,7 +77,7 @@ void \
xmysqlnd_crud_table_select__destroy(XMYSQLND_CRUD_TABLE_OP__SELECT * obj); \
enum_func_status xmysqlnd_crud_table_select__set_criteria(XMYSQLND_CRUD_TABLE_OP__SELECT \
* obj, const util::string_view& criteria); enum_func_status \
xmysqlnd_crud_table_select__set_limit(XMYSQLND_CRUD_TABLE_OP__SELECT * obj, const \
size_t limit); enum_func_status \
xmysqlnd_crud_table_select__set_offset(XMYSQLND_CRUD_TABLE_OP__SELECT * obj, const \
size_t offset);
-enum_func_status xmysqlnd_crud_table_select__bind_value(XMYSQLND_CRUD_TABLE_OP__SELECT \
* obj, const util::string_view& name, zval * value); +enum_func_status \
xmysqlnd_crud_table_select__bind_value(XMYSQLND_CRUD_TABLE_OP__SELECT * obj, const \
util::string_view& name, const util::zvalue& value); enum_func_status \
xmysqlnd_crud_table_select__add_orderby(XMYSQLND_CRUD_TABLE_OP__SELECT * obj, const \
util::string_view& orderby); enum_func_status \
xmysqlnd_crud_table_select__add_grouping(XMYSQLND_CRUD_TABLE_OP__SELECT * obj, const \
util::string_view& search_field); enum_func_status \
xmysqlnd_crud_table_select__set_having(XMYSQLND_CRUD_TABLE_OP__SELECT * obj, const \
util::string_view& criteria); @@ -99,7 +99,7 @@ XMYSQLND_STMT_OP__EXECUTE * \
xmysqlnd_stmt_execute__create(const std::string_view void \
xmysqlnd_stmt_execute__destroy(XMYSQLND_STMT_OP__EXECUTE * obj); zend_bool \
xmysqlnd_stmt_execute__is_initialized(XMYSQLND_STMT_OP__EXECUTE * obj); \
enum_func_status xmysqlnd_stmt_execute__bind_one_param(XMYSQLND_STMT_OP__EXECUTE * \
obj, const zval * param_zv);
-enum_func_status xmysqlnd_stmt_execute__bind_value(XMYSQLND_STMT_OP__EXECUTE * obj, \
zval * value); +enum_func_status \
xmysqlnd_stmt_execute__bind_value(XMYSQLND_STMT_OP__EXECUTE * obj, const \
util::zvalue& value); enum_func_status \
xmysqlnd_stmt_execute__finalize_bind(XMYSQLND_STMT_OP__EXECUTE * obj);
struct st_xmysqlnd_pb_message_shell \
xmysqlnd_stmt_execute__get_protobuf_message(XMYSQLND_STMT_OP__EXECUTE \
* obj);
diff --git a/xmysqlnd/xmysqlnd_session.cc b/xmysqlnd/xmysqlnd_session.cc
index c1ad7170..6235112d 100644
--- a/xmysqlnd/xmysqlnd_session.cc
+++ b/xmysqlnd/xmysqlnd_session.cc
@@ -276,19 +276,11 @@ xmysqlnd_session_data::send_client_attributes()
final_any.set_allocated_obj(values);
final_any.set_type( Mysqlx::Datatypes::Any_Type::Any_Type_OBJECT );
- zval name;
- ZVAL_NULL(&name);
+ util::zvalue name("session_connect_attrs");
- zval value;
- ZVAL_NULL(&value);
-
- ZVAL_STRINGL(&name,
- "session_connect_attrs",
- strlen("session_connect_attrs"));
- capability_names[0] = &name;
-
- any2zval(final_any,&value);
- capability_values[0] = &value;
+ util::zvalue value = any2zval(final_any);
+ capability_names[0] = name.ptr();
+ capability_values[0] = value.ptr();
const st_xmysqlnd_on_error_bind on_error =
{ xmysqlnd_session_data_handler_on_error, (void*) this };
@@ -298,25 +290,15 @@ xmysqlnd_session_data::send_client_attributes()
capability_names,
capability_values) ) {
DBG_INF_FMT("Successfully submitted the connection attributes to the server.");
- zval zvalue;
- ZVAL_NULL(&zvalue);
+ util::zvalue zvalue;
caps_get.init_read(&caps_get, on_error);
ret = caps_get.read_response(&caps_get,
- &zvalue);
+ zvalue.ptr());
if( ret == PASS ) {
DBG_INF_FMT("Server response OK for the submitted connection attributes.");
} else {
DBG_ERR_FMT("Negative response from the server for the submitted connection \
attributes"); }
-
- zval_ptr_dtor(&zvalue);
- }
-
- zval_ptr_dtor(&name);
- zval_ptr_dtor(&value);
- } else{
- if( values ) {
- delete values;
}
}
}
@@ -994,26 +976,22 @@ enum_func_status try_setup_crypto_connection(
zval ** capability_names = (zval **) mnd_ecalloc(2, sizeof(zval*));
zval ** capability_values = (zval **) mnd_ecalloc(2, sizeof(zval*));
- zval name, value;
-
constexpr util::string_view cstr_name("tls");
+ util::zvalue name(cstr_name);
+ util::zvalue value(true);
- ZVAL_STRINGL(&name,cstr_name.data(),cstr_name.length());
-
- capability_names[0] = &name;
- ZVAL_TRUE(&value);
- capability_values[0] = &value;
+ capability_names[0] = name.ptr();
+ capability_values[0] = value.ptr();
if( PASS == caps_set.send_request(&caps_set,
1,
capability_names,
capability_values))
{
DBG_INF_FMT("Cap. send request with tls=true success, reading response..!");
- zval zvalue;
- ZVAL_NULL(&zvalue);
+ util::zvalue zvalue;
caps_get.init_read(&caps_get, on_error);
ret = caps_get.read_response(&caps_get,
- &zvalue);
+ zvalue.ptr());
if( ret == PASS ) {
DBG_INF_FMT("Cap. response OK, setting up TLS options.!");
php_stream_context * context = php_stream_context_alloc();
@@ -1037,12 +1015,9 @@ enum_func_status try_setup_crypto_connection(
DBG_ERR_FMT("Negative response from the server, not able to setup TLS.");
util::set_error_info(util::xdevapi_exception::Code::cannot_setup_tls, \
session->error_info); }
- zval_ptr_dtor(&zvalue);
}
//Cleanup
- zval_ptr_dtor(&name);
- zval_ptr_dtor(&value);
if( capability_names ) {
mnd_efree(capability_names);
}
@@ -1120,7 +1095,7 @@ xmysqlnd_session_data_handler_on_auth_continue(
}
enum_func_status
-xmysqlnd_session_data_set_client_id(void * context, const size_t id)
+xmysqlnd_session_data_set_client_id(void * context, const uint64_t id)
{
enum_func_status ret{FAIL};
xmysqlnd_session_data * session = (xmysqlnd_session_data *) context;
diff --git a/xmysqlnd/xmysqlnd_stmt.cc b/xmysqlnd/xmysqlnd_stmt.cc
index 05e89fcf..2b6ab85c 100644
--- a/xmysqlnd/xmysqlnd_stmt.cc
+++ b/xmysqlnd/xmysqlnd_stmt.cc
@@ -203,7 +203,7 @@ handler_on_error(void * context, const unsigned int code, const \
util::string_vie }
static const enum_hnd_func_status
-handler_on_exec_state_change(void * context, const enum \
xmysqlnd_execution_state_type type, const size_t value) \
+handler_on_exec_state_change(void * context, const enum \
xmysqlnd_execution_state_type type, const uint64_t value) {
st_xmysqlnd_stmt_bind_ctx* const ctx = (st_xmysqlnd_stmt_bind_ctx*) context;
enum_hnd_func_status ret{HND_AGAIN};
@@ -968,10 +968,7 @@ bool Prepare_stmt_data::bind_values(
std::vector<Mysqlx::Datatypes::Scalar*> converted_params;
for( unsigned int i{0}; i < params_allocated; ++i ) {
Mysqlx::Datatypes::Any arg;
- ret = zval2any(&(params[i]), arg);
- if( FAIL == ret ) {
- break;
- }
+ zval2any(&(params[i]), arg);
Mysqlx::Datatypes::Scalar * new_param = new Mysqlx::Datatypes::Scalar;
new_param->CopyFrom(arg.scalar());
converted_params.push_back( new_param );
diff --git a/xmysqlnd/xmysqlnd_wireprotocol.cc b/xmysqlnd/xmysqlnd_wireprotocol.cc
index 7e86bfe1..645550c2 100644
--- a/xmysqlnd/xmysqlnd_wireprotocol.cc
+++ b/xmysqlnd/xmysqlnd_wireprotocol.cc
@@ -87,11 +87,8 @@ xmysqlnd_inspect_changed_variable(const \
st_xmysqlnd_on_session_var_change_bind o DBG_INF_FMT("value is %s", has_value? \
"SET":"NOT SET"); if (has_param && has_value) {
const util::string_view name = message.param();
- zval zv;
- ZVAL_UNDEF(&zv);
- if (PASS == scalar2zval(message.value(), &zv)) {
- ret = on_session_var_change.handler(on_session_var_change.ctx, name, &zv);
- }
+ util::zvalue zv = scalar2zval(message.value());
+ ret = on_session_var_change.handler(on_session_var_change.ctx, name, zv);
}
DBG_RETURN(ret);
@@ -148,7 +145,7 @@ xmysqlnd_inspect_changed_exec_state(const \
st_xmysqlnd_on_execution_state_change_ ret = on_execution_state_change.handler(
on_execution_state_change.ctx,
state_type,
- static_cast<size_t>(scalar2uint(message.value(0))));
+ scalar2uint(message.value(0)));
}
#ifdef PHP_DEBUG
@@ -223,7 +220,7 @@ xmysqlnd_inspect_changed_state(const \
Mysqlx::Notice::SessionStateChanged & messa if (on_client_id.handler) {
const enum_func_status status = on_client_id.handler(
on_client_id.ctx,
- static_cast<size_t>(scalar2uint(message.value(0))));
+ scalar2uint(message.value(0)));
ret = (status == PASS)? HND_AGAIN : HND_FAIL;
}
break;
diff --git a/xmysqlnd/xmysqlnd_wireprotocol.h b/xmysqlnd/xmysqlnd_wireprotocol.h
index 4ef16b94..ce226ab9 100644
--- a/xmysqlnd/xmysqlnd_wireprotocol.h
+++ b/xmysqlnd/xmysqlnd_wireprotocol.h
@@ -32,6 +32,8 @@
namespace mysqlx {
+namespace util { class zvalue; }
+
namespace drv {
namespace compression { class Executor; }
@@ -70,7 +72,7 @@ struct st_xmysqlnd_on_error_bind
struct st_xmysqlnd_on_session_var_change_bind
{
- const enum_hnd_func_status (*handler)(void * context, const util::string_view& \
name, const zval * value); + const enum_hnd_func_status (*handler)(void * context, \
const util::string_view& name, const util::zvalue& value); void * ctx;
};
@@ -115,7 +117,7 @@ struct st_xmysqlnd_on_auth_continue_bind
struct st_xmysqlnd_on_client_id_bind
{
- enum_func_status (*handler)(void * context, const size_t id);
+ enum_func_status (*handler)(void * context, const uint64_t id);
void * ctx;
};
@@ -168,7 +170,7 @@ struct st_xmysqlnd_on_meta_field_bind
struct st_xmysqlnd_on_execution_state_change_bind
{
- const enum_hnd_func_status (*handler)(void * context, const enum \
xmysqlnd_execution_state_type type, const size_t value); + const enum_hnd_func_status \
(*handler)(void * context, const enum xmysqlnd_execution_state_type type, const \
uint64_t value); void * ctx;
};
diff --git a/xmysqlnd/xmysqlnd_zval2any.cc b/xmysqlnd/xmysqlnd_zval2any.cc
index c971d524..077cf527 100644
--- a/xmysqlnd/xmysqlnd_zval2any.cc
+++ b/xmysqlnd/xmysqlnd_zval2any.cc
@@ -36,235 +36,240 @@ using namespace Mysqlx::Datatypes;
namespace {
-void zval2object(zval* zv, Mysqlx::Datatypes::Any& any)
+void zval2array(const util::zvalue& zv, Mysqlx::Datatypes::Any& any)
{
+ assert(zv.is_array());
+ any.set_type(Any_Type_ARRAY);
+ for (const auto& value : zv.values()) {
+ Mysqlx::Datatypes::Any* new_value = any.mutable_array()->add_value();
+ zval2any(value, *new_value);
+ }
+}
+
+void zval2object(const util::zvalue& obj_zv, Mysqlx::Datatypes::Any& any)
+{
+ assert(obj_zv.is_object());
any.set_type(Any_Type_OBJECT);
Mysqlx::Datatypes::Object* obj{ any.mutable_obj() };
- HashTable* properties{ zend_std_get_properties(zv) };
- zend_string* property_name{nullptr};
- zval* property_value{nullptr};
- MYSQLX_HASH_FOREACH_STR_KEY_VAL(properties, property_name, property_value) {
- if (property_name && property_value) {
- Mysqlx::Datatypes::Object_ObjectField* field{ obj->add_fld() };
- field->set_key(ZSTR_VAL(property_name), ZSTR_LEN(property_name));
- Mysqlx::Datatypes::Any* field_value{ field->mutable_value() };
- zval2any(property_value, *field_value);
- }
- } ZEND_HASH_FOREACH_END();
+ for (const auto& [property_name, property_value] : obj_zv) {
+ Mysqlx::Datatypes::Object_ObjectField* field{ obj->add_fld() };
+
+ assert(property_name.is_string());
+ field->set_key(property_name.c_str(), property_name.length());
+
+ Mysqlx::Datatypes::Any* field_value{ field->mutable_value() };
+ zval2any(property_value, *field_value);
+ }
+}
+
+void zval2str(const util::zvalue& zv, Mysqlx::Datatypes::Any& any)
+{
+ assert(zv.is_string());
+ any.set_type(Any_Type_SCALAR);
+ any.mutable_scalar()->set_type(Scalar_Type_V_STRING);
+ any.mutable_scalar()->mutable_v_string()->set_value(zv.c_str(), zv.length());
+}
+
+void zval2other(const util::zvalue& zv, Mysqlx::Datatypes::Any& any)
+{
+ util::zvalue other = zv.clone();
+ convert_to_string(other.ptr());
+ if (other.is_string()) {
+ zval2str(other, any);
+ }
}
} // anonymous namespace
-enum_func_status
-zval2any(const zval * const zv, Mysqlx::Datatypes::Any & any)
+void
+zval2any(const util::zvalue& zv, Mysqlx::Datatypes::Any & any)
{
DBG_ENTER("zval2any");
- switch (Z_TYPE_P(zv)) {
- case IS_UNDEF:
+ switch (zv.type()) {
+ case util::zvalue::Type::Undefined:
DBG_INF("IS_UNDEF");
- /* fallthrough */
- case IS_NULL:
+ [[fallthrough]];
+
+ case util::zvalue::Type::Null:
DBG_INF("IS_NULL");
any.set_type(Any_Type_SCALAR);
any.mutable_scalar()->set_type(Scalar_Type_V_NULL);
break;
- case IS_FALSE:
+
+ case util::zvalue::Type::False:
DBG_INF("IS_FALSE");
any.set_type(Any_Type_SCALAR);
any.mutable_scalar()->set_type(Scalar_Type_V_BOOL);
any.mutable_scalar()->set_v_bool(false);
break;
- case IS_TRUE:
+
+ case util::zvalue::Type::True:
DBG_INF("IS_TRUE");
any.set_type(Any_Type_SCALAR);
any.mutable_scalar()->set_type(Scalar_Type_V_BOOL);
any.mutable_scalar()->set_v_bool(true);
break;
- case IS_LONG:
- DBG_INF_FMT("IS_LONG=%lu", Z_LVAL_P(zv));
+
+ case util::zvalue::Type::Long:
+ DBG_INF_FMT("IS_LONG=%lu", zv.to_zlong());
any.set_type(Any_Type_SCALAR);
any.mutable_scalar()->set_type(Scalar_Type_V_SINT);
- any.mutable_scalar()->set_v_signed_int(Z_LVAL_P(zv));
+ any.mutable_scalar()->set_v_signed_int(zv.to_zlong());
break;
- case IS_DOUBLE:
- DBG_INF_FMT("IS_DOUBLE=%f", Z_DVAL_P(zv));
+
+ case util::zvalue::Type::Double:
+ DBG_INF_FMT("IS_DOUBLE=%f", zv.to_double());
any.set_type(Any_Type_SCALAR);
any.mutable_scalar()->set_type(Scalar_Type_V_DOUBLE);
- any.mutable_scalar()->set_v_double(Z_DVAL_P(zv));
+ any.mutable_scalar()->set_v_double(zv.to_double());
break;
- case IS_STRING:
- DBG_INF_FMT("IS_STRING=%s", Z_STRVAL_P(zv));
- any.set_type(Any_Type_SCALAR);
- any.mutable_scalar()->set_type(Scalar_Type_V_STRING);
- any.mutable_scalar()->mutable_v_string()->set_value(Z_STRVAL_P(zv), \
Z_STRLEN_P(zv)); +
+ case util::zvalue::Type::String:
+ DBG_INF_FMT("IS_STRING=%s", zv.c_str());
+ zval2str(zv, any);
break;
- case IS_ARRAY: {
+
+ case util::zvalue::Type::Array:
DBG_INF("IS_ARRAY");
- zval* entry{nullptr};
- any.set_type(Any_Type_ARRAY);
- MYSQLX_HASH_FOREACH_VAL(Z_ARR_P(zv), entry) {
- DBG_INF("ENTRY");
- Mysqlx::Datatypes::Any entry_any;
- Mysqlx::Datatypes::Any * new_value = any.mutable_array()->add_value();
- ZVAL_DEREF(entry);
- zval2any(entry, entry_any);
- new_value->CopyFrom(entry_any); /* maybe Swap() as the internal value will be \
empty anyway */
- } ZEND_HASH_FOREACH_END();
+ zval2array(zv, any);
break;
- }
- case IS_OBJECT: {
+
+ case util::zvalue::Type::Object:
DBG_INF("IS_OBJECT");
- zval2object(const_cast<zval*>(zv), any);
+ zval2object(zv, any);
break;
- }
+
default:
- zval to_str;
- ZVAL_COPY(&to_str, zv);
- convert_to_string(&to_str);
+ zval2other(zv, any);
break;
}
- DBG_RETURN(PASS);
+ DBG_VOID_RETURN;
}
-enum_func_status
-zval2any(const util::zvalue& zv, Mysqlx::Datatypes::Any& any)
+namespace {
+
+template<typename SignedInt>
+util::zvalue sint2zval(SignedInt sint)
{
- return zval2any(zv.ptr(), any);
+#if SIZEOF_ZEND_LONG==4
+ if ((sint < ZEND_LONG_MIN) || (ZEND_LONG_MAX < sint)) {
+ return util::to_string(sint);
+ }
+#endif
+ return sint;
}
-enum_func_status
-scalar2zval(const Mysqlx::Datatypes::Scalar & scalar, zval * zv)
+template<typename UnsignedInt>
+util::zvalue uint2zval(UnsignedInt uint)
{
- DBG_ENTER("scalar2zval");
- zval_ptr_dtor(zv);
- ZVAL_UNDEF(zv);
- switch (scalar.type()) {
- case Scalar_Type_V_SINT:
#if SIZEOF_ZEND_LONG==4
- if (UNEXPECTED(scalar.v_signed_int() >= ZEND_LONG_MAX)) {
- char tmp[22];
- snprintf(tmp, sizeof(tmp), "%s", \
util::to_string(scalar.v_signed_int()).c_str());
- ZVAL_STRING(zv, tmp);
- } else
+ if (uint > ZEND_ULONG_MAX) {
+ return util::to_string(uint);
+ }
#endif
- {
- ZVAL_LONG(zv, static_cast<zend_long>(scalar.v_signed_int()));
- }
- break;
+ return uint;
+}
+
+} // anonymous namespace
+
+util::zvalue scalar2zval(const Mysqlx::Datatypes::Scalar& scalar)
+{
+ switch (scalar.type()) {
+ case Scalar_Type_V_SINT:
+ return sint2zval(scalar.v_signed_int());
+
case Scalar_Type_V_UINT:
-#if SIZEOF_ZEND_LONG==8
- if (scalar.v_unsigned_int() > 9223372036854775807L) {
-#elif SIZEOF_ZEND_LONG==4
- if (scalar.v_unsigned_int() > L64(2147483647)) {
-#endif
- char tmp[22];
- snprintf(tmp, sizeof(tmp), "%s", \
util::to_string(scalar.v_unsigned_int()).c_str());
- ZVAL_STRING(zv, tmp);
- } else {
- ZVAL_LONG(zv, static_cast<zend_long>(scalar.v_unsigned_int()));
- }
- break;
+ return uint2zval(scalar.v_unsigned_int());
+
case Scalar_Type_V_NULL:
- ZVAL_NULL(zv);
- break;
- case Scalar_Type_V_OCTETS:
- ZVAL_STRINGL(zv, scalar.v_octets().value().c_str(), \
scalar.v_octets().value().size() - 1);
- break;
+ return nullptr;
+
+ case Scalar_Type_V_OCTETS: {
+ const auto& octets = scalar.v_octets().value();
+ return util::zvalue(octets.c_str(), octets.size());
+ }
+
case Scalar_Type_V_DOUBLE:
- ZVAL_DOUBLE(zv, scalar.v_double());
- break;
+ return scalar.v_double();
+
case Scalar_Type_V_FLOAT:
- ZVAL_DOUBLE(zv, mysql_float_to_double(scalar.v_float(), -1)); // Fixlength, \
without meta maybe bad results (see mysqlnd)
- break;
+ return mysql_float_to_double(scalar.v_float(), -1); // Fixlength, without meta \
maybe bad results (see mysqlnd) +
case Scalar_Type_V_BOOL:
- ZVAL_BOOL(zv, scalar.v_bool());
- break;
- case Scalar_Type_V_STRING:
- ZVAL_STRINGL(zv, scalar.v_string().value().c_str(), \
scalar.v_string().value().size());
- break;
+ return scalar.v_bool();
+
+ case Scalar_Type_V_STRING: {
+ const auto& str = scalar.v_string().value();
+ return util::zvalue(str.c_str(), str.size());
+ }
+
default:
- php_error_docref(nullptr, E_WARNING, "Unknown new type %s (%d)", \
Mysqlx::Datatypes::Scalar::Type_Name(scalar.type()).c_str(), \
scalar.type());
- DBG_RETURN(FAIL);
- ;// assert
+ php_error_docref(
+ nullptr,
+ E_WARNING,
+ "Unknown new type %s (%d)",
+ Mysqlx::Datatypes::Scalar::Type_Name(scalar.type()).c_str(),
+ scalar.type());
+ return util::zvalue();
}
- DBG_RETURN(PASS);
}
-enum_func_status
-any2zval(const Mysqlx::Datatypes::Any & any, zval * zv)
+namespace {
+
+util::zvalue array2zval(const Mysqlx::Datatypes::Array& array)
{
- DBG_ENTER("any2zval");
- zval_ptr_dtor(zv);
- ZVAL_UNDEF(zv);
- switch (any.type()) {
- case Any_Type_SCALAR:
- scalar2zval(any.scalar(), zv);
- break;
- case Any_Type_OBJECT: {
- zval properties;
- ZVAL_UNDEF(&properties);
- const int fields_count{ any.obj().fld_size() };
- array_init_size(&properties, fields_count);
-
- for (int i{0}; i < fields_count; ++i) {
- zval entry;
- ZVAL_UNDEF(&entry);
- const auto& field{ any.obj().fld(i) };
- any2zval(field.value(), &entry);
- if (Z_REFCOUNTED(entry)) {
- Z_ADDREF(entry);
- }
- add_assoc_zval_ex(&properties, field.key().c_str(), field.key().size(), &entry);
- zend_hash_next_index_insert(Z_ARRVAL(properties), &entry);
- }
-
- object_init(zv);
- zend_merge_properties(zv, Z_ARRVAL(properties));
- zval_ptr_dtor(&properties);
- break;
- }
- case Any_Type_ARRAY:
- array_init_size(zv, any.array().value_size());
- for (int i{0}; i < any.array().value_size(); ++i) {
- zval entry;
- ZVAL_UNDEF(&entry);
- any2zval(any.array().value(i), &entry);
- zend_hash_next_index_insert(Z_ARRVAL_P(zv), &entry);
- }
- break;
- default:
-#ifndef PHP_DEBUG
- php_error_docref(nullptr, E_WARNING, "Unknown type %s . Please report to the \
developers.", Any::Type_Name(any.type()).c_str());
- DBG_RETURN(FAIL);
-#else
- DBG_INF_FMT("UNHANDLED TYPE");
- exit(0);
-#endif
+ util::zvalue result = util::zvalue::create_array(array.value_size());
+ for (int i{0}; i < array.value_size(); ++i) {
+ result.push_back(any2zval(array.value(i)));
}
- DBG_RETURN(PASS);
+ return result;
}
-enum_func_status any2zval(const Mysqlx::Datatypes::Any& any, util::zvalue& zv)
+util::zvalue object2zval(const Mysqlx::Datatypes::Object& obj)
{
- return any2zval(any, zv.ptr());
+ util::zvalue result = util::zvalue::create_object();
+ const int fields_count{ obj.fld_size() };
+ for (int i{0}; i < fields_count; ++i) {
+ const auto& field{ obj.fld(i) };
+ result.set_property(field.key(), any2zval(field.value()));
+ }
+ return result;
}
-util::zvalue any2zval(const Mysqlx::Datatypes::Any& any)
+} // anonymous namespace
+
+util::zvalue
+any2zval(const Mysqlx::Datatypes::Any& any)
{
- util::zvalue value;
- any2zval(any, value.ptr());
- return value;
+ switch (any.type()) {
+ case Any_Type_SCALAR:
+ return scalar2zval(any.scalar());
+
+ case Any_Type_OBJECT:
+ return object2zval(any.obj());
+
+ case Any_Type_ARRAY:
+ return array2zval(any.array());
+
+ default:
+ assert("UNHANDLED TYPE");
+ php_error_docref(
+ nullptr,
+ E_WARNING,
+ "Unknown type %s . Please report to the developers.",
+ Any::Type_Name(any.type()).c_str());
+ return util::zvalue();
+ }
}
-uint64_t
-scalar2uint(const Mysqlx::Datatypes::Scalar & scalar)
+uint64_t scalar2uint(const Mysqlx::Datatypes::Scalar& scalar)
{
- uint64_t ret{0};
DBG_ENTER("scalar2uint");
+ uint64_t ret{0};
DBG_INF_FMT("subtype=%s", Scalar::Type_Name(scalar.type()).c_str());
switch (scalar.type()) {
case Scalar_Type_V_SINT:
- ret = scalar.v_signed_int();
+ ret = static_cast<uint64_t>(scalar.v_signed_int());
break;
case Scalar_Type_V_UINT:
ret = scalar.v_unsigned_int();
@@ -273,7 +278,7 @@ scalar2uint(const Mysqlx::Datatypes::Scalar & scalar)
ret = 0;
break;
case Scalar_Type_V_OCTETS:
- ret = ZEND_STRTOL(scalar.v_octets().value().c_str(), nullptr, 10);
+ ret = std::stoull(scalar.v_octets().value());
break;
case Scalar_Type_V_DOUBLE:
ret = static_cast<uint64_t>(scalar.v_double());
@@ -282,148 +287,55 @@ scalar2uint(const Mysqlx::Datatypes::Scalar & scalar)
ret = static_cast<uint64_t>(mysql_float_to_double(scalar.v_float(), -1));
break;
case Scalar_Type_V_BOOL:
- ret = scalar.v_bool();
+ ret = scalar.v_bool() ? 1 : 0;
break;
case Scalar_Type_V_STRING:
- ret = ZEND_STRTOL(scalar.v_string().value().c_str(), nullptr, 10);
+ ret = std::stoull(scalar.v_string().value());
break;
default:
- ;// assert
+ assert(!"unexpected type");
}
DBG_RETURN(ret);
}
-int64_t
-scalar2sint(const Mysqlx::Datatypes::Scalar & scalar)
+util::string scalar2string(const Mysqlx::Datatypes::Scalar& scalar)
{
- int64_t ret{0};
- DBG_ENTER("scalar2uint");
+ util::zvalue value = scalar2zval(scalar);
+ return value.serialize(false);
+}
+
+void scalar2log(const Mysqlx::Datatypes::Scalar& scalar)
+{
+ DBG_ENTER("scalar2log");
DBG_INF_FMT("subtype=%s", Scalar::Type_Name(scalar.type()).c_str());
- switch (scalar.type()) {
- case Scalar_Type_V_SINT:
- ret = scalar.v_signed_int();
- break;
- case Scalar_Type_V_UINT:
- ret = scalar.v_unsigned_int();
- break;
- case Scalar_Type_V_NULL:
- ret = 0;
- break;
- case Scalar_Type_V_OCTETS:
- ret = ZEND_STRTOL(scalar.v_octets().value().c_str(), nullptr, 10);
- break;
- case Scalar_Type_V_DOUBLE:
- ret = static_cast<int64_t>(scalar.v_double());
- break;
- case Scalar_Type_V_FLOAT:
- ret = static_cast<int64_t>(mysql_float_to_double(scalar.v_float(), -1));
- break;
- case Scalar_Type_V_BOOL:
- ret = scalar.v_bool();
- break;
- case Scalar_Type_V_STRING:
- ret = ZEND_STRTOL(scalar.v_string().value().c_str(), nullptr, 10);
- break;
- default:
- ;// assert
+ const util::string& str = scalar2string(scalar);
+ DBG_INF_FMT("value=[%*s]", str.c_str(), str.length());
+ DBG_VOID_RETURN;
+}
+
+void repeated2log(
+ const google::protobuf::RepeatedPtrField< Mysqlx::Datatypes::Scalar >& repeated)
+{
+ for (auto scalar : repeated) {
+ scalar2log(scalar);
}
- DBG_RETURN(ret);
}
-util::string
-scalar2string(const Mysqlx::Datatypes::Scalar & scalar)
+void object2log(const Mysqlx::Datatypes::Object& obj)
{
- util::string ret;
- DBG_ENTER("scalar2string");
- DBG_INF_FMT("subtype=%s", Scalar::Type_Name(scalar.type()).c_str());
- switch (scalar.type()) {
- case Scalar_Type_V_SINT:
- ret = util::to_string(scalar.v_signed_int());
- break;
- case Scalar_Type_V_UINT:
- ret = util::to_string(scalar.v_unsigned_int());
- break;
- case Scalar_Type_V_NULL:
- break;
- case Scalar_Type_V_OCTETS:
- ret.assign(scalar.v_octets().value().c_str(), scalar.v_octets().value().size());
- break;
- case Scalar_Type_V_DOUBLE:
- ret = util::to_string(scalar.v_double());
- break;
- case Scalar_Type_V_FLOAT:
- ret = util::to_string(scalar.v_float());
- break;
- case Scalar_Type_V_BOOL:{
- ret = scalar.v_bool() ? "TRUE" : "FALSE";
- break;
- }
- case Scalar_Type_V_STRING:{
- ret.assign(scalar.v_string().value().c_str(), scalar.v_string().value().size());
- break;
- }
- default:
- ;// assert
+ for (int i{0}; i < obj.fld_size(); ++i) {
+ any2log(obj.fld(i).value());
}
- DBG_RETURN(ret);
}
-void
-scalar2log(const Mysqlx::Datatypes::Scalar & scalar)
+void array2log(const Mysqlx::Datatypes::Array& arr)
{
- DBG_ENTER("scalar2log");
- DBG_INF_FMT("subtype=%s", Scalar::Type_Name(scalar.type()).c_str());
- switch (scalar.type()) {
- case Scalar_Type_V_SINT:
-#if SIZEOF_ZEND_LONG==4
- if (UNEXPECTED(scalar.v_signed_int() >= ZEND_LONG_MAX)) {
- char tmp[22];
- snprintf(tmp, sizeof(tmp), "%s", \
util::to_string(scalar.v_unsigned_int()).c_str());
- DBG_INF_FMT("value=%s", tmp);
- } else
-#endif
- {
- DBG_INF_FMT("value=" MYSQLX_LLU_SPEC, scalar.v_signed_int());
- }
- break;
- case Scalar_Type_V_UINT:
-#if SIZEOF_ZEND_LONG==8
- if (scalar.v_unsigned_int() > 9223372036854775807L) {
-#elif SIZEOF_ZEND_LONG==4
- if (scalar.v_unsigned_int() > L64(2147483647)) {
-#endif
- char tmp[22];
- snprintf(tmp, sizeof(tmp), "%s", \
util::to_string(scalar.v_unsigned_int()).c_str());
- DBG_INF_FMT("value=%s", tmp);
- } else {
- DBG_INF_FMT("value=" MYSQLX_LLU_SPEC, scalar.v_unsigned_int());
- }
- break;
- case Scalar_Type_V_NULL:
- break;
- case Scalar_Type_V_OCTETS:
- DBG_INF_FMT("value=[%*s]", scalar.v_octets().value().size(), \
scalar.v_octets().value().c_str());
- break;
- case Scalar_Type_V_DOUBLE:
- DBG_INF_FMT("value=%f", scalar.v_double());
- break;
- case Scalar_Type_V_FLOAT:
- DBG_INF_FMT("value=%f", mysql_float_to_double(scalar.v_float(), -1));
- break;
- case Scalar_Type_V_BOOL:
- DBG_INF_FMT("value=%s", scalar.v_bool()? "TRUE":"FALSE");
- break;
- case Scalar_Type_V_STRING:
- DBG_INF_FMT("value=[%*s]", scalar.v_string().value().size(), \
scalar.v_string().value().c_str());
- break;
- default:
- ;// assert
+ for (int i{0}; i < arr.value_size(); ++i) {
+ any2log(arr.value(i));
}
- DBG_VOID_RETURN;
}
-void
-any2log(const Mysqlx::Datatypes::Any & any)
+void any2log(const Mysqlx::Datatypes::Any& any)
{
DBG_ENTER("any2log");
DBG_INF_FMT("type=%s", Any::Type_Name(any.type()).c_str());
@@ -431,37 +343,22 @@ any2log(const Mysqlx::Datatypes::Any & any)
case Any_Type_SCALAR:
scalar2log(any.scalar());
break;
- case Any_Type_OBJECT: {
- for (int i{0}; i < any.obj().fld_size(); ++i) {
- any2log(any.obj().fld(i).value());
- }
+
+ case Any_Type_OBJECT:
+ object2log(any.obj());
break;
- }
+
case Any_Type_ARRAY:
- for (int i{0}; i < any.array().value_size(); ++i) {
- any2log(any.array().value(i));
- }
+ array2log(any.array());
break;
+
default:
-#ifndef PHP_DEBUG
DBG_INF_FMT("Unknown type %s . Please report to the developers.", \
Any::Type_Name(any.type()).c_str());
- DBG_VOID_RETURN;
-#else
- DBG_INF_FMT("UNHANDLED TYPE");
- exit(0);
-#endif
+ assert(!"unhandled type");
}
DBG_VOID_RETURN;
}
-void repeated2log(
- const google::protobuf::RepeatedPtrField< Mysqlx::Datatypes::Scalar >& repeated)
-{
- for (auto scalar : repeated) {
- scalar2log(scalar);
- }
-}
-
} // namespace drv
} // namespace mysqlx
diff --git a/xmysqlnd/xmysqlnd_zval2any.h b/xmysqlnd/xmysqlnd_zval2any.h
index c3ad9d4f..d64fd095 100644
--- a/xmysqlnd/xmysqlnd_zval2any.h
+++ b/xmysqlnd/xmysqlnd_zval2any.h
@@ -29,21 +29,20 @@ namespace util { class zvalue; }
namespace drv {
-enum_func_status scalar2zval(const Mysqlx::Datatypes::Scalar & scalar, zval * zv);
-enum_func_status zval2any(const zval * const zv, Mysqlx::Datatypes::Any & any);
-enum_func_status zval2any(const util::zvalue& zv, Mysqlx::Datatypes::Any& any);
+void zval2any(const util::zvalue& zv, Mysqlx::Datatypes::Any& any);
+Mysqlx::Datatypes::Any zval2any(const util::zvalue& zv);
-enum_func_status any2zval(const Mysqlx::Datatypes::Any & any, zval * zv);
-enum_func_status any2zval(const Mysqlx::Datatypes::Any& any, util::zvalue& zv);
+util::zvalue scalar2zval(const Mysqlx::Datatypes::Scalar& scalar);
util::zvalue any2zval(const Mysqlx::Datatypes::Any& any);
-void any2log(const Mysqlx::Datatypes::Any & any);
-void scalar2log(const Mysqlx::Datatypes::Scalar & scalar);
+uint64_t scalar2uint(const Mysqlx::Datatypes::Scalar& scalar);
+
+util::string scalar2string(const Mysqlx::Datatypes::Scalar& scalar);
+
+void scalar2log(const Mysqlx::Datatypes::Scalar& scalar);
void repeated2log(
const google::protobuf::RepeatedPtrField< Mysqlx::Datatypes::Scalar >& repeated);
-uint64_t scalar2uint(const Mysqlx::Datatypes::Scalar & scalar);
-int64_t scalar2sint(const Mysqlx::Datatypes::Scalar & scalar);
-util::string scalar2string(const Mysqlx::Datatypes::Scalar & scalar);
+void any2log(const Mysqlx::Datatypes::Any& any);
} // namespace drv
--
PECL CVS Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic