示例#1
0
 def __init__(self,server,sitename=None,storage_path=None):
     self.server = server
     self.page_register = PageRegister(self)
     self.connection_register = ConnectionRegister(self)
     self.user_register = UserRegister(self)
     self.remotebag_handler = RemoteStoreBagHandler(self)
     self.server.daemon.register(self.remotebag_handler,'RemoteData')
     self.last_cleanup = time.time()
     self.sitename = sitename
     self.storage_path = storage_path
     self.catalog = GnrClassCatalog()
     self.maintenance = False
     self.allowed_users = None
示例#2
0
 def __init__(self,
              implementation='sqlite',
              dbname='mydb',
              host=None,
              user=None,
              password=None,
              port=None,
              main_schema=None,
              debugger=None,
              application=None,
              allow_eager_many=False,
              allow_eager_one=False):
     """This is the constructor method of the GnrSqlDb class.
     
     :param implementation: 'sqlite', 'postgres' or other sql implementations.
     :param dbname: the name for your db.
     :param host: the database server host (for sqlite is None)
     :param user: a database user's name (for sqlite is None)
     :param password: the user's password (for sqlite is None)
     :param port: the connection port (for sqlite is None)
     :param main_schema: the database main_schema. Default value is ``None``
     :param debugger: the database main_schema. Default value is ``None``
     :param application: the database main_schema. Default value is ``None``
     :param allow_eager_many: the database main_schema. Default value is ``False``
     :param allow_eager_one: the database main_schema. Default value is ``False``"""
     self.implementation = implementation
     self.dbname = dbname
     self.host = host
     self.port = port
     self.user = user
     self.password = password
     self.typeConverter = GnrClassCatalog()
     self.debugger = debugger
     self.application = application
     self.model = self.createModel()
     self.adapter = importModule('gnr.sql.adapters.gnr%s' %
                                 implementation).SqlDbAdapter(self)
     self.whereTranslator = self.adapter.getWhereTranslator()
     if main_schema is None:
         main_schema = self.adapter.defaultMainSchema()
     self.main_schema = main_schema
     self._connections = {}
     self.started = False
     self._currentEnv = {}
     self.allow_eager_one = allow_eager_one
     self.allow_eager_many = allow_eager_many
     self.stores_handler = DbStoresHandler(self)
示例#3
0
 def __init__(self, implementation='sqlite', dbname='mydb',
              host=None, user=None, password=None, port=None,
              main_schema=None, debugger=None, application=None, read_only=None,**kwargs):
     """
     This is the constructor method of the GnrSqlDb class.
     
     :param implementation: 'sqlite', 'postgres' or other sql implementations
     :param dbname: the name for your database
     :param host: the database server host (for sqlite is None)
     :param user: the username (for sqlite is None)
     :param password: the username's password (for sqlite is None)
     :param port: the connection port (for sqlite is None)
     :param main_schema: the database main schema
     :param debugger: TODO
     :param application: TODO
     """
     
     self.implementation = implementation
     self.dbname = self.dbpar(dbname)
     self.host = self.dbpar(host)
     self.port = self.dbpar(str(port) if port else None)
     self.user = self.dbpar(user)
     self.password = self.dbpar(password)
     self.read_only = read_only
     self.typeConverter = GnrClassCatalog()
     self.debugger = debugger
     self.application = application
     self.model = self.createModel()
     self.adapter = importModule('gnr.sql.adapters.gnr%s' % implementation).SqlDbAdapter(self)
     self.whereTranslator = self.adapter.getWhereTranslator()
     if main_schema is None:
         main_schema = self.adapter.defaultMainSchema()
     self.main_schema = main_schema
     self._connections = {}
     self.started = False
     self._currentEnv = {}
     self.stores_handler = DbStoresHandler(self)
示例#4
0
 def __init__(self, db):
     self.db = db
     self.catalog = GnrClassCatalog()
     self.opDict = dict([(k[3:], None) for k in dir(self)
                         if k.startswith('op_')])
