package gorm

import (
	
	
	
	
	
	
	

	
	
	
)

type result struct {
	Result       sql.Result
	RowsAffected int64
}

func ( *result) ( *Statement) {
	.Result = 
}

// Build implements clause.Expression interface
func (result) (clause.Builder) {
}

func () *result {
	return &result{}
}

type Interface[ any] interface {
	Raw(sql string, values ...interface{}) ExecInterface[]
	Exec(ctx context.Context, sql string, values ...interface{}) error
	CreateInterface[]
}

type CreateInterface[ any] interface {
	ExecInterface[]
	// chain methods available at start; Select/Omit keep CreateInterface to allow Create chaining
	Scopes(scopes ...func(db *Statement)) ChainInterface[]
	Where(query interface{}, args ...interface{}) ChainInterface[]
	Not(query interface{}, args ...interface{}) ChainInterface[]
	Or(query interface{}, args ...interface{}) ChainInterface[]
	Limit(offset int) ChainInterface[]
	Offset(offset int) ChainInterface[]
	Joins(query clause.JoinTarget, on func(db JoinBuilder, joinTable clause.Table, curTable clause.Table) error) ChainInterface[]
	Preload(association string, query func(db PreloadBuilder) error) ChainInterface[]
	Select(query string, args ...interface{}) CreateInterface[]
	Omit(columns ...string) CreateInterface[]
	MapColumns(m map[string]string) ChainInterface[]
	Distinct(args ...interface{}) ChainInterface[]
	Group(name string) ChainInterface[]
	Having(query interface{}, args ...interface{}) ChainInterface[]
	Order(value interface{}) ChainInterface[]
	Build(builder clause.Builder)

	Delete(ctx context.Context) (rowsAffected int, err error)
	Update(ctx context.Context, name string, value any) (rowsAffected int, err error)
	Updates(ctx context.Context, t ) (rowsAffected int, err error)
	Count(ctx context.Context, column string) (result int64, err error)

	Table(name string, args ...interface{}) CreateInterface[]
	Create(ctx context.Context, r *) error
	CreateInBatches(ctx context.Context, r *[], batchSize int) error
	Set(assignments ...clause.Assigner) SetCreateOrUpdateInterface[]
}

type ChainInterface[ any] interface {
	ExecInterface[]
	Scopes(scopes ...func(db *Statement)) ChainInterface[]
	Where(query interface{}, args ...interface{}) ChainInterface[]
	Not(query interface{}, args ...interface{}) ChainInterface[]
	Or(query interface{}, args ...interface{}) ChainInterface[]
	Limit(offset int) ChainInterface[]
	Offset(offset int) ChainInterface[]
	Joins(query clause.JoinTarget, on func(db JoinBuilder, joinTable clause.Table, curTable clause.Table) error) ChainInterface[]
	Preload(association string, query func(db PreloadBuilder) error) ChainInterface[]
	Select(query string, args ...interface{}) ChainInterface[]
	Omit(columns ...string) ChainInterface[]
	MapColumns(m map[string]string) ChainInterface[]
	Distinct(args ...interface{}) ChainInterface[]
	Group(name string) ChainInterface[]
	Having(query interface{}, args ...interface{}) ChainInterface[]
	Order(value interface{}) ChainInterface[]
	Set(assignments ...clause.Assigner) SetUpdateOnlyInterface[]

	Build(builder clause.Builder)

	Table(name string, args ...interface{}) ChainInterface[]
	Delete(ctx context.Context) (rowsAffected int, err error)
	Update(ctx context.Context, name string, value any) (rowsAffected int, err error)
	Updates(ctx context.Context, t ) (rowsAffected int, err error)
	Count(ctx context.Context, column string) (result int64, err error)
}

// SetUpdateOnlyInterface is returned by Set after chaining; only Update is allowed
type SetUpdateOnlyInterface[ any] interface {
	Update(ctx context.Context) (rowsAffected int, err error)
}

// SetCreateOrUpdateInterface is returned by Set at start; Create or Update are allowed
type SetCreateOrUpdateInterface[ any] interface {
	Create(ctx context.Context) error
	Update(ctx context.Context) (rowsAffected int, err error)
}

type ExecInterface[ any] interface {
	Scan(ctx context.Context, r interface{}) error
	First(context.Context) (, error)
	Last(ctx context.Context) (, error)
	Take(context.Context) (, error)
	Find(ctx context.Context) ([], error)
	FindInBatches(ctx context.Context, batchSize int, fc func(data [], batch int) error) error
	Row(ctx context.Context) *sql.Row
	Rows(ctx context.Context) (*sql.Rows, error)
}

