aboutsummaryrefslogtreecommitdiff
path: root/internal/sqlutil/sql.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/sqlutil/sql.go')
-rw-r--r--internal/sqlutil/sql.go45
1 files changed, 45 insertions, 0 deletions
diff --git a/internal/sqlutil/sql.go b/internal/sqlutil/sql.go
index 1d2825d5..90562ded 100644
--- a/internal/sqlutil/sql.go
+++ b/internal/sqlutil/sql.go
@@ -15,10 +15,14 @@
package sqlutil
import (
+ "context"
"database/sql"
"errors"
"fmt"
"runtime"
+ "strings"
+
+ "github.com/matrix-org/util"
)
// ErrUserExists is returned if a username already exists in the database.
@@ -107,3 +111,44 @@ func SQLiteDriverName() string {
}
return "sqlite3"
}
+
+func minOfInts(a, b int) int {
+ if a <= b {
+ return a
+ }
+ return b
+}
+
+// QueryProvider defines the interface for querys used by RunLimitedVariablesQuery.
+type QueryProvider interface {
+ QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)
+}
+
+// SQLite3MaxVariables is the default maximum number of host parameters in a single SQL statement
+// SQLlite can handle. See https://www.sqlite.org/limits.html for more information.
+const SQLite3MaxVariables = 999
+
+// RunLimitedVariablesQuery split up a query with more variables than the used database can handle in multiple queries.
+func RunLimitedVariablesQuery(ctx context.Context, query string, qp QueryProvider, variables []interface{}, limit uint, rowHandler func(*sql.Rows) error) error {
+ var start int
+ for start < len(variables) {
+ n := minOfInts(len(variables)-start, int(limit))
+ nextQuery := strings.Replace(query, "($1)", QueryVariadic(n), 1)
+ rows, err := qp.QueryContext(ctx, nextQuery, variables[start:start+n]...)
+ if err != nil {
+ util.GetLogger(ctx).WithError(err).Error("QueryContext returned an error")
+ return err
+ }
+ err = rowHandler(rows)
+ if closeErr := rows.Close(); closeErr != nil {
+ util.GetLogger(ctx).WithError(closeErr).Error("RunLimitedVariablesQuery: failed to close rows")
+ return err
+ }
+ if err != nil {
+ util.GetLogger(ctx).WithError(err).Error("RunLimitedVariablesQuery: rowHandler returned error")
+ return err
+ }
+ start = start + n
+ }
+ return nil
+}