示例#5
0
class GnrWhereTranslator(object):
    def __init__(self, db):
        self.db = db
        self.catalog = GnrClassCatalog()
        self.opDict = dict([(k[3:], None) for k in dir(self)
                            if k.startswith('op_')])

    def __call__(self, tblobj, wherebag, sqlArgs, customOpCbDict=None):
        if sqlArgs is None:
            sqlArgs = {}
        self.customOpCbDict = customOpCbDict
        result = self.innerFromBag(tblobj, wherebag, sqlArgs, 0)
        return '\n'.join(result)

    def opCaption(self, op, localize=False):
        h = getattr(self, 'op_%s' % op.lower(), None)
        if not h and op.startswith('not_'):
            return 'Not %s' % getattr(self, 'op_%s' % op[4:].lower()).__doc__
        result = h.__doc__
        if localize and self.db.localizer:
            result = self.db.localizer.translateText(result)
        return result

    def toText(self, tblobj, wherebag, level=0, decodeDate=False):
        result = []
        for k, node in enumerate(wherebag.getNodes()):
            attr = node.getAttr()
            value = node.getValue()
            if k:
                jc = attr.get('jc_caption', '')
            else:
                jc = ''
            negate = attr.get('not') == 'not'
            if isinstance(value, Bag):
                onecondition = ('\n' + '    ' * level).join(
                    self.toText(tblobj, value, level + 1))
                onecondition = '(\n' + '    ' * level + onecondition + '\n' + '    ' * level + ')'
            else:
                op = attr.get('op_caption')
                column = attr.get('column_caption')
                if not op or not column:
                    continue
                if decodeDate:
                    if tblobj.column(attr.get('column')).dtype in ('D', 'DH',
                                                                   'DHZ'):
                        value, op = self.decodeDates(value, op, 'D')
                        op = self.opCaption(op, localize=True)
                op = op.lower()
                onecondition = '%s %s %s' % (column, op, value)
            if onecondition:
                if negate:
                    onecondition = ' %s %s  ' % (attr.get('not_caption',
                                                          ''), onecondition)
                result.append(' %s %s' % (jc, onecondition))
        return result

    def toHtml(self, tblobj, wherebag, level=0, decodeDate=False):
        result = []
        for k, node in enumerate(wherebag.getNodes()):
            attr = node.getAttr()
            value = node.getValue()
            if k:
                jc = attr.get('jc_caption', '')
            else:
                jc = ''
            negate = attr.get('not') == 'not'
            if isinstance(value, Bag):
                onecondition = '<div class="slqnested"> %s </div>' % (
                    self.toHtml(tblobj, value, level + 1)
                )  #'(\n' + '    ' * level + onecondition + '\n' + '    ' * level + ')'
            else:
                op = attr.get('op_caption')
                column = attr.get('column_caption')
                if not op or not column:
                    continue
                if decodeDate:
                    if tblobj.column(attr.get('column')).dtype in ('D', 'DH',
                                                                   'DHZ'):
                        value, op = self.decodeDates(value, op, 'D')
                        op = self.opCaption(op, localize=True)
                op = op.lower()
                onecondition = '<span class="sqlcol">%s</span> <span class="sqlop">%s</span> <span class="sqlvalue">%s</span>' % (
                    column, op, value)
            if onecondition:
                if negate:
                    onecondition = ' <span class="sqlnot">%s</span> %s  ' % (
                        attr.get('not_caption', ''), onecondition)
                result.append(
                    '<div class="sqlcondition"> <span class="sqljc">%s</span> %s </div>'
                    % (jc, onecondition))

        return ''.join(result)

    def innerFromBag(self, tblobj, wherebag, sqlArgs, level):
        """<condition column="fattura_num" op="ISNULL" rem='senza fattura' />
        <condition column="@anagrafica.provincia" op="IN" jc='AND'>MI,FI,TO</condition>
        <group not="true::B" jc='AND'>
                <condition column="" op=""/>
                <condition column="" op="" jc='OR'/>
        </group>"""

        result = []
        for node in wherebag:
            attr = node.getAttr()
            value = node.getValue()
            if isinstance(value, basestring) and value.startswith('?'):
                value = sqlArgs.get(value[1:])
            jc = attr.get('jc', '').upper()
            if not result:
                jc = ''
            negate = attr.get('not') == 'not'
            if isinstance(value, Bag):
                onecondition = ('\n' + '    ' * level).join(
                    self.innerFromBag(tblobj, value, sqlArgs, level + 1))
                onecondition = '(\n' + '    ' * level + onecondition + '\n' + '    ' * level + ')'
            else:
                op = attr.get('op')
                column = attr.get('column')
                if not op or not column:
                    #ingnoring empty query lines
                    continue
                colobj = tblobj.column(column)
                if colobj is None:
                    raise tblobj.exception('not_existing_column',
                                           column=column)
                dtype = colobj.dtype

                if value is None and attr.get('value_caption'):
                    value = sqlArgs.pop(attr['value_caption'])
                onecondition = self.prepareCondition(column,
                                                     op,
                                                     value,
                                                     dtype,
                                                     sqlArgs,
                                                     tblobj=tblobj)

            if onecondition:
                if negate:
                    onecondition = ' NOT %s  ' % onecondition
                result.append(' %s ( %s )' % (jc, onecondition))
        return result

    def prepareCondition(self, column, op, value, dtype, sqlArgs, tblobj=None):
        if not dtype:
            dtype = tblobj.column(column).dtype
        if not column[0] in '@$':
            column = '$%s' % column
        if dtype in ('D', 'DH', 'DHZ'):
            value, op = self.decodeDates(value, op, 'D')
            if dtype == 'DH':
                column = 'CAST (%s AS date)' % column
        if not dtype in ('A', 'T') and op in ('contains', 'notcontains',
                                              'startswith', 'endswith',
                                              'regex', 'wordstart'):
            value = str(value)
            column = 'CAST (%s as text)' % column
            dtype = 'A'
        ophandler = getattr(self, 'op_%s' % op, None)
        if ophandler:
            result = ophandler(column=column,
                               value=value,
                               dtype=dtype,
                               sqlArgs=sqlArgs,
                               tblobj=tblobj)
        else:
            ophandler = self.customOpCbDict.get(op)
            assert ophandler, 'undefined ophandler'
            result = ophandler(column=column,
                               value=value,
                               dtype=dtype,
                               sqlArgs=sqlArgs,
                               whereTranslator=self,
                               tblobj=tblobj)
        return result

    def decodeDates(self, value, op, dtype):
        if op == 'isnull':
            return value, op
        if op == 'in' and ',' in value:  # is a in search with multiple (single date) arguments: don't use periods!!!
            value = ','.join([
                decodeDatePeriod(v,
                                 workdate=self.db.workdate,
                                 locale=self.db.locale,
                                 dtype=dtype) for v in value.split(',')
            ])
            return value, op

        value = decodeDatePeriod(value,
                                 workdate=self.db.workdate,
                                 locale=self.db.locale,
                                 dtype=dtype)
        mode = None
        if value.startswith(';'):
            mode = 'to'
        elif value.endswith(';'):
            mode = 'from'
        elif ';' in value:
            mode = 'period'

        if op in ('greater', 'greatereq'):  # keep the higher date
            if mode in ('period', 'to'):
                value = value.split(';')[1]
            else:
                value = value.strip(';')
        elif op in ('less', 'lesseq'):  # keep the lower date
            value = value.split(';')[0]

        else:
            # equal, between and textual operators are ignored
            # the right operator is choosen according to the value to find
            if mode == 'to':  # find data lower then value
                op = 'lesseq'
                value = value.strip(';')
            elif mode == 'from':  # find data higher then value
                op = 'greatereq'
                value = value.strip(';')
            elif mode == 'period':  # find data between period (value)
                op = 'between'
            else:  # value is a single date
                op = 'equal'
        return value, op

    def storeArgs(self, value, dtype, sqlArgs):
        if not dtype in ('A', 'T'):
            if isinstance(value, list):
                value = [self.catalog.fromText(v, dtype) for v in value]
            elif isinstance(value, basestring):
                value = self.catalog.fromText(value, dtype)
        argLbl = 'v_%i' % len(sqlArgs)
        sqlArgs[argLbl] = value
        return argLbl

    def op_startswithchars(self, column, value, dtype, sqlArgs, tblobj):
        "!!Starts with Chars"
        return self.unaccentTpl(tblobj, column, 'LIKE') % (
            column, self.storeArgs('%s%%' % value, dtype, sqlArgs))

    def op_equal(self, column, value, dtype, sqlArgs, tblobj):
        "!!Equal to"
        return self.unaccentTpl(tblobj, column, '=') % (
            column, self.storeArgs(value, dtype, sqlArgs))

    def op_startswith(self, column, value, dtype, sqlArgs, tblobj):
        "!!Starts with"
        return self.unaccentTpl(tblobj, column, 'ILIKE') % (
            column, self.storeArgs('%s%%' % value, dtype, sqlArgs))

    def op_wordstart(self, column, value, dtype, sqlArgs, tblobj):
        "!!Word start"
        value = value.replace('(', '\(').replace(')', '\)').replace(
            '[', '\[').replace(']', '\]')
        return self.unaccentTpl(tblobj, column, '~*') % (
            column, self.storeArgs('(^|\\W)%s' % value, dtype, sqlArgs))

    def op_contains(self, column, value, dtype, sqlArgs, tblobj):
        "!!Contains"
        return self.unaccentTpl(tblobj, column, 'ILIKE') % (
            column, self.storeArgs('%%%s%%' % value, dtype, sqlArgs))

    def op_greater(self, column, value, dtype, sqlArgs, tblobj):
        "!!Greater than"
        return self.unaccentTpl(tblobj, column, '>') % (
            column, self.storeArgs(value, dtype, sqlArgs))

    def op_greatereq(self, column, value, dtype, sqlArgs, tblobj):
        "!!Greater or equal to"
        return self.unaccentTpl(tblobj, column, '>=') % (
            column, self.storeArgs(value, dtype, sqlArgs))

    def op_less(self, column, value, dtype, sqlArgs, tblobj):
        "!!Less than"
        return self.unaccentTpl(tblobj, column, '<') % (
            column, self.storeArgs(value, dtype, sqlArgs))

    def op_lesseq(self, column, value, dtype, sqlArgs, tblobj):
        "!!Less or equal to"
        return self.unaccentTpl(tblobj, column, '<=') % (
            column, self.storeArgs(value, dtype, sqlArgs))

    def op_between(self, column, value, dtype, sqlArgs, tblobj):
        "!!Between"
        v1, v2 = value.split(';')
        return '%s BETWEEN :%s AND :%s' % (column,
                                           self.storeArgs(v1, dtype, sqlArgs),
                                           self.storeArgs(v2, dtype, sqlArgs))

    def op_isnull(self, column, value, dtype, sqlArgs, tblobj):
        "!!Is null"
        return '%s IS NULL' % column

    def op_istrue(self, column, value, dtype, sqlArgs, tblobj):
        "!!Is true"
        return '%s IS TRUE' % column

    def op_isfalse(self, column, value, dtype, sqlArgs, tblobj):
        "!!Is false"
        return '%s IS FALSE' % column

    def op_nullorempty(self, column, value, dtype, sqlArgs, tblobj):
        "!!Is null or empty"
        if dtype in ('L', 'N', 'M', 'R'):
            return self.op_isnull(column, value, dtype, sqlArgs)
        return " (%s IS NULL OR %s ='')" % (column, column)

    def op_in(self, column, value, dtype, sqlArgs, tblobj):
        "!!In"
        values_string = self.storeArgs(value.split(','), dtype, sqlArgs)
        return '%s IN :%s' % (column, values_string)

    def op_regex(self, column, value, dtype, sqlArgs, tblobj):
        "!!Regular expression"
        return '%s ~* :%s' % (column, self.storeArgs(value, dtype, sqlArgs))

