Re: Placeholders and/or Quoting in CLSQL

Shlomi Fish <shlomif-ik1l9ssToec+JF/[email protected]> Thu, 28 Dec 2006 15:56:36 +0200
Newsgroups gmane.lisp.clsql.general,gmane.lisp.clsql.devel
Message-ID <[email protected]>
Hi!

Thanks for your reply.

On Thursday 28 December 2006 01:26, Edi Weitz wrote:
> On Fri, 22 Dec 2006 11:33:35 +0200, Shlomi Fish <shlomif-ik1l9ssToec+JF/[email protected]> wrote:
> > I'm trying to translate the following Amarok script I wrote in Perl
> > into Lisp:
> >
> > http://www.kde-apps.org/content/show.php?content=49151
>
> What is an "Anorak script"?  

Amarok is a music player for the KDE environment:

http://amarok.kde.org/

An Amarok script receives input from Amarok representing events (such as a 
song change, or a volume change), and can be used to customise it by reacting 
to these events. See:

http://amarok.kde.org/wiki/Scripts

> From your code below it looks like you're 
> always calling SBCL from the shell with the --eval option.  That
> doesn't look like a good idea to me - it's definitely not how you
> typically work in Lisp.
>

Well, actually I'm using the "--load" parameter. But you're right. I'd like to 
know a way in which I can tell SBCL to execute a Lisp script and to then 
terminate. This is similar to doing "perl myscript.pl" from the command line. 
And a good idea would also be to find a way to lose all the unnecessary 
information messages that SBCL emits.

> > Now in the script I used SQL with placeholders:
> >
> > <<<<<<<<
> > $statement = $dbh->prepare("SELECT * FROM people WHERE first_name = ?");
> >
> > $results = $statement->execute("Natan");
> >
> >
> > However, I'm unable to find anything similar in CLSQL. Is there
> > anything like that?
>
> There's PREPARE-SQL and friends for databases like PostgreSQL which
> support prepared statements.  (See doc/ref-prepared.xml which for
> reasons unknown to me isn't part of the released documentation.)  This
> is different from Perl's prepare, though, which is (IIRC) about
> preparation on the Perl side and not necessarily on the database side.
>

Thanks!

I assume that what you mean is that if the database backend doesn't support 
prepared statements, then PREPARE-SQL and friends are not available. For the 
record, Perl's DBI's prepare does make use of such a facility in the database 
if it's available, but can also emulate it in the Perl level, if it's not.

> If you're looking for a way to create SQL statements without thinking
> about quoting look at the symbolic SQL syntax:
>
>   http://clsql.b9.com/manual/ref-syntax.html
>   http://www.lispworks.com/documentation/lw50/LWUG/html/lwuser-276.htm
>  
> http://www.lispworks.com/documentation/sql-tutorial/index.html#section-4.1
>

I've looked at the CLSQL:SQL function from the first link, but as I 
demonstrated below, it didn't work.

> > An alternative would be to quote the values into SQL strings using
> > the database-safe quoting mechanism. From what I understood from the
> > documentation, that's what the (clsql:sql) function does. However,
> > the following code:
> >
> > <<<<<<<<<<<<
> > (require 'clsql)
> >
> > (let*
> >   (
> >    (db
> > (clsql:connect
> > '("/home/shlomi/.kde/share/apps/amarok/scripts-data/per-song-volume.sqlit
> >e")
> >
> >                 :database-type :sqlite3)
> >
> >        ))
> >   (print db)
> >   (print (clsql:query "SELECT path, volume FROM songs_volumes" :database
> > db :field-names nil))
> >   (print (clsql:sql :database db "Hello 'Hi Ho ' Please ' Got"))
> >   )
>
> Aside: You should seriously consider to format your Lisp code like
> everybody else does.  Code written in your style won't work with Lisp
> IDEs like SLIME and it looks butt-ugly to experienced Lispers and will
> thus reduce their willingness to help you.  

I Formatted it as best as I could at the time, but I now see several problems 
with it.

> Look for example here: 
>
>   http://www.lisp.org/table/style.htm   [see "Use whitespace
> appropriately"] http://norvig.com/luv-slides.ps
>

OK.

> > generates the following error:
> >
> > <<<<<<<<<<<
> > debugger invoked on a SIMPLE-ERROR:
> >   Error during processing of --eval option (LOAD #P"db2.lisp"):
> >
> >   A CLSQL lisp code error occurred: No type conversion to SQL for
> > SQLITE3-DATABASE is defined for DB NULL.
>
> That's because of the second argument (DB) you fed into the SQL
> function.  You probably thought that you're supposed to provide a
> keyword argument (which makes sense, see below), but you aren't.
>
> Try this instead:
>
>   (clsql:sql "Hello 'Hi Ho ' Please ' Got")
>

This should work, but what if databases differ in their quoting syntax? I'd 
like to get a way to make a backend-specific quoting.

> > Which means I cannot quote according to a database handle. On the
> > other hand the following code:
> >
> > <<<<<<<<<<<<
> > (require 'clsql)
> >
> > (let*
> >   (
> >    (db
> > (clsql:connect
> > '("/home/shlomi/.kde/share/apps/amarok/scripts-data/per-song-volume.sqlit
> >e")
> >
> >                 :database-type :sqlite3)
> >
> >        ))
> >   (print db)
> >   (print (clsql:query "SELECT path, volume FROM songs_volumes" :database
> > db :field-names nil))
> >   (print (clsql:sql "Hello \\'Hi Ho \\' Please ' Got"))
> >   )
> >
> >
> > Generates the following error at (clsql:sql):
> >
> > <<<<<<<<<
> > debugger invoked on a SIMPLE-ERROR:
> >   Error during processing of --eval option (LOAD #P"db2.lisp"):
> >
> >   There is no applicable method for the generic function
> >     #<STANDARD-GENERIC-FUNCTION CLSQL-SYS:DATABASE-TYPE (2)>
> >   when called with arguments
> >     (NIL).
> >
> >
> > So it seems I cannot use the cl:sql function with backslashes (which
> > I may need).
>
> Looks like the SQL function as it is now is bogus because it really
> doesn't make much sense without specifying a database.  Below is a
> patch which tries to at least use the default database (so it should
> work in your case), but I think the SQL function itself should be
> changed.
>

OK. Does it mean that if I do (clsql:sql "My string" my-database-handle), it 
will work?

Regards,

	Shlomi Fish

> HTH,
> Edi.
>
>
>
> --- clsql-3.7.8/sql/expressions.lisp.orig       2006-12-27
> 23:51:31.000000000 +0100 +++ clsql-3.7.8/sql/expressions.lisp    2006-12-27
> 23:54:33.000000000 +0100 @@ -22,7 +22,7 @@
>  (defvar *sql-stream* nil
>    "stream which accumulates SQL output")
>
> -(defun sql-output (sql-expr &optional database)
> +(defun sql-output (sql-expr &optional (database *default-database*))
>    "Top-level call for generating SQL strings. Returns an SQL
>    string appropriate for DATABASE which corresponds to the
>    supplied lisp expression SQL-EXPR."

---------------------------------------------------------------------
Shlomi Fish      shlomif-ik1l9ssToec+JF/[email protected]
Homepage:        http://www.shlomifish.org/

Chuck Norris wrote a complete Perl 6 implementation in a day but then
destroyed all evidence with his bare hands, so no one will know his secrets.