You've already forked mariadb-connector-c
mirror of
https://github.com/mariadb-corporation/mariadb-connector-c.git
synced 2025-08-08 14:02:17 +03:00
MDEV-17832 Protocol: extensions for Pluggable types and JSON, GEOMETRY
This commit is contained in:
@@ -113,3 +113,9 @@ struct st_mariadb_extension {
|
||||
(a)->options.extension->key : 0
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct st_mariadb_field_extension
|
||||
{
|
||||
MARIADB_CONST_STRING metadata[MARIADB_FIELD_ATTR_LAST+1]; /* 10.5 */
|
||||
} MA_FIELD_EXTENSION;
|
||||
|
@@ -24,8 +24,27 @@
|
||||
|
||||
void free_rows(MYSQL_DATA *cur);
|
||||
int ma_multi_command(MYSQL *mysql, enum enum_multi_status status);
|
||||
MYSQL_FIELD * unpack_fields(MYSQL_DATA *data,
|
||||
MYSQL_FIELD * unpack_fields(const MYSQL *mysql, MYSQL_DATA *data,
|
||||
MA_MEM_ROOT *alloc,uint fields,
|
||||
my_bool default_value);
|
||||
|
||||
static inline my_bool ma_has_extended_type_info(const MYSQL *mysql)
|
||||
{
|
||||
return ((mysql->extension->mariadb_server_capabilities << 32) &
|
||||
MARIADB_CLIENT_EXTENDED_METADATA) != 0;
|
||||
}
|
||||
|
||||
static inline uint ma_extended_type_info_rows(const MYSQL *mysql)
|
||||
{
|
||||
return ma_has_extended_type_info(mysql) ? 1 : 0;
|
||||
}
|
||||
|
||||
static inline uint ma_result_set_rows(const MYSQL *mysql)
|
||||
{
|
||||
return ma_has_extended_type_info(mysql) ? 9 : 8;
|
||||
}
|
||||
|
||||
MA_FIELD_EXTENSION *ma_field_extension_deep_dup(MA_MEM_ROOT *memroot,
|
||||
const MA_FIELD_EXTENSION *from);
|
||||
|
||||
#endif
|
||||
|
@@ -170,13 +170,16 @@ enum enum_server_command
|
||||
#define MARIADB_CLIENT_PROGRESS (1ULL << 32)
|
||||
#define MARIADB_CLIENT_COM_MULTI (1ULL << 33)
|
||||
#define MARIADB_CLIENT_STMT_BULK_OPERATIONS (1ULL << 34)
|
||||
/* support of extended data type/format information, since 10.5.0 */
|
||||
#define MARIADB_CLIENT_EXTENDED_METADATA (1ULL << 35)
|
||||
|
||||
#define IS_MARIADB_EXTENDED_SERVER(mysql)\
|
||||
!(mysql->server_capabilities & CLIENT_MYSQL)
|
||||
|
||||
#define MARIADB_CLIENT_SUPPORTED_FLAGS (MARIADB_CLIENT_PROGRESS |\
|
||||
MARIADB_CLIENT_COM_MULTI |\
|
||||
MARIADB_CLIENT_STMT_BULK_OPERATIONS)
|
||||
MARIADB_CLIENT_STMT_BULK_OPERATIONS|\
|
||||
MARIADB_CLIENT_EXTENDED_METADATA)
|
||||
|
||||
#define CLIENT_SUPPORTED_FLAGS (CLIENT_MYSQL |\
|
||||
CLIENT_FOUND_ROWS |\
|
||||
|
@@ -61,6 +61,14 @@ typedef int my_socket;
|
||||
#include "ma_list.h"
|
||||
#include "mariadb_ctype.h"
|
||||
|
||||
|
||||
typedef struct st_ma_const_string
|
||||
{
|
||||
const char *str;
|
||||
size_t length;
|
||||
} MARIADB_CONST_STRING;
|
||||
|
||||
|
||||
#ifndef ST_MA_USED_MEM_DEFINED
|
||||
#define ST_MA_USED_MEM_DEFINED
|
||||
typedef struct st_ma_used_mem { /* struct for once_alloc */
|
||||
@@ -383,6 +391,20 @@ typedef struct
|
||||
void *extension;
|
||||
} MYSQL_PARAMETERS;
|
||||
|
||||
|
||||
enum mariadb_field_attr_t
|
||||
{
|
||||
MARIADB_FIELD_ATTR_DATA_TYPE_NAME= 0,
|
||||
MARIADB_FIELD_ATTR_FORMAT_NAME= 1
|
||||
};
|
||||
|
||||
#define MARIADB_FIELD_ATTR_LAST MARIADB_FIELD_ATTR_FORMAT_NAME
|
||||
|
||||
|
||||
int STDCALL mariadb_field_attr(MARIADB_CONST_STRING *attr,
|
||||
const MYSQL_FIELD *field,
|
||||
enum mariadb_field_attr_t type);
|
||||
|
||||
#ifndef _mysql_time_h_
|
||||
enum enum_mysql_timestamp_type
|
||||
{
|
||||
|
@@ -29,7 +29,9 @@ SET(MARIADB_LIB_SYMBOLS
|
||||
mariadb_rpl_fetch
|
||||
mariadb_rpl_optionsv
|
||||
mariadb_rpl_get_optionsv
|
||||
mariadb_free_rpl_event)
|
||||
mariadb_free_rpl_event
|
||||
mariadb_field_attr
|
||||
)
|
||||
IF(WITH_SSL)
|
||||
SET(MARIADB_LIB_SYMBOLS ${MARIADB_LIB_SYMBOLS} mariadb_deinitialize_ssl)
|
||||
ENDIF()
|
||||
|
@@ -752,6 +752,79 @@ my_bool _mariadb_set_conf_option(MYSQL *mysql, const char *config_option, const
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static MARIADB_CONST_STRING null_const_string= {0,0};
|
||||
|
||||
/***************************************************************************
|
||||
** Allocate a string copy on memroot
|
||||
***************************************************************************/
|
||||
static MARIADB_CONST_STRING ma_const_string_copy_root(MA_MEM_ROOT *memroot,
|
||||
const char *str,
|
||||
size_t length)
|
||||
{
|
||||
MARIADB_CONST_STRING res;
|
||||
if (!str || !(res.str= ma_memdup_root(memroot, str, length)))
|
||||
return null_const_string;
|
||||
res.length= length;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
** Allocate and initialize MA_FIELD_EXTENSION
|
||||
***************************************************************************/
|
||||
MA_FIELD_EXTENSION *new_ma_field_extension(MA_MEM_ROOT *memroot)
|
||||
{
|
||||
MA_FIELD_EXTENSION *ext= ma_alloc_root(memroot, sizeof(MA_FIELD_EXTENSION));
|
||||
if (ext)
|
||||
memset((void *) ext, 0, sizeof(*ext));
|
||||
return ext;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
** Populate field extension from a type info packet
|
||||
***************************************************************************/
|
||||
|
||||
static void ma_field_extension_init_type_info(MA_MEM_ROOT *memroot,
|
||||
MA_FIELD_EXTENSION *ext,
|
||||
const char *ptr, size_t length)
|
||||
{
|
||||
const char *end= ptr + length;
|
||||
for ( ; ptr < end; )
|
||||
{
|
||||
uint itype= (uchar) *ptr++;
|
||||
uint len= (uchar) *ptr++;
|
||||
if (ptr + len > end || len > 127)
|
||||
break; /*Badly encoded data*/
|
||||
if (itype <= 127 && itype <= MARIADB_FIELD_ATTR_LAST)
|
||||
ext->metadata[itype]= ma_const_string_copy_root(memroot, ptr, len);
|
||||
ptr+= len;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
** Allocate a field extension deep copy
|
||||
***************************************************************************/
|
||||
|
||||
MA_FIELD_EXTENSION *ma_field_extension_deep_dup(MA_MEM_ROOT *memroot,
|
||||
const MA_FIELD_EXTENSION *from)
|
||||
{
|
||||
MA_FIELD_EXTENSION *ext= new_ma_field_extension(memroot);
|
||||
uint i;
|
||||
if (!ext)
|
||||
return NULL;
|
||||
for (i= 0; i < MARIADB_FIELD_ATTR_LAST; i++)
|
||||
{
|
||||
if (from->metadata[i].str)
|
||||
ext->metadata[i]= ma_const_string_copy_root(memroot,
|
||||
from->metadata[i].str,
|
||||
from->metadata[i].length);
|
||||
}
|
||||
return ext;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
** Change field rows to field structs
|
||||
***************************************************************************/
|
||||
@@ -772,7 +845,8 @@ static size_t rset_field_offsets[]= {
|
||||
};
|
||||
|
||||
MYSQL_FIELD *
|
||||
unpack_fields(MYSQL_DATA *data,MA_MEM_ROOT *alloc,uint fields,
|
||||
unpack_fields(const MYSQL *mysql,
|
||||
MYSQL_DATA *data, MA_MEM_ROOT *alloc, uint fields,
|
||||
my_bool default_value)
|
||||
{
|
||||
MYSQL_ROWS *row;
|
||||
@@ -805,7 +879,20 @@ unpack_fields(MYSQL_DATA *data,MA_MEM_ROOT *alloc,uint fields,
|
||||
}
|
||||
}
|
||||
|
||||
p= (char *)row->data[6];
|
||||
field->extension= NULL;
|
||||
if (ma_has_extended_type_info(mysql))
|
||||
{
|
||||
if (row->data[i+1] - row->data[i] > 1)
|
||||
{
|
||||
size_t len= row->data[i+1] - row->data[i] - 1;
|
||||
MA_FIELD_EXTENSION *ext= new_ma_field_extension(alloc);
|
||||
if ((field->extension= ext))
|
||||
ma_field_extension_init_type_info(alloc, ext, row->data[i], len);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
p= (char *)row->data[i];
|
||||
/* filler */
|
||||
field->charsetnr= uint2korr(p);
|
||||
p+= 2;
|
||||
@@ -824,10 +911,11 @@ unpack_fields(MYSQL_DATA *data,MA_MEM_ROOT *alloc,uint fields,
|
||||
if (INTERNAL_NUM_FIELD(field))
|
||||
field->flags|= NUM_FLAG;
|
||||
|
||||
i++;
|
||||
/* This is used by deprecated function mysql_list_fields only,
|
||||
however the reported length is not correct, so we always zero it */
|
||||
if (default_value && row->data[7])
|
||||
field->def=ma_strdup_root(alloc,(char*) row->data[7]);
|
||||
if (default_value && row->data[i])
|
||||
field->def=ma_strdup_root(alloc,(char*) row->data[i]);
|
||||
else
|
||||
field->def=0;
|
||||
field->def_length= 0;
|
||||
@@ -2213,9 +2301,10 @@ get_info:
|
||||
mysql->server_status|= SERVER_STATUS_IN_TRANS;
|
||||
|
||||
mysql->extra_info= net_field_length_ll(&pos); /* Maybe number of rec */
|
||||
if (!(fields=mysql->methods->db_read_rows(mysql,(MYSQL_FIELD*) 0,8)))
|
||||
if (!(fields=mysql->methods->db_read_rows(mysql,(MYSQL_FIELD*) 0,
|
||||
ma_result_set_rows(mysql))))
|
||||
return(-1);
|
||||
if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc,
|
||||
if (!(mysql->fields=unpack_fields(mysql, fields, &mysql->field_alloc,
|
||||
(uint) field_count, 1)))
|
||||
return(-1);
|
||||
mysql->status=MYSQL_STATUS_GET_RESULT;
|
||||
@@ -2365,6 +2454,26 @@ mysql_fetch_field(MYSQL_RES *result)
|
||||
return &result->fields[result->current_field++];
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
** Return mysql field metadata
|
||||
**************************************************************************/
|
||||
int STDCALL
|
||||
mariadb_field_attr(MARIADB_CONST_STRING *attr,
|
||||
const MYSQL_FIELD *field,
|
||||
enum mariadb_field_attr_t type)
|
||||
{
|
||||
MA_FIELD_EXTENSION *ext= (MA_FIELD_EXTENSION*) field->extension;
|
||||
if (!ext || type > MARIADB_FIELD_ATTR_LAST)
|
||||
{
|
||||
*attr= null_const_string;
|
||||
return 1;
|
||||
}
|
||||
*attr= ext->metadata[type];
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
** Return next row of the query results
|
||||
**************************************************************************/
|
||||
@@ -2544,7 +2653,8 @@ mysql_list_fields(MYSQL *mysql, const char *table, const char *wild)
|
||||
length= snprintf(buff, 128, "%s%c%s", table, '\0', wild ? wild : "");
|
||||
|
||||
if (ma_simple_command(mysql, COM_FIELD_LIST,buff,length,1,0) ||
|
||||
!(query = mysql->methods->db_read_rows(mysql,(MYSQL_FIELD*) 0,8)))
|
||||
!(query = mysql->methods->db_read_rows(mysql,(MYSQL_FIELD*) 0,
|
||||
ma_result_set_rows(mysql))))
|
||||
return(NULL);
|
||||
|
||||
free_old_query(mysql);
|
||||
@@ -2557,7 +2667,7 @@ mysql_list_fields(MYSQL *mysql, const char *table, const char *wild)
|
||||
mysql->fields=0;
|
||||
result->eof=1;
|
||||
result->field_count = (uint) query->rows;
|
||||
result->fields= unpack_fields(query,&result->field_alloc,
|
||||
result->fields= unpack_fields(mysql, query, &result->field_alloc,
|
||||
result->field_count, 1);
|
||||
if (result->fields)
|
||||
return(result);
|
||||
@@ -2589,7 +2699,7 @@ mysql_list_processes(MYSQL *mysql)
|
||||
field_count=(uint) net_field_length(&pos);
|
||||
if (!(fields = mysql->methods->db_read_rows(mysql,(MYSQL_FIELD*) 0,7)))
|
||||
return(NULL);
|
||||
if (!(mysql->fields=unpack_fields(fields, &mysql->field_alloc,
|
||||
if (!(mysql->fields= unpack_fields(mysql, fields, &mysql->field_alloc,
|
||||
field_count, 0)))
|
||||
return(NULL);
|
||||
mysql->status=MYSQL_STATUS_GET_RESULT;
|
||||
|
@@ -1581,7 +1581,8 @@ my_bool mthd_stmt_get_param_metadata(MYSQL_STMT *stmt)
|
||||
{
|
||||
MYSQL_DATA *result;
|
||||
|
||||
if (!(result= stmt->mysql->methods->db_read_rows(stmt->mysql, (MYSQL_FIELD *)0, 7)))
|
||||
if (!(result= stmt->mysql->methods->db_read_rows(stmt->mysql, (MYSQL_FIELD *)0,
|
||||
7 + ma_extended_type_info_rows(stmt->mysql))))
|
||||
return(1);
|
||||
|
||||
free_rows(result);
|
||||
@@ -1593,9 +1594,10 @@ my_bool mthd_stmt_get_result_metadata(MYSQL_STMT *stmt)
|
||||
MYSQL_DATA *result;
|
||||
MA_MEM_ROOT *fields_ma_alloc_root= &((MADB_STMT_EXTENSION *)stmt->extension)->fields_ma_alloc_root;
|
||||
|
||||
if (!(result= stmt->mysql->methods->db_read_rows(stmt->mysql, (MYSQL_FIELD *)0, 7)))
|
||||
if (!(result= stmt->mysql->methods->db_read_rows(stmt->mysql, (MYSQL_FIELD *)0,
|
||||
7 + ma_extended_type_info_rows(stmt->mysql))))
|
||||
return(1);
|
||||
if (!(stmt->fields= unpack_fields(result,fields_ma_alloc_root,
|
||||
if (!(stmt->fields= unpack_fields(stmt->mysql, result, fields_ma_alloc_root,
|
||||
stmt->field_count, 0)))
|
||||
return(1);
|
||||
return(0);
|
||||
@@ -1836,6 +1838,11 @@ static int madb_alloc_stmt_fields(MYSQL_STMT *stmt)
|
||||
stmt->fields[i].decimals= stmt->mysql->fields[i].decimals;
|
||||
stmt->fields[i].charsetnr= stmt->mysql->fields[i].charsetnr;
|
||||
stmt->fields[i].max_length= stmt->mysql->fields[i].max_length;
|
||||
stmt->fields[i].extension=
|
||||
stmt->mysql->fields[i].extension ?
|
||||
ma_field_extension_deep_dup(fields_ma_alloc_root,
|
||||
stmt->mysql->fields[i].extension) :
|
||||
NULL;
|
||||
}
|
||||
if (!(stmt->bind= (MYSQL_BIND *)ma_alloc_root(fields_ma_alloc_root, stmt->field_count * sizeof(MYSQL_BIND))))
|
||||
{
|
||||
@@ -1912,7 +1919,6 @@ int stmt_read_execute_response(MYSQL_STMT *stmt)
|
||||
/* since all pointers will be incorrect if another statement will
|
||||
be executed, so we need to allocate memory and copy the
|
||||
information */
|
||||
stmt->fields[i].extension= 0; /* not in use yet */
|
||||
if (mysql->fields[i].db)
|
||||
stmt->fields[i].db= ma_strdup_root(fields_ma_alloc_root, mysql->fields[i].db);
|
||||
if (mysql->fields[i].table)
|
||||
@@ -1927,6 +1933,11 @@ int stmt_read_execute_response(MYSQL_STMT *stmt)
|
||||
stmt->fields[i].catalog= ma_strdup_root(fields_ma_alloc_root, mysql->fields[i].catalog);
|
||||
if (mysql->fields[i].def)
|
||||
stmt->fields[i].def= ma_strdup_root(fields_ma_alloc_root, mysql->fields[i].def);
|
||||
stmt->fields[i].extension=
|
||||
mysql->fields[i].extension ?
|
||||
ma_field_extension_deep_dup(fields_ma_alloc_root,
|
||||
mysql->fields[i].extension) :
|
||||
NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user