mirror of
https://github.com/php/pecl-database-mysql_xdevapi.git
synced 2026-03-23 23:02:08 +01:00
225 lines
6.8 KiB
C++
225 lines
6.8 KiB
C++
/*
|
|
+----------------------------------------------------------------------+
|
|
| PHP Version 7 |
|
|
+----------------------------------------------------------------------+
|
|
| Copyright (c) The PHP Group |
|
|
+----------------------------------------------------------------------+
|
|
| This source file is subject to version 3.01 of the PHP license, |
|
|
| that is bundled with this package in the file LICENSE, and is |
|
|
| available through the world-wide-web at the following url: |
|
|
| http://www.php.net/license/3_01.txt |
|
|
| If you did not receive a copy of the PHP license and are unable to |
|
|
| obtain it through the world-wide-web, please send a note to |
|
|
| license@php.net so we can mail you a copy immediately. |
|
|
+----------------------------------------------------------------------+
|
|
| Authors: Andrey Hristov <andrey@php.net> |
|
|
+----------------------------------------------------------------------+
|
|
*/
|
|
#include "php_api.h"
|
|
#include "mysqlnd_api.h"
|
|
#include "xmysqlnd/xmysqlnd.h"
|
|
#include "xmysqlnd/xmysqlnd_session.h"
|
|
#include "php_mysqlx.h"
|
|
#include "mysqlx_class_properties.h"
|
|
|
|
namespace mysqlx {
|
|
|
|
namespace devapi {
|
|
|
|
using namespace drv;
|
|
|
|
namespace {
|
|
|
|
util::raw_zval *
|
|
mysqlx_property_get_forbidden(const st_mysqlx_object* /*not_used1*/, util::raw_zval* /*not_used2*/)
|
|
{
|
|
php_error_docref(nullptr, E_ERROR, "Write-only property");
|
|
return nullptr;
|
|
}
|
|
|
|
int
|
|
mysqlx_property_set_forbidden(st_mysqlx_object* /*not_used1*/, util::raw_zval* /*not_used2*/)
|
|
{
|
|
php_error_docref(nullptr, E_ERROR, "Read-only property");
|
|
return FAILURE;
|
|
}
|
|
|
|
void
|
|
mysqlx_add_property(HashTable * properties, const std::string_view& property_name, const func_mysqlx_property_get get, const func_mysqlx_property_set set)
|
|
{
|
|
DBG_ENTER("mysqlx_add_property");
|
|
DBG_INF_FMT("property=%s getter=%p setter=%p", property_name.data(), get, set);
|
|
|
|
st_mysqlx_property property;
|
|
property.name = zend_string_init(property_name.data(), property_name.length(), 1);
|
|
property.get_value = get? get : mysqlx_property_get_forbidden;
|
|
property.set_value = set? set : mysqlx_property_set_forbidden;
|
|
|
|
zend_hash_add_mem(properties, property.name, &property, sizeof(struct st_mysqlx_property));
|
|
|
|
zend_string_release(property.name);
|
|
DBG_VOID_RETURN;
|
|
}
|
|
|
|
util::zvalue member_to_zvalue(zend_string* member)
|
|
{
|
|
return util::zvalue(member);
|
|
}
|
|
|
|
util::zvalue member_to_zvalue(util::raw_zval* member)
|
|
{
|
|
if (Z_TYPE_P(member) != IS_STRING) {
|
|
util::raw_zval tmp_member;
|
|
util::zvalue::copy_from_to(member, &tmp_member);
|
|
convert_to_string(&tmp_member);
|
|
member = &tmp_member;
|
|
}
|
|
|
|
return util::zvalue(member);
|
|
}
|
|
|
|
} // anonymous namespace
|
|
|
|
void
|
|
mysqlx_add_properties(HashTable * ht, const st_mysqlx_property_entry* entries)
|
|
{
|
|
for (unsigned int i{0}; !entries[i].property_name.empty(); ++i) {
|
|
mysqlx_add_property(ht, entries[i].property_name, entries[i].get_value, entries[i].set_value);
|
|
}
|
|
}
|
|
|
|
util::raw_zval *
|
|
mysqlx_property_get_value(
|
|
#if PHP_VERSION_ID >= 80000 // PHP 8.0 or newer
|
|
zend_object* object, zend_string* member,
|
|
#else
|
|
util::raw_zval* object, util::raw_zval* member,
|
|
#endif
|
|
int type, void** cache_slot, util::raw_zval* rv)
|
|
{
|
|
DBG_ENTER("mysqlx_property_get_value");
|
|
const st_mysqlx_object* mysqlx_obj{ to_mysqlx_object(object) };
|
|
|
|
util::zvalue member_zval = member_to_zvalue(member);
|
|
DBG_INF_FMT("property=%s", member_zval.z_str());
|
|
|
|
const st_mysqlx_property* property{ nullptr };
|
|
if (mysqlx_obj->properties != nullptr) {
|
|
property = static_cast<const st_mysqlx_property*>(zend_hash_find_ptr(mysqlx_obj->properties, member_zval.z_str()));
|
|
}
|
|
|
|
util::raw_zval* retval{nullptr};
|
|
if (property) {
|
|
DBG_INF("internal property");
|
|
retval = property->get_value(mysqlx_obj, rv);
|
|
if (retval == nullptr) {
|
|
DBG_INF("uninitialized_zval");
|
|
retval = &EG(uninitialized_zval);
|
|
}
|
|
} else {
|
|
const zend_object_handlers * standard_handlers = zend_get_std_object_handlers();
|
|
DBG_INF("hash property");
|
|
retval = standard_handlers->read_property(object, member, type, cache_slot, rv);
|
|
}
|
|
|
|
DBG_RETURN(retval);
|
|
}
|
|
|
|
property_set_value_return_type
|
|
mysqlx_property_set_value(
|
|
#if PHP_VERSION_ID >= 80000 // PHP 8.0 or newer
|
|
zend_object* object, zend_string* member,
|
|
#else
|
|
util::raw_zval* object, util::raw_zval* member,
|
|
#endif
|
|
util::raw_zval* value, void** cache_slot)
|
|
{
|
|
DBG_ENTER("mysqlx_property_set_value");
|
|
st_mysqlx_object* mysqlx_obj{ to_mysqlx_object(object) };
|
|
|
|
util::zvalue member_zval = member_to_zvalue(member);
|
|
DBG_INF_FMT("property=%s", member_zval.z_str());
|
|
|
|
const st_mysqlx_property* property{nullptr};
|
|
if (mysqlx_obj->properties != nullptr) {
|
|
property = static_cast<const st_mysqlx_property*>(zend_hash_find_ptr(mysqlx_obj->properties, member_zval.z_str()));
|
|
}
|
|
|
|
if (property) {
|
|
property->set_value(mysqlx_obj, value);
|
|
} else {
|
|
const zend_object_handlers * standard_handlers = zend_get_std_object_handlers();
|
|
standard_handlers->write_property(object, member, value, cache_slot);
|
|
}
|
|
|
|
#if PHP_VERSION_ID >= 70400 // PHP 7.4 or newer
|
|
DBG_RETURN(value);
|
|
#else // PHP older than 7.4
|
|
DBG_VOID_RETURN;
|
|
#endif
|
|
}
|
|
|
|
int
|
|
mysqlx_object_has_property(
|
|
#if PHP_VERSION_ID >= 80000 // PHP 8.0 or newer
|
|
zend_object* object, zend_string* member,
|
|
#else
|
|
util::raw_zval* object, util::raw_zval* member,
|
|
#endif
|
|
int has_set_exists, void** cache_slot)
|
|
{
|
|
DBG_ENTER("mysqlx_object_has_property");
|
|
const st_mysqlx_object* mysqlx_obj{ to_mysqlx_object(object) };
|
|
util::zvalue member_zval = member_to_zvalue(member);
|
|
const st_mysqlx_property* property{nullptr};
|
|
int ret{0};
|
|
|
|
if ((property = static_cast<const st_mysqlx_property*>(zend_hash_find_ptr(mysqlx_obj->properties, member_zval.z_str()))) != nullptr) {
|
|
switch (has_set_exists) {
|
|
case 0:{
|
|
util::raw_zval rv, *value;
|
|
ZVAL_UNDEF(&rv);
|
|
value = mysqlx_property_get_value(object, member, BP_VAR_IS, cache_slot, &rv);
|
|
if (value != &EG(uninitialized_zval)) {
|
|
ret = Z_TYPE_P(value) != IS_NULL? 1 : 0;
|
|
zval_ptr_dtor(value);
|
|
}
|
|
DBG_INF("type 0");
|
|
break;
|
|
}
|
|
case 1: {
|
|
util::raw_zval rv, *value;
|
|
ZVAL_UNDEF(&rv);
|
|
value = mysqlx_property_get_value(object, member, BP_VAR_IS, cache_slot, &rv);
|
|
if (value != &EG(uninitialized_zval)) {
|
|
convert_to_boolean(value);
|
|
ret = Z_TYPE_P(value) == IS_TRUE ? 1 : 0;
|
|
}
|
|
DBG_INF("type 1");
|
|
break;
|
|
}
|
|
case 2:
|
|
ret = 1;
|
|
break;
|
|
default:
|
|
php_error_docref(nullptr, E_WARNING, "Invalid value for has_set_exists");
|
|
}
|
|
} else {
|
|
const zend_object_handlers * standard_handlers = zend_get_std_object_handlers();
|
|
DBG_INF("hash property");
|
|
ret = standard_handlers->has_property(object, member, has_set_exists, cache_slot);
|
|
}
|
|
|
|
DBG_RETURN(ret);
|
|
}
|
|
|
|
void
|
|
mysqlx_free_property_cb(util::raw_zval * el)
|
|
{
|
|
pefree(Z_PTR_P(el), 1);
|
|
}
|
|
|
|
} // namespace devapi
|
|
|
|
} // namespace mysqlx
|