Documentação do PostgreSQL 8.0.0 | ||||
---|---|---|---|---|
Anterior | Início | Capítulo 39. PL/Ruby - Linguagem procedural Ruby | Fim | Próxima |
Os exemplos desta seção têm por finalidade mostrar a utilização de funções escritas na linguagem PL/Ruby para validar dígito verificador.
Nestes exemplos são mostradas funções para validar o número do CPF e do CNPJ. A primeira função recebe o número do CPF com 8 a 11 dígitos, e a segunda recebe o número do CNPJ com 14 dígitos. Ambas retornam o valor booleano verdade se os dígitos verificadores estiverem corretos, ou falso caso contrário. Se o argumento for nulo, não tiver o número de dígitos esperado, ou contiver um dígito não numérico, as funções retornam nulo.
Exemplo 39-8. Função PL/Ruby para validar o número do CPF
Rotina para validação do CPF. Recebe um argumento, o número do CPF com oito a onze dígitos. Retorna verdade se os dígitos verificadores do CPF estiverem corretos, falso caso contrário, ou nulo se o argumento for nulo, não tiver entre 8 e 11 dígitos, ou contiver um dígito não numérico. Não serão considerados válidos os seguintes CPF: 000.000.000-00, 111.111.111-11, 222.222.222-22, 333.333.333-33, 444.444.444-44, 555.555.555-55, 666.666.666-66, 777.777.777-77, 888.888.888-88, 999.999.999-99.
CREATE OR REPLACE FUNCTION ruby_cpf (text) RETURNS boolean AS $$ # verificar se o argumento é nulo (desnecessário porque a função é STRICT) if args[0] == nil return nil end # número do CPF igual ao argumento recebido cpf = args[0] # verificar se o CPF tem entre 8 e 11 dígitos if cpf.length < 8 || cpf.length > 11 return nil end # colocar zeros à esquerda se tiver menos de 11 dígitos if cpf.length < 11 cpf = ("0"*(11-cpf.length)).concat(cpf) end # verificar se os dígitos são todos numéricos (0...cpf.length).each do|i| c = cpf[i]; if (c<?0 || c>?9) return nil end end # verificar se os dígitos são todos iguais iguais = true (0..cpf.length-2).each do|i| if cpf[i] != cpf[i+1] iguais = false break end end if iguais return false end # primeiro dígito verificador fator=10 digito=0 (0..cpf.length-3).each do|i| digito += (cpf[i]-?0) * fator fator -= 1; end digito = 11 - ( digito % 11 ) if digito >= 10 digito = 0 end if digito != (cpf[9]-?0) return false; end # segundo dígito verificador fator=11 digito=0 (0..cpf.length-2).each do|i| digito += (cpf[i]-?0) * fator fator -= 1; end digito = 11 - ( digito % 11 ) if digito >= 10 digito = 0 end if digito != (cpf[10]-?0) return false end return true $$ LANGUAGE 'plruby' IMMUTABLE STRICT;
Os números de CPF utilizados para testar a função não estão divulgados por motivo de confidencialidade.
Exemplo 39-9. Função PL/Ruby para validar o número do CNPJ
Rotina para validação do CNPJ. Recebe um argumento, o número do CNPJ com doze a quatorze dígitos. Retorna verdade se os dígitos verificadores do CNPJ estiverem corretos, falso caso contrário, ou nulo se o argumento for nulo, não tiver entre 12 e 14 dígitos, ou contiver um dígito não numérico.
CREATE OR REPLACE FUNCTION ruby_cnpj (text) RETURNS boolean AS $$ # verificar se o argumento é nulo (desnecessário porque a função é STRICT) if args[0] == nil return nil end # número do CNPJ igual ao argumento recebido cnpj = args[0] # verificar se o CNPJ tem entre 12 e 14 dígitos if cnpj.length < 12 || cnpj.length > 14 return nil end # colocar zeros à esquerda se tiver menos de 14 dígitos if cnpj.length < 14 cnpj = ("0"*(14-cnpj.length)).concat(cnpj) end # verificar se os dígitos são todos numéricos (0...cnpj.length).each do|i| c = cnpj[i]; if (c<?0 || c>?9) return nil end end # primeiro dígito verificador fator=13 digito=0 (0..cnpj.length-3).each do|i| digito += (cnpj[i]-?0) * (fator>9 ? fator-8 : fator) fator -= 1; end digito = 11 - ( digito % 11 ) if digito >= 10 digito = 0 end if digito != (cnpj[12]-?0) return false; end # segundo dígito verificador fator=14 digito=0 (0..cnpj.length-2).each do|i| digito += (cnpj[i]-?0) * (fator>9 ? fator-8 : fator) fator -= 1; end digito = 11 - ( digito % 11 ) if digito >= 10 digito = 0 end if digito != (cnpj[13]-?0) return false end return true $$ LANGUAGE 'plruby' IMMUTABLE STRICT;
Os testes da função foram feitos utilizando CNPJ de órgãos públicos.
plruby=# SELECT ruby_cnpj('42498634000166'); ruby_cnpj ----------- t (1 linha) plruby=# SELECT ruby_cnpj('42498733000148'); ruby_cnpj ----------- t (1 linha)
Nesta seção são mostradas duas funções para validação do dígito verificador. A primeira função valida o dígito verificador módulo 11 e a segunda módulo 10. As duas funções recebem um parâmetro, o número com o dígito verificador no final, e retornam verdade ou falso caso o dígito esteja correto ou errado, respectivamente. Se o argumento for nulo, tiver menos de dois dígitos, ou contiver um dígito não numérico, as funções retornam nulo.
Exemplo 39-10. Função PL/Ruby para validar o dígito verificador módulo 11
O cálculo do dígito verificador módulo 11 é feito da seguinte forma: os dígitos são multiplicados da direita para a esquerda pela seqüência de 2 a 9, ou seja, por 2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, e assim por diante; os resultados do produto dos dígitos pelos valores da seqüência são somados; a soma é dividida por 11, e o resto da divisão é obtido; o dígito verificador é calculado subtraindo o resto de 11; quando o resto for igual a 0 ou 1 o dígito verificador será igual a 0. Segundo o Manual Técnico Operacional - Bloquetos de Cobrança - FEBRABAN, deve ser utilizado o dígito 1 quando o resto for 0, 10 ou 1. Existem Secretarias de Fazenda onde no cálculo do dígito verificador a seqüência retorna a 2 antes de chegar a 9. Tome cuidado antes de utilizar esta função.
CREATE OR REPLACE FUNCTION ruby_dv11 (text) RETURNS boolean AS $$ # verificar se o argumento é nulo (desnecessário porque a função é STRICT) if args[0] == nil return nil end # número a ser verificado igual ao argumento recebido n = args[0] # verificar se tem ao menos dois dígitos if n.length < 2 return nil end # verificar se os dígitos são todos numéricos (0...n.length).each do|i| c = n[i]; if (c<?0 || c>?9) return nil end end # validar o dígito verificador digito = 0 fator = 2 compr = n.length (0..compr-2).each do|i| digito += (n[compr-2-i]-?0) * fator fator += 1; if fator > 9 fator = 2 end end digito = 11 - ( digito % 11 ) if digito >= 10 digito = 0 end return digito == (n[compr-1]-?0) $$ LANGUAGE 'plruby' IMMUTABLE STRICT;
Foram utilizados valores tirados do manual da FEBRABAN e de talões de cheques para testar a função.
plruby=# SELECT ruby_dv11('99991012000003500077721305301500818975000001'); ruby_dv11 ----------- t (1 linha) plruby=# SELECT ruby_dv11('29750'); ruby_dv11 ----------- t (1 linha) plruby=# SELECT ruby_dv11('27'); ruby_dv11 ----------- t (1 linha)
Exemplo 39-11. Função PL/Ruby para validar o dígito verificador módulo 10
O cálculo do dígito verificador módulo 10 é feito da seguinte forma: os dígitos são multiplicados da direita para a esquerda pela seqüência 2, 1, 2, 1, e assim por diante; os "algarismos" dos resultados do produto dos dígitos pelos valores da seqüência são somados individualmente; a soma é dividida por 10, e o resto da divisão é obtido; o dígito verificador é calculado subtraindo o resto de 10; quando o resto for igual a 0 o dígito verificador será igual a 0. Fonte: Manual Técnico Operacional - Bloquetos de Cobrança - FEBRABAN. Existe outra forma de calcular este dígito verificador onde os resultados dos produtos, e não os dígitos dos resultados dos produtos, são somados. Tome cuidado antes de utilizar esta função.
CREATE OR REPLACE FUNCTION ruby_dv10 (text) RETURNS boolean AS $$ # verificar se o argumento é nulo (desnecessário porque a função é STRICT) if args[0] == nil return nil end # número a ser verificado igual ao argumento recebido n = args[0] # verificar se tem ao menos dois dígitos if n.length < 2 return nil end # verificar se os dígitos são todos numéricos (0...n.length).each do|i| c = n[i]; if (c<?0 || c>?9) return nil end end # validar o dígito verificador digito = 0 fator = 2 compr = n.length (0..compr-2).each do|i| produto = (n[compr-2-i]-?0) * fator digito += produto/10 + produto%10; fator -= 1; if fator < 1 fator = 2 end end digito = 10 - ( digito % 10 ) if digito == 10 digito = 0 end return digito == (n[compr-1]-?0) $$ LANGUAGE 'plruby' IMMUTABLE STRICT;
Foram utilizados valores tirados do manual da FEBRABAN e de talões de cheques para testar a função.
plruby=# SELECT ruby_dv10('00635041429'); ruby_dv10 ----------- t (1 linha) plruby=# SELECT ruby_dv10('9999777213'); ruby_dv10 ----------- t (1 linha) plruby=# SELECT ruby_dv10('75'); ruby_dv10 ----------- t (1 linha)
Neste exemplo é mostrada uma função para validar o número de inscrição eleitoral. A função recebe como parâmetro o número de inscrição eleitoral, e retorna o valor booleano verdade se os dígitos verificadores estiverem corretos, ou falso caso contrário. Se o argumento for nulo, tiver menos de dez dígitos, ou contiver um dígito não numérico, a função retorna nulo. A função não verifica se a unidade da federação é válida.
Exemplo 39-12. Função PL/Ruby para validar o número de inscrição eleitoral
A função é baseada na Resolução nº 20.132, de 19.03.98, do Tribunal Superior Eleitoral, art. 10, cujo texto é reproduzido abaixo:
Art. 10 - Os Tribunais Regionais Eleitorais farão distribuir, observada a seqüência numérica fornecida pela Secretaria de Informática, às Zonas Eleitorais da respectiva Circunscrição, séries de números de inscrição eleitoral, a serem utilizados na forma deste artigo.
Parágrafo único - O número de inscrição compor-se-á de até 12 (doze) algarismos, por Unidade da Federação, assim discriminados:
a) os 8 (oito) primeiros algarismos serão seqüenciados, desprezando-se, na emissão, os zeros à esquerda;
b) os 2 (dois) algarismos seguintes serão representativos da Unidade da Federação de origem da inscrição, conforme códigos constantes da seguinte tabela:
01 - São Paulo; 02 - Minas Gerais; 03 - Rio de Janeiro; 04 - Rio Grande do Sul; 05 - Bahia; 06 - Paraná; 07 - Ceará; 08 - Pernambuco; 09 - Santa Catarina; 10 - Goiás; 11 - Maranhão; 12 - Paraíba; 13 - Pará; 14 - Espírito Santo; 15 - Piauí; 16 - Rio Grande do Norte; 17 - Alagoas; 18 - Mato Grosso; 19 - Mato Grosso do Sul; 20 - Distrito Federal; 21 - Sergipe; 22 - Amazonas; 23 - Rondônia; 24 - Acre; 25 - Amapá; 26 - Roraima; 27 - Tocantins; 28 - Exterior (ZZ).
c) os 2 (dois) últimos algarismos constituirão dígitos verificadores, determinados com base no módulo 11 (onze), sendo o primeiro calculado sobre o número seqüencial e o último sobre o código da Unidade da Federação seguido do primeiro dígito verificador.
CREATE OR REPLACE FUNCTION ruby_nie (text) RETURNS boolean AS $$ # verificar se o argumento é nulo (desnecessário porque a função é STRICT) if args[0] == nil return nil end # número a ser verificado igual ao argumento recebido n = args[0] # verificar se tem ao menos dez dígitos if n.length < 10 return nil end # verificar se os dígitos são todos numéricos (0...n.length).each do|i| c = n[i]; if (c<?0 || c>?9) return nil end end # validar o primeiro dígito verificador digito = 0 fator = 2 compr = n.length (0..compr-5).each do|i| digito += (n[compr-5-i]-?0) * fator fator += 1; if fator > 9 fator = 2 end end digito = 11 - ( digito % 11 ) if digito >= 10 digito = 0 end if digito != (n[compr-2]-?0) return false end # validar o segundo dígito verificador digito = 0 fator = 2 compr = n.length (2..4).each do|i| digito += (n[compr-i]-?0) * fator fator += 1; if fator > 9 fator = 2 end end digito = 11 - ( digito % 11 ) if digito >= 10 digito = 0 end return digito == (n[compr-1]-?0) $$ LANGUAGE 'plruby' IMMUTABLE STRICT;
Não são mostrados os números utilizados para validar a função por uma questão de confidencialidade.