SP/web2py/gluon/packages/dal/pydal/dialects/google.py

191 lines
5.8 KiB
Python
Raw Permalink Normal View History

2018-10-25 15:33:07 +00:00
from .._gae import ndb
from ..adapters.google import GoogleDatastore
from ..helpers.gae import NDBDecimalProperty
from .base import NoSQLDialect
from . import dialects, sqltype_for
@dialects.register_for(GoogleDatastore)
class GoogleDatastoreDialect(NoSQLDialect):
FILTER_OPTIONS = {
'=': lambda a, b: a == b,
'>': lambda a, b: a > b,
'<': lambda a, b: a < b,
'<=': lambda a, b: a <= b,
'>=': lambda a, b: a >= b,
'!=': lambda a, b: a != b,
'in': lambda a, b: a.IN(b)
}
@sqltype_for('string')
def type_string(self):
return (lambda **kwargs: ndb.StringProperty(**kwargs))
@sqltype_for('boolean')
def type_boolean(self):
return ndb.BooleanProperty
@sqltype_for('text')
def type_text(self):
return ndb.TextProperty
@sqltype_for('json')
def type_json(self):
return self.types['text']
@sqltype_for('password')
def type_password(self):
return ndb.StringProperty
@sqltype_for('blob')
def type_blob(self):
return ndb.BlobProperty
@sqltype_for('upload')
def type_upload(self):
return self.types['password']
@sqltype_for('integer')
def type_integer(self):
return ndb.IntegerProperty
@sqltype_for('bigint')
def type_bigint(self):
return self.types['integer']
@sqltype_for('float')
def type_float(self):
return ndb.FloatProperty
@sqltype_for('double')
def type_double(self):
return self.types['float']
@sqltype_for('decimal')
def type_decimal(self):
return NDBDecimalProperty
@sqltype_for('date')
def type_date(self):
return ndb.DateProperty
@sqltype_for('time')
def type_time(self):
return ndb.TimeProperty
@sqltype_for('datetime')
def type_datetime(self):
return ndb.DateTimeProperty
@sqltype_for('id')
def type_id(self):
return None
@sqltype_for('reference')
def type_reference(self):
return ndb.IntegerProperty
@sqltype_for('list:integer')
def type_list_integer(self):
return (lambda **kwargs: ndb.IntegerProperty(
repeated=True, default=None, **kwargs))
@sqltype_for('list:string')
def type_list_string(self):
return (lambda **kwargs: ndb.StringProperty(
repeated=True, default=None, **kwargs))
@sqltype_for('list:reference')
def type_list_reference(self):
return (lambda **kwargs: ndb.IntegerProperty(
repeated=True, default=None, **kwargs))
def _and(self, first, second, query_env={}):
first = self.expand(first, query_env=query_env)
second = self.expand(second, query_env=query_env)
# none means lack of query (true)
if first == None:
return second
return ndb.AND(first, second)
def _or(self, first, second, query_env={}):
first = self.expand(first, query_env=query_env)
second = self.expand(second, query_env=query_env)
# none means lack of query (true)
if first == None or second == None:
return None
return ndb.OR(first, second)
def __gaef(self, first, op, second):
name = first.name if first.name != 'id' else 'key'
if name == 'key' and op in ('>', '!=') and second in (0, '0', None):
return None
field = getattr(first.table._tableobj, name)
value = self.adapter.represent(second, first.type, first._tablename)
return self.FILTER_OPTIONS[op](field, value)
def eq(self, first, second=None, query_env={}):
return self.__gaef(first, '=', second)
def ne(self, first, second=None, query_env={}):
return self.__gaef(first, '!=', second)
def lt(self, first, second=None, query_env={}):
return self.__gaef(first, '<', second)
def lte(self, first, second=None, query_env={}):
return self.__gaef(first, '<=', second)
def gt(self, first, second=None, query_env={}):
return self.__gaef(first, '>', second)
def gte(self, first, second=None, query_env={}):
return self.__gaef(first, '>=', second)
def invert(self, first, query_env={}):
return '-%s' % first.name
def comma(self, first, second, query_env={}):
return '%s,%s' % (first, second)
def belongs(self, first, second, query_env={}):
if not isinstance(second, (list, tuple, set)):
raise SyntaxError("Not supported")
if not isinstance(second, list):
second = list(second)
if len(second) == 0:
# return a filter which will return a null set
f = self.eq(first, 0)
f.filter_all = True
return f
return self.__gaef(first, 'in', second)
def contains(self, first, second, case_sensitive=True, query_env={}):
# silently ignoring: GAE can only do case sensitive matches!
if not first.type.startswith('list:'):
raise SyntaxError("Not supported")
return self.__gaef(first, '=', second)
def _not(self, val, query_env={}):
op, f, s = val.op, val.first, val.second
if op in [self._or, self._and]:
not_op = self._and if op == self._or else self._or
rv = not_op(self._not(f), self._not(s))
elif op == self.eq:
rv = self.__gaef(f, '!=', s)
elif op == self.ne:
rv = self.__gaef(f, '=', s)
elif op == self.lt:
rv = self.__gaef(f, '>=', s)
elif op == self.lte:
rv = self.__gaef(f, '>', s)
elif op == self.gt:
rv = self.__gaef(f, '<=', s)
elif op == self.gte:
rv = self.__gaef(f, '<', s)
else:
# TODO the IN operator must be split into a sequence of
# (field!=value) AND (field!=value) AND ...
raise NotImplementedError
return rv