Skip to content
This repository has been archived by the owner on May 13, 2019. It is now read-only.

Commit

Permalink
Add BETWEEN SQL Operator
Browse files Browse the repository at this point in the history
* Creates `BetweenBase` orm.operators
* Creates `Between` and `NotBetween` orm.operators
* Adds `isin` operators to schema.column
* Adds `nbetween` operator to schema.column
* Adds `between` operator to schema.column
  • Loading branch information
marcoceppi committed Mar 24, 2019
1 parent 9bdb490 commit 4268672
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 0 deletions.
36 changes: 36 additions & 0 deletions asyncqlio/orm/operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,42 @@ def generate_sql(self, emitter: typing.Callable[[str], str]):
return OperatorResponse(sql, params)


class BetweenBase(BaseOperator):
"""
A helper class that implements easy generation of between comparison-based operators.
To customize the operator provided, set the value of ``operator`` in the class body.
"""

op = None

def __init__(self, column: 'md_column.Column', min: typing.Any, max: typing.Any):
self.column = column
self.min = min
self.max = max

def generate_sql(self, emitter: typing.Callable[[str], str]):
# generate a dict of params
params = {}
l = []

for p in ['min', 'max']:
emitted, name = emitter()
params[name] = getattr(self, p)
l.append(emitted)

sql = '{} {} {}'.format(self.column.quoted_fullname, op, ' AND '.join(l))
return OperatorResponse(sql, params)


class Between(BetweenBase):
op = 'BETWEEN'


class NotBetween(BetweenBase):
op = 'NOT BETWEEN'


class ComparisonOp(ColumnValueMixin, BaseOperator):
"""
A helper class that implements easy generation of comparison-based operators.
Expand Down
18 changes: 18 additions & 0 deletions asyncqlio/orm/schema/column.py
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,24 @@ def eq(self, other) -> 'md_operators.Eq':
"""
return md_operators.Eq(self, other)

def isin(self, other) -> 'md_operators.In':
"""
Checks if this column is in supplied list
"""
return md_operators.In(self, other)

def between(self, min, max) -> 'md_operators.Between':
"""
Checks if this column is between the min and max value
"""
return md_operators.Between(self, min, max)

def nbetween(self, min, max) -> 'md_operators.NotBetween':
"""
Checks if this column is not between the min and max value
"""
return md_operators.NotBetween(self, min, max)

def ne(self, other) -> 'md_operators.NEq':
"""
Checks if this column is not equal to something else.
Expand Down
20 changes: 20 additions & 0 deletions tests/test_3session.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,23 @@ async def test_numeric_decimal(db: DatabaseInterface, table: Table):

assert str(res.lat) == "12.010"
assert str(res.lon) == "12.01"


async def test_between(db: DatabaseInterface, table: Table):
test_ids = [210, 211, 212]

async with db.get_session() as sess:
await sess.insert.rows(table(id=210, name="between0", email="0", lat=55.010, lon=55.010)).run()
await sess.insert.rows(table(id=211, name="between1", email="1", lat=55.110, lon=55.110)).run()
await sess.insert.rows(table(id=212, name="between2", email="2", lat=55.110, lon=55.110)).run()

async with db.get_session() as sess:
res_first = await sess.select(table).where(table.id.between(200, 220)).first()
res_all = await sess.select(table).where(table.id.between(200, 220)).all()
res_not = await sess.select(table).where(table.id.nbetween(200, 220)).first()

all = [r async for r in res_all]

assert res_first.id == 210
assert len(all) == 3
assert res_not not in test_ids

0 comments on commit 4268672

Please sign in to comment.