Fixed non-interleaved sqlite support.

This commit is contained in:
Sascha L. Teichmann 2015-07-23 16:20:42 +02:00
parent e8e4d6afeb
commit 93d4aedffa
2 changed files with 29 additions and 97 deletions

View File

@ -17,18 +17,13 @@ import (
var globalLock sync.RWMutex var globalLock sync.RWMutex
const ( const (
fetchSQL = "SELECT data FROM blocks WHERE pos = ?" fetchSQL = "SELECT data FROM blocks WHERE pos = ?"
existsSQL = "SELECT 1 FROM blocks WHERE pos = ?" existsSQL = "SELECT 1 FROM blocks WHERE pos = ?"
updateSQL = "UPDATE blocks SET data = ? WHERE pos = ?" updateSQL = "UPDATE blocks SET data = ? WHERE pos = ?"
insertSQL = "INSERT INTO blocks (pos, data) VALUES (?, ?)" insertSQL = "INSERT INTO blocks (pos, data) VALUES (?, ?)"
countSQL = "SELECT count(*) FROM blocks" countSQL = "SELECT count(*) FROM blocks"
keysSQL = "SELECT pos FROM blocks" keysSQL = "SELECT pos FROM blocks"
rangeSQL = "SELECT pos, data FROM blocks WHERE pos BETWEEN ? AND ? ORDER BY pos" rangeSQL = "SELECT pos, data FROM blocks WHERE pos BETWEEN ? AND ? ORDER BY pos"
rangeDuffSQL = "SELECT pos, data FROM blocks WHERE " +
"pos BETWEEN ? AND ? OR " +
"pos BETWEEN ? AND ? OR " +
"pos BETWEEN ? AND ? OR " +
"pos BETWEEN ? AND ?"
) )
type SqliteBackend struct { type SqliteBackend struct {
@ -105,14 +100,7 @@ func NewSqliteBackend(
return return
} }
var rS string if res.rangeStmt, err = res.db.Prepare(rangeSQL); err != nil {
if interleaved {
rS = rangeSQL
} else {
rS = rangeDuffSQL
}
if res.rangeStmt, err = res.db.Prepare(rS); err != nil {
res.closeAll() res.closeAll()
return return
} }
@ -421,52 +409,6 @@ func (ss *SqliteSession) interleavedSpatialQuery(first, second []byte, done chan
return return
} }
type duffStmt struct {
stmt *sql.Stmt
counter int
params [8]int64
}
func (ds *duffStmt) push(a, b int64) bool {
ds.params[ds.counter] = a
ds.counter++
ds.params[ds.counter] = b
ds.counter++
return ds.counter > 7
}
func (ds *duffStmt) Query() (*sql.Rows, error) {
c := ds.counter
ds.counter = 0
switch c {
case 8:
return ds.stmt.Query(
ds.params[0], ds.params[1],
ds.params[2], ds.params[3],
ds.params[4], ds.params[5],
ds.params[0], ds.params[1])
case 6:
return ds.stmt.Query(
ds.params[0], ds.params[1],
ds.params[2], ds.params[3],
ds.params[4], ds.params[5],
ds.params[0], ds.params[1])
case 4:
return ds.stmt.Query(
ds.params[0], ds.params[1],
ds.params[2], ds.params[3],
ds.params[0], ds.params[1],
ds.params[0], ds.params[1])
case 2:
return ds.stmt.Query(
ds.params[0], ds.params[1],
ds.params[0], ds.params[1],
ds.params[0], ds.params[1],
ds.params[0], ds.params[1])
}
return nil, nil
}
func (ss *SqliteSession) plainSpatialQuery(first, second []byte, done chan struct{}) (blocks chan Block, err error) { func (ss *SqliteSession) plainSpatialQuery(first, second []byte, done chan struct{}) (blocks chan Block, err error) {
var ( var (
@ -490,18 +432,17 @@ func (ss *SqliteSession) plainSpatialQuery(first, second []byte, done chan struc
go func() { go func() {
defer globalLock.RUnlock() defer globalLock.RUnlock()
defer close(blocks) defer close(blocks)
rangeStmt := duffStmt{stmt: ss.txStmt(ss.backend.rangeStmt)} rangeStmt := ss.txStmt(ss.backend.rangeStmt)
send := func(rows *sql.Rows, err error) bool { send := func(rows *sql.Rows, err error) bool {
if rows == nil {
return true
}
if err != nil { if err != nil {
log.Printf("Error in range query: %s\n", err) log.Printf("Error in range query: %s\n", err)
return false return false
} }
defer rows.Close() defer rows.Close()
count := 0
for rows.Next() { for rows.Next() {
var key int64 var key int64
var data []byte var data []byte
@ -519,6 +460,7 @@ func (ss *SqliteSession) plainSpatialQuery(first, second []byte, done chan struc
case <-done: case <-done:
return false return false
} }
count++
} }
if err = rows.Err(); err != nil { if err = rows.Err(); err != nil {
log.Printf("Error in range query: %s\n", err) log.Printf("Error in range query: %s\n", err)
@ -527,37 +469,27 @@ func (ss *SqliteSession) plainSpatialQuery(first, second []byte, done chan struc
return true return true
} }
if ss.backend.coverage == nil { var a, b common.Coord
a, b := common.Coord{X: c1.X}, common.Coord{X: c2.X}
for a.Y = c2.Y; a.Y >= c1.Y; a.Y-- {
b.Y = a.Y
for a.Z = c1.Z; a.Z <= c2.Z; a.Z++ {
b.Z = a.Z
// Ordering should not be necessary.
from, to := order(common.CoordToPlain(a), common.CoordToPlain(b))
if rangeStmt.push(from, to) && !send(rangeStmt.Query()) {
return
}
}
}
} else {
var a, b common.Coord
for _, r := range ss.backend.coverage.Query(c1, c2) { for _, r := range ss.backend.coverage.Query(c1, c2) {
a.Z, b.Z = int16(r.Z), int16(r.Z) a.Z, b.Z = int16(r.Z), int16(r.Z)
a.X, b.X = int16(r.X1), int16(r.X2) a.X, b.X = int16(r.X1), int16(r.X2)
// log.Printf("y1 y2 x1 x2 z: %d %d, %d %d, %d\n", r.Y1, r.Y2, r.X1, r.X2, r.Z) // log.Printf("y1 y2 x1 x2 z: %d %d, %d %d, %d\n", r.Y1, r.Y2, r.X1, r.X2, r.Z)
for y := r.Y2; y >= r.Y1; y-- { for a.Y = r.Y2; a.Y >= r.Y1; a.Y-- {
a.Y, b.Y = int16(y), int16(y) b.Y = a.Y
from, to := order(common.CoordToPlain(a), common.CoordToPlain(b)) from, to := common.CoordToPlain(a), common.CoordToPlain(b)
if rangeStmt.push(from, to) && !send(rangeStmt.Query()) { if !send(rangeStmt.Query(from, to)) {
return return
}
} }
} }
} }
send(rangeStmt.Query())
}() }()
return return
} }
func clone(a []byte) []byte {
b := make([]byte, len(a))
copy(b, a)
return b
}

View File

@ -132,7 +132,7 @@ func (btc *BaseTileCreator) CreateTile(x, z int16, i, j int) error {
return err return err
} }
} }
log.Printf("Writing empty (%d, %d) to file %s\n", x, z, path) //log.Printf("Writing empty (%d, %d) to file %s\n", x, z, path)
return ioutil.WriteFile(path, btc.emptyImage, 0666) return ioutil.WriteFile(path, btc.emptyImage, 0666)
} }