Last active
August 29, 2015 14:12
-
-
Save jarshwah/35adcc1916216aecfd38 to your computer and use it in GitHub Desktop.
oracle fix notes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/django/db/backends/oracle/compiler.py b/django/db/backends/oracle/compiler.py | |
index cfc8a08..12d9ad6 100644 | |
--- a/django/db/backends/oracle/compiler.py | |
+++ b/django/db/backends/oracle/compiler.py | |
@@ -20,12 +20,12 @@ class SQLCompiler(compiler.SQLCompiler): | |
do_offset = with_limits and (self.query.high_mark is not None | |
or self.query.low_mark) | |
if not do_offset: | |
- sql, params = super(SQLCompiler, self).as_sql(with_limits=False, | |
- with_col_aliases=with_col_aliases) | |
+ sql, params = super(SQLCompiler, self).as_sql( | |
+ with_limits=False, with_col_aliases=with_col_aliases) | |
else: | |
- sql, params = super(SQLCompiler, self).as_sql(with_limits=False, | |
- with_col_aliases=True) | |
- | |
+ print ('with_aliases!') | |
+ sql, params = super(SQLCompiler, self).as_sql( | |
+ with_limits=False, with_col_aliases=True) | |
# Wrap the base query in an outer SELECT * with boundaries on | |
# the "_RN" column. This is the canonical way to emulate LIMIT | |
# and OFFSET on Oracle. | |
@@ -36,7 +36,7 @@ class SQLCompiler(compiler.SQLCompiler): | |
'SELECT * FROM (SELECT "_SUB".*, ROWNUM AS "_RN" FROM (%s) ' | |
'"_SUB" %s) WHERE "_RN" > %d' % (sql, high_where, self.query.low_mark) | |
) | |
- | |
+ print (sql) | |
return sql, params | |
diff --git a/django/db/models/expressions.py b/django/db/models/expressions.py | |
index a0d60f1..b1128ed 100644 | |
--- a/django/db/models/expressions.py | |
+++ b/django/db/models/expressions.py | |
@@ -526,14 +526,16 @@ class ColIndexRef(ExpressionNode): | |
class Col(ExpressionNode): | |
- def __init__(self, alias, target, source=None): | |
+ def __init__(self, alias, target, source=None, column_alias=None): | |
if source is None: | |
source = target | |
super(Col, self).__init__(output_field=source) | |
- self.alias, self.target = alias, target | |
+ self.alias, self.target, self.column_alias = alias, target, column_alias | |
def as_sql(self, compiler, connection): | |
qn = compiler.quote_name_unless_alias | |
+ #if self.column_alias is not None: | |
+ # return "%s.%s AS %s" % (qn(self.alias), qn(self.target.column), self.column_alias), [] | |
return "%s.%s" % (qn(self.alias), qn(self.target.column)), [] | |
def relabeled_clone(self, relabels): | |
diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py | |
index cdfd1b7..bcc6c08 100644 | |
--- a/django/db/models/fields/__init__.py | |
+++ b/django/db/models/fields/__init__.py | |
@@ -292,12 +292,12 @@ class Field(RegisterLookupMixin): | |
def _check_backend_specific_checks(self, **kwargs): | |
return connection.validation.check_field(self, **kwargs) | |
- def get_col(self, alias, source=None): | |
+ def get_col(self, alias, source=None, column_alias=None): | |
if source is None: | |
source = self | |
- if alias != self.model._meta.db_table or source != self: | |
+ if alias != self.model._meta.db_table or source != self or column_alias is not None: | |
from django.db.models.expressions import Col | |
- return Col(alias, self, source) | |
+ return Col(alias, self, source, column_alias) | |
else: | |
return self.cached_col | |
diff --git a/django/db/models/query.py b/django/db/models/query.py | |
index de2279a..e373f94 100644 | |
--- a/django/db/models/query.py | |
+++ b/django/db/models/query.py | |
@@ -237,8 +237,8 @@ class QuerySet(object): | |
# Execute the query. This will also fill compiler.select, klass_info and | |
# annotations. | |
results = compiler.execute_sql() | |
- select, klass_info, annotation_col_map = (compiler.select, compiler.klass_info, | |
- compiler.annotation_col_map) | |
+ select, klass_info, annotation_col_map = ( | |
+ compiler.select, compiler.klass_info, compiler.annotation_col_map) | |
if klass_info is None: | |
return | |
model_cls = klass_info['model'] | |
diff --git a/django/db/models/sql/compiler.py b/django/db/models/sql/compiler.py | |
index e590f3b..2218bef 100644 | |
--- a/django/db/models/sql/compiler.py | |
+++ b/django/db/models/sql/compiler.py | |
@@ -29,19 +29,19 @@ class SQLCompiler(object): | |
self.annotation_col_map = None | |
self.klass_info = None | |
- def setup_query(self): | |
+ def setup_query(self, with_col_aliases=False): | |
if all(self.query.alias_refcount[a] == 0 for a in self.query.tables): | |
self.query.get_initial_alias() | |
- self.select, self.klass_info, self.annotation_col_map = self.get_select() | |
+ self.select, self.klass_info, self.annotation_col_map = self.get_select(with_col_aliases=with_col_aliases) | |
self.col_count = len(self.select) | |
- def pre_sql_setup(self): | |
+ def pre_sql_setup(self, with_col_aliases=False): | |
""" | |
Does any necessary class setup immediately prior to producing SQL. This | |
is for things that can't necessarily be done in __init__ because we | |
might not have all the pieces in place at that time. | |
""" | |
- self.setup_query() | |
+ self.setup_query(with_col_aliases=with_col_aliases) | |
order_by = self.get_order_by() | |
extra_select = self.get_extra_select(order_by, self.select) | |
group_by = self.get_group_by(self.select + extra_select, order_by) | |
@@ -145,7 +145,7 @@ class SQLCompiler(object): | |
expressions = [pk] + [expr for expr in expressions if expr in having] | |
return expressions | |
- def get_select(self): | |
+ def get_select(self, with_col_aliases=False): | |
""" | |
Returns a list of 3-tuples of (expression, (sql, params), alias), a klass_info | |
structure and annotations found. | |
@@ -172,9 +172,9 @@ class SQLCompiler(object): | |
assert not (self.query.select and self.query.default_cols) | |
if self.query.default_cols: | |
select_list = [] | |
- for c in self.get_default_columns(): | |
+ for c in self.get_default_columns(with_col_aliases=with_col_aliases): | |
select_list.append(select_idx) | |
- select.append((c, None)) | |
+ select.append((c, c.column_alias)) | |
select_idx += 1 | |
klass_info = { | |
'model': self.query.model, | |
@@ -183,7 +183,7 @@ class SQLCompiler(object): | |
# self.query.select is a special case. These columns never go to | |
# any model. | |
for col in self.query.select: | |
- select.append((col, None)) | |
+ select.append((col, col.column_alias)) | |
select_idx += 1 | |
for alias, annotation in self.query.annotation_select.items(): | |
annotations[alias] = select_idx | |
@@ -191,7 +191,7 @@ class SQLCompiler(object): | |
select_idx += 1 | |
if self.query.select_related: | |
- related_klass_infos = self.get_related_selections(select) | |
+ related_klass_infos = self.get_related_selections(select, with_col_aliases=with_col_aliases) | |
klass_info['related_klass_infos'] = related_klass_infos | |
def get_select_from_parent(klass_info): | |
@@ -327,6 +327,10 @@ class SQLCompiler(object): | |
If 'with_limits' is False, any limit/offset information is not included | |
in the query. | |
""" | |
+ # don't bother setting up the query if the limit is a no-op. | |
+ if with_limits and self.query.low_mark == self.query.high_mark: | |
+ return '', () | |
+ | |
# After executing the query, we must get rid of any joins the query | |
# setup created. So, take note of alias counts before the query ran. | |
# However we do not want to get rid of stuff done in pre_sql_setup(), | |
@@ -334,9 +338,7 @@ class SQLCompiler(object): | |
# another run of it. | |
refcounts_before = self.query.alias_refcount.copy() | |
try: | |
- extra_select, order_by, group_by = self.pre_sql_setup() | |
- if with_limits and self.query.low_mark == self.query.high_mark: | |
- return '', () | |
+ extra_select, order_by, group_by = self.pre_sql_setup(with_col_aliases=with_col_aliases) | |
distinct_fields = self.get_distinct() | |
# This must come after 'select', 'ordering' and 'distinct' -- see | |
@@ -352,7 +354,10 @@ class SQLCompiler(object): | |
result.append(self.connection.ops.distinct_sql(distinct_fields)) | |
out_cols = [] | |
- for _, (s_sql, s_params), alias in self.select + extra_select: | |
+ for X, (s_sql, s_params), alias in self.select + extra_select: | |
+ print('X:: ', X) | |
+ print('s_sql:: ', s_sql) | |
+ print('alias:: ', alias) | |
if alias: | |
s_sql = '%s AS %s' % (s_sql, self.connection.ops.quote_name(alias)) | |
params.extend(s_params) | |
@@ -432,7 +437,7 @@ class SQLCompiler(object): | |
obj.clear_ordering(True) | |
return obj.get_compiler(connection=self.connection).as_sql() | |
- def get_default_columns(self, start_alias=None, opts=None, from_parent=None): | |
+ def get_default_columns(self, start_alias=None, opts=None, from_parent=None, with_col_aliases=False): | |
""" | |
Computes the default columns for selecting every field in the base | |
model. Will sometimes be called to pull in related models (e.g. via | |
@@ -454,7 +459,7 @@ class SQLCompiler(object): | |
# alias for a given field. This also includes None -> start_alias to | |
# be used by local fields. | |
seen_models = {None: start_alias} | |
- | |
+ counter = 0 | |
for field, model in opts.get_concrete_fields_with_model(): | |
if from_parent and model is not None and issubclass( | |
from_parent._meta.concrete_model, model._meta.concrete_model): | |
@@ -466,8 +471,8 @@ class SQLCompiler(object): | |
continue | |
if field.model in only_load and field.attname not in only_load[field.model]: | |
continue | |
- alias = self.query.join_parent_model(opts, model, start_alias, | |
- seen_models) | |
+ alias = self.query.join_parent_model( | |
+ opts, model, start_alias, seen_models) | |
column = field.get_col(alias) | |
result.append(column) | |
return result | |
@@ -573,7 +578,7 @@ class SQLCompiler(object): | |
return result, params | |
def get_related_selections(self, select, opts=None, root_alias=None, cur_depth=1, | |
- requested=None, restricted=None): | |
+ requested=None, restricted=None, with_col_aliases=False): | |
""" | |
Fill in the information needed for a select_related query. The current | |
depth is measured as the number of connections away from the root model | |
@@ -648,10 +653,10 @@ class SQLCompiler(object): | |
opts=f.rel.to._meta) | |
for col in columns: | |
select_fields.append(len(select)) | |
- select.append((col, None)) | |
+ select.append((col, col.column_alias)) | |
klass_info['select_fields'] = select_fields | |
next_klass_infos = self.get_related_selections( | |
- select, f.rel.to._meta, alias, cur_depth + 1, next, restricted) | |
+ select, f.rel.to._meta, alias, cur_depth + 1, next, restricted, with_col_aliases=with_col_aliases) | |
get_related_klass_infos(klass_info, next_klass_infos) | |
if restricted: | |
@@ -679,12 +684,12 @@ class SQLCompiler(object): | |
start_alias=alias, opts=model._meta, from_parent=opts.model) | |
for col in columns: | |
select_fields.append(len(select)) | |
- select.append((col, None)) | |
+ select.append((col, col.column_alias)) | |
klass_info['select_fields'] = select_fields | |
next = requested.get(f.related_query_name(), {}) | |
next_klass_infos = self.get_related_selections( | |
select, model._meta, alias, cur_depth + 1, | |
- next, restricted) | |
+ next, restricted, with_col_aliases=with_col_aliases) | |
get_related_klass_infos(klass_info, next_klass_infos) | |
fields_not_found = set(requested.keys()).difference(fields_found) | |
if fields_not_found: | |
@@ -1012,7 +1017,7 @@ class SQLUpdateCompiler(SQLCompiler): | |
is_empty = False | |
return rows | |
- def pre_sql_setup(self): | |
+ def pre_sql_setup(self, with_col_aliases=False): | |
""" | |
If the update depends on results from other tables, we need to do some | |
munging of the "where" conditions to match the format required for | |
diff --git a/tests/queries/tests.py b/tests/queries/tests.py | |
index 855b09b..3cbd19b 100644 | |
--- a/tests/queries/tests.py | |
+++ b/tests/queries/tests.py | |
@@ -415,8 +415,10 @@ class Queries1Tests(BaseQuerysetTest): | |
) | |
def test_ticket2496(self): | |
+ qs = Item.objects.extra(tables=['queries_author']).select_related().order_by('name') | |
+ print(qs.query) | |
self.assertQuerysetEqual( | |
- Item.objects.extra(tables=['queries_author']).select_related().order_by('name')[:1], | |
+ qs[:1], | |
['<Item: four>'] | |
) | |
@@ -1137,7 +1139,6 @@ class Queries1Tests(BaseQuerysetTest): | |
# A negated Q along with an annotated queryset failed in Django 1.4 | |
qs = Author.objects.annotate(Count('item')) | |
qs = qs.filter(~Q(extra__value=0)) | |
- | |
self.assertIn('SELECT', str(qs.query)) | |
self.assertQuerysetEqual( | |
qs, |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/django/db/backends/oracle/compiler.py b/django/db/backends/oracle/compiler.py | |
index cfc8a08..d68159a 100644 | |
--- a/django/db/backends/oracle/compiler.py | |
+++ b/django/db/backends/oracle/compiler.py | |
@@ -20,11 +20,11 @@ class SQLCompiler(compiler.SQLCompiler): | |
do_offset = with_limits and (self.query.high_mark is not None | |
or self.query.low_mark) | |
if not do_offset: | |
- sql, params = super(SQLCompiler, self).as_sql(with_limits=False, | |
- with_col_aliases=with_col_aliases) | |
+ sql, params = super(SQLCompiler, self).as_sql( | |
+ with_limits=False, with_col_aliases=with_col_aliases) | |
else: | |
- sql, params = super(SQLCompiler, self).as_sql(with_limits=False, | |
- with_col_aliases=True) | |
+ sql, params = super(SQLCompiler, self).as_sql( | |
+ with_limits=False, with_col_aliases=True) | |
# Wrap the base query in an outer SELECT * with boundaries on | |
# the "_RN" column. This is the canonical way to emulate LIMIT | |
diff --git a/django/db/models/sql/compiler.py b/django/db/models/sql/compiler.py | |
index e590f3b..c35a11c 100644 | |
--- a/django/db/models/sql/compiler.py | |
+++ b/django/db/models/sql/compiler.py | |
@@ -327,6 +327,9 @@ class SQLCompiler(object): | |
If 'with_limits' is False, any limit/offset information is not included | |
in the query. | |
""" | |
+ # don't bother setting up the query if the limit is a no-op. | |
+ if with_limits and self.query.low_mark == self.query.high_mark: | |
+ return '', () | |
# After executing the query, we must get rid of any joins the query | |
# setup created. So, take note of alias counts before the query ran. | |
# However we do not want to get rid of stuff done in pre_sql_setup(), | |
@@ -335,8 +338,6 @@ class SQLCompiler(object): | |
refcounts_before = self.query.alias_refcount.copy() | |
try: | |
extra_select, order_by, group_by = self.pre_sql_setup() | |
- if with_limits and self.query.low_mark == self.query.high_mark: | |
- return '', () | |
distinct_fields = self.get_distinct() | |
# This must come after 'select', 'ordering' and 'distinct' -- see |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment