wb-wqs885808 7095d778d1 patch228
2024-12-31 17:41:46 +08:00

657 lines
20 KiB
C

/*
Copyright (c) 2000, 2018, Oracle and/or its affiliates.
Copyright (c) 2009, 2019, MariaDB Corporation.
Copyright (c) 2021 OceanBase Technology Co.,Ltd.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
#include "ma_common.h"
#include "errmsg.h"
#include "ob_complex.h"
#include "ma_string.h"
static OB_HASH *global_hash = NULL;
static ob_rw_lock_t global_rwlock = OB_RW_INITIALIZER;
static void global_hash_free(void *record);
// #define UNUSED(x) ((void)x)
#define COMPLEX_TYPE_MAX_SQL_LENGTH 32 * 1024
#define COMPLEX_TYPE_MYSQL(M) (MYSQL_EXTENSION_PTR(M)->mysql)
#define COMPLEX_TYPE_HASH(M) (MYSQL_EXTENSION_PTR(M)->complex_type_hash)
#define COMPLEX_TYPE_USER_TYPES_SQL \
"SELECT "\
" 0 DEPTH, "\
" NULL PARENT_OWNER, "\
" NULL PARENT_TYPE, "\
" TYPE_NAME CHILD_TYPE, "\
" 0 ATTR_NO, "\
" SYS_CONTEXT('USERENV', 'CURRENT_USER') CHILD_TYPE_OWNER, "\
" A.TYPECODE ATTR_TYPE_CODE, "\
" NULL LENGTH, "\
" NULL NUMBER_PRECISION, "\
" NULL SCALE, "\
" NULL CHARACTER_SET_NAME "\
"FROM "\
" USER_TYPES A WHERE TYPE_NAME = '%s' "\
"UNION "\
"( "\
" WITH "\
" CTE_RESULT(PARENT_OWNER, PARENT_TYPE, CHILD_TYPE, ATTR_NO, CHILD_TYPE_OWNER, ATTR_TYPE_CODE, LENGTH, NUMBER_PRECISION, SCALE, CHARACTER_SET_NAME) "\
" AS ( "\
" SELECT "\
" SYS_CONTEXT('USERENV','CURRENT_USER') PARENT_OWNER, "\
" B.TYPE_NAME PARENT_TYPE, "\
" B.ELEM_TYPE_NAME CHILD_TYPE, "\
" 0 ATTR_NO, "\
" B.ELEM_TYPE_OWNER CHILD_TYPE_OWNER, "\
" NVL(A.TYPECODE, B.ELEM_TYPE_NAME) AS ATTR_TYPE_CODE, "\
" B.LENGTH LENGTH, "\
" B.NUMBER_PRECISION NUMBER_PRECISION, "\
" B.SCALE SCALE, "\
" B.CHARACTER_SET_NAME CHARACTER_SET_NAME "\
" FROM "\
" USER_COLL_TYPES B LEFT JOIN USER_TYPES A ON A.TYPE_NAME = B.ELEM_TYPE_NAME "\
" UNION "\
" SELECT "\
" SYS_CONTEXT('USERENV','CURRENT_USER') PARENT_OWNER, "\
" B.TYPE_NAME PARENT_TYPE, "\
" B.ATTR_TYPE_NAME CHILD_TYPE, "\
" B.ATTR_NO ATTR_NO, "\
" B.ATTR_TYPE_OWNER CHILD_TYPE_OWNER, "\
" NVL(A.TYPECODE, B.ATTR_TYPE_NAME) AS ATTR_TYPE_CODE, "\
" B.LENGTH LENGTH, "\
" B.NUMBER_PRECISION NUMBER_PRECISION, "\
" B.SCALE SCALE, "\
" B.CHARACTER_SET_NAME CHARACTER_SET_NAME "\
" FROM USER_TYPE_ATTRS B LEFT JOIN USER_TYPES A ON B.ATTR_TYPE_NAME = A.TYPE_NAME ORDER BY ATTR_NO "\
" ) , "\
" CTE(DEPTH, PARENT_OWNER, PARENT_TYPE, CHILD_TYPE, ATTR_NO, CHILD_TYPE_OWNER, ATTR_TYPE_CODE, LENGTH, NUMBER_PRECISION, SCALE, CHARACTER_SET_NAME) "\
" AS ( "\
" SELECT "\
" 1 DEPTH, "\
" PARENT_OWNER, "\
" PARENT_TYPE, "\
" CHILD_TYPE, "\
" ATTR_NO, "\
" CHILD_TYPE_OWNER, "\
" ATTR_TYPE_CODE, "\
" LENGTH, "\
" NUMBER_PRECISION, "\
" SCALE, CHARACTER_SET_NAME "\
" FROM CTE_RESULT WHERE PARENT_TYPE = '%s' "\
" UNION ALL "\
" SELECT "\
" DEPTH + 1 DEPTH, "\
" CTE_RESULT.PARENT_OWNER, "\
" CTE_RESULT.PARENT_TYPE, "\
" CTE_RESULT.CHILD_TYPE, "\
" CTE_RESULT.ATTR_NO, "\
" CTE_RESULT.CHILD_TYPE_OWNER, "\
" CTE_RESULT.ATTR_TYPE_CODE, "\
" CTE_RESULT.LENGTH, "\
" CTE_RESULT.NUMBER_PRECISION, "\
" CTE_RESULT.SCALE, "\
" CTE_RESULT.CHARACTER_SET_NAME "\
" FROM CTE_RESULT INNER JOIN CTE ON CTE_RESULT.PARENT_TYPE = CTE.CHILD_TYPE "\
" ) "\
" SELECT * FROM CTE "\
"); "\
#define COMPLEX_TYPE_ALL_TYPES_SQL \
"SELECT "\
" 0 DEPTH, "\
" NULL PRAENT_OWNER, "\
" NULL PARENT_TYPE, "\
" to_char(TYPE_NAME) CHILD_TYPE, "\
" 0 ATTR_NO, "\
" OWNER CHILD_TYPE_OWNER, "\
" A.TYPECODE ATTR_TYPE_CODE, "\
" NULL LENGTH, "\
" NULL NUMBER_PRECISION, "\
" NULL SCALE, "\
" NULL CHARACTER_SET_NAME "\
" FROM "\
" ALL_TYPES A WHERE TYPE_NAME = '%s' AND OWNER = '%s' "\
" UNION "\
" ( "\
" WITH "\
" CTE_RESULT(PARENT_OWNER, PARENT_TYPE, CHILD_TYPE, ATTR_NO, CHILD_TYPE_OWNER, ATTR_TYPE_CODE, LENGTH, NUMBER_PRECISION, SCALE, CHARACTER_SET_NAME) "\
" AS ( "\
" SELECT "\
" B.OWNER PARENT_OWNER, "\
" B.TYPE_NAME PARENT_TYPE, "\
" B.ELEM_TYPE_NAME CHILD_TYPE, "\
" 0 ATTR_NO, "\
" B.ELEM_TYPE_OWNER CHILD_TYPE_OWNER, "\
" NVL(A.TYPECODE, B.ELEM_TYPE_NAME) AS ATTR_TYPE_CODE, "\
" B.LENGTH LENGTH, "\
" B.NUMBER_PRECISION NUMBER_PRECISION, "\
" B.SCALE SCALE, "\
" B.CHARACTER_SET_NAME CHARACTER_SET_NAME "\
" FROM "\
" ALL_COLL_TYPES B LEFT JOIN ALL_TYPES A ON A.TYPE_NAME = B.ELEM_TYPE_NAME AND A.OWNER = B.ELEM_TYPE_OWNER "\
" UNION "\
" SELECT "\
" B.OWNER PARENT_OWNER, "\
" B.TYPE_NAME PARENT_TYPE, "\
" B.ATTR_TYPE_NAME CHILD_TYPE, "\
" B.ATTR_NO ATTR_NO, "\
" B.ATTR_TYPE_OWNER CHILD_TYPE_OWNER, "\
" NVL(A.TYPECODE, B.ATTR_TYPE_NAME) AS ATTR_TYPE_CODE, "\
" B.LENGTH LENGTH, "\
" B.NUMBER_PRECISION NUMBER_PRECISION, "\
" B.SCALE SCALE, "\
" B.CHARACTER_SET_NAME CHARACTER_SET_NAME "\
" FROM ALL_TYPE_ATTRS B LEFT JOIN ALL_TYPES A ON A.TYPE_NAME = B.ATTR_TYPE_NAME AND A.OWNER = B.ATTR_TYPE_OWNER ORDER BY ATTR_NO "\
" ) , "\
" CTE(DEPTH, PARENT_OWNER, PARENT_TYPE, CHILD_TYPE, ATTR_NO, CHILD_TYPE_OWNER, ATTR_TYPE_CODE, LENGTH, NUMBER_PRECISION, SCALE, CHARACTER_SET_NAME) "\
" AS ( "\
" SELECT "\
" 1 DEPTH, "\
" PARENT_OWNER, "\
" PARENT_TYPE, "\
" CHILD_TYPE, "\
" ATTR_NO, "\
" CHILD_TYPE_OWNER, "\
" ATTR_TYPE_CODE, "\
" LENGTH, "\
" NUMBER_PRECISION, "\
" SCALE, CHARACTER_SET_NAME "\
" FROM CTE_RESULT WHERE PARENT_TYPE = '%s' AND PARENT_OWNER = '%s' "\
" UNION ALL "\
" SELECT "\
" DEPTH + 1 DEPTH, "\
" CTE_RESULT.PARENT_OWNER, "\
" CTE_RESULT.PARENT_TYPE, "\
" CTE_RESULT.CHILD_TYPE, "\
" CTE_RESULT.ATTR_NO, "\
" CTE_RESULT.CHILD_TYPE_OWNER, "\
" CTE_RESULT.ATTR_TYPE_CODE, "\
" CTE_RESULT.LENGTH, "\
" CTE_RESULT.NUMBER_PRECISION, "\
" CTE_RESULT.SCALE, "\
" CTE_RESULT.CHARACTER_SET_NAME "\
" FROM CTE_RESULT INNER JOIN CTE ON CTE_RESULT.PARENT_TYPE = CTE.CHILD_TYPE AND CTE_RESULT.PARENT_OWNER = CTE.CHILD_TYPE_OWNER "\
" ) "\
" SELECT * FROM CTE "\
"); "\
#define DEPTH_INDEX 0
#define PARENT_TYPE_INDEX 2
#define CHILD_TYPE_INDEX 3
#define ATTR_NO_INDEX 4
#define CHILD_OWNER_INDEX 5
#define ATTR_TYPE_INDEX 6
static enum_types convert_type(const char *type) {
if (!strcmp(type, "COLLECTION")) {
return TYPE_COLLECTION;
} else if (!strcmp(type, "OBJECT")) {
return TYPE_OBJECT;
} else if (!strcmp(type, "NUMBER")) {
return TYPE_NUMBER;
} else if (!strcmp(type, "VARCHAR2")) {
return TYPE_VARCHAR2;
} else if (!strcmp(type, "CHAR")) {
return TYPE_CHAR;
} else if (!strcmp(type, "DATE")) {
return TYPE_DATE;
} else if (!strcmp(type, "RAW")) {
return TYPE_RAW;
} else if (!strcmp(type, "NVARCHAR2")) {
return TYPE_NVARCHAR2;
} else if (!strcmp(type, "FLOAT")) {
return TYPE_OB_NUMBER_FLOAT;
} else if (!strncmp(type, "INTERVAL YEAR", 13)) {
return TYPE_OB_INTERVAL_YM;
} else if (!strncmp(type, "INTERVAL DAY", 12)) {
return TYPE_OB_INTERVAL_DS;
} else if (!strncmp(type, "TIMESTAMP", 9)) {
if (strstr(type, "WITH TIME ZONE")) {
return TYPE_OB_TIMESTAMP_WITH_TIME_ZONE;
} else if (strstr(type, "WITH LOCAL TIME ZONE")) {
return TYPE_OB_TIMESTAMP_WITH_LOCAL_TIME_ZONE;
} else {
return TYPE_OB_TIMESTAMP_NANO;
}
} else if (!strcmp(type, "BINARY_FLOAT")) {
return TYPE_FLOAT;
} else if (!strcmp(type, "BINARY_DOUBLE")) {
return TYPE_DOUBLE;
} else {
return TYPE_MAX;
}
}
static int STDCALL
parser_complex(MYSQL_RES *result, OB_HASH *hash)
{
MYSQL_ROW cur;
COMPLEX_TYPE *complex_type;
unsigned char *parent_name;
COMPLEX_TYPE *parent;
while ((cur = mysql_fetch_row(result))) {
unsigned int type_size;
enum_types type = convert_type(cur[ATTR_TYPE_INDEX]);
if (TYPE_OBJECT == type || TYPE_COLLECTION == type) {
complex_type = (COMPLEX_TYPE *) hash_search(hash, (unsigned char*)cur[CHILD_TYPE_INDEX], strlen(cur[CHILD_TYPE_INDEX]));
if (!complex_type) {
type_size = TYPE_COLLECTION == type ? sizeof(COMPLEX_TYPE_COLLECTION) : sizeof(COMPLEX_TYPE_OBJECT);
complex_type = (COMPLEX_TYPE *) calloc(1, type_size);
if (!complex_type) {
return (1);
}
complex_type->is_valid = 0;
complex_type->type = type;
if (TYPE_OBJECT == complex_type->type) {
((COMPLEX_TYPE_OBJECT *)complex_type)->attr_no = 0;
}
/* name 被初始化成了 0, 所以不需要拷贝最后的 NULL 结束符 */
memcpy(complex_type->type_name, cur[CHILD_TYPE_INDEX], strlen(cur[CHILD_TYPE_INDEX]));
memcpy(complex_type->owner_name, cur[CHILD_OWNER_INDEX], strlen(cur[CHILD_OWNER_INDEX]));
if (hash_insert(hash, (unsigned char *)complex_type)) {
return (1);
}
} else {
//ReInit node's info in the query
complex_type->is_valid = 0;
if (TYPE_OBJECT == complex_type->type) {
((COMPLEX_TYPE_OBJECT *)complex_type)->attr_no = 0;
}
}
}
if (atoi(cur[DEPTH_INDEX]) != 0) {
parent_name = (unsigned char *)cur[PARENT_TYPE_INDEX];
parent = (COMPLEX_TYPE *) hash_search(hash, parent_name, strlen((char *)parent_name));
if (parent == NULL) {
return (1);
}
if (TYPE_OBJECT == parent->type &&
((COMPLEX_TYPE_OBJECT *)parent)->attr_no < strtoul(cur[ATTR_NO_INDEX], NULL, 10)) {
((COMPLEX_TYPE_OBJECT *)parent)->attr_no = strtoul(cur[ATTR_NO_INDEX], NULL, 10);
}
}
}
result->data_cursor = result->data->data;
while ((cur = mysql_fetch_row(result))) {
enum_types child_type;
COMPLEX_TYPE_OBJECT *parent_object;
COMPLEX_TYPE_COLLECTION *parent_collection;
if (atoi(cur[DEPTH_INDEX]) != 0) {
parent_name = (unsigned char *)cur[PARENT_TYPE_INDEX];
parent = (COMPLEX_TYPE *) hash_search(hash, parent_name, strlen((char *)parent_name));
if (parent == NULL) {
return (1);
}
child_type = convert_type(cur[ATTR_TYPE_INDEX]);
if (TYPE_OBJECT == parent->type) {
parent_object = (COMPLEX_TYPE_OBJECT *)parent;
if (parent_object->child == NULL) {
parent_object->child = (CHILD_TYPE *) calloc(1, parent_object->attr_no * sizeof(CHILD_TYPE));
if (parent_object->child == NULL) {
return (1);
}
}
parent_object->child[atoi(cur[ATTR_NO_INDEX]) - 1].type = child_type;
if (TYPE_COLLECTION == child_type || TYPE_OBJECT == child_type) {
complex_type = (COMPLEX_TYPE *)hash_search(hash,
(unsigned char *)cur[CHILD_TYPE_INDEX], strlen(cur[CHILD_TYPE_INDEX]));
if (complex_type == NULL) {
return (1);
}
parent_object->child[atoi(cur[ATTR_NO_INDEX]) - 1].object = complex_type;
}
parent_object->init_attr_no++;
if (parent_object->init_attr_no == parent_object->attr_no) {
parent->is_valid = 1;
}
} else if (TYPE_COLLECTION == parent->type) {
parent_collection = (COMPLEX_TYPE_COLLECTION *)parent;
parent_collection->child.type = child_type;
if (TYPE_COLLECTION == child_type || TYPE_OBJECT == child_type) {
complex_type = (COMPLEX_TYPE *)hash_search(hash,
(unsigned char *)cur[CHILD_TYPE_INDEX], strlen(cur[CHILD_TYPE_INDEX]));
if (complex_type == NULL) {
return (1);
}
parent_collection->child.object = complex_type;
}
parent->is_valid = 1;
}
}
}
return (0);
}
static int STDCALL
get_type_from_server(MYSQL *mysql, unsigned char *owner_name, unsigned char *type_name, COMPLEX_HASH *complex_hash)
{
int retval;
MYSQL_RES *result;
char sql[COMPLEX_TYPE_MAX_SQL_LENGTH] = {'\0'};
if (NULL != owner_name) {
snprintf(sql, COMPLEX_TYPE_MAX_SQL_LENGTH, COMPLEX_TYPE_ALL_TYPES_SQL, type_name, owner_name, type_name, owner_name);
} else {
/* 如果 owner 为空, 先从 user_types 视图中获取 */
snprintf(sql, COMPLEX_TYPE_MAX_SQL_LENGTH, COMPLEX_TYPE_USER_TYPES_SQL, type_name, type_name);
}
if (mysql_real_query(mysql, sql, strlen(sql))) {
return (1);
}
if (!(result = mysql_store_result(mysql))) {
return (1);
/* 如果 user_types 视图中没有该 type, 在再从 all_types 视图中获取 */
} else if (0 == mysql_num_rows(result) && NULL == owner_name) {
mysql_free_result(result);
snprintf(sql, COMPLEX_TYPE_MAX_SQL_LENGTH, COMPLEX_TYPE_ALL_TYPES_SQL, type_name, "SYS", type_name, "SYS");
if (mysql_real_query(mysql, sql, strlen(sql))) {
return (1);
}
if (!(result = mysql_store_result(mysql))) {
return (1);
}
}
ob_rw_wrlock(&(complex_hash->rwlock));
retval = parser_complex(result, complex_hash->hash);
ob_rw_unlock(&(complex_hash->rwlock));
mysql_free_result(result);
return (retval);
}
static int STDCALL
complex_mysql_init(MYSQL *mysql, MYSQL **complex_mysql)
{
int ret = 0;
*complex_mysql = NULL;
if (!(*complex_mysql = mysql_init(*complex_mysql))) {
ret = 1;
} else if (!mysql_real_connect(*complex_mysql, mysql->host, mysql->user, mysql->passwd,
mysql->db, mysql->port, mysql->unix_socket, 0))
{
ret = 1;
}
if (ret != 0 && *complex_mysql != NULL) {
mysql_close(*complex_mysql);
*complex_mysql = NULL;
}
return (ret);
}
static void complex_hash_free(void *record)
{
COMPLEX_TYPE *header = (COMPLEX_TYPE *)record;
if (header->type == TYPE_OBJECT) {
free(((COMPLEX_TYPE_OBJECT *)header)->child);
}
free(header);
}
static unsigned char *complex_get_hash_key(const unsigned char *record, uint *length,
my_bool not_used)
{
COMPLEX_TYPE *type = (COMPLEX_TYPE *)record;
*length= strlen((char *)type->type_name);
UNUSED(not_used);
return type->type_name;
}
static int STDCALL
complex_hash_init(MYSQL *mysql, unsigned char *hash_key, COMPLEX_HASH **complex_hash)
{
int ret = 0;
*complex_hash = NULL;
if (!(*complex_hash = calloc(1, sizeof(COMPLEX_HASH)))) {
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
ret = 1;
} else if(ob_rw_init(&((*complex_hash)->rwlock))) {
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
ret = 1;
} else if (!((*complex_hash)->hash = calloc(1, sizeof(OB_HASH)))) {
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
ret = 1;
} else if (hash_init((*complex_hash)->hash, 0, 0, 0, (hash_get_key) complex_get_hash_key,
complex_hash_free, HASH_CASE_INSENSITIVE)) {
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
ret = 1;
} else if (!((*complex_hash)->hash_key = calloc(1, strlen((char *)hash_key) + 1))) {
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
ret = 1;
} else {
//memset((*complex_hash)->hash_key, 0, strlen((char *)hash_key) + 1);
memcpy((*complex_hash)->hash_key, hash_key, strlen((char *)hash_key));
(*complex_hash)->hash_key[strlen((char *)hash_key)] = '\0';
if (hash_insert(global_hash, (unsigned char *)(*complex_hash))) {
SET_CLIENT_ERROR(mysql, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, 0);
ret = 1;
}
}
if (ret && *complex_hash != NULL) {
global_hash_free((void *)(*complex_hash));
*complex_hash = NULL;
}
return (ret);
}
static void global_hash_free(void *record)
{
COMPLEX_HASH *complex_hash = (COMPLEX_HASH *)record;
if (NULL != complex_hash->hash_key) {
free(complex_hash->hash_key);
}
if (NULL != complex_hash->hash) {
hash_free(complex_hash->hash);
free(complex_hash->hash);
}
ob_rw_destroy(&(complex_hash->rwlock));
free(complex_hash);
}
static unsigned char *global_get_hash_key(const unsigned char *record, uint *length,
my_bool not_used)
{
COMPLEX_HASH *complex_hash = (COMPLEX_HASH *)record;
*length= strlen((char *)complex_hash->hash_key);
UNUSED(not_used);
return complex_hash->hash_key;
}
static int STDCALL
global_hash_init(MYSQL *mysql)
{
if (!(global_hash = calloc(1, sizeof(OB_HASH)))) {
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
return 1;
} else if (hash_init(global_hash, 0, 0, 0, (hash_get_key) global_get_hash_key,
global_hash_free, HASH_CASE_INSENSITIVE)) {
hash_free(global_hash);
free(global_hash);
SET_CLIENT_ERROR(mysql, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, 0);
return 1;
}
return 0;
}
static const char digits[]= "0123456789abcdef";
char *ma_safe_utoa(int base, ulonglong val, char *buf)
{
*buf--= 0;
do {
*buf--= digits[val % base];
} while ((val /= base) != 0);
return buf + 1;
}
static int STDCALL
get_complex_hash(MYSQL *mysql, unsigned char *hash_key, int buffer_len, COMPLEX_HASH **complex_hash)
{
int ret = 0;
*complex_hash = NULL;
if (NULL == global_hash) {
ob_rw_wrlock(&global_rwlock);
if (NULL == global_hash && global_hash_init(mysql)) {
ret = 1;
}
ob_rw_unlock(&global_rwlock);
}
if (ret == 0) {
unsigned int hash_length = 0;
char port[10] = {'\0'};
char *port_ptr = NULL;
port_ptr = ma_safe_utoa(10, mysql->port, &port[sizeof(port)-1]);
if (strlen(mysql->host) + strlen(port_ptr) + strlen(mysql->user) + 1 >= (size_t)buffer_len) {
ret = 1;
} else if ((NULL != mysql->db) && (strlen(mysql->host) + strlen(port_ptr) + strlen(mysql->user) +
strlen(mysql->db) + 1 >= (size_t)buffer_len)) {
ret = 1;
} else {
memcpy(hash_key + hash_length, mysql->host, strlen(mysql->host));
hash_length += strlen(mysql->host);
memcpy(hash_key + hash_length, port_ptr, strlen(port_ptr));
hash_length += strlen(port_ptr);
memcpy(hash_key + hash_length, mysql->user, strlen(mysql->user));
hash_length += strlen(mysql->user);
if (NULL != mysql->db) {
memcpy(hash_key + hash_length, mysql->db, strlen(mysql->db));
hash_length += strlen(mysql->db);
}
hash_key[hash_length] = '\0';
ob_rw_rdlock(&global_rwlock);
*complex_hash = (COMPLEX_HASH *)hash_search(global_hash, hash_key, strlen((char *)hash_key));
ob_rw_unlock(&global_rwlock);
if (NULL == *complex_hash) {
ob_rw_wrlock(&global_rwlock);
if (NULL == *complex_hash) {
if (complex_hash_init(mysql, hash_key, complex_hash)) {
ret = 1;
}
}
ob_rw_unlock(&global_rwlock);
}
}
}
return (ret);
}
COMPLEX_TYPE* STDCALL
get_complex_type(MYSQL *mysql, unsigned char *owner_name, unsigned char *type_name)
{
COMPLEX_TYPE *type = NULL;
COMPLEX_HASH *complex_hash = NULL;
MYSQL *complex_mysql = NULL;
unsigned char hash_key[200] = {'\0'};
if (get_complex_hash(mysql, hash_key, 200, &complex_hash)) {
} else {
ob_rw_rdlock(&(complex_hash->rwlock));
type = (COMPLEX_TYPE *)hash_search(complex_hash->hash, type_name, strlen((char *)type_name));
ob_rw_unlock(&(complex_hash->rwlock));
if (NULL == type || type->is_valid != 1) {
if (complex_mysql_init(mysql, &complex_mysql)) {
} else if (get_type_from_server(complex_mysql, owner_name, type_name, complex_hash)) {
} else {
ob_rw_rdlock(&(complex_hash->rwlock));
type = (COMPLEX_TYPE *)hash_search(complex_hash->hash, type_name, strlen((char *)type_name));
ob_rw_unlock(&(complex_hash->rwlock));
}
}
}
if (complex_mysql != NULL) {
mysql_close(complex_mysql);
complex_mysql = NULL;
}
if (type && type->is_valid != 1) {
return (NULL);
}
return (type);
}
COMPLEX_TYPE* STDCALL
get_complex_type_with_local(MYSQL *mysql, unsigned char *type_name)
{
COMPLEX_TYPE *type = NULL;
COMPLEX_HASH *complex_hash = NULL;
unsigned char hash_key[200] = {'\0'};
memset(hash_key, 0, 200);
if (get_complex_hash(mysql, hash_key, 200, &complex_hash)) {
} else {
ob_rw_rdlock(&(complex_hash->rwlock));
type = (COMPLEX_TYPE *)hash_search(complex_hash->hash, type_name, strlen((char *)type_name));
ob_rw_unlock(&(complex_hash->rwlock));
}
if (type && type->is_valid != 1) {
return (NULL);
}
return (type);
}