package callbacks

import (
	
	
	
	

	
	
	
	
)

func ( *gorm.DB) {
	if .Error == nil {
		BuildQuerySQL()

		if !.DryRun && .Error == nil {
			,  := .Statement.ConnPool.QueryContext(.Statement.Context, .Statement.SQL.String(), .Statement.Vars...)
			if  != nil {
				.AddError()
				return
			}
			defer func() {
				.AddError(.Close())
			}()
			gorm.Scan(, , 0)
		}
	}
}

func ( *gorm.DB) {
	if .Statement.Schema != nil {
		for ,  := range .Statement.Schema.QueryClauses {
			.Statement.AddClause()
		}
	}

	if .Statement.SQL.Len() == 0 {
		.Statement.SQL.Grow(100)
		 := clause.Select{Distinct: .Statement.Distinct}

		if .Statement.ReflectValue.Kind() == reflect.Struct && .Statement.ReflectValue.Type() == .Statement.Schema.ModelType {
			var  []clause.Expression
			for ,  := range .Statement.Schema.PrimaryFields {
				if ,  := .ValueOf(.Statement.Context, .Statement.ReflectValue); ! {
					 = append(, clause.Eq{Column: clause.Column{Table: .Statement.Table, Name: .DBName}, Value: })
				}
			}

			if len() > 0 {
				.Statement.AddClause(clause.Where{Exprs: })
			}
		}

		if len(.Statement.Selects) > 0 {
			.Columns = make([]clause.Column, len(.Statement.Selects))
			for ,  := range .Statement.Selects {
				if .Statement.Schema == nil {
					.Columns[] = clause.Column{Name: , Raw: true}
				} else if  := .Statement.Schema.LookUpField();  != nil {
					.Columns[] = clause.Column{Name: .DBName}
				} else {
					.Columns[] = clause.Column{Name: , Raw: true}
				}
			}
		} else if .Statement.Schema != nil && len(.Statement.Omits) > 0 {
			,  := .Statement.SelectAndOmitColumns(false, false)
			.Columns = make([]clause.Column, 0, len(.Statement.Schema.DBNames))
			for ,  := range .Statement.Schema.DBNames {
				if ,  := []; ( && ) || ! {
					.Columns = append(.Columns, clause.Column{Table: .Statement.Table, Name: })
				}
			}
		} else if .Statement.Schema != nil && .Statement.ReflectValue.IsValid() {
			 := .QueryFields
			if ! {
				switch .Statement.ReflectValue.Kind() {
				case reflect.Struct:
					 = .Statement.ReflectValue.Type() != .Statement.Schema.ModelType
				case reflect.Slice:
					 = .Statement.ReflectValue.Type().Elem() != .Statement.Schema.ModelType
				}
			}

			if  {
				 := gorm.Statement{DB: }
				// smaller struct
				if  := .Parse(.Statement.Dest);  == nil && (.QueryFields || .Schema.ModelType != .Statement.Schema.ModelType) {
					.Columns = make([]clause.Column, len(.Schema.DBNames))

					for ,  := range .Schema.DBNames {
						.Columns[] = clause.Column{Table: .Statement.Table, Name: }
					}
				}
			}
		}

		// inline joins
		 := clause.From{}
		if ,  := .Statement.Clauses["FROM"].Expression.(clause.From);  {
			 = 
		}

		if len(.Statement.Joins) != 0 || len(.Joins) != 0 {
			if len(.Statement.Selects) == 0 && len(.Statement.Omits) == 0 && .Statement.Schema != nil {
				.Columns = make([]clause.Column, len(.Statement.Schema.DBNames))
				for ,  := range .Statement.Schema.DBNames {
					.Columns[] = clause.Column{Table: .Statement.Table, Name: }
				}
			}

			 := make(map[string]interface{})
			for ,  := range .Statement.Joins {
				if .Statement.Schema != nil {
					var  bool // is relations or raw sql
					var  []*schema.Relationship
					,  := .Statement.Schema.Relationships.Relations[.Name]
					if  {
						 = true
						 = append(, )
					} else {
						// handle nested join like "Manager.Company"
						 := strings.Split(.Name, ".")
						if len() > 1 {
							 := true
							 := make([]*schema.Relationship, 0, len())
							 := .Statement.Schema.Relationships.Relations
							for ,  := range  {
								// incomplete match, only treated as raw sql
								if ,  = [];  {
									 = append(, )
									 = .FieldSchema.Relationships.Relations
								} else {
									 = false
									break
								}
							}

							if  {
								 = true
								 = 
							}
						}
					}

					if  {
						 := func( clause.JoinType,  string,  *schema.Relationship) clause.Join {
							 := .Name
							if  != clause.CurrentTable {
								 = utils.NestedRelationName(, )
							}

							 := gorm.Statement{
								Table: , DB: , Schema: .FieldSchema,
								Selects: .Selects, Omits: .Omits,
							}

							,  := .SelectAndOmitColumns(false, false)
							for ,  := range .FieldSchema.DBNames {
								if ,  := []; ( && ) || (! && !) {
									.Columns = append(.Columns, clause.Column{
										Table: ,
										Name:  ,
										Alias: utils.NestedRelationName(, ),
									})
								}
							}

							 := make([]clause.Expression, len(.References))
							for ,  := range .References {
								if .OwnPrimaryKey {
									[] = clause.Eq{
										Column: clause.Column{Table: , Name: .PrimaryKey.DBName},
										Value:  clause.Column{Table: , Name: .ForeignKey.DBName},
									}
								} else {
									if .PrimaryValue == "" {
										[] = clause.Eq{
											Column: clause.Column{Table: , Name: .ForeignKey.DBName},
											Value:  clause.Column{Table: , Name: .PrimaryKey.DBName},
										}
									} else {
										[] = clause.Eq{
											Column: clause.Column{Table: , Name: .ForeignKey.DBName},
											Value:  .PrimaryValue,
										}
									}
								}
							}

							{
								 := gorm.Statement{Table: , DB: , Clauses: map[string]clause.Clause{}}
								for ,  := range .FieldSchema.QueryClauses {
									.AddClause()
								}

								if .On != nil {
									.AddClause(.On)
								}

								if ,  := .Clauses["WHERE"];  {
									if ,  := .Expression.(clause.Where);  {
										.Build(&)

										if  := .SQL.String();  != "" {
											 := .Vars
											for ,  := range  {
												 := strings.Builder{}
												.Vars = [0 : +1]
												.Dialector.BindVarTo(&, &, )
												 = strings.Replace(, .String(), "?", 1)
											}

											 = append(, clause.Expr{SQL: , Vars: })
										}
									}
								}
							}

							return clause.Join{
								Type:  ,
								Table: clause.Table{Name: .FieldSchema.Table, Alias: },
								ON:    clause.Where{Exprs: },
							}
						}

						 := clause.CurrentTable
						for ,  := range  {
							// joins table alias like "Manager, Company, Manager__Company"
							 := utils.NestedRelationName(, .Name)
							if ,  := []; ! {
								.Joins = append(.Joins, (.JoinType, , ))
								[] = nil
							}

							if  != clause.CurrentTable {
								 = utils.NestedRelationName(, .Name)
							} else {
								 = .Name
							}
						}
					} else {
						.Joins = append(.Joins, clause.Join{
							Expression: clause.NamedExpr{SQL: .Name, Vars: .Conds},
						})
					}
				} else {
					.Joins = append(.Joins, clause.Join{
						Expression: clause.NamedExpr{SQL: .Name, Vars: .Conds},
					})
				}
			}

			.Statement.AddClause()
			.Statement.Joins = nil
		} else {
			.Statement.AddClauseIfNotExists(clause.From{})
		}

		.Statement.AddClauseIfNotExists()

		.Statement.Build(.Statement.BuildClauses...)
	}
}

