adopt forked squirrel supporting from UPDATE FROM (#19896)
Fork https://github.com/Masterminds/squirrel as https://github.com/lieut-data/squirrel with the following changes: * https://github.com/Masterminds/squirrel/pull/256 supporting FROM clause to update builder (Postgres) * Extension of above to support multiple FROM in UPDATE (Postgres) * Support for multiple tables in UPDATE (MySQL) This PR then leverages those changes to simplify a query that previously had to be coded by hand and duplicate for each of MySQL and Postgres.
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
3f5eb5f6f7
Коммит
7b5ac343f0
2
go.mod
2
go.mod
@@ -126,6 +126,8 @@ require (
|
|||||||
gopkg.in/yaml.v2 v2.4.0
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
replace github.com/Masterminds/squirrel v1.5.2 => github.com/lieut-data/squirrel v1.5.4
|
||||||
|
|
||||||
// Hack to prevent the willf/bitset module from being upgraded to 1.2.0.
|
// Hack to prevent the willf/bitset module from being upgraded to 1.2.0.
|
||||||
// They changed the module path from github.com/willf/bitset to
|
// They changed the module path from github.com/willf/bitset to
|
||||||
// github.com/bits-and-blooms/bitset and a couple of dependent repos are yet
|
// github.com/bits-and-blooms/bitset and a couple of dependent repos are yet
|
||||||
|
|||||||
4
go.sum
4
go.sum
@@ -978,6 +978,10 @@ github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
|||||||
github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||||
github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk=
|
github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk=
|
||||||
github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||||
|
github.com/lieut-data/squirrel v1.5.3 h1:c6RI29VQOkUvqjpUsa45HeZ+wShtzDcSrmTUom/F65g=
|
||||||
|
github.com/lieut-data/squirrel v1.5.3/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10=
|
||||||
|
github.com/lieut-data/squirrel v1.5.4 h1:OGzJNl0/ZxdjLEHuFzDo797zB2V7i8wQXBVThcOzbHE=
|
||||||
|
github.com/lieut-data/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10=
|
||||||
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
||||||
github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w=
|
github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w=
|
||||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
|
|||||||
@@ -571,36 +571,28 @@ func (s *SqlThreadStore) MarkAllAsReadByChannels(userID string, channelIDs []str
|
|||||||
|
|
||||||
now := model.GetMillis()
|
now := model.GetMillis()
|
||||||
|
|
||||||
// TODO: Fork squirrel to include https://github.com/Masterminds/squirrel/pull/256 and
|
var query sq.UpdateBuilder
|
||||||
// support FROM in an UPDATE query.
|
|
||||||
channelIDsSql, channelIDsArgs := constructArrayArgs(channelIDs)
|
|
||||||
|
|
||||||
var query string
|
|
||||||
if s.DriverName() == model.DatabaseDriverPostgres {
|
if s.DriverName() == model.DatabaseDriverPostgres {
|
||||||
query = `
|
query = s.getQueryBuilder().Update("ThreadMemberships").From("Threads")
|
||||||
UPDATE ThreadMemberships
|
|
||||||
SET LastViewed = ?, UnreadMentions = ?, LastUpdated = ?
|
|
||||||
FROM Threads
|
|
||||||
WHERE ThreadMemberships.UserId = ?
|
|
||||||
AND Threads.PostId = ThreadMemberships.PostId
|
|
||||||
AND Threads.ChannelID IN ` + channelIDsSql + `
|
|
||||||
AND Threads.LastReplyAt > ThreadMemberships.LastViewed
|
|
||||||
`
|
|
||||||
} else {
|
} else {
|
||||||
query = `
|
query = s.getQueryBuilder().Update("ThreadMemberships", "Threads")
|
||||||
UPDATE ThreadMemberships, Threads
|
|
||||||
SET ThreadMemberships.LastViewed = ?, ThreadMemberships.UnreadMentions = ?, ThreadMemberships.LastUpdated = ?
|
|
||||||
WHERE ThreadMemberships.UserId = ?
|
|
||||||
AND Threads.PostId = ThreadMemberships.PostId
|
|
||||||
AND Threads.ChannelID IN ` + channelIDsSql + `
|
|
||||||
AND Threads.LastReplyAt > ThreadMemberships.LastViewed
|
|
||||||
`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
args := []interface{}{now, 0, now, userID}
|
query = query.Set("LastViewed", now).
|
||||||
args = append(args, channelIDsArgs...)
|
Set("UnreadMentions", 0).
|
||||||
|
Set("LastUpdated", now).
|
||||||
|
Where(sq.Eq{"ThreadMemberships.UserId": userID}).
|
||||||
|
Where(sq.Expr("Threads.PostId = ThreadMemberships.PostId")).
|
||||||
|
Where(sq.Eq{"Threads.ChannelId": channelIDs}).
|
||||||
|
Where(sq.Expr("Threads.LastReplyAt > ThreadMemberships.LastViewed"))
|
||||||
|
|
||||||
if _, err := s.GetMasterX().Exec(query, args...); err != nil {
|
sql, args, err := query.ToSql()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to build query to mark all as read by %d channels for user id=%s", len(channelIDs), userID)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := s.GetMasterX().Exec(sql, args...); err != nil {
|
||||||
return errors.Wrapf(err, "failed to mark all threads as read by channels for user id=%s", userID)
|
return errors.Wrapf(err, "failed to mark all threads as read by channels for user id=%s", userID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2
vendor/github.com/Masterminds/squirrel/squirrel_ctx.go
сгенерированный
поставляемый
2
vendor/github.com/Masterminds/squirrel/squirrel_ctx.go
сгенерированный
поставляемый
@@ -32,7 +32,7 @@ type QueryRowerContext interface {
|
|||||||
QueryRowContext(ctx context.Context, query string, args ...interface{}) RowScanner
|
QueryRowContext(ctx context.Context, query string, args ...interface{}) RowScanner
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunnerContext groups the Runner interface, along with the Contect versions of each of
|
// RunnerContext groups the Runner interface, along with the Context versions of each of
|
||||||
// its methods
|
// its methods
|
||||||
type RunnerContext interface {
|
type RunnerContext interface {
|
||||||
Runner
|
Runner
|
||||||
|
|||||||
8
vendor/github.com/Masterminds/squirrel/statement.go
сгенерированный
поставляемый
8
vendor/github.com/Masterminds/squirrel/statement.go
сгенерированный
поставляемый
@@ -22,8 +22,8 @@ func (b StatementBuilderType) Replace(into string) InsertBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update returns a UpdateBuilder for this StatementBuilderType.
|
// Update returns a UpdateBuilder for this StatementBuilderType.
|
||||||
func (b StatementBuilderType) Update(table string) UpdateBuilder {
|
func (b StatementBuilderType) Update(tables ...string) UpdateBuilder {
|
||||||
return UpdateBuilder(b).Table(table)
|
return UpdateBuilder(b).Table(tables...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete returns a DeleteBuilder for this StatementBuilderType.
|
// Delete returns a DeleteBuilder for this StatementBuilderType.
|
||||||
@@ -76,8 +76,8 @@ func Replace(into string) InsertBuilder {
|
|||||||
// Update returns a new UpdateBuilder with the given table name.
|
// Update returns a new UpdateBuilder with the given table name.
|
||||||
//
|
//
|
||||||
// See UpdateBuilder.Table.
|
// See UpdateBuilder.Table.
|
||||||
func Update(table string) UpdateBuilder {
|
func Update(tables ...string) UpdateBuilder {
|
||||||
return StatementBuilder.Update(table)
|
return StatementBuilder.Update(tables...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete returns a new DeleteBuilder with the given table name.
|
// Delete returns a new DeleteBuilder with the given table name.
|
||||||
|
|||||||
40
vendor/github.com/Masterminds/squirrel/update.go
сгенерированный
поставляемый
40
vendor/github.com/Masterminds/squirrel/update.go
сгенерированный
поставляемый
@@ -14,8 +14,9 @@ type updateData struct {
|
|||||||
PlaceholderFormat PlaceholderFormat
|
PlaceholderFormat PlaceholderFormat
|
||||||
RunWith BaseRunner
|
RunWith BaseRunner
|
||||||
Prefixes []Sqlizer
|
Prefixes []Sqlizer
|
||||||
Table string
|
Tables []string
|
||||||
SetClauses []setClause
|
SetClauses []setClause
|
||||||
|
From []Sqlizer
|
||||||
WhereParts []Sqlizer
|
WhereParts []Sqlizer
|
||||||
OrderBys []string
|
OrderBys []string
|
||||||
Limit string
|
Limit string
|
||||||
@@ -54,7 +55,7 @@ func (d *updateData) QueryRow() RowScanner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *updateData) ToSql() (sqlStr string, args []interface{}, err error) {
|
func (d *updateData) ToSql() (sqlStr string, args []interface{}, err error) {
|
||||||
if len(d.Table) == 0 {
|
if len(d.Tables) == 0 {
|
||||||
err = fmt.Errorf("update statements must specify a table")
|
err = fmt.Errorf("update statements must specify a table")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -75,7 +76,7 @@ func (d *updateData) ToSql() (sqlStr string, args []interface{}, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sql.WriteString("UPDATE ")
|
sql.WriteString("UPDATE ")
|
||||||
sql.WriteString(d.Table)
|
sql.WriteString(strings.Join(d.Tables, ", "))
|
||||||
|
|
||||||
sql.WriteString(" SET ")
|
sql.WriteString(" SET ")
|
||||||
setSqls := make([]string, len(d.SetClauses))
|
setSqls := make([]string, len(d.SetClauses))
|
||||||
@@ -100,6 +101,14 @@ func (d *updateData) ToSql() (sqlStr string, args []interface{}, err error) {
|
|||||||
}
|
}
|
||||||
sql.WriteString(strings.Join(setSqls, ", "))
|
sql.WriteString(strings.Join(setSqls, ", "))
|
||||||
|
|
||||||
|
if len(d.From) > 0 {
|
||||||
|
sql.WriteString(" FROM ")
|
||||||
|
args, err = appendToSql(d.From, sql, ", ", args)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if len(d.WhereParts) > 0 {
|
if len(d.WhereParts) > 0 {
|
||||||
sql.WriteString(" WHERE ")
|
sql.WriteString(" WHERE ")
|
||||||
args, err = appendToSql(d.WhereParts, sql, " AND ", args)
|
args, err = appendToSql(d.WhereParts, sql, " AND ", args)
|
||||||
@@ -208,8 +217,16 @@ func (b UpdateBuilder) PrefixExpr(expr Sqlizer) UpdateBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Table sets the table to be updated.
|
// Table sets the table to be updated.
|
||||||
func (b UpdateBuilder) Table(table string) UpdateBuilder {
|
// Additional tables are used with supporting databases to implicitly join.
|
||||||
return builder.Set(b, "Table", table).(UpdateBuilder)
|
func (b UpdateBuilder) Table(tables ...string) UpdateBuilder {
|
||||||
|
nonEmptyTables := make([]string, 0, len(tables))
|
||||||
|
for _, table := range tables {
|
||||||
|
if table != "" {
|
||||||
|
nonEmptyTables = append(nonEmptyTables, table)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.Set(b, "Tables", nonEmptyTables).(UpdateBuilder)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set adds SET clauses to the query.
|
// Set adds SET clauses to the query.
|
||||||
@@ -233,6 +250,19 @@ func (b UpdateBuilder) SetMap(clauses map[string]interface{}) UpdateBuilder {
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// From adds FROM clause to the query
|
||||||
|
// FROM is valid construct in postgresql only.
|
||||||
|
func (b UpdateBuilder) From(from string) UpdateBuilder {
|
||||||
|
return builder.Append(b, "From", newPart(from)).(UpdateBuilder)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromSelect sets a subquery into the FROM clause of the query.
|
||||||
|
func (b UpdateBuilder) FromSelect(from SelectBuilder, alias string) UpdateBuilder {
|
||||||
|
// Prevent misnumbered parameters in nested selects (#183).
|
||||||
|
from = from.PlaceholderFormat(Question)
|
||||||
|
return builder.Append(b, "From", Alias(from, alias)).(UpdateBuilder)
|
||||||
|
}
|
||||||
|
|
||||||
// Where adds WHERE expressions to the query.
|
// Where adds WHERE expressions to the query.
|
||||||
//
|
//
|
||||||
// See SelectBuilder.Where for more information.
|
// See SelectBuilder.Where for more information.
|
||||||
|
|||||||
2
vendor/modules.txt
поставляемый
2
vendor/modules.txt
поставляемый
@@ -10,7 +10,7 @@ github.com/JalfResi/justext
|
|||||||
# github.com/Masterminds/semver/v3 v3.1.1
|
# github.com/Masterminds/semver/v3 v3.1.1
|
||||||
## explicit
|
## explicit
|
||||||
github.com/Masterminds/semver/v3
|
github.com/Masterminds/semver/v3
|
||||||
# github.com/Masterminds/squirrel v1.5.2
|
# github.com/Masterminds/squirrel v1.5.2 => github.com/lieut-data/squirrel v1.5.4
|
||||||
## explicit
|
## explicit
|
||||||
github.com/Masterminds/squirrel
|
github.com/Masterminds/squirrel
|
||||||
# github.com/PuerkitoBio/goquery v1.8.0
|
# github.com/PuerkitoBio/goquery v1.8.0
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user