2015-07-21 22:56:27 +00:00
|
|
|
// Copyright (C) 2014-2015 Jakob Borg and Contributors (see the CONTRIBUTORS file).
|
|
|
|
|
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"database/sql"
|
2015-11-13 09:14:19 +00:00
|
|
|
"fmt"
|
2015-07-21 22:56:27 +00:00
|
|
|
|
|
|
|
_ "github.com/lib/pq"
|
|
|
|
)
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
register("postgres", postgresSetup, postgresCompile)
|
|
|
|
}
|
|
|
|
|
|
|
|
func postgresSetup(db *sql.DB) error {
|
|
|
|
var err error
|
|
|
|
|
2015-11-09 14:11:21 +00:00
|
|
|
db.SetMaxIdleConns(4)
|
|
|
|
db.SetMaxOpenConns(8)
|
|
|
|
|
2015-07-21 22:56:27 +00:00
|
|
|
_, err = db.Exec(`CREATE TABLE IF NOT EXISTS Devices (
|
|
|
|
DeviceID CHAR(63) NOT NULL PRIMARY KEY,
|
|
|
|
Seen TIMESTAMP NOT NULL
|
|
|
|
)`)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2016-08-12 09:39:10 +00:00
|
|
|
var tmp string
|
2015-07-21 22:56:27 +00:00
|
|
|
row := db.QueryRow(`SELECT 'DevicesDeviceIDIndex'::regclass`)
|
2016-08-12 09:39:10 +00:00
|
|
|
if err = row.Scan(&tmp); err != nil {
|
2015-07-21 22:56:27 +00:00
|
|
|
_, err = db.Exec(`CREATE INDEX DevicesDeviceIDIndex ON Devices (DeviceID)`)
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
row = db.QueryRow(`SELECT 'DevicesSeenIndex'::regclass`)
|
2016-08-12 09:39:10 +00:00
|
|
|
if err = row.Scan(&tmp); err != nil {
|
2015-07-21 22:56:27 +00:00
|
|
|
_, err = db.Exec(`CREATE INDEX DevicesSeenIndex ON Devices (Seen)`)
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err = db.Exec(`CREATE TABLE IF NOT EXISTS Addresses (
|
|
|
|
DeviceID CHAR(63) NOT NULL,
|
|
|
|
Seen TIMESTAMP NOT NULL,
|
2016-08-12 09:38:37 +00:00
|
|
|
Address VARCHAR(2048) NOT NULL
|
2015-07-21 22:56:27 +00:00
|
|
|
)`)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
row = db.QueryRow(`SELECT 'AddressesDeviceIDSeenIndex'::regclass`)
|
2016-08-12 09:39:10 +00:00
|
|
|
if err = row.Scan(&tmp); err != nil {
|
2015-07-21 22:56:27 +00:00
|
|
|
_, err = db.Exec(`CREATE INDEX AddressesDeviceIDSeenIndex ON Addresses (DeviceID, Seen)`)
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
row = db.QueryRow(`SELECT 'AddressesDeviceIDAddressIndex'::regclass`)
|
2016-08-12 09:39:10 +00:00
|
|
|
if err = row.Scan(&tmp); err != nil {
|
2015-07-21 22:56:27 +00:00
|
|
|
_, err = db.Exec(`CREATE INDEX AddressesDeviceIDAddressIndex ON Addresses (DeviceID, Address)`)
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func postgresCompile(db *sql.DB) (map[string]*sql.Stmt, error) {
|
|
|
|
stmts := map[string]string{
|
|
|
|
"cleanAddress": "DELETE FROM Addresses WHERE Seen < now() - '2 hour'::INTERVAL",
|
2015-11-13 09:14:19 +00:00
|
|
|
"cleanDevice": fmt.Sprintf("DELETE FROM Devices WHERE Seen < now() - '%d hour'::INTERVAL", maxDeviceAge/3600),
|
2015-07-21 22:56:27 +00:00
|
|
|
"countAddress": "SELECT count(*) FROM Addresses",
|
|
|
|
"countDevice": "SELECT count(*) FROM Devices",
|
|
|
|
"insertAddress": "INSERT INTO Addresses (DeviceID, Seen, Address) VALUES ($1, now(), $2)",
|
|
|
|
"insertDevice": "INSERT INTO Devices (DeviceID, Seen) VALUES ($1, now())",
|
2015-09-13 09:44:33 +00:00
|
|
|
"selectAddress": "SELECT Address FROM Addresses WHERE DeviceID=$1 AND Seen > now() - '1 hour'::INTERVAL ORDER BY random() LIMIT 16",
|
2015-11-13 09:14:19 +00:00
|
|
|
"selectDevice": "SELECT Seen FROM Devices WHERE DeviceID=$1",
|
2015-09-13 09:44:33 +00:00
|
|
|
"updateAddress": "UPDATE Addresses SET Seen=now() WHERE DeviceID=$1 AND Address=$2",
|
2015-07-21 22:56:27 +00:00
|
|
|
"updateDevice": "UPDATE Devices SET Seen=now() WHERE DeviceID=$1",
|
|
|
|
}
|
|
|
|
|
|
|
|
res := make(map[string]*sql.Stmt, len(stmts))
|
|
|
|
for key, stmt := range stmts {
|
|
|
|
prep, err := db.Prepare(stmt)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
res[key] = prep
|
|
|
|
}
|
|
|
|
return res, nil
|
|
|
|
}
|