func ( *gorm.DB) {
	if .Error == nil && len(.Statement.Preloads) > 0 {
		if .Statement.Schema == nil {
			.AddError(fmt.Errorf("%w when using preload", gorm.ErrModelValueRequired))
			return
		}

		 := parsePreloadMap(.Statement.Schema, .Statement.Preloads)
		 := make([]string, 0, len())
		for  := range  {
			 = append(, )
		}
		sort.Strings()

		 := .Session(&gorm.Session{Context: .Statement.Context, NewDB: true, SkipHooks: .Statement.SkipHooks, Initialized: true})
		.Statement.Settings.Range(func(,  interface{}) bool {
			.Statement.Settings.Store(, )
			return true
		})

		if  := .Statement.Parse(.Statement.Dest);  != nil {
			return
		}
		.Statement.ReflectValue = .Statement.ReflectValue
		.Statement.Unscoped = .Statement.Unscoped

		for ,  := range  {
			if  := .Statement.Schema.Relationships.EmbeddedRelations[];  != nil {
				.AddError(preloadEmbedded(.Table("").Session(&gorm.Session{Context: .Statement.Context, SkipHooks: .Statement.SkipHooks}), , .Statement.Schema, [], .Statement.Preloads[clause.Associations]))
			} else if  := .Statement.Schema.Relationships.Relations[];  != nil {
				.AddError(preload(.Table("").Session(&gorm.Session{Context: .Statement.Context, SkipHooks: .Statement.SkipHooks}), , append(.Statement.Preloads[], .Statement.Preloads[clause.Associations]...), []))
			} else {
				.AddError(fmt.Errorf("%s: %w for schema %s", , gorm.ErrUnsupportedRelation, .Statement.Schema.Name))
			}
		}
	}
}

func ( *gorm.DB) {
	if .Error == nil && .Statement.Schema != nil && !.Statement.SkipHooks && .Statement.Schema.AfterFind && .RowsAffected > 0 {
		callMethod(, func( interface{},  *gorm.DB) bool {
			if ,  := .(AfterFindInterface);  {
				.AddError(.AfterFind())
				return true
			}
			return false
		})
	}
}