Trabalhando com o Web SQL Database do HTML5

O joguinho do Pacman do Google mostrou ao mundo que o HTML5 já é uma realidade mas uma das funcionalidades mais legais ainda não foi muito divulgada, é o “Web SQL Database“.

O que é?

O Web SQL Database permite criar e acessar bancos de dados no lado do cliente (client-side) usando uma linguagem SQL.

Ou seja…

É uma alternativa a Cookies para armazenamento de dados no navegador e, mais legal ainda, dá uma independência maior as aplicações javascript, que em tese não dependerão mais de linguagens no lado do servidor (PHP, .NET, etc) para armazenar algo em um banco de dados.

O que não é

Isto tudo é muito legal, mas… é importante frisar algumas coisas:

  • Esta tecnologia não conecta a bancos de dados em servidores externos
  • O método é um pouco “caro” em termos de performance e somente deve ser usado se não houver outras alternativas
  • O navegador do usuário precisa suportar HTML5
  • Como a especificação e respectivas implementações do HTML5 ainda não estão 100% prontas, estes exemplos são mais provas de conceito do que qualquer outra coisa, a API poderá mudar na versão final

Tendo dito isto, vamos dar uma olhada mais a fundo e ver como funciona! Se ainda não tiver o Google Chrome instalado, baixe ele agora pois é o browser que melhor suporta o Web SQL Database.

Como parto do pressuposto que estamos usando o Chrome, vou usar console.log() para as demonstrações, então abra o console do chrome (clique com o botão direito, em inspecionar elemento e na aba “Console”). Todo o código vai dentro de um tag ‘script’ normal.

Como instanciar o objeto database

// o método OpenDatabase precisa de 4 parametros; o nome do banco de dados, a versão, a descrição e o tamanho estimado (em bytes)
var db = openDatabase("Teste", "1.0", "Teste Web SQL Database", 200000);

// deverá mostrar "Database"
console.log(db);

// de qualquer forma, sempre teste que o objeto foi instanciado direito antes de usá-lo
if(!db){
    alert('deu pau!');
}

O conceito de versões é um pouco enganoso, pois não é possível existirem múltiplas versões do mesmo banco ao mesmo tempo; ele é apenas para facilitar migrações entre versões de bancos.

Executando uma consulta

Para fazer consultas, utilizamos o método transaction do objeto database e, dentro dele, o método executeSql do objeto SQLTransaction:

// o método transaction aceita uma função anônima que recebe um objeto SQLTransaction como parâmetro
db.transaction(function(transaction){
    transaction.executeSql("SELECT COUNT(*) FROM Teste", null, null, null);
});

// os parametros são, respectivamente: a consulta, as variáveis a serem "bindadas", callback de sucesso e callback de erro, ou seja:

db.transaction(function(transaction){
    transaction.executeSql(
        // a consulta
        "SELECT COUNT(*) FROM Teste",
        // variáveis para bind, como é um SELECT, passamos um array vazio
        [[]],
        // callback de sucesso, uma função anônima que recebe um objeto SQLTransaction e um SQLResultSet
        function(transaction, result){
            console.log('deu certo!');
            console.log(result);
        },
        // callback de erro, função anônima que recebe um objeto SQLTransaction e um SQLError
        function(transaction, error){
            console.log('deu pau!');
            console.log(error);
        }
    );
});

Se rodar o código acima, verá que a consulta dará um erro e retornará um objeto SQLError, para acessar a mensagem de erro é só acessar as propriedades “code” e “message” do objeto.

Dê uma olhada na mensagem de erro… pois é não criamos a tabela!

Como criar e popular uma tabela

O SQL não é nenhuma novidade, só é necessário envolvê-lo nos métodos corretos:
(alias, ele utiliza statements preparados, para proteção contra SQL Injection, mas isto está fora do escopo deste artigo!)

db.transaction(function(transaction){
    // criar a tabela
    transaction.executeSql("CREATE TABLE Teste (id REAL UNIQUE, nome TEXT, timestamp REAL)", [[]], null, null);

    // num caso de verdade, iríamos incluir callbacks para verificar que deu tudo certo mas para não estender demais o código vou pular esta parte...

    // inserir dados
    // obs - repare que usamos um "statement preparado", colocamos interrogações no lugar das variáveis e as listamos em um array no segundo parametro, fazendo <em>bind</em> delas
    transaction.executeSql("INSERT INTO Teste (nome, timestamp) values(?, ?)", [['Alex', new Date().getTime()]], null, null);
});

Pronto! Fácil né? Agora tente rodar a primeira consulta denovo… não deu erro né? Se deu tudo certo, o objeto retornado será do tipo SQLResultSet. Se inspecionar o objeto verá que ele tem algumas propriedades úteis: insertId (no caso de inserts), rowsAffected, rows (no caso de selects).

Utilizando os resultados

Para finalizar o artigo, vou mostrar como interagir com os resultados. Para isto, vamos mudar um pouco a consulta inicial:

db.transaction(function(transaction){
    transaction.executeSql(
        "SELECT * FROM Teste",
        [[]],
        function(transaction, result){
            console.log('deu certo!');
            console.log(result);

           for(var i = 0; i < result.rows.length; i++){
               console.log(result.rows.item(i)[['nome']]);
           }
        },
        function(transaction, error){
            console.log('deu pau!');
            console.log(error);
        }
    );
});

Repare que podemos tratar o objeto SQLResultSet como um array e não só ver a propriedade length() mas também fazer um loop e acessar o seu conteúdo!

Legal né?

Espero que tenham curtido o artigo e que se animem com as possibilidades que o HTML5 está trazendo!

[[]]s

Nós queremos saber sua opinião aqui