version 1.1.1.1, 2012/02/21 23:47:59
|
version 1.1.1.4, 2013/10/14 08:02:28
|
Line 2
|
Line 2
|
+----------------------------------------------------------------------+ |
+----------------------------------------------------------------------+ |
| PHP Version 5 | |
| PHP Version 5 | |
+----------------------------------------------------------------------+ |
+----------------------------------------------------------------------+ |
| Copyright (c) 1997-2012 The PHP Group | | | Copyright (c) 1997-2013 The PHP Group | |
+----------------------------------------------------------------------+ |
+----------------------------------------------------------------------+ |
| This source file is subject to version 3.0 of the PHP license, | |
| This source file is subject to version 3.0 of the PHP license, | |
| that is bundled with this package in the file LICENSE, and is | |
| that is bundled with this package in the file LICENSE, and is | |
Line 286 static int odbc_stmt_param_hook(pdo_stmt_t *stmt, stru
|
Line 286 static int odbc_stmt_param_hook(pdo_stmt_t *stmt, stru
|
if (param->is_param) { |
if (param->is_param) { |
|
|
switch (event_type) { |
switch (event_type) { |
|
case PDO_PARAM_EVT_FETCH_PRE: |
|
case PDO_PARAM_EVT_FETCH_POST: |
|
case PDO_PARAM_EVT_NORMALIZE: |
|
/* Do nothing */ |
|
break; |
|
|
case PDO_PARAM_EVT_FREE: |
case PDO_PARAM_EVT_FREE: |
P = param->driver_data; |
P = param->driver_data; |
if (P) { |
if (P) { |
Line 543 static int odbc_stmt_describe(pdo_stmt_t *stmt, int co
|
Line 549 static int odbc_stmt_describe(pdo_stmt_t *stmt, int co
|
{ |
{ |
pdo_odbc_stmt *S = (pdo_odbc_stmt*)stmt->driver_data; |
pdo_odbc_stmt *S = (pdo_odbc_stmt*)stmt->driver_data; |
struct pdo_column_data *col = &stmt->columns[colno]; |
struct pdo_column_data *col = &stmt->columns[colno]; |
zend_bool dyn = FALSE; |
|
RETCODE rc; |
RETCODE rc; |
SWORD colnamelen; |
SWORD colnamelen; |
SDWORD colsize, displaysize; |
SDWORD colsize, displaysize; |
Line 614 static int odbc_stmt_get_col(pdo_stmt_t *stmt, int col
|
Line 619 static int odbc_stmt_get_col(pdo_stmt_t *stmt, int col
|
|
|
/* if it is a column containing "long" data, perform late binding now */ |
/* if it is a column containing "long" data, perform late binding now */ |
if (C->is_long) { |
if (C->is_long) { |
unsigned long alloced = 4096; |
|
unsigned long used = 0; |
unsigned long used = 0; |
char *buf; |
char *buf; |
RETCODE rc; |
RETCODE rc; |
Line 633 static int odbc_stmt_get_col(pdo_stmt_t *stmt, int col
|
Line 637 static int odbc_stmt_get_col(pdo_stmt_t *stmt, int col
|
} |
} |
|
|
if (rc == SQL_SUCCESS_WITH_INFO) { |
if (rc == SQL_SUCCESS_WITH_INFO) { |
/* promote up to a bigger buffer */ | /* this is a 'long column' |
| |
if (C->fetched_len != SQL_NO_TOTAL) { | |
/* use size suggested by the driver, if it knows it */ | |
alloced = C->fetched_len + 1; | |
} | |
|
|
buf = emalloc(alloced); | read the column in 255 byte blocks until the end of the column is reached, reassembling those blocks |
memcpy(buf, C->data, 256); | in order into the output buffer |
used = 255; /* not 256; the driver NUL terminated the buffer */ | |
| this loop has to work whether or not SQLGetData() provides the total column length. |
| calling SQLDescribeCol() or other, specifically to get the column length, then doing a single read |
| for that size would be slower except maybe for extremely long columns.*/ |
| char *buf2; |
|
|
|
buf2 = emalloc(256); |
|
buf = estrndup(C->data, 256); |
|
used = 255; /* not 256; the driver NUL terminated the buffer */ |
|
|
do { |
do { |
C->fetched_len = 0; |
C->fetched_len = 0; |
rc = SQLGetData(S->stmt, colno+1, SQL_C_CHAR, | /* read block. 256 bytes => 255 bytes are actually read, the last 1 is NULL */ |
buf + used, alloced - used, | rc = SQLGetData(S->stmt, colno+1, SQL_C_CHAR, buf2, 256, &C->fetched_len); |
&C->fetched_len); | |
| /* resize output buffer and reassemble block */ |
if (rc == SQL_NO_DATA) { | if (rc==SQL_SUCCESS_WITH_INFO) { |
/* we got the lot */ | /* point 5, in section "Retrieving Data with SQLGetData" in http://msdn.microsoft.com/en-us/library/windows/desktop/ms715441(v=vs.85).aspx |
break; | states that if SQL_SUCCESS_WITH_INFO, fetched_len will be > 255 (greater than buf2's size) |
} else if (rc != SQL_SUCCESS) { | (if a driver fails to follow that and wrote less than 255 bytes to buf2, this will AV or read garbage into buf) */ |
pdo_odbc_stmt_error("SQLGetData"); | buf = erealloc(buf, used + 255+1); |
if (rc != SQL_SUCCESS_WITH_INFO) { | memcpy(buf + used, buf2, 255); |
break; | used = used + 255; |
} | } else if (rc==SQL_SUCCESS) { |
} | buf = erealloc(buf, used + C->fetched_len+1); |
| memcpy(buf + used, buf2, C->fetched_len); |
if (C->fetched_len == SQL_NO_TOTAL) { | used = used + C->fetched_len; |
used += alloced - used; | |
} else { |
} else { |
used += C->fetched_len; | /* includes SQL_NO_DATA */ |
} | |
| |
if (rc == SQL_SUCCESS) { | |
/* this was the final fetch */ | |
break; |
break; |
} |
} |
| |
/* we need to fetch another chunk; resize the | |
* buffer */ | |
alloced *= 2; | |
buf = erealloc(buf, alloced); | |
} while (1); |
} while (1); |
| |
/* size down */ | efree(buf2); |
if (used < alloced - 1024) { | |
alloced = used+1; | /* NULL terminate the buffer once, when finished, for use with the rest of PHP */ |
buf = erealloc(buf, used+1); | |
} | |
buf[used] = '\0'; |
buf[used] = '\0'; |
|
|
*ptr = buf; |
*ptr = buf; |
*caller_frees = 1; |
*caller_frees = 1; |
*len = used; |
*len = used; |