diff options
Diffstat (limited to 'vendor/github.com/uptrace/bun/relation_join.go')
-rw-r--r-- | vendor/github.com/uptrace/bun/relation_join.go | 453 |
1 files changed, 0 insertions, 453 deletions
diff --git a/vendor/github.com/uptrace/bun/relation_join.go b/vendor/github.com/uptrace/bun/relation_join.go deleted file mode 100644 index 47f27afd5..000000000 --- a/vendor/github.com/uptrace/bun/relation_join.go +++ /dev/null @@ -1,453 +0,0 @@ -package bun - -import ( - "context" - "reflect" - "time" - - "github.com/uptrace/bun/dialect/feature" - "github.com/uptrace/bun/internal" - "github.com/uptrace/bun/schema" -) - -type relationJoin struct { - Parent *relationJoin - BaseModel TableModel - JoinModel TableModel - Relation *schema.Relation - - additionalJoinOnConditions []schema.QueryWithArgs - - apply func(*SelectQuery) *SelectQuery - columns []schema.QueryWithArgs -} - -func (j *relationJoin) applyTo(q *SelectQuery) { - if j.apply == nil { - return - } - - var table *schema.Table - var columns []schema.QueryWithArgs - - // Save state. - table, q.table = q.table, j.JoinModel.Table() - columns, q.columns = q.columns, nil - - q = j.apply(q) - - // Restore state. - q.table = table - j.columns, q.columns = q.columns, columns -} - -func (j *relationJoin) Select(ctx context.Context, q *SelectQuery) error { - switch j.Relation.Type { - } - panic("not reached") -} - -func (j *relationJoin) selectMany(ctx context.Context, q *SelectQuery) error { - q = j.manyQuery(q) - if q == nil { - return nil - } - return q.Scan(ctx) -} - -func (j *relationJoin) manyQuery(q *SelectQuery) *SelectQuery { - hasManyModel := newHasManyModel(j) - if hasManyModel == nil { - return nil - } - - q = q.Model(hasManyModel) - - var where []byte - - if q.db.HasFeature(feature.CompositeIn) { - return j.manyQueryCompositeIn(where, q) - } - return j.manyQueryMulti(where, q) -} - -func (j *relationJoin) manyQueryCompositeIn(where []byte, q *SelectQuery) *SelectQuery { - if len(j.Relation.JoinPKs) > 1 { - where = append(where, '(') - } - where = appendColumns(where, j.JoinModel.Table().SQLAlias, j.Relation.JoinPKs) - if len(j.Relation.JoinPKs) > 1 { - where = append(where, ')') - } - where = append(where, " IN ("...) - where = appendChildValues( - q.db.Formatter(), - where, - j.JoinModel.rootValue(), - j.JoinModel.parentIndex(), - j.Relation.BasePKs, - ) - where = append(where, ")"...) - if len(j.additionalJoinOnConditions) > 0 { - where = append(where, " AND "...) - where = appendAdditionalJoinOnConditions(q.db.Formatter(), where, j.additionalJoinOnConditions) - } - - q = q.Where(internal.String(where)) - - if j.Relation.PolymorphicField != nil { - q = q.Where("? = ?", j.Relation.PolymorphicField.SQLName, j.Relation.PolymorphicValue) - } - - j.applyTo(q) - q = q.Apply(j.hasManyColumns) - - return q -} - -func (j *relationJoin) manyQueryMulti(where []byte, q *SelectQuery) *SelectQuery { - where = appendMultiValues( - q.db.Formatter(), - where, - j.JoinModel.rootValue(), - j.JoinModel.parentIndex(), - j.Relation.BasePKs, - j.Relation.JoinPKs, - j.JoinModel.Table().SQLAlias, - ) - - q = q.Where(internal.String(where)) - - if len(j.additionalJoinOnConditions) > 0 { - q = q.Where(internal.String(appendAdditionalJoinOnConditions(q.db.Formatter(), []byte{}, j.additionalJoinOnConditions))) - } - - if j.Relation.PolymorphicField != nil { - q = q.Where("? = ?", j.Relation.PolymorphicField.SQLName, j.Relation.PolymorphicValue) - } - - j.applyTo(q) - q = q.Apply(j.hasManyColumns) - - return q -} - -func (j *relationJoin) hasManyColumns(q *SelectQuery) *SelectQuery { - b := make([]byte, 0, 32) - - joinTable := j.JoinModel.Table() - if len(j.columns) > 0 { - for i, col := range j.columns { - if i > 0 { - b = append(b, ", "...) - } - - if col.Args == nil { - if field, ok := joinTable.FieldMap[col.Query]; ok { - b = append(b, joinTable.SQLAlias...) - b = append(b, '.') - b = append(b, field.SQLName...) - continue - } - } - - var err error - b, err = col.AppendQuery(q.db.fmter, b) - if err != nil { - q.setErr(err) - return q - } - - } - } else { - b = appendColumns(b, joinTable.SQLAlias, joinTable.Fields) - } - - q = q.ColumnExpr(internal.String(b)) - - return q -} - -func (j *relationJoin) selectM2M(ctx context.Context, q *SelectQuery) error { - q = j.m2mQuery(q) - if q == nil { - return nil - } - return q.Scan(ctx) -} - -func (j *relationJoin) m2mQuery(q *SelectQuery) *SelectQuery { - fmter := q.db.fmter - - m2mModel := newM2MModel(j) - if m2mModel == nil { - return nil - } - q = q.Model(m2mModel) - - index := j.JoinModel.parentIndex() - - if j.Relation.M2MTable != nil { - // We only need base pks to park joined models to the base model. - fields := j.Relation.M2MBasePKs - - b := make([]byte, 0, len(fields)) - b = appendColumns(b, j.Relation.M2MTable.SQLAlias, fields) - - q = q.ColumnExpr(internal.String(b)) - } - - //nolint - var join []byte - join = append(join, "JOIN "...) - join = fmter.AppendQuery(join, string(j.Relation.M2MTable.SQLName)) - join = append(join, " AS "...) - join = append(join, j.Relation.M2MTable.SQLAlias...) - join = append(join, " ON ("...) - for i, col := range j.Relation.M2MBasePKs { - if i > 0 { - join = append(join, ", "...) - } - join = append(join, j.Relation.M2MTable.SQLAlias...) - join = append(join, '.') - join = append(join, col.SQLName...) - } - join = append(join, ") IN ("...) - join = appendChildValues(fmter, join, j.BaseModel.rootValue(), index, j.Relation.BasePKs) - join = append(join, ")"...) - - if len(j.additionalJoinOnConditions) > 0 { - join = append(join, " AND "...) - join = appendAdditionalJoinOnConditions(fmter, join, j.additionalJoinOnConditions) - } - - q = q.Join(internal.String(join)) - - joinTable := j.JoinModel.Table() - for i, m2mJoinField := range j.Relation.M2MJoinPKs { - joinField := j.Relation.JoinPKs[i] - q = q.Where("?.? = ?.?", - joinTable.SQLAlias, joinField.SQLName, - j.Relation.M2MTable.SQLAlias, m2mJoinField.SQLName) - } - - j.applyTo(q) - q = q.Apply(j.hasManyColumns) - - return q -} - -func (j *relationJoin) hasParent() bool { - if j.Parent != nil { - switch j.Parent.Relation.Type { - case schema.HasOneRelation, schema.BelongsToRelation: - return true - } - } - return false -} - -func (j *relationJoin) appendAlias(fmter schema.Formatter, b []byte) []byte { - quote := fmter.IdentQuote() - - b = append(b, quote) - b = appendAlias(b, j) - b = append(b, quote) - return b -} - -func (j *relationJoin) appendAliasColumn(fmter schema.Formatter, b []byte, column string) []byte { - quote := fmter.IdentQuote() - - b = append(b, quote) - b = appendAlias(b, j) - b = append(b, "__"...) - b = append(b, column...) - b = append(b, quote) - return b -} - -func (j *relationJoin) appendBaseAlias(fmter schema.Formatter, b []byte) []byte { - quote := fmter.IdentQuote() - - if j.hasParent() { - b = append(b, quote) - b = appendAlias(b, j.Parent) - b = append(b, quote) - return b - } - return append(b, j.BaseModel.Table().SQLAlias...) -} - -func (j *relationJoin) appendSoftDelete( - fmter schema.Formatter, b []byte, flags internal.Flag, -) []byte { - b = append(b, '.') - - field := j.JoinModel.Table().SoftDeleteField - b = append(b, field.SQLName...) - - if field.IsPtr || field.NullZero { - if flags.Has(deletedFlag) { - b = append(b, " IS NOT NULL"...) - } else { - b = append(b, " IS NULL"...) - } - } else { - if flags.Has(deletedFlag) { - b = append(b, " != "...) - } else { - b = append(b, " = "...) - } - b = fmter.Dialect().AppendTime(b, time.Time{}) - } - - return b -} - -func appendAlias(b []byte, j *relationJoin) []byte { - if j.hasParent() { - b = appendAlias(b, j.Parent) - b = append(b, "__"...) - } - b = append(b, j.Relation.Field.Name...) - return b -} - -func (j *relationJoin) appendHasOneJoin( - fmter schema.Formatter, b []byte, q *SelectQuery, -) (_ []byte, err error) { - isSoftDelete := j.JoinModel.Table().SoftDeleteField != nil && !q.flags.Has(allWithDeletedFlag) - - b = append(b, "LEFT JOIN "...) - b = fmter.AppendQuery(b, string(j.JoinModel.Table().SQLNameForSelects)) - b = append(b, " AS "...) - b = j.appendAlias(fmter, b) - - b = append(b, " ON "...) - - b = append(b, '(') - for i, baseField := range j.Relation.BasePKs { - if i > 0 { - b = append(b, " AND "...) - } - b = j.appendAlias(fmter, b) - b = append(b, '.') - b = append(b, j.Relation.JoinPKs[i].SQLName...) - b = append(b, " = "...) - b = j.appendBaseAlias(fmter, b) - b = append(b, '.') - b = append(b, baseField.SQLName...) - } - b = append(b, ')') - - if isSoftDelete { - b = append(b, " AND "...) - b = j.appendAlias(fmter, b) - b = j.appendSoftDelete(fmter, b, q.flags) - } - - if len(j.additionalJoinOnConditions) > 0 { - b = append(b, " AND "...) - b = appendAdditionalJoinOnConditions(fmter, b, j.additionalJoinOnConditions) - } - - return b, nil -} - -func appendChildValues( - fmter schema.Formatter, b []byte, v reflect.Value, index []int, fields []*schema.Field, -) []byte { - seen := make(map[string]struct{}) - walk(v, index, func(v reflect.Value) { - start := len(b) - - if len(fields) > 1 { - b = append(b, '(') - } - for i, f := range fields { - if i > 0 { - b = append(b, ", "...) - } - b = f.AppendValue(fmter, b, v) - } - if len(fields) > 1 { - b = append(b, ')') - } - b = append(b, ", "...) - - if _, ok := seen[string(b[start:])]; ok { - b = b[:start] - } else { - seen[string(b[start:])] = struct{}{} - } - }) - if len(seen) > 0 { - b = b[:len(b)-2] // trim ", " - } - return b -} - -// appendMultiValues is an alternative to appendChildValues that doesn't use the sql keyword ID -// but instead uses old style ((k1=v1) AND (k2=v2)) OR (...) conditions. -func appendMultiValues( - fmter schema.Formatter, b []byte, v reflect.Value, index []int, baseFields, joinFields []*schema.Field, joinTable schema.Safe, -) []byte { - // This is based on a mix of appendChildValues and query_base.appendColumns - - // These should never mismatch in length but nice to know if it does - if len(joinFields) != len(baseFields) { - panic("not reached") - } - - // walk the relations - b = append(b, '(') - seen := make(map[string]struct{}) - walk(v, index, func(v reflect.Value) { - start := len(b) - for i, f := range baseFields { - if i > 0 { - b = append(b, " AND "...) - } - if len(baseFields) > 1 { - b = append(b, '(') - } - // Field name - b = append(b, joinTable...) - b = append(b, '.') - b = append(b, []byte(joinFields[i].SQLName)...) - - // Equals value - b = append(b, '=') - b = f.AppendValue(fmter, b, v) - if len(baseFields) > 1 { - b = append(b, ')') - } - } - - b = append(b, ") OR ("...) - - if _, ok := seen[string(b[start:])]; ok { - b = b[:start] - } else { - seen[string(b[start:])] = struct{}{} - } - }) - if len(seen) > 0 { - b = b[:len(b)-6] // trim ") OR (" - } - b = append(b, ')') - return b -} - -func appendAdditionalJoinOnConditions( - fmter schema.Formatter, b []byte, conditions []schema.QueryWithArgs, -) []byte { - for i, cond := range conditions { - if i > 0 { - b = append(b, " AND "...) - } - b = fmter.AppendQuery(b, cond.Query, cond.Args...) - } - return b -} |