SkillAgentSearch skills...

Gosqlcrud

A Go library to work with SQL database using standard `database/sql` api. It supports SQL to array/maps/structs, and CRUD operations on structs.

Install / Use

/learn @elgs/Gosqlcrud
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

gosqlcrud

A Go library to work with SQL database using standard database/sql api. It supports SQL to array/maps/structs, and CRUD operations on structs.

Installation

go get -u github.com/elgs/gosqlcrud

Example

Please note for Exec, QueryToArrays, QueryToMaps, QueryToStructs, you are responsible for preventing SQL injection in the SQL queries. For Retrieve, Create, Update, Delete, the library will take care of it.

package gosqlcrud

import (
	"database/sql"
	"testing"

	"github.com/stretchr/testify/assert"
	_ "modernc.org/sqlite"
)

type Test struct {
	Id   int     `db:"ID" pk:"true"`
	Name *string `db:"NAME"`
	// use pointer type so when Name is nil, it won't be included in the INSERT or UPDATE statements
}

func TestQueries(t *testing.T) {
	db, err := sql.Open("sqlite", ":memory:")
	assert.NoError(t, err)

	////////////////
	//            //
	//    Exec    //
	//            //
	////////////////

	result, err := Exec(db, "CREATE TABLE test (ID INTEGER PRIMARY KEY, NAME TEXT)") // Exec
	assert.NoError(t, err)
	assert.Equal(t, int64(0), result.LastInsertId)
	assert.Equal(t, int64(0), result.RowsAffected)

	tx, err := db.Begin()
	assert.NoError(t, err)
	result, err = Exec(tx, "INSERT INTO test (ID, NAME) VALUES (?, ?)", 1, "Alpha") // Exec
	assert.NoError(t, err)
	assert.Equal(t, int64(1), result.LastInsertId)
	assert.Equal(t, int64(1), result.RowsAffected)

	result, err = Exec(tx, "INSERT INTO test (ID, NAME) VALUES (?, ?)", 2, "Beta") // Exec
	assert.NoError(t, err)
	assert.Equal(t, int64(2), result.LastInsertId)
	assert.Equal(t, int64(1), result.RowsAffected)

	result, err = Exec(tx, "INSERT INTO test (ID, NAME) VALUES (?, ?)", 3, "Gamma") // Exec
	assert.NoError(t, err)
	assert.Equal(t, int64(3), result.LastInsertId)
	assert.Equal(t, int64(1), result.RowsAffected)
	tx.Commit()

	/////////////////////////
	//                     //
	//    QueryToArrays    //
	//                     //
	/////////////////////////

	cols, resultArray, err := QueryToArrays(db, "SELECT * FROM test WHERE ID > ?", 1) // QueryToArrays
	assert.NoError(t, err)
	assert.Equal(t, "id", cols[0])
	assert.Equal(t, "name", cols[1])
	assert.Equal(t, int64(2), resultArray[0][0])
	assert.Equal(t, "Beta", resultArray[0][1])
	assert.Equal(t, int64(3), resultArray[1][0])
	assert.Equal(t, "Gamma", resultArray[1][1])

	///////////////////////
	//                   //
	//    QueryToMaps    //
	//                   //
	///////////////////////

	resultMaps, err := QueryToMaps(db, "SELECT * FROM test WHERE ID < ?", 3) // QueryToMaps
	assert.NoError(t, err)
	assert.Equal(t, int64(1), resultMaps[0]["id"])
	assert.Equal(t, "Alpha", resultMaps[0]["name"])
	assert.Equal(t, int64(2), resultMaps[1]["id"])
	assert.Equal(t, "Beta", resultMaps[1]["name"])

	//////////////////////////
	//                      //
	//    QueryToStructs    //
	//                      //
	//////////////////////////

	resultStructs := []Test{}
	err = QueryToStructs(db, &resultStructs, "SELECT NAME,ID FROM test WHERE ID > ?", 0) // QueryToStructs
	assert.NoError(t, err)
	assert.Equal(t, "Alpha", *resultStructs[0].Name)
	assert.Equal(t, 1, resultStructs[0].Id)
	assert.Equal(t, "Beta", *resultStructs[1].Name)
	assert.Equal(t, 2, resultStructs[1].Id)
	assert.Equal(t, "Gamma", *resultStructs[2].Name)
	assert.Equal(t, 3, resultStructs[2].Id)

	////////////////////
	//                //
	//    Retrieve    //
	//                //
	////////////////////

	resultStruct := Test{Id: 1}
	err = Retrieve(db, &resultStruct, "test") // Retrieve
	assert.NoError(t, err)
	assert.Equal(t, "Alpha", *resultStruct.Name)
	assert.Equal(t, 1, resultStruct.Id)
	resultStruct.Id = 2
	err = Retrieve(db, &resultStruct, "test") // Retrieve
	assert.NoError(t, err)
	assert.Equal(t, "Beta", *resultStruct.Name)
	assert.Equal(t, 2, resultStruct.Id)
	resultStruct.Id = 3
	err = Retrieve(db, &resultStruct, "test") // Retrieve
	assert.NoError(t, err)
	assert.Equal(t, "Gamma", *resultStruct.Name)
	assert.Equal(t, 3, resultStruct.Id)
	resultStruct.Id = 4
	err = Retrieve(db, &resultStruct, "test") // Retrieve
	assert.Error(t, err)

	//////////////////
	//              //
	//    Create    //
	//              //
	//////////////////

	name := "Delta"
	data := Test{Id: 4, Name: &name}
	result, err = Create(db, &data, "test") // Create
	assert.NoError(t, err)
	assert.Equal(t, int64(4), result.LastInsertId)
	assert.Equal(t, int64(1), result.RowsAffected)

	resultStruct.Id = 4
	err = Retrieve(db, &resultStruct, "test") // Retrieve
	assert.NoError(t, err)
	assert.Equal(t, "Delta", *resultStruct.Name)
	assert.Equal(t, 4, resultStruct.Id)

	//////////////////
	//              //
	//    Update    //
	//              //
	//////////////////

	name = "Omega"
	*data.Name = name
	result, err = Update(db, &data, "test") // Update
	assert.NoError(t, err)
	assert.Equal(t, int64(4), result.LastInsertId)
	assert.Equal(t, int64(1), result.RowsAffected)

	resultStruct.Id = 4
	err = Retrieve(db, &resultStruct, "test") // Retrieve
	assert.NoError(t, err)
	assert.Equal(t, name, *resultStruct.Name)
	assert.Equal(t, 4, resultStruct.Id)

	data.Name = nil
	result, err = Update(db, &data, "test") // Update
	assert.NoError(t, err)
	assert.Equal(t, int64(0), result.RowsAffected)

	resultStruct.Id = 4
	err = Retrieve(db, &resultStruct, "test") // Retrieve
	assert.NoError(t, err)
	assert.Equal(t, name, *resultStruct.Name)
	assert.Equal(t, 4, resultStruct.Id)

	//////////////////
	//              //
	//    Delete    //
	//              //
	//////////////////

	result, err = Delete(db, &data, "test") // Delete
	assert.NoError(t, err)
	assert.Equal(t, int64(4), result.LastInsertId)
	assert.Equal(t, int64(1), result.RowsAffected)

	resultStruct.Id = 4
	err = Retrieve(db, &resultStruct, "test") // Retrieve
	assert.Error(t, err)
}

func TestReflect(t *testing.T) {
	name := "test"
	test := Test{Id: 1, Name: &name}

	fields := StructFieldToDbField(&test)
	assert.Equal(t, "ID", fields[0])
	assert.Equal(t, "NAME", fields[1])

	nonPkMap, pkMap := StructToDbMap(&test)
	assert.Equal(t, "test", *nonPkMap["NAME"].(*string))
	assert.Equal(t, 1, pkMap["ID"])
}

func TestSqlSafe(t *testing.T) {
	ss := []string{
		"asdf",
		"asdf'asdf",
		"asdf--asdf",
	}
	for i := range ss {
		SqlSafe(&ss[i])
	}

	assert.Equal(t, "asdf", ss[0])
	assert.Equal(t, "asdf''asdf", ss[1])
	assert.Equal(t, "asdfasdf", ss[2])
}
View on GitHub
GitHub Stars12
CategoryData
Updated14d ago
Forks1

Languages

Go

Security Score

95/100

Audited on Mar 13, 2026

No findings