예제 #1
0
    def validate_value_list(self, ctx: Ctx, values: List[Any]) -> str:
        replaces = {}
        transformedValues = []
        args = []
        for val in values:
            if isinstance(val, datetime.datetime) or isinstance(
                    val, datetime.date):
                val, _ = process_value(str(val.astimezone(UTC)))
                replaces[val] = f'{val}::timestamptz'
            elif isinstance(val, asyncpg.pgproto.pgproto.UUID):
                val = quote_literal(str(val))
                replaces[val] = f'{val}::uuid'
            else:
                val, p = process_value(val)
                if p is not None:
                    args.append(p)
                val = str(val)
            transformedValues.append(val)

        nestedCtx = Ctx(ctx.param_offset + len(ctx.args), args)
        result = _value_list.parse(','.join(transformedValues), nestedCtx)
        for rep in replaces:
            result = result.replace(rep, replaces[rep])
        ctx.args.extend(args)
        return result
예제 #2
0
    def where(self, _where: str, *items: Any):
        if len(items) == 0 or '?' in _where:
            try:
                ctx = Ctx(self.paramOffset, items)
                sql = self.validator.validate_where(_where, ctx)
            except ValidationError as err:
                raise UserWarning(f'invalid WHERE: {err}') from None
            value = {'sql': sql, 'params': ctx.args}
        elif len(items) <= 2:
            if len(items) == 1:
                if isinstance(items[0], list):
                    operator = 'IN'
                else:
                    operator = '='
                val = items[0]
                if val is None:
                    operator = 'IS'
            else:
                operator = items[0]
                val = items[1]

            _where += f' {operator}'
            if val is None:
                _where += ' NULL'
                params = []
            else:
                jsonbTest = '->' in _where
                if operator == 'IN' or operator == 'NOT IN':
                    params = []
                    vs = []
                    for v in val:
                        processed, _ = process_value(v)
                        if processed == '?' or jsonbTest:
                            params.append(v)
                            vs.append('?')
                        else:
                            vs.append(str(processed))
                    _where += ' (' + ', '.join(vs) + ')'
                else:
                    params = []
                    processed, _ = process_value(val)
                    if processed == '?' or jsonbTest:
                        params.append(val)
                        _where += ' ?'
                    else:
                        _where += f' {processed}'

            try:
                ctx = Ctx(self.paramOffset, params)
                sql = self.validator.validate_where(_where, ctx)
            except ValidationError as err:
                raise UserWarning(f'invalid WHERE: {err}') from None
            value = {'sql': sql, 'params': ctx.args}
        else:
            raise UserWarning(f"Invalid WHERE: {_where} {items}")

        self.paramOffset += len(value['params'])
        self.append(WhereToken(value))
예제 #3
0
 def validate_insert_values(self, values: List[Any], ctx: Ctx) -> str:
     results = []
     for val in values:
         val, p = process_value(val)
         if p is not None:
             ctx.args.append(p)
         results.append(str(val))
     return '(' + _value_list.parse(','.join(results), ctx) + ')'
예제 #4
0
 def validate_rrule_values(self, ctx: Ctx, values: List[Any],
                           rrulesetVal: rrule.rruleset,
                           occurrences: slice) -> str:
     row = [None]  # slot for rrule timestamp
     args = []
     for val in values:
         val, p = process_value(val)
         if p is not None:
             args.append(p)
         row.append(str(val))
     results = []
     # set a limit in case the rrule is unbound
     for tm in rrulesetVal[occurrences]:
         row[0], _ = process_value(str(tm.astimezone(UTC)))
         nestedCtx = Ctx(ctx.param_offset + len(ctx.args), args)
         rowTmpl = '(' + _value_list.parse(','.join(row), nestedCtx) + ')'
         results.append(rowTmpl.replace(row[0], f'{row[0]}::timestamptz'))
         ctx.args.extend(args)
     return ', '.join(results)
예제 #5
0
 def update(self, *items: Any):
     if len(items) == 1 and isinstance(items[0], Dict):
         _sqls = []
         params = []
         for name, val in items[0].items():
             val, p = process_value(val)
             if p is not None:
                 params.append(p)
             _sqls.append(f'{name} = {val}')
         sql = ', '.join(_sqls)
     elif len(items) > 0:
         sql = items[0]
         params = items[1:]
     else:
         raise UserWarning(f'not valid updates: {items}')
     self.collector.update(sql, *params)
     return self