001/* 002 * Copyright (c) 2015-2023 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 */ 033@SQLAction(requires="varlena UDT", install= 034" SELECT CASE v::text = v::javatest.VarlenaUDTTest::text " + 035" WHEN true " + 036" THEN javatest.logmessage('INFO', 'VarlenaUDTTest works for ' || v) " + 037" ELSE javatest.logmessage('WARNING', 'VarlenaUDTTest fails for ' || v) " + 038" END " + 039" FROM (VALUES (('32767')), (('32768')), (('65536')), (('1048576'))) " + 040" AS t ( v )" 041) 042@BaseUDT(schema="javatest", provides="varlena UDT") 043public class VarlenaUDTTest implements SQLData { 044 int apop; 045 String typname; 046 047 public VarlenaUDTTest() { } 048 049 @Function(effects=IMMUTABLE) 050 public static VarlenaUDTTest parse( String s, String typname) { 051 int i = Integer.parseInt( s); 052 VarlenaUDTTest u = new VarlenaUDTTest(); 053 u.apop = i; 054 u.typname = typname; 055 return u; 056 } 057 058 @Function(effects=IMMUTABLE) 059 public String toString() { 060 return String.valueOf( apop); 061 } 062 063 public String getSQLTypeName() { 064 return typname; 065 } 066 067 @Function(effects=IMMUTABLE) 068 public void writeSQL( SQLOutput stream) throws SQLException { 069 for ( int i = 0 ; i < apop ; ++ i ) 070 stream.writeByte( (byte)'a'); 071 } 072 073 @Function(effects=IMMUTABLE) 074 public void readSQL( SQLInput stream, String typname) throws SQLException { 075 this.typname = typname; 076 int i = 0; 077 for ( ;; ++i ) 078 try { 079 stream.readByte(); 080 } 081 catch ( SQLException sqle ) { 082 if ( "22P03".equals( sqle.getSQLState()) ) 083 break; 084 throw sqle; 085 } 086 apop = i; 087 } 088}