Re: Escaping placeholders, take 2

2015-01-09 Thread Tim Bunce
On Fri, Jan 09, 2015 at 02:54:56PM -, Greg Sabino Mullane wrote:
 
 Just a heads up to this list - support for backslash-escaped placeholders 
 is now implemented in the current production version of DBD::Pg, 3.5.0
 
 http://search.cpan.org/dist/DBD-Pg/
 
 http://cpansearch.perl.org/src/TURNSTEP/DBD-Pg-3.5.0/Changes

Many thanks Greg.

Tim.


Re: Escaping placeholders, take 2

2015-01-09 Thread Greg Sabino Mullane

-BEGIN PGP SIGNED MESSAGE-
Hash: RIPEMD160


Just a heads up to this list - support for backslash-escaped placeholders 
is now implemented in the current production version of DBD::Pg, 3.5.0

http://search.cpan.org/dist/DBD-Pg/

http://cpansearch.perl.org/src/TURNSTEP/DBD-Pg-3.5.0/Changes

- -- 
Greg Sabino Mullane g...@turnstep.com
End Point Corporation http://www.endpoint.com/
PGP Key: 0x14964AC8 201501090952
http://biglumber.com/x/web?pk=2529DF6AB8F79407E94445B4BC9B906714964AC8
-BEGIN PGP SIGNATURE-

iEYEAREDAAYFAlSv64MACgkQvJuQZxSWSsjPNQCfbt80/2VAaRj5qIQG7fm+0TqL
kSQAmQHrbf1d22hWx5+NuOeq7TmPccmK
=+XvD
-END PGP SIGNATURE-




Re: Escaping placeholders, take 2

2015-01-02 Thread Tim Bunce
On Wed, Dec 31, 2014 at 03:55:42AM -, Greg Sabino Mullane wrote:
 
 Tim Bunce wrote:
  Wherein I attempt to summarize the requirements, the background, the 
  options,
  the risks, and the counter-proposal ...
 
 Thanks for taking the time to write all this out in a coherent manner.

You're welcome. I find the effort usually greatly clarifies my thinking.

 I may once again assume the role of devil's advocate herein.

Thanks.

  In modern application development, however, the DBI is just another
  foundation layer, low down in the stack. Above it are modules like
  SQL::Abstract, and ORMs like DBIx::Class. Companies have large and
  growing investments in these stacks, plus the modules they've built over
  them to provide abstraction and encapsulation of business logic.
 
 Agreed.
 
  For these large applications the attribute workarounds are rarely helpful.
 
 Is that a true generalization? Or is it only because these large 
 applications have not bothered to support the attributes?

Supporting attributes means supporting (non-standard) numbered placeholders.
Supporting numbered placeholders is, as previously described, very far
from trivial for SQL::Abstract and thus DBIx::Class.  (I certainly
wouldn't characterize this as not bothered.)


  +Some drivers allow you to prevent the recognition of a placeholder by 
  placing a
  +single backslash character (C\) immediately before it. The driver will 
  remove
  +the backslash character and ignore the placeholder, passing it unchanged 
  to the
  +backend. If the driver supports this then L/get_info(9000) will return 
  true.
 
 Seems a good start. I don't like the phrase prevent recognition of a 
 placeholder 
 but it's too late at night to propose an alternate right now.

s/prevent/disable/?


  Which likely means that SQL::Abstract and/or DBIx::Class will need to
  know as well. (Unless they expose the DBD directly to the user, which
  ruins the point a bit).
 
  Not true.
 
 How will a user of SQL::Abstract know if escapes are supported or not? 
 Isn't the job of such frameworks to release the user from such worries, 
 or at least present some sort of attribute the user can rely on?

SQL::Abstract isn't (just) about portability. It allows SQL conditions
to be expressed and composed via Perl data structures. That's very
powerful functionality. Users who want to use a postgres ? operator know
they're using DBD::Pg and can simply require the appropriate version.


  Question marks are the international standard for placeholders.
  The DBI should have specified a way to escape them from the start.
  I'm attempting to fix that now.
 
 Taking off the devil's advocate hat now. I can agree with this 
 position and the backslash solution.

Great. Thanks Greg.

  To demonstrate the relative complexity, here's a proof-of-concept patch
  for DBD::Pg to implement support for escaping question mark placeholders:
 
  https://github.com/timbunce/dbdpg/commit/54358c7a7efeeaf2666c5e28c301e47624fb9615
 
 +1, thanks for that. I certainly cannot see any harm in adding escape support 
 to DBD::Pg, and then letting the upstream modules start adapting to it.

Wonderful. I'll work on polishing up the patch.

Tim.


Re: Escaping placeholders, take 2

2014-12-30 Thread Ron Savage

Hi All

My apologies. Instead of Text::Balanced::Marpa, I should have pointed 
you to MarpaX::Languages::SQL2003::AST.


Here, AST is Abstract syntax tree. See 
https://en.wikipedia.org/wiki/Abstract_syntax_tree.


--
Ron Savage - savage.net.au


Re: Escaping placeholders, take 2

2014-12-30 Thread Greg Sabino Mullane

-BEGIN PGP SIGNED MESSAGE-
Hash: RIPEMD160


Tim Bunce wrote:
 Wherein I attempt to summarize the requirements, the background, the options,
 the risks, and the counter-proposal ...

Thanks for taking the time to write all this out in a coherent manner.
I may once again assume the role of devil's advocate herein.

 In modern application development, however, the DBI is just another
 foundation layer, low down in the stack. Above it are modules like
 SQL::Abstract, and ORMs like DBIx::Class. Companies have large and
 growing investments in these stacks, plus the modules they've built over
 them to provide abstraction and encapsulation of business logic.

Agreed.

 For these large applications the attribute workarounds are rarely helpful.

Is that a true generalization? Or is it only because these large 
applications have not bothered to support the attributes?

 Working 'high up' in an application stack that's dynamically constructing
 SQL with placeholders it should be possible to express any desired behavior.

Agreed.

 Some mechanism is needed to allow an individual character sequence that
 normally represents a placeholder, to appear in the SQL without it being
 treated as a placeholder by the driver. To escape it's usual meaning.

But...  okay I can't find any fault with this. :)

 If escaping question mark placeholders was already defined in 2008 then
 pg_placeholder_dollaronly might not have been added to DBD::Pg.

Perhaps, perhaps not. pg_placeholder_dollaronly still allows the same SQL to 
be slung around, including using it inside of Postgres itself. So it's 
likely both methods would have been available.

 1. Backslash

Seems like a good solution. A little ugly, but certainly unlikely to 
clash with any future SQL-isms.

 but that seems very minor as the use of backslashes in single and double
 quotes is natural and familar for Perl developers.

True. We could recommend always using double quotes - and Perl::Critic's 
inevitable nagging be damned. :)

 2. Doubling

Ugh. No thanks.

 I presume there are no database dialects where two adjacent placeholders 
 would be valid, so I think it's safe.

Nope, '??' is a perfectly legal operator in Postgres. A backslash, however, 
cannot be part of an operator's name. (nor can braces).

 3. Vendor escape clauses

Interesting. Probably overkill at this point, but certainly something 
we could think about supporting.

 $sql_abstract-where({ json_field = { '{verbatim ?}' = $bar } })

I find it hard to imagine people getting excited about writing 
that, and I would imagine SQL::Abstract would simply let people write 
{ \\? = $bar } and write the long-form behind their back.

 No code will break!

Doubling will. But nobody likes that option anyway.

 +Some drivers allow you to prevent the recognition of a placeholder by 
 placing a
 +single backslash character (C\) immediately before it. The driver will 
 remove
 +the backslash character and ignore the placeholder, passing it unchanged to 
 the
 +backend. If the driver supports this then L/get_info(9000) will return 
 true.

