Пример #1
0
 def percentile_aggr(self, percentile, fld):
     """Sum up the things"""
     percentile_val = int(percentile[len("percentile") :])
     if percentile_val not in (1, 5, 10, 25, 50, 75, 90, 95, 99):
         raise GrammarError(
             f"percentile values of {percentile_val} is not supported."
         )
     if self.drivername == "bigquery":
         percentile_fn = getattr(engine_support, f"bq_percentile{percentile_val}")
         return percentile_fn(fld)
     elif self.drivername == "sqlite":
         raise GrammarError("Percentile is not supported on sqlite")
     else:
         # Postgres + redshift
         return func.percentile_cont(percentile_val / 100.0).within_group(fld)
Пример #2
0
 def datetime_end_conv(self, _, datestr):
     # Parse a datetime as the last moment of the given day
     # if the date
     dt = dateparser.parse(datestr)
     if dt is None:
         raise GrammarError(f"Can't convert '{datestr}' to a datetime.")
     return convert_to_eod_datetime(dt)
Пример #3
0
 def switch_statement(self, expr, *cases):
     found_default = False
     for case in cases:
         if case.choice is None:
             if found_default:
                 raise GrammarError("Multiple defaults found in switch")
             found_default = True
Пример #4
0
 def date_conv(self, _, datestr):
     dt = dateparser.parse(datestr)
     if dt:
         dt = dt.date()
     else:
         raise GrammarError(f"Can't convert '{datestr}' to a date.")
     return dt
Пример #5
0
def process_int_constant(token):
    strval = token.value
    if strval == '0':
        val = 0
    elif strval[0] == '0':
        if strval[1] in 'xX':
            base = 16
        elif strval[1] in 'bB':
            base = 2
        else:
            base = 8
        val = int(strval, base)
    elif strval[0] == "'":
        if strval[1] == '\\':
            if strval[2] in simple_escapes:
                val = ord(simple_escapes[strval[2]])
            else:
                if strval[2] == 'x':
                    val = int(strval[3:-1], 16)
                elif strval[2] in '01234567':
                    val = int(strval[2:-1], 8)
                else:
                    raise GrammarError("Invalid string escape '%s'" % strval)
        else:
            val = ord(strval[1])
    else:
        val = int(strval)
    return Token.new_borrow_pos(token.type, val, token)
Пример #6
0
 def named_game(self, items):
     debug('named_game', items)
     if str(items[0]) in heap:
         return heap[str(items[0])]
     else:
         # variable not assigned
         raise GrammarError("Variable " + str(items[0]) +
                            " is not defined.")
Пример #7
0
 def dt_quarter_conv(self, _, fld):
     if self.drivername == "bigquery":
         return func.timestamp_trunc(fld, text("quarter"))
     elif self.drivername.startswith("mssql"):
         raise GrammarError("quarter is not supported on mssql")
     else:
         # Postgres + redshift
         return func.date_trunc("quarter", fld)
Пример #8
0
 def dt_week_conv(self, _, fld):
     """Truncate to mondays"""
     if self.drivername == "bigquery":
         return func.timestamp_trunc(fld, text("week(monday)"))
     elif self.drivername.startswith("mssql"):
         raise GrammarError("week is not supported on mssql")
     else:
         # Postgres + redshift
         return func.date_trunc("week", fld)
Пример #9
0
 def quarter_conv(self, _, fld):
     # Convert each date to the first day of each quarter
     if self.drivername == "bigquery":
         return func.date_trunc(fld, text("quarter"))
     elif self.drivername.startswith("mssql"):
         raise GrammarError("quarter is not supported on mssql")
     else:
         # Postgres + redshift
         return func.date_trunc("quarter", fld)
Пример #10
0
 def age_conv(self, _, fld):
     """Convert a date to an age"""
     if self.drivername == "bigquery":
         return engine_support.bq_age(fld)
     elif self.drivername == "sqlite":
         raise GrammarError("Age is not supported on sqlite")
     else:
         # Postgres + redshift
         return engine_support.postgres_age(fld)
