summaryrefslogtreecommitdiff
path: root/libmysql
diff options
context:
space:
mode:
authorunknown <monty@mysql.com>2004-04-30 14:04:51 +0300
committerunknown <monty@mysql.com>2004-04-30 14:04:51 +0300
commit72c7b3529e02d5b4b4e8ba1c907dea8b7eb743ea (patch)
treebf4afec8158711eea5af288ed4fb7f58f03fdb78 /libmysql
parentbe5d750a241dbf103f7546b2f83d1bdc312eb5ac (diff)
parent15c2bb61f505a1ce59894c3c299e533667274860 (diff)
downloadmariadb-git-72c7b3529e02d5b4b4e8ba1c907dea8b7eb743ea.tar.gz
Merge
libmysql/libmysql.c: Auto merged tests/client_test.c: Auto merged include/mysql.h: SCCS merged
Diffstat (limited to 'libmysql')
-rw-r--r--libmysql/libmysql.c181
1 files changed, 173 insertions, 8 deletions
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index ac6d6b8777a..bbff4e7a8d8 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -85,6 +85,7 @@ my_bool net_flush(NET *net);
#define MAX_LONG_DATA_LENGTH 8192
#define unsigned_field(A) ((A)->flags & UNSIGNED_FLAG)
+static void stmt_update_metadata(MYSQL_STMT *stmt, MYSQL_ROWS *data);
static void append_wild(char *to,char *end,const char *wild);
sig_handler pipe_sig_handler(int sig);
static ulong mysql_sub_escape_string(CHARSET_INFO *charset_info, char *to,
@@ -3342,12 +3343,50 @@ static void fetch_result_str(MYSQL_BIND *param, uchar **row)
/*
+ functions to calculate max lengths for strings during
+ mysql_stmt_store_result()
+*/
+
+static void skip_result_fixed(MYSQL_BIND *param,
+ MYSQL_FIELD *field __attribute__((unused)),
+ uchar **row)
+
+{
+ (*row)+= param->pack_length;
+}
+
+
+static void skip_result_with_length(MYSQL_BIND *param __attribute__((unused)),
+ MYSQL_FIELD *field __attribute__((unused)),
+ uchar **row)
+
+{
+ ulong length= net_field_length(row);
+ (*row)+= length;
+}
+
+
+static void skip_result_string(MYSQL_BIND *param __attribute__((unused)),
+ MYSQL_FIELD *field,
+ uchar **row)
+
+{
+ ulong length= net_field_length(row);
+ (*row)+= length;
+ if (field->max_length < length)
+ field->max_length= length;
+}
+
+
+
+/*
Setup the bind buffers for resultset processing
*/
my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
{
MYSQL_BIND *param, *end;
+ MYSQL_FIELD *field;
ulong bind_count;
uint param_count= 0;
DBUG_ENTER("mysql_stmt_bind_result");
@@ -3370,7 +3409,9 @@ my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
memcpy((char*) stmt->bind, (char*) bind, sizeof(MYSQL_BIND) * bind_count);
- for (param= stmt->bind, end= param+bind_count; param < end ; param++)
+ for (param= stmt->bind, end= param + bind_count, field= stmt->fields ;
+ param < end ;
+ param++, field++)
{
/*
Set param->is_null to point to a dummy variable if it's not set.
@@ -3388,15 +3429,18 @@ my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
/* Setup data copy functions for the different supported types */
switch (param->buffer_type) {
case MYSQL_TYPE_NULL: /* for dummy binds */
+ *param->length= 0;
break;
case MYSQL_TYPE_TINY:
param->fetch_result= fetch_result_tinyint;
*param->length= 1;
break;
case MYSQL_TYPE_SHORT:
+ case MYSQL_TYPE_YEAR:
param->fetch_result= fetch_result_short;
*param->length= 2;
break;
+ case MYSQL_TYPE_INT24:
case MYSQL_TYPE_LONG:
param->fetch_result= fetch_result_int32;
*param->length= 4;
@@ -3445,6 +3489,58 @@ my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
param->buffer_type, param_count);
DBUG_RETURN(1);
}
+
+ /* Setup skip_result functions (to calculate max_length) */
+ param->skip_result= skip_result_fixed;
+ switch (field->type) {
+ case MYSQL_TYPE_NULL: /* for dummy binds */
+ param->pack_length= 0;
+ break;
+ case MYSQL_TYPE_TINY:
+ param->pack_length= 1;
+ break;
+ case MYSQL_TYPE_YEAR:
+ case MYSQL_TYPE_SHORT:
+ param->pack_length= 2;
+ break;
+ case MYSQL_TYPE_INT24:
+ case MYSQL_TYPE_LONG:
+ param->pack_length= 4;
+ break;
+ case MYSQL_TYPE_LONGLONG:
+ param->pack_length= 8;
+ break;
+ case MYSQL_TYPE_FLOAT:
+ param->pack_length= 4;
+ break;
+ case MYSQL_TYPE_DOUBLE:
+ param->pack_length= 8;
+ break;
+ case MYSQL_TYPE_TIME:
+ case MYSQL_TYPE_DATE:
+ case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_TIMESTAMP:
+ param->skip_result= skip_result_with_length;
+ break;
+ case MYSQL_TYPE_DECIMAL:
+ case MYSQL_TYPE_ENUM:
+ case MYSQL_TYPE_SET:
+ case MYSQL_TYPE_GEOMETRY:
+ case MYSQL_TYPE_TINY_BLOB:
+ case MYSQL_TYPE_MEDIUM_BLOB:
+ case MYSQL_TYPE_LONG_BLOB:
+ case MYSQL_TYPE_BLOB:
+ case MYSQL_TYPE_VAR_STRING:
+ case MYSQL_TYPE_STRING:
+ param->skip_result= skip_result_string;
+ break;
+ default:
+ strmov(stmt->sqlstate, unknown_sqlstate);
+ sprintf(stmt->last_error,
+ ER(stmt->last_errno= CR_UNSUPPORTED_PARAM_TYPE),
+ field->type, param_count);
+ DBUG_RETURN(1);
+ }
}
stmt->bind_result_done= TRUE;
DBUG_RETURN(0);
@@ -3458,7 +3554,7 @@ my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
static int stmt_fetch_row(MYSQL_STMT *stmt, uchar *row)
{
MYSQL_BIND *bind, *end;
- MYSQL_FIELD *field, *field_end;
+ MYSQL_FIELD *field;
uchar *null_ptr, bit;
/*
Precondition: if stmt->field_count is zero or row is NULL, read_row_*
@@ -3478,10 +3574,8 @@ static int stmt_fetch_row(MYSQL_STMT *stmt, uchar *row)
bit= 4; /* first 2 bits are reserved */
/* Copy complete row to application buffers */
- for (bind= stmt->bind, end= (MYSQL_BIND *) bind + stmt->field_count,
- field= stmt->fields,
- field_end= (MYSQL_FIELD *)stmt->fields+stmt->field_count;
- bind < end && field < field_end;
+ for (bind= stmt->bind, end= bind + stmt->field_count, field= stmt->fields ;
+ bind < end ;
bind++, field++)
{
if (*null_ptr & bit)
@@ -3514,6 +3608,7 @@ static int stmt_fetch_row(MYSQL_STMT *stmt, uchar *row)
return 0;
}
+
int cli_unbuffered_fetch(MYSQL *mysql, char **row)
{
if (packet_error == net_safe_read(mysql))
@@ -3524,6 +3619,7 @@ int cli_unbuffered_fetch(MYSQL *mysql, char **row)
return 0;
}
+
/*
Fetch and return row data to bound buffers, if any
*/
@@ -3620,6 +3716,28 @@ int cli_read_binary_rows(MYSQL_STMT *stmt)
mysql= mysql->last_used_con;
+ if (!stmt->bind_result_done)
+ {
+ /*
+ We must initalize the bind structure to be able to calculate
+ max_length
+ */
+ MYSQL_BIND *bind, *end;
+ MYSQL_FIELD *field;
+ bzero((char*) stmt->bind, sizeof(*stmt->bind)* stmt->field_count);
+
+ for (bind= stmt->bind, end= bind + stmt->field_count, field= stmt->fields;
+ bind < end ;
+ bind++, field++)
+ {
+ bind->buffer_type= field->type;
+ bind->buffer_length=1;
+ }
+
+ mysql_stmt_bind_result(stmt, stmt->bind);
+ stmt->bind_result_done= 0; /* No normal bind done */
+ }
+
while ((pkt_len= net_safe_read(mysql)) != packet_error)
{
cp= net->read_pos;
@@ -3629,13 +3747,15 @@ int cli_read_binary_rows(MYSQL_STMT *stmt)
sizeof(MYSQL_ROWS) + pkt_len - 1)))
{
set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate);
- DBUG_RETURN(1);
+ goto err;
}
cur->data= (MYSQL_ROW) (cur+1);
*prev_ptr= cur;
prev_ptr= &cur->next;
memcpy((char *) cur->data, (char *) cp+1, pkt_len-1);
- ++result->rows;
+ cur->length= pkt_len; /* To allow us to do sanity checks */
+ result->rows++;
+ stmt_update_metadata(stmt, cur);
}
else
{
@@ -3647,6 +3767,8 @@ int cli_read_binary_rows(MYSQL_STMT *stmt)
}
}
set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate);
+
+err:
DBUG_RETURN(1);
}
@@ -3909,6 +4031,49 @@ const char *STDCALL mysql_stmt_error(MYSQL_STMT * stmt)
DBUG_RETURN(stmt->last_error);
}
+
+/*
+ Update meta data for statement
+
+ SYNOPSIS
+ stmt_update_metadata()
+ stmt Statement handler
+ row Binary data
+
+ NOTES
+ Only updates MYSQL_FIELD->max_length for strings
+
+*/
+
+static void stmt_update_metadata(MYSQL_STMT *stmt, MYSQL_ROWS *data)
+{
+ MYSQL_BIND *bind, *end;
+ MYSQL_FIELD *field;
+ uchar *null_ptr, bit;
+ uchar *row= (uchar*) data->data;
+ uchar *row_end= row + data->length;
+
+ null_ptr= row;
+ row+= (stmt->field_count+9)/8; /* skip null bits */
+ bit= 4; /* first 2 bits are reserved */
+
+ /* Go throw all fields and calculate metadata */
+ for (bind= stmt->bind, end= bind + stmt->field_count, field= stmt->fields ;
+ bind < end ;
+ bind++, field++)
+ {
+ if (!(*null_ptr & bit))
+ (*bind->skip_result)(bind, field, &row);
+ DBUG_ASSERT(row <= row_end);
+ if (!((bit<<=1) & 255))
+ {
+ bit= 1; /* To next byte */
+ null_ptr++;
+ }
+ }
+}
+
+
/********************************************************************
Transactional APIs
*********************************************************************/