001: /*
002: * Copyright 2004 (C) TJDO.
003: * All rights reserved.
004: *
005: * This software is distributed under the terms of the TJDO License version 1.0.
006: * See the terms of the TJDO License in the documentation provided with this software.
007: *
008: * $Id: NormalSetStore.java,v 1.8 2004/02/01 18:22:42 jackknifebarber Exp $
009: */
010:
011: package com.triactive.jdo.store;
012:
013: import com.triactive.jdo.ClassNotPersistenceCapableException;
014: import com.triactive.jdo.StateManager;
015: import com.triactive.jdo.model.ClassMetaData;
016: import com.triactive.jdo.util.IntArrayList;
017: import javax.jdo.JDOUnsupportedOptionException;
018:
019: class NormalSetStore extends AbstractSetStore {
020: public NormalSetStore(SetTable setTable) {
021: this .setTable = setTable;
022:
023: setName = "set";
024: storeMgr = setTable.getStoreManager();
025: dba = storeMgr.getDatabaseAdapter();
026:
027: ownerMapping = setTable.getOwnerMapping();
028: elementMapping = setTable.getElementMapping();
029:
030: ownerColumn = ownerMapping.getColumn();
031: elementColumn = elementMapping.getColumn();
032:
033: elementType = elementColumn.getType();
034: elementsAreEmbedded = !(elementMapping instanceof OIDMapping);
035:
036: loadStmt = "SELECT " + elementColumn.getName() + " FROM "
037: + setTable.getName() + " WHERE "
038: + ownerColumn.getName() + " = ?";
039: sizeStmt = "SELECT COUNT(*)" + " FROM " + setTable.getName()
040: + " WHERE " + ownerColumn.getName() + " = ?";
041: containsStmt = "SELECT " + ownerColumn.getName() + " FROM "
042: + setTable.getName() + " WHERE "
043: + ownerColumn.getName() + " = ? AND "
044: + elementColumn.getName() + " = ?";
045: addStmt = "INSERT INTO " + setTable.getName() + " ("
046: + ownerColumn.getName() + "," + elementColumn.getName()
047: + ") VALUES (?,?)";
048: removeStmt = "DELETE FROM " + setTable.getName() + " WHERE "
049: + ownerColumn.getName() + " = ? AND "
050: + elementColumn.getName() + " = ?";
051: clearStmt = "DELETE FROM " + setTable.getName() + " WHERE "
052: + ownerColumn.getName() + " = ?";
053:
054: /*
055: * Setup the prefetch field info.
056: */
057: IntArrayList colfn = new IntArrayList();
058: ColumnMapping[] colfm = null;
059:
060: ClassMetaData emd = ClassMetaData.forClass(elementType);
061:
062: if (emd != null) {
063: ClassBaseTable elementTable = storeMgr
064: .getClassBaseTable(elementType);
065: int fieldCount = emd.getInheritedFieldCount()
066: + emd.getFieldCount();
067: colfm = new ColumnMapping[fieldCount];
068:
069: boolean[] defaultFetchGroupFields = emd
070: .getDefaultFetchGroupFieldFlags();
071:
072: for (int i = 0; i < fieldCount; ++i) {
073: if (defaultFetchGroupFields[i]) {
074: Mapping m = elementTable.getFieldMapping(i);
075:
076: if (m instanceof ColumnMapping) {
077: colfn.add(i);
078: colfm[i] = (ColumnMapping) m;
079: }
080: }
081: }
082: }
083:
084: if (colfn.isEmpty()) {
085: prefetchFieldNumbers = null;
086: prefetchFieldMappings = null;
087: } else {
088: prefetchFieldNumbers = colfn.toArray();
089: prefetchFieldMappings = colfm;
090: }
091: }
092:
093: public QueryStatement newQueryStatement(StateManager sm,
094: Class candidateClass) {
095: if (elementsAreEmbedded)
096: throw new JDOUnsupportedOptionException(
097: "Can't query over a collection of second-class elements");
098:
099: TableIdentifier setRangeVar = new TableIdentifier(dba, setName);
100:
101: QueryStatement stmt = dba.newQueryStatement(setTable,
102: setRangeVar);
103:
104: BooleanExpression filterByOwner = new BooleanExpression(
105: new ObjectExpression(stmt, stmt.getColumn(setRangeVar,
106: ownerColumn)), SQLExpression.OP_EQ,
107: ownerMapping.newSQLLiteral(stmt, sm.getObject()));
108:
109: stmt.andCondition(filterByOwner);
110:
111: if (!elementType.isAssignableFrom(candidateClass))
112: throw new IncompatibleQueryElementTypeException(
113: elementType, candidateClass);
114:
115: /*
116: * Try to join to the element table and select the element ID.
117: *
118: * If the element class does not have a mapping to a table (e.g. -
119: * the Set has the element defined as Object or some other super
120: * class or interface that is not PersistenceCapable, but has
121: * PersistenceCapable implementations), just select the element
122: * ID from the join table. The actual element table will be joined
123: * in later if it is casted to in the Query.
124: */
125: try {
126: TableIdentifier elementRangeVar = new TableIdentifier(dba,
127: "this");
128:
129: ClassBaseTable candidateTable = storeMgr
130: .getClassBaseTable(candidateClass);
131: Column elementTableIDColumn = candidateTable.getIDMapping()
132: .getColumn();
133:
134: stmt.newTableExpression(candidateTable, elementRangeVar);
135:
136: stmt.innerJoin(stmt.getColumn(setRangeVar, elementColumn),
137: stmt.getColumn(elementRangeVar,
138: elementTableIDColumn));
139:
140: stmt.select(elementTableIDColumn);
141: } catch (ClassNotPersistenceCapableException e) {
142: stmt.select(setRangeVar, elementColumn);
143: }
144:
145: return stmt;
146: }
147:
148: public QueryStatement.QueryColumn joinElementsTo(
149: QueryStatement stmt,
150: QueryStatement.QueryColumn ownerIDColumn,
151: SQLIdentifier setRangeVar, Class filteredElementType,
152: SQLIdentifier elementRangeVar) {
153: if (!elementType.isAssignableFrom(filteredElementType))
154: throw new IncompatibleQueryElementTypeException(
155: elementType, filteredElementType);
156:
157: /* Join the set table on the owner ID column. */
158: stmt.newTableExpression(setTable, setRangeVar);
159: stmt.innerJoin(ownerIDColumn, stmt.getColumn(setRangeVar,
160: ownerColumn));
161:
162: try {
163: /* Join the element table on the element ID column. */
164: ClassBaseTable elementTable = storeMgr
165: .getClassBaseTable(filteredElementType);
166: Column elementTableIDColumn = elementTable.getIDMapping()
167: .getColumn();
168:
169: stmt.newTableExpression(elementTable, elementRangeVar);
170:
171: stmt.innerJoin(stmt.getColumn(setRangeVar, elementColumn),
172: stmt.getColumn(elementRangeVar,
173: elementTableIDColumn));
174:
175: return stmt
176: .getColumn(elementRangeVar, elementTableIDColumn);
177: } catch (ClassNotPersistenceCapableException e) {
178: return stmt.getColumn(setRangeVar, elementColumn);
179: }
180: }
181: }
|