Added the Accumulator to the Builder.

Renamed LoadThemes to LoadThemeActiveStatus.
Moved more statements into the stores.
More errors are propagated upwards.
Added an interface for the ForumPermsStore.
Replaced a hard-coded query which somehow managed to survive.
Replaced a few redundant Markdown tests with more targetted ones.
Added a few new BBCode tests.
Fixed a few bugs in the Markdown Parser.
This commit is contained in:
Azareal 2017-11-06 04:02:35 +00:00
parent 3fa9bf7373
commit 01239f82f1
17 changed files with 434 additions and 258 deletions

View File

@ -68,7 +68,10 @@ func initDatabase() (err error) {
} }
log.Print("Loading the forum permissions.") log.Print("Loading the forum permissions.")
fpstore = NewForumPermsStore() fpstore, err = NewMemoryForumPermsStore()
if err != nil {
return err
}
err = fpstore.Init() err = fpstore.Init()
if err != nil { if err != nil {
return err return err
@ -87,5 +90,5 @@ func initDatabase() (err error) {
} }
log.Print("Loading the themes.") log.Print("Loading the themes.")
return LoadThemes() return LoadThemeActiveStatus()
} }

View File

@ -1,20 +1,45 @@
package main package main
import ( import (
"database/sql"
"encoding/json" "encoding/json"
"log" "log"
"./query_gen/lib"
) )
var fpstore *ForumPermsStore var fpstore ForumPermsStore
type ForumPermsStore struct { type ForumPermsStore interface {
Init() error
Get(fid int, gid int) (fperms ForumPerms, err error)
Reload(id int) error
} }
func NewForumPermsStore() *ForumPermsStore { type ForumPermsCache interface {
return &ForumPermsStore{}
} }
func (fps *ForumPermsStore) Init() error { type MemoryForumPermsStore struct {
get *sql.Stmt
getByForum *sql.Stmt
}
func NewMemoryForumPermsStore() (*MemoryForumPermsStore, error) {
getPermsStmt, err := qgen.Builder.SimpleSelect("forums_permissions", "gid, fid, permissions", "", "gid ASC, fid ASC", "")
if err != nil {
return nil, err
}
getPermsByForumStmt, err := qgen.Builder.SimpleSelect("forums_permissions", "gid, permissions", "fid = ?", "gid ASC", "")
if err != nil {
return nil, err
}
return &MemoryForumPermsStore{
get: getPermsStmt,
getByForum: getPermsByForumStmt,
}, nil
}
func (fps *MemoryForumPermsStore) Init() error {
fids, err := fstore.GetAllIDs() fids, err := fstore.GetAllIDs()
if err != nil { if err != nil {
return err return err
@ -23,7 +48,7 @@ func (fps *ForumPermsStore) Init() error {
log.Print("fids: ", fids) log.Print("fids: ", fids)
} }
rows, err := stmts.getForumsPermissions.Query() rows, err := fps.get.Query()
if err != nil { if err != nil {
return err return err
} }
@ -73,7 +98,7 @@ func (fps *ForumPermsStore) Init() error {
} }
// TODO: Need a more thread-safe way of doing this. Possibly with sync.Map? // TODO: Need a more thread-safe way of doing this. Possibly with sync.Map?
func (fps *ForumPermsStore) Reload(fid int) error { func (fps *MemoryForumPermsStore) Reload(fid int) error {
if dev.DebugMode { if dev.DebugMode {
log.Printf("Reloading the forum permissions for forum #%d", fid) log.Printf("Reloading the forum permissions for forum #%d", fid)
} }
@ -82,7 +107,7 @@ func (fps *ForumPermsStore) Reload(fid int) error {
return err return err
} }
rows, err := db.Query("select gid, permissions from forums_permissions where fid = ? order by gid asc", fid) rows, err := fps.getByForum.Query(fid)
if err != nil { if err != nil {
return err return err
} }
@ -112,7 +137,7 @@ func (fps *ForumPermsStore) Reload(fid int) error {
return fps.cascadePermSetToGroups(forumPerms, fids) return fps.cascadePermSetToGroups(forumPerms, fids)
} }
func (fps *ForumPermsStore) cascadePermSetToGroups(forumPerms map[int]map[int]ForumPerms, fids []int) error { func (fps *MemoryForumPermsStore) cascadePermSetToGroups(forumPerms map[int]map[int]ForumPerms, fids []int) error {
groups, err := gstore.GetAll() groups, err := gstore.GetAll()
if err != nil { if err != nil {
return err return err
@ -134,7 +159,7 @@ func (fps *ForumPermsStore) cascadePermSetToGroups(forumPerms map[int]map[int]Fo
return nil return nil
} }
func (fps *ForumPermsStore) cascadePermSetToGroup(forumPerms map[int]map[int]ForumPerms, group *Group, fids []int) { func (fps *MemoryForumPermsStore) cascadePermSetToGroup(forumPerms map[int]map[int]ForumPerms, group *Group, fids []int) {
for _, fid := range fids { for _, fid := range fids {
if dev.SuperDebug { if dev.SuperDebug {
log.Printf("Forum #%+v\n", fid) log.Printf("Forum #%+v\n", fid)
@ -164,7 +189,7 @@ func (fps *ForumPermsStore) cascadePermSetToGroup(forumPerms map[int]map[int]For
} }
} }
func (fps *ForumPermsStore) Get(fid int, gid int) (fperms ForumPerms, err error) { func (fps *MemoryForumPermsStore) Get(fid int, gid int) (fperms ForumPerms, err error) {
// TODO: Add a hook here and have plugin_guilds use it // TODO: Add a hook here and have plugin_guilds use it
group, err := gstore.Get(gid) group, err := gstore.Get(gid)
if err != nil { if err != nil {

View File

@ -59,10 +59,14 @@ type MemoryForumStore struct {
forumView atomic.Value // []*Forum forumView atomic.Value // []*Forum
//fids []int //fids []int
get *sql.Stmt get *sql.Stmt
getAll *sql.Stmt getAll *sql.Stmt
delete *sql.Stmt delete *sql.Stmt
getForumCount *sql.Stmt create *sql.Stmt
count *sql.Stmt
updateCache *sql.Stmt
addTopicsToForum *sql.Stmt
removeTopicsFromForum *sql.Stmt
} }
// NewMemoryForumStore gives you a new instance of MemoryForumStore // NewMemoryForumStore gives you a new instance of MemoryForumStore
@ -80,15 +84,35 @@ func NewMemoryForumStore() (*MemoryForumStore, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
createStmt, err := qgen.Builder.SimpleInsert("forums", "name, desc, active, preset", "?,?,?,?")
if err != nil {
return nil, err
}
forumCountStmt, err := qgen.Builder.SimpleCount("forums", "name != ''", "") forumCountStmt, err := qgen.Builder.SimpleCount("forums", "name != ''", "")
if err != nil { if err != nil {
return nil, err return nil, err
} }
updateCacheStmt, err := qgen.Builder.SimpleUpdate("forums", "lastTopicID = ?, lastReplyerID = ?", "fid = ?")
if err != nil {
return nil, err
}
addTopicsToForumStmt, err := qgen.Builder.SimpleUpdate("forums", "topicCount = topicCount + ?", "fid = ?")
if err != nil {
return nil, err
}
removeTopicsFromForumStmt, err := qgen.Builder.SimpleUpdate("forums", "topicCount = topicCount - ?", "fid = ?")
if err != nil {
return nil, err
}
return &MemoryForumStore{ return &MemoryForumStore{
get: getStmt, get: getStmt,
getAll: getAllStmt, getAll: getAllStmt,
delete: deleteStmt, delete: deleteStmt,
getForumCount: forumCountStmt, create: createStmt,
count: forumCountStmt,
updateCache: updateCacheStmt,
addTopicsToForum: addTopicsToForumStmt,
removeTopicsFromForum: removeTopicsFromForumStmt,
}, nil }, nil
} }
@ -102,8 +126,7 @@ func (mfs *MemoryForumStore) LoadForums() error {
} }
} }
// TODO: Move this statement into the store rows, err := mfs.getAll.Query()
rows, err := stmts.getForums.Query()
if err != nil { if err != nil {
return err return err
} }
@ -122,7 +145,7 @@ func (mfs *MemoryForumStore) LoadForums() error {
log.Print("Adding a placeholder forum") log.Print("Adding a placeholder forum")
} }
} else { } else {
log.Print("Adding the " + forum.Name + " forum") log.Printf("Adding the %s forum", forum.Name)
} }
forum.Link = buildForumURL(nameToSlug(forum.Name), forum.ID) forum.Link = buildForumURL(nameToSlug(forum.Name), forum.ID)
@ -328,11 +351,11 @@ func (mfs *MemoryForumStore) Delete(id int) error {
} }
func (mfs *MemoryForumStore) AddTopic(tid int, uid int, fid int) error { func (mfs *MemoryForumStore) AddTopic(tid int, uid int, fid int) error {
_, err := stmts.updateForumCache.Exec(tid, uid, fid) _, err := mfs.updateCache.Exec(tid, uid, fid)
if err != nil { if err != nil {
return err return err
} }
_, err = stmts.addTopicsToForum.Exec(1, fid) _, err = mfs.addTopicsToForum.Exec(1, fid)
if err != nil { if err != nil {
return err return err
} }
@ -342,7 +365,7 @@ func (mfs *MemoryForumStore) AddTopic(tid int, uid int, fid int) error {
// TODO: Update the forum cache with the latest topic // TODO: Update the forum cache with the latest topic
func (mfs *MemoryForumStore) RemoveTopic(fid int) error { func (mfs *MemoryForumStore) RemoveTopic(fid int) error {
_, err := stmts.removeTopicsFromForum.Exec(1, fid) _, err := mfs.removeTopicsFromForum.Exec(1, fid)
if err != nil { if err != nil {
return err return err
} }
@ -354,7 +377,7 @@ func (mfs *MemoryForumStore) RemoveTopic(fid int) error {
// DEPRECATED. forum.Update() will be the way to do this in the future, once it's completed // DEPRECATED. forum.Update() will be the way to do this in the future, once it's completed
// TODO: Have a pointer to the last topic rather than storing it on the forum itself // TODO: Have a pointer to the last topic rather than storing it on the forum itself
func (mfs *MemoryForumStore) UpdateLastTopic(tid int, uid int, fid int) error { func (mfs *MemoryForumStore) UpdateLastTopic(tid int, uid int, fid int) error {
_, err := stmts.updateForumCache.Exec(tid, uid, fid) _, err := mfs.updateCache.Exec(tid, uid, fid)
if err != nil { if err != nil {
return err return err
} }
@ -364,8 +387,7 @@ func (mfs *MemoryForumStore) UpdateLastTopic(tid int, uid int, fid int) error {
func (mfs *MemoryForumStore) Create(forumName string, forumDesc string, active bool, preset string) (int, error) { func (mfs *MemoryForumStore) Create(forumName string, forumDesc string, active bool, preset string) (int, error) {
forumCreateMutex.Lock() forumCreateMutex.Lock()
// TODO: Move this query into the store res, err := mfs.create.Exec(forumName, forumDesc, active, preset)
res, err := stmts.createForum.Exec(forumName, forumDesc, active, preset)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -399,7 +421,7 @@ func (mfs *MemoryForumStore) Length() (length int) {
// TODO: Get the total count of forums in the forum store minus the blanked forums rather than doing a heavy query for this? // TODO: Get the total count of forums in the forum store minus the blanked forums rather than doing a heavy query for this?
// GlobalCount returns the total number of forums // GlobalCount returns the total number of forums
func (mfs *MemoryForumStore) GlobalCount() (fcount int) { func (mfs *MemoryForumStore) GlobalCount() (fcount int) {
err := mfs.getForumCount.QueryRow().Scan(&fcount) err := mfs.count.QueryRow().Scan(&fcount)
if err != nil { if err != nil {
LogError(err) LogError(err)
} }

View File

@ -8,16 +8,11 @@ import "database/sql"
// nolint // nolint
type Stmts struct { type Stmts struct {
getReply *sql.Stmt
getUserReply *sql.Stmt
getPassword *sql.Stmt getPassword *sql.Stmt
getSettings *sql.Stmt getSettings *sql.Stmt
getSetting *sql.Stmt getSetting *sql.Stmt
getFullSetting *sql.Stmt getFullSetting *sql.Stmt
getFullSettings *sql.Stmt getFullSettings *sql.Stmt
getGroups *sql.Stmt
getForums *sql.Stmt
getForumsPermissions *sql.Stmt
getPlugins *sql.Stmt getPlugins *sql.Stmt
getThemes *sql.Stmt getThemes *sql.Stmt
getWidgets *sql.Stmt getWidgets *sql.Stmt
@ -52,7 +47,6 @@ type Stmts struct {
getWatchers *sql.Stmt getWatchers *sql.Stmt
createTopic *sql.Stmt createTopic *sql.Stmt
createReport *sql.Stmt createReport *sql.Stmt
createReply *sql.Stmt
createActionReply *sql.Stmt createActionReply *sql.Stmt
createLike *sql.Stmt createLike *sql.Stmt
addActivity *sql.Stmt addActivity *sql.Stmt
@ -60,7 +54,6 @@ type Stmts struct {
addEmail *sql.Stmt addEmail *sql.Stmt
createProfileReply *sql.Stmt createProfileReply *sql.Stmt
addSubscription *sql.Stmt addSubscription *sql.Stmt
createForum *sql.Stmt
addForumPermsToForum *sql.Stmt addForumPermsToForum *sql.Stmt
addPlugin *sql.Stmt addPlugin *sql.Stmt
addTheme *sql.Stmt addTheme *sql.Stmt
@ -70,9 +63,6 @@ type Stmts struct {
createWordFilter *sql.Stmt createWordFilter *sql.Stmt
addRepliesToTopic *sql.Stmt addRepliesToTopic *sql.Stmt
removeRepliesFromTopic *sql.Stmt removeRepliesFromTopic *sql.Stmt
addTopicsToForum *sql.Stmt
removeTopicsFromForum *sql.Stmt
updateForumCache *sql.Stmt
addLikesToTopic *sql.Stmt addLikesToTopic *sql.Stmt
addLikesToReply *sql.Stmt addLikesToReply *sql.Stmt
editTopic *sql.Stmt editTopic *sql.Stmt
@ -140,20 +130,6 @@ func _gen_mssql() (err error) {
log.Print("Building the generated statements") log.Print("Building the generated statements")
} }
log.Print("Preparing getReply statement.")
stmts.getReply, err = db.Prepare("SELECT [tid],[content],[createdBy],[createdAt],[lastEdit],[lastEditBy],[ipaddress],[likeCount] FROM [replies] WHERE [rid] = ?1")
if err != nil {
log.Print("Bad Query: ","SELECT [tid],[content],[createdBy],[createdAt],[lastEdit],[lastEditBy],[ipaddress],[likeCount] FROM [replies] WHERE [rid] = ?1")
return err
}
log.Print("Preparing getUserReply statement.")
stmts.getUserReply, err = db.Prepare("SELECT [uid],[content],[createdBy],[createdAt],[lastEdit],[lastEditBy],[ipaddress] FROM [users_replies] WHERE [rid] = ?1")
if err != nil {
log.Print("Bad Query: ","SELECT [uid],[content],[createdBy],[createdAt],[lastEdit],[lastEditBy],[ipaddress] FROM [users_replies] WHERE [rid] = ?1")
return err
}
log.Print("Preparing getPassword statement.") log.Print("Preparing getPassword statement.")
stmts.getPassword, err = db.Prepare("SELECT [password],[salt] FROM [users] WHERE [uid] = ?1") stmts.getPassword, err = db.Prepare("SELECT [password],[salt] FROM [users] WHERE [uid] = ?1")
if err != nil { if err != nil {
@ -189,27 +165,6 @@ func _gen_mssql() (err error) {
return err return err
} }
log.Print("Preparing getGroups statement.")
stmts.getGroups, err = db.Prepare("SELECT [gid],[name],[permissions],[plugin_perms],[is_mod],[is_admin],[is_banned],[tag] FROM [users_groups]")
if err != nil {
log.Print("Bad Query: ","SELECT [gid],[name],[permissions],[plugin_perms],[is_mod],[is_admin],[is_banned],[tag] FROM [users_groups]")
return err
}
log.Print("Preparing getForums statement.")
stmts.getForums, err = db.Prepare("SELECT [fid],[name],[desc],[active],[preset],[parentID],[parentType],[topicCount],[lastTopicID],[lastReplyerID] FROM [forums] ORDER BY fid ASC")
if err != nil {
log.Print("Bad Query: ","SELECT [fid],[name],[desc],[active],[preset],[parentID],[parentType],[topicCount],[lastTopicID],[lastReplyerID] FROM [forums] ORDER BY fid ASC")
return err
}
log.Print("Preparing getForumsPermissions statement.")
stmts.getForumsPermissions, err = db.Prepare("SELECT [gid],[fid],[permissions] FROM [forums_permissions] ORDER BY gid ASC,fid ASC")
if err != nil {
log.Print("Bad Query: ","SELECT [gid],[fid],[permissions] FROM [forums_permissions] ORDER BY gid ASC,fid ASC")
return err
}
log.Print("Preparing getPlugins statement.") log.Print("Preparing getPlugins statement.")
stmts.getPlugins, err = db.Prepare("SELECT [uname],[active],[installed] FROM [plugins]") stmts.getPlugins, err = db.Prepare("SELECT [uname],[active],[installed] FROM [plugins]")
if err != nil { if err != nil {
@ -448,13 +403,6 @@ func _gen_mssql() (err error) {
return err return err
} }
log.Print("Preparing createReply statement.")
stmts.createReply, err = db.Prepare("INSERT INTO [replies] ([tid],[content],[parsed_content],[createdAt],[lastUpdated],[ipaddress],[words],[createdBy]) VALUES (?,?,?,GETUTCDATE(),GETUTCDATE(),?,?,?)")
if err != nil {
log.Print("Bad Query: ","INSERT INTO [replies] ([tid],[content],[parsed_content],[createdAt],[lastUpdated],[ipaddress],[words],[createdBy]) VALUES (?,?,?,GETUTCDATE(),GETUTCDATE(),?,?,?)")
return err
}
log.Print("Preparing createActionReply statement.") log.Print("Preparing createActionReply statement.")
stmts.createActionReply, err = db.Prepare("INSERT INTO [replies] ([tid],[actionType],[ipaddress],[createdBy],[createdAt],[lastUpdated],[content],[parsed_content]) VALUES (?,?,?,?,GETUTCDATE(),GETUTCDATE(),'','')") stmts.createActionReply, err = db.Prepare("INSERT INTO [replies] ([tid],[actionType],[ipaddress],[createdBy],[createdAt],[lastUpdated],[content],[parsed_content]) VALUES (?,?,?,?,GETUTCDATE(),GETUTCDATE(),'','')")
if err != nil { if err != nil {
@ -504,13 +452,6 @@ func _gen_mssql() (err error) {
return err return err
} }
log.Print("Preparing createForum statement.")
stmts.createForum, err = db.Prepare("INSERT INTO [forums] ([name],[desc],[active],[preset]) VALUES (?,?,?,?)")
if err != nil {
log.Print("Bad Query: ","INSERT INTO [forums] ([name],[desc],[active],[preset]) VALUES (?,?,?,?)")
return err
}
log.Print("Preparing addForumPermsToForum statement.") log.Print("Preparing addForumPermsToForum statement.")
stmts.addForumPermsToForum, err = db.Prepare("INSERT INTO [forums_permissions] ([gid],[fid],[preset],[permissions]) VALUES (?,?,?,?)") stmts.addForumPermsToForum, err = db.Prepare("INSERT INTO [forums_permissions] ([gid],[fid],[preset],[permissions]) VALUES (?,?,?,?)")
if err != nil { if err != nil {
@ -574,27 +515,6 @@ func _gen_mssql() (err error) {
return err return err
} }
log.Print("Preparing addTopicsToForum statement.")
stmts.addTopicsToForum, err = db.Prepare("UPDATE [forums] SET [topicCount] = [topicCount] + ? WHERE [fid] = ?")
if err != nil {
log.Print("Bad Query: ","UPDATE [forums] SET [topicCount] = [topicCount] + ? WHERE [fid] = ?")
return err
}
log.Print("Preparing removeTopicsFromForum statement.")
stmts.removeTopicsFromForum, err = db.Prepare("UPDATE [forums] SET [topicCount] = [topicCount] - ? WHERE [fid] = ?")
if err != nil {
log.Print("Bad Query: ","UPDATE [forums] SET [topicCount] = [topicCount] - ? WHERE [fid] = ?")
return err
}
log.Print("Preparing updateForumCache statement.")
stmts.updateForumCache, err = db.Prepare("UPDATE [forums] SET [lastTopicID] = ?,[lastReplyerID] = ? WHERE [fid] = ?")
if err != nil {
log.Print("Bad Query: ","UPDATE [forums] SET [lastTopicID] = ?,[lastReplyerID] = ? WHERE [fid] = ?")
return err
}
log.Print("Preparing addLikesToTopic statement.") log.Print("Preparing addLikesToTopic statement.")
stmts.addLikesToTopic, err = db.Prepare("UPDATE [topics] SET [likeCount] = [likeCount] + ? WHERE [tid] = ?") stmts.addLikesToTopic, err = db.Prepare("UPDATE [topics] SET [likeCount] = [likeCount] + ? WHERE [tid] = ?")
if err != nil { if err != nil {

View File

@ -10,16 +10,11 @@ import "database/sql"
// nolint // nolint
type Stmts struct { type Stmts struct {
getReply *sql.Stmt
getUserReply *sql.Stmt
getPassword *sql.Stmt getPassword *sql.Stmt
getSettings *sql.Stmt getSettings *sql.Stmt
getSetting *sql.Stmt getSetting *sql.Stmt
getFullSetting *sql.Stmt getFullSetting *sql.Stmt
getFullSettings *sql.Stmt getFullSettings *sql.Stmt
getGroups *sql.Stmt
getForums *sql.Stmt
getForumsPermissions *sql.Stmt
getPlugins *sql.Stmt getPlugins *sql.Stmt
getThemes *sql.Stmt getThemes *sql.Stmt
getWidgets *sql.Stmt getWidgets *sql.Stmt
@ -54,7 +49,6 @@ type Stmts struct {
getWatchers *sql.Stmt getWatchers *sql.Stmt
createTopic *sql.Stmt createTopic *sql.Stmt
createReport *sql.Stmt createReport *sql.Stmt
createReply *sql.Stmt
createActionReply *sql.Stmt createActionReply *sql.Stmt
createLike *sql.Stmt createLike *sql.Stmt
addActivity *sql.Stmt addActivity *sql.Stmt
@ -62,7 +56,6 @@ type Stmts struct {
addEmail *sql.Stmt addEmail *sql.Stmt
createProfileReply *sql.Stmt createProfileReply *sql.Stmt
addSubscription *sql.Stmt addSubscription *sql.Stmt
createForum *sql.Stmt
addForumPermsToForum *sql.Stmt addForumPermsToForum *sql.Stmt
addPlugin *sql.Stmt addPlugin *sql.Stmt
addTheme *sql.Stmt addTheme *sql.Stmt
@ -72,9 +65,6 @@ type Stmts struct {
createWordFilter *sql.Stmt createWordFilter *sql.Stmt
addRepliesToTopic *sql.Stmt addRepliesToTopic *sql.Stmt
removeRepliesFromTopic *sql.Stmt removeRepliesFromTopic *sql.Stmt
addTopicsToForum *sql.Stmt
removeTopicsFromForum *sql.Stmt
updateForumCache *sql.Stmt
addLikesToTopic *sql.Stmt addLikesToTopic *sql.Stmt
addLikesToReply *sql.Stmt addLikesToReply *sql.Stmt
editTopic *sql.Stmt editTopic *sql.Stmt
@ -142,18 +132,6 @@ func _gen_mysql() (err error) {
log.Print("Building the generated statements") log.Print("Building the generated statements")
} }
log.Print("Preparing getReply statement.")
stmts.getReply, err = db.Prepare("SELECT `tid`,`content`,`createdBy`,`createdAt`,`lastEdit`,`lastEditBy`,`ipaddress`,`likeCount` FROM `replies` WHERE `rid` = ?")
if err != nil {
return err
}
log.Print("Preparing getUserReply statement.")
stmts.getUserReply, err = db.Prepare("SELECT `uid`,`content`,`createdBy`,`createdAt`,`lastEdit`,`lastEditBy`,`ipaddress` FROM `users_replies` WHERE `rid` = ?")
if err != nil {
return err
}
log.Print("Preparing getPassword statement.") log.Print("Preparing getPassword statement.")
stmts.getPassword, err = db.Prepare("SELECT `password`,`salt` FROM `users` WHERE `uid` = ?") stmts.getPassword, err = db.Prepare("SELECT `password`,`salt` FROM `users` WHERE `uid` = ?")
if err != nil { if err != nil {
@ -184,24 +162,6 @@ func _gen_mysql() (err error) {
return err return err
} }
log.Print("Preparing getGroups statement.")
stmts.getGroups, err = db.Prepare("SELECT `gid`,`name`,`permissions`,`plugin_perms`,`is_mod`,`is_admin`,`is_banned`,`tag` FROM `users_groups`")
if err != nil {
return err
}
log.Print("Preparing getForums statement.")
stmts.getForums, err = db.Prepare("SELECT `fid`,`name`,`desc`,`active`,`preset`,`parentID`,`parentType`,`topicCount`,`lastTopicID`,`lastReplyerID` FROM `forums` ORDER BY fid ASC")
if err != nil {
return err
}
log.Print("Preparing getForumsPermissions statement.")
stmts.getForumsPermissions, err = db.Prepare("SELECT `gid`,`fid`,`permissions` FROM `forums_permissions` ORDER BY gid ASC,fid ASC")
if err != nil {
return err
}
log.Print("Preparing getPlugins statement.") log.Print("Preparing getPlugins statement.")
stmts.getPlugins, err = db.Prepare("SELECT `uname`,`active`,`installed` FROM `plugins`") stmts.getPlugins, err = db.Prepare("SELECT `uname`,`active`,`installed` FROM `plugins`")
if err != nil { if err != nil {
@ -406,12 +366,6 @@ func _gen_mysql() (err error) {
return err return err
} }
log.Print("Preparing createReply statement.")
stmts.createReply, err = db.Prepare("INSERT INTO `replies`(`tid`,`content`,`parsed_content`,`createdAt`,`lastUpdated`,`ipaddress`,`words`,`createdBy`) VALUES (?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),?,?,?)")
if err != nil {
return err
}
log.Print("Preparing createActionReply statement.") log.Print("Preparing createActionReply statement.")
stmts.createActionReply, err = db.Prepare("INSERT INTO `replies`(`tid`,`actionType`,`ipaddress`,`createdBy`,`createdAt`,`lastUpdated`,`content`,`parsed_content`) VALUES (?,?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),'','')") stmts.createActionReply, err = db.Prepare("INSERT INTO `replies`(`tid`,`actionType`,`ipaddress`,`createdBy`,`createdAt`,`lastUpdated`,`content`,`parsed_content`) VALUES (?,?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),'','')")
if err != nil { if err != nil {
@ -454,12 +408,6 @@ func _gen_mysql() (err error) {
return err return err
} }
log.Print("Preparing createForum statement.")
stmts.createForum, err = db.Prepare("INSERT INTO `forums`(`name`,`desc`,`active`,`preset`) VALUES (?,?,?,?)")
if err != nil {
return err
}
log.Print("Preparing addForumPermsToForum statement.") log.Print("Preparing addForumPermsToForum statement.")
stmts.addForumPermsToForum, err = db.Prepare("INSERT INTO `forums_permissions`(`gid`,`fid`,`preset`,`permissions`) VALUES (?,?,?,?)") stmts.addForumPermsToForum, err = db.Prepare("INSERT INTO `forums_permissions`(`gid`,`fid`,`preset`,`permissions`) VALUES (?,?,?,?)")
if err != nil { if err != nil {
@ -514,24 +462,6 @@ func _gen_mysql() (err error) {
return err return err
} }
log.Print("Preparing addTopicsToForum statement.")
stmts.addTopicsToForum, err = db.Prepare("UPDATE `forums` SET `topicCount` = `topicCount` + ? WHERE `fid` = ?")
if err != nil {
return err
}
log.Print("Preparing removeTopicsFromForum statement.")
stmts.removeTopicsFromForum, err = db.Prepare("UPDATE `forums` SET `topicCount` = `topicCount` - ? WHERE `fid` = ?")
if err != nil {
return err
}
log.Print("Preparing updateForumCache statement.")
stmts.updateForumCache, err = db.Prepare("UPDATE `forums` SET `lastTopicID` = ?,`lastReplyerID` = ? WHERE `fid` = ?")
if err != nil {
return err
}
log.Print("Preparing addLikesToTopic statement.") log.Print("Preparing addLikesToTopic statement.")
stmts.addLikesToTopic, err = db.Prepare("UPDATE `topics` SET `likeCount` = `likeCount` + ? WHERE `tid` = ?") stmts.addLikesToTopic, err = db.Prepare("UPDATE `topics` SET `likeCount` = `likeCount` + ? WHERE `tid` = ?")
if err != nil { if err != nil {

View File

@ -10,9 +10,6 @@ import "database/sql"
type Stmts struct { type Stmts struct {
addRepliesToTopic *sql.Stmt addRepliesToTopic *sql.Stmt
removeRepliesFromTopic *sql.Stmt removeRepliesFromTopic *sql.Stmt
addTopicsToForum *sql.Stmt
removeTopicsFromForum *sql.Stmt
updateForumCache *sql.Stmt
addLikesToTopic *sql.Stmt addLikesToTopic *sql.Stmt
addLikesToReply *sql.Stmt addLikesToReply *sql.Stmt
editTopic *sql.Stmt editTopic *sql.Stmt
@ -82,24 +79,6 @@ func _gen_pgsql() (err error) {
return err return err
} }
log.Print("Preparing addTopicsToForum statement.")
stmts.addTopicsToForum, err = db.Prepare("UPDATE `forums` SET `topicCount` = `topicCount` + ? WHERE `fid` = ?")
if err != nil {
return err
}
log.Print("Preparing removeTopicsFromForum statement.")
stmts.removeTopicsFromForum, err = db.Prepare("UPDATE `forums` SET `topicCount` = `topicCount` - ? WHERE `fid` = ?")
if err != nil {
return err
}
log.Print("Preparing updateForumCache statement.")
stmts.updateForumCache, err = db.Prepare("UPDATE `forums` SET `lastTopicID` = ?,`lastReplyerID` = ? WHERE `fid` = ?")
if err != nil {
return err
}
log.Print("Preparing addLikesToTopic statement.") log.Print("Preparing addLikesToTopic statement.")
stmts.addLikesToTopic, err = db.Prepare("UPDATE `topics` SET `likeCount` = `likeCount` + ? WHERE `tid` = ?") stmts.addLikesToTopic, err = db.Prepare("UPDATE `topics` SET `likeCount` = `likeCount` + ? WHERE `tid` = ?")
if err != nil { if err != nil {

View File

@ -79,8 +79,14 @@ func gloinit() (err error) {
return err return err
} }
rstore = NewSQLReplyStore() rstore, err = NewSQLReplyStore()
prstore = NewSQLProfileReplyStore() if err != nil {
return err
}
prstore, err = NewSQLProfileReplyStore()
if err != nil {
return err
}
dbProd = db dbProd = db
//db_test, err = sql.Open("testdb","") //db_test, err = sql.Open("testdb","")
@ -538,7 +544,7 @@ func BenchmarkQueryPreparedTopicParallel(b *testing.B) {
b.RunParallel(func(pb *testing.PB) { b.RunParallel(func(pb *testing.PB) {
var tu TopicUser var tu TopicUser
for pb.Next() { for pb.Next() {
err := getTopicUserStmt.QueryRow(1).Scan(&tu.Title, &tu.Content, &tu.CreatedBy, &tu.CreatedAt, &tu.IsClosed, &tu.Sticky, &tu.ParentID, &tu.IPAddress, &tu.PostCount, &tu.LikeCount, &tu.CreatedByName, &tu.Avatar, &tu.Group, &tu.URLPrefix, &tu.URLName, &tu.Level) err := stmts.getTopicUser.QueryRow(1).Scan(&tu.Title, &tu.Content, &tu.CreatedBy, &tu.CreatedAt, &tu.IsClosed, &tu.Sticky, &tu.ParentID, &tu.IPAddress, &tu.PostCount, &tu.LikeCount, &tu.CreatedByName, &tu.Avatar, &tu.Group, &tu.URLPrefix, &tu.URLName, &tu.Level)
if err == ErrNoRows { if err == ErrNoRows {
b.Fatal("No rows found!") b.Fatal("No rows found!")
return return

View File

@ -36,12 +36,17 @@ type GroupCache interface {
type MemoryGroupStore struct { type MemoryGroupStore struct {
groups map[int]*Group // TODO: Use a sync.Map instead of a map? groups map[int]*Group // TODO: Use a sync.Map instead of a map?
groupCount int groupCount int
getAll *sql.Stmt
get *sql.Stmt get *sql.Stmt
sync.RWMutex sync.RWMutex
} }
func NewMemoryGroupStore() (*MemoryGroupStore, error) { func NewMemoryGroupStore() (*MemoryGroupStore, error) {
getAllStmt, err := qgen.Builder.SimpleSelect("users_groups", "gid, name, permissions, plugin_perms, is_mod, is_admin, is_banned, tag", "", "", "")
if err != nil {
return nil, err
}
getGroupStmt, err := qgen.Builder.SimpleSelect("users_groups", "name, permissions, plugin_perms, is_mod, is_admin, is_banned, tag", "gid = ?", "", "") getGroupStmt, err := qgen.Builder.SimpleSelect("users_groups", "name, permissions, plugin_perms, is_mod, is_admin, is_banned, tag", "gid = ?", "", "")
if err != nil { if err != nil {
return nil, err return nil, err
@ -50,6 +55,7 @@ func NewMemoryGroupStore() (*MemoryGroupStore, error) {
return &MemoryGroupStore{ return &MemoryGroupStore{
groups: make(map[int]*Group), groups: make(map[int]*Group),
groupCount: 0, groupCount: 0,
getAll: getAllStmt,
get: getGroupStmt, get: getGroupStmt,
}, nil }, nil
} }
@ -60,7 +66,7 @@ func (mgs *MemoryGroupStore) LoadGroups() error {
defer mgs.Unlock() defer mgs.Unlock()
mgs.groups[0] = &Group{ID: 0, Name: "Unknown"} mgs.groups[0] = &Group{ID: 0, Name: "Unknown"}
rows, err := stmts.getGroups.Query() rows, err := mgs.getAll.Query()
if err != nil { if err != nil {
return err return err
} }

11
main.go
View File

@ -82,6 +82,7 @@ type Globs struct {
stmts *Stmts stmts *Stmts
} }
// TODO: Split this function up
func main() { func main() {
// TODO: Recover from panics // TODO: Recover from panics
/*defer func() { /*defer func() {
@ -130,8 +131,14 @@ func main() {
log.Fatal(err) log.Fatal(err)
} }
rstore = NewSQLReplyStore() rstore, err = NewSQLReplyStore()
prstore = NewSQLProfileReplyStore() if err != nil {
log.Fatal(err)
}
prstore, err = NewSQLProfileReplyStore()
if err != nil {
log.Fatal(err)
}
initTemplates() initTemplates()

View File

@ -680,11 +680,7 @@ func routeReportSubmit(w http.ResponseWriter, r *http.Request, user User, sitemI
return InternalError(err, w, r) return InternalError(err, w, r)
} }
_, err = stmts.addTopicsToForum.Exec(1, fid) err = fstore.AddTopic(int(lastID), user.ID, fid)
if err != nil {
return InternalError(err, w, r)
}
err = fstore.UpdateLastTopic(int(lastID), user.ID, fid)
if err != nil && err != ErrNoRows { if err != nil && err != ErrNoRows {
return InternalError(err, w, r) return InternalError(err, w, r)
} }

View File

@ -45,7 +45,10 @@ func deactivateMarkdown() {
// An adapter for the parser, so that the parser can call itself recursively. // An adapter for the parser, so that the parser can call itself recursively.
// This is less for the simple Markdown elements like bold and italics and more for the really complicated ones I plan on adding at some point. // This is less for the simple Markdown elements like bold and italics and more for the really complicated ones I plan on adding at some point.
func markdownParse(msg string) string { func markdownParse(msg string) string {
msg = strings.TrimSuffix(_markdownParse(msg+" ", 0), " ") msg = _markdownParse(msg+" ", 0)
if msg[len(msg)-1] == ' ' {
msg = msg[:len(msg)-1]
}
log.Print("final msg: ", msg) log.Print("final msg: ", msg)
return msg return msg
} }
@ -292,9 +295,13 @@ func _markdownParse(msg string, n int) string {
if len(outbytes) == 0 { if len(outbytes) == 0 {
return msg return msg
//return msg[:len(msg)-1]
} else if lastElement < (len(msg) - 1) { } else if lastElement < (len(msg) - 1) {
return string(outbytes) + msg[lastElement:] msg = string(outbytes) + msg[lastElement:]
return msg
//return msg[:len(msg)-1]
} }
//return string(outbytes[:len(outbytes)-1])
return string(outbytes) return string(outbytes)
} }

View File

@ -23,6 +23,12 @@ func TestBBCodeRender(t *testing.T) {
var res string var res string
var msgList []MEPair var msgList []MEPair
msgList = addMEPair(msgList, "", "")
msgList = addMEPair(msgList, " ", " ")
msgList = addMEPair(msgList, " ", " ")
msgList = addMEPair(msgList, " ", " ")
msgList = addMEPair(msgList, "[b]", "<b></b>")
msgList = addMEPair(msgList, "[b][/b]", "<b></b>")
msgList = addMEPair(msgList, "hi", "hi") msgList = addMEPair(msgList, "hi", "hi")
msgList = addMEPair(msgList, "😀", "😀") msgList = addMEPair(msgList, "😀", "😀")
msgList = addMEPair(msgList, "[b]😀[/b]", "<b>😀</b>") msgList = addMEPair(msgList, "[b]😀[/b]", "<b>😀</b>")
@ -57,7 +63,7 @@ func TestBBCodeRender(t *testing.T) {
if res != item.Expects { if res != item.Expects {
t.Error("Testing string '" + item.Msg + "'") t.Error("Testing string '" + item.Msg + "'")
t.Error("Bad output:", "'"+res+"'") t.Error("Bad output:", "'"+res+"'")
t.Error("Expected:", item.Expects) t.Error("Expected:", "'"+item.Expects+"'")
} }
} }
@ -70,7 +76,7 @@ func TestBBCodeRender(t *testing.T) {
res = bbcodeFullParse(msg) res = bbcodeFullParse(msg)
if res != expects { if res != expects {
t.Error("Bad output:", "'"+res+"'") t.Error("Bad output:", "'"+res+"'")
t.Error("Expected:", expects) t.Error("Expected:", "'"+expects+"'")
} }
msg = "[rand]-1[/rand]" msg = "[rand]-1[/rand]"
@ -79,7 +85,7 @@ func TestBBCodeRender(t *testing.T) {
res = bbcodeFullParse(msg) res = bbcodeFullParse(msg)
if res != expects { if res != expects {
t.Error("Bad output:", "'"+res+"'") t.Error("Bad output:", "'"+res+"'")
t.Error("Expected:", expects) t.Error("Expected:", "'"+expects+"'")
} }
msg = "[rand]-01[/rand]" msg = "[rand]-01[/rand]"
@ -88,7 +94,7 @@ func TestBBCodeRender(t *testing.T) {
res = bbcodeFullParse(msg) res = bbcodeFullParse(msg)
if res != expects { if res != expects {
t.Error("Bad output:", "'"+res+"'") t.Error("Bad output:", "'"+res+"'")
t.Error("Expected:", expects) t.Error("Expected:", "'"+expects+"'")
} }
msg = "[rand]NaN[/rand]" msg = "[rand]NaN[/rand]"
@ -97,7 +103,7 @@ func TestBBCodeRender(t *testing.T) {
res = bbcodeFullParse(msg) res = bbcodeFullParse(msg)
if res != expects { if res != expects {
t.Error("Bad output:", "'"+res+"'") t.Error("Bad output:", "'"+res+"'")
t.Error("Expected:", expects) t.Error("Expected:", "'"+expects+"'")
} }
msg = "[rand]Inf[/rand]" msg = "[rand]Inf[/rand]"
@ -106,7 +112,7 @@ func TestBBCodeRender(t *testing.T) {
res = bbcodeFullParse(msg) res = bbcodeFullParse(msg)
if res != expects { if res != expects {
t.Error("Bad output:", "'"+res+"'") t.Error("Bad output:", "'"+res+"'")
t.Error("Expected:", expects) t.Error("Expected:", "'"+expects+"'")
} }
msg = "[rand]+[/rand]" msg = "[rand]+[/rand]"
@ -115,7 +121,7 @@ func TestBBCodeRender(t *testing.T) {
res = bbcodeFullParse(msg) res = bbcodeFullParse(msg)
if res != expects { if res != expects {
t.Error("Bad output:", "'"+res+"'") t.Error("Bad output:", "'"+res+"'")
t.Error("Expected:", expects) t.Error("Expected:", "'"+expects+"'")
} }
msg = "[rand]1+1[/rand]" msg = "[rand]1+1[/rand]"
@ -124,7 +130,7 @@ func TestBBCodeRender(t *testing.T) {
res = bbcodeFullParse(msg) res = bbcodeFullParse(msg)
if res != expects { if res != expects {
t.Error("Bad output:", "'"+res+"'") t.Error("Bad output:", "'"+res+"'")
t.Error("Expected:", expects) t.Error("Expected:", "'"+expects+"'")
} }
var conv int var conv int
@ -202,6 +208,15 @@ func TestMarkdownRender(t *testing.T) {
var res string var res string
var msgList []MEPair var msgList []MEPair
msgList = addMEPair(msgList, "", "")
msgList = addMEPair(msgList, " ", " ")
msgList = addMEPair(msgList, " ", " ")
msgList = addMEPair(msgList, " ", " ")
msgList = addMEPair(msgList, "\t", "\t")
msgList = addMEPair(msgList, "\n", "\n")
msgList = addMEPair(msgList, "*", "*")
msgList = addMEPair(msgList, "**", "<i></i>")
msgList = addMEPair(msgList, "h", "h")
msgList = addMEPair(msgList, "hi", "hi") msgList = addMEPair(msgList, "hi", "hi")
msgList = addMEPair(msgList, "**h**", "<b>h</b>") msgList = addMEPair(msgList, "**h**", "<b>h</b>")
msgList = addMEPair(msgList, "**hi**", "<b>hi</b>") msgList = addMEPair(msgList, "**hi**", "<b>hi</b>")
@ -260,17 +275,17 @@ func TestMarkdownRender(t *testing.T) {
t.Error("Testing string '" + item.Msg + "'") t.Error("Testing string '" + item.Msg + "'")
t.Error("Bad output:", "'"+res+"'") t.Error("Bad output:", "'"+res+"'")
//t.Error("Ouput in bytes:", []byte(res)) //t.Error("Ouput in bytes:", []byte(res))
t.Error("Expected:", item.Expects) t.Error("Expected:", "'"+item.Expects+"'")
} }
} }
for _, item := range msgList { /*for _, item := range msgList {
res = markdownParse("\n" + item.Msg) res = markdownParse("\n" + item.Msg)
if res != "\n"+item.Expects { if res != "\n"+item.Expects {
t.Error("Testing string '\n" + item.Msg + "'") t.Error("Testing string '\n" + item.Msg + "'")
t.Error("Bad output:", "'"+res+"'") t.Error("Bad output:", "'"+res+"'")
//t.Error("Ouput in bytes:", []byte(res)) //t.Error("Ouput in bytes:", []byte(res))
t.Error("Expected:", "\n"+item.Expects) t.Error("Expected:", "'\n"+item.Expects+"'")
} }
} }
@ -280,9 +295,9 @@ func TestMarkdownRender(t *testing.T) {
t.Error("Testing string '\t" + item.Msg + "'") t.Error("Testing string '\t" + item.Msg + "'")
t.Error("Bad output:", "'"+res+"'") t.Error("Bad output:", "'"+res+"'")
//t.Error("Ouput in bytes:", []byte(res)) //t.Error("Ouput in bytes:", []byte(res))
t.Error("Expected:", "\t"+item.Expects) t.Error("Expected:", "'\t"+item.Expects+"'")
} }
} }*/
for _, item := range msgList { for _, item := range msgList {
res = markdownParse("d" + item.Msg) res = markdownParse("d" + item.Msg)
@ -290,7 +305,7 @@ func TestMarkdownRender(t *testing.T) {
t.Error("Testing string 'd" + item.Msg + "'") t.Error("Testing string 'd" + item.Msg + "'")
t.Error("Bad output:", "'"+res+"'") t.Error("Bad output:", "'"+res+"'")
//t.Error("Ouput in bytes:", []byte(res)) //t.Error("Ouput in bytes:", []byte(res))
t.Error("Expected:", "d"+item.Expects) t.Error("Expected:", "'d"+item.Expects+"'")
} }
} }

View File

@ -0,0 +1,248 @@
/* WIP: A version of the builder which accumulates errors, we'll see if we can't unify the implementations at some point */
package qgen
import "database/sql"
type accBuilder struct {
conn *sql.DB
adapter DB_Adapter
firstErr error
}
func (build *accBuilder) SetConn(conn *sql.DB) {
build.conn = conn
}
func (build *accBuilder) SetAdapter(name string) error {
adap, err := GetAdapter(name)
if err != nil {
return err
}
build.adapter = adap
return nil
}
func (build *accBuilder) GetAdapter() DB_Adapter {
return build.adapter
}
func (build *accBuilder) FirstError() error {
return build.firstErr
}
func (build *accBuilder) recordError(err error) {
if err == nil {
return
}
if build.firstErr != nil {
build.firstErr = err
}
}
func (build *accBuilder) prepare(res string, err error) *sql.Stmt {
if err != nil {
build.recordError(err)
return nil
}
stmt, err := build.conn.Prepare(res)
build.recordError(err)
return stmt
}
func (build *accBuilder) Tx(handler func(*TransactionBuilder) error) {
tx, err := build.conn.Begin()
if err != nil {
build.recordError(err)
return
}
err = handler(&TransactionBuilder{tx, build.adapter, nil})
if err != nil {
tx.Rollback()
build.recordError(err)
return
}
build.recordError(tx.Commit())
}
func (build *accBuilder) SimpleSelect(table string, columns string, where string, orderby string, limit string) *sql.Stmt {
return build.prepare(build.adapter.SimpleSelect("_builder", table, columns, where, orderby, limit))
}
func (build *accBuilder) SimpleCount(table string, where string, limit string) *sql.Stmt {
return build.prepare(build.adapter.SimpleCount("_builder", table, where, limit))
}
func (build *accBuilder) SimpleLeftJoin(table1 string, table2 string, columns string, joiners string, where string, orderby string, limit string) *sql.Stmt {
return build.prepare(build.adapter.SimpleLeftJoin("_builder", table1, table2, columns, joiners, where, orderby, limit))
}
func (build *accBuilder) SimpleInnerJoin(table1 string, table2 string, columns string, joiners string, where string, orderby string, limit string) *sql.Stmt {
return build.prepare(build.adapter.SimpleInnerJoin("_builder", table1, table2, columns, joiners, where, orderby, limit))
}
func (build *accBuilder) CreateTable(table string, charset string, collation string, columns []DB_Table_Column, keys []DB_Table_Key) *sql.Stmt {
return build.prepare(build.adapter.CreateTable("_builder", table, charset, collation, columns, keys))
}
func (build *accBuilder) SimpleInsert(table string, columns string, fields string) *sql.Stmt {
return build.prepare(build.adapter.SimpleInsert("_builder", table, columns, fields))
}
func (build *accBuilder) SimpleInsertSelect(ins DB_Insert, sel DB_Select) *sql.Stmt {
return build.prepare(build.adapter.SimpleInsertSelect("_builder", ins, sel))
}
func (build *accBuilder) SimpleInsertLeftJoin(ins DB_Insert, sel DB_Join) *sql.Stmt {
return build.prepare(build.adapter.SimpleInsertLeftJoin("_builder", ins, sel))
}
func (build *accBuilder) SimpleInsertInnerJoin(ins DB_Insert, sel DB_Join) *sql.Stmt {
return build.prepare(build.adapter.SimpleInsertInnerJoin("_builder", ins, sel))
}
func (build *accBuilder) SimpleUpdate(table string, set string, where string) *sql.Stmt {
return build.prepare(build.adapter.SimpleUpdate("_builder", table, set, where))
}
func (build *accBuilder) SimpleDelete(table string, where string) *sql.Stmt {
return build.prepare(build.adapter.SimpleDelete("_builder", table, where))
}
// I don't know why you need this, but here it is x.x
func (build *accBuilder) Purge(table string) *sql.Stmt {
return build.prepare(build.adapter.Purge("_builder", table))
}
// These ones support transactions
func (build *accBuilder) SimpleSelectTx(tx *sql.Tx, table string, columns string, where string, orderby string, limit string) (stmt *sql.Stmt) {
res, err := build.adapter.SimpleSelect("_builder", table, columns, where, orderby, limit)
if err != nil {
build.recordError(err)
return nil
}
stmt, err = tx.Prepare(res)
build.recordError(err)
return stmt
}
func (build *accBuilder) SimpleCountTx(tx *sql.Tx, table string, where string, limit string) (stmt *sql.Stmt) {
res, err := build.adapter.SimpleCount("_builder", table, where, limit)
if err != nil {
build.recordError(err)
return nil
}
stmt, err = tx.Prepare(res)
build.recordError(err)
return stmt
}
func (build *accBuilder) SimpleLeftJoinTx(tx *sql.Tx, table1 string, table2 string, columns string, joiners string, where string, orderby string, limit string) (stmt *sql.Stmt) {
res, err := build.adapter.SimpleLeftJoin("_builder", table1, table2, columns, joiners, where, orderby, limit)
if err != nil {
build.recordError(err)
return nil
}
stmt, err = tx.Prepare(res)
build.recordError(err)
return stmt
}
func (build *accBuilder) SimpleInnerJoinTx(tx *sql.Tx, table1 string, table2 string, columns string, joiners string, where string, orderby string, limit string) (stmt *sql.Stmt) {
res, err := build.adapter.SimpleInnerJoin("_builder", table1, table2, columns, joiners, where, orderby, limit)
if err != nil {
build.recordError(err)
return nil
}
stmt, err = tx.Prepare(res)
build.recordError(err)
return stmt
}
func (build *accBuilder) CreateTableTx(tx *sql.Tx, table string, charset string, collation string, columns []DB_Table_Column, keys []DB_Table_Key) (stmt *sql.Stmt) {
res, err := build.adapter.CreateTable("_builder", table, charset, collation, columns, keys)
if err != nil {
build.recordError(err)
return nil
}
stmt, err = tx.Prepare(res)
build.recordError(err)
return stmt
}
func (build *accBuilder) SimpleInsertTx(tx *sql.Tx, table string, columns string, fields string) (stmt *sql.Stmt) {
res, err := build.adapter.SimpleInsert("_builder", table, columns, fields)
if err != nil {
build.recordError(err)
return nil
}
stmt, err = tx.Prepare(res)
build.recordError(err)
return stmt
}
func (build *accBuilder) SimpleInsertSelectTx(tx *sql.Tx, ins DB_Insert, sel DB_Select) (stmt *sql.Stmt) {
res, err := build.adapter.SimpleInsertSelect("_builder", ins, sel)
if err != nil {
build.recordError(err)
return nil
}
stmt, err = tx.Prepare(res)
build.recordError(err)
return stmt
}
func (build *accBuilder) SimpleInsertLeftJoinTx(tx *sql.Tx, ins DB_Insert, sel DB_Join) (stmt *sql.Stmt) {
res, err := build.adapter.SimpleInsertLeftJoin("_builder", ins, sel)
if err != nil {
build.recordError(err)
return nil
}
stmt, err = tx.Prepare(res)
build.recordError(err)
return stmt
}
func (build *accBuilder) SimpleInsertInnerJoinTx(tx *sql.Tx, ins DB_Insert, sel DB_Join) (stmt *sql.Stmt) {
res, err := build.adapter.SimpleInsertInnerJoin("_builder", ins, sel)
if err != nil {
build.recordError(err)
return nil
}
stmt, err = tx.Prepare(res)
build.recordError(err)
return stmt
}
func (build *accBuilder) SimpleUpdateTx(tx *sql.Tx, table string, set string, where string) (stmt *sql.Stmt) {
res, err := build.adapter.SimpleUpdate("_builder", table, set, where)
if err != nil {
build.recordError(err)
return nil
}
stmt, err = tx.Prepare(res)
build.recordError(err)
return stmt
}
func (build *accBuilder) SimpleDeleteTx(tx *sql.Tx, table string, where string) (stmt *sql.Stmt) {
res, err := build.adapter.SimpleDelete("_builder", table, where)
if err != nil {
build.recordError(err)
return nil
}
stmt, err = tx.Prepare(res)
build.recordError(err)
return stmt
}
// I don't know why you need this, but here it is x.x
func (build *accBuilder) PurgeTx(tx *sql.Tx, table string) (stmt *sql.Stmt) {
res, err := build.adapter.Purge("_builder", table)
if err != nil {
build.recordError(err)
return nil
}
stmt, err = tx.Prepare(res)
build.recordError(err)
return stmt
}

View File

@ -16,6 +16,10 @@ type builder struct {
adapter DB_Adapter adapter DB_Adapter
} }
func (build *builder) Accumulator() *accBuilder {
return &accBuilder{build.conn, build.adapter, nil}
}
func (build *builder) SetConn(conn *sql.DB) { func (build *builder) SetConn(conn *sql.DB) {
build.conn = conn build.conn = conn
} }

View File

@ -222,10 +222,6 @@ func seedTables(adapter qgen.DB_Adapter) error {
func writeSelects(adapter qgen.DB_Adapter) error { func writeSelects(adapter qgen.DB_Adapter) error {
// Looking for getTopic? Your statement is in another castle // Looking for getTopic? Your statement is in another castle
adapter.SimpleSelect("getReply", "replies", "tid, content, createdBy, createdAt, lastEdit, lastEditBy, ipaddress, likeCount", "rid = ?", "", "")
adapter.SimpleSelect("getUserReply", "users_replies", "uid, content, createdBy, createdAt, lastEdit, lastEditBy, ipaddress", "rid = ?", "", "")
adapter.SimpleSelect("getPassword", "users", "password, salt", "uid = ?", "", "") adapter.SimpleSelect("getPassword", "users", "password, salt", "uid = ?", "", "")
adapter.SimpleSelect("getSettings", "settings", "name, content, type", "", "", "") adapter.SimpleSelect("getSettings", "settings", "name, content, type", "", "", "")
@ -236,12 +232,6 @@ func writeSelects(adapter qgen.DB_Adapter) error {
adapter.SimpleSelect("getFullSettings", "settings", "name, content, type, constraints", "", "", "") adapter.SimpleSelect("getFullSettings", "settings", "name, content, type, constraints", "", "", "")
adapter.SimpleSelect("getGroups", "users_groups", "gid, name, permissions, plugin_perms, is_mod, is_admin, is_banned, tag", "", "", "")
adapter.SimpleSelect("getForums", "forums", "fid, name, desc, active, preset, parentID, parentType, topicCount, lastTopicID, lastReplyerID", "", "fid ASC", "")
adapter.SimpleSelect("getForumsPermissions", "forums_permissions", "gid, fid, permissions", "", "gid ASC, fid ASC", "")
adapter.SimpleSelect("getPlugins", "plugins", "uname, active, installed", "", "", "") adapter.SimpleSelect("getPlugins", "plugins", "uname, active, installed", "", "", "")
adapter.SimpleSelect("getThemes", "themes", "uname, default", "", "", "") adapter.SimpleSelect("getThemes", "themes", "uname, default", "", "", "")
@ -328,8 +318,6 @@ func writeInserts(adapter qgen.DB_Adapter) error {
adapter.SimpleInsert("createReport", "topics", "title, content, parsed_content, createdAt, lastReplyAt, createdBy, lastReplyBy, data, parentID, css_class", "?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),?,?,?,1,'report'") adapter.SimpleInsert("createReport", "topics", "title, content, parsed_content, createdAt, lastReplyAt, createdBy, lastReplyBy, data, parentID, css_class", "?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),?,?,?,1,'report'")
adapter.SimpleInsert("createReply", "replies", "tid, content, parsed_content, createdAt, lastUpdated, ipaddress, words, createdBy", "?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),?,?,?")
adapter.SimpleInsert("createActionReply", "replies", "tid, actionType, ipaddress, createdBy, createdAt, lastUpdated, content, parsed_content", "?,?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),'',''") adapter.SimpleInsert("createActionReply", "replies", "tid, actionType, ipaddress, createdBy, createdAt, lastUpdated, content, parsed_content", "?,?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),'',''")
adapter.SimpleInsert("createLike", "likes", "weight, targetItem, targetType, sentBy", "?,?,?,?") adapter.SimpleInsert("createLike", "likes", "weight, targetItem, targetType, sentBy", "?,?,?,?")
@ -344,8 +332,6 @@ func writeInserts(adapter qgen.DB_Adapter) error {
adapter.SimpleInsert("addSubscription", "activity_subscriptions", "user, targetID, targetType, level", "?,?,?,2") adapter.SimpleInsert("addSubscription", "activity_subscriptions", "user, targetID, targetType, level", "?,?,?,2")
adapter.SimpleInsert("createForum", "forums", "name, desc, active, preset", "?,?,?,?")
adapter.SimpleInsert("addForumPermsToForum", "forums_permissions", "gid,fid,preset,permissions", "?,?,?,?") adapter.SimpleInsert("addForumPermsToForum", "forums_permissions", "gid,fid,preset,permissions", "?,?,?,?")
adapter.SimpleInsert("addPlugin", "plugins", "uname, active, installed", "?,?,?") adapter.SimpleInsert("addPlugin", "plugins", "uname, active, installed", "?,?,?")
@ -387,12 +373,6 @@ func writeUpdates(adapter qgen.DB_Adapter) error {
adapter.SimpleUpdate("removeRepliesFromTopic", "topics", "postCount = postCount - ?", "tid = ?") adapter.SimpleUpdate("removeRepliesFromTopic", "topics", "postCount = postCount - ?", "tid = ?")
adapter.SimpleUpdate("addTopicsToForum", "forums", "topicCount = topicCount + ?", "fid = ?")
adapter.SimpleUpdate("removeTopicsFromForum", "forums", "topicCount = topicCount - ?", "fid = ?")
adapter.SimpleUpdate("updateForumCache", "forums", "lastTopicID = ?, lastReplyerID = ?", "fid = ?")
adapter.SimpleUpdate("addLikesToTopic", "topics", "likeCount = likeCount + ?", "tid = ?") adapter.SimpleUpdate("addLikesToTopic", "topics", "likeCount = likeCount + ?", "tid = ?")
adapter.SimpleUpdate("addLikesToReply", "replies", "likeCount = likeCount + ?", "rid = ?") adapter.SimpleUpdate("addLikesToReply", "replies", "likeCount = likeCount + ?", "rid = ?")

View File

@ -7,8 +7,11 @@
package main package main
import ( import (
"database/sql"
"errors" "errors"
"time" "time"
"./query_gen/lib"
) )
// ? - Should we add a reply store to centralise all the reply logic? Would this cover profile replies too or would that be separate? // ? - Should we add a reply store to centralise all the reply logic? Would this cover profile replies too or would that be separate?
@ -107,22 +110,35 @@ type ReplyStore interface {
} }
type SQLReplyStore struct { type SQLReplyStore struct {
get *sql.Stmt
create *sql.Stmt
} }
func NewSQLReplyStore() *SQLReplyStore { func NewSQLReplyStore() (*SQLReplyStore, error) {
return &SQLReplyStore{} getReplyStmt, err := qgen.Builder.SimpleSelect("replies", "tid, content, createdBy, createdAt, lastEdit, lastEditBy, ipaddress, likeCount", "rid = ?", "", "")
if err != nil {
return nil, err
}
createReplyStmt, err := qgen.Builder.SimpleInsert("replies", "tid, content, parsed_content, createdAt, lastUpdated, ipaddress, words, createdBy", "?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),?,?,?")
if err != nil {
return nil, err
}
return &SQLReplyStore{
get: getReplyStmt,
create: createReplyStmt,
}, nil
} }
func (store *SQLReplyStore) Get(id int) (*Reply, error) { func (store *SQLReplyStore) Get(id int) (*Reply, error) {
reply := Reply{ID: id} reply := Reply{ID: id}
err := stmts.getReply.QueryRow(id).Scan(&reply.ParentID, &reply.Content, &reply.CreatedBy, &reply.CreatedAt, &reply.LastEdit, &reply.LastEditBy, &reply.IPAddress, &reply.LikeCount) err := store.get.QueryRow(id).Scan(&reply.ParentID, &reply.Content, &reply.CreatedBy, &reply.CreatedAt, &reply.LastEdit, &reply.LastEditBy, &reply.IPAddress, &reply.LikeCount)
return &reply, err return &reply, err
} }
// TODO: Write a test for this // TODO: Write a test for this
func (store *SQLReplyStore) Create(tid int, content string, ipaddress string, fid int, uid int) (id int, err error) { func (store *SQLReplyStore) Create(tid int, content string, ipaddress string, fid int, uid int) (id int, err error) {
wcount := wordCount(content) wcount := wordCount(content)
res, err := stmts.createReply.Exec(tid, content, parseMessage(content, fid, "forums"), ipaddress, wcount, uid) res, err := store.create.Exec(tid, content, parseMessage(content, fid, "forums"), ipaddress, wcount, uid)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -147,15 +163,23 @@ type ProfileReplyStore interface {
} }
// TODO: Refactor this to stop using the global stmt store // TODO: Refactor this to stop using the global stmt store
// TODO: Add more methods to this like Create()
type SQLProfileReplyStore struct { type SQLProfileReplyStore struct {
get *sql.Stmt
} }
func NewSQLProfileReplyStore() *SQLProfileReplyStore { func NewSQLProfileReplyStore() (*SQLProfileReplyStore, error) {
return &SQLProfileReplyStore{} getUserReplyStmt, err := qgen.Builder.SimpleSelect("users_replies", "uid, content, createdBy, createdAt, lastEdit, lastEditBy, ipaddress", "rid = ?", "", "")
if err != nil {
return nil, err
}
return &SQLProfileReplyStore{
get: getUserReplyStmt,
}, nil
} }
func (store *SQLProfileReplyStore) Get(id int) (*Reply, error) { func (store *SQLProfileReplyStore) Get(id int) (*Reply, error) {
reply := Reply{ID: id} reply := Reply{ID: id}
err := stmts.getUserReply.QueryRow(id).Scan(&reply.ParentID, &reply.Content, &reply.CreatedBy, &reply.CreatedAt, &reply.LastEdit, &reply.LastEditBy, &reply.IPAddress) err := store.get.QueryRow(id).Scan(&reply.ParentID, &reply.Content, &reply.CreatedBy, &reply.CreatedAt, &reply.LastEdit, &reply.LastEditBy, &reply.IPAddress)
return &reply, err return &reply, err
} }

View File

@ -19,7 +19,10 @@ import (
"text/template" "text/template"
) )
var themes = make(map[string]Theme) //var themes = make(map[string]Theme)
type ThemeList map[string]Theme
var themes ThemeList = make(map[string]Theme)
var defaultThemeBox atomic.Value var defaultThemeBox atomic.Value
var changeDefaultThemeMutex sync.Mutex var changeDefaultThemeMutex sync.Mutex
@ -74,8 +77,9 @@ func init() {
defaultThemeBox.Store(fallbackTheme) defaultThemeBox.Store(fallbackTheme)
} }
// TODO: Make the initThemes and LoadThemes functions less confusing
// ? - Delete themes which no longer exist in the themes folder from the database? // ? - Delete themes which no longer exist in the themes folder from the database?
func LoadThemes() error { func LoadThemeActiveStatus() error {
changeDefaultThemeMutex.Lock() changeDefaultThemeMutex.Lock()
rows, err := stmts.getThemes.Query() rows, err := stmts.getThemes.Query()
if err != nil { if err != nil {