HashCode

An organizer of symbols

Archive for August, 2007

Append em arquivo no Postgresql via módulo em C

Friday, August 24th, 2007

Estava desenvolvendo um sistema de distribuição de dados no Postgresql e tive a necessidade de armazenar em um arquivo as inserções caso houvesse erro. Relatarei aqui uma solução desenvolvida um módulo(zinho) em C.

Pacotes necessários para a compilação
Na verdade eu não sei bem se os outros são necessários mais o postgresql-server-dev-8.1 é certeza :)

postgresql-8.1
postgresql-client-8.1
postgresql-contrib-8.1
postgresql-server-dev-8.1

Função

#include <stdio.h>
#include "postgres.h"
#include <string.h>
#include "fmgr.h"

//Registrando a função log_pg no escopo do postgres
PG_FUNCTION_INFO_V1(log_pg);

//Datum é o tipo esperado, cast automático do int de retorno
Datum log_pg(PG_FUNCTION_ARGS){

//PG_GETARG_TEXT_P(0) pega o primeiro argumento
//VARDATA faz cast para char *
  char *filename = VARDATA(PG_GETARG_TEXT_P(0));

  FILE *fp;

  if ((fp = fopen(filename, "a"))==NULL)  {
    printf("Cannot open file \n");
    return 1;
  }else{
   //Pega o segundo argumento já convertido para char *
    fputs(VARDATA(PG_GETARG_TEXT_P(1)),fp);
    fclose(fp);
    return 0;
   }
}

Salve o arquivo como log_pg.c
Compile

gcc -fpic -I/usr/include/postgresql -I/usr/include/postgresql/8.1/server -c log_pg.c

Gere o Shared Object

gcc -shared -o log_pg.so log_pg.o

No meu caso a dynamic_library_path está apontando para /usr/lib/postgresql/8.1/lib/ portanto, o log_pg.so vai pra lá.

install log_pg.so  /usr/lib/postgresql/8.1/lib/log_pg.so

Agora no Postgresql duas funções, uma mapeia o log_pg.so em log_me

CREATE or replace FUNCTION log_me(varchar,varchar) RETURNS int
 AS 'log_pg.so', 'log_pg' LANGUAGE C;

e a outra uma abstração para gerar a data corrente e concatena .log ao fim do nome do arquivo (melhor que usar strcpy).

create or replace function logger(varchar,varchar) returns int as $BODY$

  begin
    return log_me(($1 || current_date::varchar ||'.log')::text,$2::text);
  end
$BODY$ language 'plpgsql';

Testando

select logger('/tmp/teste', 'meu primeiro teste');

Saiba mais … libpq - C Library

Rails Tree Release 0.8.5

Friday, August 10th, 2007

Nova versão do plugin railstree com criação via Hash e bugfix RSS.


  tabelas1=%w(starttelephony startvoip customers  gateways)
  tabelas2=%w(teste1 teste2 ) 

  d1=Node.new(:label => "radius", :icon => "/images/data.png", :open => true)
  d2=Node.new(:label => "teste", :icon => "/images/data.png", :open => false)

  tabelas1.each do |t|
    no=Node.new(:label => t, :icon => "/images/table_sql.png")
    d1 << no
  end

  tabelas1.each do |t|
    no=Node.new(:label => t, :icon => "/images/table_sql.png")
    d1 << no
  end

  tabelas2.each do |t|
    no=Node.new(:label => t, :url => 'link aqui', :icon => "/images/table_sql.png")
    d2 << no
  end

  tr = Tree.new(:label => "Databases[solaris]")
  tr << d1
  tr << d2
Version Download Howto Repository
0.8.5 rubyforge.png

 

 

Limite por Tipo ou Aspecto

Tuesday, August 7th, 2007

A Ruby não faz distinção de elementos de um Array, o que eu acho uma vantagem fundamental, pois, a classe Array é uma classe para atender o escopo dos objetos remanescentes da linguagem. Como já conhecido por programadores em java, um array é de tamanho fixo e obedece a premissa que todos os elementos terão o mesmo tipo(considerando hierarquia). Em um aprendizado básico e inicial de uma linguagem de programação, a tipagem obrigatória é de fácil entendimento mas a coisa que contem coisas pode ou não aceitar tipos genéricos. Exemplo de uma mochila genérica no preposto abaixo

“Uma mochila onde aceita objetos menores que ela como, caneta, pendrive, laptop, absorvente, cueca, etc.”