#def whereFromText(self, table, whereTxt, customColumns=None):
#    result = []
#    sqlArgs = {}
#    tblobj = self.db.table(table)
#    pattern = '(AND|OR)'
#    whereList = re.compile(pattern).split(whereTxt)
#    condList = [cond for cond in whereList if cond not in ('AND', 'OR')]

    def unaccentTpl(self, tblobj, column, token):
        return ' '.join(['%s', token, ':%s'])

    def whereFromDict(self, table, whereDict, customColumns=None):
        result = []
        sqlArgs = {}
        tblobj = self.db.table(table)
        for k, v in whereDict.items():
            negate = ''
            op = 'equal'
            ksplit = k.split('_')
            if ksplit[-1].lower() in self.opDict:
                op = ksplit.pop().lower()
            if ksplit[-1].lower() == 'not':
                negate = ' NOT '
                ksplit.pop()
            column = '_'.join(ksplit)
            if customColumns and column in customColumns:
                custom = customColumns[column]
                if callable(custom):
                    condition = custom(column, sqlArgs)
                if isinstance(custom, basestring):
                    dtype = tblobj.column(custom).dtype
                    column = custom
                elif isinstance(custom, tuple):
                    column, dtype = custom
                else:
                    raise
            else:
                colobj = tblobj.column('$%s' % column)
                if colobj is None:
                    raise
                dtype = colobj.dtype

            condition = self.prepareCondition(column,
                                              op,
                                              v,
                                              dtype,
                                              sqlArgs,
                                              tblobj=tblobj)
            result.append('%s%s' % (negate, condition))
        return result, sqlArgs
