forked from soundstripe/django-pyodbc-iseries
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathquery.py
127 lines (105 loc) · 5.92 KB
/
query.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# +--------------------------------------------------------------------------+
# | Licensed Materials - Property of IBM |
# | |
# | (C) Copyright IBM Corporation 2009-2018. |
# +--------------------------------------------------------------------------+
# | This module complies with Django 1.0 and is |
# | Licensed under the Apache License, Version 2.0 (the "License"); |
# | you may not use this file except in compliance with the License. |
# | You may obtain a copy of the License at |
# | http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable |
# | law or agreed to in writing, software distributed under the License is |
# | distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
# | KIND, either express or implied. See the License for the specific |
# | language governing permissions and limitations under the License. |
# +--------------------------------------------------------------------------+
# | Authors: Ambrish Bhargava, Tarun Pasrija, Rahul Priyadarshi |
# +--------------------------------------------------------------------------+
"""
Custom Query class for DB2.
Derives from: django.db.models.sql.query.Query
"""
def query_class(QueryClass):
class DB2QueryClass(QueryClass):
__rownum = 'Z.__ROWNUM'
# To get ride of LIMIT/OFFSET problem in DB2, this method has been implemented.
def as_sql(self, with_limits=True, with_col_aliases=False):
if not (with_limits and (self.high_mark is not None or self.low_mark)):
return super(DB2QueryClass, self).as_sql(False, with_col_aliases)
else:
if self.high_mark == self.low_mark:
return '', ()
sql_ori, params = super(DB2QueryClass, self).as_sql(False, with_col_aliases)
sql_split = sql_ori.split(" FROM ")
sql_sec = ""
if len(sql_split) > 2:
for i in range(1, len(sql_split)):
sql_sec = " %s FROM %s " % (sql_sec, sql_split[i])
else:
sql_sec = " FROM %s " % (sql_split[1])
dummyVal = "Z.__db2_"
sql_pri = ""
sql_sel = "SELECT"
if self.distinct:
sql_sel = "SELECT DISTINCT"
sql_select_token = sql_split[0].split(",")
i = 0
while (i < len(sql_select_token)):
if sql_select_token[i].count("TIMESTAMP(DATE(SUBSTR(CHAR(") == 1:
sql_sel = "%s \"%s%d\"," % (sql_sel, dummyVal, i + 1)
sql_pri = '%s %s,%s,%s,%s AS "%s%d",' % (
sql_pri,
sql_select_token[i],
sql_select_token[i + 1],
sql_select_token[i + 2],
sql_select_token[i + 3],
dummyVal, i + 1)
i = i + 4
continue
if sql_select_token[i].count(" AS ") == 1:
temp_col_alias = sql_select_token[i].split(" AS ")
sql_pri = '%s %s,' % (sql_pri, sql_select_token[i])
sql_sel = "%s %s," % (sql_sel, temp_col_alias[1])
i = i + 1
continue
sql_pri = '%s %s AS "%s%d",' % (sql_pri, sql_select_token[i], dummyVal, i + 1)
sql_sel = "%s \"%s%d\"," % (sql_sel, dummyVal, i + 1)
i = i + 1
sql_pri = sql_pri[:len(sql_pri) - 1]
sql_pri = "%s%s" % (sql_pri, sql_sec)
sql_sel = sql_sel[:len(sql_sel) - 1]
sql = '%s, ( ROW_NUMBER() OVER() ) AS "%s" FROM ( %s ) AS M' % (sql_sel, self.__rownum, sql_pri)
sql = '%s FROM ( %s ) Z WHERE' % (sql_sel, sql)
if self.low_mark != 0:
sql = '%s "%s" > %d' % (sql, self.__rownum, self.low_mark)
if self.low_mark != 0 and self.high_mark is not None:
sql = '%s AND ' % (sql)
if self.high_mark is not None:
sql = '%s "%s" <= %d' % (sql, self.__rownum, self.high_mark)
return sql, params
# http://www.python.org/dev/peps/pep-0307/
# See Extended __reduce__ API
def __reduce__(self):
return (__newobj__, (QueryClass,))
# For case insensitive search, converting parameter value to upper case.
# The right hand side will get converted to upper case in the SQL itself.
from django.db.models.sql.where import AND
def add_filter(self, filter_expr, connector=AND, negate=False, trim=False,
can_reuse=None, process_extras=True):
if len(filter_expr) != 0 and filter_expr is not None:
filter_expr = list(filter_expr)
if filter_expr[0].find("__iendswith") != -1 or \
filter_expr[0].find("__istartswith") != -1 or \
filter_expr[0].find("__icontains") != -1 or \
filter_expr[0].find("__iexact") != -1:
filter_expr[1] = filter_expr[1].upper()
filter_expr = tuple(filter_expr)
return super(DB2QueryClass, self).add_filter(filter_expr, connector,
negate, trim, can_reuse, process_extras)
return DB2QueryClass
# Method to make DB2QueryClass picklable
def __newobj__(QueryClass):
# http://www.python.org/dev/peps/pep-0307/
# The __newobj__ unpickling function
DB2QueryClass = query_class(QueryClass)
return DB2QueryClass.__new__(DB2QueryClass)