| 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 | |