функция массива возвращает пустое значение

Цель состоит в том, чтобы адаптировать этот ответ для возврата массива вместо типа данных 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!

РЕДАКТИРОВАТЬ

Заметки

Речь идет об «использовании Python с 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($1,$2,$3) x LIMIT 1;
$f$ language SQL IMMUTABLE;

person Peter Krauss    schedule 21.03.2017    source источник
comment
почему бы не использовать select regexp_split_to_array('a,b',',');?   -  person Ben H    schedule 21.03.2017
comment
@BenH, CSV сложный, см. это регулярное выражение, возможно, используя regexp_matches()...   -  person Peter Krauss    schedule 21.03.2017
comment
я знаю, что csv сложен, но тогда вам следует рассмотреть гораздо лучший образец, чем 'a,b'   -  person Ben H    schedule 21.03.2017
comment
Вы не использовали оператор return. ИМХО почти все процедурные языки требуют этого, если вы хотите что-то вернуть.   -  person pozs    schedule 21.03.2017


Ответы (2)


Функция csv.reader возвращает объект 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}
person Clodoaldo Neto    schedule 21.03.2017

Вы можете использовать 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;$$;
person Laurenz Albe    schedule 21.03.2017
comment
Спасибо @LaurenzAble! Хм... Этот алгоритм будет работать с любым случаем CSV? даже простой алгоритм, поскольку в этом Perl использует регулярное выражение... Я пытался использовать regexp_matches(), но нужно адаптировать ?:^|,)(?=[^"]|(")?)"?((?(1)[^"]*|[^,"]*))"?(?=,|$) к POSIX... - person Peter Krauss; 21.03.2017
comment
Это должно работать для всего, если только я не допустил программную ошибку. Иногда проще написать конечный автомат, чем указать грамматику. - person Laurenz Albe; 21.03.2017