Skip to content

Commit 3768d04

Browse files
author
Médéric RIBREUX
committedJul 25, 2015
Oracle Spatial support for DBManager
1 parent 0966dad commit 3768d04

File tree

14 files changed

+4343
-1
lines changed

14 files changed

+4343
-1
lines changed
 

‎python/plugins/db_manager/README

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ It allows showing the DBs contents and run query on them.
66
In this moment DB Manager supports the following DBMS backends:
77
- PostgreSQL/PostGIS through the psycopg2 pymodule
88
- SQLite/SpatiaLite using the pyspatialite pymodule
9-
9+
- Oracle Spatial using PyQt QtSql module
1010

1111
For more info about the project, see at the wiki page:
1212
http://qgis.org/wiki/DB_Manager_plugin_GSoC_2011
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2+
FILE(GLOB PY_FILES *.py)
3+
FILE(GLOB ICON_FILES icons/*.png)
4+
5+
PYQT4_ADD_RESOURCES(PYRC_FILES resources.qrc)
6+
7+
PLUGIN_INSTALL(db_manager db_plugins/oracle ${PY_FILES} ${PYRC_FILES})
8+
PLUGIN_INSTALL(db_manager db_plugins/oracle/icons ${ICON_FILES})
9+

‎python/plugins/db_manager/db_plugins/oracle/LICENSE

Lines changed: 339 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
# -*- coding: utf-8 -*-
2+
3+
"""
4+
/***************************************************************************
5+
Name : QtSqlDB
6+
Description : DB API 2.0 interface for QtSql
7+
Date : June 6, 2015
8+
Copyright : (C) 2015 by Jürgen E. Fischer
9+
email : jef at norbit dot de
10+
11+
***************************************************************************/
12+
13+
/***************************************************************************
14+
* *
15+
* This program is free software; you can redistribute it and/or modify *
16+
* it under the terms of the GNU General Public License as published by *
17+
* the Free Software Foundation; either version 2 of the License, or *
18+
* (at your option) any later version. *
19+
* *
20+
***************************************************************************/
21+
"""
22+
23+
from PyQt4.QtCore import QVariant, QDate, QTime, QDateTime, QByteArray
24+
from PyQt4.QtSql import QSqlDatabase, QSqlQuery, QSqlField
25+
26+
paramstyle = "qmark"
27+
threadsafety = 1
28+
apilevel = "2.0"
29+
30+
import time
31+
import datetime
32+
33+
34+
def Date(year, month, day):
35+
return datetime.date(year, month, day)
36+
37+
38+
def Time(hour, minute, second):
39+
return datetime.time(hour, minute, second)
40+
41+
42+
def Timestamp(year, month, day, hour, minute, second):
43+
return datetime.datetime(year, month, day, hour, minute, second)
44+
45+
46+
def DateFromTicks(ticks):
47+
return Date(*time.localtime(ticks)[:3])
48+
49+
50+
def TimeFromTicks(ticks):
51+
return Time(*time.localtime(ticks)[3:6])
52+
53+
54+
def TimestampFromTicks(ticks):
55+
return Timestamp(*time.localtime(ticks)[:6])
56+
57+
58+
class ConnectionError(StandardError):
59+
60+
def __init__(self, *args, **kwargs):
61+
super(StandardError, self).__init__(*args, **kwargs)
62+
63+
64+
class ExecError(StandardError):
65+
66+
def __init__(self, *args, **kwargs):
67+
super(StandardError, self).__init__(*args, **kwargs)
68+
69+
70+
class QtSqlDBCursor:
71+
72+
def __init__(self, conn):
73+
self.qry = QSqlQuery(conn)
74+
self.description = None
75+
self.rowcount = -1
76+
self.arraysize = 1
77+
78+
def close(self):
79+
self.qry.finish()
80+
81+
def execute(self, operation, parameters=[]):
82+
if len(parameters) == 0:
83+
if not self.qry.exec_(operation):
84+
raise ExecError(self.qry.lastError().databaseText())
85+
else:
86+
if not self.qry.prepare(operation):
87+
raise ExecError(self.qry.lastError().databaseText())
88+
89+
for i in range(len(parameters)):
90+
self.qry.bindValue(i, parameters[i])
91+
92+
if not self.qry.exec_():
93+
raise ExecError(self.qry.lastError().databaseText())
94+
95+
self.rowcount = self.qry.size()
96+
self.description = []
97+
for c in range(self.qry.record().count()):
98+
f = self.qry.record().field(c)
99+
100+
if f.type() == QVariant.Date:
101+
t = Date
102+
elif f.type() == QVariant.Time:
103+
t = Time
104+
elif f.type() == QVariant.DateTime:
105+
t = Timestamp
106+
elif f.type() == QVariant.Double:
107+
t = float
108+
elif f.type() == QVariant.Int:
109+
t = int
110+
elif f.type() == QVariant.String:
111+
t = unicode
112+
elif f.type() == QVariant.ByteArray:
113+
t = unicode
114+
else:
115+
continue
116+
117+
self.description.append([
118+
f.name(), # name
119+
t, # type_code
120+
f.length(), # display_size
121+
f.length(), # internal_size
122+
f.precision(), # precision
123+
None, # scale
124+
f.requiredStatus() != QSqlField.Required # null_ok
125+
])
126+
127+
def executemany(self, operation, seq_of_parameters):
128+
if len(seq_of_parameters) == 0:
129+
return
130+
131+
if not self.qry.prepare(operation):
132+
raise ExecError(self.qry.lastError().databaseText())
133+
134+
for r in seq_of_parameters:
135+
for i in range(len(r)):
136+
self.qry.bindValue(i, r[i])
137+
138+
if not self.qry.exec_():
139+
raise ExecError(self.qry.lastError().databaseText())
140+
141+
def scroll(self, row):
142+
return self.qry.seek(row)
143+
144+
def fetchone(self):
145+
if not self.qry.next():
146+
return None
147+
148+
row = []
149+
for i in range(len(self.description)):
150+
value = self.qry.value(i)
151+
if (isinstance(value, QDate)
152+
or isinstance(value, QTime)
153+
or isinstance(value, QDateTime)):
154+
value = value.toString()
155+
elif isinstance(value, QByteArray):
156+
value = u"GEOMETRY"
157+
# value = value.toHex()
158+
159+
row.append(value)
160+
161+
return row
162+
163+
def fetchmany(self, size=10):
164+
rows = []
165+
while len(rows) < size:
166+
row = self.fetchone()
167+
if row is None:
168+
break
169+
rows.append(row)
170+
171+
return rows
172+
173+
def fetchall(self):
174+
rows = []
175+
while True:
176+
row = self.fetchone()
177+
if row is None:
178+
break
179+
rows.append(row)
180+
181+
return rows
182+
183+
def setinputsize(self, sizes):
184+
raise ExecError("nyi")
185+
186+
def setoutputsize(self, size, column=None):
187+
raise ExecError("nyi")
188+
189+
190+
class QtSqlDBConnection:
191+
connections = 0
192+
193+
def __init__(self, driver, dbname, user, passwd):
194+
self.conn = QSqlDatabase.addDatabase(
195+
driver, "qtsql_%d" % QtSqlDBConnection.connections)
196+
QtSqlDBConnection.connections += 1
197+
self.conn.setDatabaseName(dbname)
198+
self.conn.setUserName(user)
199+
self.conn.setPassword(passwd)
200+
201+
if not self.conn.open():
202+
raise ConnectionError(self.conn.lastError().databaseText())
203+
204+
def close(self):
205+
self.conn.close()
206+
207+
def commit(self):
208+
self.conn.commit()
209+
210+
def rollback(self):
211+
self.conn.rollback()
212+
213+
def cursor(self):
214+
return QtSqlDBCursor(self.conn)
215+
216+
217+
def connect(driver, dbname, user, passwd):
218+
return QtSqlDBConnection(driver, dbname, user, passwd)
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# Oracle implementation of QGis DBManager plugin
2+
3+
## Introduction
4+
5+
This Python code try to implement the Oracle part of the QGis DBManager plugin. DBManager plugin is a good tool from QGis with which you can easily manage your databases and create your own queries which can be dynamically added to QGis maps.
6+
7+
For the moment, DBManager plugin is only able to connect to PostGIS and Spatialite databases. If you want to manage your Oracle Spatial repository, you can (try) to do this with this code implementation.
8+
9+
The code base of this implementation was the Postgis one. I tried to make every features of the PostGIS work under Oracle but there are some limitations. Read TODO.md to have more details about what is working and what needs to be done.
10+
11+
Expect bugs !
12+
13+
14+
## Installation
15+
16+
The code does not need [cx_Oracle](http://cx-oracle.sourceforge.net/) anymore ! Thanks to [Jürgen Fischer](https://github.com/jef-n), all Oracle connections uses PyQt QtSql module which is included in QGIS.
17+
18+
To install DBManager oracle plugin, you just have to clone the git repository in a directory named `oracle` in the `db_plugins` directory of the db_manager installation.
19+
20+
For MS-Windows users:
21+
22+
* If you have git for MS-Windows:
23+
$ cd "C:\Program Files\QGis Wien\apps\qgis\python\plugins\db_manager\db_plugins"
24+
$ git clone https://github.com/medspx/dbmanager-oracle.git oracle
25+
26+
* Or:
27+
* Just create a directory named `oracle` in "C:\Program Files\QGis Wien\apps\qgis\python\plugins\db_manager\db_plugins"
28+
* unzip `https://github.com/medspx/dbmanager-oracle/archive/master.zip` into "C:\Program Files\QGis Wien\apps\qgis\python\plugins\db_manager\db_plugins\oracle"
29+
30+
For GNU/Linux users:
31+
32+
# cd /usr/share/qgis/python/plugins/db_manager/db_plugins
33+
# git clone https://github.com/medspx/dbmanager-oracle.git oracle
34+
35+
36+
## Limitations
37+
38+
* You have to define Oracle connections directly in QGis for the plugin to work (same thing than PostGIS and Spatialite).
39+
* Oracle Spatial Rasters are not supported (as I've don't have a way to test them).
40+
* The code try to use the maximum of your Oracle connections parameters. If you have a huge geographic database with a lot of layers, listing tables can take time. So be careful about your connections parameters (try to restrict to user tables to reduce internal queries duration).
41+
* Tests have been done with QGis 2.4, 2.6 and 2.8.2. You probably should use the latest version because before 2.4 the Oracle provider of QGis was not able to load dynamic queries.
42+
* Some things could not have been well tested, particularly everything that requires administrative rights on DB like schema creation/deletion.
43+
* Tests have been done against an Oracle 10g database. I tried to incorporate the official Oracle 12c "dictionary" of commands and the internal queries should also work with 11g and 12c versions of Oracle Database server.
44+
* Some tasks cannot been done under Oracle Database like moving a table from a schema to another. There is also no PostgreSQL Rules features under Oracle.
45+
* Code has been tested only under MS-Windows (bad) but as it is Python code, I hope it will also works under other OS.
46+
47+
48+
## Bug reports
49+
50+
For the moment, use the ["issues" tool of GitHub](https://github.com/medspx/dbmanager-oracle/issues) to report bugs.
51+
52+
53+
## Main goal
54+
55+
My main goal is that this code can be incorporated in the official QGis source code repository. Once this has been done, the code upgrades will take place there.
56+
57+
58+
## License
59+
60+
This code is released under the GNU GPLv2 license. Read headers code for more information.
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
# Won't fix
2+
3+
* SQL Window - "Retrieve columns" don't work => problem in
4+
dlg_sql_window.py (not enough abstraction for connectors).
5+
6+
* SQL Window - Can't retrieve column: dlg_sql_window.py launch an
7+
invalid request for Oracle (no LIMIT operator in Oracle). Should
8+
patch dlg_sql_window.py to use a connector method to grab columns.
9+
10+
* Query-builder - Add date functions menu (needs to change the main
11+
code of query builder).
12+
13+
* Table Menu - remove GEOMETRY COLLECTION from the list of geometry
14+
types (Oracle can't handle this form of geometries). Needs to modify
15+
dlg_create_table.py
16+
17+
* Refresh - Refresh Action should transmit an argument to the
18+
db_plugin object specifying that this a refresh and not a primary
19+
dbtree population. I've build (quite) an ugly hack to use SQLite
20+
list of tables cache for primary population and once it is done,
21+
each other call to connector.tables doesn't not use cache anymore.
22+
23+
* There is a bug in the create table dialog: there should be a
24+
checkbox for Null column but it is not showned. The setData method
25+
don't fix the value for notNull attributes and whatever value of
26+
this attribute for the field, it is always shown as nullable in the
27+
modify field dialog. #13089
28+
29+
* Import Table does not work because of a problem in
30+
QgsVectorLayerImport. After the creation of the table, QGIS tries to
31+
open the layer but, as there is no geometries in it, QGIS can't
32+
determinate the geometry type of the layer and refuses to open
33+
it. Then, no data importation can occur. Must dig into
34+
src/core/qgsvectorlayerimport.cpp and into the provider code.
35+
See #13096 .
36+
37+
# Future work
38+
39+
* Implement SRID modification (with reprojection of data) ?
40+
* Modify/force wkbType to be able to open an empty layer in the canvas.
41+
42+
# TODO
43+
44+
* Nothing for the moment.
45+
46+
# DONE
47+
48+
* Code review
49+
* Try to factorise connector.py.
50+
* Connector method to handle metadata operations (update/delete/insert).
51+
* work on updateExtentMetadata.
52+
* 2.10: try to find the differences between postGIS connector 2.8 and 2.10. (Answer: nothing else than pep-8 reformatting).
53+
54+
* Plugin
55+
* Can't open spatial view (no pkcol determined).
56+
57+
* Info model
58+
* Still some problems with extent comparison: do not try to calculate extent when there is no row.
59+
* Add precision for float values (NUMBER(10,5)).
60+
* View: show the estimated metadata extent for spatial views that have metadata.
61+
* Can't rename a spatial View.
62+
* Can't rename a column.
63+
64+
* Table Tab
65+
* Problem on one layer casting for number without max_length_char.
66+
* When exploring some tables in table view: there is a sort of crash with fetchmoreData.
67+
68+
* Query Builder
69+
* Should not present the geometric columns in column values.
70+
71+
* SQL Window
72+
* Grab the row count.
73+
* Create view button.
74+
* Spatial Index tab (find if can be activated: no because Oracle use spatial index internally).
75+
* Can't open query builder.
76+
* Modify dictionnary to add math/string/aggregates functions/operators.
77+
* Can't open column values from query builder.
78+
* GEOM columns are not retrieved. (Done: don't grab them, just use GEOMETRY string instead to speed columns population)
79+
* Can't open a query in QGis.
80+
* Find the srid of a query and add it as a layer parameter.
81+
* Open non geometric queries.
82+
* Show better statistic about query duration.
83+
* handle DatabaseError in the dialog.
84+
* Make the SQL query window works !
85+
* Handle geometry type detection.
86+
87+
* Table Menu
88+
* Error when update/create/delete field in deleteCursor (was problem on QtSql Exceptions).
89+
* Can't modify the name of a geographic column: modify also the spatial index.
90+
* Create table: problem with index and geocol name is not in upper case.
91+
* Create Table: handle 3rd and 4th dimension for metadata creation.
92+
* Can't modify a field length.
93+
* Can't delete a geographic column.
94+
* Add an action to update metadata layer extent to the content of the geocolumn.
95+
* Disable move Table to another schema (impossible in Oracle, you have to import/export).
96+
* Find how to load Unknown WKBGeometryType layers.
97+
* Spatial index creation.
98+
* Edit dialog fully functionnal.
99+
* Edit Table opens.
100+
* Remove Vacuum operation in Table menu.
101+
* Fix: Add SRID when creating table.
102+
* Rename Geographic Table.
103+
* Can create non geographic tables.
104+
* Can delete non geographic tables.
105+
* Can Create geographic tables.
106+
* Can Delete geographic tables.
107+
* DO Empty table.
108+
109+
* Connector
110+
* getVectorTablesCache should present only one line per table (don't show tables more than once).
111+
* correspondance between Oracle SDO_GTYPE and QGis.WkbType in a class dict.
112+
* Show only one table/layer in the table tree even if entry is duplicated in cache.
113+
* Reuse the pre-calculated extent metadata when updating.
114+
* Create a better privilege function using ALL_PRIVS_RECD
115+
116+
* Main Tree
117+
* Bug on refreshing a whole connection.
118+
119+
* Information Tab (main tab)
120+
* If extent is not in QGIS format (dimensions named X and Y): show it and offer to correct the name of the dimension.
121+
* Syntax coloration for View and MView definitions (done with pygments which is included in QGIS).
122+
* Add date of last creation/modification for objects.
123+
* Modify "Oracle" in table information by "Oracle Spatial".
124+
* For rows estimation: use a query to scan nb_rows in object !
125+
* Refresh on the fly data that are not stored in cache (comments/table type/row counts).
126+
* Bad comparison between metadata extent and calculated extent (was format syntax).
127+
* If user can't udpate metadata, dont pull the link for update action.
128+
* Can't update metadata extent: find if table is in USER_SDO_GEOM_METADATA.
129+
* Print QGis Geometry Type in string instead of int.
130+
131+
* Constraints:
132+
* Handle foreign keys information.
133+
* Add search_condition, status, delete_rule, validated, generated
134+
135+
* Indexes:
136+
* Add rebuild index action for indexes.
137+
* Add more informations: Compression/Valid/Last analyzed/ityp_name.
138+
139+
* Refresh:
140+
* Make getTables and getVectorTables functions retrieve less informations and manage them on the fly.
141+
* Refreshing a schema refresh only the schema, not the whole connection.
142+
* Still problems with refreshing (QPyNullVariant for detectedSrid).
143+
* Mark views as views.
144+
* Grab also geographic views.
145+
* Refresh should launch a refresh of the cached list of tables (SQLite).
146+
* Implement add_sys_tables (mask MDRT index tables for example).
147+
* List of unknown geometry tables when refreshing depending upon onlyExistingTypes.
148+
* Grab the geomtypes of the layer during list refreshing.
149+
* Grab the srids of the layer during list refreshing.
150+
* Grab the pkcols for the views.
151+
* Bug with cache srids interpreted as float (convert detected srid to int).
152+
* Find if a layer is a view or a table with cache and non cache list of tables.
153+
154+
* Materialized views:
155+
* function to determine if MV or simple Table.
156+
* retrieve definition.
157+
* unitary comments retrieving.
158+
* Primary key mask.
159+
* Refreshing informations.
160+
* Action to refresh the mview.
161+
* View/MView definition is not interpreted as Html anymore.
162+
163+
* QtSqlDB:
164+
* bug with timing functions (no Time module/global name)
165+
* better handling of dates (returned as QDateTime) in query dialog.

‎python/plugins/db_manager/db_plugins/oracle/__init__.py

Whitespace-only changes.

‎python/plugins/db_manager/db_plugins/oracle/connector.py

Lines changed: 1760 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
# -*- coding: utf-8 -*-
2+
3+
"""
4+
/***************************************************************************
5+
Name : DB Manager
6+
Description : Database manager plugin for QGIS (Oracle)
7+
Date : Aug 27, 2014
8+
copyright : (C) 2014 by Médéric RIBREUX
9+
email : mederic.ribreux@gmail.com
10+
11+
The content of this file is based on
12+
- PG_Manager by Martin Dobias <wonder.sk@gmail.com> (GPLv2 license)
13+
- DB Manager by Giuseppe Sucameli <brush.tyler@gmail.com> (GPLv2 license)
14+
***************************************************************************/
15+
16+
/***************************************************************************
17+
* *
18+
* This program is free software; you can redistribute it and/or modify *
19+
* it under the terms of the GNU General Public License as published by *
20+
* the Free Software Foundation; either version 2 of the License, or *
21+
* (at your option) any later version. *
22+
* *
23+
***************************************************************************/
24+
"""
25+
26+
from PyQt4.QtCore import *
27+
from PyQt4.QtGui import *
28+
29+
from ..data_model import TableDataModel, SqlResultModel, \
30+
BaseTableModel, TableFieldsModel, SimpleTableModel
31+
from ..plugin import DbError
32+
from qgis.core import *
33+
34+
35+
class ORTableDataModel(TableDataModel):
36+
37+
def __init__(self, table, parent=None):
38+
self.cursor = None
39+
TableDataModel.__init__(self, table, parent)
40+
41+
if not self.table.rowCount:
42+
self.table.refreshRowCount()
43+
44+
self.connect(self.table, SIGNAL("aboutToChange"),
45+
self._deleteCursor)
46+
self._createCursor()
47+
48+
def _createCursor(self):
49+
fields_txt = u", ".join(self.fields)
50+
table_txt = self.db.quoteId(
51+
(self.table.schemaName(), self.table.name))
52+
53+
self.cursor = self.db._get_cursor()
54+
sql = u"SELECT {0} FROM {1}".format(fields_txt, table_txt)
55+
56+
self.db._execute(self.cursor, sql)
57+
58+
def _sanitizeTableField(self, field):
59+
# get fields, ignore geometry columns
60+
if field.dataType.upper() == u"SDO_GEOMETRY":
61+
return (u"CASE WHEN {0} IS NULL THEN NULL ELSE 'GEOMETRY'"
62+
u"END AS {0}".format(
63+
self.db.quoteId(field.name)))
64+
if field.dataType.upper() == u"DATE":
65+
return u"CAST({} AS VARCHAR2(8))".format(
66+
self.db.quoteId(field.name))
67+
if field.dataType.upper() == u"NUMBER":
68+
if not field.charMaxLen:
69+
return u"CAST({} AS VARCHAR2(135))".format(
70+
self.db.quoteId(field.name))
71+
elif field.modifier:
72+
nbChars = 2 + int(field.charMaxLen) + \
73+
int(field.modifier)
74+
return u"CAST({} AS VARCHAR2({}))".format(
75+
self.db.quoteId(field.name),
76+
unicode(nbChars))
77+
78+
return u"CAST({0} As VARCHAR2({1}))".format(
79+
self.db.quoteId(field.name), field.charMaxLen)
80+
81+
def _deleteCursor(self):
82+
self.db._close_cursor(self.cursor)
83+
self.cursor = None
84+
85+
def __del__(self):
86+
self.disconnect(
87+
self.table, SIGNAL("aboutToChange"), self._deleteCursor)
88+
self._deleteCursor()
89+
90+
def getData(self, row, col):
91+
if (row < self.fetchedFrom
92+
or row >= self.fetchedFrom + self.fetchedCount):
93+
margin = self.fetchedCount / 2
94+
if row + margin >= self.rowCount():
95+
start = self.rowCount() - margin
96+
else:
97+
start = row - margin
98+
if start < 0:
99+
start = 0
100+
self.fetchMoreData(start)
101+
102+
# For some improbable cases
103+
if row - self.fetchedFrom >= len(self.resdata):
104+
return None
105+
106+
return self.resdata[row - self.fetchedFrom][col]
107+
108+
def fetchMoreData(self, row_start):
109+
if not self.cursor:
110+
self._createCursor()
111+
112+
self.cursor.scroll(row_start - 1)
113+
114+
self.resdata = self.cursor.fetchmany(self.fetchedCount)
115+
self.fetchedFrom = row_start
116+
117+
118+
class ORSqlResultModel(SqlResultModel):
119+
120+
def __init__(self, db, sql, parent=None):
121+
self.db = db.connector
122+
123+
t = QTime()
124+
t.start()
125+
c = self.db._execute(None, unicode(sql))
126+
127+
self._affectedRows = 0
128+
data = []
129+
header = self.db._get_cursor_columns(c)
130+
if not header:
131+
header = []
132+
133+
try:
134+
if len(header) > 0:
135+
data = self.db._fetchall(c)
136+
self._affectedRows = len(data)
137+
except DbError:
138+
# nothing to fetch!
139+
data = []
140+
header = []
141+
142+
self._secs = t.elapsed() / 1000.0
143+
del t
144+
145+
BaseTableModel.__init__(self, header, data, parent)
146+
147+
# commit before closing the cursor to make sure that the
148+
# changes are stored
149+
self.db._commit()
150+
c.close()
151+
del c
Loading

‎python/plugins/db_manager/db_plugins/oracle/info_model.py

Lines changed: 674 additions & 0 deletions
Large diffs are not rendered by default.

‎python/plugins/db_manager/db_plugins/oracle/plugin.py

Lines changed: 653 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<RCC>
2+
<qresource prefix="/db_manager/oracle">
3+
<file alias="icon">icons/oracle.png</file>
4+
</qresource>
5+
</RCC>
Lines changed: 308 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,308 @@
1+
# -*- coding: utf-8 -*-
2+
3+
"""
4+
/***************************************************************************
5+
Name : DB Manager
6+
Description : Database manager plugin for QGIS (Oracle)
7+
Date : Aug 27, 2014
8+
copyright : (C) 2014 by Médéric RIBREUX
9+
email : mederic.ribreux@gmail.com
10+
11+
The content of this file is based on
12+
- PG_Manager by Martin Dobias <wonder.sk@gmail.com> (GPLv2 license)
13+
- DB Manager by Giuseppe Sucameli <brush.tyler@gmail.com> (GPLv2 license)
14+
***************************************************************************/
15+
16+
/***************************************************************************
17+
* *
18+
* This program is free software; you can redistribute it and/or modify *
19+
* it under the terms of the GNU General Public License as published by *
20+
* the Free Software Foundation; either version 2 of the License, or *
21+
* (at your option) any later version. *
22+
* *
23+
***************************************************************************/
24+
"""
25+
26+
__author__ = 'Médéric RIBREUX'
27+
__date__ = 'August 2014'
28+
__copyright__ = '(C) 2014, Médéric RIBREUX'
29+
# This will get replaced with a git SHA1 when you do a git archive
30+
__revision__ = '$Format:%H$'
31+
32+
# keywords
33+
keywords = [
34+
# From:
35+
# http://docs.oracle.com/cd/B19306_01/server.102/b14200/ap_keywd.htm
36+
"ACCESS", "ADD", "ALL", "ALTER", "AND", "ANY", "AS", "ASC",
37+
"AUDIT", "BETWEEN", "BY", "CHAR", "CHECK", "CLUSTER", "COLUMN",
38+
"COMMENT", "COMPRESS", "CONNECT", "CREATE", "CURRENT", "DATE",
39+
"DECIMAL", "DEFAULT", "DELETE", "DESC", "DISTINCT", "DROP",
40+
"ELSE", "EXCLUSIVE", "EXISTS", "FILE", "FLOAT", "FOR", "FROM",
41+
"GRANT", "GROUP", "HAVING", "IDENTIFIED", "IMMEDIATE", "IN",
42+
"INCREMENT", "INDEX", "INITIAL", "INSERT", "INTEGER", "INTERSECT",
43+
"INTO", "IS", "LEVEL", "LIKE", "LOCK", "LONG", "MAXEXTENTS",
44+
"MINUS", "MLSLABEL", "MODE", "MODIFY", "NOAUDIT", "NOCOMPRESS",
45+
"NOT", "NOWAIT", "NULL", "NUMBER", "OF", "OFFLINE", "ON",
46+
"ONLINE", "OPTION", "OR", "ORDER", "PCTFREE", "PRIOR",
47+
"PRIVILEGES", "PUBLIC", "RAW", "RENAME", "RESOURCE", "REVOKE",
48+
"ROW", "ROWID", "ROWNUM", "ROWS", "SELECT", "SESSION", "SET",
49+
"SHARE", "SIZE", "SMALLINT", "START", "SUCCESSFUL", "SYNONYM",
50+
"SYSDATE", "TABLE", "THEN", "TO", "TRIGGER", "UID", "UNION",
51+
"UNIQUE", "UPDATE", "USER", "VALIDATE", "VALUES", "VARCHAR",
52+
"VARCHAR2", "VIEW", "WHENEVER", "WHERE", "WITH",
53+
# From http://docs.oracle.com/cd/B13789_01/appdev.101/a42525/apb.htm
54+
"ADMIN", "CURSOR", "FOUND", "MOUNT", "AFTER", "CYCLE", "FUNCTION",
55+
"NEXT", "ALLOCATE", "DATABASE", "GO", "NEW", "ANALYZE",
56+
"DATAFILE", "GOTO", "NOARCHIVELOG", "ARCHIVE", "DBA", "GROUPS",
57+
"NOCACHE", "ARCHIVELOG", "DEC", "INCLUDING", "NOCYCLE",
58+
"AUTHORIZATION", "DECLARE", "INDICATOR", "NOMAXVALUE", "AVG",
59+
"DISABLE", "INITRANS", "NOMINVALUE", "BACKUP", "DISMOUNT",
60+
"INSTANCE", "NONE", "BEGIN", "DOUBLE", "INT", "NOORDER", "BECOME",
61+
"DUMP", "KEY", "NORESETLOGS", "BEFORE", "EACH", "LANGUAGE",
62+
"NORMAL", "BLOCK", "ENABLE", "LAYER", "NOSORT", "BODY", "END",
63+
"LINK", "NUMERIC", "CACHE", "ESCAPE", "LISTS", "OFF", "CANCEL",
64+
"EVENTS", "LOGFILE", "OLD", "CASCADE", "EXCEPT", "MANAGE", "ONLY",
65+
"CHANGE", "EXCEPTIONS", "MANUAL", "OPEN", "CHARACTER", "EXEC",
66+
"MAX", "OPTIMAL", "CHECKPOINT", "EXPLAIN", "MAXDATAFILES", "OWN",
67+
"CLOSE", "EXECUTE", "MAXINSTANCES", "PACKAGE", "COBOL", "EXTENT",
68+
"MAXLOGFILES", "PARALLEL", "COMMIT", "EXTERNALLY",
69+
"MAXLOGHISTORY", "PCTINCREASE", "COMPILE", "FETCH",
70+
"MAXLOGMEMBERS", "PCTUSED", "CONSTRAINT", "FLUSH", "MAXTRANS",
71+
"PLAN", "CONSTRAINTS", "FREELIST", "MAXVALUE", "PLI", "CONTENTS",
72+
"FREELISTS", "MIN", "PRECISION", "CONTINUE", "FORCE",
73+
"MINEXTENTS", "PRIMARY", "CONTROLFILE", "FOREIGN", "MINVALUE",
74+
"PRIVATE", "COUNT", "FORTRAN", "MODULE", "PROCEDURE", "PROFILE",
75+
"SAVEPOINT", "SQLSTATE", "TRACING", "QUOTA", "SCHEMA",
76+
"STATEMENT_ID", "TRANSACTION", "READ", "SCN", "STATISTICS",
77+
"TRIGGERS", "REAL", "SECTION", "STOP", "TRUNCATE", "RECOVER",
78+
"SEGMENT", "STORAGE", "UNDER", "REFERENCES", "SEQUENCE", "SUM",
79+
"UNLIMITED", "REFERENCING", "SHARED", "SWITCH", "UNTIL",
80+
"RESETLOGS", "SNAPSHOT", "SYSTEM", "USE", "RESTRICTED", "SOME",
81+
"TABLES", "USING", "REUSE", "SORT", "TABLESPACE", "WHEN", "ROLE",
82+
"SQL", "TEMPORARY", "WRITE", "ROLES", "SQLCODE", "THREAD", "WORK",
83+
"ROLLBACK", "SQLERROR", "TIME", "ABORT", "BETWEEN", "CRASH",
84+
"DIGITS", "ACCEPT", "BINARY_INTEGER", "CREATE", "DISPOSE",
85+
"ACCESS", "BODY", "CURRENT", "DISTINCT", "ADD", "BOOLEAN",
86+
"CURRVAL", "DO", "ALL", "BY", "CURSOR", "DROP", "ALTER", "CASE",
87+
"DATABASE", "ELSE", "AND", "CHAR", "DATA_BASE", "ELSIF", "ANY",
88+
"CHAR_BASE", "DATE", "END", "ARRAY", "CHECK", "DBA", "ENTRY",
89+
"ARRAYLEN", "CLOSE", "DEBUGOFF", "EXCEPTION", "AS", "CLUSTER",
90+
"DEBUGON", "EXCEPTION_INIT", "ASC", "CLUSTERS", "DECLARE",
91+
"EXISTS", "ASSERT", "COLAUTH", "DECIMAL", "EXIT", "ASSIGN",
92+
"COLUMNS", "DEFAULT", "FALSE", "AT", "COMMIT", "DEFINITION",
93+
"FETCH", "AUTHORIZATION", "COMPRESS", "DELAY", "FLOAT", "AVG",
94+
"CONNECT", "DELETE", "FOR", "BASE_TABLE", "CONSTANT", "DELTA",
95+
"FORM", "BEGIN", "COUNT", "DESC", "FROM", "FUNCTION", "NEW",
96+
"RELEASE", "SUM", "GENERIC", "NEXTVAL", "REMR", "TABAUTH", "GOTO",
97+
"NOCOMPRESS", "RENAME", "TABLE", "GRANT", "NOT", "RESOURCE",
98+
"TABLES", "GROUP", "NULL", "RETURN", "TASK", "HAVING", "NUMBER",
99+
"REVERSE", "TERMINATE", "IDENTIFIED", "NUMBER_BASE", "REVOKE",
100+
"THEN", "IF", "OF", "ROLLBACK", "TO", "IN", "ON", "ROWID", "TRUE",
101+
"INDEX", "OPEN", "ROWLABEL", "TYPE", "INDEXES", "OPTION",
102+
"ROWNUM", "UNION", "INDICATOR", "OR", "ROWTYPE", "UNIQUE",
103+
"INSERT", "ORDER", "RUN", "UPDATE", "INTEGER", "OTHERS",
104+
"SAVEPOINT", "USE", "INTERSECT", "OUT", "SCHEMA", "VALUES",
105+
"INTO", "PACKAGE", "SELECT", "VARCHAR", "IS", "PARTITION",
106+
"SEPARATE", "VARCHAR2", "LEVEL", "PCTFREE", "SET", "VARIANCE",
107+
"LIKE", "POSITIVE", "SIZE", "VIEW", "LIMITED", "PRAGMA",
108+
"SMALLINT", "VIEWS", "LOOP", "PRIOR", "SPACE", "WHEN", "MAX",
109+
"PRIVATE", "SQL", "WHERE", "MIN", "PROCEDURE", "SQLCODE", "WHILE",
110+
"MINUS", "PUBLIC", "SQLERRM", "WITH", "MLSLABEL", "RAISE",
111+
"START", "WORK", "MOD", "RANGE", "STATEMENT", "XOR", "MODE",
112+
"REAL", "STDDEV", "NATURAL", "RECORD", "SUBTYPE"
113+
]
114+
115+
oracle_spatial_keywords = []
116+
117+
# SQL functions
118+
# other than math/string/aggregate/date/conversion/xml/data mining
119+
functions = [
120+
# FROM
121+
# https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions001.htm
122+
"CAST", "COALESCE", "DECODE", "GREATEST", "LEAST", "LNNVL",
123+
"NULLIF", "NVL", "NVL2", "SET", "UID", "USER", "USERENV"
124+
]
125+
126+
# SQL math functions
127+
math_functions = [
128+
'ABS', 'ACOS', 'ASIN', 'ATAN', 'ATAN2', 'BITAND', 'CEIL', 'COS',
129+
'COSH', 'EXP', 'FLOOR', 'LN', 'LOG', 'MOD', 'NANVL', 'POWER',
130+
'REMAINDER', 'ROUND', 'SIGN', 'SIN', 'SINH', 'SQRT', 'TAN',
131+
'TANH', 'TRUNC', 'WIDTH_BUCKET'
132+
]
133+
134+
# Strings functions
135+
string_functions = [
136+
'CHR', 'CONCAT', 'INITCAP', 'LOWER', 'LPAD', 'LTRIM', 'NLS_INITCAP',
137+
'NLS_LOWER', 'NLSSORT', 'NLS_UPPER', 'REGEXP_REPLACE', 'REGEXP_SUBSTR',
138+
'REPLACE', 'RPAD', 'RTRIM', 'SOUNDEX', 'SUBSTR', 'TRANSLATE', 'TREAT',
139+
'TRIM', 'UPPER', 'ASCII', 'INSTR', 'LENGTH', 'REGEXP_INSTR'
140+
]
141+
142+
# Aggregate functions
143+
aggregate_functions = [
144+
'AVG', 'COLLECT', 'CORR', 'COUNT', 'COVAR_POP', 'COVAR_SAMP', 'CUME_DIST',
145+
'DENSE_RANK', 'FIRST', 'GROUP_ID', 'GROUPING', 'GROUPING_ID',
146+
'LAST', 'MAX', 'MEDIAN', 'MIN', 'PERCENTILE_CONT',
147+
'PERCENTILE_DISC', 'PERCENT_RANK', 'RANK',
148+
'STATS_BINOMIAL_TEST', 'STATS_CROSSTAB', 'STATS_F_TEST',
149+
'STATS_KS_TEST', 'STATS_MODE', 'STATS_MW_TEST',
150+
'STATS_ONE_WAY_ANOVA', 'STATS_WSR_TEST', 'STDDEV',
151+
'STDDEV_POP', 'STDDEV_SAMP', 'SUM', 'SYS_XMLAGG', 'VAR_POP',
152+
'VAR_SAMP', 'VARIANCE', 'XMLAGG'
153+
]
154+
155+
oracle_spatial_functions = [
156+
# From http://docs.oracle.com/cd/B19306_01/appdev.102/b14255/toc.htm
157+
# Spatial operators
158+
"SDO_ANYINTERACT", "SDO_CONTAINS", "SDO_COVEREDBY", "SDO_COVERS",
159+
"SDO_EQUAL", "SDO_FILTER", "SDO_INSIDE", "SDO_JOIN", "SDO_NN",
160+
"SDO_NN_DISTANCE", "SDO_ON", "SDO_OVERLAPBDYDISJOINT",
161+
"SDO_OVERLAPBDYINTERSECT", "SDO_OVERLAPS", "SDO_RELATE",
162+
"SDO_TOUCH", "SDO_WITHIN_DISTANCE",
163+
# SPATIAL AGGREGATE FUNCTIONS
164+
"SDO_AGGR_CENTROID", "SDO_AGGR_CONCAT_LINES",
165+
"SDO_AGGR_CONVEXHULL", "SDO_AGGR_LRS_CONCAT", "SDO_AGGR_MBR",
166+
"SDO_AGGR_UNION",
167+
# COORDINATE SYSTEM TRANSFORMATION (SDO_CS)
168+
"SDO_CS.ADD_PREFERENCE_FOR_OP", "SDO_CS.CONVERT_NADCON_TO_XML",
169+
"SDO_CS.CONVERT_NTV2_TO_XML", "SDO_CS.CONVERT_XML_TO_NADCON",
170+
"SDO_CS.CONVERT_XML_TO_NTV2", "SDO_CS.CREATE_CONCATENATED_OP",
171+
"SDO_CS.CREATE_OBVIOUS_EPSG_RULES",
172+
"SDO_CS.CREATE_PREF_CONCATENATED_OP",
173+
"SDO_CS.DELETE_ALL_EPSG_RULES", "SDO_CS.DELETE_OP",
174+
"SDO_CS.DETERMINE_CHAIN", "SDO_CS.DETERMINE_DEFAULT_CHAIN",
175+
"SDO_CS.FIND_GEOG_CRS", "SDO_CS.FIND_PROJ_CRS",
176+
"SDO_CS.FROM_OGC_SIMPLEFEATURE_SRS", "SDO_CS.FROM_USNG",
177+
"SDO_CS.MAP_EPSG_SRID_TO_ORACLE",
178+
"SDO_CS.MAP_ORACLE_SRID_TO_EPSG",
179+
"SDO_CS.REVOKE_PREFERENCE_FOR_OP",
180+
"SDO_CS.TO_OGC_SIMPLEFEATURE_SRS", "SDO_CS.TO_USNG",
181+
"SDO_CS.TRANSFORM", "SDO_CS.TRANSFORM_LAYER",
182+
"SDO_CS.UPDATE_WKTS_FOR_ALL_EPSG_CRS",
183+
"SDO_CS.UPDATE_WKTS_FOR_EPSG_CRS",
184+
"SDO_CS.UPDATE_WKTS_FOR_EPSG_DATUM",
185+
"SDO_CS.UPDATE_WKTS_FOR_EPSG_ELLIPS",
186+
"SDO_CS.UPDATE_WKTS_FOR_EPSG_OP",
187+
"SDO_CS.UPDATE_WKTS_FOR_EPSG_PARAM",
188+
"SDO_CS.UPDATE_WKTS_FOR_EPSG_PM", "SDO_CS.VALIDATE_WKT",
189+
"SDO_CS.VIEWPORT_TRANSFORM",
190+
# GEOCODING (SDO_GCDR)
191+
"SDO_GCDR.GEOCODE", "SDO_GCDR.GEOCODE_ADDR",
192+
"SDO_GCDR.GEOCODE_ADDR_ALL", "SDO_GCDR.GEOCODE_ALL",
193+
"SDO_GCDR.GEOCODE_AS_GEOMETRY", "SDO_GCDR.REVERSE_GEOCODE",
194+
# GEOMETRY (SDO_GEOM)
195+
"SDO_GEOM.RELATE", "SDO_GEOM.SDO_ARC_DENSIFY",
196+
"SDO_GEOM.SDO_AREA", "SDO_GEOM.SDO_BUFFER",
197+
"SDO_GEOM.SDO_CENTROID", "SDO_GEOM.SDO_CONVEXHULL",
198+
"SDO_GEOM.SDO_DIFFERENCE", "SDO_GEOM.SDO_DISTANCE",
199+
"SDO_GEOM.SDO_INTERSECTION", "SDO_GEOM.SDO_LENGTH",
200+
"SDO_GEOM.SDO_MAX_MBR_ORDINATE", "SDO_GEOM.SDO_MBR",
201+
"SDO_GEOM.SDO_MIN_MBR_ORDINATE", "SDO_GEOM.SDO_POINTONSURFACE",
202+
"SDO_GEOM.SDO_UNION", "SDO_GEOM.SDO_XOR",
203+
"SDO_GEOM.VALIDATE_GEOMETRY_WITH_CONTEXT",
204+
"SDO_GEOM.VALIDATE_LAYER_WITH_CONTEXT",
205+
"SDO_GEOM.WITHIN_DISTANCE",
206+
# LINEAR REFERENCING SYSTEM (SDO_LRS)
207+
"SDO_LRS.CLIP_GEOM_SEGMENT", "SDO_LRS.CONCATENATE_GEOM_SEGMENTS",
208+
"SDO_LRS.CONNECTED_GEOM_SEGMENTS",
209+
"SDO_LRS.CONVERT_TO_LRS_DIM_ARRAY", "SDO_LRS.CONVERT_TO_LRS_GEOM",
210+
"SDO_LRS.CONVERT_TO_LRS_LAYER",
211+
"SDO_LRS.CONVERT_TO_STD_DIM_ARRAY", "SDO_LRS.CONVERT_TO_STD_GEOM",
212+
"SDO_LRS.CONVERT_TO_STD_LAYER", "SDO_LRS.DEFINE_GEOM_SEGMENT",
213+
"SDO_LRS.DYNAMIC_SEGMENT", "SDO_LRS.FIND_LRS_DIM_POS",
214+
"SDO_LRS.FIND_MEASURE", "SDO_LRS.FIND_OFFSET",
215+
"SDO_LRS.GEOM_SEGMENT_END_MEASURE", "SDO_LRS.GEOM_SEGMENT_END_PT",
216+
"SDO_LRS.GEOM_SEGMENT_LENGTH",
217+
"SDO_LRS.GEOM_SEGMENT_START_MEASURE",
218+
"SDO_LRS.GEOM_SEGMENT_START_PT", "SDO_LRS.GET_MEASURE",
219+
"SDO_LRS.GET_NEXT_SHAPE_PT", "SDO_LRS.GET_NEXT_SHAPE_PT_MEASURE",
220+
"SDO_LRS.GET_PREV_SHAPE_PT", "SDO_LRS.GET_PREV_SHAPE_PT_MEASURE",
221+
"SDO_LRS.IS_GEOM_SEGMENT_DEFINED",
222+
"SDO_LRS.IS_MEASURE_DECREASING", "SDO_LRS.IS_MEASURE_INCREASING",
223+
"SDO_LRS.IS_SHAPE_PT_MEASURE", "SDO_LRS.LOCATE_PT",
224+
"SDO_LRS.LRS_INTERSECTION", "SDO_LRS.MEASURE_RANGE",
225+
"SDO_LRS.MEASURE_TO_PERCENTAGE", "SDO_LRS.OFFSET_GEOM_SEGMENT",
226+
"SDO_LRS.PERCENTAGE_TO_MEASURE", "SDO_LRS.PROJECT_PT",
227+
"SDO_LRS.REDEFINE_GEOM_SEGMENT", "SDO_LRS.RESET_MEASURE",
228+
"SDO_LRS.REVERSE_GEOMETRY", "SDO_LRS.REVERSE_MEASURE",
229+
"SDO_LRS.SET_PT_MEASURE", "SDO_LRS.SPLIT_GEOM_SEGMENT",
230+
"SDO_LRS.TRANSLATE_MEASURE", "SDO_LRS.VALID_GEOM_SEGMENT",
231+
"SDO_LRS.VALID_LRS_PT", "SDO_LRS.VALID_MEASURE",
232+
"SDO_LRS.VALIDATE_LRS_GEOMETRY",
233+
# SDO_MIGRATE
234+
"SDO_MIGRATE.TO_CURRENT",
235+
# SPATIAL ANALYSIS AND MINING (SDO_SAM)
236+
"SDO_SAM.AGGREGATES_FOR_GEOMETRY", "SDO_SAM.AGGREGATES_FOR_LAYER",
237+
"SDO_SAM.BIN_GEOMETRY", "SDO_SAM.BIN_LAYER",
238+
"SDO_SAM.COLOCATED_REFERENCE_FEATURES",
239+
"SDO_SAM.SIMPLIFY_GEOMETRY", "SDO_SAM.SIMPLIFY_LAYER",
240+
"SDO_SAM.SPATIAL_CLUSTERS", "SDO_SAM.TILED_AGGREGATES",
241+
"SDO_SAM.TILED_BINS",
242+
# TUNING (SDO_TUNE)
243+
"SDO_TUNE.AVERAGE_MBR", "SDO_TUNE.ESTIMATE_RTREE_INDEX_SIZE",
244+
"SDO_TUNE.EXTENT_OF", "SDO_TUNE.MIX_INFO",
245+
"SDO_TUNE.QUALITY_DEGRADATION",
246+
# UTILITY (SDO_UTIL)
247+
"SDO_UTIL.APPEND", "SDO_UTIL.CIRCLE_POLYGON",
248+
"SDO_UTIL.CONCAT_LINES", "SDO_UTIL.CONVERT_UNIT",
249+
"SDO_UTIL.ELLIPSE_POLYGON", "SDO_UTIL.EXTRACT",
250+
"SDO_UTIL.FROM_WKBGEOMETRY", "SDO_UTIL.FROM_WKTGEOMETRY",
251+
"SDO_UTIL.GETNUMELEM", "SDO_UTIL.GETNUMVERTICES",
252+
"SDO_UTIL.GETVERTICES", "SDO_UTIL.INITIALIZE_INDEXES_FOR_TTS",
253+
"SDO_UTIL.POINT_AT_BEARING", "SDO_UTIL.POLYGONTOLINE",
254+
"SDO_UTIL.PREPARE_FOR_TTS", "SDO_UTIL.RECTIFY_GEOMETRY",
255+
"SDO_UTIL.REMOVE_DUPLICATE_VERTICES",
256+
"SDO_UTIL.REVERSE_LINESTRING", "SDO_UTIL.SIMPLIFY",
257+
"SDO_UTIL.TO_GMLGEOMETRY", "SDO_UTIL.TO_WKBGEOMETRY",
258+
"SDO_UTIL.TO_WKTGEOMETRY", "SDO_UTIL.VALIDATE_WKBGEOMETRY",
259+
"SDO_UTIL.VALIDATE_WKTGEOMETRY"
260+
]
261+
262+
# Oracle Operators
263+
operators = [
264+
' AND ', ' OR ', '||', ' < ', ' <= ', ' > ', ' >= ', ' = ',
265+
' <> ', '!=', '^=', ' IS ', ' IS NOT ', ' IN ', ' ANY ', ' SOME ',
266+
' NOT IN ', ' LIKE ', ' GLOB ', ' MATCH ', ' REGEXP ',
267+
' BETWEEN x AND y ', ' NOT BETWEEN x AND y ', ' EXISTS ',
268+
' IS NULL ', ' IS NOT NULL', ' ALL ', ' NOT ',
269+
' CASE {column} WHEN {value} THEN {value} '
270+
]
271+
272+
273+
# constants
274+
constants = ["null", "false", "true"]
275+
oracle_spatial_constants = []
276+
277+
278+
def getSqlDictionary(spatial=True):
279+
k, c, f = list(keywords), list(constants), list(functions)
280+
281+
if spatial:
282+
k += oracle_spatial_keywords
283+
f += oracle_spatial_functions
284+
c += oracle_spatial_constants
285+
286+
return {'keyword': k, 'constant': c, 'function': f}
287+
288+
289+
def getQueryBuilderDictionary():
290+
# concat functions
291+
def ff(l):
292+
return filter(lambda s: s[0] != '*', l)
293+
294+
def add_paren(l):
295+
return map(lambda s: s + "(", l)
296+
297+
foo = sorted(
298+
add_paren(
299+
ff(
300+
list(
301+
set.union(set(functions),
302+
set(oracle_spatial_functions))))))
303+
m = sorted(add_paren(ff(math_functions)))
304+
agg = sorted(add_paren(ff(aggregate_functions)))
305+
op = ff(operators)
306+
s = sorted(add_paren(ff(string_functions)))
307+
return {'function': foo, 'math': m, 'aggregate': agg,
308+
'operator': op, 'string': s}

0 commit comments

Comments
 (0)
Please sign in to comment.