KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > impl > sql > compile > ConcatenationOperatorNode


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.compile.ConcatenationOperatorNode
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to you under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20  */

21
22 package org.apache.derby.impl.sql.compile;
23
24 import org.apache.derby.iapi.sql.compile.C_NodeTypes;
25
26 import org.apache.derby.iapi.services.sanity.SanityManager;
27
28 import org.apache.derby.iapi.error.StandardException;
29
30 import org.apache.derby.iapi.sql.dictionary.DataDictionary;
31 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
32 import org.apache.derby.iapi.types.TypeId;
33
34 import org.apache.derby.iapi.types.ConcatableDataValue;
35 import org.apache.derby.iapi.types.BitDataValue;
36
37 import org.apache.derby.iapi.sql.compile.TypeCompiler;
38 import org.apache.derby.iapi.types.DataTypeDescriptor;
39
40 import org.apache.derby.iapi.services.compiler.MethodBuilder;
41 import org.apache.derby.iapi.services.compiler.LocalField;
42 import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
43
44 import org.apache.derby.iapi.reference.Limits;
45 import org.apache.derby.iapi.reference.SQLState;
46 import org.apache.derby.iapi.reference.ClassName;
47
48 import java.sql.Types JavaDoc;
49
50 import java.util.Vector JavaDoc;
51
52
53 /**
54  * This node represents a concatenation comparison operator
55  *
56  * @author Jerry Brenner -- modified by jamie for bit and bit
57  * varying.
58  */

