Quadcap Embeddable Database

com/quadcap/sql/FunctionExpression.java

Go to the documentation of this file.
00001 package com.quadcap.sql; 00002 00003 /* Copyright 1999 - 2003 Quadcap Software. All rights reserved. 00004 * 00005 * This software is distributed under the Quadcap Free Software License. 00006 * This software may be used or modified for any purpose, personal or 00007 * commercial. Open Source redistributions are permitted. Commercial 00008 * redistribution of larger works derived from, or works which bundle 00009 * this software requires a "Commercial Redistribution License"; see 00010 * http://www.quadcap.com/purchase. 00011 * 00012 * Redistributions qualify as "Open Source" under one of the following terms: 00013 * 00014 * Redistributions are made at no charge beyond the reasonable cost of 00015 * materials and delivery. 00016 * 00017 * Redistributions are accompanied by a copy of the Source Code or by an 00018 * irrevocable offer to provide a copy of the Source Code for up to three 00019 * years at the cost of materials and delivery. Such redistributions 00020 * must allow further use, modification, and redistribution of the Source 00021 * Code under substantially the same terms as this license. 00022 * 00023 * Redistributions of source code must retain the copyright notices as they 00024 * appear in each source code file, these license terms, and the 00025 * disclaimer/limitation of liability set forth as paragraph 6 below. 00026 * 00027 * Redistributions in binary form must reproduce this Copyright Notice, 00028 * these license terms, and the disclaimer/limitation of liability set 00029 * forth as paragraph 6 below, in the documentation and/or other materials 00030 * provided with the distribution. 00031 * 00032 * The Software is provided on an "AS IS" basis. No warranty is 00033 * provided that the Software is free of defects, or fit for a 00034 * particular purpose. 00035 * 00036 * Limitation of Liability. Quadcap Software shall not be liable 00037 * for any damages suffered by the Licensee or any third party resulting 00038 * from use of the Software. 00039 */ 00040 00041 import java.io.Externalizable; 00042 import java.io.IOException; 00043 import java.io.ObjectInput; 00044 import java.io.ObjectOutput; 00045 00046 import java.util.Calendar; 00047 import java.util.Hashtable; 00048 import java.util.Random; 00049 00050 import java.math.BigDecimal; 00051 00052 import java.security.MessageDigest; 00053 00054 import java.text.SimpleDateFormat; 00055 00056 import java.sql.Date; 00057 import java.sql.SQLException; 00058 import java.sql.Time; 00059 import java.sql.Timestamp; 00060 00061 import com.quadcap.sql.types.*; 00062 00063 import com.quadcap.util.text.Soundex; 00064 00065 import com.quadcap.util.Debug; 00066 00067 /** 00068 * Implement function expressions. All of them. 00069 * 00070 * @author Stan Bailes 00071 */ 00072 public class FunctionExpression extends Expression implements Externalizable { 00073 String name; 00074 String uname; 00075 VectorExpression args; 00076 boolean not = false; 00077 Value value = null; 00078 00079 //static final Calendar cal = Calendar.getInstance(); 00080 static final SimpleDateFormat dayNameFmt = new SimpleDateFormat("EEE"); 00081 static final SimpleDateFormat monthNameFmt = new SimpleDateFormat("MMM"); 00082 00083 static final int TSI_FRAC_SECOND = -1; 00084 static final int TSI_SECOND = Calendar.SECOND; 00085 static final int TSI_MINUTE = Calendar.MINUTE; 00086 static final int TSI_HOUR = Calendar.HOUR; 00087 static final int TSI_DAY = Calendar.DAY_OF_YEAR; 00088 static final int TSI_WEEK = Calendar.WEEK_OF_YEAR; 00089 static final int TSI_MONTH = Calendar.MONTH; 00090 static final int TSI_QUARTER = -2; 00091 static final int TSI_YEAR = Calendar.YEAR; 00092 00093 // map fn name to Integer fn num 00094 static final Hashtable functions = new Hashtable(); 00095 00096 //#global ecnt; set ecnt 0 00097 //#proc nxt {} { global ecnt; return [incr ecnt] } 00098 //#set fns { 00099 //# ABS ASCII 00100 //# ACOS ASIN ATAN ATAN2 00101 //# BIT_LENGTH 00102 //# CASE CAST CEILING CHAR {CHAR_LENGTH CHARACTER_LENGTH} 00103 //# COALESCE 00104 //# COS COT CONCAT CURDATE CURTIME 00105 //# DATABASE DAYNAME DAYOFMONTH DAYOFWEEK DAYOFYEAR DEGREES DIFFERENCE 00106 //# EXP 00107 //# FLOOR 00108 //# HOUR 00109 //# IFNULL INSERT 00110 //# LEFT LENGTH LOCATE LOG LOG10 {LOWER LCASE} LTRIM 00111 //# MINUTE MOD MONTH MONTHNAME 00112 //# NOW NULLIF 00113 //# OCTET_LENGTH 00114 //# PI POWER 00115 //# QUARTER 00116 //# RADIANS RAND REPEAT REPLACE RIGHT ROUND RTRIM 00117 //# SECOND SIGN SIN SOUNDEX SPACE SQRT SUBSTRING 00118 //# TAN TIMESTAMPADD TIMESTAMPDIFF TRUNCATE 00119 //# {UPPER UCASE} USER 00120 //# WEEK 00121 //# YEAR 00122 //# DIGEST LAST_INSERT_ID 00123 //#} 00124 //#foreach f $fns { 00125 //# set name [lindex $f 0] 00126 //# set fname [format "%-24s" $name] 00127 //> static final int fn${fname} = [nxt]; 00128 //#} 00129 //> 00130 //> static { 00131 //#foreach f $fns { 00132 //# set name [lindex $f 0] 00133 //# foreach n $f { 00134 //> functions.put(\"${n}\", new Integer(fn${name})); 00135 //# } 00136 //#} 00137 //> } 00138 //> 00139 //> /*{functionIndex.xml-100} 00140 //> * <ul> 00141 //#foreach f $fns { 00142 //# set name [lindex $f 0] 00143 //# foreach n $f { 00144 //> * <li><a href=\"./fnvarExpression.html#${name}\">${n}</a></li> 00145 //# } 00146 //#} 00147 //> * </ul> 00148 //> */ 00149 //>/* 00150 //#foreach f $fns { 00151 //> <row><entry>[concat $f]</entry><entry>Yes</entry></row> 00152 //#} 00153 //>*/ 00154 //#autogen begin 00155 static final int fnABS = 1; 00156 static final int fnASCII = 2; 00157 static final int fnACOS = 3; 00158 static final int fnASIN = 4; 00159 static final int fnATAN = 5; 00160 static final int fnATAN2 = 6; 00161 static final int fnBIT_LENGTH = 7; 00162 static final int fnCASE = 8; 00163 static final int fnCAST = 9; 00164 static final int fnCEILING = 10; 00165 static final int fnCHAR = 11; 00166 static final int fnCHAR_LENGTH = 12; 00167 static final int fnCOALESCE = 13; 00168 static final int fnCOS = 14; 00169 static final int fnCOT = 15; 00170 static final int fnCONCAT = 16; 00171 static final int fnCURDATE = 17; 00172 static final int fnCURTIME = 18; 00173 static final int fnDATABASE = 19; 00174 static final int fnDAYNAME = 20; 00175 static final int fnDAYOFMONTH = 21; 00176 static final int fnDAYOFWEEK = 22; 00177 static final int fnDAYOFYEAR = 23; 00178 static final int fnDEGREES = 24; 00179 static final int fnDIFFERENCE = 25; 00180 static final int fnEXP = 26; 00181 static final int fnFLOOR = 27; 00182 static final int fnHOUR = 28; 00183 static final int fnIFNULL = 29; 00184 static final int fnINSERT = 30; 00185 static final int fnLEFT = 31; 00186 static final int fnLENGTH = 32; 00187 static final int fnLOCATE = 33; 00188 static final int fnLOG = 34; 00189 static final int fnLOG10 = 35; 00190 static final int fnLOWER = 36; 00191 static final int fnLTRIM = 37; 00192 static final int fnMINUTE = 38; 00193 static final int fnMOD = 39; 00194 static final int fnMONTH = 40; 00195 static final int fnMONTHNAME = 41; 00196 static final int fnNOW = 42; 00197 static final int fnNULLIF = 43; 00198 static final int fnOCTET_LENGTH = 44; 00199 static final int fnPI = 45; 00200 static final int fnPOWER = 46; 00201 static final int fnQUARTER = 47; 00202 static final int fnRADIANS = 48; 00203 static final int fnRAND = 49; 00204 static final int fnREPEAT = 50; 00205 static final int fnREPLACE = 51; 00206 static final int fnRIGHT = 52; 00207 static final int fnROUND = 53; 00208 static final int fnRTRIM = 54; 00209 static final int fnSECOND = 55; 00210 static final int fnSIGN = 56; 00211 static final int fnSIN = 57; 00212 static final int fnSOUNDEX = 58; 00213 static final int fnSPACE = 59; 00214 static final int fnSQRT = 60; 00215 static final int fnSUBSTRING = 61; 00216 static final int fnTAN = 62; 00217 static final int fnTIMESTAMPADD = 63; 00218 static final int fnTIMESTAMPDIFF = 64; 00219 static final int fnTRUNCATE = 65; 00220 static final int fnUPPER = 66; 00221 static final int fnUSER = 67; 00222 static final int fnWEEK = 68; 00223 static final int fnYEAR = 69; 00224 static final int fnDIGEST = 70; 00225 static final int fnLAST_INSERT_ID = 71; 00226 00227 static { 00228 functions.put("ABS", new Integer(fnABS)); 00229 functions.put("ASCII", new Integer(fnASCII)); 00230 functions.put("ACOS", new Integer(fnACOS)); 00231 functions.put("ASIN", new Integer(fnASIN)); 00232 functions.put("ATAN", new Integer(fnATAN)); 00233 functions.put("ATAN2", new Integer(fnATAN2)); 00234 functions.put("BIT_LENGTH", new Integer(fnBIT_LENGTH)); 00235 functions.put("CASE", new Integer(fnCASE)); 00236 functions.put("CAST", new Integer(fnCAST)); 00237 functions.put("CEILING", new Integer(fnCEILING)); 00238 functions.put("CHAR", new Integer(fnCHAR)); 00239 functions.put("CHAR_LENGTH", new Integer(fnCHAR_LENGTH)); 00240 functions.put("CHARACTER_LENGTH", new Integer(fnCHAR_LENGTH)); 00241 functions.put("COALESCE", new Integer(fnCOALESCE)); 00242 functions.put("COS", new Integer(fnCOS)); 00243 functions.put("COT", new Integer(fnCOT)); 00244 functions.put("CONCAT", new Integer(fnCONCAT)); 00245 functions.put("CURDATE", new Integer(fnCURDATE)); 00246 functions.put("CURTIME", new Integer(fnCURTIME)); 00247 functions.put("DATABASE", new Integer(fnDATABASE)); 00248 functions.put("DAYNAME", new Integer(fnDAYNAME)); 00249 functions.put("DAYOFMONTH", new Integer(fnDAYOFMONTH)); 00250 functions.put("DAYOFWEEK", new Integer(fnDAYOFWEEK)); 00251 functions.put("DAYOFYEAR", new Integer(fnDAYOFYEAR)); 00252 functions.put("DEGREES", new Integer(fnDEGREES)); 00253 functions.put("DIFFERENCE", new Integer(fnDIFFERENCE)); 00254 functions.put("EXP", new Integer(fnEXP)); 00255 functions.put("FLOOR", new Integer(fnFLOOR)); 00256 functions.put("HOUR", new Integer(fnHOUR)); 00257 functions.put("IFNULL", new Integer(fnIFNULL)); 00258 functions.put("INSERT", new Integer(fnINSERT)); 00259 functions.put("LEFT", new Integer(fnLEFT)); 00260 functions.put("LENGTH", new Integer(fnLENGTH)); 00261 functions.put("LOCATE", new Integer(fnLOCATE)); 00262 functions.put("LOG", new Integer(fnLOG)); 00263 functions.put("LOG10", new Integer(fnLOG10)); 00264 functions.put("LOWER", new Integer(fnLOWER)); 00265 functions.put("LCASE", new Integer(fnLOWER)); 00266 functions.put("LTRIM", new Integer(fnLTRIM)); 00267 functions.put("MINUTE", new Integer(fnMINUTE)); 00268 functions.put("MOD", new Integer(fnMOD)); 00269 functions.put("MONTH", new Integer(fnMONTH)); 00270 functions.put("MONTHNAME", new Integer(fnMONTHNAME)); 00271 functions.put("NOW", new Integer(fnNOW)); 00272 functions.put("NULLIF", new Integer(fnNULLIF)); 00273 functions.put("OCTET_LENGTH", new Integer(fnOCTET_LENGTH)); 00274 functions.put("PI", new Integer(fnPI)); 00275 functions.put("POWER", new Integer(fnPOWER)); 00276 functions.put("QUARTER", new Integer(fnQUARTER)); 00277 functions.put("RADIANS", new Integer(fnRADIANS)); 00278 functions.put("RAND", new Integer(fnRAND)); 00279 functions.put("REPEAT", new Integer(fnREPEAT)); 00280 functions.put("REPLACE", new Integer(fnREPLACE)); 00281 functions.put("RIGHT", new Integer(fnRIGHT)); 00282 functions.put("ROUND", new Integer(fnROUND)); 00283 functions.put("RTRIM", new Integer(fnRTRIM)); 00284 functions.put("SECOND", new Integer(fnSECOND)); 00285 functions.put("SIGN", new Integer(fnSIGN)); 00286 functions.put("SIN", new Integer(fnSIN)); 00287 functions.put("SOUNDEX", new Integer(fnSOUNDEX)); 00288 functions.put("SPACE", new Integer(fnSPACE)); 00289 functions.put("SQRT", new Integer(fnSQRT)); 00290 functions.put("SUBSTRING", new Integer(fnSUBSTRING)); 00291 functions.put("TAN", new Integer(fnTAN)); 00292 functions.put("TIMESTAMPADD", new Integer(fnTIMESTAMPADD)); 00293 functions.put("TIMESTAMPDIFF", new Integer(fnTIMESTAMPDIFF)); 00294 functions.put("TRUNCATE", new Integer(fnTRUNCATE)); 00295 functions.put("UPPER", new Integer(fnUPPER)); 00296 functions.put("UCASE", new Integer(fnUPPER)); 00297 functions.put("USER", new Integer(fnUSER)); 00298 functions.put("WEEK", new Integer(fnWEEK)); 00299 functions.put("YEAR", new Integer(fnYEAR)); 00300 functions.put("DIGEST", new Integer(fnDIGEST)); 00301 functions.put("LAST_INSERT_ID", new Integer(fnLAST_INSERT_ID)); 00302 } 00303 00304 /*{functionIndex.xml-100} 00305 * <ul> 00306 * <li><a href="./fnvarExpression.html#ABS">ABS</a></li> 00307 * <li><a href="./fnvarExpression.html#ASCII">ASCII</a></li> 00308 * <li><a href="./fnvarExpression.html#ACOS">ACOS</a></li> 00309 * <li><a href="./fnvarExpression.html#ASIN">ASIN</a></li> 00310 * <li><a href="./fnvarExpression.html#ATAN">ATAN</a></li> 00311 * <li><a href="./fnvarExpression.html#ATAN2">ATAN2</a></li> 00312 * <li><a href="./fnvarExpression.html#BIT_LENGTH">BIT_LENGTH</a></li> 00313 * <li><a href="./fnvarExpression.html#CASE">CASE</a></li> 00314 * <li><a href="./fnvarExpression.html#CAST">CAST</a></li> 00315 * <li><a href="./fnvarExpression.html#CEILING">CEILING</a></li> 00316 * <li><a href="./fnvarExpression.html#CHAR">CHAR</a></li> 00317 * <li><a href="./fnvarExpression.html#CHAR_LENGTH">CHAR_LENGTH</a></li> 00318 * <li><a href="./fnvarExpression.html#CHAR_LENGTH">CHARACTER_LENGTH</a></li> 00319 * <li><a href="./fnvarExpression.html#COALESCE">COALESCE</a></li> 00320 * <li><a href="./fnvarExpression.html#COS">COS</a></li> 00321 * <li><a href="./fnvarExpression.html#COT">COT</a></li> 00322 * <li><a href="./fnvarExpression.html#CONCAT">CONCAT</a></li> 00323 * <li><a href="./fnvarExpression.html#CURDATE">CURDATE</a></li> 00324 * <li><a href="./fnvarExpression.html#CURTIME">CURTIME</a></li> 00325 * <li><a href="./fnvarExpression.html#DATABASE">DATABASE</a></li> 00326 * <li><a href="./fnvarExpression.html#DAYNAME">DAYNAME</a></li> 00327 * <li><a href="./fnvarExpression.html#DAYOFMONTH">DAYOFMONTH</a></li> 00328 * <li><a href="./fnvarExpression.html#DAYOFWEEK">DAYOFWEEK</a></li> 00329 * <li><a href="./fnvarExpression.html#DAYOFYEAR">DAYOFYEAR</a></li> 00330 * <li><a href="./fnvarExpression.html#DEGREES">DEGREES</a></li> 00331 * <li><a href="./fnvarExpression.html#DIFFERENCE">DIFFERENCE</a></li> 00332 * <li><a href="./fnvarExpression.html#EXP">EXP</a></li> 00333 * <li><a href="./fnvarExpression.html#FLOOR">FLOOR</a></li> 00334 * <li><a href="./fnvarExpression.html#HOUR">HOUR</a></li> 00335 * <li><a href="./fnvarExpression.html#IFNULL">IFNULL</a></li> 00336 * <li><a href="./fnvarExpression.html#INSERT">INSERT</a></li> 00337 * <li><a href="./fnvarExpression.html#LEFT">LEFT</a></li> 00338 * <li><a href="./fnvarExpression.html#LENGTH">LENGTH</a></li> 00339 * <li><a href="./fnvarExpression.html#LOCATE">LOCATE</a></li> 00340 * <li><a href="./fnvarExpression.html#LOG">LOG</a></li> 00341 * <li><a href="./fnvarExpression.html#LOG10">LOG10</a></li> 00342 * <li><a href="./fnvarExpression.html#LOWER">LOWER</a></li> 00343 * <li><a href="./fnvarExpression.html#LOWER">LCASE</a></li> 00344 * <li><a href="./fnvarExpression.html#LTRIM">LTRIM</a></li> 00345 * <li><a href="./fnvarExpression.html#MINUTE">MINUTE</a></li> 00346 * <li><a href="./fnvarExpression.html#MOD">MOD</a></li> 00347 * <li><a href="./fnvarExpression.html#MONTH">MONTH</a></li> 00348 * <li><a href="./fnvarExpression.html#MONTHNAME">MONTHNAME</a></li> 00349 * <li><a href="./fnvarExpression.html#NOW">NOW</a></li> 00350 * <li><a href="./fnvarExpression.html#NULLIF">NULLIF</a></li> 00351 * <li><a href="./fnvarExpression.html#OCTET_LENGTH">OCTET_LENGTH</a></li> 00352 * <li><a href="./fnvarExpression.html#PI">PI</a></li> 00353 * <li><a href="./fnvarExpression.html#POWER">POWER</a></li> 00354 * <li><a href="./fnvarExpression.html#QUARTER">QUARTER</a></li> 00355 * <li><a href="./fnvarExpression.html#RADIANS">RADIANS</a></li> 00356 * <li><a href="./fnvarExpression.html#RAND">RAND</a></li> 00357 * <li><a href="./fnvarExpression.html#REPEAT">REPEAT</a></li> 00358 * <li><a href="./fnvarExpression.html#REPLACE">REPLACE</a></li> 00359 * <li><a href="./fnvarExpression.html#RIGHT">RIGHT</a></li> 00360 * <li><a href="./fnvarExpression.html#ROUND">ROUND</a></li> 00361 * <li><a href="./fnvarExpression.html#RTRIM">RTRIM</a></li> 00362 * <li><a href="./fnvarExpression.html#SECOND">SECOND</a></li> 00363 * <li><a href="./fnvarExpression.html#SIGN">SIGN</a></li> 00364 * <li><a href="./fnvarExpression.html#SIN">SIN</a></li> 00365 * <li><a href="./fnvarExpression.html#SOUNDEX">SOUNDEX</a></li> 00366 * <li><a href="./fnvarExpression.html#SPACE">SPACE</a></li> 00367 * <li><a href="./fnvarExpression.html#SQRT">SQRT</a></li> 00368 * <li><a href="./fnvarExpression.html#SUBSTRING">SUBSTRING</a></li> 00369 * <li><a href="./fnvarExpression.html#TAN">TAN</a></li> 00370 * <li><a href="./fnvarExpression.html#TIMESTAMPADD">TIMESTAMPADD</a></li> 00371 * <li><a href="./fnvarExpression.html#TIMESTAMPDIFF">TIMESTAMPDIFF</a></li> 00372 * <li><a href="./fnvarExpression.html#TRUNCATE">TRUNCATE</a></li> 00373 * <li><a href="./fnvarExpression.html#UPPER">UPPER</a></li> 00374 * <li><a href="./fnvarExpression.html#UPPER">UCASE</a></li> 00375 * <li><a href="./fnvarExpression.html#USER">USER</a></li> 00376 * <li><a href="./fnvarExpression.html#WEEK">WEEK</a></li> 00377 * <li><a href="./fnvarExpression.html#YEAR">YEAR</a></li> 00378 * <li><a href="./fnvarExpression.html#DIGEST">DIGEST</a></li> 00379 * <li><a href="./fnvarExpression.html#LAST_INSERT_ID">LAST_INSERT_ID</a></li> 00380 * </ul> 00381 */ 00382 /* 00383 <row><entry>ABS</entry><entry>Yes</entry></row> 00384 <row><entry>ASCII</entry><entry>Yes</entry></row> 00385 <row><entry>ACOS</entry><entry>Yes</entry></row> 00386 <row><entry>ASIN</entry><entry>Yes</entry></row> 00387 <row><entry>ATAN</entry><entry>Yes</entry></row> 00388 <row><entry>ATAN2</entry><entry>Yes</entry></row> 00389 <row><entry>BIT_LENGTH</entry><entry>Yes</entry></row> 00390 <row><entry>CASE</entry><entry>Yes</entry></row> 00391 <row><entry>CAST</entry><entry>Yes</entry></row> 00392 <row><entry>CEILING</entry><entry>Yes</entry></row> 00393 <row><entry>CHAR</entry><entry>Yes</entry></row> 00394 <row><entry>CHAR_LENGTH CHARACTER_LENGTH</entry><entry>Yes</entry></row> 00395 <row><entry>COALESCE</entry><entry>Yes</entry></row> 00396 <row><entry>COS</entry><entry>Yes</entry></row> 00397 <row><entry>COT</entry><entry>Yes</entry></row> 00398 <row><entry>CONCAT</entry><entry>Yes</entry></row> 00399 <row><entry>CURDATE</entry><entry>Yes</entry></row> 00400 <row><entry>CURTIME</entry><entry>Yes</entry></row> 00401 <row><entry>DATABASE</entry><entry>Yes</entry></row> 00402 <row><entry>DAYNAME</entry><entry>Yes</entry></row> 00403 <row><entry>DAYOFMONTH</entry><entry>Yes</entry></row> 00404 <row><entry>DAYOFWEEK</entry><entry>Yes</entry></row> 00405 <row><entry>DAYOFYEAR</entry><entry>Yes</entry></row> 00406 <row><entry>DEGREES</entry><entry>Yes</entry></row> 00407 <row><entry>DIFFERENCE</entry><entry>Yes</entry></row> 00408 <row><entry>EXP</entry><entry>Yes</entry></row> 00409 <row><entry>FLOOR</entry><entry>Yes</entry></row> 00410 <row><entry>HOUR</entry><entry>Yes</entry></row> 00411 <row><entry>IFNULL</entry><entry>Yes</entry></row> 00412 <row><entry>INSERT</entry><entry>Yes</entry></row> 00413 <row><entry>LEFT</entry><entry>Yes</entry></row> 00414 <row><entry>LENGTH</entry><entry>Yes</entry></row> 00415 <row><entry>LOCATE</entry><entry>Yes</entry></row> 00416 <row><entry>LOG</entry><entry>Yes</entry></row> 00417 <row><entry>LOG10</entry><entry>Yes</entry></row> 00418 <row><entry>LOWER LCASE</entry><entry>Yes</entry></row> 00419 <row><entry>LTRIM</entry><entry>Yes</entry></row> 00420 <row><entry>MINUTE</entry><entry>Yes</entry></row> 00421 <row><entry>MOD</entry><entry>Yes</entry></row> 00422 <row><entry>MONTH</entry><entry>Yes</entry></row> 00423 <row><entry>MONTHNAME</entry><entry>Yes</entry></row> 00424 <row><entry>NOW</entry><entry>Yes</entry></row> 00425 <row><entry>NULLIF</entry><entry>Yes</entry></row> 00426 <row><entry>OCTET_LENGTH</entry><entry>Yes</entry></row> 00427 <row><entry>PI</entry><entry>Yes</entry></row> 00428 <row><entry>POWER</entry><entry>Yes</entry></row> 00429 <row><entry>QUARTER</entry><entry>Yes</entry></row> 00430 <row><entry>RADIANS</entry><entry>Yes</entry></row> 00431 <row><entry>RAND</entry><entry>Yes</entry></row> 00432 <row><entry>REPEAT</entry><entry>Yes</entry></row> 00433 <row><entry>REPLACE</entry><entry>Yes</entry></row> 00434 <row><entry>RIGHT</entry><entry>Yes</entry></row> 00435 <row><entry>ROUND</entry><entry>Yes</entry></row> 00436 <row><entry>RTRIM</entry><entry>Yes</entry></row> 00437 <row><entry>SECOND</entry><entry>Yes</entry></row> 00438 <row><entry>SIGN</entry><entry>Yes</entry></row> 00439 <row><entry>SIN</entry><entry>Yes</entry></row> 00440 <row><entry>SOUNDEX</entry><entry>Yes</entry></row> 00441 <row><entry>SPACE</entry><entry>Yes</entry></row> 00442 <row><entry>SQRT</entry><entry>Yes</entry></row> 00443 <row><entry>SUBSTRING</entry><entry>Yes</entry></row> 00444 <row><entry>TAN</entry><entry>Yes</entry></row> 00445 <row><entry>TIMESTAMPADD</entry><entry>Yes</entry></row> 00446 <row><entry>TIMESTAMPDIFF</entry><entry>Yes</entry></row> 00447 <row><entry>TRUNCATE</entry><entry>Yes</entry></row> 00448 <row><entry>UPPER UCASE</entry><entry>Yes</entry></row> 00449 <row><entry>USER</entry><entry>Yes</entry></row> 00450 <row><entry>WEEK</entry><entry>Yes</entry></row> 00451 <row><entry>YEAR</entry><entry>Yes</entry></row> 00452 <row><entry>DIGEST</entry><entry>Yes</entry></row> 00453 <row><entry>LAST_INSERT_ID</entry><entry>Yes</entry></row> 00454 */ 00455 //#autogen end 00456 00457 static final Number toNumber(Value v) throws SQLException, ValueException { 00458 Object obj = v.asJavaObject(); 00459 if (obj instanceof Number) { 00460 return (Number)obj; 00461 } else { 00462 throw new ValueException("Not a number: " + v); 00463 } 00464 } 00465 00466 static final Value stringLength(Value v, int div, int mul) 00467 throws ValueException, SQLException 00468 { 00469 if (Value.isNull(v)) { 00470 return v; 00471 } else { 00472 int len; 00473 if (v instanceof ValueOctets) { 00474 len = ((ValueOctets)v).getLength() * mul; 00475 } else if (v instanceof ValueString) { 00476 len = ((ValueString)v).stringValue().length() * 16; 00477 } else if (v instanceof ValueBlob) { 00478 len = (int)(((ValueBlob)v).length() * 8 * mul); 00479 } else { 00480 throw new ValueException("BIT_LENGTH(" + v + 00481 "), wrong type"); 00482 } 00483 return new ValueInteger((len + div-1) / div); 00484 } 00485 } 00486 00487 static final String stringValue(Value v) throws ValueException { 00488 if (!(v instanceof ValueString)) { 00489 v = v.convert(TypeVarChar.typeVarChar); 00490 } 00491 return ((ValueString)v).stringValue(); 00492 } 00493 00494 static final ValueString getString(Row values, int i) 00495 throws ValueException, SQLException 00496 { 00497 Value v = values.item(i); 00498 ValueString vs = null; 00499 if (v instanceof ValueString) { 00500 vs = (ValueString)v; 00501 } else { 00502 vs = (ValueString)(v.convert(TypeVarChar.typeVarChar)); 00503 } 00504 return vs; 00505 } 00506 00507 static final Number getNumber(Row values, int i) 00508 throws ValueException, SQLException 00509 { 00510 return toNumber(values.item(i)); 00511 } 00512 00513 static final Timestamp getTimestamp(Value v, String fn) 00514 throws ValueException, SQLException 00515 { 00516 if (!(v instanceof ValueTimestamp)) { 00517 throw new ValueException("fn called with " + 00518 "non-TIMESTAMP argument: " + 00519 v.getType().getTypeName()); 00520 } 00521 Timestamp t = (Timestamp)((ValueTimestamp)v).asJavaObject(); 00522 return t; 00523 } 00524 00525 static final int getMonths(Timestamp t) { 00526 Calendar c = Calendar.getInstance(); 00527 c.setTime(t); 00528 return c.get(Calendar.YEAR) * 12 + c.get(Calendar.MONTH); 00529 } 00530 00531 /** 00532 * Generic implementation of time field extraction from DATE, TIME, 00533 * TIMESTAMP and INTERVAL components 00534 */ 00535 public Value getTimeComponent(Value v, int field, int offset, boolean time) 00536 throws ValueException, SQLException 00537 { 00538 Value ret = null; 00539 if (Value.isNull(v)) { 00540 ret = v; 00541 } else if (v instanceof ValueInterval) { 00542 ret = ((ValueInterval)v).getTimeComponent(field); 00543 } else { 00544 Calendar c = Calendar.getInstance(); 00545 boolean ok = v instanceof ValueTimestamp; 00546 if (!ok) { 00547 if (time) ok = v instanceof ValueTime; 00548 else ok = v instanceof ValueDate; 00549 } 00550 if (!ok) { 00551 throw new ValueException(uname + "() called with " + 00552 "non-" + (time ? "TIME" : "DATE") + 00553 " argument: " + 00554 v.getType().getTypeName() + 00555 "(" + v.getClass().getName() + ")"); 00556 } 00557 Date d = new Date(((ValueDateTime)v).getTime()); 00558 c.setTime(d); 00559 ret = new ValueInteger(c.get(field) + offset); 00560 } 00561 return ret; 00562 00563 } 00564 00565 public FunctionExpression() {} 00566 00567 public FunctionExpression(String name, VectorExpression args) { 00568 this.name = name; 00569 this.uname = name.toUpperCase(); 00570 this.args = args; 00571 } 00572 00573 public void invert() { 00574 not = !not; 00575 } 00576 00577 public int rank() { return 0; } 00578 00579 /*{fnvarExpression.xml-100} 00580 * <section name="Functions"> 00581 */ 00582 /*{fnvarExpression.xml-990} 00583 * </section> 00584 */ 00585 00586 00587 public Value getValue(Session session, Cursor cursor) throws SQLException { 00588 Integer fi = (Integer)functions.get(uname); 00589 Row values = args.getValues(session, cursor); 00590 Value v = values.size() > 0 ? values.item(1) : null; 00591 Value ret = null; 00592 if (fi != null) switch (fi.intValue()) { 00593 case fnABS: 00594 /*{fnvarExpression.xml-105} 00595 * <subsection name="ABS"> 00596 * 00597 * <h4>Syntax</h4> 00598 * <code>ABS(<i>numeric value</i>)</code> 00599 * 00600 * <h4>Description</h4> 00601 * <p><code>ABS</code> returns the <i>absolute value</i> of the 00602 * numeric argument. The numeric argument may be of any integral, 00603 * exact numeric or approximate numeric type, and the result will 00604 * be of the same type.</p> 00605 * </subsection> 00606 */ 00607 ret = v; 00608 if (!Value.isNull(ret) && 00609 Value.boolOp(Op.LT, ret, ValueInteger.ZERO)) { 00610 ret = ret.unop(Op.MINUS); 00611 } 00612 break; 00613 00614 case fnASCII: 00615 /*{fnvarExpression.xml-110} 00616 * <subsection name="ASCII"> 00617 * 00618 * <h4>Syntax</h4> 00619 * <code>ASCII(<i>character string</i>)</code> 00620 * 00621 * <h4>Description</h4> 00622 * <p><code>ASCII</code> returns the integer ASCII code value 00623 * of the first character in the string.</p> 00624 * </subsection> 00625 */ 00626 if (Value.isNull(v)) { 00627 ret = v; 00628 } else { 00629 ret = new ValueInteger(stringValue(v).charAt(0) & 0xff); 00630 } 00631 break; 00632 00633 case fnACOS: 00634 /*{fnvarExpression.xml-120} 00635 * <subsection name="ACOS"> 00636 * 00637 * <h4>Syntax</h4> 00638 * <code>ACOS(<i>numeric value</i>)</code> 00639 * 00640 * <h4>Description</h4> 00641 * <p><code>ACOS</code>returns the arc cosine of an angle 00642 * expressed in radians.</p> 00643 * </subsection> 00644 */ 00645 if (Value.isNull(v)) { 00646 ret = v; 00647 } else { 00648 ret = new ValueDouble(Math.acos(toNumber(v).doubleValue())); 00649 } 00650 break; 00651 00652 case fnASIN: 00653 /*{fnvarExpression.xml-130} 00654 * <subsection name="ASIN"> 00655 * 00656 * <h4>Syntax</h4> 00657 * <code>ASIN(<i>numeric value</i>)</code> 00658 * 00659 * <h4>Description</h4> 00660 * <p><code>ASIN</code>returns the arc sine of an angle 00661 * expressed in radians.</p> 00662 * </subsection> 00663 */ 00664 if (Value.isNull(v)) { 00665 ret = v; 00666 } else { 00667 ret = new ValueDouble(Math.asin(toNumber(v).doubleValue())); 00668 } 00669 break; 00670 00671 case fnATAN: 00672 /*{fnvarExpression.xml-140} 00673 * <subsection name="ATAN"> 00674 * 00675 * <h4>Syntax</h4> 00676 * <code>ATAN(<i>numeric value</i>)</code> 00677 * 00678 * <h4>Description</h4> 00679 * <p><code>ATAN</code>returns the arc tangent of an angle 00680 * expressed in radians.</p> 00681 * </subsection> 00682 */ 00683 if (Value.isNull(v)) { 00684 ret = v; 00685 } else { 00686 ret = new ValueDouble(Math.atan(toNumber(v).doubleValue())); 00687 } 00688 break; 00689 00690 case fnATAN2: 00691 /*{fnvarExpression.xml-150} 00692 * <subsection name="ATAN2"> 00693 * 00694 * <h4>Syntax</h4> 00695 * <code>ATAN2(<i>y</i>, <i>x</i>)</code> 00696 * 00697 * <h4>Description</h4> 00698 * <p><code>ATAN2</code>converts the specified rectangular 00699 * coordinates to polar and returns the theta component of the 00700 * point (<i>r</i>, <i>theta</i>) in polar coordianate space 00701 * that correspondes to the point (<i>x</i>, <i>y</i>) in 00702 * rectangular space.</p> 00703 * </subsection> 00704 */ 00705 if (Value.isNull(v)) { 00706 ret = v; 00707 } else { 00708 double y = toNumber(v).doubleValue(); 00709 double x = toNumber(values.item(2)).doubleValue(); 00710 ret = new ValueDouble(Math.atan2(y, x)); 00711 } 00712 break; 00713 00714 case fnBIT_LENGTH: 00715 /*{fnvarExpression.xml-160} 00716 * <subsection name="BIT_LENGTH"> 00717 * 00718 * <h4>Syntax</h4> 00719 * <code>BIT_LENGTH(<i>character or bit string</i>)</code> 00720 * 00721 * <h4>Description</h4> 00722 * <p><code>BIT_LENGTH</code> returns the length of the string 00723 * argument in bits.</p> 00724 * </subsection> 00725 */ 00726 ret = stringLength(v, 1, 1); 00727 break; 00728 00729 case fnCASE: 00730 /*{fnvarExpression.xml-163} 00731 * <subsection name="CASE"> 00732 * 00733 * <h4>Syntax</h4> 00734 * <code>CASE ( WHEN <i>condition</i> THEN <i>value</i> )* 00735 * ( ELSE <i>else-value</i> )? 00736 * END 00737 *</code> 00738 * 00739 * <h4>Description</h4> 00740 * <p>The value of the <code>CASE</code> expression is the 00741 * value of the '<code>THEN</code> <i>value</i>' clause 00742 * for the first '<code>WHEN</code> <i>condition</i>' which 00743 * evaluates to <code><b>TRUE</b></code>.</p> 00744 * <p>If none of the <code>WHEN</code> clauses evaluate to 00745 * true, the value returned is that of the '<code>ELSE</code> 00746 * <i>else-value</i>' clause, or <code>NULL</code>.</p> 00747 * </subsection> 00748 */ 00749 ret = null; 00750 for (int i = 1; ret == null && i < values.size(); i += 2) { 00751 Value when = values.item(i); 00752 if (Value.isTrue(when)) { 00753 ret = values.item(i+1); 00754 } 00755 } 00756 if (ret == null && ((values.size() % 2) == 1)) { 00757 ret = values.item(values.size()); 00758 } 00759 if (ret == null) { 00760 ret = ValueNull.valueNull; 00761 } 00762 break; 00763 00764 case fnCAST: 00765 /*{fnvarExpression.xml-165} 00766 * <subsection name="CAST"> 00767 * 00768 * <h4>Syntax</h4> 00769 * <code>CAST <i>expression</i> AS <i>datatype</i></code> 00770 * 00771 * <h4>Description</h4> 00772 * <p>Converts <i>expression</i> to <i>datatype</i>, where 00773 * <i>datatype</i> is one of the following types: 00774 * <ul> 00775 * <li>INT OR INTEGER</li> 00776 * <li>SMALLINT</li> 00777 * <li>TINYINT</li> 00778 * <li>BIGINT</li> 00779 * <li>VARCHAR</li> 00780 * <li>CHAR</li> 00781 * <li>DECIMAL</li> 00782 * <li>DEC</li> 00783 * <li>NUMERIC</li> 00784 * <li>REAL</li> 00785 * <li>DOUBLE</li> 00786 * <li>FLOAT</li> 00787 * <li>BOOLEAN</li> 00788 * <li>BIT</li> 00789 * <li>BINARY</li> 00790 * <li>BIT VARYING</li> 00791 * <li>VARBINARY</li> 00792 * <li>BLOB</li> 00793 * <li>BINARY LARGE OBJECT</li> 00794 * <li>DATE</li> 00795 * <li>TIME</li> 00796 * <li>TIMESTAMP</li> 00797 * <li>INTERVAL</li> 00798 * </ul> 00799 * </p> 00800 * </subsection> 00801 */ 00802 if (Value.isNull(v)) { 00803 ret = v; 00804 } else { 00805 ValueType vt = (ValueType)values.item(2); 00806 Type type = vt.getType(); 00807 if (type == null) { 00808 throw new ValueException("Can't convert value to type: " + 00809 type); 00810 } 00811 ret = type.convert(v); 00812 } 00813 break; 00814 00815 case fnCEILING: 00816 /*{fnvarExpression.xml-170} 00817 * <subsection name="CEILING"> 00818 * 00819 * <h4>Syntax</h4> 00820 * <code>CEILING(<i>numeric value</i>)</code> 00821 * 00822 * <h4>Description</h4> 00823 * <p><code>CEILING</code>returns the least integer which is 00824 * greater or equal to the specified numeric value.</p> 00825 * </subsection> 00826 */ 00827 if (Value.isNull(v)) { 00828 ret = v; 00829 } else { 00830 ret = new ValueDouble(Math.ceil(toNumber(v).doubleValue())); 00831 } 00832 break; 00833 00834 case fnCHAR: 00835 /*{fnvarExpression.xml-180} 00836 * <subsection name="CHAR"> 00837 * 00838 * <h4>Syntax</h4> 00839 * <code>CHAR(<i>ascii code value</i>)</code> 00840 * 00841 * <h4>Description</h4> 00842 * <p><code>CHAR</code>returns a string of length one, containing 00843 * the character represented by the specified ASCII code value, 00844 * as an integer in the range 0-255.</p> 00845 * </subsection> 00846 */ 00847 if (Value.isNull(v)) { 00848 ret = v; 00849 } else { 00850 int n = toNumber(v).intValue(); 00851 if (n < 0 || n > 255) { 00852 throw new ValueException("CHAR(" + n + 00853 "), not an ASCII value"); 00854 } 00855 char[] cv = new char[1]; 00856 cv[0] = (char)n; 00857 ret = new ValueString(new String(cv)); 00858 } 00859 break; 00860 00861 case fnCHAR_LENGTH: 00862 /*{fnvarExpression.xml-190} 00863 * <subsection name="CHARACTER_LENGTH"> 00864 * 00865 * <h4>Syntax</h4> 00866 * <code>CHAR_LENGTH(<i>character or bit string</i>)</code> 00867 * <code>CHARACTER_LENGTH(<i>character or bit string</i>)</code> 00868 * 00869 * <h4>Description</h4> 00870 * <p>If the argument is a character string, 00871 * <code>CHAR_LENGTH</code> and 00872 * <code>CHARACTER_LENGTH</code> 00873 * return the length of the string argument in characters, 00874 * otherwise, 00875 * they return the number of octets in the argument.</p> 00876 * </subsection> 00877 */ 00878 ret = stringLength(v, 16, 2); 00879 break; 00880 00881 case fnCOS: 00882 /*{fnvarExpression.xml-200} 00883 * <subsection name="COS"> 00884 * 00885 * <h4>Syntax</h4> 00886 * <code>COS(<i>numeric value</i>)</code> 00887 * 00888 * <h4>Description</h4> 00889 * <p><code>COS</code>returns the cosine of an angle 00890 * expressed in radians.</p> 00891 * </subsection> 00892 */ 00893 if (Value.isNull(v)) { 00894 ret = v; 00895 } else { 00896 ret = new ValueDouble(Math.cos(toNumber(v).doubleValue())); 00897 } 00898 break; 00899 00900 case fnCOALESCE: 00901 /*{fnvarExpression.xml-205} 00902 * <subsection name="COALESCE"> 00903 * 00904 * <h4>Syntax</h4> 00905 * <code>COS(<i>expression</i>, ...)</code> 00906 * 00907 * <h4>Description</h4> 00908 * <p><code>COALESCE</code>returns the first non-null value in 00909 * the expression list, or NULL if all values in the list are 00910 * NULL.</p> 00911 * </subsection> 00912 */ 00913 ret = ValueNull.valueNull; 00914 for (int i = 1; i <= values.size(); i++) { 00915 Value vt = values.item(i); 00916 if (!Value.isNull(vt)) { 00917 ret = v; 00918 break; 00919 } 00920 } 00921 break; 00922 00923 case fnCOT: 00924 /*{fnvarExpression.xml-210} 00925 * <subsection name="COT"> 00926 * 00927 * <h4>Syntax</h4> 00928 * <code>COT(<i>numeric value</i>)</code> 00929 * 00930 * <h4>Description</h4> 00931 * <p><code>COT</code>returns the cotangent of an angle 00932 * expressed in radians.</p> 00933 * </subsection> 00934 */ 00935 if (Value.isNull(v)) { 00936 ret = v; 00937 } else { 00938 double x = toNumber(v).doubleValue(); 00939 ret = new ValueDouble(Math.cos(x) / Math.sin(x)); 00940 } 00941 break; 00942 00943 case fnCONCAT: 00944 /*{fnvarExpression.xml-220} 00945 * <subsection name="CONCAT"> 00946 * 00947 * <h4>Syntax</h4> 00948 * <code>CONCAT(<i>string1</i>, <i>string2</i>)</code> 00949 * 00950 * <h4>Description</h4> 00951 * <p><code>CONCAT</code> returns a string formed by concatenating 00952 * <i>string1</i> with <i>string2</i>.</p> 00953 * </subsection> 00954 */ 00955 if (Value.isNull(v) || Value.isNull(values.item(2))) { 00956 ret = ValueNull.valueNull; 00957 } else { 00958 ValueString s1 = getString(values, 1); 00959 ValueString s2 = getString(values, 2); 00960 ret = new ValueString(s1.stringValue() + s2.stringValue()); 00961 } 00962 break; 00963 00964 case fnCURDATE: 00965 /*{fnvarExpression.xml-230} 00966 * <subsection name="CURDATE"> 00967 <