Seems a good start. I don't like the phrase prevent recognition of a 
placeholder 
but it's too late at night to propose an alternate right now.

 (I'm undecided about making the get_info(9000) return value a bit-map

Ugh, no. Drivers should escape all placeholder types it supports.

 Which likely means that SQL::Abstract and/or DBIx::Class will need to
 know as well. (Unless they expose the DBD directly to the user, which
 ruins the point a bit).

 Not true.

How will a user of SQL::Abstract know if escapes are supported or not? 
Isn't the job of such frameworks to release the user from such worries, 
or at least present some sort of attribute the user can rely on?

 So we will have both escaped and unescaped versions of SQL 
 floating around, subject to the whims of whether or not your particular 
 DBD supports it (and in which version).

 There's no such thing as escaped and unescaped versions of SQL.
 That's a false premise.  This is a really important point: the syntax
 being proposed *is invalid SQL*.

I'm not sure of the distinction you are making here. The proposed 
syntax is invalid, true, and the original syntax may or may not be 
invalid, depending on how you look at it. Portable code that won't 
know in advance if the underlying dbd supports escaping will need 
to have two SQLs paths - one with escaping, and one to do it some 
other way.

 Then ribasushi, a principle maintainer of SQL::Abstract and DBIx::Class,
 pointed out the fatal flaw: numbered placeholders aren't directly composable.
...
 Trying to do the same with numbered placeholders (colon or dollar) would
 require parsing and rewriting of the SQL.  Clearly non-trivial and slow.
 For this reason he wouldn't accept such a patch to SQL::Abstract, and I'd
 agree with that position.

Non-trivial, but not exactly difficult either, especially considering all the 
other contortions said modules are already performing. 

Re: Escaping placeholders, take 2

2014-12-29 Thread David E. Wheeler
On Dec 28, 2014, at 5:49 AM, Tim Bunce tim.bu...@pobox.com wrote:

 Question marks are the international standard for placeholders.
 The DBI should have specified a way to escape them from the start.
 I'm attempting to fix that now.

+1

David



smime.p7s
Description: S/MIME cryptographic signature


Escaping placeholders, take 2

2014-12-28 Thread Tim Bunce
Wherein I attempt to summarize the requirements, the background, the options,
the risks, and the counter-proposal ...

** Background

Drivers that support placeholders parse the SQL statement to find them.
The parsing is really just simple tokenization that only knows how to skip
over quoted strings, quoted identifiers, and comments for the SQL dialect
used by the database. The remaining text is checked for placeholders.

A question mark is the international SQL standard for placeholders.
Per ISO/IEC 9075-2:2003 section 4.24 Dynamic SQL concepts:

In SQL-statements that are executed dynamically, the parameters are
called dynamic parameters (dynamic parameter specifications) and
are represented in SQL language by a question mark (?).

Some drivers also support placeholders expressed as a colon ':' followed
by a number and/or a name. Some drivers support other forms like a dollar
'$' followed by a number. Different types of placeholders cannot be
mixed within a statement.

The number of parameters passed to execute (etc.) has to match the number
of placeholders found in the statement or an error is reported.

An individual SQL statement typically comes primarily from one of these sources:
1. Written literally in the source code, perhaps with some $interpolation
2. Constructed dynamically, in whole or part, using a module like SQL::Abstract
3. From an external source, like an SQL script file or 'catalog'.


** Historical Issues and Work-arounds

Sometimes the driver will identify placeholders in the SQL statement
that weren't intended by the developer.  So some drivers have added
ad-hoc ways to limit the parsing of placeholders.  For example:

  pg_direct - query passed directly without parsing for placeholders at all
  pg_placeholder_dollaronly - question marks are not treated as placeholders
  pg_placeholder_nocolons - colons are not treated as placeholders
  ora_placeholders - disable processing of all placeholders
  odbc_ignore_named_placeholders - disable processing of :foo placeholders

In most cases these have been added as a workaround for statements that
contain colons followed by words that the driver was treating as placeholders.
(For example :old and :new when defining Oracle triggers.)

The exception is pg_placeholder_dollaronly which was added in 2008 to
allow use of postgres geometric operators like ?|| (are parallel)
See http://www.postgresql.org/docs/9.4/static/functions-geometry.html

So supporting multiple styles of placeholders has both caused problems
and allowed drivers to dodge the bullet when one style has become a
problem in a particular situation. But that's only a limited solution.
It doesn't promote the development and use of generic higher-level reusable
modules. (You could frame the progress of software development in terms
of enabling developers to work at ever-higher levels of abstraction.)


** Limitation of Existing Workarounds

A key problem with these attribute workarounds is that they affect the
entire statement.  That's a good approach when loading statements from
an external source, and often ok when writing individual DBI calls directly
where an alternative placeholder style or quote()'ing can be used.

In modern application development, however, the DBI is just another
foundation layer, low down in the stack. Above it are modules like
SQL::Abstract, and ORMs like DBIx::Class. Companies have large and
growing investments in these stacks, plus the modules they've built over
them to provide abstraction and encapsulation of business logic.

For these large applications the attribute workarounds are rarely helpful.

Working 'high up' in an application stack that's dynamically constructing
SQL with placeholders it should be possible to express any desired behavior.


** Requirements

Some mechanism is needed to allow an individual character sequence that
normally represents a placeholder, to appear in the SQL without it being
treated as a placeholder by the driver. To escape it's usual meaning.

If escaping question mark placeholders was already defined in 2008 then
pg_placeholder_dollaronly might not have been added to DBD::Pg.

The issue of escaping placeholders is on the table now because
PostgreSQL supports a JSON type with a rich set of features and
operators, some of which use a question mark.  For example, the
expression json_type_field ? 'bar' is true if the string 'bar' exists as
a key/element exist within the JSON value of json_type_field. For more
information see http://www.postgresql.org/docs/9.4/static/functions-json.html
Use of JSON and these operators is likely to be much more common than
use of the geometric operators mentioned earlier.

So, while the needs of Postgres users is what prompted this topic now,
the requirement is more general. It would be good to agree on an approach
that could be applied to most drivers if the need arises.


** Options

There seem to be several options worth considering

1. Backslash

A backslash could be placed

Re: Escaping placeholders, take 2

2014-12-28 Thread Darren Duncan
Thank you for this post Tim, it seemed to lay out the issues well and make a lot 
of things clear.


I'm now inclined to support your backslash-escape proposal at the DBI driver 
level in principle.


(I also agree that the doubling method is nasty.)

Or alternately I suggest variation on that proposal that brings in shades of the 
vendor escape clauses.


I suggest a variant where instead of a single backslash character indicating an 
escape, we have some multi-character thing to indicate it, ideally involving 
delimiters so it is more clear on how far the effect of the new escape feature 
is supposed to go.


For example, using \{?} rather than \? or \{:foo} rather than \:foo.

One benefit of that is if you have some SQL that contains ? or : numerous times, 
you only need to surround the whole fragment with \{} and not individually 
escape each occurrence, making for neater code.


As to dealing with say literal { or } in the SQL as I could see reasonably 
happening, the quoting mechanism could be made more generic like Perl's q/etc, 
so for example it would take the form \X...X where whatever character appears 
after the \ is what is matched, and it could be a multiplicity if necessary 
within reason, eg \{{{...}}} would just work.  For that matter, heredocs or the 
quoted printable feature you can see in email messages or such, eg you have 
\foo...foo or some such.


I'm speaking in principle here, I'm not proposing a specific feature set, but 
both q as well as Perl 6's related quoting mechanism is useful for guidance, 
and I think something involving delimiters is best.


But if some of that sounds unduly complicated, I have a better idea.

I propose that the DBI include an API for users to tell the driver what possible 
escape delimiters they are using.  For example, doable at least at a statement 
level (and optionally on a connection/etc level for defaulting if that makes sense).


The API could involve an 'attr' given when preparing a SQL statement or other 
appropriate places.


  placeholder_escape_delimiters = [ '\{','}' ]
  placeholder_escape_delimiters = [ '\{','}','\[',']' ]
  placeholder_escape_delimiters = [ '\{{{','}}}' ]
  placeholder_escape_delimiters = [ '{{{','}}}' ]

In this way, the backslash is no longer special, or necessary, though I 
anticipate it would often still be used for the mnemonics.


Rather, when the driver is parsing the SQL for placeholders, if it encounters 
any left delimiter strings, if will leave the following SQL unaltered until it 
encounters the corresponding right delimiter string, and then it looks for 
placeholders again.


(As to numbered placeholders, which are effectively a special case of named 
placeholders, not being directly composable in SQL::Abstract, I see that as 
being a problem itself.  It would be a great help to developers in principle if 
the native way for working with parameters was named rather than positionally. 
However, that is really a separate matter to deal with and I think it is a good 
idea for Tim's proposal in some form to happen regardless of dealing with this 
separate matter.)


-- Darren Duncan



Re: Escaping placeholders, take 2

2014-12-28 Thread Ron Savage

Hi Darren

On 29/12/14 13:59, Darren Duncan wrote:


The API could involve an 'attr' given when preparing a SQL statement or
other appropriate places.

   placeholder_escape_delimiters = [ '\{','}' ]
   placeholder_escape_delimiters = [ '\{','}','\[',']' ]
   placeholder_escape_delimiters = [ '\{{{','}}}' ]
   placeholder_escape_delimiters = [ '{{{','}}}' ]

In this way, the backslash is no longer special, or necessary, though I
anticipate it would often still be used for the mnemonics.

Rather, when the driver is parsing the SQL for placeholders, if it
encounters any left delimiter strings, if will leave the following SQL
unaltered until it encounters the corresponding right delimiter string,
and then it looks for placeholders again.


Perhaps a job for https://metacpan.org/release/Text-Balanced-Marpa

--
Ron Savage - savage.net.au


Re: Escaping placeholders (was: [Dbix-class] Using Postgres JSONB operators in queries)

2014-12-24 Thread Tim Bunce
Sometime over the holiday period I hope to write up a summary of the
arguments for and against and suggest ways forwards.

Tim.


Re: Escaping placeholders

2014-12-23 Thread Martin J. Evans

On 22/12/2014 00:39, Darren Duncan wrote:

I agree with Greg's counter-proposal, from which I derive my own words
here.

1.  I propose that there be no modification to the DBI spec related to
new escaping whether optional or not, so leave things the way they are
here, SQL continues to be interpreted the way it long has by default.

2.  When users want to use operators in PostgreSQL that contain literal
? in their names, then they enable DBD::Pg's pg_placeholder_dollaronly
so that ? are no longer treated as placeholders.  Likewise,
pg_placeholder_nocolons can be enabled when they don't want literal : to
indicate a placeholder either.  Users would either do this directly if
they're using DBI/DBD::Pg directly, or indirectly using their over-top
framework of choice.  When users aren't using the ? operators et al,
they can leave things alone which will work as normal.

3.  SQL::Abstract et al, those tools external to DBI/DBDs, are the
correct and proper places to modify where users of said want to use the
operators with ? names and such.  These tools already have special
knowledge of individual DBMS systems to work with them effectively, and
the ? operators is just one more of those things.  The users of said
tools may have to flip a configuration switch possibly so $1 etc are
used behind the scenes, if necessary, but that's okay because the use of
? operators only happens when the users choose to make a change to use
them anyway.

In summary, now is not the time or place to be introducing backslashing
doubled or otherwise in DBI such as discussed, that's a poor solution
and its better to save such risky/etc changes for when there's a more
compelling case for them.

I should also mention I feel it is perfectly reasonable for each DBMS to
have operators composed of any characters they want where doing so makes
sense within the context of the SQL/etc itself.  See also that Perl
itself has both ? and : and etc as operator names, Perl 6 even more so,
and I don't see anyone thinking that's a bad idea.  So I have no problem
with PostgreSQL having ? in operator names such as it did.  Its not like
the SQL standard reserves ? or whatever for prepared statement
parameters, that's defined to be implementation dependent I believe (WD
9075-2:200w(E) 20.6 prepare statement).

