1 Circle class

The following Java class implements a Circle SQL UDT.

Copy
/*
 * 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.

Copy
$ 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

Copy
(38000) - Unknown throwable: (java.lang.UnsupportedClassVersionError: JVMCFRE003 bad major version; class=Circle, offset=6).

3 Install

Copy
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).

Copy
-- 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:

Copy
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.

Copy
-- 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

Copy
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