示例#6
0
 def __init__(self, db):
     self.db = db
     self.catalog = GnrClassCatalog()
     self.opDict = dict([(k[3:], None) for k in dir(self) if k.startswith('op_')])
示例#7
0
class GnrWhereTranslator(object):
    def __init__(self, db):
        self.db = db
        self.catalog = GnrClassCatalog()
        self.opDict = dict([(k[3:], None) for k in dir(self) if k.startswith('op_')])

    def __call__(self, tblobj, wherebag, sqlArgs, customOpCbDict=None):
        if sqlArgs is None:
            sqlArgs = {}
        self.customOpCbDict = customOpCbDict
        result = self.innerFromBag(tblobj, wherebag, sqlArgs, 0)
        return '\n'.join(result)

    def opCaption(self, op, localize=False):
        h = getattr(self, 'op_%s' % op.lower(), None)
        if not h and op.startswith('not_'):
            return 'Not %s' % getattr(self, 'op_%s' % op[4:].lower()).__doc__
        result = h.__doc__
        if localize and self.db.localizer:
            result = self.db.localizer.translateText(result)
        return result

    def toText(self, tblobj, wherebag, level=0, decodeDate=False):
        result = []
        for k, node in enumerate(wherebag.getNodes()):
            attr = node.getAttr()
            value = node.getValue()
            if k:
                jc = attr.get('jc_caption', '')
            else:
                jc = ''
            negate = attr.get('not') == 'not'
            if isinstance(value, Bag):
                onecondition = ('\n' + '    ' * level).join(self.toText(tblobj, value, level + 1))
                onecondition = '(\n' + '    ' * level + onecondition + '\n' + '    ' * level + ')'
            else:
                op = attr.get('op_caption')
                column = attr.get('column_caption')
                if not op or not column:
                    continue
                if decodeDate:
                    if tblobj.column(attr.get('column')).dtype in('D', 'DH'):
                        value, op = self.decodeDates(value, op, 'D')
                        op = self.opCaption(op, localize=True)
                op = op.lower()
                onecondition = '%s %s %s' % (column, op, value)
            if onecondition:
                if negate:
                    onecondition = ' %s %s  ' % (attr.get('not_caption', ''), onecondition)
                result.append(' %s %s' % (jc, onecondition ))
        return result

    def toHtml(self, tblobj, wherebag, level=0, decodeDate=False):
        result = []
        for k, node in enumerate(wherebag.getNodes()):
            attr = node.getAttr()
            value = node.getValue()
            if k:
                jc = attr.get('jc_caption', '')
            else:
                jc = ''
            negate = attr.get('not') == 'not'
            if isinstance(value, Bag):
                onecondition =  '<div class="slqnested"> %s </div>' %(self.toHtml(tblobj, value, level + 1))#'(\n' + '    ' * level + onecondition + '\n' + '    ' * level + ')'
            else:
                op = attr.get('op_caption')
                column = attr.get('column_caption')
                if not op or not column:
                    continue
                if decodeDate:
                    if tblobj.column(attr.get('column')).dtype in('D', 'DH'):
                        value, op = self.decodeDates(value, op, 'D')
                        op = self.opCaption(op, localize=True)
                op = op.lower()
                onecondition = '<span class="sqlcol">%s</span> <span class="sqlop">%s</span> <span class="sqlvalue">%s</span>' % (column, op, value)
            if onecondition:
                if negate:
                    onecondition = ' <span class="sqlnot">%s</span> %s  ' % (attr.get('not_caption', ''), onecondition)
                result.append('<div class="sqlcondition"> <span class="sqljc">%s</span> %s </div>' % (jc, onecondition ))

        return ''.join(result)


    def innerFromBag(self, tblobj, wherebag, sqlArgs, level):
        """<condition column="fattura_num" op="ISNULL" rem='senza fattura' />
        <condition column="@anagrafica.provincia" op="IN" jc='AND'>MI,FI,TO</condition>
        <group not="true::B" jc='AND'>
                <condition column="" op=""/>
                <condition column="" op="" jc='OR'/>
        </group>"""

        result = []
        for node in wherebag:
            attr = node.getAttr()
            value = node.getValue()
            if isinstance(value, basestring) and value.startswith('?'):
                value = sqlArgs.get(value[1:])
            jc = attr.get('jc', '').upper()
            negate = attr.get('not') == 'not'
            if isinstance(value, Bag):
                onecondition = ('\n' + '    ' * level).join(self.innerFromBag(tblobj, value, sqlArgs, level + 1))
                onecondition = '(\n' + '    ' * level + onecondition + '\n' + '    ' * level + ')'
            else:
                op = attr.get('op')
                column = attr.get('column')
                if not op or not column:
                    #ingnoring empty query lines
                    continue
                colobj=tblobj.column(column)
                if colobj is None:
                    raise tblobj.exception('not_existing_column', column=column)
                dtype = colobj.dtype

                if value is None and attr.get('value_caption'):
                    value = sqlArgs.pop(attr['value_caption'])
                onecondition = self.prepareCondition(column, op, value, dtype, sqlArgs,tblobj=tblobj)

            if onecondition:
                if negate:
                    onecondition = ' NOT %s  ' % onecondition
                result.append(' %s ( %s )' % (jc, onecondition ))
        return result

    def prepareCondition(self, column, op, value, dtype, sqlArgs,tblobj=None):
        if not column[0] in '@$':
            column = '$%s' % column
        if dtype in('D', 'DH'):
            value, op = self.decodeDates(value, op, 'D')
            if dtype=='DH':
                column = 'CAST (%s AS date)' % column
        if not dtype in ('A', 'T') and op in (
        'contains', 'notcontains', 'startswith', 'endswith', 'regex', 'wordstart'):
            value = str(value)
            column = 'CAST (%s as text)' % column
            dtype = 'A'
        ophandler = getattr(self, 'op_%s' % op, None)
        if ophandler:
            result = ophandler(column=column, value=value, dtype=dtype, sqlArgs=sqlArgs,tblobj=tblobj)
        else:
            ophandler = self.customOpCbDict.get(op)
            assert ophandler, 'undefined ophandler'
            result = ophandler(column=column, value=value, dtype=dtype, sqlArgs=sqlArgs, whereTranslator=self,tblobj=tblobj)
        return result

    def decodeDates(self, value, op, dtype):
        if op == 'isnull':
            return value, op
        if op == 'in' and ',' in value: # is a in search with multiple (single date) arguments: don't use periods!!!
            value = ','.join(
                    [decodeDatePeriod(v, workdate=self.db.workdate, locale=self.db.locale, dtype=dtype) for v in
                     value.split(',')])
            return value, op

        value = decodeDatePeriod(value, workdate=self.db.workdate, locale=self.db.locale, dtype=dtype)
        mode = None
        if value.startswith(';'):
            mode = 'to'
        elif value.endswith(';'):
            mode = 'from'
        elif ';' in value:
            mode = 'period'

        if op in ('greater', 'greatereq'):  # keep the higher date
            if mode in ('period', 'to'):
                value = value.split(';')[1]
            else:
                value = value.strip(';')
        elif op in ('less', 'lesseq'):      # keep the lower date
            value = value.split(';')[0]

        else:
            # equal, between and textual operators are ignored
            # the right operator is choosen according to the value to find
            if mode == 'to':               # find data lower then value
                op = 'lesseq'
                value = value.strip(';')
            elif mode == 'from':           # find data higher then value
                op = 'greatereq'
                value = value.strip(';')
            elif mode == 'period':         # find data between period (value)
                op = 'between'
            else:                          # value is a single date
                op = 'equal'
        return value, op

    def storeArgs(self, value, dtype, sqlArgs):
        if not dtype in ('A', 'T'):
            if isinstance(value, list):
                value = [self.catalog.fromText(v, dtype) for v in value]
            elif isinstance(value, basestring):
                value = self.catalog.fromText(value, dtype)
        argLbl = 'v_%i' % len(sqlArgs)
        sqlArgs[argLbl] = value
        return argLbl

    def op_startswithchars(self, column, value, dtype, sqlArgs,tblobj):
        "Starts with Chars"
        return '%s LIKE :%s' % (column, self.storeArgs('%s%%' % value, dtype, sqlArgs))

    def op_equal(self, column, value, dtype, sqlArgs,tblobj):
        "Equal to"
        return '%s = :%s' % (column, self.storeArgs(value, dtype, sqlArgs))

    def op_startswith(self, column, value, dtype, sqlArgs,tblobj):
        "Starts with"
        return '%s ILIKE :%s' % (column, self.storeArgs('%s%%' % value, dtype, sqlArgs))

    def op_wordstart(self, column, value, dtype, sqlArgs,tblobj):
        "Word start"
        value = value.replace('(', '\(').replace(')', '\)').replace('[', '\[').replace(']', '\]')
        return '%s ~* :%s' % (column, self.storeArgs('(^|\\W)%s' % value, dtype, sqlArgs))

    def op_contains(self, column, value, dtype, sqlArgs,tblobj):
        "Contains"
        return '%s ILIKE :%s' % (column, self.storeArgs('%%%s%%' % value, dtype, sqlArgs))

    def op_similar(self, column, value, dtype, sqlArgs,tblobj):
        "Similar"
        phonetic_column =  tblobj.column(column).attributes['phonetic']
        phonetic_mode = tblobj.column(column).table.column(phonetic_column).attributes['phonetic_mode']
        return '%s = %s(:%s)' % (phonetic_column, phonetic_mode, self.storeArgs(value, dtype, sqlArgs))

    def op_greater(self, column, value, dtype, sqlArgs,tblobj):
        "Greater than"
        return '%s > :%s' % (column, self.storeArgs(value, dtype, sqlArgs))

    def op_greatereq(self, column, value, dtype, sqlArgs,tblobj):
        "Greater or equal to"
        return '%s >= :%s' % (column, self.storeArgs(value, dtype, sqlArgs))

    def op_less(self, column, value, dtype, sqlArgs,tblobj):
        "Less than"
        return '%s < :%s' % (column, self.storeArgs(value, dtype, sqlArgs))

    def op_lesseq(self, column, value, dtype, sqlArgs,tblobj):
        "Less or equal to"
        return '%s <= :%s' % (column, self.storeArgs(value, dtype, sqlArgs))

    def op_between(self, column, value, dtype, sqlArgs,tblobj):
        "Between"
        v1, v2 = value.split(';')
        return '%s BETWEEN :%s AND :%s' % (
        column, self.storeArgs(v1, dtype, sqlArgs), self.storeArgs(v2, dtype, sqlArgs))

    def op_isnull(self, column, value, dtype, sqlArgs,tblobj):
        "Is null"
        return '%s IS NULL' % column

    def op_istrue(self, column, value, dtype, sqlArgs,tblobj):
        "Is true"
        return '%s IS TRUE' % column

    def op_isfalse(self, column, value, dtype, sqlArgs,tblobj):
        "Is false"
        return '%s IS FALSE' % column

    def op_nullorempty(self, column, value, dtype, sqlArgs,tblobj):
        "Is null or empty"
        if dtype in ('L', 'N', 'M', 'R'):
            return self.op_isnull(column, value, dtype, sqlArgs)
        return " (%s IS NULL OR %s ='')" % (column, column)

    def op_in(self, column, value, dtype, sqlArgs,tblobj):
        "In"
        values_string = self.storeArgs(value.split(','), dtype, sqlArgs)
        return '%s IN :%s' % (column, values_string)

    def op_regex(self, column, value, dtype, sqlArgs,tblobj):
        "Regular expression"
        return '%s ~* :%s' % (column, self.storeArgs(value, dtype, sqlArgs))


   #def whereFromText(self, table, whereTxt, customColumns=None):
   #    result = []
   #    sqlArgs = {}
   #    tblobj = self.db.table(table)
   #    pattern = '(AND|OR)'
   #    whereList = re.compile(pattern).split(whereTxt)
   #    condList = [cond for cond in whereList if cond not in ('AND', 'OR')]


    def whereFromDict(self, table, whereDict, customColumns=None):
        result = []
        sqlArgs = {}
        tblobj = self.db.table(table)
        for k, v in whereDict.items():
            negate = ''
            op = 'equal'
            ksplit = k.split('_')
            if ksplit[-1].lower() in self.opDict:
                op = ksplit.pop().lower()
            if ksplit[-1].lower() == 'not':
                negate = ' NOT '
                ksplit.pop()
            column = '_'.join(ksplit)
            if customColumns and column in customColumns:
                custom = customColumns[column]
                if callable(custom):
                    condition = custom(column, sqlArgs)
                if isinstance(custom, basestring):
                    dtype = tblobj.column(custom).dtype
                    column = custom
                elif isinstance(custom, tuple):
                    column, dtype = custom
                else:
                    raise
            else:
                colobj = tblobj.column('$%s' % column)
                if colobj is None:
                    raise
                dtype = colobj.dtype

            condition = self.prepareCondition(column, op, v, dtype, sqlArgs,tblobj=tblobj)
            result.append('%s%s' % (negate, condition))
        return result, sqlArgs