Пример #11
0
    def parse(
        self,
        text,
        forbid_aggregation=False,
        enforce_aggregation=False,
        debug=False,
        convert_dates_with=None,
        convert_datetimes_with=None,
    ):
        """Return a parse tree for text

        Args:
            text (str): A field expression
            forbid_aggregation (bool, optional):
              The expression may not contain aggregations. Defaults to False.
            enforce_aggregation (bool, optional):
              Wrap the expression in an aggregation if one is not provided. Defaults to False.
            debug (bool, optional): Show some debug info. Defaults to False.
            convert_dates_with (str, optional): A converter to use for date fields
            convert_datetimes_with (str, optional): A converter to use for datetime fields

        Raises:
            GrammarError: A description of any errors and where they occur

        Returns:
            A tuple of
                ColumnElement: A SQLALchemy expression
                DataType: The datatype of the expression (bool, date, datetime, num, str)
        """
        tree = self.parser.parse(text, start="col")
        validator = SQLALchemyValidator(text, forbid_aggregation, self.drivername)
        validator.visit(tree)
        self.last_datatype = validator.last_datatype

        if validator.errors:
            if debug:
                print("".join(validator.errors))
                print("Tree:\n" + tree.pretty())
            raise GrammarError("".join(validator.errors))
        else:
            if debug:
                print("Tree:\n" + tree.pretty())
            self.transformer.text = text
            self.transformer.convert_dates_with = convert_dates_with
            self.transformer.convert_datetimes_with = convert_datetimes_with
            expr = self.transformer.transform(tree)
            if (
                enforce_aggregation
                and not validator.found_aggregation
                and self.last_datatype == "num"
            ):
                return (func.sum(expr), self.last_datatype)
            else:
                return (expr, self.last_datatype)
Пример #12
0
    def _raise_error(self, message):
        tree = None
        tok = None
        # Find the first token
        while tree and tree.children:
            tree = tree.children[0]
            if isinstance(tree, Token):
                tok = tree
                break

        if tok:
            extra_context = self._get_context_for_token(tok)
            message = f"{message}\n{extra_context}"
        raise GrammarError(message)
Пример #13
0
 def num_div(self, num, denom):
     """SQL safe division"""
     if isinstance(denom, (int, float)):
         if denom == 0:
             raise GrammarError("When dividing, the denominator can not be zero")
         elif denom == 1:
             return num
         elif isinstance(num, (int, float)):
             return num / denom
         else:
             return cast(num, Float) / denom
     else:
         if isinstance(num, (int, float)):
             return case([(denom == 0, None)], else_=num / cast(denom, Float))
         else:
             return case(
                 [(denom == 0, None)], else_=cast(num, Float) / cast(denom, Float)
             )
Пример #14
0
def process_string_escapes(token):
    val = token.value
    new_parts = []
    start = 1  # trim off quotation
    while val:
        pos = val.find('\\')
        if pos == -1: break
        new_parts.append(val[start:pos])
        start = 0
        next = val[pos + 1]
        consume = 1
        if next in simple_escapes:
            new_parts.append(simple_escapes[next])
        else:
            raise GrammarError("Invalid string escape '%s'" % next)
        val = val[pos + 1 + consume:]
    new_parts.append(val[start:-1])
    new_val = ''.join(new_parts)
    return Token.new_borrow_pos(token.type, new_val, token)
Пример #15
0
 def datetime_conv(self, _, datestr):
     dt = dateparser.parse(datestr)
     if dt is None:
         raise GrammarError(f"Can't convert '{datestr}' to a datetime.")
     return dt
Пример #16
0
 def function_definition(self, type, decl, body):
     if not isinstance(decl.name_spec, FuncDeclSpec):
         raise GrammarError("Function definition must have a specifier \
                            of type function")
     return FunctionDeclaration(body=body, type=type, decl=decl)