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 )
}
2018-04-22 12:33:56 +00:00
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-04-22 12:33:56 +00:00
inChain * AccSelectBuilder
2018-01-21 11:17:43 +00:00
inColumn string
2017-11-12 05:25:04 +00:00
build * Accumulator
}
2018-04-22 12:33:56 +00:00
func ( selectItem * AccSelectBuilder ) Columns ( columns string ) * AccSelectBuilder {
2017-11-12 05:25:04 +00:00
selectItem . columns = columns
return selectItem
}
2018-04-22 12:33:56 +00:00
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
2018-04-22 12:33:56 +00:00
func ( selectItem * AccSelectBuilder ) In ( column string , inList [ ] int ) * AccSelectBuilder {
2018-03-31 05:25:27 +00:00
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-04-22 12:33:56 +00:00
func ( selectItem * AccSelectBuilder ) InQ ( column string , subBuilder * AccSelectBuilder ) * AccSelectBuilder {
2018-01-21 11:17:43 +00:00
selectItem . inChain = subBuilder
selectItem . inColumn = column
return selectItem
}
2018-04-22 12:33:56 +00:00
func ( selectItem * AccSelectBuilder ) DateCutoff ( column string , quantity int , unit string ) * AccSelectBuilder {
2018-01-03 07:46:18 +00:00
selectItem . dateCutoff = & dateCutoff { column , quantity , unit }
return selectItem
}
2018-04-22 12:33:56 +00:00
func ( selectItem * AccSelectBuilder ) Orderby ( orderby string ) * AccSelectBuilder {
2017-11-12 05:25:04 +00:00
selectItem . orderby = orderby
return selectItem
}
2018-04-22 12:33:56 +00:00
func ( selectItem * AccSelectBuilder ) Limit ( limit string ) * AccSelectBuilder {
2017-11-12 05:25:04 +00:00
selectItem . limit = limit
return selectItem
}
2018-04-22 12:33:56 +00:00
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 )
}
2018-04-22 12:33:56 +00:00
func ( selectItem * AccSelectBuilder ) Query ( args ... interface { } ) ( * sql . Rows , error ) {
2017-11-12 05:25:04 +00:00
stmt := selectItem . Prepare ( )
if stmt != nil {
return stmt . Query ( args ... )
}
return nil , selectItem . build . FirstError ( )
}
2018-05-14 08:56:56 +00:00
type AccRowWrap struct {
row * sql . Row
err error
}
func ( wrap * AccRowWrap ) Scan ( dest ... interface { } ) error {
if wrap . err != nil {
return wrap . err
}
return wrap . row . Scan ( dest ... )
}
// TODO: Test to make sure the errors are passed up properly
func ( selectItem * AccSelectBuilder ) QueryRow ( args ... interface { } ) * AccRowWrap {
stmt := selectItem . Prepare ( )
if stmt != nil {
return & AccRowWrap { stmt . QueryRow ( args ... ) , nil }
}
return & AccRowWrap { nil , selectItem . build . FirstError ( ) }
}
2018-04-22 12:33:56 +00:00
// Experimental, reduces lines
func ( selectItem * AccSelectBuilder ) Each ( handle func ( * sql . Rows ) error ) error {
rows , err := selectItem . Query ( )
if err != nil {
return err
}
defer rows . Close ( )
for rows . Next ( ) {
err = handle ( rows )
if err != nil {
return err
}
}
return rows . Err ( )
}
2017-11-12 05:25:04 +00:00
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?