agora inbox for pljava-dev@postgresql.org  
help / color / mirror / Atom feed
Subject: [Pljava-dev] VarLenTuple example code
Date: Thu, 28 Sep 2006 15:49:40 +0200
Message-ID: <451BD2F4.60202@tada.se> (raw)
In-Reply-To: <451BD0B1.8000408@logix-tt.com>
References: <451BD0B1.8000408@logix-tt.com>

Hmm, perhaps just an oversight, bot you don't have UDT syntax on the 
send/receive methods, i.e. this line:

+            AS 'org.postgresql.pljava.example.VarLenTuple.receive'

should read

+            AS 'UDT[org.postgresql.pljava.example.VarLenTuple] receive'

Regards,
Thomas Hallgren

Markus Schaber wrote:
> Hi, Thomas,
>
> Here's a small example I implemented for variable length data types.
>
> It's not useful for anything but an example.
>
> I included the source, as well as the diff for the examples.ddr file, so
> regard it as contribution.
>
> It all seems to work fine, apart from one small problem:
>
>   
>> [local]:pljavatest=# copy foo to '/tmp/foo' binary;
>> COPY
>> [local]:pljavatest=# copy foo from '/tmp/foo' binary;
>> ERROR:  Unable to find static method 
>> org.postgresql.pljava.example.VarLenTuple.receive
>> with signature
>> (Ljava/lang/String;)Lorg/postgresql/pljava/example/VarLenTuple;
>> CONTEXT:  COPY foo, line 1, column t
>>     
>
> >From our discussion, I had the impression that the receive method
> will get an VarLenTuple instance (as I created a type mapping)
> and not a String instance.
>
> Thanks,
> Markus
>   
> ------------------------------------------------------------------------
>
> Index: src/java/examples/deployment/examples.ddr
> ===================================================================
> RCS file: /usr/local/cvsroot/pljava/org.postgresql.pljava/src/java/examples/deployment/examples.ddr,v
> retrieving revision 1.35
> diff -u -r1.35 examples.ddr
> --- src/java/examples/deployment/examples.ddr	13 May 2006 09:18:38 -0000	1.35
> +++ src/java/examples/deployment/examples.ddr	28 Sep 2006 13:29:26 -0000
> @@ -430,6 +430,57 @@
>  			AS 'org.postgresql.pljava.example.ComplexTuple.logAndReturn'
>  			LANGUAGE java IMMUTABLE STRICT;
>  
> +		/* 
> +		 * Shell Type Definition for VarLenTuple:
> +		 */
> +		CREATE FUNCTION javatest.varlentuple(cstring) RETURNS javatest.varlentuple AS 'lower' LANGUAGE INTERNAL;
> +
> +		/* The scalar input function */
> +		CREATE FUNCTION varlentuple_in(cstring)
> +			RETURNS javatest.varlentuple
> +			AS 'UDT[org.postgresql.pljava.example.VarLenTuple] input'
> +			LANGUAGE java IMMUTABLE STRICT;
> +
> +		/* The scalar output function */
> +		CREATE FUNCTION varlentuple_out(javatest.varlentuple)
> +			RETURNS cstring
> +			AS 'UDT[org.postgresql.pljava.example.VarLenTuple] output'
> +			LANGUAGE java IMMUTABLE STRICT;
> +
> +		/* The scalar receive function */
> +		CREATE FUNCTION varlentuple_recv(internal)
> +			RETURNS javatest.varlentuple
> +			AS 'org.postgresql.pljava.example.VarLenTuple.receive'
> +			LANGUAGE java IMMUTABLE STRICT;
> +
> +		/* The scalar send function */
> +		CREATE FUNCTION varlentuple_send(javatest.varlentuple)
> +			RETURNS bytea
> +			AS 'org.postgresql.pljava.example.VarLenTuple.send'
> +			LANGUAGE java IMMUTABLE STRICT;
> +
> +		/* The scalar type declaration */
> +		CREATE TYPE javatest.varlentuple (
> +			internallength = -1,
> +			input = javatest.varlentuple_in,
> +			output = javatest.varlentuple_out,
> +			receive = javatest.varlentuple_recv,
> +			send = javatest.varlentuple_send,
> +			alignment = int4
> +			);
> +
> +		/* A test function that just logs and returns its argument.
> +		 */
> +		CREATE FUNCTION javatest.logvarlentuple(javatest.varlentuple)
> +			RETURNS javatest.varlentuple		
> +			AS 'org.postgresql.pljava.example.VarLenTuple.logAndReturn'
> +			LANGUAGE java IMMUTABLE STRICT;
> +
> +		/* Install the actual type mapping.
> +		 */
> +		SELECT sqlj.add_type_mapping('javatest.varlentuple', 'org.postgresql.pljava.example.VarLenTuple');
> +
> +
>  		/*
>  		 * An example using the ANY type
>  		 */
>   
> ------------------------------------------------------------------------
>
> /*
>  * Copyright (c) 2004, 2005, 2006 TADA AB - Taby Sweden
>  * Copyright (c) 2006 Markus Schaber <schabi at logix-tt.com>
>  * Distributed under the terms shown in the file COPYRIGHT
>  * found in the root directory of this distribution or at
>  * http://eng.tada.se/osprojects/COPYRIGHT.html
>  */
> package org.postgresql.pljava.example;
>
> import java.io.ByteArrayOutputStream;
> import java.io.DataOutputStream;
> import java.io.IOException;
> import java.nio.ByteOrder;
> import java.sql.SQLData;
> import java.sql.SQLException;
> import java.sql.SQLInput;
> import java.sql.SQLOutput;
> import java.util.logging.Logger;
>
>
> /** Datatype implementing a variable length Tuple of Doubles.
>  * 
>  * Not really useful except as an example and test for implementing fully fledged VARLENA datatyes
>  * including custom binary representation via Java. Code is intentionally kept simple, for the sake
>  * of efficency, and based on the ComplexTuple example.
>  * @author schabi
>  *
>  */
> public class VarLenTuple implements SQLData
> {
> 	private static Logger s_logger = Logger.getAnonymousLogger();
>
>         private static final String m_typeName = "javatest.varlentuple";
>         
>         private static final double[] EMPTY = {};
>         
> 	private double[] arr = EMPTY;
>
> 	public static VarLenTuple parse(String input, String typeName) throws SQLException
> 	{
>                 checkType(typeName);
>                 if ((input == null) || (input.length()<2) || (input.charAt(0)!='(') || (input.charAt(input.length()-1) != ')') ) {
>                     throw new SQLException("Illegal value for "+m_typeName+": "+input);
>                 }
>                 
>                 if (input.length()==2) {
>                     return new VarLenTuple();
>                 }
>                 String[] parts = input.substring(1, input.length()-1).split(",");
>                 
>                 double[] temparr = new double[parts.length];
>                 
>                 for (int i=0; i < parts.length; i++) {
>                     try {
>                         temparr[i] = Double.parseDouble(parts[i]);
>                     } catch (NumberFormatException e) {
>                         throw new SQLException("Bad double '"+parts[i]+"' while parsing "+m_typeName+": "+e.getMessage());
>                     }
>                 }
>                 
>                 return new VarLenTuple(temparr);
> 		
> 	}
>
>         private static void checkType(String typeName) throws SQLException {
>                 if (!m_typeName.equalsIgnoreCase(typeName)) {
>                         throw new SQLException("parser for "+m_typeName+" cannot deserialize type "+typeName+"!");
>                 }
>         }
>
> 	public VarLenTuple()
> 	{
> 	}
>
> 	public VarLenTuple(double[] arr)
> 	{
> 		this.arr = arr;
> 	}
>
> 	public String getSQLTypeName()
> 	{
> 		return m_typeName;
> 	}
>
> 	public void readSQL(SQLInput stream, String typeName) throws SQLException
> 	{
> 		s_logger.info(typeName + " from SQLInput");
>                 checkType(typeName);
>                 
>                 // fetch PostgreSQL VarLenA Header
> 		int bin_size = stream.readInt() & 0x3fffffff;
>                 int count = (bin_size - 4)/8;
>                 
>                 if (bin_size != (count*8 +4)) 
>                 {
>                     throw new SQLException("Bad Size Header!");
>                 }
>                 
>                 double[] temparr = new double[count];
>                 
>                 for (int i=0; i < count; i++) 
>                 {
>                     temparr[i] = stream.readDouble();
>                 }
>                 
> 		// all went well, we can assign the value
>                 arr = temparr;
> 	}
>
> 	public void writeSQL(SQLOutput stream) throws SQLException
> 	{
> 		s_logger.info(m_typeName + " to SQLOutput");
> 		int count = arr.length;
>                 
>                 stream.writeInt(count*8 +4);
>                 for (int i=0; i < count; i++) 
>                 {
>                     stream.writeDouble(arr[i]);
>                 }
> 	}
>
> 	public String toString()
> 	{
> 		s_logger.info(m_typeName + " toString");
> 		StringBuffer sb = new StringBuffer();
> 		sb.append('(');
> 		if (arr.length>0) 
>                 {
>                         sb.append(arr[0]);
>                         for (int i=1; i < arr.length; i++) 
>                         {
>                             sb.append(',');
>                             sb.append(arr[i]);
>                         }                  
>                 }
> 		sb.append(')');
> 		return sb.toString();
> 	}
>
> 	public static VarLenTuple logAndReturn(VarLenTuple cpl)
> 	{
> 		s_logger.info(cpl.getSQLTypeName() + cpl);
> 		return cpl;
> 	}
>         
>         public static VarLenTuple receive(SQLInput input) throws SQLException {
>                 int count = input.readInt();
>                 // we have to swap, as we use network byte order for external representation
>                 if (ByteOrder.nativeOrder()==ByteOrder.LITTLE_ENDIAN) {
>                     count = Integer.reverseBytes(count);
>                 }
>                 
>                 if (count==0) {
>                     return new VarLenTuple();
>                 }
>                 double[] temparr = new double[count];
>                 
>                 if (ByteOrder.nativeOrder()==ByteOrder.LITTLE_ENDIAN) {
>                         for (int i=0; i < count; i++) {
>                                 temparr[i] = Double.longBitsToDouble(Long.reverseBytes(input.readLong()));
>                         }
>                 } else {
>                         for (int i=0; i < count; i++) {
>                                 temparr[i] = input.readDouble();
>                         }
>                     
>                 }
>                 return new VarLenTuple(temparr);
>         }
>         
>         public static byte[] send(VarLenTuple input) throws SQLException {
>                 double[] temparr = input.arr;
>                 int count = temparr.length;
>                 
>                 ByteArrayOutputStream bos = new ByteArrayOutputStream(count*8+4);
>                 
>                 //DataOutputStream always uses Network Byte Order (Big Endian)
>                 DataOutputStream os = new DataOutputStream(bos);
>                 try {
>                         os.writeInt(count);
>                         
>                         for (int i=0; i < count; i++) {
>                             os.writeDouble(temparr[i]);
>                         }
>                         os.flush();
>                 } catch (IOException e) {
>                         throw new SQLException("Error writing temporary buffer: "+e.getMessage());
>                 }
>                 return bos.toByteArray();
>                 
>         }        
> }
>   
> ------------------------------------------------------------------------
>
> _______________________________________________
> Pljava-dev mailing list
> Pljava-dev at gborg.postgresql.org
> http://gborg.postgresql.org/mailman/listinfo/pljava-dev
>   





view thread (18+ messages)  latest in thread

Message-ID: <451BD2F4.60202@tada.se>
Permalink:  ../451BD2F4.60202@tada.se/
Also on:    postgresql.org/message-id/451BD2F4.60202@tada.se

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: pljava-dev@postgresql.org
  Subject: Re: [Pljava-dev] VarLenTuple example code
  In-Reply-To: <451BD2F4.60202@tada.se>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox