OmniSciDB  72c90bc290
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
cursor.py
Go to the documentation of this file.
2 from .exceptions import _translate_exception
3 from ._parsers import _bind_parameters, _extract_description, _extract_col_vals
4 
5 
6 class Cursor:
7  """A database cursor."""
8 
9  def __init__(self, connection):
10  # XXX: supposed to share state between cursors of the same connection
11  self.connection = connection
12  self.rowcount = -1
13  self._description = None
14  self._arraysize = 1
15  self._result = None
16  self._result_set = None
17  if connection:
18  connection.register_runtime_udfs()
19 
20  def __iter__(self):
21  if self.result_set is None:
22  return iter([])
23  return self.result_set
24 
25  def __enter__(self):
26  return self
27 
28  def __exit__(self, exc_type, exc_val, exc_tb):
29  self.close()
30 
31  @property
32  def description(self):
33  """
34  Read-only sequence describing columns of the result set.
35  Each column is an instance of `Description` describing
36 
37  - name
38  - type_code
39  - display_size
40  - internal_size
41  - precision
42  - scale
43  - null_ok
44 
45  We only use name, type_code, and null_ok; The rest are always ``None``
46  """
47  return self._description
48 
49  @property
50  def result_set(self):
51  return self._result_set
52 
53  @property
54  def arraysize(self):
55  """The number of rows to fetch at a time with `fetchmany`. Default 1.
56 
57  See Also
58  --------
59  fetchmany
60  """
61  return self._arraysize
62 
63  @arraysize.setter
64  def arraysize(self, value):
65  """Number of items to fetch with :func:`fetchmany`."""
66  if not isinstance(value, int):
67  raise TypeError(
68  "Value must be an integer, got {} instead".format(type(value))
69  )
70  self._arraysize = value
71 
72  def close(self):
73  """Close this cursor."""
74  # TODO
75  pass
76 
77  def execute(self, operation, parameters=None):
78  """Execute a SQL statement.
79 
80  Parameters
81  ----------
82  operation: str
83  A SQL query
84  parameters: dict
85  Parameters to substitute into ``operation``.
86 
87  Returns
88  -------
89  self : Cursor
90 
91  Examples
92  --------
93  >>> c = conn.cursor()
94  >>> c.execute("select symbol, qty from stocks")
95  >>> list(c)
96  [('RHAT', 100.0), ('IBM', 1000.0), ('MSFT', 1000.0), ('IBM', 500.0)]
97 
98  Passing in ``parameters``:
99 
100  >>> c.execute("select symbol qty from stocks where qty <= :max_qty",
101  ... parameters={"max_qty": 500})
102  [('RHAT', 100.0), ('IBM', 500.0)]
103  """
104 
105  # https://github.com/omnisci/pymapd/issues/263
106  operation = operation.strip()
107 
108  if parameters is not None:
109  operation = str(_bind_parameters(operation, parameters))
110  self.rowcount = -1
111  try:
112  result = self.connection._client.sql_execute(
113  self.connection._session,
114  operation,
115  column_format=True,
116  nonce=None,
117  first_n=-1,
118  at_most_n=-1,
119  )
120  except T.TDBException as e:
121  raise _translate_exception(e) from e
122  self._description = _extract_description(result.row_set.row_desc)
123 
124  try:
125  self.rowcount = len(result.row_set.columns[0].nulls)
126  except IndexError:
127  pass
128 
129  self._result_set = make_row_results_set(result)
130  self._result = result
131  return self
132 
133  def executemany(self, operation, parameters):
134  """Execute a SQL statement for many sets of parameters.
135 
136  Parameters
137  ----------
138  operation: str
139  parameters: list of dict
140 
141  Returns
142  -------
143  results: list of lists
144  """
145  results = [
146  list(self.execute(operation, params)) for params in parameters
147  ]
148  return results
149 
150  def fetchone(self):
151  """Fetch a single row from the results set"""
152  try:
153  return next(self.result_set)
154  except StopIteration:
155  return None
156 
157  def fetchmany(self, size=None):
158  """Fetch ``size`` rows from the results set."""
159  if size is None:
160  size = self.arraysize
161  results = [self.fetchone() for _ in range(size)]
162  return [x for x in results if x is not None]
163 
164  def fetchall(self):
165  return list(self)
166 
167  def setinputsizes(self, sizes):
168  pass
169 
170  def setoutputsizes(self, size, column=None):
171  pass
172 
173 
174 # -----------------------------------------------------------------------------
175 # Result Sets
176 # -----------------------------------------------------------------------------
177 
178 
180  """
181  Build a results set of python objects.
182 
183  Parameters
184  ----------
185  data: QueryResultSet
186 
187  Returns
188  -------
189  results: Iterator[tuple]
190  """
191 
192  if data.row_set.columns:
193  nrows = len(data.row_set.columns[0].nulls)
194  ncols = len(data.row_set.row_desc)
195  columns = [
196  _extract_col_vals(desc, col)
197  for desc, col in zip(data.row_set.row_desc, data.row_set.columns)
198  ]
199  for i in range(nrows):
200  yield tuple(columns[j][i] for j in range(ncols))
def make_row_results_set
Definition: cursor.py:179
def _extract_col_vals
Definition: _parsers.py:89
def _bind_parameters
Definition: _parsers.py:162
def _extract_description
Definition: _parsers.py:124