Обсуждение: function in a view
Hi All,
I have created a function that extracts three parts of a string using plperl.
Now I want to use those parts in a view and I don't even know where to start.
My first feeble attempt looked like this:
SELECT tbl_line_item.so_number,
tbl_line_item.so_line,
tbl_line_item.quantity,
'Border: '::text ||
func_parse_net_desc(tbl_item_description.description).border_str AS line_1,
'Size: '::text ||
func_parse_net_desc(tbl_item_description.description).size_str AS line_2,
'Tag: '::text ||
func_parse_net_desc(tbl_item_description.description).tag_str AS line_3
FROM tbl_line_item
LEFT JOIN tbl_item_description
ON tbl_line_item.so_number = tbl_item_description.so_number AND
tbl_line_item.so_line = tbl_item_description.so_line
LEFT JOIN tbl_item
ON tbl_line_item.item_id::text = tbl_item.id::text
WHERE tbl_item.item_type::text = 'NET'::text
ORDER BY tbl_line_item.so_number,
tbl_line_item.so_line;
I knew even before I ran it it was going to fail miserably. The end objective
is to create a view of this query.
Can this be done?
For reference here is the function and an example run using a fixed string.
-- DROP FUNCTION func_parse_net_desc("varchar");
-- DROP TYPE func_parse_net_desc;
CREATE TYPE func_parse_net_desc AS
(border_str varchar(64),
size_str varchar(64),
tag_str varchar(64));
ALTER TYPE func_parse_net_desc OWNER TO postgres;
CREATE OR REPLACE FUNCTION func_parse_net_desc("varchar")
RETURNS func_parse_net_desc AS
$BODY$
# A function to parse a net description into its border, size and tag parts.
# One input argument. description Case insensitive.
use strict;
use warnings;
# Initialize the program variables.
my $v_description = shift(@_);
my $v_border_str = "";
my $v_size_str = "";
my $v_tag_str = "";
# Perform a case insensitive check for the proper data format. Capture the
# desired parts of the data using parentheses.
if ($v_description =~ /.*border:\s*(.*)\s*size:\s*(.*)\s*tag:\s*(.*)\s*/i){
# Store the capture patterns in variables to avoid unpredictable results.
($v_border_str, $v_size_str, $v_tag_str) = ($1, $2, $3);
} else {
($v_border_str, $v_size_str, $v_tag_str) = ("", "", "");
}
return {border_str => $v_border_str,
size_str => $v_size_str,
tag_str => $v_tag_str};
$BODY$
LANGUAGE 'plperlu' STABLE STRICT;
TESTDB=# SELECT * FROM func_parse_net_desc('3000 HTPP Black 4in sq Border:
WNY200BK Size: 14\'8.5" x 16\'7" Tag: None');
border_str | size_str | tag_str
------------+------------------+---------
WNY200BK | 14'8.5" x 16'7" | None
(1 row)
Kind Regards,
Keith
On Thu, Apr 28, 2005 at 02:58:53PM -0400, Keith Worthington wrote:
>
> I have created a function that extracts three parts of a string using plperl.
> Now I want to use those parts in a view and I don't even know where to start.
Here's a simple example that might provide inspiration. It works
in PostgreSQL 8.0.2:
CREATE TYPE testtype AS (
a text,
b text,
c text
);
CREATE FUNCTION testfunc(text) RETURNS testtype AS $$
my @s = split(/:/, $_[0]);
return {a => $s[0], b => $s[1], c => $s[2]};
$$ LANGUAGE plperl IMMUTABLE STRICT;
CREATE TABLE foo (id serial, t text);
INSERT INTO foo (t) VALUES ('abc:def:ghi');
SELECT id, t, testfunc(t) FROM foo;
id | t | testfunc
----+-------------+---------------
1 | abc:def:ghi | (abc,def,ghi)
(1 row)
SELECT id, t, (testfunc(t)).* FROM foo;
id | t | a | b | c
----+-------------+-----+-----+-----
1 | abc:def:ghi | abc | def | ghi
(1 row)
SELECT id, t,
'A: ' || (testfunc(t)).a AS col_a,
'B: ' || (testfunc(t)).b AS col_b,
'C: ' || (testfunc(t)).c AS col_c
FROM foo;
id | t | col_a | col_b | col_c
----+-------------+--------+--------+--------
1 | abc:def:ghi | A: abc | B: def | C: ghi
(1 row)
--
Michael Fuhr
http://www.fuhr.org/~mfuhr/
Michael Fuhr wrote:
> On Thu, Apr 28, 2005 at 02:58:53PM -0400, Keith Worthington wrote:
>
>>I have created a function that extracts three parts of a string using plperl.
>> Now I want to use those parts in a view and I don't even know where to start.
>
>
> Here's a simple example that might provide inspiration. It works
> in PostgreSQL 8.0.2:
>
> CREATE TYPE testtype AS (
> a text,
> b text,
> c text
> );
>
> CREATE FUNCTION testfunc(text) RETURNS testtype AS $$
> my @s = split(/:/, $_[0]);
> return {a => $s[0], b => $s[1], c => $s[2]};
> $$ LANGUAGE plperl IMMUTABLE STRICT;
>
> CREATE TABLE foo (id serial, t text);
> INSERT INTO foo (t) VALUES ('abc:def:ghi');
>
> SELECT id, t, testfunc(t) FROM foo;
> id | t | testfunc
> ----+-------------+---------------
> 1 | abc:def:ghi | (abc,def,ghi)
> (1 row)
>
> SELECT id, t, (testfunc(t)).* FROM foo;
> id | t | a | b | c
> ----+-------------+-----+-----+-----
> 1 | abc:def:ghi | abc | def | ghi
> (1 row)
>
> SELECT id, t,
> 'A: ' || (testfunc(t)).a AS col_a,
> 'B: ' || (testfunc(t)).b AS col_b,
> 'C: ' || (testfunc(t)).c AS col_c
> FROM foo;
> id | t | col_a | col_b | col_c
> ----+-------------+--------+--------+--------
> 1 | abc:def:ghi | A: abc | B: def | C: ghi
> (1 row)
>
I am out of the office today so I won't be able to play with this idea
for a while but it looks interesting.
It seems like what your saying is that by enclosing the function in a
set of parentheses I can access the return elements.
I can't wait to try this.
Thanks tons for the guidance. I will let you know how I make out.
--
Kind Regards,
Keith
On Fri, Apr 29, 2005 at 10:18:35AM -0400, Keith Worthington wrote: > > It seems like what your saying is that by enclosing the function in a > set of parentheses I can access the return elements. Right. See "Field Selection" in the "SQL Syntax" chapter of the documentation, and "Accessing Composite Types" in the "Data Types" chapter. http://www.postgresql.org/docs/8.0/interactive/sql-expressions.html#AEN1642 http://www.postgresql.org/docs/8.0/interactive/rowtypes.html#AEN5582 -- Michael Fuhr http://www.fuhr.org/~mfuhr/