Search in sources :

Example 1 with ISQLTableJoin

use of com.servoy.j2db.query.ISQLTableJoin in project servoy-client by Servoy.

the class FlattenedSolution method getValuelistSortRelation.

/**
 * Get the internal relation that can be used to sort on this value list using the display values.
 * @param valueList
 * @param callingTable
 * @param dataProviderID
 * @param foundSetManager
 * @return
 * @throws RepositoryException
 */
public Relation getValuelistSortRelation(ValueList valueList, Table callingTable, String dataProviderID, IFoundSetManagerInternal foundSetManager) throws RepositoryException {
    if (callingTable == null || valueList == null) {
        return null;
    }
    String destDataSource;
    Relation[] relationSequence;
    String relationPrefix;
    switch(valueList.getDatabaseValuesType()) {
        case IValueListConstants.TABLE_VALUES:
            // create an internal relation
            relationSequence = null;
            // $NON-NLS-1$
            relationPrefix = "";
            destDataSource = valueList.getDataSource();
            break;
        case IValueListConstants.RELATED_VALUES:
            // replace the last relation in the sequence with an internal relation
            relationSequence = getRelationSequence(valueList.getRelationName());
            if (relationSequence == null) {
                return null;
            }
            if (relationSequence.length > 1) {
                for (Relation r : relationSequence) {
                    if (r.getJoinType() != INNER_JOIN) {
                        // outer join on the intermediate tables causes extra results that influence the sorting result
                        return null;
                    }
                }
            }
            StringBuilder sb = new StringBuilder();
            for (Relation r : relationSequence) {
                sb.append('-').append(r.getName());
            }
            relationPrefix = sb.toString();
            destDataSource = relationSequence[relationSequence.length - 1].getForeignDataSource();
            break;
        default:
            return null;
    }
    if (destDataSource == null || !DataSourceUtils.isSameServer(callingTable.getDataSource(), destDataSource)) {
        // do not create a cross-server relation
        return null;
    }
    Table destTable = (Table) foundSetManager.getTable(destDataSource);
    if (destTable == null) {
        return null;
    }
    String relationName = // $NON-NLS-1$
    Relation.INTERNAL_PREFIX + "VL-" + callingTable.getDataSource() + '-' + dataProviderID + relationPrefix + '-' + valueList.getName() + '-';
    synchronized (this) {
        Column callingColumn = callingTable.getColumn(dataProviderID);
        if (callingColumn == null) {
            return null;
        }
        Relation relation = getRelation(relationName);
        if (relation == null) {
            // create in internal relation
            String dp;
            int returnValues = valueList.getReturnDataProviders();
            if ((returnValues & 1) != 0) {
                dp = valueList.getDataProviderID1();
            } else if ((returnValues & 2) != 0) {
                dp = valueList.getDataProviderID2();
            } else if ((returnValues & 4) != 0) {
                dp = valueList.getDataProviderID3();
            } else {
                return null;
            }
            Column destColumn = destTable.getColumn(dp);
            if (destColumn == null) {
                return null;
            }
            // create internal value list relation
            QueryTable callingQTable = new QueryTable(callingTable.getSQLName(), callingTable.getDataSource(), callingTable.getCatalog(), callingTable.getSchema());
            QueryTable destQTable = new QueryTable(destTable.getSQLName(), destTable.getDataSource(), destTable.getCatalog(), destTable.getSchema());
            List<ISQLTableJoin> joins = new ArrayList<ISQLTableJoin>();
            ISQLTableJoin lastJoin = null;
            if (relationSequence == null) {
                // table values
                joins.add(lastJoin = new QueryJoin(relationName, callingQTable, destQTable, new AndCondition(), LEFT_OUTER_JOIN, false));
                if (// apply name as filter on column valuelist_name
                valueList.getUseTableFilter()) {
                    lastJoin.getCondition().addCondition(new CompareCondition(IBaseSQLCondition.EQUALS_OPERATOR, new QueryColumn(destQTable, DBValueList.NAME_COLUMN), valueList.getName()));
                }
            } else {
                // related values
                QueryTable primaryQTable = callingQTable;
                for (int i = 0; i < relationSequence.length; i++) {
                    Relation r = relationSequence[i];
                    QueryTable foreignQTable;
                    if (i == relationSequence.length - 1) {
                        // last one
                        foreignQTable = destQTable;
                    } else {
                        ITable relForeignTable = getTable(r.getForeignDataSource());
                        if (relForeignTable == null) {
                            return null;
                        }
                        foreignQTable = new QueryTable(relForeignTable.getSQLName(), relForeignTable.getDataSource(), relForeignTable.getCatalog(), relForeignTable.getSchema());
                    }
                    lastJoin = SQLGenerator.createJoin(this, r, primaryQTable, foreignQTable, false, new IGlobalValueEntry() {

                        public Object setDataProviderValue(String dpid, Object value) {
                            return null;
                        }

                        public Object getDataProviderValue(String dpid) {
                            // A value will be added when the relation is used, see SQLGenerator.createJoin
                            return new Placeholder(new ObjectPlaceholderKey<int[]>(null, dpid));
                        }

                        public boolean containsDataProvider(String dpid) {
                            return false;
                        }
                    });
                    joins.add(lastJoin);
                    primaryQTable = foreignQTable;
                }
            }
            // add condition for return dp id
            lastJoin.getCondition().addCondition(new CompareCondition(IBaseSQLCondition.EQUALS_OPERATOR, destColumn.queryColumn(destQTable), callingColumn.queryColumn(callingQTable)));
            relation = getSolutionCopy().createNewRelation(new ScriptNameValidator(this), relationName, callingTable.getDataSource(), destDataSource, LEFT_OUTER_JOIN);
            ISQLTableJoin join;
            if (joins.size() == 1) {
                join = lastJoin;
            } else {
                // combine joins
                join = new QueryCompositeJoin(relationName, joins);
            }
            relation.setRuntimeProperty(Relation.RELATION_JOIN, join);
        }
        return relation;
    }
}
Also used : Placeholder(com.servoy.j2db.query.Placeholder) Table(com.servoy.j2db.persistence.Table) QueryTable(com.servoy.j2db.query.QueryTable) ITable(com.servoy.j2db.persistence.ITable) ArrayList(java.util.ArrayList) QueryJoin(com.servoy.j2db.query.QueryJoin) QueryTable(com.servoy.j2db.query.QueryTable) AndCondition(com.servoy.j2db.query.AndCondition) Relation(com.servoy.j2db.persistence.Relation) IGlobalValueEntry(com.servoy.j2db.dataprocessing.IGlobalValueEntry) QueryCompositeJoin(com.servoy.j2db.query.QueryCompositeJoin) QueryColumn(com.servoy.j2db.query.QueryColumn) Column(com.servoy.j2db.persistence.Column) IColumn(com.servoy.j2db.persistence.IColumn) ISQLTableJoin(com.servoy.j2db.query.ISQLTableJoin) QueryColumn(com.servoy.j2db.query.QueryColumn) CompareCondition(com.servoy.j2db.query.CompareCondition) ITable(com.servoy.j2db.persistence.ITable) JSONObject(org.json.JSONObject) IRootObject(com.servoy.j2db.persistence.IRootObject) ScriptNameValidator(com.servoy.j2db.persistence.ScriptNameValidator)

