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
7 changes: 6 additions & 1 deletion ext/pdo/php_pdo_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ PDO_API char *php_pdo_int64_to_str(pdo_int64_t i64);
# define FALSE 0
#endif

#define PDO_DRIVER_API 20150127
#define PDO_DRIVER_API 20161017

enum pdo_param_type {
PDO_PARAM_NULL,
Expand Down Expand Up @@ -76,6 +76,11 @@ enum pdo_param_type {
*/
PDO_PARAM_ZVAL,

/* this defines the start of the range for driver specific params.
* Drivers should define their own param constants beginning with this
* value. */
PDO_PARAM_DRIVER_SPECIFIC = 1000,

/* magic flag to denote a parameter as being input/output */
PDO_PARAM_INPUT_OUTPUT = 0x80000000
};
Expand Down
82 changes: 66 additions & 16 deletions ext/pdo_dblib/dblib_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,30 +151,67 @@ static zend_long dblib_handle_doer(pdo_dbh_t *dbh, const char *sql, size_t sql_l

static int dblib_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unquotedlen, char **quoted, size_t *quotedlen, enum pdo_param_type paramtype)
{
pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data;
const char *hex = "0123456789abcdef";
zend_bool is_unicode = 0;

size_t i;
char * q;
*quotedlen = 0;

/* Detect quoted length, adding extra char for doubled single quotes */
for(i=0;i<unquotedlen;i++) {
if(unquoted[i] == '\'') ++*quotedlen;
++*quotedlen;
}
switch (PDO_PARAM_TYPE(paramtype)) {
case PDO_DBLIB_PARAM_BINARY:
*quotedlen = (unquotedlen * 2) + 2; /* 2 chars per byte +2 for "0x" prefix */
q = *quoted = emalloc(*quotedlen + 1); /* Add byte for terminal null */

*q++ = '0';
*q++ = 'x';
for (i = 0; i < unquotedlen; i++) {
*q++ = hex[(*unquoted >> 4) & 0xF];
*q++ = hex[(*unquoted++) & 0xF];
}

break;

default:
if (H->unicode_strings) {
is_unicode = 1;
}
if ((paramtype & PDO_DBLIB_PARAM_STR_UNICODE) == PDO_DBLIB_PARAM_STR_UNICODE) {
is_unicode = 1;
}
if ((paramtype & PDO_DBLIB_PARAM_STR_ASCII) == PDO_DBLIB_PARAM_STR_ASCII) {
is_unicode = 0;
}

*quotedlen += 2; /* +2 for opening, closing quotes */
q = *quoted = emalloc(*quotedlen+1); /* Add byte for terminal null */
*q++ = '\'';
/* Detect quoted length, adding extra char for doubled single quotes */
for (i = 0; i < unquotedlen; i++) {
if (unquoted[i] == '\'') ++*quotedlen;
++*quotedlen;
}

for (i=0;i<unquotedlen;i++) {
if (unquoted[i] == '\'') {
*quotedlen += 2; /* +2 for opening, closing quotes */
if (is_unicode) {
++*quotedlen; /* N prefix */
}
q = *quoted = emalloc(*quotedlen + 1); /* Add byte for terminal null */
if (is_unicode) {
*q++ = 'N';
}
*q++ = '\'';

for (i = 0; i < unquotedlen; i++) {
if (unquoted[i] == '\'') {
*q++ = '\'';
*q++ = '\'';
} else {
*q++ = unquoted[i];
}
}
*q++ = '\'';
} else {
*q++ = unquoted[i];
}

break;
}
*q++ = '\'';

*q = 0;

Expand Down Expand Up @@ -257,12 +294,17 @@ char *dblib_handle_last_id(pdo_dbh_t *dbh, const char *name, size_t *len)

static int dblib_set_attr(pdo_dbh_t *dbh, zend_long attr, zval *val)
{
pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data;

switch(attr) {
case PDO_ATTR_TIMEOUT:
case PDO_DBLIB_ATTR_QUERY_TIMEOUT:
return SUCCEED == dbsettime(zval_get_long(val)) ? 1 : 0;
case PDO_DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER:
((pdo_dblib_db_handle *)dbh->driver_data)->stringify_uniqueidentifier = zval_get_long(val);
H->stringify_uniqueidentifier = zval_get_long(val);
return 1;
case PDO_DBLIB_ATTR_UNICODE_STRINGS:
H->unicode_strings = zval_get_long(val);
return 1;
default:
return 0;
Expand All @@ -271,9 +313,15 @@ static int dblib_set_attr(pdo_dbh_t *dbh, zend_long attr, zval *val)

static int dblib_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *return_value)
{
pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data;

switch (attr) {
case PDO_DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER:
ZVAL_BOOL(return_value, ((pdo_dblib_db_handle *)dbh->driver_data)->stringify_uniqueidentifier);
ZVAL_BOOL(return_value, H->stringify_uniqueidentifier);
break;

case PDO_DBLIB_ATTR_UNICODE_STRINGS:
ZVAL_BOOL(return_value, H->unicode_strings);
break;

default:
Expand Down Expand Up @@ -348,6 +396,7 @@ static int pdo_dblib_handle_factory(pdo_dbh_t *dbh, zval *driver_options)
H->login = dblogin();
H->err.sqlstate = dbh->error_code;
H->stringify_uniqueidentifier = 0;
H->unicode_strings = 0;

if (!H->login) {
goto cleanup;
Expand All @@ -369,6 +418,7 @@ static int pdo_dblib_handle_factory(pdo_dbh_t *dbh, zval *driver_options)
dbsettime(query_timeout); /* Statement Timeout */

H->stringify_uniqueidentifier = pdo_attr_lval(driver_options, PDO_DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER, 0);
H->unicode_strings = pdo_attr_lval(driver_options, PDO_DBLIB_ATTR_UNICODE_STRINGS, 0);
}

DBERRHANDLE(H->login, (EHANDLEFUNC) pdo_dblib_error_handler);
Expand Down
4 changes: 4 additions & 0 deletions ext/pdo_dblib/pdo_dblib.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,10 @@ PHP_MINIT_FUNCTION(pdo_dblib)
REGISTER_PDO_CLASS_CONST_LONG("DBLIB_ATTR_CONNECTION_TIMEOUT", (long) PDO_DBLIB_ATTR_CONNECTION_TIMEOUT);
REGISTER_PDO_CLASS_CONST_LONG("DBLIB_ATTR_QUERY_TIMEOUT", (long) PDO_DBLIB_ATTR_QUERY_TIMEOUT);
REGISTER_PDO_CLASS_CONST_LONG("DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER", (long) PDO_DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER);
REGISTER_PDO_CLASS_CONST_LONG("DBLIB_ATTR_UNICODE_STRINGS", (long) PDO_DBLIB_ATTR_UNICODE_STRINGS);
REGISTER_PDO_CLASS_CONST_LONG("DBLIB_PARAM_BINARY", (long) PDO_DBLIB_PARAM_BINARY);
REGISTER_PDO_CLASS_CONST_LONG("DBLIB_PARAM_STR_UNICODE", (long) PDO_DBLIB_PARAM_STR_UNICODE);
REGISTER_PDO_CLASS_CONST_LONG("DBLIB_PARAM_STR_ASCII", (long) PDO_DBLIB_PARAM_STR_ASCII);

if (FAIL == dbinit()) {
return FAILURE;
Expand Down
8 changes: 8 additions & 0 deletions ext/pdo_dblib/php_pdo_dblib_int.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ typedef struct {

pdo_dblib_err err;
unsigned stringify_uniqueidentifier:1;
unsigned unicode_strings:1;
} pdo_dblib_db_handle;

typedef struct {
Expand Down Expand Up @@ -147,6 +148,13 @@ enum {
PDO_DBLIB_ATTR_CONNECTION_TIMEOUT = PDO_ATTR_DRIVER_SPECIFIC,
PDO_DBLIB_ATTR_QUERY_TIMEOUT,
PDO_DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER,
PDO_DBLIB_ATTR_UNICODE_STRINGS,
};

enum {
PDO_DBLIB_PARAM_BINARY = PDO_PARAM_DRIVER_SPECIFIC,
PDO_DBLIB_PARAM_STR_UNICODE = 0x40000000,
PDO_DBLIB_PARAM_STR_ASCII = 0x20000000,
};

#endif
Expand Down
17 changes: 16 additions & 1 deletion ext/pdo_dblib/tests/pdo_dblib_quote.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,16 @@ var_dump($db->quote(42, PDO::PARAM_INT));
var_dump($db->quote(null, PDO::PARAM_NULL));
var_dump($db->quote('\'', PDO::PARAM_STR));
var_dump($db->quote('foo', PDO::PARAM_STR));
var_dump($db->quote('foo', PDO::PARAM_STR | PDO::DBLIB_PARAM_STR_ASCII));
var_dump($db->quote('über', PDO::PARAM_STR | PDO::DBLIB_PARAM_STR_UNICODE));
var_dump($db->quote('foo', PDO::DBLIB_PARAM_BINARY));
var_dump($db->quote(123, PDO::DBLIB_PARAM_BINARY)); // numbers will be cast to strings rather than converted to hex

$db->setAttribute(PDO::DBLIB_ATTR_UNICODE_STRINGS, true);
var_dump($db->quote('foo', PDO::PARAM_STR | PDO::DBLIB_PARAM_STR_ASCII));
var_dump($db->quote('über', PDO::PARAM_STR));
var_dump($db->quote('über', PDO::PARAM_STR | PDO::DBLIB_PARAM_STR_UNICODE));

?>
--EXPECT--
string(3) "'1'"
Expand All @@ -23,4 +32,10 @@ string(4) "'42'"
string(2) "''"
string(4) "''''"
string(5) "'foo'"
string(7) "'über'"
string(5) "'foo'"
string(8) "N'über'"
string(8) "0x666f6f"
string(8) "0x313233"
string(5) "'foo'"
string(8) "N'über'"
string(8) "N'über'"