Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Filtering does not work on HasMany relations #80

Open
DeanMauro opened this issue Mar 17, 2021 · 2 comments · May be fixed by #92
Open

Filtering does not work on HasMany relations #80

DeanMauro opened this issue Mar 17, 2021 · 2 comments · May be fixed by #92

Comments

@DeanMauro
Copy link
Collaborator

DeanMauro commented Mar 17, 2021

How to Reproduce

  1. Take the two models Component and ComponentVersion, where Component HasMany ComponentVersions:

Component

class Component extends Model {
  public static tableName = 'components';
  public static idColumn = 'component_id';
  public static modelPaths = [ __dirname ];

  // Fields
  public component_id!: number;

  // Relational Fields
  public versions!: ComponentVersion[] | null;
  
  // Relational Mappings
  public static relationMappings() {
    return {
      versions: {
        relation: Model.HasManyRelation,
        modelClass: ComponentVersion,
        join: {
          from: 'components.component_id',
          to: 'component_versions.component_id'
        }
      }
    };
  }
}

ComponentVersion

class ComponentVersion extends Model {
  public static tableName = 'component_versions';
  public static idColumn = 'component_version_id';
  public static modelPaths = [ __dirname ];

  // Fields
  public component_version_id!: number;
  public component_id!: number;
  public component_version_is_active!: boolean;
}
  1. Attempt to retrieve all Components and filter on one of ComponentVersion's fields:
  public async getAllComponents(): Promise<Component[]> {
    const request = Component.query().withGraphFetched('versions');
    const filter = { 'versions.component_version_is_active:eq': '1' };

    return await findQuery(Component).build(filter, request);
  }
  1. The following SQL is produced:
select `components`.* from `components` 
where exists (
  select 1 from `component_versions` as `ComponentVersion` 
  where `ComponentVersion`.`component_id` = `components`.`component_id` 
  and `component_versions`.`component_version_is_active` like '1'
)

Notice that an alias is given to the relational table's name (in this example, the component_versions table is aliased as ComponentVersion), but this alias is not used on the last line where the query performs the filter operation. Instead, ComponentVersion's table_name is used, causing the query to fail with error:

ER_BAD_FIELD_ERROR: Unknown column 'component_versions.component_version_is_active' in 'where clause'.

When the alias is used, the SQL statement works as intended:

select `components`.* from `components` 
where exists (
  select 1 from `component_versions` as `ComponentVersion` 
  where `ComponentVersion`.`component_id` = `components`.`component_id` 
  and `ComponentVersion`.`component_version_is_active` like '1'
)

Proposed Solution

This issue exists because PropertyRef.buildFilter() aliases XToMany relations, but PropertyRef.fullColumnName() does not. I propose adding this aliasing to PropertyRef.fullColumnName() as well.
Resolved in #81

@vpeltola
Copy link

vpeltola commented Sep 21, 2021

I'm running into this issue as well. Could this fix be released, please?
Here's the bad sql generated by objection-find

'select "store_items".* from "store_items" where exists (
  select 1 from "store_item_products" "Store_Item_Product"
 where "Store_Item_Product"."item_id" = "store_items"."item_id" and "store_item_products"."product_id" in (?)
) and "type" = ?'

The and "store_item_products"."product_id" should be and "Store_Item_Product"."product_id"

@DavidPayne-Woodscamp
Copy link
Contributor

I have also encountered this issue. Here is the bad SQL generated:

select "landowners".* from "landowners" where exists (select 1 from "landowner_parcel" as "LandownerParcel" where "LandownerParcel"."landowner_id" = "landowners"."id" and "landowner_parcel"."parcel_id" = ?)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants