You've already forked mariadb-connector-c
mirror of
https://github.com/mariadb-corporation/mariadb-connector-c.git
synced 2025-08-07 02:42:49 +03:00
MDEV-19237 - do not resend prepared statement metadata unnecessarily
fix warnings
This commit is contained in:
@@ -39,6 +39,13 @@ static inline uint ma_extended_type_info_rows(const MYSQL *mysql)
|
||||
return ma_has_extended_type_info(mysql) ? 1 : 0;
|
||||
}
|
||||
|
||||
static inline my_bool ma_supports_cache_metadata(const MYSQL *mysql)
|
||||
{
|
||||
return (mysql->extension->mariadb_server_capabilities &
|
||||
(MARIADB_CLIENT_CACHE_METADATA >> 32)) != 0 ;
|
||||
}
|
||||
|
||||
|
||||
static inline uint ma_result_set_rows(const MYSQL *mysql)
|
||||
{
|
||||
return ma_has_extended_type_info(mysql) ? 9 : 8;
|
||||
@@ -47,4 +54,7 @@ static inline uint ma_result_set_rows(const MYSQL *mysql)
|
||||
MA_FIELD_EXTENSION *ma_field_extension_deep_dup(MA_MEM_ROOT *memroot,
|
||||
const MA_FIELD_EXTENSION *from);
|
||||
|
||||
MYSQL_FIELD *ma_duplicate_resultset_metadata(MYSQL_FIELD *fields, size_t count,
|
||||
MA_MEM_ROOT *memroot);
|
||||
|
||||
#endif
|
||||
|
@@ -172,13 +172,16 @@ enum enum_server_command
|
||||
#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)
|
||||
/* Do not resend metadata for prepared statements, since 10.6*/
|
||||
#define MARIADB_CLIENT_CACHE_METADATA (1ULL << 36)
|
||||
|
||||
#define IS_MARIADB_EXTENDED_SERVER(mysql)\
|
||||
(!(mysql->server_capabilities & CLIENT_MYSQL))
|
||||
|
||||
#define MARIADB_CLIENT_SUPPORTED_FLAGS (MARIADB_CLIENT_PROGRESS |\
|
||||
MARIADB_CLIENT_STMT_BULK_OPERATIONS|\
|
||||
MARIADB_CLIENT_EXTENDED_METADATA)
|
||||
MARIADB_CLIENT_EXTENDED_METADATA|\
|
||||
MARIADB_CLIENT_CACHE_METADATA)
|
||||
|
||||
#define CLIENT_SUPPORTED_FLAGS (CLIENT_MYSQL |\
|
||||
CLIENT_FOUND_ROWS |\
|
||||
|
@@ -2300,12 +2300,84 @@ corrupted:
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static int ma_deep_copy_field(const MYSQL_FIELD *src, MYSQL_FIELD *dst,
|
||||
MA_MEM_ROOT *r)
|
||||
{
|
||||
#define MA_STRDUP(f) \
|
||||
do \
|
||||
{ \
|
||||
if (src->f) \
|
||||
{ \
|
||||
if ((dst->f= ma_strdup_root(r, src->f)) == NULL) \
|
||||
return -1; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
dst->f= NULL; \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
|
||||
MA_STRDUP(catalog);
|
||||
MA_STRDUP(db);
|
||||
MA_STRDUP(def);
|
||||
MA_STRDUP(name);
|
||||
MA_STRDUP(org_name);
|
||||
MA_STRDUP(org_table);
|
||||
MA_STRDUP(table);
|
||||
#undef MA_STRDUP
|
||||
|
||||
dst->catalog_length= src->catalog_length;
|
||||
dst->charsetnr= src->charsetnr;
|
||||
dst->db_length= src->db_length;
|
||||
dst->decimals= src->decimals;
|
||||
dst->def_length= src->def_length;
|
||||
dst->extension=
|
||||
src->extension
|
||||
? ma_field_extension_deep_dup(r,
|
||||
src->extension)
|
||||
: NULL;
|
||||
dst->flags= src->flags;
|
||||
dst->length= src->length;
|
||||
dst->max_length = src->max_length;
|
||||
dst->name_length= src->name_length;
|
||||
dst->org_name_length= src->org_name_length;
|
||||
dst->org_table_length= src->org_table_length;
|
||||
dst->table_length= src->table_length;
|
||||
dst->type= src->type;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
MYSQL_FIELD *ma_duplicate_resultset_metadata(MYSQL_FIELD *fields, size_t count,
|
||||
MA_MEM_ROOT *memroot)
|
||||
{
|
||||
size_t i;
|
||||
MYSQL_FIELD *result=
|
||||
(MYSQL_FIELD *) ma_alloc_root(memroot, sizeof(MYSQL_FIELD) * count);
|
||||
if (!result)
|
||||
return NULL;
|
||||
|
||||
for (i= 0; i < count; i++)
|
||||
{
|
||||
if (ma_deep_copy_field(&fields[i], &result[i], memroot))
|
||||
return NULL;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int mthd_my_read_query_result(MYSQL *mysql)
|
||||
{
|
||||
uchar *pos;
|
||||
ulong field_count;
|
||||
MYSQL_DATA *fields;
|
||||
ulong length;
|
||||
const uchar *end;
|
||||
uchar has_metadata;
|
||||
|
||||
my_bool can_local_infile= (mysql->options.extension) && (mysql->extension->auto_local_infile != WAIT_FOR_QUERY);
|
||||
|
||||
if (mysql->options.extension && mysql->extension->auto_local_infile == ACCEPT_FILE_REQUEST)
|
||||
@@ -2318,6 +2390,7 @@ int mthd_my_read_query_result(MYSQL *mysql)
|
||||
free_old_query(mysql); /* Free old result */
|
||||
get_info:
|
||||
pos=(uchar*) mysql->net.read_pos;
|
||||
end= pos + length;
|
||||
if ((field_count= net_field_length(&pos)) == 0)
|
||||
return ma_read_ok_packet(mysql, pos, length);
|
||||
if (field_count == NULL_LENGTH) /* LOAD DATA LOCAL INFILE */
|
||||
@@ -2328,16 +2401,45 @@ get_info:
|
||||
return(-1);
|
||||
goto get_info; /* Get info packet */
|
||||
}
|
||||
|
||||
has_metadata= 1;
|
||||
if (ma_supports_cache_metadata(mysql))
|
||||
{
|
||||
assert(mysql->fields == NULL);
|
||||
if (pos < end)
|
||||
{
|
||||
has_metadata= *pos;
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT))
|
||||
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,
|
||||
if (has_metadata)
|
||||
{
|
||||
if (!(fields= mysql->methods->db_read_rows(mysql, (MYSQL_FIELD *) 0,
|
||||
ma_result_set_rows(mysql))))
|
||||
return(-1);
|
||||
if (!(mysql->fields=unpack_fields(mysql, fields, &mysql->field_alloc,
|
||||
return (-1);
|
||||
if (!(mysql->fields= unpack_fields(mysql, fields, &mysql->field_alloc,
|
||||
(uint) field_count, 1)))
|
||||
return(-1);
|
||||
return (-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Read EOF, to get the status and warning count. */
|
||||
if ((length= ma_net_safe_read(mysql)) == packet_error)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
pos= (uchar *) mysql->net.read_pos;
|
||||
if (length != 5 || pos[0] != 0xfe)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
mysql->warning_count= uint2korr(pos + 1);
|
||||
mysql->server_status= uint2korr(pos + 3);
|
||||
}
|
||||
mysql->status=MYSQL_STATUS_GET_RESULT;
|
||||
mysql->field_count=field_count;
|
||||
return(0);
|
||||
|
@@ -56,6 +56,7 @@
|
||||
#include <mysql/client_plugin.h>
|
||||
#include <ma_common.h>
|
||||
#include "ma_priv.h"
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
#define UPDATE_STMT_ERROR(stmt)\
|
||||
@@ -1648,7 +1649,8 @@ int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, unsigned lon
|
||||
|
||||
stmt->param_count= 0;
|
||||
stmt->field_count= 0;
|
||||
stmt->params= 0;
|
||||
stmt->fields= NULL;
|
||||
stmt->params= NULL;
|
||||
|
||||
int4store(stmt_id, stmt->stmt_id);
|
||||
if (mysql->methods->db_command(mysql, COM_STMT_CLOSE, stmt_id,
|
||||
@@ -1803,55 +1805,32 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt)
|
||||
|
||||
static int madb_alloc_stmt_fields(MYSQL_STMT *stmt)
|
||||
{
|
||||
uint i;
|
||||
MA_MEM_ROOT *fields_ma_alloc_root= &((MADB_STMT_EXTENSION *)stmt->extension)->fields_ma_alloc_root;
|
||||
MYSQL *mysql= stmt->mysql;
|
||||
if (!mysql->field_count)
|
||||
return 0;
|
||||
|
||||
if (stmt->mysql->field_count)
|
||||
stmt->field_count= mysql->field_count;
|
||||
if (mysql->fields)
|
||||
{
|
||||
/* Column info was sent by server */
|
||||
ma_free_root(fields_ma_alloc_root, MYF(0));
|
||||
if (!(stmt->fields= (MYSQL_FIELD *)ma_alloc_root(fields_ma_alloc_root,
|
||||
sizeof(MYSQL_FIELD) * stmt->mysql->field_count)))
|
||||
if (!(stmt->fields= ma_duplicate_resultset_metadata(
|
||||
mysql->fields, mysql->field_count,
|
||||
fields_ma_alloc_root)))
|
||||
{
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
|
||||
return(1);
|
||||
}
|
||||
stmt->field_count= stmt->mysql->field_count;
|
||||
|
||||
for (i=0; i < stmt->field_count; i++)
|
||||
{
|
||||
if (stmt->mysql->fields[i].db)
|
||||
stmt->fields[i].db= ma_strdup_root(fields_ma_alloc_root, stmt->mysql->fields[i].db);
|
||||
if (stmt->mysql->fields[i].table)
|
||||
stmt->fields[i].table= ma_strdup_root(fields_ma_alloc_root, stmt->mysql->fields[i].table);
|
||||
if (stmt->mysql->fields[i].org_table)
|
||||
stmt->fields[i].org_table= ma_strdup_root(fields_ma_alloc_root, stmt->mysql->fields[i].org_table);
|
||||
if (stmt->mysql->fields[i].name)
|
||||
stmt->fields[i].name= ma_strdup_root(fields_ma_alloc_root, stmt->mysql->fields[i].name);
|
||||
if (stmt->mysql->fields[i].org_name)
|
||||
stmt->fields[i].org_name= ma_strdup_root(fields_ma_alloc_root, stmt->mysql->fields[i].org_name);
|
||||
if (stmt->mysql->fields[i].catalog)
|
||||
stmt->fields[i].catalog= ma_strdup_root(fields_ma_alloc_root, stmt->mysql->fields[i].catalog);
|
||||
stmt->fields[i].def= stmt->mysql->fields[i].def ? ma_strdup_root(fields_ma_alloc_root, stmt->mysql->fields[i].def) : NULL;
|
||||
stmt->fields[i].type= stmt->mysql->fields[i].type;
|
||||
stmt->fields[i].length= stmt->mysql->fields[i].length;
|
||||
stmt->fields[i].flags= stmt->mysql->fields[i].flags;
|
||||
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))))
|
||||
if (!(stmt->bind= (MYSQL_BIND *) ma_alloc_root(
|
||||
fields_ma_alloc_root, stmt->field_count * sizeof(MYSQL_BIND))))
|
||||
{
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
|
||||
return(1);
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
memset(stmt->bind, 0, stmt->field_count * sizeof(MYSQL_BIND));
|
||||
stmt->bind_result_done= 0;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -1863,11 +1842,36 @@ int stmt_read_execute_response(MYSQL_STMT *stmt)
|
||||
if (!mysql)
|
||||
return(1);
|
||||
|
||||
ret= test((mysql->methods->db_read_stmt_result &&
|
||||
mysql->methods->db_read_stmt_result(mysql)));
|
||||
/* if a reconnect occurred, our connection handle is invalid */
|
||||
if (!stmt->mysql)
|
||||
return(1);
|
||||
return (1);
|
||||
|
||||
ret= test((mysql->methods->db_read_stmt_result &&
|
||||
mysql->methods->db_read_stmt_result(mysql)));
|
||||
|
||||
if (!ret && mysql->field_count && !mysql->fields)
|
||||
{
|
||||
/*
|
||||
Column info was not sent by server, copy
|
||||
from stmt->fields
|
||||
*/
|
||||
assert(stmt->fields);
|
||||
/*
|
||||
Too bad, C/C resets stmt->field_count to 0
|
||||
before reading SP output variables result sets.
|
||||
*/
|
||||
if(!stmt->field_count)
|
||||
stmt->field_count = mysql->field_count;
|
||||
else
|
||||
assert(mysql->field_count == stmt->field_count);
|
||||
mysql->fields= ma_duplicate_resultset_metadata(
|
||||
stmt->fields, stmt->field_count, &mysql->field_alloc);
|
||||
if (!mysql->fields)
|
||||
{
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
/* update affected rows, also if an error occurred */
|
||||
stmt->upsert_status.affected_rows= stmt->mysql->affected_rows;
|
||||
|
@@ -267,7 +267,10 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
|
||||
memset(buff + 9, 0, 32-9);
|
||||
if (!(mysql->server_capabilities & CLIENT_MYSQL))
|
||||
{
|
||||
mysql->extension->mariadb_client_flag = MARIADB_CLIENT_SUPPORTED_FLAGS >> 32;
|
||||
uint server_extended_cap= mysql->extension->mariadb_server_capabilities;
|
||||
uint client_extended_cap= (uint)(MARIADB_CLIENT_SUPPORTED_FLAGS >> 32);
|
||||
mysql->extension->mariadb_client_flag=
|
||||
server_extended_cap & client_extended_cap;
|
||||
int4store(buff + 28, mysql->extension->mariadb_client_flag);
|
||||
}
|
||||
end= buff+32;
|
||||
|
Reference in New Issue
Block a user