示例#8
0
class SiteRegister(BaseRemoteObject):
    def __init__(self,server,sitename=None,storage_path=None):
        self.server = server
        self.page_register = PageRegister(self)
        self.connection_register = ConnectionRegister(self)
        self.user_register = UserRegister(self)
        self.remotebag_handler = RemoteStoreBagHandler(self)
        self.server.daemon.register(self.remotebag_handler,'RemoteData')
        self.last_cleanup = time.time()
        self.sitename = sitename
        self.storage_path = storage_path
        self.catalog = GnrClassCatalog()
        self.maintenance = False
        self.allowed_users = None




    def setConfiguration(self,cleanup=None):
        cleanup = cleanup or dict()
        self.cleanup_interval = int(cleanup.get('interval') or 120)
        self.page_max_age = int(cleanup.get('page_max_age') or 120)
        self.connection_max_age = int(cleanup.get('connection_max_age')or 600)

    def new_connection(self,connection_id,connection_name=None,user=None,user_id=None,
                            user_name=None,user_tags=None,user_ip=None,user_agent=None,browser_name=None,avatar_extra=None):
        assert not self.connection_register.exists(connection_id), 'SITEREGISTER ERROR: connection_id %s already registered' % connection_id
        if not self.user_register.exists(user):
            self.new_user( user, user_id=user_id,user_name=user_name,user_tags=user_tags,avatar_extra=avatar_extra)
        connection_item = self.connection_register.create(connection_id, connection_name=connection_name,user=user,user_id=user_id,
                            user_name=user_name,user_tags=user_tags,user_ip=user_ip,user_agent=user_agent,browser_name=browser_name)

        return connection_item


    def drop_pages(self,connection_id):
        for page_id in self.connection_page_keys(connection_id):
            self.drop_page(page_id)

    def drop_page(self,page_id, cascade=None):
        return self.page_register.drop(page_id,cascade=cascade)   

    def drop_connections(self,user):
        for connection_id in self.user_connection_keys(user):
            self.drop_connection(connection_id)

    def drop_connection(self,connection_id,cascade=None):
        self.connection_register.drop(connection_id,cascade=cascade)

    def drop_user(self,user):
        self.user_register.drop(user)

    def user_connection_keys(self,user):
        return self.connection_register.user_connection_keys(user)

    def user_connection_items(self,user):
        return self.connection_register.user_connection_items(user)

    def user_connections(self,user):
        return self.connection_register.user_connections(user)

    def connection_page_keys(self,connection_id):
        return self.page_register.connection_page_keys(connection_id=connection_id)

    def connection_page_items(self,connection_id):
        return self.page_register.connection_page_items(connection_id=connection_id)

    def connection_pages(self,connection_id):
        return self.page_register.connection_pages(connection_id=connection_id)


    def new_page(self,page_id,pagename=None,connection_id=None,subscribed_tables=None,user=None,user_ip=None,user_agent=None ,data=None):
        page_item = self.page_register.create(page_id, pagename = pagename,connection_id=connection_id,user=user,
                                            user_ip=user_ip,user_agent=user_agent, data=data)
        return page_item


    def new_user(self,user=None, user_tags=None, user_id=None, user_name=None,
                               avatar_extra=None):
        user_item = self.user_register.create( user=user, user_tags=user_tags, user_id=user_id, user_name=user_name,
                               avatar_extra=avatar_extra)
        return user_item

    def subscribed_table_pages(self,table=None):
        return self.page_register.subscribed_table_pages(table)

    def pages(self, connection_id=None,user=None,index_name=None, filters=None,include_data=None):
        if index_name:
            print 'call subscribed_table_pages instead of pages'
            return self.subscribed_table_pages(index_name)
        return self.page_register.pages(connection_id=connection_id,user=user,filters=filters,include_data=include_data)
        

    def page(self,page_id):
        return self.page_register.get_item(page_id)

    def connection(self,connection_id):
        return self.connection_register.get_item(connection_id)

    def user(self,user):
        return self.user_register.get_item(user)


    def users(self,include_data=None):
        return self.user_register.values(include_data)

    def connections(self,user=None,include_data=None):
        return self.connection_register.connections(user=user,include_data=include_data)
 

    def change_connection_user(self, connection_id, user=None, user_tags=None, user_id=None, user_name=None,
                               avatar_extra=None):
        connection_item = self.connection(connection_id)

        olduser = connection_item['user']
        newuser_item = self.user(user)
        if not newuser_item:
            newuser_item = self.new_user( user=user, user_tags=user_tags, user_id=user_id, user_name=user_name,
                               avatar_extra=avatar_extra)
        connection_item['user'] = user
        connection_item['user_tags'] = user_tags
        connection_item['user_name'] = user_name
        connection_item['user_id'] = user_id
        connection_item['avatar_extra'] = avatar_extra
        for p in self.pages(connection_id=connection_id):
            p['user'] = user
        if not self.connection_register.connections(olduser):
            self.drop_user(olduser)

    def refresh(self, page_id, last_user_ts=None,last_rpc_ts=None,pageProfilers=None):
        refresh_ts = datetime.now()
        page = self.page_register.refresh(page_id,last_user_ts=last_user_ts,last_rpc_ts=last_rpc_ts,refresh_ts=refresh_ts)
        if not page:
            return
        self.page_register.updatePageProfilers(page_id,pageProfilers)
        connection = self.connection_register.refresh(page['connection_id'],last_user_ts=last_user_ts,last_rpc_ts=last_rpc_ts,refresh_ts=refresh_ts)
        if not connection:
            return
        return self.user_register.refresh(connection['user'],last_user_ts=last_user_ts,last_rpc_ts=last_rpc_ts,refresh_ts=refresh_ts)


    def cleanup(self):
        if time.time()-self.last_cleanup < self.cleanup_interval:
            return
        now = datetime.now()
        for page in self.pages():
            page_max_age = self.page_max_age if not page['user'].startswith('guest_') else 40
            last_refresh_ts = page.get('last_refresh_ts') or page.get('start_ts')
            if ((now - last_refresh_ts).seconds > page_max_age):
                self.drop_page(page['register_item_id'])
        for connection in self.connections():
            last_refresh_ts = connection.get('last_refresh_ts') or  connection.get('start_ts')
            connection_max_age = self.connection_max_age if not connection['user'].startswith('guest_') else 40
            if (now - last_refresh_ts).seconds > connection_max_age:
                self.drop_connection(connection['register_item_id'],cascade=True)
        self.last_cleanup = time.time()


    def get_register(self,register_name):
        return getattr(self,'%s_register' %register_name)

    def setStoreSubscription(self,page_id,storename=None, client_path=None, active=None):
        self.page_register.setStoreSubscription(page_id,storename=storename,client_path=client_path,active=active)
            
    def subscribeTable(self,page_id,table,subscribe,subscribeMode=None):
        self.page_register.subscribeTable(page_id,table=table,subscribe=subscribe,subscribeMode=subscribeMode)

    def subscription_storechanges(self, user, page_id):
        external_datachanges = self.page_register.get_datachanges(register_item_id=page_id,reset=True)
        page_item_data = self.page_register.get_item_data(page_id)
        if not page_item_data:
            return external_datachanges
        user_subscriptions = page_item_data.getItem('_subscriptions.user')
        if not user_subscriptions:
            return external_datachanges
        store_datachanges = []
        datachanges = self.user_register.get_datachanges(user)
        user_item_data = self.user_register.get_item_data(user)
        storesubscriptions_items = user_subscriptions.items()
        global_offsets = user_item_data.getItem('_subscriptions.offsets')
        if global_offsets is None:
            global_offsets = {}
            user_item_data.setItem('_subscriptions.offsets', global_offsets)
        for j, change in enumerate(datachanges):
            changepath = change.path
            change_idx = change.change_idx
            for subpath, subdict in storesubscriptions_items:
                if subdict['on'] and changepath.startswith(subpath):
                    if change_idx > subdict.get('offset', 0):
                        subdict['offset'] = change_idx
                        change.attributes = change.attributes or {}
                        if change_idx > global_offsets.get(subpath, 0):
                            global_offsets[subpath] = change_idx
                            change.attributes['_new_datachange'] = True
                        else:
                            change.attributes.pop('_new_datachange', None)
                        store_datachanges.append(change)
        return external_datachanges+store_datachanges

    def handle_ping(self, page_id=None, reason=None, _serverstore_changes=None,**kwargs):
        _children_pages_info= kwargs.get('_children_pages_info')
        _lastUserEventTs = kwargs.get('_lastUserEventTs')
        _lastRpc = kwargs.get('_lastRpc')
        _pageProfilers = kwargs.get('_pageProfilers')
        page_item = self.refresh(page_id, _lastUserEventTs,last_rpc_ts=_lastRpc,pageProfilers=_pageProfilers)
        if not page_item:
            return False
        catalog = self.catalog
        if _serverstore_changes:
            self.set_serverstore_changes(page_id, _serverstore_changes)
        if _children_pages_info:
            for k,v in _children_pages_info.items():
                child_lastUserEventTs = v.pop('_lastUserEventTs', None)
                child_lastRpc = v.pop('_lastRpc', None)
                child_pageProfilers = v.pop('_pageProfilers', None)
                if v:
                    self.set_serverstore_changes(k, v)
                if child_lastUserEventTs:
                    child_lastUserEventTs = catalog.fromTypedText(child_lastUserEventTs)
                if child_lastRpc:
                    child_lastRpc = catalog.fromTypedText(child_lastRpc)
                self.refresh(k, child_lastUserEventTs,last_rpc_ts=child_lastRpc,pageProfilers=child_pageProfilers)
        envelope = Bag(dict(result=None))
        user=page_item['user']
        datachanges = self.handle_ping_get_datachanges(page_id, user=user)            
        if datachanges:
            envelope.setItem('dataChanges', datachanges)
        if _children_pages_info:
            for k in _children_pages_info.keys():
                datachanges = self.handle_ping_get_datachanges(k, user=user)
                if datachanges:
                    envelope.setItem('childDataChanges.%s' %k, datachanges)
        user_register_data = self.user_register.get_item_data(user)
        lastBatchUpdate = user_register_data.getItem('lastBatchUpdate')
        if lastBatchUpdate:
            if (datetime.now()-lastBatchUpdate).seconds<5:
                envelope.setItem('runningBatch',True)
            else:
                user_register_data.setItem('lastBatchUpdate',None)
        return envelope

    def handle_ping_get_datachanges(self, page_id, user=None):
        result = Bag()
        store_datachanges = self.subscription_storechanges(user,page_id)
        if store_datachanges:
            for j, change in enumerate(store_datachanges):
                result.setItem('sc_%i' % j, change.value, change_path=change.path, change_reason=change.reason,
                           change_fired=change.fired, change_attr=change.attributes,
                           change_ts=change.change_ts, change_delete=change.delete)
        return result
        
    def set_serverstore_changes(self, page_id=None, datachanges=None):
        page_item_data = self.page_register.get_item_data(page_id)
        for k, v in datachanges.items():
            page_item_data.setItem(k, self._parse_change_value(v))


    def _parse_change_value(self, change_value):
        if isinstance(change_value, basestring):
            try:
                v = self.catalog.fromTypedText(change_value)
                if isinstance(v, basestring):
                    v = v.decode('utf-8')
                return v
            except Exception, e:
                raise e
        return change_value