/** * Generate statement for getting the size of the container. The order part is only present when * an order mapping is used. The discriminator part is only present when the element has a * discriminator. * * <PRE> * SELECT COUNT(*) FROM TBL THIS * [INNER JOIN ELEM_TBL ELEM ON TBL.COL = ELEM.ID] - when no null * [LEFT OUTER JOIN ELEM_TBL ELEM ON TBL.COL = ELEM.ID] - when allows null * WHERE THIS.OWNERCOL=? * [AND THIS.ORDERCOL IS NOT NULL] * [AND (DISCRIMINATOR=? OR DISCRMINATOR=? OR DISCRIMINATOR=? [OR DISCRIMINATOR IS NULL])] * [AND RELATION_DISCRIM=?] * </PRE> * * The discriminator part includes all subclasses of the element type. If the element is in a * different table to the container then an INNER JOIN will be present to link the two tables, and * table aliases will be present also. * * @return The Statement returning the size of the container. */ protected String getSizeStmt() { if (sizeStmt != null) { // Statement exists and didn't need any discriminator when setting up the statement so just // reuse it return sizeStmt; } synchronized (this) { boolean usingDiscriminatorInSizeStmt = false; String containerAlias = "THIS"; StringBuilder stmt = new StringBuilder(); if (elementInfo == null) { // Serialised/embedded elements in a join table stmt.append("SELECT COUNT(*) FROM ") .append(containerTable.toString()) .append(" ") .append(containerAlias); stmt.append(" WHERE "); BackingStoreHelper.appendWhereClauseForMapping(stmt, ownerMapping, containerAlias, true); if (orderMapping != null) { // If an ordering is present, restrict to items where the index is not null to // eliminate records that are added but may not be positioned yet. for (int i = 0; i < orderMapping.getNumberOfDatastoreMappings(); i++) { stmt.append(" AND "); stmt.append(containerAlias) .append(".") .append(orderMapping.getDatastoreMapping(i).getColumn().getIdentifier().toString()); stmt.append(">=0"); } } if (relationDiscriminatorMapping != null) { BackingStoreHelper.appendWhereClauseForMapping( stmt, relationDiscriminatorMapping, containerAlias, false); } sizeStmt = stmt.toString(); return sizeStmt; } if (usingJoinTable()) { // Join table collection/array, so do COUNT of join table String joinedElementAlias = "ELEM"; ElementInfo elemInfo = elementInfo[0]; stmt.append("SELECT COUNT(*) FROM ") .append(containerTable.toString()) .append(" ") .append(containerAlias); // Add join to element table if required (only allows for 1 element table currently) boolean joinedDiscrim = false; if (elemInfo.getDiscriminatorMapping() != null) { // Need join to the element table to restrict the discriminator joinedDiscrim = true; JavaTypeMapping elemIdMapping = elemInfo.getDatastoreClass().getIdMapping(); stmt.append(allowNulls ? " LEFT OUTER JOIN " : " INNER JOIN "); stmt.append(elemInfo.getDatastoreClass().toString()) .append(" ") .append(joinedElementAlias) .append(" ON "); for (int j = 0; j < elementMapping.getNumberOfDatastoreMappings(); j++) { if (j > 0) { stmt.append(" AND "); } stmt.append(containerAlias) .append(".") .append(elementMapping.getDatastoreMapping(j).getColumn().getIdentifier()); stmt.append("="); stmt.append(joinedElementAlias) .append(".") .append(elemIdMapping.getDatastoreMapping(j).getColumn().getIdentifier()); } } // TODO Add join to owner if ownerMapping is for supertable stmt.append(" WHERE "); BackingStoreHelper.appendWhereClauseForMapping(stmt, ownerMapping, containerAlias, true); if (orderMapping != null) { // If an ordering is present, restrict to items where the index is not null to // eliminate records that are added but may not be positioned yet. for (int j = 0; j < orderMapping.getNumberOfDatastoreMappings(); j++) { stmt.append(" AND "); stmt.append(containerAlias) .append(".") .append(orderMapping.getDatastoreMapping(j).getColumn().getIdentifier().toString()); stmt.append(">=0"); } } // Add a discriminator filter for collections with an element discriminator StringBuilder discrStmt = new StringBuilder(); if (elemInfo.getDiscriminatorMapping() != null) { usingDiscriminatorInSizeStmt = true; JavaTypeMapping discrimMapping = elemInfo.getDiscriminatorMapping(); Collection<String> classNames = storeMgr.getSubClassesForClass(elemInfo.getClassName(), true, clr); classNames.add(elemInfo.getClassName()); for (String className : classNames) { Class cls = clr.classForName(className); if (!Modifier.isAbstract(cls.getModifiers())) { for (int j = 0; j < discrimMapping.getNumberOfDatastoreMappings(); j++) { if (discrStmt.length() > 0) { discrStmt.append(" OR "); } discrStmt.append(joinedDiscrim ? joinedElementAlias : containerAlias); discrStmt.append("."); discrStmt.append( discrimMapping.getDatastoreMapping(j).getColumn().getIdentifier().toString()); discrStmt.append("="); discrStmt.append( ((AbstractDatastoreMapping) discrimMapping.getDatastoreMapping(j)) .getUpdateInputParameter()); } } } } if (discrStmt.length() > 0) { stmt.append(" AND ("); stmt.append(discrStmt); if (allowNulls) { stmt.append(" OR "); stmt.append( elemInfo .getDiscriminatorMapping() .getDatastoreMapping(0) .getColumn() .getIdentifier() .toString()); stmt.append(" IS NULL"); } stmt.append(")"); } if (relationDiscriminatorMapping != null) { BackingStoreHelper.appendWhereClauseForMapping( stmt, relationDiscriminatorMapping, containerAlias, false); } } else { // ForeignKey collection/array, so UNION all of the element COUNTs for (int i = 0; i < elementInfo.length; i++) { if (i > 0) { stmt.append(" UNION "); } ElementInfo elemInfo = elementInfo[i]; stmt.append("SELECT COUNT(*),") .append("'" + elemInfo.getAbstractClassMetaData().getName() + "'"); stmt.append(" FROM ") .append(elemInfo.getDatastoreClass().toString()) .append(" ") .append(containerAlias); stmt.append(" WHERE "); BackingStoreHelper.appendWhereClauseForMapping(stmt, ownerMapping, containerAlias, true); if (orderMapping != null) { // If an ordering is present, restrict to items where the index is not null to // eliminate records that are added but may not be positioned yet. for (int j = 0; j < orderMapping.getNumberOfDatastoreMappings(); j++) { stmt.append(" AND "); stmt.append(containerAlias) .append(".") .append( orderMapping.getDatastoreMapping(j).getColumn().getIdentifier().toString()); stmt.append(">=0"); } } // Add a discriminator filter for collections with an element discriminator StringBuilder discrStmt = new StringBuilder(); if (elemInfo.getDiscriminatorMapping() != null) { usingDiscriminatorInSizeStmt = true; JavaTypeMapping discrimMapping = elemInfo.getDiscriminatorMapping(); Collection<String> classNames = storeMgr.getSubClassesForClass(elemInfo.getClassName(), true, clr); classNames.add(elemInfo.getClassName()); for (String className : classNames) { Class cls = clr.classForName(className); if (!Modifier.isAbstract(cls.getModifiers())) { for (int j = 0; j < discrimMapping.getNumberOfDatastoreMappings(); j++) { if (discrStmt.length() > 0) { discrStmt.append(" OR "); } discrStmt .append(containerAlias) .append(".") .append( discrimMapping .getDatastoreMapping(j) .getColumn() .getIdentifier() .toString()); discrStmt.append("="); discrStmt.append( ((AbstractDatastoreMapping) discrimMapping.getDatastoreMapping(j)) .getUpdateInputParameter()); } } } } if (discrStmt.length() > 0) { stmt.append(" AND ("); stmt.append(discrStmt); if (allowNulls) { stmt.append(" OR "); stmt.append( elemInfo .getDiscriminatorMapping() .getDatastoreMapping(0) .getColumn() .getIdentifier() .toString()); stmt.append(" IS NULL"); } stmt.append(")"); } if (relationDiscriminatorMapping != null) { BackingStoreHelper.appendWhereClauseForMapping( stmt, relationDiscriminatorMapping, containerAlias, false); } } } if (!usingDiscriminatorInSizeStmt) { sizeStmt = stmt.toString(); } return stmt.toString(); } }
/** * Generate statement for getting the size of thecontainer. The order part is only present when an * order mapping is used. The discriminator part is only present when the element has a * discriminator. * * <PRE> * SELECT COUNT(*) FROM TBL THIS * [INNER JOIN ELEM_TBL ELEM ON TBL.COL = ELEM.ID] - when no null * [LEFT OUTER JOIN ELEM_TBL ELEM ON TBL.COL = ELEM.ID] - when allows null * WHERE THIS.OWNERCOL=? * [AND THIS.ORDERCOL IS NOT NULL] * [AND (DISCRIMINATOR=? OR DISCRMINATOR=? OR DISCRIMINATOR=? [OR DISCRIMINATOR IS NULL])] * [AND RELATION_DISCRIM=?] * </PRE> * * The discriminator part includes all subclasses of the element type. If the element is in a * different table to the container then an INNER JOIN will be present to link the two tables, and * table aliases will be present also. TODO Update this to allow for getting the size when more * than 1 element table. * * @return The Statement returning the size of the container. */ protected String getSizeStmt() { if (sizeStmt != null && !usingDiscriminatorInSizeStmt) { // Statement exists and didnt need any discriminator when setting up the statement so just // reuse it return sizeStmt; } synchronized (this) { String containerAlias = "THIS"; String joinedElementAlias = "ELEM"; StringBuilder stmt = new StringBuilder("SELECT COUNT(*) FROM "); stmt.append(getContainerTable().toString()).append(" ").append(containerAlias); // Add join to element table if required (only allows for 1 element table currently) boolean joinedDiscrim = false; if (getElementInfo() != null && getElementInfo().length == 1 && getElementInfo()[0].getDatastoreClass() != getContainerTable() && getElementInfo()[0].getDiscriminatorMapping() != null) { // TODO Allow for more than 1 possible element table // Need join to the element table to restrict the discriminator joinedDiscrim = true; JavaTypeMapping elemIdMapping = getElementInfo()[0].getDatastoreClass().getIdMapping(); if (allowNulls) { // User wants to allow for nulls so have to use left outer join stmt.append(" LEFT OUTER JOIN "); } else { // No nulls so use inner join stmt.append(" INNER JOIN "); } stmt.append(getElementInfo()[0].getDatastoreClass().toString()) .append(" ") .append(joinedElementAlias) .append(" ON "); for (int i = 0; i < getElementMapping().getNumberOfDatastoreMappings(); i++) { if (i > 0) { stmt.append(" AND "); } stmt.append(containerAlias) .append(".") .append(getElementMapping().getDatastoreMapping(i).getColumn().getIdentifier()); stmt.append("="); stmt.append(joinedElementAlias) .append(".") .append(elemIdMapping.getDatastoreMapping(i).getColumn().getIdentifier()); } } stmt.append(" WHERE "); BackingStoreHelper.appendWhereClauseForMapping(stmt, ownerMapping, containerAlias, true); if (orderMapping != null) { // If an ordering is present, restrict to items where the index is not null to // eliminate records that are added but may not be positioned yet. for (int i = 0; i < orderMapping.getNumberOfDatastoreMappings(); i++) { stmt.append(" AND "); stmt.append(containerAlias) .append(".") .append(orderMapping.getDatastoreMapping(i).getColumn().getIdentifier().toString()); stmt.append(">=0"); } } if (getElementInfo() != null && getElementInfo().length == 1) { // TODO Support more than one element table // Add a discriminator filter for collections with an element discriminator StringBuilder discrStmt = new StringBuilder(); for (int i = 0; i < getElementInfo().length; i++) { ElementInfo elemInfo = getElementInfo()[i]; if (elemInfo.getDiscriminatorMapping() != null) { usingDiscriminatorInSizeStmt = true; JavaTypeMapping discrimMapping = elemInfo.getDiscriminatorMapping(); // TODO What if we have the discriminator in a supertable? the mapping will be null so // we don't get this clause added! Class cls = clr.classForName(elemInfo.getClassName()); if (!Modifier.isAbstract(cls.getModifiers())) { for (int j = 0; j < discrimMapping.getNumberOfDatastoreMappings(); j++) { if (discrStmt.length() > 0) { discrStmt.append(" OR "); } if (joinedDiscrim) { discrStmt.append(joinedElementAlias); } else { discrStmt.append(containerAlias); } discrStmt.append("."); discrStmt.append( discrimMapping.getDatastoreMapping(j).getColumn().getIdentifier().toString()); discrStmt.append("="); discrStmt.append( ((AbstractDatastoreMapping) discrimMapping.getDatastoreMapping(j)) .getUpdateInputParameter()); } } Collection<String> subclasses = storeMgr.getSubClassesForClass(elemInfo.getClassName(), true, clr); if (subclasses != null && subclasses.size() > 0) { for (String subclass : subclasses) { cls = clr.classForName(subclass); if (!Modifier.isAbstract(cls.getModifiers())) { for (int k = 0; k < discrimMapping.getNumberOfDatastoreMappings(); k++) { if (discrStmt.length() > 0) { discrStmt.append(" OR "); } if (joinedDiscrim) { discrStmt.append(joinedElementAlias); } else { discrStmt.append(containerAlias); } discrStmt.append("."); discrStmt.append( discrimMapping .getDatastoreMapping(k) .getColumn() .getIdentifier() .toString()); discrStmt.append("="); discrStmt.append( ((AbstractDatastoreMapping) discrimMapping.getDatastoreMapping(k)) .getUpdateInputParameter()); } } } } } } if (discrStmt.length() > 0) { stmt.append(" AND ("); stmt.append(discrStmt); if (allowNulls) { stmt.append(" OR "); stmt.append( getElementInfo()[0] .getDiscriminatorMapping() .getDatastoreMapping(0) .getColumn() .getIdentifier() .toString()); stmt.append(" IS NULL"); } stmt.append(")"); } } if (relationDiscriminatorMapping != null) { BackingStoreHelper.appendWhereClauseForMapping( stmt, relationDiscriminatorMapping, containerAlias, false); } sizeStmt = stmt.toString(); return sizeStmt; } }