Archived
1
0

optimize queries more

This commit is contained in:
Jeff Becker 2017-09-12 09:27:48 -04:00
parent 22dc099105
commit 2e1b934705
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05
3 changed files with 44 additions and 21 deletions

View File

@ -65,6 +65,11 @@ type PostingStats struct {
History []PostingStatsEntry History []PostingStatsEntry
} }
// newsgroup, first, last
type NewsgroupListEntry [3]string
type NewsgroupList []NewsgroupListEntry
type Database interface { type Database interface {
Close() Close()
CreateTables() CreateTables()
@ -322,6 +327,9 @@ type Database interface {
// get post message-id where hash is similar to string // get post message-id where hash is similar to string
GetCitesByPostHashLike(like string) ([]MessageIDTuple, error) GetCitesByPostHashLike(like string) ([]MessageIDTuple, error)
// get newsgroup list with watermarks
GetNewsgroupList() (NewsgroupList, error)
} }
func NewDatabase(db_type, schema, host, port, user, password string) Database { func NewDatabase(db_type, schema, host, port, user, password string) Database {

View File

@ -1030,19 +1030,18 @@ func (self *nntpConnection) handleLine(daemon *NNTPDaemon, code int, line string
conn.PrintfLine("411 No Such Newsgroup") conn.PrintfLine("411 No Such Newsgroup")
} }
} else if cmd == "LIST" && parts[1] == "NEWSGROUPS" { } else if cmd == "LIST" && parts[1] == "NEWSGROUPS" {
conn.PrintfLine("215 list of newsgroups follows")
// handle list command // handle list command
groups := daemon.database.GetAllNewsgroups() list, err := daemon.database.GetNewsgroupList()
dw := conn.DotWriter() if err == nil {
for _, group := range groups { conn.PrintfLine("215 list of newsgroups follows")
last, first, err := daemon.database.GetLastAndFirstForGroup(group) dw := conn.DotWriter()
if err == nil { for _, entry := range list {
io.WriteString(dw, fmt.Sprintf("%s %d %d y\r\n", group, first, last)) io.WriteString(dw, fmt.Sprintf("%s %s %s y\r\n", entry[0], entry[1], entry[2]))
} else {
log.Println("cannot get last/first ids for group", group, err)
} }
dw.Close()
} else {
conn.PrintfLine("500 failed to get list: %s", err.Error())
} }
dw.Close()
} else if cmd == "STAT" { } else if cmd == "STAT" {
if len(self.group) == 0 { if len(self.group) == 0 {
if len(parts) == 2 { if len(parts) == 2 {
@ -1135,19 +1134,17 @@ func (self *nntpConnection) handleLine(daemon *NNTPDaemon, code int, line string
} }
} else { } else {
if line == "LIST" { if line == "LIST" {
conn.PrintfLine("215 list of newsgroups follows") list, err := daemon.database.GetNewsgroupList()
// handle list command if err == nil {
groups := daemon.database.GetAllNewsgroups() conn.PrintfLine("215 list of newsgroups follows")
dw := conn.DotWriter() dw := conn.DotWriter()
for _, group := range groups { for _, entry := range list {
last, first, err := daemon.database.GetLastAndFirstForGroup(group) io.WriteString(dw, fmt.Sprintf("%s %s %s y\r\n", entry[0], entry[1], entry[2]))
if err == nil {
io.WriteString(dw, fmt.Sprintf("%s %d %d y\r\n", group, first, last))
} else {
log.Println("cannot get last/first ids for group", group, err)
} }
dw.Close()
} else {
conn.PrintfLine("500 failed to get list: %s", err.Error())
} }
dw.Close()
} else if line == "POST" { } else if line == "POST" {
if !self.authenticated { if !self.authenticated {
// needs tls to work if not logged in // needs tls to work if not logged in

View File

@ -146,6 +146,7 @@ const SearchByHash_2 = "SearchByHash_2"
const GetNNTPPostsInGroup = "GetNNTPPostsInGroup" const GetNNTPPostsInGroup = "GetNNTPPostsInGroup"
const GetCitesByPostHashLike = "GetCitesByPostHashLike" const GetCitesByPostHashLike = "GetCitesByPostHashLike"
const GetYearlyPostHistory = "GetYearlyPostHistory" const GetYearlyPostHistory = "GetYearlyPostHistory"
const GetNewsgroupList = "GetNewsgroupList"
func (self *PostgresDatabase) prepareStatements() { func (self *PostgresDatabase) prepareStatements() {
self.stmt = map[string]string{ self.stmt = map[string]string{
@ -191,6 +192,7 @@ func (self *PostgresDatabase) prepareStatements() {
GetMessageIDByHash: "SELECT message_id, message_newsgroup FROM Articles WHERE message_id_hash = $1 LIMIT 1", GetMessageIDByHash: "SELECT message_id, message_newsgroup FROM Articles WHERE message_id_hash = $1 LIMIT 1",
CheckEncIPBanned: "SELECT 1 FROM EncIPBans WHERE encaddr = $1", CheckEncIPBanned: "SELECT 1 FROM EncIPBans WHERE encaddr = $1",
GetFirstAndLastForGroup: "WITH x(min_no, max_no) AS ( SELECT MIN(message_no) AS min_no, MAX(message_no) AS max_no FROM ArticleNumbers WHERE newsgroup = $1) SELECT CASE WHEN min_no IS NULL THEN 0 ELSE min_no END AS min_no FROM x UNION SELECT CASE WHEN max_no IS NULL THEN 1 ELSE max_no END AS max_no FROM x", GetFirstAndLastForGroup: "WITH x(min_no, max_no) AS ( SELECT MIN(message_no) AS min_no, MAX(message_no) AS max_no FROM ArticleNumbers WHERE newsgroup = $1) SELECT CASE WHEN min_no IS NULL THEN 0 ELSE min_no END AS min_no FROM x UNION SELECT CASE WHEN max_no IS NULL THEN 1 ELSE max_no END AS max_no FROM x",
GetNewsgroupList: "SELECT newsgroup, min(message_no), max(message_no) FROM ArticlePosts GROUP BY newsgroup",
GetMessageIDForNNTPID: "SELECT message_id FROM ArticleNumbers WHERE newsgroup = $1 AND message_no = $2 LIMIT 1", GetMessageIDForNNTPID: "SELECT message_id FROM ArticleNumbers WHERE newsgroup = $1 AND message_no = $2 LIMIT 1",
GetNNTPIDForMessageID: "SELECT message_no FROM ArticleNumbers WHERE newsgroup = $1 AND message_id = $2 LIMIT 1", GetNNTPIDForMessageID: "SELECT message_no FROM ArticleNumbers WHERE newsgroup = $1 AND message_id = $2 LIMIT 1",
IsExpired: "WITH x(msgid) AS ( SELECT message_id FROM Articles WHERE message_id = $1 INTERSECT ( SELECT message_id FROM ArticlePosts WHERE message_id = $1 ) ) SELECT COUNT(*) FROM x", IsExpired: "WITH x(msgid) AS ( SELECT message_id FROM Articles WHERE message_id = $1 INTERSECT ( SELECT message_id FROM ArticlePosts WHERE message_id = $1 ) ) SELECT COUNT(*) FROM x",
@ -1893,3 +1895,19 @@ func (self *PostgresDatabase) SearchByHash(prefix, group, text string, chnl chan
close(chnl) close(chnl)
return return
} }
func (self *PostgresDatabase) GetNewsgroupList() (list NewsgroupList, err error) {
var rows *sql.Rows
rows, err = self.conn.Query(self.stmt[GetNewsgroupList])
if err == nil {
for rows.Next() {
var l NewsgroupListEntry
var lo, hi int64
rows.Scan(&l[0], &lo, &hi)
l[1] = fmt.Sprintf("%d", lo)
l[2] = fmt.Sprintf("%d", hi)
}
rows.Close()
}
return
}