Skip to content

Commit

Permalink
[bugfix] Support MySQL < 5.6.4
Browse files Browse the repository at this point in the history
  • Loading branch information
alexedwards committed Aug 6, 2017
1 parent f36d272 commit 0fdd3ef
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 5 deletions.
15 changes: 13 additions & 2 deletions engine/mysqlstore/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# mysqlstore
# mysqlstore
[![godoc](https://godoc.org/github.com/alexedwards/scs/engine/mysqlstore?status.png)](https://godoc.org/github.com/alexedwards/scs/engine/mysqlstore)

Package mysqlstore is a MySQL-based storage engine for the [SCS session package](https://godoc.org/github.com/alexedwards/scs/session).
Expand Down Expand Up @@ -33,6 +33,17 @@ CREATE TABLE sessions (
CREATE INDEX sessions_expiry_idx ON sessions (expiry);
```

Or for MySQL versions < 5.6.4:

```sql
CREATE TABLE sessions (
token CHAR(43) PRIMARY KEY,
data BLOB NOT NULL,
expiry TIMESTAMP NOT NULL
);
CREATE INDEX sessions_expiry_idx ON sessions (expiry);
```

### Example

```go
Expand All @@ -57,7 +68,7 @@ func main() {
}
defer db.Close()

// Create a new MySQLStore instance using the existing database/sql pool,
// Create a new MySQLStore instance using the existing database/sql pool,
// with a cleanup interval of 5 minutes.
engine := mysqlstore.New(db, 5*time.Minute)

Expand Down
70 changes: 67 additions & 3 deletions engine/mysqlstore/mysqlstore.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ package mysqlstore
import (
"database/sql"
"log"
"strconv"
"strings"
"time"

// Register go-sql-driver/mysql with database/sql
Expand All @@ -47,6 +49,7 @@ import (
// MySQLStore represents the currently configured session storage engine.
type MySQLStore struct {
*sql.DB
version string
stopCleanup chan bool
}

Expand All @@ -56,10 +59,15 @@ type MySQLStore struct {
// is removed by the background cleanup goroutine. Setting it to 0 prevents
// the cleanup goroutine from running (i.e. expired sessions will not be removed).
func New(db *sql.DB, cleanupInterval time.Duration) *MySQLStore {
m := &MySQLStore{DB: db}
m := &MySQLStore{
DB: db,
version: getVersion(db),
}

if cleanupInterval > 0 {
go m.startCleanup(cleanupInterval)
}

return m
}

Expand All @@ -68,7 +76,15 @@ func New(db *sql.DB, cleanupInterval time.Duration) *MySQLStore {
// set to false.
func (m *MySQLStore) Find(token string) ([]byte, bool, error) {
var b []byte
row := m.DB.QueryRow("SELECT data FROM sessions WHERE token = ? AND UTC_TIMESTAMP(6) < expiry", token)
var stmt string

if compareVersion("5.6.4", m.version) >= 0 {
stmt = "SELECT data FROM sessions WHERE token = ? AND UTC_TIMESTAMP(6) < expiry"
} else {
stmt = "SELECT data FROM sessions WHERE token = ? AND UTC_TIMESTAMP < expiry"
}

row := m.DB.QueryRow(stmt, token)
err := row.Scan(&b)
if err == sql.ErrNoRows {
return nil, false, nil
Expand Down Expand Up @@ -143,6 +159,54 @@ func (m *MySQLStore) StopCleanup() {
}

func (m *MySQLStore) deleteExpired() error {
_, err := m.DB.Exec("DELETE FROM sessions WHERE expiry < UTC_TIMESTAMP(6)")
var stmt string

if compareVersion("5.6.4", m.version) >= 0 {
stmt = "DELETE FROM sessions WHERE expiry < UTC_TIMESTAMP(6)"
} else {
stmt = "DELETE FROM sessions WHERE expiry < UTC_TIMESTAMP"
}

_, err := m.DB.Exec(stmt)
return err
}

func getVersion(db *sql.DB) string {
var version string
row := db.QueryRow("SELECT VERSION()")
err := row.Scan(&version)
if err != nil {
return ""
}
return strings.Split(version, "-")[0]
}

// Based on https://stackoverflow.com/a/26729704
func compareVersion(a, b string) (ret int) {
as := strings.Split(a, ".")
bs := strings.Split(b, ".")
loopMax := len(bs)
if len(as) > len(bs) {
loopMax = len(as)
}
for i := 0; i < loopMax; i++ {
var x, y string
if len(as) > i {
x = as[i]
}
if len(bs) > i {
y = bs[i]
}
xi, _ := strconv.Atoi(x)
yi, _ := strconv.Atoi(y)
if xi > yi {
ret = -1
} else if xi < yi {
ret = 1
}
if ret != 0 {
break
}
}
return
}

0 comments on commit 0fdd3ef

Please # to comment.