Skip to content

What's New in Version 1.0.18

April 27, 2026 4:42 PM UTC

Version 1.0.18 of the relationalai Python package is now available!

To upgrade, activate your virtual environment and run the following command:

Terminal window
pip install --upgrade relationalai
  • You can now pass an existing Snowpark session to create_config() with snowflake_session=.

    For example:

    from snowflake.snowpark import Session
    from relationalai.config import create_config
    snowflake_connection_parameters = {...}
    snowpark_session = Session.builder.configs(snowflake_connection_parameters).create()
    config = create_config(snowflake_session=snowpark_session)
    assert config.get_session() is snowpark_session

    This change makes it easier to use PyRel in environments where you already have a Snowpark session.

  • Fixed nested lookups that could drop rows when the inner lookup had no match. Before, PyRel could skip rows instead of keeping the row and showing NULL for the missing value. For example:

    from relationalai.semantics import Integer, Model, String
    m = Model("CustomerModel")
    Customer = m.Concept("Customer", identify_by={"id": Integer})
    Customer.name = m.Property(f"{Customer} has name {String:name}")
    ReferralCode = m.Relationship(f"{Integer:customer_id} maps to {String:referral_code}")
    m.define(
    Customer.new(id=1, name="Alice"),
    Customer.new(id=2, name="Bob"),
    ReferralCode(1, "ABC123")
    )
    customer_id = Integer.ref()
    code = String.ref()
    q = (
    m.where(
    Customer.id == customer_id,
    referral_code := m.where(ReferralCode(customer_id, code)).select(code),
    )
    .select(Customer.name, referral_code.alias("referral_code"))
    )
    print(q.to_df())

    Output before the fix:

    name referral_code
    0 Alice ABC123

    Output after the fix:

    name referral_code
    0 Alice ABC123
    1 Bob NULL
  • Fixed datetime.date.range() and datetime.datetime.range() when the end value comes from a DSL value like a Concept, Property or Relationship instead of a regular Python date or datetime. Before, the query could return one combined date range instead of a separate date range for each entity. For example:

    from relationalai.semantics import Date, Integer, Model, define, select, std
    import datetime as dt
    m = Model("dates")
    Foo = m.Concept("Foo", identify_by={"id": Integer})
    Foo.end_date = m.Property(f"{Foo} has {Date:end_date}")
    define(
    Foo.new(id=1, end_date=dt.date(2020, 1, 2)),
    Foo.new(id=2, end_date=dt.date(2020, 1, 4)),
    )
    select(
    std.datetime.date.range(dt.date(2020, 1, 1), Foo.end_date, freq="D")
    ).to_df()

    Before, that query could return one combined date range instead of a separate date range for each Foo row:

    # Before the fix:
    result
    0 2020-01-01
    1 2020-01-02
    2 2020-01-03
    3 2020-01-04

    Now there are duplicate dates because both Foo rows contribute to the result:

    # After the fix:
    result
    0 2020-01-01
    2 2020-01-02
    3 2020-01-02
    4 2020-01-03
    5 2020-01-04
  • Fixed inferred field naming for numeric aliases such as Integer. Before, if you let PyRel infer a field name from one of those types, it would generate a name like number_38_0 instead of integer, so string lookups such as Scores["integer"] would fail with a KeyError exception. For example:

    from relationalai.semantics import Integer, Model, String
    m = Model("scores")
    # The Integer field is unnamed here, so PyRel infers its field name.
    Scores = m.Relationship(f"{String:name} has {Integer}")
    # Prior to the fix, this lookup would raise a KeyError.
    m.select(Scores["integer"]).to_df()

    Now PyRel infers the correct field name, so Scores["integer"] resolves to the Integer field.