Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

Potential bug: SIGSEGV in Thin-mode AsyncConnection.fetch_df_batches() for VARCHAR2 + TIMESTAMP result; synchronous dataframe fetch succeeds

Đang mở
#607 6 bình luận 0 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

Đánh giá

Độ khó
5/5
Thời gian dự kiến
Hơn một tuần
Mức phù hợp với người mới
20/100
Loại issue
Lỗi
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
python
Lĩnh vực
backend, databases

Hướng nghiên cứu

The crash occurs in the thin-mode async dataframe fetch path, specifically in AsyncConnection.fetch_df_batches() when a VARCHAR2 column is followed by a TIMESTAMP column. Start by examining the async dataframe fetching implementation in the oracledb source, focusing on type conversion and memory management. Reproduce the crash using the provided script to understand the exact point of failure, then compare with the synchronous fetch path to identify differences.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

bug
1. Versions
  • python-oracledb: 26.0.1

  • Mode: Thin

  • Python: 3.14.7

  • PyArrow: 25.0.1

  • Platform: Linux 7.0.0-29-generic x86_64, glibc 2.41

  • 64-bit Python: yes

  • OS family used by the application: Debian 13 or newer

  • init_oracle_client() is not called

2. Is this an error, hang, or crash?

Crash: the Python interpreter terminates with SIGSEGV, normally with exit

status 139.

No Python exception is raised.

3. Behavior

Thin-mode AsyncConnection.fetch_df_batches() segfaults while fetching a

result containing a VARCHAR2 column followed by a TIMESTAMP(6) column.

The crash occurs while advancing the async dataframe iterator, before the

returned object is converted with pyarrow.table().

The equivalent synchronous Connection.fetch_df_batches() call succeeds and

returns all rows.

Ordinary row fetching with AsyncCursor.fetchmany() also succeeds.

The two source columns are described as:


STATEMENTKEY:

    type_code=DB_TYPE_VARCHAR

    display_size=30

    internal_size=30

    precision=None

    scale=None

    null_ok=False

 

WRITETIME:

    type_code=DB_TYPE_TIMESTAMP

    display_size=23

    internal_size=None

    precision=0

    scale=6

    null_ok=True

For a representative 1,000-row result:

all 1,000 VARCHAR2 values are non-null;
all 1,000 TIMESTAMP values are non-null;
the VARCHAR2 column contains one distinct/repeated value;
the TIMESTAMP column contains 1,000 distinct values.
Isolation results:

Query shape

Async dataframe fetch

VARCHAR2 only

succeeds

NUMBER only

succeeds

TIMESTAMP only

succeeds

VARCHAR2 + NUMBER

succeeds

NUMBER + TIMESTAMP

succeeds

VARCHAR2 + TIMESTAMP

SIGSEGV

VARCHAR2 + CAST(TIMESTAMP AS TIMESTAMP(6))

succeeds in the reduced test

Same VARCHAR2 + TIMESTAMP query using synchronous Connection.fetch_df_batches()

succeeds

A synthetic DUAL CONNECT BY query with a repeated VARCHAR2 value and generated
TIMESTAMP values did not reproduce the crash. It may therefore depend on
additional result metadata or the exact encoded values.

This appears related to, but different from, issue #597:

the VARCHAR2 column has a defined internal_size of 30;
the failure was isolated to AsyncConnection.fetch_df_batches();
synchronous Connection.fetch_df_batches() succeeds.
4. Reproducer using an existing table

The following reproduces consistently against the affected view. The object and
column names below are anonymized, but the reported Oracle data types and
metadata are unchanged.

import asyncio

import faulthandler

 

import oracledb

import pyarrow as pa

 

faulthandler.enable()

 

USER = "..."

PASSWORD = "..."

DSN = "host:1521/service"

 

SQL = """

    select varchar_key, timestamp_value

    from affected_view

    where rownum <= 1000

"""

 

 

async def reproduce_async():

    async with oracledb.connect_async(

        user=USER,

        password=PASSWORD,

        dsn=DSN,

    ) as connection:

        batches = connection.fetch_df_batches(

            statement=SQL,

            size=1000,

            fetch_decimals=True,

        )

 

        iterator = aiter(batches)

 

        print("before async fetch", flush=True)

 

        # The interpreter segfaults during this await. The next print is not

        # reached, and pyarrow.table() is not involved in the crash.

        oracle_dataframe = await anext(iterator)

 

        print("after async fetch", flush=True)

        table = pa.table(oracle_dataframe)

        print(table.schema)

 

 

asyncio.run(reproduce_async())

Equivalent synchronous control:

import oracledb

import pyarrow as pa

 

with oracledb.connect(

    user=USER,

    password=PASSWORD,

    dsn=DSN,

) as connection:

    for oracle_dataframe in connection.fetch_df_batches(

        statement=SQL,

        size=1000,

        fetch_decimals=True,

    ):

        table = pa.table(oracle_dataframe)

        print(table.schema, table.num_rows)

The synchronous control completes successfully.

Ordinary async row-fetch control:

import asyncio

import oracledb

 

 

async def row_fetch_control():

    async with oracledb.connect_async(

        user=USER,

        password=PASSWORD,

        dsn=DSN,

    ) as connection:

        async with connection.cursor() as cursor:

            cursor.arraysize = 1000

            cursor.prefetchrows = 1000

            await cursor.execute(SQL)

            rows = await cursor.fetchmany(1000)

            print(len(rows))

 

 

asyncio.run(row_fetch_control())

This also completes successfully.

5. Requested-schema behavior

The async crash was also observed in the application when passing a PyArrow
requested_schema, for example:

schema = pa.schema([

    ("VARCHAR_KEY", pa.string()),

    ("TIMESTAMP_VALUE", pa.timestamp("us")),

])

 

async for oracle_dataframe in connection.fetch_df_batches(

    statement=SQL,

    size=1000,

    fetch_decimals=True,

    requested_schema=schema,

):

    table = pa.table(oracle_dataframe)

The crash still occurs while fetching, before the pa.table() call.

6. Expected behavior

AsyncConnection.fetch_df_batches() should return the same dataframe values as
the successful synchronous dataframe fetch, or raise a Python exception if the
result cannot be represented.

It should not terminate the interpreter.
Ngôn ngữ chính
Python
Star
454
Fork
119
Chỉ số merge pull request
Không có pull request nào được merge trong 30 ngày

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của oracle/python-oracledb

Tất cả issue của oracle/python-oracledb

Issue tương tự

Thêm issue về Python

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.