After upgrading Postgres 8.4 -> 9.3 and Ruby 1.8 -> 2.1, PL/ruby fails to run. I get immediate Postgres server coredump on first execution of any PL/ruby function. I am in the process of analyzing stacktraces, but it does not look good. Also, the maintenance state of PL/ruby does not look good.
So, changing focus to the actual database problem for which I use PL/ruby and think about alternatives.
Simplified example of problem: Given a warehouse journal as a database table with following fields:
- date (date)
- type of good (foreign key)
- count (numeric)
Considering the warehouse runs in strict FIFO mode, I need a list that shows how long each bunch of items has stayed in the warehouse (and a list of remainders which are still in the warehouse):
- journal_recno_in (foreign key)
- journal_recno_out (foreign key)
- count (numeric)
All other info can easily be joined to this.
I need this dynamically created within the current SQL query, so that the most recent data gets included; therefore an external procedure is ruled out. I consider it impossible to solve this with plain SQL query language, so a procedural language seems the only option.
I tried with PL/pgSQL, this is definitely possible, but it looked crude and ugly.
Now I am searching for the way of least pain, having in mind future extensions. Ruby would be my clear favourite, as this language seems to almost code itself along my thinking. But if PL/ruby cannot be brought to a solid behaviour (and that looks currently like a lot additional work and learning), that is rather pointless.
Suggestions? Things that I may have overlooked?
Addendum: outcome of the stacktraces
The first issue was that PL/ruby sets ruby SAFE_LEVEL
to 12, while ruby 2.1 accepts a maximum of 3 and does raise otherwise. That is easy to correct, and then it becomes possible to do simple functions. But when doing RETURNS SETOF
functions, it crashes again, this time from near rb_iterate()
in the ruby lib. I gave up here, with the conclusion that PL/ruby might need a lookover from beginning to end (i.e. 5000+ loc).
@Erwin: here is your req'd data:
Input table:
CREATE TABLE events (
id serial PRIMARY KEY,
datum date NOT NULL,
name_id integer,
count numeric(12,4),
created_at timestamp without time zone,
updated_at timestamp without time zone,
);
Output format:
SELECT * FROM ev_fifo() AS (id_in int, id_out int,
datum_in date, datum_out date,
name_id int,
count numeric)
Input example:
id | datum | name_id | count | created_at | updated_at
------+------------+---------+------------+---------------------+---------------------
1 | 23.04.2008 | 1 | 1.0000 | 23.04.2008 02:11:45 | 06.06.2008 02:11:45
2 | 28.04.2008 | 2 | 50.0000 | 29.04.2008 07:17:24 | 16.12.2008 04:32:43
3 | 03.07.2008 | 2 | 250.0000 | 21.07.2008 01:26:15 | 16.12.2008 04:36:20
4 | 03.07.2008 | 2 | -1.0000 | 21.07.2008 01:31:00 | 16.12.2008 04:37:22
5 | 03.07.2008 | 1 | -1.0000 | 21.07.2008 01:28:19 | 16.12.2008 04:36:50
6 | 04.07.2008 | 2 | -60.0000 | 21.07.2008 01:32:26 | 16.12.2008 04:37:50
Desired output:
id_in | id_out | datum_in | datum_out | name_id | count
---------+----------+------------+-------------+----------+-----------
2 | 4 | 28.04.2008 | 03.07.2008 | 2 | 1.0000
1 | 5 | 23.04.2009 | 03.07.2008 | 1 | 1.0000
2 | 6 | 28.04.2008 | 04.07.2008 | 2 | 49.0000
3 | 6 | 03.07.2008 | 04.07.2008 | 2 | 11.0000
3 | NULL | 03.07.2008 | NULL | 2 | 239.0000