ImaginarTI

quinta-feira, 28 de julho de 2011

CLOB e ORA-06502 - Por que e como corrigir

Ontem eu estava depurando uma procedure Oracle que faz a importação de dados de um sistema para outro. Essa procedure de importação gera log de tudo: dados importados, dados rejeitados, motivo de rejeição e etc. O log é todo armazenado em uma variável CLOB, que ao final do processo é anexada ao registro que armazena a execução da importação - foi executado na data tal, e o resultado foi tal.

Ocorre que com o aumento da massa de dados a ser importada, começaram a aparecer erros ORA-06502 (PL/SQL: numeric or value error). Com a ajuda do PL/SQL Developer, consegui identificar que a exceção era gerada em uma linha que concatenava alguns valores na variável CLOB. Eu demorei algumas horas até me lembrar que uu já tinha visto esse erro devido à conversão implícita de string em número.

Nessas horas foram algumas pesquisas na internet, até que achei um blog que me deu algumas dicas e a memória clareou (vou ficar devendo o crédito pois perdi o endereço do blog original).

O fato é que na conversão implícita, o Oracle tenta converter tudo para NÚMERO. Isso é porque as operações com números (geralmente comparações, originadas de cláusulas WHERE) são muito mais rápidas que comparações de string. Só que apesar de mais rápido, é uma conversão menos segura, pois pode não funcionar em todos os casos. No nosso caso de CONCATENAÇÃO (e não de comparação), o Oracle tenta converter tudo para varchar, e nisso dá erro.

Vamos a comprovação: Um laço que a cada volta, concatena um número em um CLOB.



declare
    l_clob clob;
 
begin

    for i in 1..50000
    loop
        l_clob   := l_clob || 1;
        -- conversão implícita de número em varchar
        -- força a conversão do blob em varchar também.
    end loop;
    dbms_output.put_line (length(l_clob));

exception
    when others then
          dbms_output.put_line ('error: ' || sqlerrm);
          dbms_output.put_line (length(l_clob));
end;


Internamente o oracle converte esse CLOB em varchar, concatena com o 1 (também internamente já convertido em varchar), e armazena de volta na variável CLOB. Só que conforme a variável CLOB vai crescendo, chega um momento que fica maior que 32768 bytes (o limite de tamanho de varchar). Nessa hora, gera a exceção.

Agora veja o exemplo abaixo, quase igual ao anterior. A diferença é que agora a concatenação é de uma string em um CLOB. Nesse caso o Oracle não faz a conversão do CLOB em varchar, e portanto não viola o limite do varchar. Logo, não dá erro!



declare
    l_clob clob;
 
begin

    for i in 1..50000
    loop
        l_clob := l_clob || to_char(1);
        -- sem conversão implícita de número (ou datas),
        -- a operação é entre varchar e clob. Neste caso,
        -- não há conversão do clob em varchar.
    end loop;
    dbms_output.put_line (length(l_clob));

exception
    when others then
          dbms_output.put_line ('error: ' || sqlerrm);
          dbms_output.put_line (length(l_clob));
end;


É isso.
Espero que sirva para ajudar mais alguém por aí.

Abraços e até a próxima!

Marcadores: , , , ,

sexta-feira, 22 de julho de 2011

ASP.NET MVC3 com Assemblies Privados

Esta semana eu precisei colocar um site novo no ar, no espaço de hospedagem da ImaginarTI. Curiosamente foi o primeiro site em ASP.NET MVC3 que vai para a nossa hospedagem - os demais ficaram hospedados diretamente nos clientes. O nosso provedor de hospedagem afirma que suporta MVC3, então achei que seria 100% transparente. Não foi bem assim...

O fato é que após subir os arquivos, começaram a aparecer um monte de problemas. Modificamos o web.config para exibir os erros (só para debug do deloy mesmo) e vimos que eram assemblies faltando. Como assim faltando?

Entrei em contato com o suporte da hospedagem e eles disseram que suportam o MVC 3, mas que eu tenho que colocar as DLL's no BIN. Ora, isso não é exatamente "suportar" MVC3, né? Me senti enganado (menos um ponto para esses caras), mas resolvi não brigar dessas vez. Bola para frente.

Como resolver?
Bem, o projeto (no VS2010) tinha sido criado com o template de projeto do próprio MVC, então todas as referências já estavam setadas corretamente. Bastou eu alterar algumas referências, mudando o COPY LOCAL para true, e acrescentar outras referências (também com COPY LOCAL true) e tudo voltou a funcionar.

Não cheguei nem a procurar na internet, mas me lembro que o Scott Gu já tinha falado sobre isso. De qualquer forma, o que resolveu o meu caso foi:


Mudar o COPY LOCAL para True
  • System.Web.Helpers
  • System.Web.Mvc
  • System.Web.WebPages


Novas referências
  • Microsoft.Web.Infrastructure
  • System.Web.WebPages.Razor
  • System.Web.WebPages.Deployment
  • System.Web.Razor
Tomara que ajude mais alguém por aí.
Até a próxima!

Marcadores: , ,

segunda-feira, 4 de julho de 2011

ASP x Asp.Net -- como explicar para leigos

Hoje um amigo aqui do trabalho, o Rodrigo Diniz (responsável pelo ExtJS Extender Controls) tentava me explicar como tentar fazer um advogado entender a diferença entre as tecnologias ASP (Asp 3 ou Asp "clássico") e Asp.Net. O advogado em questão era um outro funcionário que validava uma feature do sistema jurídico.

Conta o Diniz que argumentou o seguinte:
Escrever em Asp é como escrever em Latim, enquanto Asp.Net é como escrever em Portugês. Dá para dizer a mesma coisa, mas um é mais antigo, menos preciso e já não há tanta gente que consegue entender.

Exageros a parte, até concordei com a idéia.
E você, o que achou?

Marcadores: ,