Example 2 with ISQLTableJoin

use of com.servoy.j2db.query.ISQLTableJoin in project servoy-client by Servoy.

the class FindState method createFindStateJoins.

/**
 * Find all processable related find states and create joins. A find state is processable when it has changed or when a related find state has changed.
 * @param sqlSelect
 * @param relations path to this state
 * @param selectTable
 * @param provider
 * @return
 * @throws RepositoryException
 */
public List<RelatedFindState> createFindStateJoins(QuerySelect sqlSelect, List<IRelation> relations, BaseQueryTable selectTable, IGlobalValueEntry provider) throws RepositoryException {
    List<RelatedFindState> relatedFindStates = null;
    List<Relation> searchRelations = getValidSearchRelations();
    // find processable find states of related find states
    for (Relation relation : searchRelations) {
        if (relation != null) {
            IFoundSetInternal set = relatedStates.get(relation.getName());
            if (set != null && set.getSize() > 0) {
                ISQLTableJoin existingJoin = (ISQLTableJoin) sqlSelect.getJoin(selectTable, relation.getName());
                BaseQueryTable foreignQTable;
                if (existingJoin == null) {
                    ITable foreignTable = parent.getFoundSetManager().getApplication().getFlattenedSolution().getTable(relation.getForeignDataSource());
                    foreignQTable = new QueryTable(foreignTable.getSQLName(), foreignTable.getDataSource(), foreignTable.getCatalog(), foreignTable.getSchema());
                } else {
                    foreignQTable = existingJoin.getForeignTable();
                }
                FindState fs = (FindState) set.getRecord(0);
                List<IRelation> nextRelations = new ArrayList<IRelation>(relations);
                nextRelations.add(relation);
                List<RelatedFindState> rfs = fs.createFindStateJoins(sqlSelect, nextRelations, foreignQTable, provider);
                if (rfs != null && rfs.size() > 0) {
                    // changed related findstate, add self with join
                    if (relatedFindStates == null) {
                        relatedFindStates = rfs;
                    } else {
                        relatedFindStates.addAll(rfs);
                    }
                    if (existingJoin == null) {
                        sqlSelect.addJoin(SQLGenerator.createJoin(parent.getFoundSetManager().getApplication().getFlattenedSolution(), relation, selectTable, foreignQTable, false, provider));
                    }
                }
            }
        }
    }
    // add yourself if you have changed or one or more related states has changed
    if (isChanged() || (relatedFindStates != null && relatedFindStates.size() > 0)) {
        if (relatedFindStates == null) {
            relatedFindStates = new ArrayList<RelatedFindState>();
        }
        relatedFindStates.add(new RelatedFindState(this, relations, selectTable));
    }
    return relatedFindStates;
}
Also used : ArrayList(java.util.ArrayList) BaseQueryTable(com.servoy.base.query.BaseQueryTable) QueryTable(com.servoy.j2db.query.QueryTable) Relation(com.servoy.j2db.persistence.Relation) IRelation(com.servoy.j2db.persistence.IRelation) BaseQueryTable(com.servoy.base.query.BaseQueryTable) ISQLTableJoin(com.servoy.j2db.query.ISQLTableJoin) IRelation(com.servoy.j2db.persistence.IRelation) ITable(com.servoy.j2db.persistence.ITable)

