001: /*
002:
003: Derby - Class org.apache.derby.impl.sql.compile.BaseTypeCompiler
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to you under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.impl.sql.compile;
023:
024: import org.apache.derby.iapi.reference.SQLState;
025: import org.apache.derby.iapi.services.loader.ClassFactory;
026:
027: import org.apache.derby.iapi.services.sanity.SanityManager;
028:
029: import org.apache.derby.iapi.error.StandardException;
030: import org.apache.derby.iapi.sql.conn.ConnectionUtil;
031:
032: import org.apache.derby.iapi.sql.compile.TypeCompiler;
033:
034: import org.apache.derby.iapi.types.BitDataValue;
035: import org.apache.derby.iapi.types.DataValueFactory;
036: import org.apache.derby.iapi.types.DataValueDescriptor;
037: import org.apache.derby.iapi.types.TypeId;
038:
039: import org.apache.derby.iapi.types.DataTypeDescriptor;
040:
041: import org.apache.derby.iapi.reference.SQLState;
042: import org.apache.derby.iapi.reference.ClassName;
043:
044: import org.apache.derby.iapi.services.compiler.LocalField;
045: import org.apache.derby.iapi.services.compiler.MethodBuilder;
046:
047: import org.apache.derby.iapi.services.classfile.VMOpcode;
048:
049: import java.sql.Types;
050:
051: /**
052: * This is the base implementation of TypeCompiler
053: *
054: * @author Jeff
055: */
056:
057: abstract class BaseTypeCompiler implements TypeCompiler {
058: private TypeId correspondingTypeId;
059:
060: /**
061: * Get the method name for getting out the corresponding primitive
062: * Java type.
063: *
064: * @return String The method call name for getting the
065: * corresponding primitive Java type.
066: */
067: public String getPrimitiveMethodName() {
068: if (SanityManager.DEBUG) {
069: SanityManager
070: .THROWASSERT("getPrimitiveMethodName not applicable for "
071: + getClass().toString());
072: }
073: return null;
074: }
075:
076: /** @see TypeCompiler#getMatchingNationalCharTypeName */
077: public String getMatchingNationalCharTypeName() {
078: return TypeId.NATIONAL_CHAR_NAME;
079: }
080:
081: /**
082: * @see TypeCompiler#resolveArithmeticOperation
083: *
084: * @exception StandardException Thrown on error
085: */
086: public DataTypeDescriptor resolveArithmeticOperation(
087: DataTypeDescriptor leftType, DataTypeDescriptor rightType,
088: String operator) throws StandardException {
089: throw StandardException.newException(
090: SQLState.LANG_BINARY_OPERATOR_NOT_SUPPORTED, operator,
091: leftType.getTypeId().getSQLTypeName(), rightType
092: .getTypeId().getSQLTypeName());
093: }
094:
095: /** @see TypeCompiler#generateNull */
096:
097: public void generateNull(MethodBuilder mb) {
098: mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null,
099: nullMethodName(), interfaceName(), 1);
100: }
101:
102: /** @see TypeCompiler#generateDataValue */
103: public void generateDataValue(MethodBuilder mb, LocalField field) {
104: String interfaceName = interfaceName();
105:
106: // push the second argument
107:
108: /* If fieldName is null, then there is no
109: * reusable wrapper (null), else we
110: * reuse the field.
111: */
112: if (field == null) {
113: mb.pushNull(interfaceName);
114: } else {
115: mb.getField(field);
116: }
117:
118: mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null,
119: dataValueMethodName(), interfaceName, 2);
120:
121: if (field != null) {
122: /* Store the result of the method call in the field,
123: * so we can re-use the wrapper.
124: */
125: mb.putField(field);
126: }
127: }
128:
129: protected abstract String nullMethodName();
130:
131: /**
132: Return the method name to get a Derby DataValueDescriptor
133: object of the correct type. This implementation returns "getDataValue".
134: */
135: protected String dataValueMethodName() {
136: return "getDataValue";
137: }
138:
139: /**
140: * Determine whether thisType is storable in otherType due to otherType
141: * being a user type.
142: *
143: * @param thisType The TypeId of the value to be stored
144: * @param otherType The TypeId of the value to be stored in
145: *
146: * @return true if thisType is storable in otherType
147: */
148: protected boolean userTypeStorable(TypeId this Type,
149: TypeId otherType, ClassFactory cf) {
150: /*
151: ** If the other type is user-defined, use the java types to determine
152: ** assignability.
153: */
154: if (otherType.userType()) {
155: return cf.getClassInspector().assignableTo(
156: this Type.getCorrespondingJavaTypeName(),
157: otherType.getCorrespondingJavaTypeName());
158: }
159:
160: return false;
161: }
162:
163: /**
164: * Tell whether this numeric type can be compared to the given type.
165: *
166: * @param otherType The TypeId of the other type.
167: */
168:
169: public boolean numberComparable(TypeId otherType,
170: boolean forEquals, ClassFactory cf) {
171: TypeCompiler otherTC = getTypeCompiler(otherType);
172:
173: /* Numbers can be compared to other numbers,
174: * boolean and objects
175: */
176: return otherType.isNumericTypeId()
177: || otherType.isBooleanTypeId()
178: || (otherType.userType() && otherTC.comparable(
179: otherType, forEquals, cf));
180: }
181:
182: /**
183: * Tell whether this numeric type can be converted to the given type.
184: *
185: * @param otherType The TypeId of the other type.
186: * @param forDataTypeFunction was this called from a scalarFunction like
187: * CHAR() or DOUBLE()
188: */
189: public boolean numberConvertible(TypeId otherType,
190: boolean forDataTypeFunction) {
191:
192: // Can't convert numbers to long types
193: if (otherType.isLongConcatableTypeId())
194: return false;
195:
196: // Numbers can only be converted to other numbers,
197: // and CHAR, (not VARCHARS or LONGVARCHAR).
198: // Only with the CHAR() or VARCHAR()function can they be converted.
199: boolean retval = ((otherType.isNumericTypeId())
200: || (otherType.isBooleanTypeId()) || (otherType
201: .userType()));
202:
203: // For CHAR Conversions, function can convert
204: // Floating types
205: if (forDataTypeFunction)
206: retval = retval
207: || (otherType.isFixedStringTypeId() && (getTypeId()
208: .isFloatingPointTypeId()));
209:
210: retval = retval
211: || (otherType.isFixedStringTypeId() && (!getTypeId()
212: .isFloatingPointTypeId()));
213:
214: return retval;
215:
216: }
217:
218: /**
219: * Tell whether this numeric type can be stored into from the given type.
220: *
221: * @param thisType The TypeId of this type
222: * @param otherType The TypeId of the other type.
223: * @param cf A ClassFactory
224: */
225:
226: public boolean numberStorable(TypeId this Type, TypeId otherType,
227: ClassFactory cf) {
228: /*
229: ** Numbers can be stored into from other number types.
230: ** Also, user types with compatible classes can be stored into numbers.
231: */
232: if ((otherType.isNumericTypeId())
233: || (otherType.isBooleanTypeId()))
234: return true;
235:
236: /*
237: ** If the other type is user-defined, use the java types to determine
238: ** assignability.
239: */
240: return userTypeStorable(this Type, otherType, cf);
241: }
242:
243: /**
244: * Get the TypeId that corresponds to this TypeCompiler.
245: */
246: protected TypeId getTypeId() {
247: return correspondingTypeId;
248: }
249:
250: /**
251: * Get the TypeCompiler that corresponds to the given TypeId.
252: */
253: protected TypeCompiler getTypeCompiler(TypeId typeId) {
254: return TypeCompilerFactoryImpl.staticGetTypeCompiler(typeId);
255: }
256:
257: /**
258: * Set the TypeCompiler that corresponds to the given TypeId.
259: */
260: void setTypeId(TypeId typeId) {
261: correspondingTypeId = typeId;
262: }
263:
264: /**
265: * Get the StoredFormatId from the corresponding
266: * TypeId.
267: *
268: * @return The StoredFormatId from the corresponding
269: * TypeId.
270: */
271: protected int getStoredFormatIdFromTypeId() {
272: return getTypeId().getTypeFormatId();
273: }
274:
275: }
|