001/* 002 * Copyright (c) 2004-2016 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 * Tada AB 011 * Chapman Flack 012 */ 013package org.postgresql.pljava.example.annotation; 014 015import java.sql.SQLData; 016import java.sql.SQLException; 017import java.sql.SQLInput; 018import java.sql.SQLOutput; 019import java.util.logging.Logger; 020 021import org.postgresql.pljava.annotation.Function; 022import org.postgresql.pljava.annotation.MappedUDT; 023import org.postgresql.pljava.annotation.SQLAction; 024 025import static org.postgresql.pljava.annotation.Function.Effects.IMMUTABLE; 026import static 027 org.postgresql.pljava.annotation.Function.OnNullInput.RETURNS_NULL; 028 029/** 030 * Example of a "mirrored UDT": a user-defined type that exposes to Java the 031 * internal representation of an existing (but not SQL-standard) PostgreSQL 032 * type. Naturally, the author of this type has to know (from the PostgreSQL 033 * source) that a {@code Point} is stored as two {@code float8}s, {@code x} 034 * first and then {@code y}. 035 */ 036@SQLAction(requires={"point mirror type", "point assertHasValues"}, install= 037 "SELECT javatest.assertHasValues(CAST('(1,2)' AS point), 1, 2)" 038) 039@MappedUDT(name="point", provides="point mirror type") 040public class Point implements SQLData { 041 private static Logger s_logger = Logger.getAnonymousLogger(); 042 043 /** 044 * Return the same 'point' passed in, logging its contents at level INFO. 045 * @param pt any instance of the type this UDT mirrors 046 * @return the same instance passed in 047 */ 048 @Function(schema="javatest", requires="point mirror type", 049 effects=IMMUTABLE, onNullInput=RETURNS_NULL) 050 public static Point logAndReturn(Point pt) { 051 s_logger.info(pt.getSQLTypeName() + pt); 052 return pt; 053 } 054 055 /** 056 * Assert a 'point' has given x and y values, to test that its 057 * representation in Java corresponds to what PostgreSQL sees. 058 * @param pt an instance of this UDT 059 * @param x the x value it should have 060 * @param y the y value it should have 061 * @throws SQLException if the values do not match 062 */ 063 @Function(schema="javatest", 064 requires="point mirror type", provides="point assertHasValues", 065 effects=IMMUTABLE, onNullInput=RETURNS_NULL) 066 public static void assertHasValues(Point pt, double x, double y) 067 throws SQLException 068 { 069 if ( pt.m_x != x || pt.m_y != y ) 070 throw new SQLException("assertHasValues fails"); 071 } 072 073 private double m_x; 074 private double m_y; 075 076 private String m_typeName; 077 078 @Override 079 public String getSQLTypeName() { 080 return m_typeName; 081 } 082 083 @Override 084 public void readSQL(SQLInput stream, String typeName) throws SQLException { 085 s_logger.info(typeName + " from SQLInput"); 086 m_x = stream.readDouble(); 087 m_y = stream.readDouble(); 088 m_typeName = typeName; 089 } 090 091 @Override 092 public void writeSQL(SQLOutput stream) throws SQLException { 093 s_logger.info(m_typeName + " to SQLOutput"); 094 stream.writeDouble(m_x); 095 stream.writeDouble(m_y); 096 } 097 098 @Override 099 public String toString() 100 { 101 return String.format("(%g,%g)", m_x, m_y); 102 } 103}