def start(self, database_name, user, readonly=False, context=None, close=False, autocommit=False): ''' Start transaction ''' Database = backend.get('Database') assert self.user is None assert self.database is None assert self.cursor is None assert self.close is None assert self.context is None if not database_name: database = Database().connect() else: database = Database(database_name).connect() Flavor.set(Database.flavor) cursor = database.cursor(readonly=readonly, autocommit=autocommit) self.user = user self.database = database self.cursor = cursor self.close = close self.context = context or {} self.create_records = {} self.delete_records = {} self.delete = {} self.timestamp = {} self.counter = 0 return _TransactionManager()
def work(options): Flavor.set(backend.Database.flavor) if not config.getboolean('queue', 'worker', default=False): return try: processes = options.processes or cpu_count() except NotImplementedError: processes = 1 logger.info("start %d workers", processes) mpool = MPool(processes, initializer, (options, ), options.maxtasksperchild) queues = [Queue(pool, mpool) for pool in initializer(options, False)] tasks = TaskList() timeout = options.timeout try: while True: while len(tasks.filter()) >= processes: time.sleep(0.1) for queue in queues: task_id, next_ = queue.pull(options.name) timeout = min(next_ or options.timeout, timeout, options.timeout) if task_id: tasks.append(queue.run(task_id)) break else: connections = [q.connection for q in queues] connections, _, _ = select.select(connections, [], [], timeout) for connection in connections: connection.poll() while connection.notifies: connection.notifies.pop(0) except KeyboardInterrupt: mpool.close()
def test_select_limit_offset(self): query = self.table.select(limit=50, offset=10) self.assertEqual(str(query), 'SELECT * FROM "t" AS "a" LIMIT 50 OFFSET 10') self.assertEqual(query.params, ()) query.limit = None self.assertEqual(str(query), 'SELECT * FROM "t" AS "a" OFFSET 10') self.assertEqual(query.params, ()) query.offset = 0 self.assertEqual(str(query), 'SELECT * FROM "t" AS "a"') self.assertEqual(query.params, ()) flavor = Flavor(max_limit=-1) Flavor.set(flavor) try: query.offset = None self.assertEqual(str(query), 'SELECT * FROM "t" AS "a"') self.assertEqual(query.params, ()) query.offset = 0 self.assertEqual(str(query), 'SELECT * FROM "t" AS "a"') self.assertEqual(query.params, ()) query.offset = 10 self.assertEqual(str(query), 'SELECT * FROM "t" AS "a" LIMIT -1 OFFSET 10') self.assertEqual(query.params, ()) finally: Flavor.set(Flavor())
def init(self): from trytond.modules import get_module_info Flavor.set(self.flavor) with self.get_connection() as conn: cursor = conn.cursor() sql_file = os.path.join(os.path.dirname(__file__), 'init.sql') with open(sql_file) as fp: for line in fp.read().split(';'): if (len(line) > 0) and (not line.isspace()): cursor.execute(line) ir_module = Table('ir_module') ir_module_dependency = Table('ir_module_dependency') for module in ('ir', 'res'): state = 'not activated' if module in ('ir', 'res'): state = 'to activate' info = get_module_info(module) insert = ir_module.insert([ ir_module.create_uid, ir_module.create_date, ir_module.name, ir_module.state ], [[0, CurrentTimestamp(), module, state]]) cursor.execute(*insert) cursor.execute('SELECT last_insert_rowid()') module_id, = cursor.fetchone() for dependency in info.get('depends', []): insert = ir_module_dependency.insert([ ir_module_dependency.create_uid, ir_module_dependency.create_date, ir_module_dependency.module, ir_module_dependency.name, ], [[0, CurrentTimestamp(), module_id, dependency]]) cursor.execute(*insert) conn.commit()
def test_select_union_flavor(self): flavor = Flavor.get() prev = flavor.quote_character flavor.quote_character = '`' self._test_select_union_quote('`') flavor.quote_character = prev Flavor.set(flavor)
def start(self, database_name, user, readonly=False, context=None, close=False, autocommit=False): ''' Start transaction ''' Database = backend.get('Database') assert self.user is None assert self.database is None assert self.close is None assert self.context is None if not database_name: database = Database().connect() else: database = Database(database_name).connect() Flavor.set(Database.flavor) self.user = user self.database = database self.readonly = readonly self.connection = database.get_connection(readonly=readonly, autocommit=autocommit) self.close = close self.context = context or {} self.create_records = {} self.delete_records = {} self.delete = {} self.timestamp = {} self.counter = 0 self._datamanagers = [] return self
def test(self, hostname=None): Flavor.set(self.flavor) tables = [ 'ir_model', 'ir_model_field', 'ir_ui_view', 'ir_ui_menu', 'res_user', 'res_group', 'ir_module', 'ir_module_dependency', 'ir_translation', 'ir_lang', 'ir_configuration' ] sqlite_master = Table('sqlite_master') select = sqlite_master.select(sqlite_master.name) select.where = sqlite_master.type == 'table' select.where &= sqlite_master.name.in_(tables) with self._conn as conn: cursor = conn.cursor() try: cursor.execute(*select) except Exception: return False if len(cursor.fetchall()) != len(tables): return False if hostname: configuration = Table('ir_configuration') try: cursor.execute( *configuration.select(configuration.hostname)) except Exception: return False hostnames = {h for h, in cursor if h} if hostnames and hostname not in hostnames: return False return True
def test_no_as(self): query = self.table.select(self.column.as_('foo')) try: Flavor.set(Flavor(no_as=True)) self.assertEqual(str(query), 'SELECT "a"."c" "foo" FROM "t" "a"') self.assertEqual(query.params, ()) finally: Flavor.set(Flavor())
def test_no_as(self): query = self.table.select(self.table.c) try: Flavor.set(Flavor(no_as=True)) self.assertEqual(str(query), 'SELECT "a"."c" FROM "t" "a"') self.assertEqual(query.params, ()) finally: Flavor.set(Flavor())
def test_filter(self): flavor = Flavor(filter_=True) Flavor.set(flavor) try: avg = Avg(self.table.a + 1, filter_=self.table.a > 0) self.assertEqual(str(avg), 'AVG(("a" + %s)) FILTER (WHERE ("a" > %s))') self.assertEqual(avg.params, (1, 0)) finally: Flavor.set(Flavor())
def start(self, database_name, user, readonly=False, context=None, close=False, autocommit=False): ''' Start transaction ''' assert self.user is None assert self.database is None assert self.close is None assert self.context is None # Compute started_at before connect to ensure # it is strictly before all transactions started after # but it may be also before transactions started before self.started_at = self.monotonic_time() if not database_name: database = backend.Database().connect() else: database = backend.Database(database_name).connect() Flavor.set(backend.Database.flavor) self.connection = database.get_connection(readonly=readonly, autocommit=autocommit) self.user = user self.database = database self.readonly = readonly self.close = close self.context = context or {} self.create_records = {} self.delete_records = {} self.delete = {} self.trigger_records = defaultdict(set) self.timestamp = {} self.counter = 0 self._datamanagers = [] self._sub_transactions = [] self._sub_transactions_to_close = [] if database_name: from trytond.cache import Cache try: Cache.sync(self) except BaseException: self.stop(False) raise from trytond import iwc try: iwc.start(database_name) except BaseException: self.stop(False) raise return self
def test_at_time_zone_mapping(self): class MyAtTimeZone(Function): _function = 'MY_TIMEZONE' time_zone = AtTimeZone(self.table.c1, 'UTC') flavor = Flavor(function_mapping={ AtTimeZone: MyAtTimeZone, }) Flavor.set(flavor) try: self.assertEqual(str(time_zone), 'MY_TIMEZONE("c1", %s)') self.assertEqual(time_zone.params, ('UTC',)) finally: Flavor.set(Flavor())
def test_at_time_zone_mapping(self): class MyAtTimeZone(Function): _function = 'MY_TIMEZONE' time_zone = AtTimeZone(self.table.c1, 'UTC') flavor = Flavor(function_mapping={ AtTimeZone: MyAtTimeZone, }) Flavor.set(flavor) try: self.assertEqual(str(time_zone), 'MY_TIMEZONE("c1", %s)') self.assertEqual(time_zone.params, ('UTC', )) finally: Flavor.set(Flavor())
def test_no_boolean(self): true = Literal(True) false = Literal(False) self.assertEqual(str(true), '%s') self.assertEqual(true.params, (True, )) self.assertEqual(str(false), '%s') self.assertEqual(false.params, (False, )) try: Flavor.set(Flavor(no_boolean=True)) self.assertEqual(str(true), '(1 = 1)') self.assertEqual(str(false), '(1 != 1)') self.assertEqual(true.params, ()) self.assertEqual(false.params, ()) finally: Flavor.set(Flavor())
def test_mapping(self): class MyAbs(Function): _function = 'MY_ABS' params = ('test', ) abs_ = Abs(self.table.c1) flavor = Flavor(function_mapping={ Abs: MyAbs, }) Flavor.set(flavor) try: self.assertEqual(str(abs_), 'MY_ABS("c1")') self.assertEqual(abs_.params, ('test', )) finally: Flavor.set(Flavor())
def test_no_boolean(self): true = Literal(True) false = Literal(False) self.assertEqual(str(true), '%s') self.assertEqual(true.params, (True,)) self.assertEqual(str(false), '%s') self.assertEqual(false.params, (False,)) try: Flavor.set(Flavor(no_boolean=True)) self.assertEqual(str(true), '(1 = 1)') self.assertEqual(str(false), '(1 != 1)') self.assertEqual(true.params, ()) self.assertEqual(false.params, ()) finally: Flavor.set(Flavor())
def test_mapping(self): class MyAbs(Function): _function = 'MY_ABS' params = ('test',) abs_ = Abs(self.table.c1) flavor = Flavor(function_mapping={ Abs: MyAbs, }) Flavor.set(flavor) try: self.assertEqual(str(abs_), 'MY_ABS("c1")') self.assertEqual(abs_.params, ('test',)) finally: Flavor.set(Flavor())
def test_mapping(self): class MyAbs(Function): _function = 'MY_ABS' params = ('test', ) class MyOverlay(FunctionKeyword): _function = 'MY_OVERLAY' _keywords = ('', 'PLACING', 'FROM', 'FOR') class MyCurrentTime(FunctionNotCallable): _function = 'MY_CURRENT_TIME' class MyTrim(Trim): _function = 'MY_TRIM' abs_ = Abs(self.table.c1) overlay = Overlay(self.table.c1, 'test', 2) current_time = CurrentTime() trim = Trim(' test ') flavor = Flavor( function_mapping={ Abs: MyAbs, Overlay: MyOverlay, CurrentTime: MyCurrentTime, Trim: MyTrim, }) Flavor.set(flavor) try: self.assertEqual(str(abs_), 'MY_ABS("c1")') self.assertEqual(abs_.params, ('test', )) self.assertEqual(str(overlay), 'MY_OVERLAY("c1" PLACING %s FROM %s)') self.assertEqual(overlay.params, ('test', 2)) self.assertEqual(str(current_time), 'MY_CURRENT_TIME') self.assertEqual(current_time.params, ()) self.assertEqual(str(trim), 'MY_TRIM(BOTH %s FROM %s)') self.assertEqual(trim.params, ( ' ', ' test ', )) finally: Flavor.set(Flavor())
def start(self, database_name, user, readonly=False, context=None, close=False, autocommit=False, _nocache=False): ''' Start transaction ''' Database = backend.get('Database') assert self.user is None assert self.database is None assert self.close is None assert self.context is None if not database_name: database = Database().connect() else: database = Database(database_name).connect() Flavor.set(Database.flavor) self.connection = database.get_connection(readonly=readonly, autocommit=autocommit) self.user = user self.database = database self.readonly = readonly self.close = close self.context = context or {} self.create_records = {} self.delete_records = {} self.delete = {} self.timestamp = {} self.counter = 0 self._datamanagers = [] self._sub_transactions = [] self._nocache = _nocache if not _nocache: from trytond.cache import Cache try: Cache.clean(database.name) except BaseException: self.stop(False) raise return self
def test_select_offset_fetch(self): try: Flavor.set(Flavor(limitstyle='fetch')) query = self.table.select(limit=50, offset=10) self.assertEqual( str(query), 'SELECT * FROM "t" AS "a" ' 'OFFSET (10) ROWS FETCH FIRST (50) ROWS ONLY') self.assertEqual(query.params, ()) query.limit = None self.assertEqual(str(query), 'SELECT * FROM "t" AS "a" OFFSET (10) ROWS') self.assertEqual(query.params, ()) query.offset = 0 self.assertEqual(str(query), 'SELECT * FROM "t" AS "a"') self.assertEqual(query.params, ()) finally: Flavor.set(Flavor())
def test_no_null_ordering(self): try: Flavor.set(Flavor(null_ordering=False)) exp = NullsFirst(self.column) self.assertEqual(str(exp), 'CASE WHEN ("c" IS NULL) THEN %s ELSE %s END ASC, "c"') self.assertEqual(exp.params, (0, 1)) exp = NullsFirst(Desc(self.column)) self.assertEqual(str(exp), 'CASE WHEN ("c" IS NULL) THEN %s ELSE %s END ASC, "c" DESC') self.assertEqual(exp.params, (0, 1)) exp = NullsLast(Literal(2)) self.assertEqual(str(exp), 'CASE WHEN (%s IS NULL) THEN %s ELSE %s END ASC, %s') self.assertEqual(exp.params, (2, 1, 0, 2)) finally: Flavor.set(Flavor())
def test_select_offset_fetch(self): try: Flavor.set(Flavor(limitstyle='fetch')) query = self.table.select(limit=50, offset=10) self.assertEqual(str(query), 'SELECT * FROM "t" AS "a" ' 'OFFSET (10) ROWS FETCH FIRST (50) ROWS ONLY') self.assertEqual(query.params, ()) query.limit = None self.assertEqual(str(query), 'SELECT * FROM "t" AS "a" OFFSET (10) ROWS') self.assertEqual(query.params, ()) query.offset = 0 self.assertEqual(str(query), 'SELECT * FROM "t" AS "a"') self.assertEqual(query.params, ()) finally: Flavor.set(Flavor())
def test_mapping(self): class MyAbs(Function): _function = 'MY_ABS' params = ('test',) class MyOverlay(FunctionKeyword): _function = 'MY_OVERLAY' _keywords = ('', 'PLACING', 'FROM', 'FOR') class MyCurrentTime(FunctionNotCallable): _function = 'MY_CURRENT_TIME' class MyTrim(Trim): _function = 'MY_TRIM' abs_ = Abs(self.table.c1) overlay = Overlay(self.table.c1, 'test', 2) current_time = CurrentTime() trim = Trim(' test ') flavor = Flavor(function_mapping={ Abs: MyAbs, Overlay: MyOverlay, CurrentTime: MyCurrentTime, Trim: MyTrim, }) Flavor.set(flavor) try: self.assertEqual(str(abs_), 'MY_ABS("c1")') self.assertEqual(abs_.params, ('test',)) self.assertEqual(str(overlay), 'MY_OVERLAY("c1" PLACING %s FROM %s)') self.assertEqual(overlay.params, ('test', 2)) self.assertEqual(str(current_time), 'MY_CURRENT_TIME') self.assertEqual(current_time.params, ()) self.assertEqual(str(trim), 'MY_TRIM(BOTH %s FROM %s)') self.assertEqual(trim.params, (' ', ' test ',)) finally: Flavor.set(Flavor())
def work(options): Flavor.set(backend.Database.flavor) if not config.getboolean('queue', 'worker', default=False): return try: processes = options.processes or cpu_count() except NotImplementedError: processes = 1 logger.info("start %d workers", processes) mpool = MPool( processes, initializer, (options.database_names,), options.maxtasksperchild) queues = [Queue(name, mpool) for name in options.database_names] tasks = TaskList() timeout = options.timeout selector = selectors.DefaultSelector() for queue in queues: selector.register(queue.connection, selectors.EVENT_READ) try: while True: while len(tasks.filter()) >= processes: time.sleep(0.1) for queue in queues: task_id, next_ = queue.pull(options.name) timeout = min( next_ or options.timeout, timeout, options.timeout) if task_id: tasks.append(queue.run(task_id)) break else: for key, _ in selector.select(timeout=timeout): connection = key.fileobj connection.poll() while connection.notifies: connection.notifies.pop(0) except KeyboardInterrupt: mpool.close() finally: selector.close()
def test_no_null_ordering(self): try: Flavor.set(Flavor(null_ordering=False)) exp = NullsFirst(self.column) self.assertEqual( str(exp), 'CASE WHEN ("c" IS NULL) THEN %s ELSE %s END ASC, "c"') self.assertEqual(exp.params, (0, 1)) exp = NullsFirst(Desc(self.column)) self.assertEqual( str(exp), 'CASE WHEN ("c" IS NULL) THEN %s ELSE %s END ASC, "c" DESC') self.assertEqual(exp.params, (0, 1)) exp = NullsLast(Literal(2)) self.assertEqual( str(exp), 'CASE WHEN (%s IS NULL) THEN %s ELSE %s END ASC, %s') self.assertEqual(exp.params, (2, 1, 0, 2)) finally: Flavor.set(Flavor())
def test_mod_paramstyle(self): flavor = Flavor(paramstyle='format') Flavor.set(flavor) try: mod = Mod(self.table.c1, self.table.c2) self.assertEqual(str(mod), '("c1" %% "c2")') self.assertEqual(mod.params, ()) finally: Flavor.set(Flavor()) flavor = Flavor(paramstyle='qmark') Flavor.set(flavor) try: mod = Mod(self.table.c1, self.table.c2) self.assertEqual(str(mod), '("c1" % "c2")') self.assertEqual(mod.params, ()) finally: Flavor.set(Flavor())
def test_not_ilike(self): flavor = Flavor(ilike=True) Flavor.set(flavor) try: for like in [NotILike(self.table.c1, 'foo'), ~self.table.c1.ilike('foo')]: self.assertEqual(str(like), '("c1" NOT ILIKE %s)') self.assertEqual(like.params, ('foo',)) finally: Flavor.set(Flavor()) flavor = Flavor(ilike=False) Flavor.set(flavor) try: like = NotILike(self.table.c1, 'foo') self.assertEqual(str(like), '(UPPER("c1") NOT LIKE UPPER(%s))') self.assertEqual(like.params, ('foo',)) finally: Flavor.set(Flavor())
def test_ilike(self): flavor = Flavor(ilike=True) Flavor.set(flavor) try: for like in [ILike(self.table.c1, 'foo'), self.table.c1.ilike('foo'), ~NotILike(self.table.c1, 'foo')]: self.assertEqual(str(like), '("c1" ILIKE %s)') self.assertEqual(like.params, ('foo',)) finally: Flavor.set(Flavor()) flavor = Flavor(ilike=False) Flavor.set(flavor) try: like = ILike(self.table.c1, 'foo') self.assertEqual(str(like), '("c1" LIKE %s)') self.assertEqual(like.params, ('foo',)) finally: Flavor.set(Flavor())
def test_ilike(self): flavor = Flavor(ilike=True) Flavor.set(flavor) try: for like in [ ILike(self.table.c1, 'foo'), self.table.c1.ilike('foo'), ~NotILike(self.table.c1, 'foo') ]: self.assertEqual(str(like), '("c1" ILIKE %s)') self.assertEqual(like.params, ('foo', )) finally: Flavor.set(Flavor()) flavor = Flavor(ilike=False) Flavor.set(flavor) try: like = ILike(self.table.c1, 'foo') self.assertEqual(str(like), '("c1" LIKE %s)') self.assertEqual(like.params, ('foo', )) finally: Flavor.set(Flavor())
def test_select_rownum(self): try: Flavor.set(Flavor(limitstyle='rownum')) query = self.table.select(limit=50, offset=10) self.assertEqual( str(query), 'SELECT "a".* FROM (' 'SELECT "b".*, ROWNUM AS "rnum" FROM (' 'SELECT * FROM "t" AS "c") AS "b" ' 'WHERE (ROWNUM <= %s)) AS "a" ' 'WHERE ("rnum" > %s)') self.assertEqual(query.params, (60, 10)) query = self.table.select(self.table.c1.as_('col1'), self.table.c2.as_('col2'), limit=50, offset=10) self.assertEqual( str(query), 'SELECT "a"."col1", "a"."col2" FROM (' 'SELECT "b"."col1", "b"."col2", ROWNUM AS "rnum" FROM (' 'SELECT "c"."c1" AS "col1", "c"."c2" AS "col2" ' 'FROM "t" AS "c") AS "b" ' 'WHERE (ROWNUM <= %s)) AS "a" ' 'WHERE ("rnum" > %s)') self.assertEqual(query.params, (60, 10)) subquery = query.select(query.col1, query.col2) self.assertEqual( str(subquery), 'SELECT "a"."col1", "a"."col2" FROM (' 'SELECT "b"."col1", "b"."col2" FROM (' 'SELECT "a"."col1", "a"."col2", ROWNUM AS "rnum" ' 'FROM (' 'SELECT "c"."c1" AS "col1", "c"."c2" AS "col2" ' 'FROM "t" AS "c") AS "a" ' 'WHERE (ROWNUM <= %s)) AS "b" ' 'WHERE ("rnum" > %s)) AS "a"') # XXX alias of query is reused but not a problem # as it is hidden in subquery self.assertEqual(query.params, (60, 10)) query = self.table.select(limit=50, offset=10, order_by=[self.table.c]) self.assertEqual( str(query), 'SELECT "a".* FROM (' 'SELECT "b".*, ROWNUM AS "rnum" FROM (' 'SELECT * FROM "t" AS "c" ORDER BY "c"."c") AS "b" ' 'WHERE (ROWNUM <= %s)) AS "a" ' 'WHERE ("rnum" > %s)') self.assertEqual(query.params, (60, 10)) query = self.table.select(limit=50) self.assertEqual( str(query), 'SELECT "a".* FROM (' 'SELECT * FROM "t" AS "b") AS "a" ' 'WHERE (ROWNUM <= %s)') self.assertEqual(query.params, (50, )) query = self.table.select(offset=10) self.assertEqual( str(query), 'SELECT "a".* FROM (' 'SELECT "b".*, ROWNUM AS "rnum" FROM (' 'SELECT * FROM "t" AS "c") AS "b") AS "a" ' 'WHERE ("rnum" > %s)') self.assertEqual(query.params, (10, )) query = self.table.select(self.table.c.as_('col'), where=self.table.c >= 20, limit=50, offset=10) self.assertEqual( str(query), 'SELECT "a"."col" FROM (' 'SELECT "b"."col", ROWNUM AS "rnum" FROM (' 'SELECT "c"."c" AS "col" FROM "t" AS "c" ' 'WHERE ("c"."c" >= %s)) AS "b" ' 'WHERE (ROWNUM <= %s)) AS "a" ' 'WHERE ("rnum" > %s)') self.assertEqual(query.params, (20, 60, 10)) finally: Flavor.set(Flavor())
def test_select_rownum(self): try: Flavor.set(Flavor(limitstyle='rownum')) query = self.table.select(limit=50, offset=10) self.assertEqual(str(query), 'SELECT "a".* FROM (' 'SELECT "b".*, ROWNUM AS "rnum" FROM (' 'SELECT * FROM "t" AS "c") AS "b" ' 'WHERE (ROWNUM <= %s)) AS "a" ' 'WHERE ("rnum" > %s)') self.assertEqual(query.params, (60, 10)) query = self.table.select( self.table.c1.as_('col1'), self.table.c2.as_('col2'), limit=50, offset=10) self.assertEqual(str(query), 'SELECT "a"."col1", "a"."col2" FROM (' 'SELECT "b"."col1", "b"."col2", ROWNUM AS "rnum" FROM (' 'SELECT "c"."c1" AS "col1", "c"."c2" AS "col2" ' 'FROM "t" AS "c") AS "b" ' 'WHERE (ROWNUM <= %s)) AS "a" ' 'WHERE ("rnum" > %s)') self.assertEqual(query.params, (60, 10)) subquery = query.select(query.col1, query.col2) self.assertEqual(str(subquery), 'SELECT "a"."col1", "a"."col2" FROM (' 'SELECT "b"."col1", "b"."col2" FROM (' 'SELECT "a"."col1", "a"."col2", ROWNUM AS "rnum" ' 'FROM (' 'SELECT "c"."c1" AS "col1", "c"."c2" AS "col2" ' 'FROM "t" AS "c") AS "a" ' 'WHERE (ROWNUM <= %s)) AS "b" ' 'WHERE ("rnum" > %s)) AS "a"') # XXX alias of query is reused but not a problem # as it is hidden in subquery self.assertEqual(query.params, (60, 10)) query = self.table.select(limit=50, offset=10, order_by=[self.table.c]) self.assertEqual(str(query), 'SELECT "a".* FROM (' 'SELECT "b".*, ROWNUM AS "rnum" FROM (' 'SELECT * FROM "t" AS "c" ORDER BY "c"."c") AS "b" ' 'WHERE (ROWNUM <= %s)) AS "a" ' 'WHERE ("rnum" > %s)') self.assertEqual(query.params, (60, 10)) query = self.table.select(limit=50) self.assertEqual(str(query), 'SELECT "a".* FROM (' 'SELECT * FROM "t" AS "b") AS "a" ' 'WHERE (ROWNUM <= %s)') self.assertEqual(query.params, (50,)) query = self.table.select(offset=10) self.assertEqual(str(query), 'SELECT "a".* FROM (' 'SELECT "b".*, ROWNUM AS "rnum" FROM (' 'SELECT * FROM "t" AS "c") AS "b") AS "a" ' 'WHERE ("rnum" > %s)') self.assertEqual(query.params, (10,)) query = self.table.select(self.table.c.as_('col'), where=self.table.c >= 20, limit=50, offset=10) self.assertEqual(str(query), 'SELECT "a"."col" FROM (' 'SELECT "b"."col", ROWNUM AS "rnum" FROM (' 'SELECT "c"."c" AS "col" FROM "t" AS "c" ' 'WHERE ("c"."c" >= %s)) AS "b" ' 'WHERE (ROWNUM <= %s)) AS "a" ' 'WHERE ("rnum" > %s)') self.assertEqual(query.params, (20, 60, 10)) finally: Flavor.set(Flavor())