Ah - thanks. I had a poke around in django/core/meta/__init__.py, but
managed to miss the definition of quote_only_if_word. Your reply was
just enough to point me in the right direction.

I've put together a patch that uses smart quoting for the tables
clause. It's submitted as ticket #967.

However, in looking at the code for function_get_sql_clause() and
working up the patch, something occurred to me. This quoting fix could
go a lot further.

The purpose of the function_get_sql_clause() is to turn a kwargs
dictionary into an SQL query. At the moment, the assumption is that all
the kwargs keys (select, tables, etc) are tied to lists or dictionaries
that contain strings. If the string is a table/column name, it is
quoted; otherwise, it has a space in it, it gets used verbatim where a
single table/column name would be valid - so if your string is a block
of SQL, you can get better results. The purpose of quote_only_if_word
is to protect these potentially useful SQL statements.

It occurred to me that you should be able to modify
quote_only_if_word() to use function_get_sql_clause() recursively. If
you provide a string to quote_only_if_word(), then insert it (either
quoted or verbatim). However, if you find a tuple, then use its values
as the values for opts and kwargs in a recursive call to
function_get_sql_clause(). The recursive call returns a string, which
can get inserted as required. This would allow you to build almost
arbitrarily complex nested SQL queries using Django DB syntax.

For example, the example for the 'select' keyword in the database model
documentation would no longer need the inner SQL clause - it would
become something like :

polls.get_list(
    select={
        'choice_count': {
            db_table='choices',
            db_columns=['COUNT(*)']
            kwargs={
                where=['poll_id=polls.id']
            }
        }
    }
)

I'm not completely happy with the syntax for
db_table/db_columns/kwargs. I'm open to suggestions.

Am I on to a good idea, or have I missed something?

Russ %-)

Reply via email to