def scan()

in elasticapm/instrumentation/packages/dbapi2.py [0:0]


def scan(tokens):
    literal_start_idx = None
    literal_started = None
    prev_was_escape = False
    lexeme = []
    digits = set(string.digits)

    i = 0
    while i < len(tokens):
        token = tokens[i]
        if literal_start_idx:
            if prev_was_escape:
                prev_was_escape = False
                lexeme.append(token)
            else:
                if token == literal_started:
                    if literal_started == "'" and len(tokens) > i + 1 and tokens[i + 1] == "'":  # double quotes
                        i += 1
                        lexeme.append("'")
                    else:
                        yield i, Literal(literal_started, "".join(lexeme))
                        literal_start_idx = None
                        literal_started = None
                        lexeme = []
                else:
                    if token == "\\":
                        prev_was_escape = token
                    else:
                        prev_was_escape = False
                        lexeme.append(token)
        elif literal_start_idx is None:
            if token in ["'", '"', "`"]:
                literal_start_idx = i
                literal_started = token
            elif token == "$":
                # exclude query parameters that have a digit following the dollar
                if True and len(tokens) > i + 1 and tokens[i + 1] in digits:
                    yield i, token
                    i += 1
                    continue
                # Postgres can use arbitrary characters between two $'s as a
                # literal separation token, e.g.: $fish$ literal $fish$
                # This part will detect that and skip over the literal.
                try:
                    # Closing dollar of the opening quote,
                    # i.e. the second $ in the first $fish$
                    closing_dollar_idx = tokens.index("$", i + 1)
                except ValueError:
                    pass
                else:
                    quote = tokens[i : closing_dollar_idx + 1]
                    length = len(quote)
                    # Opening dollar of the closing quote,
                    # i.e. the first $ in the second $fish$
                    closing_quote_idx = closing_dollar_idx + 1
                    while True:
                        try:
                            closing_quote_idx = tokens.index("$", closing_quote_idx)
                        except ValueError:
                            break
                        if tokens[closing_quote_idx : closing_quote_idx + length] == quote:
                            yield i, Literal(
                                "".join(quote), "".join(tokens[closing_dollar_idx + 1 : closing_quote_idx])
                            )
                            i = closing_quote_idx + length
                            break
                        closing_quote_idx += 1
            else:
                if token != " ":
                    yield i, token
        i += 1

    if lexeme:
        yield i, lexeme