Skip to content

Commit b417336

Browse files
vranavrana
authored and
vrana
committed
Add quoteName() method with MySQL, SQLite, PgSQL, Firebird, Oracle and MS SQL implementations
1 parent 75cf51d commit b417336

File tree

9 files changed

+205
-7
lines changed

9 files changed

+205
-7
lines changed

ext/pdo/pdo_dbh.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1185,6 +1185,35 @@ static PHP_METHOD(PDO, quote)
11851185
}
11861186
/* }}} */
11871187

1188+
/* {{{ proto string PDO::quoteName(string identifier)
1189+
Quotes string for use as a table or column name. */
1190+
static PHP_METHOD(PDO, quoteName)
1191+
{
1192+
pdo_dbh_t *dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
1193+
char *str;
1194+
int str_len;
1195+
char *qstr;
1196+
int qlen;
1197+
1198+
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len)) {
1199+
RETURN_FALSE;
1200+
}
1201+
1202+
PDO_DBH_CLEAR_ERR();
1203+
PDO_CONSTRUCT_CHECK;
1204+
if (!dbh->methods->name_quoter) {
1205+
pdo_raise_impl_error(dbh, NULL, "IM001", "driver does not support name quoting" TSRMLS_CC);
1206+
RETURN_FALSE;
1207+
}
1208+
1209+
if (dbh->methods->name_quoter(dbh, str, str_len, &qstr, &qlen TSRMLS_CC)) {
1210+
RETURN_STRINGL(qstr, qlen, 0);
1211+
}
1212+
PDO_HANDLE_DBH_ERR();
1213+
RETURN_FALSE;
1214+
}
1215+
/* }}} */
1216+
11881217
/* {{{ proto int PDO::__wakeup()
11891218
Prevents use of a PDO instance that has been unserialized */
11901219
static PHP_METHOD(PDO, __wakeup)
@@ -1257,6 +1286,10 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_pdo_quote, 0, 0, 1)
12571286
ZEND_ARG_INFO(0, paramtype)
12581287
ZEND_END_ARG_INFO()
12591288

1289+
ZEND_BEGIN_ARG_INFO_EX(arginfo_pdo_quotename, 0, 0, 1)
1290+
ZEND_ARG_INFO(0, identifier)
1291+
ZEND_END_ARG_INFO()
1292+
12601293
ZEND_BEGIN_ARG_INFO(arginfo_pdo__void, 0)
12611294
ZEND_END_ARG_INFO()
12621295
/* }}} */
@@ -1276,6 +1309,7 @@ const zend_function_entry pdo_dbh_functions[] = {
12761309
PHP_ME(PDO, errorInfo, arginfo_pdo__void, ZEND_ACC_PUBLIC)
12771310
PHP_ME(PDO, getAttribute, arginfo_pdo_getattribute, ZEND_ACC_PUBLIC)
12781311
PHP_ME(PDO, quote, arginfo_pdo_quote, ZEND_ACC_PUBLIC)
1312+
PHP_ME(PDO, quoteName, arginfo_pdo_quotename, ZEND_ACC_PUBLIC)
12791313
PHP_ME(PDO, __wakeup, arginfo_pdo__void, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
12801314
PHP_ME(PDO, __sleep, arginfo_pdo__void, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
12811315
PHP_ME(PDO, getAvailableDrivers, arginfo_pdo__void, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)

ext/pdo/php_pdo_driver.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,9 @@ typedef long (*pdo_dbh_do_func)(pdo_dbh_t *dbh, const char *sql, long sql_len TS
250250
/* quote a string */
251251
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);
252252

253+
/* quote an identifier */
254+
typedef int (*pdo_dbh_quote_name_func)(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen);
255+
253256
/* transaction related */
254257
typedef int (*pdo_dbh_txn_func)(pdo_dbh_t *dbh TSRMLS_DC);
255258

@@ -311,6 +314,7 @@ struct pdo_dbh_methods {
311314
pdo_dbh_get_driver_methods_func get_driver_methods;
312315
pdo_dbh_request_shutdown persistent_shutdown;
313316
pdo_dbh_txn_func in_transaction;
317+
pdo_dbh_quote_name_func name_quoter;
314318
};
315319

316320
/* }}} */

ext/pdo_dblib/dblib_driver.c

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,26 @@ static int dblib_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquote
166166
return 1;
167167
}
168168

169+
/* {{{ dblib_handle_name_quoter */
170+
static int dblib_handle_name_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen TSRMLS_DC)
171+
{
172+
int i;
173+
int j = 0;
174+
*quoted = safe_emalloc(2, unquotedlen, 3);
175+
(*quoted)[j++] = '[';
176+
for (i = 0; i < unquotedlen; i++) {
177+
(*quoted)[j++] = unquoted[i];
178+
if (unquoted[i] == ']') {
179+
(*quoted)[j++] = ']';
180+
}
181+
}
182+
(*quoted)[j++] = ']';
183+
(*quoted)[j] = '\0';
184+
*quotedlen = j;
185+
return 1;
186+
}
187+
/* }}} */
188+
169189
static int pdo_dblib_transaction_cmd(const char *cmd, pdo_dbh_t *dbh TSRMLS_DC)
170190
{
171191
pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data;
@@ -256,7 +276,8 @@ static struct pdo_dbh_methods dblib_methods = {
256276
NULL, /* check liveness */
257277
NULL, /* get driver methods */
258278
NULL, /* request shutdown */
259-
NULL /* in transaction */
279+
NULL, /* in_transaction */
280+
dblib_handle_name_quoter,
260281
};
261282

262283
static int pdo_dblib_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC)

ext/pdo_firebird/firebird_driver.c

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,26 @@ static int firebird_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unqu
313313
}
314314
/* }}} */
315315