type JoinBuilder interface {
	Select(...string) JoinBuilder
	Omit(...string) JoinBuilder
	Where(query interface{}, args ...interface{}) JoinBuilder
	Not(query interface{}, args ...interface{}) JoinBuilder
	Or(query interface{}, args ...interface{}) JoinBuilder
}

type PreloadBuilder interface {
	Select(...string) PreloadBuilder
	Omit(...string) PreloadBuilder
	Where(query interface{}, args ...interface{}) PreloadBuilder
	Not(query interface{}, args ...interface{}) PreloadBuilder
	Or(query interface{}, args ...interface{}) PreloadBuilder
	Limit(offset int) PreloadBuilder
	Offset(offset int) PreloadBuilder
	Order(value interface{}) PreloadBuilder
	LimitPerRecord(num int) PreloadBuilder
}

type op func(*DB) *DB

func [ any]( *DB,  ...clause.Expression) Interface[] {
	 := &g[]{
		db:  ,
		ops: make([]op, 0, 5),
	}

	if len() > 0 {
		.ops = append(.ops, func( *DB) *DB {
			return .Clauses(...)
		})
	}

	.createG = &createG[]{
		chainG: chainG[]{
			execG: execG[]{g: },
		},
	}
	return 
}

type g[ any] struct {
	*createG[]
	db  *DB
	ops []op
}

func ( *g[]) ( context.Context) *DB {
	 := .db
	if !.DryRun {
		 = .Session(&Session{NewDB: true, Context: }).getInstance()
	}

	for ,  := range .ops {
		 = ()
	}
	return 
}

func ( *g[]) ( string,  ...interface{}) ExecInterface[] {
	return execG[]{g: &g[]{
		db: .db,
		ops: append(.ops, func( *DB) *DB {
			var  
			return .Model().Raw(, ...)
		}),
	}}
}

func ( *g[]) ( context.Context,  string,  ...interface{}) error {
	var  
	return .apply().Model().Exec(, ...).Error
}

type createG[ any] struct {
	chainG[]
}

func ( createG[]) ( string,  ...interface{}) CreateInterface[] {
	return createG[]{.with(func( *DB) *DB {
		return .Table(, ...)
	})}
}

func ( createG[]) ( string,  ...interface{}) CreateInterface[] {
	return createG[]{.with(func( *DB) *DB {
		return .Select(, ...)
	})}
}

func ( createG[]) ( ...string) CreateInterface[] {
	return createG[]{.with(func( *DB) *DB {
		return .Omit(...)
	})}
}

func ( createG[]) ( ...clause.Assigner) SetCreateOrUpdateInterface[] {
	return .processSet(...)
}

func ( createG[]) ( context.Context,  *) error {
	return .g.apply().Create().Error
}

func ( createG[]) ( context.Context,  *[],  int) error {
	return .g.apply().CreateInBatches(, ).Error
}

type chainG[ any] struct {
	execG[]
}

func ( chainG[]) () *DB {
	var  
	return .g.apply(context.Background()).Model().getInstance()
}

func ( chainG[]) ( op) chainG[] {
	return chainG[]{
		execG: execG[]{g: &g[]{
			db:  .g.db,
			ops: append(append([]op(nil), .g.ops...), ),
		}},
	}
}

func ( chainG[]) ( string,  ...interface{}) ChainInterface[] {
	return .with(func( *DB) *DB {
		return .Table(, ...)
	})
}

func ( chainG[]) ( ...func( *Statement)) ChainInterface[] {
	return .with(func( *DB) *DB {
		for ,  := range  {
			(.Statement)
		}
		return 
	})
}

func ( chainG[]) ( interface{},  ...interface{}) ChainInterface[] {
	return .with(func( *DB) *DB {
		return .Where(, ...)
	})
}

func ( chainG[]) ( interface{},  ...interface{}) ChainInterface[] {
	return .with(func( *DB) *DB {
		return .Not(, ...)
	})
}

func ( chainG[]) ( interface{},  ...interface{}) ChainInterface[] {
	return .with(func( *DB) *DB {
		return .Or(, ...)
	})
}

func ( chainG[]) ( int) ChainInterface[] {
	return .with(func( *DB) *DB {
		return .Limit()
	})
}

func ( chainG[]) ( int) ChainInterface[] {
	return .with(func( *DB) *DB {
		return .Offset()
	})
}

