We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
db.export_to_csv_file() error with python 3.7
**Describe the bug**
db.export_to_csv_file() error with python 3.7
```
TypeError: a bytes-like object is required, not 'str'
```
in
```
web2py/gluon/packages/dal/pydal/base.py", line 844, in export_to_csv_file
    ofile.write('TABLE %s\r\n' % table)
```

**To Reproduce**
```
Bens-iMac:web2py ben$ pipenv run python web2py.py -M -S pacificW
/Users/ben/.local/share/virtualenvs/web2py-6f1t1lX6/lib/python3.7/site-packages/psycopg2/__init__.py:144: UserWarning: The psycopg2 wheel package will be renamed from release 2.8; in order to keep installing from binary please use "pip install psycopg2-binary" instead. For details see: <http://initd.org/psycopg/docs/install.html#binary-install-from-pypi>.
  """)
web2py Web Framework
Created by Massimo Di Pierro, Copyright 2007-2018
Version 2.17.1-stable+timestamp.2018.08.05.17.57.00
Database drivers available: sqlite3, psycopg2, imaplib, pymysql, pyodbc
WARNING:web2py:import IPython error; use default python shell
Python 3.7.0 (default, Jul 23 2018, 20:22:55) 
[Clang 9.1.0 (clang-902.0.39.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> db.export_to_csv_file(open('somefile.csv', 'wb'))
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/Users/ben/Documents/programs/web2py/gluon/packages/dal/pydal/base.py", line 844, in export_to_csv_file
    ofile.write('TABLE %s\r\n' % table)
TypeError: a bytes-like object is required, not 'str'
>>> 
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `gluon/dal/adapters/oracle.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 import base64
3 import datetime
4 import re
5 
6 from .._globals import IDENTITY
7 from .._load import cx_Oracle
8 from .base import BaseAdapter
9 
10 class OracleAdapter(BaseAdapter):
11     drivers = ('cx_Oracle',)
12 
13     commit_on_alter_table = False
14     types = {
15         'boolean': 'CHAR(1)',
16         'string': 'VARCHAR2(%(length)s)',
17         'text': 'CLOB',
18         'json': 'CLOB',
19         'password': 'VARCHAR2(%(length)s)',
20         'blob': 'CLOB',
21         'upload': 'VARCHAR2(%(length)s)',
22         'integer': 'INT',
23         'bigint': 'NUMBER',
24         'float': 'FLOAT',
25         'double': 'BINARY_DOUBLE',
26         'decimal': 'NUMERIC(%(precision)s,%(scale)s)',
27         'date': 'DATE',
28         'time': 'CHAR(8)',
29         'datetime': 'DATE',
30         'id': 'NUMBER PRIMARY KEY',
31         'reference': 'NUMBER, CONSTRAINT %(constraint_name)s FOREIGN KEY (%(field_name)s) REFERENCES %(foreign_key)s ON DELETE %(on_delete_action)s',
32         'list:integer': 'CLOB',
33         'list:string': 'CLOB',
34         'list:reference': 'CLOB',
35         'big-id': 'NUMBER PRIMARY KEY',
36         'big-reference': 'NUMBER, CONSTRAINT %(constraint_name)s FOREIGN KEY (%(field_name)s) REFERENCES %(foreign_key)s ON DELETE %(on_delete_action)s',
37         'reference FK': ', CONSTRAINT FK_%(constraint_name)s FOREIGN KEY (%(field_name)s) REFERENCES %(foreign_key)s ON DELETE %(on_delete_action)s',
38         'reference TFK': ' CONSTRAINT FK_%(foreign_table)s_PK FOREIGN KEY (%(field_name)s) REFERENCES %(foreign_table)s (%(foreign_key)s) ON DELETE %(on_delete_action)s',
39         }
40 
41 
42     def trigger_name(self,tablename):
43         return '%s_trigger' % tablename
44 
45     def LEFT_JOIN(self):
46         return 'LEFT OUTER JOIN'
47 
48     def RANDOM(self):
49         return 'dbms_random.value'
50 
51     def NOT_NULL(self,default,field_type):
52         return 'DEFAULT %s NOT NULL' % self.represent(default,field_type)
53 
54     def REGEXP(self, first, second):
55         return 'REGEXP_LIKE(%s, %s)' % (self.expand(first),
56                                         self.expand(second, 'string'))
57 
58     def _drop(self,table,mode):
59         sequence_name = table._sequence_name
60         return ['DROP TABLE %s %s;' % (table.sqlsafe, mode), 'DROP SEQUENCE %s;' % sequence_name]
61 
62     def select_limitby(self, sql_s, sql_f, sql_t, sql_w, sql_o, limitby):
63         if limitby:
64             (lmin, lmax) = limitby
65             if len(sql_w) > 1:
66                 sql_w_row = sql_w + ' AND w_row > %i' % lmin
67             else:
68                 sql_w_row = 'WHERE w_row > %i' % lmin
69             return 'SELECT %s %s FROM (SELECT w_tmp.*, ROWNUM w_row FROM (SELECT %s FROM %s%s%s) w_tmp WHERE ROWNUM<=%i) %s %s %s;' % (sql_s, sql_f, sql_f, sql_t, sql_w, sql_o, lmax, sql_t, sql_w_row, sql_o)
70         return 'SELECT %s %s FROM %s%s%s;' % (sql_s, sql_f, sql_t, sql_w, sql_o)
71 
72     def constraint_name(self, tablename, fieldname):
73         constraint_name = BaseAdapter.constraint_name(self, tablename, fieldname)
74         if len(constraint_name)>30:
75             constraint_name = '%s_%s__constraint' % (tablename[:10], fieldname[:7])
76         return constraint_name
77 
78     def represent_exceptions(self, obj, fieldtype):
79         if fieldtype == 'blob':
80             obj = base64.b64encode(str(obj))
81             return ":CLOB('%s')" % obj
82         elif fieldtype == 'date':
83             if isinstance(obj, (datetime.date, datetime.datetime)):
84                 obj = obj.isoformat()[:10]
85             else:
86                 obj = str(obj)
87             return "to_date('%s','yyyy-mm-dd')" % obj
88         elif fieldtype == 'datetime':
89             if isinstance(obj, datetime.datetime):
90                 obj = obj.isoformat()[:19].replace('T',' ')
91             elif isinstance(obj, datetime.date):
92                 obj = obj.isoformat()[:10]+' 00:00:00'
93             else:
94                 obj = str(obj)
95             return "to_date('%s','yyyy-mm-dd hh24:mi:ss')" % obj
96         return None
97 
98     def __init__(self,db,uri,pool_size=0,folder=None,db_codec ='UTF-8',
99                  credential_decoder=IDENTITY, driver_args={},
100                  adapter_args={}, do_connect=True, after_connection=None):
101         self.db = db
102         self.dbengine = "oracle"
103         self.uri = uri
104         if do_connect: self.find_driver(adapter_args,uri)
105         self.pool_size = pool_size
106         self.folder = folder
107         self.db_codec = db_codec
108         self._after_connection = after_connection
109         self.find_or_make_work_folder()
110         ruri = uri.split('://',1)[1]
111         if not 'threaded' in driver_args:
112             driver_args['threaded']=True
113         def connector(uri=ruri,driver_args=driver_args):
114             return self.driver.connect(uri,**driver_args)
115         self.connector = connector
116         if do_connect: self.reconnect()
117 
118     def after_connection(self):
119         self.execute("ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';")
120         self.execute("ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS';")
121 
122     oracle_fix = re.compile("[^']*('[^']*'[^']*)*\:(?P<clob>CLOB\('([^']+|'')*'\))")
123 
124     def execute(self, command, args=None):
125         args = args or []
126         i = 1
127         while True:
128             m = self.oracle_fix.match(command)
129             if not m:
130                 break
131             command = command[:m.start('clob')] + str(i) + command[m.end('clob'):]
132             args.append(m.group('clob')[6:-2].replace("''", "'"))
133             i += 1
134         if command[-1:]==';':
135             command = command[:-1]
136         return self.log_execute(command, args)
137 
138     def create_sequence_and_triggers(self, query, table, **args):
139         tablename = table._tablename
140         id_name = table._id.name
141         sequence_name = table._sequence_name
142         trigger_name = table._trigger_name
143         self.execute(query)
144         self.execute('CREATE SEQUENCE %s START WITH 1 INCREMENT BY 1 NOMAXVALUE MINVALUE -1;' % sequence_name)
145         self.execute("""
146             CREATE OR REPLACE TRIGGER %(trigger_name)s BEFORE INSERT ON %(tablename)s FOR EACH ROW
147             DECLARE
148                 curr_val NUMBER;
149                 diff_val NUMBER;
150                 PRAGMA autonomous_transaction;
151             BEGIN
152                 IF :NEW.%(id)s IS NOT NULL THEN
153                     EXECUTE IMMEDIATE 'SELECT %(sequence_name)s.nextval FROM dual' INTO curr_val;
154                     diff_val := :NEW.%(id)s - curr_val - 1;
155                     IF diff_val != 0 THEN
156                       EXECUTE IMMEDIATE 'alter sequence %(sequence_name)s increment by '|| diff_val;
157                       EXECUTE IMMEDIATE 'SELECT %(sequence_name)s.nextval FROM dual' INTO curr_val;
158                       EXECUTE IMMEDIATE 'alter sequence %(sequence_name)s increment by 1';
159                     END IF;
160                 END IF;
161                 SELECT %(sequence_name)s.nextval INTO :NEW.%(id)s FROM DUAL;
162             END;
163         """ % dict(trigger_name=trigger_name, tablename=tablename,
164                    sequence_name=sequence_name,id=id_name))
165 
166     def lastrowid(self,table):
167         sequence_name = table._sequence_name
168         self.execute('SELECT %s.currval FROM dual;' % sequence_name)
169         return long(self.cursor.fetchone()[0])
170 
171     #def parse_value(self, value, field_type, blob_decode=True):
172     #    if blob_decode and isinstance(value, cx_Oracle.LOB):
173     #        try:
174     #            value = value.read()
175     #        except self.driver.ProgrammingError:
176     #            # After a subsequent fetch the LOB value is not valid anymore
177     #            pass
178     #    return BaseAdapter.parse_value(self, value, field_type, blob_decode)
179 
180     def _fetchall(self):
181         if any(x[1]==cx_Oracle.LOB for x in self.cursor.description):
182             return [tuple([(c.read() if type(c) == cx_Oracle.LOB else c) \
183                                for c in r]) for r in self.cursor]
184         else:
185             return self.cursor.fetchall()
186 
187     def sqlsafe_table(self, tablename, ot=None):
188         if ot is not None:
189             return (self.QUOTE_TEMPLATE + ' ' \
190                     + self.QUOTE_TEMPLATE) % (ot, tablename)
191         return self.QUOTE_TEMPLATE % tablename
192
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/gluon/dal/adapters/oracle.py b/gluon/dal/adapters/oracle.py
--- a/gluon/dal/adapters/oracle.py
+++ b/gluon/dal/adapters/oracle.py
@@ -136,7 +136,7 @@
         return self.log_execute(command, args)
 
     def create_sequence_and_triggers(self, query, table, **args):
