数组函数返回空
array function returning empty
这里的目的是将this answer适配为return数组而不是setof数据类型。
CREATE FUNCTION split_csvline(
line text, -- the input CSV string
delim_char char(1) = ',', -- can be also E'\t', ';', '|', etc.
quote_char char(1) = '"' -- field quotation
) RETURNS text[] AS $f$
import csv
row = csv.reader(
[line],
quotechar=quote_char,
delimiter=delim_char,
skipinitialspace=True,
escapechar='\'
)
next(row)
$f$ IMMUTABLE language PLpythonU;
SELECT split_csvline('a,b'); -- empty!
编辑
备注
这是一个关于"using Python with PostgreSQL"的问题。
我正在使用 PLpythonU 因为工作人员使用 Python 并且因为 CSV 很复杂并且需要 可靠 (多年的测试) 算法。
不需要解决方法,因为正在使用一个简单的解决方法:
CREATE FUNCTION split_csv_line(
text, char(1) DEFAULT ',', char(1) DEFAULT '"'
) RETURNS text[] AS $f$
SELECT x FROM split_csv(,,) x LIMIT 1;
$f$ language SQL IMMUTABLE;
你可以使用 PL/pgSQL:
CREATE OR REPLACE FUNCTION split_csvline(
line text, -- the input CSV string
delim_char char(1) = ',', -- can be also E'\t', ';', '|', etc.
quote_char char(1) = '"', -- field quotation
OUT result text[]
) LANGUAGE plpgsql AS
$$DECLARE
i integer;
t text := '';
c char(1);
/*
* 0 means unquoted
* 1 means quoted
* 2 means quoted, and we just read a quote
*/
q integer := 0;
BEGIN
/* loop through the characters */
FOR i IN 1..length(line) LOOP
/* get i-th character */
c := substring(line FROM i FOR 1);
/* end of string is at an unquoted delimiter */
IF c = delim_char AND q <> 1 THEN
result := result || t;
t := '';
q := 0;
ELSIF c = quote_char THEN
CASE q
WHEN 0 THEN
q := 1;
WHEN 1 THEN
IF c = quote_char THEN
q := 2;
ELSE
t := t || c;
END IF;
WHEN 2 THEN
q := 1;
t := t || quote_char;
END CASE;
ELSE
IF q = 2 THEN
q := 0;
END IF;
t := t || c;
END IF;
END LOOP;
/* add the last string */
result := result || t;
END;$$;
csv.reader
函数returns一个reader
对象。 next
是一个 reader
对象方法:
create or replace function split_csvline(
_line text,
_delim_char char(1) = ',',
_quote_char char(1) = '"'
) returns text[] as $f$
import csv
reader = csv.reader(
[_line],
quotechar = _quote_char,
delimiter = _delim_char,
skipinitialspace = True,
escapechar = '\'
)
return reader.next()
$f$ immutable language plpythonu;
select split_csvline('a,b');
split_csvline
---------------
{a,b}
这里的目的是将this answer适配为return数组而不是setof数据类型。
CREATE FUNCTION split_csvline(
line text, -- the input CSV string
delim_char char(1) = ',', -- can be also E'\t', ';', '|', etc.
quote_char char(1) = '"' -- field quotation
) RETURNS text[] AS $f$
import csv
row = csv.reader(
[line],
quotechar=quote_char,
delimiter=delim_char,
skipinitialspace=True,
escapechar='\'
)
next(row)
$f$ IMMUTABLE language PLpythonU;
SELECT split_csvline('a,b'); -- empty!
编辑
备注
这是一个关于"using Python with PostgreSQL"的问题。
我正在使用 PLpythonU 因为工作人员使用 Python 并且因为 CSV 很复杂并且需要 可靠 (多年的测试) 算法。
不需要解决方法,因为正在使用一个简单的解决方法:
CREATE FUNCTION split_csv_line(
text, char(1) DEFAULT ',', char(1) DEFAULT '"'
) RETURNS text[] AS $f$
SELECT x FROM split_csv(,,) x LIMIT 1;
$f$ language SQL IMMUTABLE;
你可以使用 PL/pgSQL:
CREATE OR REPLACE FUNCTION split_csvline(
line text, -- the input CSV string
delim_char char(1) = ',', -- can be also E'\t', ';', '|', etc.
quote_char char(1) = '"', -- field quotation
OUT result text[]
) LANGUAGE plpgsql AS
$$DECLARE
i integer;
t text := '';
c char(1);
/*
* 0 means unquoted
* 1 means quoted
* 2 means quoted, and we just read a quote
*/
q integer := 0;
BEGIN
/* loop through the characters */
FOR i IN 1..length(line) LOOP
/* get i-th character */
c := substring(line FROM i FOR 1);
/* end of string is at an unquoted delimiter */
IF c = delim_char AND q <> 1 THEN
result := result || t;
t := '';
q := 0;
ELSIF c = quote_char THEN
CASE q
WHEN 0 THEN
q := 1;
WHEN 1 THEN
IF c = quote_char THEN
q := 2;
ELSE
t := t || c;
END IF;
WHEN 2 THEN
q := 1;
t := t || quote_char;
END CASE;
ELSE
IF q = 2 THEN
q := 0;
END IF;
t := t || c;
END IF;
END LOOP;
/* add the last string */
result := result || t;
END;$$;
csv.reader
函数returns一个reader
对象。 next
是一个 reader
对象方法:
create or replace function split_csvline(
_line text,
_delim_char char(1) = ',',
_quote_char char(1) = '"'
) returns text[] as $f$
import csv
reader = csv.reader(
[_line],
quotechar = _quote_char,
delimiter = _delim_char,
skipinitialspace = True,
escapechar = '\'
)
return reader.next()
$f$ immutable language plpythonu;
select split_csvline('a,b');
split_csvline
---------------
{a,b}