Example 3 with ISQLTableJoin

use of com.servoy.j2db.query.ISQLTableJoin in project servoy-client by Servoy.

the class FoundSet method loadByQuery.

public boolean loadByQuery(String query, Object[] args) throws ServoyException {
    if (query == null || sheet.getTable() == null)
        return false;
    int from_index = -1;
    int order_by_index;
    // check requirements
    if (!SQLGenerator.isSelectQuery(query)) {
        throw new IllegalArgumentException(SQLGenerator.SQL_QUERY_VALIDATION_MESSAGE + ':' + query);
    }
    String sql_lowercase = Utils.toEnglishLocaleLowerCase(query);
    // $NON-NLS-1$
    order_by_index = sql_lowercase.lastIndexOf("order by");
    boolean analyse_query_parts = (order_by_index != -1);
    if (analyse_query_parts) {
        // subquery. NOTE: this means that the ordering defined in the order-by part is lost.
        if (// $NON-NLS-1$
        ((from_index = sql_lowercase.indexOf("from")) == -1) || (sql_lowercase.indexOf(Utils.toEnglishLocaleLowerCase(sheet.getTable().getSQLName())) == -1) || // $NON-NLS-1$
        (sql_lowercase.indexOf("group by") != -1) || // $NON-NLS-1$
        (sql_lowercase.indexOf("having") != -1) || // $NON-NLS-1$
        (sql_lowercase.indexOf("union") != -1) || // $NON-NLS-1$
        (sql_lowercase.indexOf("join") != -1) || // $NON-NLS-1$
        (sql_lowercase.indexOf(".") == -1)) {
            analyse_query_parts = false;
        }
    }
    if (initialized && (getFoundSetManager().getEditRecordList().stopIfEditing(this) != ISaveConstants.STOPPED)) {
        fsm.getApplication().reportJSError(// $NON-NLS-1$
        "couldn't load dataset because foundset had edited records but couldn't save it: " + this + ", edited record(s): " + Utils.stringJoin(getFoundSetManager().getEditRecordList().getEditedRecords(this), '.') + ", failed record(s): " + Utils.stringJoin(getFoundSetManager().getEditRecordList().getFailedRecords(this), '.'), null);
        return false;
    }
    QuerySelect originalQuery = pksAndRecords.getQuerySelectForReading();
    QuerySelect sqlSelect = AbstractBaseQuery.deepClone(creationSqlSelect);
    sqlSelect.clearCondition(SQLGenerator.CONDITION_RELATION);
    sqlSelect.clearCondition(SQLGenerator.CONDITION_OMIT);
    if (rowManager != null)
        rowManager.clearAndCheckCache();
    initialized = true;
    Object[] whereArgs = null;
    if (args != null) {
        whereArgs = new Object[args.length];
        for (int i = 0; i < args.length; i++) {
            Object o = args[i];
            if (o != null && o.getClass().equals(Date.class)) {
                o = new Timestamp(((Date) o).getTime());
            }
            whereArgs[i] = o;
        }
    }
    // for instance, loadRecords(SQL) followed by extended search (S) and invertrecords executes query 'NOT(SQL OR S)'
    if (!analyse_query_parts) {
        // do not analyze the parts of the query, just create a set-condition that compares the pk columns with the result of the subquery
        Iterator<Column> pkIt = ((Table) getTable()).getRowIdentColumns().iterator();
        if (!pkIt.hasNext()) {
            throw new RepositoryException(ServoyException.InternalCodes.PRIMARY_KEY_NOT_FOUND, new Object[] { getTable().getName() }).setContext(this.toString());
        }
        List<QueryColumn> pkQueryColumns = new ArrayList<QueryColumn>();
        while (pkIt.hasNext()) {
            Column c = pkIt.next();
            pkQueryColumns.add(c.queryColumn(sqlSelect.getTable()));
        }
        // must strip of the order-by part because not all databases (Oracle, who else) like order-by in subselect
        String customQuery = query;
        if (order_by_index > 0) {
            // query contains order-by clause, find the next a closing bracket if it exists.
            // order-by has to be removed because some dbs do not allow that inside subselect.
            char[] chars = query.toCharArray();
            int level = 1;
            int i;
            for (i = order_by_index; level > 0 && i < chars.length; i++) {
                switch(chars[i]) {
                    case ')':
                        level--;
                        break;
                    case '(':
                        level++;
                        break;
                }
            }
            // in that case we can leave the ordering in place because it it not the sorting of the top-level query.
            if (level == 1) {
                // order-by clause was at the end
                customQuery = query.substring(0, order_by_index);
            }
        }
        sqlSelect.setCondition(SQLGenerator.CONDITION_SEARCH, new SetCondition(IBaseSQLCondition.IN_OPERATOR, pkQueryColumns.toArray(new QueryColumn[pkQueryColumns.size()]), new QueryCustomSelect(customQuery, whereArgs), true));
        // set the previous sort, add all joins that are needed for this sort
        List<IQuerySort> origSorts = originalQuery.getSorts();
        if (origSorts != null) {
            ArrayList<IQuerySort> sorts = new ArrayList<IQuerySort>();
            // find which sorts we will use and which tables are needed for that
            Set<BaseQueryTable> sortTables = new HashSet<BaseQueryTable>();
            for (IQuerySort isort : origSorts) {
                if (isort instanceof QuerySort) {
                    QuerySort sort = (QuerySort) isort;
                    IQuerySelectValue icolumn = sort.getColumn();
                    if (icolumn instanceof QueryColumn) {
                        QueryColumn column = (QueryColumn) icolumn;
                        sortTables.add(column.getTable());
                        sorts.add(sort);
                    }
                }
            // ignore custom sorts and sorts on other things than columns
            }
            // try to find the joins that are needed to satisfy tablesToResolve
            List<BaseQueryTable> tablesToResolve = new ArrayList<BaseQueryTable>();
            tablesToResolve.addAll(sortTables);
            List<BaseQueryTable> resolvedTables = new ArrayList<BaseQueryTable>();
            resolvedTables.add(sqlSelect.getTable());
            ArrayList<ISQLJoin> requiredJoins = new ArrayList<ISQLJoin>();
            boolean found = true;
            while (found && tablesToResolve.size() > 0) {
                BaseQueryTable table = tablesToResolve.remove(0);
                if (resolvedTables.contains(table)) {
                    continue;
                }
                found = false;
                ArrayList<ISQLJoin> joins = originalQuery.getJoins();
                if (joins != null) {
                    for (ISQLJoin ijoin : joins) {
                        if (!found && ijoin instanceof ISQLTableJoin) {
                            ISQLTableJoin join = (ISQLTableJoin) ijoin;
                            if (table.equals(join.getForeignTable())) {
                                // have to add this join
                                tablesToResolve.add(join.getPrimaryTable());
                                resolvedTables.add(table);
                                requiredJoins.add(join);
                                found = true;
                            }
                        }
                    }
                }
            }
            if (found) {
                sqlSelect.setJoins(requiredJoins);
                sqlSelect.setSorts(sorts);
            } else {
                // $NON-NLS-1$
                Debug.log("Could not restore order by in loadRecords(): couild not find all tables for sorting in " + originalQuery);
            }
        }
    } else {
        // create a query with the different parts as custom elements
        sqlSelect.clearJoins();
        // not needed when you have no joins and may conflict with order by
        sqlSelect.setDistinct(false);
        String tables;
        // $NON-NLS-1$
        int where_index = sql_lowercase.indexOf("where");
        if (where_index == -1) {
            tables = query.substring(from_index + 4, order_by_index);
            // no where-clause, remove the search condition (was set to FALSE in clear()
            sqlSelect.clearCondition(SQLGenerator.CONDITION_SEARCH);
        } else {
            tables = query.substring(from_index + 4, where_index);
            sqlSelect.setCondition(SQLGenerator.CONDITION_SEARCH, new CustomCondition(query.substring(where_index + 5, order_by_index).trim(), whereArgs));
        }
        // pick the foundset main table from the tables in the query (does not have to be the first one, we generate sql ourselves
        // that puts the main table at the end, see QueryGenerator)
        boolean foundTable = false;
        String mainTable = sheet.getTable().getName();
        StringBuilder otherTables = new StringBuilder();
        // $NON-NLS-1$
        StringTokenizer tok = new StringTokenizer(tables, ",");
        // default alias to table name
        String mainTableAlias = mainTable;
        // $NON-NLS-1$
        String whitespace = "\\s+";
        while (tok.hasMoreElements()) {
            String tableName = tok.nextToken().trim();
            String[] lcTableName = tableName.toLowerCase().split(whitespace);
            if (matchesMainTablename(lcTableName[0])) {
                foundTable = true;
                // either 'tabname', 'tabname aliasname' or 'tabname AS aliasname', when no alias is given, use table name as alias
                mainTableAlias = tableName.split(whitespace)[lcTableName.length - 1];
            } else {
                if (otherTables.length() > 0) {
                    // $NON-NLS-1$
                    otherTables.append(", ");
                }
                otherTables.append(tableName);
            }
        }
        // set table alias or unalias table when no alias was used
        BaseQueryTable qTable = sqlSelect.getTable();
        sqlSelect.relinkTable(sqlSelect.getTable(), new QueryTable(qTable.getName(), qTable.getDataSource(), qTable.getCatalogName(), qTable.getSchemaName(), mainTableAlias));
        if (otherTables.length() > 0) {
            // $NON-NLS-1$
            if (!foundTable)
                throw new IllegalArgumentException(fsm.getApplication().getI18NMessage("servoy.foundSet.query.error.firstTable"));
            // $NON-NLS-1$
            sqlSelect.addJoin(new QueryCustomJoin("foundset.loadbyquery", sqlSelect.getTable(), otherTables.toString()));
        }
        ArrayList<IQuerySort> sorts = new ArrayList<IQuerySort>();
        // $NON-NLS-1$
        Enumeration<Object> sortParts = new StringTokenizer(query.substring(order_by_index + 8), ",");
        while (sortParts.hasMoreElements()) {
            sorts.add(new QueryCustomSort(((String) sortParts.nextElement()).trim()));
        }
        sqlSelect.setSorts(sorts);
    }
    return loadByQuery(sqlSelect);
}
Also used : ArrayList(java.util.ArrayList) SafeArrayList(com.servoy.j2db.util.SafeArrayList) SetCondition(com.servoy.j2db.query.SetCondition) Timestamp(java.sql.Timestamp) IQuerySort(com.servoy.j2db.query.IQuerySort) QueryCustomSort(com.servoy.j2db.query.QueryCustomSort) QueryColumn(com.servoy.j2db.query.QueryColumn) Column(com.servoy.j2db.persistence.Column) IColumn(com.servoy.j2db.persistence.IColumn) ISQLTableJoin(com.servoy.j2db.query.ISQLTableJoin) IQuerySort(com.servoy.j2db.query.IQuerySort) QuerySort(com.servoy.j2db.query.QuerySort) HashSet(java.util.HashSet) CustomCondition(com.servoy.j2db.query.CustomCondition) RepositoryException(com.servoy.j2db.persistence.RepositoryException) ISQLJoin(com.servoy.j2db.query.ISQLJoin) QueryCustomSelect(com.servoy.j2db.query.QueryCustomSelect) QuerySelect(com.servoy.j2db.query.QuerySelect) Date(java.util.Date) BaseQueryTable(com.servoy.base.query.BaseQueryTable) QueryTable(com.servoy.j2db.query.QueryTable) StringTokenizer(java.util.StringTokenizer) BaseQueryTable(com.servoy.base.query.BaseQueryTable) QueryCustomJoin(com.servoy.j2db.query.QueryCustomJoin) QueryColumn(com.servoy.j2db.query.QueryColumn) IQuerySelectValue(com.servoy.j2db.query.IQuerySelectValue)

