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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions