Skip to content

Nested records - value not returned in specific cases #456

Closed
@pvapenka-cen69045

Description

@pvapenka-cen69045

What versions are you using?

database: 21XE / 19c EE 19.0.0.0.0
platform.platform: macOS-15.3-arm64-arm-64bit-Mach-O
sys.maxsize > 2**32: True
platform.python_version: 3.13.0
oracledb.version: 2.5.1

Is it an error or a hang or a crash?

ERROR - incorrect behaviour of output variables (plsql records)

What error(s) or behavior you are seeing?

Depending on the definition of nested record (number of fields and their position) I get different outcomes.
Below is a runnable scripts that shows 2 failing cases which I believe should pass (for example filling a value in nested field INNER2 should return the record from the DB and contain the fillled value, however, None is returned l_i_am_causing_troubles_here field is the last field in the nested record).

To see the different behaviours, comment/uncomment the different definitions of inner_t record.

Does your application call init_oracle_client()?

NO - using thin mode

Include a runnable Python script that shows the problem.

import oracledb

DB_DSN='XEPDB1'
DB_USER='test'
DB_PASSWORD='test'

DDLS = [
"""
CREATE OR REPLACE PACKAGE test_pkg AS

TYPE inner_t IS RECORD (
  ---------------------------------------
  -- works
  ---------------------------------------
  -- lnum                         NUMBER

  ---------------------------------------
  -- fails for test case: 1, 2
  ---------------------------------------
  -- l_i_am_causing_troubles_here NUMBER,
  -- lnum                         NUMBER

  ---------------------------------------
  -- fails for test case: NULL, 2
  ---------------------------------------
  lnum                         NUMBER,
  l_i_am_causing_troubles_here NUMBER
);

TYPE outer_t IS RECORD (
  inner1 inner_t,
  inner2 inner_t
);

FUNCTION parse(num1 NUMBER, num2 NUMBER) RETURN outer_t;

END test_pkg;
""",

"""
CREATE OR REPLACE PACKAGE BODY test_pkg AS

FUNCTION parse(num1 NUMBER, num2 NUMBER) RETURN outer_t
IS
  l_outer outer_t;
BEGIN
  l_outer.inner1.lnum := num1;
  l_outer.inner2.lnum := num2;
  RETURN l_outer;
END parse;

END test_pkg;
"""
]


with oracledb.connect(user=DB_USER, password=DB_PASSWORD, dsn=DB_DSN) as db_conn:
    with db_conn.cursor() as cursor:
        for ddl in DDLS:
            cursor.execute(ddl)

        outer_type = db_conn.gettype('TEST_PKG.OUTER_T')
        outer_var = cursor.var(outer_type)

        def parse(num1, num2):
            cursor.execute(
                """
                BEGIN
                  :result := test_pkg.parse(:num1, :num2);
                END;
                """,
                result=outer_var,
                num1=num1,
                num2=num2
            )
            return outer_var.getvalue()

        outer = parse(None, None)
        assert outer is not None
        assert outer.INNER1 is None
        assert outer.INNER2 is None

        outer = parse(1, 2)
        assert outer is not None
        assert outer.INNER1 is not None
        assert outer.INNER2 is not None
        assert outer.INNER1.LNUM == 1
        assert outer.INNER2.LNUM == 2

        outer = parse(1, None)
        assert outer is not None
        assert outer.INNER1 is not None
        assert outer.INNER2 is None
        assert outer.INNER1.LNUM == 1

        outer = parse(None, 2)
        assert outer is not None
        assert outer.INNER1 is None
        assert outer.INNER2 is not None
        assert outer.INNER2.LNUM == 2

        print("All tests passed")

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions