-- -- Data type mapping between PostgreSQL and Ruby. -- -- Each argument arrives as the natural Ruby class. CREATE FUNCTION t_classes(smallint, integer, bigint, real, double precision, numeric, boolean, text) RETURNS text LANGUAGE plruby AS $$ args.map { |a| a.class.name }.join(',') $$; SELECT t_classes(1::int2, 2, 3::int8, 4.5::real, 6.5::float8, 7.5::numeric, true, 'x'); t_classes ------------------------------------------------------------- Integer,Integer,Integer,Float,Float,String,TrueClass,String (1 row) -- Integer widths round-trip, including bigint. CREATE FUNCTION t_int8(bigint) RETURNS bigint LANGUAGE plruby AS $$ args[0] * 2 $$; SELECT t_int8(5000000000); t_int8 ------------- 10000000000 (1 row) -- Arbitrary-precision Integer (Bignum) returned into numeric. CREATE FUNCTION t_bignum() RETURNS numeric LANGUAGE plruby AS $$ 2 ** 100 $$; SELECT t_bignum(); t_bignum --------------------------------- 1267650600228229401496703205376 (1 row) -- Float arithmetic. CREATE FUNCTION t_float(double precision) RETURNS double precision LANGUAGE plruby AS $$ args[0] / 4 $$; SELECT t_float(10.0); t_float --------- 2.5 (1 row) -- numeric arrives losslessly as a String. CREATE FUNCTION t_numeric(numeric) RETURNS text LANGUAGE plruby AS $$ "#{args[0].class}:#{args[0]}" $$; SELECT t_numeric(3.14159265358979323846); t_numeric ------------------------------- String:3.14159265358979323846 (1 row) -- Booleans map to true/false and back. CREATE FUNCTION t_bool(boolean) RETURNS boolean LANGUAGE plruby AS $$ !args[0] $$; SELECT t_bool(true), t_bool(false); t_bool | t_bool --------+-------- f | t (1 row) -- NULL arrives as nil in a non-strict function. CREATE FUNCTION t_nullarg(integer) RETURNS text LANGUAGE plruby AS $$ args[0].nil? ? 'nil' : "val:#{args[0]}" $$; SELECT t_nullarg(NULL), t_nullarg(7); t_nullarg | t_nullarg -----------+----------- nil | val:7 (1 row) -- Empty array. CREATE FUNCTION t_empty_array() RETURNS int[] LANGUAGE plruby AS $$ [] $$; SELECT t_empty_array(); t_empty_array --------------- {} (1 row) -- Arrays may contain NULLs (nil). CREATE FUNCTION t_array_with_nil() RETURNS int[] LANGUAGE plruby AS $$ [1, nil, 3] $$; SELECT t_array_with_nil(); t_array_with_nil ------------------ {1,NULL,3} (1 row) -- Text arrays round-trip, quoting commas, quotes, and NULLs correctly. CREATE FUNCTION t_text_array(text[]) RETURNS text[] LANGUAGE plruby AS $$ args[0].map { |s| s.nil? ? nil : s.reverse } $$; SELECT t_text_array(ARRAY['ab', 'c,d', 'e"f', NULL, 'g\h']); t_text_array ------------------------------- {ba,"d,c","f\"e",NULL,"h\\g"} (1 row) -- A boolean array. CREATE FUNCTION t_bool_array(boolean[]) RETURNS boolean[] LANGUAGE plruby AS $$ args[0].map { |b| b.nil? ? nil : !b } $$; SELECT t_bool_array(ARRAY[true, false, NULL]); t_bool_array -------------- {f,t,NULL} (1 row) -- Multibyte text is handled by character, not by byte (UTF-8 databases). CREATE FUNCTION t_unicode(text) RETURNS text LANGUAGE plruby AS $$ "chars=#{args[0].length} rev=#{args[0].reverse}" $$; SELECT t_unicode(U&'h\00e9llo'); t_unicode ------------------- chars=5 rev=olléh (1 row)