Source Code Cross Referenced for JdbcFKCollectionField.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) 


001:        /*
002:         * Copyright (c) 1998 - 2005 Versant Corporation
003:         * All rights reserved. This program and the accompanying materials
004:         * are made available under the terms of the Eclipse Public License v1.0
005:         * which accompanies this distribution, and is available at
006:         * http://www.eclipse.org/legal/epl-v10.html
007:         *
008:         * Contributors:
009:         * Versant Corporation - initial API and implementation
010:         */
011:        package com.versant.core.jdbc.metadata;
012:
013:        import com.versant.core.metadata.parser.JdoElement;
014:        import com.versant.core.metadata.parser.JdoExtension;
015:        import com.versant.core.metadata.parser.JdoExtensionKeys;
016:        import com.versant.core.metadata.*;
017:        import com.versant.core.common.OID;
018:        import com.versant.core.common.State;
019:        import com.versant.core.jdbc.*;
020:        import com.versant.core.jdbc.query.JdbcJDOQLCompiler;
021:        import com.versant.core.jdbc.sql.exp.*;
022:        import com.versant.core.server.PersistGraph;
023:        import com.versant.core.server.StateContainer;
024:        import com.versant.core.common.*;
025:        import com.versant.core.util.CharBuf;
026:        import com.versant.core.jdo.query.Node;
027:        import com.versant.core.jdo.query.VarNode;
028:        import com.versant.core.jdo.query.VarNodeIF;
029:        import com.versant.core.common.Debug;
030:
031:        import java.io.PrintStream;
032:        import java.sql.Connection;
033:        import java.sql.SQLException;
034:        import java.sql.PreparedStatement;
035:        import java.sql.ResultSet;
036:
037:        import com.versant.core.common.BindingSupportImpl;
038:
039:        /**
040:         * A field that is a Collection or array of a PC class stored using a
041:         * foreign key in the value class.
042:         */
043:        public class JdbcFKCollectionField extends JdbcCollectionField {
044:
045:            /**
046:             * This is the 'foreign key' field in the value class.
047:             */
048:            public JdbcRefField fkField;
049:
050:            /**
051:             * This is the JdbcClass for the elements.
052:             */
053:            private JdbcClass elementJdbcClass;
054:
055:            // Size of the moving window used to calculate avgRowCount.
056:            private static final int WINDOW_SIZE = 20;
057:            // The initial array size is avgRowCount multiplied by this.
058:            private static final float FUDGE_FACTOR = 1.5f;
059:            // This is the minimum initial array size.
060:            private static final int MIN_LEN = 4;
061:
062:            // Total number of fetches done so far.
063:            protected transient int fetchCount;
064:            // Average number of rows retrieved with each fetch.
065:            protected transient float avgRowCount;
066:            // Total number of times the values array for a fetch has had to be
067:            // expanded (i.e. we guessed the size incorrectly. This is the number
068:            // of extra objects and array copies we have had to do.
069:            protected transient int expansionCount;
070:
071:            public void dump(PrintStream out, String indent) {
072:                super .dump(out, indent);
073:                String is = indent + "  ";
074:                out.println(is + "fkField " + fkField);
075:            }
076:
077:            /**
078:             * Complete the meta data for this collection. This must use info
079:             * already supplied in the .jdo file and add anything else needed.
080:             */
081:            public void processMetaData(JdoElement context,
082:                    JdbcMetaDataBuilder mdb, boolean quiet) {
083:                ClassMetaData ecmd = fmd.elementTypeMetaData;
084:                elementJdbcClass = (JdbcClass) ecmd.storeClass;
085:                if (elementJdbcClass == null) {
086:                    throw BindingSupportImpl
087:                            .getInstance()
088:                            .runtime(
089:                                    "The inverse extension may only be used for "
090:                                            + "collections of PC instances stored by JDBC\n"
091:                                            + context.getContext());
092:                }
093:                ClassMetaData cmd = fmd.classMetaData;
094:
095:                super .processMetaData(context, mdb, quiet);
096:
097:                useJoin = JdbcField.USE_JOIN_INNER;
098:                if (fmd.category != MDStatics.CATEGORY_ARRAY) {
099:                    fmd.managed = mdb.getJdbcConfig().managedOneToMany;
100:                } else {
101:                    fmd.managed = false;
102:                }
103:
104:                JdoExtension[] a;
105:                if (fmd.category == MDStatics.CATEGORY_ARRAY) {
106:                    a = fmd.jdoArray.extensions;
107:                } else if (fmd.category == MDStatics.CATEGORY_COLLECTION) {
108:                    a = fmd.jdoCollection.extensions;
109:                } else {
110:                    throw BindingSupportImpl.getInstance().internal(
111:                            "Category '"
112:                                    + MDStaticUtils
113:                                            .toCategoryString(fmd.category)
114:                                    + "' is not supported for FK Collections");
115:                }
116:                int len = a.length;
117:                for (int i = 0; i < len; i++) {
118:                    JdoExtension e = a[i];
119:                    switch (e.key) {
120:                    case JdoExtensionKeys.MANAGED:
121:                        if (fmd.category == MDStatics.CATEGORY_ARRAY
122:                                && e.getBoolean()) {
123:                            throw BindingSupportImpl.getInstance()
124:                                    .invalidOperation(
125:                                            "The managed option is not supported for arrays: "
126:                                                    + fmd.name);
127:                        }
128:                        fmd.managed = e.getBoolean();
129:                        break;
130:                    case JdoExtensionKeys.INVERSE:
131:                    case JdoExtensionKeys.JDBC_LINK_FOREIGN_KEY:
132:                        String fname = e.getString();
133:                        FieldMetaData f = ecmd.getFieldMetaData(fname);
134:                        if (f == null) {
135:                            f = createFakeFKBackRef(cmd, ecmd, mdb, e, quiet);
136:                        }
137:                        if (f.isEmbeddedRef()) {
138:                            throw BindingSupportImpl
139:                                    .getInstance()
140:                                    .invalidOperation(
141:                                            "an Inverse field may not be Embedded");
142:                        }
143:                        if (f.storeField == null) {
144:                            throw BindingSupportImpl.getInstance().runtime(
145:                                    "Field '" + fname + "' is not persistent\n"
146:                                            + context.getContext());
147:                        }
148:                        if (!(f.storeField instanceof  JdbcRefField)) {
149:                            throw BindingSupportImpl.getInstance().runtime(
150:                                    "Field '" + fname
151:                                            + "' is not a reference\n"
152:                                            + context.getContext());
153:                        }
154:                        fkField = (JdbcRefField) f.storeField;
155:                        if (!cmd.isAncestorOrSelf(fkField.targetClass)) {
156:                            throw BindingSupportImpl.getInstance().runtime(
157:                                    "Field '" + fname + "' references "
158:                                            + fkField.targetClass
159:                                            + " and not our class\n"
160:                                            + context.getContext());
161:                        }
162:                        fmd.ordered = false;
163:                        createIndex(mdb, ecmd, e.nested);
164:                        break;
165:
166:                    default:
167:                        if (e.isJdbc()) {
168:                            throw BindingSupportImpl.getInstance().runtime(
169:                                    "Unexpected extension: " + e + "\n"
170:                                            + e.getContext());
171:                        }
172:                    }
173:                }
174:                if (fkField == null) {
175:                    throw BindingSupportImpl.getInstance().internal(
176:                            "fkField is null");
177:                }
178:
179:                fkField.masterCollectionField = this ;
180:                ourPkColumns = fkField.cols;
181:            }
182:
183:            private FieldMetaData createFakeFKBackRef(ClassMetaData cmd,
184:                    ClassMetaData ecmd, JdbcMetaDataBuilder mdb,
185:                    JdoExtension e, boolean quiet) {
186:                fmd.managed = false;
187:
188:                FieldMetaData f = new FieldMetaData();
189:                f.fake = true;
190:                f.typeMetaData = cmd;
191:                f.name = cmd.getShortName() + "_" + fmd.name;
192:                f.category = MDStatics.CATEGORY_REF;
193:                f.ordered = false;
194:                f.managed = false;
195:                f.primaryField = true;
196:                JdbcRefField jdbcRefField = new JdbcRefField();
197:                jdbcRefField.targetClass = cmd;
198:                fkField = jdbcRefField;
199:                f.classMetaData = ecmd;
200:                jdbcRefField.fmd = f;
201:                f.storeField = jdbcRefField;
202:                jdbcRefField.fake = true;
203:                f.type = cmd.cls;
204:                f.inverseFieldMetaData = fmd;
205:                mdb.processRefFieldImpl(elementJdbcClass, jdbcRefField, f, e,
206:                        e.nested, quiet);
207:
208:                //                        JdbcRefMetaDataBuilder rmdb = new JdbcRefMetaDataBuilder(
209:                //                                fmd.classMetaData, mdb, cmd,
210:                //                                cmd.jdbcClass.store, e, fname, e.nested, quiet);
211:                //                        JdbcColumn[] cols = rmdb.getCols();
212:                //                        jdbcRefField.cols = cols;
213:                //                        if (cols != null) {
214:                //                            for (int j = 0; j < cols.length; j++) {
215:                //                                JdbcColumn col = cols[j];
216:                //                                col.nulls = true;
217:                //                                col.comment = "inverse FK for " + cmd.getShortName() + "-" + fmd.name;
218:                //                            }
219:                //                        }
220:                mdb.getClassInfo(ecmd).elements.add(f.storeField);
221:                return f;
222:            }
223:
224:            /**
225:             * Create an index on our pkField unless this has been disabled.
226:             */
227:            private void createIndex(JdbcMetaDataBuilder mdb,
228:                    ClassMetaData refCmd, JdoExtension[] nested) {
229:                JdbcClass refJdbcClass = (JdbcClass) refCmd.storeClass;
230:                JdbcIndex idx = null;
231:                boolean doNotCreateIndex = false;
232:
233:                int n = nested == null ? 0 : nested.length;
234:                for (int i = 0; i < n; i++) {
235:                    JdoExtension e = nested[i];
236:                    switch (e.key) {
237:                    case JdoExtensionKeys.JDBC_INDEX:
238:                        if (idx != null) {
239:                            throw BindingSupportImpl.getInstance().runtime(
240:                                    "Only one jdbc-index extension is allowed here\n"
241:                                            + e.getContext());
242:                        }
243:                        if (e.isNoValue()) {
244:                            doNotCreateIndex = true;
245:                            break;
246:                        }
247:                        idx = new JdbcIndex();
248:                        idx.name = e.value;
249:                        break;
250:                    case JdoExtensionKeys.JDBC_COLUMN:
251:                    case JdoExtensionKeys.JDBC_USE_JOIN:
252:                    case JdoExtensionKeys.JDBC_CONSTRAINT:
253:                    case JdoExtensionKeys.JDBC_REF:
254:                        // Handled
255:                        break;
256:                    default:
257:                        if (e.isJdbc()) {
258:                            MetaDataBuilder.throwUnexpectedExtension(e);
259:                        }
260:                    }
261:                }
262:
263:                if (doNotCreateIndex)
264:                    return;
265:                if (idx == null)
266:                    idx = new JdbcIndex();
267:                if (fkField.cols != null) {
268:                    idx.setCols(fkField.cols);
269:                }
270:
271:                // register the name of the index if one was specified otherwise one
272:                // will be generated later along with user specified indexes
273:                if (idx.name != null) {
274:                    try {
275:                        mdb.getNameGenerator().addIndexName(
276:                                refJdbcClass.table.name, idx.name);
277:                    } catch (IllegalArgumentException x) {
278:                        throw BindingSupportImpl.getInstance().runtime(
279:                                x.getMessage(), x);
280:                    }
281:                }
282:
283:                mdb.getClassInfo(refCmd).autoIndexes.add(idx);
284:            }
285:
286:            /**
287:             * Persist pass 2 field for a block of graph entries all with
288:             * the same class. The same ps'es can be used for all entries in the block.
289:             */
290:            public void persistPass2Block(PersistGraph graph, int blockStart,
291:                    int blockEnd, CharBuf s, Connection con,
292:                    boolean batchInserts, boolean batchUpdates)
293:                    throws SQLException {
294:                // nothing to do
295:            }
296:
297:            /**
298:             * Fetch the values for this field.
299:             */
300:            public int fetch(JdbcStorageManager sm, OID oid, State state,
301:                    FetchGroupField field, boolean forUpdate,
302:                    StateContainer container, boolean fetchPass2Fields,
303:                    ColFieldHolder colFHolder) throws SQLException {
304:
305:                String sql = forUpdate ? field.jdbcSelectSqlForUpdate
306:                        : field.jdbcSelectSql;
307:                final boolean joined = field.jdbcUseJoin != JdbcField.USE_JOIN_NO;
308:
309:                FetchGroup nextFetchGroup = field.nextFetchGroup;
310:                FgDs[] fgDses = new FgDs[1];
311:
312:                if (sql == null) {
313:                    SelectExp se = getSelectExp(field, sm, fgDses);
314:                    CharBuf s = sm.generateSql(se);
315:                    sql = s.toString();
316:                    if (forUpdate) {
317:                        field.jdbcSelectSqlForUpdate = sql;
318:                    } else {
319:                        field.jdbcSelectSql = sql;
320:                    }
321:                } else {
322:                    fgDses[0] = ((JdbcFetchGroup) nextFetchGroup.storeFetchGroup)
323:                            .getExistingFgDs(true, false);
324:                }
325:
326:                if (colFHolder != null && fgDses[0] != null) {
327:                    colFHolder.valueJs = fgDses[0].getJoinStruct();
328:                }
329:
330:                PreparedStatement ps = null;
331:                ResultSet rs = null;
332:                Struct s = new Struct();
333:                try {
334:                    ps = sm.con().prepareStatement(sql);
335:                    ((JdbcOID) oid).setParams(ps, 1);
336:                    try {
337:                        rs = ps.executeQuery();
338:                    } catch (Exception e) {
339:                        throw mapException(e,
340:                                "Fetch inverse foreign key collection failed: "
341:                                        + JdbcUtils.toString(e)
342:                                        + "\n"
343:                                        + "Field: "
344:                                        + fmd.getTypeQName()
345:                                        + "\n"
346:                                        + "Instance: "
347:                                        + oid.toSString()
348:                                        + "\n"
349:                                        + JdbcUtils.getPreparedStatementInfo(
350:                                                sql, ps));
351:                    }
352:
353:                    s.init();
354:
355:                    ClassMetaData valueCmd = fmd.elementTypeMetaData;
356:
357:                    int valuePkLen = 0;
358:                    if (joined)
359:                        valuePkLen = elementJdbcClass.table.pkSimpleColumnCount;
360:                    for (; rs.next();) {
361:                        OID valueOid = valueCmd.createOID(false);
362:                        boolean isNull = !((JdbcOID) valueOid).copyKeyFields(
363:                                rs, 1);
364:                        if (isNull) {
365:                            s.add(null);
366:                        } else {
367:                            s.add(valueOid);
368:                        }
369:
370:                        if (!isNull
371:                                && joined
372:                                && container.isStateRequired(valueOid,
373:                                        nextFetchGroup)) {
374:                            State valueState = sm.createStateImp(rs, valueOid,
375:                                    nextFetchGroup, forUpdate, 1 + valuePkLen,
376:                                    null, true, container, fgDses[0],
377:                                    fetchPass2Fields, false, null);
378:                            container.addState(valueOid, valueState);
379:                        }
380:                    }
381:
382:                    // this can come out when the bugs are removed from the rest
383:                    // of the code
384:                    updateState(s, state);
385:                    updateStats(s.size);
386:                } finally {
387:                    cleanup(rs);
388:                    cleanup(ps);
389:                }
390:                return s.size;
391:            }
392:
393:            public int fetchFrom(ResultSet rs, OID oid, State state,
394:                    FetchGroupField field, boolean forUpdate,
395:                    StateContainer container, boolean fetchPass2Fields,
396:                    int colIndex, FetchInfo fetchInfo, JdbcStorageManager sm)
397:                    throws SQLException {
398:
399:                Struct s = new Struct();
400:                final boolean joined = field.jdbcUseJoin != JdbcField.USE_JOIN_NO;
401:                boolean first = true;
402:                s.init();
403:                ClassMetaData valueCmd = fmd.elementTypeMetaData;
404:
405:                FetchGroup nextFetchGroup = field.nextFetchGroup;
406:
407:                int valuePkLen = 0;
408:                if (joined)
409:                    valuePkLen = elementJdbcClass.table.pkSimpleColumnCount;
410:                for (;;) {
411:                    boolean mustBreak = false;
412:                    if (first) {
413:                        first = false;
414:                        mustBreak = updateForFirstRow(fetchInfo, mustBreak, rs,
415:                                colIndex, oid);
416:                    } else {
417:                        if (rs.next()) {
418:                            mustBreak = checkKeyOid(rs, colIndex, fetchInfo,
419:                                    mustBreak, oid);
420:                            fetchInfo.onNextRow = true;
421:                        } else {
422:                            fetchInfo.onNextRow = false;
423:                            fetchInfo.finished = true;
424:                            mustBreak = true;
425:                        }
426:                    }
427:                    if (mustBreak)
428:                        break;
429:
430:                    OID valueOid = valueCmd.createOID(false);
431:                    boolean isNull = !((JdbcOID) valueOid).copyKeyFields(rs,
432:                            colIndex + ourPkColumns.length);
433:                    if (!isNull) {
434:                        s.add(valueOid);
435:                        if (joined
436:                                && container.isStateRequired(valueOid,
437:                                        nextFetchGroup)) {
438:                            State valueState = sm
439:                                    .createStateImp(
440:                                            rs,
441:                                            valueOid,
442:                                            nextFetchGroup,
443:                                            forUpdate,
444:                                            colIndex + ourPkColumns.length
445:                                                    + valuePkLen,
446:                                            null,
447:                                            true,
448:                                            container,
449:                                            ((JdbcFetchGroup) nextFetchGroup.storeFetchGroup)
450:                                                    .getExistingFgDs(true, true),
451:                                            fetchPass2Fields, false, null);
452:                            container.addState(valueOid, valueState);
453:                        }
454:                    } else {
455:                        //no elements
456:                        break;
457:                    }
458:                }
459:
460:                updateState(s, state);
461:                updateStats(s.size);
462:                return s.size;
463:            }
464:
465:            private void updateStats(int size) {
466:                // Update statistics. This is not thread safe but it is not a
467:                // problem if the avgRowCount is a bit out sometimes.
468:                int fc = ++fetchCount;
469:                if (fc > WINDOW_SIZE) {
470:                    fc = WINDOW_SIZE;
471:                } else if (fc == 1) {
472:                    avgRowCount = size;
473:                } else if (fc < 0) {
474:                    fc = fetchCount = WINDOW_SIZE;
475:                } else {
476:                    avgRowCount = (avgRowCount * (fc - 1) + size) / fc;
477:                }
478:            }
479:
480:            public int fetchWithFilter(JdbcStorageManager sm,
481:                    StateContainer oidStates, FetchGroupField field,
482:                    ResultSet rs, boolean forUpdate, OID oidToCheckOn,
483:                    OID[] lastReadStateOID, ClassMetaData cmd,
484:                    ColFieldHolder colFHolder) throws SQLException {
485:
486:                ClassMetaData valueCmd = fmd.elementTypeMetaData;
487:                final boolean joined = field.jdbcUseJoin != JdbcField.USE_JOIN_NO;
488:                FetchGroup nextFetchGroup = field.nextFetchGroup;
489:
490:                if (colFHolder != null) {
491:                    colFHolder.valueJs = new JoinStructure(nextFetchGroup);
492:                }
493:
494:                int valuePkLen = 0;
495:                if (joined)
496:                    valuePkLen = elementJdbcClass.table.pkSimpleColumnCount;
497:
498:                int rootOIDLenght = ((JdbcClass) cmd.storeClass).table.pkSimpleColumnCount;
499:                int stateOIDPKLen = ((JdbcClass) fmd.classMetaData.storeClass).table.pkSimpleColumnCount;
500:
501:                //the oid just read from the rs row
502:                OID rootOid = cmd.createOID(false);
503:                //the oid read from the previous rs row
504:                OID prevRootOid = cmd.createOID(false);
505:                OID tmpOID = null;
506:
507:                OID stateOID = fmd.classMetaData.createOID(false);
508:                OID prevStateOID = fmd.classMetaData.createOID(false);
509:                OID tmpStateOID = null;
510:
511:                Struct s = new Struct();
512:                s.init();
513:
514:                boolean currentRowValid = false;
515:                boolean prevRowValid = false;
516:                int returnState = 0;
517:
518:                FgDs fgDs = ((JdbcFetchGroup) nextFetchGroup.storeFetchGroup)
519:                        .getExistingFgDs(true,
520:                                field.jdbcUseJoin == JdbcField.USE_JOIN_OUTER);
521:                if (colFHolder != null) {
522:                    colFHolder.valueJs = fgDs.getJoinStruct();
523:                }
524:
525:                //This oid was read previously so we have to read the rest of the row now.
526:                if (lastReadStateOID[0] != null) {
527:                    int index = 1;
528:
529:                    prevRootOid = lastReadStateOID[0];
530:                    index += rootOIDLenght;
531:
532:                    stateOID = lastReadStateOID[1];
533:                    index += stateOIDPKLen;
534:
535:                    currentRowValid = oidStates.containsKey(stateOID);
536:
537:                    if (currentRowValid) {
538:                        returnState |= STATUS_VALID_ROWS;
539:                        OID valueOid = valueCmd.createOID(false);
540:                        boolean isNull = !((JdbcOID) valueOid).copyKeyFields(
541:                                rs, index);
542:                        index += valuePkLen;
543:
544:                        if (!isNull) {
545:                            s.add(valueOid);
546:                        } else {
547:                            s.add(null);
548:                        }
549:
550:                        if (!isNull
551:                                && joined
552:                                && oidStates.isStateRequired(valueOid,
553:                                        nextFetchGroup)) {
554:
555:                            State valueState = sm.createStateImp(rs, valueOid,
556:                                    nextFetchGroup, forUpdate, index, null,
557:                                    true, oidStates, fgDs, false, false, null);
558:                            oidStates.addState(valueOid, valueState);
559:                        }
560:                    }
561:
562:                    //preserve the prevRootOid
563:                    tmpOID = rootOid;
564:                    rootOid = prevRootOid;
565:                    prevRootOid = tmpOID;
566:
567:                    //preserve the prevStateOID
568:                    tmpStateOID = stateOID;
569:                    stateOID = prevStateOID;
570:                    prevStateOID = tmpStateOID;
571:
572:                    prevRowValid = currentRowValid;
573:                }
574:
575:                //go through the rs until we reach the end or oidToCheckOn
576:                for (; rs.next();) {
577:                    int index = 1;
578:                    ((JdbcOID) rootOid).copyKeyFields(rs, index);
579:                    index += rootOIDLenght;
580:
581:                    ((JdbcOID) stateOID).copyKeyFields(rs, index);
582:                    index += stateOIDPKLen;
583:
584:                    currentRowValid = oidStates.containsKey(stateOID);
585:
586:                    //detected a change in stateOid. Only update if the previous
587:                    // row was for a valid oid.
588:                    if (!stateOID.equals(prevStateOID) && prevRowValid) {
589:                        if (updateStateFilter(s, oidStates.get(prevStateOID))) {
590:                            returnState |= STATUS_DATA_ADDED;
591:                        }
592:                        updateStatistics(s.size);
593:                        //if lastRootOid is the oid to check on then return do no process further.
594:                        if (oidToCheckOn.equals(prevRootOid)
595:                                && !oidToCheckOn.equals(rootOid)) {
596:                            lastReadStateOID[0] = rootOid;
597:                            lastReadStateOID[1] = stateOID;
598:                            returnState |= STATUS_VALID_ROWS;
599:                            return returnState;
600:                        }
601:                        //reset the struct for next usage.
602:                        s.init();
603:                    }
604:
605:                    if (currentRowValid) {
606:                        returnState |= STATUS_VALID_ROWS;
607:                        OID valueOid = valueCmd.createOID(false);
608:                        boolean isNull = !((JdbcOID) valueOid).copyKeyFields(
609:                                rs, index);
610:                        if (!isNull) {
611:                            s.add(valueOid);
612:                        } else {
613:                            s.add(null);
614:                        }
615:
616:                        index += valuePkLen;
617:                        if (!isNull
618:                                && joined
619:                                && oidStates.isStateRequired(valueOid,
620:                                        nextFetchGroup)) {
621:                            State valueState = sm
622:                                    .createStateImp(
623:                                            rs,
624:                                            valueOid,
625:                                            nextFetchGroup,
626:                                            forUpdate,
627:                                            index,
628:                                            null,
629:                                            true,
630:                                            oidStates,
631:                                            ((JdbcFetchGroup) nextFetchGroup.storeFetchGroup)
632:                                                    .getFgDs(
633:                                                            true,
634:                                                            field.jdbcUseJoin == JdbcField.USE_JOIN_OUTER),
635:                                            false, false, null);
636:                            oidStates.addState(valueOid, valueState);
637:                        }
638:                    }
639:
640:                    //preserve the prevRootOid
641:                    tmpOID = rootOid;
642:                    rootOid = prevRootOid;
643:                    prevRootOid = tmpOID;
644:
645:                    //preserve the prevStateOID
646:                    tmpStateOID = stateOID;
647:                    stateOID = prevStateOID;
648:                    prevStateOID = tmpStateOID;
649:
650:                    prevRowValid = currentRowValid;
651:                }
652:                rs.close();
653:                if ((returnState & STATUS_VALID_ROWS) == STATUS_VALID_ROWS) {
654:                    if (updateStateFilter(s, oidStates.get(prevStateOID))) {
655:                        returnState |= STATUS_DATA_ADDED;
656:                    }
657:                }
658:                returnState |= STATUS_CLOSED;
659:                return returnState;
660:            }
661:
662:            public void fillStateWithEmpty(FetchGroupField field, State state) {
663:                if (!state.containsField(fmd.stateFieldNo)) {
664:                    state.setInternalObjectField(fmd.stateFieldNo,
665:                            PRE_GEN_EMPTY_OBJECT_ARRAY);
666:                }
667:            }
668:
669:            private boolean updateState(Struct s, State state) {
670:                if (state == null)
671:                    return false;
672:                if (s.values == null)
673:                    s.values = EMPTY_OID_ARRAY;
674:                s.trim();
675:                state.setInternalObjectField(fmd.stateFieldNo, s.values);
676:                return true;
677:            }
678:
679:            private boolean updateStateFilter(Struct s, State state) {
680:                if (state == null)
681:                    return false;
682:                if (s.values == null)
683:                    s.values = EMPTY_OID_ARRAY;
684:                if (state.getInternalObjectField(fmd.stateFieldNo) == PRE_GEN_EMPTY_OBJECT_ARRAY) {
685:                    s.trim();
686:                    state.setInternalObjectField(fmd.stateFieldNo, s.values);
687:                    return true;
688:                }
689:                return false;
690:            }
691:
692:            public void appendOrderExpForFilterExp(SelectExp se, SelectExp root) {
693:                if (fmd.elementTypeMetaData != null) {
694:                    root
695:                            .appendOrderByForColumns(
696:                                    ((JdbcClass) fmd.elementTypeMetaData.storeClass).table.pk,
697:                                    se);
698:                }
699:            }
700:
701:            private class Struct {
702:
703:                public int len;
704:                public OID[] values;
705:                public int size;
706:
707:                public OID prevRootOID;
708:                public OID currentRootOID;
709:
710:                public OID prevStateOID;
711:                public OID currentStateOID;
712:
713:                public void init() {
714:                    len = (int) (avgRowCount * FUDGE_FACTOR);
715:                    if (len < MIN_LEN)
716:                        len = 0;
717:                    values = len == 0 ? null : new OID[len];
718:                    if (Debug.DEBUG) {
719:                        if (((fetchCount + 1) % 10) == 0) {
720:                            System.out.println("JdbcFkCollectionField.fetch"
721:                                    + " avgRowCount = " + avgRowCount + " "
722:                                    + " len = " + len + " "
723:                                    + " expansionCount = " + expansionCount
724:                                    + " " + " fetchCount = " + fetchCount);
725:                        }
726:                    }
727:                    size = 0;
728:                }
729:
730:                private void add(OID value) {
731:                    //grow if nec.
732:                    if (size == len) {
733:                        if (len == 0) {
734:                            values = new OID[len = MIN_LEN];
735:                        } else {
736:                            len = len * 3 / 2 + 1;
737:                            OID[] a = new OID[len];
738:                            System.arraycopy(values, 0, a, 0, size);
739:                            values = a;
740:                            expansionCount++;
741:                        }
742:                    }
743:                    values[size++] = value;
744:                }
745:
746:                /**
747:                 * Trim values down to size elements.
748:                 */
749:                public void trim() {
750:                    if (values.length == size)
751:                        return;
752:                    OID[] a = new OID[size];
753:                    System.arraycopy(values, 0, a, 0, size);
754:                    values = a;
755:                }
756:            }
757:
758:            /**
759:             * Update statistics. This is not thread safe but it is not a
760:             * problem if the avgRowCount is a bit out sometimes.
761:             */
762:            private void updateStatistics(int size) {
763:                int fc = ++fetchCount;
764:                if (fc > WINDOW_SIZE) {
765:                    fc = WINDOW_SIZE;
766:                } else if (fc == 1) {
767:                    avgRowCount = size;
768:                } else if (fc < 0) {
769:                    fc = fetchCount = WINDOW_SIZE;
770:                } else {
771:                    avgRowCount = (avgRowCount * (fc - 1) + size) / fc;
772:                }
773:            }
774:
775:            /**
776:             * Get a SelectExp to select all the rows in this collection using the
777:             * supplied fetch group field to control joins and so on.
778:             */
779:            private SelectExp getSelectExp(FetchGroupField field,
780:                    JdbcStorageManager sm, FgDs[] fgDses) {
781:                SelectExp root = new SelectExp();
782:                root.table = elementJdbcClass.table;
783:                root.selectList = JdbcColumn.toSqlExp(root.table.pk, root);
784:
785:                if (field.jdbcUseJoin != JdbcField.USE_JOIN_NO) {
786:                    sm
787:                            .addSelectFetchGroup(
788:                                    root,
789:                                    field.nextFetchGroup,
790:                                    true,
791:                                    fgDses[0] = ((JdbcFetchGroup) field.nextFetchGroup.storeFetchGroup)
792:                                            .getFgDs(true, false), root,
793:                                    root.table.pk, this );
794:                }
795:
796:                // add ourPkColumns to the where clause list creating a new
797:                // join to the base table if necessary
798:                SelectExp se = root.findTable(ourPkColumns[0].table);
799:                if (se == null) {
800:                    se = new SelectExp();
801:                    se.table = ourPkColumns[0].table;
802:                    root.addJoin(root.table.pk, se.table.pk, se);
803:                }
804:
805:                // put the expression at the start of the where clause list
806:                root.whereExp = JdbcColumn.createEqualsParamExp(ourPkColumns,
807:                        se);
808:                if (((JdbcClass) fmd.elementTypeMetaData.storeClass).classIdCol != null) {
809:                    root.whereExp.next = ((JdbcClass) fmd.elementTypeMetaData.storeClass)
810:                            .getCheckClassIdExp(root);
811:                    AndExp andExp = new AndExp(root.whereExp);
812:                    root.whereExp = andExp;
813:                }
814:
815:                // add order by if ordering extension has been used
816:                if (fmd.ordering != null) {
817:                    root.addOrderBy(fmd.ordering, false);
818:                }
819:
820:                if (Debug.DEBUG) {
821:                    System.out
822:                            .println("%%% JdbcFKCollectionField.getSelectExp: "
823:                                    + fmd.getQName());
824:                    root.dump("  ");
825:                    System.out.println("%%%");
826:                }
827:
828:                return root;
829:            }
830:
831:            /**
832:             * Get a SelectExp to select all the rows in this collection using the
833:             * supplied fetch group field to control joins and so on.
834:             */
835:            public SelectExp getSelectExpFrom(JdbcStorageManager sm,
836:                    SelectExp joinToExp, FetchGroupField field, FgDs owningFgDs) {
837:                SelectExp root = new SelectExp();
838:                root.outer = true;
839:                root.table = elementJdbcClass.table;
840:                root.selectList = JdbcColumn.toSqlExp(ourPkColumns, root,
841:                        JdbcColumn.toSqlExp(root.table.pk, root));
842:
843:                if (field.jdbcUseJoin != JdbcField.USE_JOIN_NO) {
844:                    FgDs fgDs = ((JdbcFetchGroup) field.nextFetchGroup.storeFetchGroup)
845:                            .getFgDs(true, true);
846:                    sm.addSelectFetchGroup(root, field.nextFetchGroup, true,
847:                            fgDs, root, root.table.pk, this );
848:                    owningFgDs.valueJs = fgDs.getJoinStruct();
849:                }
850:
851:                // add order by if ordering extension has been used
852:                if (fmd.ordering != null) {
853:                    root.addOrderBy(fmd.ordering, false);
854:                }
855:
856:                if (Debug.DEBUG) {
857:                    System.out
858:                            .println("%%% JdbcFKCollectionField.getSelectExp: "
859:                                    + fmd.getQName());
860:                    root.dump("  ");
861:                    System.out.println("%%%");
862:                }
863:
864:                joinToExp.addJoin(joinToExp.table.pk, ourPkColumns, root);
865:                joinToExp.appendOrderByExp(root.orderByList);
866:                root.orderByList = null;
867:                return root;
868:            }
869:
870:            public SelectExp getSelectFilterExp(JdbcStorageManager sm,
871:                    FetchGroupField field, ColFieldHolder colFHolder) {
872:                SelectExp root = new SelectExp();
873:                root.table = elementJdbcClass.table;
874:                root.selectList = JdbcColumn.toSqlExp(root.table.pk, root);
875:
876:                root.whereExp = ((JdbcClass) fmd.elementTypeMetaData.storeClass)
877:                        .getCheckClassIdExp(root);
878:
879:                //         prepend our pk columns to the select list
880:                SqlExp e = JdbcColumn.toSqlExp(ourPkColumns, root,
881:                        root.selectList);
882:                root.selectList = e;
883:                root.appendOrderByForColumns(ourPkColumns);
884:
885:                if (field.jdbcUseJoin != JdbcField.USE_JOIN_NO) {
886:                    FgDs fgDs = ((JdbcFetchGroup) field.nextFetchGroup.storeFetchGroup)
887:                            .getFgDs(
888:                                    true,
889:                                    field.jdbcUseJoin == JdbcField.USE_JOIN_OUTER);
890:                    colFHolder.valueJs = fgDs.getJoinStruct();
891:                    sm.addSelectFetchGroup(root, field.nextFetchGroup, true,
892:                            fgDs, false);
893:                }
894:
895:                // add order by if ordering extension has been used
896:                if (fmd.ordering != null) {
897:                    root.addOrderBy(fmd.ordering, true);
898:                }
899:
900:                return root;
901:            }
902:
903:            public SelectExp getSelectFilterJoinExp(boolean value,
904:                    SelectExp lhSe, SelectExp rootSe, boolean addRootJoin) {
905:                SelectExp root = new SelectExp();
906:                root.table = elementJdbcClass.table;
907:                lhSe.addJoin(lhSe.table.pk, ourPkColumns, root);
908:                return root;
909:            }
910:
911:            /**
912:             * Convert this field into an isEmpty expression.
913:             */
914:            public SqlExp toIsEmptySqlExp(JdbcJDOQLCompiler comp, SelectExp root) {
915:                SelectExp se = new SelectExp();
916:                se.table = elementJdbcClass.table;
917:                se.jdbcField = this ;
918:                se.subSelectJoinExp = root.createJoinExp(root.table.pk,
919:                        ourPkColumns, se);
920:                // @todo what about empty/null checking?
921:                return new UnaryOpExp(new ExistsExp(se, true),
922:                        UnaryOpExp.OP_NOT);
923:            }
924:
925:            /**
926:             * Convert this field into a contains expression.
927:             */
928:            public SqlExp toContainsSqlExp(JdbcJDOQLCompiler comp,
929:                    SelectExp root, Node args) {
930:                if (args instanceof  VarNodeIF) {
931:                    VarNode v = ((VarNodeIF) args).getVarNode();
932:                    SelectExp vse = (SelectExp) v.getStoreExtent();
933:
934:                    //same table
935:                    if (vse.table == ourPkColumns[0].table) {
936:                        vse.subSelectJoinExp = root.createJoinExp(
937:                                root.table.pk, ourPkColumns, vse);
938:                    } else {
939:                        SelectExp se = new SelectExp();
940:                        se.table = ourPkColumns[0].table;
941:                        se.outer = vse.outer;
942:                        vse.addJoin(vse.table.pk, ourPkColumns[0].table.pk, se);
943:                    }
944:
945:                    if (v.getCmd() != fmd.elementTypeMetaData) {
946:                        //should be a subclass
947:                        vse.whereExp = SelectExp
948:                                .appendWithAnd(
949:                                        vse.whereExp,
950:                                        ((JdbcClass) fmd.elementTypeMetaData.storeClass)
951:                                                .getCheckClassIdExp(vse));
952:                    }
953:
954:                    return new ExistsExp(vse, true, v);
955:                } else {
956:                    SelectExp se = new SelectExp();
957:                    se.table = elementJdbcClass.table;
958:                    se.jdbcField = this ;
959:                    se.subSelectJoinExp = root.createJoinExp(root.table.pk,
960:                            ourPkColumns, se);
961:                    SqlExp left = JdbcColumn
962:                            .toSqlExp(se.table.pkSimpleCols, se);
963:                    for (SqlExp e = left; e != null; e = e.next) {
964:                        ((ColumnExp) e).cmd = fmd.elementTypeMetaData;
965:                    }
966:                    SqlExp right = comp.getVisitor().toSqlExp(args, root, left,
967:                            0, null);
968:                    if (left.next == null && right.next == null) {
969:                        BinaryOpExp ans = new BinaryOpExp(left,
970:                                BinaryOpExp.EQUAL, right);
971:                        if (right instanceof  ParamExp) {
972:                            ParamExp p = (ParamExp) right;
973:                            p.usage.expList = ans;
974:                            p.usage.expCount = 1;
975:                        }
976:                        se.whereExp = ans;
977:                    } else {
978:                        throw BindingSupportImpl.getInstance().internal(
979:                                "not implemented");
980:                    }
981:                    return new ExistsExp(se, false);
982:                }
983:            }
984:
985:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.