psql.go 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. // Copyright (C) 2014-2015 Jakob Borg and Contributors (see the CONTRIBUTORS file).
  2. package main
  3. import (
  4. "database/sql"
  5. "fmt"
  6. _ "github.com/lib/pq"
  7. )
  8. func init() {
  9. register("postgres", postgresSetup, postgresCompile)
  10. }
  11. func postgresSetup(db *sql.DB) error {
  12. var err error
  13. db.SetMaxIdleConns(4)
  14. db.SetMaxOpenConns(8)
  15. _, err = db.Exec(`CREATE TABLE IF NOT EXISTS Devices (
  16. DeviceID CHAR(63) NOT NULL PRIMARY KEY,
  17. Seen TIMESTAMP NOT NULL
  18. )`)
  19. if err != nil {
  20. return err
  21. }
  22. row := db.QueryRow(`SELECT 'DevicesDeviceIDIndex'::regclass`)
  23. if err = row.Scan(nil); err != nil {
  24. _, err = db.Exec(`CREATE INDEX DevicesDeviceIDIndex ON Devices (DeviceID)`)
  25. }
  26. if err != nil {
  27. return err
  28. }
  29. row = db.QueryRow(`SELECT 'DevicesSeenIndex'::regclass`)
  30. if err = row.Scan(nil); err != nil {
  31. _, err = db.Exec(`CREATE INDEX DevicesSeenIndex ON Devices (Seen)`)
  32. }
  33. if err != nil {
  34. return err
  35. }
  36. _, err = db.Exec(`CREATE TABLE IF NOT EXISTS Addresses (
  37. DeviceID CHAR(63) NOT NULL,
  38. Seen TIMESTAMP NOT NULL,
  39. Address VARCHAR(256) NOT NULL
  40. )`)
  41. if err != nil {
  42. return err
  43. }
  44. row = db.QueryRow(`SELECT 'AddressesDeviceIDSeenIndex'::regclass`)
  45. if err = row.Scan(nil); err != nil {
  46. _, err = db.Exec(`CREATE INDEX AddressesDeviceIDSeenIndex ON Addresses (DeviceID, Seen)`)
  47. }
  48. if err != nil {
  49. return err
  50. }
  51. row = db.QueryRow(`SELECT 'AddressesDeviceIDAddressIndex'::regclass`)
  52. if err = row.Scan(nil); err != nil {
  53. _, err = db.Exec(`CREATE INDEX AddressesDeviceIDAddressIndex ON Addresses (DeviceID, Address)`)
  54. }
  55. if err != nil {
  56. return err
  57. }
  58. return nil
  59. }
  60. func postgresCompile(db *sql.DB) (map[string]*sql.Stmt, error) {
  61. stmts := map[string]string{
  62. "cleanAddress": "DELETE FROM Addresses WHERE Seen < now() - '2 hour'::INTERVAL",
  63. "cleanDevice": fmt.Sprintf("DELETE FROM Devices WHERE Seen < now() - '%d hour'::INTERVAL", maxDeviceAge/3600),
  64. "countAddress": "SELECT count(*) FROM Addresses",
  65. "countDevice": "SELECT count(*) FROM Devices",
  66. "insertAddress": "INSERT INTO Addresses (DeviceID, Seen, Address) VALUES ($1, now(), $2)",
  67. "insertDevice": "INSERT INTO Devices (DeviceID, Seen) VALUES ($1, now())",
  68. "selectAddress": "SELECT Address FROM Addresses WHERE DeviceID=$1 AND Seen > now() - '1 hour'::INTERVAL ORDER BY random() LIMIT 16",
  69. "selectDevice": "SELECT Seen FROM Devices WHERE DeviceID=$1",
  70. "updateAddress": "UPDATE Addresses SET Seen=now() WHERE DeviceID=$1 AND Address=$2",
  71. "updateDevice": "UPDATE Devices SET Seen=now() WHERE DeviceID=$1",
  72. }
  73. res := make(map[string]*sql.Stmt, len(stmts))
  74. for key, stmt := range stmts {
  75. prep, err := db.Prepare(stmt)
  76. if err != nil {
  77. return nil, err
  78. }
  79. res[key] = prep
  80. }
  81. return res, nil
  82. }