[DBD::Pg] Implement pg_placeholder_nocolons rt#95173
[email protected] Thu, 8 May 2014 21:55:16 +0000
| Newsgroups | perl.dbd.pg.changes |
|---|---|
| Message-ID | <[email protected]> |
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