Source code for postgast.scan

"""SQL scanning/tokenization via libpg_query."""

from __future__ import annotations

import ctypes

from postgast.errors import check_error
from postgast.native import lib
from postgast.pg_query_pb2 import ScanResult


[docs] def scan(sql: str) -> ScanResult: """Tokenize a SQL string into a sequence of scan tokens. Calls libpg_query's ``pg_query_scan`` to tokenize the input and returns the deserialized ``ScanResult`` protobuf message containing a list of ``ScanToken`` objects with token type, keyword kind, and byte positions. Args: sql: A SQL string to tokenize. Returns: A ``ScanResult`` protobuf message with ``version`` (int) and ``tokens`` (list of ``ScanToken``) fields. Raises: PgQueryError: If the input contains a scan error (e.g., unterminated string literal). Example: >>> result = scan("SELECT 1") >>> len(result.tokens) 2 >>> result.tokens[0].start, result.tokens[0].end (0, 6) """ result = lib.pg_query_scan(sql.encode("utf-8")) try: check_error(result) pbuf = result.pbuf data = ctypes.string_at(pbuf.data, pbuf.len) return ScanResult.FromString(data) finally: lib.pg_query_free_scan_result(result)