Source Code Cross Referenced for Column.java in  » Database-DBMS » hsql » org » hsqldb » 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 » Database DBMS » hsql » org.hsqldb 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /* Copyright (c) 1995-2000, The Hypersonic SQL Group.
0002:         * All rights reserved.
0003:         *
0004:         * Redistribution and use in source and binary forms, with or without
0005:         * modification, are permitted provided that the following conditions are met:
0006:         *
0007:         * Redistributions of source code must retain the above copyright notice, this
0008:         * list of conditions and the following disclaimer.
0009:         *
0010:         * Redistributions in binary form must reproduce the above copyright notice,
0011:         * this list of conditions and the following disclaimer in the documentation
0012:         * and/or other materials provided with the distribution.
0013:         *
0014:         * Neither the name of the Hypersonic SQL Group nor the names of its
0015:         * contributors may be used to endorse or promote products derived from this
0016:         * software without specific prior written permission.
0017:         *
0018:         * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0019:         * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0020:         * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0021:         * ARE DISCLAIMED. IN NO EVENT SHALL THE HYPERSONIC SQL GROUP,
0022:         * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
0023:         * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
0024:         * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
0025:         * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0026:         * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0027:         * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
0028:         * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0029:         *
0030:         * This software consists of voluntary contributions made by many individuals 
0031:         * on behalf of the Hypersonic SQL Group.
0032:         *
0033:         *
0034:         * For work added by the HSQL Development Group:
0035:         *
0036:         * Copyright (c) 2001-2005, The HSQL Development Group
0037:         * All rights reserved.
0038:         *
0039:         * Redistribution and use in source and binary forms, with or without
0040:         * modification, are permitted provided that the following conditions are met:
0041:         *
0042:         * Redistributions of source code must retain the above copyright notice, this
0043:         * list of conditions and the following disclaimer.
0044:         *
0045:         * Redistributions in binary form must reproduce the above copyright notice,
0046:         * this list of conditions and the following disclaimer in the documentation
0047:         * and/or other materials provided with the distribution.
0048:         *
0049:         * Neither the name of the HSQL Development Group nor the names of its
0050:         * contributors may be used to endorse or promote products derived from this
0051:         * software without specific prior written permission.
0052:         *
0053:         * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0054:         * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0055:         * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0056:         * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
0057:         * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
0058:         * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
0059:         * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
0060:         * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0061:         * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0062:         * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
0063:         * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0064:         */
0065:
0066:        package org.hsqldb;
0067:
0068:        import java.io.IOException;
0069:        import java.io.Serializable;
0070:        import java.math.BigDecimal;
0071:        import java.math.BigInteger;
0072:        import java.sql.Date;
0073:        import java.sql.Time;
0074:        import java.sql.Timestamp;
0075:
0076:        import org.hsqldb.HsqlNameManager.HsqlName;
0077:        import org.hsqldb.lib.StringConverter;
0078:        import org.hsqldb.store.ValuePool;
0079:        import org.hsqldb.types.Binary;
0080:        import org.hsqldb.types.JavaObject;
0081:        import org.hsqldb.lib.java.JavaSystem;
0082:
0083:        // fredt@users 20020130 - patch 491987 by jimbag@users
0084:        // fredt@users 20020320 - doc 1.7.0 - update
0085:        // fredt@users 20020401 - patch 442993 by fredt - arithmetic expressions
0086:        // to allow mixed type arithmetic expressions beginning with a narrower type
0087:        // changes applied to several lines of code and not marked separately
0088:        // consists of changes to arithmatic functions to allow promotion of
0089:        // java.lang.Number values and new functions to choose type for promotion
0090:        // fredt@users 20020401 - patch 455757 by galena@users (Michiel de Roo)
0091:        // interpretation of TINYINT as Byte instead of Short
0092:        // fredt@users 20020130 - patch 491987 by jimbag@users
0093:        // support for sql standard char and varchar. size is maintained as
0094:        // defined in the DDL and trimming and padding takes place accordingly
0095:        // modified by fredt - trimming and padding are turned off by default but
0096:        // can be applied accross the database by defining sql.enforce_size=true in
0097:        // database.properties file
0098:        // fredt@users 20020215 - patch 1.7.0 by fredt - quoted identifiers
0099:        // applied to different parts to support the sql standard for
0100:        // naming of columns and tables (use of quoted identifiers as names)
0101:        // fredt@users 20020328 - patch 1.7.0 by fredt - change REAL to Double
0102:        // fredt@users 20020402 - patch 1.7.0 by fredt - type conversions
0103:        // frequently used type conversions are done without creating temporary
0104:        // Strings to reduce execution time and garbage collection
0105:        // fredt@users 20021013 - patch 1.7.1 by fredt - type conversions
0106:        // scripting of Double.Nan and infinity values
0107:        // fredt@users 20030715 - patch 1.7.2 - type narrowing for numeric values
0108:        // fredt@users - patch 1.8.0 - enforcement of precision and scale
0109:
0110:        /**
0111:         *  Implementation of SQL table columns as defined in DDL statements with
0112:         *  static methods to process their values.<p>
0113:         *
0114:         *  Enhanced type checking and conversion by fredt@users
0115:         *
0116:         * @author Thomas Mueller (Hypersonic SQL Group)
0117:         * @author fredt@users
0118:         * @version    1.8.0
0119:         * @since Hypersonic SQL
0120:         */
0121:        public class Column {
0122:
0123:            // --------------------------------------------------
0124:            // DDL name, size, scale, null, identity and default values
0125:            // most variables are final but not declared so because of a bug in
0126:            // JDK 1.1.8 compiler
0127:            public HsqlName columnName;
0128:            private int colType;
0129:            private int colSize;
0130:            private int colScale;
0131:            private boolean isNullable;
0132:            private boolean isIdentity;
0133:            private boolean isPrimaryKey;
0134:            private Expression defaultExpression;
0135:            long identityStart;
0136:            long identityIncrement;
0137:            static final BigInteger MAX_LONG = BigInteger
0138:                    .valueOf(Long.MAX_VALUE);
0139:            static final BigInteger MIN_LONG = BigInteger
0140:                    .valueOf(Long.MIN_VALUE);
0141:            static final BigInteger MAX_INT = BigInteger
0142:                    .valueOf(Integer.MAX_VALUE);
0143:            static final BigInteger MIN_INT = BigInteger
0144:                    .valueOf(Integer.MIN_VALUE);
0145:            static final BigDecimal BIG_DECIMAL_0 = new BigDecimal(0.0);
0146:            static final BigDecimal BIG_DECIMAL_1 = new BigDecimal(1.0);
0147:
0148:            /**
0149:             *  Creates a column defined in DDL statement.
0150:             *
0151:             * @param  name
0152:             * @param  nullable
0153:             * @param  type
0154:             * @param  size
0155:             * @param  scale
0156:             * @param  identity
0157:             * @param  startvalue
0158:             * @param  increment
0159:             * @param  primarykey
0160:             * @param  defstring
0161:             */
0162:            Column(HsqlName name, boolean nullable, int type, int size,
0163:                    int scale, boolean primarykey, Expression defexpression)
0164:                    throws HsqlException {
0165:
0166:                columnName = name;
0167:                isNullable = nullable;
0168:                colType = type;
0169:                colSize = size;
0170:                colScale = scale;
0171:                isPrimaryKey = primarykey;
0172:                defaultExpression = defexpression;
0173:            }
0174:
0175:            void setIdentity(boolean identity, long startvalue, long increment)
0176:                    throws HsqlException {
0177:
0178:                isIdentity = identity;
0179:                identityStart = startvalue;
0180:                identityIncrement = increment;
0181:
0182:                if (isIdentity) {
0183:                    if (colType == Types.INTEGER) {
0184:                        if (identityStart > Integer.MAX_VALUE
0185:                                || identityIncrement > Integer.MAX_VALUE) {
0186:                            throw Trace.error(Trace.NUMERIC_VALUE_OUT_OF_RANGE,
0187:                                    columnName.statementName);
0188:                        }
0189:                    }
0190:                }
0191:            }
0192:
0193:            private Column() {
0194:            }
0195:
0196:            /**
0197:             * Used for primary key changes.
0198:             */
0199:            Column duplicate(boolean withIdentity) throws HsqlException {
0200:
0201:                Column newCol = new Column();
0202:
0203:                newCol.columnName = columnName;
0204:                newCol.isNullable = isNullable;
0205:                newCol.colType = colType;
0206:                newCol.colSize = colSize;
0207:                newCol.colScale = colScale;
0208:                newCol.defaultExpression = defaultExpression;
0209:
0210:                if (withIdentity) {
0211:                    newCol.setIdentity(isIdentity, identityStart,
0212:                            identityIncrement);
0213:                }
0214:
0215:                return newCol;
0216:            }
0217:
0218:            void setType(Column other) {
0219:
0220:                isNullable = other.isNullable;
0221:                colType = other.colType;
0222:                colSize = other.colSize;
0223:                colScale = other.colScale;
0224:            }
0225:
0226:            /**
0227:             *  Is this the identity column in the table.
0228:             *
0229:             * @return boolean
0230:             */
0231:            boolean isIdentity() {
0232:                return isIdentity;
0233:            }
0234:
0235:            /**
0236:             *  Is column nullable.
0237:             *
0238:             * @return boolean
0239:             */
0240:            boolean isNullable() {
0241:                return isNullable;
0242:            }
0243:
0244:            /**
0245:             *  Set nullable.
0246:             *
0247:             */
0248:            void setNullable(boolean value) {
0249:                isNullable = value;
0250:            }
0251:
0252:            /**
0253:             *  Is this single column primary key of the table.
0254:             *
0255:             * @return boolean
0256:             */
0257:            public boolean isPrimaryKey() {
0258:                return isPrimaryKey;
0259:            }
0260:
0261:            /**
0262:             *  Set primary key.
0263:             *
0264:             */
0265:            void setPrimaryKey(boolean value) {
0266:                isPrimaryKey = value;
0267:            }
0268:
0269:            /**
0270:             *  Returns default value in the session context.
0271:             */
0272:            Object getDefaultValue(Session session) throws HsqlException {
0273:
0274:                return defaultExpression == null ? null : defaultExpression
0275:                        .getValue(session, colType);
0276:            }
0277:
0278:            /**
0279:             *  Returns DDL for default value.
0280:             */
0281:            String getDefaultDDL() {
0282:
0283:                String ddl = null;
0284:
0285:                try {
0286:                    ddl = defaultExpression == null ? null : defaultExpression
0287:                            .getDDL();
0288:                } catch (HsqlException e) {
0289:                }
0290:
0291:                return ddl;
0292:            }
0293:
0294:            /**
0295:             *  Returns default expression for the column.
0296:             */
0297:            Expression getDefaultExpression() {
0298:                return defaultExpression;
0299:            }
0300:
0301:            void setDefaultExpression(Expression expr) {
0302:                defaultExpression = expr;
0303:            }
0304:
0305:            /**
0306:             *  Type of the column.
0307:             *
0308:             * @return java.sql.Types int value for the column
0309:             */
0310:            int getType() {
0311:                return colType;
0312:            }
0313:
0314:            int getDIType() {
0315:                return colType == Types.VARCHAR_IGNORECASE ? Types.VARCHAR
0316:                        : colType;
0317:            }
0318:
0319:            int getDITypeSub() {
0320:
0321:                if (colType == Types.VARCHAR_IGNORECASE) {
0322:                    return Types.TYPE_SUB_IGNORECASE;
0323:                }
0324:
0325:                return Types.TYPE_SUB_DEFAULT;
0326:            }
0327:
0328:            /**
0329:             *  Size of the column in DDL (0 if not defined).
0330:             *
0331:             * @return DDL size of column
0332:             */
0333:            int getSize() {
0334:                return colSize;
0335:            }
0336:
0337:            /**
0338:             *  Scale of the column in DDL (0 if not defined).
0339:             *
0340:             * @return DDL scale of column
0341:             */
0342:            int getScale() {
0343:                return colScale;
0344:            }
0345:
0346:            /**
0347:             *  Add two object of a given type
0348:             *
0349:             * @param  a
0350:             * @param  b
0351:             * @param  type
0352:             * @return result
0353:             * @throws  HsqlException
0354:             */
0355:            static Object add(Object a, Object b, int type)
0356:                    throws HsqlException {
0357:
0358:                if (a == null || b == null) {
0359:                    return null;
0360:                }
0361:
0362:                switch (type) {
0363:
0364:                case Types.NULL:
0365:                    return null;
0366:
0367:                case Types.REAL:
0368:                case Types.FLOAT:
0369:                case Types.DOUBLE: {
0370:                    double ad = ((Number) a).doubleValue();
0371:                    double bd = ((Number) b).doubleValue();
0372:
0373:                    return ValuePool
0374:                            .getDouble(Double.doubleToLongBits(ad + bd));
0375:
0376:                    //                return new Double(ad + bd);
0377:                }
0378:                case Types.VARCHAR:
0379:                case Types.CHAR:
0380:                case Types.LONGVARCHAR:
0381:                case Types.VARCHAR_IGNORECASE:
0382:                    return (String) a + (String) b;
0383:
0384:                case Types.NUMERIC:
0385:                case Types.DECIMAL: {
0386:                    BigDecimal abd = (BigDecimal) a;
0387:                    BigDecimal bbd = (BigDecimal) b;
0388:
0389:                    return abd.add(bbd);
0390:                }
0391:                case Types.TINYINT:
0392:                case Types.SMALLINT:
0393:                case Types.INTEGER: {
0394:                    int ai = ((Number) a).intValue();
0395:                    int bi = ((Number) b).intValue();
0396:
0397:                    return ValuePool.getInt(ai + bi);
0398:                }
0399:                case Types.BIGINT: {
0400:                    long longa = ((Number) a).longValue();
0401:                    long longb = ((Number) b).longValue();
0402:
0403:                    return ValuePool.getLong(longa + longb);
0404:                }
0405:                default:
0406:                    throw Trace.error(Trace.FUNCTION_NOT_SUPPORTED, Types
0407:                            .getTypeString(type));
0408:                }
0409:            }
0410:
0411:            /**
0412:             *  Concat two objects by turning them into strings first.
0413:             *
0414:             * @param  a
0415:             * @param  b
0416:             * @return result
0417:             * @throws  HsqlException
0418:             */
0419:            static Object concat(Object a, Object b) throws HsqlException {
0420:
0421:                if (a == null || b == null) {
0422:                    return null;
0423:                }
0424:
0425:                return a.toString() + b.toString();
0426:            }
0427:
0428:            /**
0429:             *  Negate a numeric object.
0430:             *
0431:             * @param  a
0432:             * @param  type
0433:             * @return result
0434:             * @throws  HsqlException
0435:             */
0436:            static Object negate(Object a, int type) throws HsqlException {
0437:
0438:                if (a == null) {
0439:                    return null;
0440:                }
0441:
0442:                switch (type) {
0443:
0444:                case Types.NULL:
0445:                    return null;
0446:
0447:                case Types.REAL:
0448:                case Types.FLOAT:
0449:                case Types.DOUBLE: {
0450:                    double ad = -((Number) a).doubleValue();
0451:
0452:                    return ValuePool.getDouble(Double.doubleToLongBits(ad));
0453:                }
0454:                case Types.NUMERIC:
0455:                case Types.DECIMAL:
0456:                    return ((BigDecimal) a).negate();
0457:
0458:                case Types.TINYINT:
0459:                case Types.SMALLINT:
0460:                case Types.INTEGER:
0461:                    return ValuePool.getInt(-((Number) a).intValue());
0462:
0463:                case Types.BIGINT:
0464:                    return ValuePool.getLong(-((Number) a).longValue());
0465:
0466:                default:
0467:                    throw Trace.error(Trace.FUNCTION_NOT_SUPPORTED, Types
0468:                            .getTypeString(type));
0469:                }
0470:            }
0471:
0472:            /**
0473:             *  Multiply two numeric objects.
0474:             *
0475:             * @param  a
0476:             * @param  b
0477:             * @param  type
0478:             * @return result
0479:             * @throws  HsqlException
0480:             */
0481:            static Object multiply(Object a, Object b, int type)
0482:                    throws HsqlException {
0483:
0484:                if (a == null || b == null) {
0485:                    return null;
0486:                }
0487:
0488:                // fredt@users - type conversion - may need to apply to other arithmetic operations too
0489:                if (!(a instanceof  Number && b instanceof  Number)) {
0490:                    a = Column.convertObject(a, type);
0491:                    b = Column.convertObject(b, type);
0492:                }
0493:
0494:                switch (type) {
0495:
0496:                case Types.NULL:
0497:                    return null;
0498:
0499:                case Types.REAL:
0500:                case Types.FLOAT:
0501:                case Types.DOUBLE: {
0502:                    double ad = ((Number) a).doubleValue();
0503:                    double bd = ((Number) b).doubleValue();
0504:
0505:                    return ValuePool
0506:                            .getDouble(Double.doubleToLongBits(ad * bd));
0507:                }
0508:                case Types.NUMERIC:
0509:                case Types.DECIMAL: {
0510:                    BigDecimal abd = (BigDecimal) a;
0511:                    BigDecimal bbd = (BigDecimal) b;
0512:
0513:                    return abd.multiply(bbd);
0514:                }
0515:                case Types.TINYINT:
0516:                case Types.SMALLINT:
0517:                case Types.INTEGER: {
0518:                    int ai = ((Number) a).intValue();
0519:                    int bi = ((Number) b).intValue();
0520:
0521:                    return ValuePool.getInt(ai * bi);
0522:                }
0523:                case Types.BIGINT: {
0524:                    long longa = ((Number) a).longValue();
0525:                    long longb = ((Number) b).longValue();
0526:
0527:                    return ValuePool.getLong(longa * longb);
0528:                }
0529:                default:
0530:                    throw Trace.error(Trace.FUNCTION_NOT_SUPPORTED, Types
0531:                            .getTypeString(type));
0532:                }
0533:            }
0534:
0535:            /**
0536:             *  Divide numeric object a by object b.
0537:             *
0538:             * @param  a
0539:             * @param  b
0540:             * @param  type
0541:             * @return result
0542:             * @throws  HsqlException
0543:             */
0544:            static Object divide(Object a, Object b, int type)
0545:                    throws HsqlException {
0546:
0547:                if (a == null || b == null) {
0548:                    return null;
0549:                }
0550:
0551:                switch (type) {
0552:
0553:                case Types.NULL:
0554:                    return null;
0555:
0556:                case Types.REAL:
0557:                case Types.FLOAT:
0558:                case Types.DOUBLE: {
0559:                    double ad = ((Number) a).doubleValue();
0560:                    double bd = ((Number) b).doubleValue();
0561:
0562:                    return ValuePool
0563:                            .getDouble(Double.doubleToLongBits(ad / bd));
0564:                }
0565:                case Types.NUMERIC:
0566:                case Types.DECIMAL: {
0567:                    BigDecimal abd = (BigDecimal) a;
0568:                    BigDecimal bbd = (BigDecimal) b;
0569:                    int scale = abd.scale() > bbd.scale() ? abd.scale() : bbd
0570:                            .scale();
0571:
0572:                    return (bbd.signum() == 0) ? null : abd.divide(bbd, scale,
0573:                            BigDecimal.ROUND_HALF_DOWN);
0574:                }
0575:                case Types.TINYINT:
0576:                case Types.SMALLINT:
0577:                case Types.INTEGER: {
0578:                    int ai = ((Number) a).intValue();
0579:                    int bi = ((Number) b).intValue();
0580:
0581:                    if (bi == 0) {
0582:                        throw Trace.error(Trace.DIVISION_BY_ZERO);
0583:                    }
0584:
0585:                    return ValuePool.getInt(ai / bi);
0586:                }
0587:                case Types.BIGINT: {
0588:                    long longa = ((Number) a).longValue();
0589:                    long longb = ((Number) b).longValue();
0590:
0591:                    return (longb == 0) ? null : ValuePool.getLong(longa
0592:                            / longb);
0593:                }
0594:                default:
0595:                    throw Trace.error(Trace.FUNCTION_NOT_SUPPORTED, Types
0596:                            .getTypeString(type));
0597:                }
0598:            }
0599:
0600:            /**
0601:             *  Subtract numeric object b from object a.
0602:             *
0603:             * @param  a
0604:             * @param  b
0605:             * @param  type
0606:             * @return result
0607:             * @throws  HsqlException
0608:             */
0609:            static Object subtract(Object a, Object b, int type)
0610:                    throws HsqlException {
0611:
0612:                if (a == null || b == null) {
0613:                    return null;
0614:                }
0615:
0616:                switch (type) {
0617:
0618:                case Types.NULL:
0619:                    return null;
0620:
0621:                case Types.REAL:
0622:                case Types.FLOAT:
0623:                case Types.DOUBLE: {
0624:                    double ad = ((Number) a).doubleValue();
0625:                    double bd = ((Number) b).doubleValue();
0626:
0627:                    return ValuePool
0628:                            .getDouble(Double.doubleToLongBits(ad - bd));
0629:                }
0630:                case Types.NUMERIC:
0631:                case Types.DECIMAL: {
0632:                    BigDecimal abd = (BigDecimal) a;
0633:                    BigDecimal bbd = (BigDecimal) b;
0634:
0635:                    return abd.subtract(bbd);
0636:                }
0637:                case Types.TINYINT:
0638:                case Types.SMALLINT:
0639:                case Types.INTEGER: {
0640:                    int ai = ((Number) a).intValue();
0641:                    int bi = ((Number) b).intValue();
0642:
0643:                    return ValuePool.getInt(ai - bi);
0644:                }
0645:                case Types.BIGINT: {
0646:                    long longa = ((Number) a).longValue();
0647:                    long longb = ((Number) b).longValue();
0648:
0649:                    return ValuePool.getLong(longa - longb);
0650:                }
0651:                default:
0652:                    throw Trace.error(Trace.FUNCTION_NOT_SUPPORTED, Types
0653:                            .getTypeString(type));
0654:                }
0655:            }
0656:
0657:            // boucherb@users 2003-09-25
0658:            // TODO:  Maybe use //#ifdef tag or reflective static method attribute
0659:            // instantiation to take advantage of String.compareToIgnoreCase when
0660:            // available (JDK 1.2 and greater) during ANT build. That or perhaps
0661:            // consider using either local character-wise comparison or first converting
0662:            // to lower case and then to upper case. Sun states that the JDK 1.2 introduced
0663:            // String.compareToIngnorCase() comparison involves calling
0664:            // Character.toLowerCase(Character.toUpperCase()) on compared characters,
0665:            // to correctly handle some caveats concering using only the one operation or
0666:            // the other outside the ascii character range.
0667:            // fredt@users 20020130 - patch 418022 by deforest@users
0668:            // use of rtrim() to mimic SQL92 behaviour
0669:
0670:            /**
0671:             *  Compare a with b and return int value as result.
0672:             *
0673:             * @param  a instance of Java wrapper, depending on type, but always same for a & b (can be null)
0674:             * @param  b instance of Java wrapper, depending on type, but always same for a & b (can be null)
0675:             * @param  type one of the java.sql.Types
0676:             * @return result 1 if a>b, 0 if a=b, -1 if b>a
0677:             * @throws  HsqlException
0678:             */
0679:            static int compare(Collation collation, Object a, Object b, int type) {
0680:
0681:                int i = 0;
0682:
0683:                if (a == b) {
0684:                    return 0;
0685:                }
0686:
0687:                // Current null handling here: null==null and smaller any value
0688:                // Note, standard SQL null handling is handled by Expression.test() calling testNull() instead of this!
0689:                // Attention, this is also used for grouping ('null' is one group)
0690:                if (a == null) {
0691:                    return -1;
0692:                }
0693:
0694:                if (b == null) {
0695:                    return 1;
0696:                }
0697:
0698:                switch (type) {
0699:
0700:                case Types.NULL:
0701:                    return 0;
0702:
0703:                case Types.VARCHAR:
0704:                case Types.LONGVARCHAR:
0705:                    return collation.compare((String) a, (String) b);
0706:
0707:                case Types.CHAR:
0708:                    return collation.compare(Library.rtrim((String) a), Library
0709:                            .rtrim((String) b));
0710:
0711:                case Types.VARCHAR_IGNORECASE:
0712:                    return collation.compareIgnoreCase(((String) a),
0713:                            ((String) b));
0714:
0715:                case Types.TINYINT:
0716:                case Types.SMALLINT:
0717:                case Types.INTEGER: {
0718:                    int ai = ((Number) a).intValue();
0719:                    int bi = ((Number) b).intValue();
0720:
0721:                    return (ai > bi) ? 1 : (bi > ai ? -1 : 0);
0722:                }
0723:                case Types.BIGINT: {
0724:                    long longa = ((Number) a).longValue();
0725:                    long longb = ((Number) b).longValue();
0726:
0727:                    return (longa > longb) ? 1 : (longb > longa ? -1 : 0);
0728:                }
0729:                case Types.REAL:
0730:                case Types.FLOAT:
0731:                case Types.DOUBLE: {
0732:                    double ad = ((Number) a).doubleValue();
0733:                    double bd = ((Number) b).doubleValue();
0734:
0735:                    return (ad > bd) ? 1 : (bd > ad ? -1 : 0);
0736:                }
0737:                case Types.NUMERIC:
0738:                case Types.DECIMAL:
0739:                    i = ((BigDecimal) a).compareTo((BigDecimal) b);
0740:                    break;
0741:
0742:                case Types.DATE:
0743:                    return HsqlDateTime.compare((Date) a, (Date) b);
0744:
0745:                case Types.TIME:
0746:                    return HsqlDateTime.compare((Time) a, (Time) b);
0747:
0748:                case Types.TIMESTAMP:
0749:                    return HsqlDateTime.compare((Timestamp) a, (Timestamp) b);
0750:
0751:                case Types.BOOLEAN: {
0752:                    boolean boola = ((Boolean) a).booleanValue();
0753:                    boolean boolb = ((Boolean) b).booleanValue();
0754:
0755:                    return (boola == boolb) ? 0 : (boolb ? -1 : 1);
0756:                }
0757:                case Types.BINARY:
0758:                case Types.VARBINARY:
0759:                case Types.LONGVARBINARY:
0760:                    if (a instanceof  Binary && b instanceof  Binary) {
0761:                        i = compareTo(((Binary) a).getBytes(), ((Binary) b)
0762:                                .getBytes());
0763:                    }
0764:                    break;
0765:
0766:                case Types.OTHER:
0767:                    return 0;
0768:                }
0769:
0770:                return (i == 0) ? 0 : (i < 0 ? -1 : 1);
0771:            }
0772:
0773:            /**
0774:             *  Convert an object into a Java object that represents its SQL type.<p>
0775:             *  All internal type conversion operations start with
0776:             *  this method. If a direct conversion doesn't take place, the object
0777:             *  is converted into a string first and an attempt is made to convert
0778:             *  the string into the target type.<br>
0779:             *
0780:             *  One objective of this mehod is to ensure the Object can be converted
0781:             *  to the given SQL type. For example, a very large BIGINT
0782:             *  value cannot be narrowed down to an INTEGER or SMALLINT.<br>
0783:             *
0784:             *  Type conversion performed by this method has gradually evolved in 1.7.2
0785:             *  to allow narrowing of numeric types in all cases according to the SQL
0786:             *  standard.<br>
0787:             *
0788:             *  Another new objective is to normalize DATETIME values.<br>
0789:             *
0790:             *  Objects set via JDBC PreparedStatement use this method to convert
0791:             *  the data to the Java type that is required for custom serialization
0792:             *  by the engine. <br>
0793:             *
0794:             * @param  o
0795:             * @param  type
0796:             * @return result
0797:             * @throws  HsqlException
0798:             */
0799:            public static Object convertObject(Object o, int type)
0800:                    throws HsqlException {
0801:
0802:                try {
0803:                    if (o == null) {
0804:                        return null;
0805:                    }
0806:
0807:                    switch (type) {
0808:
0809:                    case Types.NULL:
0810:                        return null;
0811:
0812:                    case Types.TINYINT:
0813:                        if (o instanceof  java.lang.String) {
0814:                            o = Library.trim((String) o, " ", true, true);
0815:
0816:                            int val = Integer.parseInt((String) o);
0817:
0818:                            o = ValuePool.getInt(val);
0819:                        }
0820:
0821:                        if (o instanceof  java.lang.Integer) {
0822:                            int temp = ((Number) o).intValue();
0823:
0824:                            if (Byte.MAX_VALUE < temp || temp < Byte.MIN_VALUE) {
0825:                                throw Trace
0826:                                        .error(Trace.NUMERIC_VALUE_OUT_OF_RANGE);
0827:                            }
0828:
0829:                            return o;
0830:                        }
0831:
0832:                        if (o instanceof  java.lang.Long) {
0833:                            long temp = ((Number) o).longValue();
0834:
0835:                            if (Byte.MAX_VALUE < temp || temp < Byte.MIN_VALUE) {
0836:                                throw Trace
0837:                                        .error(Trace.NUMERIC_VALUE_OUT_OF_RANGE);
0838:                            }
0839:
0840:                            return ValuePool.getInt(((Number) o).intValue());
0841:                        }
0842:
0843:                        // fredt@users - direct conversion to optimise JDBC setObject(Byte)
0844:                        if (o instanceof  java.lang.Byte) {
0845:                            return ValuePool.getInt(((Number) o).intValue());
0846:                        }
0847:
0848:                        // fredt@users - returns to this method for range checking
0849:                        if (o instanceof  java.lang.Number) {
0850:                            return convertObject(convertToInt(o), type);
0851:                        }
0852:
0853:                        if (o instanceof  java.lang.Boolean) {
0854:                            return ((Boolean) o).booleanValue() ? ValuePool
0855:                                    .getInt(1) : ValuePool.getInt(0);
0856:                        }
0857:                        break;
0858:
0859:                    case Types.SMALLINT:
0860:                        if (o instanceof  java.lang.String) {
0861:                            o = Library.trim((String) o, " ", true, true);
0862:
0863:                            int val = Integer.parseInt((String) o);
0864:
0865:                            o = ValuePool.getInt(val);
0866:                        }
0867:
0868:                        if (o instanceof  java.lang.Integer) {
0869:                            int temp = ((Number) o).intValue();
0870:
0871:                            if (Short.MAX_VALUE < temp
0872:                                    || temp < Short.MIN_VALUE) {
0873:                                throw Trace
0874:                                        .error(Trace.NUMERIC_VALUE_OUT_OF_RANGE);
0875:                            }
0876:
0877:                            return o;
0878:                        }
0879:
0880:                        if (o instanceof  java.lang.Long) {
0881:                            long temp = ((Number) o).longValue();
0882:
0883:                            if (Short.MAX_VALUE < temp
0884:                                    || temp < Short.MIN_VALUE) {
0885:                                throw Trace
0886:                                        .error(Trace.NUMERIC_VALUE_OUT_OF_RANGE);
0887:                            }
0888:
0889:                            return ValuePool.getInt(((Number) o).intValue());
0890:                        }
0891:
0892:                        // fredt@users - direct conversion for JDBC setObject(Short), etc.
0893:                        if (o instanceof  Byte || o instanceof  Short) {
0894:                            return ValuePool.getInt(((Number) o).intValue());
0895:                        }
0896:
0897:                        // fredt@users - returns to this method for range checking
0898:                        if (o instanceof  Number) {
0899:                            return convertObject(convertToInt(o), type);
0900:                        }
0901:
0902:                        if (o instanceof  java.lang.Boolean) {
0903:                            return ((Boolean) o).booleanValue() ? ValuePool
0904:                                    .getInt(1) : ValuePool.getInt(0);
0905:                        }
0906:                        break;
0907:
0908:                    case Types.INTEGER:
0909:                        if (o instanceof  java.lang.Integer) {
0910:                            return o;
0911:                        }
0912:
0913:                        if (o instanceof  java.lang.String) {
0914:                            o = Library.trim((String) o, " ", true, true);
0915:
0916:                            int val = Integer.parseInt((String) o);
0917:
0918:                            return ValuePool.getInt(val);
0919:                        }
0920:
0921:                        if (o instanceof  java.lang.Long) {
0922:                            long temp = ((Number) o).longValue();
0923:
0924:                            if (Integer.MAX_VALUE < temp
0925:                                    || temp < Integer.MIN_VALUE) {
0926:                                throw Trace
0927:                                        .error(Trace.NUMERIC_VALUE_OUT_OF_RANGE);
0928:                            }
0929:
0930:                            return ValuePool.getInt(((Number) o).intValue());
0931:                        }
0932:
0933:                        if (o instanceof  Byte || o instanceof  Short) {
0934:                            return ValuePool.getInt(((Number) o).intValue());
0935:                        }
0936:
0937:                        if (o instanceof  java.lang.Number) {
0938:                            return convertToInt(o);
0939:                        }
0940:
0941:                        if (o instanceof  java.lang.Boolean) {
0942:                            return ((Boolean) o).booleanValue() ? ValuePool
0943:                                    .getInt(1) : ValuePool.getInt(0);
0944:                        }
0945:                        break;
0946:
0947:                    case Types.BIGINT:
0948:                        if (o instanceof  java.lang.Long) {
0949:                            return o;
0950:                        }
0951:
0952:                        if (o instanceof  java.lang.String) {
0953:                            o = Library.trim((String) o, " ", true, true);
0954:
0955:                            long val = Long.parseLong((String) o);
0956:
0957:                            return ValuePool.getLong(val);
0958:                        }
0959:
0960:                        if (o instanceof  java.lang.Integer) {
0961:                            return ValuePool.getLong(((Integer) o).longValue());
0962:                        }
0963:
0964:                        if (o instanceof  Byte || o instanceof  Short) {
0965:                            return ValuePool.getLong(((Number) o).intValue());
0966:                        }
0967:
0968:                        if (o instanceof  java.lang.Number) {
0969:                            return convertToLong(o);
0970:                        }
0971:
0972:                        if (o instanceof  java.lang.Boolean) {
0973:                            return ((Boolean) o).booleanValue() ? ValuePool
0974:                                    .getLong(1) : ValuePool.getLong(0);
0975:                        }
0976:                        break;
0977:
0978:                    case Types.REAL:
0979:                    case Types.FLOAT:
0980:                    case Types.DOUBLE:
0981:                        if (o instanceof  java.lang.Double) {
0982:                            return o;
0983:                        }
0984:
0985:                        if (o instanceof  java.lang.String) {
0986:                            o = Library.trim((String) o, " ", true, true);
0987:
0988:                            double d = JavaSystem.parseDouble((String) o);
0989:                            long l = Double.doubleToLongBits(d);
0990:
0991:                            return ValuePool.getDouble(l);
0992:                        }
0993:
0994:                        if (o instanceof  java.lang.Number) {
0995:                            return convertToDouble(o);
0996:                        }
0997:
0998:                        if (o instanceof  java.lang.Boolean) {
0999:                            return ((Boolean) o).booleanValue() ? ValuePool
1000:                                    .getDouble(1) : ValuePool.getDouble(0);
1001:                        }
1002:                        break;
1003:
1004:                    case Types.NUMERIC:
1005:                    case Types.DECIMAL:
1006:                        if (o instanceof  BigDecimal) {
1007:                            return o;
1008:                        }
1009:
1010:                        if (o instanceof  Long) {
1011:                            return BigDecimal.valueOf(((Long) o).longValue());
1012:                        }
1013:
1014:                        if (o instanceof  java.lang.Boolean) {
1015:                            return ((Boolean) o).booleanValue() ? BIG_DECIMAL_1
1016:                                    : BIG_DECIMAL_0;
1017:                        }
1018:                        break;
1019:
1020:                    case Types.BOOLEAN:
1021:                        if (o instanceof  java.lang.Boolean) {
1022:                            return (Boolean) o;
1023:                        }
1024:
1025:                        if (o instanceof  java.lang.String) {
1026:                            o = Library.trim((String) o, " ", true, true);
1027:
1028:                            return ((String) o).equalsIgnoreCase("TRUE") ? Boolean.TRUE
1029:                                    : Boolean.FALSE;
1030:                        }
1031:
1032:                        if (o instanceof  Integer) {
1033:                            return ((Integer) o).intValue() == 0 ? Boolean.FALSE
1034:                                    : Boolean.TRUE;
1035:                        }
1036:
1037:                        if (o instanceof  Long) {
1038:                            return ((Long) o).longValue() == 0L ? Boolean.FALSE
1039:                                    : Boolean.TRUE;
1040:                        }
1041:
1042:                        if (o instanceof  java.lang.Double) {
1043:                            return ((Double) o).doubleValue() == 0.0 ? Boolean.FALSE
1044:                                    : Boolean.TRUE;
1045:                        }
1046:
1047:                        if (o instanceof  BigDecimal) {
1048:                            return ((BigDecimal) o).equals(BIG_DECIMAL_0) ? Boolean.FALSE
1049:                                    : Boolean.TRUE;
1050:                        }
1051:
1052:                        throw Trace.error(Trace.WRONG_DATA_TYPE);
1053:                    case Types.VARCHAR_IGNORECASE:
1054:                    case Types.VARCHAR:
1055:                    case Types.CHAR:
1056:                    case Types.LONGVARCHAR:
1057:                        if (o instanceof  java.lang.String) {
1058:                            return o;
1059:                        }
1060:
1061:                        if (o instanceof  Time) {
1062:                            return HsqlDateTime.getTimeString((Time) o, null);
1063:                        }
1064:
1065:                        if (o instanceof  Timestamp) {
1066:                            return HsqlDateTime.getTimestampString(
1067:                                    (Timestamp) o, null);
1068:                        }
1069:
1070:                        if (o instanceof  Date) {
1071:                            return HsqlDateTime.getDateString((Date) o, null);
1072:                        }
1073:
1074:                        if (o instanceof  byte[]) {
1075:                            return StringConverter.byteToHex((byte[]) o);
1076:                        }
1077:                        break;
1078:
1079:                    case Types.TIME:
1080:                        if (o instanceof  Time) {
1081:                            return HsqlDateTime.getNormalisedTime((Time) o);
1082:                        }
1083:
1084:                        if (o instanceof  Timestamp) {
1085:                            return HsqlDateTime
1086:                                    .getNormalisedTime((Timestamp) o);
1087:                        }
1088:
1089:                        if (o instanceof  String) {
1090:                            return HsqlDateTime.timeValue((String) o);
1091:                        }
1092:
1093:                        if (o instanceof  Date) {
1094:                            throw Trace.error(Trace.INVALID_CONVERSION, Types
1095:                                    .getTypeString(type));
1096:                        }
1097:                        break;
1098:
1099:                    case Types.TIMESTAMP:
1100:                        if (o instanceof  Timestamp) {
1101:                            return o;
1102:                        }
1103:
1104:                        if (o instanceof  Time) {
1105:                            return HsqlDateTime
1106:                                    .getNormalisedTimestamp((Time) o);
1107:                        }
1108:
1109:                        if (o instanceof  Date) {
1110:                            return HsqlDateTime
1111:                                    .getNormalisedTimestamp((Date) o);
1112:                        }
1113:
1114:                        if (o instanceof  String) {
1115:                            return HsqlDateTime.timestampValue((String) o);
1116:                        }
1117:                        break;
1118:
1119:                    case Types.DATE:
1120:                        if (o instanceof  Date) {
1121:                            return HsqlDateTime.getNormalisedDate((Date) o);
1122:                        }
1123:
1124:                        if (o instanceof  Timestamp) {
1125:                            return HsqlDateTime
1126:                                    .getNormalisedDate((Timestamp) o);
1127:                        }
1128:
1129:                        if (o instanceof  String) {
1130:                            return HsqlDateTime.dateValue((String) o);
1131:                        }
1132:
1133:                        if (o instanceof  Time) {
1134:                            throw Trace.error(Trace.INVALID_CONVERSION, Types
1135:                                    .getTypeString(type));
1136:                        }
1137:                        break;
1138:
1139:                    case Types.BINARY:
1140:                    case Types.VARBINARY:
1141:                    case Types.LONGVARBINARY:
1142:                        if (o instanceof  Binary) {
1143:                            return o;
1144:                        } else if (o instanceof  byte[]) {
1145:                            return new Binary((byte[]) o, false);
1146:                        } else if (o instanceof  String) {
1147:
1148:                            /**
1149:                             * @todo fredt - we need this for script processing only
1150:                             *  handle the script separately and process normal
1151:                             *  conversion according to rules in SQL
1152:                             *  standard
1153:                             */
1154:                            return new Binary(StringConverter
1155:                                    .hexToByte((String) o), false);
1156:                        }
1157:
1158:                        throw Trace.error(Trace.INVALID_CONVERSION, Types
1159:                                .getTypeString(type));
1160:
1161:                        // fredt@users 20030708 -  patch 1.7.2 - OBJECT handling - superseded
1162:                    case Types.OTHER:
1163:                        if (o instanceof  JavaObject) {
1164:                            return o;
1165:                        } else if (o instanceof  String) {
1166:
1167:                            /**
1168:                             * @todo fredt - we need this for script processing only
1169:                             *  handle the script separately and allow normal Sting
1170:                             *  objects to be stored as JavaObject
1171:                             */
1172:                            return new JavaObject(StringConverter
1173:                                    .hexToByte((String) o));
1174:                        } else if (o instanceof  Binary) {
1175:                            return new JavaObject(((Binary) o).getBytes());
1176:                        }
1177:
1178:                        return new JavaObject((Serializable) o);
1179:
1180:                    default:
1181:                    }
1182:
1183:                    if (o instanceof  JavaObject) {
1184:                        o = ((JavaObject) o).getObject();
1185:
1186:                        return convertObject(o, type);
1187:                    }
1188:
1189:                    return convertString(o.toString(), type);
1190:                } catch (HsqlException e) {
1191:                    throw e;
1192:                } catch (Exception e) {
1193:                    throw Trace.error(Trace.WRONG_DATA_TYPE, e.toString());
1194:                }
1195:            }
1196:
1197:            /**
1198:             *  Return a java object based on a SQL string. This is called from
1199:             *  convertObject(Object o, int type).
1200:             *
1201:             * @param  s
1202:             * @param  type
1203:             * @return
1204:             * @throws  HsqlException
1205:             */
1206:            private static Object convertString(String s, int type)
1207:                    throws HsqlException {
1208:
1209:                switch (type) {
1210:
1211:                case Types.TINYINT:
1212:                case Types.SMALLINT:
1213:
1214:                    // fredt - do maximumm / minimum checks on each type
1215:                    return convertObject(s, type);
1216:
1217:                case Types.INTEGER:
1218:                    int val = Integer.parseInt(s);
1219:
1220:                    return ValuePool.getInt(val);
1221:
1222:                case Types.BIGINT:
1223:                    return ValuePool.getLong(Long.parseLong(s));
1224:
1225:                case Types.REAL:
1226:                case Types.FLOAT:
1227:                case Types.DOUBLE:
1228:                    double d = JavaSystem.parseDouble(s);
1229:                    long l = Double.doubleToLongBits(d);
1230:
1231:                    return ValuePool.getDouble(l);
1232:
1233:                case Types.VARCHAR_IGNORECASE:
1234:                case Types.VARCHAR:
1235:                case Types.CHAR:
1236:                case Types.LONGVARCHAR:
1237:                    return s;
1238:
1239:                case Types.DATE:
1240:                    return HsqlDateTime.dateValue(s);
1241:
1242:                case Types.TIME:
1243:                    return HsqlDateTime.timeValue(s);
1244:
1245:                case Types.TIMESTAMP:
1246:                    return HsqlDateTime.timestampValue(s);
1247:
1248:                case Types.NUMERIC:
1249:                case Types.DECIMAL:
1250:                    s = Library.trim(s, " ", true, true);
1251:
1252:                    return new BigDecimal(s);
1253:
1254:                case Types.BOOLEAN:
1255:                    return s.equalsIgnoreCase("TRUE") ? Boolean.TRUE
1256:                            : Boolean.FALSE;
1257:
1258:                case Types.BINARY:
1259:                case Types.VARBINARY:
1260:                case Types.LONGVARBINARY:
1261:                case Types.OTHER:
1262:                default:
1263:                    throw Trace.error(Trace.INVALID_CONVERSION, Types
1264:                            .getTypeString(type));
1265:                }
1266:            }
1267:
1268:            /**
1269:             *  Return an SQL representation of an object. Strings will be quoted
1270:             *  with single quotes, other objects will represented as in a SQL
1271:             *  statement.
1272:             *
1273:             * @param  o
1274:             * @param  type
1275:             * @return result
1276:             * @throws  HsqlException
1277:             */
1278:            static String createSQLString(Object o, int type)
1279:                    throws HsqlException {
1280:
1281:                if (o == null) {
1282:                    return "NULL";
1283:                }
1284:
1285:                switch (type) {
1286:
1287:                case Types.NULL:
1288:                    return "NULL";
1289:
1290:                case Types.REAL:
1291:                case Types.FLOAT:
1292:                case Types.DOUBLE:
1293:                    return createSQLString(((Number) o).doubleValue());
1294:
1295:                case Types.DATE:
1296:                case Types.TIME:
1297:                case Types.TIMESTAMP:
1298:                    return StringConverter.toQuotedString(o.toString(), '\'',
1299:                            false);
1300:
1301:                case Types.BINARY:
1302:                case Types.VARBINARY:
1303:                case Types.LONGVARBINARY:
1304:                    if (!(o instanceof  Binary)) {
1305:                        throw Trace.error(Trace.INVALID_CONVERSION);
1306:                    }
1307:
1308:                    return StringConverter.toQuotedString(StringConverter
1309:                            .byteToHex(((Binary) o).getBytes()), '\'', false);
1310:
1311:                case Types.OTHER:
1312:                    if (!(o instanceof  JavaObject)) {
1313:                        throw Trace.error(Trace.SERIALIZATION_FAILURE);
1314:                    }
1315:
1316:                    return StringConverter.toQuotedString(StringConverter
1317:                            .byteToHex(((JavaObject) o).getBytes()), '\'',
1318:                            false);
1319:
1320:                case Types.VARCHAR_IGNORECASE:
1321:                case Types.VARCHAR:
1322:                case Types.CHAR:
1323:                case Types.LONGVARCHAR:
1324:                    return createSQLString((String) o);
1325:
1326:                default:
1327:                    return o.toString();
1328:                }
1329:            }
1330:
1331:            public static String createSQLString(double x) {
1332:
1333:                if (x == Double.NEGATIVE_INFINITY) {
1334:                    return "-1E0/0";
1335:                }
1336:
1337:                if (x == Double.POSITIVE_INFINITY) {
1338:                    return "1E0/0";
1339:                }
1340:
1341:                if (Double.isNaN(x)) {
1342:                    return "0E0/0E0";
1343:                }
1344:
1345:                String s = Double.toString(x);
1346:
1347:                // ensure the engine treats the value as a DOUBLE, not DECIMAL
1348:                if (s.indexOf('E') < 0) {
1349:                    s = s.concat("E0");
1350:                }
1351:
1352:                return s;
1353:            }
1354:
1355:            /**
1356:             *  Turns a java string into a quoted SQL string
1357:             *
1358:             * @param  s java string
1359:             * @return quoted SQL string
1360:             */
1361:            public static String createSQLString(String s) {
1362:
1363:                if (s == null) {
1364:                    return "NULL";
1365:                }
1366:
1367:                return StringConverter.toQuotedString(s, '\'', true);
1368:            }
1369:
1370:            /**
1371:             * Explicit casts are handled here. This is separate from the implicit
1372:             * casts carried out when inserting/updating rows.
1373:             * SQL standard 6.12 rules for enforcement of size, precision and scale
1374:             * are implemented here are as follows:
1375:             *
1376:             * For no size, precision or scale, default to convertObject(Object)
1377:             *
1378:             * Right truncation is allowed only for CHAR to CHAR casts
1379:             * (CHAR is generic for all string types).
1380:             *
1381:             * For other casts to CHAR, right truncation is not allowed.
1382:             *
1383:             * For numeric conversions, scale is always converted to target first,
1384:             * then precision is imposed. No truncation is allowed. (fredt)
1385:             */
1386:            public static Object convertObject(Session session, Object o,
1387:                    int type, int precision, int scale) throws HsqlException {
1388:
1389:                if (o == null) {
1390:                    return o;
1391:                }
1392:
1393:                if (precision == 0) {
1394:                    return convertObject(o, type);
1395:                }
1396:
1397:                boolean check = true;
1398:
1399:                switch (type) {
1400:
1401:                case Types.VARCHAR_IGNORECASE:
1402:                case Types.LONGVARCHAR:
1403:                    type = Types.VARCHAR;
1404:                case Types.VARCHAR:
1405:                case Types.CHAR:
1406:                    if (o instanceof  String) {
1407:                        check = false;
1408:                    } else {
1409:                        o = convertObject(o, Types.VARCHAR);
1410:                    }
1411:
1412:                    return enforceSize(o, type, precision, scale, check);
1413:
1414:                case Types.NUMERIC:
1415:                case Types.DECIMAL:
1416:                    if (!(o instanceof  BigDecimal)) {
1417:                        o = convertObject(o, type);
1418:                    }
1419:
1420:                    return enforceSize(o, type, precision, scale, true);
1421:
1422:                case Types.TIMESTAMP:
1423:                    if (o instanceof  Time) {
1424:                        long millis = session.currentDate.getTime()
1425:                                + ((Time) o).getTime();
1426:
1427:                        o = HsqlDateTime.getTimestamp(millis);
1428:                    }
1429:
1430:                    if (o instanceof  Timestamp) {
1431:                        return enforceSize(o, type, precision, scale, false);
1432:                    }
1433:                }
1434:
1435:                return convertObject(o, type);
1436:            }
1437:
1438:            static int[] tenPower = { 1000000000, 100000000, 10000000, 1000000,
1439:                    100000, 10000, 1000 };
1440:
1441:            /**
1442:             *  Check an object for type CHAR and VARCHAR and truncate/pad based on
1443:             *  the  size
1444:             *
1445:             * @param  obj   object to check
1446:             * @param  type  the object type
1447:             * @param  size  size to enforce
1448:             * @param check  throw if too long
1449:             * @return       the altered object if the right type, else the object
1450:             *      passed in unaltered
1451:             * @throws HsqlException if data too long
1452:             */
1453:            static Object enforceSize(Object obj, int type, int size,
1454:                    int scale, boolean check) throws HsqlException {
1455:
1456:                if (obj == null) {
1457:                    return obj;
1458:                }
1459:
1460:                if (size == 0 && type != Types.TIMESTAMP) {
1461:                    return obj;
1462:                }
1463:
1464:                // todo: need to handle BINARY like this as well
1465:                switch (type) {
1466:
1467:                case Types.CHAR:
1468:                    return checkChar((String) obj, size, check);
1469:
1470:                case Types.VARCHAR:
1471:                case Types.VARCHAR_IGNORECASE:
1472:                    return checkVarchar((String) obj, size, check);
1473:
1474:                case Types.NUMERIC:
1475:                case Types.DECIMAL:
1476:                    BigDecimal dec = (BigDecimal) obj;
1477:
1478:                    dec = dec.setScale(scale, BigDecimal.ROUND_HALF_DOWN);
1479:
1480:                    BigInteger big = JavaSystem.getUnscaledValue(dec);
1481:                    int sign = big.signum() == -1 ? 1 : 0;
1482:
1483:                    if (big.toString().length() - sign > size) {
1484:                        throw Trace.error(Trace.STRING_DATA_TRUNCATION);
1485:                    }
1486:
1487:                    return dec;
1488:
1489:                case Types.TIMESTAMP:
1490:                    if (size == 6) {
1491:                        return obj;
1492:                    }
1493:
1494:                    Timestamp ts = (Timestamp) obj;
1495:                    int nanos = ts.getNanos();
1496:                    int divisor = tenPower[size];
1497:                    int newNanos = (nanos / divisor) * divisor;
1498:
1499:                    ts.setNanos(newNanos);
1500:
1501:                    return ts;
1502:
1503:                default:
1504:                    return obj;
1505:                }
1506:            }
1507:
1508:            /**
1509:             *  Checks the length of a VARCHAR string.
1510:             *
1511:             * @param s     the string to pad to truncate
1512:             * @param len   the len to make the string
1513:             * @param check if true, throw an exception if truncation takes place
1514:             * @return      the string of size len
1515:             */
1516:            static String checkVarchar(String s, int len, boolean check)
1517:                    throws HsqlException {
1518:
1519:                int slen = s.length();
1520:
1521:                if (slen > len) {
1522:                    if (check) {
1523:                        throw Trace.error(Trace.STRING_DATA_TRUNCATION);
1524:                    }
1525:
1526:                    return s.substring(0, len);
1527:                }
1528:
1529:                return s;
1530:            }
1531:
1532:            /**
1533:             *  Checks and pads a CHARACTER string to len size
1534:             *
1535:             * @param s     the string to pad to truncate
1536:             * @param len   the len to make the string
1537:             * @param check if true, throw an exception if truncation takes place
1538:             * @return      the string of size len
1539:             */
1540:            static String checkChar(String s, int len, boolean check)
1541:                    throws HsqlException {
1542:
1543:                int slen = s.length();
1544:
1545:                if (slen == len) {
1546:                    return s;
1547:                }
1548:
1549:                if (slen > len) {
1550:                    if (check) {
1551:                        throw Trace.error(Trace.STRING_DATA_TRUNCATION);
1552:                    }
1553:
1554:                    return s.substring(0, len);
1555:                }
1556:
1557:                char[] b = new char[len];
1558:
1559:                s.getChars(0, slen, b, 0);
1560:
1561:                for (int i = slen; i < len; i++) {
1562:                    b[i] = ' ';
1563:                }
1564:
1565:                return new String(b);
1566:            }
1567:
1568:            /**
1569:             * Type narrowing from DOUBLE/DECIMAL/NUMERIC to BIGINT / INT / SMALLINT / TINYINT
1570:             * following the SQL rules. When conversion is from a non-integral type,
1571:             * digits to the right of the decimal point are lost.
1572:             */
1573:
1574:            /**
1575:             * Converter from a numeric object to Integer. Input is checked to be
1576:             * within range represented by Integer.
1577:             */
1578:            static Integer convertToInt(Object o) throws HsqlException {
1579:
1580:                if (o instanceof  BigDecimal) {
1581:                    BigInteger bi = ((BigDecimal) o).toBigInteger();
1582:
1583:                    if (bi.compareTo(MAX_INT) > 0 || bi.compareTo(MIN_INT) < 0) {
1584:                        throw Trace.error(Trace.NUMERIC_VALUE_OUT_OF_RANGE);
1585:                    }
1586:
1587:                    return ValuePool.getInt(bi.intValue());
1588:                }
1589:
1590:                if (o instanceof  Double || o instanceof  Float) {
1591:                    double d = ((Number) o).doubleValue();
1592:
1593:                    if (Double.isNaN(d) || d >= (double) Integer.MAX_VALUE + 1
1594:                            || d <= (double) Integer.MIN_VALUE - 1) {
1595:                        throw Trace.error(Trace.NUMERIC_VALUE_OUT_OF_RANGE);
1596:                    }
1597:
1598:                    return ValuePool.getInt((int) d);
1599:                }
1600:
1601:                throw Trace.error(Trace.INVALID_CONVERSION);
1602:            }
1603:
1604:            /**
1605:             * Converter from a numeric object to Long. Input is checked to be
1606:             * within range represented by Long.
1607:             */
1608:            static Long convertToLong(Object o) throws HsqlException {
1609:
1610:                if (o instanceof  BigDecimal) {
1611:                    BigInteger bi = ((BigDecimal) o).toBigInteger();
1612:
1613:                    if (bi.compareTo(MAX_LONG) > 0
1614:                            || bi.compareTo(MIN_LONG) < 0) {
1615:                        throw Trace.error(Trace.NUMERIC_VALUE_OUT_OF_RANGE);
1616:                    }
1617:
1618:                    return ValuePool.getLong(bi.longValue());
1619:                }
1620:
1621:                if (o instanceof  Double || o instanceof  Float) {
1622:                    double d = ((Number) o).doubleValue();
1623:
1624:                    if (Double.isNaN(d) || d >= (double) Long.MAX_VALUE + 1
1625:                            || d <= (double) Long.MIN_VALUE - 1) {
1626:                        throw Trace.error(Trace.NUMERIC_VALUE_OUT_OF_RANGE);
1627:                    }
1628:
1629:                    return ValuePool.getLong((long) d);
1630:                }
1631:
1632:                throw Trace.error(Trace.INVALID_CONVERSION);
1633:            }
1634:
1635:            /**
1636:             * Converter from a numeric object to Double. Input is checked to be
1637:             * within range represented by Double
1638:             */
1639:            static Double convertToDouble(Object o) throws HsqlException {
1640:
1641:                double val;
1642:
1643:                if (o instanceof  BigDecimal) {
1644:                    BigDecimal bd = (BigDecimal) o;
1645:
1646:                    val = bd.doubleValue();
1647:
1648:                    int signum = bd.signum();
1649:                    BigDecimal bo = new BigDecimal(val + signum);
1650:
1651:                    if (bo.compareTo(bd) != signum) {
1652:                        throw Trace.error(Trace.NUMERIC_VALUE_OUT_OF_RANGE);
1653:                    }
1654:                } else {
1655:                    val = ((Number) o).doubleValue();
1656:                }
1657:
1658:                return ValuePool.getDouble(Double.doubleToLongBits(val));
1659:            }
1660:
1661:            // fredt@users 20020408 - patch 442993 by fredt - arithmetic expressions
1662:
1663:            /**
1664:             *  Arithmetic expression terms are promoted to a type that can
1665:             *  represent the resulting values and avoid incorrect results.<p>
1666:             *  When the result or the expression is converted to the
1667:             *  type of the target column for storage, an exception is thrown if the
1668:             *  resulting value cannot be stored in the column<p>
1669:             *  Returns a SQL type "wide" enough to represent the result of the
1670:             *  expression.<br>
1671:             *  A type is "wider" than the other if it can represent all its
1672:             *  numeric values.<BR>
1673:             *  Types narrower than INTEGER (int) are promoted to
1674:             *  INTEGER. The order is as follows<p>
1675:             *
1676:             *  INTEGER, BIGINT, DOUBLE, DECIMAL<p>
1677:             *
1678:             *  TINYINT and SMALLINT in any combination return INTEGER<br>
1679:             *  INTEGER and INTEGER return BIGINT<br>
1680:             *  BIGINT and INTEGER return NUMERIC/DECIMAL<br>
1681:             *  BIGINT and BIGINT return NUMERIC/DECIMAL<br>
1682:             *  DOUBLE and INTEGER return DOUBLE<br>
1683:             *  DOUBLE and BIGINT return DOUBLE<br>
1684:             *  NUMERIC/DECIMAL and any type returns NUMERIC/DECIMAL<br>
1685:             *
1686:             * @author fredt@users
1687:             * @param  type1  java.sql.Types value for the first numeric type
1688:             * @param  type2  java.sql.Types value for the second numeric type
1689:             * @return        either type1 or type2 on the basis of the above order
1690:             */
1691:            static int getCombinedNumberType(int type1, int type2, int expType) {
1692:
1693:                int typeWidth1 = getNumTypeWidth(type1);
1694:                int typeWidth2 = getNumTypeWidth(type2);
1695:
1696:                if (typeWidth1 == 16 || typeWidth2 == 16) {
1697:                    return Types.DOUBLE;
1698:                }
1699:
1700:                switch (expType) {
1701:
1702:                case Expression.EQUAL:
1703:                case Expression.BIGGER:
1704:                case Expression.BIGGER_EQUAL:
1705:                case Expression.SMALLER_EQUAL:
1706:                case Expression.SMALLER:
1707:                case Expression.NOT_EQUAL:
1708:                case Expression.ALTERNATIVE:
1709:                case Expression.DIVIDE:
1710:                    return (typeWidth1 > typeWidth2) ? type1 : type2;
1711:
1712:                default:
1713:                    int sum = typeWidth1 + typeWidth2;
1714:
1715:                    if (sum <= 4) {
1716:                        return Types.INTEGER;
1717:                    }
1718:
1719:                    if (sum <= 8) {
1720:                        return Types.BIGINT;
1721:                    }
1722:
1723:                    return Types.NUMERIC;
1724:                }
1725:            }
1726:
1727:            /**
1728:             * @param  type java.sql.Types int for a numeric type
1729:             * @return relative width
1730:             */
1731:            static int getNumTypeWidth(int type) {
1732:
1733:                switch (type) {
1734:
1735:                case Types.TINYINT:
1736:                    return 1;
1737:
1738:                case Types.SMALLINT:
1739:                    return 2;
1740:
1741:                case Types.INTEGER:
1742:                    return 4;
1743:
1744:                case Types.BIGINT:
1745:                    return 8;
1746:
1747:                case Types.REAL:
1748:                case Types.FLOAT:
1749:                case Types.DOUBLE:
1750:                    return 16;
1751:
1752:                case Types.NUMERIC:
1753:                case Types.DECIMAL:
1754:                    return 32;
1755:
1756:                default:
1757:                    return 32;
1758:                }
1759:            }
1760:
1761:            /**
1762:             * returns -1, 0 , +1
1763:             */
1764:            static int compareToTypeRange(Object o, int targettype) {
1765:
1766:                if (!(o instanceof  Number)) {
1767:                    return 0;
1768:                }
1769:
1770:                if (o instanceof  Integer || o instanceof  Long) {
1771:                    long temp = ((Number) o).longValue();
1772:                    int min;
1773:                    int max;
1774:
1775:                    switch (targettype) {
1776:
1777:                    case Types.TINYINT:
1778:                        min = Byte.MIN_VALUE;
1779:                        max = Byte.MAX_VALUE;
1780:                        break;
1781:
1782:                    case Types.SMALLINT:
1783:                        min = Short.MIN_VALUE;
1784:                        max = Short.MAX_VALUE;
1785:                        break;
1786:
1787:                    case Types.INTEGER:
1788:                        min = Integer.MIN_VALUE;
1789:                        max = Integer.MAX_VALUE;
1790:                        break;
1791:
1792:                    case Types.BIGINT:
1793:                    case Types.DECIMAL:
1794:                    case Types.NUMERIC:
1795:                    default:
1796:                        return 0;
1797:                    }
1798:
1799:                    if (max < temp) {
1800:                        return 1;
1801:                    }
1802:
1803:                    if (temp < min) {
1804:                        return -1;
1805:                    }
1806:
1807:                    return 0;
1808:                } else {
1809:                    try {
1810:                        o = convertToLong(o);
1811:
1812:                        return compareToTypeRange(o, targettype);
1813:                    } catch (HsqlException e) {
1814:                        if (e.getErrorCode() == -Trace.NUMERIC_VALUE_OUT_OF_RANGE) {
1815:                            if (o instanceof  BigDecimal) {
1816:                                return ((BigDecimal) o).signum();
1817:                            } else if (o instanceof  Double) {
1818:                                return ((Double) o).doubleValue() > 0 ? 1 : -1;
1819:                            }
1820:                        }
1821:                    }
1822:                }
1823:
1824:                return 0;
1825:            }
1826:
1827:            /**
1828:             * Converts the specified hexadecimal digit <CODE>String</CODE>
1829:             * to an equivalent array of bytes.
1830:             *
1831:             * @param hexString a <CODE>String</CODE> of hexadecimal digits
1832:             * @throws HsqlException if the specified string contains non-hexadecimal digits.
1833:             * @return a byte array equivalent to the specified string of hexadecimal digits
1834:             */
1835:            public static byte[] hexToByteArray(String hexString)
1836:                    throws HsqlException {
1837:
1838:                try {
1839:                    return StringConverter.hexToByte(hexString);
1840:                } catch (IOException e) {
1841:                    throw Trace.error(Trace.INVALID_CHARACTER_ENCODING);
1842:                }
1843:            }
1844:
1845:            /**
1846:             * Compares a <CODE>byte[]</CODE> with another specified
1847:             * <CODE>byte[]</CODE> for order.  Returns a negative integer, zero,
1848:             * or a positive integer as the first object is less than, equal to, or
1849:             * greater than the specified second <CODE>byte[]</CODE>.<p>
1850:             *
1851:             * @param o1 the first byte[] to be compared
1852:             * @param o2 the second byte[] to be compared
1853:             * @return a negative integer, zero, or a positive integer as this object
1854:             * is less than, equal to, or greater than the specified object.
1855:             */
1856:            static int compareTo(byte[] o1, byte[] o2) {
1857:
1858:                int len = o1.length;
1859:                int lenb = o2.length;
1860:
1861:                for (int i = 0;; i++) {
1862:                    int a = 0;
1863:                    int b = 0;
1864:
1865:                    if (i < len) {
1866:                        a = ((int) o1[i]) & 0xff;
1867:                    } else if (i >= lenb) {
1868:                        return 0;
1869:                    }
1870:
1871:                    if (i < lenb) {
1872:                        b = ((int) o2[i]) & 0xff;
1873:                    }
1874:
1875:                    if (a > b) {
1876:                        return 1;
1877:                    }
1878:
1879:                    if (b > a) {
1880:                        return -1;
1881:                    }
1882:                }
1883:            }
1884:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.