Skip to content

Commit

Permalink
MDEV-17832 Protocol: extensions for Pluggable types and JSON, GEOMETRY
Browse files Browse the repository at this point in the history
  • Loading branch information
abarkov committed Mar 10, 2020
1 parent d4f7548 commit 6632cb6
Show file tree
Hide file tree
Showing 7 changed files with 190 additions and 17 deletions.
6 changes: 6 additions & 0 deletions include/ma_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
21 changes: 20 additions & 1 deletion include/ma_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
5 changes: 4 additions & 1 deletion include/mariadb_com.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 |\
Expand Down
22 changes: 22 additions & 0 deletions include/mysql.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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
{
Expand Down
4 changes: 3 additions & 1 deletion libmariadb/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
130 changes: 120 additions & 10 deletions libmariadb/mariadb_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
***************************************************************************/
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -2213,9 +2301,10 @@ int mthd_my_read_query_result(MYSQL *mysql)
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;
Expand Down Expand Up @@ -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
**************************************************************************/
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -2589,8 +2699,8 @@ 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,
field_count, 0)))
if (!(mysql->fields= unpack_fields(mysql, fields, &mysql->field_alloc,
field_count, 0)))
return(NULL);
mysql->status=MYSQL_STATUS_GET_RESULT;
mysql->field_count=field_count;
Expand Down
19 changes: 15 additions & 4 deletions libmariadb/mariadb_stmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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))))
{
Expand Down Expand Up @@ -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)
Expand All @@ -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;
}
}

Expand Down

0 comments on commit 6632cb6

Please sign in to comment.