Skip to content

.withCount() on hasManyThrough() throws arrays do not have the same lengths [4,2] when intermediary relationship has a compound key #262

@DiscountDarcy

Description

@DiscountDarcy

We have an entity, qCompetitionSeasonDivision that translates to 'settings for this sports program (competition) for this division for this season' and a relationship where we want to see how many people have registered for that program in that division in that season.

Using a scope with .withCount() causes arrayZipEach() to throw The arrays do not have the same length [[4,2]].

Stripped down entity and relationships:

component table="competition_seasonal_divisional" extends="model.q.inLeagueBaseEntity" accessors=true {
	property name="compSeasonDivUID" column="compSeasonDivUID" type="string" sqltype="idstamp";
	property name="competitionUID"   column="competitionUID"   type="string" sqltype="idstamp";
	property name="seasonUID"        column="seasonUID"        type="string" sqltype="idstamp";
	property name="divID"            column="divID"            type="string" sqltype="idstamp";

    
function v_compSeasonDiv_forAllSourceCompsIncludingSelfSource() {
		return hasMany(
			relationName = "q_v_compSeasonDiv_forAllSourceCompsIncludingSelfSource",
			foreignKey = "compSeasonDivUID",
			localKey = "compSeasonDivUID"
		);
	}

	function competitionRegistrationsIncludingSourcedCompetitions() {
		return hasManyThrough(
			relationships = [ "v_compSeasonDiv_forAllSourceCompsIncludingSelfSource", "competitionRegistrations" ]
		)
	}

The intermediary entity:

component extends="model.q.inLeagueBaseEntity" table="v_competition_seasonal_divisional_forAllSourceCompsIncludingSelfSource" accessors=true {

	property name="compSeasonDivUID"     type="guid"    sqltype="idstamp" readonly=true update=false;
	property name="competitionUID"       type="guid"    sqltype="idstamp" readonly=true update=false;
    property name="seasonUID"            type="guid"    sqltype="idstamp" readonly=true update=false;
	property name="divID"                type="guid"    sqltype="idstamp" readonly=true update=false;
	property name="sourceCompetitionUID" type="guid"    sqltype="idstamp" readonly=true update=false;

	// This definition of the key is not true, but is required to play nice with hasOneOrManyThrough in left side of this "join" table (i.e. in compSeasonDiv).
	// Actual candidate keys are:
	//  - (sourceCompetitionUID, compSeasonDivUID, sourceCompetitionUID)
	//  - (sourceCompetitionUID, competitionUID, seasonUID, divID, sourceCompetitionUID)
	variables._key = 'compSeasonDivUID'

    function competitionRegistrations() {
        return hasMany(
            relationName = "qCompetitionRegistration",
            foreignKey = ["competitionUID", "seasonUID", "divID"],
            localKey = ["sourceCompetitionUID", "seasonUID", "divID"]
        )
    }

	function compSeasonDiv() {
		return belongsTo(
			relationName = "qCompetitionSeasonDivision",
			foreignKey = ["competitionUID", "seasonUID", "divID"],
            localKey = ["sourceCompetitionUID", "seasonUID", "divID"]
		)
	}
}

The following scope throws the error:

function scopeWithCurrentActiveRegistrationsCountIncludingSourcedCompetitions( qb ) {
		qb.withCount( {
			"competitionRegistrationsIncludingSourcedCompetitions as currentActiveRegistrationsCountIncludingSourcedCompetitions" : function(
				qCompetitionRegistration
			) {
				qCompetitionRegistration
					.where( ( qb ) => {
						qb.orWherePaid( 1 )
							.orWhereNotNull( "awaitingAsyncPaymentCompletion" )
					} )
					.whereCanceled( 0 )
			}
		} )
	}

Stack trace:

modules/quick/models/Relationships/BaseRelationship.cfc:609
modules/quick/models/Relationships/HasManyDeep.cfc:217
/root/modules/quick/models/QuickQB.cfc:990
modules/qb/models/Query/QueryBuilder.cfc:1661
modules/quick/models/QuickBuilder.cfc:775
modules/quick/models/Relationships/HasManyDeep.cfc:219
modules/quick/models/QuickBuilder.cfc:265
modules/quick/models/BaseEntity.cfc:1291
modules/quick/models/QuickBuilder.cfc:270
modules/quick/models/BaseEntity.cfc:3079
modules/quick/models/QuickBuilder.cfc:271
model/q/Competition/qCompetitionSeasonDivision.cfc:155

Metadata

Metadata

Assignees

No one assigned

    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