type joinBuilder struct {
	db *DB
}

func ( *joinBuilder) ( interface{},  ...interface{}) JoinBuilder {
	.db.Where(, ...)
	return 
}

func ( *joinBuilder) ( interface{},  ...interface{}) JoinBuilder {
	.db.Where(, ...)
	return 
}

func ( *joinBuilder) ( interface{},  ...interface{}) JoinBuilder {
	.db.Where(, ...)
	return 
}

func ( *joinBuilder) ( ...string) JoinBuilder {
	.db.Select()
	return 
}

func ( *joinBuilder) ( ...string) JoinBuilder {
	.db.Omit(...)
	return 
}

type preloadBuilder struct {
	limitPerRecord int
	db             *DB
}

func ( *preloadBuilder) ( interface{},  ...interface{}) PreloadBuilder {
	.db.Where(, ...)
	return 
}

func ( *preloadBuilder) ( interface{},  ...interface{}) PreloadBuilder {
	.db.Where(, ...)
	return 
}

func ( *preloadBuilder) ( interface{},  ...interface{}) PreloadBuilder {
	.db.Where(, ...)
	return 
}

func ( *preloadBuilder) ( ...string) PreloadBuilder {
	.db.Select()
	return 
}

func ( *preloadBuilder) ( ...string) PreloadBuilder {
	.db.Omit(...)
	return 
}

func ( *preloadBuilder) ( int) PreloadBuilder {
	.db.Limit()
	return 
}

func ( *preloadBuilder) ( int) PreloadBuilder {
	.db.Offset()
	return 
}

func ( *preloadBuilder) ( interface{}) PreloadBuilder {
	.db.Order()
	return 
}

func ( *preloadBuilder) ( int) PreloadBuilder {
	.limitPerRecord = 
	return 
}

func ( chainG[]) ( clause.JoinTarget,  func( JoinBuilder,  clause.Table,  clause.Table) error) ChainInterface[] {
	return .with(func( *DB) *DB {
		if .Table == "" {
			.Table = clause.JoinTable(strings.Split(.Association, ".")...).Name
		}

		 := joinBuilder{db: .Session(&Session{NewDB: true, Initialized: true}).Table(.Table)}
		if  != nil {
			if  := (&, clause.Table{Name: .Table}, clause.Table{Name: clause.CurrentTable});  != nil {
				.AddError()
			}
		}

		 := join{
			Name:     .Association,
			Alias:    .Table,
			Selects:  .db.Statement.Selects,
			Omits:    .db.Statement.Omits,
			JoinType: .Type,
		}

		if ,  := .db.Statement.Clauses["WHERE"].Expression.(clause.Where);  {
			.On = &
		}

		if .Subquery != nil {
			 := .JoinType
			if  == "" {
				 = clause.LeftJoin
			}

			if ,  := .Subquery.(interface{ () *DB });  {
				 := .().Statement
				if len(.Selects) == 0 {
					.Selects = .Selects
				}
				if len(.Omits) == 0 {
					.Omits = .Omits
				}
			}

			 := clause.NamedExpr{SQL: fmt.Sprintf("%s JOIN (?) AS ?", ), Vars: []interface{}{.Subquery, clause.Table{Name: .Alias}}}

			if .On != nil {
				.SQL += " ON ?"
				.Vars = append(.Vars, clause.AndConditions{Exprs: .On.Exprs})
			}

			.Expression = 
		}

		.Statement.Joins = append(.Statement.Joins, )
		sort.Slice(.Statement.Joins, func(,  int) bool {
			return .Statement.Joins[].Name < .Statement.Joins[].Name
		})
		return 
	})
}

func ( chainG[]) ( string,  ...interface{}) ChainInterface[] {
	return .with(func( *DB) *DB {
		return .Select(, ...)
	})
}

func ( chainG[]) ( ...string) ChainInterface[] {
	return .with(func( *DB) *DB {
		return .Omit(...)
	})
}

func ( chainG[]) ( map[string]string) ChainInterface[] {
	return .with(func( *DB) *DB {
		return .MapColumns()
	})
}

func ( chainG[]) ( ...clause.Assigner) SetUpdateOnlyInterface[] {
	return .processSet(...)
}

func ( chainG[]) ( ...interface{}) ChainInterface[] {
	return .with(func( *DB) *DB {
		return .Distinct(...)
	})
}

func ( chainG[]) ( string) ChainInterface[] {
	return .with(func( *DB) *DB {
		return .Group()
	})
}

