Committed by Graham Ollis <[email protected]>
Implement pg_placeholder_nocolons rt#95173
---
Pg.pm | 28 ++++++++++++++++++++++++++++
dbdimp.c | 35 ++++++++++++++++++++++++++++++++++-
dbdimp.h | 2 ++
3 files changed, 64 insertions(+), 1 deletion(-)
diff --git a/Pg.pm b/Pg.pm
index 1dc8971..68e2772 100644
--- a/Pg.pm
+++ b/Pg.pm
@@ -1679,6 +1679,7 @@ use 5.008001;
pg_pass => undef,
pg_pid => undef,
pg_placeholder_dollaronly => undef,
+ pg_placeholder_nocolons => undef,
pg_port => undef,
pg_prepare_now => undef,
pg_protocol => undef,
@@ -1736,6 +1737,7 @@ use 5.008001;
pg_cmd_status => undef,
pg_oid_status => undef,
pg_placeholder_dollaronly => undef,
+ pg_placeholder_nocolons => undef,
pg_prepare_name => undef,
pg_prepare_now => undef,
pg_segments => undef,
@@ -2604,6 +2606,20 @@ Alternatively, you can set it at prepare time:
{pg_placeholder_dollaronly => 1});
$sth->execute('segname');
+If your queries use array slices but you still want to use question marks as
+placeholders, you can tell DBD::Pg to ignore just colon placeholders by setting
+the L</pg_placeholder_nocolons> attribute in the same way. Examples:
+
+ $dbh->{pg_placeholder_nocolons} = 1;
+ $sth = $dbh->prepare(q{SELECT array[1:2] FROM mytable WHERE id = ?});
+ $sth->execute(1);
+
+Again, you may set it param time as well:
+
+ $sth = $dbh->prepare(q{SELECT array[1:2] FROM mytable WHERE id = ?}.
+ {pg_placeholder_nocolons => 1});
+ $sth->execute(1);
+
=head3 B<prepare_cached>
$sth = $dbh->prepare_cached($statement, \%attr);
@@ -3203,6 +3219,12 @@ DBD::Pg specific attribute. Defaults to false. When
true, question marks inside
are not treated as L<placeholders|/Placeholders>. Useful for statements that
contain unquoted question
marks, such as geometric operators.
+=head3 B<pg_placeholder_nocolons> (boolean)
+
+DBD::Pg specific attribute. Defaults to false. When true, colons inside of
statements
+are not treated as L<placeholders|/Placeholders>. Useful for statements that
contain an
+array slice.
+
=head3 B<pg_enable_utf8> (integer)
DBD::Pg specific attribute. The behavior of DBD::Pg with regards to this flag
has
@@ -3870,6 +3892,12 @@ DBD::Pg specific attribute. Defaults to off. When true,
question marks inside of
being prepared are not treated as placeholders. Useful for statements that
contain unquoted question
marks, such as geometric operators.
+=head3 B<pg_placeholder_nocolons> (boolean)
+
+DBD::Pg specific attribute. Defaults to off. When true, colons inside of
statements
+are not treated as L<placeholders|/Placeholders>. Useful for statements that
contain an
+array slice.
+
=head3 B<pg_async> (integer)
DBD::Pg specific attribute. Indicates the current behavior for asynchronous
queries. See the section
diff --git a/dbdimp.c b/dbdimp.c
index e55dd83..bfc8a44 100644
--- a/dbdimp.c
+++ b/dbdimp.c
@@ -236,6 +236,7 @@ int dbd_db_login6 (SV * dbh, imp_dbh_t * imp_dbh, char *
dbname, char * uid, cha
imp_dbh->prepare_now = DBDPG_FALSE;
imp_dbh->done_begin = DBDPG_FALSE;
imp_dbh->dollaronly = DBDPG_FALSE;
+ imp_dbh->nocolons = DBDPG_FALSE;
imp_dbh->expand_array = DBDPG_TRUE;
imp_dbh->txn_read_only = DBDPG_FALSE;
imp_dbh->pid_number = getpid();
@@ -791,6 +792,12 @@ SV * dbd_db_FETCH_attrib (SV * dbh, imp_dbh_t * imp_dbh,
SV * keysv)
retsv = newSViv((IV)imp_dbh->switch_prepared);
break;
+ case 23: /* pg_placeholder_nocolons */
+
+ if (strEQ("pg_placeholder_nocolons", key))
+ retsv = newSViv((IV)imp_dbh->nocolons);
+ break;
+
case 25: /* pg_placeholder_dollaronly */
if (strEQ("pg_placeholder_dollaronly", key))
@@ -954,6 +961,14 @@ int dbd_db_STORE_attrib (SV * dbh, imp_dbh_t * imp_dbh, SV
* keysv, SV * valuesv
}
break;
+ case 23: /* pg_placeholder_nocolons */
+
+ if (strEQ("pg_placeholder_nocolons", key)) {
+ imp_dbh->nocolons = newval ? DBDPG_TRUE : DBDPG_FALSE;
+ retval = 1;
+ }
+ break;
+
case 25: /* pg_placeholder_dollaronly */
if (strEQ("pg_placeholder_dollaronly", key)) {
@@ -1113,6 +1128,12 @@ SV * dbd_st_FETCH_attrib (SV * sth, imp_sth_t * imp_sth,
SV * keysv)
retsv = newSViv((IV)imp_sth->switch_prepared);
break;
+ case 23: /* pg_placeholder_nocolons */
+
+ if (strEQ("pg_placeholder_nocolons", key))
+ retsv = newSViv((IV)imp_sth->nocolons);
+ break;
+
case 25: /* pg_placeholder_dollaronly */
if (strEQ("pg_placeholder_dollaronly", key))
@@ -1389,6 +1410,14 @@ int dbd_st_STORE_attrib (SV * sth, imp_sth_t * imp_sth,
SV * keysv, SV * valuesv
}
break;
+ case 23: /* pg_placeholder_nocolons */
+
+ if (strEQ("pg_placeholder_nocolons", key)) {
+ imp_sth->nocolons = SvTRUE(valuesv) ? DBDPG_TRUE :
DBDPG_FALSE;
+ retval = 1;
+ }
+ break;
+
case 25: /* pg_placeholder_dollaronly */
if (strEQ("pg_placeholder_dollaronly", key)) {
@@ -1549,6 +1578,7 @@ int dbd_st_prepare (SV * sth, imp_sth_t * imp_sth, char *
statement, SV * attrib
imp_sth->switch_prepared = imp_dbh->switch_prepared;
imp_sth->prepare_now = imp_dbh->prepare_now;
imp_sth->dollaronly = imp_dbh->dollaronly;
+ imp_sth->nocolons = imp_dbh->nocolons;
/* Parse and set any attributes passed in */
if (attribs) {
@@ -1565,6 +1595,9 @@ int dbd_st_prepare (SV * sth, imp_sth_t * imp_sth, char *
statement, SV * attrib
if ((svp =
hv_fetch((HV*)SvRV(attribs),"pg_placeholder_dollaronly", 25, 0)) != NULL) {
imp_sth->dollaronly = SvTRUE(*svp) ? DBDPG_TRUE :
DBDPG_FALSE;
}
+ if ((svp =
hv_fetch((HV*)SvRV(attribs),"pg_placeholder_nocolons", 23, 0)) != NULL) {
+ imp_sth->nocolons = SvTRUE(*svp) ? DBDPG_TRUE :
DBDPG_FALSE;
+ }
if ((svp = hv_fetch((HV*)SvRV(attribs),"pg_async", 8, 0)) !=
NULL) {
imp_sth->async_flag = (int)SvIV(*svp);
}
@@ -1950,7 +1983,7 @@ static void pg_st_split_statement (pTHX_ imp_sth_t *
imp_sth, int version, char
placeholder_type = 1;
}
/* Colon style, but skip two colons in a row (e.g.
myval::float) */
- else if (':' == ch) {
+ else if (':' == ch && ! imp_sth->nocolons) {
if (':' == *statement) {
/* Might as well skip _all_ consecutive
colons */
while(':' == *statement) {
diff --git a/dbdimp.h b/dbdimp.h
index 22d55e7..350f1a3 100644
--- a/dbdimp.h
+++ b/dbdimp.h
@@ -36,6 +36,7 @@ struct imp_dbh_st {
bool prepare_now; /* force immediate prepares, even with
placeholders. Set by user, default is 0 */
bool done_begin; /* have we done a begin? (e.g. are we in a
transaction?) */
bool dollaronly; /* only consider $1, $2 ... as valid
placeholders */
+ bool nocolons; /* do not consider :1, :2 ... as valid
placeholders */
bool expand_array; /* transform arrays from the db into Perl
arrays? Default is 1 */
bool txn_read_only; /* are we in read-only mode? Set with
$dbh->{ReadOnly} */
@@ -112,6 +113,7 @@ struct imp_sth_st {
bool has_default; /* does it have one or more 'DEFAULT' values?
*/
bool has_current; /* does it have one or more 'DEFAULT' values?
*/
bool dollaronly; /* Only use $1 as placeholders, allow all else
*/
+ bool nocolons; /* do not consider :1, :2 ... as valid
placeholders */
bool use_inout; /* Any placeholders using inout? */
bool all_bound; /* Have all placeholders been bound? */
};
--
1.8.4