/*
* DBD::mysql - DBI driver for the mysql database
*
* Copyright (c) 2005 Patrick Galbraith
* Copyright (c) 2003 Rudolf Lippan
* Copyright (c) 1997-2003 Jochen Wiedmann
*
* You may distribute this under the terms of either the GNU General Public
* License or the Artistic License, as specified in the Perl README file.
*
* $Id: dbdimp.c 7931 2006-10-10 19:58:53Z capttofu $
*/
#ifdef WIN32
#include "windows.h"
#include "winsock.h"
#endif
#include "dbdimp.h"
#if defined(WIN32) && defined(WORD)
/* Don't exactly know who's responsible for defining WORD ... :-( */
#undef WORD
typedef short WORD;
#endif
DBISTATE_DECLARE;
typedef struct sql_type_info_s
{
const char *type_name;
int data_type;
int column_size;
const char *literal_prefix;
const char *literal_suffix;
const char *create_params;
int nullable;
int case_sensitive;
int searchable;
int unsigned_attribute;
int fixed_prec_scale;
int auto_unique_value;
const char *local_type_name;
int minimum_scale;
int maximum_scale;
int num_prec_radix;
int sql_datatype;
int sql_datetime_sub;
int interval_precision;
int native_type;
int is_num;
} sql_type_info_t;
/*
This function manually counts the number of placeholders in an SQL statement,
used for emulated prepare statements < 4.1.3
*/
static int
count_params(char *statement)
{
char* ptr = statement;
int num_params = 0;
char c;
while ( (c = *ptr++) )
{
switch (c) {
case '`':
case '"':
case '\'':
/* Skip string */
{
char end_token = c;
while ((c = *ptr) && c != end_token)
{
if (c == '\\')
if (! *ptr)
continue;
++ptr;
}
if (c)
++ptr;
break;
}
case '?':
++num_params;
break;
default:
break;
}
}
return num_params;
}
/*
allocate memory in statement handle per number of placeholders
*/
static imp_sth_ph_t *alloc_param(int num_params)
{
imp_sth_ph_t *params;
if (num_params)
Newz(908, params, num_params, imp_sth_ph_t);
else
params= NULL;
return params;
}
#if MYSQL_VERSION_ID >= SERVER_PREPARE_VERSION
/*
allocate memory in MYSQL_BIND bind structure per
number of placeholders
*/
static MYSQL_BIND *alloc_bind(int num_params)
{
MYSQL_BIND *bind;
if (num_params)
Newz(908, bind, num_params, MYSQL_BIND);
else
bind= NULL;
return bind;
}
/*
allocate memory in fbind imp_sth_phb_t structure per
number of placeholders
*/
static imp_sth_phb_t *alloc_fbind(int num_params)
{
imp_sth_phb_t *fbind;
if (num_params)
Newz(908, fbind, num_params, imp_sth_phb_t);
else
fbind= NULL;
return fbind;
}
/*
alloc memory for imp_sth_fbh_t fbuffer per number of fields
*/
static imp_sth_fbh_t *alloc_fbuffer(int num_fields)
{
imp_sth_fbh_t *fbh;
if (num_fields)
Newz(908, fbh, num_fields, imp_sth_fbh_t);
else
fbh= NULL;
return fbh;
}
/*
free MYSQL_BIND bind struct
*/
static void FreeBind(MYSQL_BIND* bind)
{
if (bind)
Safefree(bind);
else
fprintf(stderr,"FREE ERROR BIND!");
}
/*
free imp_sth_phb_t fbind structure
*/
static void FreeFBind(imp_sth_phb_t *fbind)
{
if (fbind)
Safefree(fbind);
else
fprintf(stderr,"FREE ERROR FBIND!");
}
/*
free imp_sth_fbh_t fbh structure
*/
static void FreeFBuffer(imp_sth_fbh_t * fbh)
{
if (fbh)
Safefree(fbh);
else
fprintf(stderr,"FREE ERROR FBUFFER!");
}
#endif
/*
free statement param structure per num_params
*/
static void
FreeParam(imp_sth_ph_t *params, int num_params)
{
if (params)
{
int i;
for (i= 0; i < num_params; i++)
{
imp_sth_ph_t *ph= params+i;
if (ph->value)
{
(void) SvREFCNT_dec(ph->value);
ph->value= NULL;
}
}
Safefree(params);
}
}
#if MYSQL_VERSION_ID >= SERVER_PREPARE_VERSION
/*
Convert a MySQL type to a type that perl can handle
NOTE: In the future we may want to return a struct with a lot of
information for each type
*/
static enum enum_field_types mysql_to_perl_type(enum enum_field_types type)
{
switch (type) {
case MYSQL_TYPE_DOUBLE:
case MYSQL_TYPE_FLOAT:
return MYSQL_TYPE_DOUBLE;
case MYSQL_TYPE_SHORT:
case MYSQL_TYPE_TINY:
case MYSQL_TYPE_LONG:
case MYSQL_TYPE_INT24:
case MYSQL_TYPE_YEAR:
return MYSQL_TYPE_LONG;
case MYSQL_TYPE_DECIMAL:
case MYSQL_TYPE_LONGLONG: /* No longlong in perl */
case MYSQL_TYPE_DATE:
case MYSQL_TYPE_TIME:
case MYSQL_TYPE_DATETIME:
case MYSQL_TYPE_NEWDATE:
case MYSQL_TYPE_VAR_STRING:
case MYSQL_TYPE_STRING:
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_TIMESTAMP:
/* case MYSQL_TYPE_UNKNOWN: */
return MYSQL_TYPE_STRING;
default:
if (dbis->debug >= 2)
PerlIO_printf(DBILOGFP, "case default for col_type => %d\n", type);
return MYSQL_TYPE_STRING; /* MySQL can handle all types as strings */
}
}
#endif
#if defined(DBD_MYSQL_EMBEDDED)
/*
count embedded options
*/
int count_embedded_options(char *st)
{
int rc;
char c;
char *ptr;
ptr= st;
rc= 0;
if (st)
{
while ((c= *ptr++))
{
if (c == ',')
rc++;
}
rc++;
}
return rc;
}
/*
Free embbedded options
*/
int free_embedded_options(char ** options_list, int options_count)
{
int i;
for (i= 0; i < options_count; i++)
{
if (options_list[i])
free(options_list[i]);
}
free(options_list);
return 1;
}
/*
Print out embbedded option settings
*/
int print_embedded_options(char ** options_list, int options_count)
{
int i;
for (i=0; i<options_count; i++)
{
if (options_list[i])
PerlIO_printf(DBILOGFP,
"Embedded server, parameter[%d]=%s\n",
i, options_list[i]);
}
return 1;
}
/*
*/
char **fill_out_embedded_options(char *options,
int options_type,
int slen, int cnt)
{
int ind, len;
char c;
char *ptr;
char **options_list= NULL;
if (!(options_list= (char **) calloc(cnt, sizeof(char *))))
{
PerlIO_printf(DBILOGFP,
"Initialize embedded server. Out of memory \n");
return NULL;
}
ptr= options;
ind= 0;
if (options_type == 0)
{
/* server_groups list NULL terminated */
options_list[cnt]= (char *) NULL;
}
if (options_type == 1)
{
/* first item in server_options list is ignored. fill it with \0 */
if (!(options_list[0]= calloc(1,sizeof(char))))
{
PerlIO_printf(DBILOGFP,
"Initialize embedded server. Out of memory \n");
return NULL;
}
ind++;
}
while ((c= *ptr++))
{
slen--;
if (c == ',' || !slen)
{
len= ptr - options;
if (c == ',')
len--;
if (!(options_list[ind]=calloc(len+1,sizeof(char))))
{
PerlIO_printf(DBILOGFP,
"Initialize embedded server. Out of memory\n");
return NULL;
}
strncpy(options_list[ind], options, len);
ind++;
options= ptr;
}
}
return options_list;
}
#endif
/*
constructs an SQL statement previously prepared with
actual values replacing placeholders
*/
static char *parse_params(
MYSQL *sock,
char *statement,
STRLEN *slen_ptr,
imp_sth_ph_t* params,
int num_params,
bool bind_type_guessing)
{
bool seen_neg, seen_dec;
char *salloc, *statement_ptr;
char *statement_ptr_end, testchar, *ptr, *valbuf;
int alen, i, j;
int slen= *slen_ptr;
int limit_flag= 0;
STRLEN vallen;
imp_sth_ph_t *ph;
/* I want to add mysql DBUG_ENTER (DBUG_<> macros) */
if (dbis->debug >= 2)
PerlIO_printf(DBILOGFP,
"---> parse_params with statement %s num params %d\n",
statement,
- 1
- 2
- 3
- 4
前往页