func ( chainG[]) ( interface{},  ...interface{}) ChainInterface[] {
	return .with(func( *DB) *DB {
		return .Having(, ...)
	})
}

func ( chainG[]) ( interface{}) ChainInterface[] {
	return .with(func( *DB) *DB {
		return .Order()
	})
}

func ( chainG[]) ( string,  func( PreloadBuilder) error) ChainInterface[] {
	return .with(func( *DB) *DB {
		return .Preload(, func( *DB) *DB {
			 := preloadBuilder{db: .getInstance()}
			if  != nil {
				if  := (&);  != nil {
					.AddError()
				}
			}

			,  := .Statement.Schema.Relationships.Relations[]
			if ! {
				if  := strings.Split(, "."); len() > 1 {
					 := &.Statement.Schema.Relationships
					for ,  := range  {
						var  bool
						,  = .Relations[]
						if  {
							 = &.FieldSchema.Relationships
						} else {
							.AddError(fmt.Errorf("relation %s not found", ))
							return nil
						}
					}
				} else {
					.AddError(fmt.Errorf("relation %s not found", ))
					return nil
				}
			}

			if .limitPerRecord > 0 {
				if .JoinTable != nil {
					.AddError(fmt.Errorf("many2many relation %s don't support LimitPerRecord", ))
					return 
				}

				 := []clause.Column{}
				for ,  := range .References {
					if .OwnPrimaryKey {
						 = append(, clause.Column{Name: .ForeignKey.DBName})
					}
				}

				if len() != 0 {
					 := clause.CommaExpression{}
					for ,  := range .db.Statement.Selects {
						.Exprs = append(.Exprs, clause.Expr{SQL: "?", Vars: []interface{}{clause.Column{Name: }}})
					}

					if len(.Exprs) == 0 {
						.Exprs = []clause.Expression{clause.Expr{SQL: "*", Vars: []interface{}{}}}
					}

					 := clause.CommaExpression{}
					for ,  := range  {
						.Exprs = append(.Exprs, clause.Expr{SQL: "?", Vars: []interface{}{clause.Column{Name: .Name}}})
					}

					 := clause.Column{Name: "gorm_preload_rnn"}
					 := "ROW_NUMBER() OVER (PARTITION BY ? ?)"
					 := []interface{}{}
					if ,  := .db.Statement.Clauses["ORDER BY"];  {
						 = append(, )
					} else {
						 = append(, clause.Clause{Name: "ORDER BY", Expression: clause.OrderBy{
							Columns: []clause.OrderByColumn{{Column: clause.PrimaryColumn, Desc: true}},
						}})
					}
					 = append(, )

					.Exprs = append(.Exprs, clause.Expr{SQL:  + " AS ?", Vars: })

					.db.Clauses(clause.Select{Expression: })

					return .db.Session(&Session{NewDB: true}).Unscoped().Table("(?) t", .db).Where("? <= ?", , .limitPerRecord)
				}
			}

			return .db
		})
	})
}

func ( chainG[]) ( context.Context) ( int,  error) {
	 := new()
	 := .g.apply().Delete()
	return int(.RowsAffected), .Error
}

func ( chainG[]) ( context.Context,  string,  any) ( int,  error) {
	var  
	 := .g.apply().Model().Update(, )
	return int(.RowsAffected), .Error
}

func ( chainG[]) ( context.Context,  ) ( int,  error) {
	 := .g.apply().Updates()
	return int(.RowsAffected), .Error
}

func ( chainG[]) ( context.Context,  string) ( int64,  error) {
	var  
	 = .g.apply().Model().Select().Count(&).Error
	return
}

func ( chainG[]) ( clause.Builder) {
	 := .getInstance()
	.Logger = logger.Discard
	.DryRun = true

	if ,  := .(*Statement);  {
		if .Statement.SQL.Len() > 0 {
			var (
				 = .Statement.Vars
				  = .Statement.SQL.String()
			)

			.Statement.Vars = make([]interface{}, 0, len())
			for ,  := range  {
				.Statement.Vars = append(.Statement.Vars, )
				 := strings.Builder{}
				.BindVarTo(&, .Statement, )
				 = strings.Replace(, .String(), "?", 1)
			}

			.Statement.SQL.Reset()
			.Statement.Vars = .Vars
			if strings.Contains(, "@") {
				clause.NamedExpr{SQL: , Vars: }.Build(.Statement)
			} else {
				clause.Expr{SQL: , Vars: }.Build(.Statement)
			}
		} else {
			.Statement.Vars = append(.Vars, .Statement.Vars...)
			.callbacks.Query().Execute()
		}

		.WriteString(.Statement.SQL.String())
		.Vars = .Statement.Vars
	}
}