316+
/* {{{ firebird_handle_name_quoter */
317+
static int firebird_handle_name_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen TSRMLS_DC)
318+
{
319+
int i;
320+
int j = 0;
321+
*quoted = safe_emalloc(2, unquotedlen, 3);
322+
(*quoted)[j++] = '"';
323+
for (i = 0; i < unquotedlen; i++) {
324+
(*quoted)[j++] = unquoted[i];
325+
if (unquoted[i] == '"') {
326+
(*quoted)[j++] = '"';
327+
}
328+
}
329+
(*quoted)[j++] = '"';
330+
(*quoted)[j] = '\0';
331+
*quotedlen = j;
332+
return 1;
333+
}
334+
/* }}} */
335+
316336
/* called by PDO to start a transaction */
317337
static int firebird_handle_begin(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
318338
{
@@ -639,7 +659,11 @@ static struct pdo_dbh_methods firebird_methods = { /* {{{ */
639659
NULL, /* last_id not supported */
640660
pdo_firebird_fetch_error_func,
641661
firebird_handle_get_attribute,
642-
NULL /* check_liveness */
662+
NULL, /* check liveness */
663+
NULL, /* get driver methods */
664+
NULL, /* request shutdown */
665+
NULL, /* in_transaction */
666+
firebird_handle_name_quoter,
643667
};
644668
/* }}} */
645669

ext/pdo_mysql/mysql_driver.c

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,10 +314,35 @@ static int mysql_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquote
314314
}
315315
/* }}} */
316316

317+
/* {{{ mysql_handle_name_quoter */
318+
static int mysql_handle_name_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen TSRMLS_DC)
319+
{
320+
pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data;
321+
int i;
322+
int j = 0;
323+
PDO_DBG_ENTER("mysql_handle_name_quoter");
324+
PDO_DBG_INF_FMT("dbh=%p", dbh);
325+
PDO_DBG_INF_FMT("unquoted=%.*s", unquotedlen, unquoted);
326+
*quoted = safe_emalloc(2, unquotedlen, 3);
327+
(*quoted)[j++] = '`';
328+
for (i = 0; i < unquotedlen; i++) {
329+
(*quoted)[j++] = unquoted[i];
330+
if (unquoted[i] == '`') {
331+
(*quoted)[j++] = '`';
332+
}
333+
}
334+
(*quoted)[j++] = '`';
335+
(*quoted)[j] = '\0';
336+
*quotedlen = j;
337+
PDO_DBG_INF_FMT("quoted=%.*s", *quotedlen, *quoted);
338+
PDO_DBG_RETURN(1);
339+
}
340+
/* }}} */
341+
317342
/* {{{ mysql_handle_begin */
318343
static int mysql_handle_begin(pdo_dbh_t *dbh TSRMLS_DC)
319344
{
320-
PDO_DBG_ENTER("mysql_handle_quoter");
345+
PDO_DBG_ENTER("mysql_handle_begin");
321346
PDO_DBG_INF_FMT("dbh=%p", dbh);
322347
PDO_DBG_RETURN(0 <= mysql_handle_doer(dbh, ZEND_STRL("START TRANSACTION") TSRMLS_CC));
323348
}
@@ -522,7 +547,11 @@ static struct pdo_dbh_methods mysql_methods = {
522547
pdo_mysql_last_insert_id,
523548
pdo_mysql_fetch_error_func,
524549
pdo_mysql_get_attribute,
525-
pdo_mysql_check_liveness
550+
pdo_mysql_check_liveness,
551+
NULL, /* get_driver_methods */
552+
NULL, /* persistent_shutdown */
553+
NULL, /* in_transaction */
554+
mysql_handle_name_quoter,
526555
};
527556
/* }}} */
528557

ext/pdo_oci/oci_driver.c

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,26 @@ static int oci_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedl
403403
}
404404
/* }}} */
405405

