Skip to content

scopes applied to a hasMany referenced via a hasManyThrough use raw tablename instead of alias (11.2.1) #264

@davidAtInleague

Description

@davidAtInleague

Bug is in the subselect here, where it uses the raw table name instead of the generated alias.

SELECT
    [Cs_2].[bID],
    [Cs_2].[cID],
    [Cs_2].[dID],
    (
        SELECT TOP (1)
        [rmme_D].[dValue]
        FROM [rmme_D]
        WHERE ([rmme_C].[dID] = [rmme_D].[dID]) -- << invalid name -- rmme_C should be Cs_2
    ) AS [inlined_dValue]
    FROM [rmme_C] AS [Cs_2]
    INNER JOIN [rmme_B] AS [Bs_1] ON [Bs_1].[bID] = [Cs_2].[bID]
    WHERE [Bs_1].[aID] = 1

Reproduction:

transaction {
    A::initTable() // A has many Cs through B and C includes a subselect from D
    B::initTable()
    C::initTable()
    D::initTable()

    queryExecute("
        insert into rmme_d(dID, dValue) values (42, 'some value in table D');

        insert into rmme_a (aID) values (1);
        insert into rmme_b (bID, aID) values (2, 1);
        insert into rmme_c (cID, bID, dID) values (3, 2, 42);
    ")
    
    v = getInstance("A").asMemento(includes = ["Cs"]).get()
    writedump(v)
    // throws:
    // The multi-part identifier "rmme_C.dID" could not be bound.
}

component extends="quick.models.BaseEntity" accessors=true table="rmme_A" {
    property name="aID";
    variables._key = "aID";

    function Bs() {
        return hasMany(
            relationName = "B",
            foreignKey = "aID",
            localKey = "aID"
        );
    }

    function Cs() {
        return hasManyThrough( [ "Bs", "Cs" ] )
    }

    static function initTable() {
        queryExecute("
            drop table if exists rmme_A;
            create table rmme_A(aID int);
        ")
    }
}

component extends="quick.models.BaseEntity" accessors=true table="rmme_B" {
    property name="bID";
    property name="aID";
    
    variables._key = "bID";

    function Cs() {
        return hasMany(
            relationName = "C",
            foreignKey = "bID",
            localKey = "bID"
        ).withSomeScope();
    }

    static function initTable() {
        queryExecute("
            drop table if exists rmme_B;
            create table rmme_B(bID int, aID int);
        ")
    }
}

component extends="quick.models.BaseEntity" accessors=true table="rmme_C" {
    property name="cID";
    property name="bID";
    property name="dID";
    
    variables._key = "cID";

    function scopeWithSomeScope( qb ) {
        qb.addSubselect("inlined_dValue", "d.dValue")
    }

    function D() {
        return hasOne(
            relationName = "D",
            foreignKey = "dID",
            localKey = "dID"
        )
    }

    static function initTable() {
        queryExecute("
            drop table if exists rmme_C;
            create table rmme_C(cID int, bID int, dID int);
        ")
    }
}

component extends="quick.models.BaseEntity" accessors=true table="rmme_D" {
    property name="dID";
    property name="dValue";
    
    variables._key = "dID";

    static function initTable() {
        queryExecute("
            drop table if exists rmme_D;
            create table rmme_D(dID int, dValue varchar(max));
        ")
    }
}

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions