Source Code Cross Referenced for SqlStruct.java in  » Testing » PolePosition-0.20 » com » versant » core » jdbc » query » 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.query 
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.query;
012:
013:        import com.versant.core.util.CharBuf;
014:        import com.versant.core.common.Debug;
015:        import com.versant.core.common.OID;
016:        import com.versant.core.common.Utils;
017:        import com.versant.core.metadata.ModelMetaData;
018:        import com.versant.core.metadata.ClassMetaData;
019:        import com.versant.core.metadata.MDStaticUtils;
020:        import com.versant.core.jdbc.sql.SqlDriver;
021:        import com.versant.core.jdbc.metadata.JdbcColumn;
022:        import com.versant.core.jdbc.metadata.JdbcField;
023:        import com.versant.core.jdbc.metadata.JdbcClass;
024:        import com.versant.core.jdbc.JdbcUtils;
025:        import com.versant.core.jdbc.JdbcOID;
026:
027:        import java.io.Serializable;
028:        import java.sql.PreparedStatement;
029:        import java.sql.SQLException;
030:        import java.util.Collection;
031:        import java.util.Iterator;
032:
033:        import com.versant.core.common.BindingSupportImpl;
034:
035:        /**
036:         * A struct representing sql for a query.
037:         */
038:        public class SqlStruct {
039:
040:            private static final char[] COUNT_STAR_PRE = "COUNT(".toCharArray();
041:            private static final char[] COUNT_STAR_POST = ")".toCharArray();
042:            private static final char[] COUNT_STAR_PRE_DISTINCT = "COUNT(DISTINCT("
043:                    .toCharArray();
044:            private static final char[] COUNT_STAR_POST_DISTINCT = "))"
045:                    .toCharArray();
046:            private static final char[] IS_NULL = "is null".toCharArray();
047:            private static final char[] IS_NOT_NULL = "is not null"
048:                    .toCharArray();
049:
050:            public String jdoqlFilter;
051:
052:            /**
053:             * The SQL to execute the query. It is kept in a CharBuf as
054:             * it may need to be modified before each execution of the query depending
055:             * on which parameters are null.
056:             */
057:            private CharBuf sqlbuf;
058:            /**
059:             * Is the query a 'select distinct'?
060:             */
061:            private boolean distinct;
062:            /**
063:             * Index of the first character in the select list.
064:             */
065:            private int selectListStartIndex;
066:            /**
067:             * Number of characters in the select list.
068:             */
069:            private int selectListLength;
070:            /**
071:             * Index of the first column in the select list.
072:             */
073:            private int selectFirstColStart;
074:            /**
075:             * Index of the first column in the select list.
076:             */
077:            private int selectFirstColLength;
078:            /**
079:             * Index of the start of the 'order by ..' clause or 0 if none.
080:             */
081:            private int orderByStartIndex;
082:            /**
083:             * Number of characters in the 'order by ..' clause.
084:             */
085:            private int orderByLength;
086:            /**
087:             * The first table or alias in the from clause for the query. This is
088:             * required for some databases if the query needs to be converted into a
089:             * 'select for update' query (e.g. postgres).
090:             */
091:            private String firstTableOrAlias;
092:            /**
093:             * The sql is cached here in string form.
094:             */
095:            private transient String sql;
096:            /**
097:             * Is the current sqlbuf 'select for update'?
098:             */
099:            private boolean sqlForUpdate;
100:            /**
101:             * What was the original size of the sqlbuf before any modifications for
102:             * 'select for update'?
103:             */
104:            private int sqlbufNotForUpdateSize;
105:            /**
106:             * Is the current sqlbuf 'select count(*)'?
107:             */
108:            private boolean sqlForCount;
109:            /**
110:             * Store for the select list when query is converted to count(*).
111:             */
112:            private char[] originalSelectList;
113:            /**
114:             * Store for the first column of the select list when query is converted to
115:             * count(*).
116:             */
117:            private char[] originalSelectListFirstColumn;
118:            /**
119:             * Store for the order by clause when query is converted to count(*).
120:             */
121:            private char[] originalOrderByClause;
122:            /**
123:             * Params in the order that they appear in the SQL string. Each declared
124:             * parameter may have several entries in this array if it was used more
125:             * than once in the original query.
126:             */
127:            private Param paramList;
128:            /**
129:             * Characters used to convert a param into 'is null'.
130:             */
131:            private char[] isNullChars;
132:            /**
133:             * Characters used to convert a param into 'is not null'.
134:             */
135:            private char[] isNotNullChars;
136:            /**
137:             * Is this an aggregate query.
138:             */
139:            private boolean aggregate;
140:
141:            public SqlStruct() {
142:                sqlbuf = new CharBuf(256);
143:            }
144:
145:            public synchronized SqlStruct getClone() {
146:                SqlStruct clone = new SqlStruct();
147:                clone.jdoqlFilter = jdoqlFilter;
148:                clone.sqlbuf = new CharBuf(sqlbuf);
149:                clone.distinct = distinct;
150:                clone.selectListStartIndex = selectListStartIndex;
151:                clone.selectListLength = selectListLength;
152:                clone.orderByStartIndex = orderByStartIndex;
153:                clone.orderByLength = orderByLength;
154:                clone.firstTableOrAlias = firstTableOrAlias;
155:                clone.sql = sql;
156:                clone.sqlForUpdate = sqlForUpdate;
157:                clone.sqlbufNotForUpdateSize = sqlbufNotForUpdateSize;
158:                clone.sqlForCount = sqlForCount;
159:                clone.originalSelectList = originalSelectList;
160:                clone.originalOrderByClause = originalOrderByClause;
161:                clone.paramList = (paramList == null ? null : paramList
162:                        .getClone());
163:
164:                if (isNullChars != null) {
165:                    clone.isNullChars = new char[isNullChars.length];
166:                    for (int i = 0; i < isNullChars.length; i++) {
167:                        clone.isNullChars[i] = isNullChars[i];
168:                    }
169:                }
170:
171:                if (isNotNullChars != null) {
172:                    clone.isNotNullChars = new char[isNotNullChars.length];
173:                    for (int i = 0; i < isNotNullChars.length; i++) {
174:                        clone.isNotNullChars[i] = isNotNullChars[i];
175:                    }
176:                }
177:                return clone;
178:            }
179:
180:            public boolean isAggregate() {
181:                return aggregate;
182:            }
183:
184:            public void setAggregate(boolean aggregate) {
185:                this .aggregate = aggregate;
186:            }
187:
188:            /**
189:             * Set the range of characters in our buffer that contain all the columns
190:             * in the select list.
191:             * @param start Index of the first character in the select list (after
192:             *          'SELECT ' or 'SELECT DISTINCT ')
193:             * @param firstColEnd Index of the last character in the first column + 1
194:             * @param end Index of the last character in the list + 1
195:             */
196:            public void setSelectListRange(boolean distinct, int start,
197:                    int firstColEnd, int end) {
198:                this .distinct = distinct;
199:                if (distinct) {
200:                    selectListStartIndex = start - 9; // "DISTINCT ".length()
201:                } else {
202:                    selectListStartIndex = start;
203:                }
204:                selectFirstColStart = start;
205:                selectListLength = end - selectListStartIndex;
206:                selectFirstColLength = firstColEnd - selectFirstColStart;
207:            }
208:
209:            /**
210:             * Set the range of characters in our buffer that contain order by clause
211:             * including the 'order by' keywords. The end index is exclusive.
212:             */
213:            public void setOrderByRange(int start, int end) {
214:                orderByStartIndex = start;
215:                orderByLength = end - start;
216:            }
217:
218:            public CharBuf getSqlbuf() {
219:                return sqlbuf;
220:            }
221:
222:            public boolean isDistinct() {
223:                return distinct;
224:            }
225:
226:            public String getFirstTableOrAlias() {
227:                return firstTableOrAlias;
228:            }
229:
230:            public void setFirstTableOrAlias(String firstTableOrAlias) {
231:                this .firstTableOrAlias = firstTableOrAlias;
232:            }
233:
234:            public String getSql() {
235:                if (sql == null)
236:                    sql = sqlbuf.toString();
237:                return sql;
238:            }
239:
240:            public boolean isSqlForUpdate() {
241:                return sqlForUpdate;
242:            }
243:
244:            public int getSqlbufNotForUpdateSize() {
245:                return sqlbufNotForUpdateSize;
246:            }
247:
248:            public boolean isSqlForCount() {
249:                return sqlForCount;
250:            }
251:
252:            public char[] getOriginalSelectList() {
253:                return originalSelectList;
254:            }
255:
256:            public char[] getOriginalOrderByClause() {
257:                return originalOrderByClause;
258:            }
259:
260:            public Param getParamList() {
261:                return paramList;
262:            }
263:
264:            public void setParamList(Param paramList) {
265:                this .paramList = paramList;
266:                if (paramList != null)
267:                    analyzeCharSpans();
268:            }
269:
270:            private void analyzeCharSpans() {
271:                int max = IS_NOT_NULL.length;
272:                for (Param p = paramList; p != null; p = p.next) {
273:                    for (CharSpan s = p.charSpanList; s != null; s = s.next) {
274:                        if (s.type == CharSpan.TYPE_REMOVE)
275:                            continue;
276:                        int len = s.lastCharIndex - s.firstCharIndex;
277:                        if (len > max)
278:                            max = len;
279:                    }
280:                }
281:                if (max > 0) {
282:                    isNullChars = new char[max];
283:                    copyAndPad(IS_NULL, isNullChars, max);
284:                    isNotNullChars = new char[max];
285:                    copyAndPad(IS_NOT_NULL, isNotNullChars, max);
286:                }
287:            }
288:
289:            /**
290:             * This must create space in the charBuf at the index.
291:             */
292:            public void createSpace(CharBuf charBuf, int index, int amount) {
293:                sql = null;
294:                for (SqlStruct.Param p = paramList; p != null; p = p.next) {
295:                    if (p.firstCharIndex > index) {
296:                        //must update
297:                        p.firstCharIndex += amount;
298:                        for (CharSpan cs = p.charSpanList; cs != null; cs = cs.next) {
299:                            cs.firstCharIndex += amount;
300:                            cs.lastCharIndex += amount;
301:                        }
302:                    }
303:                }
304:
305:                if (orderByStartIndex > index) {
306:                    orderByStartIndex += amount;
307:                }
308:            }
309:
310:            /**
311:             * This must create space in the charBuf at the index.
312:             */
313:            public void removeSpace(CharBuf charBuf, int index, int amount) {
314:                sql = null;
315:                for (SqlStruct.Param p = paramList; p != null; p = p.next) {
316:                    if (p.firstCharIndex > index) {
317:                        //must update
318:                        p.firstCharIndex -= amount;
319:                        for (CharSpan cs = p.charSpanList; cs != null; cs = cs.next) {
320:                            cs.firstCharIndex -= amount;
321:                            cs.lastCharIndex -= amount;
322:                        }
323:                    }
324:                }
325:
326:                if (orderByStartIndex > index) {
327:                    orderByStartIndex -= amount;
328:                }
329:            }
330:
331:            /**
332:             * Update all our Param's for the null/not null state of their parameters
333:             * and for 'select for update' or not. This may change the SQL query
334:             * string.
335:             */
336:            public synchronized void updateSql(SqlDriver driver,
337:                    Object[] params, boolean forUpdate, boolean forCount) {
338:                boolean changed = false;
339:                if (params != null) {
340:                    int paramIndex = 0;
341:                    for (SqlStruct.Param p = paramList; p != null; p = p.next, paramIndex++) {
342:                        if (params[p.declaredParamIndex] instanceof  Collection) {
343:                            Collection col = (Collection) params[p.declaredParamIndex];
344:                            int n = col.size();
345:                            if (n == 0) {
346:                                throw BindingSupportImpl.getInstance()
347:                                        .invalidOperation(
348:                                                "The supplied collection param at index "
349:                                                        + paramIndex
350:                                                        + " may not be empty");
351:                            }
352:                            if (p.inListParamCount == 0) {
353:                                //this is a readOnly char[]. it may not be modified
354:                                final char[] charsToInsert = driver
355:                                        .getSqlParamStringChars(p.jdbcType);
356:                                int toInsert = (n == 1 ? charsToInsert.length
357:                                        : (n * charsToInsert.length) + (n - 1));
358:                                char[] chars = new char[toInsert];
359:
360:                                int offset = 0;
361:                                for (int i = 0; i < n; i++) {
362:                                    if (offset > 0) {
363:                                        chars[offset++] = ',';
364:                                    }
365:                                    for (int j = 0; j < charsToInsert.length; j++) {
366:                                        chars[j + offset] = charsToInsert[j];
367:                                    }
368:                                    offset += charsToInsert.length;
369:                                }
370:                                createSpace(sqlbuf, p.firstCharIndex, toInsert);
371:                                sqlbuf.insert(p.firstCharIndex, chars);
372:                                p.charLength = chars.length;
373:                                p.inListParamCount = n;
374:                                changed = true;
375:                            } else if (p.inListParamCount < n) {
376:                                //must insert more param's
377:                                int insertPoint = p.charLength
378:                                        + p.firstCharIndex;
379:                                //the diff between the required number and what is already there
380:                                int paramsToInsert = n - p.inListParamCount;
381:                                final char[] charStamp = driver
382:                                        .getSqlParamStringChars(p.jdbcType);
383:                                int charsToInsert = (charStamp.length * paramsToInsert)
384:                                        + paramsToInsert;
385:                                char[] chars = new char[charsToInsert];
386:                                int offset = 0;
387:                                for (int i = 0; i < paramsToInsert; i++) {
388:                                    chars[offset++] = ',';
389:                                    for (int j = 0; j < charStamp.length; j++) {
390:                                        chars[offset++] = charStamp[j];
391:                                    }
392:                                }
393:                                if (Debug.DEBUG) {
394:                                    if (offset != chars.length) {
395:                                        throw BindingSupportImpl.getInstance()
396:                                                .internal("");
397:                                    }
398:                                }
399:                                createSpace(sqlbuf, insertPoint, charsToInsert);
400:                                sqlbuf.insert(insertPoint, chars);
401:                                p.charLength += chars.length;
402:                                p.inListParamCount = n;
403:                                changed = true;
404:                            } else if (p.inListParamCount > n) {
405:                                //must remove some
406:                                changed = true;
407:                                int removeStart = p.firstCharIndex;
408:                                int paramToRemove = p.inListParamCount - n;
409:
410:                                int charsToRemove = driver
411:                                        .getSqlParamStringChars(p.jdbcType).length
412:                                        * paramToRemove + paramToRemove;
413:                                int removeTo = charsToRemove + removeStart;
414:                                sqlbuf.remove(removeStart, removeTo);
415:                                removeSpace(sqlbuf, p.firstCharIndex, removeTo
416:                                        - removeStart);
417:
418:                                p.charLength -= (removeTo - removeStart);
419:                                p.inListParamCount = n;
420:                                changed = true;
421:                            }
422:
423:                        }
424:                    }
425:                }
426:
427:                if (params != null) {
428:                    for (SqlStruct.Param p = paramList; p != null; p = p.next) {
429:                        if (p
430:                                .update(this ,
431:                                        params[p.declaredParamIndex] == null)) {
432:                            changed = true;
433:                        }
434:                    }
435:                }
436:                if (forUpdate != sqlForUpdate
437:                        && (!distinct || driver
438:                                .isSelectForUpdateWithDistinctOk())
439:                        && (!aggregate || driver
440:                                .isSelectForUpdateWithAggregateOk())) {
441:                    char[] a = driver.getSelectForUpdate();
442:                    if (a != null) {
443:                        if (forUpdate) {
444:                            sqlbufNotForUpdateSize = sqlbuf.size();
445:                            sqlbuf.append(a);
446:                            if (driver.isSelectForUpdateAppendTable()) {
447:                                sqlbuf.append(firstTableOrAlias);
448:                            }
449:                        } else {
450:                            sqlbuf.setSize(sqlbufNotForUpdateSize);
451:                        }
452:                        sqlForUpdate = forUpdate;
453:                        changed = true;
454:                    }
455:                }
456:                if (forCount != sqlForCount) {
457:                    if (forCount) {
458:                        if (originalSelectList == null) {
459:                            originalSelectList = sqlbuf.toArray(
460:                                    selectListStartIndex, selectListLength);
461:                            originalSelectListFirstColumn = sqlbuf.toArray(
462:                                    selectFirstColStart, selectFirstColLength);
463:                        }
464:                        int start;
465:                        if (distinct) {
466:                            sqlbuf.replace(selectListStartIndex,
467:                                    COUNT_STAR_PRE_DISTINCT);
468:                            start = selectListStartIndex
469:                                    + COUNT_STAR_PRE_DISTINCT.length;
470:                        } else {
471:                            sqlbuf
472:                                    .replace(selectListStartIndex,
473:                                            COUNT_STAR_PRE);
474:                            start = selectListStartIndex
475:                                    + COUNT_STAR_PRE.length;
476:                        }
477:                        sqlbuf.replace(start, originalSelectListFirstColumn);
478:                        start += originalSelectListFirstColumn.length;
479:                        if (distinct) {
480:                            sqlbuf.replace(start, COUNT_STAR_POST_DISTINCT);
481:                            start += COUNT_STAR_POST_DISTINCT.length;
482:                        } else {
483:                            sqlbuf.replace(start, COUNT_STAR_POST);
484:                            start += COUNT_STAR_POST.length;
485:                        }
486:                        int n = (selectListStartIndex + selectListLength)
487:                                - start;
488:                        if (n > 0)
489:                            sqlbuf.replace(start, start + n, ' ');
490:                        if (orderByStartIndex > 0) {
491:                            if (originalOrderByClause == null) {
492:                                originalOrderByClause = sqlbuf.toArray(
493:                                        orderByStartIndex, orderByLength);
494:                            }
495:                            sqlbuf.replace(orderByStartIndex, orderByStartIndex
496:                                    + orderByLength, ' ');
497:                        }
498:                    } else {
499:                        sqlbuf
500:                                .replace(selectListStartIndex,
501:                                        originalSelectList);
502:                        if (orderByStartIndex > 0) {
503:                            sqlbuf.replace(orderByStartIndex,
504:                                    originalOrderByClause);
505:                        }
506:                    }
507:                    sqlForCount = forCount;
508:                    changed = true;
509:                }
510:
511:                if (changed)
512:                    sql = null;
513:            }
514:
515:            /**
516:             * Set all the parameters for this query on ps. This is a NOP if params
517:             * is null.
518:             */
519:            public synchronized void setParamsOnPS(ModelMetaData jmd,
520:                    SqlDriver driver, PreparedStatement ps, Object[] params,
521:                    String sql) throws SQLException {
522:                if (params == null)
523:                    return;
524:                int pos = 1;
525:                SqlStruct.Param p = paramList;
526:                Object value = null;
527:                try {
528:                    for (; p != null; p = p.next) {
529:                        value = params[p.declaredParamIndex];
530:                        switch (p.mod) {
531:                        case Param.MOD_NONE:
532:                            break;
533:                        case Param.MOD_APPEND_PERCENT:
534:                            if (value != null)
535:                                value = value + "%";
536:                            break;
537:                        case Param.MOD_PREPEND_PERCENT:
538:                            if (value != null)
539:                                value = "%" + value;
540:                            break;
541:                        default:
542:                            throw BindingSupportImpl.getInstance().internal(
543:                                    "Invalid mod: " + p.mod);
544:                        }
545:                        if (value == null && p.requiresUpdate())
546:                            continue;
547:                        int pci = p.classIndex;
548:                        if (pci >= 0) {
549:                            ClassMetaData pcmd = jmd.classes[pci];
550:                            int pfno = p.fieldNo;
551:                            if (pfno >= 0) {
552:                                JdbcField f = ((JdbcClass) pcmd.storeClass).stateFields[pfno];
553:                                if (value instanceof  Collection) {
554:                                    Collection col = (Collection) value;
555:                                    for (Iterator iterator = col.iterator(); iterator
556:                                            .hasNext();) {
557:                                        Object o = iterator.next();
558:                                        if (o instanceof  OID) {
559:                                            pos = ((JdbcOID) o).setParams(ps,
560:                                                    pos);
561:                                        } else {
562:                                            pos = f.setQueryParam(ps, pos, o);
563:                                        }
564:                                    }
565:                                } else {
566:                                    pos = f.setQueryParam(ps, pos, value);
567:                                }
568:                            } else { // this is an OID param for a link table
569:                                if (value != null) {
570:                                    pos = ((JdbcOID) value).setParams(ps, pos);
571:                                } else {
572:                                    JdbcColumn[] pkcols = ((JdbcClass) pcmd.storeClass).table.pkSimpleCols;
573:                                    int nc = pkcols.length;
574:                                    for (int i = 0; i < nc; i++) {
575:                                        ps.setNull(pos++, pkcols[i].jdbcType);
576:                                    }
577:                                }
578:                            }
579:                        } else {
580:                            if (p.col != null) {
581:                                p.col.set(ps, pos++, value);
582:                            } else {
583:                                int javaTypeCode = p.javaTypeCode;
584:                                if (javaTypeCode == 0 && value != null) {
585:                                    javaTypeCode = MDStaticUtils
586:                                            .toTypeCode(value.getClass());
587:                                }
588:                                JdbcUtils.set(ps, pos++, value, javaTypeCode,
589:                                        p.jdbcType);
590:                            }
591:                        }
592:                    }
593:                } catch (Exception e) {
594:                    throw driver.mapException(e,
595:                            "Error setting query parameter "
596:                                    + p.getIdentifier()
597:                                    + " = '"
598:                                    + Utils.toString(value)
599:                                    + "' at PreparedStatement index "
600:                                    + pos
601:                                    + " in\n"
602:                                    + JdbcUtils.getPreparedStatementInfo(sql,
603:                                            ps) + "\n" + JdbcUtils.toString(e),
604:                            false);
605:                }
606:            }
607:
608:            private static void copyAndPad(char[] src, char[] dest, int len) {
609:                int n = src.length;
610:                System.arraycopy(src, 0, dest, 0, n);
611:                for (; n < len;)
612:                    dest[n++] = ' ';
613:            }
614:
615:            public char[] getNullChars() {
616:                return isNullChars;
617:            }
618:
619:            public void setNullChars(char[] nullChars) {
620:                isNullChars = nullChars;
621:            }
622:
623:            public char[] getNotNullChars() {
624:                return isNotNullChars;
625:            }
626:
627:            public void setNotNullChars(char[] notNullChars) {
628:                isNotNullChars = notNullChars;
629:            }
630:
631:            /**
632:             * A parameter. This tells us the indexes of the first and last characters
633:             * of this parameter and its index within the original list of declared
634:             * parameters.
635:             */
636:            public final static class Param implements  Serializable {
637:
638:                public static final int MOD_NONE = 0;
639:                public static final int MOD_PREPEND_PERCENT = 1;
640:                public static final int MOD_APPEND_PERCENT = 2;
641:
642:                /**
643:                 * An identifier for this parameter for error messages.
644:                 */
645:                private String identifier;
646:                /**
647:                 * The next Param in the list.
648:                 */
649:                public Param next;
650:                /**
651:                 * The index of this parameter in the original list of declared
652:                 * parameters for the query.
653:                 */
654:                public int declaredParamIndex;
655:                /**
656:                 * The index of the first character in sql for this Param.
657:                 * If charSpanList is not null then this is the same as there. It
658:                 * is used for sorting.
659:                 */
660:                public transient int firstCharIndex;
661:                /**
662:                 * The current amount of chars that the param occupies when used a in list
663:                 * for collection params
664:                 */
665:                public transient int charLength;
666:                /**
667:                 * The current amount params that this param can take is used as a collection
668:                 * param.
669:                 */
670:                public transient int inListParamCount;
671:                /**
672:                 * List of character ranges used by this Param. This info is used
673:                 * to turn '= ?' into 'is null' and so on. It is null if there is
674:                 * no need for any replacement (e.g. using Sybase).
675:                 */
676:                public CharSpan charSpanList;
677:                /**
678:                 * The classIndex of the class associated with this parameter or
679:                 * -1 if there is none (e.g. a parameter used in an expression).
680:                 * @see #fieldNo
681:                 */
682:                public int classIndex;
683:                /**
684:                 * The field number associated with this parameter or -1 if none.
685:                 * This is used with cls to locate its column(s). It is not used if
686:                 * the classIndex is -1.
687:                 * @see #classIndex
688:                 */
689:                public int fieldNo;
690:                /**
691:                 * The java type code of this parameter. This is only set if
692:                 * classIndex is -1 i.e. this parameter is not for a field.
693:                 */
694:                public int javaTypeCode;
695:                /**
696:                 * The JDBC type (from java.sql.Types) for this parameter. This is
697:                 * only set if classIndex is -1.
698:                 * @see java.sql.Types
699:                 */
700:                public int jdbcType;
701:                /**
702:                 * How must the parameter value be modified before being set? This is
703:                 * used for startsWith and endsWith for databases that do not allow
704:                 * expressions on the right hand side of a LIKE (e.g. Informix).
705:                 * @see #MOD_APPEND_PERCENT
706:                 */
707:                public int mod;
708:
709:                public transient JdbcColumn col;
710:
711:                public Param(String identifier) {
712:                    this .identifier = identifier;
713:                }
714:
715:                public String getIdentifier() {
716:                    return identifier;
717:                }
718:
719:                /**
720:                 * Update all our CharSpan's for the null/not null state of the
721:                 * parameter. This is a NOP if the parameter does not require update.
722:                 * @return True if changes were made else false
723:                 * @see #requiresUpdate
724:                 */
725:                public boolean update(SqlStruct q, boolean newParamIsNull) {
726:                    boolean ans = false;
727:                    for (CharSpan cs = charSpanList; cs != null; cs = cs.next) {
728:                        if (cs.update(q, newParamIsNull))
729:                            ans = true;
730:                    }
731:                    return ans;
732:                }
733:
734:                /**
735:                 * Does this need to be updated for null/not null parameter values?
736:                 * @see #update
737:                 */
738:                public boolean requiresUpdate() {
739:                    return charSpanList != null;
740:                }
741:
742:                public Param getClone() {
743:                    Param clone = new Param(identifier);
744:                    clone.next = (next == null ? null : next.getClone());
745:                    clone.declaredParamIndex = declaredParamIndex;
746:                    clone.firstCharIndex = firstCharIndex;
747:                    clone.charSpanList = (charSpanList == null ? null
748:                            : charSpanList.getClone());
749:                    clone.classIndex = classIndex;
750:                    clone.fieldNo = fieldNo;
751:                    clone.javaTypeCode = javaTypeCode;
752:                    clone.jdbcType = jdbcType;
753:                    clone.mod = mod;
754:                    clone.col = col;
755:
756:                    return clone;
757:                }
758:            }
759:
760:            /**
761:             * This specifies a range of characters for a Param in our sql buffer. The
762:             * lastCharIndex is the index of the character after the last character
763:             * in the range.
764:             */
765:            public final static class CharSpan implements  Serializable {
766:
767:                public static final int TYPE_NULL = 1;
768:                public static final int TYPE_NOT_NULL = 2;
769:                public static final int TYPE_REMOVE = 3;
770:
771:                /**
772:                 * What must be done to this span?
773:                 */
774:                public int type;
775:                /**
776:                 * The index of the first character in sql.
777:                 */
778:                public int firstCharIndex;
779:                /**
780:                 * The index of the character after the last character in the span.
781:                 */
782:                public int lastCharIndex;
783:                /**
784:                 * The next span in the list.
785:                 */
786:                public CharSpan next;
787:
788:                /**
789:                 * The current state of the parameter in sql. If this is true then
790:                 * the parameter has been replaced with an 'is null' or 'is not null'.
791:                 */
792:                private boolean paramIsNull;
793:                /**
794:                 * The original text from the sql query. This is filled the first
795:                 * time the param is null and is used to restore the query when it
796:                 * is not null in future.
797:                 */
798:                private char[] originalSql;
799:
800:                public CharSpan getClone() {
801:                    CharSpan clone = new CharSpan();
802:                    clone.type = type;
803:                    clone.firstCharIndex = firstCharIndex;
804:                    clone.lastCharIndex = lastCharIndex;
805:                    clone.next = (next == null ? null : next.getClone());
806:                    clone.paramIsNull = paramIsNull;
807:                    if (originalSql != null) {
808:                        clone.originalSql = new char[originalSql.length];
809:                        for (int i = 0; i < originalSql.length; i++) {
810:                            clone.originalSql[i] = originalSql[i];
811:                        }
812:                    }
813:                    return clone;
814:                }
815:
816:                /**
817:                 * Update the query and our state if the newParamIsNull value differs
818:                 * from our paramIsNull field.
819:                 * @return True if changes were made else false
820:                 */
821:                public boolean update(SqlStruct q, boolean newParamIsNull) {
822:                    if (newParamIsNull == paramIsNull)
823:                        return false;
824:                    CharBuf sql = q.sqlbuf;
825:                    if (newParamIsNull) {
826:                        if (originalSql == null) {
827:                            originalSql = sql.toArray(firstCharIndex,
828:                                    lastCharIndex - firstCharIndex);
829:                        }
830:                        if (Debug.DEBUG) {
831:                            System.out
832:                                    .println("*** CharSpan.update replacing '"
833:                                            + new String(originalSql) + "' "
834:                                            + originalSql.length + " "
835:                                            + q.isNullChars.length);
836:                        }
837:                        switch (type) {
838:                        case TYPE_NULL:
839:                            sql.replace(firstCharIndex, q.isNullChars);
840:                            break;
841:                        case TYPE_NOT_NULL:
842:                            sql.replace(firstCharIndex, q.isNotNullChars);
843:                            break;
844:                        case TYPE_REMOVE:
845:                            sql.replace(firstCharIndex, lastCharIndex, ' ');
846:                            break;
847:                        default:
848:                            throw BindingSupportImpl.getInstance().internal(
849:                                    "Unknown CharSpan type: " + type);
850:                        }
851:                    } else {
852:                        sql.replace(firstCharIndex, originalSql);
853:                    }
854:                    paramIsNull = newParamIsNull;
855:                    return true;
856:                }
857:            }
858:
859:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.