SET standard_conforming_strings TO ON;
CREATE OR REPLACE FUNCTION nummod22(numeric) RETURNS numeric LANGUAGE python AS
$python$
def main(n):
	return type(n)(n, mod = (2,2))
$python$;
SELECT nummod22(0.22::numeric);
 nummod22 
----------
     0.22
(1 row)

-- should throw error
SELECT nummod22(1.22::numeric);
ERROR:  numeric field overflow
DETAIL:  A field with precision 2, scale 2 must round to an absolute value less than 1.
CONTEXT:  [exception from Python]
Traceback (most recent call last):
   File "public.nummod22(numeric)", line 3, in main
    return type(n)(n, mod = (2,2))
 Postgres.Exception

[public.nummod22(numeric)]
-- using mod with typinput
CREATE OR REPLACE FUNCTION strnummod22(numeric) RETURNS numeric LANGUAGE python AS
$python$
def main(n):
	return type(n)(str(n), mod = (2,2))
$python$;
SELECT strnummod22(0.22::numeric);
 strnummod22 
-------------
        0.22
(1 row)

-- should throw error
SELECT strnummod22(1.22::numeric);
ERROR:  numeric field overflow
DETAIL:  A field with precision 2, scale 2 must round to an absolute value less than 1.
CONTEXT:  [exception from Python]
Traceback (most recent call last):
   File "public.strnummod22(numeric)", line 3, in main
    return type(n)(str(n), mod = (2,2))
 Postgres.Exception

[public.strnummod22(numeric)]
-- truncate some varchars
CREATE OR REPLACE FUNCTION truncvc(varchar) RETURNS varchar LANGUAGE python AS
$python$
from Postgres.types import varchar
def main(n):
	return varchar(n, mod = (10,))
$python$;
SELECT truncvc('foo'::varchar);
 truncvc 
---------
 foo
(1 row)

SELECT truncvc('too-many-characters'::varchar);
  truncvc   
------------
 too-many-c
(1 row)

-- modin and modout
-- a few consistency checks to exercise the code paths.
CREATE OR REPLACE FUNCTION py_modin(anyelement, text[]) RETURNS int4 STRICT LANGUAGE python AS
$python$

def main(ob, modrepr):
	return type(ob).typmodin(modrepr)
$python$;
SELECT py_modin(1::numeric, ARRAY['2','2']) = numerictypmodin(ARRAY['2','2']::cstring[]) as numeric_check;
 numeric_check 
---------------
 t
(1 row)

SELECT py_modin(''::varchar, ARRAY['20']) = varchartypmodin(ARRAY['20']::cstring[]) as varchar_check;
 varchar_check 
---------------
 t
(1 row)

CREATE OR REPLACE FUNCTION py_modout(anyelement, int4) RETURNS text STRICT LANGUAGE python AS
$python$

def main(ob, mod):
	return type(ob).typmodout(mod)
$python$;
SELECT py_modout(1::numeric, -1) = numerictypmodout(-1)::text AS numeric_check;
 numeric_check 
---------------
 t
(1 row)

SELECT py_modout(1::numeric, 100) = numerictypmodout(100)::text AS numeric_check;
 numeric_check 
---------------
 t
(1 row)

SELECT py_modout(''::varchar, -1) = varchartypmodout(-1)::text AS varchar_check;
 varchar_check 
---------------
 t
(1 row)

SELECT py_modout(''::varchar, 20) = varchartypmodout(20)::text AS varchar_check;
 varchar_check 
---------------
 t
(1 row)

CREATE OR REPLACE FUNCTION py_modout_str(anyelement, text) RETURNS text STRICT LANGUAGE python AS
$python$

def main(ob, mod):
	return type(ob).typmodout(mod)
$python$;
-- error while building datum
SELECT py_modout_str(1::numeric, 'foo');
ERROR:  invalid input syntax for integer: "foo"
CONTEXT:  [exception from Python]
Traceback (most recent call last):
   File "public.py_modout_str(anyelement,text)", line 4, in main
    return type(ob).typmodout(mod)
 Postgres.Exception

[public.py_modout_str(anyelement,text)]
-- some errors
SELECT py_modin(1::numeric, ARRAY['not-a-number']);
ERROR:  invalid input syntax for integer: "not-a-number"
CONTEXT:  [exception from Python]
Traceback (most recent call last):
   File "public.py_modin(anyelement,text[])", line 4, in main
    return type(ob).typmodin(modrepr)
 Postgres.Exception

[public.py_modin(anyelement,text[])]
SELECT py_modin(1::numeric, ARRAY['3','2','1']);
ERROR:  invalid NUMERIC type modifier
CONTEXT:  [exception from Python]
Traceback (most recent call last):
   File "public.py_modin(anyelement,text[])", line 4, in main
    return type(ob).typmodin(modrepr)
 Postgres.Exception

[public.py_modin(anyelement,text[])]