type execG[ any] struct {
	g *g[]
}

func ( execG[]) ( context.Context) (, error) {
	var  
	 := .g.apply().First(&).Error
	return , 
}

func ( execG[]) ( context.Context,  interface{}) error {
	var  
	 := .g.apply().Model().Find().Error
	return 
}

func ( execG[]) ( context.Context) (, error) {
	var  
	 := .g.apply().Last(&).Error
	return , 
}

func ( execG[]) ( context.Context) (, error) {
	var  
	 := .g.apply().Take(&).Error
	return , 
}

func ( execG[]) ( context.Context) ([], error) {
	var  []
	 := .g.apply().Find(&).Error
	return , 
}

func ( execG[]) ( context.Context,  int,  func( [],  int) error) error {
	var  []
	return .g.apply().FindInBatches(&, , func( *DB,  int) error {
		return (, )
	}).Error
}

func ( execG[]) ( context.Context) *sql.Row {
	return .g.apply().Row()
}

func ( execG[]) ( context.Context) (*sql.Rows, error) {
	return .g.apply().Rows()
}

func ( chainG[]) ( ...clause.Assigner) setCreateOrUpdateG[] {
	var (
		  []clause.Assignment
		 []clause.Association
	)

	for ,  := range  {
		// Check if it's an AssociationAssigner
		if ,  := .(clause.AssociationAssigner);  {
			 = append(, .AssociationAssignments()...)
		} else {
			 = append(, .Assignments()...)
		}
	}

	return setCreateOrUpdateG[]{
		c:        ,
		assigns:  ,
		assocOps: ,
	}
}

// setCreateOrUpdateG[T] is a struct that holds operations to be executed in a batch.
// It supports regular assignments and association operations.
type setCreateOrUpdateG[ any] struct {
	c        chainG[]
	assigns  []clause.Assignment
	assocOps []clause.Association
}

func ( setCreateOrUpdateG[]) ( context.Context) ( int,  error) {
	// Execute association operations
	for ,  := range .assocOps {
		if  := .executeAssociationOperation(, );  != nil {
			return 0, 
		}
	}

	// Execute assignment operations
	if len(.assigns) > 0 {
		var  
		 := .c.g.apply().Model().Clauses(clause.Set(.assigns)).Updates(map[string]interface{}{})
		return int(.RowsAffected), .Error
	}

	return 0, nil
}

func ( setCreateOrUpdateG[]) ( context.Context) error {
	// Execute association operations
	for ,  := range .assocOps {
		if  := .executeAssociationOperation(, );  != nil {
			return 
		}
	}

	// Execute assignment operations
	if len(.assigns) > 0 {
		 := make(map[string]interface{}, len(.assigns))
		for ,  := range .assigns {
			[.Column.Name] = .Value
		}
		var  
		return .c.g.apply().Model().Create().Error
	}

	return nil
}

// executeAssociationOperation executes an association operation
func ( setCreateOrUpdateG[]) ( context.Context,  clause.Association) error {
	var  
	 := .c.g.apply().Model()

	switch .Type {
	case clause.OpCreate:
		return .handleAssociationCreate(, , )
	case clause.OpUnlink, clause.OpDelete, clause.OpUpdate:
		return .handleAssociation(, , )
	default:
		return fmt.Errorf("unknown association operation type: %v", .Type)
	}
}

func ( setCreateOrUpdateG[]) ( context.Context,  *DB,  clause.Association) error {
	if len(.Set) > 0 {
		return .handleAssociationForOwners(, , func( ,  *Association) error {
			 := make(map[string]interface{}, len(.Set))
			for ,  := range .Set {
				[.Column.Name] = .Value
			}
			return .Append()
		}, .Association)
	}

	return .handleAssociationForOwners(, , func( ,  *Association) error {
		return .Append(.Values...)
	}, .Association)
}

// handleAssociationForOwners is a helper function that handles associations for all owners
func ( setCreateOrUpdateG[]) ( *DB,  context.Context,  func( ,  *Association) error,  string) error {
	var  []
	if  := .Find(&).Error;  != nil {
		return 
	}

	for ,  := range  {
		 := .Session(&Session{NewDB: true, Context: }).Model(&).Association()
		if .Error != nil {
			return .Error
		}

		if  := (, );  != nil {
			return 
		}
	}
	return nil
}

