001/* 002 * Copyright (c) 2015- Tada AB and other contributors, as listed below. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the The BSD 3-Clause License 006 * which accompanies this distribution, and is available at 007 * http://opensource.org/licenses/BSD-3-Clause 008 * 009 * Contributors: 010 * Chapman Flack 011 */ 012package org.postgresql.pljava.example.annotation; 013 014import java.sql.SQLData; 015import java.sql.SQLException; 016import java.sql.SQLInput; 017import java.sql.SQLOutput; 018 019import org.postgresql.pljava.annotation.SQLAction; 020import org.postgresql.pljava.annotation.BaseUDT; 021import org.postgresql.pljava.annotation.Function; 022import static org.postgresql.pljava.annotation.Function.Effects.IMMUTABLE; 023 024/** 025 * A User Defined Type with varlena storage, testing github issue 52. 026 * 027 * This looks from SQL like an integer type, but is stored in <em>unary</em>: 028 * the integer value <em>n</em> is represented by <em>n</em> {@code a} 029 * characters. That makes it easy to test how big a value gets correctly stored 030 * and retrieved. It should be about a GB, but in issue 52 was failing at 32768 031 * because of a narrowing assignment in the native code. 032 *<p> 033 * This example relies on {@code implementor} tags reflecting the PostgreSQL 034 * version, set up in the {@link ConditionalDDR} example. 035 */ 036@SQLAction(requires="varlena UDT", implementor="postgresql_ge_80300", install= 037" SELECT CASE v::text = v::javatest.VarlenaUDTTest::text " + 038" WHEN true THEN javatest.logmessage('INFO', 'works for ' || v) " + 039" ELSE javatest.logmessage('WARNING', 'fails for ' || v) " + 040" END " + 041" FROM (VALUES (('32767')), (('32768')), (('65536')), (('1048576'))) " + 042" AS t ( v )" 043) 044@BaseUDT(schema="javatest", provides="varlena UDT") 045public class VarlenaUDTTest implements SQLData { 046 int apop; 047 String typname; 048 049 public VarlenaUDTTest() { } 050 051 @Function(effects=IMMUTABLE) 052 public static VarlenaUDTTest parse( String s, String typname) { 053 int i = Integer.parseInt( s); 054 VarlenaUDTTest u = new VarlenaUDTTest(); 055 u.apop = i; 056 u.typname = typname; 057 return u; 058 } 059 060 @Function(effects=IMMUTABLE) 061 public String toString() { 062 return String.valueOf( apop); 063 } 064 065 public String getSQLTypeName() { 066 return typname; 067 } 068 069 @Function(effects=IMMUTABLE) 070 public void writeSQL( SQLOutput stream) throws SQLException { 071 for ( int i = 0 ; i < apop ; ++ i ) 072 stream.writeByte( (byte)'a'); 073 } 074 075 @Function(effects=IMMUTABLE) 076 public void readSQL( SQLInput stream, String typname) throws SQLException { 077 this.typname = typname; 078 int i = 0; 079 for ( ;; ++i ) 080 try { 081 stream.readByte(); 082 } 083 catch ( SQLException sqle ) { 084 if ( "22P03".equals( sqle.getSQLState()) ) 085 break; 086 throw sqle; 087 } 088 apop = i; 089 } 090}