1 65 66 67 package org.hsqldb; 68 69 import java.lang.reflect.InvocationTargetException ; 70 import java.lang.reflect.Method ; 71 import java.lang.reflect.Modifier ; 72 import java.sql.Connection ; 73 74 import org.hsqldb.lib.HashMap; 75 import org.hsqldb.lib.HsqlArrayList; 76 import org.hsqldb.lib.StringConverter; 77 import org.hsqldb.types.Binary; 78 import org.hsqldb.types.JavaObject; 79 80 87 97 class Function { 98 99 private String sFunction; 100 private Method mMethod; 101 private String returnClassName; 102 private Class [] aArgClasses; 103 private int iReturnType; 104 private int iArgCount; 105 private int iSqlArgCount; 106 private int iSqlArgStart; 107 private int[] iArgType; 108 private boolean[] bArgNullable; 109 Expression[] eArg; 110 private boolean bConnection; 111 private static HashMap methodCache = new HashMap(); 112 private int fID; 113 String name; boolean isSimple; boolean hasAggregate; 116 117 147 Function(String name, String fqn, boolean isSimple) throws HsqlException { 148 149 this.name = name; 150 this.isSimple = isSimple; 151 152 sFunction = fqn; 154 fID = Library.functionID(fqn); 155 156 int i = fqn.lastIndexOf('.'); 157 158 Trace.check(i != -1, Trace.UNEXPECTED_TOKEN, fqn); 159 160 String classname = fqn.substring(0, i); 161 162 mMethod = (Method ) methodCache.get(fqn); 163 164 if (mMethod == null) { 165 String methodname = fqn.substring(i + 1); 166 Class classinstance = null; 167 168 try { 169 classinstance = Class.forName(classname); 170 } catch (Exception e) { 171 throw Trace.error(Trace.FUNCTION_NOT_FOUND, 172 Trace.Message_Pair, new Object [] { 173 classname, e 174 }); 175 } 176 177 Method [] methods = classinstance.getMethods(); 180 181 for (i = 0; i < methods.length; i++) { 182 Method m = methods[i]; 183 184 if (m.getName().equals(methodname) 185 && Modifier.isStatic(m.getModifiers())) { 186 mMethod = m; 187 188 break; 189 } 190 } 191 192 Trace.check(mMethod != null, Trace.UNKNOWN_FUNCTION, methodname); 193 methodCache.put(fqn, mMethod); 194 } 195 196 Class returnClass = mMethod.getReturnType(); 197 198 if (returnClass.equals(org.hsqldb.Result.class)) { 199 200 iReturnType = Types.OTHER; 206 } else { 207 208 iReturnType = Types.getParameterTypeNr(returnClass); 250 } 251 252 returnClassName = 253 Types.getFunctionReturnClassName(returnClass.getName()); 254 aArgClasses = mMethod.getParameterTypes(); 255 iArgCount = aArgClasses.length; 256 iArgType = new int[iArgCount]; 257 bArgNullable = new boolean[iArgCount]; 258 259 for (i = 0; i < aArgClasses.length; i++) { 260 Class a = aArgClasses[i]; 261 String type = a.getName(); 262 263 if ((i == 0) && a.equals(Connection .class)) { 264 265 bConnection = true; 269 } else { 270 271 iArgType[i] = Types.getParameterTypeNr(a); 273 bArgNullable[i] = !a.isPrimitive(); 274 } 275 } 276 277 iSqlArgCount = iArgCount; 278 279 if (bConnection) { 280 iSqlArgCount--; 281 282 iSqlArgStart = 1; 283 } else { 284 iSqlArgStart = 0; 285 } 286 287 eArg = new Expression[iArgCount]; 288 } 289 290 293 Object getValue(Session session) throws HsqlException { 294 295 switch (fID) { 296 297 case Library.curtime : 298 return session.getCurrentTime(); 299 300 case Library.curdate : 301 return session.getCurrentDate(); 302 303 case Library.database : 304 return session.getDatabase().getPath(); 305 306 case Library.getAutoCommit : 307 return session.isAutoCommit() ? Boolean.TRUE 308 : Boolean.FALSE; 309 310 case Library.identity : 311 return session.getLastIdentity(); 312 313 case Library.isReadOnlyDatabase : 314 return session.getDatabase().databaseReadOnly ? Boolean.TRUE 315 : Boolean.FALSE; 316 317 case Library.isReadOnlyConnection : 318 return session.isReadOnly() ? Boolean.TRUE 319 : Boolean.FALSE; 320 321 case Library.isReadOnlyDatabaseFiles : 322 return session.getDatabase().isFilesReadOnly() ? Boolean.TRUE 323 : Boolean 324 .FALSE; 325 326 case Library.now : 327 return session.getCurrentTimestamp(); 328 329 case Library.user : 330 return session.getUsername(); 331 } 332 333 Object [] oArg = getArguments(session); 334 335 if (oArg == null) { 336 return null; 337 } 338 339 return getValue(session, oArg); 340 } 341 342 345 Object getValue(Session session, 346 Object [] arguments) throws HsqlException { 347 348 if (bConnection) { 349 arguments[0] = session.getInternalConnection(); 350 } 351 352 try { 353 Object ret = (fID >= 0) ? Library.invoke(fID, arguments) 354 : mMethod.invoke(null, arguments); 355 356 return Column.convertObject(ret, iReturnType); 357 } catch (InvocationTargetException e) { 358 359 Throwable t = e.getTargetException(); 361 String s = sFunction + " : " + t.toString(); 362 363 throw Trace.error(Trace.FUNCTION_CALL_ERROR, s); 364 } catch (IllegalAccessException e) { 365 366 throw Trace.error(Trace.FUNCTION_CALL_ERROR); 368 } 369 370 } 372 373 private Object [] getArguments(Session session) throws HsqlException { 374 375 int i = bConnection ? 1 376 : 0; 377 Object [] oArg = new Object [iArgCount]; 378 379 for (; i < iArgCount; i++) { 380 Expression e = eArg[i]; 381 Object o = null; 382 383 if (e != null) { 384 385 o = e.getValue(session, iArgType[i]); 387 } 388 389 if ((o == null) &&!bArgNullable[i]) { 390 391 return null; 393 } 394 395 if (o instanceof JavaObject) { 396 o = ((JavaObject) o).getObject(); 397 } else if (o instanceof Binary) { 398 o = ((Binary) o).getBytes(); 399 } 400 401 oArg[i] = o; 402 } 403 404 return oArg; 405 } 406 407 410 private Object [] getNotNull(Object [] values) throws HsqlException { 411 412 int i = bConnection ? 1 413 : 0; 414 415 for (; i < iArgCount; i++) { 416 Object o = values[i]; 417 418 if (o == null &&!bArgNullable[i]) { 419 420 return null; 422 } 423 } 424 425 return values; 426 } 427 428 void collectInGroupByExpressions(HsqlArrayList colExps) { 429 430 for (int i = 0; i < iArgCount; i++) { 431 Expression e = eArg[i]; 432 433 if (e != null) { 434 e.collectInGroupByExpressions(colExps); 435 } 436 } 437 } 438 439 Object getAggregatedValue(Session session, 440 Object currValue) throws HsqlException { 441 442 Object [] valueArray = (Object []) currValue; 443 444 if (valueArray == null) { 445 valueArray = new Object [iArgCount]; 446 } 447 448 for (int i = 0; i < iArgCount; i++) { 449 Expression e = eArg[i]; 450 451 if (eArg[i] != null) { 452 if (eArg[i].isAggregate()) { 453 valueArray[i] = Column.convertObject( 454 e.getAggregatedValue(session, valueArray[i]), 455 iArgType[i]); 456 } else { 457 valueArray[i] = e.getValue(session, iArgType[i]); 458 } 459 } 460 } 461 462 valueArray = getNotNull(valueArray); 463 464 if (valueArray == null) { 465 return null; 466 } 467 468 return getValue(session, valueArray); 469 } 470 471 Object updateAggregatingValue(Session session, 472 Object currValue) throws HsqlException { 473 474 Object [] valueArray = (Object []) currValue; 475 476 if (valueArray == null) { 477 valueArray = new Object [iArgCount]; 478 } 479 480 for (int i = 0; i < iArgCount; i++) { 481 Expression e = eArg[i]; 482 483 if (eArg[i] != null) { 484 valueArray[i] = e.updateAggregatingValue(session, 485 valueArray[i]); 486 } 487 } 488 489 return valueArray; 490 } 491 492 502 int getArgCount() { 503 return iSqlArgCount; 504 } 505 506 512 526 void replaceAliases(Expression[] columns, 527 int length) throws HsqlException { 528 529 Expression e; 530 531 for (int i = iSqlArgStart; i < iArgCount; i++) { 532 e = eArg[i]; 533 534 if (e != null) { 535 if (e.exprType == Expression.COLUMN) { 536 eArg[i] = e.getExpressionForAlias(columns, length); 537 } else { 538 e.replaceAliases(columns, length); 539 } 540 } 541 } 542 } 543 544 548 void checkTables(HsqlArrayList fa) throws HsqlException { 549 550 Expression e; 551 552 for (int i = iSqlArgStart; i < iArgCount; i++) { 553 e = eArg[i]; 554 555 if (e != null) { 556 e.checkTables(fa); 557 } 558 } 559 } 560 561 565 void resolveTables(TableFilter f) throws HsqlException { 566 567 Expression e; 568 569 for (int i = iSqlArgStart; i < iArgCount; i++) { 570 e = eArg[i]; 571 572 if (e != null) { 573 e.resolveTables(f); 574 } 575 } 576 } 577 578 582 void resolveType(Session session) throws HsqlException { 583 584 Expression e; 585 586 for (int i = iSqlArgStart; i < iArgCount; i++) { 587 e = eArg[i]; 588 589 if (e != null) { 590 if (e.isParam()) { 591 e.setDataType(iArgType[i]); 592 593 e.nullability = getArgNullability(i); 594 e.valueClassName = getArgClass(i).getName(); 595 } else { 596 e.resolveTypes(session); 597 } 598 } 599 } 600 } 601 602 607 boolean checkResolved(boolean check) throws HsqlException { 608 609 boolean result = true; 610 611 for (int i = iSqlArgStart; i < iArgCount; i++) { 612 if (eArg[i] != null) { 613 result = result && eArg[i].checkResolved(check); 614 } 615 } 616 617 return result; 618 } 619 620 624 int getArgType(int i) { 625 return iArgType[i]; 626 } 627 628 632 int getReturnType() { 633 return iReturnType; 634 } 635 636 640 void setArgument(int i, Expression e) { 641 642 if (bConnection) { 643 i++; 644 } 645 646 eArg[i] = e; 647 hasAggregate = hasAggregate || (e != null && e.isAggregate()); 648 } 649 650 653 String getDLL() throws HsqlException { 654 655 StringBuffer sb = new StringBuffer (); 656 657 String ddlName = name; 659 660 if (isSimple) { 661 return name; 662 } else if (Token.T_TRIM.equals(name)) { 663 664 sb.append(name).append('('); 666 667 boolean leading = eArg[2].testCondition(null); 668 boolean trailing = eArg[3].testCondition(null); 669 670 if (leading && trailing) { 671 sb.append(Token.T_BOTH); 672 } else { 673 sb.append(leading ? Token.T_LEADING 674 : Token.T_TRAILING); 675 } 676 677 sb.append(' '); 679 680 String charval = (String ) eArg[1].getValue(null); 681 682 sb.append(Column.createSQLString(charval)).append(' '); 683 sb.append(Token.T_FROM).append(' '); 684 sb.append(eArg[0].getDDL()).append(')'); 685 686 return sb.toString(); 687 } 688 689 if (sFunction.equals(name)) { 690 ddlName = StringConverter.toQuotedString(name, '"', true); 691 } 692 693 sb.append(ddlName).append('('); 694 695 for (int i = iSqlArgStart; i < eArg.length; i++) { 696 sb.append(eArg[i].getDDL()); 697 698 if (i < eArg.length - 1) { 699 sb.append(','); 700 } 701 } 702 703 sb.append(')'); 704 705 return sb.toString(); 706 } 707 708 711 public String describe(Session session) { 712 713 StringBuffer sb = new StringBuffer (); 714 715 sb.append(super.toString()).append("=[\n"); 716 sb.append(sFunction).append("("); 717 718 for (int i = iSqlArgStart; i < eArg.length; i++) { 719 sb.append("[").append(eArg[i].describe(session)).append("]"); 720 } 721 722 sb.append(") returns ").append(Types.getTypeString(getReturnType())); 723 sb.append("]\n"); 724 725 return sb.toString(); 726 } 727 728 731 String getReturnClassName() { 732 return returnClassName; 733 } 734 735 738 Class getArgClass(int i) { 739 return aArgClasses[i]; 740 } 741 742 745 int getArgNullability(int i) { 746 return bArgNullable[i] ? Expression.NULLABLE 747 : Expression.NO_NULLS; 748 } 749 750 Method getMethod() { 751 return mMethod; 752 } 753 } 754 | Popular Tags |