"Fossies" - the Fresh Open Source Software Archive

Member "mariadb-connector-c-3.0.9-src/libmariadb/mariadb_stmt.c" (8 Feb 2019, 72378 Bytes) of package /linux/misc/mariadb-connector-c-3.0.9-src.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "mariadb_stmt.c": 3.0.6-src_vs_3.0.7-src.

    1 /****************************************************************************
    2   Copyright (C) 2012 Monty Program AB
    3 
    4   This library is free software; you can redistribute it and/or
    5   modify it under the terms of the GNU Library General Public
    6   License as published by the Free Software Foundation; either
    7   version 2 of the License, or (at your option) any later version.
    8 
    9   This library is distributed in the hope that it will be useful,
   10   but WITHOUT ANY WARRANTY; without even the implied warranty of
   11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   12   Library General Public License for more details.
   13 
   14   You should have received a copy of the GNU Library General Public
   15   License along with this library; if not see <http://www.gnu.org/licenses>
   16   or write to the Free Software Foundation, Inc.,
   17   51 Franklin St., Fifth Floor, Boston, MA 02110, USA
   18 
   19   Part of this code includes code from the PHP project which
   20   is freely available from http://www.php.net
   21  *****************************************************************************/
   22 
   23 /* The implementation for prepared statements was ported from PHP's mysqlnd
   24    extension, written by Andrey Hristov, Georg Richter and Ulf Wendel
   25 
   26    Original file header:
   27    +----------------------------------------------------------------------+
   28    | PHP Version 5                                                        |
   29    +----------------------------------------------------------------------+
   30    | Copyright (c) 2006-2011 The PHP Group                                |
   31    +----------------------------------------------------------------------+
   32    | This source file is subject to version 3.01 of the PHP license,      |
   33    | that is bundled with this package in the file LICENSE, and is        |
   34    | available through the world-wide-web at the following url:           |
   35    | http://www.php.net/license/3_01.txt                                  |
   36    | If you did not receive a copy of the PHP license and are unable to   |
   37    | obtain it through the world-wide-web, please send a note to          |
   38    | license@php.net so we can mail you a copy immediately.               |
   39    +----------------------------------------------------------------------+
   40    | Authors: Georg Richter <georg@mysql.com>                             |
   41    |          Andrey Hristov <andrey@mysql.com>                           |
   42    |          Ulf Wendel <uwendel@mysql.com>                              |
   43    +----------------------------------------------------------------------+
   44    */
   45 
   46 #include "ma_global.h"
   47 #include <ma_sys.h>
   48 #include <ma_string.h>
   49 #include <mariadb_ctype.h>
   50 #include "mysql.h"
   51 #include "errmsg.h"
   52 #include <ma_pvio.h>
   53 #include <sys/stat.h>
   54 #include <signal.h>
   55 #include <time.h>
   56 #include <mysql/client_plugin.h>
   57 #include <ma_common.h>
   58 
   59 #define STMT_NUM_OFS(type, a,r) ((type *)(a))[r]
   60 #define MADB_RESET_ERROR     1
   61 #define MADB_RESET_LONGDATA  2
   62 #define MADB_RESET_SERVER    4
   63 #define MADB_RESET_BUFFER    8
   64 #define MADB_RESET_STORED   16
   65 
   66 #define MAX_TIME_STR_LEN 13
   67 #define MAX_DATE_STR_LEN 5
   68 #define MAX_DATETIME_STR_LEN 12
   69 
   70 typedef struct
   71 {
   72   MA_MEM_ROOT fields_ma_alloc_root;
   73 } MADB_STMT_EXTENSION;
   74 
   75 MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, uint fields);
   76 void free_rows(MYSQL_DATA *cur);
   77 int ma_multi_command(MYSQL *mysql, enum enum_multi_status status);
   78 MYSQL_FIELD * unpack_fields(MYSQL_DATA *data,MA_MEM_ROOT *alloc,uint fields, my_bool default_value, my_bool long_flag_protocol);
   79 static my_bool net_stmt_close(MYSQL_STMT *stmt, my_bool remove);
   80 
   81 static my_bool is_not_null= 0;
   82 static my_bool is_null= 1;
   83 
   84 void stmt_set_error(MYSQL_STMT *stmt,
   85                   unsigned int error_nr,
   86                   const char *sqlstate,
   87                   const char *format,
   88                   ...)
   89 {
   90   va_list ap;
   91   const char *error= NULL;
   92 
   93   if (error_nr >= CR_MIN_ERROR && error_nr <= CR_MYSQL_LAST_ERROR)
   94     error= ER(error_nr);
   95   else if (error_nr >= CER_MIN_ERROR && error_nr <= CR_MARIADB_LAST_ERROR)
   96     error= CER(error_nr);
   97 
   98   stmt->last_errno= error_nr;
   99   ma_strmake(stmt->sqlstate, sqlstate, SQLSTATE_LENGTH);
  100   va_start(ap, format);
  101   vsnprintf(stmt->last_error, MYSQL_ERRMSG_SIZE,
  102             format ? format : error ? error : "", ap);
  103   va_end(ap);
  104   return;
  105 }
  106 
  107 my_bool mthd_supported_buffer_type(enum enum_field_types type)
  108 {
  109   switch (type) {
  110   case MYSQL_TYPE_BIT:
  111   case MYSQL_TYPE_BLOB:
  112   case MYSQL_TYPE_DATE:
  113   case MYSQL_TYPE_DATETIME:
  114   case MYSQL_TYPE_DECIMAL:
  115   case MYSQL_TYPE_DOUBLE:
  116   case MYSQL_TYPE_FLOAT:
  117   case MYSQL_TYPE_GEOMETRY:
  118   case MYSQL_TYPE_INT24:
  119   case MYSQL_TYPE_LONG:
  120   case MYSQL_TYPE_LONG_BLOB:
  121   case MYSQL_TYPE_LONGLONG:
  122   case MYSQL_TYPE_MEDIUM_BLOB:
  123   case MYSQL_TYPE_NEWDATE:
  124   case MYSQL_TYPE_NEWDECIMAL:
  125   case MYSQL_TYPE_NULL:
  126   case MYSQL_TYPE_SHORT:
  127   case MYSQL_TYPE_STRING:
  128   case MYSQL_TYPE_JSON:
  129   case MYSQL_TYPE_TIME:
  130   case MYSQL_TYPE_TIMESTAMP:
  131   case MYSQL_TYPE_TINY:
  132   case MYSQL_TYPE_TINY_BLOB:
  133   case MYSQL_TYPE_VAR_STRING:
  134   case MYSQL_TYPE_YEAR:
  135     return 1;
  136     break;
  137   default:
  138     return 0;
  139     break;
  140   }
  141 }
  142 
  143 static my_bool madb_reset_stmt(MYSQL_STMT *stmt, unsigned int flags);
  144 static my_bool mysql_stmt_internal_reset(MYSQL_STMT *stmt, my_bool is_close);
  145 static int stmt_unbuffered_eof(MYSQL_STMT *stmt __attribute__((unused)),
  146                                uchar **row __attribute__((unused)))
  147 {
  148   return MYSQL_NO_DATA;
  149 }
  150 
  151 static int stmt_unbuffered_fetch(MYSQL_STMT *stmt, uchar **row)
  152 {
  153   ulong pkt_len;
  154 
  155   pkt_len= ma_net_safe_read(stmt->mysql);
  156 
  157   if (pkt_len == packet_error)
  158   {
  159     stmt->fetch_row_func= stmt_unbuffered_eof;
  160     return(1);
  161   }
  162 
  163   if (stmt->mysql->net.read_pos[0] == 254)
  164   {
  165     *row = NULL;
  166     stmt->fetch_row_func= stmt_unbuffered_eof;
  167     return(MYSQL_NO_DATA);
  168   }
  169   else
  170     *row = stmt->mysql->net.read_pos;
  171   stmt->result.rows++;
  172   return(0);
  173 }
  174 
  175 static int stmt_buffered_fetch(MYSQL_STMT *stmt, uchar **row)
  176 {
  177   if (!stmt->result_cursor)
  178   {
  179     *row= NULL;
  180     stmt->state= MYSQL_STMT_FETCH_DONE;
  181     return MYSQL_NO_DATA;
  182   }
  183   stmt->state= MYSQL_STMT_USER_FETCHING;
  184   *row= (uchar *)stmt->result_cursor->data;
  185 
  186   stmt->result_cursor= stmt->result_cursor->next;
  187   return 0;
  188 }
  189 
  190 int mthd_stmt_read_all_rows(MYSQL_STMT *stmt)
  191 {
  192   MYSQL_DATA *result= &stmt->result;
  193   MYSQL_ROWS *current, **pprevious;
  194   ulong packet_len;
  195   unsigned char *p;
  196 
  197   pprevious= &result->data;
  198 
  199   while ((packet_len = ma_net_safe_read(stmt->mysql)) != packet_error)
  200   {
  201     p= stmt->mysql->net.read_pos;
  202     if (packet_len > 7 || p[0] != 254)
  203     {
  204       /* allocate space for rows */
  205       if (!(current= (MYSQL_ROWS *)ma_alloc_root(&result->alloc, sizeof(MYSQL_ROWS) + packet_len)))
  206       {
  207         SET_CLIENT_STMT_ERROR(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
  208         return(1);
  209       }
  210       current->data= (MYSQL_ROW)(current + 1);
  211       *pprevious= current;
  212       pprevious= &current->next;
  213 
  214       /* copy binary row, we will encode it during mysql_stmt_fetch */
  215       memcpy((char *)current->data, (char *)p, packet_len);
  216 
  217       if (stmt->update_max_length)
  218       {
  219         uchar *null_ptr, bit_offset= 4;
  220         uchar *cp= p;
  221         unsigned int i;
  222 
  223         cp++; /* skip first byte */
  224         null_ptr= cp;
  225         cp+= (stmt->field_count + 9) / 8;
  226 
  227         for (i=0; i < stmt->field_count; i++)
  228         {
  229           if (!(*null_ptr & bit_offset))
  230           {
  231             if (mysql_ps_fetch_functions[stmt->fields[i].type].pack_len < 0)
  232             {
  233               /* We need to calculate the sizes for date and time types */
  234               size_t len= net_field_length(&cp);
  235               switch(stmt->fields[i].type) {
  236               case MYSQL_TYPE_TIME:
  237               case MYSQL_TYPE_DATE:
  238               case MYSQL_TYPE_DATETIME:
  239               case MYSQL_TYPE_TIMESTAMP:
  240                 stmt->fields[i].max_length= mysql_ps_fetch_functions[stmt->fields[i].type].max_len;
  241                 break;
  242               default:
  243                 if (len > stmt->fields[i].max_length)
  244                   stmt->fields[i].max_length= (ulong)len;
  245                 break;
  246               }
  247               cp+= len;
  248             }
  249             else
  250             {
  251               if (stmt->fields[i].flags & ZEROFILL_FLAG)
  252               {
  253                 size_t len= MAX(stmt->fields[i].length, mysql_ps_fetch_functions[stmt->fields[i].type].max_len);
  254                 if (len > stmt->fields[i].max_length)
  255                   stmt->fields[i].max_length= (unsigned long)len;
  256               }
  257               else if (!stmt->fields[i].max_length)
  258               {
  259                 stmt->fields[i].max_length= mysql_ps_fetch_functions[stmt->fields[i].type].max_len;
  260               }
  261               cp+= mysql_ps_fetch_functions[stmt->fields[i].type].pack_len;
  262             }
  263           }
  264           if (!((bit_offset <<=1) & 255))
  265           {
  266             bit_offset= 1; /* To next byte */
  267             null_ptr++;
  268           }
  269         }
  270       }
  271       current->length= packet_len;
  272       result->rows++;
  273     } else  /* end of stream */
  274     {
  275       *pprevious= 0;
  276       /* sace status info */
  277       p++;
  278       stmt->upsert_status.warning_count= stmt->mysql->warning_count= uint2korr(p);
  279       p+=2;
  280       stmt->upsert_status.server_status= stmt->mysql->server_status= uint2korr(p);
  281       stmt->result_cursor= result->data;
  282       return(0);
  283     }
  284   }
  285   stmt->result_cursor= 0;
  286   SET_CLIENT_STMT_ERROR(stmt, stmt->mysql->net.last_errno, stmt->mysql->net.sqlstate,
  287       stmt->mysql->net.last_error);
  288   return(1);
  289 }
  290 
  291 static int stmt_cursor_fetch(MYSQL_STMT *stmt, uchar **row)
  292 {
  293   uchar buf[STMT_ID_LENGTH + 4];
  294   MYSQL_DATA *result= &stmt->result;
  295 
  296   if (stmt->state < MYSQL_STMT_USE_OR_STORE_CALLED)
  297   {
  298     SET_CLIENT_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
  299     return(1);
  300   }
  301 
  302   /* do we have some prefetched rows available ? */
  303   if (stmt->result_cursor)
  304     return(stmt_buffered_fetch(stmt, row));
  305   if (stmt->upsert_status.server_status & SERVER_STATUS_LAST_ROW_SENT)
  306     stmt->upsert_status.server_status&=  ~SERVER_STATUS_LAST_ROW_SENT;
  307   else
  308   {
  309     int4store(buf, stmt->stmt_id);
  310     int4store(buf + STMT_ID_LENGTH, stmt->prefetch_rows);
  311 
  312     if (stmt->mysql->methods->db_command(stmt->mysql, COM_STMT_FETCH, (char *)buf, sizeof(buf), 1, stmt))
  313       return(1);
  314 
  315     /* free previously allocated buffer */
  316     ma_free_root(&result->alloc, MYF(MY_KEEP_PREALLOC));
  317     result->data= 0;
  318     result->rows= 0;
  319 
  320     if (stmt->mysql->methods->db_stmt_read_all_rows(stmt))
  321       return(1);
  322 
  323     return(stmt_buffered_fetch(stmt, row));
  324   }
  325   /* no more cursor data available */
  326   *row= NULL;
  327   return(MYSQL_NO_DATA);
  328 }
  329 
  330 /* flush one result set */
  331 void mthd_stmt_flush_unbuffered(MYSQL_STMT *stmt)
  332 {
  333   ulong packet_len;
  334   int in_resultset= stmt->state > MYSQL_STMT_EXECUTED &&
  335                     stmt->state < MYSQL_STMT_FETCH_DONE;
  336   while ((packet_len = ma_net_safe_read(stmt->mysql)) != packet_error)
  337   {
  338     uchar *pos= stmt->mysql->net.read_pos;
  339     if (!in_resultset && *pos == 0) /* OK */
  340     {
  341       pos++;
  342       net_field_length(&pos);
  343       net_field_length(&pos);
  344       stmt->mysql->server_status= uint2korr(pos);
  345       goto end;
  346     }
  347     if (packet_len < 8 && *pos == 254) /* EOF */
  348     {
  349       if (mariadb_connection(stmt->mysql))
  350       {
  351         stmt->mysql->server_status= uint2korr(pos + 3);
  352         if (in_resultset)
  353           goto end;
  354         in_resultset= 1;
  355       }
  356       else
  357         goto end;
  358     }
  359   }
  360 end:
  361   stmt->state= MYSQL_STMT_FETCH_DONE;
  362 }
  363 
  364 int mthd_stmt_fetch_to_bind(MYSQL_STMT *stmt, unsigned char *row)
  365 {
  366   uint i;
  367   size_t truncations= 0;
  368   unsigned char *null_ptr, bit_offset= 4;
  369   row++; /* skip status byte */
  370   null_ptr= row;
  371   row+= (stmt->field_count + 9) / 8;
  372 
  373   for (i=0; i < stmt->field_count; i++)
  374   {
  375     /* save row position for fetching values in pieces */
  376     if (*null_ptr & bit_offset)
  377     {
  378       if (!stmt->bind[i].is_null)
  379         stmt->bind[i].is_null= &stmt->bind[i].is_null_value;
  380       *stmt->bind[i].is_null= 1;
  381       stmt->bind[i].u.row_ptr= NULL;
  382     } else
  383     {
  384       stmt->bind[i].u.row_ptr= row;
  385       if (!stmt->bind_result_done ||
  386           stmt->bind[i].flags & MADB_BIND_DUMMY)
  387       {
  388         unsigned long length;
  389 
  390         if (mysql_ps_fetch_functions[stmt->fields[i].type].pack_len >= 0)
  391           length= mysql_ps_fetch_functions[stmt->fields[i].type].pack_len;
  392         else
  393           length= net_field_length(&row);
  394         row+= length;
  395         if (!stmt->bind[i].length)
  396           stmt->bind[i].length= &stmt->bind[i].length_value;
  397         *stmt->bind[i].length= stmt->bind[i].length_value= length;
  398       }
  399       else
  400       {
  401         if (!stmt->bind[i].length)
  402           stmt->bind[i].length= &stmt->bind[i].length_value;
  403         if (!stmt->bind[i].is_null)
  404           stmt->bind[i].is_null= &stmt->bind[i].is_null_value;
  405         *stmt->bind[i].is_null= 0;
  406         mysql_ps_fetch_functions[stmt->fields[i].type].func(&stmt->bind[i], &stmt->fields[i], &row);
  407         if (stmt->mysql->options.report_data_truncation)
  408           truncations+= *stmt->bind[i].error;
  409       }
  410     }
  411 
  412     if (!((bit_offset <<=1) & 255)) {
  413       bit_offset= 1; /* To next byte */
  414       null_ptr++;
  415     }
  416   }
  417   return((truncations) ? MYSQL_DATA_TRUNCATED : 0);
  418 }
  419 
  420 MYSQL_RES *_mysql_stmt_use_result(MYSQL_STMT *stmt)
  421 {
  422   MYSQL *mysql= stmt->mysql;
  423 
  424   if (!stmt->field_count ||
  425       (!stmt->cursor_exists && mysql->status != MYSQL_STATUS_STMT_RESULT) ||
  426       (stmt->cursor_exists && mysql->status != MYSQL_STATUS_READY) ||
  427       (stmt->state != MYSQL_STMT_WAITING_USE_OR_STORE))
  428   {
  429     SET_CLIENT_ERROR(mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
  430     return(NULL);
  431   }
  432 
  433   CLEAR_CLIENT_STMT_ERROR(stmt);
  434 
  435   stmt->state = MYSQL_STMT_USE_OR_STORE_CALLED;
  436   if (!stmt->cursor_exists)
  437     stmt->fetch_row_func= stmt_unbuffered_fetch; //mysql_stmt_fetch_unbuffered_row;
  438   else
  439     stmt->fetch_row_func= stmt_cursor_fetch;
  440 
  441   return(NULL);
  442 }
  443 
  444 unsigned char *mysql_net_store_length(unsigned char *packet, size_t length)
  445 {
  446   if (length < (unsigned long long) L64(251)) {
  447     *packet = (unsigned char) length;
  448     return packet + 1;
  449   }
  450 
  451   if (length < (unsigned long long) L64(65536)) {
  452     *packet++ = 252;
  453     int2store(packet,(uint) length);
  454     return packet + 2;
  455   }
  456 
  457   if (length < (unsigned long long) L64(16777216)) {
  458     *packet++ = 253;
  459     int3store(packet,(ulong) length);
  460     return packet + 3;
  461   }
  462   *packet++ = 254;
  463   int8store(packet, length);
  464   return packet + 8;
  465 }
  466 
  467 static long ma_get_length(MYSQL_STMT *stmt, unsigned int param_nr, unsigned long row_nr)
  468 {
  469   if (!stmt->params[param_nr].length)
  470     return 0;
  471   if (stmt->row_size)
  472     return *(long *)((char *)stmt->params[param_nr].length + row_nr * stmt->row_size);
  473   else
  474     return stmt->params[param_nr].length[row_nr];
  475 }
  476 
  477 static signed char ma_get_indicator(MYSQL_STMT *stmt, unsigned int param_nr, unsigned long row_nr)
  478 {
  479   if (!MARIADB_STMT_BULK_SUPPORTED(stmt) ||
  480       !stmt->array_size ||
  481       !stmt->params[param_nr].u.indicator)
  482     return 0;
  483   if (stmt->row_size)
  484     return *((char *)stmt->params[param_nr].u.indicator + (row_nr * stmt->row_size));
  485   return stmt->params[param_nr].u.indicator[row_nr];
  486 }
  487 
  488 static void *ma_get_buffer_offset(MYSQL_STMT *stmt, enum enum_field_types type,
  489                                   void *buffer, unsigned long row_nr)
  490 {
  491   if (stmt->array_size)
  492   {
  493     int len;
  494     if (stmt->row_size)
  495       return (void *)((char *)buffer + stmt->row_size * row_nr);
  496     len= mysql_ps_fetch_functions[type].pack_len;
  497     if (len > 0)
  498       return (void *)((char *)buffer + len * row_nr);
  499     return ((void **)buffer)[row_nr];
  500   }
  501   return buffer;
  502 }
  503 
  504 int store_param(MYSQL_STMT *stmt, int column, unsigned char **p, unsigned long row_nr)
  505 {
  506   void *buf= ma_get_buffer_offset(stmt, stmt->params[column].buffer_type,
  507                                   stmt->params[column].buffer, row_nr);
  508   signed char indicator= ma_get_indicator(stmt, column, row_nr);
  509 
  510   switch (stmt->params[column].buffer_type) {
  511   case MYSQL_TYPE_TINY:
  512     int1store(*p, (*(uchar *)buf));
  513     (*p) += 1;
  514     break;
  515   case MYSQL_TYPE_SHORT:
  516   case MYSQL_TYPE_YEAR:
  517     int2store(*p, (*(short *)buf));
  518     (*p) += 2;
  519     break;
  520   case MYSQL_TYPE_FLOAT:
  521     float4store(*p, (*(float *)buf));
  522     (*p) += 4;
  523     break;
  524   case MYSQL_TYPE_DOUBLE:
  525     float8store(*p, (*(double *)buf));
  526     (*p) += 8;
  527     break;
  528   case MYSQL_TYPE_LONGLONG:
  529     int8store(*p, (*(ulonglong *)buf));
  530     (*p) += 8;
  531     break;
  532   case MYSQL_TYPE_LONG:
  533   case MYSQL_TYPE_INT24:
  534     int4store(*p, (*(int32 *)buf));
  535     (*p)+= 4;
  536     break;
  537   case MYSQL_TYPE_TIME:
  538   {
  539     /* binary encoding:
  540        Offset     Length  Field
  541        0          1       Length
  542        1          1       negative
  543        2-5        4       day
  544        6          1       hour
  545        7          1       ninute
  546        8          1       second;
  547        9-13       4       second_part
  548        */
  549     MYSQL_TIME *t= (MYSQL_TIME *)ma_get_buffer_offset(stmt, stmt->params[column].buffer_type,
  550                                                       stmt->params[column].buffer, row_nr);
  551     char t_buffer[MAX_TIME_STR_LEN];
  552     uint len= 0;
  553 
  554     t_buffer[1]= t->neg ? 1 : 0;
  555     int4store(t_buffer + 2, t->day);
  556     t_buffer[6]= (uchar) t->hour;
  557     t_buffer[7]= (uchar) t->minute;
  558     t_buffer[8]= (uchar) t->second;
  559     if (t->second_part)
  560     {
  561       int4store(t_buffer + 9, t->second_part);
  562       len= 12;
  563     }
  564     else if (t->day || t->hour || t->minute || t->second)
  565       len= 8;
  566     t_buffer[0]= len++;
  567     memcpy(*p, t_buffer, len);
  568     (*p)+= len;
  569     break;
  570   }
  571   case MYSQL_TYPE_DATE:
  572   case MYSQL_TYPE_TIMESTAMP:
  573   case MYSQL_TYPE_DATETIME:
  574   {
  575     /* binary format for date, timestamp and datetime
  576        Offset     Length  Field
  577        0          1       Length
  578        1-2        2       Year
  579        3          1       Month
  580        4          1       Day
  581        5          1       Hour
  582        6          1       minute
  583        7          1       second
  584        8-11       4       secondpart
  585        */
  586     MYSQL_TIME *t= (MYSQL_TIME *)ma_get_buffer_offset(stmt, stmt->params[column].buffer_type,
  587                                                       stmt->params[column].buffer, row_nr);
  588     char t_buffer[MAX_DATETIME_STR_LEN];
  589     uint len= 0;
  590 
  591     int2store(t_buffer + 1, t->year);
  592     t_buffer[3]= (char) t->month;
  593     t_buffer[4]= (char) t->day;
  594     t_buffer[5]= (char) t->hour;
  595     t_buffer[6]= (char) t->minute;
  596     t_buffer[7]= (char) t->second;
  597     if (t->second_part)
  598     {
  599       int4store(t_buffer + 8, t->second_part);
  600       len= 11;
  601     }
  602     else if (t->hour || t->minute || t->second)
  603       len= 7;
  604     else if (t->year || t->month || t->day)
  605       len= 4;
  606     else
  607       len=0;
  608     t_buffer[0]= len++;
  609     memcpy(*p, t_buffer, len);
  610     (*p)+= len;
  611     break;
  612   }
  613   case MYSQL_TYPE_TINY_BLOB:
  614   case MYSQL_TYPE_MEDIUM_BLOB:
  615   case MYSQL_TYPE_LONG_BLOB:
  616   case MYSQL_TYPE_BLOB:
  617   case MYSQL_TYPE_VARCHAR:
  618   case MYSQL_TYPE_VAR_STRING:
  619   case MYSQL_TYPE_STRING:
  620   case MYSQL_TYPE_JSON:
  621   case MYSQL_TYPE_DECIMAL:
  622   case MYSQL_TYPE_NEWDECIMAL:
  623   {
  624     ulong len;
  625     /* to is after p. The latter hasn't been moved */
  626     uchar *to;
  627 
  628     if (indicator == STMT_INDICATOR_NTS)
  629       len= -1;
  630     else
  631       len= ma_get_length(stmt, column, row_nr);
  632 
  633     if (len == (ulong)-1)
  634       len= (ulong)strlen((char *)buf);
  635 
  636     to = mysql_net_store_length(*p, len);
  637 
  638     if (len)
  639       memcpy(to, buf, len);
  640     (*p) = to + len;
  641     break;
  642   }
  643 
  644   default:
  645     /* unsupported parameter type */
  646     SET_CLIENT_STMT_ERROR(stmt, CR_UNSUPPORTED_PARAM_TYPE, SQLSTATE_UNKNOWN, 0);
  647     return 1;
  648   }
  649   return 0;
  650 }
  651 
  652 /* {{{ mysqlnd_stmt_execute_generate_simple_request */
  653 unsigned char* mysql_stmt_execute_generate_simple_request(MYSQL_STMT *stmt, size_t *request_len)
  654 {
  655   /* execute packet has the following format:
  656      Offset   Length      Description
  657      -----------------------------------------
  658      0             4      Statement id
  659      4             1      Flags (cursor type)
  660      5             4      Iteration count
  661      -----------------------------------------
  662      if (stmt->param_count):
  663      6  (paramcount+7)/8  null bitmap
  664      ------------------------------------------
  665      if (stmt->send_types_to_server):
  666      param_count*2    parameter types
  667      1st byte: parameter type
  668      2nd byte flag:
  669               unsigned flag (32768)
  670               indicator variable exists (16384)
  671      ------------------------------------------
  672      n      data from bind_buffer
  673 
  674      */
  675 
  676   size_t length= 1024;
  677   size_t free_bytes= 0;
  678   size_t null_byte_offset= 0;
  679   uint i;
  680 
  681   uchar *start= NULL, *p;
  682 
  683   /* preallocate length bytes */
  684   /* check: gr */
  685   if (!(start= p= (uchar *)malloc(length)))
  686     goto mem_error;
  687 
  688   int4store(p, stmt->stmt_id);
  689   p += STMT_ID_LENGTH;
  690 
  691   /* flags is 4 bytes, we store just 1 */
  692   int1store(p, (unsigned char) stmt->flags);
  693   p++;
  694 
  695   int4store(p, 1);
  696   p+= 4;
  697 
  698   if (stmt->param_count)
  699   {
  700     size_t null_count= (stmt->param_count + 7) / 8;
  701 
  702     free_bytes= length - (p - start);
  703     if (null_count + 20 > free_bytes)
  704     {
  705       size_t offset= p - start;
  706       length+= offset + null_count + 20;
  707       if (!(start= (uchar *)realloc(start, length)))
  708         goto mem_error;
  709       p= start + offset;
  710     }
  711 
  712     null_byte_offset= p - start;
  713     memset(p, 0, null_count);
  714     p += null_count;
  715 
  716     int1store(p, stmt->send_types_to_server);
  717     p++;
  718 
  719     free_bytes= length - (p - start);
  720 
  721     /* Store type information:
  722        2 bytes per type
  723        */
  724     if (stmt->send_types_to_server)
  725     {
  726       if (free_bytes < stmt->param_count * 2 + 20)
  727       {
  728         size_t offset= p - start;
  729         length= offset + stmt->param_count * 2 + 20;
  730         if (!(start= (uchar *)realloc(start, length)))
  731           goto mem_error;
  732         p= start + offset;
  733       }
  734       for (i = 0; i < stmt->param_count; i++)
  735       {
  736         /* this differs from mysqlnd, c api supports unsigned !! */
  737         uint buffer_type= stmt->params[i].buffer_type | (stmt->params[i].is_unsigned ? 32768 : 0);
  738         /* check if parameter requires indicator variable */
  739         int2store(p, buffer_type);
  740         p+= 2;
  741       }
  742     }
  743 
  744     /* calculate data size */
  745     for (i=0; i < stmt->param_count; i++)
  746     {
  747       size_t size= 0;
  748       my_bool has_data= TRUE;
  749 
  750       if (stmt->params[i].long_data_used)
  751       {
  752         has_data= FALSE;
  753         stmt->params[i].long_data_used= 0;
  754       }
  755 
  756       if (has_data)
  757       {
  758         switch (stmt->params[i].buffer_type) {
  759         case MYSQL_TYPE_NULL:
  760           has_data= FALSE;
  761           break;
  762         case MYSQL_TYPE_TINY_BLOB:
  763         case MYSQL_TYPE_MEDIUM_BLOB:
  764         case MYSQL_TYPE_LONG_BLOB:
  765         case MYSQL_TYPE_BLOB:
  766         case MYSQL_TYPE_VARCHAR:
  767         case MYSQL_TYPE_VAR_STRING:
  768         case MYSQL_TYPE_STRING:
  769         case MYSQL_TYPE_JSON:
  770         case MYSQL_TYPE_DECIMAL:
  771         case MYSQL_TYPE_NEWDECIMAL:
  772         case MYSQL_TYPE_GEOMETRY:
  773         case MYSQL_TYPE_NEWDATE:
  774         case MYSQL_TYPE_ENUM:
  775         case MYSQL_TYPE_BIT:
  776         case MYSQL_TYPE_SET:
  777           size+= 5; /* max 8 bytes for size */
  778           size+= (size_t)ma_get_length(stmt, i, 0);
  779           break;
  780         default:
  781           size+= mysql_ps_fetch_functions[stmt->params[i].buffer_type].pack_len;
  782           break;
  783         }
  784       }
  785       free_bytes= length - (p - start);
  786       if (free_bytes < size + 20)
  787       {
  788         size_t offset= p - start;
  789         length= MAX(2 * length, offset + size + 20);
  790         if (!(start= (uchar *)realloc(start, length)))
  791           goto mem_error;
  792         p= start + offset;
  793       }
  794       if (((stmt->params[i].is_null && *stmt->params[i].is_null) ||
  795              stmt->params[i].buffer_type == MYSQL_TYPE_NULL ||
  796              !stmt->params[i].buffer))
  797       {
  798         has_data= FALSE;
  799         (start + null_byte_offset)[i/8] |= (unsigned char) (1 << (i & 7));
  800       }
  801 
  802       if (has_data)
  803       {
  804         store_param(stmt, i, &p, 0);
  805       }
  806     }
  807   }
  808   stmt->send_types_to_server= 0;
  809   *request_len = (size_t)(p - start);
  810   return start;
  811 mem_error:
  812   SET_CLIENT_STMT_ERROR(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
  813   free(start);
  814   *request_len= 0;
  815   return NULL;
  816 }
  817 /* }}} */
  818 
  819 /* {{{ mysql_stmt_skip_paramset */
  820 my_bool mysql_stmt_skip_paramset(MYSQL_STMT *stmt, uint row)
  821 {
  822   uint i;
  823   for (i=0; i < stmt->param_count; i++)
  824   {
  825     if (ma_get_indicator(stmt, i, row) == STMT_INDICATOR_IGNORE_ROW)
  826       return '\1';
  827   }
  828   
  829   return '\0';
  830 }
  831 /* }}} */
  832 
  833 /* {{{ mysql_stmt_execute_generate_bulk_request */
  834 unsigned char* mysql_stmt_execute_generate_bulk_request(MYSQL_STMT *stmt, size_t *request_len)
  835 {
  836   /* execute packet has the following format:
  837      Offset   Length      Description
  838      -----------------------------------------
  839      0             4      Statement id
  840      4             2      Flags (cursor type):
  841                             STMT_BULK_FLAG_CLIENT_SEND_TYPES = 128
  842                             STMT_BULK_FLAG_INSERT_ID_REQUEST = 64
  843      -----------------------------------------
  844      if (stmt->send_types_to_server):
  845      for (i=0; i < param_count; i++)
  846        1st byte: parameter type
  847        2nd byte flag:
  848               unsigned flag (32768)
  849      ------------------------------------------
  850      for (i=0; i < param_count; i++)
  851                    1      indicator variable
  852                             STMT_INDICATOR_NONE 0
  853                             STMT_INDICATOR_NULL 1
  854                             STMT_INDICATOR_DEFAULT 2
  855                             STMT_INDICATOR_IGNORE 3
  856                             STMT_INDICATOR_SKIP_SET 4
  857                    n      data from bind buffer
  858 
  859      */
  860 
  861   size_t length= 1024;
  862   size_t free_bytes= 0;
  863   ushort flags= 0;
  864   uint i, j;
  865 
  866   uchar *start= NULL, *p;
  867 
  868   if (!MARIADB_STMT_BULK_SUPPORTED(stmt))
  869   {
  870     stmt_set_error(stmt, CR_FUNCTION_NOT_SUPPORTED, "IM001",
  871                    CER(CR_FUNCTION_NOT_SUPPORTED), "Bulk operation");
  872     return NULL;
  873   }
  874 
  875   if (!stmt->param_count)
  876   {
  877     stmt_set_error(stmt, CR_BULK_WITHOUT_PARAMETERS, "IM001",
  878                    CER(CR_BULK_WITHOUT_PARAMETERS));
  879     return NULL;
  880   }
  881 
  882   /* preallocate length bytes */
  883   if (!(start= p= (uchar *)malloc(length)))
  884     goto mem_error;
  885 
  886   int4store(p, stmt->stmt_id);
  887   p += STMT_ID_LENGTH;
  888 
  889   /* todo: request to return auto generated ids */
  890   if (stmt->send_types_to_server)
  891     flags|= STMT_BULK_FLAG_CLIENT_SEND_TYPES;
  892   int2store(p, flags);
  893   p+=2;
  894 
  895   /* When using mariadb_stmt_execute_direct stmt->paran_count is
  896      not knowm, so we need to assign prebind_params, which was previously
  897      set by mysql_stmt_attr_set
  898   */
  899   if (!stmt->param_count && stmt->prebind_params)
  900     stmt->param_count= stmt->prebind_params;
  901 
  902   if (stmt->param_count)
  903   {
  904     free_bytes= length - (p - start);
  905 
  906     /* Store type information:
  907        2 bytes per type
  908        */
  909     if (stmt->send_types_to_server)
  910     {
  911       if (free_bytes < stmt->param_count * 2 + 20)
  912       {
  913         size_t offset= p - start;
  914         length= offset + stmt->param_count * 2 + 20;
  915         if (!(start= (uchar *)realloc(start, length)))
  916           goto mem_error;
  917         p= start + offset;
  918       }
  919       for (i = 0; i < stmt->param_count; i++)
  920       {
  921         /* this differs from mysqlnd, c api supports unsigned !! */
  922         uint buffer_type= stmt->params[i].buffer_type | (stmt->params[i].is_unsigned ? 32768 : 0);
  923         int2store(p, buffer_type);
  924         p+= 2;
  925       }
  926     }
  927 
  928     /* calculate data size */
  929     for (j=0; j < stmt->array_size; j++)
  930     {
  931       if (mysql_stmt_skip_paramset(stmt, j))
  932         continue;
  933 
  934       for (i=0; i < stmt->param_count; i++)
  935       {
  936         size_t size= 0;
  937         my_bool has_data= TRUE;
  938         signed char indicator= ma_get_indicator(stmt, i, j);
  939         /* check if we need to send data */
  940         if (indicator > 0)
  941           has_data= FALSE;
  942         size= 1;
  943 
  944         /* Please note that mysql_stmt_send_long_data is not supported
  945            current when performing bulk execute */
  946 
  947         if (has_data)
  948         {
  949           switch (stmt->params[i].buffer_type) {
  950           case MYSQL_TYPE_NULL:
  951             has_data= FALSE;
  952             indicator= STMT_INDICATOR_NULL;
  953             break;
  954           case MYSQL_TYPE_TINY_BLOB:
  955           case MYSQL_TYPE_MEDIUM_BLOB:
  956           case MYSQL_TYPE_LONG_BLOB:
  957           case MYSQL_TYPE_BLOB:
  958           case MYSQL_TYPE_VARCHAR:
  959           case MYSQL_TYPE_VAR_STRING:
  960           case MYSQL_TYPE_STRING:
  961           case MYSQL_TYPE_JSON:
  962           case MYSQL_TYPE_DECIMAL:
  963           case MYSQL_TYPE_NEWDECIMAL:
  964           case MYSQL_TYPE_GEOMETRY:
  965           case MYSQL_TYPE_NEWDATE:
  966           case MYSQL_TYPE_ENUM:
  967           case MYSQL_TYPE_BIT:
  968           case MYSQL_TYPE_SET:
  969             size+= 5; /* max 8 bytes for size */
  970             if (indicator == STMT_INDICATOR_NTS ||
  971               (!stmt->row_size && ma_get_length(stmt,i,j) == -1))
  972             {
  973                 size+= strlen(ma_get_buffer_offset(stmt,
  974                                                    stmt->params[i].buffer_type,
  975                                                    stmt->params[i].buffer,j));
  976             }
  977             else
  978               size+= (size_t)ma_get_length(stmt, i, j);
  979             break;
  980           default:
  981             size+= mysql_ps_fetch_functions[stmt->params[i].buffer_type].pack_len;
  982             break;
  983           }
  984         }
  985         free_bytes= length - (p - start);
  986         if (free_bytes < size + 20)
  987         {
  988           size_t offset= p - start;
  989           length= MAX(2 * length, offset + size + 20);
  990           if (!(start= (uchar *)realloc(start, length)))
  991             goto mem_error;
  992           p= start + offset;
  993         }
  994 
  995         int1store(p, indicator > 0 ? indicator : 0);
  996         p++;
  997         if (has_data)
  998           store_param(stmt, i, &p, j);
  999       }
 1000     }
 1001 
 1002   }
 1003   stmt->send_types_to_server= 0;
 1004   *request_len = (size_t)(p - start);
 1005   return start;
 1006 mem_error:
 1007   SET_CLIENT_STMT_ERROR(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
 1008   free(start);
 1009   *request_len= 0;
 1010   return NULL;
 1011 }
 1012 /* }}} */
 1013 /*!
 1014  *******************************************************************************
 1015 
 1016  \fn        unsigned long long mysql_stmt_affected_rows
 1017  \brief     returns the number of affected rows from last mysql_stmt_execute
 1018  call
 1019 
 1020  \param[in]  stmt The statement handle
 1021  *******************************************************************************
 1022  */
 1023 unsigned long long STDCALL mysql_stmt_affected_rows(MYSQL_STMT *stmt)
 1024 {
 1025   return stmt->upsert_status.affected_rows;
 1026 }
 1027 
 1028 my_bool STDCALL mysql_stmt_attr_get(MYSQL_STMT *stmt, enum enum_stmt_attr_type attr_type, void *value)
 1029 {
 1030   switch (attr_type) {
 1031     case STMT_ATTR_STATE:
 1032       *(enum mysql_stmt_state *)value= stmt->state;
 1033       break;
 1034     case STMT_ATTR_UPDATE_MAX_LENGTH:
 1035       *(my_bool *)value= stmt->update_max_length;
 1036       break;
 1037     case STMT_ATTR_CURSOR_TYPE:
 1038       *(unsigned long *)value= stmt->flags;
 1039       break;
 1040     case STMT_ATTR_PREFETCH_ROWS:
 1041       *(unsigned long *)value= stmt->prefetch_rows;
 1042       break;
 1043     case STMT_ATTR_PREBIND_PARAMS:
 1044       *(unsigned int *)value= stmt->prebind_params;
 1045       break;
 1046     case STMT_ATTR_ARRAY_SIZE:
 1047       *(unsigned int *)value= stmt->array_size;
 1048       break;
 1049     case STMT_ATTR_ROW_SIZE:
 1050       *(size_t *)value= stmt->row_size;
 1051       break;
 1052     default:
 1053       return(1);
 1054   }
 1055   return(0);
 1056 }
 1057 
 1058 my_bool STDCALL mysql_stmt_attr_set(MYSQL_STMT *stmt, enum enum_stmt_attr_type attr_type, const void *value)
 1059 {
 1060   switch (attr_type) {
 1061   case STMT_ATTR_UPDATE_MAX_LENGTH:
 1062     stmt->update_max_length= *(my_bool *)value;
 1063     break;
 1064   case STMT_ATTR_CURSOR_TYPE:
 1065     if (*(ulong *)value > (unsigned long) CURSOR_TYPE_READ_ONLY)
 1066     {
 1067       SET_CLIENT_STMT_ERROR(stmt, CR_NOT_IMPLEMENTED, SQLSTATE_UNKNOWN, 0);
 1068       return(1);
 1069     }
 1070     stmt->flags = *(ulong *)value;
 1071     break;
 1072   case STMT_ATTR_PREFETCH_ROWS:
 1073     if (*(ulong *)value == 0)
 1074       *(long *)value= MYSQL_DEFAULT_PREFETCH_ROWS;
 1075     else
 1076       stmt->prefetch_rows= *(long *)value;
 1077     break;
 1078   case STMT_ATTR_PREBIND_PARAMS:
 1079     if (stmt->state > MYSQL_STMT_INITTED)
 1080     {
 1081       mysql_stmt_internal_reset(stmt, 1);
 1082       net_stmt_close(stmt, 0);
 1083       stmt->state= MYSQL_STMT_INITTED;
 1084       stmt->params= 0;
 1085     }
 1086     stmt->prebind_params= *(unsigned int *)value;
 1087     break;
 1088   case STMT_ATTR_ARRAY_SIZE:
 1089     stmt->array_size= *(unsigned int *)value;
 1090     break;
 1091   case STMT_ATTR_ROW_SIZE:
 1092     stmt->row_size= *(size_t *)value;
 1093     break;
 1094   default:
 1095     SET_CLIENT_STMT_ERROR(stmt, CR_NOT_IMPLEMENTED, SQLSTATE_UNKNOWN, 0);
 1096     return(1);
 1097   }
 1098   return(0);
 1099 }
 1100 
 1101 my_bool STDCALL mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND *bind)
 1102 {
 1103   MYSQL *mysql= stmt->mysql;
 1104 
 1105   if (!mysql)
 1106   {
 1107     SET_CLIENT_STMT_ERROR(stmt, CR_SERVER_LOST, SQLSTATE_UNKNOWN, 0);
 1108     return(1);
 1109   }
 1110 
 1111   /* If number of parameters was specified via mysql_stmt_attr_set we need to realloc
 1112      them, e.g. for mariadb_stmt_execute_direct()
 1113      */
 1114   if ((stmt->state < MYSQL_STMT_PREPARED || stmt->state >= MYSQL_STMT_EXECUTED) &&
 1115        stmt->prebind_params > 0)
 1116   {
 1117     if (!stmt->params && stmt->prebind_params)
 1118     {
 1119       if (!(stmt->params= (MYSQL_BIND *)ma_alloc_root(&stmt->mem_root, stmt->prebind_params * sizeof(MYSQL_BIND))))
 1120       {
 1121         SET_CLIENT_STMT_ERROR(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
 1122         return(1);
 1123       }
 1124       memset(stmt->params, '\0', stmt->prebind_params * sizeof(MYSQL_BIND));
 1125     }
 1126     stmt->param_count= stmt->prebind_params;
 1127   }
 1128   else if (stmt->state < MYSQL_STMT_PREPARED) {
 1129     SET_CLIENT_STMT_ERROR(stmt, CR_NO_PREPARE_STMT, SQLSTATE_UNKNOWN, 0);
 1130     return(1);
 1131   }
 1132 
 1133   if (stmt->param_count && bind)
 1134   {
 1135     uint i;
 1136 
 1137     memcpy(stmt->params, bind, sizeof(MYSQL_BIND) * stmt->param_count);
 1138     stmt->send_types_to_server= 1;
 1139 
 1140     for (i=0; i < stmt->param_count; i++)
 1141     {
 1142       if (stmt->mysql->methods->db_supported_buffer_type &&
 1143           !stmt->mysql->methods->db_supported_buffer_type(stmt->params[i].buffer_type))
 1144       {
 1145         SET_CLIENT_STMT_ERROR(stmt, CR_UNSUPPORTED_PARAM_TYPE, SQLSTATE_UNKNOWN, 0);
 1146         return(1);
 1147       }
 1148       if (!stmt->params[i].is_null)
 1149         stmt->params[i].is_null= &is_not_null;
 1150 
 1151       if (stmt->params[i].long_data_used)
 1152         stmt->params[i].long_data_used= 0;
 1153 
 1154       if (!stmt->params[i].length)
 1155         stmt->params[i].length= &stmt->params[i].buffer_length;
 1156 
 1157       switch(stmt->params[i].buffer_type) {
 1158       case MYSQL_TYPE_NULL:
 1159         stmt->params[i].is_null= &is_null;
 1160         break;
 1161       case MYSQL_TYPE_TINY:
 1162         stmt->params[i].buffer_length= 1;
 1163         break;
 1164       case MYSQL_TYPE_SHORT:
 1165       case MYSQL_TYPE_YEAR:
 1166         stmt->params[i].buffer_length= 2;
 1167         break;
 1168       case MYSQL_TYPE_LONG:
 1169       case MYSQL_TYPE_FLOAT:
 1170         stmt->params[i].buffer_length= 4;
 1171         break;
 1172       case MYSQL_TYPE_LONGLONG:
 1173       case MYSQL_TYPE_DOUBLE:
 1174         stmt->params[i].buffer_length= 8;
 1175         break;
 1176       case MYSQL_TYPE_DATETIME:
 1177       case MYSQL_TYPE_TIMESTAMP:
 1178         stmt->params[i].buffer_length= 12;
 1179         break;
 1180       case MYSQL_TYPE_TIME:
 1181         stmt->params[i].buffer_length= 13;
 1182         break;
 1183       case MYSQL_TYPE_DATE:
 1184         stmt->params[i].buffer_length= 5;
 1185         break;
 1186       case MYSQL_TYPE_STRING:
 1187       case MYSQL_TYPE_JSON:
 1188       case MYSQL_TYPE_VAR_STRING:
 1189       case MYSQL_TYPE_BLOB:
 1190       case MYSQL_TYPE_TINY_BLOB:
 1191       case MYSQL_TYPE_MEDIUM_BLOB:
 1192       case MYSQL_TYPE_LONG_BLOB:
 1193       case MYSQL_TYPE_DECIMAL:
 1194       case MYSQL_TYPE_NEWDECIMAL:
 1195         break;
 1196       default:
 1197         SET_CLIENT_STMT_ERROR(stmt, CR_UNSUPPORTED_PARAM_TYPE, SQLSTATE_UNKNOWN, 0);
 1198         return(1);
 1199         break;
 1200       }
 1201     }
 1202   }
 1203   stmt->bind_param_done= stmt->send_types_to_server= 1;
 1204 
 1205   CLEAR_CLIENT_STMT_ERROR(stmt);
 1206   return(0);
 1207 }
 1208 
 1209 my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
 1210 {
 1211   uint i;
 1212 
 1213   if (stmt->state < MYSQL_STMT_PREPARED)
 1214   {
 1215     SET_CLIENT_STMT_ERROR(stmt, CR_NO_PREPARE_STMT, SQLSTATE_UNKNOWN, 0);
 1216     return(1);
 1217   }
 1218 
 1219   if (!stmt->field_count)
 1220   {
 1221     SET_CLIENT_STMT_ERROR(stmt, CR_NO_STMT_METADATA, SQLSTATE_UNKNOWN, 0);
 1222     return(1);
 1223   }
 1224 
 1225   if (!bind)
 1226     return(1);
 1227 
 1228   /* In case of a stored procedure we don't allocate memory for bind
 1229      in mysql_stmt_prepare
 1230      */
 1231 
 1232   if (stmt->field_count && !stmt->bind)
 1233   {
 1234     MA_MEM_ROOT *fields_ma_alloc_root=
 1235                 &((MADB_STMT_EXTENSION *)stmt->extension)->fields_ma_alloc_root;
 1236     if (!(stmt->bind= (MYSQL_BIND *)ma_alloc_root(fields_ma_alloc_root, stmt->field_count * sizeof(MYSQL_BIND))))
 1237     {
 1238       SET_CLIENT_STMT_ERROR(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
 1239       return(1);
 1240     }
 1241   }
 1242 
 1243   memcpy(stmt->bind, bind, sizeof(MYSQL_BIND) * stmt->field_count);
 1244 
 1245   for (i=0; i < stmt->field_count; i++)
 1246   {
 1247     if (stmt->mysql->methods->db_supported_buffer_type &&
 1248         !stmt->mysql->methods->db_supported_buffer_type(bind[i].buffer_type))
 1249     {
 1250       SET_CLIENT_STMT_ERROR(stmt, CR_UNSUPPORTED_PARAM_TYPE, SQLSTATE_UNKNOWN, 0);
 1251       return(1);
 1252     }
 1253 
 1254     if (!stmt->bind[i].is_null)
 1255       stmt->bind[i].is_null= &stmt->bind[i].is_null_value;
 1256     if (!stmt->bind[i].length)
 1257       stmt->bind[i].length= &stmt->bind[i].length_value;
 1258     if (!stmt->bind[i].error)
 1259       stmt->bind[i].error= &stmt->bind[i].error_value;
 1260 
 1261     /* set length values for numeric types */
 1262     switch(bind[i].buffer_type) {
 1263     case MYSQL_TYPE_NULL:
 1264       *stmt->bind[i].length= stmt->bind[i].length_value= 0;
 1265       break;
 1266     case MYSQL_TYPE_TINY:
 1267       *stmt->bind[i].length= stmt->bind[i].length_value= 1;
 1268       break;
 1269     case MYSQL_TYPE_SHORT:
 1270     case MYSQL_TYPE_YEAR:
 1271       *stmt->bind[i].length= stmt->bind[i].length_value= 2;
 1272       break;
 1273     case MYSQL_TYPE_INT24:
 1274     case MYSQL_TYPE_LONG:
 1275     case MYSQL_TYPE_FLOAT:
 1276       *stmt->bind[i].length= stmt->bind[i].length_value= 4;
 1277       break;
 1278     case MYSQL_TYPE_LONGLONG:
 1279     case MYSQL_TYPE_DOUBLE:
 1280       *stmt->bind[i].length= stmt->bind[i].length_value= 8;
 1281       break;
 1282     case MYSQL_TYPE_TIME:
 1283     case MYSQL_TYPE_DATE:
 1284     case MYSQL_TYPE_DATETIME:
 1285     case MYSQL_TYPE_TIMESTAMP:
 1286       *stmt->bind[i].length= stmt->bind[i].length_value= sizeof(MYSQL_TIME);
 1287       break;
 1288     default:
 1289       break;
 1290     }
 1291   }
 1292   stmt->bind_result_done= 1;
 1293   CLEAR_CLIENT_STMT_ERROR(stmt);
 1294 
 1295   return(0);
 1296 }
 1297 
 1298 static my_bool net_stmt_close(MYSQL_STMT *stmt, my_bool remove)
 1299 {
 1300   char stmt_id[STMT_ID_LENGTH];
 1301   MA_MEM_ROOT *fields_ma_alloc_root= &((MADB_STMT_EXTENSION *)stmt->extension)->fields_ma_alloc_root;
 1302 
 1303   /* clear memory */
 1304   ma_free_root(&stmt->result.alloc, MYF(0)); /* allocated in mysql_stmt_store_result */
 1305   ma_free_root(&stmt->mem_root,MYF(0));
 1306   ma_free_root(fields_ma_alloc_root, MYF(0));
 1307 
 1308   if (stmt->mysql)
 1309   {
 1310     CLEAR_CLIENT_ERROR(stmt->mysql);
 1311 
 1312     /* remove from stmt list */
 1313     if (remove)
 1314       stmt->mysql->stmts= list_delete(stmt->mysql->stmts, &stmt->list);
 1315 
 1316     /* check if all data are fetched */
 1317     if (stmt->mysql->status != MYSQL_STATUS_READY)
 1318     {
 1319       do {
 1320         stmt->mysql->methods->db_stmt_flush_unbuffered(stmt);
 1321       } while(mysql_stmt_more_results(stmt));
 1322       stmt->mysql->status= MYSQL_STATUS_READY;
 1323     }
 1324     if (stmt->state > MYSQL_STMT_INITTED)
 1325     {
 1326       int4store(stmt_id, stmt->stmt_id);
 1327       if (stmt->mysql->methods->db_command(stmt->mysql,COM_STMT_CLOSE, stmt_id,
 1328                                            sizeof(stmt_id), 1, stmt))
 1329       {
 1330         SET_CLIENT_STMT_ERROR(stmt, stmt->mysql->net.last_errno, stmt->mysql->net.sqlstate, stmt->mysql->net.last_error);
 1331         return 1;
 1332       }
 1333     }
 1334   }
 1335   return 0;
 1336 }
 1337 
 1338 my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
 1339 {
 1340   my_bool rc= 1;
 1341 
 1342   if (stmt)
 1343   {
 1344     if (stmt->mysql && stmt->mysql->net.pvio)
 1345       mysql_stmt_internal_reset(stmt, 1);
 1346 
 1347     rc= net_stmt_close(stmt, 1);
 1348 
 1349     free(stmt->extension);
 1350     free(stmt);
 1351   }
 1352   return(rc);
 1353 }
 1354 
 1355 void STDCALL mysql_stmt_data_seek(MYSQL_STMT *stmt, unsigned long long offset)
 1356 {
 1357   unsigned long long i= offset;
 1358   MYSQL_ROWS *ptr= stmt->result.data;
 1359 
 1360   while(i-- && ptr)
 1361     ptr= ptr->next;
 1362 
 1363   stmt->result_cursor= ptr;
 1364   stmt->state= MYSQL_STMT_USER_FETCHING;
 1365 
 1366   return;
 1367 }
 1368 
 1369 unsigned int STDCALL mysql_stmt_errno(MYSQL_STMT *stmt)
 1370 {
 1371   return stmt->last_errno;
 1372 }
 1373 
 1374 const char * STDCALL mysql_stmt_error(MYSQL_STMT *stmt)
 1375 {
 1376   return (const char *)stmt->last_error;
 1377 }
 1378 
 1379 int mthd_stmt_fetch_row(MYSQL_STMT *stmt, unsigned char **row)
 1380 {
 1381   return stmt->fetch_row_func(stmt, row);
 1382 }
 1383 
 1384 int STDCALL mysql_stmt_fetch(MYSQL_STMT *stmt)
 1385 {
 1386   unsigned char *row;
 1387   int rc;
 1388 
 1389   if (stmt->state <= MYSQL_STMT_EXECUTED)
 1390   {
 1391     SET_CLIENT_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
 1392     return(1);
 1393   }
 1394 
 1395   if (stmt->state < MYSQL_STMT_WAITING_USE_OR_STORE || !stmt->field_count)
 1396   {
 1397     SET_CLIENT_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
 1398     return(1);
 1399   } else if (stmt->state== MYSQL_STMT_WAITING_USE_OR_STORE)
 1400   {
 1401     stmt->default_rset_handler(stmt);
 1402   }
 1403 
 1404   if (stmt->state == MYSQL_STMT_FETCH_DONE)
 1405     return(MYSQL_NO_DATA);
 1406 
 1407   if ((rc= stmt->mysql->methods->db_stmt_fetch(stmt, &row)))
 1408   {
 1409     stmt->state= MYSQL_STMT_FETCH_DONE;
 1410     stmt->mysql->status= MYSQL_STATUS_READY;
 1411     /* to fetch data again, stmt must be executed again */
 1412     return(rc);
 1413   }
 1414 
 1415   if ((rc= stmt->mysql->methods->db_stmt_fetch_to_bind(stmt, row)))
 1416   {
 1417     return(rc);
 1418   }
 1419 
 1420   stmt->state= MYSQL_STMT_USER_FETCHING;
 1421   CLEAR_CLIENT_ERROR(stmt->mysql);
 1422   CLEAR_CLIENT_STMT_ERROR(stmt);
 1423   return(0);
 1424 }
 1425 
 1426 int STDCALL mysql_stmt_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind, unsigned int column, unsigned long offset)
 1427 {
 1428   if (stmt->state < MYSQL_STMT_USER_FETCHING || column >= stmt->field_count ||
 1429       stmt->state == MYSQL_STMT_FETCH_DONE)  {
 1430     SET_CLIENT_STMT_ERROR(stmt, CR_NO_DATA, SQLSTATE_UNKNOWN, 0);
 1431     return(1);
 1432   }
 1433 
 1434   if (!stmt->bind[column].u.row_ptr)
 1435   {
 1436     /* we set row_ptr only for columns which contain data, so this must be a NULL column */
 1437     if (bind[0].is_null)
 1438       *bind[0].is_null= 1;
 1439   }
 1440   else
 1441   {
 1442     unsigned char *save_ptr;
 1443     if (bind[0].length)
 1444       *bind[0].length= *stmt->bind[column].length;
 1445     else
 1446       bind[0].length= &stmt->bind[column].length_value;
 1447     if (bind[0].is_null)
 1448       *bind[0].is_null= 0;
 1449     else
 1450       bind[0].is_null= &bind[0].is_null_value;
 1451     if (!bind[0].error)
 1452       bind[0].error= &bind[0].error_value;
 1453     *bind[0].error= 0;
 1454     bind[0].offset= offset;
 1455     save_ptr= stmt->bind[column].u.row_ptr;
 1456     mysql_ps_fetch_functions[stmt->fields[column].type].func(&bind[0], &stmt->fields[column], &stmt->bind[column].u.row_ptr);
 1457     stmt->bind[column].u.row_ptr= save_ptr;
 1458   }
 1459   return(0);
 1460 }
 1461 
 1462 unsigned int STDCALL mysql_stmt_field_count(MYSQL_STMT *stmt)
 1463 {
 1464   return stmt->field_count;
 1465 }
 1466 
 1467 my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt)
 1468 {
 1469   return madb_reset_stmt(stmt, MADB_RESET_LONGDATA | MADB_RESET_STORED |
 1470                                MADB_RESET_BUFFER | MADB_RESET_ERROR);
 1471 }
 1472 
 1473 MYSQL_STMT * STDCALL mysql_stmt_init(MYSQL *mysql)
 1474 {
 1475 
 1476   MYSQL_STMT *stmt= NULL;
 1477 
 1478   if (!(stmt= (MYSQL_STMT *)calloc(1, sizeof(MYSQL_STMT))) ||
 1479       !(stmt->extension= (MADB_STMT_EXTENSION *)calloc(1, sizeof(MADB_STMT_EXTENSION))))
 1480   {
 1481     free(stmt);
 1482     SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
 1483     return(NULL);
 1484   }
 1485 
 1486 
 1487   /* fill mysql's stmt list */
 1488   stmt->list.data= stmt;
 1489   stmt->mysql= mysql;
 1490   stmt->stmt_id= 0;
 1491   mysql->stmts= list_add(mysql->stmts, &stmt->list);
 1492 
 1493 
 1494   /* clear flags */
 1495   strcpy(stmt->sqlstate, "00000");
 1496 
 1497   stmt->state= MYSQL_STMT_INITTED;
 1498 
 1499   /* set default */
 1500   stmt->prefetch_rows= 1;
 1501 
 1502   ma_init_alloc_root(&stmt->mem_root, 2048, 2048);
 1503   ma_init_alloc_root(&stmt->result.alloc, 4096, 4096);
 1504   ma_init_alloc_root(&((MADB_STMT_EXTENSION *)stmt->extension)->fields_ma_alloc_root, 2048, 2048);
 1505 
 1506   return(stmt);
 1507 }
 1508 
 1509 my_bool mthd_stmt_read_prepare_response(MYSQL_STMT *stmt)
 1510 {
 1511   ulong packet_length;
 1512   uchar *p;
 1513 
 1514   if ((packet_length= ma_net_safe_read(stmt->mysql)) == packet_error)
 1515     return(1);
 1516 
 1517   p= (uchar *)stmt->mysql->net.read_pos;
 1518 
 1519   if (0xFF == p[0])  /* Error occurred */
 1520   {
 1521     return(1);
 1522   }
 1523 
 1524   p++;
 1525   stmt->stmt_id= uint4korr(p);
 1526   p+= 4;
 1527   stmt->field_count= uint2korr(p);
 1528   p+= 2;
 1529   stmt->param_count= uint2korr(p);
 1530   p+= 2;
 1531 
 1532   /* filler */
 1533   p++;
 1534   /* for backward compatibility we also update mysql->warning_count */
 1535   stmt->mysql->warning_count= stmt->upsert_status.warning_count= uint2korr(p);
 1536   return(0);
 1537 }
 1538 
 1539 my_bool mthd_stmt_get_param_metadata(MYSQL_STMT *stmt)
 1540 {
 1541   MYSQL_DATA *result;
 1542 
 1543   if (!(result= stmt->mysql->methods->db_read_rows(stmt->mysql, (MYSQL_FIELD *)0, 7)))
 1544     return(1);
 1545 
 1546   free_rows(result);
 1547   return(0);
 1548 }
 1549 
 1550 my_bool mthd_stmt_get_result_metadata(MYSQL_STMT *stmt)
 1551 {
 1552   MYSQL_DATA *result;
 1553   MA_MEM_ROOT *fields_ma_alloc_root= &((MADB_STMT_EXTENSION *)stmt->extension)->fields_ma_alloc_root;
 1554 
 1555   if (!(result= stmt->mysql->methods->db_read_rows(stmt->mysql, (MYSQL_FIELD *)0, 7)))
 1556     return(1);
 1557   if (!(stmt->fields= unpack_fields(result,fields_ma_alloc_root,
 1558           stmt->field_count, 0,
 1559           stmt->mysql->server_capabilities & CLIENT_LONG_FLAG)))
 1560     return(1);
 1561   return(0);
 1562 }
 1563 
 1564 int STDCALL mysql_stmt_warning_count(MYSQL_STMT *stmt)
 1565 {
 1566   return stmt->upsert_status.warning_count;
 1567 }
 1568 
 1569 int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, unsigned long length)
 1570 {
 1571   MYSQL *mysql= stmt->mysql;
 1572   int rc= 1;
 1573   my_bool is_multi= 0;
 1574 
 1575   if (!stmt->mysql)
 1576   {
 1577     SET_CLIENT_STMT_ERROR(stmt, CR_SERVER_LOST, SQLSTATE_UNKNOWN, 0);
 1578     return(1);
 1579   }
 1580 
 1581   if (length == (unsigned long) -1)
 1582     length= (unsigned long)strlen(query);
 1583 
 1584   /* clear flags */
 1585   CLEAR_CLIENT_STMT_ERROR(stmt);
 1586   CLEAR_CLIENT_ERROR(stmt->mysql);
 1587   stmt->upsert_status.affected_rows= mysql->affected_rows= (unsigned long long) ~0;
 1588 
 1589   /* check if we have to clear results */
 1590   if (stmt->state > MYSQL_STMT_INITTED)
 1591   {
 1592     char stmt_id[STMT_ID_LENGTH];
 1593     is_multi= (mysql->net.extension->multi_status > COM_MULTI_OFF);
 1594     /* We need to semi-close the prepared statement:
 1595        reset stmt and free all buffers and close the statement
 1596        on server side. Statement handle will get a new stmt_id */
 1597 
 1598     if (!is_multi)
 1599       ma_multi_command(mysql, COM_MULTI_ENABLED);
 1600 
 1601     if (mysql_stmt_internal_reset(stmt, 1))
 1602       goto fail;
 1603 
 1604     ma_free_root(&stmt->mem_root, MYF(MY_KEEP_PREALLOC));
 1605     ma_free_root(&((MADB_STMT_EXTENSION *)stmt->extension)->fields_ma_alloc_root, MYF(0));
 1606 
 1607     stmt->param_count= 0;
 1608     stmt->field_count= 0;
 1609     stmt->params= 0;
 1610 
 1611     int4store(stmt_id, stmt->stmt_id);
 1612     if (mysql->methods->db_command(mysql, COM_STMT_CLOSE, stmt_id,
 1613                                          sizeof(stmt_id), 1, stmt))
 1614       goto fail;
 1615   }
 1616   if (mysql->methods->db_command(mysql, COM_STMT_PREPARE, query, length, 1, stmt))
 1617     goto fail;
 1618 
 1619   if (!is_multi && mysql->net.extension->multi_status == COM_MULTI_ENABLED)
 1620     ma_multi_command(mysql, COM_MULTI_END);
 1621   
 1622   if (mysql->net.extension->multi_status > COM_MULTI_OFF)
 1623     return 0;
 1624 
 1625   if (mysql->methods->db_read_prepare_response &&
 1626       mysql->methods->db_read_prepare_response(stmt))
 1627     goto fail;
 1628 
 1629   /* metadata not supported yet */
 1630 
 1631   if (stmt->param_count &&
 1632       stmt->mysql->methods->db_stmt_get_param_metadata(stmt))
 1633   {
 1634     goto fail;
 1635   }
 1636 
 1637   /* allocated bind buffer for parameters */
 1638   if (stmt->field_count &&
 1639       stmt->mysql->methods->db_stmt_get_result_metadata(stmt))
 1640   {
 1641     goto fail;
 1642   }
 1643   if (stmt->param_count)
 1644   {
 1645     if (stmt->prebind_params)
 1646     {
 1647       if (stmt->prebind_params != stmt->param_count)
 1648       {
 1649         SET_CLIENT_STMT_ERROR(stmt, CR_INVALID_PARAMETER_NO, SQLSTATE_UNKNOWN, 0);
 1650         goto fail;
 1651       }
 1652     } else {
 1653       if (!(stmt->params= (MYSQL_BIND *)ma_alloc_root(&stmt->mem_root, stmt->param_count * sizeof(MYSQL_BIND))))
 1654       {
 1655         SET_CLIENT_STMT_ERROR(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
 1656         goto fail;
 1657       }
 1658       memset(stmt->params, '\0', stmt->param_count * sizeof(MYSQL_BIND));
 1659     }
 1660   }
 1661   /* allocated bind buffer for result */
 1662   if (stmt->field_count)
 1663   {
 1664     MA_MEM_ROOT *fields_ma_alloc_root= &((MADB_STMT_EXTENSION *)stmt->extension)->fields_ma_alloc_root;
 1665     if (!(stmt->bind= (MYSQL_BIND *)ma_alloc_root(fields_ma_alloc_root, stmt->field_count * sizeof(MYSQL_BIND))))
 1666     {
 1667       SET_CLIENT_STMT_ERROR(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
 1668       goto fail;
 1669     }
 1670     memset(stmt->bind, 0, sizeof(MYSQL_BIND) * stmt->field_count);
 1671   }
 1672   stmt->state = MYSQL_STMT_PREPARED;
 1673   return(0);
 1674 
 1675 fail:
 1676   stmt->state= MYSQL_STMT_INITTED;
 1677   SET_CLIENT_STMT_ERROR(stmt, mysql->net.last_errno, mysql->net.sqlstate,
 1678       mysql->net.last_error);
 1679   return(rc);
 1680 }
 1681 
 1682 int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt)
 1683 {
 1684   unsigned int last_server_status;
 1685 
 1686   if (!stmt->mysql)
 1687   {
 1688     SET_CLIENT_STMT_ERROR(stmt, CR_SERVER_LOST, SQLSTATE_UNKNOWN, 0);
 1689     return(1);
 1690   }
 1691 
 1692   if (!stmt->field_count)
 1693     return(0);
 1694 
 1695   /* test_pure_coverage requires checking of error_no */
 1696   if (stmt->last_errno)
 1697     return(1);
 1698 
 1699   if (stmt->state < MYSQL_STMT_EXECUTED)
 1700   {
 1701     SET_CLIENT_ERROR(stmt->mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
 1702     SET_CLIENT_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
 1703     return(1);
 1704   }
 1705 
 1706   last_server_status= stmt->mysql->server_status;
 1707 
 1708   /* if stmt is a cursor, we need to tell server to send all rows */
 1709   if (stmt->cursor_exists && stmt->mysql->status == MYSQL_STATUS_READY)
 1710   {
 1711     char buff[STMT_ID_LENGTH + 4];
 1712     int4store(buff, stmt->stmt_id);
 1713     int4store(buff + STMT_ID_LENGTH, (int)~0);
 1714 
 1715     if (stmt->mysql->methods->db_command(stmt->mysql, COM_STMT_FETCH,
 1716                                          buff, sizeof(buff), 1, stmt))
 1717       return(1);
 1718     /* todo: cursor */
 1719   }
 1720   else if (stmt->mysql->status != MYSQL_STATUS_STMT_RESULT)
 1721   {
 1722     SET_CLIENT_ERROR(stmt->mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
 1723     SET_CLIENT_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
 1724     return(1);
 1725   }
 1726 
 1727   if (stmt->mysql->methods->db_stmt_read_all_rows(stmt))
 1728   {
 1729     /* error during read - reset stmt->data */
 1730     ma_free_root(&stmt->result.alloc, 0);
 1731     stmt->result.data= NULL;
 1732     stmt->result.rows= 0;
 1733     stmt->mysql->status= MYSQL_STATUS_READY;
 1734     return(1);
 1735   }
 1736 
 1737   /* workaround for MDEV 6304:
 1738      more results not set if the resultset has
 1739      SERVER_PS_OUT_PARAMS set
 1740    */
 1741   if (last_server_status & SERVER_PS_OUT_PARAMS &&
 1742       !(stmt->mysql->server_status & SERVER_MORE_RESULTS_EXIST))
 1743     stmt->mysql->server_status|= SERVER_MORE_RESULTS_EXIST;
 1744 
 1745   stmt->result_cursor= stmt->result.data;
 1746   stmt->fetch_row_func= stmt_buffered_fetch;
 1747   stmt->mysql->status= MYSQL_STATUS_READY;
 1748 
 1749   if (!stmt->result.rows)
 1750     stmt->state= MYSQL_STMT_FETCH_DONE;
 1751   else
 1752     stmt->state= MYSQL_STMT_USE_OR_STORE_CALLED;
 1753 
 1754   /* set affected rows: see bug 2247 */
 1755   stmt->upsert_status.affected_rows= stmt->result.rows;
 1756   stmt->mysql->affected_rows= stmt->result.rows;
 1757 
 1758   return(0);
 1759 }
 1760 
 1761 static int madb_alloc_stmt_fields(MYSQL_STMT *stmt)
 1762 {
 1763   uint i;
 1764   MA_MEM_ROOT *fields_ma_alloc_root= &((MADB_STMT_EXTENSION *)stmt->extension)->fields_ma_alloc_root;
 1765 
 1766   if (stmt->mysql->field_count)
 1767   {
 1768     ma_free_root(fields_ma_alloc_root, MYF(0));
 1769     if (!(stmt->fields= (MYSQL_FIELD *)ma_alloc_root(fields_ma_alloc_root,
 1770             sizeof(MYSQL_FIELD) * stmt->mysql->field_count)))
 1771     {
 1772       SET_CLIENT_STMT_ERROR(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
 1773       return(1);
 1774     }
 1775     stmt->field_count= stmt->mysql->field_count;
 1776 
 1777     for (i=0; i < stmt->field_count; i++)
 1778     {
 1779       if (stmt->mysql->fields[i].db)
 1780         stmt->fields[i].db= ma_strdup_root(fields_ma_alloc_root, stmt->mysql->fields[i].db);
 1781       if (stmt->mysql->fields[i].table)
 1782         stmt->fields[i].table= ma_strdup_root(fields_ma_alloc_root, stmt->mysql->fields[i].table);
 1783       if (stmt->mysql->fields[i].org_table)
 1784         stmt->fields[i].org_table= ma_strdup_root(fields_ma_alloc_root, stmt->mysql->fields[i].org_table);
 1785       if (stmt->mysql->fields[i].name)
 1786         stmt->fields[i].name= ma_strdup_root(fields_ma_alloc_root, stmt->mysql->fields[i].name);
 1787       if (stmt->mysql->fields[i].org_name)
 1788         stmt->fields[i].org_name= ma_strdup_root(fields_ma_alloc_root, stmt->mysql->fields[i].org_name);
 1789       if (stmt->mysql->fields[i].catalog)
 1790         stmt->fields[i].catalog= ma_strdup_root(fields_ma_alloc_root, stmt->mysql->fields[i].catalog);
 1791       stmt->fields[i].def= stmt->mysql->fields[i].def ? ma_strdup_root(fields_ma_alloc_root, stmt->mysql->fields[i].def) : NULL;
 1792       stmt->fields[i].type= stmt->mysql->fields[i].type;
 1793       stmt->fields[i].length= stmt->mysql->fields[i].length;
 1794       stmt->fields[i].flags= stmt->mysql->fields[i].flags;
 1795       stmt->fields[i].decimals= stmt->mysql->fields[i].decimals;
 1796       stmt->fields[i].charsetnr= stmt->mysql->fields[i].charsetnr;
 1797       stmt->fields[i].max_length= stmt->mysql->fields[i].max_length;
 1798     }
 1799     if (!(stmt->bind= (MYSQL_BIND *)ma_alloc_root(fields_ma_alloc_root, stmt->field_count * sizeof(MYSQL_BIND))))
 1800     {
 1801       SET_CLIENT_STMT_ERROR(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
 1802       return(1);
 1803     }
 1804     memset(stmt->bind, 0, stmt->field_count * sizeof(MYSQL_BIND));
 1805     stmt->bind_result_done= 0;
 1806   }
 1807   return(0);
 1808 }
 1809 
 1810 int stmt_read_execute_response(MYSQL_STMT *stmt)
 1811 {
 1812   MYSQL *mysql= stmt->mysql;
 1813   int ret;
 1814 
 1815   if (!mysql)
 1816     return(1);
 1817 
 1818   ret= test((mysql->methods->db_read_stmt_result &&
 1819                  mysql->methods->db_read_stmt_result(mysql)));
 1820   /* if a reconnect occurred, our connection handle is invalid */
 1821   if (!stmt->mysql)
 1822     return(1);
 1823 
 1824   /* update affected rows, also if an error occurred */
 1825   stmt->upsert_status.affected_rows= stmt->mysql->affected_rows;
 1826 
 1827   if (ret)
 1828   {
 1829     SET_CLIENT_STMT_ERROR(stmt, mysql->net.last_errno, mysql->net.sqlstate,
 1830        mysql->net.last_error);
 1831     stmt->state= MYSQL_STMT_PREPARED;
 1832     return(1);
 1833   }
 1834   stmt->upsert_status.last_insert_id= mysql->insert_id;
 1835   stmt->upsert_status.server_status= mysql->server_status;
 1836   stmt->upsert_status.warning_count= mysql->warning_count;
 1837 
 1838   CLEAR_CLIENT_ERROR(mysql);
 1839   CLEAR_CLIENT_STMT_ERROR(stmt);
 1840 
 1841   stmt->execute_count++;
 1842   stmt->send_types_to_server= 0;
 1843 
 1844   stmt->state= MYSQL_STMT_EXECUTED;
 1845 
 1846   if (mysql->field_count)
 1847   {
 1848     if (!stmt->field_count ||
 1849         mysql->server_status & SERVER_MORE_RESULTS_EXIST) /* fix for ps_bug: test_misc */
 1850     {
 1851       MA_MEM_ROOT *fields_ma_alloc_root=
 1852                   &((MADB_STMT_EXTENSION *)stmt->extension)->fields_ma_alloc_root;
 1853       uint i;
 1854 
 1855       ma_free_root(fields_ma_alloc_root, MYF(0));
 1856       if (!(stmt->bind= (MYSQL_BIND *)ma_alloc_root(fields_ma_alloc_root,
 1857               sizeof(MYSQL_BIND) * mysql->field_count)) ||
 1858           !(stmt->fields= (MYSQL_FIELD *)ma_alloc_root(fields_ma_alloc_root,
 1859               sizeof(MYSQL_FIELD) * mysql->field_count)))
 1860       {
 1861         SET_CLIENT_STMT_ERROR(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
 1862         return(1);
 1863       }
 1864       memset(stmt->bind, 0, sizeof(MYSQL_BIND) * mysql->field_count);
 1865       stmt->field_count= mysql->field_count;
 1866 
 1867       for (i=0; i < stmt->field_count; i++)
 1868       {
 1869         memcpy(&stmt->fields[i], &mysql->fields[i], sizeof(MYSQL_FIELD));
 1870 
 1871         /* since  all pointers will be incorrect if another statement will
 1872            be executed, so we need to allocate memory and copy the
 1873            information */
 1874         stmt->fields[i].extension= 0; /* not in use yet */
 1875         if (mysql->fields[i].db)
 1876           stmt->fields[i].db= ma_strdup_root(fields_ma_alloc_root, mysql->fields[i].db);
 1877         if (mysql->fields[i].table)
 1878           stmt->fields[i].table= ma_strdup_root(fields_ma_alloc_root, mysql->fields[i].table);
 1879         if (mysql->fields[i].org_table)
 1880           stmt->fields[i].org_table= ma_strdup_root(fields_ma_alloc_root, mysql->fields[i].org_table);
 1881         if (mysql->fields[i].name)
 1882           stmt->fields[i].name= ma_strdup_root(fields_ma_alloc_root, mysql->fields[i].name);
 1883         if (mysql->fields[i].org_name)
 1884           stmt->fields[i].org_name= ma_strdup_root(fields_ma_alloc_root, mysql->fields[i].org_name);
 1885         if (mysql->fields[i].catalog)
 1886           stmt->fields[i].catalog= ma_strdup_root(fields_ma_alloc_root, mysql->fields[i].catalog);
 1887         if (mysql->fields[i].def)
 1888           stmt->fields[i].def= ma_strdup_root(fields_ma_alloc_root, mysql->fields[i].def);
 1889       }
 1890     }
 1891 
 1892     if (stmt->upsert_status.server_status & SERVER_STATUS_CURSOR_EXISTS)
 1893     {
 1894       stmt->cursor_exists = TRUE;
 1895       mysql->status = MYSQL_STATUS_READY;
 1896 
 1897       /* Only cursor read */
 1898       stmt->default_rset_handler = _mysql_stmt_use_result;
 1899 
 1900     } else if (stmt->flags & CURSOR_TYPE_READ_ONLY)
 1901     {
 1902       /*
 1903          We have asked for CURSOR but got no cursor, because the condition
 1904          above is not fulfilled. Then...
 1905          This is a single-row result set, a result set with no rows, EXPLAIN,
 1906          SHOW VARIABLES, or some other command which either a) bypasses the
 1907          cursors framework in the server and writes rows directly to the
 1908          network or b) is more efficient if all (few) result set rows are
 1909          precached on client and server's resources are freed.
 1910          */
 1911 
 1912       /* preferred is buffered read */
 1913       if (mysql_stmt_store_result(stmt))
 1914         return 1;
 1915       stmt->mysql->status= MYSQL_STATUS_STMT_RESULT;
 1916     } else
 1917     {
 1918       /* preferred is unbuffered read */
 1919       stmt->default_rset_handler = _mysql_stmt_use_result;
 1920       stmt->mysql->status= MYSQL_STATUS_STMT_RESULT;
 1921     }
 1922     stmt->state= MYSQL_STMT_WAITING_USE_OR_STORE;
 1923     /* in certain cases parameter types can change: For example see bug
 1924        4026 (SELECT ?), so we need to update field information */
 1925     if (mysql->field_count == stmt->field_count)
 1926     {
 1927       uint i;
 1928       for (i=0; i < stmt->field_count; i++)
 1929       {
 1930         stmt->fields[i].type= mysql->fields[i].type;
 1931         stmt->fields[i].length= mysql->fields[i].length;
 1932         stmt->fields[i].flags= mysql->fields[i].flags;
 1933         stmt->fields[i].decimals= mysql->fields[i].decimals;
 1934         stmt->fields[i].charsetnr= mysql->fields[i].charsetnr;
 1935         stmt->fields[i].max_length= mysql->fields[i].max_length;
 1936       }
 1937     } else
 1938     {
 1939       /* table was altered, see test_wl4166_2  */
 1940       SET_CLIENT_STMT_ERROR(stmt, CR_NEW_STMT_METADATA, SQLSTATE_UNKNOWN, 0);
 1941       return(1);
 1942     }
 1943   }
 1944   return(0);
 1945 }
 1946 
 1947 int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt)
 1948 {
 1949   MYSQL *mysql= stmt->mysql;
 1950   char *request;
 1951   int ret;
 1952   size_t request_len= 0;
 1953 
 1954   if (!stmt->mysql)
 1955   {
 1956     SET_CLIENT_STMT_ERROR(stmt, CR_SERVER_LOST, SQLSTATE_UNKNOWN, 0);
 1957     return(1);
 1958   }
 1959 
 1960   if (stmt->state < MYSQL_STMT_PREPARED)
 1961   {
 1962     SET_CLIENT_ERROR(mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
 1963     SET_CLIENT_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
 1964     return(1);
 1965   }
 1966 
 1967   if (stmt->param_count && !stmt->bind_param_done)
 1968   {
 1969     SET_CLIENT_STMT_ERROR(stmt, CR_PARAMS_NOT_BOUND, SQLSTATE_UNKNOWN, 0);
 1970     return(1);
 1971   }
 1972 
 1973   if (stmt->state == MYSQL_STMT_WAITING_USE_OR_STORE)
 1974   {
 1975     stmt->default_rset_handler = _mysql_stmt_use_result;
 1976     stmt->default_rset_handler(stmt);
 1977   }
 1978   if (stmt->state > MYSQL_STMT_WAITING_USE_OR_STORE && stmt->state < MYSQL_STMT_FETCH_DONE && !stmt->result.data)
 1979   {
 1980     if (!stmt->cursor_exists)
 1981       do {
 1982         stmt->mysql->methods->db_stmt_flush_unbuffered(stmt);
 1983       } while(mysql_stmt_more_results(stmt));
 1984     stmt->state= MYSQL_STMT_PREPARED;
 1985     stmt->mysql->status= MYSQL_STATUS_READY;
 1986   }
 1987 
 1988   /* clear data, in case mysql_stmt_store_result was called */
 1989   if (stmt->result.data)
 1990   {
 1991     ma_free_root(&stmt->result.alloc, MYF(MY_KEEP_PREALLOC));
 1992     stmt->result_cursor= stmt->result.data= 0;
 1993   }
 1994   /* CONC-344: set row count to zero */
 1995   stmt->result.rows= 0;
 1996   if (stmt->array_size > 0)
 1997     request= (char *)mysql_stmt_execute_generate_bulk_request(stmt, &request_len);
 1998   else
 1999     request= (char *)mysql_stmt_execute_generate_simple_request(stmt, &request_len);
 2000 
 2001   if (!request)
 2002     return 1;
 2003 
 2004   ret= stmt->mysql->methods->db_command(mysql, 
 2005                                         stmt->array_size > 0 ? COM_STMT_BULK_EXECUTE : COM_STMT_EXECUTE,
 2006                                         request, request_len, 1, stmt);
 2007   if (request)
 2008     free(request);
 2009 
 2010   if (ret)
 2011   {
 2012     SET_CLIENT_STMT_ERROR(stmt, mysql->net.last_errno, mysql->net.sqlstate,
 2013     mysql->net.last_error);
 2014     return(1);
 2015   }
 2016 
 2017   if (mysql->net.extension->multi_status > COM_MULTI_OFF)
 2018     return(0);
 2019 
 2020   return(stmt_read_execute_response(stmt));
 2021 }
 2022 
 2023 static my_bool madb_reset_stmt(MYSQL_STMT *stmt, unsigned int flags)
 2024 {
 2025   MYSQL *mysql= stmt->mysql;
 2026   my_bool ret= 0;
 2027 
 2028   if (!stmt->mysql)
 2029   {
 2030     SET_CLIENT_STMT_ERROR(stmt, CR_SERVER_LOST, SQLSTATE_UNKNOWN, 0);
 2031     return(1);
 2032   }
 2033 
 2034   /* clear error */
 2035   if (flags & MADB_RESET_ERROR)
 2036   {
 2037     CLEAR_CLIENT_ERROR(stmt->mysql);
 2038     CLEAR_CLIENT_STMT_ERROR(stmt);
 2039   }
 2040 
 2041   if (stmt->stmt_id)
 2042   {
 2043     /* free buffered resultset, previously allocated
 2044      * by mysql_stmt_store_result
 2045      */
 2046     if (flags & MADB_RESET_STORED &&
 2047         stmt->result_cursor)
 2048     {
 2049       ma_free_root(&stmt->result.alloc, MYF(MY_KEEP_PREALLOC));
 2050       stmt->result.data= NULL;
 2051       stmt->result.rows= 0;
 2052       stmt->result_cursor= NULL;
 2053       stmt->mysql->status= MYSQL_STATUS_READY;
 2054       stmt->state= MYSQL_STMT_FETCH_DONE;
 2055     }
 2056 
 2057     /* if there is a pending result set, we will flush it */
 2058     if (flags & MADB_RESET_BUFFER)
 2059     {
 2060       if (stmt->state == MYSQL_STMT_WAITING_USE_OR_STORE)
 2061       {
 2062         stmt->default_rset_handler(stmt);
 2063         stmt->state = MYSQL_STMT_USER_FETCHING;
 2064       }
 2065 
 2066       if (stmt->mysql->status!= MYSQL_STATUS_READY && stmt->field_count)
 2067       {
 2068         mysql->methods->db_stmt_flush_unbuffered(stmt);
 2069         mysql->status= MYSQL_STATUS_READY;
 2070       }
 2071     }
 2072 
 2073     if (flags & MADB_RESET_SERVER)
 2074     {
 2075       /* reset statement on server side */
 2076       if (stmt->mysql && stmt->mysql->status == MYSQL_STATUS_READY &&
 2077           stmt->mysql->net.pvio)
 2078       {
 2079         unsigned char cmd_buf[STMT_ID_LENGTH];
 2080         int4store(cmd_buf, stmt->stmt_id);
 2081         if ((ret= stmt->mysql->methods->db_command(mysql,COM_STMT_RESET, (char *)cmd_buf,
 2082                                                    sizeof(cmd_buf), 0, stmt)))
 2083         {
 2084           SET_CLIENT_STMT_ERROR(stmt, mysql->net.last_errno, mysql->net.sqlstate,
 2085               mysql->net.last_error);
 2086           return(ret);
 2087         }
 2088       }
 2089     }
 2090 
 2091     if (flags & MADB_RESET_LONGDATA)
 2092     {
 2093       if (stmt->params)
 2094       {
 2095         ulonglong i;
 2096         for (i=0; i < stmt->param_count; i++)
 2097           if (stmt->params[i].long_data_used)
 2098             stmt->params[i].long_data_used= 0;
 2099       }
 2100     }
 2101 
 2102   }
 2103   return(ret);
 2104 }
 2105 
 2106 static my_bool mysql_stmt_internal_reset(MYSQL_STMT *stmt, my_bool is_close)
 2107 {
 2108   MYSQL *mysql= stmt->mysql;
 2109   my_bool ret= 1;
 2110   unsigned int flags= MADB_RESET_LONGDATA | MADB_RESET_BUFFER | MADB_RESET_ERROR;
 2111 
 2112   if (!mysql)
 2113   {
 2114     /* connection could be invalid, e.g. after mysql_stmt_close or failed reconnect
 2115        attempt (see bug CONC-97) */
 2116     SET_CLIENT_STMT_ERROR(stmt, CR_SERVER_LOST, SQLSTATE_UNKNOWN, 0);
 2117     return(1);
 2118   }
 2119 
 2120   if (stmt->state >= MYSQL_STMT_USER_FETCHING &&
 2121       stmt->fetch_row_func == stmt_unbuffered_fetch)
 2122     flags|= MADB_RESET_BUFFER;
 2123 
 2124   ret= madb_reset_stmt(stmt, flags);
 2125 
 2126   if (stmt->stmt_id)
 2127   {
 2128     if ((stmt->state > MYSQL_STMT_EXECUTED &&
 2129         stmt->mysql->status != MYSQL_STATUS_READY) ||
 2130         stmt->mysql->server_status & SERVER_MORE_RESULTS_EXIST)
 2131     {
 2132       /* flush any pending (multiple) result sets */
 2133       if (stmt->state == MYSQL_STMT_WAITING_USE_OR_STORE)
 2134       {
 2135         stmt->default_rset_handler(stmt);
 2136         stmt->state = MYSQL_STMT_USER_FETCHING;
 2137       }
 2138 
 2139       if (stmt->field_count)
 2140       {
 2141         while (mysql_stmt_next_result(stmt) == 0);
 2142         stmt->mysql->status= MYSQL_STATUS_READY;
 2143       }
 2144     }
 2145     if (!is_close)
 2146       ret= madb_reset_stmt(stmt, MADB_RESET_SERVER);
 2147   }
 2148   stmt->state= MYSQL_STMT_PREPARED;
 2149   stmt->upsert_status.affected_rows= mysql->affected_rows;
 2150   stmt->upsert_status.last_insert_id= mysql->insert_id;
 2151   stmt->upsert_status.server_status= mysql->server_status;
 2152   stmt->upsert_status.warning_count= mysql->warning_count;
 2153   mysql->status= MYSQL_STATUS_READY;
 2154 
 2155   return(ret);
 2156 }
 2157 
 2158 MYSQL_RES * STDCALL mysql_stmt_result_metadata(MYSQL_STMT *stmt)
 2159 {
 2160   MYSQL_RES *res;
 2161 
 2162   if (!stmt->field_count)
 2163     return(NULL);
 2164 
 2165   /* aloocate result set structutr and copy stmt information */
 2166   if (!(res= (MYSQL_RES *)calloc(1, sizeof(MYSQL_RES))))
 2167   {
 2168     SET_CLIENT_STMT_ERROR(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
 2169     return(NULL);
 2170   }
 2171 
 2172   res->eof= 1;
 2173   res->fields= stmt->fields;
 2174   res->field_count= stmt->field_count;
 2175   return(res);
 2176 }
 2177 
 2178 my_bool STDCALL mysql_stmt_reset(MYSQL_STMT *stmt)
 2179 {
 2180   return mysql_stmt_internal_reset(stmt, 0);
 2181 }
 2182 
 2183 const char * STDCALL mysql_stmt_sqlstate(MYSQL_STMT *stmt)
 2184 {
 2185   return stmt->sqlstate;
 2186 }
 2187 
 2188 MYSQL_ROW_OFFSET STDCALL mysql_stmt_row_tell(MYSQL_STMT *stmt)
 2189 {
 2190   return(stmt->result_cursor);
 2191 }
 2192 
 2193 unsigned long STDCALL mysql_stmt_param_count(MYSQL_STMT *stmt)
 2194 {
 2195   return stmt->param_count;
 2196 }
 2197 
 2198 MYSQL_ROW_OFFSET STDCALL mysql_stmt_row_seek(MYSQL_STMT *stmt, MYSQL_ROW_OFFSET new_row)
 2199 {
 2200   MYSQL_ROW_OFFSET old_row; /* for returning old position */
 2201 
 2202   old_row= stmt->result_cursor;
 2203   stmt->result_cursor= new_row;
 2204 
 2205   return(old_row);
 2206 }
 2207 
 2208 my_bool STDCALL mysql_stmt_send_long_data(MYSQL_STMT *stmt, uint param_number,
 2209     const char *data, unsigned long length)
 2210 {
 2211   CLEAR_CLIENT_ERROR(stmt->mysql);
 2212   CLEAR_CLIENT_STMT_ERROR(stmt);
 2213 
 2214   if (stmt->state < MYSQL_STMT_PREPARED || !stmt->params)
 2215   {
 2216     SET_CLIENT_STMT_ERROR(stmt, CR_NO_PREPARE_STMT, SQLSTATE_UNKNOWN, 0);
 2217     return(1);
 2218   }
 2219 
 2220   if (param_number >= stmt->param_count)
 2221   {
 2222     SET_CLIENT_STMT_ERROR(stmt, CR_INVALID_PARAMETER_NO, SQLSTATE_UNKNOWN, 0);
 2223     return(1);
 2224   }
 2225 
 2226   if (length || !stmt->params[param_number].long_data_used)
 2227   {
 2228     int ret;
 2229     size_t packet_len= STMT_ID_LENGTH + 2 + length;
 2230     uchar *cmd_buff= (uchar *)calloc(1, packet_len);
 2231     int4store(cmd_buff, stmt->stmt_id);
 2232     int2store(cmd_buff + STMT_ID_LENGTH, param_number);
 2233     memcpy(cmd_buff + STMT_ID_LENGTH + 2, data, length);
 2234     stmt->params[param_number].long_data_used= 1;
 2235     ret= stmt->mysql->methods->db_command(stmt->mysql, COM_STMT_SEND_LONG_DATA,
 2236                                          (char *)cmd_buff, packet_len, 1, stmt);
 2237     free(cmd_buff);
 2238     return(ret);
 2239   }
 2240   return(0);
 2241 }
 2242 
 2243 unsigned long long STDCALL mysql_stmt_insert_id(MYSQL_STMT *stmt)
 2244 {
 2245   return stmt->upsert_status.last_insert_id;
 2246 }
 2247 
 2248 unsigned long long STDCALL mysql_stmt_num_rows(MYSQL_STMT *stmt)
 2249 {
 2250   return stmt->result.rows;
 2251 }
 2252 
 2253 MYSQL_RES* STDCALL mysql_stmt_param_metadata(MYSQL_STMT *stmt __attribute__((unused)))
 2254 {
 2255   /* server doesn't deliver any information yet,
 2256      so we just return NULL
 2257      */
 2258   return(NULL);
 2259 }
 2260 
 2261 my_bool STDCALL mysql_stmt_more_results(MYSQL_STMT *stmt)
 2262 {
 2263   /* MDEV 4604: Server doesn't set MORE_RESULT flag for
 2264                 OutParam result set, so we need to check
 2265                 for SERVER_MORE_RESULTS_EXIST and for
 2266                 SERVER_PS_OUT_PARAMS)
 2267   */
 2268   return (stmt &&
 2269           stmt->mysql &&
 2270           ((stmt->mysql->server_status & SERVER_MORE_RESULTS_EXIST) ||
 2271            (stmt->mysql->server_status & SERVER_PS_OUT_PARAMS)));
 2272 }
 2273 
 2274 int STDCALL mysql_stmt_next_result(MYSQL_STMT *stmt)
 2275 {
 2276   int rc= 0;
 2277 
 2278   if (!stmt->mysql)
 2279   {
 2280     SET_CLIENT_STMT_ERROR(stmt, CR_SERVER_LOST, SQLSTATE_UNKNOWN, 0);
 2281     return(1);
 2282   }
 2283 
 2284   if (stmt->state < MYSQL_STMT_EXECUTED)
 2285   {
 2286     SET_CLIENT_ERROR(stmt->mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
 2287     SET_CLIENT_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
 2288     return(1);
 2289   }
 2290 
 2291   if (!mysql_stmt_more_results(stmt))
 2292     return(-1);
 2293 
 2294   if (stmt->state > MYSQL_STMT_EXECUTED &&
 2295       stmt->state < MYSQL_STMT_FETCH_DONE)
 2296     madb_reset_stmt(stmt, MADB_RESET_ERROR | MADB_RESET_BUFFER | MADB_RESET_LONGDATA);
 2297   stmt->state= MYSQL_STMT_WAITING_USE_OR_STORE;
 2298 
 2299   if (mysql_next_result(stmt->mysql))
 2300   {
 2301     stmt->state= MYSQL_STMT_FETCH_DONE;
 2302     SET_CLIENT_STMT_ERROR(stmt, stmt->mysql->net.last_errno, stmt->mysql->net.sqlstate,
 2303         stmt->mysql->net.last_error);
 2304     return(1);
 2305   }
 2306 
 2307   if (stmt->mysql->status == MYSQL_STATUS_GET_RESULT)
 2308     stmt->mysql->status= MYSQL_STATUS_STMT_RESULT; 
 2309 
 2310   if (stmt->mysql->field_count)
 2311     rc= madb_alloc_stmt_fields(stmt);
 2312   else
 2313   {
 2314     stmt->upsert_status.affected_rows= stmt->mysql->affected_rows;
 2315     stmt->upsert_status.last_insert_id= stmt->mysql->insert_id;
 2316     stmt->upsert_status.server_status= stmt->mysql->server_status;
 2317     stmt->upsert_status.warning_count= stmt->mysql->warning_count;
 2318   }
 2319 
 2320   stmt->field_count= stmt->mysql->field_count;
 2321 
 2322   return(rc);
 2323 }
 2324 
 2325 int STDCALL mariadb_stmt_execute_direct(MYSQL_STMT *stmt,
 2326                                       const char *stmt_str,
 2327                                       size_t length)
 2328 {
 2329   MYSQL *mysql;
 2330   my_bool emulate_cmd;
 2331 
 2332   if (!stmt)
 2333     return 1;
 2334 
 2335   mysql= stmt->mysql;
 2336   if (!mysql)
 2337   {
 2338     SET_CLIENT_STMT_ERROR(stmt, CR_SERVER_LOST, SQLSTATE_UNKNOWN, 0);
 2339     return 1;
 2340   }
 2341 
 2342   emulate_cmd= !(!(stmt->mysql->server_capabilities & CLIENT_MYSQL) &&
 2343       (stmt->mysql->extension->mariadb_server_capabilities &
 2344       (MARIADB_CLIENT_STMT_BULK_OPERATIONS >> 32))) || mysql->net.compress;
 2345 
 2346   /* Server versions < 10.2 don't support execute_direct, so we need to 
 2347      emulate it */
 2348   if (emulate_cmd)
 2349   {
 2350     int rc;
 2351 
 2352     /* avoid sending close + prepare in 2 packets */
 2353     if ((rc= mysql_stmt_prepare(stmt, stmt_str, (unsigned long)length)))
 2354       return rc;
 2355     return mysql_stmt_execute(stmt);
 2356   }
 2357 
 2358   if (ma_multi_command(mysql, COM_MULTI_ENABLED))
 2359   {
 2360     SET_CLIENT_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
 2361     return 1;
 2362   }
 2363 
 2364   if (length == (size_t) -1)
 2365     length= strlen(stmt_str);
 2366 
 2367   /* clear flags */
 2368   CLEAR_CLIENT_STMT_ERROR(stmt);
 2369   CLEAR_CLIENT_ERROR(stmt->mysql);
 2370   stmt->upsert_status.affected_rows= mysql->affected_rows= (unsigned long long) ~0;
 2371 
 2372   /* check if we have to clear results */
 2373   if (stmt->state > MYSQL_STMT_INITTED)
 2374   {
 2375     /* We need to semi-close the prepared statement:
 2376        reset stmt and free all buffers and close the statement
 2377        on server side. Statement handle will get a new stmt_id */
 2378     char stmt_id[STMT_ID_LENGTH];
 2379 
 2380     if (mysql_stmt_internal_reset(stmt, 1))
 2381       goto fail;
 2382 
 2383     ma_free_root(&stmt->mem_root, MYF(MY_KEEP_PREALLOC));
 2384     ma_free_root(&((MADB_STMT_EXTENSION *)stmt->extension)->fields_ma_alloc_root, MYF(0));
 2385     stmt->field_count= 0;
 2386     stmt->param_count= 0;
 2387     stmt->params= 0;
 2388 
 2389     int4store(stmt_id, stmt->stmt_id);
 2390     if (mysql->methods->db_command(mysql, COM_STMT_CLOSE, stmt_id,
 2391                                          sizeof(stmt_id), 1, stmt))
 2392       goto fail;
 2393   }
 2394   stmt->stmt_id= -1;
 2395   if (mysql->methods->db_command(mysql, COM_STMT_PREPARE, stmt_str, length, 1, stmt))
 2396     goto fail;
 2397 
 2398   stmt->state= MYSQL_STMT_PREPARED;
 2399   /* Since we can't determine stmt_id here, we need to set it to -1, so server will know that the
 2400    * execute command belongs to previous prepare */
 2401   stmt->stmt_id= -1;
 2402   if (mysql_stmt_execute(stmt))
 2403     goto fail;
 2404 
 2405   /* flush multi buffer */
 2406   if (ma_multi_command(mysql, COM_MULTI_END))
 2407     goto fail;
 2408 
 2409   /* read prepare response */
 2410   if (mysql->methods->db_read_prepare_response &&
 2411     mysql->methods->db_read_prepare_response(stmt))
 2412   goto fail;
 2413 
 2414   /* metadata not supported yet */
 2415 
 2416   if (stmt->param_count &&
 2417       stmt->mysql->methods->db_stmt_get_param_metadata(stmt))
 2418   {
 2419     goto fail;
 2420   }
 2421 
 2422   /* allocated bind buffer for parameters */
 2423   if (stmt->field_count &&
 2424       stmt->mysql->methods->db_stmt_get_result_metadata(stmt))
 2425   {
 2426     goto fail;
 2427   }
 2428 
 2429   /* allocated bind buffer for result */
 2430   if (stmt->field_count)
 2431   {
 2432     MA_MEM_ROOT *fields_ma_alloc_root= &((MADB_STMT_EXTENSION *)stmt->extension)->fields_ma_alloc_root;
 2433     if (!(stmt->bind= (MYSQL_BIND *)ma_alloc_root(fields_ma_alloc_root, stmt->field_count * sizeof(MYSQL_BIND))))
 2434     {
 2435       SET_CLIENT_STMT_ERROR(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
 2436       goto fail;
 2437     }
 2438     memset(stmt->bind, 0, sizeof(MYSQL_BIND) * stmt->field_count);
 2439   }
 2440   stmt->state = MYSQL_STMT_PREPARED;
 2441 
 2442   /* read execute response packet */
 2443   return stmt_read_execute_response(stmt);
 2444 fail:
 2445   /* check if we need to set error message */
 2446   if (!mysql_stmt_errno(stmt))
 2447     SET_CLIENT_STMT_ERROR(stmt, mysql->net.last_errno, mysql->net.sqlstate,
 2448         mysql->net.last_error);
 2449   do {
 2450     stmt->mysql->methods->db_stmt_flush_unbuffered(stmt);
 2451   } while(mysql_stmt_more_results(stmt));
 2452   stmt->state= MYSQL_STMT_INITTED;
 2453   return 1;
 2454 }