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