-- Darren Duncan


I tend to agree with Greg and Darren on this for all the same reasons.

If it could be done in DBI without affecting DBDs then I might have less 
of a problem with it as anything wanting this feature would only have to 
check DBI. There are already too many differences between DBDs and 
introducing yet another one which would make applications and interfaces 
even more complex. Plus, this seems to be a postgres specific issue and 
escaping of ? or : would only benefit other DBDs in the few rare cases 
where those are legitmate chrs in themselves.


There is already an inconsistency in placeholders as some DBDs 
need/support ':name' when binding and some only support 'name'.


DBD::ODBC already has a ignore placeholders switch for when users want 
to pass SQL containing a ? or : when neither is a placeholder e.g., SQL 
Server procedures often contain colons.


If it was not for some poor ODBC drivers that don't support SQLNumParams 
DBD::ODBC could get away with not parsing the SQL at all which would be 
my preferred solution and in fact, the version I use does not parse the 
SQL at all. Adding escaping would mean more work and probably taking a 
copy of the scalar for modification.


However, I think Greg and Darren's arguments are strong enough on their own.

If, it ends up where the DBI spec is changed to allow escaping can we 
please introduce the DBD capabilities API at the same time. I know I 
started the thread some time ago and put together an initial list then 
did not move it forward, but it would make application and interface 
layers so much easier if they could just say 'does this DBD do X' and 
maybe 'how do I make it do X'.


Martin
--
Martin J. Evans
Wetherby, UK


On 2014-12-21 7:17 AM, Greg Sabino Mullane (the tenth man) wrote:

Tim Bunce wrote:


For code not using DBIx::Class the pg_placeholder_dollaronly attribute
might work, see https://metacpan.org/pod/DBD::Pg#Placeholders


Yes, this is the current canonical solution. It's a real shame
that ? was used as an operator, but that horse has left the barn.