59
60 public class ConcatenationOperatorNode extends BinaryOperatorNode
61 {
62     /**
63      * Initializer for a ConcatenationOperatorNode
64      *
65      * @param leftOperand The left operand of the concatenation
66      * @param rightOperand The right operand of the concatenation
67      */

68     public void init(Object JavaDoc leftOperand, Object JavaDoc rightOperand)
69     {
70         super.init(leftOperand, rightOperand, "||", "concatenate",
71                 ClassName.ConcatableDataValue, ClassName.ConcatableDataValue);
72     }
73
74     /**
75      * overrides BindOperatorNode.bindExpression because concatenation has special
76      * requirements for parameter binding.
77      *
78      * @exception StandardException thrown on failure
79      */

80     public ValueNode bindExpression(
81         FromList fromList, SubqueryList subqueryList,
82         Vector JavaDoc aggregateVector)
83             throws StandardException
84     {
85         // deal with binding operands
86
leftOperand = leftOperand.bindExpression(fromList, subqueryList,
87             aggregateVector);
88         rightOperand = rightOperand.bindExpression(fromList, subqueryList,
89             aggregateVector);
90
91         // deal with operand parameters
92
/*
93             Is there a ? parameter on the left?
94             If so, it's type is the type of the other parameter, with
95             maximum length for that type.
96         */

97
98         if (leftOperand.requiresTypeFromContext())
99         {
100             if (rightOperand.requiresTypeFromContext())
101             {
102                 throw StandardException.newException(SQLState.LANG_BINARY_OPERANDS_BOTH_PARMS,
103                                                                     operator);
104             }
105
106             TypeId leftType;
107
108             /*
109             ** A ? on the left gets its type from the right. There are eight
110             ** legal types for the concatenation operator: CHAR, VARCHAR,
111             ** LONG VARCHAR, CLOB, BIT, BIT VARYING, LONG BIT VARYING, and BLOB.
112             ** If the right type is BLOB, set the parameter type to BLOB with max length.
113             ** If the right type is one of the other bit types, set the parameter type to
114             ** BIT VARYING with maximum length.
115             **
116             ** If the right type is CLOB, set parameter type to CLOB with max length.
117             ** If the right type is anything else, set it to VARCHAR with
118             ** maximum length. We count on the resolveConcatOperation method to
119             ** catch an illegal type.
120             **
121             ** NOTE: When I added the long types, I could have changed the
122             ** resulting parameter types to LONG VARCHAR and LONG BIT VARYING,
123             ** but they were already VARCHAR and BIT VARYING, and it wasn't
124             ** clear to me what effect it would have to change it. - Jeff
125             */

126             if (rightOperand.getTypeId().isBitTypeId())
127             {
128                 if (rightOperand.getTypeId().isBlobTypeId())
129                     leftType = TypeId.getBuiltInTypeId(Types.BLOB);
130                 else
131                     leftType = TypeId.getBuiltInTypeId(Types.VARBINARY);
132             }
133             else
134             {
135                 if (rightOperand.getTypeId().isClobTypeId())
136                     leftType = TypeId.getBuiltInTypeId(Types.CLOB);
137                 else
138                     leftType = TypeId.getBuiltInTypeId(Types.VARCHAR);
139             }
140
141         leftOperand.setType(new DataTypeDescriptor(leftType, true));
142         }
143
144         /*
145             Is there a ? parameter on the right?
146         */

147         if (rightOperand.requiresTypeFromContext())
148         {
149             TypeId rightType;
150
151             /*
152             ** A ? on the right gets its type from the left. There are eight
153             ** legal types for the concatenation operator: CHAR, VARCHAR,
154             ** LONG VARCHAR, CLOB, BIT, BIT VARYING, LONG BIT VARYING, and BLOB.
155             ** If the left type is BLOB, set the parameter type to BLOB with max length.
156             ** If the left type is one of the other bit types, set the parameter type to
157             ** BIT VARYING with maximum length.
158             **
159             ** If the left type is CLOB, set parameter type to CLOB with max length.
160             ** If the left type is anything else, set it to VARCHAR with
161             ** maximum length. We count on the resolveConcatOperation method to
162             ** catch an illegal type.
163             **
164             ** NOTE: When I added the long types, I could have changed the
165             ** resulting parameter types to LONG VARCHAR and LONG BIT VARYING,
166             ** but they were already VARCHAR and BIT VARYING, and it wasn't
167             ** clear to me what effect it would have to change it. - Jeff
168             */

169             if (leftOperand.getTypeId().isBitTypeId())
170             {
171                 if (leftOperand.getTypeId().isBlobTypeId())
172                     rightType = TypeId.getBuiltInTypeId(Types.BLOB);
173                 else
174                     rightType = TypeId.getBuiltInTypeId(Types.VARBINARY);
175             }
176             else
177             {
178                 if (leftOperand.getTypeId().isClobTypeId())
179                     rightType = TypeId.getBuiltInTypeId(Types.CLOB);
180                 else
181                     rightType = TypeId.getBuiltInTypeId(Types.VARCHAR);
182             }
183         
184         rightOperand.setType(
185                             new DataTypeDescriptor(
186                                         rightType,
187                                         true));
188         }
189
190         /* If the left operand is not a built-in type, then generate a bound conversion
191          * tree to a built-in type.
192          */

193         if (leftOperand.getTypeId().userType())
194         {
195             leftOperand = leftOperand.genSQLJavaSQLTree();
196         }
197
198         /* If the right operand is not a built-in type, then generate a bound conversion
199          * tree to a built-in type.
200          */

201         if (rightOperand.getTypeId().userType())
202         {
203             rightOperand = rightOperand.genSQLJavaSQLTree();
204         }
205
206         /* If either the left or right operands are non-string, non-bit types,
207          * then we generate an implicit cast to VARCHAR.
208          */

209         TypeCompiler tc = leftOperand.getTypeCompiler();
210         if (! (leftOperand.getTypeId().isStringTypeId() || leftOperand.getTypeId().isBitTypeId()))
211         {
212             leftOperand = (ValueNode)
213                     getNodeFactory().getNode(
214                         C_NodeTypes.CAST_NODE,
215                         leftOperand,
216                         DataTypeDescriptor.getBuiltInDataTypeDescriptor(Types.VARCHAR, true,
217                                             tc.getCastToCharWidth(
218                                                 leftOperand.getTypeServices())),
219                         getContextManager());
220             ((CastNode) leftOperand).bindCastNodeOnly();
221         }
222         tc = rightOperand.getTypeCompiler();
223         if (! (rightOperand.getTypeId().isStringTypeId() || rightOperand.getTypeId().isBitTypeId()))
224         {
225             rightOperand = (ValueNode)
226                     getNodeFactory().getNode(
227                         C_NodeTypes.CAST_NODE,
228                         rightOperand,
229                         DataTypeDescriptor.getBuiltInDataTypeDescriptor(Types.VARCHAR, true,
230                                             tc.getCastToCharWidth(
231                                                 rightOperand.getTypeServices())),
232                         getContextManager());
233             ((CastNode) rightOperand).bindCastNodeOnly();
234         }
235
236
237         /*
238         ** Set the result type of this operator based on the operands.
239         ** By convention, the left operand gets to decide the result type
240         ** of a binary operator.
241         */

242         tc = leftOperand.getTypeCompiler();
243         setType(resolveConcatOperation(
244                         leftOperand.getTypeServices(),
245                         rightOperand.getTypeServices()));
246
247         /*
248         ** Make sure the maximum width set for the result doesn't exceed the result type's maximum width
249         */

250         if (SanityManager.DEBUG)
251         {
252             if (getTypeServices().getMaximumWidth() > getTypeId().getMaximumMaximumWidth())
253             {
254                 SanityManager.THROWASSERT("The maximum length " + getTypeServices().getMaximumWidth() +
255                         " for the result type " + getTypeId().getSQLTypeName() +
256                         " can't be greater than it's maximum width of result's typeid" + getTypeId().getMaximumMaximumWidth());
257             }
258         }
259
260         /*
261         ** Now that we know the target interface type, set it. This assumes
262         ** that both operands have the same interface type, which is a safe
263         ** assumption for the concatenation operator.
264         */

265         this.setLeftRightInterfaceType(tc.interfaceName());
266
267         return this;
268     }
269
270     /**
271      * Resolve a concatenation operator
272      *
273      * @param leftType The DataTypeDescriptor of the left operand
274      * @param rightType The DataTypeDescriptor of the right operand
275      *
276      * @return A DataTypeDescriptor telling the result type of the
277      * concatenate operation
278      *
279      * @exception StandardException BinaryOperatorNotSupported
280      * Thrown when a BinaryOperator is not supported
281      * on the operand types.
282      */

283     private DataTypeDescriptor resolveConcatOperation(
284                                 DataTypeDescriptor leftType,
285                                 DataTypeDescriptor rightType
286                             ) throws StandardException
287     {
288         TypeId leftTypeId;
289         TypeId rightTypeId;
290         String JavaDoc higherType;
291         int resultLength;
292         boolean nullable;
293
294         leftTypeId = leftType.getTypeId();
295         rightTypeId = rightType.getTypeId();
296
297         /*
298         ** Check the right type to be sure it's a concatable. By convention,
299         ** we call this method off the TypeId of the left operand, so if
300         ** we get here, we know the left operand is a concatable.
301         */

302         /*
303         ** Make sure we haven't been given a char and a
304         ** bit to concatenate.
305         */

306
307         if (!leftTypeId.isConcatableTypeId()
308             || !rightTypeId.isConcatableTypeId()
309             || (rightTypeId.isBitTypeId() && leftTypeId.isStringTypeId())
310             || (leftTypeId.isBitTypeId() && rightTypeId.isStringTypeId()))
311                 throw StandardException.newException(SQLState.LANG_DB2_FUNCTION_INCOMPATIBLE, "||", "FUNCTION");
312
313         /*
314         ** The types aren't the same. The result of the operation is the
315         ** type of higher precedence.
316         */

317     
318         higherType = (leftTypeId.typePrecedence() >=
319                                     rightTypeId.typePrecedence()) ?
320                 leftType.getTypeName() : rightType.getTypeName();
321
322         /* Get the length of the result */
323         resultLength = leftType.getMaximumWidth() +
324                        rightType.getMaximumWidth();
325
326         /*
327         ** Use following chart to handle overflow
328         ** operands CHAR(A) CHAR(B) and A+B<255 then result is CHAR(A+B)
329         ** operands CHAR FOR BIT DATA(A) CHAR FOR BIT DATA(B) and A+B<255 then result is CHAR FOR BIT DATA(A+B)
330         **
331         ** operands CHAR(A) CHAR(B) and A+B>254 then result is VARCHAR(A+B)
332         ** operands CHAR FOR BIT DATA(A) CHAR FOR BIT DATA(B) and A+B>254 then result is VARCHAR FOR BIT DATA(A+B)
333         **
334         ** operands CHAR(A) VARCHAR(B) and A+B<4001 then result is VARCHAR(A+B)
335         ** operands CHAR FOR BIT DATA(A) VARCHAR FOR BIT DATA(B) and A+B<4001 then result is VARCHAR FOR BIT DATA(A+B)
336         **
337         ** operands CHAR(A) VARCHAR(B) and A+B>4000 then result is LONG VARCHAR
338         ** operands CHAR FOR BIT DATA(A) VARCHAR FOR BIT DATA(B) and A+B>4000 then result is LONG VARCHAR FOR BIT DATA
339         **
340         ** operands CHAR(A) LONG VARCHAR then result is LONG VARCHAR
341         ** operands CHAR FOR BIT DATA(A) LONG VARCHAR FOR BIT DATA then result is LONG VARCHAR FOR BIT DATA
342         **
343         ** operands VARCHAR(A) VARCHAR(B) and A+B<4001 then result is VARCHAR(A+B)
344         ** operands VARCHAR FOR BIT DATA(A) VARCHAR FOR BIT DATA(B) and A+B<4001 then result is VARCHAR FOR BIT DATA(A+B)
345         **
346         ** operands VARCHAR(A) VARCHAR(B) and A+B>4000 then result is LONG VARCHAR
347         ** operands VARCHAR FOR BIT DATA(A) VARCHAR FOR BIT DATA(B) and A+B>4000 then result is LONG VARCHAR FOR BIT DATA
348         **
349         ** operands VARCHAR(A) LONG VARCHAR then result is LONG VARCHAR
350         ** operands VARCHAR FOR BIT DATA(A) LONG VARCHAR FOR BIT DATA then result is LONG VARCHAR FOR BIT DATA
351         **
352         ** operands LONG VARCHAR, LONG VARCHAR then result is LONG VARCHAR
353         ** operands LONG VARCHAR FOR BIT DATA, LONG VARCHAR FOR BIT DATA then result is LONG VARCHAR FOR BIT DATA
354         **
355         ** operands CLOB(A), CHAR(B) then result is CLOB(MIN(A+B,2G))
356         ** operands CLOB(A), VARCHAR(B) then result is CLOB(MIN(A+B,2G))
357         ** operands CLOB(A), LONG VARCHAR then result is CLOB(MIN(A+32K,2G))
358         ** operands CLOB(A), CLOB(B) then result is CLOB(MIN(A+B,2G))
359         **
360         ** operands BLOB(A), CHAR FOR BIT DATA(B) then result is BLOB(MIN(A+B,2G))
361         ** operands BLOB(A), VARCHAR FOR BIT DATA(B) then result is BLOB(MIN(A+B,2G))
362         ** operands BLOB(A), LONG VARCHAR FOR BIT DATA then result is BLOB(MIN(A+32K,2G))
363         ** operands BLOB(A), BLOB(B) then result is BLOB(MIN(A+B,2G))
364         **
365         ** operands CHAR(A)/VARCHAR(A)/LONGVARCHAR, LONGVARCHAR and "concatenated string length">32700 does not cause automatic escalation
366         ** to LOB for compatibility with previous releases. Any such cases would result in an error at runtime
367         **
368         */

369         //in the following code, I can assume that left and right operands both will be either char kind
370
//of datatypes or they will be both binary kind of datatypes. That's because operand datatypes
371
//mismatch has already been handled earlier
372
if (leftTypeId.getJDBCTypeId() == Types.CHAR || leftTypeId.getJDBCTypeId() == Types.BINARY)
373         {
374             switch (rightTypeId.getJDBCTypeId())
375             {
376                 case Types.CHAR:
377                 case Types.BINARY:
378                     if (resultLength > Limits.DB2_CHAR_MAXWIDTH) {
379                         if (rightTypeId.getJDBCTypeId() == Types.CHAR)
380                                 //operands CHAR(A) CHAR(B) and A+B>254 then result is VARCHAR(A+B)
381
higherType = TypeId.VARCHAR_NAME;
382                         else
383                                 //operands CHAR FOR BIT DATA(A) CHAR FOR BIT DATA(B) and A+B>254 then result is VARCHAR FOR BIT DATA(A+B)
384
higherType = TypeId.VARBIT_NAME;
385                     }
386                     break;
387
388                 case Types.VARCHAR:
389                 case Types.VARBINARY:
390                     if (resultLength > Limits.DB2_CONCAT_VARCHAR_LENGTH) {
391                         if (rightTypeId.getJDBCTypeId() == Types.VARCHAR)
392                                 //operands CHAR(A) VARCHAR(B) and A+B>4000 then result is LONG VARCHAR
393
higherType = TypeId.LONGVARCHAR_NAME;
394                         else
395                                 //operands CHAR FOR BIT DATA(A) VARCHAR FOR BIT DATA(B) and A+B>4000 then result is LONG VARCHAR FOR BIT DATA
396
higherType = TypeId.LONGVARBIT_NAME;
397                     }
398                     break;
399
400                 case Types.CLOB:
401                 case Types.BLOB:
402                     //operands CHAR(A), CLOB(B) then result is CLOB(MIN(A+B,2G))
403
//operands CHAR FOR BIT DATA(A), BLOB(B) then result is BLOB(MIN(A+B,2G))
404
resultLength = clobBlobHandling(rightType, leftType);
405                     break;
406             }
407         } else if (leftTypeId.getJDBCTypeId() == Types.VARCHAR) {
408             switch (rightTypeId.getJDBCTypeId())
409             {
410                 case Types.CHAR: //operands CHAR(A) VARCHAR(B) and A+B>4000 then result is LONG VARCHAR
411
case Types.VARCHAR: //operands VARCHAR(A) VARCHAR(B) and A+B>4000 then result is LONG VARCHAR
412
if (resultLength > Limits.DB2_CONCAT_VARCHAR_LENGTH)
413                         higherType = TypeId.LONGVARCHAR_NAME;
414                     break;
415
416                 case Types.CLOB:
417                     //operands VARCHAR(A), CLOB(B) then result is CLOB(MIN(A+B,2G))
418
resultLength = clobBlobHandling(rightType, leftType);
419                     break;
420             }
421         } else if (leftTypeId.getJDBCTypeId() == Types.VARBINARY) {
422             switch (rightTypeId.getJDBCTypeId())
423             {
424                 case Types.BINARY: //operands CHAR FOR BIT DATA(A) VARCHAR FOR BIT DATA(B) and A+B>4000 then result is LONG VARCHAR FOR BIT DATA
425
case Types.VARBINARY://operands VARCHAR FOR BIT DATA(A) VARCHAR FOR BIT DATA(B) and A+B>4000 then result is LONG VARCHAR FOR BIT DATA
426
if (resultLength > Limits.DB2_CONCAT_VARCHAR_LENGTH)
427                         higherType = TypeId.LONGVARBIT_NAME;
428                     break;
429
430                 case Types.BLOB:
431                     //operands VARCHAR FOR BIT DATA(A), BLOB(B) then result is BLOB(MIN(A+B,2G))
432
resultLength = clobBlobHandling(rightType, leftType);
433                     break;
434             }
435         } else if (leftTypeId.getJDBCTypeId() == Types.CLOB || leftTypeId.getJDBCTypeId() == Types.BLOB) {
436             //operands CLOB(A), CHAR(B) then result is CLOB(MIN(A+B,2G))
437
//operands CLOB(A), VARCHAR(B) then result is CLOB(MIN(A+B,2G))
438
//operands CLOB(A), LONG VARCHAR then result is CLOB(MIN(A+32K,2G))
439
//operands CLOB(A), CLOB(B) then result is CLOB(MIN(A+B,2G))
440
//operands BLOB(A), CHAR FOR BIT DATA(B) then result is BLOB(MIN(A+B,2G))
441
//operands BLOB(A), VARCHAR FOR BIT DATA(B) then result is BLOB(MIN(A+B,2G))
442
//operands BLOB(A), LONG VARCHAR FOR BIT DATA then result is BLOB(MIN(A+32K,2G))
443
//operands BLOB(A), BLOB(B) then result is BLOB(MIN(A+B,2G))
444
resultLength = clobBlobHandling(leftType, rightType);
445         } else if (rightTypeId.getJDBCTypeId() == Types.CLOB || rightTypeId.getJDBCTypeId() == Types.BLOB) {
446             //operands LONG VARCHAR, CLOB(A) then result is CLOB(MIN(A+32K,2G))
447
//operands LONG VARCHAR FOR BIT DATA, BLOB(A) then result is BLOB(MIN(A+32K,2G))
448
resultLength = clobBlobHandling(rightType, leftType);
449         }
450
451         //bug - 5837. long varchar and long binary can't hold more data than their specific limits. If this length is violated by resulting
452
//concatenated string, an exception will be thrown at execute time.
453
if (higherType.equals(TypeId.LONGVARCHAR_NAME))
454             resultLength = TypeId.LONGVARCHAR_MAXWIDTH;
455         else if (higherType.equals(TypeId.LONGVARBIT_NAME))
456             resultLength = TypeId.LONGVARBIT_MAXWIDTH;
457
458
459         /*
460         ** Result Length can't be negative
461         */

462         if (SanityManager.DEBUG)
463         {
464             if (resultLength < 0)
465             {
466                 SanityManager.THROWASSERT("There should not be an overflow of maximum length for any result type at this point. Overflow for BLOB/CLOB has already been handled earlier");
467             }
468         }
469
470         /* The result is nullable if either side is nullable */
471         nullable = leftType.isNullable() || rightType.isNullable();
472
473         /*
474         ** Create a new DataTypeDescriptor that has the correct
475         ** type and nullability.
476         **
477         ** It's OK to call the implementation of the DataTypeDescriptorFactory
478         ** here, because we're in the same package.
479         */

480         return new DataTypeDescriptor(
481                     TypeId.getBuiltInTypeId(higherType),
482                     nullable,
483                     resultLength
484                 );
485     }
486
487     /*
488      *for conatenation operator, we generate code as follows
489      *field = method(p1, p2, field);
490      *what we are ensuring here is if field is null then initialize it to NULL SQLxxx type.
491      *Because of the following, at execution time, SQLxxx concatenate method do not have to
492      *worry about field coming in as null
493     */

494     protected void initializeResultField(ExpressionClassBuilder acb, MethodBuilder mb, LocalField resultField)
495     throws StandardException
496     {
497         mb.conditionalIfNull();//get the field on the stack and if it is null
498
acb.generateNull(mb, getTypeCompiler());// yes, it is, hence create a NULL SQLxxx type object and put that on stack
499
mb.startElseCode(); //no, it is not null
500
mb.getField(resultField); //so put it back on the stack
501
mb.completeConditional(); //complete if else block
502
}
503
504     private static int clobBlobHandling(
505                                 DataTypeDescriptor clobBlobType,
506                                 DataTypeDescriptor otherType
507                             ) throws StandardException
508     {
509         int resultLength;
510
511         if (otherType.getTypeId().getJDBCTypeId() == Types.LONGVARCHAR ||
512             otherType.getTypeId().getJDBCTypeId() == Types.LONGVARBINARY) {
513             //operands CLOB(A), LONG VARCHAR then result is CLOB(MIN(A+32K,2G))
514
//operands BLOB(A), LONG VARCHAR FOR BIT DATA then result is BLOB(MIN(A+32K,2G))
515
resultLength = clobBlobType.getMaximumWidth() + 32768;
516         } else {
517             //operands CLOB(A), CHAR(B) then result is CLOB(MIN(A+B,2G))
518
//operands CLOB(A), VARCHAR(B) then result is CLOB(MIN(A+B,2G))
519
//operands CLOB(A), CLOB(B) then result is CLOB(MIN(A+B,2G))
520
//operands BLOB(A), CHAR FOR BIT DATA(B) then result is BLOB(MIN(A+B,2G))
521
//operands BLOB(A), VARCHAR FOR BIT DATA(B) then result is BLOB(MIN(A+B,2G))
522
//operands BLOB(A), BLOB(B) then result is BLOB(MIN(A+B,2G))
523
resultLength = clobBlobType.getMaximumWidth() + otherType.getMaximumWidth();
524         }
525
526         if (resultLength < 1) //this mean A+B or A+32K is bigger than 2G
527
return(Integer.MAX_VALUE);
528         else
529             return(resultLength);
530
531     }
532 }
533
Popular Tags