[firebase-br] procedure de leitura de arquivo txt

Carlos H. Cantu listas em warmboot.com.br
Quarta Março 30 21:28:02 -03 2022


Pra sua procedure retornar as linhas vc teria que ter usado "for select" e
colocado o suspend dentro do loop, mas transformar seu select em procedure do
jeito que você fez não vai resolver o problema de 1024 iterações de uma CTE
recursiva, pois a CTE continuou existindo dentro da procedure.

Você vai ter que se livrar da CTE pra não ter essa limitação.

Você pode tentar fazer o parse usando uma variável do tipo blob textual e as
funções internas substring, position, etc. pra fazer o parse das informações,
mas tenha em mente que toda mudança no conteúdo dessa variável criará uma nova
cópia em memória, portanto, dependendo do tamanho dos dados, pode consumir muita
RAM a ponto de fazer SWAP no disco.

Outra opção (que não sei se é viável no seu caso, pois desconheço a estrutura do
arquivo) seria manter o arquivo em disco e acessá-lo através de uma external
table, como descrito no exemplo em https://www.firebase.com.br/artigo.php?id=403

[]s
Carlos H. Cantu
eBook Guia de Migração para o FB 4 - www.firebase.com.br/guiafb4.php
www.FireBase.com.br - www.firebirdnews.org - blog.firebase.com.br

jvl> bom tarde pessoal.

jvl> precisava fazer um PROCEDURE que leia um arquivo txt com delimitador e
jvl> me retorne a lista de dados.

jvl> com um select funciona belezinha, porem o txt fica limitado a 1024
jvl> interações. então precisava transformar em uma procedure... alguém tem
jvl> alguma ideia de como fazer ou alguém tem algo parecido? segue abaixo o
jvl> select funcionando, procedure que ainda não esta funcionando. segue
jvl> também txt de teste.

jvl> Select (funciona)

jvl> with recursive
jvl> p as (
jvl>  select
jvl>  iif(right(p.arq,2) <> p.lb, p.arq || p.lb, p.arq) arq,
jvl>  p.delimitador,
jvl>  p.lb
jvl>  from (
jvl>  select
jvl>  cast(:pArq as blob sub_type text) arq,
jvl>  cast(:pDelimitador as char(1)) delimitador,
jvl>  cast(ascii_char(13)||ascii_char(10) as char(2)) lb
jvl>  from rdb$database) p), 

jvl> linha as (
jvl>  select
jvl>  0 idx,
jvl>  left(p.arq,position(p.lb, p.arq) - 1) txt,
jvl>  substring(p.arq from position(p.lb, p.arq) + 2) restante
jvl>  from p 

jvl> union all 

jvl> select
jvl>  l.idx + 1,
jvl>  left(l.restante,position(p.lb, l.restante) - 1) txt,
jvl>  substring(l.restante from position(p.lb, l.restante) + 2) restante
jvl>  from linha l, p
jvl>  where l.restante <> ''
jvl> ), 

jvl> coluna as (
jvl>  select
jvl>  l.idx idx_linha,
jvl>  1 idx,
jvl>  left(l.txt, position(p.delimitador, l.txt) - 1) txt,
jvl>  substring(l.txt from position(p.delimitador, l.txt) + 1) ||
jvl> p.delimitador restante
jvl>  from linha l, p 

jvl> union all 

jvl> select
jvl>  c.idx_linha,
jvl>  c.idx + 1,
jvl>  left(c.restante, position(p.delimitador, c.restante) - 1),
jvl>  substring(c.restante from position(p.delimitador, c.restante) + 1)
jvl>  from coluna c, p
jvl>  where c.restante <> ''
jvl> ) 

jvl> select
jvl>  max(iif(c.idx = 1,c.txt,null)) coluna1,
jvl>  max(iif(c.idx = 2,c.txt,null)) coluna2,
jvl>  max(iif(c.idx = 3,c.txt,null)) coluna3
jvl> from coluna c
where c.idx_linha >> 0
jvl> group by c.idx_linha 

jvl> Procedure (não funcional) 

jvl> CREATE OR ALTER procedure SP_TESTE (
jvl>  PARQ blob sub_type 1 segment size 80,
jvl>  PDELIMITADOR char(1))
jvl> returns (
jvl>  COL1 integer)
jvl> as
jvl> begin
jvl>  with recursive
jvl>  p as (
jvl>  select
jvl>  iif(right(p.arq,2) <> p.lb, p.arq || p.lb, p.arq) arq,
jvl>  p.delimitador,
jvl>  p.lb
jvl>  from (
jvl>  select
jvl>  cast(:pArq as blob sub_type text) arq,
jvl>  cast(:pDelimitador as char(1)) delimitador,
jvl>  cast(ascii_char(13)||ascii_char(10) as char(2)) lb
jvl>  from rdb$database) p ),

jvl>  linha as (
jvl>  select
jvl>  0 idx,
jvl>  left(p.arq,position(p.lb, p.arq) - 1) txt,
jvl>  substring(p.arq from position(p.lb, p.arq) + 2) restante
jvl>  from p

jvl>  union all

jvl>  select
jvl>  l.idx + 1,
jvl>  left(l.restante,position(p.lb, l.restante) - 1) txt,
jvl>  substring(l.restante from position(p.lb, l.restante) + 2) restante
jvl>  from linha l, p
jvl>  where l.restante <> ''
jvl>  ),

jvl>  coluna as (
jvl>  select
jvl>  l.idx idx_linha,
jvl>  1 idx,
jvl>  left(l.txt, position(p.delimitador, l.txt) - 1) txt,
jvl>  substring(l.txt from position(p.delimitador, l.txt) + 1) ||
jvl> p.delimitador restante
jvl>  from linha l, p

jvl>  union all

jvl>  select
jvl>  c.idx_linha,
jvl>  c.idx + 1,
jvl>  left(c.restante, position(p.delimitador, c.restante) - 1),
jvl>  substring(c.restante from position(p.delimitador, c.restante) + 1)
jvl>  from coluna c, p
jvl>  where c.restante <> ''
jvl>  )
jvl>  select
jvl>  max(iif(c.idx = 1,c.txt,null)) coluna1--,
jvl>  -- max(iif(c.idx = 2,c.txt,null)) coluna2,
jvl>  -- max(iif(c.idx = 3,c.txt,null)) coluna3
jvl>  from coluna c
jvl>  where c.idx_linha > 0
jvl>  group by c.idx_linha 

jvl> into :col1;--, :col2, :col3; 

jvl> suspend; 

jvl> end 

jvl> desde já agradeço pela atenção




Mais detalhes sobre a lista de discussão lista