-- Test methods on Postgres.Type instances.
CREATE OR REPLACE FUNCTION typreceive_none_is_none() RETURNS text LANGUAGE python AS
$python$
from Postgres.types import int2, int4, int8, text, point, bytea

def main():
	# multiple types checked for no particular reason.
	assert int2.typreceive(None) is None
	assert int4.typreceive(None) is None
	assert int8.typreceive(None) is None
	assert text.typreceive(None) is None
	assert point.typreceive(None) is None
	assert bytea.typreceive(None) is None
	return 'success'
$python$;
SELECT typreceive_none_is_none();
 typreceive_none_is_none 
-------------------------
 success
(1 row)

DROP DOMAIN IF EXISTS binio_d;
NOTICE:  type "binio_d" does not exist, skipping
-- We should *not* be applying the check.
-- That is left to the user of the untrusted language.
CREATE DOMAIN binio_d AS int2 CHECK (VALUE > 100);
DROP TYPE IF EXISTS binio_c;
NOTICE:  type "binio_c" does not exist, skipping
CREATE TYPE binio_c AS (i int, t text);
DROP TYPE IF EXISTS binio_e;
NOTICE:  type "binio_e" does not exist, skipping
CREATE TYPE binio_e AS ENUM ('foo', 'bar');
CREATE OR REPLACE FUNCTION binio() RETURNS text LANGUAGE python AS
$python$
from Postgres.types import int2, int4, int8, text, bytea, regtype
from Postgres import Type

domain = Type(regtype('binio_d'))
composite = Type(regtype('binio_c'))
enum = Type(regtype('binio_e'))

# simple consistency checks for some types
samples = [
	int2(321), int2(123),
	int4(321), int4(123),
	int8(321), int8(123),
	text('meh'), text('feh'),
	bytea(b'(\x00)'), bytea(b'\x00\x01'),
	domain(200), domain(10),
	enum('foo'), enum('bar'),
	composite((123, 'foo')), composite((321, 'bar')),
]

def main():
	for x in samples:
		t = type(x)
		b = t.typsend(x)
		assert type(b) is bytes
		x2 = t.typreceive(b)
		assert type(x2) is type(x) 
		assert x2 == x
	return 'success'
$python$;
SELECT binio();
ERROR:  operator does not exist: binio_c = binio_c
HINT:  No operator matches the given name and argument type(s). You might need to add explicit type casts.
CONTEXT:  [exception from Python]
Traceback (most recent call last):
   File "public.binio()", line 28, in main
    assert x2 == x
 Postgres.Exception

[public.binio()]
CREATE OR REPLACE FUNCTION typreceive_not_a_buffer() RETURNS VOID LANGUAGE python AS
$python$
from Postgres.types import int4

def main():
	int4.typreceive(1234)
$python$;
SELECT typreceive_not_a_buffer();
ERROR:  function's "main" raised a Python exception
CONTEXT:  [exception from Python]
Traceback (most recent call last):
   File "public.typreceive_not_a_buffer()", line 5, in main
    int4.typreceive(1234)
 TypeError: expected an object with a buffer interface

[public.typreceive_not_a_buffer()]
CREATE OR REPLACE FUNCTION invalid_type_typsend() RETURNS VOID LANGUAGE python AS
$python$
from Postgres.types import int2, int4

def main():
	int4.typsend(int2(42))
$python$;
SELECT invalid_type_typsend();
ERROR:  function's "main" raised a Python exception
CONTEXT:  [exception from Python]
Traceback (most recent call last):
   File "public.invalid_type_typsend()", line 5, in main
    int4.typsend(int2(42))
 TypeError: cannot send Postgres.types.int2 using Postgres.types.int4

[public.invalid_type_typsend()]
CREATE OR REPLACE FUNCTION invalid_type_typreceive() RETURNS VOID LANGUAGE python AS
$python$
from Postgres.types import int2, int4

def main():
	int4.typreceive(int2.typsend(int2(42)))
$python$;
SELECT invalid_type_typreceive();
ERROR:  insufficient data left in message
CONTEXT:  [exception from Python]
Traceback (most recent call last):
   File "public.invalid_type_typreceive()", line 5, in main
    int4.typreceive(int2.typsend(int2(42)))
 Postgres.Exception

[public.invalid_type_typreceive()]
CREATE OR REPLACE FUNCTION check_typinput() RETURNS text LANGUAGE python AS
$python$
from Postgres.types import int2, int4, bytea, text, point

def main():
	assert str(int2.typinput('200')) == '200'
	assert str(int4.typinput('400')) == '400'
	assert bytes(bytea.typinput('\\000')) == b'\x00'
	assert str(point.typinput('(1.0,1.0)')) in ('(1.0,1.0)', '(1,1)')
	return 'success'
$python$;
SELECT check_typinput();
 check_typinput 
----------------
 success
(1 row)

-- make sure shell types are getting loaded
DROP TYPE IF EXISTS shell_check;
NOTICE:  type "shell_check" does not exist, skipping
CREATE TYPE shell_check;
CREATE OR REPLACE FUNCTION check_typisdefined(oid) RETURNS VOID LANGUAGE python AS
$python$
import Postgres

def main(oid):
	Postgres.Type(oid)
$python$;
SELECT check_typisdefined((SELECT oid FROM pg_type WHERE typname = 'shell_check' LIMIT 1));
ERROR:  type is not defined
CONTEXT:  [exception from Python]
Traceback (most recent call last):
   File "public.check_typisdefined(oid)", line 5, in main
    Postgres.Type(oid)
 Postgres.Exception

[public.check_typisdefined(oid)]
