diff options
| author | Jacob Kaplan-Moss <jacob@jacobian.org> | 2009-12-20 02:46:58 +0000 |
|---|---|---|
| committer | Jacob Kaplan-Moss <jacob@jacobian.org> | 2009-12-20 02:46:58 +0000 |
| commit | 20ad30713e1162b26a62920d06a4beb3f3b678d9 (patch) | |
| tree | 7484a65e3de932bfdefc3925371e59ad12ac9363 /django/db/models/sql | |
| parent | 25ab93457c2c294420fa50302834f3623200b690 (diff) | |
Fixed #11863: added a `Model.objects.raw()` method for executing raw SQL queries and yield models.
See `docs/topics/db/raw.txt` for details.
Thanks to seanoc for getting the ball rolling, and to Russ for wrapping things up.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@11921 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django/db/models/sql')
| -rw-r--r-- | django/db/models/sql/query.py | 39 |
1 files changed, 37 insertions, 2 deletions
diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index f3e24ed8ee..9ecf273be3 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -15,7 +15,7 @@ from django.db.backends.util import truncate_name from django.db import connection from django.db.models import signals from django.db.models.fields import FieldDoesNotExist -from django.db.models.query_utils import select_related_descend +from django.db.models.query_utils import select_related_descend, InvalidQuery from django.db.models.sql import aggregates as base_aggregates_module from django.db.models.sql.expressions import SQLEvaluator from django.db.models.sql.where import WhereNode, Constraint, EverythingNode, AND, OR @@ -23,7 +23,42 @@ from django.core.exceptions import FieldError from datastructures import EmptyResultSet, Empty, MultiJoin from constants import * -__all__ = ['Query', 'BaseQuery'] +__all__ = ['Query', 'BaseQuery', 'RawQuery'] + +class RawQuery(object): + """ + A single raw SQL query + """ + + def __init__(self, sql, connection, params=None): + self.validate_sql(sql) + self.params = params or () + self.sql = sql + self.connection = connection + self.cursor = None + + def get_columns(self): + if self.cursor is None: + self._execute_query() + return [column_meta[0] for column_meta in self.cursor.description] + + def validate_sql(self, sql): + if not sql.lower().strip().startswith('select'): + raise InvalidQuery('Raw queries are limited to SELECT queries. Use ' + 'connection.cursor directly for types of queries.') + + def __iter__(self): + # Always execute a new query for a new iterator. + # This could be optomized with a cache at the expense of RAM. + self._execute_query() + return self.cursor + + def __repr__(self): + return "<RawQuery: %r>" % (self.sql % self.params) + + def _execute_query(self): + self.cursor = self.connection.cursor() + self.cursor.execute(self.sql, self.params) class BaseQuery(object): """ |
