def query(self, query): """ Run a statement on the database directly, allowing for the execution of arbitrary read/write queries. A query can either be a plain text string, or a `SQLAlchemy expression <http://docs.sqlalchemy.org/ru/latest/core/tutorial.html#selecting>`_. The returned iterator will yield each result sequentially. :: res = db.query('SELECT user, COUNT(*) c FROM photos GROUP BY user') for row in res: print row['user'], row['c'] """ return ResultIter(self.executable.execute(query))
def find(self, _limit=None, _offset=0, _step=5000, order_by='id', return_count=False, **_filter): """ Performs a simple search on the table. Simply pass keyword arguments as ``filter``. :: results = table.find(country='France') results = table.find(country='France', year=1980) Using ``_limit``:: # just return the first 10 rows results = table.find(country='France', _limit=10) You can sort the results by single or multiple columns. Append a minus sign to the column name for descending order:: # sort results by a column 'year' results = table.find(country='France', order_by='year') # return all rows sorted by multiple columns (by year in descending order) results = table.find(order_by=['country', '-year']) For more complex queries, please use :py:meth:`db.query() <dataset.Database.query>` instead.""" self._check_dropped() if not isinstance(order_by, (list, tuple)): order_by = [order_by] order_by = [o for o in order_by if (o.startswith('-') and o[1:] or o) in self.table.columns] order_by = [self._args_to_order_by(o) for o in order_by] args = self._args_to_clause(_filter, ensure=False) # query total number of rows first count_query = alias(self.table.select(whereclause=args, limit=_limit, offset=_offset), name='count_query_alias').count() rp = self.database.executable.execute(count_query) total_row_count = rp.fetchone()[0] if return_count: return total_row_count if _limit is None: _limit = total_row_count if _step is None or _step is False or _step == 0: _step = total_row_count query = self.table.select(whereclause=args, limit=_limit, offset=_offset, order_by=order_by) return ResultIter(self.database.executable.execute(query), row_type=self.database.row_type, step=_step)
def find(self, *_clauses, **kwargs): """ Perform a simple search on the table. Simply pass keyword arguments as ``filter``. :: results = table.find(country='France') results = table.find(country='France', year=1980) Using ``_limit``:: # just return the first 10 rows results = table.find(country='France', _limit=10) You can sort the results by single or multiple columns. Append a minus sign to the column name for descending order:: # sort results by a column 'year' results = table.find(country='France', order_by='year') # return all rows sorted by multiple columns (by year in descending order) results = table.find(order_by=['country', '-year']) For more complex queries, please use :py:meth:`db.query() <dataset.Database.query>` instead. """ _limit = kwargs.pop('_limit', None) _offset = kwargs.pop('_offset', 0) _step = kwargs.pop('_step', 5000) order_by = kwargs.pop('order_by', None) self._check_dropped() order_by = self._args_to_order_by(order_by) args = self._args_to_clause(kwargs, ensure=False, clauses=_clauses) if _step is False or _step == 0: _step = None query = self.table.select(whereclause=args, limit=_limit, offset=_offset) if len(order_by): query = query.order_by(*order_by) return ResultIter(self.database.executable.execute(query), row_type=self.database.row_type, step=_step)
def query(self, query, **kw): """ Run a statement on the database directly, allowing for the execution of arbitrary read/write queries. A query can either be a plain text string, or a `SQLAlchemy expression <http://docs.sqlalchemy.org/en/latest/core/tutorial.html#selecting>`_. If a plain string is passed in, it will be converted to an expression automatically. Keyword arguments will be used for parameter binding. See the `SQLAlchemy documentation <http://docs.sqlalchemy.org/en/rel_0_9/core/connections.html#sqlalchemy.engine.Connection.execute>`_ for details. The returned iterator will yield each result sequentially. :: res = db.query('SELECT user, COUNT(*) c FROM photos GROUP BY user') for row in res: print(row['user'], row['c']) """ if isinstance(query, six.string_types): query = text(query) return ResultIter(self.executable.execute(query, **kw))
def find(self, _limit=None, _offset=0, _step=5000, order_by='id', **_filter): """ Performs a simple search on the table. Simply pass keyword arguments as ``filter``. :: results = table.find(country='France') results = table.find(country='France', year=1980) Using ``_limit``:: # just return the first 10 rows results = table.find(country='France', _limit=10) You can sort the results by single or multiple columns. Append a minus sign to the column name for descending order:: # sort results by a column 'year' results = table.find(country='France', order_by='year') # return all rows sorted by multiple columns (by year in descending order) results = table.find(order_by=['country', '-year']) By default :py:meth:`find() <dataset.Table.find>` will break the query into chunks of ``_step`` rows to prevent huge tables from being loaded into memory at once. For more complex queries, please use :py:meth:`db.query() <dataset.Database.query>` instead.""" self._check_dropped() if isinstance(order_by, (str, unicode)): order_by = [order_by] order_by = filter(lambda o: o in self.table.columns, order_by) order_by = [self._args_to_order_by(o) for o in order_by] args = self._args_to_clause(_filter) # query total number of rows first count_query = self.table.count(whereclause=args, limit=_limit, offset=_offset) rp = self.database.executable.execute(count_query) total_row_count = rp.fetchone()[0] if _step is None or _step is False or _step == 0: _step = total_row_count if total_row_count > _step and len(order_by) == 0: _step = total_row_count log.warn( "query cannot be broken into smaller sections because it is unordered" ) queries = [] for i in count(): qoffset = _offset + (_step * i) qlimit = _step if _limit is not None: qlimit = min(_limit - (_step * i), _step) if qlimit <= 0: break if qoffset > total_row_count: break queries.append( self.table.select(whereclause=args, limit=qlimit, offset=qoffset, order_by=order_by)) return ResultIter( (self.database.executable.execute(q) for q in queries))