2017-11-12 05:25:04 +00:00
package qgen
2018-03-31 05:25:27 +00:00
import (
"database/sql"
"strconv"
)
2017-11-12 05:25:04 +00:00
type accDeleteBuilder struct {
table string
where string
build * Accumulator
}
func ( delete * accDeleteBuilder ) Where ( where string ) * accDeleteBuilder {
2018-03-31 05:25:27 +00:00
if delete . where != "" {
delete . where += " AND "
}
delete . where += where
2017-11-12 05:25:04 +00:00
return delete
}
func ( delete * accDeleteBuilder ) Prepare ( ) * sql . Stmt {
return delete . build . SimpleDelete ( delete . table , delete . where )
}
type accUpdateBuilder struct {
table string
set string
where string
build * Accumulator
}
func ( update * accUpdateBuilder ) Set ( set string ) * accUpdateBuilder {
update . set = set
return update
}
func ( update * accUpdateBuilder ) Where ( where string ) * accUpdateBuilder {
2018-03-31 05:25:27 +00:00
if update . where != "" {
update . where += " AND "
}
update . where += where
2017-11-12 05:25:04 +00:00
return update
}
func ( update * accUpdateBuilder ) Prepare ( ) * sql . Stmt {
return update . build . SimpleUpdate ( update . table , update . set , update . where )
}
type accSelectBuilder struct {
2018-01-03 07:46:18 +00:00
table string
columns string
where string
orderby string
limit string
dateCutoff * dateCutoff // We might want to do this in a slightly less hacky way
2018-01-21 11:17:43 +00:00
inChain * accSelectBuilder
inColumn string
2017-11-12 05:25:04 +00:00
build * Accumulator
}
func ( selectItem * accSelectBuilder ) Columns ( columns string ) * accSelectBuilder {
selectItem . columns = columns
return selectItem
}
func ( selectItem * accSelectBuilder ) Where ( where string ) * accSelectBuilder {
2018-03-31 05:25:27 +00:00
if selectItem . where != "" {
selectItem . where += " AND "
}
selectItem . where += where
return selectItem
}
// TODO: Don't implement the SQL at the accumulator level but the adapter level
func ( selectItem * accSelectBuilder ) In ( column string , inList [ ] int ) * accSelectBuilder {
if len ( inList ) == 0 {
return selectItem
}
var where = column + " IN("
for _ , item := range inList {
where += strconv . Itoa ( item ) + ","
}
where = where [ : len ( where ) - 1 ] + ")"
if selectItem . where != "" {
where += " AND " + selectItem . where
}
2017-11-12 05:25:04 +00:00
selectItem . where = where
return selectItem
}
2018-01-21 11:17:43 +00:00
func ( selectItem * accSelectBuilder ) InQ ( column string , subBuilder * accSelectBuilder ) * accSelectBuilder {
selectItem . inChain = subBuilder
selectItem . inColumn = column
return selectItem
}
2018-01-03 07:46:18 +00:00
func ( selectItem * accSelectBuilder ) DateCutoff ( column string , quantity int , unit string ) * accSelectBuilder {
selectItem . dateCutoff = & dateCutoff { column , quantity , unit }
return selectItem
}
2017-11-12 05:25:04 +00:00
func ( selectItem * accSelectBuilder ) Orderby ( orderby string ) * accSelectBuilder {
selectItem . orderby = orderby
return selectItem
}
func ( selectItem * accSelectBuilder ) Limit ( limit string ) * accSelectBuilder {
selectItem . limit = limit
return selectItem
}
func ( selectItem * accSelectBuilder ) Prepare ( ) * sql . Stmt {
2018-01-03 07:46:18 +00:00
// TODO: Phase out the procedural API and use the adapter's OO API? The OO API might need a bit more work before we do that and it needs to be rolled out to MSSQL.
2018-01-21 11:17:43 +00:00
if selectItem . dateCutoff != nil || selectItem . inChain != nil {
2018-01-03 07:46:18 +00:00
selectBuilder := selectItem . build . GetAdapter ( ) . Builder ( ) . Select ( ) . FromAcc ( selectItem )
return selectItem . build . prepare ( selectItem . build . GetAdapter ( ) . ComplexSelect ( selectBuilder ) )
}
2017-11-12 05:25:04 +00:00
return selectItem . build . SimpleSelect ( selectItem . table , selectItem . columns , selectItem . where , selectItem . orderby , selectItem . limit )
}
func ( selectItem * accSelectBuilder ) Query ( args ... interface { } ) ( * sql . Rows , error ) {
stmt := selectItem . Prepare ( )
if stmt != nil {
return stmt . Query ( args ... )
}
return nil , selectItem . build . FirstError ( )
}
type accInsertBuilder struct {
table string
columns string
fields string
build * Accumulator
}
func ( insert * accInsertBuilder ) Columns ( columns string ) * accInsertBuilder {
insert . columns = columns
return insert
}
func ( insert * accInsertBuilder ) Fields ( fields string ) * accInsertBuilder {
insert . fields = fields
return insert
}
func ( insert * accInsertBuilder ) Prepare ( ) * sql . Stmt {
return insert . build . SimpleInsert ( insert . table , insert . columns , insert . fields )
}
2018-02-03 05:47:14 +00:00
func ( insert * accInsertBuilder ) Exec ( args ... interface { } ) ( res sql . Result , err error ) {
stmt := insert . Prepare ( )
if stmt != nil {
return stmt . Exec ( args ... )
}
return res , insert . build . FirstError ( )
}
2017-11-12 05:25:04 +00:00
type accCountBuilder struct {
table string
where string
limit string
build * Accumulator
}
func ( count * accCountBuilder ) Where ( where string ) * accCountBuilder {
2018-03-31 05:25:27 +00:00
if count . where != "" {
count . where += " AND "
}
count . where += where
2017-11-12 05:25:04 +00:00
return count
}
func ( count * accCountBuilder ) Limit ( limit string ) * accCountBuilder {
count . limit = limit
return count
}
2017-12-30 05:47:46 +00:00
// TODO: Add QueryRow for this and use it in statistics.go
2017-11-12 05:25:04 +00:00
func ( count * accCountBuilder ) Prepare ( ) * sql . Stmt {
return count . build . SimpleCount ( count . table , count . where , count . limit )
}
2017-12-30 05:47:46 +00:00
// TODO: Add a Sum builder for summing viewchunks up into one number for the dashboard?