I've recently started using web2py with some legacy databases (no id
field so no DAL) and would like to offer a patch to gluon/sql.py

1) Adjusts the SQLite connection to use sqlite3.ROW so that the
results of queries run with db.executesql (or my executesql2 below)
can be referred to by field name instead of just index.  This lets you
say something like this in your views:

{{for row in results:}}
{{=row['first_name']}} {{=row['last_name']}}
{{pass}}

instead of having to use the less readable

{{for row in results:}}
{{=row[0]}} {{=row[1]}}
{{pass}}

2) Create an alternate executesql2 function that allows custom sql to
be used in conjunction with placeholders. This way you don't have to
worry as much about escaping variables you're using in your query
(avoids sql injections).

With the new function, a third "args" parameter has been added. This
can be either a dictionary or list.

In your controller:

#passing a dictionary (works with SQLite but not MS SQL Server)
results = db.executesql2("""SELECT firstname, lastname, birthdate FROM
person WHERE birthdate < :date AND first_name == :name""",dict(name =
"Fred", date = "2009-01-01"))

#passing a list (works with SQLite and MS SQL Server, possibly others)
results = db.executesql2("""SELECT firstname, lastname, birthdate FROM
person WHERE birthdate < ? AND first_name == ?""", ("Fred",
"2009-01-01"))

In the view:

<p>Results returned from SQLite</p>
{{for row in results:}}
{{=row['first_name']}} {{=row['last_name']}}
{{pass}}

<p>Results returned from MS SQL</p>
{{for row in results:}}
{{=row.first_name}} {{=row.last_name}}
{{pass}}


Here's the patch against the devel bzr branch.

=== modified file 'gluon/sql.py'
--- gluon/sql.py        2009-07-14 13:49:44 +0000
+++ gluon/sql.py        2009-07-17 01:47:13 +0000
@@ -699,6 +699,8 @@
                                            check_same_thread=False))
             self._connection.create_function('web2py_extract', 2,
                                              sqlite3_web2py_extract)
+            #make it so we can get results as a dictionary when using
executesql
+            self._connection.row_factory = sqlite3.Row
             self._cursor = self._connection.cursor()
             self._execute = lambda *a, **b: self._cursor.execute(*a,
**b)
         elif self._uri[:8] == 'mysql://':
@@ -1027,6 +1029,14 @@
             return self._cursor.fetchall()
         except:
             return None
+
+    def executesql2(self, query, args):
+        self['_lastsql'] = query+"  with "+str(args)
+        self._execute(query, args)
+        try:
+            return self._cursor.fetchall()
+        except:
+            return None

     def _update_referenced_by(self, other):
         for tablename in self.tables:


These changes make working with non-DAL compliant legacy databases in
web2py a bit easier and do not appear to hinder the normal use of DAL.
I've tested with SQLite and MS SQL Server, but it may also work with
other databases (PostgreSQL, Oracle?)

~Brian

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"web2py Web Framework" group.
To post to this group, send email to web2py@googlegroups.com
To unsubscribe from this group, send email to 
web2py+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/web2py?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to