Source Code Cross Referenced for SQLDecimal.java in  » Database-DBMS » db-derby-10.2 » org » apache » derby » iapi » types » 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 » db derby 10.2 » org.apache.derby.iapi.types 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:
0003:           Derby - Class org.apache.derby.iapi.types.SQLDecimal
0004:
0005:           Licensed to the Apache Software Foundation (ASF) under one or more
0006:           contributor license agreements.  See the NOTICE file distributed with
0007:           this work for additional information regarding copyright ownership.
0008:           The ASF licenses this file to you under the Apache License, Version 2.0
0009:           (the "License"); you may not use this file except in compliance with
0010:           the License.  You may obtain a copy of the License at
0011:
0012:              http://www.apache.org/licenses/LICENSE-2.0
0013:
0014:           Unless required by applicable law or agreed to in writing, software
0015:           distributed under the License is distributed on an "AS IS" BASIS,
0016:           WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0017:           See the License for the specific language governing permissions and
0018:           limitations under the License.
0019:
0020:         */
0021:
0022:        package org.apache.derby.iapi.types;
0023:
0024:        import org.apache.derby.iapi.reference.SQLState;
0025:
0026:        import org.apache.derby.iapi.services.io.ArrayInputStream;
0027:
0028:        import org.apache.derby.iapi.services.sanity.SanityManager;
0029:
0030:        import org.apache.derby.iapi.services.io.StoredFormatIds;
0031:        import org.apache.derby.iapi.services.io.Storable;
0032:
0033:        import org.apache.derby.iapi.error.StandardException;
0034:
0035:        import org.apache.derby.iapi.services.cache.ClassSize;
0036:        import org.apache.derby.iapi.services.info.JVMInfo;
0037:
0038:        import java.math.BigDecimal;
0039:        import java.math.BigInteger;
0040:        import java.lang.Math;
0041:        import java.lang.reflect.Method;
0042:        import java.lang.reflect.InvocationTargetException;
0043:        import java.io.ObjectOutput;
0044:        import java.io.ObjectInput;
0045:        import java.io.IOException;
0046:
0047:        import java.sql.ResultSet;
0048:        import java.sql.PreparedStatement;
0049:        import java.sql.SQLException;
0050:        import java.sql.Types;
0051:
0052:        /**
0053:         * SQLDecimal satisfies the DataValueDescriptor
0054:         * interfaces (i.e., OrderableDataType). It implements a numeric/decimal column, 
0055:         * e.g. for * storing a column value; it can be specified
0056:         * when constructed to not allow nulls. Nullability cannot be changed
0057:         * after construction, as it affects the storage size and mechanism.
0058:         * <p>
0059:         * Because OrderableDataType is a subtype of DataType,
0060:         * SQLDecimal can play a role in either a DataType/Row
0061:         * or a OrderableDataType/Row, interchangeably.
0062:         * <p>
0063:         * We assume the store has a flag for nullness of the value,
0064:         * and simply return a 0-length array for the stored form
0065:         * when the value is null.
0066:         *
0067:         * @author jamie
0068:         */
0069:        public final class SQLDecimal extends NumberDataType implements 
0070:                VariableSizeDataValue {
0071:            private static final BigDecimal ZERO = BigDecimal.valueOf(0L);
0072:            private static final BigDecimal ONE = BigDecimal.valueOf(1L);
0073:            static final BigDecimal MAXLONG_PLUS_ONE = BigDecimal.valueOf(
0074:                    Long.MAX_VALUE).add(ONE);
0075:            static final BigDecimal MINLONG_MINUS_ONE = BigDecimal.valueOf(
0076:                    Long.MIN_VALUE).subtract(ONE);
0077:
0078:            /**
0079:             * object state.  Note that scale and precision are 
0080:             * always determined dynamically from value when
0081:             * it is not null.
0082:
0083:               The field value can be null without the data value being null.
0084:               In this case the value is stored in rawData and rawScale. This
0085:               is to allow the minimal amount of work to read a SQLDecimal from disk.
0086:               Creating the BigDecimal is expensive as it requires allocating
0087:               three objects, the last two are a waste in the case the row does
0088:               not qualify or the row will be written out by the sorter before being
0089:               returned to the application.
0090:            	<P>
0091:            	This means that this field must be accessed for read indirectly through
0092:            	the getBigDecimal() method, and when setting it the rawData field must
0093:            	be set to null.
0094:
0095:             */
0096:            private BigDecimal value;
0097:
0098:            /**
0099:            	See comments for value
0100:             */
0101:            private byte[] rawData;
0102:
0103:            /**
0104:            	See comments for value
0105:             */
0106:            private int rawScale;
0107:
0108:            private static final int BASE_MEMORY_USAGE = ClassSize
0109:                    .estimateBaseFromCatalog(SQLDecimal.class);
0110:            private static final int BIG_DECIMAL_MEMORY_USAGE = ClassSize
0111:                    .estimateBaseFromCatalog(BigDecimal.class);
0112:
0113:            public int estimateMemoryUsage() {
0114:                int sz = BASE_MEMORY_USAGE;
0115:                if (null != value)
0116:                    sz += BIG_DECIMAL_MEMORY_USAGE
0117:                            + (value.unscaledValue().bitLength() + 8) / 8;
0118:                if (null != rawData)
0119:                    sz += rawData.length;
0120:                return sz;
0121:            }
0122:
0123:            ////////////////////////////////////////////////////////////////////
0124:            //
0125:            // CLASS INTERFACE
0126:            //
0127:            ////////////////////////////////////////////////////////////////////
0128:            /** no-arg constructor, required by Formattable */
0129:            public SQLDecimal() {
0130:            }
0131:
0132:            public SQLDecimal(BigDecimal val) {
0133:                value = val;
0134:            }
0135:
0136:            public SQLDecimal(BigDecimal val, int nprecision, int scale)
0137:                    throws StandardException {
0138:
0139:                value = val;
0140:                if ((value != null) && (scale >= 0)) {
0141:                    value = value.setScale(scale, BigDecimal.ROUND_DOWN);
0142:                }
0143:            }
0144:
0145:            public SQLDecimal(String val) {
0146:                value = new BigDecimal(val);
0147:            }
0148:
0149:            /*
0150:             * DataValueDescriptor interface
0151:             * (mostly implemented in DataType)
0152:             *
0153:             */
0154:
0155:            /**
0156:             * @exception StandardException thrown on failure to convert
0157:             */
0158:            public int getInt() throws StandardException {
0159:                if (isNull())
0160:                    return 0;
0161:
0162:                try {
0163:                    long lv = getLong();
0164:
0165:                    if ((lv >= Integer.MIN_VALUE) && (lv <= Integer.MAX_VALUE))
0166:                        return (int) lv;
0167:
0168:                } catch (StandardException se) {
0169:                }
0170:
0171:                throw StandardException.newException(
0172:                        SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE, "INTEGER");
0173:            }
0174:
0175:            /**
0176:             * @exception StandardException thrown on failure to convert
0177:             */
0178:            public byte getByte() throws StandardException {
0179:                if (isNull())
0180:                    return (byte) 0;
0181:
0182:                try {
0183:                    long lv = getLong();
0184:
0185:                    if ((lv >= Byte.MIN_VALUE) && (lv <= Byte.MAX_VALUE))
0186:                        return (byte) lv;
0187:
0188:                } catch (StandardException se) {
0189:                }
0190:
0191:                throw StandardException.newException(
0192:                        SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE, "TINYINT");
0193:            }
0194:
0195:            /**
0196:             * @exception StandardException thrown on failure to convert
0197:             */
0198:            public short getShort() throws StandardException {
0199:                if (isNull())
0200:                    return (short) 0;
0201:
0202:                try {
0203:                    long lv = getLong();
0204:
0205:                    if ((lv >= Short.MIN_VALUE) && (lv <= Short.MAX_VALUE))
0206:                        return (short) lv;
0207:
0208:                } catch (StandardException se) {
0209:                }
0210:
0211:                throw StandardException.newException(
0212:                        SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE, "SMALLINT");
0213:            }
0214:
0215:            /**
0216:             * @exception StandardException thrown on failure to convert
0217:             */
0218:            public long getLong() throws StandardException {
0219:                BigDecimal localValue = getBigDecimal();
0220:                if (localValue == null)
0221:                    return (long) 0;
0222:
0223:                // Valid range for long is
0224:                //   greater than Long.MIN_VALUE - 1
0225:                // *and*
0226:                //   less than Long.MAX_VALUE + 1
0227:                //
0228:                // This ensures that DECIMAL values with an integral value
0229:                // equal to the Long.MIN/MAX_VALUE round correctly to those values.
0230:                // e.g. 9223372036854775807.1  converts to 9223372036854775807
0231:                // this matches DB2 UDB behaviour
0232:
0233:                if ((localValue.compareTo(SQLDecimal.MINLONG_MINUS_ONE) == 1)
0234:                        && (localValue.compareTo(SQLDecimal.MAXLONG_PLUS_ONE) == -1)) {
0235:
0236:                    return localValue.longValue();
0237:                }
0238:
0239:                throw StandardException.newException(
0240:                        SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE, "BIGINT");
0241:            }
0242:
0243:            /**
0244:             * @exception StandardException thrown on failure to convert
0245:             */
0246:            public float getFloat() throws StandardException {
0247:                BigDecimal localValue = getBigDecimal();
0248:                if (localValue == null)
0249:                    return (float) 0;
0250:
0251:                // If the BigDecimal is out of range for the float
0252:                // then positive or negative infinity is returned.
0253:                float value = NumberDataType.normalizeREAL(localValue
0254:                        .floatValue());
0255:
0256:                return value;
0257:            }
0258:
0259:            /**
0260:             * 
0261:             * If we have a value that is greater than the maximum double,
0262:             * exception is thrown.  Otherwise, ok.  If the value is less
0263:             * than can be represented by a double, ti will get set to
0264:             * the smallest double value.
0265:             *
0266:             * @exception StandardException thrown on failure to convert
0267:             */
0268:            public double getDouble() throws StandardException {
0269:                BigDecimal localValue = getBigDecimal();
0270:                if (localValue == null)
0271:                    return (double) 0;
0272:
0273:                // If the BigDecimal is out of range for double
0274:                // then positive or negative infinity is returned.
0275:                double value = NumberDataType.normalizeDOUBLE(localValue
0276:                        .doubleValue());
0277:                return value;
0278:            }
0279:
0280:            private BigDecimal getBigDecimal() {
0281:                if ((value == null) && (rawData != null)) {
0282:                    value = new BigDecimal(new BigInteger(rawData), rawScale);
0283:                }
0284:
0285:                return value;
0286:            }
0287:
0288:            /**
0289:             * DECIMAL implementation. Convert to a BigDecimal using getObject
0290:             * which will return a BigDecimal
0291:             */
0292:            public int typeToBigDecimal() {
0293:                return java.sql.Types.DECIMAL;
0294:            }
0295:
0296:            // 0 or null is false, all else is true
0297:            public boolean getBoolean() {
0298:
0299:                BigDecimal localValue = getBigDecimal();
0300:                if (localValue == null)
0301:                    return false;
0302:
0303:                return localValue.compareTo(ZERO) != 0;
0304:            }
0305:
0306:            public String getString() {
0307:                BigDecimal localValue = getBigDecimal();
0308:                if (localValue == null)
0309:                    return null;
0310:                else if (JVMInfo.JDK_ID < JVMInfo.J2SE_15)
0311:                    return localValue.toString();
0312:                else {
0313:                    // use reflection so we can still compile using JDK1.4
0314:                    // if we are prepared to require 1.5 to compile then this can be a direct call
0315:                    try {
0316:                        return (String) toPlainString.invoke(localValue, null);
0317:                    } catch (IllegalAccessException e) {
0318:                        // can't happen based on the JDK spec
0319:                        throw new IllegalAccessError("toPlainString");
0320:                    } catch (InvocationTargetException e) {
0321:                        Throwable t = e.getTargetException();
0322:                        if (t instanceof  RuntimeException) {
0323:                            throw (RuntimeException) t;
0324:                        } else if (t instanceof  Error) {
0325:                            throw (Error) t;
0326:                        } else {
0327:                            // can't happen
0328:                            throw new IncompatibleClassChangeError(
0329:                                    "toPlainString");
0330:                        }
0331:                    }
0332:                }
0333:            }
0334:
0335:            private static final Method toPlainString;
0336:            private static final Method bdPrecision;
0337:            static {
0338:                Method m;
0339:                try {
0340:                    m = BigDecimal.class.getMethod("toPlainString", null);
0341:                } catch (NoSuchMethodException e) {
0342:                    m = null;
0343:                }
0344:                toPlainString = m;
0345:                try {
0346:                    m = BigDecimal.class.getMethod("precision", null);
0347:                } catch (NoSuchMethodException e) {
0348:                    m = null;
0349:                }
0350:                bdPrecision = m;
0351:            }
0352:
0353:            public Object getObject() {
0354:                /*
0355:                 ** BigDecimal is immutable
0356:                 */
0357:                return getBigDecimal();
0358:            }
0359:
0360:            /**
0361:             * Set the value from a correctly typed BigDecimal object.
0362:             * @throws StandardException 
0363:             */
0364:            void setObject(Object theValue) throws StandardException {
0365:                setValue((BigDecimal) theValue);
0366:            }
0367:
0368:            protected void setFrom(DataValueDescriptor theValue)
0369:                    throws StandardException {
0370:
0371:                setCoreValue(SQLDecimal.getBigDecimal(theValue));
0372:            }
0373:
0374:            public int getLength() {
0375:                return getDecimalValuePrecision();
0376:            }
0377:
0378:            // this is for DataType's error generator
0379:            public String getTypeName() {
0380:                return TypeId.DECIMAL_NAME;
0381:            }
0382:
0383:            /*
0384:             * Storable interface, implies Externalizable, TypedFormat
0385:             */
0386:
0387:            /**
0388:            	Return my format identifier.
0389:
0390:            	@see org.apache.derby.iapi.services.io.TypedFormat#getTypeFormatId
0391:             */
0392:            public int getTypeFormatId() {
0393:                return StoredFormatIds.SQL_DECIMAL_ID;
0394:            }
0395:
0396:            /*
0397:             * see if the decimal value is null.
0398:             */
0399:            /** @see Storable#isNull */
0400:            public boolean isNull() {
0401:                return (value == null) && (rawData == null);
0402:            }
0403:
0404:            /** 
0405:             * Distill the BigDecimal to a byte array and
0406:             * write out: <UL>
0407:             *	<LI> scale (zero or positive) as a byte </LI>
0408:             *	<LI> length of byte array as a byte</LI>
0409:             *	<LI> the byte array </LI> </UL>
0410:             *
0411:             */
0412:            public void writeExternal(ObjectOutput out) throws IOException {
0413:                // never called when value is null
0414:                if (SanityManager.DEBUG)
0415:                    SanityManager.ASSERT(!isNull());
0416:
0417:                int scale;
0418:                byte[] byteArray;
0419:
0420:                if (value != null) {
0421:                    scale = value.scale();
0422:
0423:                    // J2SE 5.0 introduced negative scale value for BigDecimals.
0424:                    // In previouse Java releases a negative scale was not allowed
0425:                    // (threw an exception on setScale and the constructor that took
0426:                    // a scale).
0427:                    //
0428:                    // Thus the Derby format for DECIMAL implictly assumed a
0429:                    // positive or zero scale value, and thus now must explicitly
0430:                    // be positive. This is to allow databases created under J2SE 5.0
0431:                    // to continue to be supported under JDK 1.3/JDK 1.4, ie. to continue
0432:                    // the platform independence, independent of OS/cpu and JVM.
0433:                    //
0434:                    // If the scale is negative set the scale to be zero, this results
0435:                    // in an unchanged value with a new scale. A BigDecimal with a
0436:                    // negative scale by definition is a whole number.
0437:                    // e.g. 1000 can be represented by:
0438:                    //    a BigDecimal with scale -3 (unscaled value of 1)
0439:                    // or a BigDecimal with scale 0 (unscaled value of 1000)
0440:
0441:                    if (scale < 0) {
0442:                        scale = 0;
0443:                        value = value.setScale(0);
0444:                    }
0445:
0446:                    BigInteger bi = value.unscaledValue();
0447:                    byteArray = bi.toByteArray();
0448:                } else {
0449:                    scale = rawScale;
0450:                    byteArray = rawData;
0451:                }
0452:
0453:                if (SanityManager.DEBUG) {
0454:                    if (scale < 0)
0455:                        SanityManager
0456:                                .THROWASSERT("DECIMAL scale at writeExternal is negative "
0457:                                        + scale + " value " + toString());
0458:                }
0459:
0460:                out.writeByte(scale);
0461:                out.writeByte(byteArray.length);
0462:                out.write(byteArray);
0463:            }
0464:
0465:            /** 
0466:             * Note the use of rawData: we reuse the array if the
0467:             * incoming array is the same length or smaller than
0468:             * the array length.  
0469:             * 
0470:             * @see java.io.Externalizable#readExternal 
0471:             */
0472:            public void readExternal(ObjectInput in) throws IOException {
0473:                // clear the previous value to ensure that the
0474:                // rawData value will be used
0475:                value = null;
0476:
0477:                rawScale = in.readUnsignedByte();
0478:                int size = in.readUnsignedByte();
0479:
0480:                /*
0481:                 ** Allocate a new array if the data to read
0482:                 ** is larger than the existing array, or if
0483:                 ** we don't have an array yet.
0484:
0485:                Need to use readFully below and NOT just read because read does not
0486:                guarantee getting size bytes back, whereas readFully does (unless EOF).
0487:                 */
0488:                if ((rawData == null) || size != rawData.length) {
0489:                    rawData = new byte[size];
0490:                }
0491:                in.readFully(rawData);
0492:
0493:            }
0494:
0495:            public void readExternalFromArray(ArrayInputStream in)
0496:                    throws IOException {
0497:                // clear the previous value to ensure that the
0498:                // rawData value will be used
0499:                value = null;
0500:
0501:                rawScale = in.readUnsignedByte();
0502:                int size = in.readUnsignedByte();
0503:
0504:                /*
0505:                 ** Allocate a new array if the data to read
0506:                 ** is larger than the existing array, or if
0507:                 ** we don't have an array yet.
0508:
0509:                Need to use readFully below and NOT just read because read does not
0510:                guarantee getting size bytes back, whereas readFully does (unless EOF).
0511:                 */
0512:                if ((rawData == null) || size != rawData.length) {
0513:                    rawData = new byte[size];
0514:                }
0515:                in.readFully(rawData);
0516:            }
0517:
0518:            /**
0519:             * @see Storable#restoreToNull
0520:             *
0521:             */
0522:            public void restoreToNull() {
0523:                value = null;
0524:                rawData = null;
0525:            }
0526:
0527:            /** @exception StandardException		Thrown on error */
0528:            protected int typeCompare(DataValueDescriptor arg)
0529:                    throws StandardException {
0530:                BigDecimal otherValue = SQLDecimal.getBigDecimal(arg);
0531:                return getBigDecimal().compareTo(otherValue);
0532:            }
0533:
0534:            /*
0535:             * DataValueDescriptor interface
0536:             */
0537:
0538:            /**
0539:             * <B> WARNING </B> clone is a shallow copy
0540:             * @see DataValueDescriptor#getClone 
0541:             */
0542:            public DataValueDescriptor getClone() {
0543:                return new SQLDecimal(getBigDecimal());
0544:            }
0545:
0546:            /**
0547:             * @see DataValueDescriptor#getNewNull
0548:             */
0549:            public DataValueDescriptor getNewNull() {
0550:                return new SQLDecimal();
0551:            }
0552:
0553:            /** 
0554:             * @see DataValueDescriptor#setValueFromResultSet 
0555:             *
0556:             * @exception SQLException		Thrown on error
0557:             */
0558:            public void setValueFromResultSet(ResultSet resultSet,
0559:                    int colNumber, boolean isNullable) throws SQLException {
0560:                value = resultSet.getBigDecimal(colNumber);
0561:                rawData = null;
0562:            }
0563:
0564:            /**
0565:            	Set the value into a PreparedStatement.
0566:
0567:            	@exception SQLException Error setting value in PreparedStatement
0568:             */
0569:            public final void setInto(PreparedStatement ps, int position)
0570:                    throws SQLException {
0571:
0572:                if (isNull()) {
0573:                    ps.setNull(position, java.sql.Types.DECIMAL);
0574:                    return;
0575:                }
0576:
0577:                ps.setBigDecimal(position, getBigDecimal());
0578:            }
0579:
0580:            /**
0581:             *
0582:             * <B> WARNING </B> there is no checking to make sure
0583:             * that theValue doesn't exceed the precision/scale of
0584:             * the current SQLDecimal.  It is just assumed that the
0585:             * SQLDecimal is supposed to take the precision/scale of
0586:             * the BigDecimalized String.
0587:             *
0588:             * @exception StandardException throws NumberFormatException
0589:             *		when the String format is not recognized.
0590:             */
0591:            public void setValue(String theValue) throws StandardException {
0592:                rawData = null;
0593:
0594:                if (theValue == null) {
0595:                    value = null;
0596:                } else {
0597:                    try {
0598:                        theValue = theValue.trim();
0599:                        value = new BigDecimal(theValue);
0600:                        rawData = null;
0601:                    } catch (NumberFormatException nfe) {
0602:                        throw invalidFormat();
0603:                    }
0604:                }
0605:            }
0606:
0607:            /**
0608:             * @see NumberDataValue#setValue
0609:             *
0610:             * @exception StandardException		Thrown on error
0611:             */
0612:            public void setValue(double theValue) throws StandardException {
0613:                setCoreValue(NumberDataType.normalizeDOUBLE(theValue));
0614:            }
0615:
0616:            /**
0617:             * @see NumberDataValue#setValue
0618:             *
0619:             */
0620:            public void setValue(float theValue) throws StandardException {
0621:                setCoreValue((double) NumberDataType.normalizeREAL(theValue));
0622:            }
0623:
0624:            /**
0625:             * @see NumberDataValue#setValue
0626:             *
0627:             */
0628:            public void setValue(long theValue) {
0629:                value = BigDecimal.valueOf(theValue);
0630:                rawData = null;
0631:            }
0632:
0633:            /**
0634:             * @see NumberDataValue#setValue
0635:             *
0636:             */
0637:            public void setValue(int theValue) {
0638:                setValue((long) theValue);
0639:            }
0640:
0641:            /**
0642:            	Only to be called when the application sets a value using BigDecimal
0643:            	through setBigDecimal calls.
0644:             */
0645:            public void setBigDecimal(Number theValue) throws StandardException {
0646:                setCoreValue((BigDecimal) theValue);
0647:            }
0648:
0649:            /**
0650:            	Called when setting a DECIMAL value internally or from
0651:            	through a procedure or function.
0652:            	Handles long in addition to BigDecimal to handle
0653:            	identity being stored as a long but returned as a DECIMAL.
0654:             */
0655:            public void setValue(Number theValue) throws StandardException {
0656:                if (SanityManager.ASSERT) {
0657:                    if (theValue != null
0658:                            && !(theValue instanceof  java.math.BigDecimal)
0659:                            && !(theValue instanceof  java.lang.Long))
0660:                        SanityManager
0661:                                .THROWASSERT("SQLDecimal.setValue(Number) passed a "
0662:                                        + theValue.getClass());
0663:                }
0664:
0665:                if (theValue instanceof  BigDecimal || theValue == null)
0666:                    setCoreValue((BigDecimal) theValue);
0667:                else
0668:                    setValue(theValue.longValue());
0669:            }
0670:
0671:            /**
0672:             * @see NumberDataValue#setValue
0673:             *
0674:             */
0675:            public void setValue(boolean theValue) {
0676:                setCoreValue(theValue ? ONE : ZERO);
0677:            }
0678:
0679:            /*
0680:             * DataValueDescriptor interface
0681:             */
0682:
0683:            /** @see DataValueDescriptor#typePrecedence */
0684:            public int typePrecedence() {
0685:                return TypeId.DECIMAL_PRECEDENCE;
0686:            }
0687:
0688:            // END DataValueDescriptor interface
0689:
0690:            private void setCoreValue(BigDecimal theValue) {
0691:                value = theValue;
0692:                rawData = null;
0693:            }
0694:
0695:            private void setCoreValue(double theValue) {
0696:                value = new BigDecimal(Double.toString(theValue));
0697:                rawData = null;
0698:            }
0699:
0700:            /**
0701:             * Normalization method - this method may be called when putting
0702:             * a value into a SQLDecimal, for example, when inserting into a SQLDecimal
0703:             * column.  See NormalizeResultSet in execution.
0704:             * <p>
0705:             * Note that truncation is allowed on the decimal portion
0706:             * of a numeric only.	
0707:             *
0708:             * @param desiredType	The type to normalize the source column to
0709:             * @param source		The value to normalize
0710:             *
0711:             * @throws StandardException				Thrown for null into
0712:             *											non-nullable column, and for
0713:             *											truncation error
0714:             */
0715:            public void normalize(DataTypeDescriptor desiredType,
0716:                    DataValueDescriptor source) throws StandardException {
0717:                int desiredScale = desiredType.getScale();
0718:                int desiredPrecision = desiredType.getPrecision();
0719:
0720:                setFrom(source);
0721:                setWidth(desiredPrecision, desiredScale, true);
0722:            }
0723:
0724:            /*
0725:             ** SQL Operators
0726:             */
0727:
0728:            /**
0729:             * This method implements the + operator for DECIMAL.
0730:             *
0731:             * @param addend1	One of the addends
0732:             * @param addend2	The other addend
0733:             * @param result	The result of a previous call to this method, null
0734:             *					if not called yet
0735:             *
0736:             * @return	A SQLDecimal containing the result of the addition
0737:             *
0738:             * @exception StandardException		Thrown on error
0739:             */
0740:
0741:            public NumberDataValue plus(NumberDataValue addend1,
0742:                    NumberDataValue addend2, NumberDataValue result)
0743:                    throws StandardException {
0744:                if (result == null) {
0745:                    result = new SQLDecimal();
0746:                }
0747:
0748:                if (addend1.isNull() || addend2.isNull()) {
0749:                    result.setToNull();
0750:                    return result;
0751:                }
0752:
0753:                result.setBigDecimal(SQLDecimal.getBigDecimal(addend1).add(
0754:                        SQLDecimal.getBigDecimal(addend2)));
0755:                return result;
0756:            }
0757:
0758:            /**
0759:             * This method implements the - operator for "decimal - decimal".
0760:             *
0761:             * @param left	The value to be subtracted from
0762:             * @param right	The value to be subtracted
0763:             * @param result	The result of a previous call to this method, null
0764:             *					if not called yet
0765:             *
0766:             * @return	A SQLDecimal containing the result of the subtraction
0767:             *
0768:             * @exception StandardException		Thrown on error
0769:             */
0770:
0771:            public NumberDataValue minus(NumberDataValue left,
0772:                    NumberDataValue right, NumberDataValue result)
0773:                    throws StandardException {
0774:                if (result == null) {
0775:                    result = new SQLDecimal();
0776:                }
0777:
0778:                if (left.isNull() || right.isNull()) {
0779:                    result.setToNull();
0780:                    return result;
0781:                }
0782:
0783:                result.setBigDecimal(SQLDecimal.getBigDecimal(left).subtract(
0784:                        SQLDecimal.getBigDecimal(right)));
0785:                return result;
0786:            }
0787:
0788:            /**
0789:             * This method implements the * operator for "double * double".
0790:             *
0791:             * @param left	The first value to be multiplied
0792:             * @param right	The second value to be multiplied
0793:             * @param result	The result of a previous call to this method, null
0794:             *					if not called yet
0795:             *
0796:             * @return	A SQLDecimal containing the result of the multiplication
0797:             *
0798:             * @exception StandardException		Thrown on error
0799:             */
0800:
0801:            public NumberDataValue times(NumberDataValue left,
0802:                    NumberDataValue right, NumberDataValue result)
0803:                    throws StandardException {
0804:                if (result == null) {
0805:                    result = new SQLDecimal();
0806:                }
0807:
0808:                if (left.isNull() || right.isNull()) {
0809:                    result.setToNull();
0810:                    return result;
0811:                }
0812:
0813:                result.setBigDecimal(SQLDecimal.getBigDecimal(left).multiply(
0814:                        SQLDecimal.getBigDecimal(right)));
0815:                return result;
0816:            }
0817:
0818:            /**
0819:             * This method implements the / operator for BigDecimal/BigDecimal
0820:             *
0821:             * @param dividend	The numerator
0822:             * @param divisor	The denominator
0823:             * @param result	The result of a previous call to this method, null
0824:             *					if not called yet
0825:             *
0826:             * @return	A SQLDecimal containing the result of the division
0827:             *
0828:             * @exception StandardException		Thrown on error
0829:             */
0830:
0831:            public NumberDataValue divide(NumberDataValue dividend,
0832:                    NumberDataValue divisor, NumberDataValue result)
0833:                    throws StandardException {
0834:                return divide(dividend, divisor, result, -1);
0835:            }
0836:
0837:            /**
0838:             * This method implements the / operator for BigDecimal/BigDecimal
0839:             *
0840:             * @param dividend	The numerator
0841:             * @param divisor	The denominator
0842:             * @param result	The result of a previous call to this method, null
0843:             *					if not called yet
0844:             * @param scale		The result scale, if < 0, calculate the scale according
0845:             *					to the actual values' sizes
0846:             *
0847:             * @return	A SQLDecimal containing the result of the division
0848:             *
0849:             * @exception StandardException		Thrown on error
0850:             */
0851:
0852:            public NumberDataValue divide(NumberDataValue dividend,
0853:                    NumberDataValue divisor, NumberDataValue result, int scale)
0854:                    throws StandardException {
0855:                if (result == null) {
0856:                    result = new SQLDecimal();
0857:                }
0858:
0859:                if (dividend.isNull() || divisor.isNull()) {
0860:                    result.setToNull();
0861:                    return result;
0862:                }
0863:
0864:                BigDecimal divisorBigDecimal = SQLDecimal
0865:                        .getBigDecimal(divisor);
0866:
0867:                if (divisorBigDecimal.compareTo(ZERO) == 0) {
0868:                    throw StandardException
0869:                            .newException(SQLState.LANG_DIVIDE_BY_ZERO);
0870:                }
0871:                BigDecimal dividendBigDecimal = SQLDecimal
0872:                        .getBigDecimal(dividend);
0873:
0874:                /*
0875:                 ** Set the result scale to be either the passed in scale, whcih was
0876:                 ** calculated at bind time to be max(ls+rp-rs+1, 4), where ls,rp,rs
0877:                 ** are static data types' sizes, which are predictable and stable
0878:                 ** (for the whole result set column, eg.); otherwise dynamically
0879:                 ** calculates the scale according to actual values.  Beetle 3901
0880:                 */
0881:                result
0882:                        .setBigDecimal(dividendBigDecimal
0883:                                .divide(
0884:                                        divisorBigDecimal,
0885:                                        scale > -1 ? scale
0886:                                                : Math
0887:                                                        .max(
0888:                                                                (dividendBigDecimal
0889:                                                                        .scale()
0890:                                                                        + SQLDecimal
0891:                                                                                .getWholeDigits(divisorBigDecimal) + 1),
0892:                                                                NumberDataValue.MIN_DECIMAL_DIVIDE_SCALE),
0893:                                        BigDecimal.ROUND_DOWN));
0894:
0895:                return result;
0896:            }
0897:
0898:            /**
0899:             * This method implements the unary minus operator for double.
0900:             *
0901:             * @param result	The result of a previous call to this method, null
0902:             *					if not called yet
0903:             *
0904:             * @return	A SQLDecimal containing the result of the division
0905:             *
0906:             * @exception StandardException		Thrown on error
0907:             */
0908:
0909:            public NumberDataValue minus(NumberDataValue result)
0910:                    throws StandardException {
0911:                if (result == null) {
0912:                    result = new SQLDecimal();
0913:                }
0914:
0915:                if (this .isNull()) {
0916:                    result.setToNull();
0917:                    return result;
0918:                }
0919:
0920:                result.setBigDecimal(getBigDecimal().negate());
0921:                return result;
0922:            }
0923:
0924:            /**
0925:             * This method implements the isNegative method.
0926:             * 
0927:             * @return  A boolean.  If this.value is negative, return true.
0928:             *          For positive values or null, return false.
0929:             */
0930:
0931:            protected boolean isNegative() {
0932:                return !isNull() && (getBigDecimal().compareTo(ZERO) == -1);
0933:            }
0934:
0935:            /*
0936:             * String display of value
0937:             */
0938:            public String toString() {
0939:                if (isNull())
0940:                    return "NULL";
0941:                else
0942:                    return getString();
0943:            }
0944:
0945:            /*
0946:             * Hash code
0947:             */
0948:            public int hashCode() {
0949:                long longVal;
0950:                BigDecimal localValue = getBigDecimal();
0951:
0952:                double doubleVal = (localValue != null) ? localValue
0953:                        .doubleValue() : 0;
0954:
0955:                if (Double.isInfinite(doubleVal)) {
0956:                    /*
0957:                     ** This loses the fractional part, but it probably doesn't
0958:                     ** matter for numbers that are big enough to overflow a double -
0959:                     ** it's probably rare for numbers this big to be different only in
0960:                     ** their fractional parts.
0961:                     */
0962:                    longVal = localValue.longValue();
0963:                } else {
0964:                    longVal = (long) doubleVal;
0965:                    if (longVal != doubleVal) {
0966:                        longVal = Double.doubleToLongBits(doubleVal);
0967:                    }
0968:                }
0969:
0970:                return (int) (longVal ^ (longVal >> 32));
0971:            }
0972:
0973:            ///////////////////////////////////////////////////////////////////////////////
0974:            //
0975:            // VariableSizeDataValue interface
0976:            //
0977:            ///////////////////////////////////////////////////////////////////////////////
0978:
0979:            /**
0980:             * Set the precision/scale of the to the desired values. 
0981:             * Used when CASTing.  Ideally we'd recycle normalize(), but
0982:             * the use is different.  
0983:             *
0984:             * @param desiredPrecision	the desired precision -- IGNORE_PREICISION
0985:             *					if it is to be ignored.
0986:             * @param desiredScale	the desired scale 
0987:             * @param errorOnTrunc	throw error on truncation (ignored -- 
0988:             *		always thrown if we truncate the non-decimal part of
0989:             *		the value)
0990:             *
0991:             * @exception StandardException		Thrown on non-zero truncation
0992:             *		if errorOnTrunc is true	
0993:             */
0994:            public void setWidth(int desiredPrecision, int desiredScale,
0995:                    boolean errorOnTrunc) throws StandardException {
0996:                if (isNull())
0997:                    return;
0998:
0999:                if (desiredPrecision != IGNORE_PRECISION
1000:                        && ((desiredPrecision - desiredScale) < SQLDecimal
1001:                                .getWholeDigits(getBigDecimal()))) {
1002:                    throw StandardException.newException(
1003:                            SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE,
1004:                            ("DECIMAL/NUMERIC(" + desiredPrecision + ","
1005:                                    + desiredScale + ")"));
1006:                }
1007:                value = value.setScale(desiredScale, BigDecimal.ROUND_DOWN);
1008:                rawData = null;
1009:            }
1010:
1011:            /**
1012:             * Return the SQL scale of this value, number of digits after the
1013:             * decimal point, or zero for a whole number. This does not match the
1014:             * return from BigDecimal.scale() since in J2SE 5.0 onwards that can return
1015:             * negative scales.
1016:             */
1017:            public int getDecimalValuePrecision() {
1018:                if (isNull())
1019:                    return 0;
1020:
1021:                BigDecimal localValue = getBigDecimal();
1022:
1023:                return SQLDecimal.getWholeDigits(localValue)
1024:                        + getDecimalValueScale();
1025:            }
1026:
1027:            /**
1028:             * Return the SQL scale of this value, number of digits after the
1029:             * decimal point, or zero for a whole number. This does not match the
1030:             * return from BigDecimal.scale() since in J2SE 5.0 onwards that can return
1031:             * negative scales.
1032:             */
1033:            public int getDecimalValueScale() {
1034:                if (isNull())
1035:                    return 0;
1036:
1037:                if (value == null)
1038:                    return rawScale;
1039:
1040:                int scale = value.scale();
1041:                if (scale >= 0)
1042:                    return scale;
1043:
1044:                // BigDecimal scale is negative, so number must have no fractional
1045:                // part as its value is the unscaled value * 10^-scale
1046:                return 0;
1047:            }
1048:
1049:            /**
1050:             * Get a BigDecimal representing the value of a DataValueDescriptor
1051:             * @param value Non-null value to be converted
1052:             * @return BigDecimal value
1053:             * @throws StandardException Invalid conversion or out of range.
1054:             */
1055:            public static BigDecimal getBigDecimal(DataValueDescriptor value)
1056:                    throws StandardException {
1057:                if (SanityManager.DEBUG) {
1058:                    if (value.isNull())
1059:                        SanityManager
1060:                                .THROWASSERT("NULL value passed to SQLDecimal.getBigDecimal");
1061:                }
1062:
1063:                switch (value.typeToBigDecimal()) {
1064:                case Types.DECIMAL:
1065:                    return (BigDecimal) value.getObject();
1066:                case Types.CHAR:
1067:                    try {
1068:                        return new BigDecimal(value.getString().trim());
1069:                    } catch (NumberFormatException nfe) {
1070:                        throw StandardException.newException(
1071:                                SQLState.LANG_FORMAT_EXCEPTION,
1072:                                "java.math.BigDecimal");
1073:                    }
1074:                case Types.BIGINT:
1075:                    return BigDecimal.valueOf(value.getLong());
1076:                default:
1077:                    if (SanityManager.DEBUG)
1078:                        SanityManager.THROWASSERT("invalid return from "
1079:                                + value.getClass() + ".typeToBigDecimal() "
1080:                                + value.typeToBigDecimal());
1081:                    return null;
1082:                }
1083:            }
1084:
1085:            /**
1086:             * Calculate the number of digits to the left of the decimal point
1087:             * of the passed in value.
1088:             * @param decimalValue Value to get whole digits from, never null.
1089:             * @return number of whole digits.
1090:             */
1091:            private static int getWholeDigits(BigDecimal decimalValue) {
1092:                /**
1093:                 * if ONE > abs(value) then the number of whole digits is 0
1094:                 */
1095:                decimalValue = decimalValue.abs();
1096:                if (ONE.compareTo(decimalValue) == 1) {
1097:                    return 0;
1098:                }
1099:
1100:                if (JVMInfo.JDK_ID >= JVMInfo.J2SE_15) {
1101:                    // use reflection so we can still compile using JDK1.4
1102:                    // if we are prepared to require 1.5 to compile then this can be a
1103:                    // direct call
1104:                    try {
1105:                        // precision is the number of digits in the unscaled value,
1106:                        // subtracting the scale (positive or negative) will give the
1107:                        // number of whole digits.
1108:                        int precision = ((Integer) bdPrecision.invoke(
1109:                                decimalValue, null)).intValue();
1110:                        return precision - decimalValue.scale();
1111:                    } catch (IllegalAccessException e) {
1112:                        // can't happen based on the JDK spec
1113:                        throw new IllegalAccessError("precision");
1114:                    } catch (InvocationTargetException e) {
1115:                        Throwable t = e.getTargetException();
1116:                        if (t instanceof  RuntimeException) {
1117:                            throw (RuntimeException) t;
1118:                        } else if (t instanceof  Error) {
1119:                            throw (Error) t;
1120:                        } else {
1121:                            // can't happen
1122:                            throw new IncompatibleClassChangeError("precision");
1123:                        }
1124:                    }
1125:
1126:                }
1127:
1128:                String s = decimalValue.toString();
1129:                return (decimalValue.scale() == 0) ? s.length() : s
1130:                        .indexOf('.');
1131:            }
1132:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.