Example 4 with ISQLTableJoin

use of com.servoy.j2db.query.ISQLTableJoin in project servoy-client by Servoy.

the class SQLGenerator method addSorts.

public void addSorts(QuerySelect sqlSelect, BaseQueryTable selectTable, IGlobalValueEntry provider, ITable table, List<SortColumn> orderByFields, boolean includeRelated, boolean permanentJoins) throws RepositoryException {
    List<Column> unusedRowidentColumns = new ArrayList<Column>(table.getRowIdentColumns());
    for (int i = 0; orderByFields != null && i < orderByFields.size(); i++) {
        SortColumn sc = orderByFields.get(i);
        // can be column or aggregate
        IColumn column = sc.getColumn();
        if (column.getDataProviderType() == MEDIA && (column.getFlags() & (IDENT_COLUMNS | UUID_COLUMN)) == 0) {
            // skip cannot sort blob columns
            continue;
        }
        SortOptions sortOptions = application.getFoundSetManager().getSortOptions(sc.getColumn());
        Relation[] relations = sc.getRelations();
        // compare on server objects, relation.foreignServerName may be different in case of duplicates
        boolean doRelatedJoin = (includeRelated && relations != null);
        if (doRelatedJoin) {
            FlattenedSolution fs = application.getFlattenedSolution();
            for (Relation relation : relations) {
                if (relation.isMultiServer() && !fs.getTable(relation.getForeignDataSource()).getServerName().equals(table.getServerName())) {
                    doRelatedJoin = false;
                    break;
                }
            }
        }
        if (doRelatedJoin) // related sort, cannot join across multiple servers
        {
            BaseQueryTable primaryQtable = selectTable;
            BaseQueryTable foreignQtable = null;
            for (Relation relation : relations) {
                // join must be re-created as it is possible to have globals involved;
                // first remove, then create it
                ISQLTableJoin join = (ISQLTableJoin) sqlSelect.getJoin(primaryQtable, relation.getName());
                if (join != null)
                    sqlSelect.getJoins().remove(join);
                if (join == null) {
                    ITable foreignTable = application.getFlattenedSolution().getTable(relation.getForeignDataSource());
                    foreignQtable = new QueryTable(foreignTable.getSQLName(), foreignTable.getDataSource(), foreignTable.getCatalog(), foreignTable.getSchema());
                } else {
                    foreignQtable = join.getForeignTable();
                }
                sqlSelect.addJoin(createJoin(application.getFlattenedSolution(), relation, primaryQtable, foreignQtable, permanentJoins, provider));
                primaryQtable = foreignQtable;
            }
            IQuerySelectValue queryColumn;
            if (column instanceof Column) {
                queryColumn = ((Column) column).queryColumn(foreignQtable);
                unusedRowidentColumns.remove(column);
            } else if (column instanceof AggregateVariable) {
                AggregateVariable aggregate = (AggregateVariable) column;
                queryColumn = new QueryAggregate(aggregate.getType(), new QueryColumn(foreignQtable, -1, aggregate.getColumnNameToAggregate(), aggregate.getDataProviderType(), aggregate.getLength(), 0, null, aggregate.getFlags()), aggregate.getName());
                // there has to be a group-by clause for all selected fields
                List<IQuerySelectValue> columns = sqlSelect.getColumns();
                for (IQuerySelectValue selectVal : columns) {
                    List<IQuerySelectValue> groupBy = sqlSelect.getGroupBy();
                    if (selectVal instanceof QueryColumn && (groupBy == null || !groupBy.contains(selectVal))) {
                        sqlSelect.addGroupBy(selectVal);
                    }
                }
                // if the aggregate has not been selected yet, add it and skip it in the result
                QueryAggregate skippedAggregate = new QueryAggregate(aggregate.getType(), QueryAggregate.ALL, new QueryColumn(foreignQtable, -1, aggregate.getColumnNameToAggregate(), aggregate.getDataProviderType(), aggregate.getLength(), 0, null, aggregate.getFlags()), aggregate.getName(), null, true);
                if (!columns.contains(skippedAggregate)) {
                    sqlSelect.addColumn(skippedAggregate);
                }
            } else {
                // $NON-NLS-1$
                Debug.log("Skipping sort on unexpected related column type " + column.getClass());
                continue;
            }
            sqlSelect.addSort(new QuerySort(queryColumn, sc.getSortOrder() == ASCENDING, sortOptions));
        } else {
            // make sure an invalid sort is not possible
            if (column instanceof Column && column.getTable().getName().equals(table.getName())) {
                sqlSelect.addSort(new QuerySort(((Column) column).queryColumn(selectTable), sc.getSortOrder() == ASCENDING, sortOptions));
                unusedRowidentColumns.remove(column);
            } else {
                // $NON-NLS-1$ //$NON-NLS-2$
                Debug.log("Skipping sort on unrelated column " + column.getName() + '.' + column.getTable().getName() + " for table " + table.getName());
            }
        }
    }
    // Make sure pk is part of the sort, in case of non-unique sort columns, the sorted result may not be the same in each fetch
    if (enforcePkInSort) {
        for (Column column : unusedRowidentColumns) {
            SortOptions sortOptions = application.getFoundSetManager().getSortOptions(column);
            sqlSelect.addSort(new QuerySort(column.queryColumn(selectTable), true, sortOptions));
        }
    }
}
Also used : QueryAggregate(com.servoy.j2db.query.QueryAggregate) ArrayList(java.util.ArrayList) SafeArrayList(com.servoy.j2db.util.SafeArrayList) FlattenedSolution(com.servoy.j2db.FlattenedSolution) AggregateVariable(com.servoy.j2db.persistence.AggregateVariable) BaseQueryTable(com.servoy.base.query.BaseQueryTable) QueryTable(com.servoy.j2db.query.QueryTable) Relation(com.servoy.j2db.persistence.Relation) IRelation(com.servoy.j2db.persistence.IRelation) BaseQueryTable(com.servoy.base.query.BaseQueryTable) QueryColumn(com.servoy.j2db.query.QueryColumn) BaseQueryColumn(com.servoy.base.query.BaseQueryColumn) IColumn(com.servoy.j2db.persistence.IColumn) Column(com.servoy.j2db.persistence.Column) IColumn(com.servoy.j2db.persistence.IColumn) ISQLTableJoin(com.servoy.j2db.query.ISQLTableJoin) QueryColumn(com.servoy.j2db.query.QueryColumn) BaseQueryColumn(com.servoy.base.query.BaseQueryColumn) QuerySort(com.servoy.j2db.query.QuerySort) IQuerySort(com.servoy.j2db.query.IQuerySort) ITable(com.servoy.j2db.persistence.ITable) List(java.util.List) ArrayList(java.util.ArrayList) SafeArrayList(com.servoy.j2db.util.SafeArrayList) Collectors.toList(java.util.stream.Collectors.toList) SortOptions(com.servoy.j2db.query.SortOptions) IQuerySelectValue(com.servoy.j2db.query.IQuerySelectValue)