-        tablename = table._tablename
+        tablename = table._rname or table._tablename
         id_name = table._id.name
         sequence_name = table._sequence_name
         trigger_name = table._trigger_name

{"golden_diff": "diff --git a/gluon/dal/adapters/oracle.py b/gluon/dal/adapters/oracle.py\n--- a/gluon/dal/adapters/oracle.py\n+++ b/gluon/dal/adapters/oracle.py\n@@ -136,7 +136,7 @@\n         return self.log_execute(command, args)\n \n     def create_sequence_and_triggers(self, query, table, **args):\n-        tablename = table._tablename\n+        tablename = table._rname or table._tablename\n         id_name = table._id.name\n         sequence_name = table._sequence_name\n         trigger_name = table._trigger_name\n", "issue": "db.export_to_csv_file() error with python 3.7\n**Describe the bug**\r\ndb.export_to_csv_file() error with python 3.7\r\n```\r\nTypeError: a bytes-like object is required, not 'str'\r\n```\r\nin\r\n```\r\nweb2py/gluon/packages/dal/pydal/base.py\", line 844, in export_to_csv_file\r\n    ofile.write('TABLE %s\\r\\n' % table)\r\n```\r\n\r\n**To Reproduce**\r\n```\r\nBens-iMac:web2py ben$ pipenv run python web2py.py -M -S pacificW\r\n/Users/ben/.local/share/virtualenvs/web2py-6f1t1lX6/lib/python3.7/site-packages/psycopg2/__init__.py:144: UserWarning: The psycopg2 wheel package will be renamed from release 2.8; in order to keep installing from binary please use \"pip install psycopg2-binary\" instead. For details see: <http://initd.org/psycopg/docs/install.html#binary-install-from-pypi>.\r\n  \"\"\")\r\nweb2py Web Framework\r\nCreated by Massimo Di Pierro, Copyright 2007-2018\r\nVersion 2.17.1-stable+timestamp.2018.08.05.17.57.00\r\nDatabase drivers available: sqlite3, psycopg2, imaplib, pymysql, pyodbc\r\nWARNING:web2py:import IPython error; use default python shell\r\nPython 3.7.0 (default, Jul 23 2018, 20:22:55) \r\n[Clang 9.1.0 (clang-902.0.39.2)] on darwin\r\nType \"help\", \"copyright\", \"credits\" or \"license\" for more information.\r\n(InteractiveConsole)\r\n>>> db.export_to_csv_file(open('somefile.csv', 'wb'))\r\nTraceback (most recent call last):\r\n  File \"<console>\", line 1, in <module>\r\n  File \"/Users/ben/Documents/programs/web2py/gluon/packages/dal/pydal/base.py\", line 844, in export_to_csv_file\r\n    ofile.write('TABLE %s\\r\\n' % table)\r\nTypeError: a bytes-like object is required, not 'str'\r\n>>> \r\n```\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\nimport base64\nimport datetime\nimport re\n\nfrom .._globals import IDENTITY\nfrom .._load import cx_Oracle\nfrom .base import BaseAdapter\n\nclass OracleAdapter(BaseAdapter):\n    drivers = ('cx_Oracle',)\n\n    commit_on_alter_table = False\n    types = {\n        'boolean': 'CHAR(1)',\n        'string': 'VARCHAR2(%(length)s)',\n        'text': 'CLOB',\n        'json': 'CLOB',\n        'password': 'VARCHAR2(%(length)s)',\n        'blob': 'CLOB',\n        'upload': 'VARCHAR2(%(length)s)',\n        'integer': 'INT',\n        'bigint': 'NUMBER',\n        'float': 'FLOAT',\n        'double': 'BINARY_DOUBLE',\n        'decimal': 'NUMERIC(%(precision)s,%(scale)s)',\n        'date': 'DATE',\n        'time': 'CHAR(8)',\n        'datetime': 'DATE',\n        'id': 'NUMBER PRIMARY KEY',\n        'reference': 'NUMBER, CONSTRAINT %(constraint_name)s FOREIGN KEY (%(field_name)s) REFERENCES %(foreign_key)s ON DELETE %(on_delete_action)s',\n        'list:integer': 'CLOB',\n        'list:string': 'CLOB',\n        'list:reference': 'CLOB',\n        'big-id': 'NUMBER PRIMARY KEY',\n        'big-reference': 'NUMBER, CONSTRAINT %(constraint_name)s FOREIGN KEY (%(field_name)s) REFERENCES %(foreign_key)s ON DELETE %(on_delete_action)s',\n        'reference FK': ', CONSTRAINT FK_%(constraint_name)s FOREIGN KEY (%(field_name)s) REFERENCES %(foreign_key)s ON DELETE %(on_delete_action)s',\n        'reference TFK': ' CONSTRAINT FK_%(foreign_table)s_PK FOREIGN KEY (%(field_name)s) REFERENCES %(foreign_table)s (%(foreign_key)s) ON DELETE %(on_delete_action)s',\n        }\n\n\n    def trigger_name(self,tablename):\n        return '%s_trigger' % tablename\n\n    def LEFT_JOIN(self):\n        return 'LEFT OUTER JOIN'\n\n    def RANDOM(self):\n        return 'dbms_random.value'\n\n    def NOT_NULL(self,default,field_type):\n        return 'DEFAULT %s NOT NULL' % self.represent(default,field_type)\n\n    def REGEXP(self, first, second):\n        return 'REGEXP_LIKE(%s, %s)' % (self.expand(first),\n                                        self.expand(second, 'string'))\n\n    def _drop(self,table,mode):\n        sequence_name = table._sequence_name\n        return ['DROP TABLE %s %s;' % (table.sqlsafe, mode), 'DROP SEQUENCE %s;' % sequence_name]\n\n    def select_limitby(self, sql_s, sql_f, sql_t, sql_w, sql_o, limitby):\n        if limitby:\n            (lmin, lmax) = limitby\n            if len(sql_w) > 1:\n                sql_w_row = sql_w + ' AND w_row > %i' % lmin\n            else:\n                sql_w_row = 'WHERE w_row > %i' % lmin\n            return 'SELECT %s %s FROM (SELECT w_tmp.*, ROWNUM w_row FROM (SELECT %s FROM %s%s%s) w_tmp WHERE ROWNUM<=%i) %s %s %s;' % (sql_s, sql_f, sql_f, sql_t, sql_w, sql_o, lmax, sql_t, sql_w_row, sql_o)\n        return 'SELECT %s %s FROM %s%s%s;' % (sql_s, sql_f, sql_t, sql_w, sql_o)\n\n    def constraint_name(self, tablename, fieldname):\n        constraint_name = BaseAdapter.constraint_name(self, tablename, fieldname)\n        if len(constraint_name)>30:\n            constraint_name = '%s_%s__constraint' % (tablename[:10], fieldname[:7])\n        return constraint_name\n\n    def represent_exceptions(self, obj, fieldtype):\n        if fieldtype == 'blob':\n            obj = base64.b64encode(str(obj))\n            return \":CLOB('%s')\" % obj\n        elif fieldtype == 'date':\n            if isinstance(obj, (datetime.date, datetime.datetime)):\n                obj = obj.isoformat()[:10]\n            else:\n                obj = str(obj)\n            return \"to_date('%s','yyyy-mm-dd')\" % obj\n        elif fieldtype == 'datetime':\n            if isinstance(obj, datetime.datetime):\n                obj = obj.isoformat()[:19].replace('T',' ')\n            elif isinstance(obj, datetime.date):\n                obj = obj.isoformat()[:10]+' 00:00:00'\n            else:\n                obj = str(obj)\n            return \"to_date('%s','yyyy-mm-dd hh24:mi:ss')\" % obj\n        return None\n\n    def __init__(self,db,uri,pool_size=0,folder=None,db_codec ='UTF-8',\n                 credential_decoder=IDENTITY, driver_args={},\n                 adapter_args={}, do_connect=True, after_connection=None):\n        self.db = db\n        self.dbengine = \"oracle\"\n        self.uri = uri\n        if do_connect: self.find_driver(adapter_args,uri)\n        self.pool_size = pool_size\n        self.folder = folder\n        self.db_codec = db_codec\n        self._after_connection = after_connection\n        self.find_or_make_work_folder()\n        ruri = uri.split('://',1)[1]\n        if not 'threaded' in driver_args:\n            driver_args['threaded']=True\n        def connector(uri=ruri,driver_args=driver_args):\n            return self.driver.connect(uri,**driver_args)\n        self.connector = connector\n        if do_connect: self.reconnect()\n\n    def after_connection(self):\n        self.execute(\"ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';\")\n        self.execute(\"ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS';\")\n\n    oracle_fix = re.compile(\"[^']*('[^']*'[^']*)*\\:(?P<clob>CLOB\\('([^']+|'')*'\\))\")\n\n    def execute(self, command, args=None):\n        args = args or []\n        i = 1\n        while True:\n            m = self.oracle_fix.match(command)\n            if not m:\n                break\n            command = command[:m.start('clob')] + str(i) + command[m.end('clob'):]\n            args.append(m.group('clob')[6:-2].replace(\"''\", \"'\"))\n            i += 1\n        if command[-1:]==';':\n            command = command[:-1]\n        return self.log_execute(command, args)\n\n    def create_sequence_and_triggers(self, query, table, **args):\n        tablename = table._tablename\n        id_name = table._id.name\n        sequence_name = table._sequence_name\n        trigger_name = table._trigger_name\n        self.execute(query)\n        self.execute('CREATE SEQUENCE %s START WITH 1 INCREMENT BY 1 NOMAXVALUE MINVALUE -1;' % sequence_name)\n        self.execute(\"\"\"\n            CREATE OR REPLACE TRIGGER %(trigger_name)s BEFORE INSERT ON %(tablename)s FOR EACH ROW\n            DECLARE\n                curr_val NUMBER;\n                diff_val NUMBER;\n                PRAGMA autonomous_transaction;\n            BEGIN\n                IF :NEW.%(id)s IS NOT NULL THEN\n                    EXECUTE IMMEDIATE 'SELECT %(sequence_name)s.nextval FROM dual' INTO curr_val;\n                    diff_val := :NEW.%(id)s - curr_val - 1;\n                    IF diff_val != 0 THEN\n                      EXECUTE IMMEDIATE 'alter sequence %(sequence_name)s increment by '|| diff_val;\n                      EXECUTE IMMEDIATE 'SELECT %(sequence_name)s.nextval FROM dual' INTO curr_val;\n                      EXECUTE IMMEDIATE 'alter sequence %(sequence_name)s increment by 1';\n                    END IF;\n                END IF;\n                SELECT %(sequence_name)s.nextval INTO :NEW.%(id)s FROM DUAL;\n            END;\n        \"\"\" % dict(trigger_name=trigger_name, tablename=tablename,\n                   sequence_name=sequence_name,id=id_name))\n\n    def lastrowid(self,table):\n        sequence_name = table._sequence_name\n        self.execute('SELECT %s.currval FROM dual;' % sequence_name)\n        return long(self.cursor.fetchone()[0])\n\n    #def parse_value(self, value, field_type, blob_decode=True):\n    #    if blob_decode and isinstance(value, cx_Oracle.LOB):\n    #        try:\n    #            value = value.read()\n    #        except self.driver.ProgrammingError:\n    #            # After a subsequent fetch the LOB value is not valid anymore\n    #            pass\n    #    return BaseAdapter.parse_value(self, value, field_type, blob_decode)\n\n    def _fetchall(self):\n        if any(x[1]==cx_Oracle.LOB for x in self.cursor.description):\n            return [tuple([(c.read() if type(c) == cx_Oracle.LOB else c) \\\n                               for c in r]) for r in self.cursor]\n        else:\n            return self.cursor.fetchall()\n\n    def sqlsafe_table(self, tablename, ot=None):\n        if ot is not None:\n            return (self.QUOTE_TEMPLATE + ' ' \\\n                    + self.QUOTE_TEMPLATE) % (ot, tablename)\n        return self.QUOTE_TEMPLATE % tablename\n", "path": "gluon/dal/adapters/oracle.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\nimport base64\nimport datetime\nimport re\n\nfrom .._globals import IDENTITY\nfrom .._load import cx_Oracle\nfrom .base import BaseAdapter\n\nclass OracleAdapter(BaseAdapter):\n    drivers = ('cx_Oracle',)\n\n    commit_on_alter_table = False\n    types = {\n        'boolean': 'CHAR(1)',\n        'string': 'VARCHAR2(%(length)s)',\n        'text': 'CLOB',\n        'json': 'CLOB',\n        'password': 'VARCHAR2(%(length)s)',\n        'blob': 'CLOB',\n        'upload': 'VARCHAR2(%(length)s)',\n        'integer': 'INT',\n        'bigint': 'NUMBER',\n        'float': 'FLOAT',\n        'double': 'BINARY_DOUBLE',\n        'decimal': 'NUMERIC(%(precision)s,%(scale)s)',\n        'date': 'DATE',\n        'time': 'CHAR(8)',\n        'datetime': 'DATE',\n        'id': 'NUMBER PRIMARY KEY',\n        'reference': 'NUMBER, CONSTRAINT %(constraint_name)s FOREIGN KEY (%(field_name)s) REFERENCES %(foreign_key)s ON DELETE %(on_delete_action)s',\n        'list:integer': 'CLOB',\n        'list:string': 'CLOB',\n        'list:reference': 'CLOB',\n        'big-id': 'NUMBER PRIMARY KEY',\n        'big-reference': 'NUMBER, CONSTRAINT %(constraint_name)s FOREIGN KEY (%(field_name)s) REFERENCES %(foreign_key)s ON DELETE %(on_delete_action)s',\n        'reference FK': ', CONSTRAINT FK_%(constraint_name)s FOREIGN KEY (%(field_name)s) REFERENCES %(foreign_key)s ON DELETE %(on_delete_action)s',\n        'reference TFK': ' CONSTRAINT FK_%(foreign_table)s_PK FOREIGN KEY (%(field_name)s) REFERENCES %(foreign_table)s (%(foreign_key)s) ON DELETE %(on_delete_action)s',\n        }\n\n\n    def trigger_name(self,tablename):\n        return '%s_trigger' % tablename\n\n    def LEFT_JOIN(self):\n        return 'LEFT OUTER JOIN'\n\n    def RANDOM(self):\n        return 'dbms_random.value'\n\n    def NOT_NULL(self,default,field_type):\n        return 'DEFAULT %s NOT NULL' % self.represent(default,field_type)\n\n    def REGEXP(self, first, second):\n        return 'REGEXP_LIKE(%s, %s)' % (self.expand(first),\n                                        self.expand(second, 'string'))\n\n    def _drop(self,table,mode):\n        sequence_name = table._sequence_name\n        return ['DROP TABLE %s %s;' % (table.sqlsafe, mode), 'DROP SEQUENCE %s;' % sequence_name]\n\n    def select_limitby(self, sql_s, sql_f, sql_t, sql_w, sql_o, limitby):\n        if limitby:\n            (lmin, lmax) = limitby\n            if len(sql_w) > 1:\n                sql_w_row = sql_w + ' AND w_row > %i' % lmin\n            else:\n                sql_w_row = 'WHERE w_row > %i' % lmin\n            return 'SELECT %s %s FROM (SELECT w_tmp.*, ROWNUM w_row FROM (SELECT %s FROM %s%s%s) w_tmp WHERE ROWNUM<=%i) %s %s %s;' % (sql_s, sql_f, sql_f, sql_t, sql_w, sql_o, lmax, sql_t, sql_w_row, sql_o)\n        return 'SELECT %s %s FROM %s%s%s;' % (sql_s, sql_f, sql_t, sql_w, sql_o)\n\n    def constraint_name(self, tablename, fieldname):\n        constraint_name = BaseAdapter.constraint_name(self, tablename, fieldname)\n        if len(constraint_name)>30:\n            constraint_name = '%s_%s__constraint' % (tablename[:10], fieldname[:7])\n        return constraint_name\n\n    def represent_exceptions(self, obj, fieldtype):\n        if fieldtype == 'blob':\n            obj = base64.b64encode(str(obj))\n            return \":CLOB('%s')\" % obj\n        elif fieldtype == 'date':\n            if isinstance(obj, (datetime.date, datetime.datetime)):\n                obj = obj.isoformat()[:10]\n            else:\n                obj = str(obj)\n            return \"to_date('%s','yyyy-mm-dd')\" % obj\n        elif fieldtype == 'datetime':\n            if isinstance(obj, datetime.datetime):\n                obj = obj.isoformat()[:19].replace('T',' ')\n            elif isinstance(obj, datetime.date):\n                obj = obj.isoformat()[:10]+' 00:00:00'\n            else:\n                obj = str(obj)\n            return \"to_date('%s','yyyy-mm-dd hh24:mi:ss')\" % obj\n        return None\n\n    def __init__(self,db,uri,pool_size=0,folder=None,db_codec ='UTF-8',\n                 credential_decoder=IDENTITY, driver_args={},\n                 adapter_args={}, do_connect=True, after_connection=None):\n        self.db = db\n        self.dbengine = \"oracle\"\n        self.uri = uri\n        if do_connect: self.find_driver(adapter_args,uri)\n        self.pool_size = pool_size\n        self.folder = folder\n        self.db_codec = db_codec\n        self._after_connection = after_connection\n        self.find_or_make_work_folder()\n        ruri = uri.split('://',1)[1]\n        if not 'threaded' in driver_args:\n            driver_args['threaded']=True\n        def connector(uri=ruri,driver_args=driver_args):\n            return self.driver.connect(uri,**driver_args)\n        self.connector = connector\n        if do_connect: self.reconnect()\n\n    def after_connection(self):\n        self.execute(\"ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';\")\n        self.execute(\"ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS';\")\n\n    oracle_fix = re.compile(\"[^']*('[^']*'[^']*)*\\:(?P<clob>CLOB\\('([^']+|'')*'\\))\")\n\n    def execute(self, command, args=None):\n        args = args or []\n        i = 1\n        while True:\n            m = self.oracle_fix.match(command)\n            if not m:\n                break\n            command = command[:m.start('clob')] + str(i) + command[m.end('clob'):]\n            args.append(m.group('clob')[6:-2].replace(\"''\", \"'\"))\n            i += 1\n        if command[-1:]==';':\n            command = command[:-1]\n        return self.log_execute(command, args)\n\n    def create_sequence_and_triggers(self, query, table, **args):\n        tablename = table._rname or table._tablename\n        id_name = table._id.name\n        sequence_name = table._sequence_name\n        trigger_name = table._trigger_name\n        self.execute(query)\n        self.execute('CREATE SEQUENCE %s START WITH 1 INCREMENT BY 1 NOMAXVALUE MINVALUE -1;' % sequence_name)\n        self.execute(\"\"\"\n            CREATE OR REPLACE TRIGGER %(trigger_name)s BEFORE INSERT ON %(tablename)s FOR EACH ROW\n            DECLARE\n                curr_val NUMBER;\n                diff_val NUMBER;\n                PRAGMA autonomous_transaction;\n            BEGIN\n                IF :NEW.%(id)s IS NOT NULL THEN\n                    EXECUTE IMMEDIATE 'SELECT %(sequence_name)s.nextval FROM dual' INTO curr_val;\n                    diff_val := :NEW.%(id)s - curr_val - 1;\n                    IF diff_val != 0 THEN\n                      EXECUTE IMMEDIATE 'alter sequence %(sequence_name)s increment by '|| diff_val;\n                      EXECUTE IMMEDIATE 'SELECT %(sequence_name)s.nextval FROM dual' INTO curr_val;\n                      EXECUTE IMMEDIATE 'alter sequence %(sequence_name)s increment by 1';\n                    END IF;\n                END IF;\n                SELECT %(sequence_name)s.nextval INTO :NEW.%(id)s FROM DUAL;\n            END;\n        \"\"\" % dict(trigger_name=trigger_name, tablename=tablename,\n                   sequence_name=sequence_name,id=id_name))\n\n    def lastrowid(self,table):\n        sequence_name = table._sequence_name\n        self.execute('SELECT %s.currval FROM dual;' % sequence_name)\n        return long(self.cursor.fetchone()[0])\n\n    #def parse_value(self, value, field_type, blob_decode=True):\n    #    if blob_decode and isinstance(value, cx_Oracle.LOB):\n    #        try:\n    #            value = value.read()\n    #        except self.driver.ProgrammingError:\n    #            # After a subsequent fetch the LOB value is not valid anymore\n    #            pass\n    #    return BaseAdapter.parse_value(self, value, field_type, blob_decode)\n\n    def _fetchall(self):\n        if any(x[1]==cx_Oracle.LOB for x in self.cursor.description):\n            return [tuple([(c.read() if type(c) == cx_Oracle.LOB else c) \\\n                               for c in r]) for r in self.cursor]\n        else:\n            return self.cursor.fetchall()\n\n    def sqlsafe_table(self, tablename, ot=None):\n        if ot is not None:\n            return (self.QUOTE_TEMPLATE + ' ' \\\n                    + self.QUOTE_TEMPLATE) % (ot, tablename)\n        return self.QUOTE_TEMPLATE % tablename\n", "path": "gluon/dal/adapters/oracle.py"}]}