2021-01-19 19:00:42 +01:00
|
|
|
package sqlite3
|
|
|
|
|
|
|
|
import (
|
|
|
|
"database/sql"
|
|
|
|
"fmt"
|
|
|
|
|
|
|
|
"github.com/matrix-org/dendrite/internal/sqlutil"
|
|
|
|
)
|
|
|
|
|
|
|
|
type FilterOrder int
|
|
|
|
|
|
|
|
const (
|
|
|
|
FilterOrderNone = iota
|
|
|
|
FilterOrderAsc
|
|
|
|
FilterOrderDesc
|
|
|
|
)
|
|
|
|
|
|
|
|
// prepareWithFilters returns a prepared statement with the
|
|
|
|
// relevant filters included. It also includes an []interface{}
|
|
|
|
// list of all the relevant parameters to pass straight to
|
|
|
|
// QueryContext, QueryRowContext etc.
|
|
|
|
// We don't take the filter object directly here because the
|
|
|
|
// fields might come from either a StateFilter or an EventFilter,
|
|
|
|
// and it's easier just to have the caller extract the relevant
|
|
|
|
// parts.
|
|
|
|
func prepareWithFilters(
|
|
|
|
db *sql.DB, txn *sql.Tx, query string, params []interface{},
|
2022-04-11 09:05:23 +02:00
|
|
|
senders, notsenders, types, nottypes *[]string, excludeEventIDs []string,
|
2022-04-13 13:16:02 +02:00
|
|
|
containsURL *bool, limit int, order FilterOrder,
|
2021-01-19 19:00:42 +01:00
|
|
|
) (*sql.Stmt, []interface{}, error) {
|
|
|
|
offset := len(params)
|
2022-04-11 09:05:23 +02:00
|
|
|
if senders != nil {
|
|
|
|
if count := len(*senders); count > 0 {
|
|
|
|
query += " AND sender IN " + sqlutil.QueryVariadicOffset(count, offset)
|
|
|
|
for _, v := range *senders {
|
|
|
|
params, offset = append(params, v), offset+1
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
query += ` AND sender = ""`
|
2021-01-19 19:00:42 +01:00
|
|
|
}
|
|
|
|
}
|
2022-04-11 09:05:23 +02:00
|
|
|
if notsenders != nil {
|
|
|
|
if count := len(*notsenders); count > 0 {
|
|
|
|
query += " AND sender NOT IN " + sqlutil.QueryVariadicOffset(count, offset)
|
|
|
|
for _, v := range *notsenders {
|
|
|
|
params, offset = append(params, v), offset+1
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
query += ` AND sender NOT = ""`
|
2021-01-19 19:00:42 +01:00
|
|
|
}
|
|
|
|
}
|
2022-04-11 09:05:23 +02:00
|
|
|
if types != nil {
|
|
|
|
if count := len(*types); count > 0 {
|
|
|
|
query += " AND type IN " + sqlutil.QueryVariadicOffset(count, offset)
|
|
|
|
for _, v := range *types {
|
|
|
|
params, offset = append(params, v), offset+1
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
query += ` AND type = ""`
|
2021-01-19 19:00:42 +01:00
|
|
|
}
|
|
|
|
}
|
2022-04-11 09:05:23 +02:00
|
|
|
if nottypes != nil {
|
|
|
|
if count := len(*nottypes); count > 0 {
|
|
|
|
query += " AND type NOT IN " + sqlutil.QueryVariadicOffset(count, offset)
|
|
|
|
for _, v := range *nottypes {
|
|
|
|
params, offset = append(params, v), offset+1
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
query += ` AND type NOT = ""`
|
2021-01-19 19:00:42 +01:00
|
|
|
}
|
|
|
|
}
|
2022-04-13 13:16:02 +02:00
|
|
|
if containsURL != nil {
|
|
|
|
query += fmt.Sprintf(" AND contains_url = %v", *containsURL)
|
|
|
|
}
|
2021-02-04 13:20:37 +01:00
|
|
|
if count := len(excludeEventIDs); count > 0 {
|
|
|
|
query += " AND event_id NOT IN " + sqlutil.QueryVariadicOffset(count, offset)
|
|
|
|
for _, v := range excludeEventIDs {
|
|
|
|
params, offset = append(params, v), offset+1
|
|
|
|
}
|
|
|
|
}
|
2021-01-19 19:00:42 +01:00
|
|
|
switch order {
|
|
|
|
case FilterOrderAsc:
|
|
|
|
query += " ORDER BY id ASC"
|
|
|
|
case FilterOrderDesc:
|
|
|
|
query += " ORDER BY id DESC"
|
|
|
|
}
|
|
|
|
query += fmt.Sprintf(" LIMIT $%d", offset+1)
|
|
|
|
params = append(params, limit)
|
|
|
|
|
|
|
|
var stmt *sql.Stmt
|
|
|
|
var err error
|
|
|
|
if txn != nil {
|
|
|
|
stmt, err = txn.Prepare(query)
|
|
|
|
} else {
|
|
|
|
stmt, err = db.Prepare(query)
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, fmt.Errorf("s.db.Prepare: %w", err)
|
|
|
|
}
|
|
|
|
return stmt, params, nil
|
|
|
|
}
|