Re: :PgSQL: More Queestions - Mailing list pgsql-interfaces

From Jeff Urlwin
Subject Re: :PgSQL: More Queestions
Date
Msg-id OEEMJFLOJPABMFADAPIKKECEEDAA.jurlwin@bellatlantic.net
Whole thread Raw
In response to Re: :PgSQL: More Queestions  (David Wheeler <david@wheeler.net>)
List pgsql-interfaces
>
>
> On Tuesday, November 19, 2002, at 03:42  PM, Jeff Urlwin wrote:
>
> > You probably only need dTHR to support older, pre-threading perls.  I
> > don't
> > believe you need the #ifdef, but it can't hurt (except visually in your
> > code).
>
> Okay. What is it?

See the other posts.  They did a better job of describing it.

>
> > In the preparse(), we're looking for placeholders to notify DBI that
> > we need
> > specific parameters to execute the query and, in the case of DBD::ODBC,
> > later notify the ODBC Driver that we are binding parameters (and what
> > type
> > they are, VARCHAR, etc).  Then the Driver does the binding in whatever
> > DBMS
> > specific way it needs to.  You may have to do more, as you *are* the
> > driver.
> > Note that there is also a way in DBD::ODBC to ignore :foo style
> > parameters
> > because some databases use that for syntax in stored procedures or
> > triggers.
> > For example, with Oracle a trigger can access :old.column_name or
> > :new.column_name and DBD::ODBC allows you to turn off treating
> > :anything as
> > a bind variable to support that.  You may not need that...
>
> I understand that the goal is to convert the placeholders from '?' or
> ':nn' to the PostgreSQL internal version (':pn'). What I'm referring to
> specifically, however, is this snippet from DBD::Pg:
>
>          if (in_literal) {
>              /* Check if literal ends but keep quotes in literal */
>              if (*src == in_literal) {
>                  int bs = 0;
>                  char *str;
>                  str = src-1; /* Back a character. */
>                  while (*(str - bs) == '\\')
>                      bs++;
>                  if (!(bs & 1))
>                      /* bs is an even number? */
>                      in_literal = 0;
>              }
>              *dest++ = *src++;
>              continue;
>          }
>
> in_literal is set when the last character wasn't a placeholder
> character ('?' or ':') and is either a single or a double quotation
> mark. So while I understand that one might want to ignore placeholder
> characters, I don't really understand what the above code is doing.
> Probably'll be easier for me after I've been looking a C for a while...

I'm not sure what it's really trying to do, either, really...

>
> Maybe it's just too complex, because, looking at DBD::ODBC's
> dbd_preparse(), the handling of literals in the query seems a good deal
> more straight-forward (though it doesn't appear to handle '\'' or "\""
> -- am I reading that right?

Nope, it handles " or '.
if (*src == '"' || *src == '\'') {    etc...}
>
> > It's going to depend upon what you need to handle.  For the most part,
> > it
> > shouldn't change after the prepare, but in DBD::ODBC, for example,
> > it's more
> > complex because some statements can return multiple result sets.
>
> Ah, that makes sense. Not sure if it's an issue for PostgreSQL, but I
> doesn't appear to be much of an overhead to set it on a per-execute
> basis...

Actually, if you can get away with doing it only once, the first execute, go
with it.  DBD::ODBC tries to do that, but rechecks under two conditions:1) we "know" there are multiple result sets in
thisquery via already
 
experiencing it2) the user sets a DBD::ODBC private attributed to recheck the result set
types (this is to support nasty things like stored procedures returning only
one result set per call, but a different result set based upon the input
(yes, I've seen this!).

My advice: if you don't have to support multiple result sets, do it once per
execute.  If you setup that "flag" to avoid re-doing work and find that you
need to support multiple-result sets, you can always clear the flag...

>
> > svp is a temporary reference to obtain a pointer to a scalar value
> > (scalar
> > value pointer).  You are then casting it to a pointer to a phs_t, which
> > holds your parameter information.  You'll "create" the phs_t instances
> > when
> > you preparse the query.  In DBD::ODBC, the ftype is queried from the
> > driver
> > itself (may go back to the database for information) to determine if
> > it's
> > numeric, varchar, etc.  The phs_t instance can hold whatever you need
> > to
> > track the parameter (type, scale, etc).  Some drivers assume
> > everything is a
> > varchar and the database itself performs the conversion.
> >
> > So: all_params_hv is in your statement handle and you actually put the
> > information in the all_params_hv hash when you preparse the statement
> > (and
> > update it during execute/bind_param).  Each "phs_t" represents a
> > parameter
> > in the query.  The information contained in the phs_t instance comes
> > from
> > your parsing the query and, possibly querying the database to
> > determine the
> > type of the parameter.
> >
> > Also, the all_params_hv is handy in handling the relatively new DBI
> > attribute ParamValues...
>
> Yes, thank you. I'm spending a lot of time right now just studying the
> code in dbd_preparse() and dbd_st_execute() in both DBD::Pg and
> DBD::ODBC. I think I'll keep at it until I feel I understand it as well
> as I can, and then post my thoughts on what to do next.

I would make the statement that DBD::Oracle may provide a better reference
on the pre-parse stuff.  DBD::ODBC's is probably a bit watered down from
DBD::Oracle -- especially because I'm avoiding comments.

Regards,

Jeff




pgsql-interfaces by date:

Previous
From: Rudy Lippan
Date:
Subject: Re: :PgSQL: More Queestions
Next
From: "Peter Haworth"
Date:
Subject: Re: DBD::PostgreSQL