1 Circle class
The following Java class implements a Circle SQL
UDT
.
/* * Avoid package declaration or UDR will not be found as * they are reference from root package. */ /* * The Java mappings of the SQL user-defined type "circle". * */ import java.sql.*; import java.util.Scanner; public class Circle implements SQLData { private static double PI = 3.14159; /* * JDBC 2.0 style SQL/Java object mapping */ private double x; private double y; private double radius; private String type; /** * Default constructor for database object creation */ public Circle() { } /** * Internal constructor * * @param x * @param y * @param radius */ private Circle(double x, double y, double radius) { this.x = x; this.y = y; this.radius = radius; } /** * Returns the fully-qualified name of the SQL user-defined type that this object represents. */ @Override public String getSQLTypeName() { return type; } /** * Populates this object with data read from the database. */ @Override public void readSQL (SQLInput stream, String typeName) throws SQLException { type = typeName; x = stream.readDouble(); y = stream.readDouble(); radius = stream.readDouble(); } /** * Writes this object to the given SQL data stream, converting it back to its SQL value in the data source. */ @Override public void writeSQL (SQLOutput stream) throws SQLException { stream.writeDouble(x); stream.writeDouble(y); stream.writeDouble(radius); } /* * UDR to create a Circle from Float Java type (SQL SMALLFLOAT) */ public static Circle circle(Float x, Float y , Float r) { return new Circle(x, y, r); } /* * UDR to create a Circle from Double Java type (SQL DOUBLE) */ public static Circle circle(Double x, Double y, Double r) { return new Circle(x, y, r); } /* A Java UDR that returns the area of the circle. */ public static double area(Circle c) { return PI * c.radius * c.radius; } /* * Mapping for * function circle_input(circle) returns Circle */ public static Circle circle_input(String text) { double[] temp = new double[] {0,0,0}; Scanner sc = new Scanner(text != null ? text : ""); if (sc.hasNextDouble()) temp[0] = sc.nextDouble(); if (sc.hasNextDouble()) temp[1] = sc.nextDouble(); if (sc.hasNextDouble()) temp[2] = sc.nextDouble(); return new Circle(temp[0], temp[1], temp[2]); } /* * Mapping for * function circle_output(circle) returns lvarchar */ public static String circle_output(Circle c) { return String.format("%f %f %f", c.x, c.y, c.radius); } }
Notice that UDR classes must have no package declaration.
2 Compile
Compile the class using the database Java version (1.7) and generate a jar file with it.
$ javac -source 1.7 -target 1.7 Circle.java $ jar cvf Circle.jar Circle.class
Loading incompatible Java versions may throw an exception during methods execution
(38000) - Unknown throwable: (java.lang.UnsupportedClassVersionError: JVMCFRE003 bad major version; class=Circle, offset=6).
3 Install
database test; -- create the circle UDT create opaque type circle (internallength = 24, alignment = 8); -- install the Java class Circle (customize the URL for your installation) execute procedure install_jar( "file:$INFORMIXDIR/extend/krakatoa/examples/Circle.jar", "circle_jar", 0); -- Register the UDT name execute procedure setUDTExtName("circle", "Circle"); -- Declare functions circle to allow create a Circle from smallfloat or float sqltype -- Notice the mapping from SQLtype to Java type -- https://www.ibm.com/support/knowledgecenter/SSGU8G_11.70.0/com.ibm.jccids.doc/src/tpc/imjcc_rjvjdata.htm create function circle(smallfloat, smallfloat, smallfloat) returns Circle external name 'circle_jar:Circle.circle(java.lang.Float, java.lang.Float, java.lang.Float)' language java; create function circle(float, float, float) returns Circle external name 'circle_jar:Circle.circle(java.lang.Double, java.lang.Double, java.lang.Double)' language java; -- Create an area function create function area(circle) returns float external name 'circle_jar:Circle.area(Circle)' language java; -- Map a Circle to String so it can be represented in SQL statements create explicit cast (circle as lvarchar with circle_output); create function circle_output(circle) returns lvarchar external name 'circle_jar:Circle.circle_output(Circle)' language java;
3.1 Test
Now you can create a table with the Circle UDT
and insert data on it.
But you still have a problem to select the data cause thre is no conversion
defined for a Circle to be represented as a string (lvachar in sql output).
-- Create a table with circle type CREATE TABLE mytable (c circle); -- Insert a circle INSERT INFO mytable VALUES(circle(1,1,1)) -- Now select SELECT c, area(c) FROM mytable;
c 1.000000 1.000000 1.000000
(expression) 3,141590000000
You can check the JVPLOGFILE
for compilation messages:
tail -n 50 `onstat -g cfg | grep JVPLOGFILE | awk '{print $2}'`
Installing jar test.informix.circle_jar...
Setting UDT external name as Circle for type circle...
PARAM is not NULL
4 Type casts
Let's define implicit cast to allow conversion from input string to a Circle UDT
.
-- Map a lvarchar to String allowing construction of circles using strings create implicit cast (lvarchar as circle with circle_input); create function circle_input(lvarchar) returns Circle external name 'circle_jar:Circle.circle_input(java.lang.String)' language java;
4.1 Test
database test; -- Notice circle input is a varchar so the cast conversion is used insert into mytable values("2 2 2"); insert into mytable values("3 3 3"); -- test the Java UDR select c::char(40), area(c) area from mytable;
c 1.000000 1.000000 1.000000
area 3,141590000000
c 2.000000 2.000000 2.000000
area 12,56636000000
c 3.000000 3.000000 3.000000
area 28,27431000000