![]() |
SQL-J Language Reference
|
Reference Manual |
Method InvocationCloudscape allows you to invoke methods within SQL-J statements. Method invocation invokes an object method or a class method. Object methods can be static or non-static (the first form of the syntax shown below), and are invoked on instances of Java classes. Class methods (the second form of the syntax shown below) are static, and are invoked on Java classes. There is no requirement that all Java data types used by SQL-J be used in columns or be serializable. Only Java classes that are used in columns of tables created with CREATE TABLE must be serializable. You can invoke methods of non-serializable Java data types and pass the values they return to other Java methods. Only public methods are accessible through SQL-J. Private, protected, and package methods are not accessible through SQL-J. You can invoke methods that have a void return type only in the CALL statement (see CALL statement). To retrieve the value returned by a method, use a VALUES expression or a CALL statement using the ? = syntax (see VALUES expression) or if the method is a static method. Use a SELECT if the object is stored in the database (see SelectExpression). Syntax
{ The expression to which the JavaMethodName is applied is called the method receiver. ClassAlias is the name of a user-created or system-supplied alias for Java class. For more information, see CREATE CLASS ALIAS statement. MethodAlias is the name of a user-created alias for a static Java method. For more information, see CREATE METHOD ALIAS statement. Method Invocation ExamplesSELECT city.toString() FROM Cities VALUES (CLASS COM.cloudscape.database.PropertyInfo).getDatabaseProperties()
-- PropertyInfo is an alias for
-- PropertyInfo is an alias for VALUES NEW java.lang.Integer(3).shortValue() Type Conversion During Method InvocationYou can invoke Java methods on SQL-J expressions. Every SQL-J expression has an SQL-J type; every SQL-J type has a corresponding Java class. This means that you can invoke methods of that corresponding class on SQL-J expressions and access the values they return. For example, you can use an SQL-J INTEGER column as a method receiver to invoke any method of java.lang.Integer. You can also use an SQL-J INTEGER type as a parameter to a method that takes a parameter of type java.lang.Integer. For more information about the SQL-J to Java type conversion of method receivers and parameters during method invocation, see SQL-J to Java Type Correspondence. The values returned by methods are converted to SQL-J types in most cases. For more information about the Java to SQL-J type conversion of return values, see Java to SQL-J Type Correspondence. Method Invocation and NULLA null return value from a method is converted to a SQL-J NULL value, and SQL-J NULL values are converted to Java null references. If the value of the instance specified in an instance method invocation is null, then the result of the invocation is NULL. For example: SELECT city.getName() FROM Cities If the City column is NULL, the getName() method invocation returns a NULL. Primitive types in java (boolean, char, byte, short, int, long, float, and double) cannot be null. So, when a method returning a primitive is called with a null receiver, or a null value is used to reference a non-static field, the field reference evaluates to null only if the value is being returned to the SQL domain. If the value is being returned to another Java construct, a NullPointerException is raised. For example, in the following SQL-J statement, where the City column is null, a null is returned:
SELECT city.showTemperature() However, the situation changes when the return value of that method call is passed to another Java construct:
SELECT NEW java.lang.Double(city.showTemperature()) In this situation, if the City column contains any nulls, a NullPointerException is raised because the null value is passed to the Java constructor, which does not accept nulls. Note that when a method invocation evaluates to null because its receiver is null, the method is not actually called, and its arguments are not evaluated. The non-evaluation of arguments matters only in the case in which arguments are method calls that have side effects. (A side effect is anything the method does other than return a value using calculations based on its parameters. For example, changing the value of a field, static or non-static, doing I/O, and doing an update in the database are all side effects.) NOTE: This is not the expected behavior for method invocation in Java. Java rules state the evaluation of arguments happens (left to right) before the method is called. Within a Cloudscape SQL-J statement, this is not true if the receiver is null. Static Method Access and Null ReceiversIt is possible to call a static method, however, off of a null receiver. The method is actually called. For example:
-- method is called even though receiver is null
-- method is called even though receiver is null
-- the city column contains some nulls. Method Invocation and Dynamic Parameters (?)For a statement to compile correctly, Cloudscape must be able to infer the data type of a dynamic parameter (?). Because of signature overloading, to use a dynamic parameter as a parameter to a Java method, you sometimes must cast the data type of the ?. For example, consider a method myMethod with two signatures: You would not be able to call the method within an SQL-J statement using a dynamic parameter without casting the data type of the parameter, because Cloudscape would not be able to determine the data type of the parameter. If there is only one method in the class with that name and number of parameters, you do not need to cast. If there is more than one method with the same name and number of parameters, you do not need to cast if the other parameters that are not dynamic parameters (?) serve to distinguish the method. For more information about when dynamic parameters and method resolution, see Method Resolution and Type Correspondence. Method Invocation and ExceptionsA runtime exception that is thrown from a method is caught and translated to the following statement exception: The exception "{0}" was thrown from a user expression.
When the return value for a method is passed to another method, exceptions from the first method are not caught and translated. Only exceptions that are allowed to "escape" from user-written code into the rest of the query are caught and translated. Consider the following example: SELECT c1.catchesTheException(c2.throwsAnException()) The exception thrown by the throwsAnException method is caught by the catchesTheException method. Since catchesTheException does not throw an exception itself, the query does not get the statement exception described above. Methods invoked within SQL-J statements should not catch SQLExceptions of transaction severity or higher. If the SQLException is of transaction severity (for example, a deadlock), you will get unpredictable results. Instead, SQLExceptions of transaction severity or higher should be passed to the calling application. For more information, see Database-Side JDBC Methods and SQLExceptions in the Cloudscape Developer's Guide. Method ResolutionFor information on method resolution, see Method Resolution and Type Correspondence. Method Invocation and INTEGER LiteralsYou cannot directly call a method off an INTEGER literal, since following an INTEGER literal with a period turns it into a DOUBLE PRECISION literal. Instead, you can put it in parentheses or turn it into a DOUBLE PRECISION literal with an additional period; for example: Class Alias and Column Name AmbiguityIt is possible that a database has a class alias and a column of the same name and that a method call or field reference could be ambiguous. Where such duplication exists, Cloudscape first attempts to resolve the name as a column name. For example, in the following method call, City could be a class alias or a column: City.getName() If City is a class alias, the method must be a static method. If City is a column name, then the method could be any public method. The same holds true for field references. Usually, the context determines the resolution. If the statement is a SELECT, Cloudscape attempts to resolve City as a column name. It can do this if the table that contains the column City is in the FROM list. For example: SELECT City.getName() FROM Cities In this case, the method getName() can be either an object or a static class method. However, keep in mind that you don't typically execute static methods for every row in a table, so it makes more sense if the method is a non-static method. If the statement is not a SELECT, Cloudscape would not be able to resolve City as a column name, and it attempts to resolve it as a class alias: VALUES City.getName() In this case, the method getName() would have to be a static method (which, in the sample database, it is not). In the unlikely situation that you alter a table to add or drop a column name that is the same as a class alias, existing statements are invalidated and may be recompiled with a different resolution, as described below. Imagine a table called TropicalCities: CREATE TABLE TropicalCities (ID int, Name VARCHAR(85)) Your application also has a class called JBMSTours.serializabletypes.City, for which you have created the alias City. This class has a static method called findCity. You would probably execute the method with the VALUES statement (and not a SELECT statement), something like this: VALUES City.findCity(getCurrentConnection(), 3) However, you could conceivably execute it within a SELECT statement, in which case the method would be executed once for every row returned (which probably wouldn't make a lot of sense unless you passed in one of the columns somehow has an argument): SELECT name, City.findCity(getCurrentConnection(), ID) FROM TropicalCities Suppose that after compiling this statement, you alter the TropicalCities table and add a column called City: ALTER TABLE TropicalCities ADD COLUMN city SERIALIZE(City) Such a change would invalidate the existing statement and cause it to be recompiled upon the next execution. When Cloudscape recompiles the statement, it would notice the ambiguity in the name City in the select list and would interpret it as a column name instead of an alias name. The statement may then return very different results. |
|
![]() Cloudscape Version 3.6 For information about Cloudscape technical support, go to: www.cloudscape.com/support/.Copyright © 1998, 1999, 2000 Informix Software, Inc. All rights reserved. |