1510
1490
DBUG_RETURN(0);
1515
Allocate memory and init prepared statement structure.
1519
mysql connection handle
1522
This is an entry point of the new API. Returned handle stands for
1523
a server-side prepared statement. Memory for this structure (~700
1524
bytes) is allocated using 'malloc'. Once created, the handle can be
1525
reused many times. Created statement handle is bound to connection
1526
handle provided to this call: its lifetime is limited by lifetime
1528
'mysql_stmt_init()' is a pure local call, server side structure is
1529
created only in mysql_stmt_prepare.
1530
Next steps you may want to make:
1531
- set a statement attribute (mysql_stmt_attr_set()),
1532
- prepare statement handle with a query (mysql_stmt_prepare()),
1533
- close statement handle and free its memory (mysql_stmt_close()),
1534
- reset statement with mysql_stmt_reset() (a no-op which will
1536
Behaviour of the rest of API calls on this statement is not defined yet
1537
(though we're working on making each wrong call sequence return
1541
statement structure upon success and NULL if out of
1545
MYSQL_STMT * STDCALL
1546
mysql_stmt_init(MYSQL *mysql)
1549
DBUG_ENTER("mysql_stmt_init");
1551
if (!(stmt= (MYSQL_STMT *) my_malloc(sizeof(MYSQL_STMT),
1552
MYF(MY_WME | MY_ZEROFILL))))
1554
set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
1558
init_alloc_root(&stmt->mem_root, 2048, 2048);
1559
init_alloc_root(&stmt->result.alloc, 4096, 4096);
1560
stmt->result.alloc.min_malloc= sizeof(MYSQL_ROWS);
1561
mysql->stmts= list_add(mysql->stmts, &stmt->list);
1562
stmt->list.data= stmt;
1563
stmt->state= MYSQL_STMT_INIT_DONE;
1565
stmt->read_row_func= stmt_read_row_no_result_set;
1566
stmt->prefetch_rows= DEFAULT_PREFETCH_ROWS;
1567
strmov(stmt->sqlstate, not_error_sqlstate);
1568
/* The rest of statement members was bzeroed inside malloc */
1575
Prepare server side statement with query.
1578
mysql_stmt_prepare()
1579
stmt statement handle
1580
query statement to prepare
1581
length statement length
1584
Associate statement with statement handle. This is done both on
1585
client and server sides. At this point the server parses given query
1586
and creates an internal structure to represent it.
1587
Next steps you may want to make:
1588
- find out if this statement returns a result set by
1589
calling mysql_stmt_field_count(), and get result set metadata
1590
with mysql_stmt_result_metadata(),
1591
- if query contains placeholders, bind input parameters to placeholders
1592
using mysql_stmt_bind_param(),
1593
- otherwise proceed directly to mysql_stmt_execute().
1595
IMPLEMENTATION NOTES
1596
- if this is a re-prepare of the statement, first close previous data
1597
structure on the server and free old statement data
1598
- then send the query to server and get back number of placeholders,
1599
number of columns in result set (if any), and result set metadata.
1600
At the same time allocate memory for input and output parameters
1601
to have less checks in mysql_stmt_bind_{param, result}.
1609
mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, ulong length)
1611
MYSQL *mysql= stmt->mysql;
1612
DBUG_ENTER("mysql_stmt_prepare");
1616
/* mysql can be reset in mysql_close called from mysql_reconnect */
1617
set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate, NULL);
1622
Reset the last error in any case: that would clear the statement
1623
if the previous prepare failed.
1625
stmt->last_errno= 0;
1626
stmt->last_error[0]= '\0';
1628
if ((int) stmt->state > (int) MYSQL_STMT_INIT_DONE)
1630
/* This is second prepare with another statement */
1631
uchar buff[MYSQL_STMT_HEADER]; /* 4 bytes - stmt id */
1633
if (reset_stmt_handle(stmt, RESET_LONG_DATA | RESET_STORE_RESULT))
1636
These members must be reset for API to
1637
function in case of error or misuse.
1639
stmt->bind_param_done= stmt->bind_result_done= FALSE;
1640
stmt->param_count= stmt->field_count= 0;
1641
free_root(&stmt->mem_root, MYF(MY_KEEP_PREALLOC));
1643
int4store(buff, stmt->stmt_id);
1646
Close statement in server
1648
If there was a 'use' result from another statement, or from
1649
mysql_use_result it won't be freed in mysql_stmt_free_result and
1650
we should get 'Commands out of sync' here.
1652
stmt->state= MYSQL_STMT_INIT_DONE;
1653
if (stmt_command(mysql, COM_STMT_CLOSE, buff, 4, stmt))
1655
set_stmt_errmsg(stmt, &mysql->net);
1660
if (stmt_command(mysql, COM_STMT_PREPARE, (const uchar*) query, length, stmt))
1662
set_stmt_errmsg(stmt, &mysql->net);
1666
if ((*mysql->methods->read_prepare_result)(mysql, stmt))
1668
set_stmt_errmsg(stmt, &mysql->net);
1673
alloc_root will return valid address even in case when param_count
1674
and field_count are zero. Thus we should never rely on stmt->bind
1675
or stmt->params when checking for existence of placeholders or
1678
if (!(stmt->params= (MYSQL_BIND *) alloc_root(&stmt->mem_root,
1680
(stmt->param_count +
1681
stmt->field_count))))
1683
set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate, NULL);
1686
stmt->bind= stmt->params + stmt->param_count;
1687
stmt->state= MYSQL_STMT_PREPARE_DONE;
1688
DBUG_PRINT("info", ("Parameter count: %u", stmt->param_count));
1693
Get result set metadata from reply to mysql_stmt_execute.
1694
This is used mainly for SHOW commands, as metadata for these
1695
commands is sent only with result set.
1696
To be removed when all commands will fully support prepared mode.
1699
static unsigned int alloc_stmt_fields(MYSQL_STMT *stmt)
1701
MYSQL_FIELD *fields, *field, *end;
1702
MEM_ROOT *alloc= &stmt->mem_root;
1703
MYSQL *mysql= stmt->mysql;
1705
stmt->field_count= mysql->field_count;
1708
Get the field information for non-select statements
1709
like SHOW and DESCRIBE commands
1711
if (!(stmt->fields= (MYSQL_FIELD *) alloc_root(alloc,
1712
sizeof(MYSQL_FIELD) *
1713
stmt->field_count)) ||
1714
!(stmt->bind= (MYSQL_BIND *) alloc_root(alloc,
1715
sizeof(MYSQL_BIND) *
1716
stmt->field_count)))
1719
for (fields= mysql->fields, end= fields+stmt->field_count,
1720
field= stmt->fields;
1721
field && fields < end; fields++, field++)
1723
field->db = strdup_root(alloc,fields->db);
1724
field->table = strdup_root(alloc,fields->table);
1725
field->org_table= strdup_root(alloc,fields->org_table);
1726
field->name = strdup_root(alloc,fields->name);
1727
field->org_name = strdup_root(alloc,fields->org_name);
1728
field->charsetnr= fields->charsetnr;
1729
field->length = fields->length;
1730
field->type = fields->type;
1731
field->flags = fields->flags;
1732
field->decimals = fields->decimals;
1733
field->def = fields->def ? strdup_root(alloc,fields->def): 0;
1734
field->max_length= 0;
1736
return stmt->field_count;
1741
Update result set columns metadata if it was sent again in
1742
reply to COM_STMT_EXECUTE.
1745
static void update_stmt_fields(MYSQL_STMT *stmt)
1747
MYSQL_FIELD *field= stmt->mysql->fields;
1748
MYSQL_FIELD *field_end= field + stmt->field_count;
1749
MYSQL_FIELD *stmt_field= stmt->fields;
1750
MYSQL_BIND *my_bind= stmt->bind_result_done ? stmt->bind : 0;
1752
DBUG_ASSERT(stmt->field_count == stmt->mysql->field_count);
1754
for (; field < field_end; ++field, ++stmt_field)
1756
stmt_field->charsetnr= field->charsetnr;
1757
stmt_field->length = field->length;
1758
stmt_field->type = field->type;
1759
stmt_field->flags = field->flags;
1760
stmt_field->decimals = field->decimals;
1763
/* Ignore return value: it should be 0 if bind_result succeeded. */
1764
(void) setup_one_fetch_function(my_bind++, stmt_field);
1770
Returns prepared statement metadata in the form of a result set.
1773
mysql_stmt_result_metadata()
1774
stmt statement handle
1777
This function should be used after mysql_stmt_execute().
1778
You can safely check that prepared statement has a result set by calling
1779
mysql_stmt_field_count(): if number of fields is not zero, you can call
1780
this function to get fields metadata.
1781
Next steps you may want to make:
1782
- find out number of columns in result set by calling
1783
mysql_num_fields(res) (the same value is returned by
1784
mysql_stmt_field_count())
1785
- fetch metadata for any column with mysql_fetch_field,
1786
mysql_fetch_field_direct, mysql_fetch_fields, mysql_field_seek.
1787
- free returned MYSQL_RES structure with mysql_free_result.
1788
- proceed to binding of output parameters.
1791
NULL statement contains no result set or out of memory.
1792
In the latter case you can retreive error message
1793
with mysql_stmt_error.
1794
MYSQL_RES a result set with no rows
1798
mysql_stmt_result_metadata(MYSQL_STMT *stmt)
1801
DBUG_ENTER("mysql_stmt_result_metadata");
1804
stmt->fields is only defined if stmt->field_count is not null;
1805
stmt->field_count is initialized in prepare.
1807
if (!stmt->field_count)
1810
if (!(result=(MYSQL_RES*) my_malloc(sizeof(*result),
1811
MYF(MY_WME | MY_ZEROFILL))))
1813
set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate, NULL);
1817
result->methods= stmt->mysql->methods;
1818
result->eof= 1; /* Marker for buffered */
1819
result->fields= stmt->fields;
1820
result->field_count= stmt->field_count;
1821
/* The rest of members of 'result' was bzeroed inside malloc */
1822
DBUG_RETURN(result);
1827
Returns parameter columns meta information in the form of
1831
mysql_stmt_param_metadata()
1832
stmt statement handle
1835
This function can be called after you prepared the statement handle
1836
with mysql_stmt_prepare().
1837
XXX: not implemented yet.
1840
MYSQL_RES on success, 0 if there is no metadata.
1841
Currently this function always returns 0.
1845
mysql_stmt_param_metadata(MYSQL_STMT *stmt)
1847
DBUG_ENTER("mysql_stmt_param_metadata");
1849
if (!stmt->param_count)
1853
TODO: Fix this when server sends the information.
1854
Till then keep a dummy prototype.
1860
/* Store type of parameter in network buffer. */
1862
static void store_param_type(char **pos, MYSQL_BIND *param)
1864
uint typecode= param->buffer_type | (param->is_unsigned ? 32768 : 0);
1865
int2store(*pos, typecode);
1871
Functions to store parameter data in network packet.
1875
net MySQL NET connection
1876
param MySQL bind param
1879
These funtions are invoked from mysql_stmt_execute() by
1880
MYSQL_BIND::store_param_func pointer. This pointer is set once per
1881
many executions in mysql_stmt_bind_param(). The caller must ensure
1882
that network buffer have enough capacity to store parameter
1883
(MYSQL_BIND::buffer_length contains needed number of bytes).
1886
static void store_param_tinyint(NET *net, MYSQL_BIND *param)
1888
*(net->write_pos++)= *(uchar *) param->buffer;
1891
static void store_param_short(NET *net, MYSQL_BIND *param)
1893
short value= *(short*) param->buffer;
1894
int2store(net->write_pos,value);
1898
static void store_param_int32(NET *net, MYSQL_BIND *param)
1900
int32 value= *(int32*) param->buffer;
1901
int4store(net->write_pos,value);
1905
static void store_param_int64(NET *net, MYSQL_BIND *param)
1907
longlong value= *(longlong*) param->buffer;
1908
int8store(net->write_pos,value);
1912
static void store_param_float(NET *net, MYSQL_BIND *param)
1914
float value= *(float*) param->buffer;
1915
float4store(net->write_pos, value);
1919
static void store_param_double(NET *net, MYSQL_BIND *param)
1921
double value= *(double*) param->buffer;
1922
float8store(net->write_pos, value);
1926
static void store_param_time(NET *net, MYSQL_BIND *param)
1928
MYSQL_TIME *tm= (MYSQL_TIME *) param->buffer;
1929
char buff[MAX_TIME_REP_LENGTH], *pos;
1933
pos[0]= tm->neg ? 1: 0;
1934
int4store(pos+1, tm->day);
1935
pos[5]= (uchar) tm->hour;
1936
pos[6]= (uchar) tm->minute;
1937
pos[7]= (uchar) tm->second;
1938
int4store(pos+8, tm->second_part);
1939
if (tm->second_part)
1941
else if (tm->hour || tm->minute || tm->second || tm->day)
1945
buff[0]= (char) length++;
1946
memcpy((char *)net->write_pos, buff, length);
1947
net->write_pos+= length;
1950
1493
static void net_store_datetime(NET *net, MYSQL_TIME *tm)
1952
1495
char buff[MAX_DATETIME_REP_LENGTH], *pos;
1974
1517
net->write_pos+= length;
1977
static void store_param_date(NET *net, MYSQL_BIND *param)
1979
MYSQL_TIME tm= *((MYSQL_TIME *) param->buffer);
1980
tm.hour= tm.minute= tm.second= tm.second_part= 0;
1981
net_store_datetime(net, &tm);
1984
static void store_param_datetime(NET *net, MYSQL_BIND *param)
1986
MYSQL_TIME *tm= (MYSQL_TIME *) param->buffer;
1987
net_store_datetime(net, tm);
1990
static void store_param_str(NET *net, MYSQL_BIND *param)
1992
/* param->length is always set in mysql_stmt_bind_param */
1993
ulong length= *param->length;
1994
uchar *to= net_store_length(net->write_pos, length);
1995
memcpy(to, param->buffer, length);
1996
net->write_pos= to+length;
2001
Mark if the parameter is NULL.
2005
net MySQL NET connection
2006
param MySQL bind param
2009
A data package starts with a string of bits where we set a bit
2010
if a parameter is NULL. Unlike bit string in result set row, here
2011
we don't have reserved bits for OK/error packet.
2014
static void store_param_null(NET *net, MYSQL_BIND *param)
2016
uint pos= param->param_number;
2017
net->buff[pos/8]|= (uchar) (1 << (pos & 7));
2022
Store one parameter in network packet: data is read from
2023
client buffer and saved in network packet by means of one
2024
of store_param_xxxx functions.
2027
static my_bool store_param(MYSQL_STMT *stmt, MYSQL_BIND *param)
2029
NET *net= &stmt->mysql->net;
2030
DBUG_ENTER("store_param");
2031
DBUG_PRINT("enter",("type: %d buffer: 0x%lx length: %lu is_null: %d",
2033
(long) (param->buffer ? param->buffer : NullS),
2034
*param->length, *param->is_null));
2036
if (*param->is_null)
2037
store_param_null(net, param);
2041
Param->length should ALWAYS point to the correct length for the type
2042
Either to the length pointer given by the user or param->buffer_length
2044
if ((my_realloc_str(net, *param->length)))
2046
set_stmt_errmsg(stmt, net);
2049
(*param->store_param_func)(net, param);
2056
Auxilary function to send COM_STMT_EXECUTE packet to server and read reply.
2057
Used from cli_stmt_execute, which is in turn used by mysql_stmt_execute.
2060
static my_bool execute(MYSQL_STMT *stmt, char *packet, ulong length)
2062
MYSQL *mysql= stmt->mysql;
2063
NET *net= &mysql->net;
2064
uchar buff[4 /* size of stmt id */ +
2065
5 /* execution flags */];
2067
DBUG_ENTER("execute");
2068
DBUG_DUMP("packet", (uchar *) packet, length);
2070
int4store(buff, stmt->stmt_id); /* Send stmt id to server */
2071
buff[4]= (char) stmt->flags;
2072
int4store(buff+5, 1); /* iteration count */
2074
res= test(cli_advanced_command(mysql, COM_STMT_EXECUTE, buff, sizeof(buff),
2075
(uchar*) packet, length, 1, stmt) ||
2076
(*mysql->methods->read_query_result)(mysql));
2077
stmt->affected_rows= mysql->affected_rows;
2078
stmt->server_status= mysql->server_status;
2079
stmt->insert_id= mysql->insert_id;
2082
set_stmt_errmsg(stmt, net);
2089
int cli_stmt_execute(MYSQL_STMT *stmt)
2091
DBUG_ENTER("cli_stmt_execute");
2093
if (stmt->param_count)
2095
MYSQL *mysql= stmt->mysql;
2096
NET *net= &mysql->net;
2097
MYSQL_BIND *param, *param_end;
2103
if (!stmt->bind_param_done)
2105
set_stmt_error(stmt, CR_PARAMS_NOT_BOUND, unknown_sqlstate, NULL);
2108
if (mysql->status != MYSQL_STATUS_READY ||
2109
mysql->server_status & SERVER_MORE_RESULTS_EXISTS)
2111
set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate, NULL);
2115
net_clear(net, 1); /* Sets net->write_pos */
2116
/* Reserve place for null-marker bytes */
2117
null_count= (stmt->param_count+7) /8;
2118
if (my_realloc_str(net, null_count + 1))
2120
set_stmt_errmsg(stmt, net);
2123
bzero((char*) net->write_pos, null_count);
2124
net->write_pos+= null_count;
2125
param_end= stmt->params + stmt->param_count;
2127
/* In case if buffers (type) altered, indicate to server */
2128
*(net->write_pos)++= (uchar) stmt->send_types_to_server;
2129
if (stmt->send_types_to_server)
2131
if (my_realloc_str(net, 2 * stmt->param_count))
2133
set_stmt_errmsg(stmt, net);
2137
Store types of parameters in first in first package
2138
that is sent to the server.
2140
for (param= stmt->params; param < param_end ; param++)
2141
store_param_type((char**) &net->write_pos, param);
2144
for (param= stmt->params; param < param_end; param++)
2146
/* check if mysql_stmt_send_long_data() was used */
2147
if (param->long_data_used)
2148
param->long_data_used= 0; /* Clear for next execute call */
2149
else if (store_param(stmt, param))
2152
length= (ulong) (net->write_pos - net->buff);
2153
/* TODO: Look into avoding the following memdup */
2154
if (!(param_data= my_memdup(net->buff, length, MYF(0))))
2156
set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate, NULL);
2159
result= execute(stmt, param_data, length);
2160
stmt->send_types_to_server=0;
2161
my_free(param_data, MYF(MY_WME));
2162
DBUG_RETURN(result);
2164
DBUG_RETURN((int) execute(stmt,0,0));
2168
Read one row from buffered result set. Result set is created by prior
2169
call to mysql_stmt_store_result().
2171
stmt_read_row_buffered()
2174
0 - success; *row is set to valid row pointer (row data
2175
is stored in result set buffer)
2176
MYSQL_NO_DATA - end of result set. *row is set to NULL
2179
static int stmt_read_row_buffered(MYSQL_STMT *stmt, unsigned char **row)
2181
if (stmt->data_cursor)
2183
*row= (uchar *) stmt->data_cursor->data;
2184
stmt->data_cursor= stmt->data_cursor->next;
2188
return MYSQL_NO_DATA;
2192
1521
Read one row from network: unbuffered non-cursor fetch.
2193
1522
If last row was read, or error occured, erase this statement
2330
Get/set statement attributes
2333
mysql_stmt_attr_get()
2334
mysql_stmt_attr_set()
2336
attr_type statement attribute
2337
value casted to const void * pointer to value.
2341
!0 wrong attribute type
2344
my_bool STDCALL mysql_stmt_attr_set(MYSQL_STMT *stmt,
2345
enum enum_stmt_attr_type attr_type,
2348
switch (attr_type) {
2349
case STMT_ATTR_UPDATE_MAX_LENGTH:
2350
stmt->update_max_length= value ? *(const my_bool*) value : 0;
2352
case STMT_ATTR_CURSOR_TYPE:
2355
cursor_type= value ? *(ulong*) value : 0UL;
2356
if (cursor_type > (ulong) CURSOR_TYPE_READ_ONLY)
2357
goto err_not_implemented;
2358
stmt->flags= cursor_type;
2361
case STMT_ATTR_PREFETCH_ROWS:
2363
ulong prefetch_rows= value ? *(ulong*) value : DEFAULT_PREFETCH_ROWS;
2366
stmt->prefetch_rows= prefetch_rows;
2370
goto err_not_implemented;
2373
err_not_implemented:
2374
set_stmt_error(stmt, CR_NOT_IMPLEMENTED, unknown_sqlstate, NULL);
2379
my_bool STDCALL mysql_stmt_attr_get(MYSQL_STMT *stmt,
2380
enum enum_stmt_attr_type attr_type,
2383
switch (attr_type) {
2384
case STMT_ATTR_UPDATE_MAX_LENGTH:
2385
*(my_bool*) value= stmt->update_max_length;
2387
case STMT_ATTR_CURSOR_TYPE:
2388
*(ulong*) value= stmt->flags;
2390
case STMT_ATTR_PREFETCH_ROWS:
2391
*(ulong*) value= stmt->prefetch_rows;
2401
Send placeholders data to server (if there are placeholders)
2402
and execute prepared statement.
2405
mysql_stmt_execute()
2406
stmt statement handle. The handle must be created
2407
with mysql_stmt_init() and prepared with
2408
mysql_stmt_prepare(). If there are placeholders
2409
in the statement they must be bound to local
2410
variables with mysql_stmt_bind_param().
2413
This function will automatically flush pending result
2414
set (if there is one), send parameters data to the server
2415
and read result of statement execution.
2416
If previous result set was cached with mysql_stmt_store_result()
2417
it will also be freed in the beginning of this call.
2418
The server can return 3 types of responses to this command:
2419
- error, can be retrieved with mysql_stmt_error()
2420
- ok, no result set pending. In this case we just update
2421
stmt->insert_id and stmt->affected_rows.
2422
- the query returns a result set: there could be 0 .. N
2423
rows in it. In this case the server can also send updated
2424
result set metadata.
2426
Next steps you may want to make:
2427
- find out if there is result set with mysql_stmt_field_count().
2429
- optionally, cache entire result set on client to unblock
2430
connection with mysql_stmt_store_result()
2431
- bind client variables to result set columns and start read rows
2432
with mysql_stmt_fetch().
2433
- reset statement with mysql_stmt_reset() or close it with
2436
- find out last insert id and number of affected rows with
2437
mysql_stmt_insert_id(), mysql_stmt_affected_rows()
2441
1 error, message can be retrieved with mysql_stmt_error().
2444
int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt)
2446
MYSQL *mysql= stmt->mysql;
2447
DBUG_ENTER("mysql_stmt_execute");
2451
/* Error is already set in mysql_detatch_stmt_list */
2455
if (reset_stmt_handle(stmt, RESET_STORE_RESULT))
2458
No need to check for stmt->state: if the statement wasn't
2459
prepared we'll get 'unknown statement handler' error from server.
2461
if (mysql->methods->stmt_execute(stmt))
2463
if (mysql->field_count)
2465
/* Server has sent result set metadata */
2466
if (stmt->field_count == 0)
2469
This is 'SHOW'/'EXPLAIN'-like query. Current implementation of
2470
prepared statements can't send result set metadata for these queries
2471
on prepare stage. Read it now.
2473
alloc_stmt_fields(stmt);
2478
Update result set metadata if it for some reason changed between
2479
prepare and execute, i.e.:
2480
- in case of 'SELECT ?' we don't know column type unless data was
2481
supplied to mysql_stmt_execute, so updated column type is sent
2483
- if data dictionary changed between prepare and execute, for
2484
example a table used in the query was altered.
2485
Note, that now (4.1.3) we always send metadata in reply to
2486
COM_STMT_EXECUTE (even if it is not necessary), so either this or
2487
previous branch always works.
2488
TODO: send metadata only when it's really necessary and add a warning
2489
'Metadata changed' when it's sent twice.
2491
update_stmt_fields(stmt);
2494
stmt->state= MYSQL_STMT_EXECUTE_DONE;
2495
if (stmt->field_count)
2497
if (stmt->server_status & SERVER_STATUS_CURSOR_EXISTS)
2499
mysql->status= MYSQL_STATUS_READY;
2500
stmt->read_row_func= stmt_read_row_from_cursor;
2502
else if (stmt->flags & CURSOR_TYPE_READ_ONLY)
2505
This is a single-row result set, a result set with no rows, EXPLAIN,
2506
SHOW VARIABLES, or some other command which either a) bypasses the
2507
cursors framework in the server and writes rows directly to the
2508
network or b) is more efficient if all (few) result set rows are
2509
precached on client and server's resources are freed.
2511
DBUG_RETURN(mysql_stmt_store_result(stmt));
2515
stmt->mysql->unbuffered_fetch_owner= &stmt->unbuffered_fetch_cancelled;
2516
stmt->unbuffered_fetch_cancelled= FALSE;
2517
stmt->read_row_func= stmt_read_row_unbuffered;
2525
Return total parameters count in the statement
2528
ulong STDCALL mysql_stmt_param_count(MYSQL_STMT * stmt)
2530
DBUG_ENTER("mysql_stmt_param_count");
2531
DBUG_RETURN(stmt->param_count);
2535
Return total affected rows from the last statement
2538
my_ulonglong STDCALL mysql_stmt_affected_rows(MYSQL_STMT *stmt)
2540
return stmt->affected_rows;
2545
Returns the number of result columns for the most recent query
2546
run on this statement.
2549
unsigned int STDCALL mysql_stmt_field_count(MYSQL_STMT *stmt)
2551
return stmt->field_count;
2555
Return last inserted id for auto_increment columns.
2558
mysql_stmt_insert_id()
2559
stmt statement handle
2562
Current implementation of this call has a caveat: stmt->insert_id is
2563
unconditionally updated from mysql->insert_id in the end of each
2564
mysql_stmt_execute(). This works OK if mysql->insert_id contains new
2565
value (sent in reply to mysql_stmt_execute()), otherwise stmt->insert_id
2566
value gets undefined, as it's updated from some arbitrary value saved in
2567
connection structure during some other call.
2570
my_ulonglong STDCALL mysql_stmt_insert_id(MYSQL_STMT *stmt)
2572
return stmt->insert_id;
2576
1606
static my_bool int_is_null_true= 1; /* Used for MYSQL_TYPE_NULL */
2577
1607
static my_bool int_is_null_false= 0;
2581
Set up input data buffers for a statement.
2584
mysql_stmt_bind_param()
2585
stmt statement handle
2586
The statement must be prepared with mysql_stmt_prepare().
2587
my_bind Array of mysql_stmt_param_count() bind parameters.
2588
This function doesn't check that size of this argument
2589
is >= mysql_stmt_field_count(): it's user's responsibility.
2592
Use this call after mysql_stmt_prepare() to bind user variables to
2594
Each element of bind array stands for a placeholder. Placeholders
2595
are counted from 0. For example statement
2596
'INSERT INTO t (a, b) VALUES (?, ?)'
2597
contains two placeholders, and for such statement you should supply
2598
bind array of two elements (MYSQL_BIND bind[2]).
2600
By properly initializing bind array you can bind virtually any
2601
C language type to statement's placeholders:
2602
First, it's strongly recommended to always zero-initialize entire
2603
bind structure before setting its members. This will both shorten
2604
your application code and make it robust to future extensions of
2605
MYSQL_BIND structure.
2606
Then you need to assign typecode of your application buffer to
2607
MYSQL_BIND::buffer_type. The following typecodes with their
2608
correspondence to C language types are supported:
2609
MYSQL_TYPE_TINY for 8-bit integer variables. Normally it's
2610
'signed char' and 'unsigned char';
2611
MYSQL_TYPE_SHORT for 16-bit signed and unsigned variables. This
2612
is usually 'short' and 'unsigned short';
2613
MYSQL_TYPE_LONG for 32-bit signed and unsigned variables. It
2614
corresponds to 'int' and 'unsigned int' on
2615
vast majority of platforms. On IA-32 and some
2616
other 32-bit systems you can also use 'long'
2618
MYSQL_TYPE_LONGLONG 64-bit signed or unsigned integer. Stands for
2619
'[unsigned] long long' on most platforms;
2620
MYSQL_TYPE_FLOAT 32-bit floating point type, 'float' on most
2622
MYSQL_TYPE_DOUBLE 64-bit floating point type, 'double' on most
2624
MYSQL_TYPE_TIME broken-down time stored in MYSQL_TIME
2626
MYSQL_TYPE_DATE date stored in MYSQL_TIME structure
2627
MYSQL_TYPE_DATETIME datetime stored in MYSQL_TIME structure See
2628
more on how to use these types for sending
2629
dates and times below;
2630
MYSQL_TYPE_STRING character string, assumed to be in
2631
character-set-client. If character set of
2632
client is not equal to character set of
2633
column, value for this placeholder will be
2634
converted to destination character set before
2636
MYSQL_TYPE_BLOB sequence of bytes. This sequence is assumed to
2637
be in binary character set (which is the same
2638
as no particular character set), and is never
2639
converted to any other character set. See also
2640
notes about supplying string/blob length
2642
MYSQL_TYPE_NULL special typecode for binding nulls.
2643
These C/C++ types are not supported yet by the API: long double,
2646
As you can see from the list above, it's responsibility of
2647
application programmer to ensure that chosen typecode properly
2648
corresponds to host language type. For example on all platforms
2649
where we build MySQL packages (as of MySQL 4.1.4) int is a 32-bit
2650
type. So for int you can always assume that proper typecode is
2651
MYSQL_TYPE_LONG (however queer it sounds, the name is legacy of the
2652
old MySQL API). In contrary sizeof(long) can be 4 or 8 8-bit bytes,
2653
depending on platform.
2655
TODO: provide client typedefs for each integer and floating point
2656
typecode, i. e. int8, uint8, float32, etc.
2658
Once typecode was set, it's necessary to assign MYSQL_BIND::buffer
2659
to point to the buffer of given type. Finally, additional actions
2660
may be taken for some types or use cases:
2662
Binding integer types.
2663
For integer types you might also need to set MYSQL_BIND::is_unsigned
2664
member. Set it to TRUE when binding unsigned char, unsigned short,
2665
unsigned int, unsigned long, unsigned long long.
2667
Binding floating point types.
2668
For floating point types you just need to set
2669
MYSQL_BIND::buffer_type and MYSQL_BIND::buffer. The rest of the
2670
members should be zero-initialized.
2673
You might have a column always NULL, never NULL, or sometimes
2674
NULL. For an always NULL column set MYSQL_BIND::buffer_type to
2675
MYSQL_TYPE_NULL. The rest of the members just need to be
2676
zero-initialized. For never NULL columns set
2677
MYSQL_BIND::is_null to 0, or this has already been done if you
2678
zero-initialized the entire structure. If you set
2679
MYSQL_TYPE::is_null to point to an application buffer of type
2680
'my_bool', then this buffer will be checked on each execution:
2681
this way you can set the buffer to TRUE, or any non-0 value for
2682
NULLs, and to FALSE or 0 for not NULL data.
2684
Binding text strings and sequences of bytes.
2685
For strings, in addition to MYSQL_BIND::buffer_type and
2686
MYSQL_BIND::buffer you need to set MYSQL_BIND::length or
2687
MYSQL_BIND::buffer_length. If 'length' is set, 'buffer_length'
2688
is ignored. 'buffer_length' member should be used when size of
2689
string doesn't change between executions. If you want to vary
2690
buffer length for each value, set 'length' to point to an
2691
application buffer of type 'unsigned long' and set this long to
2692
length of the string before each mysql_stmt_execute().
2694
Binding dates and times.
2695
For binding dates and times prepared statements API provides
2696
clients with MYSQL_TIME structure. A pointer to instance of this
2697
structure should be assigned to MYSQL_BIND::buffer whenever
2698
MYSQL_TYPE_TIME, MYSQL_TYPE_DATE, MYSQL_TYPE_DATETIME typecodes
2699
are used. When typecode is MYSQL_TYPE_TIME, only members
2700
'hour', 'minute', 'second' and 'neg' (is time offset negative)
2701
are used. These members only will be sent to the server.
2702
MYSQL_TYPE_DATE implies use of 'year', 'month', 'day', 'neg'.
2703
MYSQL_TYPE_DATETIME utilizes both parts of MYSQL_TIME structure.
2704
You don't have to set MYSQL_TIME::time_type member: it's not
2705
used when sending data to the server, typecode information is
2706
enough. 'second_part' member can hold microsecond precision of
2707
time value, but now it's only supported on protocol level: you
2708
can't store microsecond in a column, or use in temporal
2709
calculations. However, if you send a time value with microsecond
2710
part for 'SELECT ?', statement, you'll get it back unchanged
2714
If conversion from host language type to data representation,
2715
corresponding to SQL type, is required it's done on the server.
2716
Data truncation is possible when conversion is lossy. For
2717
example, if you supply MYSQL_TYPE_DATETIME value out of valid
2718
SQL type TIMESTAMP range, the same conversion will be applied as
2719
if this value would have been sent as string in the old
2720
protocol. TODO: document how the server will behave in case of
2721
truncation/data loss.
2723
After variables were bound, you can repeatedly set/change their
2724
values and mysql_stmt_execute() the statement.
2726
See also: mysql_stmt_send_long_data() for sending long text/blob
2727
data in pieces, examples in tests/mysql_client_test.c.
2728
Next steps you might want to make:
2729
- execute statement with mysql_stmt_execute(),
2730
- reset statement using mysql_stmt_reset() or reprepare it with
2731
another query using mysql_stmt_prepare()
2732
- close statement with mysql_stmt_close().
2735
The function copies given bind array to internal storage of the
2736
statement, and sets up typecode-specific handlers to perform
2737
serialization of bound data. This means that although you don't need
2738
to call this routine after each assignment to bind buffers, you
2739
need to call it each time you change parameter typecodes, or other
2740
members of MYSQL_BIND array.
2741
This is a pure local call. Data types of client buffers are sent
2742
along with buffers' data at first execution of the statement.
2746
1 error, can be retrieved with mysql_stmt_error.
2749
my_bool STDCALL mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND *my_bind)
2752
MYSQL_BIND *param, *end;
2753
DBUG_ENTER("mysql_stmt_bind_param");
2755
if (!stmt->param_count)
2757
if ((int) stmt->state < (int) MYSQL_STMT_PREPARE_DONE)
2759
set_stmt_error(stmt, CR_NO_PREPARE_STMT, unknown_sqlstate, NULL);
2765
/* Allocated on prepare */
2766
memcpy((char*) stmt->params, (char*) my_bind,
2767
sizeof(MYSQL_BIND) * stmt->param_count);
2769
for (param= stmt->params, end= param+stmt->param_count;
2773
param->param_number= count++;
2774
param->long_data_used= 0;
2776
/* If param->is_null is not set, then the value can never be NULL */
2777
if (!param->is_null)
2778
param->is_null= &int_is_null_false;
2780
/* Setup data copy functions for the different supported types */
2781
switch (param->buffer_type) {
2782
case MYSQL_TYPE_NULL:
2783
param->is_null= &int_is_null_true;
2785
case MYSQL_TYPE_TINY:
2786
/* Force param->length as this is fixed for this type */
2787
param->length= ¶m->buffer_length;
2788
param->buffer_length= 1;
2789
param->store_param_func= store_param_tinyint;
2791
case MYSQL_TYPE_SHORT:
2792
param->length= ¶m->buffer_length;
2793
param->buffer_length= 2;
2794
param->store_param_func= store_param_short;
2796
case MYSQL_TYPE_LONG:
2797
param->length= ¶m->buffer_length;
2798
param->buffer_length= 4;
2799
param->store_param_func= store_param_int32;
2801
case MYSQL_TYPE_LONGLONG:
2802
param->length= ¶m->buffer_length;
2803
param->buffer_length= 8;
2804
param->store_param_func= store_param_int64;
2806
case MYSQL_TYPE_FLOAT:
2807
param->length= ¶m->buffer_length;
2808
param->buffer_length= 4;
2809
param->store_param_func= store_param_float;
2811
case MYSQL_TYPE_DOUBLE:
2812
param->length= ¶m->buffer_length;
2813
param->buffer_length= 8;
2814
param->store_param_func= store_param_double;
2816
case MYSQL_TYPE_TIME:
2817
param->store_param_func= store_param_time;
2818
param->buffer_length= MAX_TIME_REP_LENGTH;
2820
case MYSQL_TYPE_DATE:
2821
param->store_param_func= store_param_date;
2822
param->buffer_length= MAX_DATE_REP_LENGTH;
2824
case MYSQL_TYPE_DATETIME:
2825
case MYSQL_TYPE_TIMESTAMP:
2826
param->store_param_func= store_param_datetime;
2827
param->buffer_length= MAX_DATETIME_REP_LENGTH;
2829
case MYSQL_TYPE_TINY_BLOB:
2830
case MYSQL_TYPE_MEDIUM_BLOB:
2831
case MYSQL_TYPE_LONG_BLOB:
2832
case MYSQL_TYPE_BLOB:
2833
case MYSQL_TYPE_VARCHAR:
2834
case MYSQL_TYPE_VAR_STRING:
2835
case MYSQL_TYPE_STRING:
2836
case MYSQL_TYPE_DECIMAL:
2837
case MYSQL_TYPE_NEWDECIMAL:
2838
param->store_param_func= store_param_str;
2840
For variable length types user must set either length or
2845
strmov(stmt->sqlstate, unknown_sqlstate);
2846
sprintf(stmt->last_error,
2847
ER(stmt->last_errno= CR_UNSUPPORTED_PARAM_TYPE),
2848
param->buffer_type, count);
2852
If param->length is not given, change it to point to buffer_length.
2853
This way we can always use *param->length to get the length of data
2856
param->length= ¶m->buffer_length;
2858
/* We have to send/resend type information to MySQL */
2859
stmt->send_types_to_server= TRUE;
2860
stmt->bind_param_done= TRUE;
2865
/********************************************************************
2866
Long data implementation
2867
*********************************************************************/
2870
Send long data in pieces to the server
2873
mysql_stmt_send_long_data()
2874
stmt Statement handler
2875
param_number Parameter number (0 - N-1)
2876
data Data to send to server
2877
length Length of data to send (may be 0)
2880
This call can be used repeatedly to send long data in pieces
2881
for any string/binary placeholder. Data supplied for
2882
a placeholder is saved at server side till execute, and then
2883
used instead of value from MYSQL_BIND object. More precisely,
2884
if long data for a parameter was supplied, MYSQL_BIND object
2885
corresponding to this parameter is not sent to server. In the
2886
end of execution long data states of placeholders are reset,
2887
so next time values of such placeholders will be taken again
2888
from MYSQL_BIND array.
2889
The server does not reply to this call: if there was an error
2890
in data handling (which now only can happen if server run out
2891
of memory) it would be returned in reply to
2892
mysql_stmt_execute().
2893
You should choose type of long data carefully if you care
2894
about character set conversions performed by server when the
2895
statement is executed. No conversion is performed at all for
2896
MYSQL_TYPE_BLOB and other binary typecodes. For
2897
MYSQL_TYPE_STRING and the rest of text placeholders data is
2898
converted from client character set to character set of
2899
connection. If these character sets are different, this
2900
conversion may require additional memory at server, equal to
2901
total size of supplied pieces.
2909
mysql_stmt_send_long_data(MYSQL_STMT *stmt, uint param_number,
2910
const char *data, ulong length)
2913
DBUG_ENTER("mysql_stmt_send_long_data");
2914
DBUG_ASSERT(stmt != 0);
2915
DBUG_PRINT("enter",("param no: %d data: 0x%lx, length : %ld",
2916
param_number, (long) data, length));
2919
We only need to check for stmt->param_count, if it's not null
2922
if (param_number >= stmt->param_count)
2924
set_stmt_error(stmt, CR_INVALID_PARAMETER_NO, unknown_sqlstate, NULL);
2928
param= stmt->params+param_number;
2929
if (!IS_LONGDATA(param->buffer_type))
2931
/* Long data handling should be used only for string/binary types */
2932
strmov(stmt->sqlstate, unknown_sqlstate);
2933
sprintf(stmt->last_error, ER(stmt->last_errno= CR_INVALID_BUFFER_USE),
2934
param->param_number);
2939
Send long data packet if there is data or we're sending long data
2942
if (length || param->long_data_used == 0)
2944
MYSQL *mysql= stmt->mysql;
2945
/* Packet header: stmt id (4 bytes), param no (2 bytes) */
2946
uchar buff[MYSQL_LONG_DATA_HEADER];
2948
int4store(buff, stmt->stmt_id);
2949
int2store(buff + 4, param_number);
2950
param->long_data_used= 1;
2953
Note that we don't get any ok packet from the server in this case
2954
This is intentional to save bandwidth.
2956
if ((*mysql->methods->advanced_command)(mysql, COM_STMT_SEND_LONG_DATA,
2957
buff, sizeof(buff), (uchar*) data,
2960
set_stmt_errmsg(stmt, &mysql->net);
2968
1609
/********************************************************************
2969
1610
Fetch and conversion of result set rows (binary protocol).
2970
1611
*********************************************************************/
3072
Convert string to supplied buffer of any type.
3075
fetch_string_with_conversion()
3076
param output buffer descriptor
3081
static void fetch_string_with_conversion(MYSQL_BIND *param, char *value,
3084
char *buffer= (char *)param->buffer;
3086
char *endptr= value + length;
3089
This function should support all target buffer types: the rest
3090
of conversion functions can delegate conversion to it.
3092
switch (param->buffer_type) {
3093
case MYSQL_TYPE_NULL: /* do nothing */
3095
case MYSQL_TYPE_TINY:
3097
longlong data= my_strtoll10(value, &endptr, &err);
3098
*param->error= (IS_TRUNCATED(data, param->is_unsigned,
3099
INT_MIN8, INT_MAX8, UINT_MAX8) || err > 0);
3100
*buffer= (uchar) data;
3103
case MYSQL_TYPE_SHORT:
3105
longlong data= my_strtoll10(value, &endptr, &err);
3106
*param->error= (IS_TRUNCATED(data, param->is_unsigned,
3107
INT_MIN16, INT_MAX16, UINT_MAX16) || err > 0);
3108
shortstore(buffer, (short) data);
3111
case MYSQL_TYPE_LONG:
3113
longlong data= my_strtoll10(value, &endptr, &err);
3114
*param->error= (IS_TRUNCATED(data, param->is_unsigned,
3115
INT_MIN32, INT_MAX32, UINT_MAX32) || err > 0);
3116
longstore(buffer, (int32) data);
3119
case MYSQL_TYPE_LONGLONG:
3121
longlong data= my_strtoll10(value, &endptr, &err);
3122
*param->error= param->is_unsigned ? err != 0 :
3123
(err > 0 || (err == 0 && data < 0));
3124
longlongstore(buffer, data);
3127
case MYSQL_TYPE_FLOAT:
3129
double data= my_strntod(&my_charset_latin1, value, length, &endptr, &err);
3130
float fdata= (float) data;
3131
*param->error= (fdata != data) | test(err);
3132
floatstore(buffer, fdata);
3135
case MYSQL_TYPE_DOUBLE:
3137
double data= my_strntod(&my_charset_latin1, value, length, &endptr, &err);
3138
*param->error= test(err);
3139
doublestore(buffer, data);
3142
case MYSQL_TYPE_TIME:
3144
MYSQL_TIME *tm= (MYSQL_TIME *)buffer;
3145
str_to_time(value, length, tm, &err);
3146
*param->error= test(err);
3149
case MYSQL_TYPE_DATE:
3150
case MYSQL_TYPE_DATETIME:
3151
case MYSQL_TYPE_TIMESTAMP:
3153
MYSQL_TIME *tm= (MYSQL_TIME *)buffer;
3154
(void) str_to_datetime(value, length, tm, TIME_FUZZY_DATE, &err);
3155
*param->error= test(err) && (param->buffer_type == MYSQL_TYPE_DATE &&
3156
tm->time_type != MYSQL_TIMESTAMP_DATE);
3159
case MYSQL_TYPE_TINY_BLOB:
3160
case MYSQL_TYPE_MEDIUM_BLOB:
3161
case MYSQL_TYPE_LONG_BLOB:
3162
case MYSQL_TYPE_BLOB:
3163
case MYSQL_TYPE_DECIMAL:
3164
case MYSQL_TYPE_NEWDECIMAL:
3168
Copy column data to the buffer taking into account offset,
3169
data length and buffer length.
3171
char *start= value + param->offset;
3172
char *end= value + length;
3176
copy_length= end - start;
3177
/* We've got some data beyond offset: copy up to buffer_length bytes */
3178
if (param->buffer_length)
3179
memcpy(buffer, start, min(copy_length, param->buffer_length));
3183
if (copy_length < param->buffer_length)
3184
buffer[copy_length]= '\0';
3185
*param->error= copy_length > param->buffer_length;
3187
param->length will always contain length of entire column;
3188
number of copied bytes may be way different:
3190
*param->length= length;
3198
Convert integer value to client buffer of any type.
3201
fetch_long_with_conversion()
3202
param output buffer descriptor
3203
field column metadata
3207
static void fetch_long_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field,
3208
longlong value, my_bool is_unsigned)
3210
char *buffer= (char *)param->buffer;
3212
switch (param->buffer_type) {
3213
case MYSQL_TYPE_NULL: /* do nothing */
3215
case MYSQL_TYPE_TINY:
3216
*param->error= IS_TRUNCATED(value, param->is_unsigned,
3217
INT_MIN8, INT_MAX8, UINT_MAX8);
3218
*(uchar *)param->buffer= (uchar) value;
3220
case MYSQL_TYPE_SHORT:
3221
*param->error= IS_TRUNCATED(value, param->is_unsigned,
3222
INT_MIN16, INT_MAX16, UINT_MAX16);
3223
shortstore(buffer, (short) value);
3225
case MYSQL_TYPE_LONG:
3226
*param->error= IS_TRUNCATED(value, param->is_unsigned,
3227
INT_MIN32, INT_MAX32, UINT_MAX32);
3228
longstore(buffer, (int32) value);
3230
case MYSQL_TYPE_LONGLONG:
3231
longlongstore(buffer, value);
3232
*param->error= param->is_unsigned != is_unsigned && value < 0;
3234
case MYSQL_TYPE_FLOAT:
3237
We need to mark the local variable volatile to
3238
workaround Intel FPU executive precision feature.
3239
(See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=323 for details)
3241
volatile float data;
3244
data= (float) ulonglong2double(value);
3245
*param->error= ((ulonglong) value) != ((ulonglong) data);
3250
*param->error= value != ((longlong) data);
3252
floatstore(buffer, data);
3255
case MYSQL_TYPE_DOUBLE:
3257
volatile double data;
3260
data= ulonglong2double(value);
3261
*param->error= ((ulonglong) value) != ((ulonglong) data);
3265
data= (double)value;
3266
*param->error= value != ((longlong) data);
3268
doublestore(buffer, data);
3271
case MYSQL_TYPE_TIME:
3272
case MYSQL_TYPE_DATE:
3273
case MYSQL_TYPE_TIMESTAMP:
3274
case MYSQL_TYPE_DATETIME:
3277
value= number_to_datetime(value, (MYSQL_TIME *) buffer, TIME_FUZZY_DATE,
3279
*param->error= test(error);
3284
uchar buff[22]; /* Enough for longlong */
3285
uchar *end= (uchar*) longlong10_to_str(value, (char*) buff,
3286
is_unsigned ? 10: -10);
3287
/* Resort to string conversion which supports all typecodes */
3288
uint length= (uint) (end-buff);
3290
if (field->flags & ZEROFILL_FLAG && length < field->length &&
3293
bmove_upp(buff+field->length,buff+length, length);
3294
bfill(buff, field->length - length,'0');
3295
length= field->length;
3297
fetch_string_with_conversion(param, (char*) buff, length);
3304
Convert double/float column to supplied buffer of any type.
3307
fetch_float_with_conversion()
3308
param output buffer descriptor
3309
field column metadata
3311
type either MY_GCVT_ARG_FLOAT or MY_GCVT_ARG_DOUBLE.
3312
Affects the maximum number of significant digits
3313
returned by my_gcvt().
3316
static void fetch_float_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field,
3317
double value, my_gcvt_arg_type type)
3319
char *buffer= (char *)param->buffer;
3320
double val64 = (value < 0 ? -floor(-value) : floor(value));
3322
switch (param->buffer_type) {
3323
case MYSQL_TYPE_NULL: /* do nothing */
3325
case MYSQL_TYPE_TINY:
3327
We need to _store_ data in the buffer before the truncation check to
3328
workaround Intel FPU executive precision feature.
3329
(See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=323 for details)
3330
Sic: AFAIU it does not guarantee to work.
3332
if (param->is_unsigned)
3333
*buffer= (uint8) value;
3335
*buffer= (int8) value;
3336
*param->error= val64 != (param->is_unsigned ? (double)((uint8) *buffer) :
3337
(double)((int8) *buffer));
3339
case MYSQL_TYPE_SHORT:
3340
if (param->is_unsigned)
3342
ushort data= (ushort) value;
3343
shortstore(buffer, data);
3347
short data= (short) value;
3348
shortstore(buffer, data);
3350
*param->error= val64 != (param->is_unsigned ? (double) (*(ushort*) buffer):
3351
(double) (*(short*) buffer));
3353
case MYSQL_TYPE_LONG:
3354
if (param->is_unsigned)
3356
uint32 data= (uint32) value;
3357
longstore(buffer, data);
3361
int32 data= (int32) value;
3362
longstore(buffer, data);
3364
*param->error= val64 != (param->is_unsigned ? (double) (*(uint32*) buffer):
3365
(double) (*(int32*) buffer));
3367
case MYSQL_TYPE_LONGLONG:
3368
if (param->is_unsigned)
3370
ulonglong data= (ulonglong) value;
3371
longlongstore(buffer, data);
3375
longlong data= (longlong) value;
3376
longlongstore(buffer, data);
3378
*param->error= val64 != (param->is_unsigned ?
3379
ulonglong2double(*(ulonglong*) buffer) :
3380
(double) (*(longlong*) buffer));
3382
case MYSQL_TYPE_FLOAT:
3384
float data= (float) value;
3385
floatstore(buffer, data);
3386
*param->error= (*(float*) buffer) != value;
3389
case MYSQL_TYPE_DOUBLE:
3391
doublestore(buffer, value);
3397
Resort to fetch_string_with_conversion: this should handle
3398
floating point -> string conversion nicely, honor all typecodes
3399
and param->offset possibly set in mysql_stmt_fetch_column
3401
char buff[FLOATING_POINT_BUFFER];
3403
if (field->decimals >= NOT_FIXED_DEC)
3404
len= my_gcvt(value, type,
3405
(int) min(sizeof(buff)-1, param->buffer_length),
3408
len= my_fcvt(value, (int) field->decimals, buff, NULL);
3410
if (field->flags & ZEROFILL_FLAG && len < field->length &&
3411
field->length < MAX_DOUBLE_STRING_REP_LENGTH - 1)
3413
bmove_upp((uchar*) buff + field->length, (uchar*) buff + len,
3415
bfill((char*) buff, field->length - len, '0');
3418
fetch_string_with_conversion(param, buff, len);
3427
Fetch time/date/datetime to supplied buffer of any type
3430
param output buffer descriptor
3434
static void fetch_datetime_with_conversion(MYSQL_BIND *param,
3436
MYSQL_TIME *my_time)
3438
switch (param->buffer_type) {
3439
case MYSQL_TYPE_NULL: /* do nothing */
3441
case MYSQL_TYPE_DATE:
3442
*(MYSQL_TIME *)(param->buffer)= *my_time;
3443
*param->error= my_time->time_type != MYSQL_TIMESTAMP_DATE;
3445
case MYSQL_TYPE_TIME:
3446
*(MYSQL_TIME *)(param->buffer)= *my_time;
3447
*param->error= my_time->time_type != MYSQL_TIMESTAMP_TIME;
3449
case MYSQL_TYPE_DATETIME:
3450
case MYSQL_TYPE_TIMESTAMP:
3451
*(MYSQL_TIME *)(param->buffer)= *my_time;
3452
/* No error: time and date are compatible with datetime */
3454
case MYSQL_TYPE_YEAR:
3455
shortstore(param->buffer, my_time->year);
3458
case MYSQL_TYPE_FLOAT:
3459
case MYSQL_TYPE_DOUBLE:
3461
ulonglong value= TIME_to_ulonglong(my_time);
3462
fetch_float_with_conversion(param, field,
3463
ulonglong2double(value), MY_GCVT_ARG_DOUBLE);
3466
case MYSQL_TYPE_TINY:
3467
case MYSQL_TYPE_SHORT:
3468
case MYSQL_TYPE_INT24:
3469
case MYSQL_TYPE_LONG:
3470
case MYSQL_TYPE_LONGLONG:
3472
longlong value= (longlong) TIME_to_ulonglong(my_time);
3473
fetch_long_with_conversion(param, field, value, TRUE);
3479
Convert time value to string and delegate the rest to
3480
fetch_string_with_conversion:
3482
char buff[MAX_DATE_STRING_REP_LENGTH];
3483
uint length= my_TIME_to_str(my_time, buff);
3484
/* Resort to string conversion */
3485
fetch_string_with_conversion(param, (char *)buff, length);
3493
Fetch and convert result set column to output buffer.
3496
fetch_result_with_conversion()
3497
param output buffer descriptor
3498
field column metadata
3499
row points to a column of result set tuple in binary format
3502
This is a fallback implementation of column fetch used
3503
if column and output buffer types do not match.
3504
Increases tuple pointer to point at the next column within the
3508
static void fetch_result_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field,
3511
enum enum_field_types field_type= field->type;
3512
uint field_is_unsigned= field->flags & UNSIGNED_FLAG;
3514
switch (field_type) {
3515
case MYSQL_TYPE_TINY:
3518
/* sic: we need to cast to 'signed char' as 'char' may be unsigned */
3519
longlong data= field_is_unsigned ? (longlong) value :
3520
(longlong) (signed char) value;
3521
fetch_long_with_conversion(param, field, data, 0);
3525
case MYSQL_TYPE_SHORT:
3526
case MYSQL_TYPE_YEAR:
3528
short value= sint2korr(*row);
3529
longlong data= field_is_unsigned ? (longlong) (unsigned short) value :
3531
fetch_long_with_conversion(param, field, data, 0);
3535
case MYSQL_TYPE_INT24: /* mediumint is sent as 4 bytes int */
3536
case MYSQL_TYPE_LONG:
3538
int32 value= sint4korr(*row);
3539
longlong data= field_is_unsigned ? (longlong) (uint32) value :
3541
fetch_long_with_conversion(param, field, data, 0);
3545
case MYSQL_TYPE_LONGLONG:
3547
longlong value= (longlong)sint8korr(*row);
3548
fetch_long_with_conversion(param, field, value,
3549
field->flags & UNSIGNED_FLAG);
3553
case MYSQL_TYPE_FLOAT:
3556
float4get(value,*row);
3557
fetch_float_with_conversion(param, field, value, MY_GCVT_ARG_FLOAT);
3561
case MYSQL_TYPE_DOUBLE:
3564
float8get(value,*row);
3565
fetch_float_with_conversion(param, field, value, MY_GCVT_ARG_DOUBLE);
3569
case MYSQL_TYPE_DATE:
3573
read_binary_date(&tm, row);
3574
fetch_datetime_with_conversion(param, field, &tm);
3577
case MYSQL_TYPE_TIME:
3581
read_binary_time(&tm, row);
3582
fetch_datetime_with_conversion(param, field, &tm);
3585
case MYSQL_TYPE_DATETIME:
3586
case MYSQL_TYPE_TIMESTAMP:
3590
read_binary_datetime(&tm, row);
3591
fetch_datetime_with_conversion(param, field, &tm);
3596
ulong length= net_field_length(row);
3597
fetch_string_with_conversion(param, (char*) *row, length);
3606
Functions to fetch data to application buffers without conversion.
3608
All functions have the following characteristics:
3612
param MySQL bind param
3616
These are no-conversion functions, used in binary protocol to store
3617
rows in application buffers. A function used only if type of binary data
3618
is compatible with type of application buffer.
3624
static void fetch_result_tinyint(MYSQL_BIND *param, MYSQL_FIELD *field,
3627
my_bool field_is_unsigned= test(field->flags & UNSIGNED_FLAG);
3629
*(uchar *)param->buffer= data;
3630
*param->error= param->is_unsigned != field_is_unsigned && data > INT_MAX8;
3634
static void fetch_result_short(MYSQL_BIND *param, MYSQL_FIELD *field,
3637
my_bool field_is_unsigned= test(field->flags & UNSIGNED_FLAG);
3638
ushort data= (ushort) sint2korr(*row);
3639
shortstore(param->buffer, data);
3640
*param->error= param->is_unsigned != field_is_unsigned && data > INT_MAX16;
3644
static void fetch_result_int32(MYSQL_BIND *param,
3645
MYSQL_FIELD *field __attribute__((unused)),
3648
my_bool field_is_unsigned= test(field->flags & UNSIGNED_FLAG);
3649
uint32 data= (uint32) sint4korr(*row);
3650
longstore(param->buffer, data);
3651
*param->error= param->is_unsigned != field_is_unsigned && data > INT_MAX32;
3655
static void fetch_result_int64(MYSQL_BIND *param,
3656
MYSQL_FIELD *field __attribute__((unused)),
3659
my_bool field_is_unsigned= test(field->flags & UNSIGNED_FLAG);
3660
ulonglong data= (ulonglong) sint8korr(*row);
3661
*param->error= param->is_unsigned != field_is_unsigned && data > LONGLONG_MAX;
3662
longlongstore(param->buffer, data);
3666
static void fetch_result_float(MYSQL_BIND *param,
3667
MYSQL_FIELD *field __attribute__((unused)),
3671
float4get(value,*row);
3672
floatstore(param->buffer, value);
3676
static void fetch_result_double(MYSQL_BIND *param,
3677
MYSQL_FIELD *field __attribute__((unused)),
3681
float8get(value,*row);
3682
doublestore(param->buffer, value);
3686
static void fetch_result_time(MYSQL_BIND *param,
3687
MYSQL_FIELD *field __attribute__((unused)),
3690
MYSQL_TIME *tm= (MYSQL_TIME *)param->buffer;
3691
read_binary_time(tm, row);
3694
static void fetch_result_date(MYSQL_BIND *param,
3695
MYSQL_FIELD *field __attribute__((unused)),
3698
MYSQL_TIME *tm= (MYSQL_TIME *)param->buffer;
3699
read_binary_date(tm, row);
3702
static void fetch_result_datetime(MYSQL_BIND *param,
3703
MYSQL_FIELD *field __attribute__((unused)),
3706
MYSQL_TIME *tm= (MYSQL_TIME *)param->buffer;
3707
read_binary_datetime(tm, row);
3710
static void fetch_result_bin(MYSQL_BIND *param,
3711
MYSQL_FIELD *field __attribute__((unused)),
3714
ulong length= net_field_length(row);
3715
ulong copy_length= min(length, param->buffer_length);
3716
memcpy(param->buffer, (char *)*row, copy_length);
3717
*param->length= length;
3718
*param->error= copy_length < length;
3722
static void fetch_result_str(MYSQL_BIND *param,
3723
MYSQL_FIELD *field __attribute__((unused)),
3726
ulong length= net_field_length(row);
3727
ulong copy_length= min(length, param->buffer_length);
3728
memcpy(param->buffer, (char *)*row, copy_length);
3729
/* Add an end null if there is room in the buffer */
3730
if (copy_length != param->buffer_length)
3731
((uchar *)param->buffer)[copy_length]= '\0';
3732
*param->length= length; /* return total length */
3733
*param->error= copy_length < length;
3739
functions to calculate max lengths for strings during
3740
mysql_stmt_store_result()
3743
static void skip_result_fixed(MYSQL_BIND *param,
3744
MYSQL_FIELD *field __attribute__((unused)),
3748
(*row)+= param->pack_length;
3752
static void skip_result_with_length(MYSQL_BIND *param __attribute__((unused)),
3753
MYSQL_FIELD *field __attribute__((unused)),
3757
ulong length= net_field_length(row);
3762
static void skip_result_string(MYSQL_BIND *param __attribute__((unused)),
3767
ulong length= net_field_length(row);
3769
if (field->max_length < length)
3770
field->max_length= length;
3775
1713
Check that two field types are binary compatible i. e.
3776
1714
have equal representation in the binary protocol and
3777
1715
require client-side buffers of the same type.
3823
Setup a fetch function for one column of a result set.
3826
setup_one_fetch_function()
3827
param output buffer descriptor
3828
field column descriptor
3831
When user binds result set buffers or when result set
3832
metadata is changed, we need to setup fetch (and possibly
3833
conversion) functions for all columns of the result set.
3834
In addition to that here we set up skip_result function, used
3835
to update result set metadata in case when
3836
STMT_ATTR_UPDATE_MAX_LENGTH attribute is set.
3837
Notice that while fetch_result is chosen depending on both
3838
field->type and param->type, skip_result depends on field->type
3842
TRUE fetch function for this typecode was not found (typecode
3843
is not supported by the client library)
3847
static my_bool setup_one_fetch_function(MYSQL_BIND *param, MYSQL_FIELD *field)
3849
DBUG_ENTER("setup_one_fetch_function");
3851
/* Setup data copy functions for the different supported types */
3852
switch (param->buffer_type) {
3853
case MYSQL_TYPE_NULL: /* for dummy binds */
3855
It's not binary compatible with anything the server can return:
3856
no need to setup fetch_result, as it'll be reset anyway
3860
case MYSQL_TYPE_TINY:
3861
param->fetch_result= fetch_result_tinyint;
3864
case MYSQL_TYPE_SHORT:
3865
case MYSQL_TYPE_YEAR:
3866
param->fetch_result= fetch_result_short;
3869
case MYSQL_TYPE_INT24:
3870
case MYSQL_TYPE_LONG:
3871
param->fetch_result= fetch_result_int32;
3874
case MYSQL_TYPE_LONGLONG:
3875
param->fetch_result= fetch_result_int64;
3878
case MYSQL_TYPE_FLOAT:
3879
param->fetch_result= fetch_result_float;
3882
case MYSQL_TYPE_DOUBLE:
3883
param->fetch_result= fetch_result_double;
3886
case MYSQL_TYPE_TIME:
3887
param->fetch_result= fetch_result_time;
3888
*param->length= sizeof(MYSQL_TIME);
3890
case MYSQL_TYPE_DATE:
3891
param->fetch_result= fetch_result_date;
3892
*param->length= sizeof(MYSQL_TIME);
3894
case MYSQL_TYPE_DATETIME:
3895
case MYSQL_TYPE_TIMESTAMP:
3896
param->fetch_result= fetch_result_datetime;
3897
*param->length= sizeof(MYSQL_TIME);
3899
case MYSQL_TYPE_TINY_BLOB:
3900
case MYSQL_TYPE_MEDIUM_BLOB:
3901
case MYSQL_TYPE_LONG_BLOB:
3902
case MYSQL_TYPE_BLOB:
3903
case MYSQL_TYPE_BIT:
3904
DBUG_ASSERT(param->buffer_length != 0);
3905
param->fetch_result= fetch_result_bin;
3907
case MYSQL_TYPE_VAR_STRING:
3908
case MYSQL_TYPE_STRING:
3909
case MYSQL_TYPE_DECIMAL:
3910
case MYSQL_TYPE_NEWDECIMAL:
3911
case MYSQL_TYPE_NEWDATE:
3912
DBUG_ASSERT(param->buffer_length != 0);
3913
param->fetch_result= fetch_result_str;
3916
DBUG_PRINT("error", ("Unknown param->buffer_type: %u",
3917
(uint) param->buffer_type));
3920
if (! is_binary_compatible(param->buffer_type, field->type))
3921
param->fetch_result= fetch_result_with_conversion;
3923
/* Setup skip_result functions (to calculate max_length) */
3924
param->skip_result= skip_result_fixed;
3925
switch (field->type) {
3926
case MYSQL_TYPE_NULL: /* for dummy binds */
3927
param->pack_length= 0;
3928
field->max_length= 0;
3930
case MYSQL_TYPE_TINY:
3931
param->pack_length= 1;
3932
field->max_length= 4; /* as in '-127' */
3934
case MYSQL_TYPE_YEAR:
3935
case MYSQL_TYPE_SHORT:
3936
param->pack_length= 2;
3937
field->max_length= 6; /* as in '-32767' */
3939
case MYSQL_TYPE_INT24:
3940
field->max_length= 9; /* as in '16777216' or in '-8388607' */
3941
param->pack_length= 4;
3943
case MYSQL_TYPE_LONG:
3944
field->max_length= 11; /* '-2147483647' */
3945
param->pack_length= 4;
3947
case MYSQL_TYPE_LONGLONG:
3948
field->max_length= 21; /* '18446744073709551616' */
3949
param->pack_length= 8;
3951
case MYSQL_TYPE_FLOAT:
3952
param->pack_length= 4;
3953
field->max_length= MAX_DOUBLE_STRING_REP_LENGTH;
3955
case MYSQL_TYPE_DOUBLE:
3956
param->pack_length= 8;
3957
field->max_length= MAX_DOUBLE_STRING_REP_LENGTH;
3959
case MYSQL_TYPE_TIME:
3960
field->max_length= 15; /* 19:23:48.123456 */
3961
param->skip_result= skip_result_with_length;
3962
case MYSQL_TYPE_DATE:
3963
field->max_length= 10; /* 2003-11-11 */
3964
param->skip_result= skip_result_with_length;
3967
case MYSQL_TYPE_DATETIME:
3968
case MYSQL_TYPE_TIMESTAMP:
3969
param->skip_result= skip_result_with_length;
3970
field->max_length= MAX_DATE_STRING_REP_LENGTH;
3972
case MYSQL_TYPE_DECIMAL:
3973
case MYSQL_TYPE_NEWDECIMAL:
3974
case MYSQL_TYPE_ENUM:
3975
case MYSQL_TYPE_SET:
3976
case MYSQL_TYPE_GEOMETRY:
3977
case MYSQL_TYPE_TINY_BLOB:
3978
case MYSQL_TYPE_MEDIUM_BLOB:
3979
case MYSQL_TYPE_LONG_BLOB:
3980
case MYSQL_TYPE_BLOB:
3981
case MYSQL_TYPE_VAR_STRING:
3982
case MYSQL_TYPE_STRING:
3983
case MYSQL_TYPE_BIT:
3984
case MYSQL_TYPE_NEWDATE:
3985
param->skip_result= skip_result_string;
3988
DBUG_PRINT("error", ("Unknown field->type: %u", (uint) field->type));
3996
Setup the bind buffers for resultset processing
3999
my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *my_bind)
4001
MYSQL_BIND *param, *end;
4003
ulong bind_count= stmt->field_count;
4004
uint param_count= 0;
4005
DBUG_ENTER("mysql_stmt_bind_result");
4006
DBUG_PRINT("enter",("field_count: %lu", bind_count));
4010
int errorcode= (int) stmt->state < (int) MYSQL_STMT_PREPARE_DONE ?
4011
CR_NO_PREPARE_STMT : CR_NO_STMT_METADATA;
4012
set_stmt_error(stmt, errorcode, unknown_sqlstate, NULL);
4017
We only need to check that stmt->field_count - if it is not null
4018
stmt->bind was initialized in mysql_stmt_prepare
4019
stmt->bind overlaps with bind if mysql_stmt_bind_param
4020
is called from mysql_stmt_store_result.
4023
if (stmt->bind != my_bind)
4024
memcpy((char*) stmt->bind, (char*) my_bind,
4025
sizeof(MYSQL_BIND) * bind_count);
4027
for (param= stmt->bind, end= param + bind_count, field= stmt->fields ;
4031
DBUG_PRINT("info",("buffer_type: %u field_type: %u",
4032
(uint) param->buffer_type, (uint) field->type));
4034
Set param->is_null to point to a dummy variable if it's not set.
4035
This is to make the execute code easier
4037
if (!param->is_null)
4038
param->is_null= ¶m->is_null_value;
4041
param->length= ¶m->length_value;
4044
param->error= ¶m->error_value;
4046
param->param_number= param_count++;
4049
if (setup_one_fetch_function(param, field))
4051
strmov(stmt->sqlstate, unknown_sqlstate);
4052
sprintf(stmt->last_error,
4053
ER(stmt->last_errno= CR_UNSUPPORTED_PARAM_TYPE),
4054
field->type, param_count);
4058
stmt->bind_result_done= BIND_RESULT_DONE;
4059
if (stmt->mysql->options.report_data_truncation)
4060
stmt->bind_result_done|= REPORT_DATA_TRUNCATION;
4067
Fetch row data to bind buffers
4070
static int stmt_fetch_row(MYSQL_STMT *stmt, uchar *row)
4072
MYSQL_BIND *my_bind, *end;
4074
uchar *null_ptr, bit;
4075
int truncation_count= 0;
4077
Precondition: if stmt->field_count is zero or row is NULL, read_row_*
4078
function must return no data.
4080
DBUG_ASSERT(stmt->field_count);
4083
if (!stmt->bind_result_done)
4085
/* If output parameters were not bound we should just return success */
4090
row+= (stmt->field_count+9)/8; /* skip null bits */
4091
bit= 4; /* first 2 bits are reserved */
4093
/* Copy complete row to application buffers */
4094
for (my_bind= stmt->bind, end= my_bind + stmt->field_count,
4095
field= stmt->fields ;
4100
if (*null_ptr & bit)
4103
We should set both row_ptr and is_null to be able to see
4104
nulls in mysql_stmt_fetch_column. This is because is_null may point
4105
to user data which can be overwritten between mysql_stmt_fetch and
4106
mysql_stmt_fetch_column, and in this case nullness of column will be
4107
lost. See mysql_stmt_fetch_column for details.
4109
my_bind->row_ptr= NULL;
4110
*my_bind->is_null= 1;
4114
*my_bind->is_null= 0;
4115
my_bind->row_ptr= row;
4116
(*my_bind->fetch_result)(my_bind, field, &row);
4117
truncation_count+= *my_bind->error;
4119
if (!((bit<<=1) & 255))
4121
bit= 1; /* To next uchar */
4125
if (truncation_count && (stmt->bind_result_done & REPORT_DATA_TRUNCATION))
4126
return MYSQL_DATA_TRUNCATED;
4131
1760
int cli_unbuffered_fetch(MYSQL *mysql, char **row)
4133
1762
if (packet_error == cli_safe_read(mysql))
4281
1826
DBUG_RETURN(1);
4286
Update meta data for statement
4289
stmt_update_metadata()
4290
stmt Statement handler
4294
Only updates MYSQL_FIELD->max_length for strings
4297
static void stmt_update_metadata(MYSQL_STMT *stmt, MYSQL_ROWS *data)
4299
MYSQL_BIND *my_bind, *end;
4301
uchar *null_ptr, bit;
4302
uchar *row= (uchar*) data->data;
4304
uchar *row_end= row + data->length;
4308
row+= (stmt->field_count+9)/8; /* skip null bits */
4309
bit= 4; /* first 2 bits are reserved */
4311
/* Go through all fields and calculate metadata */
4312
for (my_bind= stmt->bind, end= my_bind + stmt->field_count, field= stmt->fields ;
4316
if (!(*null_ptr & bit))
4317
(*my_bind->skip_result)(my_bind, field, &row);
4318
DBUG_ASSERT(row <= row_end);
4319
if (!((bit<<=1) & 255))
4321
bit= 1; /* To next uchar */
4329
Store or buffer the binary results to stmt
4332
int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt)
4334
MYSQL *mysql= stmt->mysql;
4335
MYSQL_DATA *result= &stmt->result;
4336
DBUG_ENTER("mysql_stmt_store_result");
4340
/* mysql can be reset in mysql_close called from mysql_reconnect */
4341
set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate, NULL);
4345
if (!stmt->field_count)
4348
if ((int) stmt->state < (int) MYSQL_STMT_EXECUTE_DONE)
4350
set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate, NULL);
4354
if (mysql->status == MYSQL_STATUS_READY &&
4355
stmt->server_status & SERVER_STATUS_CURSOR_EXISTS)
4358
Server side cursor exist, tell server to start sending the rows
4360
NET *net= &mysql->net;
4361
uchar buff[4 /* statement id */ +
4362
4 /* number of rows to fetch */];
4364
/* Send row request to the server */
4365
int4store(buff, stmt->stmt_id);
4366
int4store(buff + 4, (int)~0); /* number of rows to fetch */
4367
if (cli_advanced_command(mysql, COM_STMT_FETCH, buff, sizeof(buff),
4368
(uchar*) 0, 0, 1, stmt))
4370
set_stmt_errmsg(stmt, net);
4374
else if (mysql->status != MYSQL_STATUS_GET_RESULT)
4376
set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate, NULL);
4380
if (stmt->update_max_length && !stmt->bind_result_done)
4383
We must initalize the bind structure to be able to calculate
4386
MYSQL_BIND *my_bind, *end;
4388
bzero((char*) stmt->bind, sizeof(*stmt->bind)* stmt->field_count);
4390
for (my_bind= stmt->bind, end= my_bind + stmt->field_count,
4391
field= stmt->fields;
4395
my_bind->buffer_type= MYSQL_TYPE_NULL;
4396
my_bind->buffer_length=1;
4399
if (mysql_stmt_bind_result(stmt, stmt->bind))
4401
stmt->bind_result_done= 0; /* No normal bind done */
4404
if ((*mysql->methods->read_binary_rows)(stmt))
4406
free_root(&result->alloc, MYF(MY_KEEP_PREALLOC));
4409
mysql->status= MYSQL_STATUS_READY;
4413
/* Assert that if there was a cursor, all rows have been fetched */
4414
DBUG_ASSERT(mysql->status != MYSQL_STATUS_READY ||
4415
(mysql->server_status & SERVER_STATUS_LAST_ROW_SENT));
4417
if (stmt->update_max_length)
4419
MYSQL_ROWS *cur= result->data;
4420
for(; cur; cur=cur->next)
4421
stmt_update_metadata(stmt, cur);
4424
stmt->data_cursor= result->data;
4425
mysql->affected_rows= stmt->affected_rows= result->rows;
4426
stmt->read_row_func= stmt_read_row_buffered;
4427
mysql->unbuffered_fetch_owner= 0; /* set in stmt_execute */
4428
mysql->status= MYSQL_STATUS_READY; /* server is ready */
4429
DBUG_RETURN(0); /* Data buffered, must be fetched with mysql_stmt_fetch() */
4434
Seek to desired row in the statement result set
4437
MYSQL_ROW_OFFSET STDCALL
4438
mysql_stmt_row_seek(MYSQL_STMT *stmt, MYSQL_ROW_OFFSET row)
4440
MYSQL_ROW_OFFSET offset= stmt->data_cursor;
4441
DBUG_ENTER("mysql_stmt_row_seek");
4443
stmt->data_cursor= row;
4444
DBUG_RETURN(offset);
4449
Return the current statement row cursor position
4452
MYSQL_ROW_OFFSET STDCALL
4453
mysql_stmt_row_tell(MYSQL_STMT *stmt)
4455
DBUG_ENTER("mysql_stmt_row_tell");
4457
DBUG_RETURN(stmt->data_cursor);
4462
Move the stmt result set data cursor to specified row
4466
mysql_stmt_data_seek(MYSQL_STMT *stmt, my_ulonglong row)
4468
MYSQL_ROWS *tmp= stmt->result.data;
4469
DBUG_ENTER("mysql_stmt_data_seek");
4470
DBUG_PRINT("enter",("row id to seek: %ld",(long) row));
4472
for (; tmp && row; --row, tmp= tmp->next)
4474
stmt->data_cursor= tmp;
4477
/* Rewind the counter */
4478
stmt->read_row_func= stmt_read_row_buffered;
4479
stmt->state= MYSQL_STMT_EXECUTE_DONE;
4486
Return total rows the current statement result set
4489
my_ulonglong STDCALL mysql_stmt_num_rows(MYSQL_STMT *stmt)
4491
DBUG_ENTER("mysql_stmt_num_rows");
4493
DBUG_RETURN(stmt->result.rows);
4498
Free the client side memory buffers, reset long data state
4499
on client if necessary, and reset the server side statement if
4500
this has been requested.
4503
static my_bool reset_stmt_handle(MYSQL_STMT *stmt, uint flags)
4505
/* If statement hasn't been prepared there is nothing to reset */
4506
if ((int) stmt->state > (int) MYSQL_STMT_INIT_DONE)
4508
MYSQL *mysql= stmt->mysql;
4509
MYSQL_DATA *result= &stmt->result;
4512
Reset stored result set if so was requested or it's a part
4515
if (flags & RESET_STORE_RESULT)
4517
/* Result buffered */
4518
free_root(&result->alloc, MYF(MY_KEEP_PREALLOC));
4521
stmt->data_cursor= NULL;
4523
if (flags & RESET_LONG_DATA)
4525
MYSQL_BIND *param= stmt->params, *param_end= param + stmt->param_count;
4526
/* Clear long_data_used flags */
4527
for (; param < param_end; param++)
4528
param->long_data_used= 0;
4530
stmt->read_row_func= stmt_read_row_no_result_set;
4533
if ((int) stmt->state > (int) MYSQL_STMT_PREPARE_DONE)
4535
if (mysql->unbuffered_fetch_owner == &stmt->unbuffered_fetch_cancelled)
4536
mysql->unbuffered_fetch_owner= 0;
4537
if (stmt->field_count && mysql->status != MYSQL_STATUS_READY)
4539
/* There is a result set and it belongs to this statement */
4540
(*mysql->methods->flush_use_result)(mysql);
4541
if (mysql->unbuffered_fetch_owner)
4542
*mysql->unbuffered_fetch_owner= TRUE;
4543
mysql->status= MYSQL_STATUS_READY;
4546
if (flags & RESET_SERVER_SIDE)
4549
Reset the server side statement and close the server side
4550
cursor if it exists.
4552
uchar buff[MYSQL_STMT_HEADER]; /* packet header: 4 bytes for stmt id */
4553
int4store(buff, stmt->stmt_id);
4554
if ((*mysql->methods->advanced_command)(mysql, COM_STMT_RESET, buff,
4555
sizeof(buff), 0, 0, 0, stmt))
4557
set_stmt_errmsg(stmt, &mysql->net);
4558
stmt->state= MYSQL_STMT_INIT_DONE;
4561
stmt_clear_error(stmt);
4564
stmt->state= MYSQL_STMT_PREPARE_DONE;
4569
my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt)
4571
DBUG_ENTER("mysql_stmt_free_result");
4573
/* Free the client side and close the server side cursor if there is one */
4574
DBUG_RETURN(reset_stmt_handle(stmt, RESET_LONG_DATA | RESET_STORE_RESULT));
4577
/********************************************************************
4578
statement error handling and close
4579
*********************************************************************/
4582
Close the statement handle by freeing all alloced resources
4586
stmt Statement handle
4593
my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
4595
MYSQL *mysql= stmt->mysql;
4597
DBUG_ENTER("mysql_stmt_close");
4599
free_root(&stmt->result.alloc, MYF(0));
4600
free_root(&stmt->mem_root, MYF(0));
4604
mysql->stmts= list_delete(mysql->stmts, &stmt->list);
4606
Clear NET error state: if the following commands come through
4607
successfully, connection will still be usable for other commands.
4609
net_clear_error(&mysql->net);
4610
if ((int) stmt->state > (int) MYSQL_STMT_INIT_DONE)
4612
uchar buff[MYSQL_STMT_HEADER]; /* 4 bytes - stmt id */
4614
if (mysql->unbuffered_fetch_owner == &stmt->unbuffered_fetch_cancelled)
4615
mysql->unbuffered_fetch_owner= 0;
4616
if (mysql->status != MYSQL_STATUS_READY)
4619
Flush result set of the connection. If it does not belong
4620
to this statement, set a warning.
4622
(*mysql->methods->flush_use_result)(mysql);
4623
if (mysql->unbuffered_fetch_owner)
4624
*mysql->unbuffered_fetch_owner= TRUE;
4625
mysql->status= MYSQL_STATUS_READY;
4627
int4store(buff, stmt->stmt_id);
4628
if ((rc= stmt_command(mysql, COM_STMT_CLOSE, buff, 4, stmt)))
4630
set_stmt_errmsg(stmt, &mysql->net);
4635
my_free((uchar*) stmt, MYF(MY_WME));
4637
DBUG_RETURN(test(rc));
4641
Reset the statement buffers in server
4644
my_bool STDCALL mysql_stmt_reset(MYSQL_STMT *stmt)
4646
DBUG_ENTER("mysql_stmt_reset");
4647
DBUG_ASSERT(stmt != 0);
4650
/* mysql can be reset in mysql_close called from mysql_reconnect */
4651
set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate, NULL);
4654
/* Reset the client and server sides of the prepared statement */
4655
DBUG_RETURN(reset_stmt_handle(stmt, RESET_SERVER_SIDE | RESET_LONG_DATA));
4659
Return statement error code
4662
uint STDCALL mysql_stmt_errno(MYSQL_STMT * stmt)
4664
DBUG_ENTER("mysql_stmt_errno");
4665
DBUG_RETURN(stmt->last_errno);
4668
const char *STDCALL mysql_stmt_sqlstate(MYSQL_STMT * stmt)
4670
DBUG_ENTER("mysql_stmt_sqlstate");
4671
DBUG_RETURN(stmt->sqlstate);
4675
Return statement error message
4678
const char *STDCALL mysql_stmt_error(MYSQL_STMT * stmt)
4680
DBUG_ENTER("mysql_stmt_error");
4681
DBUG_RETURN(stmt->last_error);
4685
1829
/********************************************************************
4686
1830
Transactional APIs
4687
1831
*********************************************************************/