mtsatellite/common/pgclient.go

99 lines
1.7 KiB
Go
Raw Normal View History

// Copyright 2022 by Sascha L. Teichmann
// Use of this source code is governed by the MIT license
// that can be found in the LICENSE file.
package common
import (
"context"
"database/sql"
_ "github.com/jackc/pgx/v4/stdlib"
)
const queryCuboidSQL = `
SELECT posx, posy, posz, data FROM blocks
WHERE
posx BETWEEN $1 AND $2 AND
posy BETWEEN $3 AND $4 AND
posz BETWEEN $5 AND $6`
type PGClient struct {
db *sql.DB
queryCuboidStmt *sql.Stmt
}
func NewPGClient(connS string) (*PGClient, error) {
db, err := sql.Open("pgx", connS)
if err != nil {
return nil, err
}
stmt, err := db.Prepare(queryCuboidSQL)
if err != nil {
return nil, err
}
client := PGClient{
db: db,
queryCuboidStmt: stmt,
}
return &client, nil
}
func (pgc *PGClient) QueryCuboid(
cuboid Cuboid,
fn func(*Block) *Block,
) (int, error) {
rows, err := pgc.queryCuboidStmt.QueryContext(
context.Background(),
cuboid.P1.X, cuboid.P2.X,
cuboid.P1.Y, cuboid.P2.Y,
cuboid.P1.Z, cuboid.P2.Z)
if err != nil {
return 0, err
}
defer rows.Close()
var (
posX, posY, posZ int
data []byte
count int
block *Block
)
for ; rows.Next(); count++ {
if err := rows.Scan(
&posX, &posY, posZ,
&data,
); err != nil {
return count, err
}
c := Coord{
X: int16(posX),
Y: int16(posY),
Z: int16(posZ),
}
if block == nil {
block = &Block{Coord: c, Data: data}
} else {
*block = Block{Coord: c, Data: data}
}
if block = fn(block); block != nil {
data = block.Data[:0]
} else {
data = nil
}
}
return count, rows.Err()
}
func (pgc *PGClient) Close() error {
if pgc.queryCuboidStmt != nil {
pgc.queryCuboidStmt.Close()
}
return pgc.db.Close()
}