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}