private runQuery()

in uui-db/src/DbTable.ts [173:263]


    private runQuery(q: DataQuery<TEntity>) {
        let result: TEntity[] = null;
        let filter = q.filter;

        if (filter) {
            const indexes = this.state.indexes;

            // Try to use indexes to fulfill filter conditions
            for (let n = 0; n < indexes.length; n++) {
                const index = indexes[n];

                if (index.field in filter) {
                    const { [index.field]: condition, ...rest } = filter as any;
                    let conditionValues: any[] = null;

                    if (condition != null && typeof condition === 'object') {
                        // Attempt to use index for 'in' and 'isNull' criteria.
                        // We need to be very conservative here, indexed field should work the same way as getPatternPredicate. So
                        // - it's better to leave corner cases to getPatternPredicate

                        const { in: inCriteria, isNull: nullCriteria, ...restCriteria } = condition as any;
                        if (inCriteria && Array.isArray(inCriteria)) {
                            conditionValues = inCriteria;
                        } else {
                            restCriteria.in = inCriteria;
                        }

                        // Conditions in getPatternPredicate are composed with 'and' logic,
                        // For now, let's not attempt to handle tricky cases like { in: [1,2] isNull: true }, or { in: [1, null] isNull: false }
                        // - just leave this to getPatternPredicate.
                        // Let's just handle the a most common case { isNull: true } - find all null and undefined
                        if (nullCriteria === true && !conditionValues) {
                            conditionValues = [null, undefined];
                        } else {
                            restCriteria.in = inCriteria;
                        }

                        // Keep other conditions, e.g. { in: [1,2,3], isNull: true } - in works via index, isNull - via filter
                        if (Object.keys(restCriteria).length > 0) {
                            rest[index.field] = restCriteria;
                        }
                    } else {
                        conditionValues = [condition];
                    }

                    if (conditionValues) {
                        result = [];

                        for (let i = 0; i < conditionValues.length; i++) {
                            const idsSet = index.map.get(conditionValues[i]);
                            if (idsSet) {
                                const idsArray = idsSet.toArray();
                                for (let j = 0; j < idsArray.length; j++) {
                                    const item = this.state.pk.get(idsArray[j]);
                                    result.push(item);
                                }
                            }
                        }

                        filter = Object.keys(rest).length > 0 ? (rest as any) : null;
                        break;
                    }
                }
            }
        }

        if (!result) {
            result = this.state.pk.toArray();
        }

        if (filter) {
            const predicate = getFilterPredicate<TEntity>(q.filter);
            result = result.filter(predicate);
        }

        if (q.search) {
            const searchFilter = getSearchFilter(q.search);
            result = result.filter((item) => searchFilter(this.schema.searchBy.map((field) => (item as any)[field])));
        }

        if (q.sorting) {
            const comparer = getOrderComparer(q.sorting);
            result = result.sort(comparer);
        }

        if (q.range) {
            result = result.slice(q.range.from, q.range.from + q.range.count);
        }

        return result;
    }