Para evitar de esquecer de fechar as conexões com o banco, normalmente uso um procedimento que recebe uma query como argumento. Este procedimento abre a conexão com o banco, executa a query e fecha a conexão automaticamente (o desempenho que se dane
:-)
). As credenciais do banco mantenho em um parâmetro (definido com make-parameter
). O procedimento é algo como:(define db-credentials (make-parameter '()))
(define (db-query query)
(let* ((db (pg:connect (db-credentials)))
(output (pg:query-tuples query db)))
(pg:close db)
output))
Mesmo com o uso do procedimento
db-query
, o acesso a colunas do banco não é das tarefas mais simples. Abaixo está um exemplo em que quero acessar as colunas username
e email
de uma tabela e associar o valor delas à variáveis em Scheme:(db-credentials '((host . "localhost")
(user . "usuario")
(password . "****")
(dbname . "nome-da-base")))
(let* ((results
(let ((results
(db-query
"select username,email from users where user_id=1")))
(if (null? results)
#f
(car results))))
(username (and results (vector-ref results 0)))
(email (and results (vector-ref results 1))))
(print username)
(print email))
Como pode ser visto no exemplo, associar valores de colunas da base de dados a variáveis em Scheme é uma certa novela. Para facilitar esta tarefa, fiz o esquema mostrado abaixo:
(use postgresql)
(define db-map:credentials (make-parameter '()))
(define db-map:create-object
(let ()
(define (db-query query)
(let* ((db (pg:connect (db-map:credentials)))
(output (pg:query-tuples query db)))
(pg:close db)
output))
(lambda (query fields)
(let* ((query-results (let ((results (db-query query)))
(if (null? results)
#f
(car results)))))
(lambda (field)
(and query-results
(let ((pos (list-index (cut eq? <> field)
fields)))
(vector-ref query-results pos))))))))
O procedimento
db-map:create-object
recebe uma query SQL e uma lista de símbolos a serem associados com os valores das colunas obtidos como resultado da execução da query. db-map:create-object
retorna um procedimento que recebe como argumento um símbolo representando uma coluna da base de dados e que retorna o valor associado ao símbolo.Assim, para acessar o valor das colunas
username
e email
, faço o seguinte:(let ((obj (db-map:create-object
"select username,email from users where user_id=1"
'(username email))))
(print (obj 'username))
(print (obj 'email)))
A ordem dos símbolos da lista passada como segundo argumento deve ser a mesma dos valores das colunas resultantes da query SQL.
3 comentários:
Mario, eu gostaria de saber qual e-mail vc está utilizando atualmente, pois gostaria de verificar com você a licensa de uma de suas publicações.
Se possivel me informe atraves do ligia.gabriele@gmail.com
Aguardo contato.
Lígia.
2 comentarios
1) o layout do blog truncou a query string
2) parabens! tu quase conseguiste construir um procedimento presente na maioria das SQL APIs modernas
exceto por duas diferenças básicas:
a) os nomes dos campos vêm automaticamente
b) o resultado também permite acessar as linhas
é possivel chegar numa construcao desse estilo?
// retorna um handle para pegar as linhas
result = query("select * from clientes")
// row é uma colecao de pares contendo nome e valor
row = fetch(result)
enquanto row nao vazio
infere em row
row = fetch(result)
fim enquanto
abraços
Carlão Bazuca
Alô Engenheiro Diego (ou Carlão) :-)
Quanto ao truncamento da query string: esse esquema de colocar código no blogger é meio sacal. Dependendo da configuração do browser, o truncamento pode ou não ocorrer. De qualquer forma, se selecionares o texto no browser, copiares e colares em um editor de textos, deve aparecer tudo.
Sobre o acesso aos dados: na realidade, este é um hack simples e rápido para acessar os dados de forma mais agradável. Não é uma solução ideal. Nunca vi como são implementadas essas APIs modernas em outras linguagens, mas, suponho, elas devem fazer um parsing da query SQL.
Postar um comentário