Compatibilidade em Consultas Dinâmicas com SQL Builder para Go

Precisa escrever uma consulta dinâmica em Go usando SQL Builder mas está tendo problemas com seu SGBD? Conheça o recurso de compatibilidade do SQL Builder!

Compatibilidade em Consultas Dinâmicas com SQL Builder para Go

No artigo "Escrevendo consultas SQL dinâmicas com Go", exploramos como a biblioteca SQL Builder for Go simplifica a criação de consultas SQL dinâmicas. Contudo, um aspecto que merece atenção especial é a compatibilidade com diferentes sistemas de gerenciamento de banco de dados (SGBDs).

Escrevendo consultas SQL dinâmicas com Go
Você precisa escrever consultas SQL nativas que recebem um número variável de parâmetros de busca e quer evitar o inferno que é ficar concatenando strings. Aprenda a fazer isto com a lib SQL Builder for Go!

Cada SGBD tem suas particularidades — desde placeholders usados em consultas parametrizadas até funcionalidades proprietárias. Ignorar essas diferenças pode resultar em erros difíceis de depurar ou na necessidade de criar várias versões da mesma consulta para cada banco suportado. Neste post, vamos abordar como o SQL Builder for Go lida com essas questões de compatibilidade e como você pode utilizar o recurso BuildWithFlavor para ajustar o SQL gerado às necessidades do seu projeto.

Recurso BuildWithFlavor

O método BuildWithFlavor é um dos recursos mais úteis do SQL Builder for Go. Ele permite que você especifique o "flavor" (ou estilo) do SQL gerado, garantindo que a sintaxe da consulta seja compatível com o banco de dados escolhido.

Ao construir consultas dinâmicas, é comum enfrentar problemas como:

  • Placeholders incompatíveis: Enquanto o MySQL e o SQLite utilizam o caractere ? para indicar parâmetros, o PostgreSQL usa $1, $2 e assim por diante. Isso pode causar erros caso o SQL gerado não esteja alinhado à sintaxe esperada pelo banco. Esse foi o principal motivador para a escrita deste post. Todo o meu endpoint simplesmente não funcionava por causa de uma '?' no lugar de um '$1'.
  • Diferenças na sintaxe: Alguns bancos suportam funcionalidades específicas ou exigem adaptações na estrutura das consultas (exemplo: a cláusula LIMIT no SQL Server é diferente da usada no PostgreSQL ou MySQL).
  • Extensões proprietárias: Recursos avançados, como funções de agregação customizadas ou suporte a JSON, podem ser exclusivos de determinados bancos.

Exemplo de Uso

Aqui está o código de exemplo adaptado do outro post, agora utilizando o BuildWithFlavor para torná-lo compatível com o PostgreSQL:




func GetSite(id int) (*Site, *PostError) {
	query := sqlbuilder.NewSelectBuilder()
	query.Select("id", "nome", "endereco", "rss", "sobre").
		From("site").
		Where(
			query.Equal("id", id),
			query.Equal("bloqueado", false),
			query.Equal("ativo", true),
		)

	// Gera SQL compatível com PostgreSQL
	sqlString, parametros := query.BuildWithFlavor(sqlbuilder.PostgreSQL)

	var site Site

	// Início da transação
	var tx, errTx = data.BeginTransaction()
	if errTx != nil {
		return nil, &PostError{Code: "500", Message: errTx.Error()}
	}

	// Executa a consulta gerada
	errScan := tx.QueryRow(sqlString, parametros...).Scan(&site.Id, &site.Name, &site.Url, &site.Rss, &site.About)
	if errScan != nil {
		tx.Rollback()
		if errScan == sql.ErrNoRows {
			return nil, &PostError{Code: "404", Message: "Site not found"}
		}
		return nil, &PostError{Code: "500", Message: errScan.Error()}
	}
	tx.Commit()
	return &site, nil
}

Mantido por itexto Consultoria