Em uma tentativa de identificar o sexo do(a) dono(a) da mochila pelo seu conteúdo fica complicado pelo fato que ‘absorvente’ é usado por mulheres e ‘cueca’ por homens( normalmente é assim :).

Uma mochila genérica de um homem(deixa de ser genérica e passa a ser mochila-homem) não aceita ‘absorvente’ mas continua aceitando o catálogo de objetos masculinos. E outra coisa quando eu digo que a mochila ‘aceita objetos menores que ela’ também deixa de ser genérica e passa a ser limitada.

Limite por Tipo ou Aspecto

Em Java(a linguagem) as coleções tais como Vector e HashSet que antes da versão 1.5 recebiam apenas o tipo do topo da hierarquia ficando a critério do programador especificar em implementação de interfaces as conversões e verificação de tipo. Em uma proposta mais humana e menos burocrática o java 1.5 recebeu as definições de Generics tendo apenas a deficiência da dispersão das psedos-tags na declaração e na instância do objeto.

Array em Ruby o tipo não importa e também a linguagem não define uma limitação fixa da quantidade de elementos e as peculiaridades relativa a cada instância da coleção.

Considerando a linguagem na sua mais simples forma, a forma padrão sem APIs externas nenhuma das duas linguagens define uma coleção por aspecto.

Como seria este aspecto então?

Seria uma coleção capaz de determinar um contrato não burocrático sobre quais aspectos gostarias que a classe tenha. Algo como

“Aceite qualquer instância que siga a seguinte regra: tenha o método ’somar’ , criada na terça-feira, tenha a variável ‘hello’(string) com o conteúdo maior que 5″

Você deve estar pensando “Você tá ficando doido!!”… não, não é isso; isso é : Reduzir as condicionais para uso de elementos da coleção pense em “Coleções cuja as condicionais fiquem na entrada do elemento e não na saída”

De volta a pragmática…

Proponho aqui uma forma de criar um Array em Ruby que aceita apenas um tipo de classe, podemos estudar depois como fariamos algo utilizando os aspectos do objeto….

Módulo OnlyClass
Criei o módulo OnlyClass para facilitar o acoplamento na classe Array. Temos então a instância de um Array que aceita apenas um tipo de classe:

 colecao=Array.only String

O uso da classe é normal, há apenas verificação de inclusão dos elementos, neste caso String.

 colecao=Array.only String
 colecao << "Um elemento"   #ou
 colecao[1]="Dois elemento"  #ou
 colecao.push("Mais um elemento","Mais n elementos")

Veja que o array adiciona os elementos sem problema. Mas quando um elemento não for do tipo especificado uma exceção será lançada.

 colecao=Array.only String
 colecao << "esse vai"
 colecao << 333 #esse não
 #TypeError: can't append Fixnum into Array.only String

Módulo OnlyClass obtendo elementos e elementos dos métodos

Criei uma forma automática de obter os elementos de um método específico que já é comum a todas as instâncias pertencentes a coleção. Um exemplo seria obter os sucessores de todos elementos de um Array#Fixnum, chamando o each_nome-do-método-de-instância e um bloco(opcional)

 colecao=Array.only Fixnum
 colecao << 10
 colecao << 20
 colecao.push(30,40)
 colecao.each_succ {|n| puts n}
#resultado
# 11
# 21
# 31
# 41

sem o bloco, atribuição do resultado em uma variável

 colecao=Array.only Fixnum
 colecao << 10
 colecao << 20
 colecao.push(30,40)
 succs=colecao.each_succ              #=> [11, 21, 31, 41]

Podemos também passar parâmetros para o método, exemplo: obter todos os valores do resultado do match de cada elemento em um array.

 colecao=Array.only String
 colecao << "Um elemento"   #ou
 colecao[1]="Dois elemento"  #ou
 colecao.push("Mais um elemento","Mais n elementos")
 colecao.each_match(/.*u.*/) {|r| puts r}
#saída
# nil
# nil
# "Mais um elemento"
# nil

ou substituir os valores internos

 colecao=Array.only String
 colecao << "Um elemento"
 colecao[1]="Dois elemento"
 colecao.push("Mais um elemento","Mais n elementos")
 colecao.each_gsub!(/elemento/,'coisa')    #=> => ["Um coisa", "Dois coisa", "Mais um coisa", "Mais n coisas"]