Example 5 with ISQLTableJoin

use of com.servoy.j2db.query.ISQLTableJoin in project servoy-client by Servoy.

the class SQLGenerator method createJoin.

/**
 * Join clause for this relation.
 */
public static ISQLTableJoin createJoin(IDataProviderHandler flattenedSolution, IRelation relation, BaseQueryTable primaryTable, BaseQueryTable foreignTable, boolean permanentJoin, final IGlobalValueEntry provider) throws RepositoryException {
    if (relation instanceof AbstractBase) {
        ISQLTableJoin queryJoin = ((AbstractBase) relation).getRuntimeProperty(Relation.RELATION_JOIN);
        if (queryJoin != null) {
            // a query join was defined for this relation, just relink the tables for the first and last in the joins
            queryJoin = deepClone(queryJoin);
            queryJoin = AbstractBaseQuery.relinkTable(queryJoin.getPrimaryTable(), primaryTable, queryJoin);
            queryJoin = AbstractBaseQuery.relinkTable(queryJoin.getForeignTable(), foreignTable, queryJoin);
            // update the placeholders for globals
            queryJoin.acceptVisitor(new IVisitor() {

                public Object visit(Object o) {
                    if (o instanceof Placeholder && ((Placeholder) o).getKey() instanceof ObjectPlaceholderKey) {
                        Object value = provider.getDataProviderValue(((ObjectPlaceholderKey<int[]>) ((Placeholder) o).getKey()).getName());
                        int[] args = ((ObjectPlaceholderKey<int[]>) ((Placeholder) o).getKey()).getObject();
                        int dataProviderType = args[0];
                        int flags = args[1];
                        if (value == null) {
                            return ValueFactory.createNullValue(dataProviderType);
                        }
                        return Column.getAsRightType(dataProviderType, flags, value, Integer.MAX_VALUE, false, false);
                    }
                    return o;
                }
            });
            return queryJoin;
        }
    }
    // build a join from the relation items
    IDataProvider[] primary = relation.getPrimaryDataProviders(flattenedSolution);
    Column[] foreign = relation.getForeignColumns(flattenedSolution);
    int[] operators = relation.getOperators();
    AndCondition joinCondition = new AndCondition();
    for (int x = 0; x < primary.length; x++) {
        Column primaryColumn = null;
        // check if stored script calc or table column
        if (primary[x] instanceof ScriptCalculation) {
            ScriptCalculation sc = ((ScriptCalculation) primary[x]);
            // null when not stored
            primaryColumn = sc.getTable().getColumn(sc.getName());
        } else if (primary[x] instanceof Column) {
            primaryColumn = (Column) primary[x];
        }
        QueryColumn foreignColumn = foreign[x].queryColumn(foreignTable);
        Object value;
        if (primaryColumn == null) {
            if (primary[x] instanceof LiteralDataprovider) {
                value = ((LiteralDataprovider) primary[x]).getValue();
                value = foreign[x].getAsRightType(value);
            } else {
                value = provider.getDataProviderValue(primary[x].getDataProviderID());
                if (value == null) {
                    value = ValueFactory.createNullValue(primary[x].getDataProviderType());
                } else if (value instanceof Placeholder) {
                    if (((Placeholder) value).getKey() instanceof ObjectPlaceholderKey<?>) {
                        ((ObjectPlaceholderKey) ((Placeholder) value).getKey()).setObject(new int[] { primary[x].getDataProviderType(), primary[x].getFlags() });
                    }
                } else {
                    value = Column.getAsRightType(primary[x].getDataProviderType(), primary[x].getFlags(), value, Integer.MAX_VALUE, false, false);
                }
            }
        } else // table type, can be stored calc
        {
            value = primaryColumn.queryColumn(primaryTable);
        }
        // all operators are swappable because only relation operators in RelationItem.RELATION_OPERATORS can be defined.
        // NOTE: elements in joinCondition MUST be CompareConditions (expected in QueryGenerator and SQLGenerator.createConditionFromFindState)
        joinCondition.addCondition(new CompareCondition(RelationItem.swapOperator(operators[x]), foreignColumn, value));
    }
    if (joinCondition.getConditions().size() == 0) {
        // $NON-NLS-1$
        throw new RepositoryException("Missing join condition in relation " + relation.getName());
    }
    return new QueryJoin(relation.getName(), primaryTable, foreignTable, joinCondition, relation.getJoinType(), permanentJoin);
}
Also used : Placeholder(com.servoy.j2db.query.Placeholder) IVisitor(com.servoy.j2db.util.visitor.IVisitor) AbstractBase(com.servoy.j2db.persistence.AbstractBase) QueryJoin(com.servoy.j2db.query.QueryJoin) RepositoryException(com.servoy.j2db.persistence.RepositoryException) IDataProvider(com.servoy.j2db.persistence.IDataProvider) LiteralDataprovider(com.servoy.j2db.persistence.LiteralDataprovider) AndCondition(com.servoy.j2db.query.AndCondition) ScriptCalculation(com.servoy.j2db.persistence.ScriptCalculation) ISQLTableJoin(com.servoy.j2db.query.ISQLTableJoin) QueryColumn(com.servoy.j2db.query.QueryColumn) BaseQueryColumn(com.servoy.base.query.BaseQueryColumn) IColumn(com.servoy.j2db.persistence.IColumn) Column(com.servoy.j2db.persistence.Column) QueryColumn(com.servoy.j2db.query.QueryColumn) BaseQueryColumn(com.servoy.base.query.BaseQueryColumn) CompareCondition(com.servoy.j2db.query.CompareCondition) ObjectPlaceholderKey(com.servoy.j2db.query.ObjectPlaceholderKey)

