diff --git a/README.markdown b/README.markdown index 4e7c549..e501dc5 100644 --- a/README.markdown +++ b/README.markdown @@ -9,17 +9,29 @@ PL/ruby Prerequisite ------------ -> * ruby 1.8.7 or later (maybe 1.8.6 too) +> * ruby 1.8.7 or later > * postgresql >= 7.3 - All PostgreSQL headers need to be installed. Command (see `INSTALL` in the - directory postgresql-7.x.y) + All PostgreSQL development headers need to be installed. If you installed + using a package manager of some sort, be sure to install the "dev" package. + + If you built from source you can run the following command: make install-all-headers Installation ------------ + If you're installing the gem: + + gem install postgresql-plruby + + If you want to allow the ability to require external libraries: + + gem install postgresql-plruby -- --with-safe-level=0 + + If you're doing things the old fashioned way: + ruby extconf.rb make make install @@ -92,8 +104,7 @@ Test (and examples) language 'C'; create trusted language 'plruby' - handler plruby_call_handler - lancompiler 'PL/Ruby'; + handler plruby_call_handler; The `trusted` keyword on `create language` tells PostgreSQL, @@ -102,6 +113,24 @@ Test (and examples) absolutely safe, because there is nothing a normal user can do with PL/Ruby, to get around access restrictions he/she has. +Sample Functions +---------------- + CREATE FUNCTION ruby_max(int4, int4) RETURNS int4 AS ' + if args[0] > args[1] + return args[0] + else + return args[1] + end + ' LANGUAGE 'plruby'; + + select ruby_max(1,2); + + CREATE FUNCTION ruby_max2(x int4, y int4) RETURNS int4 AS ' + return x > y ? x : y + ' LANGUAGE 'plruby'; + + select ruby_max2(7,8); + Documentation ------------- diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..390e8db --- /dev/null +++ b/Rakefile @@ -0,0 +1,48 @@ +require 'rake' +require 'rake/testtask' +require 'rake/clean' +require 'rbconfig' +include Config + +# TODO: Reorganize code to use Rake compiler. + +CLEAN.include( + '**/*.gem', # Gem files + '**/*.rbc', # Rubinius + '**/*.o', # C object file + '**/*.log', # Ruby extension build log + '**/Makefile', # C Makefile + '**/conftest.dSYM', # OS X build directory + "**/*.#{CONFIG['DLEXT']}" # C shared object +) + +desc 'Build the postgresql-plruby source code' +task :build => [:clean] do + ruby "extconf.rb" + sh "make" +end + +namespace :gem do + desc 'Create the gem' + task :create => [:clean] do + spec = eval(IO.read('postgresql-plruby.gemspec')) + Gem::Builder.new(spec).build + end + + desc 'Install the gem' + task :install => [:create] do + file = Dir["*.gem"].first + sh "gem install #{file}" + end +end + +# TODO: Reorganize tests to make them work. +Rake::TestTask.new do |t| + task :test => [:build] + t.libs << 'ext' + t.test_files = FileList['test/**/*.rb'] + t.warning = true + t.verbose = true +end + +task :default => :test diff --git a/extconf.rb b/extconf.rb index 06a6284..cb97dc8 100755 --- a/extconf.rb +++ b/extconf.rb @@ -56,8 +56,7 @@ def create_lang(version = 74, suffix = '', safe = 0) language '#{language}'; create #{trusted} language 'plruby#{suffix}' - handler plruby#{suffix}_call_handler - lancompiler 'PL/Ruby#{suffix}'; + handler plruby#{suffix}_call_handler; ======================================================================== EOT @@ -87,6 +86,7 @@ def rule(target, clean = nil) $CFLAGS << " -I" << include_dir $CFLAGS << " -I" << `#{pg_config} --includedir-server`.strip + if safe = with_config("safe-level") safe = Integer(safe) if safe < 0 @@ -141,6 +141,7 @@ def rule(target, clean = nil) end have_func("rb_block_call") +have_header("ruby/st.h") have_header("st.h") if version >= 74 @@ -156,6 +157,8 @@ def rule(target, clean = nil) $CFLAGS += " -DPG_PL_TRYCATCH" end +have_library('pq', 'PQconnectdb') + enable_conversion = false if enable_conversion = enable_config("conversion", true) $CFLAGS += " -DPLRUBY_ENABLE_CONVERSION" diff --git a/postgresql-plruby.gemspec b/postgresql-plruby.gemspec new file mode 100644 index 0000000..c423e7f --- /dev/null +++ b/postgresql-plruby.gemspec @@ -0,0 +1,55 @@ +require 'rubygems' +require 'rbconfig' + +Gem::Specification.new do |spec| + spec.name = 'globegit-postgresql-plruby' + spec.version = '0.5.4' + spec.authors = ['Akinori MUSHA', 'Guy Decoux'] + spec.license = 'Ruby' + spec.email = 'akinori@musha.org' + spec.homepage = 'https://github.com/knu/postgresql-plruby' + spec.summary = 'Enable Ruby for use as a procedural language within PostgreSQL' + spec.test_files = Dir['test/test*'] + spec.extensions = ['extconf.rb'] + spec.files = Dir['**/*'].reject{ |f| f.include?('git') || f.include?('tmp') } + + spec.rubyforge_project = 'plruby' + + spec.extra_rdoc_files = [ + 'README.markdown', + 'Changes' + ] + Dir['ext/*.c'] + + spec.description = <<-EOF + PL/Ruby is a loadable procedural language for the PostgreSQL database + system that enables the Ruby language to create functions and trigger + procedures. + EOF + + plruby_bin = 'plruby.' + Config::CONFIG['DLEXT'] + plruby_dir = File.join(spec.name + '-' + spec.version.to_s, 'src') + path_to_binary = File.join(Gem.dir, 'gems', plruby_dir, plruby_bin) + + possible_paths = Gem.path.map{ |path| + File.join(path, 'gems', plruby_dir, plruby_bin) + } + + spec.post_install_message = <<-EOF + + Now run the following commands from within a postgresql shell in order + to create the plruby language on in database server: + + create function plruby_call_handler() returns language_handler + as '#{path_to_binary}' + language 'C'; + + create trusted language 'plruby' + handler plruby_call_handler; + + NOTE: Your actual path to #{plruby_bin} may be different. Possible + paths to the plruby binary are: + + #{possible_paths.join("\n ")} + + EOF +end diff --git a/src/conversions/basic/extconf.rb b/src/conversions/basic/extconf.rb index d4833b8..f788d9c 100644 --- a/src/conversions/basic/extconf.rb +++ b/src/conversions/basic/extconf.rb @@ -4,4 +4,5 @@ !enable_config("plruby-shared") $LIBRUBYARG = "" end +have_library('ruby18', 'ruby_init') create_makefile('plruby/plruby_basic') diff --git a/src/conversions/bitstring/extconf.rb b/src/conversions/bitstring/extconf.rb index e980c1e..b6f89d3 100644 --- a/src/conversions/bitstring/extconf.rb +++ b/src/conversions/bitstring/extconf.rb @@ -4,4 +4,5 @@ !enable_config("plruby-shared") $LIBRUBYARG = "" end +have_library('ruby18', 'ruby_init') create_makefile('plruby/plruby_bitstring') diff --git a/src/conversions/bitstring/plruby_bitstring.c b/src/conversions/bitstring/plruby_bitstring.c index fdb2253..3d74617 100644 --- a/src/conversions/bitstring/plruby_bitstring.c +++ b/src/conversions/bitstring/plruby_bitstring.c @@ -195,8 +195,14 @@ name_(VALUE obj, VALUE a) \ } BIT_OPERATOR(pl_bit_add, bitcat); +#if PG_PL_VERSION >= 91 +/* avoid the names bitand and bitor, since they are C++ keywords */ +BIT_OPERATOR(pl_bit_and, bit_and); +BIT_OPERATOR(pl_bit_or, bit_or); +#else BIT_OPERATOR(pl_bit_and, bitand); BIT_OPERATOR(pl_bit_or, bitor); +#endif BIT_OPERATOR(pl_bit_xor, bitxor); static VALUE diff --git a/src/conversions/datetime/extconf.rb b/src/conversions/datetime/extconf.rb index c5de23b..caeebea 100644 --- a/src/conversions/datetime/extconf.rb +++ b/src/conversions/datetime/extconf.rb @@ -4,4 +4,5 @@ !enable_config("plruby-shared") $LIBRUBYARG = "" end +have_library('ruby18', 'ruby_init') create_makefile('plruby/plruby_datetime') diff --git a/src/conversions/geometry/extconf.rb b/src/conversions/geometry/extconf.rb index 9fcf48e..74655b3 100644 --- a/src/conversions/geometry/extconf.rb +++ b/src/conversions/geometry/extconf.rb @@ -4,4 +4,5 @@ !enable_config("plruby-shared") $LIBRUBYARG = "" end +have_library('ruby18', 'ruby_init') create_makefile('plruby/plruby_geometry') diff --git a/src/conversions/network/extconf.rb b/src/conversions/network/extconf.rb index 29952ee..612e7fa 100644 --- a/src/conversions/network/extconf.rb +++ b/src/conversions/network/extconf.rb @@ -4,4 +4,5 @@ !enable_config("plruby-shared") $LIBRUBYARG = "" end +have_library('ruby18', 'ruby_init') create_makefile('plruby/plruby_network') diff --git a/src/plpl.c b/src/plpl.c index 8105c75..eecc7c9 100644 --- a/src/plpl.c +++ b/src/plpl.c @@ -359,7 +359,7 @@ pl_tuple_s_new(PG_FUNCTION_ARGS, pl_proc_desc *prodesc) GetTuple(res, tpl); tpl->cxt = rsi->econtext->ecxt_per_query_memory; tpl->dsc = rsi->expectedDesc; - tpl->att = TupleDescGetAttInMetadata(rsi->expectedDesc); + tpl->att = TupleDescGetAttInMetadata(tpl->dsc); tpl->pro = prodesc; rb_thread_local_aset(rb_thread_current(), id_thr, res); return res; @@ -547,32 +547,6 @@ struct each_st { TupleDesc tup; }; -static VALUE -pl_each(VALUE obj, struct each_st *st) -{ - VALUE key, value; - char *column; - int attn; - - key = rb_ary_entry(obj, 0); - value = rb_ary_entry(obj, 1); - key = plruby_to_s(key); - column = RSTRING_PTR(key); - attn = SPI_fnumber(st->tup, column); - if (attn <= 0 || st->tup->attrs[attn - 1]->attisdropped) { - rb_raise(pl_ePLruby, "Invalid column name '%s'", column); - } - attn -= 1; - if (TYPE(st->res) != T_ARRAY || !RARRAY_PTR(st->res)) { - rb_raise(pl_ePLruby, "expected an Array"); - } - if (attn >= RARRAY_LEN(st->res)) { - rb_raise(pl_ePLruby, "Invalid column position '%d'", attn); - } - RARRAY_PTR(st->res)[attn] = value; - return Qnil; -} - static HeapTuple pl_tuple_heap(VALUE c, VALUE tuple) { @@ -706,6 +680,15 @@ pl_tuple_put(VALUE c, VALUE tuple) return Qnil; } +static VALUE +pl_ary_collect(VALUE c, VALUE ary) +{ + PLRUBY_BEGIN_PROTECT(1); + rb_ary_push(ary,c); + PLRUBY_END_PROTECT; + return Qnil; +} + static Datum pl_tuple_datum(VALUE c, VALUE tuple) { @@ -841,7 +824,7 @@ pl_warn(argc, argv, obj) rb_raise(pl_ePLruby, "invalid syntax"); } PLRUBY_BEGIN_PROTECT(1); - elog(level, RSTRING_PTR(res)); + elog(level, "%s", RSTRING_PTR(res)); PLRUBY_END_PROTECT; return Qnil; } @@ -1388,7 +1371,117 @@ plruby_return_value(struct pl_thread_st *plth, pl_proc_desc *prodesc, rb_raise(pl_ePLruby, "no description given"); } rsi = (ReturnSetInfo *)fcinfo->resultinfo; - if ((rsi->allowedModes & SFRM_Materialize) && rsi->expectedDesc) { + if (prodesc->result_is_setof && !rsi->expectedDesc) { + VALUE res, retary, arg; + struct pl_arg *args; + TupleDesc tupdesc; + FuncCallContext *funcctx; + Datum result; + + arg = Data_Make_Struct(rb_cObject, struct pl_arg, pl_arg_mark, free, args); + args->id = rb_intern(RSTRING_PTR(value_proname)); + args->ary = ary; +#if PG_PL_VERSION >= 75 + args->named = prodesc->named_args; +#endif + + if (SRF_IS_FIRSTCALL()) + { + MemoryContext oldcontext; + + funcctx = SRF_FIRSTCALL_INIT(); + + oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); + + /* Build a tuple descriptor for our result type */ + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("function returning record called in context " + "that cannot accept type record"))); + /* + * generate attribute metadata needed later to produce tuples from raw + * C strings + */ + funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc); + + MemoryContextSwitchTo(oldcontext); + + retary = rb_ary_new(); +#if HAVE_RB_BLOCK_CALL + if (args->named) { + res = rb_block_call(pl_mPLtemp, args->id, + RARRAY_LEN(args->ary), + RARRAY_PTR(args->ary), + pl_ary_collect, retary); + } + else { + res = rb_block_call(pl_mPLtemp, args->id, + 1, &args->ary, + pl_ary_collect, retary); + } +#else + res = rb_iterate(pl_func, arg, pl_ary_collect, retary); +#endif + elog(NOTICE, "returned array len is: %ld", RARRAY_LEN(retary) ); + + funcctx->max_calls = RARRAY_LEN(retary) ; + funcctx->user_fctx = (void *)retary; + + } + funcctx = SRF_PERCALL_SETUP(); + + retary = (VALUE)funcctx->user_fctx; + + if (funcctx->call_cntr < funcctx->max_calls) /* do when there is more left to send */ + { + char ** values; + HeapTuple tuple; + size_t idx; + VALUE resary; + + resary = RARRAY_PTR(retary)[funcctx->call_cntr]; + values = (char **)palloc(RARRAY_LEN(resary) * sizeof(char *)); + + for ( idx = 0; idx < RARRAY_LEN(resary); idx++ ) + { + VALUE str = rb_ary_entry( resary, idx ); + if (TYPE(str) != T_STRING) { + str = rb_obj_as_string(str); + } + values[idx] = pstrdup( StringValueCStr( str ) ); + } + + /* build a tuple */ + tuple = BuildTupleFromCStrings(funcctx->attinmeta, values); + + /* make the tuple into a datum */ + result = HeapTupleGetDatum(tuple); + } + + PLRUBY_BEGIN_PROTECT(1); + { + MemoryContext oldcxt; + int rc; + + oldcxt = MemoryContextSwitchTo(plruby_spi_context); + if ((rc = SPI_finish()) != SPI_OK_FINISH) { + elog(ERROR, "SPI_finish() failed : %d", rc); + } + MemoryContextSwitchTo(oldcxt); + } + PLRUBY_END_PROTECT; + + if ( funcctx->call_cntr < funcctx->max_calls ) + { + SRF_RETURN_NEXT(funcctx, result); + } + else + { + SRF_RETURN_DONE(funcctx); + } + + } else if ((rsi->allowedModes & SFRM_Materialize) && rsi->expectedDesc) { VALUE tuple, res, arg; struct pl_arg *args; struct pl_tuple *tpl; diff --git a/src/plruby.c b/src/plruby.c index 69c493b..7ea5843 100644 --- a/src/plruby.c +++ b/src/plruby.c @@ -703,7 +703,6 @@ pl_validator_handler(struct pl_thread_st *plth) Datum PLRUBY_CALL_HANDLER(PG_FUNCTION_ARGS) { - VALUE result; struct pl_thread_st plth; plth.fcinfo = fcinfo; @@ -958,7 +957,8 @@ pl_compile(struct pl_thread_st *plth, int istrigger) break; } } - + + prodesc->result_is_setof = procStruct->proretset; if (procStruct->proretset) { Oid funcid, functypeid; char functyptype; diff --git a/src/plruby.h b/src/plruby.h index 10cb107..cf57fdf 100644 --- a/src/plruby.h +++ b/src/plruby.h @@ -4,6 +4,7 @@ #include "postgres.h" #include "executor/spi.h" +#include "executor/executor.h" #include "commands/trigger.h" #include "utils/elog.h" #include "utils/builtins.h" @@ -37,7 +38,9 @@ #include "package.h" #include -#if HAVE_ST_H +#if HAVE_RUBY_ST_H +#include +#elif HAVE_ST_H #include #endif @@ -214,6 +217,7 @@ typedef struct pl_proc_desc int result_len; bool result_is_array; bool result_val; + bool result_is_setof; char result_align; int nargs; #if PG_PL_VERSION >= 75 diff --git a/test/conv_bitstring/b.rb b/test/conv_bitstring/b.rb index 6310536..a0c7b2b 100755 --- a/test/conv_bitstring/b.rb +++ b/test/conv_bitstring/b.rb @@ -36,8 +36,7 @@ language '#{language}'; create trusted procedural language 'plruby#{suffix}' - handler plruby#{suffix}_call_handler - lancompiler 'PL/Ruby'; + handler plruby#{suffix}_call_handler; EOF f.close rescue diff --git a/test/conv_geometry/b.rb b/test/conv_geometry/b.rb index 6310536..a0c7b2b 100755 --- a/test/conv_geometry/b.rb +++ b/test/conv_geometry/b.rb @@ -36,8 +36,7 @@ language '#{language}'; create trusted procedural language 'plruby#{suffix}' - handler plruby#{suffix}_call_handler - lancompiler 'PL/Ruby'; + handler plruby#{suffix}_call_handler; EOF f.close rescue diff --git a/test/conv_network/b.rb b/test/conv_network/b.rb index 6310536..a0c7b2b 100755 --- a/test/conv_network/b.rb +++ b/test/conv_network/b.rb @@ -36,8 +36,7 @@ language '#{language}'; create trusted procedural language 'plruby#{suffix}' - handler plruby#{suffix}_call_handler - lancompiler 'PL/Ruby'; + handler plruby#{suffix}_call_handler; EOF f.close rescue diff --git a/test/conv_network/test.expected.91 b/test/conv_network/test.expected.91 new file mode 100644 index 0000000..35c52b1 --- /dev/null +++ b/test/conv_network/test.expected.91 @@ -0,0 +1,237 @@ +create table pl_inet ( + host text, abbrev text, masklen int, + network inet, netmask inet, first inet, last inet +); +create or replace function inet_val(inet) returns pl_inet as ' + a = args[0] + [a.host, a.abbrev, a.masklen, a.network, a.netmask, + a.first, a.last] + ' language 'plruby'; +select * from inet_val('192.168.1'::cidr); + host | abbrev | masklen | network | netmask | first | last +-------------+----------------+---------+----------------+---------------+----------------+--------------- + 192.168.1.0 | 192.168.1.0/24 | 24 | 192.168.1.0/24 | 255.255.255.0 | 192.168.1.0/24 | 192.168.1.255 +(1 row) + +select * from inet_val('192.168.1.226/24'::inet); + host | abbrev | masklen | network | netmask | first | last +---------------+------------------+---------+----------------+---------------+----------------+--------------- + 192.168.1.226 | 192.168.1.226/24 | 24 | 192.168.1.0/24 | 255.255.255.0 | 192.168.1.0/24 | 192.168.1.255 +(1 row) + +select * from inet_val('192.168.1.0/24'::cidr); + host | abbrev | masklen | network | netmask | first | last +-------------+----------------+---------+----------------+---------------+----------------+--------------- + 192.168.1.0 | 192.168.1.0/24 | 24 | 192.168.1.0/24 | 255.255.255.0 | 192.168.1.0/24 | 192.168.1.255 +(1 row) + +select * from inet_val('192.168.1.226'::inet); + host | abbrev | masklen | network | netmask | first | last +---------------+---------------+---------+---------------+-----------------+---------------+--------------- + 192.168.1.226 | 192.168.1.226 | 32 | 192.168.1.226 | 255.255.255.255 | 192.168.1.226 | 192.168.1.226 +(1 row) + +select * from inet_val('192.168.1'::cidr); + host | abbrev | masklen | network | netmask | first | last +-------------+----------------+---------+----------------+---------------+----------------+--------------- + 192.168.1.0 | 192.168.1.0/24 | 24 | 192.168.1.0/24 | 255.255.255.0 | 192.168.1.0/24 | 192.168.1.255 +(1 row) + +select * from inet_val('192.168.1.0/24'::inet); + host | abbrev | masklen | network | netmask | first | last +-------------+----------------+---------+----------------+---------------+----------------+--------------- + 192.168.1.0 | 192.168.1.0/24 | 24 | 192.168.1.0/24 | 255.255.255.0 | 192.168.1.0/24 | 192.168.1.255 +(1 row) + +select * from inet_val('192.168.1'::cidr); + host | abbrev | masklen | network | netmask | first | last +-------------+----------------+---------+----------------+---------------+----------------+--------------- + 192.168.1.0 | 192.168.1.0/24 | 24 | 192.168.1.0/24 | 255.255.255.0 | 192.168.1.0/24 | 192.168.1.255 +(1 row) + +select * from inet_val('192.168.1.0/25'::inet); + host | abbrev | masklen | network | netmask | first | last +-------------+----------------+---------+----------------+-----------------+----------------+--------------- + 192.168.1.0 | 192.168.1.0/25 | 25 | 192.168.1.0/25 | 255.255.255.128 | 192.168.1.0/25 | 192.168.1.127 +(1 row) + +select * from inet_val('192.168.1'::cidr); + host | abbrev | masklen | network | netmask | first | last +-------------+----------------+---------+----------------+---------------+----------------+--------------- + 192.168.1.0 | 192.168.1.0/24 | 24 | 192.168.1.0/24 | 255.255.255.0 | 192.168.1.0/24 | 192.168.1.255 +(1 row) + +select * from inet_val('192.168.1.255/24'::inet); + host | abbrev | masklen | network | netmask | first | last +---------------+------------------+---------+----------------+---------------+----------------+--------------- + 192.168.1.255 | 192.168.1.255/24 | 24 | 192.168.1.0/24 | 255.255.255.0 | 192.168.1.0/24 | 192.168.1.255 +(1 row) + +select * from inet_val('192.168.1'::cidr); + host | abbrev | masklen | network | netmask | first | last +-------------+----------------+---------+----------------+---------------+----------------+--------------- + 192.168.1.0 | 192.168.1.0/24 | 24 | 192.168.1.0/24 | 255.255.255.0 | 192.168.1.0/24 | 192.168.1.255 +(1 row) + +select * from inet_val('192.168.1.255/25'::inet); + host | abbrev | masklen | network | netmask | first | last +---------------+------------------+---------+------------------+-----------------+------------------+--------------- + 192.168.1.255 | 192.168.1.255/25 | 25 | 192.168.1.128/25 | 255.255.255.128 | 192.168.1.128/25 | 192.168.1.255 +(1 row) + +select * from inet_val('10'::cidr); + host | abbrev | masklen | network | netmask | first | last +----------+------------+---------+------------+-----------+------------+---------------- + 10.0.0.0 | 10.0.0.0/8 | 8 | 10.0.0.0/8 | 255.0.0.0 | 10.0.0.0/8 | 10.255.255.255 +(1 row) + +select * from inet_val('10.1.2.3/8'::inet); + host | abbrev | masklen | network | netmask | first | last +----------+------------+---------+------------+-----------+------------+---------------- + 10.1.2.3 | 10.1.2.3/8 | 8 | 10.0.0.0/8 | 255.0.0.0 | 10.0.0.0/8 | 10.255.255.255 +(1 row) + +select * from inet_val('10.0.0.0'::cidr); + host | abbrev | masklen | network | netmask | first | last +----------+----------+---------+----------+-----------------+----------+---------- + 10.0.0.0 | 10.0.0.0 | 32 | 10.0.0.0 | 255.255.255.255 | 10.0.0.0 | 10.0.0.0 +(1 row) + +select * from inet_val('10.1.2.3/8'::inet); + host | abbrev | masklen | network | netmask | first | last +----------+------------+---------+------------+-----------+------------+---------------- + 10.1.2.3 | 10.1.2.3/8 | 8 | 10.0.0.0/8 | 255.0.0.0 | 10.0.0.0/8 | 10.255.255.255 +(1 row) + +select * from inet_val('10.1.2.3'::cidr); + host | abbrev | masklen | network | netmask | first | last +----------+----------+---------+----------+-----------------+----------+---------- + 10.1.2.3 | 10.1.2.3 | 32 | 10.1.2.3 | 255.255.255.255 | 10.1.2.3 | 10.1.2.3 +(1 row) + +select * from inet_val('10.1.2.3/32'::inet); + host | abbrev | masklen | network | netmask | first | last +----------+----------+---------+----------+-----------------+----------+---------- + 10.1.2.3 | 10.1.2.3 | 32 | 10.1.2.3 | 255.255.255.255 | 10.1.2.3 | 10.1.2.3 +(1 row) + +select * from inet_val('10.1.2'::cidr); + host | abbrev | masklen | network | netmask | first | last +----------+-------------+---------+-------------+---------------+-------------+------------ + 10.1.2.0 | 10.1.2.0/24 | 24 | 10.1.2.0/24 | 255.255.255.0 | 10.1.2.0/24 | 10.1.2.255 +(1 row) + +select * from inet_val('10.1.2.3/24'::inet); + host | abbrev | masklen | network | netmask | first | last +----------+-------------+---------+-------------+---------------+-------------+------------ + 10.1.2.3 | 10.1.2.3/24 | 24 | 10.1.2.0/24 | 255.255.255.0 | 10.1.2.0/24 | 10.1.2.255 +(1 row) + +select * from inet_val('10.1'::cidr); + host | abbrev | masklen | network | netmask | first | last +----------+-------------+---------+-------------+-------------+-------------+-------------- + 10.1.0.0 | 10.1.0.0/16 | 16 | 10.1.0.0/16 | 255.255.0.0 | 10.1.0.0/16 | 10.1.255.255 +(1 row) + +select * from inet_val('10.1.2.3/16'::inet); + host | abbrev | masklen | network | netmask | first | last +----------+-------------+---------+-------------+-------------+-------------+-------------- + 10.1.2.3 | 10.1.2.3/16 | 16 | 10.1.0.0/16 | 255.255.0.0 | 10.1.0.0/16 | 10.1.255.255 +(1 row) + +select * from inet_val('10'::cidr); + host | abbrev | masklen | network | netmask | first | last +----------+------------+---------+------------+-----------+------------+---------------- + 10.0.0.0 | 10.0.0.0/8 | 8 | 10.0.0.0/8 | 255.0.0.0 | 10.0.0.0/8 | 10.255.255.255 +(1 row) + +select * from inet_val('10.1.2.3/8'::inet); + host | abbrev | masklen | network | netmask | first | last +----------+------------+---------+------------+-----------+------------+---------------- + 10.1.2.3 | 10.1.2.3/8 | 8 | 10.0.0.0/8 | 255.0.0.0 | 10.0.0.0/8 | 10.255.255.255 +(1 row) + +select * from inet_val('10'::cidr); + host | abbrev | masklen | network | netmask | first | last +----------+------------+---------+------------+-----------+------------+---------------- + 10.0.0.0 | 10.0.0.0/8 | 8 | 10.0.0.0/8 | 255.0.0.0 | 10.0.0.0/8 | 10.255.255.255 +(1 row) + +select * from inet_val('11.1.2.3/8'::inet); + host | abbrev | masklen | network | netmask | first | last +----------+------------+---------+------------+-----------+------------+---------------- + 11.1.2.3 | 11.1.2.3/8 | 8 | 11.0.0.0/8 | 255.0.0.0 | 11.0.0.0/8 | 11.255.255.255 +(1 row) + +select * from inet_val('10'::cidr); + host | abbrev | masklen | network | netmask | first | last +----------+------------+---------+------------+-----------+------------+---------------- + 10.0.0.0 | 10.0.0.0/8 | 8 | 10.0.0.0/8 | 255.0.0.0 | 10.0.0.0/8 | 10.255.255.255 +(1 row) + +select * from inet_val('9.1.2.3/8'::inet); + host | abbrev | masklen | network | netmask | first | last +---------+-----------+---------+-----------+-----------+-----------+--------------- + 9.1.2.3 | 9.1.2.3/8 | 8 | 9.0.0.0/8 | 255.0.0.0 | 9.0.0.0/8 | 9.255.255.255 +(1 row) + +select * from inet_val('10:23::f1'::cidr); + host | abbrev | masklen | network | netmask | first | last +-----------+-----------+---------+-----------+-----------------------------------------+-----------+----------- + 10:23::f1 | 10:23::f1 | 128 | 10:23::f1 | ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff | 10:23::f1 | 10:23::f1 +(1 row) + +select * from inet_val('10:23::f1/64'::inet); + host | abbrev | masklen | network | netmask | first | last +-----------+--------------+---------+------------+-----------------------+------------+---------------------------- + 10:23::f1 | 10:23::f1/64 | 64 | 10:23::/64 | ffff:ffff:ffff:ffff:: | 10:23::/64 | 10:23::ffff:ffff:ffff:ffff +(1 row) + +select * from inet_val('10:23::8000/113'::cidr); + host | abbrev | masklen | network | netmask | first | last +-------------+-----------------+---------+-----------------+-----------------------------------------+-----------------+------------- + 10:23::8000 | 10:23::8000/113 | 113 | 10:23::8000/113 | ffff:ffff:ffff:ffff:ffff:ffff:ffff:8000 | 10:23::8000/113 | 10:23::ffff +(1 row) + +select * from inet_val('10:23::ffff'::inet); + host | abbrev | masklen | network | netmask | first | last +-------------+-------------+---------+-------------+-----------------------------------------+-------------+------------- + 10:23::ffff | 10:23::ffff | 128 | 10:23::ffff | ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff | 10:23::ffff | 10:23::ffff +(1 row) + +select * from inet_val('::ffff:1.2.3.4'::cidr); + host | abbrev | masklen | network | netmask | first | last +----------------+----------------+---------+----------------+-----------------------------------------+----------------+---------------- + ::ffff:1.2.3.4 | ::ffff:1.2.3.4 | 128 | ::ffff:1.2.3.4 | ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff | ::ffff:1.2.3.4 | ::ffff:1.2.3.4 +(1 row) + +select * from inet_val('::4.3.2.1/24'::inet); + host | abbrev | masklen | network | netmask | first | last +-----------+--------------+---------+---------+-------------+-------+------------------------------------ + ::4.3.2.1 | ::4.3.2.1/24 | 24 | ::/24 | ffff:ff00:: | ::/24 | 0:ff:ffff:ffff:ffff:ffff:ffff:ffff +(1 row) + +create or replace function mac_cmp(macaddr, macaddr) returns int as ' + args[0] <=> args[1] +' language 'plruby'; +select mac_cmp('00:07:E9:85:3E:C5'::macaddr, '00:E0:29:3E:E7:25'::macaddr); + mac_cmp +--------- + -1 +(1 row) + +create or replace function mac_trunc(macaddr) returns macaddr as ' + args[0].truncate +' language 'plruby'; +select mac_trunc('00:07:E9:85:3E:C5'::macaddr); + mac_trunc +------------------- + 00:07:e9:00:00:00 +(1 row) + +select mac_trunc('00:E0:29:3E:E7:25'::macaddr); + mac_trunc +------------------- + 00:e0:29:00:00:00 +(1 row) + diff --git a/test/plp/b.rb b/test/plp/b.rb index 778a624..c4d5956 100755 --- a/test/plp/b.rb +++ b/test/plp/b.rb @@ -25,8 +25,7 @@ language '#{language}'; create trusted procedural language 'plruby#{suffix}' - handler plruby#{suffix}_call_handler - lancompiler 'PL/Ruby'; + handler plruby#{suffix}_call_handler; EOF f.close rescue diff --git a/test/plt/b.rb b/test/plt/b.rb index 778a624..c4d5956 100755 --- a/test/plt/b.rb +++ b/test/plt/b.rb @@ -25,8 +25,7 @@ language '#{language}'; create trusted procedural language 'plruby#{suffix}' - handler plruby#{suffix}_call_handler - lancompiler 'PL/Ruby'; + handler plruby#{suffix}_call_handler; EOF f.close rescue diff --git a/test/range/b.rb b/test/range/b.rb index 6310536..a0c7b2b 100755 --- a/test/range/b.rb +++ b/test/range/b.rb @@ -36,8 +36,7 @@ language '#{language}'; create trusted procedural language 'plruby#{suffix}' - handler plruby#{suffix}_call_handler - lancompiler 'PL/Ruby'; + handler plruby#{suffix}_call_handler; EOF f.close rescue