|
6 | 6 | from datetime import datetime, date, timedelta
|
7 | 7 |
|
8 | 8 | import warnings
|
| 9 | +import traceback |
9 | 10 | import itertools
|
10 | 11 | import re
|
11 | 12 | import numpy as np
|
@@ -102,75 +103,122 @@ def execute(sql, con, cur=None, params=None, flavor='sqlite'):
|
102 | 103 | return pandas_sql.execute(*args)
|
103 | 104 |
|
104 | 105 |
|
105 |
| -def tquery(sql, con, cur=None, params=None, flavor='sqlite'): |
| 106 | +#------------------------------------------------------------------------------ |
| 107 | +#--- Deprecated tquery and uquery |
| 108 | + |
| 109 | +def _safe_fetch(cur): |
| 110 | + try: |
| 111 | + result = cur.fetchall() |
| 112 | + if not isinstance(result, list): |
| 113 | + result = list(result) |
| 114 | + return result |
| 115 | + except Exception as e: # pragma: no cover |
| 116 | + excName = e.__class__.__name__ |
| 117 | + if excName == 'OperationalError': |
| 118 | + return [] |
| 119 | + |
| 120 | +def tquery(sql, con=None, cur=None, retry=True): |
106 | 121 | """
|
107 |
| - Returns list of tuples corresponding to each row in given sql |
| 122 | + DEPRECATED. Returns list of tuples corresponding to each row in given sql |
108 | 123 | query.
|
109 | 124 |
|
110 | 125 | If only one column selected, then plain list is returned.
|
111 | 126 |
|
| 127 | + To obtain the same result in the future, you can use the following: |
| 128 | + |
| 129 | + >>> execute(sql, con, params).fetchall() |
| 130 | +
|
112 | 131 | Parameters
|
113 | 132 | ----------
|
114 | 133 | sql: string
|
115 | 134 | SQL query to be executed
|
116 |
| - con: SQLAlchemy engine or DBAPI2 connection (legacy mode) |
117 |
| - Using SQLAlchemy makes it possible to use any DB supported by that |
118 |
| - library. |
119 |
| - If a DBAPI2 object is given, a supported SQL flavor must also be provided |
| 135 | + con: DBAPI2 connection |
120 | 136 | cur: depreciated, cursor is obtained from connection
|
121 |
| - params: list or tuple, optional |
122 |
| - List of parameters to pass to execute method. |
123 |
| - flavor : string "sqlite", "mysql" |
124 |
| - Specifies the flavor of SQL to use. |
125 |
| - Ignored when using SQLAlchemy engine. Required when using DBAPI2 |
126 |
| - connection. |
| 137 | +
|
127 | 138 | Returns
|
128 | 139 | -------
|
129 | 140 | Results Iterable
|
| 141 | +
|
130 | 142 | """
|
131 | 143 | warnings.warn(
|
132 |
| - "tquery is depreciated, and will be removed in future versions", |
| 144 | + "tquery is depreciated, and will be removed in future versions. " |
| 145 | + "You can use ``execute(...).fetchall()`` instead.", |
133 | 146 | FutureWarning)
|
| 147 | + |
| 148 | + cur = execute(sql, con, cur=cur) |
| 149 | + result = _safe_fetch(cur) |
134 | 150 |
|
135 |
| - pandas_sql = pandasSQL_builder(con, flavor=flavor) |
136 |
| - args = _convert_params(sql, params) |
137 |
| - return pandas_sql.tquery(*args) |
| 151 | + if con is not None: |
| 152 | + try: |
| 153 | + cur.close() |
| 154 | + con.commit() |
| 155 | + except Exception as e: |
| 156 | + excName = e.__class__.__name__ |
| 157 | + if excName == 'OperationalError': # pragma: no cover |
| 158 | + print('Failed to commit, may need to restart interpreter') |
| 159 | + else: |
| 160 | + raise |
138 | 161 |
|
| 162 | + traceback.print_exc() |
| 163 | + if retry: |
| 164 | + return tquery(sql, con=con, retry=False) |
139 | 165 |
|
140 |
| -def uquery(sql, con, cur=None, params=None, engine=None, flavor='sqlite'): |
| 166 | + if result and len(result[0]) == 1: |
| 167 | + # python 3 compat |
| 168 | + result = list(lzip(*result)[0]) |
| 169 | + elif result is None: # pragma: no cover |
| 170 | + result = [] |
| 171 | + |
| 172 | + return result |
| 173 | + |
| 174 | + |
| 175 | +def uquery(sql, con=None, cur=None, retry=True, params=None): |
141 | 176 | """
|
142 |
| - Does the same thing as tquery, but instead of returning results, it |
| 177 | + DEPRECATED. Does the same thing as tquery, but instead of returning results, it |
143 | 178 | returns the number of rows affected. Good for update queries.
|
144 | 179 |
|
| 180 | + To obtain the same result in the future, you can use the following: |
| 181 | + |
| 182 | + >>> execute(sql, con).rowcount |
| 183 | +
|
145 | 184 | Parameters
|
146 | 185 | ----------
|
147 | 186 | sql: string
|
148 | 187 | SQL query to be executed
|
149 |
| - con: SQLAlchemy engine or DBAPI2 connection (legacy mode) |
150 |
| - Using SQLAlchemy makes it possible to use any DB supported by that |
151 |
| - library. |
152 |
| - If a DBAPI2 object is given, a supported SQL flavor must also be provided |
| 188 | + con: DBAPI2 connection |
153 | 189 | cur: depreciated, cursor is obtained from connection
|
154 | 190 | params: list or tuple, optional
|
155 | 191 | List of parameters to pass to execute method.
|
156 |
| - flavor : string "sqlite", "mysql" |
157 |
| - Specifies the flavor of SQL to use. |
158 |
| - Ignored when using SQLAlchemy engine. Required when using DBAPI2 |
159 |
| - connection. |
| 192 | +
|
160 | 193 | Returns
|
161 | 194 | -------
|
162 | 195 | Number of affected rows
|
| 196 | +
|
163 | 197 | """
|
164 | 198 | warnings.warn(
|
165 |
| - "uquery is depreciated, and will be removed in future versions", |
| 199 | + "uquery is depreciated, and will be removed in future versions. " |
| 200 | + "You can use ``execute(...).rowcount`` instead.", |
166 | 201 | FutureWarning)
|
167 |
| - pandas_sql = pandasSQL_builder(con, flavor=flavor) |
168 |
| - args = _convert_params(sql, params) |
169 |
| - return pandas_sql.uquery(*args) |
| 202 | + |
| 203 | + cur = execute(sql, con, cur=cur, params=params) |
| 204 | + |
| 205 | + result = cur.rowcount |
| 206 | + try: |
| 207 | + con.commit() |
| 208 | + except Exception as e: |
| 209 | + excName = e.__class__.__name__ |
| 210 | + if excName != 'OperationalError': |
| 211 | + raise |
| 212 | + |
| 213 | + traceback.print_exc() |
| 214 | + if retry: |
| 215 | + print('Looks like your connection failed, reconnecting...') |
| 216 | + return uquery(sql, con, retry=False) |
| 217 | + return result |
170 | 218 |
|
171 | 219 |
|
172 | 220 | #------------------------------------------------------------------------------
|
173 |
| -# Read and write to DataFrames |
| 221 | +#--- Read and write to DataFrames |
174 | 222 |
|
175 | 223 | def read_sql_table(table_name, con, meta=None, index_col=None,
|
176 | 224 | coerce_float=True, parse_dates=None, columns=None):
|
@@ -722,14 +770,6 @@ def execute(self, *args, **kwargs):
|
722 | 770 | """Simple passthrough to SQLAlchemy engine"""
|
723 | 771 | return self.engine.execute(*args, **kwargs)
|
724 | 772 |
|
725 |
| - def tquery(self, *args, **kwargs): |
726 |
| - result = self.execute(*args, **kwargs) |
727 |
| - return result.fetchall() |
728 |
| - |
729 |
| - def uquery(self, *args, **kwargs): |
730 |
| - result = self.execute(*args, **kwargs) |
731 |
| - return result.rowcount |
732 |
| - |
733 | 773 | def read_table(self, table_name, index_col=None, coerce_float=True,
|
734 | 774 | parse_dates=None, columns=None):
|
735 | 775 |
|
@@ -953,22 +993,6 @@ def execute(self, *args, **kwargs):
|
953 | 993 | ex = DatabaseError("Execution failed on sql: %s" % args[0])
|
954 | 994 | raise_with_traceback(ex)
|
955 | 995 |
|
956 |
| - def tquery(self, *args): |
957 |
| - cur = self.execute(*args) |
958 |
| - result = self._fetchall_as_list(cur) |
959 |
| - |
960 |
| - # This makes into tuples |
961 |
| - if result and len(result[0]) == 1: |
962 |
| - # python 3 compat |
963 |
| - result = list(lzip(*result)[0]) |
964 |
| - elif result is None: # pragma: no cover |
965 |
| - result = [] |
966 |
| - return result |
967 |
| - |
968 |
| - def uquery(self, *args): |
969 |
| - cur = self.execute(*args) |
970 |
| - return cur.rowcount |
971 |
| - |
972 | 996 | def read_sql(self, sql, index_col=None, coerce_float=True, params=None,
|
973 | 997 | parse_dates=None):
|
974 | 998 | args = _convert_params(sql, params)
|
@@ -1020,7 +1044,7 @@ def has_table(self, name):
|
1020 | 1044 | 'mysql': "SHOW TABLES LIKE '%s'" % name}
|
1021 | 1045 | query = flavor_map.get(self.flavor)
|
1022 | 1046 |
|
1023 |
| - return len(self.tquery(query)) > 0 |
| 1047 | + return len(self.execute(query).fetchall()) > 0 |
1024 | 1048 |
|
1025 | 1049 | def get_table(self, table_name):
|
1026 | 1050 | return None # not supported in Legacy mode
|
|
0 commit comments