Source Code Cross Referenced for JdbcMapField.java in  » Testing » PolePosition-0.20 » com » versant » core » jdbc » metadata » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Testing » PolePosition 0.20 » com.versant.core.jdbc.metadata 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright (c) 1998 - 2005 Versant Corporation
0003:         * All rights reserved. This program and the accompanying materials
0004:         * are made available under the terms of the Eclipse Public License v1.0
0005:         * which accompanies this distribution, and is available at
0006:         * http://www.eclipse.org/legal/epl-v10.html
0007:         *
0008:         * Contributors:
0009:         * Versant Corporation - initial API and implementation
0010:         */
0011:        package com.versant.core.jdbc.metadata;
0012:
0013:        import com.versant.core.jdbc.sql.JdbcNameGenerator;
0014:        import com.versant.core.jdbc.sql.exp.*;
0015:        import com.versant.core.jdbc.*;
0016:        import com.versant.core.jdbc.query.JdbcJDOQLCompiler;
0017:        import com.versant.core.server.*;
0018:        import com.versant.core.metadata.parser.JdoElement;
0019:        import com.versant.core.metadata.parser.JdoExtension;
0020:        import com.versant.core.metadata.parser.JdoExtensionKeys;
0021:        import com.versant.core.metadata.*;
0022:        import com.versant.core.common.OID;
0023:        import com.versant.core.common.State;
0024:        import com.versant.core.common.Utils;
0025:        import com.versant.core.util.CharBuf;
0026:        import com.versant.core.common.*;
0027:        import com.versant.core.jdo.query.Node;
0028:        import com.versant.core.jdo.query.OrderNode;
0029:        import com.versant.core.common.Debug;
0030:
0031:        import java.io.PrintStream;
0032:        import java.util.ArrayList;
0033:        import java.util.List;
0034:        import java.util.Map;
0035:        import java.sql.*;
0036:
0037:        import com.versant.core.common.BindingSupportImpl;
0038:
0039:        /**
0040:         * This is a Map field stored using a link table.
0041:         */
0042:        public class JdbcMapField extends JdbcLinkCollectionField {
0043:
0044:            private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
0045:            private static final OID[] EMPTY_OID_ARRAY = new OID[0];
0046:
0047:            /**
0048:             * The column(s) holding the keys. This array will have length 1 unless
0049:             * the keys are of a PC class with a composite primary key.
0050:             */
0051:            public JdbcColumn keyColumns[];
0052:            /**
0053:             * Should the keys be considered a dependent? If they are
0054:             * they will be deleted if removed from the map or if our
0055:             * instance is deleted. This only makes sense if the keys are instances
0056:             * of a PC class.
0057:             */
0058:            public boolean keysDependent;
0059:            /**
0060:             * Are the keys OID's?
0061:             */
0062:            public boolean keysAreOIDs;
0063:            /**
0064:             * Should a join be done to pick up the fields for keys when they are
0065:             * read? This only makes sense if the key is a PC class.
0066:             */
0067:            public int useKeyJoin;
0068:
0069:            private transient boolean createKeyConstraint;
0070:            private transient String keyConstraintName;
0071:
0072:            public void dump(PrintStream out, String indent) {
0073:                super .dump(out, indent);
0074:                String is = indent + "  ";
0075:                if (keyColumns == null) {
0076:                    out.println(is + "keyColumns null");
0077:                } else {
0078:                    for (int i = 0; i < keyColumns.length; i++) {
0079:                        out.println(is + "keyColumns[" + i + "] "
0080:                                + keyColumns[i]);
0081:                    }
0082:                }
0083:                out.println(is + "keysDependent " + keysDependent);
0084:                out.println(is + "keysAreOIDs " + keysAreOIDs);
0085:                out.println(is + "useKeyJoin " + toUseJoinString(useKeyJoin));
0086:            }
0087:
0088:            /**
0089:             * Get the useKeyJoin value for this field. This is only valid for maps.
0090:             */
0091:            public int getUseKeyJoin() {
0092:                return useKeyJoin;
0093:            }
0094:
0095:            /**
0096:             * Complete the meta data for this collection. This must use info
0097:             * already supplied in the .jdo file and add anything else needed.
0098:             */
0099:            public void processMetaData(JdoElement context,
0100:                    JdbcMetaDataBuilder mdb, boolean quiet) {
0101:                keysAreOIDs = fmd.keyTypeMetaData != null;
0102:                if (keysAreOIDs) {
0103:                    useKeyJoin = JdbcField.USE_JOIN_INNER;
0104:                } else {
0105:                    useKeyJoin = JdbcField.USE_JOIN_NO;
0106:                }
0107:                super .processMetaData(context, mdb, quiet);
0108:            }
0109:
0110:            /**
0111:             * Set the PK of the link table.
0112:             */
0113:            protected void createLinkTablePK() {
0114:                linkTable.setPk(JdbcColumn.concat(ourPkColumns, keyColumns));
0115:            }
0116:
0117:            /**
0118:             * Complete the key and value column related meta data.
0119:             */
0120:            protected void completeKeyAndValueColumnMetaData(
0121:                    JdbcClass jdbcClass, ArrayList cols, JdoElement context,
0122:                    JdoExtension[] linkNested, JdbcMetaDataBuilder mdb,
0123:                    boolean quiet) {
0124:
0125:                // create the key column(s)
0126:                JdoExtension ext = JdoExtension.find(JdoExtensionKeys.JDBC_KEY,
0127:                        linkNested);
0128:                if (fmd.keyTypeMetaData != null) { // values are OIDs
0129:                    JdbcRefMetaDataBuilder rdb = new JdbcRefMetaDataBuilder(
0130:                            fmd.classMetaData, mdb, fmd.keyTypeMetaData,
0131:                            context, JdbcMetaDataBuilder.KEY_FIELDNAME,
0132:                            ext == null ? null : ext.nested, quiet);
0133:                    keyColumns = rdb.getCols();
0134:                    cols.addAll(rdb.getColsList());
0135:                    createKeyConstraint = !rdb.isDoNotCreateConstraint();
0136:                    keyConstraintName = rdb.getConstraintName();
0137:                } else {
0138:                    if (fmd.keyType == Object.class) {
0139:                        throw BindingSupportImpl.getInstance().runtime(
0140:                                "You must specify the key-type for maps\n"
0141:                                        + fmd + "\n" + context.getContext());
0142:                    }
0143:                    JdbcColumn kc = mdb.createColumn(ext == null ? null
0144:                            : ext.nested, JdbcMetaDataBuilder.KEY_FIELDNAME,
0145:                            fmd.keyType);
0146:                    keyColumns = new JdbcColumn[] { kc };
0147:                    cols.add(kc);
0148:                }
0149:
0150:                int n = keyColumns.length;
0151:                for (int i = 0; i < n; i++)
0152:                    keyColumns[i].setNulls(false);
0153:
0154:                super .completeKeyAndValueColumnMetaData(jdbcClass, cols,
0155:                        context, linkNested, mdb, quiet);
0156:            }
0157:
0158:            /**
0159:             * Name the key and value columns.
0160:             */
0161:            protected void nameKeyAndValueColumns(JdbcNameGenerator namegen,
0162:                    String linkTableNameForNamegen) {
0163:                // name the keycolumn(s)
0164:                if (keysAreOIDs) {
0165:                    String[] keyPkNames = JdbcColumn
0166:                            .getColumnNames(((JdbcClass) fmd.keyTypeMetaData.storeClass).table.pk);
0167:                    String[] linkKeyRefNames = JdbcColumn
0168:                            .getColumnNames(keyColumns);
0169:                    namegen.generateLinkTableValueRefNames(linkTable.name,
0170:                            keyPkNames, fmd.keyType.getName(), linkKeyRefNames,
0171:                            true);
0172:                    JdbcColumn.setColumnNames(keyColumns, linkKeyRefNames);
0173:                } else {
0174:                    JdbcColumn c = keyColumns[0];
0175:                    if (c.name == null) {
0176:                        c.name = namegen.generateLinkTableValueName(
0177:                                linkTable.name, fmd.keyType, true);
0178:                    }
0179:                }
0180:
0181:                super .nameKeyAndValueColumns(namegen, linkTableNameForNamegen);
0182:            }
0183:
0184:            /**
0185:             * Name our linkTable.
0186:             */
0187:            protected void nameLinkTable(JdbcNameGenerator namegen,
0188:                    JdbcClass jdbcClass) {
0189:                linkTable.name = namegen.generateLinkTableName(
0190:                        jdbcClass.table.name, fmd.name, null);
0191:            }
0192:
0193:            /**
0194:             * Create all the constraints for our link table.
0195:             */
0196:            protected List createConstraints(boolean pkConstraint,
0197:                    String pkConstraintName) {
0198:                List constraints = super .createConstraints(pkConstraint,
0199:                        pkConstraintName);
0200:
0201:                if (createKeyConstraint && keysAreOIDs
0202:                        && fmd.keyTypeMetaData.storeClass != null) {
0203:                    JdbcConstraint keyCon = new JdbcConstraint();
0204:                    keyCon.src = linkTable;
0205:                    keyCon.srcCols = keyColumns;
0206:                    keyCon.dest = ((JdbcClass) fmd.keyTypeMetaData.storeClass).table;
0207:                    keyCon.name = keyConstraintName;
0208:                    constraints.add(keyCon);
0209:                }
0210:
0211:                return constraints;
0212:            }
0213:
0214:            /**
0215:             * Persist pass 2 field for a block of graph entries all with
0216:             * the same class. The same ps'es can be used for all entries in the block.
0217:             */
0218:            public void persistPass2Block(PersistGraph graph, int blockStart,
0219:                    int blockEnd, CharBuf s, Connection con,
0220:                    boolean batchInserts, boolean batchUpdates)
0221:                    throws SQLException {
0222:                PreparedStatement psdel = null;
0223:                PreparedStatement psdelAll = null;
0224:                PreparedStatement psins = null;
0225:                int delCount = 0;
0226:                try {
0227:                    String psdelSql = null;
0228:                    String psdelAllSql = null;
0229:                    String psinsSql = null;
0230:                    for (int pos = blockStart; pos < blockEnd; pos++) {
0231:                        State ns = graph.getNewState(pos);
0232:                        if (!ns.containsField(stateFieldNo))
0233:                            continue;
0234:
0235:                        MapDiff diff = (MapDiff) ns
0236:                                .getInternalObjectField(stateFieldNo);
0237:
0238:                        OID oid = graph.getOID(pos);
0239:
0240:                        if (diff == null
0241:                                || diff.status == CollectionDiff.STATUS_NEW) {
0242:                            if (!oid.isNew()) {
0243:                                if (psdelAll == null) {
0244:                                    psdelAllSql = getDeleteAllLinkTableRowsSql(s);
0245:                                    psdelAll = con
0246:                                            .prepareStatement(psdelAllSql);
0247:                                }
0248:                                ((JdbcOID) oid).setParams(psdelAll, 1);
0249:                                if (batchUpdates) {
0250:                                    psdelAll.addBatch();
0251:                                } else {
0252:                                    try {
0253:                                        psdelAll.execute();
0254:                                    } catch (Exception e) {
0255:                                        throw mapException(
0256:                                                e,
0257:                                                "Delete all link table rows failed: "
0258:                                                        + JdbcUtils.toString(e)
0259:                                                        + "\n"
0260:                                                        + "Field: "
0261:                                                        + fmd.getQName()
0262:                                                        + "\n"
0263:                                                        + "Instance: "
0264:                                                        + oid.toSString()
0265:                                                        + "\n"
0266:                                                        + JdbcUtils
0267:                                                                .getPreparedStatementInfo(
0268:                                                                        psdelAllSql,
0269:                                                                        psdelAll));
0270:                                    }
0271:                                }
0272:                            }
0273:                        } else {
0274:                            Object[] deleted = diff.deletedKeys;
0275:                            if (deleted != null && deleted.length > 0) {
0276:                                if (psdel == null) {
0277:                                    psdelSql = getDeleteLinkTableRowSql(s);
0278:                                    psdel = con.prepareStatement(psdelSql);
0279:                                }
0280:                                deleteMapLinkTableRows(oid, deleted, psdel,
0281:                                        batchUpdates, psdelSql);
0282:                                delCount += deleted.length;
0283:                            }
0284:                        }
0285:
0286:                        if (diff != null) {
0287:                            Object[] inserted = diff.insertedKeys;
0288:                            if (inserted != null && inserted.length > 0) {
0289:                                if (psins == null) {
0290:                                    psinsSql = getInsertLinkTableRowSql(s);
0291:                                    psins = con.prepareStatement(psinsSql);
0292:                                }
0293:                                insertMapLinkTableRows(oid, inserted,
0294:                                        diff.insertedValues, psins,
0295:                                        batchInserts, psinsSql);
0296:                            }
0297:                        }
0298:                    }
0299:
0300:                    if (batchUpdates) {
0301:                        execLinkTableBatchDeletes(delCount, psdel, psdelSql,
0302:                                psdelAll, psdelAllSql);
0303:                    }
0304:                    if (batchInserts && psins != null) {
0305:                        execLinkTableBatchInserts(psins, psinsSql);
0306:                    }
0307:                } finally {
0308:                    cleanup(psdel);
0309:                    cleanup(psdelAll);
0310:                    cleanup(psins);
0311:                }
0312:            }
0313:
0314:            /**
0315:             * Delete keys from an map link table.
0316:             */
0317:            private void deleteMapLinkTableRows(OID oid, Object[] deleted,
0318:                    PreparedStatement psdel, boolean batch, String sql)
0319:                    throws SQLException {
0320:                if (keysAreOIDs) {
0321:                    for (int j = deleted.length - 1; j >= 0; j--) {
0322:                        int pp = ((JdbcOID) oid).setParams(psdel, 1);
0323:                        ((JdbcOID) deleted[j]).setParams(psdel, pp);
0324:                        if (batch) {
0325:                            psdel.addBatch();
0326:                        } else {
0327:                            int uc;
0328:                            try {
0329:                                uc = psdel.executeUpdate();
0330:                            } catch (Exception e) {
0331:                                throw mapException(
0332:                                        e,
0333:                                        "Delete map link table row failed: "
0334:                                                + JdbcUtils.toString(e)
0335:                                                + "\n"
0336:                                                + "Field: "
0337:                                                + fmd.getTypeQName()
0338:                                                + "\n"
0339:                                                + "Key: "
0340:                                                + ((OID) deleted[j])
0341:                                                        .toSString()
0342:                                                + "\n"
0343:                                                + "Instance: "
0344:                                                + oid.toSString()
0345:                                                + "\n"
0346:                                                + JdbcUtils
0347:                                                        .getPreparedStatementInfo(
0348:                                                                sql, psdel));
0349:                            }
0350:                            if (uc == 0) {
0351:                                throw BindingSupportImpl
0352:                                        .getInstance()
0353:                                        .concurrentUpdate(
0354:                                                "Map link table row not found: "
0355:                                                        + "Field: "
0356:                                                        + fmd.getTypeQName()
0357:                                                        + "\n"
0358:                                                        + "Key: "
0359:                                                        + ((OID) deleted[j])
0360:                                                                .toSString()
0361:                                                        + "\n"
0362:                                                        + "Instance: "
0363:                                                        + oid.toSString()
0364:                                                        + "\n"
0365:                                                        + JdbcUtils
0366:                                                                .getPreparedStatementInfo(
0367:                                                                        sql,
0368:                                                                        psdel),
0369:                                                deleted[j]);
0370:                            }
0371:                        }
0372:                    }
0373:                } else {
0374:                    JdbcColumn kc = keyColumns[0];
0375:                    for (int j = deleted.length - 1; j >= 0; j--) {
0376:                        int pp = ((JdbcOID) oid).setParams(psdel, 1);
0377:                        kc.set(psdel, pp, deleted[j]);
0378:                        if (batch) {
0379:                            psdel.addBatch();
0380:                        } else {
0381:                            int uc;
0382:                            try {
0383:                                uc = psdel.executeUpdate();
0384:                            } catch (Exception e) {
0385:                                throw mapException(
0386:                                        e,
0387:                                        "Delete map link table row failed: "
0388:                                                + JdbcUtils.toString(e)
0389:                                                + "\n"
0390:                                                + "Field: "
0391:                                                + fmd.getTypeQName()
0392:                                                + "\n"
0393:                                                + "Key: "
0394:                                                + Utils.toString(deleted[j])
0395:                                                + "\n"
0396:                                                + "Instance: "
0397:                                                + oid.toSString()
0398:                                                + "\n"
0399:                                                + JdbcUtils
0400:                                                        .getPreparedStatementInfo(
0401:                                                                sql, psdel));
0402:                            }
0403:                            if (uc == 0) {
0404:                                throw BindingSupportImpl
0405:                                        .getInstance()
0406:                                        .concurrentUpdate(
0407:                                                "Map link table row not found: "
0408:                                                        + "Field: "
0409:                                                        + fmd.getTypeQName()
0410:                                                        + "\n"
0411:                                                        + "Key: "
0412:                                                        + Utils
0413:                                                                .toString(deleted[j])
0414:                                                        + "\n"
0415:                                                        + "Instance: "
0416:                                                        + oid.toSString()
0417:                                                        + "\n"
0418:                                                        + JdbcUtils
0419:                                                                .getPreparedStatementInfo(
0420:                                                                        sql,
0421:                                                                        psdel),
0422:                                                oid);
0423:                            }
0424:                        }
0425:                    }
0426:                }
0427:            }
0428:
0429:            /**
0430:             * Insert rows into an map link table.
0431:             */
0432:            private void insertMapLinkTableRows(OID oid, Object[] insertedKeys,
0433:                    Object[] insertedValues, PreparedStatement psins,
0434:                    boolean batch, String sql) throws SQLException {
0435:
0436:                JdbcColumn kc = keyColumns[0];
0437:                JdbcColumn vc = valueColumns[0];
0438:
0439:                // do the inserts
0440:                int ilen = insertedKeys.length;
0441:                for (int j = 0; j < ilen; j++) {
0442:                    int pp = ((JdbcOID) oid).setParams(psins, 1);
0443:
0444:                    // set key
0445:                    if (keysAreOIDs) {
0446:                        pp = ((JdbcOID) insertedKeys[j]).setParams(psins, pp);
0447:                    } else {
0448:                        kc.set(psins, pp++, insertedKeys[j]);
0449:                    }
0450:
0451:                    // set value
0452:                    if (valuesAreOIDs) {
0453:                        if (insertedValues[j] == null) {
0454:                            JdbcGenericOID.setNullParams(psins, pp,
0455:                                    fmd.elementTypeMetaData);
0456:                        } else {
0457:                            ((JdbcOID) insertedValues[j]).setParams(psins, pp);
0458:                        }
0459:                    } else {
0460:                        vc.set(psins, pp, insertedValues[j]);
0461:                    }
0462:
0463:                    if (batch) {
0464:                        psins.addBatch();
0465:                    } else {
0466:                        try {
0467:                            psins.execute();
0468:                        } catch (Exception e) {
0469:                            String keyStr = keysAreOIDs ? ((OID) insertedKeys[j])
0470:                                    .toSString()
0471:                                    : Utils.toString(insertedKeys[j]);
0472:                            String valueStr = valuesAreOIDs ? ((OID) insertedValues[j])
0473:                                    .toSString()
0474:                                    : Utils.toString(insertedValues[j]);
0475:                            throw mapException(e,
0476:                                    "Insert link table row failed: "
0477:                                            + JdbcUtils.toString(e)
0478:                                            + "\n"
0479:                                            + "Field: "
0480:                                            + fmd.getQName()
0481:                                            + "\n"
0482:                                            + "Instance: "
0483:                                            + oid.toSString()
0484:                                            + "\n"
0485:                                            + "Key: "
0486:                                            + keyStr
0487:                                            + "\n"
0488:                                            + "Value: "
0489:                                            + valueStr
0490:                                            + "\n"
0491:                                            + JdbcUtils
0492:                                                    .getPreparedStatementInfo(
0493:                                                            sql, psins));
0494:                        }
0495:                    }
0496:                }
0497:            }
0498:
0499:            /**
0500:             * Get a SelectExp to select all the rows in this map using the
0501:             * supplied fetch group field to control joins and so on.
0502:             */
0503:            public SelectExp getSelectExp(JdbcStorageManager dataStore,
0504:                    FetchGroupField field, FgDs[] fgDses) {
0505:                SelectExp root = super .getSelectExp(dataStore, field, fgDses);
0506:
0507:                // prepend our key columns to the select list
0508:                SqlExp e = JdbcColumn.toSqlExp(keyColumns, root,
0509:                        root.selectList);
0510:                root.selectList = e;
0511:
0512:                // add a join for the keys if required
0513:                if (keysAreOIDs) {
0514:                    if (field.jdbcUseKeyJoin != JdbcField.USE_JOIN_NO) {
0515:                        SelectExp se = new SelectExp();
0516:                        JdbcClass keyJdbcClass = (JdbcClass) fmd.keyTypeMetaData.storeClass;
0517:                        se.table = keyJdbcClass.table;
0518:                        se.outer = field.jdbcUseKeyJoin == JdbcField.USE_JOIN_OUTER;
0519:                        dataStore
0520:                                .addSelectFetchGroup(
0521:                                        se,
0522:                                        field.nextKeyFetchGroup,
0523:                                        true,
0524:                                        fgDses[1] = ((JdbcFetchGroup) field.nextKeyFetchGroup.storeFetchGroup)
0525:                                                .getFgDs(true, se.outer), false);
0526:                        root.addJoin(keyColumns, se.table.pk, se);
0527:                    }
0528:                }
0529:                return root;
0530:            }
0531:
0532:            public SelectExp getSelectFilterJoinExp(boolean value,
0533:                    SelectExp lhSe, SelectExp rootSe, boolean addRootJoin) {
0534:                SelectExp root = new SelectExp();
0535:                root.table = linkTable;
0536:
0537:                SelectExp se = new SelectExp();
0538:                if (value) {
0539:                    se.table = ((JdbcClass) fmd.elementTypeMetaData.storeClass).table;
0540:                    root.addJoin(valueColumns, se.table.pk, se);
0541:                } else {
0542:                    se.table = ((JdbcClass) fmd.keyTypeMetaData.storeClass).table;
0543:                    root.addJoin(keyColumns, se.table.pk, se);
0544:                }
0545:
0546:                lhSe.addJoin(lhSe.table.pk, ourPkColumns, root);
0547:                return se;
0548:            }
0549:
0550:            public SelectExp getSelectFilterExp(JdbcStorageManager sm,
0551:                    FetchGroupField field, ColFieldHolder colFHolder) {
0552:                SelectExp root = new SelectExp();
0553:                root.table = linkTable;
0554:
0555:                // add value columns to the select list
0556:                SqlExp e = JdbcColumn.toSqlExp(valueColumns, root);
0557:                root.selectList = e;
0558:
0559:                // prepend our key columns to the select list
0560:                e = JdbcColumn.toSqlExp(keyColumns, root, root.selectList);
0561:                root.selectList = e;
0562:
0563:                // prepend our pk columns to the select list
0564:                e = JdbcColumn.toSqlExp(ourPkColumns, root, root.selectList);
0565:                root.selectList = e;
0566:                //add the order by to the owner
0567:                root.appendOrderByForColumns(ourPkColumns);
0568:
0569:                if (valuesAreOIDs) {
0570:                    if (field.jdbcUseJoin != JdbcField.USE_JOIN_NO
0571:                            || fmd.ordering != null) {
0572:                        SelectExp se = new SelectExp();
0573:                        JdbcClass valueJdbcClass = (JdbcClass) fmd.elementTypeMetaData.storeClass;
0574:                        se.table = valueJdbcClass.table;
0575:                        se.outer = field.jdbcUseJoin == JdbcField.USE_JOIN_OUTER;
0576:                        FgDs fgDs = ((JdbcFetchGroup) field.nextFetchGroup.storeFetchGroup)
0577:                                .getFgDs(true, se.outer);
0578:                        sm.addSelectFetchGroup(se, field.nextFetchGroup, true,
0579:                                fgDs, false);
0580:                        colFHolder.valueJs = fgDs.getJoinStruct();
0581:
0582:                        root.addJoin(valueColumns, se.table.pk, se);
0583:
0584:                        if (fmd.ordering != null) {
0585:                            se.addOrderBy(fmd.ordering, false);
0586:                            root.appendOrderByExp(se.orderByList);
0587:                            se.orderByList = null;
0588:                        }
0589:                    }
0590:                } else {
0591:                    if (fmd.ordering != null) {
0592:                        // the ordering can only be 'this ascending' or 'this descending'
0593:                        boolean desc = fmd.ordering[0].order == OrderNode.ORDER_DESCENDING;
0594:                        root.appendOrderByExp(new OrderExp(valueColumns[0]
0595:                                .toSqlExp(root), desc));
0596:                        // there will be only one entry in valueColumns as this is
0597:                        // not a collection of PC instances
0598:                    }
0599:                }
0600:
0601:                if (fmd.ordered) {
0602:                    if (fmd.ordering != null) {
0603:                        throw BindingSupportImpl.getInstance().internal(
0604:                                "ordered == true && ordering != null, "
0605:                                        + fmd.getTypeQName());
0606:                    }
0607:                    root.appendOrderByForColumns(linkTable.pkSimpleCols);
0608:                }
0609:
0610:                // add a join for the keys if required
0611:                if (keysAreOIDs) {
0612:                    if (field.jdbcUseKeyJoin != JdbcField.USE_JOIN_NO) {
0613:                        SelectExp se = new SelectExp();
0614:                        JdbcClass keyJdbcClass = (JdbcClass) fmd.keyTypeMetaData.storeClass;
0615:                        se.table = keyJdbcClass.table;
0616:                        se.outer = field.jdbcUseKeyJoin == JdbcField.USE_JOIN_OUTER;
0617:
0618:                        FgDs fgDs = ((JdbcFetchGroup) field.nextKeyFetchGroup.storeFetchGroup)
0619:                                .getFgDs(true, se.outer);
0620:                        sm.addSelectFetchGroup(se, field.nextKeyFetchGroup,
0621:                                true, fgDs, false);
0622:                        colFHolder.keyJs = fgDs.getJoinStruct();
0623:                        root.addJoin(keyColumns, se.table.pk, se);
0624:                    }
0625:                }
0626:                return root;
0627:            }
0628:
0629:            public int fetchFrom(ResultSet rs, OID oid, State state,
0630:                    FetchGroupField field, boolean forUpdate,
0631:                    StateContainer container, boolean fetchPass2Fields,
0632:                    int colIndex, FetchInfo fetchInfo, JdbcStorageManager sm)
0633:                    throws SQLException {
0634:                ArrayList keys = new ArrayList();
0635:                ArrayList values = new ArrayList();
0636:
0637:                // get info to extract the keys
0638:                ClassMetaData keyCmd = fmd.keyTypeMetaData;
0639:                boolean keyJoined = field.jdbcUseKeyJoin != JdbcField.USE_JOIN_NO;
0640:                FetchGroup keyNFG = field.nextKeyFetchGroup;
0641:                JdbcColumn kc = keyColumns[0];
0642:                int keyScc = keyColumns.length;
0643:                OID keyOid = null;
0644:
0645:                // get info to extract the values
0646:                ClassMetaData valueCmd = fmd.elementTypeMetaData;
0647:                boolean valueJoined = field.jdbcUseJoin != JdbcField.USE_JOIN_NO;
0648:                FetchGroup nfg = field.nextFetchGroup;
0649:                JdbcColumn vc = valueColumns[0];
0650:                int valueScc = valueColumns.length;
0651:
0652:                MutableInt nextIndex = null;
0653:                if (valuesAreOIDs)
0654:                    nextIndex = new MutableInt();
0655:                boolean first = true;
0656:                for (;;) {
0657:                    if (first) {
0658:                        first = false;
0659:                    } else {
0660:                        if (!rs.next())
0661:                            break;
0662:                    }
0663:
0664:                    OID owningOid = fmd.classMetaData.createOID(false);
0665:                    if (!((JdbcOID) owningOid).copyKeyFields(rs, colIndex)) {
0666:                        //no elements found
0667:                        break;
0668:                    }
0669:                    int index = colIndex + ourPkColumns.length;
0670:
0671:                    if (keysAreOIDs) {
0672:                        keyOid = keyCmd.createOID(false);
0673:                        boolean isNull = !((JdbcOID) keyOid).copyKeyFields(rs,
0674:                                colIndex);
0675:                        if (!isNull)
0676:                            keys.add(keyOid);
0677:                    } else {
0678:                        keys.add(kc.get(rs, colIndex));
0679:                    }
0680:                    index += keyScc;
0681:
0682:                    if (valuesAreOIDs) {
0683:                        OID valueOid = valueCmd.createOID(false);
0684:                        boolean isNull = !((JdbcOID) valueOid).copyKeyFields(
0685:                                rs, index);
0686:                        index += valueScc;
0687:                        if (!isNull)
0688:                            values.add(valueOid);
0689:
0690:                        if (!isNull && valueJoined) {
0691:                            if (container.isStateRequired(valueOid, nfg)) {
0692:                                State valueState = sm
0693:                                        .createStateImp(
0694:                                                rs,
0695:                                                valueOid,
0696:                                                field.nextFetchGroup,
0697:                                                forUpdate,
0698:                                                index,
0699:                                                nextIndex,
0700:                                                true,
0701:                                                container,
0702:                                                ((JdbcFetchGroup) field.nextFetchGroup.storeFetchGroup)
0703:                                                        .getFgDs(true, true),
0704:                                                fetchPass2Fields, false, null);
0705:                                index = nextIndex.value;
0706:                                container.addState(valueOid, valueState);
0707:                            } else {
0708:                                index = sm
0709:                                        .skipState(
0710:                                                index,
0711:                                                ((JdbcFetchGroup) field.nextFetchGroup.storeFetchGroup)
0712:                                                        .getFgDs(true, true));
0713:                            }
0714:                        }
0715:                    } else {
0716:                        values.add(vc.get(rs, index));
0717:                        index += valueScc;
0718:                    }
0719:
0720:                    if (keysAreOIDs && keyJoined
0721:                            && container.isStateRequired(keyOid, keyNFG)) {
0722:                        State keyState = sm
0723:                                .createStateImp(
0724:                                        rs,
0725:                                        keyOid,
0726:                                        field.nextKeyFetchGroup,
0727:                                        forUpdate,
0728:                                        index,
0729:                                        null,
0730:                                        true,
0731:                                        container,
0732:                                        ((JdbcFetchGroup) field.nextFetchGroup.storeFetchGroup)
0733:                                                .getFgDs(true, true),
0734:                                        fetchPass2Fields, false, null);
0735:                        container.addState(keyOid, keyState);
0736:                    }
0737:                }
0738:
0739:                MapEntries me = new MapEntries();
0740:                if (keysAreOIDs) {
0741:                    me.keys = new OID[keys.size()];
0742:                    keys.toArray(me.keys);
0743:                } else {
0744:                    me.keys = keys.toArray();
0745:                }
0746:                if (valuesAreOIDs) {
0747:                    me.values = new OID[values.size()];
0748:                    values.toArray(me.values);
0749:                } else {
0750:                    me.values = values.toArray();
0751:                }
0752:                state.setInternalObjectField(fmd.stateFieldNo, me);
0753:                return keys.size();
0754:            }
0755:
0756:            public SelectExp getSelectExpFrom(JdbcStorageManager sm,
0757:                    SelectExp joinToExp, FetchGroupField field, FgDs owningFgDs) {
0758:                SelectExp root = super .getSelectExpFromImp(joinToExp, field,
0759:                        sm, owningFgDs);
0760:                root.selectList = JdbcColumn.toSqlExp(keyColumns, root,
0761:                        root.selectList);
0762:                root.selectList = JdbcColumn.toSqlExp(ourPkColumns, root,
0763:                        root.selectList);
0764:
0765:                // add a join for the keys if required
0766:                if (keysAreOIDs) {
0767:                    if (field.jdbcUseKeyJoin != JdbcField.USE_JOIN_NO) {
0768:                        SelectExp se = new SelectExp();
0769:                        JdbcClass keyJdbcClass = (JdbcClass) fmd.keyTypeMetaData.storeClass;
0770:                        se.table = keyJdbcClass.table;
0771:                        se.outer = true;
0772:                        FgDs fgDs = ((JdbcFetchGroup) field.nextKeyFetchGroup.storeFetchGroup)
0773:                                .getFgDs(true, se.outer);
0774:                        sm.addSelectFetchGroup(se, field.nextKeyFetchGroup,
0775:                                true, fgDs, false);
0776:                        owningFgDs.keyJs = fgDs.getJoinStruct();
0777:                        root.addJoin(keyColumns, se.table.pk, se);
0778:                    }
0779:                }
0780:                return root;
0781:            }
0782:
0783:            /**
0784:             * Fetch the values for this field.
0785:             */
0786:            public int fetch(JdbcStorageManager sm, OID oid, State state,
0787:                    FetchGroupField field, boolean forUpdate,
0788:                    StateContainer container, boolean fetchPass2Fields,
0789:                    ColFieldHolder colFHolder) throws SQLException {
0790:                JoinStructure valueJs = null;
0791:                JoinStructure keyJs = null;
0792:
0793:                FgDs[] fgDses = new FgDs[2];
0794:
0795:                String sql = forUpdate ? field.jdbcSelectSqlForUpdate
0796:                        : field.jdbcSelectSql;
0797:                if (sql == null) {
0798:                    SelectExp se = getSelectExp(sm, field, fgDses);
0799:                    CharBuf s = sm.generateSql(se);
0800:                    sql = s.toString();
0801:                    if (forUpdate) {
0802:                        field.jdbcSelectSqlForUpdate = sql;
0803:                    } else {
0804:                        field.jdbcSelectSql = sql;
0805:                    }
0806:                }
0807:
0808:                if (valuesAreOIDs) {
0809:                    fgDses[0] = ((JdbcFetchGroup) field.nextFetchGroup.storeFetchGroup)
0810:                            .getExistingFgDs(
0811:                                    true,
0812:                                    field.jdbcUseJoin != JdbcField.USE_JOIN_INNER);
0813:                    if (colFHolder != null) {
0814:                        if (fgDses[0] != null) {
0815:                            colFHolder.valueJs = fgDses[0].getJoinStruct();
0816:                        }
0817:                    }
0818:                }
0819:                if (keysAreOIDs) {
0820:                    fgDses[1] = ((JdbcFetchGroup) field.nextKeyFetchGroup.storeFetchGroup)
0821:                            .getExistingFgDs(
0822:                                    true,
0823:                                    field.jdbcUseKeyJoin == JdbcField.USE_JOIN_OUTER);
0824:                    if (colFHolder != null) {
0825:                        if (fgDses[1] != null) {
0826:                            colFHolder.keyJs = fgDses[1].getJoinStruct();
0827:                        }
0828:                    }
0829:                }
0830:
0831:                PreparedStatement ps = null;
0832:                ResultSet rs = null;
0833:                try {
0834:                    ps = sm.con().prepareStatement(sql);
0835:
0836:                    ArrayList keys = new ArrayList();
0837:                    ArrayList values = new ArrayList();
0838:
0839:                    // get info to extract the keys
0840:                    final boolean keyJoined = field.jdbcUseKeyJoin != JdbcField.USE_JOIN_NO;
0841:                    int keyScc = keyColumns.length;
0842:                    OID keyOid = null;
0843:
0844:                    // get info to extract the values
0845:                    final boolean valueJoined = field.jdbcUseJoin != JdbcField.USE_JOIN_NO
0846:                            || fmd.ordering != null;
0847:                    final int valueScc = valueColumns.length;
0848:
0849:                    // process the rows
0850:                    ((JdbcOID) oid).setParams(ps, 1);
0851:                    try {
0852:                        rs = ps.executeQuery();
0853:                    } catch (Exception e) {
0854:                        throw mapException(e, "Fetch link table rows failed: "
0855:                                + JdbcUtils.toString(e) + "\n" + "Field: "
0856:                                + fmd.getTypeQName() + "\n" + "Instance: "
0857:                                + oid.toSString() + "\n"
0858:                                + JdbcUtils.getPreparedStatementInfo(sql, ps));
0859:                    }
0860:
0861:                    MutableInt nextIndex = null;
0862:                    if (valuesAreOIDs)
0863:                        nextIndex = new MutableInt();
0864:                    for (; rs.next();) {
0865:
0866:                        if (keysAreOIDs) {
0867:                            keyOid = fmd.keyTypeMetaData.createOID(false);
0868:                            ((JdbcOID) keyOid).copyKeyFields(rs, 1);
0869:                            keys.add(keyOid);
0870:                        } else {
0871:                            keys.add(keyColumns[0].get(rs, 1));
0872:                        }
0873:                        int index = 1 + keyScc;
0874:
0875:                        if (valuesAreOIDs) {
0876:                            OID valueOid = fmd.elementTypeMetaData
0877:                                    .createOID(false);
0878:                            if (((JdbcOID) valueOid).copyKeyFields(rs, index)) {
0879:                                values.add(valueOid);
0880:                                index += valueScc;
0881:                                if (valueJoined) {
0882:                                    if (container.isStateRequired(valueOid,
0883:                                            field.nextFetchGroup)) {
0884:                                        container.addState(valueOid, sm
0885:                                                .createStateImp(rs, valueOid,
0886:                                                        field.nextFetchGroup,
0887:                                                        forUpdate, index,
0888:                                                        nextIndex, true,
0889:                                                        container, fgDses[0],
0890:                                                        fetchPass2Fields,
0891:                                                        false, valueJs));
0892:                                        index = nextIndex.value;
0893:                                    } else {
0894:                                        index = sm.skipState(index, fgDses[0]);
0895:                                    }
0896:                                }
0897:                            } else {
0898:                                index += valueScc;
0899:                                values.add(null);
0900:                            }
0901:                        } else {
0902:                            values.add(valueColumns[0].get(rs, index));
0903:                            index += valueScc;
0904:                        }
0905:
0906:                        if (keysAreOIDs
0907:                                && keyJoined
0908:                                && container.isStateRequired(keyOid,
0909:                                        field.nextKeyFetchGroup)) {
0910:                            container.addState(keyOid, sm.createStateImp(rs,
0911:                                    keyOid, field.nextKeyFetchGroup, forUpdate,
0912:                                    index, null, true, container, fgDses[1],
0913:                                    fetchPass2Fields, false, keyJs));
0914:                        }
0915:                    }
0916:
0917:                    MapEntries me = new MapEntries();
0918:                    if (keysAreOIDs) {
0919:                        me.keys = new OID[keys.size()];
0920:                        keys.toArray(me.keys);
0921:                    } else {
0922:                        me.keys = keys.toArray();
0923:                    }
0924:                    if (valuesAreOIDs) {
0925:                        me.values = new OID[values.size()];
0926:                        values.toArray(me.values);
0927:                    } else {
0928:                        me.values = values.toArray();
0929:                    }
0930:                    state.setInternalObjectField(fmd.stateFieldNo, me);
0931:                    // @todo what about empty/null checking?
0932:
0933:                    return keys.size();
0934:                } finally {
0935:                    cleanup(rs);
0936:                    cleanup(ps);
0937:                }
0938:            }
0939:
0940:            /**
0941:             * Fetch the values for this field using parallel query processing.
0942:             */
0943:            public int fetchWithFilter(JdbcStorageManager sm,
0944:                    StateContainer oidStates, FetchGroupField field,
0945:                    ResultSet rs, boolean forUpdate, OID oidToCheckOn,
0946:                    OID[] lastReadStateOID, ClassMetaData cmd,
0947:                    ColFieldHolder colFHolder) throws SQLException {
0948:
0949:                ClassMetaData keyCmd = fmd.keyTypeMetaData;
0950:                boolean keyJoined = field.jdbcUseKeyJoin != JdbcField.USE_JOIN_NO;
0951:                FetchGroup keyNFG = field.nextKeyFetchGroup;
0952:                JdbcColumn kc = keyColumns[0];
0953:                int keyScc = keyColumns.length;
0954:
0955:                // get info to extract the values
0956:                ClassMetaData valueCmd = fmd.elementTypeMetaData;
0957:                boolean valueJoined = field.jdbcUseJoin != JdbcField.USE_JOIN_NO;
0958:                FetchGroup nfg = field.nextFetchGroup;
0959:                JdbcColumn vc = valueColumns[0];
0960:                int valueScc = valueColumns.length;
0961:
0962:                int rootOIDLength = ((JdbcClass) cmd.storeClass).table.pkSimpleColumnCount;
0963:                int stateOIDPKLen = ((JdbcClass) fmd.classMetaData.storeClass).table.pkSimpleColumnCount;
0964:
0965:                //the oid just read from the rs row
0966:                OID rootOid = cmd.createOID(false);
0967:                //the oid read from the previous rs row
0968:                OID prevRootOid = cmd.createOID(false);
0969:                OID tmpOID = null;
0970:
0971:                OID stateOID = fmd.classMetaData.createOID(false);
0972:                OID prevStateOID = fmd.classMetaData.createOID(false);
0973:                OID tmpStateOID = null;
0974:
0975:                boolean currentRowValid = false;
0976:                boolean prevRowValid = false;
0977:
0978:                final ArrayList keys = new ArrayList();
0979:                final ArrayList values = new ArrayList();
0980:
0981:                MutableInt nextIndex = null;
0982:                if (valuesAreOIDs)
0983:                    nextIndex = new MutableInt();
0984:                int returnState = 0;
0985:
0986:                FgDs fgDsValue = null;
0987:                if (valuesAreOIDs) {
0988:                    fgDsValue = ((JdbcFetchGroup) field.nextFetchGroup.storeFetchGroup)
0989:                            .getExistingFgDs(
0990:                                    true,
0991:                                    field.jdbcUseJoin == JdbcField.USE_JOIN_OUTER);
0992:                    if (colFHolder != null) {
0993:                        colFHolder.valueJs = fgDsValue.getJoinStruct();
0994:                    }
0995:                }
0996:
0997:                FgDs fgDsKeys = null;
0998:                if (keysAreOIDs) {
0999:                    fgDsKeys = ((JdbcFetchGroup) field.nextKeyFetchGroup.storeFetchGroup)
1000:                            .getFgDs(
1001:                                    true,
1002:                                    field.jdbcUseJoin == JdbcField.USE_JOIN_OUTER);
1003:                    if (colFHolder != null) {
1004:                        colFHolder.keyJs = fgDsKeys.getJoinStruct();
1005:                    }
1006:                }
1007:
1008:                //This oid was read previously so we have to read the rest of the row now.
1009:                if (lastReadStateOID[0] != null) {
1010:                    //            System.out.println("--- FINISHING LAST ROW READ");
1011:                    int index = 1 + rootOIDLength + stateOIDPKLen;
1012:
1013:                    prevRootOid = lastReadStateOID[0];
1014:                    //            index += rootOIDLength;
1015:
1016:                    stateOID = lastReadStateOID[1];
1017:                    //            index += stateOIDPKLen;
1018:
1019:                    currentRowValid = oidStates.containsKey(stateOID);
1020:                    if (currentRowValid) {
1021:                        returnState |= STATUS_VALID_ROWS;
1022:                        OID keyOid = null;
1023:                        if (keysAreOIDs) {
1024:                            keyOid = keyCmd.createOID(false);
1025:                            ((JdbcOID) keyOid).copyKeyFields(rs, index);
1026:                            keys.add(keyOid);
1027:                        } else {
1028:                            keys.add(kc.get(rs, index));
1029:                        }
1030:                        index += keyScc;
1031:
1032:                        if (valuesAreOIDs) {
1033:                            OID valueOid = valueCmd.createOID(false);
1034:                            ((JdbcOID) valueOid).copyKeyFields(rs, index);
1035:                            index += valueScc;
1036:                            values.add(valueOid);
1037:                            if (valueJoined) {
1038:                                if (oidStates.isStateRequired(valueOid, nfg)) {
1039:                                    State valueState = sm.createStateImp(rs,
1040:                                            valueOid, field.nextFetchGroup,
1041:                                            forUpdate, index, nextIndex, true,
1042:                                            oidStates, fgDsValue, false, false,
1043:                                            null);
1044:
1045:                                    index = nextIndex.value;
1046:                                    //                            valueOid.resolve(valueState);
1047:                                    oidStates.addState(valueOid, valueState);
1048:                                } else {
1049:                                    index = sm.skipState(index, fgDsValue);
1050:                                }
1051:                            }
1052:                        } else {
1053:                            values.add(vc.get(rs, index));
1054:                            index += valueScc;
1055:                        }
1056:
1057:                        if (keysAreOIDs && keyJoined
1058:                                && oidStates.isStateRequired(keyOid, keyNFG)) {
1059:                            State keyState = sm.createStateImp(rs, keyOid,
1060:                                    field.nextKeyFetchGroup, forUpdate, index,
1061:                                    nextIndex, true, oidStates, fgDsKeys,
1062:                                    false, false, colFHolder.keyJs);
1063:                            oidStates.addState(keyOid, keyState);
1064:                        }
1065:                        if (nextIndex != null)
1066:                            nextIndex.value = 0;
1067:                    }
1068:
1069:                    //preserve the prevRootOid
1070:                    tmpOID = rootOid;
1071:                    rootOid = prevRootOid;
1072:                    prevRootOid = tmpOID;
1073:
1074:                    //preserve the prevStateOID
1075:                    tmpStateOID = stateOID;
1076:                    stateOID = prevStateOID;
1077:                    prevStateOID = tmpStateOID;
1078:
1079:                    prevRowValid = currentRowValid;
1080:                }
1081:
1082:                for (; rs.next();) {
1083:                    int index = 1;
1084:
1085:                    ((JdbcOID) rootOid).copyKeyFields(rs, index);
1086:                    index += rootOIDLength;
1087:
1088:                    ((JdbcOID) stateOID).copyKeyFields(rs, index);
1089:                    index += stateOIDPKLen;
1090:
1091:                    currentRowValid = oidStates.containsKey(stateOID);
1092:
1093:                    if (!stateOID.equals(prevStateOID) && prevRowValid) {
1094:                        if (Debug.DEBUG) {
1095:                            if (oidStates.get(prevStateOID) == null) {
1096:                                ((StatesReturned) oidStates).dump();
1097:                                throw new NullPointerException(prevStateOID
1098:                                        .toSString()
1099:                                        + " oidStates " + oidStates);
1100:                            }
1101:                        }
1102:                        if (updateStateFilter(keys, values, oidStates
1103:                                .get(prevStateOID))) {
1104:                            returnState |= STATUS_DATA_ADDED;
1105:                        }
1106:
1107:                        if (oidToCheckOn.equals(prevRootOid)
1108:                                && !oidToCheckOn.equals(rootOid)) {
1109:                            lastReadStateOID[0] = rootOid;
1110:                            lastReadStateOID[1] = stateOID;
1111:                            returnState |= STATUS_VALID_ROWS;
1112:                            return returnState;
1113:                        }
1114:
1115:                        keys.clear();
1116:                        values.clear();
1117:                    }
1118:
1119:                    if (currentRowValid) {
1120:                        returnState |= STATUS_VALID_ROWS;
1121:                        OID keyOid = null;
1122:                        if (keysAreOIDs) {
1123:                            keyOid = keyCmd.createOID(false);
1124:                            ((JdbcOID) keyOid).copyKeyFields(rs, index);
1125:                            keys.add(keyOid);
1126:                        } else {
1127:                            keys.add(kc.get(rs, index));
1128:                        }
1129:                        index += keyScc;
1130:
1131:                        if (valuesAreOIDs) {
1132:                            OID valueOid = valueCmd.createOID(false);
1133:                            ((JdbcOID) valueOid).copyKeyFields(rs, index);
1134:                            index += valueScc;
1135:                            values.add(valueOid);
1136:                            if (valueJoined) {
1137:                                if (oidStates.isStateRequired(valueOid, nfg)) {
1138:                                    State valueState = sm
1139:                                            .createStateImp(
1140:                                                    rs,
1141:                                                    valueOid,
1142:                                                    field.nextFetchGroup,
1143:                                                    forUpdate,
1144:                                                    index,
1145:                                                    nextIndex,
1146:                                                    true,
1147:                                                    oidStates,
1148:                                                    ((JdbcFetchGroup) field.nextFetchGroup.storeFetchGroup)
1149:                                                            .getFgDs(
1150:                                                                    true,
1151:                                                                    field.jdbcUseJoin == JdbcField.USE_JOIN_OUTER),
1152:                                                    false, false, null);
1153:
1154:                                    index = nextIndex.value;
1155:                                    oidStates.addState(valueOid, valueState);
1156:                                } else {
1157:                                    index = sm
1158:                                            .skipState(
1159:                                                    index,
1160:                                                    ((JdbcFetchGroup) field.nextFetchGroup.storeFetchGroup)
1161:                                                            .getFgDs(
1162:                                                                    true,
1163:                                                                    field.jdbcUseJoin == JdbcField.USE_JOIN_OUTER));
1164:                                }
1165:                            }
1166:                        } else {
1167:                            values.add(vc.get(rs, index));
1168:                            index += valueScc;
1169:                        }
1170:
1171:                        if (keysAreOIDs && keyJoined
1172:                                && oidStates.isStateRequired(keyOid, keyNFG)) {
1173:                            State keyState = sm
1174:                                    .createStateImp(
1175:                                            rs,
1176:                                            keyOid,
1177:                                            field.nextKeyFetchGroup,
1178:                                            forUpdate,
1179:                                            index,
1180:                                            nextIndex,
1181:                                            true,
1182:                                            oidStates,
1183:                                            ((JdbcFetchGroup) field.nextKeyFetchGroup.storeFetchGroup)
1184:                                                    .getFgDs(
1185:                                                            true,
1186:                                                            field.jdbcUseJoin == JdbcField.USE_JOIN_OUTER),
1187:                                            false, false, colFHolder.keyJs);
1188:                            oidStates.addState(keyOid, keyState);
1189:                        }
1190:
1191:                        if (nextIndex != null)
1192:                            nextIndex.value = 0;
1193:                    }
1194:
1195:                    //preserve the prevRootOid
1196:                    tmpOID = rootOid;
1197:                    rootOid = prevRootOid;
1198:                    prevRootOid = tmpOID;
1199:
1200:                    //preserve the prevStateOID
1201:                    tmpStateOID = stateOID;
1202:                    stateOID = prevStateOID;
1203:                    prevStateOID = tmpStateOID;
1204:
1205:                    prevRowValid = currentRowValid;
1206:                }
1207:
1208:                rs.close();
1209:                returnState |= STATUS_CLOSED;
1210:                if ((returnState & STATUS_VALID_ROWS) == STATUS_VALID_ROWS) {
1211:                    if (updateStateFilter(keys, values, oidStates
1212:                            .get(prevStateOID))) {
1213:                        returnState |= STATUS_DATA_ADDED;
1214:                    }
1215:                }
1216:                return returnState;
1217:            }
1218:
1219:            public void fillStateWithEmpty(FetchGroupField field, State state) {
1220:                if (!state.containsField(fmd.stateFieldNo)) {
1221:                    MapEntries me = new MapEntries();
1222:                    me.preGenerated = true;
1223:                    if (keysAreOIDs) {
1224:                        me.keys = EMPTY_OID_ARRAY;
1225:                    } else {
1226:                        me.keys = EMPTY_OBJECT_ARRAY;
1227:                    }
1228:                    if (valuesAreOIDs) {
1229:                        me.values = EMPTY_OID_ARRAY;
1230:                    } else {
1231:                        me.values = EMPTY_OBJECT_ARRAY;
1232:                    }
1233:                    state.setInternalObjectField(fmd.stateFieldNo, me);
1234:                }
1235:            }
1236:
1237:            /**
1238:             * Update the supplied state with a MapEntries intsance. This method expects
1239:             * the field to be filled with a non-null value.
1240:             */
1241:            private boolean updateStateFilter(ArrayList keys, ArrayList values,
1242:                    State state) {
1243:                if (Debug.DEBUG) {
1244:                    //TODO START IF(DEBUG)
1245:                    if (!state.containsField(fmd.stateFieldNo)) {
1246:                        throw BindingSupportImpl.getInstance()
1247:                                .internal(
1248:                                        "The mapField '" + fmd.name
1249:                                                + "' is not filled");
1250:                    }
1251:                    if (state.getInternalObjectField(fmd.stateFieldNo) == null) {
1252:                        throw BindingSupportImpl.getInstance().internal(
1253:                                "The mapField '" + fmd.name
1254:                                        + "' is filled with a null value");
1255:                    }
1256:                    //TODO END IF(DEBUG)
1257:                }
1258:
1259:                /**
1260:                 * The field is already resolved for client and this should be a state
1261:                 * that was retrieved from the localPMCache
1262:                 */
1263:                if ((state.getInternalObjectField(fmd.stateFieldNo) instanceof  Map)) {
1264:                    //            if (state.txId != TxId.PM_STATE_ID) {
1265:                    //                throw BindingSupportImpl.getInstance().internal(
1266:                    //                        "The field is filled with " +
1267:                    //                        "a Map instance, but the state is not a localPmCache state");
1268:                    //            }
1269:                    return false;
1270:                }
1271:
1272:                if (!((MapEntries) state
1273:                        .getInternalObjectField(fmd.stateFieldNo)).preGenerated) {
1274:                    return false;
1275:                }
1276:
1277:                MapEntries me = new MapEntries();
1278:                if (keysAreOIDs) {
1279:                    me.keys = new OID[keys.size()];
1280:                    keys.toArray(me.keys);
1281:                } else {
1282:                    me.keys = keys.toArray();
1283:                }
1284:                if (valuesAreOIDs) {
1285:                    me.values = new OID[values.size()];
1286:                    values.toArray(me.values);
1287:                } else {
1288:                    me.values = values.toArray();
1289:                }
1290:                state.setInternalObjectField(fmd.stateFieldNo, me);
1291:                return true;
1292:            }
1293:
1294:            /**
1295:             * Convert this field into a containsKey expression.
1296:             */
1297:            public SqlExp toContainsKeySqlExp(JdbcJDOQLCompiler comp,
1298:                    SelectExp root, Node args) {
1299:                return toContainsSqlExp(keyColumns, fmd.keyTypeMetaData, comp,
1300:                        root, args);
1301:            }
1302:
1303:            /**
1304:             * Add our key columns to the row.
1305:             */
1306:            protected void addFetchAllRowsKey(SqlExp e, SelectExp se) {
1307:                for (; e.next != null; e = e.next)
1308:                    ;
1309:                e.next = JdbcColumn.toSqlExp(keyColumns, se);
1310:            }
1311:
1312:            /**
1313:             * Fetch a row of values for this field. This is used when bulk copying
1314:             * one database to another to read all the rows in a given link table.
1315:             * Return the index of the last column read + 1.
1316:             */
1317:            public int readRow(ResultSet rs, JdbcLinkCollectionField.LinkRow row)
1318:                    throws SQLException {
1319:                int pos = super .readRow(rs, row);
1320:                if (keysAreOIDs) {
1321:                    OID keyOid = fmd.keyTypeMetaData.createOID(false);
1322:                    ((JdbcOID) keyOid).copyKeyFields(rs, pos);
1323:                    row.key = keyOid;
1324:                    pos += keyColumns.length;
1325:                } else {
1326:                    row.key = keyColumns[0].get(rs, pos++);
1327:                }
1328:                return pos;
1329:            }
1330:
1331:            /**
1332:             * Set a row of values for this field on a PreparedStatement.
1333:             * This is used when bulk copying one database to another.
1334:             */
1335:            public void writeRow(PreparedStatement ps, LinkRow row)
1336:                    throws SQLException {
1337:                row.owner.setCmd(fmd.classMetaData);
1338:                int pos = row.owner.setParams(ps, 1);
1339:                if (keysAreOIDs) {
1340:                    JdbcGenericOID k = (JdbcGenericOID) row.key;
1341:                    k.setCmd(fmd.classMetaData);
1342:                    pos = k.setParams(ps, pos);
1343:                } else {
1344:                    keyColumns[0].set(ps, pos++, row.key);
1345:                }
1346:                if (valuesAreOIDs) {
1347:                    JdbcGenericOID v = (JdbcGenericOID) row.value;
1348:                    v.setCmd(fmd.classMetaData);
1349:                    v.setParams(ps, pos);
1350:                } else {
1351:                    valueColumns[0].set(ps, pos, row.value);
1352:                }
1353:            }
1354:
1355:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.