mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2024-11-14 11:47:15 +01:00
1118 lines
33 KiB
C
1118 lines
33 KiB
C
/****************************************************************************
|
|
Copyright (C) 2012 Monty Program AB
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Library General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public
|
|
License along with this library; if not see <http://www.gnu.org/licenses>
|
|
or write to the Free Software Foundation, Inc.,
|
|
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
|
|
|
|
Part of this code includes code from the PHP project which
|
|
is freely available from http://www.php.net
|
|
*****************************************************************************/
|
|
|
|
/* The implementation for prepared statements was ported from PHP's mysqlnd
|
|
extension, written by Andrey Hristov, Georg Richter and Ulf Wendel
|
|
|
|
Original file header:
|
|
+----------------------------------------------------------------------+
|
|
| PHP Version 5 |
|
|
+----------------------------------------------------------------------+
|
|
| Copyright (c) 2006-2011 The PHP Group |
|
|
+----------------------------------------------------------------------+
|
|
| This source file is subject to version 3.01 of the PHP license, |
|
|
| that is bundled with this package in the file LICENSE, and is |
|
|
| available through the world-wide-web at the following url: |
|
|
| http://www.php.net/license/3_01.txt |
|
|
| If you did not receive a copy of the PHP license and are unable to |
|
|
| obtain it through the world-wide-web, please send a note to |
|
|
| license@php.net so we can mail you a copy immediately. |
|
|
+----------------------------------------------------------------------+
|
|
| Authors: Georg Richter <georg@mysql.com> |
|
|
| Andrey Hristov <andrey@mysql.com> |
|
|
| Ulf Wendel <uwendel@mysql.com> |
|
|
+----------------------------------------------------------------------+
|
|
*/
|
|
|
|
#include "my_global.h"
|
|
#include <my_sys.h>
|
|
#include <mysys_err.h>
|
|
#include <m_string.h>
|
|
#include <m_ctype.h>
|
|
#include "mysql.h"
|
|
|
|
#define MYSQL_SILENT
|
|
|
|
/* ranges for C-binding */
|
|
#define UINT_MAX32 0xFFFFFFFFL
|
|
#define UINT_MAX24 0x00FFFFFF
|
|
#define UINT_MAX16 0xFFFF
|
|
#ifndef INT_MIN8
|
|
#define INT_MIN8 (~0x7F)
|
|
#define INT_MAX8 0x7F
|
|
#endif
|
|
#define UINT_MAX8 0xFF
|
|
|
|
#if defined(HAVE_LONG_LONG) && !defined(LONGLONG_MIN)
|
|
#define LONGLONG_MIN ((long long) 0x8000000000000000LL)
|
|
#define LONGLONG_MAX ((long long) 0x7FFFFFFFFFFFFFFFLL)
|
|
#endif
|
|
|
|
#if defined(HAVE_LONG_LONG) && !defined(ULONGLONG_MAX)
|
|
/* First check for ANSI C99 definition: */
|
|
#ifdef ULLONG_MAX
|
|
#define ULONGLONG_MAX ULLONG_MAX
|
|
#else
|
|
#define ULONGLONG_MAX ((unsigned long long)(~0ULL))
|
|
#endif
|
|
#endif /* defined (HAVE_LONG_LONG) && !defined(ULONGLONG_MAX)*/
|
|
|
|
#define YY_PART_YEAR 70
|
|
#define MAX_DOUBLE_STRING_REP_LENGTH 300
|
|
|
|
MYSQL_PS_CONVERSION mysql_ps_fetch_functions[MYSQL_TYPE_GEOMETRY + 1];
|
|
my_bool mysql_ps_subsystem_initialized= 0;
|
|
|
|
|
|
#define NUMERIC_TRUNCATION(val,min_range, max_range)\
|
|
((((val) > (max_range)) || ((val) < (min_range)) ? 1 : 0))
|
|
|
|
/* helper function for zero fill */
|
|
void ma_bmove_upp(register char *dst, register const char *src, register size_t len)
|
|
{
|
|
while (len-- != 0) *--dst = *--src;
|
|
}
|
|
|
|
/* {{{ ps_fetch_from_1_to_8_bytes */
|
|
void ps_fetch_from_1_to_8_bytes(MYSQL_BIND *r_param, const MYSQL_FIELD * const field,
|
|
unsigned char **row, unsigned int byte_count)
|
|
{
|
|
my_bool is_unsigned= test(field->flags & UNSIGNED_FLAG);
|
|
r_param->buffer_length= byte_count;
|
|
switch (byte_count) {
|
|
case 1:
|
|
*(uchar *)r_param->buffer= **row;
|
|
*r_param->error= is_unsigned != r_param->is_unsigned && *(uchar *)r_param->buffer > INT_MAX8;
|
|
break;
|
|
case 2:
|
|
shortstore(r_param->buffer, ((ushort) sint2korr(*row)));
|
|
*r_param->error= is_unsigned != r_param->is_unsigned && *(ushort *)r_param->buffer > INT_MAX16;
|
|
break;
|
|
case 4:
|
|
{
|
|
longstore(r_param->buffer, ((uint32)sint4korr(*row)));
|
|
*r_param->error= is_unsigned != r_param->is_unsigned && *(uint32 *)r_param->buffer > INT_MAX32;
|
|
}
|
|
break;
|
|
case 8:
|
|
{
|
|
ulonglong val= (ulonglong)sint8korr(*row);
|
|
longlongstore(r_param->buffer, val);
|
|
*r_param->error= is_unsigned != r_param->is_unsigned && val > LONGLONG_MAX ;
|
|
}
|
|
break;
|
|
default:
|
|
r_param->buffer_length= 0;
|
|
break;
|
|
}
|
|
(*row)+= byte_count;
|
|
}
|
|
/* }}} */
|
|
|
|
static longlong my_atoll(const char *number, const char *end, int *error)
|
|
{
|
|
char buffer[255];
|
|
longlong llval= 0;
|
|
size_t i;
|
|
/* set error at the following conditions:
|
|
- string contains invalid character(s)
|
|
- length > 254
|
|
- strtoll returns invalid range
|
|
*/
|
|
|
|
memcpy(buffer, number, MIN((uint)(end - number), 254));
|
|
buffer[(uint)(end - number)]= 0;
|
|
|
|
llval= strtoll(buffer, NULL, 10);
|
|
|
|
/* check size */
|
|
if ((uint)(end - number) > 254)
|
|
{
|
|
*error= 1;
|
|
return llval;
|
|
}
|
|
|
|
/* check characters */
|
|
for (i=0; i < strlen(buffer); i++)
|
|
{
|
|
if (buffer[i] < '0' || buffer[i] > '9')
|
|
{
|
|
*error= 1;
|
|
return llval;
|
|
}
|
|
}
|
|
|
|
/* check strtoll result */
|
|
if (errno == ERANGE)
|
|
*error= errno;
|
|
return llval;
|
|
}
|
|
|
|
double my_atod(const char *number, const char *end, int *error)
|
|
{
|
|
double val= 0.0;
|
|
char buffer[255];
|
|
int len= (int)(end - number);
|
|
|
|
if (len > 254)
|
|
*error= 1;
|
|
|
|
len= MIN(len, 254);
|
|
memcpy(&buffer, number, len);
|
|
buffer[len]= '\0';
|
|
|
|
val= strtod(buffer, NULL);
|
|
/* if (!*error)
|
|
*error= errno; */
|
|
return val;
|
|
}
|
|
|
|
my_bool str_to_TIME(const char *str, size_t length, MYSQL_TIME *tm)
|
|
{
|
|
char *start= alloca(length + 1);
|
|
my_bool is_date= 0, is_time= 0;
|
|
|
|
memset(tm, 0, sizeof(MYSQL_TIME));
|
|
if (!start)
|
|
goto error;
|
|
tm->time_type= MYSQL_TIMESTAMP_NONE;
|
|
|
|
memcpy(start, str, length);
|
|
start[length]= '\0';
|
|
|
|
while (length && isspace(*start)) start++, length--;
|
|
|
|
if (!length)
|
|
goto error;
|
|
|
|
/* negativ value? */
|
|
if (*start == '-')
|
|
{
|
|
tm->neg= 1;
|
|
start++;
|
|
length--;
|
|
}
|
|
|
|
if (!length)
|
|
return 1;
|
|
|
|
/* Determine time type:
|
|
MYSQL_TIMESTAMP_DATE: [-]YY[YY].MM.DD
|
|
MYSQL_TIMESTAMP_DATETIME: [-]YY[YY].MM.DD hh:mm:ss.mmmmmm
|
|
MYSQL_TIMESTAMP_TIME: [-]hh:mm:ss.mmmmmm
|
|
*/
|
|
if (strchr(start, '-'))
|
|
{
|
|
if (tm->neg)
|
|
goto error;
|
|
tm->time_type= MYSQL_TIMESTAMP_DATE;
|
|
if (sscanf(start, "%d-%d-%d", &tm->year, &tm->month, &tm->day) < 3)
|
|
goto error;
|
|
is_date= 1;
|
|
if (!(start= strchr(start, ' ')))
|
|
goto check;
|
|
}
|
|
if (!strchr(start, ':'))
|
|
goto check;
|
|
|
|
is_time= 1;
|
|
if (tm->time_type== MYSQL_TIMESTAMP_DATE)
|
|
tm->time_type= MYSQL_TIMESTAMP_DATETIME;
|
|
else
|
|
tm->time_type= MYSQL_TIMESTAMP_TIME;
|
|
|
|
if (strchr(start, '.')) /* fractional seconds */
|
|
{
|
|
if (sscanf(start, "%d:%d:%d.%ld", &tm->hour, &tm->minute,
|
|
&tm->second,&tm->second_part) < 4)
|
|
goto error;
|
|
} else {
|
|
if (sscanf(start, "%d:%d:%d", &tm->hour, &tm->minute,
|
|
&tm->second) < 3)
|
|
goto error;
|
|
}
|
|
|
|
check:
|
|
if (tm->time_type == MYSQL_TIMESTAMP_NONE)
|
|
goto error;
|
|
|
|
if (is_date)
|
|
{
|
|
if (tm->year < 69)
|
|
tm->year+= 2000;
|
|
else if (tm->year < 100)
|
|
tm->year+= 1900;
|
|
if (tm->day > 31 || tm->month > 12)
|
|
goto error;
|
|
}
|
|
if (is_time)
|
|
{
|
|
if (tm->minute > 59 || tm->second > 59)
|
|
goto error;
|
|
}
|
|
return 0;
|
|
error:
|
|
tm->time_type= MYSQL_TIMESTAMP_ERROR;
|
|
return 1;
|
|
}
|
|
|
|
static void convert_from_string(MYSQL_BIND *r_param, char *buffer, size_t len)
|
|
{
|
|
int error= 0;
|
|
switch (r_param->buffer_type)
|
|
{
|
|
case MYSQL_TYPE_TINY:
|
|
{
|
|
longlong val= my_atoll(buffer, buffer + len, &error);
|
|
*r_param->error= error ? 1 : r_param->is_unsigned ? NUMERIC_TRUNCATION(val, 0, UINT_MAX8) : NUMERIC_TRUNCATION(val, INT_MIN8, INT_MAX8) || error > 0;
|
|
int1store(r_param->buffer, (uchar) val);
|
|
r_param->buffer_length= sizeof(uchar);
|
|
}
|
|
break;
|
|
case MYSQL_TYPE_YEAR:
|
|
case MYSQL_TYPE_SHORT:
|
|
{
|
|
longlong val= my_atoll(buffer, buffer + len, &error);
|
|
*r_param->error= error ? 1 : r_param->is_unsigned ? NUMERIC_TRUNCATION(val, 0, UINT_MAX16) : NUMERIC_TRUNCATION(val, INT_MIN16, INT_MAX16) || error > 0;
|
|
shortstore(r_param->buffer, (short)val);
|
|
r_param->buffer_length= sizeof(short);
|
|
}
|
|
break;
|
|
case MYSQL_TYPE_LONG:
|
|
{
|
|
longlong val= my_atoll(buffer, buffer + len, &error);
|
|
*r_param->error=error ? 1 : r_param->is_unsigned ? NUMERIC_TRUNCATION(val, 0, UINT_MAX32) : NUMERIC_TRUNCATION(val, INT_MIN32, INT_MAX32) || error > 0;
|
|
longstore(r_param->buffer, (int32)val);
|
|
r_param->buffer_length= sizeof(uint32);
|
|
}
|
|
break;
|
|
case MYSQL_TYPE_LONGLONG:
|
|
{
|
|
longlong val= my_atoll(buffer, buffer + len, &error);
|
|
*r_param->error= error > 0; /* no need to check for truncation */
|
|
longlongstore(r_param->buffer, val);
|
|
r_param->buffer_length= sizeof(longlong);
|
|
}
|
|
break;
|
|
case MYSQL_TYPE_DOUBLE:
|
|
{
|
|
double val= my_atod(buffer, buffer + len, &error);
|
|
*r_param->error= error > 0; /* no need to check for truncation */
|
|
doublestore((uchar *)r_param->buffer, val);
|
|
r_param->buffer_length= sizeof(double);
|
|
}
|
|
break;
|
|
case MYSQL_TYPE_FLOAT:
|
|
{
|
|
float val= (float)my_atod(buffer, buffer + len, &error);
|
|
*r_param->error= error > 0; /* no need to check for truncation */
|
|
floatstore((uchar *)r_param->buffer, val);
|
|
r_param->buffer_length= sizeof(float);
|
|
}
|
|
break;
|
|
case MYSQL_TYPE_TIME:
|
|
case MYSQL_TYPE_DATE:
|
|
case MYSQL_TYPE_DATETIME:
|
|
case MYSQL_TYPE_TIMESTAMP:
|
|
{
|
|
MYSQL_TIME *tm= (MYSQL_TIME *)r_param->buffer;
|
|
str_to_TIME(buffer, len, tm);
|
|
break;
|
|
}
|
|
break;
|
|
case MYSQL_TYPE_TINY_BLOB:
|
|
case MYSQL_TYPE_MEDIUM_BLOB:
|
|
case MYSQL_TYPE_LONG_BLOB:
|
|
case MYSQL_TYPE_BLOB:
|
|
case MYSQL_TYPE_DECIMAL:
|
|
case MYSQL_TYPE_NEWDECIMAL:
|
|
default:
|
|
{
|
|
char *start= buffer + r_param->offset; /* stmt_fetch_column sets offset */
|
|
char *end= buffer + len;
|
|
size_t copylen= 0;
|
|
|
|
if (start < end)
|
|
{
|
|
copylen= end - start;
|
|
if (r_param->buffer_length)
|
|
memcpy(r_param->buffer, start, MIN(copylen, r_param->buffer_length));
|
|
}
|
|
if (copylen < r_param->buffer_length)
|
|
((char *)r_param->buffer)[copylen]= '\0';
|
|
*r_param->error= (copylen > r_param->buffer_length);
|
|
|
|
*r_param->length= (ulong)len;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void convert_from_long(MYSQL_BIND *r_param, const MYSQL_FIELD *field, longlong val, my_bool is_unsigned)
|
|
{
|
|
switch (r_param->buffer_type) {
|
|
case MYSQL_TYPE_TINY:
|
|
*(uchar *)r_param->buffer= (uchar)val;
|
|
*r_param->error= r_param->is_unsigned ? NUMERIC_TRUNCATION(val, 0, UINT_MAX8) : NUMERIC_TRUNCATION(val, INT_MIN8, INT_MAX8);
|
|
r_param->buffer_length= 1;
|
|
break;
|
|
case MYSQL_TYPE_SHORT:
|
|
case MYSQL_TYPE_YEAR:
|
|
shortstore(r_param->buffer, (short)val);
|
|
*r_param->error= r_param->is_unsigned ? NUMERIC_TRUNCATION(val, 0, UINT_MAX16) : NUMERIC_TRUNCATION(val, INT_MIN16, INT_MAX16);
|
|
r_param->buffer_length= 2;
|
|
break;
|
|
case MYSQL_TYPE_LONG:
|
|
longstore(r_param->buffer, (int32)val);
|
|
*r_param->error= r_param->is_unsigned ? NUMERIC_TRUNCATION(val, 0, UINT_MAX32) : NUMERIC_TRUNCATION(val, INT_MIN32, INT_MAX32);
|
|
r_param->buffer_length= 4;
|
|
break;
|
|
case MYSQL_TYPE_LONGLONG:
|
|
*r_param->error= (val < 0 && r_param->is_unsigned != is_unsigned);
|
|
longlongstore(r_param->buffer, val);
|
|
r_param->buffer_length= 8;
|
|
break;
|
|
case MYSQL_TYPE_DOUBLE:
|
|
{
|
|
volatile double dbl;
|
|
|
|
dbl= (is_unsigned) ? ulonglong2double((ulonglong)val) : (double)val;
|
|
doublestore(r_param->buffer, dbl);
|
|
*r_param->error= is_unsigned ? (ulonglong )dbl != (ulonglong)val : (longlong)dbl != (longlong)val;
|
|
r_param->buffer_length= 8;
|
|
break;
|
|
}
|
|
case MYSQL_TYPE_FLOAT:
|
|
{
|
|
float fval;
|
|
fval= is_unsigned ? (float)(ulonglong)(val) : (float)val;
|
|
float4store((float *)r_param->buffer, fval);
|
|
*r_param->error= is_unsigned ? (ulonglong)fval != (ulonglong)val : (longlong)fval != val;
|
|
r_param->buffer_length= 4;
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
char buffer[22];
|
|
char *endptr;
|
|
uint len;
|
|
|
|
endptr= longlong10_to_str(val, buffer, is_unsigned ? 10 : -10);
|
|
len= (uint)(endptr - buffer);
|
|
|
|
if (field->flags & ZEROFILL_FLAG &&
|
|
len < field->length && len < r_param->buffer_length)
|
|
{
|
|
ma_bmove_upp(buffer + field->length, buffer + len, len);
|
|
memset((char*) buffer, '0', field->length - len);
|
|
len= field->length;
|
|
}
|
|
convert_from_string(r_param, buffer, len);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/* {{{ ps_fetch_null */
|
|
static
|
|
void ps_fetch_null(MYSQL_BIND *r_param, const MYSQL_FIELD * field, unsigned char **row)
|
|
{
|
|
/* do nothing */
|
|
}
|
|
/* }}} */
|
|
|
|
#define GET_LVALUE_FROM_ROW(is_unsigned, data, ucast, scast)\
|
|
(is_unsigned) ? (longlong)(ucast) *(longlong *)(data) : (longlong)(scast) *(longlong *)(data)
|
|
/* {{{ ps_fetch_int8 */
|
|
static
|
|
void ps_fetch_int8(MYSQL_BIND *r_param, const MYSQL_FIELD * const field,
|
|
unsigned char **row)
|
|
{
|
|
switch(r_param->buffer_type) {
|
|
case MYSQL_TYPE_TINY:
|
|
ps_fetch_from_1_to_8_bytes(r_param, field, row, 1);
|
|
break;
|
|
default:
|
|
{
|
|
uchar val= **row;
|
|
longlong lval= field->flags & UNSIGNED_FLAG ? (longlong) val : (longlong)(signed char)val;
|
|
convert_from_long(r_param, field, lval, field->flags & UNSIGNED_FLAG);
|
|
(*row) += 1;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
/* }}} */
|
|
|
|
|
|
/* {{{ ps_fetch_int16 */
|
|
static
|
|
void ps_fetch_int16(MYSQL_BIND *r_param, const MYSQL_FIELD * const field,
|
|
unsigned char **row)
|
|
{
|
|
switch (r_param->buffer_type) {
|
|
case MYSQL_TYPE_YEAR:
|
|
case MYSQL_TYPE_SHORT:
|
|
ps_fetch_from_1_to_8_bytes(r_param, field, row, 2);
|
|
break;
|
|
default:
|
|
{
|
|
short sval= sint2korr(*row);
|
|
longlong lval= field->flags & UNSIGNED_FLAG ? (longlong)(ushort) sval : (longlong)sval;
|
|
convert_from_long(r_param, field, lval, field->flags & UNSIGNED_FLAG);
|
|
(*row) += 2;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
/* }}} */
|
|
|
|
|
|
/* {{{ ps_fetch_int32 */
|
|
static
|
|
void ps_fetch_int32(MYSQL_BIND *r_param, const MYSQL_FIELD * const field,
|
|
unsigned char **row)
|
|
{
|
|
switch (r_param->buffer_type) {
|
|
/* case MYSQL_TYPE_TINY:
|
|
ps_fetch_from_1_to_8_bytes(r_param, field, row, 1);
|
|
break;
|
|
case MYSQL_TYPE_YEAR:
|
|
case MYSQL_TYPE_SHORT:
|
|
ps_fetch_from_1_to_8_bytes(r_param, field, row, 2);
|
|
break; */
|
|
case MYSQL_TYPE_INT24:
|
|
case MYSQL_TYPE_LONG:
|
|
ps_fetch_from_1_to_8_bytes(r_param, field, row, 4);
|
|
break;
|
|
default:
|
|
{
|
|
int32 sval= sint4korr(*row);
|
|
longlong lval= field->flags & UNSIGNED_FLAG ? (longlong)(uint32) sval : (longlong)sval;
|
|
convert_from_long(r_param, field, lval, field->flags & UNSIGNED_FLAG);
|
|
(*row) += 4;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
/* }}} */
|
|
|
|
|
|
/* {{{ ps_fetch_int64 */
|
|
static
|
|
void ps_fetch_int64(MYSQL_BIND *r_param, const MYSQL_FIELD * const field,
|
|
unsigned char **row)
|
|
{
|
|
switch(r_param->buffer_type)
|
|
{
|
|
/* case MYSQL_TYPE_TINY:
|
|
ps_fetch_from_1_to_8_bytes(r_param, field, row, 1);
|
|
break;
|
|
case MYSQL_TYPE_YEAR:
|
|
case MYSQL_TYPE_SHORT:
|
|
ps_fetch_from_1_to_8_bytes(r_param, field, row, 2);
|
|
break;
|
|
case MYSQL_TYPE_INT24:
|
|
case MYSQL_TYPE_LONG:
|
|
ps_fetch_from_1_to_8_bytes(r_param, field, row, 4);
|
|
break; */
|
|
case MYSQL_TYPE_LONGLONG:
|
|
ps_fetch_from_1_to_8_bytes(r_param, field, row, 8);
|
|
break;
|
|
default:
|
|
{
|
|
longlong sval= (longlong)sint8korr(*row);
|
|
longlong lval= field->flags & UNSIGNED_FLAG ? (ulonglong) sval : (longlong)sval;
|
|
convert_from_long(r_param, field, lval, field->flags & UNSIGNED_FLAG);
|
|
(*row) += 8;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
/* }}} */
|
|
|
|
static void convert_from_float(MYSQL_BIND *r_param, const MYSQL_FIELD *field, double val, int size)
|
|
{
|
|
double check_trunc_val= (val > 0) ? floor(val) : -floor(-val);
|
|
char *buf= (char *)r_param->buffer;
|
|
switch (r_param->buffer_type)
|
|
{
|
|
case MYSQL_TYPE_TINY:
|
|
*buf= (r_param->is_unsigned) ? (uint8)val : (int8)val;
|
|
*r_param->error= check_trunc_val != (r_param->is_unsigned ? (double)((uint8)*buf) :
|
|
(double)((int8)*buf));
|
|
r_param->buffer_length= 1;
|
|
break;
|
|
case MYSQL_TYPE_SHORT:
|
|
case MYSQL_TYPE_YEAR:
|
|
{
|
|
if (r_param->is_unsigned)
|
|
{
|
|
ushort sval= (ushort)val;
|
|
shortstore(buf, sval);
|
|
*r_param->error= check_trunc_val != (double)sval;
|
|
} else {
|
|
short sval= (short)val;
|
|
shortstore(buf, sval);
|
|
*r_param->error= check_trunc_val != (double)sval;
|
|
}
|
|
r_param->buffer_length= 2;
|
|
}
|
|
break;
|
|
case MYSQL_TYPE_LONG:
|
|
{
|
|
if (r_param->is_unsigned)
|
|
{
|
|
uint32 lval= (uint32)val;
|
|
longstore(buf, lval);
|
|
*r_param->error= (check_trunc_val != (double)lval);
|
|
} else {
|
|
int32 lval= (int32)val;
|
|
longstore(buf, lval);
|
|
*r_param->error= (check_trunc_val != (double)lval);
|
|
}
|
|
r_param->buffer_length= 4;
|
|
}
|
|
break;
|
|
case MYSQL_TYPE_LONGLONG:
|
|
{
|
|
if (r_param->is_unsigned)
|
|
{
|
|
ulonglong llval= (ulonglong)val;
|
|
longlongstore(buf, llval);
|
|
*r_param->error= (check_trunc_val != (double)llval);
|
|
} else {
|
|
longlong llval= (longlong)val;
|
|
longlongstore(buf, llval);
|
|
*r_param->error= (check_trunc_val != (double)llval);
|
|
}
|
|
r_param->buffer_length= 8;
|
|
}
|
|
break;
|
|
case MYSQL_TYPE_FLOAT:
|
|
{
|
|
float fval= (float)val;
|
|
memcpy(buf, &fval, sizeof(float));
|
|
*r_param->error= (*(float*)buf != fval);
|
|
r_param->buffer_length= 4;
|
|
}
|
|
break;
|
|
case MYSQL_TYPE_DOUBLE:
|
|
{
|
|
memcpy(buf, &val, sizeof(double));
|
|
r_param->buffer_length= 8;
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
char buff[MAX_DOUBLE_STRING_REP_LENGTH];
|
|
size_t length;
|
|
|
|
length= MIN(MAX_DOUBLE_STRING_REP_LENGTH - 1, r_param->buffer_length);
|
|
|
|
if (field->decimals >= NOT_FIXED_DEC)
|
|
{
|
|
length= ma_gcvt(val, MY_GCVT_ARG_FLOAT, length, buff, NULL);
|
|
}
|
|
else
|
|
{
|
|
length= ma_fcvt(val, field->decimals, buff, NULL);
|
|
}
|
|
|
|
/* check if ZEROFILL flag is active */
|
|
if (field->flags & ZEROFILL_FLAG)
|
|
{
|
|
/* enough space available ? */
|
|
if (field->length < length || field->length > MAX_DOUBLE_STRING_REP_LENGTH - 1)
|
|
break;
|
|
ma_bmove_upp(buff + field->length, buff + length, length);
|
|
memset((char*) buff, '0', field->length - length);
|
|
length= field->length;
|
|
}
|
|
convert_from_string(r_param, buff, length);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void convert_from_double(MYSQL_BIND *r_param, const MYSQL_FIELD *field, double val, int size)
|
|
{
|
|
double check_trunc_val= (val > 0) ? floor(val) : -floor(-val);
|
|
char *buf= (char *)r_param->buffer;
|
|
switch (r_param->buffer_type)
|
|
{
|
|
case MYSQL_TYPE_TINY:
|
|
*buf= (r_param->is_unsigned) ? (uint8)val : (int8)val;
|
|
*r_param->error= check_trunc_val != (r_param->is_unsigned ? (double)((uint8)*buf) :
|
|
(double)((int8)*buf));
|
|
r_param->buffer_length= 1;
|
|
break;
|
|
case MYSQL_TYPE_SHORT:
|
|
case MYSQL_TYPE_YEAR:
|
|
{
|
|
if (r_param->is_unsigned)
|
|
{
|
|
ushort sval= (ushort)val;
|
|
shortstore(buf, sval);
|
|
*r_param->error= check_trunc_val != (double)sval;
|
|
} else {
|
|
short sval= (short)val;
|
|
shortstore(buf, sval);
|
|
*r_param->error= check_trunc_val != (double)sval;
|
|
}
|
|
r_param->buffer_length= 2;
|
|
}
|
|
break;
|
|
case MYSQL_TYPE_LONG:
|
|
{
|
|
if (r_param->is_unsigned)
|
|
{
|
|
uint32 lval= (uint32)val;
|
|
longstore(buf, lval);
|
|
*r_param->error= (check_trunc_val != (double)lval);
|
|
} else {
|
|
int32 lval= (int32)val;
|
|
longstore(buf, lval);
|
|
*r_param->error= (check_trunc_val != (double)lval);
|
|
}
|
|
r_param->buffer_length= 4;
|
|
}
|
|
break;
|
|
case MYSQL_TYPE_LONGLONG:
|
|
{
|
|
if (r_param->is_unsigned)
|
|
{
|
|
ulonglong llval= (ulonglong)val;
|
|
longlongstore(buf, llval);
|
|
*r_param->error= (check_trunc_val != (double)llval);
|
|
} else {
|
|
longlong llval= (longlong)val;
|
|
longlongstore(buf, llval);
|
|
*r_param->error= (check_trunc_val != (double)llval);
|
|
}
|
|
r_param->buffer_length= 8;
|
|
}
|
|
break;
|
|
case MYSQL_TYPE_FLOAT:
|
|
{
|
|
float fval= (float)val;
|
|
memcpy(buf, &fval, sizeof(float));
|
|
*r_param->error= (*(float*)buf != fval);
|
|
r_param->buffer_length= 4;
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
char buff[MAX_DOUBLE_STRING_REP_LENGTH];
|
|
size_t length;
|
|
|
|
length= MIN(MAX_DOUBLE_STRING_REP_LENGTH - 1, r_param->buffer_length);
|
|
|
|
if (field->decimals >= NOT_FIXED_DEC)
|
|
{
|
|
length= ma_gcvt(val, MY_GCVT_ARG_DOUBLE, length, buff, NULL);
|
|
}
|
|
else
|
|
{
|
|
length= ma_fcvt(val, field->decimals, buff, NULL);
|
|
}
|
|
|
|
/* check if ZEROFILL flag is active */
|
|
if (field->flags & ZEROFILL_FLAG)
|
|
{
|
|
/* enough space available ? */
|
|
if (field->length < length || field->length > MAX_DOUBLE_STRING_REP_LENGTH - 1)
|
|
break;
|
|
ma_bmove_upp(buff + field->length, buff + length, length);
|
|
memset((char*) buff, '0', field->length - length);
|
|
length= field->length;
|
|
}
|
|
convert_from_string(r_param, buff, length);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/* {{{ ps_fetch_float */
|
|
static
|
|
void ps_fetch_float(MYSQL_BIND *r_param, const MYSQL_FIELD * field, unsigned char **row)
|
|
{
|
|
switch(r_param->buffer_type)
|
|
{
|
|
case MYSQL_TYPE_FLOAT:
|
|
{
|
|
float *value= (float *)r_param->buffer;
|
|
float4get(*value, *row);
|
|
r_param->buffer_length= 4;
|
|
*r_param->error= 0;
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
float value;
|
|
memcpy(&value, *row, sizeof(float));
|
|
float4get(value, (char *)*row);
|
|
convert_from_float(r_param, field, value, sizeof(float));
|
|
}
|
|
break;
|
|
}
|
|
(*row)+= 4;
|
|
}
|
|
/* }}} */
|
|
|
|
|
|
/* {{{ ps_fetch_double */
|
|
static
|
|
void ps_fetch_double(MYSQL_BIND *r_param, const MYSQL_FIELD * field , unsigned char **row)
|
|
{
|
|
switch (r_param->buffer_type)
|
|
{
|
|
case MYSQL_TYPE_DOUBLE:
|
|
{
|
|
double *value= (double *)r_param->buffer;
|
|
float8get(*value, *row);
|
|
r_param->buffer_length= 8;
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
double value;
|
|
float8get(value, *row);
|
|
convert_from_double(r_param, field, value, sizeof(double));
|
|
}
|
|
break;
|
|
}
|
|
(*row)+= 8;
|
|
}
|
|
/* }}} */
|
|
|
|
|
|
static void convert_to_datetime(MYSQL_TIME *t, unsigned char **row, uint len, enum enum_field_types type)
|
|
{
|
|
memset(t, 0, sizeof(MYSQL_TIME));
|
|
|
|
/* binary protocol for datetime:
|
|
4-bytes: DATE
|
|
7-bytes: DATE + TIME
|
|
>7 bytes: DATE + TIME with second_part
|
|
*/
|
|
|
|
if (len)
|
|
{
|
|
unsigned char *to= *row;
|
|
int has_date= 0;
|
|
uint offset= 7;
|
|
|
|
if (type == MYSQL_TYPE_TIME)
|
|
{
|
|
t->neg= to[0];
|
|
t->day= (ulong) sint4korr(to + 1);
|
|
t->time_type= MYSQL_TIMESTAMP_TIME;
|
|
offset= 8;
|
|
to++;
|
|
} else
|
|
{
|
|
t->year= (uint) sint2korr(to);
|
|
t->month= (uint) to[2];
|
|
t->day= (uint) to[3];
|
|
t->time_type= MYSQL_TIMESTAMP_DATE;
|
|
if (type == MYSQL_TYPE_DATE)
|
|
return;
|
|
has_date= 1;
|
|
}
|
|
|
|
if (len > 4)
|
|
{
|
|
t->hour= (uint) to[4];
|
|
t->minute= (uint) to[5];
|
|
t->second= (uint) to[6];
|
|
if (has_date)
|
|
t->time_type= MYSQL_TIMESTAMP_DATETIME;
|
|
}
|
|
if (len > offset)
|
|
{
|
|
t->second_part= (ulong)sint4korr(to+7);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* {{{ ps_fetch_datetime */
|
|
static
|
|
void ps_fetch_datetime(MYSQL_BIND *r_param, const MYSQL_FIELD * field,
|
|
unsigned char **row)
|
|
{
|
|
MYSQL_TIME *t= (MYSQL_TIME *)r_param->buffer;
|
|
unsigned int len= net_field_length(row);
|
|
|
|
switch (r_param->buffer_type) {
|
|
case MYSQL_TYPE_DATETIME:
|
|
case MYSQL_TYPE_TIMESTAMP:
|
|
convert_to_datetime(t, row, len, field->type);
|
|
break;
|
|
case MYSQL_TYPE_DATE:
|
|
convert_to_datetime(t, row, len, field->type);
|
|
break;
|
|
case MYSQL_TYPE_TIME:
|
|
convert_to_datetime(t, row, len, field->type);
|
|
if (t->day)
|
|
{
|
|
t->hour+= t->day * 24;
|
|
t->day= 0;
|
|
}
|
|
t->year= t->day= t->month= 0;
|
|
break;
|
|
case MYSQL_TYPE_YEAR:
|
|
{
|
|
MYSQL_TIME tm;
|
|
convert_to_datetime(&tm, row, len, field->type);
|
|
shortstore(r_param->buffer, tm.year);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
char dtbuffer[60];
|
|
MYSQL_TIME tm;
|
|
unsigned int length;
|
|
convert_to_datetime(&tm, row, len, field->type);
|
|
|
|
if (tm.time_type== MYSQL_TIMESTAMP_TIME && tm.day)
|
|
{
|
|
tm.hour+= tm.day * 24;
|
|
tm.day=0;
|
|
}
|
|
switch(field->type) {
|
|
case MYSQL_TYPE_DATE:
|
|
length= sprintf(dtbuffer, "%04u-%02u-%02u", tm.year, tm.month, tm.day);
|
|
break;
|
|
case MYSQL_TYPE_TIME:
|
|
length= sprintf(dtbuffer, "%s%02u:%02u:%02u", (tm.neg ? "-" : ""), tm.hour, tm.minute, tm.second);
|
|
if (field->decimals)
|
|
{
|
|
char ms[8];
|
|
sprintf(ms, ".%06lu", tm.second_part);
|
|
if (field->decimals < 6)
|
|
ms[field->decimals + 1]= 0;
|
|
length+= strlen(ms);
|
|
strcat(dtbuffer, ms);
|
|
}
|
|
break;
|
|
case MYSQL_TYPE_DATETIME:
|
|
case MYSQL_TYPE_TIMESTAMP:
|
|
length= sprintf(dtbuffer, "%04u-%02u-%02u %02u:%02u:%02u", tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second);
|
|
if (field->decimals)
|
|
{
|
|
char ms[8];
|
|
sprintf(ms, ".%06lu", tm.second_part);
|
|
if (field->decimals < 6)
|
|
ms[field->decimals + 1]= 0;
|
|
length+= strlen(ms);
|
|
strcat(dtbuffer, ms);
|
|
}
|
|
break;
|
|
default:
|
|
dtbuffer[0]= 0;
|
|
length= 0;
|
|
break;
|
|
}
|
|
convert_from_string(r_param, dtbuffer, length);
|
|
break;
|
|
}
|
|
}
|
|
(*row) += len;
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ ps_fetch_string */
|
|
static
|
|
void ps_fetch_string(MYSQL_BIND *r_param, const MYSQL_FIELD *field,
|
|
unsigned char **row)
|
|
{
|
|
/* C-API differs from PHP. While PHP just converts string to string,
|
|
C-API needs to convert the string to the defined type with in
|
|
the result bind buffer.
|
|
*/
|
|
ulong field_length= net_field_length(row);
|
|
|
|
convert_from_string(r_param, (char *)*row, field_length);
|
|
(*row) += field_length;
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ ps_fetch_bin */
|
|
static
|
|
void ps_fetch_bin(MYSQL_BIND *r_param, const MYSQL_FIELD *field,
|
|
unsigned char **row)
|
|
{
|
|
if (field->charsetnr == 63)
|
|
{
|
|
ulong field_length= *r_param->length= net_field_length(row);
|
|
uchar *current_pos= (*row) + r_param->offset,
|
|
*end= (*row) + field_length;
|
|
size_t copylen= 0;
|
|
|
|
if (current_pos < end)
|
|
{
|
|
copylen= end - current_pos;
|
|
if (r_param->buffer_length)
|
|
memcpy(r_param->buffer, current_pos, MIN(copylen, r_param->buffer_length));
|
|
}
|
|
if (copylen < r_param->buffer_length &&
|
|
r_param->buffer_type == MYSQL_TYPE_STRING)
|
|
((char *)r_param->buffer)[copylen]= 0;
|
|
*r_param->error= copylen > r_param->buffer_length;
|
|
(*row)+= field_length;
|
|
}
|
|
else
|
|
ps_fetch_string(r_param, field, row);
|
|
}
|
|
/* }}} */
|
|
|
|
|
|
/* {{{ _mysqlnd_init_ps_subsystem */
|
|
void mysql_init_ps_subsystem(void)
|
|
{
|
|
memset(mysql_ps_fetch_functions, 0, sizeof(mysql_ps_fetch_functions));
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_NULL].func= ps_fetch_null;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_NULL].pack_len = 0;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_NULL].max_len = 0;
|
|
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_TINY].func = ps_fetch_int8;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_TINY].pack_len = 1;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_TINY].max_len = 4;
|
|
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_SHORT].func = ps_fetch_int16;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_SHORT].pack_len = 2;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_SHORT].max_len = 6;
|
|
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_YEAR].func = ps_fetch_int16;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_YEAR].pack_len = 2;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_YEAR].max_len = 6;
|
|
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_INT24].func = ps_fetch_int32;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_INT24].pack_len = 4;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_INT24].max_len = 9;
|
|
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_LONG].func = ps_fetch_int32;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_LONG].pack_len = 4;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_LONG].max_len = 11;
|
|
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_LONGLONG].func = ps_fetch_int64;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_LONGLONG].pack_len= 8;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_LONGLONG].max_len = 21;
|
|
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_FLOAT].func = ps_fetch_float;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_FLOAT].pack_len = 4;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_FLOAT].max_len = MAX_DOUBLE_STRING_REP_LENGTH;
|
|
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_DOUBLE].func = ps_fetch_double;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_DOUBLE].pack_len = 8;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_DOUBLE].max_len = MAX_DOUBLE_STRING_REP_LENGTH;
|
|
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_TIME].func = ps_fetch_datetime;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_TIME].pack_len = MYSQL_PS_SKIP_RESULT_W_LEN;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_TIME].max_len = 15;
|
|
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_DATE].func = ps_fetch_datetime;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_DATE].pack_len = MYSQL_PS_SKIP_RESULT_W_LEN;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_DATE].max_len = 10;
|
|
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_NEWDATE].func = ps_fetch_string;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_NEWDATE].pack_len = MYSQL_PS_SKIP_RESULT_W_LEN;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_NEWDATE].max_len = -1;
|
|
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_DATETIME].func = ps_fetch_datetime;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_DATETIME].pack_len= MYSQL_PS_SKIP_RESULT_W_LEN;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_DATETIME].max_len = 30;
|
|
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_TIMESTAMP].func = ps_fetch_datetime;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_TIMESTAMP].pack_len= MYSQL_PS_SKIP_RESULT_W_LEN;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_TIMESTAMP].max_len = 30;
|
|
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_TINY_BLOB].func = ps_fetch_bin;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_TINY_BLOB].pack_len= MYSQL_PS_SKIP_RESULT_STR;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_TINY_BLOB].max_len = -1;
|
|
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_BLOB].func = ps_fetch_bin;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_BLOB].pack_len = MYSQL_PS_SKIP_RESULT_STR;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_BLOB].max_len = -1;
|
|
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_MEDIUM_BLOB].func = ps_fetch_bin;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_MEDIUM_BLOB].pack_len= MYSQL_PS_SKIP_RESULT_STR;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_MEDIUM_BLOB].max_len = -1;
|
|
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_LONG_BLOB].func = ps_fetch_bin;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_LONG_BLOB].pack_len = MYSQL_PS_SKIP_RESULT_STR;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_LONG_BLOB].max_len = -1;
|
|
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_BIT].func = ps_fetch_bin;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_BIT].pack_len = MYSQL_PS_SKIP_RESULT_STR;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_BIT].max_len = -1;
|
|
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_VAR_STRING].func = ps_fetch_string;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_VAR_STRING].pack_len = MYSQL_PS_SKIP_RESULT_STR;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_VAR_STRING].max_len = -1;
|
|
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_VARCHAR].func = ps_fetch_string;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_VARCHAR].pack_len = MYSQL_PS_SKIP_RESULT_STR;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_VARCHAR].max_len = -1;
|
|
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_STRING].func = ps_fetch_string;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_STRING].pack_len = MYSQL_PS_SKIP_RESULT_STR;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_STRING].max_len = -1;
|
|
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_DECIMAL].func = ps_fetch_string;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_DECIMAL].pack_len = MYSQL_PS_SKIP_RESULT_STR;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_DECIMAL].max_len = -1;
|
|
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_NEWDECIMAL].func = ps_fetch_string;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_NEWDECIMAL].pack_len = MYSQL_PS_SKIP_RESULT_STR;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_NEWDECIMAL].max_len = -1;
|
|
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_ENUM].func = ps_fetch_string;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_ENUM].pack_len = MYSQL_PS_SKIP_RESULT_STR;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_ENUM].max_len = -1;
|
|
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_SET].func = ps_fetch_string;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_SET].pack_len = MYSQL_PS_SKIP_RESULT_STR;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_SET].max_len = -1;
|
|
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_GEOMETRY].func = ps_fetch_string;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_GEOMETRY].pack_len= MYSQL_PS_SKIP_RESULT_STR;
|
|
mysql_ps_fetch_functions[MYSQL_TYPE_GEOMETRY].max_len = -1;
|
|
|
|
mysql_ps_subsystem_initialized= 1;
|
|
}
|
|
/* }}} */
|
|
|
|
|
|
/*
|
|
* Local variables:
|
|
* tab-width: 4
|
|
* c-basic-offset: 4
|
|
* End:
|
|
* vim600: noet sw=4 ts=4 fdm=marker
|
|
* vim<600: noet sw=4 ts=4
|
|
*/
|