406+
/* {{{ oci_handle_name_quoter */
407+
static int oci_handle_name_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen TSRMLS_DC)
408+
{
409+
int i;
410+
int j = 0;
411+
*quoted = safe_emalloc(2, unquotedlen, 3);
412+
(*quoted)[j++] = '"';
413+
for (i = 0; i < unquotedlen; i++) {
414+
(*quoted)[j++] = unquoted[i];
415+
if (unquoted[i] == '"') {
416+
(*quoted)[j++] = '"';
417+
}
418+
}
419+
(*quoted)[j++] = '"';
420+
(*quoted)[j] = '\0';
421+
*quotedlen = j;
422+
return 1;
423+
}
424+
/* }}} */
425+
406426
static int oci_handle_begin(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
407427
{
408428
/* with Oracle, there is nothing special to be done */
@@ -581,7 +601,10 @@ static struct pdo_dbh_methods oci_methods = {
581601
pdo_oci_fetch_error_func,
582602
oci_handle_get_attribute,
583603
pdo_oci_check_liveness, /* check_liveness */
584-
NULL /* get_driver_methods */
604+
NULL, /* get_driver_methods */
605+
NULL, /* persistent_shutdown */
606+
NULL, /* in_transaction */
607+
oci_handle_name_quoter,
585608
};
586609

587610
static int pdo_oci_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) /* {{{ */

ext/pdo_pgsql/pgsql_driver.c

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,26 @@ static int pgsql_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquote
342342
return 1;
343343
}
344344

345+
/* {{{ pgsql_handle_name_quoter */
346+
static int pgsql_handle_name_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen TSRMLS_DC)
347+
{
348+
int i;
349+
int j = 0;
350+
*quoted = safe_emalloc(2, unquotedlen, 3);
351+
(*quoted)[j++] = '"';
352+
for (i = 0; i < unquotedlen; i++) {
353+
(*quoted)[j++] = unquoted[i];
354+
if (unquoted[i] == '"') {
355+
(*quoted)[j++] = '"';
356+
}
357+
}
358+
(*quoted)[j++] = '"';
359+
(*quoted)[j] = '\0';
360+
*quotedlen = j;
361+
return 1;
362+
}
363+
/* }}} */
364+
345365
static char *pdo_pgsql_last_insert_id(pdo_dbh_t *dbh, const char *name, unsigned int *len TSRMLS_DC)
346366
{
347367
pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data;
@@ -1030,8 +1050,9 @@ static struct pdo_dbh_methods pgsql_methods = {
10301050
pdo_pgsql_get_attribute,
10311051
pdo_pgsql_check_liveness, /* check_liveness */
10321052
pdo_pgsql_get_driver_methods, /* get_driver_methods */
1033-
NULL,
1053+
NULL, /* persistent_shutdown */
10341054
pgsql_handle_in_transaction,
1055+
pgsql_handle_name_quoter,
10351056
};
10361057

10371058
static int pdo_pgsql_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) /* {{{ */

ext/pdo_sqlite/sqlite_driver.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,26 @@ static int sqlite_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquot
238238
return 1;
239239
}
240240

241+
/* {{{ sqlite_handle_name_quoter */
242+
static int sqlite_handle_name_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen TSRMLS_DC)
243+
{
244+
int i;
245+
int j = 0;
246+
*quoted = safe_emalloc(2, unquotedlen, 3);
247+
(*quoted)[j++] = '"';
248+
for (i = 0; i < unquotedlen; i++) {
249+
(*quoted)[j++] = unquoted[i];
250+
if (unquoted[i] == '"') {
251+
(*quoted)[j++] = '"';
252+
}
253+
}
254+
(*quoted)[j++] = '"';
255+
(*quoted)[j] = '\0';
256+
*quotedlen = j;
257+
return 1;
258+
}
259+
/* }}} */
260+
241261
static int sqlite_handle_begin(pdo_dbh_t *dbh TSRMLS_DC)
242262
{
243263
pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
@@ -755,7 +775,9 @@ static struct pdo_dbh_methods sqlite_methods = {
755775
pdo_sqlite_get_attribute,
756776
NULL, /* check_liveness: not needed */
757777
get_driver_methods,
758-
pdo_sqlite_request_shutdown
778+
pdo_sqlite_request_shutdown,
779+
NULL, /* in_transaction */
780+
sqlite_handle_name_quoter,
759781
};
760782

761783
static char *make_filename_safe(const char *filename TSRMLS_DC)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
PDO SQLite quote name
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('pdo_sqlite')) print 'skip not loaded';
6+
?>
7+
--FILE--
8+
<?php
9+
$pdo = new PDO("sqlite::memory:");
10+
11+
echo $pdo->quoteName('id') . "\n";
12+
echo $pdo->quoteName('order') . "\n";
13+
echo $pdo->quoteName('') . "\n";
14+
echo $pdo->quoteName('x"y') . "\n";
15+
?>
16+
--EXPECT--
17+
"id"
18+
"order"
19+
""
20+
"x""y"

0 commit comments

Comments
 (0)