func ( setCreateOrUpdateG[]) ( context.Context,  *DB,  clause.Association) error {
	 := .Association(.Association)
	if .Error != nil {
		return .Error
	}

	var (
		            = .Relationship
		     = reflect.New(.FieldSchema.ModelType).Interface()
		          = map[string]any{}
		         = make(map[string]any, len(.Set))
		   []string
		   []string
		 []any
		 []any
	)

	for ,  := range .Set {
		[.Column.Name] = .Value
	}

	for ,  := range .References {
		[.ForeignKey.DBName] = nil

		if .OwnPrimaryKey && .PrimaryKey != nil {
			 = append(, .PrimaryKey.DBName)
			 = append(, clause.Column{Name: .PrimaryKey.DBName})
			 = append(, clause.Column{Name: .ForeignKey.DBName})
		} else if !.OwnPrimaryKey && .PrimaryKey != nil {
			 = append(, .ForeignKey.DBName)
			 = append(, clause.Column{Name: .PrimaryKey.DBName})
		}
	}

	 := .c.g.db.Session(&Session{NewDB: true, Context: }).Model().Where(.Conditions)

	switch .Type {
	case schema.HasOne, schema.HasMany:
		 = .Where("? IN (?)", , .Select())
		switch .Type {
		case clause.OpUnlink:
			return .Updates().Error
		case clause.OpDelete:
			return .Delete().Error
		case clause.OpUpdate:
			return .Updates().Error
		}
	case schema.BelongsTo:
		switch .Type {
		case clause.OpDelete:
			return .Transaction(func( *DB) error {
				.Statement.ConnPool = .Statement.ConnPool
				.Statement.ConnPool = .Statement.ConnPool

				if  := .Where("? IN (?)", , .Select()).Delete().Error;  != nil {
					return 
				}
				return .Updates().Error
			})
		case clause.OpUnlink:
			return .Updates().Error
		case clause.OpUpdate:
			return .Where("? IN (?)", , .Select()).Updates().Error
		}
	case schema.Many2Many:
		 := reflect.New(.JoinTable.ModelType).Interface()
		 := .Session(&Session{NewDB: true, Context: }).Model()

		// EXISTS owners: owners.pk = join.owner_fk for all owner refs
		 := .Session(&Session{NewDB: true, Context: }).Table(.Schema.Table).Select("1")
		for ,  := range .References {
			if .OwnPrimaryKey && .PrimaryKey != nil {
				 = .Where(clause.Eq{
					Column: clause.Column{Table: .Schema.Table, Name: .PrimaryKey.DBName},
					Value:  clause.Column{Table: .JoinTable.Table, Name: .ForeignKey.DBName},
				})
			}
		}

		// EXISTS related: related.pk = join.rel_fk for all related refs, plus optional conditions
		 := .Session(&Session{NewDB: true, Context: }).Table(.FieldSchema.Table).Select("1")
		for ,  := range .References {
			if !.OwnPrimaryKey && .PrimaryKey != nil {
				 = .Where(clause.Eq{
					Column: clause.Column{Table: .FieldSchema.Table, Name: .PrimaryKey.DBName},
					Value:  clause.Column{Table: .JoinTable.Table, Name: .ForeignKey.DBName},
				})
			}
		}
		 = .Where(.Conditions)

		switch .Type {
		case clause.OpUnlink, clause.OpDelete:
			 = .Where("EXISTS (?)", )
			if len(.Conditions) > 0 {
				 = .Where("EXISTS (?)", )
			}
			return .Delete(nil).Error
		case clause.OpUpdate:
			// Update related table rows that have join rows matching owners
			 := .Session(&Session{NewDB: true, Context: }).Table(.FieldSchema.Table).Where(.Conditions)

			// correlated join subquery: join.rel_fk = related.pk AND EXISTS owners
			 := .Session(&Session{NewDB: true, Context: }).Table(.JoinTable.Table).Select("1")
			for ,  := range .References {
				if !.OwnPrimaryKey && .PrimaryKey != nil {
					 = .Where(clause.Eq{
						Column: clause.Column{Table: .JoinTable.Table, Name: .ForeignKey.DBName},
						Value:  clause.Column{Table: .FieldSchema.Table, Name: .PrimaryKey.DBName},
					})
				}
			}
			 = .Where("EXISTS (?)", )
			return .Where("EXISTS (?)", ).Updates().Error
		}
	}
	return errors.New("unsupported relationship")
}