Add PDO::quoteName() method #167

Closed
wants to merge 1 commit into
from
View
34 ext/pdo/pdo_dbh.c
@@ -1185,6 +1185,35 @@ static PHP_METHOD(PDO, quote)
}
/* }}} */
+/* {{{ proto string PDO::quoteName(string identifier)
+ Quotes string for use as a table or column name. */
+static PHP_METHOD(PDO, quoteName)
+{
+ pdo_dbh_t *dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
+ char *str;
+ int str_len;
+ char *qstr;
+ int qlen;
+
+ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len)) {
+ RETURN_FALSE;
+ }
+
+ PDO_DBH_CLEAR_ERR();
+ PDO_CONSTRUCT_CHECK;
+ if (!dbh->methods->name_quoter) {
+ pdo_raise_impl_error(dbh, NULL, "IM001", "driver does not support name quoting" TSRMLS_CC);
+ RETURN_FALSE;
+ }
+
+ if (dbh->methods->name_quoter(dbh, str, str_len, &qstr, &qlen TSRMLS_CC)) {
+ RETURN_STRINGL(qstr, qlen, 0);
+ }
+ PDO_HANDLE_DBH_ERR();
+ RETURN_FALSE;
+}
+/* }}} */
+
/* {{{ proto int PDO::__wakeup()
Prevents use of a PDO instance that has been unserialized */
static PHP_METHOD(PDO, __wakeup)
@@ -1257,6 +1286,10 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_pdo_quote, 0, 0, 1)
ZEND_ARG_INFO(0, paramtype)
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_INFO_EX(arginfo_pdo_quotename, 0, 0, 1)
+ ZEND_ARG_INFO(0, identifier)
+ZEND_END_ARG_INFO()
+
ZEND_BEGIN_ARG_INFO(arginfo_pdo__void, 0)
ZEND_END_ARG_INFO()
/* }}} */
@@ -1276,6 +1309,7 @@ const zend_function_entry pdo_dbh_functions[] = {
PHP_ME(PDO, errorInfo, arginfo_pdo__void, ZEND_ACC_PUBLIC)
PHP_ME(PDO, getAttribute, arginfo_pdo_getattribute, ZEND_ACC_PUBLIC)
PHP_ME(PDO, quote, arginfo_pdo_quote, ZEND_ACC_PUBLIC)
+ PHP_ME(PDO, quoteName, arginfo_pdo_quotename, ZEND_ACC_PUBLIC)
PHP_ME(PDO, __wakeup, arginfo_pdo__void, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
PHP_ME(PDO, __sleep, arginfo_pdo__void, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
PHP_ME(PDO, getAvailableDrivers, arginfo_pdo__void, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
View
4 ext/pdo/php_pdo_driver.h
@@ -250,6 +250,9 @@ typedef long (*pdo_dbh_do_func)(pdo_dbh_t *dbh, const char *sql, long sql_len TS
/* quote a string */
typedef int (*pdo_dbh_quote_func)(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen, enum pdo_param_type paramtype TSRMLS_DC);
+/* quote an identifier */
+typedef int (*pdo_dbh_quote_name_func)(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen);
+
/* transaction related */
typedef int (*pdo_dbh_txn_func)(pdo_dbh_t *dbh TSRMLS_DC);
@@ -311,6 +314,7 @@ struct pdo_dbh_methods {
pdo_dbh_get_driver_methods_func get_driver_methods;
pdo_dbh_request_shutdown persistent_shutdown;
pdo_dbh_txn_func in_transaction;
+ pdo_dbh_quote_name_func name_quoter;
};
/* }}} */
View
23 ext/pdo_dblib/dblib_driver.c
@@ -166,6 +166,26 @@ static int dblib_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquote
return 1;
}
+/* {{{ dblib_handle_name_quoter */
+static int dblib_handle_name_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen TSRMLS_DC)
+{
+ int i;
+ int j = 0;
+ *quoted = safe_emalloc(2, unquotedlen, 3);
+ (*quoted)[j++] = '[';
+ for (i = 0; i < unquotedlen; i++) {
+ (*quoted)[j++] = unquoted[i];
+ if (unquoted[i] == ']') {
+ (*quoted)[j++] = ']';
+ }
+ }
+ (*quoted)[j++] = ']';
+ (*quoted)[j] = '\0';
+ *quotedlen = j;
+ return 1;
+}
+/* }}} */
+
static int pdo_dblib_transaction_cmd(const char *cmd, pdo_dbh_t *dbh TSRMLS_DC)
{
pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data;
@@ -256,7 +276,8 @@ static struct pdo_dbh_methods dblib_methods = {
NULL, /* check liveness */
NULL, /* get driver methods */
NULL, /* request shutdown */
- NULL /* in transaction */
+ NULL, /* in_transaction */
+ dblib_handle_name_quoter,
};
static int pdo_dblib_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC)
View
26 ext/pdo_firebird/firebird_driver.c
@@ -313,6 +313,26 @@ static int firebird_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unqu
}
/* }}} */
+/* {{{ firebird_handle_name_quoter */
+static int firebird_handle_name_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen TSRMLS_DC)
+{
+ int i;
+ int j = 0;
+ *quoted = safe_emalloc(2, unquotedlen, 3);
+ (*quoted)[j++] = '"';
+ for (i = 0; i < unquotedlen; i++) {
+ (*quoted)[j++] = unquoted[i];
+ if (unquoted[i] == '"') {
+ (*quoted)[j++] = '"';
+ }
+ }
+ (*quoted)[j++] = '"';
+ (*quoted)[j] = '\0';
+ *quotedlen = j;
+ return 1;
+}
+/* }}} */
+
/* called by PDO to start a transaction */
static int firebird_handle_begin(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
{
@@ -639,7 +659,11 @@ static struct pdo_dbh_methods firebird_methods = { /* {{{ */
NULL, /* last_id not supported */
pdo_firebird_fetch_error_func,
firebird_handle_get_attribute,
- NULL /* check_liveness */
+ NULL, /* check liveness */
+ NULL, /* get driver methods */
+ NULL, /* request shutdown */
+ NULL, /* in_transaction */
+ firebird_handle_name_quoter,
};
/* }}} */
View
33 ext/pdo_mysql/mysql_driver.c
@@ -314,10 +314,35 @@ static int mysql_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquote
}
/* }}} */
+/* {{{ mysql_handle_name_quoter */
+static int mysql_handle_name_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen TSRMLS_DC)
+{
+ pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data;
+ int i;
+ int j = 0;
+ PDO_DBG_ENTER("mysql_handle_name_quoter");
+ PDO_DBG_INF_FMT("dbh=%p", dbh);
+ PDO_DBG_INF_FMT("unquoted=%.*s", unquotedlen, unquoted);
+ *quoted = safe_emalloc(2, unquotedlen, 3);
+ (*quoted)[j++] = '`';
+ for (i = 0; i < unquotedlen; i++) {
+ (*quoted)[j++] = unquoted[i];
+ if (unquoted[i] == '`') {
+ (*quoted)[j++] = '`';
+ }
+ }
+ (*quoted)[j++] = '`';
+ (*quoted)[j] = '\0';
+ *quotedlen = j;
+ PDO_DBG_INF_FMT("quoted=%.*s", *quotedlen, *quoted);
+ PDO_DBG_RETURN(1);
+}
+/* }}} */
+
/* {{{ mysql_handle_begin */
static int mysql_handle_begin(pdo_dbh_t *dbh TSRMLS_DC)
{
- PDO_DBG_ENTER("mysql_handle_quoter");
+ PDO_DBG_ENTER("mysql_handle_begin");
PDO_DBG_INF_FMT("dbh=%p", dbh);
PDO_DBG_RETURN(0 <= mysql_handle_doer(dbh, ZEND_STRL("START TRANSACTION") TSRMLS_CC));
}
@@ -522,7 +547,11 @@ static struct pdo_dbh_methods mysql_methods = {
pdo_mysql_last_insert_id,
pdo_mysql_fetch_error_func,
pdo_mysql_get_attribute,
- pdo_mysql_check_liveness
+ pdo_mysql_check_liveness,
+ NULL, /* get_driver_methods */
+ NULL, /* persistent_shutdown */
+ NULL, /* in_transaction */
+ mysql_handle_name_quoter,
};
/* }}} */
View
25 ext/pdo_oci/oci_driver.c
@@ -403,6 +403,26 @@ static int oci_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedl
}
/* }}} */
+/* {{{ oci_handle_name_quoter */
+static int oci_handle_name_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen TSRMLS_DC)
+{
+ int i;
+ int j = 0;
+ *quoted = safe_emalloc(2, unquotedlen, 3);
+ (*quoted)[j++] = '"';
+ for (i = 0; i < unquotedlen; i++) {
+ (*quoted)[j++] = unquoted[i];
+ if (unquoted[i] == '"') {
+ (*quoted)[j++] = '"';
+ }
+ }
+ (*quoted)[j++] = '"';
+ (*quoted)[j] = '\0';
+ *quotedlen = j;
+ return 1;
+}
+/* }}} */
+
static int oci_handle_begin(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
{
/* with Oracle, there is nothing special to be done */
@@ -581,7 +601,10 @@ static struct pdo_dbh_methods oci_methods = {
pdo_oci_fetch_error_func,
oci_handle_get_attribute,
pdo_oci_check_liveness, /* check_liveness */
- NULL /* get_driver_methods */
+ NULL, /* get_driver_methods */
+ NULL, /* persistent_shutdown */
+ NULL, /* in_transaction */
+ oci_handle_name_quoter,
};
static int pdo_oci_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) /* {{{ */
View
23 ext/pdo_pgsql/pgsql_driver.c
@@ -342,6 +342,26 @@ static int pgsql_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquote
return 1;
}
+/* {{{ pgsql_handle_name_quoter */
+static int pgsql_handle_name_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen TSRMLS_DC)
+{
+ int i;
+ int j = 0;
+ *quoted = safe_emalloc(2, unquotedlen, 3);
+ (*quoted)[j++] = '"';
+ for (i = 0; i < unquotedlen; i++) {
+ (*quoted)[j++] = unquoted[i];
+ if (unquoted[i] == '"') {
+ (*quoted)[j++] = '"';
+ }
+ }
+ (*quoted)[j++] = '"';
+ (*quoted)[j] = '\0';
+ *quotedlen = j;
+ return 1;
+}
+/* }}} */
+
static char *pdo_pgsql_last_insert_id(pdo_dbh_t *dbh, const char *name, unsigned int *len TSRMLS_DC)
{
pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data;
@@ -1030,8 +1050,9 @@ static struct pdo_dbh_methods pgsql_methods = {
pdo_pgsql_get_attribute,
pdo_pgsql_check_liveness, /* check_liveness */
pdo_pgsql_get_driver_methods, /* get_driver_methods */
- NULL,
+ NULL, /* persistent_shutdown */
pgsql_handle_in_transaction,
+ pgsql_handle_name_quoter,
};
static int pdo_pgsql_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) /* {{{ */
View
24 ext/pdo_sqlite/sqlite_driver.c
@@ -238,6 +238,26 @@ static int sqlite_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquot
return 1;
}
+/* {{{ sqlite_handle_name_quoter */
+static int sqlite_handle_name_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen TSRMLS_DC)
+{
+ int i;
+ int j = 0;
+ *quoted = safe_emalloc(2, unquotedlen, 3);
+ (*quoted)[j++] = '"';
+ for (i = 0; i < unquotedlen; i++) {
+ (*quoted)[j++] = unquoted[i];
+ if (unquoted[i] == '"') {
+ (*quoted)[j++] = '"';
+ }
+ }
+ (*quoted)[j++] = '"';
+ (*quoted)[j] = '\0';
+ *quotedlen = j;
+ return 1;
+}
+/* }}} */
+
static int sqlite_handle_begin(pdo_dbh_t *dbh TSRMLS_DC)
{
pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
@@ -755,7 +775,9 @@ static struct pdo_dbh_methods sqlite_methods = {
pdo_sqlite_get_attribute,
NULL, /* check_liveness: not needed */
get_driver_methods,
- pdo_sqlite_request_shutdown
+ pdo_sqlite_request_shutdown,
+ NULL, /* in_transaction */
+ sqlite_handle_name_quoter,
};
static char *make_filename_safe(const char *filename TSRMLS_DC)
View
20 ext/pdo_sqlite/tests/pdo_sqlite_quote_name.phpt
@@ -0,0 +1,20 @@
+--TEST--
+PDO SQLite quote name
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo_sqlite')) print 'skip not loaded';
+?>
+--FILE--
+<?php
+$pdo = new PDO("sqlite::memory:");
+
+echo $pdo->quoteName('id') . "\n";
+echo $pdo->quoteName('order') . "\n";
+echo $pdo->quoteName('') . "\n";
+echo $pdo->quoteName('x"y') . "\n";
+?>
+--EXPECT--
+"id"
+"order"
+""
+"x""y"