Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
238 changes: 170 additions & 68 deletions ext/pdo_dblib/dblib_stmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ static int pdo_dblib_stmt_describe(pdo_stmt_t *stmt, int colno)
}

col->maxlen = dbcollen(H->link, colno+1);
col->param_type = PDO_PARAM_STR;
col->param_type = PDO_PARAM_ZVAL;

return 1;
}
Expand All @@ -225,78 +225,165 @@ static int pdo_dblib_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr,
pdo_dblib_db_handle *H = S->H;

int coltype;
unsigned int tmp_len;
char *tmp_ptr = NULL;
char *data, *tmp_data;
size_t data_len, tmp_data_len;
zval *zv = NULL;

coltype = dbcoltype(H->link, colno+1);

*len = dbdatlen(H->link, colno+1);
*ptr = dbdata(H->link, colno+1);

if (*len == 0 && *ptr == NULL) {
return 1;
}

switch (coltype) {
case SQLVARBINARY:
case SQLBINARY:
case SQLIMAGE:
case SQLTEXT:
/* FIXME: Above types should be returned as a stream as they can be VERY large */
case SQLCHAR:
case SQLVARCHAR:
tmp_ptr = emalloc(*len + 1);
memcpy(tmp_ptr, *ptr, *len);
tmp_ptr[*len] = '\0';
*ptr = tmp_ptr;
break;
case SQLMONEY:
case SQLMONEY4:
case SQLMONEYN: {
DBFLT8 money_value;
dbconvert(NULL, coltype, *ptr, *len, SQLFLT8, (LPBYTE)&money_value, 8);
*len = spprintf(&tmp_ptr, 0, "%.4f", money_value);
*ptr = tmp_ptr;
break;
}
case SQLUNIQUE: {
*len = 37;
tmp_ptr = emalloc(*len + 1);
*len = dbconvert(NULL, SQLUNIQUE, *ptr, *len, SQLCHAR, tmp_ptr, *len);
php_strtoupper(tmp_ptr, *len);
tmp_ptr[36] = '\0';
*ptr = tmp_ptr;
break;
data = dbdata(H->link, colno+1);
data_len = dbdatlen(H->link, colno+1);

if (data_len != 0 && data != NULL) {
if (stmt->dbh->stringify) {
switch (coltype) {
case SQLFLT4:
case SQLFLT8:
case SQLINT4:
case SQLINT2:
case SQLINT1:
case SQLBIT: {
if (dbwillconvert(coltype, SQLCHAR)) {
tmp_data_len = 32 + (2 * (data_len)); /* FIXME: We allocate more than we need here */
tmp_data = emalloc(tmp_data_len);
data_len = dbconvert(NULL, coltype, data, data_len, SQLCHAR, tmp_data, -1);

zv = emalloc(sizeof(zval));
ZVAL_STRING(zv, tmp_data);

efree(tmp_data);
}
break;
}
}
}
case SQLDATETIM4:
case SQLDATETIME: {
DBDATETIME dt;
DBDATEREC di;

dbconvert(H->link, coltype, (BYTE*) *ptr, -1, SQLDATETIME, (LPBYTE) &dt, -1);
dbdatecrack(H->link, &di, &dt);

*len = spprintf((char**) &tmp_ptr, 20, "%d-%02d-%02d %02d:%02d:%02d",
#ifdef PHP_DBLIB_IS_MSSQL || MSDBLIB
di.year, di.month, di.day, di.hour, di.minute, di.second
if (!zv) {
switch (coltype) {
case SQLCHAR:
case SQLVARCHAR:
case SQLTEXT:
#if ilia_0
while (data_len>0 && data[data_len-1] == ' ') { // nuke trailing whitespace
data_len--;
}
#endif
case SQLVARBINARY:
case SQLBINARY:
case SQLIMAGE: {
zv = emalloc(sizeof(zval));
if (!data_len) {
ZVAL_NULL(zv); // @todo?
} else {
ZVAL_STRINGL(zv, data, data_len);
}

break;
}
case SQLDATETIME:
case SQLDATETIM4: {
size_t dl;
DBDATEREC di;
DBDATETIME dt;

dbconvert(H->link, coltype, data, -1, SQLDATETIME, (LPBYTE) &dt, -1);
dbdatecrack(H->link, &di, &dt);

dl = spprintf((char**) &tmp_data, 20, "%d-%02d-%02d %02d:%02d:%02d",
#if defined(PHP_DBLIB_IS_MSSQL) || defined(MSDBLIB)
di.year, di.month, di.day, di.hour, di.minute, di.second
#else
di.dateyear, di.datemonth+1, di.datedmonth, di.datehour, di.dateminute, di.datesecond
di.dateyear, di.datemonth+1, di.datedmonth, di.datehour, di.dateminute, di.datesecond
#endif
);

*ptr = (char*) tmp_ptr;
break;
}
default:
if (dbwillconvert(coltype, SQLCHAR)) {
tmp_len = 32 + (2 * (*len)); /* FIXME: We allocate more than we need here */
tmp_ptr = emalloc(tmp_len);
*len = dbconvert(NULL, coltype, *ptr, *len, SQLCHAR, tmp_ptr, -1);
*ptr = tmp_ptr;
} else {
*len = 0; /* FIXME: Silently fails and returns null on conversion errors */
*ptr = NULL;
);

zv = emalloc(sizeof(zval));
ZVAL_STRINGL(zv, tmp_data, dl);

efree(tmp_data);

break;
}
case SQLFLT4: {
zv = emalloc(sizeof(zval));
ZVAL_DOUBLE(zv, (double) (*(DBFLT4 *) data));

break;
}
case SQLFLT8: {
zv = emalloc(sizeof(zval));
ZVAL_DOUBLE(zv, (double) (*(DBFLT8 *) data));

break;
}
case SQLINT4: {
zv = emalloc(sizeof(zval));
ZVAL_LONG(zv, (long) ((int) *(DBINT *) data));

break;
}
case SQLINT2: {
zv = emalloc(sizeof(zval));
ZVAL_LONG(zv, (long) ((int) *(DBSMALLINT *) data));

break;
}
case SQLINT1:
case SQLBIT: {
zv = emalloc(sizeof(zval));
ZVAL_LONG(zv, (long) ((int) *(DBTINYINT *) data));

break;
}
case SQLMONEY:
case SQLMONEY4:
case SQLMONEYN: {
DBFLT8 money_value;
dbconvert(NULL, coltype, data, 8, SQLFLT8, (LPBYTE)&money_value, -1);

zv = emalloc(sizeof(zval));

if (stmt->dbh->stringify) {
tmp_data_len = spprintf(&tmp_data, 0, "%.4f", money_value);
ZVAL_STRINGL(zv, tmp_data, tmp_data_len);
efree(tmp_data);
} else {
ZVAL_DOUBLE(zv, money_value);
}

break;
}
#ifdef SQLUNIQUE
case SQLUNIQUE: {
#else
case 36: { // FreeTDS hack
#endif
zv = emalloc(sizeof(zval));
ZVAL_STRINGL(zv, data, 16); // uniqueidentifier is a 16-byte binary number

break;
}
default: {
if (dbwillconvert(coltype, SQLCHAR)) {
tmp_data_len = 32 + (2 * (data_len)); /* FIXME: We allocate more than we need here */
tmp_data = emalloc(tmp_data_len);
data_len = dbconvert(NULL, coltype, data, data_len, SQLCHAR, tmp_data, -1);

zv = emalloc(sizeof(zval));
ZVAL_STRING(zv, tmp_data);

efree(tmp_data);
}
}
}
}
}

if (zv != NULL) {
*ptr = (char*)zv;
*len = sizeof(zval);
} else {
*ptr = NULL;
*len = 0;
}

*caller_frees = 1;
Expand All @@ -315,6 +402,7 @@ static int pdo_dblib_stmt_get_column_meta(pdo_stmt_t *stmt, zend_long colno, zva
pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
pdo_dblib_db_handle *H = S->H;
DBTYPEINFO* dbtypeinfo;
int coltype;

if(colno >= stmt->column_count || colno < 0) {
return FAILURE;
Expand All @@ -326,14 +414,28 @@ static int pdo_dblib_stmt_get_column_meta(pdo_stmt_t *stmt, zend_long colno, zva

if(!dbtypeinfo) return FAILURE;

coltype = dbcoltype(H->link, colno+1);

add_assoc_long(return_value, "max_length", dbcollen(H->link, colno+1) );
add_assoc_long(return_value, "precision", (int) dbtypeinfo->precision );
add_assoc_long(return_value, "scale", (int) dbtypeinfo->scale );
add_assoc_string(return_value, "column_source", dbcolsource(H->link, colno+1));
add_assoc_string(return_value, "native_type", pdo_dblib_get_field_name(dbcoltype(H->link, colno+1)));
add_assoc_long(return_value, "native_type_id", dbcoltype(H->link, colno+1));
add_assoc_string(return_value, "native_type", pdo_dblib_get_field_name(coltype));
add_assoc_long(return_value, "native_type_id", coltype);
add_assoc_long(return_value, "native_usertype_id", dbcolutype(H->link, colno+1));

switch (coltype) {
case SQLBIT:
case SQLINT1:
case SQLINT2:
case SQLINT4:
add_assoc_long(return_value, "pdo_type", PDO_PARAM_INT);
break;
default:
add_assoc_long(return_value, "pdo_type", PDO_PARAM_STR);
break;
}

return 1;
}

Expand Down
8 changes: 4 additions & 4 deletions ext/pdo_dblib/tests/bug_38955.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -37,21 +37,21 @@ array(4) {
[0]=>
array(1) {
["val"]=>
string(1) "1"
int(1)
}
[1]=>
array(1) {
["val"]=>
string(1) "2"
int(2)
}
[2]=>
array(1) {
["val"]=>
string(1) "3"
int(3)
}
[3]=>
array(1) {
["val"]=>
string(1) "4"
int(4)
}
}
8 changes: 4 additions & 4 deletions ext/pdo_dblib/tests/bug_45876.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ require dirname(__FILE__) . '/config.inc';
<?php
require dirname(__FILE__) . '/config.inc';

$stmt = $db->prepare("select ic1.* from information_schema.columns ic1");
$stmt = $db->prepare("select top 1 ic1.* from information_schema.columns ic1");
$stmt->execute();
var_dump($stmt->getColumnMeta(0));
$stmt = null;
Expand All @@ -30,10 +30,10 @@ array(10) {
int(47)
["native_usertype_id"]=>
int(2)
["pdo_type"]=>
int(2)
["name"]=>
string(13) "TABLE_CATALOG"
["len"]=>
int(255)
["pdo_type"]=>
int(2)
}
}
6 changes: 3 additions & 3 deletions ext/pdo_dblib/tests/bug_47588.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,21 @@ array(3) {
[0]=>
array(2) {
["My Field"]=>
string(1) "1"
int(1)
["Another Field"]=>
string(11) "test_string"
}
[1]=>
array(2) {
["My Field"]=>
string(1) "2"
int(2)
["Another Field"]=>
string(11) "test_string"
}
[2]=>
array(2) {
["My Field"]=>
string(1) "3"
int(3)
["Another Field"]=>
string(11) "test_string"
}
Expand Down
Loading