Aggregations

ISQLTableJoin (com.servoy.j2db.query.ISQLTableJoin)8 ArrayList (java.util.ArrayList)7 BaseQueryTable (com.servoy.base.query.BaseQueryTable)6 Column (com.servoy.j2db.persistence.Column)6 QueryColumn (com.servoy.j2db.query.QueryColumn)6 QueryTable (com.servoy.j2db.query.QueryTable)6 ITable (com.servoy.j2db.persistence.ITable)5 Relation (com.servoy.j2db.persistence.Relation)5 IQuerySelectValue (com.servoy.j2db.query.IQuerySelectValue)5 IColumn (com.servoy.j2db.persistence.IColumn)4 QuerySelect (com.servoy.j2db.query.QuerySelect)4 RepositoryException (com.servoy.j2db.persistence.RepositoryException)3 CompareCondition (com.servoy.j2db.query.CompareCondition)3 IQuerySort (com.servoy.j2db.query.IQuerySort)3 Placeholder (com.servoy.j2db.query.Placeholder)3 BaseQueryColumn (com.servoy.base.query.BaseQueryColumn)2 FlattenedSolution (com.servoy.j2db.FlattenedSolution)2 AggregateVariable (com.servoy.j2db.persistence.AggregateVariable)2 IRelation (com.servoy.j2db.persistence.IRelation)2 AndCondition (com.servoy.j2db.query.AndCondition)2