| 1 | /************************************************************************ | 
| 2 |    | 
| 3 |    This library is free software; you can redistribute it and/or | 
| 4 |    modify it under the terms of the GNU Library General Public | 
| 5 |    License as published by the Free Software Foundation; either | 
| 6 |    version 2 of the License, or (at your option) any later version. | 
| 7 |     | 
| 8 |    This library is distributed in the hope that it will be useful, | 
| 9 |    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
| 10 |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
| 11 |    Library General Public License for more details. | 
| 12 |     | 
| 13 |    You should have received a copy of the GNU Library General Public | 
| 14 |    License along with this library; if not, write to the Free | 
| 15 |    Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, | 
| 16 |    MA 02111-1301, USA  | 
| 17 |  | 
| 18 |    Part of this code includes code from PHP's mysqlnd extension | 
| 19 |    (written by Andrey Hristov, Georg Richter and Ulf Wendel), freely | 
| 20 |    available from http://www.php.net/software | 
| 21 |  | 
| 22 | *************************************************************************/ | 
| 23 |  | 
| 24 | #define MYSQL_NO_DATA 100 | 
| 25 | #define MYSQL_DATA_TRUNCATED 101 | 
| 26 | #define MYSQL_DEFAULT_PREFETCH_ROWS (unsigned long) 1 | 
| 27 |  | 
| 28 | /* Bind flags */ | 
| 29 | #define MADB_BIND_DUMMY 1 | 
| 30 |  | 
| 31 | #define MARIADB_STMT_BULK_SUPPORTED(stmt)\ | 
| 32 |   ((stmt)->mysql && \ | 
| 33 |   (!((stmt)->mysql->server_capabilities & CLIENT_MYSQL) &&\ | 
| 34 |     ((stmt)->mysql->extension->mariadb_server_capabilities & \ | 
| 35 |     (MARIADB_CLIENT_STMT_BULK_OPERATIONS >> 32)))) | 
| 36 |  | 
| 37 | #define SET_CLIENT_STMT_ERROR(a, b, c, d) \ | 
| 38 | { \ | 
| 39 |   (a)->last_errno= (b);\ | 
| 40 |   strncpy((a)->sqlstate, (c), sizeof((a)->sqlstate));\ | 
| 41 |   strncpy((a)->last_error, (d) ? (d) : ER((b)), sizeof((a)->last_error));\ | 
| 42 | } | 
| 43 |  | 
| 44 | #define CLEAR_CLIENT_STMT_ERROR(a) \ | 
| 45 | { \ | 
| 46 |   (a)->last_errno= 0;\ | 
| 47 |   strcpy((a)->sqlstate, "00000");\ | 
| 48 |   (a)->last_error[0]= 0;\ | 
| 49 | } | 
| 50 |  | 
| 51 | #define MYSQL_PS_SKIP_RESULT_W_LEN  -1 | 
| 52 | #define MYSQL_PS_SKIP_RESULT_STR    -2 | 
| 53 | #define STMT_ID_LENGTH 4 | 
| 54 |  | 
| 55 |  | 
| 56 | typedef struct st_mysql_stmt MYSQL_STMT; | 
| 57 |  | 
| 58 | typedef MYSQL_RES* (*mysql_stmt_use_or_store_func)(MYSQL_STMT *); | 
| 59 |  | 
| 60 | enum enum_stmt_attr_type | 
| 61 | { | 
| 62 |   STMT_ATTR_UPDATE_MAX_LENGTH, | 
| 63 |   STMT_ATTR_CURSOR_TYPE, | 
| 64 |   STMT_ATTR_PREFETCH_ROWS, | 
| 65 |   STMT_ATTR_PREBIND_PARAMS=200, | 
| 66 |   STMT_ATTR_ARRAY_SIZE, | 
| 67 |   STMT_ATTR_ROW_SIZE | 
| 68 | }; | 
| 69 |  | 
| 70 | enum enum_cursor_type | 
| 71 | { | 
| 72 |   CURSOR_TYPE_NO_CURSOR= 0, | 
| 73 |   CURSOR_TYPE_READ_ONLY= 1, | 
| 74 |   CURSOR_TYPE_FOR_UPDATE= 2, | 
| 75 |   CURSOR_TYPE_SCROLLABLE= 4 | 
| 76 | }; | 
| 77 |  | 
| 78 | enum enum_indicator_type | 
| 79 | { | 
| 80 |   STMT_INDICATOR_NTS=-1, | 
| 81 |   STMT_INDICATOR_NONE=0, | 
| 82 |   STMT_INDICATOR_NULL=1, | 
| 83 |   STMT_INDICATOR_DEFAULT=2, | 
| 84 |   STMT_INDICATOR_IGNORE=3, | 
| 85 |   STMT_INDICATOR_IGNORE_ROW=4 | 
| 86 | }; | 
| 87 |  | 
| 88 | /* | 
| 89 |   bulk PS flags | 
| 90 | */ | 
| 91 | #define STMT_BULK_FLAG_CLIENT_SEND_TYPES 128 | 
| 92 | #define STMT_BULK_FLAG_INSERT_ID_REQUEST 64 | 
| 93 |  | 
| 94 | typedef enum mysql_stmt_state | 
| 95 | { | 
| 96 |   MYSQL_STMT_INITTED = 0, | 
| 97 |   MYSQL_STMT_PREPARED, | 
| 98 |   MYSQL_STMT_EXECUTED, | 
| 99 |   MYSQL_STMT_WAITING_USE_OR_STORE, | 
| 100 |   MYSQL_STMT_USE_OR_STORE_CALLED, | 
| 101 |   MYSQL_STMT_USER_FETCHING, /* fetch_row_buff or fetch_row_unbuf */ | 
| 102 |   MYSQL_STMT_FETCH_DONE | 
| 103 | } enum_mysqlnd_stmt_state; | 
| 104 |  | 
| 105 | typedef struct st_mysql_bind | 
| 106 | { | 
| 107 |   unsigned long  *length;          /* output length pointer */ | 
| 108 |   my_bool        *is_null;         /* Pointer to null indicator */ | 
| 109 |   void           *buffer;          /* buffer to get/put data */ | 
| 110 |   /* set this if you want to track data truncations happened during fetch */ | 
| 111 |   my_bool        *error; | 
| 112 |   union { | 
| 113 |     unsigned char *row_ptr;        /* for the current data position */ | 
| 114 |     char *indicator;               /* indicator variable */ | 
| 115 |   } u; | 
| 116 |   void (*store_param_func)(NET *net, struct st_mysql_bind *param); | 
| 117 |   void (*fetch_result)(struct st_mysql_bind *, MYSQL_FIELD *, | 
| 118 |                        unsigned char **row); | 
| 119 |   void (*skip_result)(struct st_mysql_bind *, MYSQL_FIELD *, | 
| 120 |           unsigned char **row); | 
| 121 |   /* output buffer length, must be set when fetching str/binary */ | 
| 122 |   unsigned long  buffer_length; | 
| 123 |   unsigned long  offset;           /* offset position for char/binary fetch */ | 
| 124 |   unsigned long  length_value;     /* Used if length is 0 */ | 
| 125 |   unsigned int   flags;            /* special flags, e.g. for dummy bind  */ | 
| 126 |   unsigned int   pack_length;      /* Internal length for packed data */ | 
| 127 |   enum enum_field_types buffer_type;  /* buffer type */ | 
| 128 |   my_bool        error_value;      /* used if error is 0 */ | 
| 129 |   my_bool        is_unsigned;      /* set if integer type is unsigned */ | 
| 130 |   my_bool        long_data_used;   /* If used with mysql_send_long_data */ | 
| 131 |   my_bool        is_null_value;    /* Used if is_null is 0 */ | 
| 132 |   void           *extension; | 
| 133 | } MYSQL_BIND; | 
| 134 |  | 
| 135 | typedef struct st_mysqlnd_upsert_result | 
| 136 | { | 
| 137 |   unsigned int  warning_count; | 
| 138 |   unsigned int  server_status; | 
| 139 |   unsigned long long affected_rows; | 
| 140 |   unsigned long long last_insert_id; | 
| 141 | } mysql_upsert_status; | 
| 142 |  | 
| 143 | typedef struct st_mysql_cmd_buffer | 
| 144 | { | 
| 145 |   unsigned char   *buffer; | 
| 146 |   size_t     length; | 
| 147 | } MYSQL_CMD_BUFFER; | 
| 148 |  | 
| 149 | typedef struct st_mysql_error_info | 
| 150 | { | 
| 151 |   unsigned int error_no; | 
| 152 |   char error[MYSQL_ERRMSG_SIZE+1]; | 
| 153 |   char sqlstate[SQLSTATE_LENGTH + 1]; | 
| 154 | } mysql_error_info; | 
| 155 |  | 
| 156 |  | 
| 157 | struct st_mysqlnd_stmt_methods | 
| 158 | { | 
| 159 |   my_bool (*prepare)(const MYSQL_STMT * stmt, const char * const query, size_t query_len); | 
| 160 |   my_bool (*execute)(const MYSQL_STMT * stmt); | 
| 161 |   MYSQL_RES * (*use_result)(const MYSQL_STMT * stmt); | 
| 162 |   MYSQL_RES * (*store_result)(const MYSQL_STMT * stmt); | 
| 163 |   MYSQL_RES * (*get_result)(const MYSQL_STMT * stmt); | 
| 164 |   my_bool (*free_result)(const MYSQL_STMT * stmt); | 
| 165 |   my_bool (*seek_data)(const MYSQL_STMT * stmt, unsigned long long row); | 
| 166 |   my_bool (*reset)(const MYSQL_STMT * stmt); | 
| 167 |   my_bool (*close)(const MYSQL_STMT * stmt); /* private */ | 
| 168 |   my_bool (*dtor)(const MYSQL_STMT * stmt); /* use this for mysqlnd_stmt_close */ | 
| 169 |  | 
| 170 |   my_bool (*fetch)(const MYSQL_STMT * stmt, my_bool * const fetched_anything); | 
| 171 |  | 
| 172 |   my_bool (*bind_param)(const MYSQL_STMT * stmt, const MYSQL_BIND bind); | 
| 173 |   my_bool (*refresh_bind_param)(const MYSQL_STMT * stmt); | 
| 174 |   my_bool (*bind_result)(const MYSQL_STMT * stmt, const MYSQL_BIND *bind); | 
| 175 |   my_bool (*send_long_data)(const MYSQL_STMT * stmt, unsigned int param_num, | 
| 176 |                             const char * const data, size_t length); | 
| 177 |   MYSQL_RES *(*get_parameter_metadata)(const MYSQL_STMT * stmt); | 
| 178 |   MYSQL_RES *(*get_result_metadata)(const MYSQL_STMT * stmt); | 
| 179 |   unsigned long long (*get_last_insert_id)(const MYSQL_STMT * stmt); | 
| 180 |   unsigned long long (*get_affected_rows)(const MYSQL_STMT * stmt); | 
| 181 |   unsigned long long (*get_num_rows)(const MYSQL_STMT * stmt); | 
| 182 |  | 
| 183 |   unsigned int (*get_param_count)(const MYSQL_STMT * stmt); | 
| 184 |   unsigned int (*get_field_count)(const MYSQL_STMT * stmt); | 
| 185 |   unsigned int (*get_warning_count)(const MYSQL_STMT * stmt); | 
| 186 |  | 
| 187 |   unsigned int (*get_error_no)(const MYSQL_STMT * stmt); | 
| 188 |   const char * (*get_error_str)(const MYSQL_STMT * stmt); | 
| 189 |   const char * (*get_sqlstate)(const MYSQL_STMT * stmt); | 
| 190 |  | 
| 191 |   my_bool (*get_attribute)(const MYSQL_STMT * stmt, enum enum_stmt_attr_type attr_type, const void * value); | 
| 192 |   my_bool (*set_attribute)(const MYSQL_STMT * stmt, enum enum_stmt_attr_type attr_type, const void * value); | 
| 193 |   void (*set_error)(MYSQL_STMT *stmt, unsigned int error_nr, const char *sqlstate, const char *format, ...); | 
| 194 | }; | 
| 195 |  | 
| 196 | typedef int  (*mysql_stmt_fetch_row_func)(MYSQL_STMT *stmt, unsigned char **row); | 
| 197 |  | 
| 198 | struct st_mysql_stmt | 
| 199 | { | 
| 200 |   MA_MEM_ROOT              mem_root; | 
| 201 |   MYSQL                    *mysql; | 
| 202 |   unsigned long            stmt_id; | 
| 203 |   unsigned long            flags;/* cursor is set here */ | 
| 204 |   enum_mysqlnd_stmt_state  state; | 
| 205 |   MYSQL_FIELD              *fields; | 
| 206 |   unsigned int             field_count; | 
| 207 |   unsigned int             param_count; | 
| 208 |   unsigned char            send_types_to_server; | 
| 209 |   MYSQL_BIND               *params; | 
| 210 |   MYSQL_BIND               *bind; | 
| 211 |   MYSQL_DATA               result;  /* we don't use mysqlnd's result set logic */ | 
| 212 |   MYSQL_ROWS               *result_cursor; | 
| 213 |   my_bool                  bind_result_done; | 
| 214 |   my_bool                  bind_param_done; | 
| 215 |  | 
| 216 |   mysql_upsert_status      upsert_status; | 
| 217 |  | 
| 218 |   unsigned int last_errno; | 
| 219 |   char last_error[MYSQL_ERRMSG_SIZE+1]; | 
| 220 |   char sqlstate[SQLSTATE_LENGTH + 1]; | 
| 221 |  | 
| 222 |   my_bool                  update_max_length; | 
| 223 |   unsigned long            prefetch_rows; | 
| 224 |   LIST                     list; | 
| 225 |  | 
| 226 |   my_bool                  cursor_exists; | 
| 227 |  | 
| 228 |   void                     *extension; | 
| 229 |   mysql_stmt_fetch_row_func fetch_row_func; | 
| 230 |   unsigned int             execute_count;/* count how many times the stmt was executed */ | 
| 231 |   mysql_stmt_use_or_store_func default_rset_handler; | 
| 232 |   struct st_mysqlnd_stmt_methods  *m; | 
| 233 |   unsigned int             array_size; | 
| 234 |   size_t row_size; | 
| 235 |   unsigned int prebind_params; | 
| 236 | }; | 
| 237 |  | 
| 238 | typedef void (*ps_field_fetch_func)(MYSQL_BIND *r_param, const MYSQL_FIELD * field, unsigned char **row); | 
| 239 | typedef struct st_mysql_perm_bind { | 
| 240 |   ps_field_fetch_func func; | 
| 241 |   /* should be signed int */ | 
| 242 |   int pack_len; | 
| 243 |   unsigned long max_len; | 
| 244 | } MYSQL_PS_CONVERSION; | 
| 245 |  | 
| 246 | extern MYSQL_PS_CONVERSION mysql_ps_fetch_functions[MYSQL_TYPE_GEOMETRY + 1]; | 
| 247 | unsigned long ma_net_safe_read(MYSQL *mysql); | 
| 248 | void mysql_init_ps_subsystem(void); | 
| 249 | unsigned long net_field_length(unsigned char **packet); | 
| 250 | int ma_simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg, | 
| 251 |           	       size_t length, my_bool skipp_check, void *opt_arg); | 
| 252 | /* | 
| 253 |  *  function prototypes | 
| 254 |  */ | 
| 255 | MYSQL_STMT * STDCALL mysql_stmt_init(MYSQL *mysql); | 
| 256 | int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, unsigned long length); | 
| 257 | int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt); | 
| 258 | int STDCALL mysql_stmt_fetch(MYSQL_STMT *stmt); | 
| 259 | int STDCALL mysql_stmt_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind_arg, unsigned int column, unsigned long offset); | 
| 260 | int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt); | 
| 261 | unsigned long STDCALL mysql_stmt_param_count(MYSQL_STMT * stmt); | 
| 262 | my_bool STDCALL mysql_stmt_attr_set(MYSQL_STMT *stmt, enum enum_stmt_attr_type attr_type, const void *attr); | 
| 263 | my_bool STDCALL mysql_stmt_attr_get(MYSQL_STMT *stmt, enum enum_stmt_attr_type attr_type, void *attr); | 
| 264 | my_bool STDCALL mysql_stmt_bind_param(MYSQL_STMT * stmt, MYSQL_BIND * bnd); | 
| 265 | my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT * stmt, MYSQL_BIND * bnd); | 
| 266 | my_bool STDCALL mysql_stmt_close(MYSQL_STMT * stmt); | 
| 267 | my_bool STDCALL mysql_stmt_reset(MYSQL_STMT * stmt); | 
| 268 | my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt); | 
| 269 | my_bool STDCALL mysql_stmt_send_long_data(MYSQL_STMT *stmt, unsigned int param_number, const char *data, unsigned long length); | 
| 270 | MYSQL_RES *STDCALL mysql_stmt_result_metadata(MYSQL_STMT *stmt); | 
| 271 | MYSQL_RES *STDCALL mysql_stmt_param_metadata(MYSQL_STMT *stmt); | 
| 272 | unsigned int STDCALL mysql_stmt_errno(MYSQL_STMT * stmt); | 
| 273 | const char *STDCALL mysql_stmt_error(MYSQL_STMT * stmt); | 
| 274 | const char *STDCALL mysql_stmt_sqlstate(MYSQL_STMT * stmt); | 
| 275 | MYSQL_ROW_OFFSET STDCALL mysql_stmt_row_seek(MYSQL_STMT *stmt, MYSQL_ROW_OFFSET offset); | 
| 276 | MYSQL_ROW_OFFSET STDCALL mysql_stmt_row_tell(MYSQL_STMT *stmt); | 
| 277 | void STDCALL mysql_stmt_data_seek(MYSQL_STMT *stmt, unsigned long long offset); | 
| 278 | unsigned long long STDCALL mysql_stmt_num_rows(MYSQL_STMT *stmt); | 
| 279 | unsigned long long STDCALL mysql_stmt_affected_rows(MYSQL_STMT *stmt); | 
| 280 | unsigned long long STDCALL mysql_stmt_insert_id(MYSQL_STMT *stmt); | 
| 281 | unsigned int STDCALL mysql_stmt_field_count(MYSQL_STMT *stmt); | 
| 282 | int STDCALL mysql_stmt_next_result(MYSQL_STMT *stmt); | 
| 283 | my_bool STDCALL mysql_stmt_more_results(MYSQL_STMT *stmt); | 
| 284 | int STDCALL mariadb_stmt_execute_direct(MYSQL_STMT *stmt, const char *stmt_str, size_t length); | 
| 285 |  |