For code using DBIx::Class the problem is more tricky. I'm pretty sure
that SQL::Abstract and thus DBIx::Class only support question mark
placeholders. That means it probably impossible to use expressions
containing a question mark operator with SQL::Abstract/DBIx::Class.
(Though I'd be delighted to be proven wrong.)

So I think the DBI spec for placeholders needs to be extended to allow a
way to 'escape' a question mark that the driver would otherwise treat as
a placeholder.

The obvious and natural approach would be to use a backslash before a
question mark. The backslash would be removed by the driver before 

Re: [Dbix-class] Escaping placeholders

2014-12-22 Thread Peter Rabbitson

On 12/20/2014 03:38 PM, Tim Bunce wrote:

On Fri, Dec 19, 2014 at 01:12:16PM +0100, Alexander Foken wrote:

Hello all,

this reminds me of a similar problem I had in 2000 with DBI,
DBD::Oracle, and Oracle. See
http://marc.info/?t=9506395904r=1w=2,
http://173.79.223.25/?l=dbi-devm=95077716125217w=2.

Problem was using named placeholders (:foo) in DBI and at the same
time use PL/SQL code containing variables (:bar), DBI considered
both :foo and :bar to be placeholders instead of leaving :bar
alone and pass it to Oracle. A set of patches from Michael A. Chase
allowed disabling parts or all of the placeholder parsing, so using
unnamed placeholders (?) allowed using PL/SQL variables in SQL
statements.

But the fundamental problem was not solved, there was and still is
no way to escape placeholders.


Can you, or anyone else, think of any situation where a backslash before
a ? or :foo (or even $1) style placeholder might be valid SQL?

So far no one has come up with one, so I'm getting more comfortable
with the idea that a backslash before a placeholder is a safe change.
I.e., there's a near-zero risk that upgrading a DBI driver to support
backslashes would cause breakage in existing code.



I am not sure why but a backlashed version makes me wary... What about 
?? instead?




Re: Escaping placeholders

2014-12-22 Thread Jens Rehsack

Am 20.12.2014 um 23:10 schrieb Tim Bunce tim.bu...@pobox.com:

 On Sat, Dec 20, 2014 at 05:35:55PM +0100, Alexander Foken wrote:
 On 20.12.2014 15:38, Tim Bunce wrote:
 Can you, or anyone else, think of any situation where a backslash before
 a ? or :foo (or even $1) style placeholder might be valid SQL?
 
 I found two situations for PostgreSQL:
 
 (1) PostgreSQL allows almost any character as escape character in
 Unicode string constants 
 (http://www.postgresql.org/docs/current/static/sql-syntax-lexical.html#SQL-SYNTAX-STRINGS-UESCAPE).
 With that, I can construct  an expression containing \:foo that is
 valid SQL as understood by PostgreSQL:
 
U'foo\:bar' UESCAPE ':'
 
 This expression represents the string foo\Xbar, where X is the
 Unicode character U+ (TAI VIET LETTER LOW VO).
 
 I don't think that'll be a problem because the driver code that parses
 the statement looking for placeholders will skip over quoted strings.

Sure, strings can be manipulated on language level, no need for driver
to interfere.

 (2) PostgreSQL also allows Dollar quoting 
 (http://www.postgresql.org/docs/current/static/sql-syntax-lexical.html#SQL-SYNTAX-DOLLAR-QUOTING).
 With that, I can construct an expression containing \$1 that is
 valid SQL as understood by PostgreSQL:
 
$1$foo\$1$
 
 This expression represents the string foo\, quoted by dollar signs
 using the character 1 as tag.
 
 I'm not sure if the driver code that parses statements in DBD::Pg
 handles dollar quoting. I presume so. In which case this shouldn't be a
 problem either for the same reason as above.
 
 So far no one has come up with one, so I'm getting more comfortable
 with the idea that a backslash before a placeholder is a safe change.
 I.e., there's a near-zero risk that upgrading a DBI driver to support
 backslashes would cause breakage in existing code.
 
 Do you plan to escape the escape character, i.e. use a double
 backslash at DBI level to represent a single backslash at database
 level?
 
 That's a good question. I'm not sure. I think the answer has to be no.
 I'd welcome any input on that.

We have a dictum (translated word by word ...): One can't even think as
foolish as it sometimes happens.

When escaping is specified, escaping the escape character itself should
be mandatory - just for being complete and do not ask for future trouble.
Of course - outside of quotes only.

Cheers
-- 
Jens Rehsack
rehs...@gmail.com



Re: Escaping placeholders

2014-12-21 Thread peter
On 20.12.2014 15:38, Tim Bunce wrote:
 [...]
 Can you, or anyone else, think of any situation where a backslash before
 a ? or :foo (or even $1) style placeholder might be valid SQL?

Inside quoted text: of course, yes.
Outside quoted text: maybe some RDBMS accept a backslash as a valid character
in the name of a table or column? (Haven't tried this out yet.)
At least make sure \? will not be handled as placeholder inside column name
quoting, as in e.g.
foo \? bar
or in
[foo \? bar]
with SQL Server, or
`foo \? bar`
for MySQL.
But my fear is that even
foo\?bar
would be accepted as valid column or table name by some RDBMS...

--  Peter Vanroose,
ABIS Training  Consulting
Leuven, Belgium.



Re: Escaping placeholders

2014-12-21 Thread Tim Bunce
On Sat, Dec 20, 2014 at 02:23:43PM -0800, Jonathan Leffler wrote:
 
  INSERT INTO SomeTable(DateTimeCol)
  VALUES(DATETIME[1](2014-12-31 23\:59\:59) YEAR TO SECOND);
 
I really won't want people have to futz with their legitimate Informix SQL 
 in order to pass it through
DBD::Informix.

Whatever is provided, whether by DBI or DBD::Informix, must accept the 
 code without the
backslashes in front of the colons.  It is simply not acceptable to have 
 to modify valid SQL to get it
past the gatekeeper code.

Understood. I wouldn't expect DBD::Informix to enable this by default.

We were only discussing a hypothetical situation where DBD::Informix
could optionally enable use of colon placeholders, if desired.

At the moment, the unescaped code works fine.  It will continue to work 
 fine.  As long as DBI does not
break the currently working code, I will survive �� like I have for the 
 last decade and more.  Just
make sure that whatever you do does not break working valid Informix SQL 
 code.

I have absolutely no intention of breaking anything :)

It'll be up to the individual driver authors to add support for escaping
placeholders, if they want to.

(The DBI has a built-in preparse function that's intended for parsing
placeholders but few, if any, drivers use it. I know DBD::Informix doesn't.)

Tim.

On Sat, Dec 20, 2014 at 2:17 PM, Tim Bunce [2]tim.bu...@pobox.com wrote:
 
  On Sat, Dec 20, 2014 at 01:14:29PM -0800, Jonathan Leffler wrote:
  Many, many years ago, DBD::Informix had to give up on the 
 DBI-provided parsing for placeholders
  because
  there were too many contexts in which it was wrong for Informix.  
 It may have improved since
  then, but:
  
INSERT INTO SomeTable(DateTimeCol)
  VALUES(DATETIME(2014-12-31 23:59:59) YEAR TO SECOND);
 
  I think I raised this as an issue back in the 1996-1998 timeframe 
 (I said 'many years ago' and
  meant
  it).  I'd have to dig through my release notes to be more precise.  
 Informix only supports
  natively the
  `?` placeholders.  It doesn't yet have the complexities introduced 
 by the PostgreSQL operators.
  
  I don't know whether this can be handled at all.  It may be that 
 DBD::Informix has to stay out in
  isolation but it would be nice if it wasn't necessary.
 
  The `?` placeholders are 'standard' (for some definition) so 
 DBD::Informix
  isn't really 'in isolation'. There are quite a few drivers that only
  support `?` placeholders.
 
  In theory, if this proposal goes ahead, and is applied to `:` 
 placeholders
  as seems likely, then you'd be able to write the above as:
  INSERT INTO SomeTable(DateTimeCol)
VALUES(DATETIME[3](2014-12-31 23\:59\:59) YEAR TO SECOND);
 
  Tim.
 
--
Jonathan Leffler [4]jonathan.leff...@gmail.com  #include disclaimer.h
Guardian of DBD::Informix - v2013.0521 - [5]http://dbi.perl.org
Blessed are we who can laugh at ourselves, for we shall never cease to be 
 amused.
 
 References
 
Visible links
1. file:///tmp/tel:%282014-12-31%2023
2. mailto:tim.bu...@pobox.com
3. file:///tmp/tel:%282014-12-31%2023
4. mailto:jonathan.leff...@gmail.com
5. http://dbi.perl.org/


Re: Escaping placeholders

2014-12-21 Thread Alexander Foken

On 20.12.2014 23:10, Tim Bunce wrote:

On Sat, Dec 20, 2014 at 05:35:55PM +0100, Alexander Foken wrote:

On 20.12.2014 15:38, Tim Bunce wrote:

Can you, or anyone else, think of any situation where a backslash before
a ? or :foo (or even $1) style placeholder might be valid SQL?

[...]

Do you plan to escape the escape character, i.e. use a double
backslash at DBI level to represent a single backslash at database
level?

That's a good question. I'm not sure. I think the answer has to be no.
I'd welcome any input on that.


The current problem with any kind of DBI placeholders is that there is 
no way to prevent DBI (including any DBDs) to interpret them as 
placeholders. This hasn't changed since 2000. The patches from 2000 
disable placeholders by type (?, $1, :foo) or entirely, but it is not 
possible to pass :foo unchanged and uninterpreted to the database while 
at the same time having a named placeholder :bar.


The proposed backslash escape allows exactly this, so you can have a 
named placeholder :bar and can pass :foo unchanged and uninterpreted to 
the database, but you have to add a backslash in front of :foo. No 
problems with old code for this usage, because this was simply not possible.


But with the proposed backslash escape, the backslash in SQL statements 
passed to the DBI will suddenly have a new meaning, were it is currently 
passed unmodified to the database. This will break old code.


Making the backslash escape special only directly in front of possible 
placeholders will probably break less code, because all other 
backslashes will behave as before. At the same time, the rules when a 
backslash is needed will become more complicated, and they may depend on 
the DBD, because different DBDs implement differrent placeholders (as 
far as I understand DBI).


Also, the rule that a backslash in front of a possible placeholder 
passes the placeholder, but not the backslash, unmodified to the 
database prevents passing a backslash followed by an actual placeholder 
to the database. This is possible with the current DBI code.


So, the backslash-is-only-special-in-front-of-placeholders rule breaks 
some existing code, makes it impossible to have a backslask in front of 
a placeholder, and the rules for when to use a backslash depend on the 
DBD implementation. This will likely lead to another change that will 
again changes the rules and break old code.


Can we do better? I think that we can:

As there is currently no escaping mechanism for placeholders in DBI, any 
new escaping mechanism will break some existing code. Breaking old code 
that uses DBI has happened before, e.g. in  DBI 1.20, 24th August 2001 
(selectall_hashref) DBI 1.19, 20th July 2001 (fetchall_arrayref), DBI 
0.91, 10th December 1997 (connect).


1. Use a clean escaping mechanism that won't need future changes that 
will again break old code:


Make all backslashes in SQL special. Require double backslashes for a 
single backslash at database level. Require escaping characters that 
otherwise might be parsed as placeholders (:, ?, $). Make unknown escape 
sequences fatal errors. This allows mixing placeholders and 
placeholder-like SQL sequences as before, it allows placing backslashes 
in front of placeholders, and it allows future extensions using the 
currently unknown escape sequences.


Existing code just has to double each and every backslash in SQL code.

2. Slowly introduce the new mechanism:

First, the backslash-escape must explicitly be enabled using an 
attribute BackslashEscape during connect(). Default is off, i.e. no 
backslash escaping. No old code should have problems. New code can 
enable backslash-escapes when needed by using connect() with 
BackslashEscape=on.


After a while, change the default to warn, so that backslash escaping 
stays off, but any backslash in SQL statements will issue a 
compatibility warning. Old code will still run unmodified, but will 
likely issue some warnings. Those warnings can be disabled by adding 
BackslashEscape=off to connect().


After some more time, make changing BackslashEscape to off cause a 
compatibility warning. Old unmaintained code will still run unmodified, 
but issue some warnings. Maintained old code that sets BackslashEscape 
to off will issue one warning per connect.


After even more time, change the default to on, so backslash escaping is 
enabled. This will intentionally break old unmaintained code that was 
not modified to switch off BackslashEscape. Old maintained code will 
continue to run, but issue one warning per connect.


Finally, remove the non-backslash-escape code and make swiching to that 
code (off or warn) a fatal error. This will intentionally break old code 
that had a one-time maintainance but was not changed to use backslashes 
properly.


The above is the user view of DBI.

DBI developer view:

As far as I understand the DBI, DBDs may also parse SQL code. They need 
to be changed to respect the BackslashEscape attribute. Using old 

Re: Escaping placeholders

2014-12-21 Thread Tim Bunce
On Sun, Dec 21, 2014 at 10:27:18AM +0100, pe...@vanroose.be wrote:
 On 20.12.2014 15:38, Tim Bunce wrote:
  [...]
  Can you, or anyone else, think of any situation where a backslash before
  a ? or :foo (or even $1) style placeholder might be valid SQL?
 
 Inside quoted text: of course, yes.
 Outside quoted text: maybe some RDBMS accept a backslash as a valid character
 in the name of a table or column? (Haven't tried this out yet.)
 At least make sure \? will not be handled as placeholder inside column name
 quoting, as in e.g.
 foo \? bar

That's standard identifier quoting so should be ignored by the driver
for the same reason that single quoted strings are.

 or in
 [foo \? bar]
 with SQL Server, or
 `foo \? bar`
 for MySQL.

For databases that support those non-standard identifier quoting styles
the driver should be treating them as strings and so skipping them anyway.

 But my fear is that even
 foo\?bar
 would be accepted as valid column or table name by some RDBMS...

I find that very hard to believe without any evidence.
Even if true, the driver for such a database would, I presume,
treat that ? as a placeholder and so it would already be broken.

Tim.


Re: Escaping placeholders

2014-12-21 Thread Greg Sabino Mullane (the tenth man)

-BEGIN PGP SIGNED MESSAGE-
Hash: RIPEMD160


Tim Bunce wrote:

 For code not using DBIx::Class the pg_placeholder_dollaronly attribute
 might work, see https://metacpan.org/pod/DBD::Pg#Placeholders

Yes, this is the current canonical solution. It's a real shame 
that ? was used as an operator, but that horse has left the barn.

 For code using DBIx::Class the problem is more tricky. I'm pretty sure
 that SQL::Abstract and thus DBIx::Class only support question mark
 placeholders. That means it probably impossible to use expressions
 containing a question mark operator with SQL::Abstract/DBIx::Class.
 (Though I'd be delighted to be proven wrong.)
 
 So I think the DBI spec for placeholders needs to be extended to allow a
 way to 'escape' a question mark that the driver would otherwise treat as
 a placeholder.

 The obvious and natural approach would be to use a backslash before a
 question mark. The backslash would be removed by the driver before the
 statement is passed to the backend.

I'm going to play devil's advocate a bit here. There are some problems with 
this approach. First, it will require that the user know if the underlying 
DBD supports backslashes. Which likely means that SQL::Abstract and/or 
DBIx::Class will need to know as well. (Unless they expose the DBD directly 
to the user, which ruins the point a bit). Since we will thus need to patch 
those other modules, so why not fix them to do the right thing? (see below 
for a counter proposal).

Another problem is that we have now extended the SQL syntax for our own 
purposes. While one could argue that placeholders already do so, their 
current use is consistent, widespread (e.g. not just DBI), and in part 
used by the underlying RDBMSs themselves (e.g. Postgres uses dollar-number 
placeholders). So we will have both escaped and unescaped versions of SQL 
floating around, subject to the whims of whether or not your particular 
DBD supports it (and in which version). All of which seems like an awful 
lot of work to fix SQL::Abstract. Why bother patching every DBD in 
existence when we can simply patch SQL::Abstract?

Which leads to my counter-proposal: have SQL::Abstract accept dollar-number 
placeholders. It can pass pg_placeholder_dollaronly down the stack as 
needed. This neatly puts the onus back onto the frameworks, rather than 
having the DBDs selectively remove backslashes before passing to the 
RDBMS (ick). DBIx::Class and friends could even map dollar signs back to 
a format supported by the underlying DBDs, if they don't support dollar 
signs (that is one of their grand purposes after all - abstracting out 
details and taking care of things in the background).

- -- 
Greg Sabino Mullane g...@turnstep.com
PGP Key: 0x14964AC8 201412211008
http://biglumber.com/x/web?pk=2529DF6AB8F79407E94445B4BC9B906714964AC8
-BEGIN PGP SIGNATURE-

iEYEAREDAAYFAlSW5E8ACgkQvJuQZxSWSshusgCfXOIjbJxQAF9s7FJEncDFoBGG
oHgAnjMs9kP/imrZTnknJpUIuXOhmoPL
=FxZ4
-END PGP SIGNATURE-




Re: Escaping placeholders

2014-12-21 Thread Darren Duncan

I agree with Greg's counter-proposal, from which I derive my own words here.

1.  I propose that there be no modification to the DBI spec related to new 
escaping whether optional or not, so leave things the way they are here, SQL 
continues to be interpreted the way it long has by default.


2.  When users want to use operators in PostgreSQL that contain literal ? in 
their names, then they enable DBD::Pg's pg_placeholder_dollaronly so that ? are 
no longer treated as placeholders.  Likewise, pg_placeholder_nocolons can be 
enabled when they don't want literal : to indicate a placeholder either.  Users 
would either do this directly if they're using DBI/DBD::Pg directly, or 
indirectly using their over-top framework of choice.  When users aren't using 
the ? operators et al, they can leave things alone which will work as normal.


3.  SQL::Abstract et al, those tools external to DBI/DBDs, are the correct and 
proper places to modify where users of said want to use the operators with ? 
names and such.  These tools already have special knowledge of individual DBMS 
systems to work with them effectively, and the ? operators is just one more of 
those things.  The users of said tools may have to flip a configuration switch 
possibly so $1 etc are used behind the scenes, if necessary, but that's okay 
because the use of ? operators only happens when the users choose to make a 
change to use them anyway.


In summary, now is not the time or place to be introducing backslashing doubled 
or otherwise in DBI such as discussed, that's a poor solution and its better to 
save such risky/etc changes for when there's a more compelling case for them.


I should also mention I feel it is perfectly reasonable for each DBMS to have 
operators composed of any characters they want where doing so makes sense within 
the context of the SQL/etc itself.  See also that Perl itself has both ? and : 
and etc as operator names, Perl 6 even more so, and I don't see anyone thinking 
that's a bad idea.  So I have no problem with PostgreSQL having ? in operator 
names such as it did.  Its not like the SQL standard reserves ? or whatever for 
prepared statement parameters, that's defined to be implementation dependent I 
believe (WD 9075-2:200w(E) 20.6 prepare statement).


-- Darren Duncan

On 2014-12-21 7:17 AM, Greg Sabino Mullane (the tenth man) wrote:

Tim Bunce wrote:


For code not using DBIx::Class the pg_placeholder_dollaronly attribute
might work, see https://metacpan.org/pod/DBD::Pg#Placeholders


Yes, this is the current canonical solution. It's a real shame
that ? was used as an operator, but that horse has left the barn.


For code using DBIx::Class the problem is more tricky. I'm pretty sure
that SQL::Abstract and thus DBIx::Class only support question mark
placeholders. That means it probably impossible to use expressions
containing a question mark operator with SQL::Abstract/DBIx::Class.
(Though I'd be delighted to be proven wrong.)

So I think the DBI spec for placeholders needs to be extended to allow a
way to 'escape' a question mark that the driver would otherwise treat as
a placeholder.

The obvious and natural approach would be to use a backslash before a
question mark. The backslash would be removed by the driver before the
statement is passed to the backend.


I'm going to play devil's advocate a bit here. There are some problems with
this approach. First, it will require that the user know if the underlying
DBD supports backslashes. Which likely means that SQL::Abstract and/or
DBIx::Class will need to know as well. (Unless they expose the DBD directly
to the user, which ruins the point a bit). Since we will thus need to patch
those other modules, so why not fix them to do the right thing? (see below
for a counter proposal).

Another problem is that we have now extended the SQL syntax for our own
purposes. While one could argue that placeholders already do so, their
current use is consistent, widespread (e.g. not just DBI), and in part
used by the underlying RDBMSs themselves (e.g. Postgres uses dollar-number
placeholders). So we will have both escaped and unescaped versions of SQL
floating around, subject to the whims of whether or not your particular
DBD supports it (and in which version). All of which seems like an awful
lot of work to fix SQL::Abstract. Why bother patching every DBD in
existence when we can simply patch SQL::Abstract?

Which leads to my counter-proposal: have SQL::Abstract accept dollar-number
placeholders. It can pass pg_placeholder_dollaronly down the stack as
needed. This neatly puts the onus back onto the frameworks, rather than
having the DBDs selectively remove backslashes before passing to the
RDBMS (ick). DBIx::Class and friends could even map dollar signs back to
a format supported by the underlying DBDs, if they don't support dollar
signs (that is one of their grand purposes after all - abstracting out
details and taking care of things in the background).




Re: Escaping placeholders

2014-12-20 Thread Tim Bunce
Thanks David :)

Tim.

On Fri, Dec 19, 2014 at 12:23:23PM -0600, David Nicol wrote:
Please disregard my previous. After reading Tim Bunce's earlier response 
 and thinking about this some
more, although backslash escaping can be tricky, that is how Perl does 
 these things, and Perl coders are
familiar with the nuances of when they must be doubled to get through 
 quoting. Doubling of syntax
characters is a database thing, but it would have to be revised for every 
 new escapable character.
Backslash escaping can be embraced once and will continue to work in 
 potentialfutures where other
significant characters (aside from colon and question mark) might need to 
 be escaped too.
On Fri, Dec 19, 2014 at 10:27 AM, David Nicol [1]davidni...@gmail.com 
 wrote:
 
  I think the suggestion of making ::(\w+) become :$1 and exempting that 
 from placeholder recognition
  seems like a complete winner and DBD maintainers could do that right 
 away, and by do that I mean
  accepting, applying, and redistributing patches..
 
 References
 
Visible links
1. mailto:davidni...@gmail.com


Re: Escaping placeholders

2014-12-20 Thread Tim Bunce
On Fri, Dec 19, 2014 at 01:12:16PM +0100, Alexander Foken wrote:
 Hello all,
 
 this reminds me of a similar problem I had in 2000 with DBI,
 DBD::Oracle, and Oracle. See
 http://marc.info/?t=9506395904r=1w=2,
 http://173.79.223.25/?l=dbi-devm=95077716125217w=2.
 
 Problem was using named placeholders (:foo) in DBI and at the same
 time use PL/SQL code containing variables (:bar), DBI considered
 both :foo and :bar to be placeholders instead of leaving :bar
 alone and pass it to Oracle. A set of patches from Michael A. Chase
 allowed disabling parts or all of the placeholder parsing, so using
 unnamed placeholders (?) allowed using PL/SQL variables in SQL
 statements.
 
 But the fundamental problem was not solved, there was and still is
 no way to escape placeholders.

Can you, or anyone else, think of any situation where a backslash before
a ? or :foo (or even $1) style placeholder might be valid SQL?

So far no one has come up with one, so I'm getting more comfortable
with the idea that a backslash before a placeholder is a safe change.
I.e., there's a near-zero risk that upgrading a DBI driver to support
backslashes would cause breakage in existing code.

Tim.


Re: Escaping placeholders

2014-12-20 Thread Alexander Foken

On 20.12.2014 15:38, Tim Bunce wrote:

On Fri, Dec 19, 2014 at 01:12:16PM +0100, Alexander Foken wrote:

Hello all,

this reminds me of a similar problem I had in 2000 with DBI,
DBD::Oracle, and Oracle. See
http://marc.info/?t=9506395904r=1w=2,
http://173.79.223.25/?l=dbi-devm=95077716125217w=2.

Problem was using named placeholders (:foo) in DBI and at the same
time use PL/SQL code containing variables (:bar), DBI considered
both :foo and :bar to be placeholders instead of leaving :bar
alone and pass it to Oracle. A set of patches from Michael A. Chase
allowed disabling parts or all of the placeholder parsing, so using
unnamed placeholders (?) allowed using PL/SQL variables in SQL
statements.

But the fundamental problem was not solved, there was and still is
no way to escape placeholders.

Can you, or anyone else, think of any situation where a backslash before
a ? or :foo (or even $1) style placeholder might be valid SQL?


I found two situations for PostgreSQL:

(1) PostgreSQL allows almost any character as escape character in 
Unicode string constants 
(http://www.postgresql.org/docs/current/static/sql-syntax-lexical.html#SQL-SYNTAX-STRINGS-UESCAPE). 
With that, I can construct  an expression containing \:foo that is valid 
SQL as understood by PostgreSQL:


U'foo\:bar' UESCAPE ':'

This expression represents the string foo\Xbar, where X is the Unicode 
character U+ (TAI VIET LETTER LOW VO).


(2) PostgreSQL also allows Dollar quoting 
(http://www.postgresql.org/docs/current/static/sql-syntax-lexical.html#SQL-SYNTAX-DOLLAR-QUOTING). 
With that, I can construct an expression containing \$1 that is valid 
SQL as understood by PostgreSQL:


$1$foo\$1$

This expression represents the string foo\, quoted by dollar signs using 
the character 1 as tag.





So far no one has come up with one, so I'm getting more comfortable
with the idea that a backslash before a placeholder is a safe change.
I.e., there's a near-zero risk that upgrading a DBI driver to support
backslashes would cause breakage in existing code.


Do you plan to escape the escape character, i.e. use a double backslash 
at DBI level to represent a single backslash at database level?


Alexander



Tim.



--
Alexander Foken
mailto:alexan...@foken.de  http://www.foken.de/alexander/



Re: Escaping placeholders

2014-12-20 Thread Jonathan Leffler
Many, many years ago, DBD::Informix had to give up on the DBI-provided
parsing for placeholders because there were too many contexts in which it
was wrong for Informix.  It may have improved since then, but:

INSERT INTO SomeTable(DateTimeCol)
VALUES(DATETIME(2014-12-31 23:59:59) YEAR TO SECOND);

is valid Informix-dialect SQL with no placeholders whatsoever.  The
Standard SQL notation would be:

VALUES(TIMESTAMP '2014-12-31 23:59:59')

and many systems would likely get away without needing the TIMESTAMP
(automatically coercing the string into the correct type).  Indeed,
Informix accepts the string notation (without the TIMESTAMP prefix), but
the other notation is also valid and therefore DBD::Informix must support
it.  The standard notation avoids problems because the colons are embedded
within strings, whereas the Informix DATETIME literal notation uses
parentheses instead of quotes around what is otherwise effectively a
string.  I could also insert INTERVAL(23 13:45:19) DAY TO SECOND with
similar comments about its behaviour.

Also, Informix uses the notation:

dbase@server:owner.table

for a fully qualified table name, with no placeholders present.  You can
omit the '@server' to reference the current server (hence dbase:owner.table
is valid too); you can omit the 'owner.' if you want to refer to a table
(depending on context) owned by the current user or uniquely named
belonging to an arbitrary user (so dbase:table is valid too).  You can omit
the dbase altogether, but then the colon isn't present and it is no longer
relevant to the handling of placeholders prefixed by colon.  This leads to
the synoptic notation:

[dbase[@server]:][owner.]table

I think I raised this as an issue back in the 1996-1998 timeframe (I said
'many years ago' and meant it).  I'd have to dig through my release notes
to be more precise.  Informix only supports natively the `?` placeholders.
It doesn't yet have the complexities introduced by the PostgreSQL operators.

I don't know whether this can be handled at all.  It may be that
DBD::Informix has to stay out in isolation — but it would be nice if it
wasn't necessary.


On Sat, Dec 20, 2014 at 8:35 AM, Alexander Foken alexan...@foken.de wrote:

 On 20.12.2014 15:38, Tim Bunce wrote:

 On Fri, Dec 19, 2014 at 01:12:16PM +0100, Alexander Foken wrote:

 Hello all,

 this reminds me of a similar problem I had in 2000 with DBI,
 DBD::Oracle, and Oracle. See
 http://marc.info/?t=9506395904r=1w=2,
 http://173.79.223.25/?l=dbi-devm=95077716125217w=2.

 Problem was using named placeholders (:foo) in DBI and at the same
 time use PL/SQL code containing variables (:bar), DBI considered
 both :foo and :bar to be placeholders instead of leaving :bar
 alone and pass it to Oracle. A set of patches from Michael A. Chase
 allowed disabling parts or all of the placeholder parsing, so using
 unnamed placeholders (?) allowed using PL/SQL variables in SQL
 statements.

 But the fundamental problem was not solved, there was and still is
 no way to escape placeholders.

 Can you, or anyone else, think of any situation where a backslash before
 a ? or :foo (or even $1) style placeholder might be valid SQL?


 I found two situations for PostgreSQL:

 (1) PostgreSQL allows almost any character as escape character in Unicode
 string constants (http://www.postgresql.org/docs/current/static/sql-
 syntax-lexical.html#SQL-SYNTAX-STRINGS-UESCAPE). With that, I can
 construct  an expression containing \:foo that is valid SQL as understood
 by PostgreSQL:

 U'foo\:bar' UESCAPE ':'

 This expression represents the string foo\Xbar, where X is the Unicode
 character U+ (TAI VIET LETTER LOW VO).

 (2) PostgreSQL also allows Dollar quoting (http://www.postgresql.org/
 docs/current/static/sql-syntax-lexical.html#SQL-SYNTAX-DOLLAR-QUOTING).
 With that, I can construct an expression containing \$1 that is valid SQL
 as understood by PostgreSQL:

 $1$foo\$1$

 This expression represents the string foo\, quoted by dollar signs using
 the character 1 as tag.



 So far no one has come up with one, so I'm getting more comfortable
 with the idea that a backslash before a placeholder is a safe change.
 I.e., there's a near-zero risk that upgrading a DBI driver to support
 backslashes would cause breakage in existing code.


 Do you plan to escape the escape character, i.e. use a double backslash at
 DBI level to represent a single backslash at database level?

 Alexander



 Tim.



 --
 Alexander Foken
 mailto:alexan...@foken.de  http://www.foken.de/alexander/



-- 
Jonathan Leffler jonathan.leff...@gmail.com  #include disclaimer.h
Guardian of DBD::Informix - v2013.0521 - http://dbi.perl.org
Blessed are we who can laugh at ourselves, for we shall never cease to be
amused.


Re: Escaping placeholders

2014-12-20 Thread Tim Bunce
On Sat, Dec 20, 2014 at 05:35:55PM +0100, Alexander Foken wrote:
 On 20.12.2014 15:38, Tim Bunce wrote:
 Can you, or anyone else, think of any situation where a backslash before
 a ? or :foo (or even $1) style placeholder might be valid SQL?
 
 I found two situations for PostgreSQL:
 
 (1) PostgreSQL allows almost any character as escape character in
 Unicode string constants 
 (http://www.postgresql.org/docs/current/static/sql-syntax-lexical.html#SQL-SYNTAX-STRINGS-UESCAPE).
 With that, I can construct  an expression containing \:foo that is
 valid SQL as understood by PostgreSQL:
 
 U'foo\:bar' UESCAPE ':'
 
 This expression represents the string foo\Xbar, where X is the
 Unicode character U+ (TAI VIET LETTER LOW VO).

I don't think that'll be a problem because the driver code that parses
the statement looking for placeholders will skip over quoted strings.

 (2) PostgreSQL also allows Dollar quoting 
 (http://www.postgresql.org/docs/current/static/sql-syntax-lexical.html#SQL-SYNTAX-DOLLAR-QUOTING).
 With that, I can construct an expression containing \$1 that is
 valid SQL as understood by PostgreSQL:
 
 $1$foo\$1$
 
 This expression represents the string foo\, quoted by dollar signs
 using the character 1 as tag.

I'm not sure if the driver code that parses statements in DBD::Pg
handles dollar quoting. I presume so. In which case this shouldn't be a
problem either for the same reason as above.

 So far no one has come up with one, so I'm getting more comfortable
 with the idea that a backslash before a placeholder is a safe change.
 I.e., there's a near-zero risk that upgrading a DBI driver to support
 backslashes would cause breakage in existing code.
 
 Do you plan to escape the escape character, i.e. use a double
 backslash at DBI level to represent a single backslash at database
 level?

That's a good question. I'm not sure. I think the answer has to be no.
I'd welcome any input on that.

Tim.


Re: Escaping placeholders

2014-12-20 Thread Tim Bunce
On Sat, Dec 20, 2014 at 01:14:29PM -0800, Jonathan Leffler wrote:
Many, many years ago, DBD::Informix had to give up on the DBI-provided 
 parsing for placeholders because
there were too many contexts in which it was wrong for Informix.  It may 
 have improved since then, but:
 
  INSERT INTO SomeTable(DateTimeCol)
VALUES(DATETIME(2014-12-31 23:59:59) YEAR TO SECOND);

I think I raised this as an issue back in the 1996-1998 timeframe (I said 
 'many years ago' and meant
it).  I'd have to dig through my release notes to be more precise.  
 Informix only supports natively the
`?` placeholders.  It doesn't yet have the complexities introduced by the 
 PostgreSQL operators.
 
I don't know whether this can be handled at all.  It may be that 
 DBD::Informix has to stay out in
isolation but it would be nice if it wasn't necessary.

The `?` placeholders are 'standard' (for some definition) so DBD::Informix
isn't really 'in isolation'. There are quite a few drivers that only
support `?` placeholders.

In theory, if this proposal goes ahead, and is applied to `:` placeholders
as seems likely, then you'd be able to write the above as:

   INSERT INTO SomeTable(DateTimeCol)
 VALUES(DATETIME(2014-12-31 23\:59\:59) YEAR TO SECOND);

Tim.


Re: Escaping placeholders

2014-12-20 Thread Jonathan Leffler
Gmail hid the line you gave (as if it was the same as something I'd sent —
curious behaviour by Gmail):

 INSERT INTO SomeTable(DateTimeCol)
 VALUES(DATETIME(2014-12-31 23\:59\:59) YEAR TO SECOND);

I really won't want people have to futz with their legitimate Informix SQL
in order to pass it through DBD::Informix.  Whatever is provided, whether
by DBI or DBD::Informix, must accept the code without the backslashes in
front of the colons.  It is simply not acceptable to have to modify valid
SQL to get it past the gatekeeper code.

At the moment, the unescaped code works fine.  It will continue to work
fine.  As long as DBI does not break the currently working code, I will
survive — like I have for the last decade and more.  Just make sure that
whatever you do does not break working valid Informix SQL code.


On Sat, Dec 20, 2014 at 2:17 PM, Tim Bunce tim.bu...@pobox.com wrote:

 On Sat, Dec 20, 2014 at 01:14:29PM -0800, Jonathan Leffler wrote:
 Many, many years ago, DBD::Informix had to give up on the
 DBI-provided parsing for placeholders because
 there were too many contexts in which it was wrong for Informix.  It
 may have improved since then, but:
 
   INSERT INTO SomeTable(DateTimeCol)
 VALUES(DATETIME(2014-12-31 23:59:59) YEAR TO SECOND);

 I think I raised this as an issue back in the 1996-1998 timeframe (I
 said 'many years ago' and meant
 it).  I'd have to dig through my release notes to be more precise.
 Informix only supports natively the
 `?` placeholders.  It doesn't yet have the complexities introduced by
 the PostgreSQL operators.
 
 I don't know whether this can be handled at all.  It may be that
 DBD::Informix has to stay out in
 isolation but it would be nice if it wasn't necessary.

 The `?` placeholders are 'standard' (for some definition) so DBD::Informix
 isn't really 'in isolation'. There are quite a few drivers that only
 support `?` placeholders.

 In theory, if this proposal goes ahead, and is applied to `:` placeholders
 as seems likely, then you'd be able to write the above as:

INSERT INTO SomeTable(DateTimeCol)
  VALUES(DATETIME(2014-12-31 23\:59\:59) YEAR TO SECOND);

 Tim.



-- 
Jonathan Leffler jonathan.leff...@gmail.com  #include disclaimer.h
Guardian of DBD::Informix - v2013.0521 - http://dbi.perl.org
Blessed are we who can laugh at ourselves, for we shall never cease to be
amused.


Escaping placeholders (was: [Dbix-class] Using Postgres JSONB operators in queries)

2014-12-19 Thread Tim Bunce
Hello Augustus.

On Thu, Dec 04, 2014 at 03:38:14PM -0800, Augustus Saunders wrote:
Hi all, I have been unable to find a way to use some of the new
JSONB operators in Postgres 9.4 with DBIx::Class. A quick search
for JSONB on the email archive site didn't turn up any results, so
I thought I would ask.

In particular, ?, ?, and ?| are now operators, and we run into
problems with the DBI placeholder being ?.

As more people start using Postgres 9.4 and the JSON operators this
is going to become a significant problem.

I read that putting single quotes around the question mark would
allow a literal question mark in DBI, but I can't seem to make this
work from DBIx::Class.

It won't do what you want. Question marks in quotes are ignored by the
DBI driver, but question marks in quotes won't work as JSON operators.

Can anybody tell me whether this is currently possible, if so how,
and if not what might be involved or where in the code to look?

For code not using DBIx::Class the pg_placeholder_dollaronly attribute
might work, see https://metacpan.org/pod/DBD::Pg#Placeholders

For code using DBIx::Class the problem is more tricky. I'm pretty sure
that SQL::Abstract and thus DBIx::Class only support question mark
placeholders. That means it probably impossible to use expressions
containing a question mark operator with SQL::Abstract/DBIx::Class.
(Though I'd be delighted to be proven wrong.)

So I think the DBI spec for placeholders needs to be extended to allow a
way to 'escape' a question mark that the driver would otherwise treat as
a placeholder.

The obvious and natural approach would be to use a backslash before a
question mark. The backslash would be removed by the driver before the
statement is passed to the backend.

  $dbh-selectrow_array(q{ SELECT {a:1, b:2}'::jsonb  ? 'b' }); # breaks
  $dbh-selectrow_array(q{ SELECT {a:1, b:2}'::jsonb \? 'b' }); # would work

The key question is: what is the risk of any existing DBI SQL statements
containing a question mark placeholder that's preceeded by a backslash?

Can anyone think of realistic examples? (For ANY DBI driver or backend.)

Tim.


Re: Escaping placeholders

2014-12-19 Thread Alexander Foken

Hello all,

this reminds me of a similar problem I had in 2000 with DBI, 
DBD::Oracle, and Oracle. See 
http://marc.info/?t=9506395904r=1w=2, 
http://173.79.223.25/?l=dbi-devm=95077716125217w=2.


Problem was using named placeholders (:foo) in DBI and at the same 
time use PL/SQL code containing variables (:bar), DBI considered both 
:foo and :bar to be placeholders instead of leaving :bar alone and 
pass it to Oracle. A set of patches from Michael A. Chase allowed 
disabling parts or all of the placeholder parsing, so using unnamed 
placeholders (?) allowed using PL/SQL variables in SQL statements.


But the fundamental problem was not solved, there was and still is no 
way to escape placeholders.


I think being able to escape placeholders (both unnamed AND named ones) 
would help. A backslash seems reasonable, but doubling the question mark 
resp. the colon works with single and double quoting, you don't have to 
think about escaping backslashes in double quoted strings. And with 
doubling, you don't need to quote backslashes.


My ancient problem could have been solved by simply replacing every 
colon in the PL/SQL code with either a backslash and a colon or two colons.


Alexander


On 19.12.2014 11:40, Tim Bunce wrote:

Hello Augustus.

On Thu, Dec 04, 2014 at 03:38:14PM -0800, Augustus Saunders wrote:

Hi all, I have been unable to find a way to use some of the new
JSONB operators in Postgres 9.4 with DBIx::Class. A quick search
for JSONB on the email archive site didn't turn up any results, so
I thought I would ask.

In particular, ?, ?, and ?| are now operators, and we run into
problems with the DBI placeholder being ?.

As more people start using Postgres 9.4 and the JSON operators this
is going to become a significant problem.


I read that putting single quotes around the question mark would
allow a literal question mark in DBI, but I can't seem to make this
work from DBIx::Class.

It won't do what you want. Question marks in quotes are ignored by the
DBI driver, but question marks in quotes won't work as JSON operators.


Can anybody tell me whether this is currently possible, if so how,
and if not what might be involved or where in the code to look?

For code not using DBIx::Class the pg_placeholder_dollaronly attribute
might work, see https://metacpan.org/pod/DBD::Pg#Placeholders

For code using DBIx::Class the problem is more tricky. I'm pretty sure
that SQL::Abstract and thus DBIx::Class only support question mark
placeholders. That means it probably impossible to use expressions
containing a question mark operator with SQL::Abstract/DBIx::Class.
(Though I'd be delighted to be proven wrong.)

So I think the DBI spec for placeholders needs to be extended to allow a
way to 'escape' a question mark that the driver would otherwise treat as
a placeholder.

The obvious and natural approach would be to use a backslash before a
question mark. The backslash would be removed by the driver before the
statement is passed to the backend.

   $dbh-selectrow_array(q{ SELECT {a:1, b:2}'::jsonb  ? 'b' }); # breaks
   $dbh-selectrow_array(q{ SELECT {a:1, b:2}'::jsonb \? 'b' }); # would 
work

The key question is: what is the risk of any existing DBI SQL statements
containing a question mark placeholder that's preceeded by a backslash?

Can anyone think of realistic examples? (For ANY DBI driver or backend.)

Tim.



--
Alexander Foken
mailto:alexan...@foken.de  http://www.foken.de/alexander/



Re: Escaping placeholders

2014-12-19 Thread David Nicol
On Fri, Dec 19, 2014 at 6:12 AM, Alexander Foken alexan...@foken.de wrote:


 Problem was using named placeholders (:foo) in DBI and at the same time
 use PL/SQL code containing variables (:bar), DBI considered both :foo
 and :bar to be placeholders instead of leaving :bar alone and pass it
 to Oracle.


But the fundamental problem was not solved, there was and still is no way
 to escape placeholders.


I think the suggestion of making ::(\w+) become :$1 and exempting that from
placeholder recognition seems like a complete winner and DBD maintainers
could do that right away, and by do that I mean accepting, applying, and
redistributing patches..


Re: Escaping placeholders

2014-12-19 Thread David Nicol
Please disregard my previous. After reading Tim Bunce's earlier response
and thinking about this some more, although backslash escaping can be
tricky, that is how Perl does these things, and Perl coders are familiar
with the nuances of when they must be doubled to get through quoting.
Doubling of syntax characters is a database thing, but it would have to be
revised for every new escapable character. Backslash escaping can be
embraced once and will continue to work in potentialfutures where other
significant characters (aside from colon and question mark) might need to
be escaped too.

On Fri, Dec 19, 2014 at 10:27 AM, David Nicol davidni...@gmail.com wrote:



 I think the suggestion of making ::(\w+) become :$1 and exempting that
 from placeholder recognition seems like a complete winner and DBD
 maintainers could do that right away, and by do that I mean accepting,
 applying, and redistributing patches..