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