Full Code of go-gorm/gorm for AI

master 4380dd6dd1a5 cached
184 files
1.2 MB
367.6k tokens
1607 symbols
1 requests
Download .txt
Showing preview only (1,293K chars total). Download the full file or copy to clipboard to get everything.
Repository: go-gorm/gorm
Branch: master
Commit: 4380dd6dd1a5
Files: 184
Total size: 1.2 MB

Directory structure:
gitextract_lfhwtntz/

├── .github/
│   ├── FUNDING.yml
│   ├── dependabot.yml
│   ├── labels.json
│   ├── release-drafter.yml
│   └── workflows/
│       ├── create-release.yml
│       ├── golangci-lint.yml
│       ├── invalid_question.yml
│       ├── labeler.yml
│       ├── missing_playground.yml
│       ├── stale.yml
│       └── tests.yml
├── .gitignore
├── .golangci.yml
├── CODE_OF_CONDUCT.md
├── LICENSE
├── README.md
├── association.go
├── callbacks/
│   ├── associations.go
│   ├── callbacks.go
│   ├── callmethod.go
│   ├── create.go
│   ├── create_test.go
│   ├── delete.go
│   ├── helper.go
│   ├── helper_test.go
│   ├── interfaces.go
│   ├── preload.go
│   ├── query.go
│   ├── raw.go
│   ├── row.go
│   ├── transaction.go
│   └── update.go
├── callbacks.go
├── chainable_api.go
├── clause/
│   ├── association.go
│   ├── benchmarks_test.go
│   ├── clause.go
│   ├── clause_test.go
│   ├── delete.go
│   ├── delete_test.go
│   ├── expression.go
│   ├── expression_test.go
│   ├── from.go
│   ├── from_test.go
│   ├── group_by.go
│   ├── group_by_test.go
│   ├── insert.go
│   ├── insert_test.go
│   ├── joins.go
│   ├── joins_test.go
│   ├── limit.go
│   ├── limit_test.go
│   ├── locking.go
│   ├── locking_test.go
│   ├── on_conflict.go
│   ├── order_by.go
│   ├── order_by_test.go
│   ├── returning.go
│   ├── returning_test.go
│   ├── select.go
│   ├── select_test.go
│   ├── set.go
│   ├── set_test.go
│   ├── update.go
│   ├── update_test.go
│   ├── values.go
│   ├── values_test.go
│   ├── where.go
│   ├── where_test.go
│   └── with.go
├── errors.go
├── finisher_api.go
├── generics.go
├── go.mod
├── go.sum
├── gorm.go
├── interfaces.go
├── internal/
│   ├── lru/
│   │   └── lru.go
│   └── stmt_store/
│       └── stmt_store.go
├── logger/
│   ├── logger.go
│   ├── slog.go
│   ├── slog_test.go
│   ├── sql.go
│   └── sql_test.go
├── migrator/
│   ├── column_type.go
│   ├── index.go
│   ├── migrator.go
│   └── table_type.go
├── migrator.go
├── model.go
├── prepare_stmt.go
├── scan.go
├── schema/
│   ├── callbacks_test.go
│   ├── constraint.go
│   ├── constraint_test.go
│   ├── field.go
│   ├── field_test.go
│   ├── index.go
│   ├── index_test.go
│   ├── interfaces.go
│   ├── model_test.go
│   ├── naming.go
│   ├── naming_test.go
│   ├── pool.go
│   ├── relationship.go
│   ├── relationship_test.go
│   ├── schema.go
│   ├── schema_helper_test.go
│   ├── schema_test.go
│   ├── serializer.go
│   ├── serializer_test.go
│   ├── utils.go
│   └── utils_test.go
├── soft_delete.go
├── statement.go
├── statement_test.go
├── tests/
│   ├── .gitignore
│   ├── README.md
│   ├── association_generics_test.go
│   ├── associations_belongs_to_test.go
│   ├── associations_has_many_test.go
│   ├── associations_has_one_test.go
│   ├── associations_many2many_test.go
│   ├── associations_test.go
│   ├── benchmark_test.go
│   ├── callbacks_test.go
│   ├── chainable_api_test.go
│   ├── compose.yml
│   ├── connection_test.go
│   ├── connpool_test.go
│   ├── count_test.go
│   ├── create_test.go
│   ├── customize_field_test.go
│   ├── default_value_test.go
│   ├── delete_test.go
│   ├── distinct_test.go
│   ├── embedded_struct_test.go
│   ├── error_translator_test.go
│   ├── gaussdb_test.go
│   ├── generics_test.go
│   ├── go.mod
│   ├── gorm_test.go
│   ├── group_by_test.go
│   ├── helper_test.go
│   ├── hooks_test.go
│   ├── joins_table_test.go
│   ├── joins_test.go
│   ├── lru_test.go
│   ├── main_test.go
│   ├── migrate_test.go
│   ├── multi_primary_keys_test.go
│   ├── named_argument_test.go
│   ├── named_polymorphic_test.go
│   ├── non_std_test.go
│   ├── postgres_test.go
│   ├── preload_suits_test.go
│   ├── preload_test.go
│   ├── prepared_stmt_test.go
│   ├── query_test.go
│   ├── scan_test.go
│   ├── scanner_valuer_test.go
│   ├── scopes_test.go
│   ├── serializer_test.go
│   ├── soft_delete_test.go
│   ├── sql_builder_test.go
│   ├── submodel_test.go
│   ├── table_test.go
│   ├── tests_all.sh
│   ├── tests_test.go
│   ├── tracer_test.go
│   ├── transaction_test.go
│   ├── update_belongs_to_test.go
│   ├── update_has_many_test.go
│   ├── update_has_one_test.go
│   ├── update_many2many_test.go
│   ├── update_test.go
│   └── upsert_test.go
└── utils/
    ├── tests/
    │   ├── dummy_dialecter.go
    │   ├── models.go
    │   └── utils.go
    ├── utils.go
    ├── utils_test.go
    ├── utils_unix_test.go
    └── utils_windows_test.go

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms

github: [jinzhu]
patreon: jinzhu
open_collective: gorm


================================================
FILE: .github/dependabot.yml
================================================
---
version: 2
updates:
  - package-ecosystem: gomod
    directory: /
    schedule:
      interval: weekly
  - package-ecosystem: github-actions
    directory: /
    schedule:
      interval: weekly
  - package-ecosystem: gomod
    directory: /tests
    schedule:
      interval: weekly


================================================
FILE: .github/labels.json
================================================
{
  "labels": {
    "critical": {
      "name": "type:critical",
      "colour": "#E84137",
      "description": "critical questions"
    },
    "question": {
      "name": "type:question",
      "colour": "#EDEDED",
      "description": "general questions"
    },
    "feature": {
      "name": "type:feature_request",
      "colour": "#43952A",
      "description": "feature request"
    },
    "invalid_question": {
      "name": "type:invalid question",
      "colour": "#CF2E1F",
      "description": "invalid question (not related to GORM or described in document or not enough information provided)"
    },
    "with_playground": {
      "name": "type:with reproduction steps",
      "colour": "#00ff00",
      "description": "with reproduction steps"
    },
    "without_playground": {
      "name": "type:missing reproduction steps",
      "colour": "#CF2E1F",
      "description": "missing reproduction steps"
    },
    "has_pr": {
      "name": "type:has pull request",
      "colour": "#43952A",
      "description": "has pull request"
    },
    "not_tested": {
      "name": "type:not tested",
      "colour": "#CF2E1F",
      "description": "not tested"
    },
    "tested": {
      "name": "type:tested",
      "colour": "#00ff00",
      "description": "tested"
    },
    "breaking_change": {
      "name": "type:breaking change",
      "colour": "#CF2E1F",
      "description": "breaking change"
    }
  },
  "issue": {
    "with_playground": {
      "requires": 1,
      "conditions": [
        {
          "type": "descriptionMatches",
          "pattern": "/github.com\/go-gorm\/playground\/pull\/\\d\\d+/s"
        }
      ]
    },
    "critical": {
      "requires": 1,
      "conditions": [
        {
          "type": "descriptionMatches",
          "pattern": "/(critical|urgent)/i"
        },
        {
          "type": "titleMatches",
          "pattern": "/(critical|urgent)/i"
        }
      ]
    },
    "question": {
      "requires": 1,
      "conditions": [
        {
          "type": "titleMatches",
          "pattern": "/question/i"
        },
        {
          "type": "descriptionMatches",
          "pattern": "/question/i"
        }
      ]
    },
    "feature": {
      "requires": 1,
      "conditions": [
        {
          "type": "titleMatches",
          "pattern": "/feature/i"
        },
        {
          "type": "descriptionMatches",
          "pattern": "/Describe the feature/i"
        }
      ]
    },
    "without_playground": {
      "requires": 6,
      "conditions": [
        {
          "type": "descriptionMatches",
          "pattern": "/^((?!github.com\/go-gorm\/playground\/pull\/\\d\\d+).)*$/s"
        },
        {
          "type": "titleMatches",
          "pattern": "/^((?!question).)*$/s"
        },
        {
          "type": "descriptionMatches",
          "pattern": "/^((?!question).)*$/is"
        },
        {
          "type": "descriptionMatches",
          "pattern": "/^((?!Describe the feature).)*$/is"
        },
        {
          "type": "titleMatches",
          "pattern": "/^((?!critical|urgent).)*$/s"
        },
        {
          "type": "descriptionMatches",
          "pattern": "/^((?!critical|urgent).)*$/s"
        }
      ]
    }
  },
  "pr": {
    "critical": {
      "requires": 1,
      "conditions": [
        {
          "type": "descriptionMatches",
          "pattern": "/(critical|urgent)/i"
        },
        {
          "type": "titleMatches",
          "pattern": "/(critical|urgent)/i"
        }
      ]
    },
    "not_tested": {
      "requires": 1,
      "conditions": [
        {
          "type": "descriptionMatches",
          "pattern": "/\\[\\] Tested/"
        }
      ]
    },
    "breaking_change": {
      "requires": 1,
      "conditions": [
        {
          "type": "descriptionMatches",
          "pattern": "/\\[\\] Non breaking API changes/"
        }
      ]
    }
  }
}


================================================
FILE: .github/release-drafter.yml
================================================
name-template: 'v Release $NEXT_PATCH_VERSION 🌈'
tag-template: 'v$NEXT_PATCH_VERSION'
categories:
  - title: '🚀 Features'
    labels:
      - 'feature'
      - 'enhancement'
  - title: '🐛 Bug Fixes'
    labels:
      - 'fix'
      - 'bugfix'
      - 'bug'
  - title: '🧰 Maintenance'
    label: 'chore'
change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
change-title-escapes: '\<*_&'
template: |
  ## Changes

  $CHANGES

================================================
FILE: .github/workflows/create-release.yml
================================================
name: Create Release

on:
  push:
    tags:
      - 'v*.*.*'

permissions:
  contents: write
  pull-requests: read

jobs:
  create_release:
    name: Create Release
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Generate Release Notes and Publish
        id: generate_release_notes
        uses: release-drafter/release-drafter@v6
        with:
          config-name: 'release-drafter.yml'
          name: "Release ${{ github.ref_name }}"
          tag: ${{ github.ref_name }}
          publish: true
          prerelease: false
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}


================================================
FILE: .github/workflows/golangci-lint.yml
================================================
name: golangci-lint
on:
  push:
    branches:
      - main
      - master
  pull_request:

permissions:
  contents: read
  pull-requests: read

jobs:
  golangci:
    name: lint
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-go@v5
        with:
          go-version: stable
      - name: golangci-lint
        uses: golangci/golangci-lint-action@v7
        with:
          version: v2.0
          only-new-issues: true


================================================
FILE: .github/workflows/invalid_question.yml
================================================
name: "Close invalid questions issues"
on:
  schedule:
  - cron: "*/10 * * * *"

permissions:
  contents: read

jobs:
  stale:
    permissions:
      issues: write  # for actions/stale to close stale issues
      pull-requests: write  # for actions/stale to close stale PRs
    runs-on: ubuntu-latest
    env:
      ACTIONS_STEP_DEBUG: true
    steps:
    - name: Close Stale Issues
      uses: actions/stale@v8
      with:
        repo-token: ${{ secrets.GITHUB_TOKEN }}
        stale-issue-message: "This issue has been marked as invalid question, please give more information by following the `Question` template, if you believe there is a bug of GORM, please create a pull request that could reproduce the issue on [https://github.com/go-gorm/playground](https://github.com/go-gorm/playground), the issue will be closed in 30 days if no further activity occurs. most likely your question already answered https://github.com/go-gorm/gorm/issues or described in the document https://gorm.io ✨ [Search Before Asking](https://stackoverflow.com/help/how-to-ask) ✨"
        stale-issue-label: "status:stale"
        days-before-stale: 0
        days-before-close: 30
        remove-stale-when-updated: true
        only-labels: "type:invalid question"



================================================
FILE: .github/workflows/labeler.yml
================================================
name: "Issue Labeler"
on:
  issues:
    types: [opened, edited, reopened]
  pull_request:
    types: [opened, edited, reopened]

jobs:
  triage:
    runs-on: ubuntu-latest
    name: Label issues and pull requests
    steps:
      - name: check out
        uses: actions/checkout@v4

      - name: labeler
        uses: jinzhu/super-labeler-action@develop
        with:
          GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"


================================================
FILE: .github/workflows/missing_playground.yml
================================================
name: "Close Missing Playground issues"
on:
  schedule:
  - cron: "*/10 * * * *"

permissions:
  contents: read

jobs:
  stale:
    permissions:
      issues: write  # for actions/stale to close stale issues
      pull-requests: write  # for actions/stale to close stale PRs
    runs-on: ubuntu-latest
    env:
      ACTIONS_STEP_DEBUG: true
    steps:
    - name: Close Stale Issues
      uses: actions/stale@v8
      with:
        repo-token: ${{ secrets.GITHUB_TOKEN }}
        stale-issue-message: "The issue has been automatically marked as stale as it missing playground pull request link, which is important to help others understand your issue effectively and make sure the issue hasn't been fixed on latest master, checkout [https://github.com/go-gorm/playground](https://github.com/go-gorm/playground) for details. it will be closed in 30 days if no further activity occurs. if you are asking question, please use the `Question` template, most likely your question already answered https://github.com/go-gorm/gorm/issues or described in the document https://gorm.io ✨ [Search Before Asking](https://stackoverflow.com/help/how-to-ask) ✨"
        stale-issue-label: "status:stale"
        days-before-stale: 0
        days-before-close: 30
        remove-stale-when-updated: true
        only-labels: "type:missing reproduction steps"


================================================
FILE: .github/workflows/stale.yml
================================================
name: "Stale"
on:
  schedule:
  - cron: "0 2 * * *"

permissions:
  contents: read

jobs:
  stale:
    permissions:
      issues: write  # for actions/stale to close stale issues
      pull-requests: write  # for actions/stale to close stale PRs
    runs-on: ubuntu-latest
    env:
      ACTIONS_STEP_DEBUG: true
    steps:
    - name: Close Stale Issues
      uses: actions/stale@v8
      with:
        repo-token: ${{ secrets.GITHUB_TOKEN }}
        stale-issue-message: "This issue has been automatically marked as stale because it has been open 360 days with no activity. Remove stale label or comment or this will be closed in 180 days"
        days-before-stale: 360
        days-before-close: 180
        stale-issue-label: "status:stale"
        exempt-issue-labels: 'type:feature,type:with reproduction steps,type:has pull request'
        stale-pr-label: 'status:stale'
        exempt-pr-labels: 'type:feature,type:with reproduction steps,type:has pull request'


================================================
FILE: .github/workflows/tests.yml
================================================
name: tests

on:
  push:
    branches-ignore:
      - 'gh-pages'
  pull_request:
    branches-ignore:
      - 'gh-pages'

permissions:
  contents: read

jobs:
  # Label of the container job
  sqlite:
    strategy:
      matrix:
        go: ['1.24', '1.25']
        platform: [ubuntu-latest] # can not run in windows OS
    runs-on: ${{ matrix.platform }}

    steps:
    - name: Set up Go 1.x
      uses: actions/setup-go@v4
      with:
        go-version: ${{ matrix.go }}

    - name: Check out code into the Go module directory
      uses: actions/checkout@v4

    - name: go mod package cache
      uses: actions/cache@v4
      with:
        path: ~/go/pkg/mod
        key: ${{ runner.os }}-go-${{ matrix.go }}-${{ hashFiles('tests/go.mod') }}

    - name: Tests
      run: GITHUB_ACTION=true GORM_DIALECT=sqlite ./tests/tests_all.sh

  mysql:
    strategy:
      matrix:
        dbversion: ['mysql:9', 'mysql:8', 'mysql:5.7']
        go: ['1.24', '1.25']
        platform: [ubuntu-latest]
    runs-on: ${{ matrix.platform }}

    services:
      mysql:
        image: ${{ matrix.dbversion }}
        env:
          MYSQL_DATABASE: gorm
          MYSQL_USER: gorm
          MYSQL_PASSWORD: gorm
          MYSQL_RANDOM_ROOT_PASSWORD: "yes"
        ports:
          - 9910:3306
        options: >-
          --health-cmd "mysqladmin ping -ugorm -pgorm"
          --health-interval 10s
          --health-start-period 10s
          --health-timeout 5s
          --health-retries 10

    steps:
    - name: Set up Go 1.x
      uses: actions/setup-go@v4
      with:
        go-version: ${{ matrix.go }}

    - name: Check out code into the Go module directory
      uses: actions/checkout@v4

    - name: go mod package cache
      uses: actions/cache@v4
      with:
        path: ~/go/pkg/mod
        key: ${{ runner.os }}-go-${{ matrix.go }}-${{ hashFiles('tests/go.mod') }}

    - name: Tests
      run: GITHUB_ACTION=true GORM_DIALECT=mysql GORM_DSN="gorm:gorm@tcp(localhost:9910)/gorm?charset=utf8&parseTime=True" ./tests/tests_all.sh

  mariadb:
    strategy:
      matrix:
        dbversion: [ 'mariadb:latest' ]
        go: ['1.24', '1.25']
        platform: [ ubuntu-latest ]
    runs-on: ${{ matrix.platform }}

    services:
      mysql:
        image: ${{ matrix.dbversion }}
        env:
          MYSQL_DATABASE: gorm
          MYSQL_USER: gorm
          MYSQL_PASSWORD: gorm
          MYSQL_RANDOM_ROOT_PASSWORD: "yes"
        ports:
          - 9910:3306
        options: >-
          --health-cmd "mariadb-admin ping -ugorm -pgorm"
          --health-interval 10s
          --health-start-period 10s
          --health-timeout 5s
          --health-retries 10

    steps:
      - name: Set up Go 1.x
        uses: actions/setup-go@v4
        with:
          go-version: ${{ matrix.go }}

      - name: Check out code into the Go module directory
        uses: actions/checkout@v4

      - name: go mod package cache
        uses: actions/cache@v4
        with:
          path: ~/go/pkg/mod
          key: ${{ runner.os }}-go-${{ matrix.go }}-${{ hashFiles('tests/go.mod') }}

      - name: Tests
        run: GITHUB_ACTION=true GORM_DIALECT=mysql GORM_DSN="gorm:gorm@tcp(localhost:9910)/gorm?charset=utf8&parseTime=True" ./tests/tests_all.sh

  postgres:
    strategy:
      matrix:
        dbversion: ['postgres:latest', 'postgres:15', 'postgres:14', 'postgres:13']
        go: ['1.24', '1.25']
        platform: [ubuntu-latest] # can not run in macOS and Windows
    runs-on: ${{ matrix.platform }}

    services:
      postgres:
        image: ${{ matrix.dbversion }}
        env:
          POSTGRES_PASSWORD: gorm
          POSTGRES_USER: gorm
          POSTGRES_DB: gorm
          TZ: Asia/Shanghai
        ports:
          - 9920:5432
        # Set health checks to wait until postgres has started
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5

    steps:
    - name: Set up Go 1.x
      uses: actions/setup-go@v4
      with:
        go-version: ${{ matrix.go }}

    - name: Check out code into the Go module directory
      uses: actions/checkout@v4

    - name: go mod package cache
      uses: actions/cache@v4
      with:
        path: ~/go/pkg/mod
        key: ${{ runner.os }}-go-${{ matrix.go }}-${{ hashFiles('tests/go.mod') }}

    - name: Tests
      run: GITHUB_ACTION=true GORM_DIALECT=postgres GORM_DSN="user=gorm password=gorm dbname=gorm host=localhost port=9920 sslmode=disable TimeZone=Asia/Shanghai" ./tests/tests_all.sh

  sqlserver:
    strategy:
      matrix:
        go: ['1.24', '1.25']
        platform: [ubuntu-latest] # can not run test in macOS and windows
    runs-on: ${{ matrix.platform }}

    services:
      mssql:
        image: mcr.microsoft.com/mssql/server:2022-latest
        env:
          TZ: Asia/Shanghai
          ACCEPT_EULA: Y
          MSSQL_SA_PASSWORD: LoremIpsum86
        ports:
          - 9930:1433
        options: >-
          --health-cmd="/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P ${MSSQL_SA_PASSWORD} -N -C -l 30 -Q \"SELECT 1\" || exit 1"
          --health-start-period 10s
          --health-interval 10s
          --health-timeout 5s
          --health-retries 10

    steps:
    - name: Set up Go 1.x
      uses: actions/setup-go@v4
      with:
        go-version: ${{ matrix.go }}

    - name: Check out code into the Go module directory
      uses: actions/checkout@v4

    - name: go mod package cache
      uses: actions/cache@v4
      with:
        path: ~/go/pkg/mod
        key: ${{ runner.os }}-go-${{ matrix.go }}-${{ hashFiles('tests/go.mod') }}

    - name: Tests
      run: GITHUB_ACTION=true GORM_DIALECT=sqlserver GORM_DSN="sqlserver://sa:LoremIpsum86@localhost:9930?database=master" ./tests/tests_all.sh

  tidb:
    strategy:
      matrix:
        dbversion: [ 'v6.5.0' ]
        go: ['1.24', '1.25']
        platform: [ ubuntu-latest ]
    runs-on: ${{ matrix.platform }}

    steps:
      - name: Setup TiDB
        uses: Icemap/tidb-action@main
        with:
          port: 9940
          version: ${{matrix.dbversion}}

      - name: Set up Go 1.x
        uses: actions/setup-go@v4
        with:
          go-version: ${{ matrix.go }}

      - name: Check out code into the Go module directory
        uses: actions/checkout@v4


      - name: go mod package cache
        uses: actions/cache@v4
        with:
          path: ~/go/pkg/mod
          key: ${{ runner.os }}-go-${{ matrix.go }}-${{ hashFiles('tests/go.mod') }}

      - name: Tests
        run: GITHUB_ACTION=true GORM_DIALECT=tidb GORM_DSN="root:@tcp(localhost:9940)/test?charset=utf8&parseTime=True&loc=Local" ./tests/tests_all.sh

  gaussdb:
    strategy:
      matrix:
        dbversion: ['opengauss/opengauss:7.0.0-RC1.B023']
        go: ['1.24', '1.25']
        platform: [ubuntu-latest] # can not run in macOS and Windows
    runs-on: ${{ matrix.platform }}

    services:
      gaussdb:
        image: ${{ matrix.dbversion }}
        env:
          # GaussDB has password limitations
          GS_PASSWORD: Gaussdb@123
          TZ: Asia/Shanghai
        ports:
          - 9950:5432

    steps:
      - name: Set up Go 1.x
        uses: actions/setup-go@v4
        with:
          go-version: ${{ matrix.go }}

      - name: Check out code into the Go module directory
        uses: actions/checkout@v4

      - name: Waiting for GaussDB to be ready
        run: |
          container_name=$(docker ps --filter "ancestor=opengauss/opengauss:7.0.0-RC1.B023" --format "{{.Names}}")
          if [ -z "$container_name" ]; then
            echo "Error: failed to find a container created from the 'opengauss/opengauss:7.0.0-RC1.B023' image."
            exit 1
          fi
          max_retries=12
          retry_count=0
          if [ -t 0 ]; then
            TTY_FLAG="-t"
          else
            TTY_FLAG=""
          fi
          while [ $retry_count -lt $max_retries ]; do
            if docker exec -i "${container_name}" bash -c "su - omm -c 'gsql -U omm -c \"select 1;\"'" 
            then
              echo "Creating database gorm..."
              sql_file='/tmp/create_database.sql'
              echo "CREATE DATABASE gorm DBCOMPATIBILITY 'PG';" > ${sql_file}
              docker cp "${sql_file}" "${container_name}":"${sql_file}"
              docker exec -i ${TTY_FLAG} "${container_name}" bash -c "su - omm -c 'gsql -U omm -f ${sql_file}'"
              echo "Database initialization completed."
              break
            fi

            echo "Waiting for database to be ready... (attempt $((retry_count + 1))/$max_retries)"
            sleep 10
            ((++retry_count))
          done
          exit 0

      - name: go mod package cache
        uses: actions/cache@v4
        with:
          path: ~/go/pkg/mod
          key: ${{ runner.os }}-go-${{ matrix.go }}-${{ hashFiles('tests/go.mod') }}

      - name: Tests
        run: GITHUB_ACTION=true GORM_DIALECT=gaussdb GORM_DSN="user=gaussdb password=Gaussdb@123 dbname=gorm host=localhost port=9950 sslmode=disable TimeZone=Asia/Shanghai" ./tests/tests_all.sh


================================================
FILE: .gitignore
================================================
TODO*
documents
coverage.txt
_book
.idea
vendor
.vscode


================================================
FILE: .golangci.yml
================================================
version: "2"

linters:
  default: standard
  enable:
    - cyclop
    - gocritic
    - gosec
    - ineffassign
    - misspell
    - prealloc
    - unconvert
    - unparam
    - whitespace

formatters:
  enable:
    - gofumpt
    - goimports


================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct

## Our Pledge

We as members, contributors, and leaders pledge to participate in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.

We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.

## Our Standards

Examples of behavior that contributes to a positive environment for our
community includes:

* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
  and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
  overall community

Examples of unacceptable behavior include:

* The use of sexualized language or imagery, and sexual attention or
  advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
  address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
  professional setting

## Enforcement Responsibilities

Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.

Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.

## Scope

This Code of Conduct applies within all community spaces and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
.
All complaints will be reviewed and investigated promptly and fairly.

All community leaders are obligated to respect the privacy and security of the
reporter of any incident.

## Enforcement Guidelines

Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:

### 1. Correction

**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.

**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.

### 2. Warning

**Community Impact**: A violation through a single incident or series
of actions.

**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period. This
includes avoiding interactions in community spaces and external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.

### 3. Temporary Ban

**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.

**Consequence**: A temporary ban from any interaction or public
communication with the community for a specified period. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.

### 4. Permanent Ban

**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior,  harassment of an
individual, or aggression toward or disparagement of classes of individuals.

**Consequence**: A permanent ban from any sort of public interaction within
the community.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.

Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).

[homepage]: https://www.contributor-covenant.org

For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.


================================================
FILE: LICENSE
================================================
The MIT License (MIT)

Copyright (c) 2013-present  Jinzhu <wosmvp@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.


================================================
FILE: README.md
================================================
# GORM

The fantastic ORM library for Golang, aims to be developer friendly.

[![go report card](https://goreportcard.com/badge/github.com/go-gorm/gorm "go report card")](https://goreportcard.com/report/github.com/go-gorm/gorm)
[![test status](https://github.com/go-gorm/gorm/actions/workflows/tests.yml/badge.svg)](https://github.com/go-gorm/gorm/actions)
[![MIT license](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://opensource.org/licenses/MIT)
[![Go.Dev reference](https://img.shields.io/badge/go.dev-reference-blue?logo=go&logoColor=white)](https://pkg.go.dev/gorm.io/gorm?tab=doc)

## Overview

* Full-Featured ORM
* Associations (Has One, Has Many, Belongs To, Many To Many, Polymorphism, Single-table inheritance)
* Hooks (Before/After Create/Save/Update/Delete/Find)
* Eager loading with `Preload`, `Joins`
* Transactions, Nested Transactions, Save Point, RollbackTo to Saved Point
* Context, Prepared Statement Mode, DryRun Mode
* Batch Insert, FindInBatches, Find To Map
* SQL Builder, Upsert, Locking, Optimizer/Index/Comment Hints, NamedArg, Search/Update/Create with SQL Expr
* Composite Primary Key
* Auto Migrations
* Logger
* Extendable, flexible plugin API: Database Resolver (Multiple Databases, Read/Write Splitting) / Prometheus…
* Every feature comes with tests
* Developer Friendly

## Getting Started

* GORM Guides [https://gorm.io](https://gorm.io)
* Gen Guides [https://gorm.io/gen/index.html](https://gorm.io/gen/index.html)

## Contributing

[You can help to deliver a better GORM, check out things you can do](https://gorm.io/contribute.html)

## Contributors

[Thank you](https://github.com/go-gorm/gorm/graphs/contributors) for contributing to the GORM framework!

## License

© Jinzhu, 2013~time.Now

Released under the [MIT License](https://github.com/go-gorm/gorm/blob/master/LICENSE)


================================================
FILE: association.go
================================================
package gorm

import (
	"fmt"
	"reflect"
	"strings"

	"gorm.io/gorm/clause"
	"gorm.io/gorm/schema"
	"gorm.io/gorm/utils"
)

// Association Mode contains some helper methods to handle relationship things easily.
type Association struct {
	DB           *DB
	Relationship *schema.Relationship
	Unscope      bool
	Error        error
}

func (db *DB) Association(column string) *Association {
	association := &Association{DB: db, Unscope: db.Statement.Unscoped}
	table := db.Statement.Table

	if association.Error = db.Statement.Parse(db.Statement.Model); association.Error == nil {
		db.Statement.Table = table
		association.Relationship = db.Statement.Schema.Relationships.Relations[column]

		if association.Relationship == nil {
			association.Error = fmt.Errorf("%w: %s", ErrUnsupportedRelation, column)
		}

		db.Statement.ReflectValue = reflect.ValueOf(db.Statement.Model)
		for db.Statement.ReflectValue.Kind() == reflect.Ptr {
			db.Statement.ReflectValue = db.Statement.ReflectValue.Elem()
		}
	}

	return association
}

func (association *Association) Unscoped() *Association {
	return &Association{
		DB:           association.DB,
		Relationship: association.Relationship,
		Error:        association.Error,
		Unscope:      true,
	}
}

func (association *Association) Find(out interface{}, conds ...interface{}) error {
	if association.Error == nil {
		association.Error = association.buildCondition().Find(out, conds...).Error
	}
	return association.Error
}

func (association *Association) Append(values ...interface{}) error {
	values = expandValues(values)

	if association.Error == nil {
		switch association.Relationship.Type {
		case schema.HasOne, schema.BelongsTo:
			if len(values) > 0 {
				association.Error = association.Replace(values...)
			}
		default:
			association.saveAssociation( /*clear*/ false, values...)
		}
	}

	return association.Error
}

func (association *Association) Replace(values ...interface{}) error {
	values = expandValues(values)

	if association.Error == nil {
		reflectValue := association.DB.Statement.ReflectValue
		rel := association.Relationship

		var oldBelongsToExpr clause.Expression
		// we have to record the old BelongsTo value
		if association.Unscope && rel.Type == schema.BelongsTo {
			var foreignFields []*schema.Field
			for _, ref := range rel.References {
				if !ref.OwnPrimaryKey {
					foreignFields = append(foreignFields, ref.ForeignKey)
				}
			}
			if _, fvs := schema.GetIdentityFieldValuesMap(association.DB.Statement.Context, reflectValue, foreignFields); len(fvs) > 0 {
				column, values := schema.ToQueryValues(rel.FieldSchema.Table, rel.FieldSchema.PrimaryFieldDBNames, fvs)
				oldBelongsToExpr = clause.IN{Column: column, Values: values}
			}
		}

		// save associations
		if association.saveAssociation( /*clear*/ true, values...); association.Error != nil {
			return association.Error
		}

		// set old association's foreign key to null
		switch rel.Type {
		case schema.BelongsTo:
			if len(values) == 0 {
				updateMap := map[string]interface{}{}
				switch reflectValue.Kind() {
				case reflect.Slice, reflect.Array:
					for i := 0; i < reflectValue.Len(); i++ {
						association.Error = rel.Field.Set(association.DB.Statement.Context, reflectValue.Index(i), reflect.Zero(rel.Field.FieldType).Interface())
					}
				case reflect.Struct:
					association.Error = rel.Field.Set(association.DB.Statement.Context, reflectValue, reflect.Zero(rel.Field.FieldType).Interface())
				}

				for _, ref := range rel.References {
					updateMap[ref.ForeignKey.DBName] = nil
				}

				association.Error = association.DB.UpdateColumns(updateMap).Error
			}
			if association.Unscope && oldBelongsToExpr != nil {
				association.Error = association.DB.Model(nil).Where(oldBelongsToExpr).Delete(reflect.New(rel.FieldSchema.ModelType).Interface()).Error
			}
		case schema.HasOne, schema.HasMany:
			var (
				primaryFields []*schema.Field
				foreignKeys   []string
				updateMap     = map[string]interface{}{}
				relValues     = schema.GetRelationsValues(association.DB.Statement.Context, reflectValue, []*schema.Relationship{rel})
				modelValue    = reflect.New(rel.FieldSchema.ModelType).Interface()
				tx            = association.DB.Model(modelValue)
			)

			if _, rvs := schema.GetIdentityFieldValuesMap(association.DB.Statement.Context, relValues, rel.FieldSchema.PrimaryFields); len(rvs) > 0 {
				if column, values := schema.ToQueryValues(rel.FieldSchema.Table, rel.FieldSchema.PrimaryFieldDBNames, rvs); len(values) > 0 {
					tx.Not(clause.IN{Column: column, Values: values})
				}
			}

			for _, ref := range rel.References {
				if ref.OwnPrimaryKey {
					primaryFields = append(primaryFields, ref.PrimaryKey)
					foreignKeys = append(foreignKeys, ref.ForeignKey.DBName)
					updateMap[ref.ForeignKey.DBName] = nil
				} else if ref.PrimaryValue != "" {
					tx.Where(clause.Eq{Column: ref.ForeignKey.DBName, Value: ref.PrimaryValue})
				}
			}

			if _, pvs := schema.GetIdentityFieldValuesMap(association.DB.Statement.Context, reflectValue, primaryFields); len(pvs) > 0 {
				column, values := schema.ToQueryValues(rel.FieldSchema.Table, foreignKeys, pvs)
				if association.Unscope {
					association.Error = tx.Where(clause.IN{Column: column, Values: values}).Delete(modelValue).Error
				} else {
					association.Error = tx.Where(clause.IN{Column: column, Values: values}).UpdateColumns(updateMap).Error
				}
			}
		case schema.Many2Many:
			var (
				primaryFields, relPrimaryFields     []*schema.Field
				joinPrimaryKeys, joinRelPrimaryKeys []string
				modelValue                          = reflect.New(rel.JoinTable.ModelType).Interface()
				tx                                  = association.DB.Model(modelValue)
			)

			for _, ref := range rel.References {
				if ref.PrimaryValue == "" {
					if ref.OwnPrimaryKey {
						primaryFields = append(primaryFields, ref.PrimaryKey)
						joinPrimaryKeys = append(joinPrimaryKeys, ref.ForeignKey.DBName)
					} else {
						relPrimaryFields = append(relPrimaryFields, ref.PrimaryKey)
						joinRelPrimaryKeys = append(joinRelPrimaryKeys, ref.ForeignKey.DBName)
					}
				} else {
					tx.Clauses(clause.Eq{Column: ref.ForeignKey.DBName, Value: ref.PrimaryValue})
				}
			}

			_, pvs := schema.GetIdentityFieldValuesMap(association.DB.Statement.Context, reflectValue, primaryFields)
			if column, values := schema.ToQueryValues(rel.JoinTable.Table, joinPrimaryKeys, pvs); len(values) > 0 {
				tx.Where(clause.IN{Column: column, Values: values})
			} else {
				return ErrPrimaryKeyRequired
			}

			_, rvs := schema.GetIdentityFieldValuesMapFromValues(association.DB.Statement.Context, values, relPrimaryFields)
			if relColumn, relValues := schema.ToQueryValues(rel.JoinTable.Table, joinRelPrimaryKeys, rvs); len(relValues) > 0 {
				tx.Where(clause.Not(clause.IN{Column: relColumn, Values: relValues}))
			}

			association.Error = tx.Delete(modelValue).Error
		}
	}
	return association.Error
}

func (association *Association) Delete(values ...interface{}) error {
	values = expandValues(values)

	if association.Error == nil {
		var (
			reflectValue  = association.DB.Statement.ReflectValue
			rel           = association.Relationship
			primaryFields []*schema.Field
			foreignKeys   []string
			updateAttrs   = map[string]interface{}{}
			conds         []clause.Expression
		)

		for _, ref := range rel.References {
			if ref.PrimaryValue == "" {
				primaryFields = append(primaryFields, ref.PrimaryKey)
				foreignKeys = append(foreignKeys, ref.ForeignKey.DBName)
				updateAttrs[ref.ForeignKey.DBName] = nil
			} else {
				conds = append(conds, clause.Eq{Column: ref.ForeignKey.DBName, Value: ref.PrimaryValue})
			}
		}

		switch rel.Type {
		case schema.BelongsTo:
			associationDB := association.DB.Session(&Session{})
			tx := associationDB.Model(reflect.New(rel.Schema.ModelType).Interface())

			_, pvs := schema.GetIdentityFieldValuesMap(association.DB.Statement.Context, reflectValue, rel.Schema.PrimaryFields)
			if pcolumn, pvalues := schema.ToQueryValues(rel.Schema.Table, rel.Schema.PrimaryFieldDBNames, pvs); len(pvalues) > 0 {
				conds = append(conds, clause.IN{Column: pcolumn, Values: pvalues})
			} else {
				return ErrPrimaryKeyRequired
			}

			_, rvs := schema.GetIdentityFieldValuesMapFromValues(association.DB.Statement.Context, values, primaryFields)
			relColumn, relValues := schema.ToQueryValues(rel.Schema.Table, foreignKeys, rvs)
			conds = append(conds, clause.IN{Column: relColumn, Values: relValues})

			association.Error = tx.Clauses(conds...).UpdateColumns(updateAttrs).Error
			if association.Unscope {
				var foreignFields []*schema.Field
				for _, ref := range rel.References {
					if !ref.OwnPrimaryKey {
						foreignFields = append(foreignFields, ref.ForeignKey)
					}
				}
				if _, fvs := schema.GetIdentityFieldValuesMap(association.DB.Statement.Context, reflectValue, foreignFields); len(fvs) > 0 {
					column, values := schema.ToQueryValues(rel.FieldSchema.Table, rel.FieldSchema.PrimaryFieldDBNames, fvs)
					association.Error = associationDB.Model(nil).Where(clause.IN{Column: column, Values: values}).Delete(reflect.New(rel.FieldSchema.ModelType).Interface()).Error
				}
			}
		case schema.HasOne, schema.HasMany:
			model := reflect.New(rel.FieldSchema.ModelType).Interface()
			tx := association.DB.Model(model)

			_, pvs := schema.GetIdentityFieldValuesMap(association.DB.Statement.Context, reflectValue, primaryFields)
			if pcolumn, pvalues := schema.ToQueryValues(rel.FieldSchema.Table, foreignKeys, pvs); len(pvalues) > 0 {
				conds = append(conds, clause.IN{Column: pcolumn, Values: pvalues})
			} else {
				return ErrPrimaryKeyRequired
			}

			_, rvs := schema.GetIdentityFieldValuesMapFromValues(association.DB.Statement.Context, values, rel.FieldSchema.PrimaryFields)
			relColumn, relValues := schema.ToQueryValues(rel.FieldSchema.Table, rel.FieldSchema.PrimaryFieldDBNames, rvs)
			conds = append(conds, clause.IN{Column: relColumn, Values: relValues})

			if association.Unscope {
				association.Error = tx.Clauses(conds...).Delete(model).Error
			} else {
				association.Error = tx.Clauses(conds...).UpdateColumns(updateAttrs).Error
			}
		case schema.Many2Many:
			var (
				primaryFields, relPrimaryFields     []*schema.Field
				joinPrimaryKeys, joinRelPrimaryKeys []string
				joinValue                           = reflect.New(rel.JoinTable.ModelType).Interface()
			)

			for _, ref := range rel.References {
				if ref.PrimaryValue == "" {
					if ref.OwnPrimaryKey {
						primaryFields = append(primaryFields, ref.PrimaryKey)
						joinPrimaryKeys = append(joinPrimaryKeys, ref.ForeignKey.DBName)
					} else {
						relPrimaryFields = append(relPrimaryFields, ref.PrimaryKey)
						joinRelPrimaryKeys = append(joinRelPrimaryKeys, ref.ForeignKey.DBName)
					}
				} else {
					conds = append(conds, clause.Eq{Column: ref.ForeignKey.DBName, Value: ref.PrimaryValue})
				}
			}

			_, pvs := schema.GetIdentityFieldValuesMap(association.DB.Statement.Context, reflectValue, primaryFields)
			if pcolumn, pvalues := schema.ToQueryValues(rel.JoinTable.Table, joinPrimaryKeys, pvs); len(pvalues) > 0 {
				conds = append(conds, clause.IN{Column: pcolumn, Values: pvalues})
			} else {
				return ErrPrimaryKeyRequired
			}

			_, rvs := schema.GetIdentityFieldValuesMapFromValues(association.DB.Statement.Context, values, relPrimaryFields)
			relColumn, relValues := schema.ToQueryValues(rel.JoinTable.Table, joinRelPrimaryKeys, rvs)
			conds = append(conds, clause.IN{Column: relColumn, Values: relValues})

			association.Error = association.DB.Where(clause.Where{Exprs: conds}).Model(nil).Delete(joinValue).Error
		}

		if association.Error == nil {
			// clean up deleted values' foreign key
			relValuesMap, _ := schema.GetIdentityFieldValuesMapFromValues(association.DB.Statement.Context, values, rel.FieldSchema.PrimaryFields)

			cleanUpDeletedRelations := func(data reflect.Value) {
				if _, zero := rel.Field.ValueOf(association.DB.Statement.Context, data); !zero {
					fieldValue := reflect.Indirect(rel.Field.ReflectValueOf(association.DB.Statement.Context, data))
					primaryValues := make([]interface{}, len(rel.FieldSchema.PrimaryFields))

					switch fieldValue.Kind() {
					case reflect.Slice, reflect.Array:
						validFieldValues := reflect.Zero(rel.Field.IndirectFieldType)
						for i := 0; i < fieldValue.Len(); i++ {
							for idx, field := range rel.FieldSchema.PrimaryFields {
								primaryValues[idx], _ = field.ValueOf(association.DB.Statement.Context, fieldValue.Index(i))
							}

							if _, ok := relValuesMap[utils.ToStringKey(primaryValues...)]; !ok {
								validFieldValues = reflect.Append(validFieldValues, fieldValue.Index(i))
							}
						}

						association.Error = rel.Field.Set(association.DB.Statement.Context, data, validFieldValues.Interface())
					case reflect.Struct:
						for idx, field := range rel.FieldSchema.PrimaryFields {
							primaryValues[idx], _ = field.ValueOf(association.DB.Statement.Context, fieldValue)
						}

						if _, ok := relValuesMap[utils.ToStringKey(primaryValues...)]; ok {
							if association.Error = rel.Field.Set(association.DB.Statement.Context, data, reflect.Zero(rel.FieldSchema.ModelType).Interface()); association.Error != nil {
								break
							}

							if rel.JoinTable == nil {
								for _, ref := range rel.References {
									if ref.OwnPrimaryKey || ref.PrimaryValue != "" {
										association.Error = ref.ForeignKey.Set(association.DB.Statement.Context, fieldValue, reflect.Zero(ref.ForeignKey.FieldType).Interface())
									} else {
										association.Error = ref.ForeignKey.Set(association.DB.Statement.Context, data, reflect.Zero(ref.ForeignKey.FieldType).Interface())
									}
								}
							}
						}
					}
				}
			}

			switch reflectValue.Kind() {
			case reflect.Slice, reflect.Array:
				for i := 0; i < reflectValue.Len(); i++ {
					cleanUpDeletedRelations(reflect.Indirect(reflectValue.Index(i)))
				}
			case reflect.Struct:
				cleanUpDeletedRelations(reflectValue)
			}
		}
	}

	return association.Error
}

func (association *Association) Clear() error {
	return association.Replace()
}

func (association *Association) Count() (count int64) {
	if association.Error == nil {
		association.Error = association.buildCondition().Count(&count).Error
	}
	return
}

type assignBack struct {
	Source reflect.Value
	Index  int
	Dest   reflect.Value
}

func (association *Association) saveAssociation(clear bool, values ...interface{}) {
	var (
		reflectValue = association.DB.Statement.ReflectValue
		assignBacks  []assignBack // assign association values back to arguments after save
	)

	appendToRelations := func(source, rv reflect.Value, clear bool) {
		switch association.Relationship.Type {
		case schema.HasOne, schema.BelongsTo:
			switch rv.Kind() {
			case reflect.Slice, reflect.Array:
				if rv.Len() > 0 {
					association.Error = association.Relationship.Field.Set(association.DB.Statement.Context, source, rv.Index(0).Addr().Interface())

					if association.Relationship.Field.FieldType.Kind() == reflect.Struct {
						assignBacks = append(assignBacks, assignBack{Source: source, Dest: rv.Index(0)})
					}
				}
			case reflect.Struct:
				if !rv.CanAddr() {
					association.Error = ErrInvalidValue
					return
				}
				association.Error = association.Relationship.Field.Set(association.DB.Statement.Context, source, rv.Addr().Interface())

				if association.Relationship.Field.FieldType.Kind() == reflect.Struct {
					assignBacks = append(assignBacks, assignBack{Source: source, Dest: rv})
				}
			}
		case schema.HasMany, schema.Many2Many:
			elemType := association.Relationship.Field.IndirectFieldType.Elem()
			oldFieldValue := reflect.Indirect(association.Relationship.Field.ReflectValueOf(association.DB.Statement.Context, source))
			var fieldValue reflect.Value
			if clear {
				fieldValue = reflect.MakeSlice(oldFieldValue.Type(), 0, oldFieldValue.Cap())
			} else {
				fieldValue = reflect.MakeSlice(oldFieldValue.Type(), oldFieldValue.Len(), oldFieldValue.Cap())
				reflect.Copy(fieldValue, oldFieldValue)
			}

			appendToFieldValues := func(ev reflect.Value) {
				if ev.Type().AssignableTo(elemType) {
					fieldValue = reflect.Append(fieldValue, ev)
				} else if ev.Type().Elem().AssignableTo(elemType) {
					fieldValue = reflect.Append(fieldValue, ev.Elem())
				} else {
					association.Error = fmt.Errorf("unsupported data type: %v for relation %s", ev.Type(), association.Relationship.Name)
				}

				if elemType.Kind() == reflect.Struct {
					assignBacks = append(assignBacks, assignBack{Source: source, Dest: ev, Index: fieldValue.Len()})
				}
			}

			processMap := func(mapv reflect.Value) {
				child := reflect.New(association.Relationship.FieldSchema.ModelType)

				switch association.Relationship.Type {
				case schema.HasMany:
					for _, ref := range association.Relationship.References {
						key := reflect.ValueOf(ref.ForeignKey.DBName)
						if ref.OwnPrimaryKey {
							v := ref.PrimaryKey.ReflectValueOf(association.DB.Statement.Context, source)
							mapv.SetMapIndex(key, v)
						} else if ref.PrimaryValue != "" {
							mapv.SetMapIndex(key, reflect.ValueOf(ref.PrimaryValue))
						}
					}
					association.Error = association.DB.Session(&Session{
						NewDB: true,
					}).Model(child.Interface()).Create(mapv.Interface()).Error
				case schema.Many2Many:
					association.Error = association.DB.Session(&Session{
						NewDB: true,
					}).Model(child.Interface()).Create(mapv.Interface()).Error

					for _, key := range mapv.MapKeys() {
						k := strings.ToLower(key.String())
						if f, ok := association.Relationship.FieldSchema.FieldsByDBName[k]; ok {
							_ = f.Set(association.DB.Statement.Context, child, mapv.MapIndex(key).Interface())
						}
					}
					appendToFieldValues(child)
				}
			}

			switch rv.Kind() {
			case reflect.Map:
				processMap(rv)
			case reflect.Slice, reflect.Array:
				for i := 0; i < rv.Len(); i++ {
					elem := reflect.Indirect(rv.Index(i))
					if elem.Kind() == reflect.Map {
						processMap(elem)
						continue
					}
					appendToFieldValues(elem.Addr())
				}
			case reflect.Struct:
				if !rv.CanAddr() {
					association.Error = ErrInvalidValue
					return
				}
				appendToFieldValues(rv.Addr())
			}

			if association.Error == nil {
				association.Error = association.Relationship.Field.Set(association.DB.Statement.Context, source, fieldValue.Interface())
			}
		}
	}

	selectedSaveColumns := []string{association.Relationship.Name}
	omitColumns := []string{}
	selectColumns, _ := association.DB.Statement.SelectAndOmitColumns(true, false)
	for name, ok := range selectColumns {
		columnName := ""
		if strings.HasPrefix(name, association.Relationship.Name) {
			if columnName = strings.TrimPrefix(name, association.Relationship.Name); columnName == ".*" {
				columnName = name
			}
		} else if strings.HasPrefix(name, clause.Associations) {
			columnName = name
		}

		if columnName != "" {
			if ok {
				selectedSaveColumns = append(selectedSaveColumns, columnName)
			} else {
				omitColumns = append(omitColumns, columnName)
			}
		}
	}

	for _, ref := range association.Relationship.References {
		if !ref.OwnPrimaryKey {
			selectedSaveColumns = append(selectedSaveColumns, ref.ForeignKey.Name)
		}
	}

	associationDB := association.DB.Session(&Session{}).Model(nil)
	if !association.DB.FullSaveAssociations {
		associationDB.Select(selectedSaveColumns)
	}
	if len(omitColumns) > 0 {
		associationDB.Omit(omitColumns...)
	}
	associationDB = associationDB.Session(&Session{})

	switch reflectValue.Kind() {
	case reflect.Slice, reflect.Array:
		if len(values) != reflectValue.Len() {
			// clear old data
			if clear && len(values) == 0 {
				for i := 0; i < reflectValue.Len(); i++ {
					if err := association.Relationship.Field.Set(association.DB.Statement.Context, reflectValue.Index(i), reflect.New(association.Relationship.Field.IndirectFieldType).Interface()); err != nil {
						association.Error = err
						break
					}

					if association.Relationship.JoinTable == nil {
						for _, ref := range association.Relationship.References {
							if !ref.OwnPrimaryKey && ref.PrimaryValue == "" {
								if err := ref.ForeignKey.Set(association.DB.Statement.Context, reflectValue.Index(i), reflect.Zero(ref.ForeignKey.FieldType).Interface()); err != nil {
									association.Error = err
									break
								}
							}
						}
					}
				}
				break
			}

			association.Error = ErrInvalidValueOfLength
			return
		}

		for i := 0; i < reflectValue.Len(); i++ {
			appendToRelations(reflectValue.Index(i), reflect.Indirect(reflect.ValueOf(values[i])), clear)
			if association.Error != nil {
				return
			}

			// TODO support save slice data, sql with case?
			association.Error = associationDB.Updates(reflectValue.Index(i).Addr().Interface()).Error
		}
	case reflect.Struct:
		// clear old data
		if clear && len(values) == 0 {
			association.Error = association.Relationship.Field.Set(association.DB.Statement.Context, reflectValue, reflect.New(association.Relationship.Field.IndirectFieldType).Interface())

			if association.Relationship.JoinTable == nil && association.Error == nil {
				for _, ref := range association.Relationship.References {
					if !ref.OwnPrimaryKey && ref.PrimaryValue == "" {
						association.Error = ref.ForeignKey.Set(association.DB.Statement.Context, reflectValue, reflect.Zero(ref.ForeignKey.FieldType).Interface())
					}
				}
			}
		}

		for idx, value := range values {
			rv := reflect.Indirect(reflect.ValueOf(value))
			appendToRelations(reflectValue, rv, clear && idx == 0)
			if association.Error != nil {
				return
			}
		}

		if len(values) > 0 {
			association.Error = associationDB.Updates(reflectValue.Addr().Interface()).Error
		}
	}

	for _, assignBack := range assignBacks {
		fieldValue := reflect.Indirect(association.Relationship.Field.ReflectValueOf(association.DB.Statement.Context, assignBack.Source))
		if assignBack.Index > 0 {
			reflect.Indirect(assignBack.Dest).Set(fieldValue.Index(assignBack.Index - 1))
		} else {
			reflect.Indirect(assignBack.Dest).Set(fieldValue)
		}
	}
}

func (association *Association) buildCondition() *DB {
	var (
		queryConds = association.Relationship.ToQueryConditions(association.DB.Statement.Context, association.DB.Statement.ReflectValue)
		modelValue = reflect.New(association.Relationship.FieldSchema.ModelType).Interface()
		tx         = association.DB.Model(modelValue)
	)

	if association.Relationship.JoinTable != nil {
		if !tx.Statement.Unscoped && len(association.Relationship.JoinTable.QueryClauses) > 0 {
			joinStmt := Statement{DB: tx, Context: tx.Statement.Context, Schema: association.Relationship.JoinTable, Table: association.Relationship.JoinTable.Table, Clauses: map[string]clause.Clause{}}
			for _, queryClause := range association.Relationship.JoinTable.QueryClauses {
				joinStmt.AddClause(queryClause)
			}
			joinStmt.Build("WHERE")
			if len(joinStmt.SQL.String()) > 0 {
				tx.Clauses(clause.Expr{SQL: strings.Replace(joinStmt.SQL.String(), "WHERE ", "", 1), Vars: joinStmt.Vars})
			}
		}

		tx = tx.Session(&Session{QueryFields: true}).Clauses(clause.From{Joins: []clause.Join{{
			Table: clause.Table{Name: association.Relationship.JoinTable.Table},
			ON:    clause.Where{Exprs: queryConds},
		}}})
	} else {
		tx.Clauses(clause.Where{Exprs: queryConds})
	}

	return tx
}

func expandValues(values ...any) (results []any) {
	appendToResult := func(rv reflect.Value) {
		// unwrap interface
		if rv.IsValid() && rv.Kind() == reflect.Interface {
			rv = rv.Elem()
		}
		if rv.IsValid() && rv.Kind() == reflect.Struct {
			p := reflect.New(rv.Type())
			p.Elem().Set(rv)
			results = append(results, p.Interface())
		} else if rv.IsValid() {
			results = append(results, rv.Interface())
		}
	}

	// Process each argument; if an argument is a slice/array, expand its elements
	for _, value := range values {
		rv := reflect.ValueOf(value)
		if rv.Kind() == reflect.Slice || rv.Kind() == reflect.Array {
			for i := 0; i < rv.Len(); i++ {
				appendToResult(rv.Index(i))
			}
		} else {
			appendToResult(rv)
		}
	}
	return
}


================================================
FILE: callbacks/associations.go
================================================
package callbacks

import (
	"reflect"
	"strings"

	"gorm.io/gorm"
	"gorm.io/gorm/clause"
	"gorm.io/gorm/schema"
	"gorm.io/gorm/utils"
)

func SaveBeforeAssociations(create bool) func(db *gorm.DB) {
	return func(db *gorm.DB) {
		if db.Error == nil && db.Statement.Schema != nil {
			selectColumns, restricted := db.Statement.SelectAndOmitColumns(create, !create)

			// Save Belongs To associations
			for _, rel := range db.Statement.Schema.Relationships.BelongsTo {
				if v, ok := selectColumns[rel.Name]; (ok && !v) || (!ok && restricted) {
					continue
				}

				setupReferences := func(obj reflect.Value, elem reflect.Value) {
					for _, ref := range rel.References {
						if !ref.OwnPrimaryKey {
							pv, _ := ref.PrimaryKey.ValueOf(db.Statement.Context, elem)
							db.AddError(ref.ForeignKey.Set(db.Statement.Context, obj, pv))

							if dest, ok := db.Statement.Dest.(map[string]interface{}); ok {
								dest[ref.ForeignKey.DBName] = pv
								if _, ok := dest[rel.Name]; ok {
									dest[rel.Name] = elem.Interface()
								}
							}
						}
					}
				}

				switch db.Statement.ReflectValue.Kind() {
				case reflect.Slice, reflect.Array:
					var (
						rValLen   = db.Statement.ReflectValue.Len()
						objs      = make([]reflect.Value, 0, rValLen)
						fieldType = rel.Field.FieldType
						isPtr     = fieldType.Kind() == reflect.Ptr
					)

					if !isPtr {
						fieldType = reflect.PointerTo(fieldType)
					}

					elems := reflect.MakeSlice(reflect.SliceOf(fieldType), 0, 10)
					distinctElems := reflect.MakeSlice(reflect.SliceOf(fieldType), 0, 10)
					identityMap := map[string]bool{}
					for i := 0; i < rValLen; i++ {
						obj := db.Statement.ReflectValue.Index(i)
						if reflect.Indirect(obj).Kind() != reflect.Struct {
							break
						}
						if _, zero := rel.Field.ValueOf(db.Statement.Context, obj); !zero { // check belongs to relation value
							rv := rel.Field.ReflectValueOf(db.Statement.Context, obj) // relation reflect value
							if !isPtr {
								rv = rv.Addr()
							}
							objs = append(objs, obj)
							elems = reflect.Append(elems, rv)

							relPrimaryValues := make([]interface{}, 0, len(rel.FieldSchema.PrimaryFields))
							for _, pf := range rel.FieldSchema.PrimaryFields {
								if pfv, ok := pf.ValueOf(db.Statement.Context, rv); !ok {
									relPrimaryValues = append(relPrimaryValues, pfv)
								}
							}
							cacheKey := utils.ToStringKey(relPrimaryValues...)
							if len(relPrimaryValues) != len(rel.FieldSchema.PrimaryFields) || !identityMap[cacheKey] {
								if cacheKey != "" { // has primary fields
									identityMap[cacheKey] = true
								}

								distinctElems = reflect.Append(distinctElems, rv)
							}
						}
					}

					if elems.Len() > 0 {
						if saveAssociations(db, rel, distinctElems, selectColumns, restricted, nil) == nil {
							for i := 0; i < elems.Len(); i++ {
								setupReferences(objs[i], elems.Index(i))
							}
						}
					}
				case reflect.Struct:
					if _, zero := rel.Field.ValueOf(db.Statement.Context, db.Statement.ReflectValue); !zero {
						rv := rel.Field.ReflectValueOf(db.Statement.Context, db.Statement.ReflectValue) // relation reflect value
						if rv.Kind() != reflect.Ptr {
							rv = rv.Addr()
						}

						if saveAssociations(db, rel, rv, selectColumns, restricted, nil) == nil {
							setupReferences(db.Statement.ReflectValue, rv)
						}
					}
				}
			}
		}
	}
}

func SaveAfterAssociations(create bool) func(db *gorm.DB) {
	return func(db *gorm.DB) {
		if db.Error == nil && db.Statement.Schema != nil {
			selectColumns, restricted := db.Statement.SelectAndOmitColumns(create, !create)

			// Save Has One associations
			for _, rel := range db.Statement.Schema.Relationships.HasOne {
				if v, ok := selectColumns[rel.Name]; (ok && !v) || (!ok && restricted) {
					continue
				}

				switch db.Statement.ReflectValue.Kind() {
				case reflect.Slice, reflect.Array:
					var (
						fieldType = rel.Field.FieldType
						isPtr     = fieldType.Kind() == reflect.Ptr
					)

					if !isPtr {
						fieldType = reflect.PointerTo(fieldType)
					}

					elems := reflect.MakeSlice(reflect.SliceOf(fieldType), 0, 10)

					for i := 0; i < db.Statement.ReflectValue.Len(); i++ {
						obj := db.Statement.ReflectValue.Index(i)

						if reflect.Indirect(obj).Kind() == reflect.Struct {
							if _, zero := rel.Field.ValueOf(db.Statement.Context, obj); !zero {
								rv := rel.Field.ReflectValueOf(db.Statement.Context, obj)
								if rv.Kind() != reflect.Ptr {
									rv = rv.Addr()
								}

								for _, ref := range rel.References {
									if ref.OwnPrimaryKey {
										fv, _ := ref.PrimaryKey.ValueOf(db.Statement.Context, obj)
										db.AddError(ref.ForeignKey.Set(db.Statement.Context, rv, fv))
									} else if ref.PrimaryValue != "" {
										db.AddError(ref.ForeignKey.Set(db.Statement.Context, rv, ref.PrimaryValue))
									}
								}

								elems = reflect.Append(elems, rv)
							}
						}
					}

					if elems.Len() > 0 {
						assignmentColumns := make([]string, 0, len(rel.References))
						for _, ref := range rel.References {
							assignmentColumns = append(assignmentColumns, ref.ForeignKey.DBName)
						}

						saveAssociations(db, rel, elems, selectColumns, restricted, assignmentColumns)
					}
				case reflect.Struct:
					if _, zero := rel.Field.ValueOf(db.Statement.Context, db.Statement.ReflectValue); !zero {
						f := rel.Field.ReflectValueOf(db.Statement.Context, db.Statement.ReflectValue)
						if f.Kind() != reflect.Ptr {
							f = f.Addr()
						}

						assignmentColumns := make([]string, 0, len(rel.References))
						for _, ref := range rel.References {
							if ref.OwnPrimaryKey {
								fv, _ := ref.PrimaryKey.ValueOf(db.Statement.Context, db.Statement.ReflectValue)
								db.AddError(ref.ForeignKey.Set(db.Statement.Context, f, fv))
							} else if ref.PrimaryValue != "" {
								db.AddError(ref.ForeignKey.Set(db.Statement.Context, f, ref.PrimaryValue))
							}
							assignmentColumns = append(assignmentColumns, ref.ForeignKey.DBName)
						}

						saveAssociations(db, rel, f, selectColumns, restricted, assignmentColumns)
					}
				}
			}

			// Save Has Many associations
			for _, rel := range db.Statement.Schema.Relationships.HasMany {
				if v, ok := selectColumns[rel.Name]; (ok && !v) || (!ok && restricted) {
					continue
				}

				fieldType := rel.Field.IndirectFieldType.Elem()
				isPtr := fieldType.Kind() == reflect.Ptr
				if !isPtr {
					fieldType = reflect.PointerTo(fieldType)
				}
				elems := reflect.MakeSlice(reflect.SliceOf(fieldType), 0, 10)
				identityMap := map[string]bool{}
				appendToElems := func(v reflect.Value) {
					if _, zero := rel.Field.ValueOf(db.Statement.Context, v); !zero {
						f := reflect.Indirect(rel.Field.ReflectValueOf(db.Statement.Context, v))

						for i := 0; i < f.Len(); i++ {
							elem := f.Index(i)
							for _, ref := range rel.References {
								if ref.OwnPrimaryKey {
									pv, _ := ref.PrimaryKey.ValueOf(db.Statement.Context, v)
									db.AddError(ref.ForeignKey.Set(db.Statement.Context, elem, pv))
								} else if ref.PrimaryValue != "" {
									db.AddError(ref.ForeignKey.Set(db.Statement.Context, elem, ref.PrimaryValue))
								}
							}

							relPrimaryValues := make([]interface{}, 0, len(rel.FieldSchema.PrimaryFields))
							for _, pf := range rel.FieldSchema.PrimaryFields {
								if pfv, ok := pf.ValueOf(db.Statement.Context, elem); !ok {
									relPrimaryValues = append(relPrimaryValues, pfv)
								}
							}

							cacheKey := utils.ToStringKey(relPrimaryValues...)
							if len(relPrimaryValues) != len(rel.FieldSchema.PrimaryFields) || !identityMap[cacheKey] {
								if cacheKey != "" { // has primary fields
									identityMap[cacheKey] = true
								}

								if isPtr {
									elems = reflect.Append(elems, elem)
								} else {
									elems = reflect.Append(elems, elem.Addr())
								}
							}
						}
					}
				}

				switch db.Statement.ReflectValue.Kind() {
				case reflect.Slice, reflect.Array:
					for i := 0; i < db.Statement.ReflectValue.Len(); i++ {
						obj := db.Statement.ReflectValue.Index(i)
						if reflect.Indirect(obj).Kind() == reflect.Struct {
							appendToElems(obj)
						}
					}
				case reflect.Struct:
					appendToElems(db.Statement.ReflectValue)
				}

				if elems.Len() > 0 {
					assignmentColumns := make([]string, 0, len(rel.References))
					for _, ref := range rel.References {
						assignmentColumns = append(assignmentColumns, ref.ForeignKey.DBName)
					}

					saveAssociations(db, rel, elems, selectColumns, restricted, assignmentColumns)
				}
			}

			// Save Many2Many associations
			for _, rel := range db.Statement.Schema.Relationships.Many2Many {
				if v, ok := selectColumns[rel.Name]; (ok && !v) || (!ok && restricted) {
					continue
				}

				fieldType := rel.Field.IndirectFieldType.Elem()
				isPtr := fieldType.Kind() == reflect.Ptr
				if !isPtr {
					fieldType = reflect.PointerTo(fieldType)
				}
				elems := reflect.MakeSlice(reflect.SliceOf(fieldType), 0, 10)
				distinctElems := reflect.MakeSlice(reflect.SliceOf(fieldType), 0, 10)
				joins := reflect.MakeSlice(reflect.SliceOf(reflect.PointerTo(rel.JoinTable.ModelType)), 0, 10)
				objs := []reflect.Value{}

				appendToJoins := func(obj reflect.Value, elem reflect.Value) {
					joinValue := reflect.New(rel.JoinTable.ModelType)
					for _, ref := range rel.References {
						if ref.OwnPrimaryKey {
							fv, _ := ref.PrimaryKey.ValueOf(db.Statement.Context, obj)
							db.AddError(ref.ForeignKey.Set(db.Statement.Context, joinValue, fv))
						} else if ref.PrimaryValue != "" {
							db.AddError(ref.ForeignKey.Set(db.Statement.Context, joinValue, ref.PrimaryValue))
						} else {
							fv, _ := ref.PrimaryKey.ValueOf(db.Statement.Context, elem)
							db.AddError(ref.ForeignKey.Set(db.Statement.Context, joinValue, fv))
						}
					}
					joins = reflect.Append(joins, joinValue)
				}

				identityMap := map[string]bool{}
				appendToElems := func(v reflect.Value) {
					if _, zero := rel.Field.ValueOf(db.Statement.Context, v); !zero {
						f := reflect.Indirect(rel.Field.ReflectValueOf(db.Statement.Context, v))
						for i := 0; i < f.Len(); i++ {
							elem := f.Index(i)
							if !isPtr {
								elem = elem.Addr()
							}
							objs = append(objs, v)
							elems = reflect.Append(elems, elem)

							relPrimaryValues := make([]interface{}, 0, len(rel.FieldSchema.PrimaryFields))
							for _, pf := range rel.FieldSchema.PrimaryFields {
								if pfv, ok := pf.ValueOf(db.Statement.Context, elem); !ok {
									relPrimaryValues = append(relPrimaryValues, pfv)
								}
							}

							cacheKey := utils.ToStringKey(relPrimaryValues...)
							if len(relPrimaryValues) != len(rel.FieldSchema.PrimaryFields) || !identityMap[cacheKey] {
								if cacheKey != "" { // has primary fields
									identityMap[cacheKey] = true
								}

								distinctElems = reflect.Append(distinctElems, elem)
							}

						}
					}
				}

				switch db.Statement.ReflectValue.Kind() {
				case reflect.Slice, reflect.Array:
					for i := 0; i < db.Statement.ReflectValue.Len(); i++ {
						obj := db.Statement.ReflectValue.Index(i)
						if reflect.Indirect(obj).Kind() == reflect.Struct {
							appendToElems(obj)
						}
					}
				case reflect.Struct:
					appendToElems(db.Statement.ReflectValue)
				}

				// optimize elems of reflect value length
				if elemLen := elems.Len(); elemLen > 0 {
					if v, ok := selectColumns[rel.Name+".*"]; !ok || v {
						saveAssociations(db, rel, distinctElems, selectColumns, restricted, nil)
					}

					for i := 0; i < elemLen; i++ {
						appendToJoins(objs[i], elems.Index(i))
					}
				}

				if joins.Len() > 0 {
					db.AddError(db.Session(&gorm.Session{NewDB: true}).Clauses(clause.OnConflict{DoNothing: true}).Session(&gorm.Session{
						SkipHooks:                db.Statement.SkipHooks,
						DisableNestedTransaction: true,
					}).Create(joins.Interface()).Error)
				}
			}
		}
	}
}

func onConflictOption(stmt *gorm.Statement, s *schema.Schema, defaultUpdatingColumns []string) (onConflict clause.OnConflict) {
	if len(defaultUpdatingColumns) > 0 || stmt.DB.FullSaveAssociations {
		onConflict.Columns = make([]clause.Column, 0, len(s.PrimaryFieldDBNames))
		for _, dbName := range s.PrimaryFieldDBNames {
			onConflict.Columns = append(onConflict.Columns, clause.Column{Name: dbName})
		}

		onConflict.UpdateAll = stmt.DB.FullSaveAssociations
		if !onConflict.UpdateAll {
			onConflict.DoUpdates = clause.AssignmentColumns(defaultUpdatingColumns)
		}
	} else {
		onConflict.DoNothing = true
	}

	return
}

func saveAssociations(db *gorm.DB, rel *schema.Relationship, rValues reflect.Value, selectColumns map[string]bool, restricted bool, defaultUpdatingColumns []string) error {
	// stop save association loop
	if checkAssociationsSaved(db, rValues) {
		return nil
	}

	var (
		selects, omits []string
		onConflict     = onConflictOption(db.Statement, rel.FieldSchema, defaultUpdatingColumns)
		refName        = rel.Name + "."
		values         = rValues.Interface()
	)

	for name, ok := range selectColumns {
		columnName := ""
		if strings.HasPrefix(name, refName) {
			columnName = strings.TrimPrefix(name, refName)
		}

		if columnName != "" {
			if ok {
				selects = append(selects, columnName)
			} else {
				omits = append(omits, columnName)
			}
		}
	}

	tx := db.Session(&gorm.Session{NewDB: true}).Clauses(onConflict).Session(&gorm.Session{
		FullSaveAssociations:     db.FullSaveAssociations,
		SkipHooks:                db.Statement.SkipHooks,
		DisableNestedTransaction: true,
	})

	db.Statement.Settings.Range(func(k, v interface{}) bool {
		tx.Statement.Settings.Store(k, v)
		return true
	})

	if tx.Statement.FullSaveAssociations {
		tx = tx.Set("gorm:update_track_time", true)
	}

	if len(selects) > 0 {
		tx = tx.Select(selects)
	} else if restricted && len(omits) == 0 {
		tx = tx.Omit(clause.Associations)
	}

	if len(omits) > 0 {
		tx = tx.Omit(omits...)
	}

	return db.AddError(tx.Create(values).Error)
}

// check association values has been saved
// if values kind is Struct, check it has been saved
// if values kind is Slice/Array, check all items have been saved
var visitMapStoreKey = "gorm:saved_association_map"

func checkAssociationsSaved(db *gorm.DB, values reflect.Value) bool {
	if visit, ok := db.Get(visitMapStoreKey); ok {
		if v, ok := visit.(*visitMap); ok {
			if loadOrStoreVisitMap(v, values) {
				return true
			}
		}
	} else {
		vistMap := make(visitMap)
		loadOrStoreVisitMap(&vistMap, values)
		db.Set(visitMapStoreKey, &vistMap)
	}

	return false
}


================================================
FILE: callbacks/callbacks.go
================================================
package callbacks

import (
	"gorm.io/gorm"
)

var (
	createClauses = []string{"INSERT", "VALUES", "ON CONFLICT"}
	queryClauses  = []string{"SELECT", "FROM", "WHERE", "GROUP BY", "ORDER BY", "LIMIT", "FOR"}
	updateClauses = []string{"UPDATE", "SET", "WHERE"}
	deleteClauses = []string{"DELETE", "FROM", "WHERE"}
)

type Config struct {
	LastInsertIDReversed bool
	CreateClauses        []string
	QueryClauses         []string
	UpdateClauses        []string
	DeleteClauses        []string
}

func RegisterDefaultCallbacks(db *gorm.DB, config *Config) {
	enableTransaction := func(db *gorm.DB) bool {
		return !db.SkipDefaultTransaction
	}

	if len(config.CreateClauses) == 0 {
		config.CreateClauses = createClauses
	}
	if len(config.QueryClauses) == 0 {
		config.QueryClauses = queryClauses
	}
	if len(config.DeleteClauses) == 0 {
		config.DeleteClauses = deleteClauses
	}
	if len(config.UpdateClauses) == 0 {
		config.UpdateClauses = updateClauses
	}

	createCallback := db.Callback().Create()
	createCallback.Match(enableTransaction).Register("gorm:begin_transaction", BeginTransaction)
	createCallback.Register("gorm:before_create", BeforeCreate)
	createCallback.Register("gorm:save_before_associations", SaveBeforeAssociations(true))
	createCallback.Register("gorm:create", Create(config))
	createCallback.Register("gorm:save_after_associations", SaveAfterAssociations(true))
	createCallback.Register("gorm:after_create", AfterCreate)
	createCallback.Match(enableTransaction).Register("gorm:commit_or_rollback_transaction", CommitOrRollbackTransaction)
	createCallback.Clauses = config.CreateClauses

	queryCallback := db.Callback().Query()
	queryCallback.Register("gorm:query", Query)
	queryCallback.Register("gorm:preload", Preload)
	queryCallback.Register("gorm:after_query", AfterQuery)
	queryCallback.Clauses = config.QueryClauses

	deleteCallback := db.Callback().Delete()
	deleteCallback.Match(enableTransaction).Register("gorm:begin_transaction", BeginTransaction)
	deleteCallback.Register("gorm:before_delete", BeforeDelete)
	deleteCallback.Register("gorm:delete_before_associations", DeleteBeforeAssociations)
	deleteCallback.Register("gorm:delete", Delete(config))
	deleteCallback.Register("gorm:after_delete", AfterDelete)
	deleteCallback.Match(enableTransaction).Register("gorm:commit_or_rollback_transaction", CommitOrRollbackTransaction)
	deleteCallback.Clauses = config.DeleteClauses

	updateCallback := db.Callback().Update()
	updateCallback.Match(enableTransaction).Register("gorm:begin_transaction", BeginTransaction)
	updateCallback.Register("gorm:setup_reflect_value", SetupUpdateReflectValue)
	updateCallback.Register("gorm:before_update", BeforeUpdate)
	updateCallback.Register("gorm:save_before_associations", SaveBeforeAssociations(false))
	updateCallback.Register("gorm:update", Update(config))
	updateCallback.Register("gorm:save_after_associations", SaveAfterAssociations(false))
	updateCallback.Register("gorm:after_update", AfterUpdate)
	updateCallback.Match(enableTransaction).Register("gorm:commit_or_rollback_transaction", CommitOrRollbackTransaction)
	updateCallback.Clauses = config.UpdateClauses

	rowCallback := db.Callback().Row()
	rowCallback.Register("gorm:row", RowQuery)
	rowCallback.Clauses = config.QueryClauses

	rawCallback := db.Callback().Raw()
	rawCallback.Register("gorm:raw", RawExec)
	rawCallback.Clauses = config.QueryClauses
}


================================================
FILE: callbacks/callmethod.go
================================================
package callbacks

import (
	"reflect"

	"gorm.io/gorm"
)

func callMethod(db *gorm.DB, fc func(value interface{}, tx *gorm.DB) bool) {
	tx := db.Session(&gorm.Session{NewDB: true})
	if called := fc(db.Statement.ReflectValue.Interface(), tx); !called {
		switch db.Statement.ReflectValue.Kind() {
		case reflect.Slice, reflect.Array:
			db.Statement.CurDestIndex = 0
			for i := 0; i < db.Statement.ReflectValue.Len(); i++ {
				if value := reflect.Indirect(db.Statement.ReflectValue.Index(i)); value.CanAddr() {
					fc(value.Addr().Interface(), tx)
				} else {
					db.AddError(gorm.ErrInvalidValue)
					return
				}
				db.Statement.CurDestIndex++
			}
		case reflect.Struct:
			if db.Statement.ReflectValue.CanAddr() {
				fc(db.Statement.ReflectValue.Addr().Interface(), tx)
			} else {
				db.AddError(gorm.ErrInvalidValue)
			}
		}
	}
}


================================================
FILE: callbacks/create.go
================================================
package callbacks

import (
	"fmt"
	"reflect"
	"strings"

	"gorm.io/gorm"
	"gorm.io/gorm/clause"
	"gorm.io/gorm/schema"
	"gorm.io/gorm/utils"
)

// BeforeCreate before create hooks
func BeforeCreate(db *gorm.DB) {
	if db.Error == nil && db.Statement.Schema != nil && !db.Statement.SkipHooks && (db.Statement.Schema.BeforeSave || db.Statement.Schema.BeforeCreate) {
		callMethod(db, func(value interface{}, tx *gorm.DB) (called bool) {
			if db.Statement.Schema.BeforeSave {
				if i, ok := value.(BeforeSaveInterface); ok {
					called = true
					db.AddError(i.BeforeSave(tx))
				}
			}

			if db.Statement.Schema.BeforeCreate {
				if i, ok := value.(BeforeCreateInterface); ok {
					called = true
					db.AddError(i.BeforeCreate(tx))
				}
			}
			return called
		})
	}
}

// Create create hook
func Create(config *Config) func(db *gorm.DB) {
	supportReturning := utils.Contains(config.CreateClauses, "RETURNING")

	return func(db *gorm.DB) {
		if db.Error != nil {
			return
		}

		if db.Statement.Schema != nil {
			if !db.Statement.Unscoped {
				for _, c := range db.Statement.Schema.CreateClauses {
					db.Statement.AddClause(c)
				}
			}

			if supportReturning && len(db.Statement.Schema.FieldsWithDefaultDBValue) > 0 {
				if _, ok := db.Statement.Clauses["RETURNING"]; !ok {
					fromColumns := make([]clause.Column, 0, len(db.Statement.Schema.FieldsWithDefaultDBValue))
					for _, field := range db.Statement.Schema.FieldsWithDefaultDBValue {
						if field.Readable {
							fromColumns = append(fromColumns, clause.Column{Name: field.DBName})
						}
					}
					if len(fromColumns) > 0 {
						db.Statement.AddClause(clause.Returning{Columns: fromColumns})
					}
				}
			}
		}

		if db.Statement.SQL.Len() == 0 {
			db.Statement.SQL.Grow(180)
			db.Statement.AddClauseIfNotExists(clause.Insert{})
			db.Statement.AddClause(ConvertToCreateValues(db.Statement))

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

		isDryRun := !db.DryRun && db.Error == nil
		if !isDryRun {
			return
		}

		ok, mode := hasReturning(db, supportReturning)
		if ok {
			if c, ok := db.Statement.Clauses["ON CONFLICT"]; ok {
				onConflict, _ := c.Expression.(clause.OnConflict)
				if onConflict.DoNothing {
					mode |= gorm.ScanOnConflictDoNothing
				} else if len(onConflict.DoUpdates) > 0 || onConflict.UpdateAll {
					mode |= gorm.ScanUpdate
				}
			}

			rows, err := db.Statement.ConnPool.QueryContext(
				db.Statement.Context, db.Statement.SQL.String(), db.Statement.Vars...,
			)
			if db.AddError(err) == nil {
				defer func() {
					db.AddError(rows.Close())
				}()
				gorm.Scan(rows, db, mode)

				if db.Statement.Result != nil {
					db.Statement.Result.RowsAffected = db.RowsAffected
				}
			}

			return
		}

		result, err := db.Statement.ConnPool.ExecContext(
			db.Statement.Context, db.Statement.SQL.String(), db.Statement.Vars...,
		)
		if err != nil {
			db.AddError(err)
			return
		}

		db.RowsAffected, _ = result.RowsAffected()

		if db.Statement.Result != nil {
			db.Statement.Result.Result = result
			db.Statement.Result.RowsAffected = db.RowsAffected
		}

		if db.RowsAffected == 0 {
			return
		}

		var (
			pkField     *schema.Field
			pkFieldName = "@id"
		)

		if db.Statement.Schema != nil {
			if db.Statement.Schema.PrioritizedPrimaryField == nil ||
				!db.Statement.Schema.PrioritizedPrimaryField.HasDefaultValue ||
				!db.Statement.Schema.PrioritizedPrimaryField.Readable {
				return
			}
			pkField = db.Statement.Schema.PrioritizedPrimaryField
			pkFieldName = db.Statement.Schema.PrioritizedPrimaryField.DBName
		}

		insertID, err := result.LastInsertId()
		insertOk := err == nil && insertID > 0

		if !insertOk {
			if !supportReturning {
				db.AddError(err)
			}
			return
		}

		// append @id column with value for auto-increment primary key
		// the @id value is correct, when: 1. without setting auto-increment primary key, 2. database AutoIncrementIncrement = 1
		switch values := db.Statement.Dest.(type) {
		case map[string]interface{}:
			values[pkFieldName] = insertID
		case *map[string]interface{}:
			(*values)[pkFieldName] = insertID
		case []map[string]interface{}, *[]map[string]interface{}:
			mapValues, ok := values.([]map[string]interface{})
			if !ok {
				if v, ok := values.(*[]map[string]interface{}); ok {
					if *v != nil {
						mapValues = *v
					}
				}
			}

			if config.LastInsertIDReversed {
				insertID -= int64(len(mapValues)-1) * schema.DefaultAutoIncrementIncrement
			}

			for _, mapValue := range mapValues {
				if mapValue != nil {
					mapValue[pkFieldName] = insertID
				}
				insertID += schema.DefaultAutoIncrementIncrement
			}
		default:
			if pkField == nil {
				return
			}

			switch db.Statement.ReflectValue.Kind() {
			case reflect.Slice, reflect.Array:
				if config.LastInsertIDReversed {
					for i := db.Statement.ReflectValue.Len() - 1; i >= 0; i-- {
						rv := db.Statement.ReflectValue.Index(i)
						if reflect.Indirect(rv).Kind() != reflect.Struct {
							break
						}

						_, isZero := pkField.ValueOf(db.Statement.Context, rv)
						if isZero {
							db.AddError(pkField.Set(db.Statement.Context, rv, insertID))
							insertID -= pkField.AutoIncrementIncrement
						}
					}
				} else {
					for i := 0; i < db.Statement.ReflectValue.Len(); i++ {
						rv := db.Statement.ReflectValue.Index(i)
						if reflect.Indirect(rv).Kind() != reflect.Struct {
							break
						}

						if _, isZero := pkField.ValueOf(db.Statement.Context, rv); isZero {
							db.AddError(pkField.Set(db.Statement.Context, rv, insertID))
							insertID += pkField.AutoIncrementIncrement
						}
					}
				}
			case reflect.Struct:
				_, isZero := pkField.ValueOf(db.Statement.Context, db.Statement.ReflectValue)
				if isZero {
					db.AddError(pkField.Set(db.Statement.Context, db.Statement.ReflectValue, insertID))
				}
			}
		}
	}
}

// AfterCreate after create hooks
func AfterCreate(db *gorm.DB) {
	if db.Error == nil && db.Statement.Schema != nil && !db.Statement.SkipHooks && (db.Statement.Schema.AfterSave || db.Statement.Schema.AfterCreate) {
		callMethod(db, func(value interface{}, tx *gorm.DB) (called bool) {
			if db.Statement.Schema.AfterCreate {
				if i, ok := value.(AfterCreateInterface); ok {
					called = true
					db.AddError(i.AfterCreate(tx))
				}
			}

			if db.Statement.Schema.AfterSave {
				if i, ok := value.(AfterSaveInterface); ok {
					called = true
					db.AddError(i.AfterSave(tx))
				}
			}
			return called
		})
	}
}

// ConvertToCreateValues convert to create values
func ConvertToCreateValues(stmt *gorm.Statement) (values clause.Values) {
	curTime := stmt.DB.NowFunc()

	switch value := stmt.Dest.(type) {
	case map[string]interface{}:
		values = ConvertMapToValuesForCreate(stmt, value)
	case *map[string]interface{}:
		values = ConvertMapToValuesForCreate(stmt, *value)
	case []map[string]interface{}:
		values = ConvertSliceOfMapToValuesForCreate(stmt, value)
	case *[]map[string]interface{}:
		values = ConvertSliceOfMapToValuesForCreate(stmt, *value)
	default:
		var (
			selectColumns, restricted = stmt.SelectAndOmitColumns(true, false)
			_, updateTrackTime        = stmt.Get("gorm:update_track_time")
			isZero                    bool
		)
		stmt.Settings.Delete("gorm:update_track_time")

		values = clause.Values{Columns: make([]clause.Column, 0, len(stmt.Schema.DBNames))}

		for _, db := range stmt.Schema.DBNames {
			if field := stmt.Schema.FieldsByDBName[db]; !field.HasDefaultValue || field.DefaultValueInterface != nil {
				if v, ok := selectColumns[db]; (ok && v) || (!ok && (!restricted || field.AutoCreateTime > 0 || field.AutoUpdateTime > 0)) {
					values.Columns = append(values.Columns, clause.Column{Name: db})
				}
			}
		}

		switch stmt.ReflectValue.Kind() {
		case reflect.Slice, reflect.Array:
			rValLen := stmt.ReflectValue.Len()
			if rValLen == 0 {
				stmt.AddError(gorm.ErrEmptySlice)
				return
			}

			stmt.SQL.Grow(rValLen * 18)
			stmt.Vars = make([]interface{}, 0, rValLen*len(values.Columns))
			values.Values = make([][]interface{}, rValLen)

			defaultValueFieldsHavingValue := map[*schema.Field][]interface{}{}
			for i := 0; i < rValLen; i++ {
				rv := reflect.Indirect(stmt.ReflectValue.Index(i))
				if !rv.IsValid() {
					stmt.AddError(fmt.Errorf("slice data #%v is invalid: %w", i, gorm.ErrInvalidData))
					return
				}

				values.Values[i] = make([]interface{}, len(values.Columns))
				for idx, column := range values.Columns {
					field := stmt.Schema.FieldsByDBName[column.Name]
					if values.Values[i][idx], isZero = field.ValueOf(stmt.Context, rv); isZero {
						if field.DefaultValueInterface != nil {
							values.Values[i][idx] = field.DefaultValueInterface
							stmt.AddError(field.Set(stmt.Context, rv, field.DefaultValueInterface))
						} else if field.AutoCreateTime > 0 || field.AutoUpdateTime > 0 {
							stmt.AddError(field.Set(stmt.Context, rv, curTime))
							values.Values[i][idx], _ = field.ValueOf(stmt.Context, rv)
						}
					} else if field.AutoUpdateTime > 0 && updateTrackTime {
						stmt.AddError(field.Set(stmt.Context, rv, curTime))
						values.Values[i][idx], _ = field.ValueOf(stmt.Context, rv)
					}
				}

				for _, field := range stmt.Schema.FieldsWithDefaultDBValue {
					if v, ok := selectColumns[field.DBName]; (ok && v) || (!ok && !restricted) {
						if rvOfvalue, isZero := field.ValueOf(stmt.Context, rv); !isZero {
							if len(defaultValueFieldsHavingValue[field]) == 0 {
								defaultValueFieldsHavingValue[field] = make([]interface{}, rValLen)
							}
							defaultValueFieldsHavingValue[field][i] = rvOfvalue
						}
					}
				}
			}

			for _, field := range stmt.Schema.FieldsWithDefaultDBValue {
				if vs, ok := defaultValueFieldsHavingValue[field]; ok {
					values.Columns = append(values.Columns, clause.Column{Name: field.DBName})
					for idx := range values.Values {
						if vs[idx] == nil {
							values.Values[idx] = append(values.Values[idx], stmt.DefaultValueOf(field))
						} else {
							values.Values[idx] = append(values.Values[idx], vs[idx])
						}
					}
				}
			}
		case reflect.Struct:
			values.Values = [][]interface{}{make([]interface{}, len(values.Columns))}
			for idx, column := range values.Columns {
				field := stmt.Schema.FieldsByDBName[column.Name]
				if values.Values[0][idx], isZero = field.ValueOf(stmt.Context, stmt.ReflectValue); isZero {
					if field.DefaultValueInterface != nil {
						values.Values[0][idx] = field.DefaultValueInterface
						stmt.AddError(field.Set(stmt.Context, stmt.ReflectValue, field.DefaultValueInterface))
					} else if field.AutoCreateTime > 0 || field.AutoUpdateTime > 0 {
						stmt.AddError(field.Set(stmt.Context, stmt.ReflectValue, curTime))
						values.Values[0][idx], _ = field.ValueOf(stmt.Context, stmt.ReflectValue)
					}
				} else if field.AutoUpdateTime > 0 && updateTrackTime {
					stmt.AddError(field.Set(stmt.Context, stmt.ReflectValue, curTime))
					values.Values[0][idx], _ = field.ValueOf(stmt.Context, stmt.ReflectValue)
				}
			}

			for _, field := range stmt.Schema.FieldsWithDefaultDBValue {
				if v, ok := selectColumns[field.DBName]; (ok && v) || (!ok && !restricted) && field.DefaultValueInterface == nil {
					if rvOfvalue, isZero := field.ValueOf(stmt.Context, stmt.ReflectValue); !isZero {
						values.Columns = append(values.Columns, clause.Column{Name: field.DBName})
						values.Values[0] = append(values.Values[0], rvOfvalue)
					}
				}
			}
		default:
			stmt.AddError(gorm.ErrInvalidData)
		}
	}

	if c, ok := stmt.Clauses["ON CONFLICT"]; ok {
		if onConflict, _ := c.Expression.(clause.OnConflict); onConflict.UpdateAll {
			if stmt.Schema != nil && len(values.Columns) >= 1 {
				selectColumns, restricted := stmt.SelectAndOmitColumns(true, true)

				columns := make([]string, 0, len(values.Columns)-1)
				for _, column := range values.Columns {
					if field := stmt.Schema.LookUpField(column.Name); field != nil {
						if v, ok := selectColumns[field.DBName]; (ok && v) || (!ok && !restricted) {
							if !field.PrimaryKey && (!field.HasDefaultValue || field.DefaultValueInterface != nil ||
								strings.EqualFold(field.DefaultValue, "NULL")) && field.AutoCreateTime == 0 {
								if field.AutoUpdateTime > 0 {
									assignment := clause.Assignment{Column: clause.Column{Name: field.DBName}, Value: curTime}
									switch field.AutoUpdateTime {
									case schema.UnixNanosecond:
										assignment.Value = curTime.UnixNano()
									case schema.UnixMillisecond:
										assignment.Value = curTime.UnixMilli()
									case schema.UnixSecond:
										assignment.Value = curTime.Unix()
									}

									onConflict.DoUpdates = append(onConflict.DoUpdates, assignment)
								} else {
									columns = append(columns, column.Name)
								}
							}
						}
					}
				}

				onConflict.DoUpdates = append(onConflict.DoUpdates, clause.AssignmentColumns(columns)...)
				if len(onConflict.DoUpdates) == 0 {
					onConflict.DoNothing = true
				}

				// use primary fields as default OnConflict columns
				if len(onConflict.Columns) == 0 {
					for _, field := range stmt.Schema.PrimaryFields {
						onConflict.Columns = append(onConflict.Columns, clause.Column{Name: field.DBName})
					}
				}
				stmt.AddClause(onConflict)
			}
		}
	}

	return values
}


================================================
FILE: callbacks/create_test.go
================================================
package callbacks

import (
	"reflect"
	"sync"
	"testing"
	"time"

	"gorm.io/gorm"
	"gorm.io/gorm/clause"
	"gorm.io/gorm/schema"
)

var schemaCache = &sync.Map{}

func TestConvertToCreateValues_DestType_Slice(t *testing.T) {
	type user struct {
		ID    int `gorm:"primaryKey"`
		Name  string
		Email string `gorm:"default:(-)"`
		Age   int    `gorm:"default:(-)"`
	}

	s, err := schema.Parse(&user{}, schemaCache, schema.NamingStrategy{})
	if err != nil {
		t.Errorf("parse schema error: %v, is not expected", err)
		return
	}
	dest := []*user{
		{
			ID:    1,
			Name:  "alice",
			Email: "email",
			Age:   18,
		},
		{
			ID:    2,
			Name:  "bob",
			Email: "email",
			Age:   19,
		},
	}
	stmt := &gorm.Statement{
		DB: &gorm.DB{
			Config: &gorm.Config{
				NowFunc: func() time.Time { return time.Time{} },
			},
			Statement: &gorm.Statement{
				Settings: sync.Map{},
				Schema:   s,
			},
		},
		ReflectValue: reflect.ValueOf(dest),
		Dest:         dest,
	}

	stmt.Schema = s

	values := ConvertToCreateValues(stmt)
	expected := clause.Values{
		// column has value + defaultValue column has value (which should have a stable order)
		Columns: []clause.Column{{Name: "name"}, {Name: "email"}, {Name: "age"}, {Name: "id"}},
		Values: [][]interface{}{
			{"alice", "email", 18, 1},
			{"bob", "email", 19, 2},
		},
	}
	if !reflect.DeepEqual(expected, values) {
		t.Errorf("expected: %v got %v", expected, values)
	}
}


================================================
FILE: callbacks/delete.go
================================================
package callbacks

import (
	"reflect"
	"strings"

	"gorm.io/gorm"
	"gorm.io/gorm/clause"
	"gorm.io/gorm/schema"
	"gorm.io/gorm/utils"
)

func BeforeDelete(db *gorm.DB) {
	if db.Error == nil && db.Statement.Schema != nil && !db.Statement.SkipHooks && db.Statement.Schema.BeforeDelete {
		callMethod(db, func(value interface{}, tx *gorm.DB) bool {
			if i, ok := value.(BeforeDeleteInterface); ok {
				db.AddError(i.BeforeDelete(tx))
				return true
			}

			return false
		})
	}
}

func DeleteBeforeAssociations(db *gorm.DB) {
	if db.Error == nil && db.Statement.Schema != nil {
		selectColumns, restricted := db.Statement.SelectAndOmitColumns(true, false)
		if !restricted {
			return
		}

		for column, v := range selectColumns {
			if !v {
				continue
			}

			rel, ok := db.Statement.Schema.Relationships.Relations[column]
			if !ok {
				continue
			}

			switch rel.Type {
			case schema.HasOne, schema.HasMany:
				queryConds := rel.ToQueryConditions(db.Statement.Context, db.Statement.ReflectValue)
				modelValue := reflect.New(rel.FieldSchema.ModelType).Interface()
				tx := db.Session(&gorm.Session{NewDB: true}).Model(modelValue)
				withoutConditions := false
				if db.Statement.Unscoped {
					tx = tx.Unscoped()
				}

				if len(db.Statement.Selects) > 0 {
					selects := make([]string, 0, len(db.Statement.Selects))
					for _, s := range db.Statement.Selects {
						if s == clause.Associations {
							selects = append(selects, s)
						} else if columnPrefix := column + "."; strings.HasPrefix(s, columnPrefix) {
							selects = append(selects, strings.TrimPrefix(s, columnPrefix))
						}
					}

					if len(selects) > 0 {
						tx = tx.Select(selects)
					}
				}

				for _, cond := range queryConds {
					if c, ok := cond.(clause.IN); ok && len(c.Values) == 0 {
						withoutConditions = true
						break
					}
				}

				if !withoutConditions && db.AddError(tx.Clauses(clause.Where{Exprs: queryConds}).Delete(modelValue).Error) != nil {
					return
				}
			case schema.Many2Many:
				var (
					queryConds     = make([]clause.Expression, 0, len(rel.References))
					foreignFields  = make([]*schema.Field, 0, len(rel.References))
					relForeignKeys = make([]string, 0, len(rel.References))
					modelValue     = reflect.New(rel.JoinTable.ModelType).Interface()
					table          = rel.JoinTable.Table
					tx             = db.Session(&gorm.Session{NewDB: true}).Model(modelValue).Table(table)
				)

				for _, ref := range rel.References {
					if ref.OwnPrimaryKey {
						foreignFields = append(foreignFields, ref.PrimaryKey)
						relForeignKeys = append(relForeignKeys, ref.ForeignKey.DBName)
					} else if ref.PrimaryValue != "" {
						queryConds = append(queryConds, clause.Eq{
							Column: clause.Column{Table: rel.JoinTable.Table, Name: ref.ForeignKey.DBName},
							Value:  ref.PrimaryValue,
						})
					}
				}

				_, foreignValues := schema.GetIdentityFieldValuesMap(db.Statement.Context, db.Statement.ReflectValue, foreignFields)
				column, values := schema.ToQueryValues(table, relForeignKeys, foreignValues)
				queryConds = append(queryConds, clause.IN{Column: column, Values: values})

				if db.AddError(tx.Clauses(clause.Where{Exprs: queryConds}).Delete(modelValue).Error) != nil {
					return
				}
			}
		}

	}
}

func Delete(config *Config) func(db *gorm.DB) {
	supportReturning := utils.Contains(config.DeleteClauses, "RETURNING")

	return func(db *gorm.DB) {
		if db.Error != nil {
			return
		}

		if db.Statement.Schema != nil {
			for _, c := range db.Statement.Schema.DeleteClauses {
				db.Statement.AddClause(c)
			}
		}

		if db.Statement.SQL.Len() == 0 {
			db.Statement.SQL.Grow(100)
			db.Statement.AddClauseIfNotExists(clause.Delete{})

			if db.Statement.Schema != nil {
				_, queryValues := schema.GetIdentityFieldValuesMap(db.Statement.Context, db.Statement.ReflectValue, db.Statement.Schema.PrimaryFields)
				column, values := schema.ToQueryValues(db.Statement.Table, db.Statement.Schema.PrimaryFieldDBNames, queryValues)

				if len(values) > 0 {
					db.Statement.AddClause(clause.Where{Exprs: []clause.Expression{clause.IN{Column: column, Values: values}}})
				}

				if db.Statement.ReflectValue.CanAddr() && db.Statement.Dest != db.Statement.Model && db.Statement.Model != nil {
					_, queryValues = schema.GetIdentityFieldValuesMap(db.Statement.Context, reflect.ValueOf(db.Statement.Model), db.Statement.Schema.PrimaryFields)
					column, values = schema.ToQueryValues(db.Statement.Table, db.Statement.Schema.PrimaryFieldDBNames, queryValues)

					if len(values) > 0 {
						db.Statement.AddClause(clause.Where{Exprs: []clause.Expression{clause.IN{Column: column, Values: values}}})
					}
				}
			}

			db.Statement.AddClauseIfNotExists(clause.From{})

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

		checkMissingWhereConditions(db)

		if !db.DryRun && db.Error == nil {
			ok, mode := hasReturning(db, supportReturning)
			if !ok {
				result, err := db.Statement.ConnPool.ExecContext(db.Statement.Context, db.Statement.SQL.String(), db.Statement.Vars...)

				if db.AddError(err) == nil {
					db.RowsAffected, _ = result.RowsAffected()

					if db.Statement.Result != nil {
						db.Statement.Result.Result = result
						db.Statement.Result.RowsAffected = db.RowsAffected
					}
				}

				return
			}

			if rows, err := db.Statement.ConnPool.QueryContext(db.Statement.Context, db.Statement.SQL.String(), db.Statement.Vars...); db.AddError(err) == nil {
				gorm.Scan(rows, db, mode)

				if db.Statement.Result != nil {
					db.Statement.Result.RowsAffected = db.RowsAffected
				}
				db.AddError(rows.Close())
			}
		}
	}
}

func AfterDelete(db *gorm.DB) {
	if db.Error == nil && db.Statement.Schema != nil && !db.Statement.SkipHooks && db.Statement.Schema.AfterDelete {
		callMethod(db, func(value interface{}, tx *gorm.DB) bool {
			if i, ok := value.(AfterDeleteInterface); ok {
				db.AddError(i.AfterDelete(tx))
				return true
			}
			return false
		})
	}
}


================================================
FILE: callbacks/helper.go
================================================
package callbacks

import (
	"reflect"
	"sort"

	"gorm.io/gorm"
	"gorm.io/gorm/clause"
)

// ConvertMapToValuesForCreate convert map to values
func ConvertMapToValuesForCreate(stmt *gorm.Statement, mapValue map[string]interface{}) (values clause.Values) {
	values.Columns = make([]clause.Column, 0, len(mapValue))
	selectColumns, restricted := stmt.SelectAndOmitColumns(true, false)

	keys := make([]string, 0, len(mapValue))
	for k := range mapValue {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	for _, k := range keys {
		value := mapValue[k]
		if stmt.Schema != nil {
			if field := stmt.Schema.LookUpField(k); field != nil {
				k = field.DBName
			}
		}

		if v, ok := selectColumns[k]; (ok && v) || (!ok && !restricted) {
			values.Columns = append(values.Columns, clause.Column{Name: k})
			if len(values.Values) == 0 {
				values.Values = [][]interface{}{{}}
			}

			values.Values[0] = append(values.Values[0], value)
		}
	}
	return
}

// ConvertSliceOfMapToValuesForCreate convert slice of map to values
func ConvertSliceOfMapToValuesForCreate(stmt *gorm.Statement, mapValues []map[string]interface{}) (values clause.Values) {
	columns := make([]string, 0, len(mapValues))

	// when the length of mapValues is zero,return directly here
	// no need to call stmt.SelectAndOmitColumns method
	if len(mapValues) == 0 {
		stmt.AddError(gorm.ErrEmptySlice)
		return
	}

	var (
		result                    = make(map[string][]interface{}, len(mapValues))
		selectColumns, restricted = stmt.SelectAndOmitColumns(true, false)
	)

	for idx, mapValue := range mapValues {
		for k, v := range mapValue {
			if stmt.Schema != nil {
				if field := stmt.Schema.LookUpField(k); field != nil {
					k = field.DBName
				}
			}

			if _, ok := result[k]; !ok {
				if v, ok := selectColumns[k]; (ok && v) || (!ok && !restricted) {
					result[k] = make([]interface{}, len(mapValues))
					columns = append(columns, k)
				} else {
					continue
				}
			}

			result[k][idx] = v
		}
	}

	sort.Strings(columns)
	values.Values = make([][]interface{}, len(mapValues))
	values.Columns = make([]clause.Column, len(columns))
	for idx, column := range columns {
		values.Columns[idx] = clause.Column{Name: column}

		for i, v := range result[column] {
			if len(values.Values[i]) == 0 {
				values.Values[i] = make([]interface{}, len(columns))
			}

			values.Values[i][idx] = v
		}
	}
	return
}

func hasReturning(tx *gorm.DB, supportReturning bool) (bool, gorm.ScanMode) {
	if supportReturning {
		if c, ok := tx.Statement.Clauses["RETURNING"]; ok {
			returning, _ := c.Expression.(clause.Returning)
			if len(returning.Columns) == 0 || (len(returning.Columns) == 1 && returning.Columns[0].Name == "*") {
				return true, 0
			}
			return true, gorm.ScanUpdate
		}
	}
	return false, 0
}

func checkMissingWhereConditions(db *gorm.DB) {
	if !db.AllowGlobalUpdate && db.Error == nil {
		where, withCondition := db.Statement.Clauses["WHERE"]
		if withCondition {
			if _, withSoftDelete := db.Statement.Clauses["soft_delete_enabled"]; withSoftDelete {
				whereClause, _ := where.Expression.(clause.Where)
				withCondition = len(whereClause.Exprs) > 1
			}
		}
		if !withCondition {
			db.AddError(gorm.ErrMissingWhereClause)
		}
		return
	}
}

type visitMap = map[reflect.Value]bool

// Check if circular values, return true if loaded
func loadOrStoreVisitMap(visitMap *visitMap, v reflect.Value) (loaded bool) {
	if v.Kind() == reflect.Ptr {
		v = v.Elem()
	}

	switch v.Kind() {
	case reflect.Slice, reflect.Array:
		loaded = true
		for i := 0; i < v.Len(); i++ {
			if !loadOrStoreVisitMap(visitMap, v.Index(i)) {
				loaded = false
			}
		}
	case reflect.Struct, reflect.Interface:
		if v.CanAddr() {
			p := v.Addr()
			if _, ok := (*visitMap)[p]; ok {
				return true
			}
			(*visitMap)[p] = true
		}
	}

	return
}


================================================
FILE: callbacks/helper_test.go
================================================
package callbacks

import (
	"reflect"
	"testing"

	"gorm.io/gorm"
	"gorm.io/gorm/clause"
)

func TestLoadOrStoreVisitMap(t *testing.T) {
	var vm visitMap
	var loaded bool
	type testM struct {
		Name string
	}

	t1 := testM{Name: "t1"}
	t2 := testM{Name: "t2"}
	t3 := testM{Name: "t3"}

	vm = make(visitMap)
	if loaded = loadOrStoreVisitMap(&vm, reflect.ValueOf(&t1)); loaded {
		t.Fatalf("loaded should be false")
	}

	if loaded = loadOrStoreVisitMap(&vm, reflect.ValueOf(&t1)); !loaded {
		t.Fatalf("loaded should be true")
	}

	// t1 already exist but t2 not
	if loaded = loadOrStoreVisitMap(&vm, reflect.ValueOf([]*testM{&t1, &t2, &t3})); loaded {
		t.Fatalf("loaded should be false")
	}

	if loaded = loadOrStoreVisitMap(&vm, reflect.ValueOf([]*testM{&t2, &t3})); !loaded {
		t.Fatalf("loaded should be true")
	}
}

func TestConvertMapToValuesForCreate(t *testing.T) {
	testCase := []struct {
		name   string
		input  map[string]interface{}
		expect clause.Values
	}{
		{
			name: "Test convert string value",
			input: map[string]interface{}{
				"name": "my name",
			},
			expect: clause.Values{
				Columns: []clause.Column{{Name: "name"}},
				Values:  [][]interface{}{{"my name"}},
			},
		},
		{
			name: "Test convert int value",
			input: map[string]interface{}{
				"age": 18,
			},
			expect: clause.Values{
				Columns: []clause.Column{{Name: "age"}},
				Values:  [][]interface{}{{18}},
			},
		},
		{
			name: "Test convert float value",
			input: map[string]interface{}{
				"score": 99.5,
			},
			expect: clause.Values{
				Columns: []clause.Column{{Name: "score"}},
				Values:  [][]interface{}{{99.5}},
			},
		},
		{
			name: "Test convert bool value",
			input: map[string]interface{}{
				"active": true,
			},
			expect: clause.Values{
				Columns: []clause.Column{{Name: "active"}},
				Values:  [][]interface{}{{true}},
			},
		},
	}

	for _, tc := range testCase {
		t.Run(tc.name, func(t *testing.T) {
			actual := ConvertMapToValuesForCreate(&gorm.Statement{}, tc.input)
			if !reflect.DeepEqual(actual, tc.expect) {
				t.Errorf("expect %v got %v", tc.expect, actual)
			}
		})
	}
}

func TestConvertSliceOfMapToValuesForCreate(t *testing.T) {
	testCase := []struct {
		name   string
		input  []map[string]interface{}
		expect clause.Values
	}{
		{
			name: "Test convert slice of string value",
			input: []map[string]interface{}{
				{"name": "my name"},
			},
			expect: clause.Values{
				Columns: []clause.Column{{Name: "name"}},
				Values:  [][]interface{}{{"my name"}},
			},
		},
		{
			name: "Test convert slice of int value",
			input: []map[string]interface{}{
				{"age": 18},
			},
			expect: clause.Values{
				Columns: []clause.Column{{Name: "age"}},
				Values:  [][]interface{}{{18}},
			},
		},
		{
			name: "Test convert slice of float value",
			input: []map[string]interface{}{
				{"score": 99.5},
			},
			expect: clause.Values{
				Columns: []clause.Column{{Name: "score"}},
				Values:  [][]interface{}{{99.5}},
			},
		},
		{
			name: "Test convert slice of bool value",
			input: []map[string]interface{}{
				{"active": true},
			},
			expect: clause.Values{
				Columns: []clause.Column{{Name: "active"}},
				Values:  [][]interface{}{{true}},
			},
		},
	}

	for _, tc := range testCase {
		t.Run(tc.name, func(t *testing.T) {
			actual := ConvertSliceOfMapToValuesForCreate(&gorm.Statement{}, tc.input)

			if !reflect.DeepEqual(actual, tc.expect) {
				t.Errorf("expected %v but got %v", tc.expect, actual)
			}
		})
	}

}


================================================
FILE: callbacks/interfaces.go
================================================
package callbacks

import "gorm.io/gorm"

type BeforeCreateInterface interface {
	BeforeCreate(*gorm.DB) error
}

type AfterCreateInterface interface {
	AfterCreate(*gorm.DB) error
}

type BeforeUpdateInterface interface {
	BeforeUpdate(*gorm.DB) error
}

type AfterUpdateInterface interface {
	AfterUpdate(*gorm.DB) error
}

type BeforeSaveInterface interface {
	BeforeSave(*gorm.DB) error
}

type AfterSaveInterface interface {
	AfterSave(*gorm.DB) error
}

type BeforeDeleteInterface interface {
	BeforeDelete(*gorm.DB) error
}

type AfterDeleteInterface interface {
	AfterDelete(*gorm.DB) error
}

type AfterFindInterface interface {
	AfterFind(*gorm.DB) error
}


================================================
FILE: callbacks/preload.go
================================================
package callbacks

import (
	"fmt"
	"reflect"
	"sort"
	"strings"

	"gorm.io/gorm"
	"gorm.io/gorm/clause"
	"gorm.io/gorm/schema"
	"gorm.io/gorm/utils"
)

// parsePreloadMap extracts nested preloads. e.g.
//
//	// schema has a "k0" relation and a "k7.k8" embedded relation
//	parsePreloadMap(schema, map[string][]interface{}{
//		clause.Associations: {"arg1"},
//		"k1":                {"arg2"},
//		"k2.k3":             {"arg3"},
//		"k4.k5.k6":          {"arg4"},
//	})
//	// preloadMap is
//	map[string]map[string][]interface{}{
//		"k0": {},
//		"k7": {
//			"k8": {},
//		},
//		"k1": {},
//		"k2": {
//			"k3": {"arg3"},
//		},
//		"k4": {
//			"k5.k6": {"arg4"},
//		},
//	}
func parsePreloadMap(s *schema.Schema, preloads map[string][]interface{}) map[string]map[string][]interface{} {
	preloadMap := map[string]map[string][]interface{}{}
	setPreloadMap := func(name, value string, args []interface{}) {
		if _, ok := preloadMap[name]; !ok {
			preloadMap[name] = map[string][]interface{}{}
		}
		if value != "" {
			preloadMap[name][value] = args
		}
	}

	for name, args := range preloads {
		preloadFields := strings.Split(name, ".")
		value := strings.TrimPrefix(strings.TrimPrefix(name, preloadFields[0]), ".")
		if preloadFields[0] == clause.Associations {
			for _, relation := range s.Relationships.Relations {
				if relation.Schema == s {
					setPreloadMap(relation.Name, value, args)
				}
			}

			for embedded, embeddedRelations := range s.Relationships.EmbeddedRelations {
				for _, value := range embeddedValues(embeddedRelations) {
					setPreloadMap(embedded, value, args)
				}
			}
		} else {
			setPreloadMap(preloadFields[0], value, args)
		}
	}
	return preloadMap
}

func embeddedValues(embeddedRelations *schema.Relationships) []string {
	if embeddedRelations == nil {
		return nil
	}
	names := make([]string, 0, len(embeddedRelations.Relations)+len(embeddedRelations.EmbeddedRelations))
	for _, relation := range embeddedRelations.Relations {
		// skip first struct name
		names = append(names, strings.Join(relation.Field.EmbeddedBindNames[1:], "."))
	}
	for _, relations := range embeddedRelations.EmbeddedRelations {
		names = append(names, embeddedValues(relations)...)
	}
	return names
}

// preloadEntryPoint enters layer by layer. It will call real preload if it finds the right entry point.
// If the current relationship is embedded or joined, current query will be ignored.
//
//nolint:cyclop
func preloadEntryPoint(db *gorm.DB, joins []string, relationships *schema.Relationships, preloads map[string][]interface{}, associationsConds []interface{}) error {
	preloadMap := parsePreloadMap(db.Statement.Schema, preloads)

	// avoid random traversal of the map
	preloadNames := make([]string, 0, len(preloadMap))
	for key := range preloadMap {
		preloadNames = append(preloadNames, key)
	}
	sort.Strings(preloadNames)

	isJoined := func(name string) (joined bool, nestedJoins []string) {
		for _, join := range joins {
			if _, ok := relationships.Relations[join]; ok && name == join {
				joined = true
				continue
			}
			join0, join1, cut := strings.Cut(join, ".")
			if cut {
				if _, ok := relationships.Relations[join0]; ok && name == join0 {
					joined = true
					nestedJoins = append(nestedJoins, join1)
				}
			}
		}
		return joined, nestedJoins
	}

	for _, name := range preloadNames {
		if relations := relationships.EmbeddedRelations[name]; relations != nil {
			if err := preloadEntryPoint(db, joins, relations, preloadMap[name], associationsConds); err != nil {
				return err
			}
		} else if rel := relationships.Relations[name]; rel != nil {
			if joined, nestedJoins := isJoined(name); joined {
				switch rv := db.Statement.ReflectValue; rv.Kind() {
				case reflect.Slice, reflect.Array:
					if rv.Len() > 0 {
						reflectValue := rel.FieldSchema.MakeSlice().Elem()
						for i := 0; i < rv.Len(); i++ {
							frv := rel.Field.ReflectValueOf(db.Statement.Context, rv.Index(i))
							if frv.Kind() != reflect.Ptr {
								reflectValue = reflect.Append(reflectValue, frv.Addr())
							} else {
								if frv.IsNil() {
									continue
								}
								reflectValue = reflect.Append(reflectValue, frv)
							}
						}

						tx := preloadDB(db, reflectValue, reflectValue.Interface())
						if err := preloadEntryPoint(tx, nestedJoins, &tx.Statement.Schema.Relationships, preloadMap[name], associationsConds); err != nil {
							return err
						}
					}
				case reflect.Struct, reflect.Pointer:
					reflectValue := rel.Field.ReflectValueOf(db.Statement.Context, rv)
					tx := preloadDB(db, reflectValue, reflectValue.Interface())
					if err := preloadEntryPoint(tx, nestedJoins, &tx.Statement.Schema.Relationships, preloadMap[name], associationsConds); err != nil {
						return err
					}
				default:
					return gorm.ErrInvalidData
				}
			} else {
				tx := db.Table("").Session(&gorm.Session{Context: db.Statement.Context, SkipHooks: db.Statement.SkipHooks})
				tx.Statement.ReflectValue = db.Statement.ReflectValue
				tx.Statement.Unscoped = db.Statement.Unscoped
				if err := preload(tx, rel, append(preloads[name], associationsConds...), preloadMap[name]); err != nil {
					return err
				}
			}
		} else {
			return fmt.Errorf("%s: %w for schema %s", name, gorm.ErrUnsupportedRelation, db.Statement.Schema.Name)
		}
	}
	return nil
}

func preloadDB(db *gorm.DB, reflectValue reflect.Value, dest interface{}) *gorm.DB {
	tx := db.Session(&gorm.Session{Context: db.Statement.Context, NewDB: true, SkipHooks: db.Statement.SkipHooks, Initialized: true})
	db.Statement.Settings.Range(func(k, v interface{}) bool {
		tx.Statement.Settings.Store(k, v)
		return true
	})

	if err := tx.Statement.Parse(dest); err != nil {
		tx.AddError(err)
		return tx
	}
	tx.Statement.ReflectValue = reflectValue
	tx.Statement.Unscoped = db.Statement.Unscoped
	return tx
}

func preload(tx *gorm.DB, rel *schema.Relationship, conds []interface{}, preloads map[string][]interface{}) error {
	var (
		reflectValue     = tx.Statement.ReflectValue
		relForeignKeys   []string
		relForeignFields []*schema.Field
		foreignFields    []*schema.Field
		foreignValues    [][]interface{}
		identityMap      = map[string][]reflect.Value{}
		inlineConds      []interface{}
	)

	if rel.JoinTable != nil {
		var (
			joinForeignFields    = make([]*schema.Field, 0, len(rel.References))
			joinRelForeignFields = make([]*schema.Field, 0, len(rel.References))
			joinForeignKeys      = make([]string, 0, len(rel.References))
		)

		for _, ref := range rel.References {
			if ref.OwnPrimaryKey {
				joinForeignKeys = append(joinForeignKeys, ref.ForeignKey.DBName)
				joinForeignFields = append(joinForeignFields, ref.ForeignKey)
				foreignFields = append(foreignFields, ref.PrimaryKey)
			} else if ref.PrimaryValue != "" {
				tx = tx.Where(clause.Eq{Column: ref.ForeignKey.DBName, Value: ref.PrimaryValue})
			} else {
				joinRelForeignFields = append(joinRelForeignFields, ref.ForeignKey)
				relForeignKeys = append(relForeignKeys, ref.PrimaryKey.DBName)
				relForeignFields = append(relForeignFields, ref.PrimaryKey)
			}
		}

		joinIdentityMap, joinForeignValues := schema.GetIdentityFieldValuesMap(tx.Statement.Context, reflectValue, foreignFields)
		if len(joinForeignValues) == 0 {
			return nil
		}

		joinResults := rel.JoinTable.MakeSlice().Elem()
		column, values := schema.ToQueryValues(clause.CurrentTable, joinForeignKeys, joinForeignValues)
		if err := tx.Where(clause.IN{Column: column, Values: values}).Find(joinResults.Addr().Interface()).Error; err != nil {
			return err
		}

		// convert join identity map to relation identity map
		fieldValues := make([]interface{}, len(joinForeignFields))
		joinFieldValues := make([]interface{}, len(joinRelForeignFields))
		for i := 0; i < joinResults.Len(); i++ {
			joinIndexValue := joinResults.Index(i)
			for idx, field := range joinForeignFields {
				fieldValues[idx], _ = field.ValueOf(tx.Statement.Context, joinIndexValue)
			}

			for idx, field := range joinRelForeignFields {
				joinFieldValues[idx], _ = field.ValueOf(tx.Statement.Context, joinIndexValue)
			}

			if results, ok := joinIdentityMap[utils.ToStringKey(fieldValues...)]; ok {
				joinKey := utils.ToStringKey(joinFieldValues...)
				identityMap[joinKey] = append(identityMap[joinKey], results...)
			}
		}

		_, foreignValues = schema.GetIdentityFieldValuesMap(tx.Statement.Context, joinResults, joinRelForeignFields)
	} else {
		for _, ref := range rel.References {
			if ref.OwnPrimaryKey {
				relForeignKeys = append(relForeignKeys, ref.ForeignKey.DBName)
				relForeignFields = append(relForeignFields, ref.ForeignKey)
				foreignFields = append(foreignFields, ref.PrimaryKey)
			} else if ref.PrimaryValue != "" {
				tx = tx.Where(clause.Eq{Column: ref.ForeignKey.DBName, Value: ref.PrimaryValue})
			} else {
				relForeignKeys = append(relForeignKeys, ref.PrimaryKey.DBName)
				relForeignFields = append(relForeignFields, ref.PrimaryKey)
				foreignFields = append(foreignFields, ref.ForeignKey)
			}
		}

		identityMap, foreignValues = schema.GetIdentityFieldValuesMap(tx.Statement.Context, reflectValue, foreignFields)
		if len(foreignValues) == 0 {
			return nil
		}
	}

	// nested preload
	for p, pvs := range preloads {
		tx = tx.Preload(p, pvs...)
	}

	reflectResults := rel.FieldSchema.MakeSlice().Elem()
	column, values := schema.ToQueryValues(clause.CurrentTable, relForeignKeys, foreignValues)

	if len(values) != 0 {
		tx = tx.Model(reflectResults.Addr().Interface()).Where(clause.IN{Column: column, Values: values})

		for _, cond := range conds {
			if fc, ok := cond.(func(*gorm.DB) *gorm.DB); ok {
				tx = fc(tx)
			} else {
				inlineConds = append(inlineConds, cond)
			}
		}

		if len(inlineConds) > 0 {
			tx = tx.Where(inlineConds[0], inlineConds[1:]...)
		}

		if err := tx.Find(reflectResults.Addr().Interface()).Error; err != nil {
			return err
		}
	}

	fieldValues := make([]interface{}, len(relForeignFields))

	// clean up old values before preloading
	switch reflectValue.Kind() {
	case reflect.Struct:
		switch rel.Type {
		case schema.HasMany, schema.Many2Many:
			tx.AddError(rel.Field.Set(tx.Statement.Context, reflectValue, reflect.MakeSlice(rel.Field.IndirectFieldType, 0, 10).Interface()))
		default:
			tx.AddError(rel.Field.Set(tx.Statement.Context, reflectValue, reflect.New(rel.Field.FieldType).Interface()))
		}
	case reflect.Slice, reflect.Array:
		for i := 0; i < reflectValue.Len(); i++ {
			switch rel.Type {
			case schema.HasMany, schema.Many2Many:
				tx.AddError(rel.Field.Set(tx.Statement.Context, reflectValue.Index(i), reflect.MakeSlice(rel.Field.IndirectFieldType, 0, 10).Interface()))
			default:
				tx.AddError(rel.Field.Set(tx.Statement.Context, reflectValue.Index(i), reflect.New(rel.Field.FieldType).Interface()))
			}
		}
	}

	for i := 0; i < reflectResults.Len(); i++ {
		elem := reflectResults.Index(i)
		for idx, field := range relForeignFields {
			fieldValues[idx], _ = field.ValueOf(tx.Statement.Context, elem)
		}

		datas, ok := identityMap[utils.ToStringKey(fieldValues...)]
		if !ok {
			return fmt.Errorf("failed to assign association %#v, make sure foreign fields exists", elem.Interface())
		}

		for _, data := range datas {
			reflectFieldValue := rel.Field.ReflectValueOf(tx.Statement.Context, data)
			if reflectFieldValue.Kind() == reflect.Ptr && reflectFieldValue.IsNil() {
				reflectFieldValue.Set(reflect.New(rel.Field.FieldType.Elem()))
			}

			reflectFieldValue = reflect.Indirect(reflectFieldValue)
			switch reflectFieldValue.Kind() {
			case reflect.Struct:
				tx.AddError(rel.Field.Set(tx.Statement.Context, data, elem.Interface()))
			case reflect.Slice, reflect.Array:
				if reflectFieldValue.Type().Elem().Kind() == reflect.Ptr {
					tx.AddError(rel.Field.Set(tx.Statement.Context, data, reflect.Append(reflectFieldValue, elem).Interface()))
				} else {
					tx.AddError(rel.Field.Set(tx.Statement.Context, data, reflect.Append(reflectFieldValue, elem.Elem()).Interface()))
				}
			}
		}
	}

	return tx.Error
}


================================================
FILE: callbacks/query.go
================================================
package callbacks

import (
	"fmt"
	"reflect"
	"strings"

	"gorm.io/gorm"
	"gorm.io/gorm/clause"
	"gorm.io/gorm/schema"
	"gorm.io/gorm/utils"
)

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

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

			if db.Statement.Result != nil {
				db.Statement.Result.RowsAffected = db.RowsAffected
			}
		}
	}
}

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

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

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

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

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

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

					for idx, dbName := range stmt.Schema.DBNames {
						clauseSelect.Columns[idx] = clause.Column{Table: db.Statement.Table, Name: dbName}
					}
				}
			}
		}

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

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

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

							if isNestedJoin {
								isRelations = true
								relations = guessNestedRelations
							}
						}
					}

					if isRelations {
						genJoinClause := func(joinType clause.JoinType, tableAliasName string, parentTableName string, relation *schema.Relationship) clause.Join {
							columnStmt := gorm.Statement{
								Table: tableAliasName, DB: db, Schema: relation.FieldSchema,
								Selects: join.Selects, Omits: join.Omits,
							}

							selectColumns, restricted := columnStmt.SelectAndOmitColumns(false, false)
							for _, s := range relation.FieldSchema.DBNames {
								if v, ok := selectColumns[s]; (ok && v) || (!ok && !restricted) {
									clauseSelect.Columns = append(clauseSelect.Columns, clause.Column{
										Table: tableAliasName,
										Name:  s,
										Alias: utils.NestedRelationName(tableAliasName, s),
									})
								}
							}

							if join.Expression != nil {
								return clause.Join{
									Type:       join.JoinType,
									Expression: join.Expression,
								}
							}

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

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

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

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

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

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

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

						parentTableName := clause.CurrentTable
						for idx, rel := range relations {
							// joins table alias like "Manager, Company, Manager__Company"
							curAliasName := rel.Name
							if parentTableName != clause.CurrentTable {
								curAliasName = utils.NestedRelationName(parentTableName, curAliasName)
							}

							if _, ok := specifiedRelationsName[curAliasName]; !ok {
								aliasName := curAliasName
								if idx == len(relations)-1 && join.Alias != "" {
									aliasName = join.Alias
								}

								fromClause.Joins = append(fromClause.Joins, genJoinClause(join.JoinType, aliasName, specifiedRelationsName[parentTableName], rel))
								specifiedRelationsName[curAliasName] = aliasName
							}

							parentTableName = curAliasName
						}
					} else {
						fromClause.Joins = append(fromClause.Joins, clause.Join{
							Expression: clause.NamedExpr{SQL: join.Name, Vars: join.Conds},
						})
					}
				} else {
					fromClause.Joins = append(fromClause.Joins, clause.Join{
						Expression: clause.NamedExpr{SQL: join.Name, Vars: join.Conds},
					})
				}
			}

			db.Statement.AddClause(fromClause)
		} else {
			db.Statement.AddClauseIfNotExists(clause.From{})
		}

		db.Statement.AddClauseIfNotExists(clauseSelect)

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

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

		joins := make([]string, 0, len(db.Statement.Joins))
		for _, join := range db.Statement.Joins {
			joins = append(joins, join.Name)
		}

		tx := preloadDB(db, db.Statement.ReflectValue, db.Statement.Dest)
		if tx.Error != nil {
			return
		}

		db.AddError(preloadEntryPoint(tx, joins, &tx.Statement.Schema.Relationships, db.Statement.Preloads, db.Statement.Preloads[clause.Associations]))
	}
}

func AfterQuery(db *gorm.DB) {
	// clear the joins after query because preload need it
	if v, ok := db.Statement.Clauses["FROM"].Expression.(clause.From); ok {
		fromClause := db.Statement.Clauses["FROM"]
		fromClause.Expression = clause.From{Tables: v.Tables, Joins: utils.RTrimSlice(v.Joins, len(db.Statement.Joins))} // keep the original From Joins
		db.Statement.Clauses["FROM"] = fromClause
	}
	if db.Error == nil && db.Statement.Schema != nil && !db.Statement.SkipHooks && db.Statement.Schema.AfterFind && db.RowsAffected > 0 {
		callMethod(db, func(value interface{}, tx *gorm.DB) bool {
			if i, ok := value.(AfterFindInterface); ok {
				db.AddError(i.AfterFind(tx))
				return true
			}
			return false
		})
	}
}


================================================
FILE: callbacks/raw.go
================================================
package callbacks

import (
	"gorm.io/gorm"
)

func RawExec(db *gorm.DB) {
	if db.Error == nil && !db.DryRun {
		result, err := db.Statement.ConnPool.ExecContext(db.Statement.Context, db.Statement.SQL.String(), db.Statement.Vars...)
		if err != nil {
			db.AddError(err)
			return
		}

		db.RowsAffected, _ = result.RowsAffected()

		if db.Statement.Result != nil {
			db.Statement.Result.Result = result
			db.Statement.Result.RowsAffected = db.RowsAffected
		}
	}
}


================================================
FILE: callbacks/row.go
================================================
package callbacks

import (
	"gorm.io/gorm"
)

func RowQuery(db *gorm.DB) {
	if db.Error == nil {
		BuildQuerySQL(db)
		if db.DryRun || db.Error != nil {
			return
		}

		if isRows, ok := db.Get("rows"); ok && isRows.(bool) {
			db.Statement.Settings.Delete("rows")
			db.Statement.Dest, db.Error = db.Statement.ConnPool.QueryContext(db.Statement.Context, db.Statement.SQL.String(), db.Statement.Vars...)
		} else {
			db.Statement.Dest = db.Statement.ConnPool.QueryRowContext(db.Statement.Context, db.Statement.SQL.String(), db.Statement.Vars...)
		}

		db.RowsAffected = -1
	}
}


================================================
FILE: callbacks/transaction.go
================================================
package callbacks

import (
	"gorm.io/gorm"
)

func BeginTransaction(db *gorm.DB) {
	if !db.Config.SkipDefaultTransaction && db.Error == nil {
		if tx := db.Begin(); tx.Error == nil {
			db.Statement.ConnPool = tx.Statement.ConnPool
			db.InstanceSet("gorm:started_transaction", true)
		} else if tx.Error == gorm.ErrInvalidTransaction {
			tx.Error = nil
		} else {
			db.Error = tx.Error
		}
	}
}

func CommitOrRollbackTransaction(db *gorm.DB) {
	if !db.Config.SkipDefaultTransaction {
		if _, ok := db.InstanceGet("gorm:started_transaction"); ok {
			if db.Error != nil {
				db.Rollback()
			} else {
				db.Commit()
			}

			db.Statement.ConnPool = db.ConnPool
		}
	}
}


================================================
FILE: callbacks/update.go
================================================
package callbacks

import (
	"reflect"
	"sort"

	"gorm.io/gorm"
	"gorm.io/gorm/clause"
	"gorm.io/gorm/schema"
	"gorm.io/gorm/utils"
)

func SetupUpdateReflectValue(db *gorm.DB) {
	if db.Error == nil && db.Statement.Schema != nil {
		if !db.Statement.ReflectValue.CanAddr() || db.Statement.Model != db.Statement.Dest {
			db.Statement.ReflectValue = reflect.ValueOf(db.Statement.Model)
			for db.Statement.ReflectValue.Kind() == reflect.Ptr {
				db.Statement.ReflectValue = db.Statement.ReflectValue.Elem()
			}

			if dest, ok := db.Statement.Dest.(map[string]interface{}); ok {
				for _, rel := range db.Statement.Schema.Relationships.BelongsTo {
					if _, ok := dest[rel.Name]; ok {
						db.AddError(rel.Field.Set(db.Statement.Context, db.Statement.ReflectValue, dest[rel.Name]))
					}
				}
			}
		}
	}
}

// BeforeUpdate before update hooks
func BeforeUpdate(db *gorm.DB) {
	if db.Error == nil && db.Statement.Schema != nil && !db.Statement.SkipHooks && (db.Statement.Schema.BeforeSave || db.Statement.Schema.BeforeUpdate) {
		callMethod(db, func(value interface{}, tx *gorm.DB) (called bool) {
			if db.Statement.Schema.BeforeSave {
				if i, ok := value.(BeforeSaveInterface); ok {
					called = true
					db.AddError(i.BeforeSave(tx))
				}
			}

			if db.Statement.Schema.BeforeUpdate {
				if i, ok := value.(BeforeUpdateInterface); ok {
					called = true
					db.AddError(i.BeforeUpdate(tx))
				}
			}

			return called
		})
	}
}

// Update update hook
func Update(config *Config) func(db *gorm.DB) {
	supportReturning := utils.Contains(config.UpdateClauses, "RETURNING")

	return func(db *gorm.DB) {
		if db.Error != nil {
			return
		}

		if db.Statement.Schema != nil {
			for _, c := range db.Statement.Schema.UpdateClauses {
				db.Statement.AddClause(c)
			}
		}

		if db.Statement.SQL.Len() == 0 {
			db.Statement.SQL.Grow(180)
			db.Statement.AddClauseIfNotExists(clause.Update{})
			if _, ok := db.Statement.Clauses["SET"]; !ok {
				if set := ConvertToAssignments(db.Statement); len(set) != 0 {
					defer delete(db.Statement.Clauses, "SET")
					db.Statement.AddClause(set)
				} else {
					return
				}
			}

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

		checkMissingWhereConditions(db)

		if !db.DryRun && db.Error == nil {
			if ok, mode := hasReturning(db, supportReturning); ok {
				if rows, err := db.Statement.ConnPool.QueryContext(db.Statement.Context, db.Statement.SQL.String(), db.Statement.Vars...); db.AddError(err) == nil {
					dest := db.Statement.Dest
					db.Statement.Dest = db.Statement.ReflectValue.Addr().Interface()
					gorm.Scan(rows, db, mode)
					db.Statement.Dest = dest
					db.AddError(rows.Close())

					if db.Statement.Result != nil {
						db.Statement.Result.RowsAffected = db.RowsAffected
					}
				}
			} else {
				result, err := db.Statement.ConnPool.ExecContext(db.Statement.Context, db.Statement.SQL.String(), db.Statement.Vars...)

				if db.AddError(err) == nil {
					db.RowsAffected, _ = result.RowsAffected()
				}

				if db.Statement.Result != nil {
					db.Statement.Result.Result = result
					db.Statement.Result.RowsAffected = db.RowsAffected
				}
			}
		}
	}
}

// AfterUpdate after update hooks
func AfterUpdate(db *gorm.DB) {
	if db.Error == nil && db.Statement.Schema != nil && !db.Statement.SkipHooks && (db.Statement.Schema.AfterSave || db.Statement.Schema.AfterUpdate) {
		callMethod(db, func(value interface{}, tx *gorm.DB) (called bool) {
			if db.Statement.Schema.AfterUpdate {
				if i, ok := value.(AfterUpdateInterface); ok {
					called = true
					db.AddError(i.AfterUpdate(tx))
				}
			}

			if db.Statement.Schema.AfterSave {
				if i, ok := value.(AfterSaveInterface); ok {
					called = true
					db.AddError(i.AfterSave(tx))
				}
			}

			return called
		})
	}
}

// ConvertToAssignments convert to update assignments
func ConvertToAssignments(stmt *gorm.Statement) (set clause.Set) {
	var (
		selectColumns, restricted = stmt.SelectAndOmitColumns(false, true)
		assignValue               func(field *schema.Field, value interface{})
	)

	switch stmt.ReflectValue.Kind() {
	case reflect.Slice, reflect.Array:
		assignValue = func(field *schema.Field, value interface{}) {
			for i := 0; i < stmt.ReflectValue.Len(); i++ {
				if stmt.ReflectValue.CanAddr() {
					field.Set(stmt.Context, stmt.ReflectValue.Index(i), value)
				}
			}
		}
	case reflect.Struct:
		assignValue = func(field *schema.Field, value interface{}) {
			if stmt.ReflectValue.CanAddr() {
				field.Set(stmt.Context, stmt.ReflectValue, value)
			}
		}
	default:
		assignValue = func(field *schema.Field, value interface{}) {
		}
	}

	updatingValue := reflect.ValueOf(stmt.Dest)
	for updatingValue.Kind() == reflect.Ptr {
		updatingValue = updatingValue.Elem()
	}

	if !updatingValue.CanAddr() || stmt.Dest != stmt.Model {
		switch stmt.ReflectValue.Kind() {
		case reflect.Slice, reflect.Array:
			if size := stmt.ReflectValue.Len(); size > 0 {
				var isZero bool
				for i := 0; i < size; i++ {
					for _, field := range stmt.Schema.PrimaryFields {
						_, isZero = field.ValueOf(stmt.Context, stmt.ReflectValue.Index(i))
						if !isZero {
							break
						}
					}
				}

				if !isZero {
					_, primaryValues := schema.GetIdentityFieldValuesMap(stmt.Context, stmt.ReflectValue, stmt.Schema.PrimaryFields)
					column, values := schema.ToQueryValues("", stmt.Schema.PrimaryFieldDBNames, primaryValues)
					stmt.AddClause(clause.Where{Exprs: []clause.Expression{clause.IN{Column: column, Values: values}}})
				}
			}
		case reflect.Struct:
			for _, field := range stmt.Schema.PrimaryFields {
				if value, isZero := field.ValueOf(stmt.Context, stmt.ReflectValue); !isZero {
					stmt.AddClause(clause.Where{Exprs: []clause.Expression{clause.Eq{Column: field.DBName, Value: value}}})
				}
			}
		}
	}

	switch value := updatingValue.Interface().(type) {
	case map[string]interface{}:
		set = make([]clause.Assignment, 0, len(value))

		keys := make([]string, 0, len(value))
		for k := range value {
			keys = append(keys, k)
		}
		sort.Strings(keys)

		for _, k := range keys {
			kv := value[k]
			if _, ok := kv.(*gorm.DB); ok {
				kv = []interface{}{kv}
			}

			if stmt.Schema != nil {
				if field := stmt.Schema.LookUpField(k); field != nil {
					if field.DBName != "" {
						if v, ok := selectColumns[field.DBName]; (ok && v) || (!ok && !restricted) {
							set = append(set, clause.Assignment{Column: clause.Column{Name: field.DBName}, Value: kv})
							assignValue(field, value[k])
						}
					} else if v, ok := selectColumns[field.Name]; (ok && v) || (!ok && !restricted) {
						assignValue(field, value[k])
					}
					continue
				}
			}

			if v, ok := selectColumns[k]; (ok && v) || (!ok && !restricted) {
				set = append(set, clause.Assignment{Column: clause.Column{Name: k}, Value: kv})
			}
		}

		if !stmt.SkipHooks && stmt.Schema != nil {
			for _, dbName := range stmt.Schema.DBNames {
				field := stmt.Schema.LookUpField(dbName)
				if field.AutoUpdateTime > 0 && value[field.Name] == nil && value[field.DBName] == nil {
					if v, ok := selectColumns[field.DBName]; (ok && v) || !ok {
						now := stmt.DB.NowFunc()
						assignValue(field, now)

						if field.AutoUpdateTime == schema.UnixNanosecond {
							set = append(set, clause.Assignment{Column: clause.Column{Name: field.DBName}, Value: now.UnixNano()})
						} else if field.AutoUpdateTime == schema.UnixMillisecond {
							set = append(set, clause.Assignment{Column: clause.Column{Name: field.DBName}, Value: now.UnixMilli()})
						} else if field.AutoUpdateTime == schema.UnixSecond {
							set = append(set, clause.Assignment{Column: clause.Column{Name: field.DBName}, Value: now.Unix()})
						} else {
							set = append(set, clause.Assignment{Column: clause.Column{Name: field.DBName}, Value: now})
						}
					}
				}
			}
		}
	default:
		updatingSchema := stmt.Schema
		var isDiffSchema bool
		if !updatingValue.CanAddr() || stmt.Dest != stmt.Model {
			// different schema
			updatingStmt := &gorm.Statement{DB: stmt.DB}
			if err := updatingStmt.Parse(stmt.Dest); err == nil {
				updatingSchema = updatingStmt.Schema
				isDiffSchema = true
			}
		}

		switch updatingValue.Kind() {
		case reflect.Struct:
			set = make([]clause.Assignment, 0, len(stmt.Schema.FieldsByDBName))
			for _, dbName := range stmt.Schema.DBNames {
				if field := updatingSchema.LookUpField(dbName); field != nil {
					if !field.PrimaryKey || !updatingValue.CanAddr() || stmt.Dest != stmt.Model {
						if v, ok := selectColumns[field.DBName]; (ok && v) || (!ok && (!restricted || (!stmt.SkipHooks && field.AutoUpdateTime > 0))) {
							value, isZero := field.ValueOf(stmt.Context, updatingValue)
							if !stmt.SkipHooks && field.AutoUpdateTime > 0 {
								if field.AutoUpdateTime == schema.UnixNanosecond {
									value = stmt.DB.NowFunc().UnixNano()
								} else if field.AutoUpdateTime == schema.UnixMillisecond {
									value = stmt.DB.NowFunc().UnixMilli()
								} else if field.AutoUpdateTime == schema.UnixSecond {
									value = stmt.DB.NowFunc().Unix()
								} else {
									value = stmt.DB.NowFunc()
								}
								isZero = false
							}

							if (ok || !isZero) && field.Updatable {
								set = append(set, clause.Assignment{Column: clause.Column{Name: field.DBName}, Value: value})
								assignField := field
								if isDiffSchema {
									if originField := stmt.Schema.LookUpField(dbName); originField != nil {
										assignField = originField
									}
								}
								assignValue(assignField, value)
							}
						}
					} else {
						if value, isZero := field.ValueOf(stmt.Context, updatingValue); !isZero {
							stmt.AddClause(clause.Where{Exprs: []clause.Expression{clause.Eq{Column: field.DBName, Value: value}}})
						}
					}
				}
			}
		default:
			stmt.AddError(gorm.ErrInvalidData)
		}
	}

	return
}


================================================
FILE: callbacks.go
================================================
package gorm

import (
	"context"
	"errors"
	"fmt"
	"reflect"
	"sort"
	"time"

	"gorm.io/gorm/schema"
	"gorm.io/gorm/utils"
)

func initializeCallbacks(db *DB) *callbacks {
	return &callbacks{
		processors: map[string]*processor{
			"create": {db: db},
			"query":  {db: db},
			"update": {db: db},
			"delete": {db: db},
			"row":    {db: db},
			"raw":    {db: db},
		},
	}
}

// callbacks gorm callbacks manager
type callbacks struct {
	processors map[string]*processor
}

type processor struct {
	db        *DB
	Clauses   []string
	fns       []func(*DB)
	callbacks []*callback
}

type callback struct {
	name      string
	before    string
	after     string
	remove    bool
	replace   bool
	match     func(*DB) bool
	handler   func(*DB)
	processor *processor
}

func (cs *callbacks) Create() *processor {
	return cs.processors["create"]
}

func (cs *callbacks) Query() *processor {
	return cs.processors["query"]
}

func (cs *callbacks) Update() *processor {
	return cs.processors["update"]
}

func (cs *callbacks) Delete() *processor {
	return cs.processors["delete"]
}

func (cs *callbacks) Row() *processor {
	return cs.processors["row"]
}

func (cs *callbacks) Raw() *processor {
	return cs.processors["raw"]
}

func (p *processor) Execute(db *DB) *DB {
	// call scopes
	for len(db.Statement.scopes) > 0 {
		db = db.executeScopes()
	}

	var (
		curTime           = time.Now()
		stmt              = db.Statement
		resetBuildClauses bool
	)

	if len(stmt.BuildClauses) == 0 {
		stmt.BuildClauses = p.Clauses
		resetBuildClauses = true
	}

	if optimizer, ok := stmt.Dest.(StatementModifier); ok {
		optimizer.ModifyStatement(stmt)
	}

	if db.DefaultContextTimeout > 0 {
		if _, ok := stmt.Context.Deadline(); !ok {
			stmt.Context, _ = context.WithTimeout(stmt.Context, db.DefaultContextTimeout)
		}
	}

	// assign model values
	if stmt.Model == nil {
		stmt.Model = stmt.Dest
	} else if stmt.Dest == nil {
		stmt.Dest = stmt.Model
	}

	// parse model values
	if stmt.Model != nil {
		if err := stmt.Parse(stmt.Model); err != nil && (!errors.Is(err, schema.ErrUnsupportedDataType) || (stmt.Table == "" && stmt.TableExpr == nil && stmt.SQL.Len() == 0)) {
			if errors.Is(err, schema.ErrUnsupportedDataType) && stmt.Table == "" && stmt.TableExpr == nil {
				db.AddError(fmt.Errorf("%w: Table not set, please set it like: db.Model(&user) or db.Table(\"users\")", err))
			} else {
				db.AddError(err)
			}
		}
	}

	// assign stmt.ReflectValue
	if stmt.Dest != nil {
		stmt.ReflectValue = reflect.ValueOf(stmt.Dest)
		for stmt.ReflectValue.Kind() == reflect.Ptr {
			if stmt.ReflectValue.IsNil() && stmt.ReflectValue.CanAddr() {
				stmt.ReflectValue.Set(reflect.New(stmt.ReflectValue.Type().Elem()))
			}

			stmt.ReflectValue = stmt.ReflectValue.Elem()
		}
		if !stmt.ReflectValue.IsValid() {
			db.AddError(ErrInvalidValue)
		}
	}

	for _, f := range p.fns {
		f(db)
	}

	if stmt.SQL.Len() > 0 {
		db.Logger.Trace(stmt.Context, curTime, func() (string, int64) {
			sql, vars := stmt.SQL.String(), stmt.Vars
			if filter, ok := db.Logger.(ParamsFilter); ok {
				sql, vars = filter.ParamsFilter(stmt.Context, stmt.SQL.String(), stmt.Vars...)
			}
			return db.Dialector.Explain(sql, vars...), db.RowsAffected
		}, db.Error)
	}

	if !stmt.DB.DryRun {
		stmt.SQL.Reset()
		stmt.Vars = nil
	}

	if resetBuildClauses {
		stmt.BuildClauses = nil
	}

	return db
}

func (p *processor) Get(name string) func(*DB) {
	for i := len(p.callbacks) - 1; i >= 0; i-- {
		if v := p.callbacks[i]; v.name == name && !v.remove {
			return v.handler
		}
	}
	return nil
}

func (p *processor) Before(name string) *callback {
	return &callback{before: name, processor: p}
}

func (p *processor) After(name string) *callback {
	return &callback{after: name, processor: p}
}

func (p *processor) Match(fc func(*DB) bool) *callback {
	return &callback{match: fc, processor: p}
}

func (p *processor) Register(name string, fn func(*DB)) error {
	return (&callback{processor: p}).Register(name, fn)
}

func (p *processor) Remove(name string) error {
	return (&callback{processor: p}).Remove(name)
}

func (p *processor) Replace(name string, fn func(*DB)) error {
	return (&callback{processor: p}).Replace(name, fn)
}

func (p *processor) compile() (err error) {
	var callbacks []*callback
	removedMap := map[string]bool{}
	for _, callback := range p.callbacks {
		if callback.match == nil || callback.match(p.db) {
			callbacks = append(callbacks, callback)
		}
		if callback.remove {
			removedMap[callback.name] = true
		}
	}

	if len(removedMap) > 0 {
		callbacks = removeCallbacks(callbacks, removedMap)
	}
	p.callbacks = callbacks

	if p.fns, err = sortCallbacks(p.callbacks); err != nil {
		p.db.Logger.Error(context.Background(), "Got error when compile callbacks, got %v", err)
	}
	return
}

func (c *callback) Before(name string) *callback {
	c.before = name
	return c
}

func (c *callback) After(name string) *callback {
	c.after = name
	return c
}

func (c *callback) Register(name string, fn func(*DB)) error {
	c.name = name
	c.handler = fn
	c.processor.callbacks = append(c.processor.callbacks, c)
	return c.processor.compile()
}

func (c *callback) Remove(name string) error {
	c.processor.db.Logger.Warn(context.Background(), "removing callback `%s` from %s\n", name, utils.FileWithLineNum())
	c.name = name
	c.remove = true
	c.processor.callbacks = append(c.processor.callbacks, c)
	return c.processor.compile()
}

func (c *callback) Replace(name string, fn func(*DB)) error {
	c.processor.db.Logger.Info(context.Background(), "replacing callback `%s` from %s\n", name, utils.FileWithLineNum())
	c.name = name
	c.handler = fn
	c.replace = true
	c.processor.callbacks = append(c.processor.callbacks, c)
	return c.processor.compile()
}

// getRIndex get right index from string slice
func getRIndex(strs []string, str string) int {
	for i := len(strs) - 1; i >= 0; i-- {
		if strs[i] == str {
			return i
		}
	}
	return -1
}

func sortCallbacks(cs []*callback) (fns []func(*DB), err error) {
	var (
		names, sorted []string
		sortCallback  func(*callback) error
	)
	sort.SliceStable(cs, func(i, j int) bool {
		if cs[j].before == "*" && cs[i].before != "*" {
			return true
		}
		if cs[j].after == "*" && cs[i].after != "*" {
			return true
		}
		return false
	})

	for _, c := range cs {
		// show warning message the callback name already exists
		if idx := getRIndex(names, c.name); idx > -1 && !c.replace && !c.remove && !cs[idx].remove {
			c.processor.db.Logger.Warn(context.Background(), "duplicated callback `%s` from %s\n", c.name, utils.FileWithLineNum())
		}
		names = append(names, c.name)
	}

	sortCallback = func(c *callback) error {
		if c.before != "" { // if defined before callback
			if c.before == "*" && len(sorted) > 0 {
				if curIdx := getRIndex(sorted, c.name); curIdx == -1 {
					sorted = append([]string{c.name}, sorted...)
				}
			} else if sortedIdx := getRIndex(sorted, c.before); sortedIdx != -1 {
				if curIdx := getRIndex(sorted, c.name); curIdx == -1 {
					// if before callback already sorted, append current callback just after it
					sorted = append(sorted[:sortedIdx], append([]string{c.name}, sorted[sortedIdx:]...)...)
				} else if curIdx > sortedIdx {
					return fmt.Errorf("conflicting callback %s with before %s", c.name, c.before)
				}
			} else if idx := getRIndex(names, c.before); idx != -1 {
				// if before callback exists
				cs[idx].after = c.name
			}
		}

		if c.after != "" { // if defined after callback
			if c.after == "*" && len(sorted) > 0 {
				if curIdx := getRIndex(sorted, c.name); curIdx == -1 {
					sorted = append(sorted, c.name)
				}
			} else if sortedIdx := getRIndex(sorted, c.after); sortedIdx != -1 {
				if curIdx := getRIndex(sorted, c.name); curIdx == -1 {
					// if after callback sorted, append current callback to last
					sorted = append(sorted, c.name)
				} else if curIdx < sortedIdx {
					return fmt.Errorf("conflicting callback %s with before %s", c.name, c.after)
				}
			} else if idx := getRIndex(names, c.after); idx != -1 {
				// if after callback exists but haven't sorted
				// set after callback's before callback to current callback
				after := cs[idx]

				if after.before == "" {
					after.before = c.name
				}

				if err := sortCallback(after); err != nil {
					return err
				}

				if err := sortCallback(c); err != nil {
					return err
				}
			}
		}

		// if current callback haven't been sorted, append it to last
		if getRIndex(sorted, c.name) == -1 {
			sorted = append(sorted, c.name)
		}

		return nil
	}

	for _, c := range cs {
		if err = sortCallback(c); err != nil {
			return
		}
	}

	for _, name := range sorted {
		if idx := getRIndex(names, name); !cs[idx].remove {
			fns = append(fns, cs[idx].handler)
		}
	}

	return
}

func removeCallbacks(cs []*callback, nameMap map[string]bool) []*callback {
	callbacks := make([]*callback, 0, len(cs))
	for _, callback := range cs {
		if nameMap[callback.name] {
			continue
		}
		callbacks = append(callbacks, callback)
	}
	return callbacks
}


================================================
FILE: chainable_api.go
================================================
package gorm

import (
	"fmt"
	"regexp"
	"strings"

	"gorm.io/gorm/clause"
	"gorm.io/gorm/utils"
)

// Model specify the model you would like to run db operations
//
//	// update all users's name to `hello`
//	db.Model(&User{}).Update("name", "hello")
//	// if user's primary key is non-blank, will use it as condition, then will only update that user's name to `hello`
//	db.Model(&user).Update("name", "hello")
func (db *DB) Model(value interface{}) (tx *DB) {
	tx = db.getInstance()
	tx.Statement.Model = value
	return
}

// Clauses Add clauses
//
// This supports both standard clauses (clause.OrderBy, clause.Limit, clause.Where) and more
// advanced techniques like specifying lock strength and optimizer hints. See the
// [docs] for more depth.
//
//	// add a simple limit clause
//	db.Clauses(clause.Limit{Limit: 1}).Find(&User{})
//	// tell the optimizer to use the `idx_user_name` index
//	db.Clauses(hints.UseIndex("idx_user_name")).Find(&User{})
//	// specify the lock strength to UPDATE
//	db.Clauses(clause.Locking{Strength: "UPDATE"}).Find(&users)
//
// [docs]: https://gorm.io/docs/sql_builder.html#Clauses
func (db *DB) Clauses(conds ...clause.Expression) (tx *DB) {
	tx = db.getInstance()
	var whereConds []interface{}

	for _, cond := range conds {
		if c, ok := cond.(clause.Interface); ok {
			tx.Statement.AddClause(c)
		} else if optimizer, ok := cond.(StatementModifier); ok {
			optimizer.ModifyStatement(tx.Statement)
		} else {
			whereConds = append(whereConds, cond)
		}
	}

	if len(whereConds) > 0 {
		tx.Statement.AddClause(clause.Where{Exprs: tx.Statement.BuildCondition(whereConds[0], whereConds[1:]...)})
	}
	return
}

var tableRegexp = regexp.MustCompile(`(?i)(?:.+? AS (\w+)\s*(?:$|,)|^\w+\s+(\w+)$)`)

// Table specify the table you would like to run db operations
//
//	// Get a user
//	db.Table("users").Take(&result)
func (db *DB) Table(name string, args ...interface{}) (tx *DB) {
	tx = db.getInstance()
	if strings.Contains(name, " ") || strings.Contains(name, "`") || len(args) > 0 {
		tx.Statement.TableExpr = &clause.Expr{SQL: name, Vars: args}
		if results := tableRegexp.FindStringSubmatch(name); len(results) == 3 {
			if results[1] != "" {
				tx.Statement.Table = results[1]
			} else {
				tx.Statement.Table = results[2]
			}
		}
	} else if tables := strings.Split(name, "."); len(tables) == 2 {
		tx.Statement.TableExpr = &clause.Expr{SQL: tx.Statement.Quote(name)}
		tx.Statement.Table = tables[1]
	} else if name != "" {
		tx.Statement.TableExpr = &clause.Expr{SQL: tx.Statement.Quote(name)}
		tx.Statement.Table = name
	} else {
		tx.Statement.TableExpr = nil
		tx.Statement.Table = ""
	}
	return
}

// Distinct specify distinct fields that you want querying
//
//	// Select distinct names of users
//	db.Distinct("name").Find(&results)
//	// Select distinct name/age pairs from users
//	db.Distinct("name", "age").Find(&results)
func (db *DB) Distinct(args ...interface{}) (tx *DB) {
	tx = db.getInstance()
	tx.Statement.Distinct = true
	if len(args) > 0 {
		tx = tx.Select(args[0], args[1:]...)
	}
	return
}

// Select specify fields that you want when querying, creating, updating
//
// Use Select when you only want a subset of the fields. By default, GORM will select all fields.
// Select accepts both string arguments and arrays.
//
//	// Select name and age of user using multiple arguments
//	db.Select("name", "age").Find(&users)
//	// Select name and age of user using an array
//	db.Select([]string{"name", "age"}).Find(&users)
func (db *DB) Select(query interface{}, args ...interface{}) (tx *DB) {
	tx = db.getInstance()

	switch v := query.(type) {
	case []string:
		tx.Statement.Selects = v

		for _, arg := range args {
			switch arg := arg.(type) {
			case string:
				tx.Statement.Selects = append(tx.Statement.Selects, arg)
			case []string:
				tx.Statement.Selects = append(tx.Statement.Selects, arg...)
			default:
				tx.AddError(fmt.Errorf("unsupported select args %v %v", query, args))
				return
			}
		}

		if clause, ok := tx.Statement.Clauses["SELECT"]; ok {
			clause.Expression = nil
			tx.Statement.Clauses["SELECT"] = clause
		}
	case string:
		if strings.Count(v, "?") >= len(args) && len(args) > 0 {
			tx.Statement.AddClause(clause.Select{
				Distinct:   db.Statement.Distinct,
				Expression: clause.Expr{SQL: v, Vars: args},
			})
		} else if strings.Count(v, "@") > 0 && len(args) > 0 {
			tx.Statement.AddClause(clause.Select{
				Distinct:   db.Statement.Distinct,
				Expression: clause.NamedExpr{SQL: v, Vars: args},
			})
		} else {
			tx.Statement.Selects = []string{v}

			for _, arg := range args {
				switch arg := arg.(type) {
				case string:
					tx.Statement.Selects = append(tx.Statement.Selects, arg)
				case []string:
					tx.Statement.Selects = append(tx.Statement.Selects, arg...)
				default:
					tx.Statement.AddClause(clause.Select{
						Distinct:   db.Statement.Distinct,
						Expression: clause.Expr{SQL: v, Vars: args},
					})
					return
				}
			}

			if clause, ok := tx.Statement.Clauses["SELECT"]; ok {
				clause.Expression = nil
				tx.Statement.Clauses["SELECT"] = clause
			}
		}
	default:
		tx.AddError(fmt.Errorf("unsupported select args %v %v", query, args))
	}

	return
}

// Omit specify fields that you want to ignore when creating, updating and querying
func (db *DB) Omit(columns ...string) (tx *DB) {
	tx = db.getInstance()

	if len(columns) == 1 && strings.ContainsRune(columns[0], ',') {
		tx.Statement.Omits = strings.FieldsFunc(columns[0], utils.IsInvalidDBNameChar)
	} else {
		tx.Statement.Omits = columns
	}
	return
}

// MapColumns modify the column names in the query results to facilitate align to the corresponding structural fields
func (db *DB) MapColumns(m map[string]string) (tx *DB) {
	tx = db.getInstance()
	tx.Statement.ColumnMapping = m
	return
}

// Where add conditions
//
// See the [docs] for details on the various formats that where clauses can take. By default, where clauses chain with AND.
//
//	// Find the first user with name jinzhu
//	db.Where("name = ?", "jinzhu").First(&user)
//	// Find the first user with name jinzhu and age 20
//	db.Where(&User{Name: "jinzhu", Age: 20}).First(&user)
//	// Find the first user with name jinzhu and age not equal to 20
//	db.Where("name = ?", "jinzhu").Where("age <> ?", "20").First(&user)
//
// [docs]: https://gorm.io/docs/query.html#Conditions
func (db *DB) Where(query interface{}, args ...interface{}) (tx *DB) {
	tx = db.getInstance()
	if conds := tx.Statement.BuildCondition(query, args...); len(conds) > 0 {
		tx.Statement.AddClause(clause.Where{Exprs: conds})
	}
	return
}

// Not add NOT conditions
//
// Not works similarly to where, and has the same syntax.
//
//	// Find the first user with name not equal to jinzhu
//	db.Not("name = ?", "jinzhu").First(&user)
func (db *DB) Not(query interface{}, args ...interface{}) (tx *DB) {
	tx = db.getInstance()
	if conds := tx.Statement.BuildCondition(query, args...); len(conds) > 0 {
		tx.Statement.AddClause(clause.Where{Exprs: []clause.Expression{clause.Not(conds...)}})
	}
	return
}

// Or add OR conditions
//
// Or is used to chain together queries with an OR.
//
//	// Find the first user with name equal to jinzhu or john
//	db.Where("name = ?", "jinzhu").Or("name = ?", "john").First(&user)
func (db *DB) Or(query interface{}, args ...interface{}) (tx *DB) {
	tx = db.getInstance()
	if conds := tx.Statement.BuildCondition(query, args...); len(conds) > 0 {
		tx.Statement.AddClause(clause.Where{Exprs: []clause.Expression{clause.Or(clause.And(conds...))}})
	}
	return
}

// Joins specify Joins conditions
//
//	db.Joins("Account").Find(&user)
//	db.Joins("JOIN emails ON emails.user_id = users.id AND emails.email = ?", "jinzhu@example.org").Find(&user)
//	db.Joins("Account", DB.Select("id").Where("user_id = users.id AND name = ?", "someName").Model(&Account{}))
func (db *DB) Joins(query string, args ...interface{}) (tx *DB) {
	return joins(db, clause.LeftJoin, query, args...)
}

// InnerJoins specify inner joins conditions
// db.InnerJoins("Account").Find(&user)
func (db *DB) InnerJoins(query string, args ...interface{}) (tx *DB) {
	return joins(db, clause.InnerJoin, query, args...)
}

func joins(db *DB, joinType clause.JoinType, query string, args ...interface{}) (tx *DB) {
	tx = db.getInstance()

	if len(args) == 1 {
		if db, ok := args[0].(*DB); ok {
			j := join{
				Name: query, Conds: args, Selects: db.Statement.Selects,
				Omits: db.Statement.Omits, JoinType: joinType,
			}
			if where, ok := db.Statement.Clauses["WHERE"].Expression.(clause.Where); ok {
				j.On = &where
			}
			tx.Statement.Joins = append(tx.Statement.Joins, j)
			return
		}
	}

	tx.Statement.Joins = append(tx.Statement.Joins, join{Name: query, Conds: args, JoinType: joinType})
	return
}

// Group specify the group method on the find
//
//	// Select the sum age of users with given names
//	db.Model(&User{}).Select("name, sum(age) as total").Group("name").Find(&results)
func (db *DB) Group(name string) (tx *DB) {
	tx = db.getInstance()

	fields := strings.FieldsFunc(name, utils.IsInvalidDBNameChar)
	tx.Statement.AddClause(clause.GroupBy{
		Columns: []clause.Column{{Name: name, Raw: len(fields) != 1}},
	})
	return
}

// Having specify HAVING conditions for GROUP BY
//
//	// Select the sum age of users with name jinzhu
//	db.Model(&User{}).Select("name, sum(age) as total").Group("name").Having("name = ?", "jinzhu").Find(&result)
func (db *DB) Having(query interface{}, args ...interface{}) (tx *DB) {
	tx = db.getInstance()
	tx.Statement.AddClause(clause.GroupBy{
		Having: tx.Statement.BuildCondition(query, args...),
	})
	return
}

// Order specify order when retrieving records from database
//
//	db.Order("name DESC")
//	db.Order(clause.OrderByColumn{Column: clause.Column{Name: "name"}, Desc: true})
//	db.Order(clause.OrderBy{Columns: []clause.OrderByColumn{
//		{Column: clause.Column{Name: "name"}, Desc: true},
//		{Column: clause.Column{Name: "age"}, Desc: true},
//	}})
func (db *DB) Order(value interface{}) (tx *DB) {
	tx = db.getInstance()

	switch v := value.(type) {
	case clause.OrderBy:
		tx.Statement.AddClause(v)
	case clause.OrderByColumn:
		tx.Statement.AddClause(clause.OrderBy{
			Columns: []clause.OrderByColumn{v},
		})
	case string:
		if v != "" {
			tx.Statement.AddClause(clause.OrderBy{
				Columns: []clause.OrderByColumn{{
					Column: clause.Column{Name: v, Raw: true},
				}},
			})
		}
	}
	return
}

// Limit specify the number of records to be retrieved
//
// Limit conditions can be cancelled by using `Limit(-1)`.
//
//	// retrieve 3 users
//	db.Limit(3).Find(&users)
//	// retrieve 3 users into users1, and all users into users2
//	db.Limit(3).Find(&users1).Limit(-1).Find(&users2)
func (db *DB) Limit(limit int) (tx *DB) {
	tx = db.getInstance()
	tx.Statement.AddClause(clause.Limit{Limit: &limit})
	return
}

// Offset specify the number of records to skip before starting to return the records
//
// Offset conditions can be cancelled by using `Offset(-1)`.
//
//	// select the third user
//	db.Offset(2).First(&user)
//	// select the first user by cancelling an earlier chained offset
//	db.Offset(5).Offset(-1).First(&user)
func (db *DB) Offset(offset int) (tx *DB) {
	tx = db.getInstance()
	tx.Statement.AddClause(clause.Limit{Offset: offset})
	return
}

// Scopes pass current database connection to arguments `func(DB) DB`, which could be used to add conditions dynamically
//
//	func AmountGreaterThan1000(db *gorm.DB) *gorm.DB {
//	    return db.Where("amount > ?", 1000)
//	}
//
//	func OrderStatus(status []string) func (db *gorm.DB) *gorm.DB {
//	    return func (db *gorm.DB) *gorm.DB {
//	        return db.Scopes(AmountGreaterThan1000).Where("status in (?)", status)
//	    }
//	}
//
//	db.Scopes(AmountGreaterThan1000, OrderStatus([]string{"paid", "shipped"})).Find(&orders)
func (db *DB) Scopes(funcs ...func(*DB) *DB) (tx *DB) {
	tx = db.getInstance()
	tx.Statement.scopes = append(tx.Statement.scopes, funcs...)
	return tx
}

func (db *DB) executeScopes() (tx *DB) {
	scopes := db.Statement.scopes
	db.Statement.scopes = nil
	for _, scope := range scopes {
		db = scope(db)
	}
	return db
}

// Preload preload associations with given conditions
//
//	// get all users, and preload all non-cancelled orders
//	db.Preload("Orders", "state NOT IN (?)", "cancelled").Find(&users)
func (db *DB) Preload(query string, args ...interface{}) (tx *DB) {
	tx = db.getInstance()
	if tx.Statement.Preloads == nil {
		tx.Statement.Preloads = map[string][]interface{}{}
	}
	tx.Statement.Preloads[query] = args
	return
}

// Attrs provide attributes used in [FirstOrCreate] or [FirstOrInit]
//
// Attrs only adds attributes if the record is not found.
//
//	// assign an email if the record is not found
//	db.Where(User{Name: "non_existing"}).Attrs(User{Email: "fake@fake.org"}).FirstOrInit(&user)
//	// user -> User{Name: "non_existing", Email: "fake@fake.org"}
//
//	// assign an email if the record is not found, otherwise ignore provided email
//	db.Where(User{Name: "jinzhu"}).Attrs(User{Email: "fake@fake.org"}).FirstOrInit(&user)
//	// user -> User{Name: "jinzhu", Age: 20}
//
// [FirstOrCreate]: https://gorm.io/docs/advanced_query.html#FirstOrCreate
// [FirstOrInit]: https://gorm.io/docs/advanced_query.html#FirstOrInit
func (db *DB) Attrs(attrs ...interface{}) (tx *DB) {
	tx = db.getInstance()
	tx.Statement.attrs = attrs
	return
}

// Assign provide attributes used in [FirstOrCreate] or [FirstOrInit]
//
// Assign adds attributes even if the record is found. If using FirstOrCreate, this means that
// records will be updated even if they are found.
//
//	// assign an email regardless of if the record is not found
//	db.Where(User{Name: "non_existing"}).Assign(User{Email: "fake@fake.org"}).FirstOrInit(&user)
//	// user -> User{Name: "non_existing", Email: "fake@fake.org"}
//
//	// assign email regardless of if record is found
//	db.Where(User{Name: "jinzhu"}).Assign(User{Email: "fake@fake.org"}).FirstOrInit(&user)
//	// user -> User{Name: "jinzhu", Age: 20, Email: "fake@fake.org"}
//
// [FirstOrCreate]: https://gorm.io/docs/advanced_query.html#FirstOrCreate
// [FirstOrInit]: https://gorm.io/docs/advanced_query.html#FirstOrInit
func (db *DB) Assign(attrs ...interface{}) (tx *DB) {
	tx = db.getInstance()
	tx.Statement.assigns = attrs
	return
}

// Unscoped disables the global scope of soft deletion in a query.
// By default, GORM uses soft deletion, marking records as "deleted"
// by setting a timestamp on a specific field (e.g., `deleted_at`).
// Unscoped allows queries to include records marked as deleted,
// overriding the soft deletion behavior.
// Example:
//
//	var users []User
//	db.Unscoped().Find(&users)
//	// Retrieves all users, including deleted ones.
func (db *DB) Unscoped() (tx *DB) {
	tx = db.getInstance()
	tx.Statement.Unscoped = true
	return
}

func (db *DB) Raw(sql string, values ...interface{}) (tx *DB) {
	tx = db.getInstance()
	tx.Statement.SQL = strings.Builder{}

	if strings.Contains(sql, "@") {
		clause.NamedExpr{SQL: sql, Vars: values}.Build(tx.Statement)
	} else {
		clause.Expr{SQL: sql, Vars: values}.Build(tx.Statement)
	}
	return
}


================================================
FILE: clause/association.go
================================================
package clause

// AssociationOpType represents association operation types
type AssociationOpType int

const (
	OpUnlink AssociationOpType = iota // Unlink association
	OpDelete                          // Delete association records
	OpUpdate                          // Update association records
	OpCreate                          // Create association records with assignments
)

// Association represents an association operation
type Association struct {
	Association string            // Association name
	Type        AssociationOpType // Operation type
	Conditions  []Expression      // Filter conditions
	Set         []Assignment      // Assignment operations (for Update and Create)
	Values      []interface{}     // Values for Create operation
}

// AssociationAssigner is an interface for association operation providers
type AssociationAssigner interface {
	AssociationAssignments() []Association
}

// Assignments implements the Assigner interface so that AssociationOperation can be used as a Set method parameter
func (ao Association) Assignments() []Assignment {
	return []Assignment{}
}

// AssociationAssignments implements the AssociationAssigner interface
func (ao Association) AssociationAssignments() []Association {
	return []Association{ao}
}


================================================
FILE: clause/benchmarks_test.go
================================================
package clause_test

import (
	"sync"
	"testing"

	"gorm.io/gorm"
	"gorm.io/gorm/clause"
	"gorm.io/gorm/schema"
	"gorm.io/gorm/utils/tests"
)

func BenchmarkSelect(b *testing.B) {
	user, _ := schema.Parse(&tests.User{}, &sync.Map{}, db.NamingStrategy)

	for i := 0; i < b.N; i++ {
		stmt := gorm.Statement{DB: db, Table: user.Table, Schema: user, Clauses: map[string]clause.Clause{}}
		clauses := []clause.Interface{clause.Select{}, clause.From{}, clause.Where{Exprs: []clause.Expression{clause.Eq{Column: clause.PrimaryColumn, Value: "1"}, clause.Gt{Column: "age", Value: 18}, clause.Or(clause.Neq{Column: "name", Value: "jinzhu"})}}}

		for _, clause := range clauses {
			stmt.AddClause(clause)
		}

		stmt.Build("SELECT", "FROM", "WHERE")
		_ = stmt.SQL.String()
	}
}

func BenchmarkComplexSelect(b *testing.B) {
	user, _ := schema.Parse(&tests.User{}, &sync.Map{}, db.NamingStrategy)

	limit10 := 10
	for i := 0; i < b.N; i++ {
		stmt := gorm.Statement{DB: db, Table: user.Table, Schema: user, Clauses: map[string]clause.Clause{}}
		clauses := []clause.Interface{
			clause.Select{},
			clause.From{},
			clause.Where{Exprs: []clause.Expression{
				clause.Eq{Column: clause.PrimaryColumn, Value: "1"},
				clause.Gt{Column: "age", Value: 18},
				clause.Or(clause.Neq{Column: "name", Value: "jinzhu"}),
			}},
			clause.Where{Exprs: []clause.Expression{
				clause.Or(clause.Gt{Column: "score", Value: 100}, clause.Like{Column: "name", Value: "%linus%"}),
			}},
			clause.GroupBy{Columns: []clause.Column{{Name: "role"}}, Having: []clause.Expression{clause.Eq{"role", "admin"}}},
			clause.Limit{Limit: &limit10, Offset: 20},
			clause.OrderBy{Columns: []clause.OrderByColumn{{Column: clause.PrimaryColumn, Desc: true}}},
		}

		for _, clause := range clauses {
			stmt.AddClause(clause)
		}

		stmt.Build("SELECT", "FROM", "WHERE", "GROUP BY", "LIMIT", "ORDER BY")
		_ = stmt.SQL.String()
	}
}


================================================
FILE: clause/clause.go
================================================
package clause

// Interface clause interface
type Interface interface {
	Name() string
	Build(Builder)
	MergeClause(*Clause)
}

// ClauseBuilder clause builder, allows to customize how to build clause
type ClauseBuilder func(Clause, Builder)

type Writer interface {
	WriteByte(byte) error
	WriteString(string) (int, error)
}

// Builder builder interface
type Builder interface {
	Writer
	WriteQuoted(field interface{})
	AddVar(Writer, ...interface{})
	AddError(error) error
}

// Clause
type Clause struct {
	Name                string // WHERE
	BeforeExpression    Expression
	AfterNameExpression Expression
	AfterExpression     Expression
	Expression          Expression
	Builder             ClauseBuilder
}

// Build build clause
func (c Clause) Build(builder Builder) {
	if c.Builder != nil {
		c.Builder(c, builder)
	} else if c.Expression != nil {
		if c.BeforeExpression != nil {
			c.BeforeExpression.Build(builder)
			builder.WriteByte(' ')
		}

		if c.Name != "" {
			builder.WriteString(c.Name)
			builder.WriteByte(' ')
		}

		if c.AfterNameExpression != nil {
			c.AfterNameExpression.Build(builder)
			builder.WriteByte(' ')
		}

		c.Expression.Build(builder)

		if c.AfterExpression != nil {
			builder.WriteByte(' ')
			c.AfterExpression.Build(builder)
		}
	}
}

const (
	PrimaryKey   string = "~~~py~~~" // primary key
	CurrentTable string = "~~~ct~~~" // current table
	Associations string = "~~~as~~~" // associations
)

var (
	currentTable  = Table{Name: CurrentTable}
	PrimaryColumn = Column{Table: CurrentTable, Name: PrimaryKey}
)

// Column quote with name
type Column struct {
	Table string
	Name  string
	Alias string
	Raw   bool
}

// Table quote with name
type Table struct {
	Name  string
	Alias string
	Raw   bool
}


================================================
FILE: clause/clause_test.go
================================================
package clause_test

import (
	"reflect"
	"strings"
	"sync"
	"testing"

	"gorm.io/gorm"
	"gorm.io/gorm/clause"
	"gorm.io/gorm/schema"
	"gorm.io/gorm/utils/tests"
)

var db, _ = gorm.Open(tests.DummyDialector{}, nil)

func checkBuildClauses(t *testing.T, clauses []clause.Interface, result string, vars []interface{}) {
	var (
		buildNames    []string
		buildNamesMap = map[string]bool{}
		user, _       = schema.Parse(&tests.User{}, &sync.Map{}, db.NamingStrategy)
		stmt          = gorm.Statement{DB: db, Table: user.Table, Schema: user, Clauses: map[string]clause.Clause{}}
	)

	for _, c := range clauses {
		if _, ok := buildNamesMap[c.Name()]; !ok {
			buildNames = append(buildNames, c.Name())
			buildNamesMap[c.Name()] = true
		}

		stmt.AddClause(c)
	}

	stmt.Build(buildNames...)

	if strings.TrimSpace(stmt.SQL.String()) != result {
		t.Errorf("SQL expects %v got %v", result, stmt.SQL.String())
	}

	if !reflect.DeepEqual(stmt.Vars, vars) {
		t.Errorf("Vars expects %+v got %v", stmt.Vars, vars)
	}
}


================================================
FILE: clause/delete.go
================================================
package clause

type Delete struct {
	Modifier string
}

func (d Delete) Name() string {
	return "DELETE"
}

func (d Delete) Build(builder Builder) {
	builder.WriteString("DELETE")

	if d.Modifier != "" {
		builder.WriteByte(' ')
		builder.WriteString(d.Modifier)
	}
}

func (d Delete) MergeClause(clause *Clause) {
	clause.Name = ""
	clause.Expression = d
}


================================================
FILE: clause/delete_test.go
================================================
package clause_test

import (
	"fmt"
	"testing"

	"gorm.io/gorm/clause"
)

func TestDelete(t *testing.T) {
	results := []struct {
		Clauses []clause.Interface
		Result  string
		Vars    []interface{}
	}{
		{
			[]clause.Interface{clause.Delete{}, clause.From{}},
			"DELETE FROM `users`", nil,
		},
		{
			[]clause.Interface{clause.Delete{Modifier: "LOW_PRIORITY"}, clause.From{}},
			"DELETE LOW_PRIORITY FROM `users`", nil,
		},
	}

	for idx, result := range results {
		t.Run(fmt.Sprintf("case #%v", idx), func(t *testing.T) {
			checkBuildClauses(t, result.Clauses, result.Result, result.Vars)
		})
	}
}


================================================
FILE: clause/expression.go
================================================
package clause

import (
	"database/sql"
	"database/sql/driver"
	"go/ast"
	"reflect"
)

// Expression expression interface
type Expression interface {
	Build(builder Builder)
}

// NegationExpressionBuilder negation expression builder
type NegationExpressionBuilder interface {
	NegationBuild(builder Builder)
}

// Expr raw expression
type Expr struct {
	SQL                string
	Vars               []interface{}
	WithoutParentheses bool
}

// Build build raw expression
func (expr Expr) Build(builder Builder) {
	var (
		afterParenthesis bool
		idx              int
	)

	for _, v := range []byte(expr.SQL) {
		if v == '?' && len(expr.Vars) > idx {
			if afterParenthesis || expr.WithoutParentheses {
				processValue(builder, expr.Vars[idx])
			} else {
				builder.AddVar(builder, expr.Vars[idx])
			}

			idx++
		} else {
			if v == '(' {
				afterParenthesis = true
			} else {
				afterParenthesis = false
			}
			builder.WriteByte(v)
		}
	}

	if idx < len(expr.Vars) {
		for _, v := range expr.Vars[idx:] {
			builder.AddVar(builder, sql.NamedArg{Value: v})
		}
	}
}

// NamedExpr raw expression for named expr
type NamedExpr struct {
	SQL  string
	Vars []interface{}
}

// Build build raw expression
func (expr NamedExpr) Build(builder Builder) {
	var (
		idx              int
		inName           bool
		afterParenthesis bool
		namedMap         = make(map[string]interface{}, len(expr.Vars))
	)

	for _, v := range expr.Vars {
		switch value := v.(type) {
		case sql.NamedArg:
			namedMap[value.Name] = value.Value
		case map[string]interface{}:
			for k, v := range value {
				namedMap[k] = v
			}
		default:
			var appendFieldsToMap func(reflect.Value)
			appendFieldsToMap = func(reflectValue reflect.Value) {
				reflectValue = reflect.Indirect(reflectValue)
				switch reflectValue.Kind() {
				case reflect.Struct:
					modelType := reflectValue.Type()
					for i := 0; i < modelType.NumField(); i++ {
						if fieldStruct := modelType.Field(i); ast.IsExported(fieldStruct.Name) {
							namedMap[fieldStruct.Name] = reflectValue.Field(i).Interface()

							if fieldStruct.Anonymous {
								appendFieldsToMap(reflectValue.Field(i))
							}
						}
					}
				}
			}

			appendFieldsToMap(reflect.ValueOf(value))
		}
	}

	name := make([]byte, 0, 10)

	for _, v := range []byte(expr.SQL) {
		if v == '@' && !inName {
			inName = true
			name = name[:0]
		} else if v == ' ' || v == ',' || v == ')' || v == '"' || v == '\'' || v == '`' || v == '\r' || v == '\n' || v == ';' {
			if inName {
				if nv, ok := namedMap[string(name)]; ok {
					if afterParenthesis {
						processValue(builder, nv)
					} else {
						builder.AddVar(builder, nv)
					}
				} else {
					builder.WriteByte('@')
					builder.WriteString(string(name))
				}
				inName = false
			}

			afterParenthesis = false
			builder.WriteByte(v)
		} else if v == '?' && len(expr.Vars) > idx {
			if afterParenthesis {
				processValue(builder, expr.Vars[idx])
			} else {
				builder.AddVar(builder, expr.Vars[idx])
			}

			idx++
		} else if inName {
			name = append(name, v)
		} else {
			if v == '(' {
				afterParenthesis = true
			} else {
				afterParenthesis = false
			}
			builder.WriteByte(v)
		}
	}

	if inName {
		if nv, ok := namedMap[string(name)]; ok {
			builder.AddVar(builder, nv)
		} else {
			builder.WriteByte('@')
			builder.WriteString(string(name))
		}
	}
}

// processValue handles different value types appropriately for SQL parameter binding
// It checks for driver.Valuer first, then handles slices/arrays, and finally adds single values
func processValue(builder Builder, value interface{}) {
	if _, ok := value.(driver.Valuer); ok {
		builder.AddVar(builder, value)
		return
	}

	switch rv := reflect.ValueOf(value); rv.Kind() {
	case reflect.Slice, reflect.Array:
		if rv.Len() == 0 {
			builder.AddVar(builder, nil)
		} else {
			for i := 0; i < rv.Len(); i++ {
				if i > 0 {
					builder.WriteByte(',')
				}
				builder.AddVar(builder, rv.Index(i).Interface())
			}
		}
	default:
		builder.AddVar(builder, value)
	}
}

// IN Whether a value is within a set of values
type IN struct {
	Column interface{}
	Values []interface{}
}

func (in IN) Build(builder Builder) {
	builder.WriteQuoted(in.Column)

	switch len(in.Values) {
	case 0:
		builder.WriteString(" IN (NULL)")
	case 1:
		if _, ok := in.Values[0].([]interface{}); !ok {
			builder.WriteString(" = ")
			builder.AddVar(builder, in.Values[0])
			break
		}

		fallthrough
	default:
		builder.WriteString(" IN (")
		builder.AddVar(builder, in.Values...)
		builder.WriteByte(')')
	}
}

func (in IN) NegationBuild(builder Builder) {
	builder.WriteQuoted(in.Column)
	switch len(in.Values) {
	case 0:
		builder.WriteString(" IS NOT NULL")
	case 1:
		if _, ok := in.Values[0].([]interface{}); !ok {
			builder.WriteString(" <> ")
			builder.AddVar(builder, in.Values[0])
			break
		}

		fallthrough
	default:
		builder.WriteString(" NOT IN (")
		builder.AddVar(builder, in.Values...)
		builder.WriteByte(')')
	}
}

// Eq equal to for where
type Eq struct {
	Column interface{}
	Value  interface{}
}

func (eq Eq) Build(builder Builder) {
	builder.WriteQuoted(eq.Column)

	switch eq.Value.(type) {
	case []string, []int, []int32, []int64, []uint, []uint32, []uint64, []interface{}:
		rv := reflect.ValueOf(eq.Value)
		if rv.Len() == 0 {
			builder.WriteString(" IN (NULL)")
		} else {
			builder.WriteString(" IN (")
			for i := 0; i < rv.Len(); i++ {
				if i > 0 {
					builder.WriteByte(',')
				}
				builder.AddVar(builder, rv.Index(i).Interface())
			}
			builder.WriteByte(')')
		}
	default:
		if eqNil(eq.Value) {
			builder.WriteString(" IS NULL")
		} else {
			builder.WriteString(" = ")
			builder.AddVar(builder, eq.Value)
		}
	}
}

func (eq Eq) NegationBuild(builder Builder) {
	Neq(eq).Build(builder)
}

// Neq not equal to for where
type Neq Eq

func (neq Neq) Build(builder Builder) {
	builder.WriteQuoted(neq.Column)

	switch neq.Value.(type) {
	case []string, []int, []int32, []int64, []uint, []uint32, []uint64, []interface{}:
		builder.WriteString(" NOT IN (")
		rv := reflect.ValueOf(neq.Value)
		for i := 0; i < rv.Len(); i++ {
			if i > 0 {
				builder.WriteByte(',')
			}
			builder.AddVar(builder, rv.Index(i).Interface())
		}
		builder.WriteByte(')')
	default:
		if eqNil(neq.Value) {
			builder.WriteString(" IS NOT NULL")
		} else {
			builder.WriteString(" <> ")
			builder.AddVar(builder, neq.Value)
		}
	}
}

func (neq Neq) NegationBuild(builder Builder) {
	Eq(neq).Build(builder)
}

// Gt greater than for where
type Gt Eq

func (gt Gt) Build(builder Builder) {
	builder.WriteQuoted(gt.Column)
	builder.WriteString(" > ")
	builder.AddVar(builder, gt.Value)
}

func (gt Gt) NegationBuild(builder Builder) {
	Lte(gt).Build(builder)
}

// Gte greater than or equal to for where
type Gte Eq

func (gte Gte) Build(builder Builder) {
	builder.WriteQuoted(gte.Column)
	builder.WriteString(" >= ")
	builder.AddVar(builder, gte.Value)
}

func (gte Gte) NegationBuild(builder Builder) {
	Lt(gte).Build(builder)
}

// Lt less than for where
type Lt Eq

func (lt Lt) Build(builder Builder) {
	builder.WriteQuoted(lt.Column)
	builder.WriteString(" < ")
	builder.AddVar(builder, lt.Value)
}

func (lt Lt) NegationBuild(builder Builder) {
	Gte(lt).Build(builder)
}

// Lte less than or equal to for where
type Lte Eq

func (lte Lte) Build(builder Builder) {
	builder.WriteQuoted(lte.Column)
	builder.WriteString(" <= ")
	builder.AddVar(builder, lte.Value)
}

func (lte Lte) NegationBuild(builder Builder) {
	Gt(lte).Build(builder)
}

// Like whether string matches regular expression
type Like Eq

func (like Like) Build(builder Builder) {
	builder.WriteQuoted(like.Column)
	builder.WriteString(" LIKE ")
	builder.AddVar(builder, like.Value)
}

func (like Like) NegationBuild(builder Builder) {
	builder.WriteQuoted(like.Column)
	builder.WriteString(" NOT LIKE ")
	builder.AddVar(builder, like.Value)
}

func eqNil(value interface{}) bool {
	if valuer, ok := value.(driver.Valuer); ok && !eqNilReflect(valuer) {
		value, _ = valuer.Value()
	}

	return value == nil || eqNilReflect(value)
}

func eqNilReflect(value interface{}) bool {
	reflectValue := reflect.ValueOf(value)
	return reflectValue.Kind() == reflect.Ptr && reflectValue.IsNil()
}


================================================
FILE: clause/expression_test.go
================================================
package clause_test

import (
	"database/sql"
	"fmt"
	"reflect"
	"sync"
	"testing"

	"gorm.io/gorm"
	"gorm.io/gorm/clause"
	"gorm.io/gorm/schema"
	"gorm.io/gorm/utils/tests"
)

func TestExpr(t *testing.T) {
	results := []struct {
		SQL    string
		Result string
		Vars   []interface{}
	}{{
		SQL:    "create table ? (? ?, ? ?)",
		Vars:   []interface{}{clause.Table{Name: "users"}, clause.Column{Name: "id"}, clause.Expr{SQL: "int"}, clause.Column{Name: "name"}, clause.Expr{SQL: "text"}},
		Result: "create table `users` (`id` int, `name` text)",
	}}

	for idx, result := range results {
		t.Run(fmt.Sprintf("case #%v", idx), func(t *testing.T) {
			user, _ := schema.Parse(&tests.User{}, &sync.Map{}, db.NamingStrategy)
			stmt := &gorm.Statement{DB: db, Table: user.Table, Schema: user, Clauses: map[string]clause.Clause{}}
			clause.Expr{SQL: result.SQL, Vars: result.Vars}.Build(stmt)
			if stmt.SQL.String() != result.Result {
				t.Errorf("generated SQL is not equal, expects %v, but got %v", result.Result, stmt.SQL.String())
			}
		})
	}
}

func TestNamedExpr(t *testing.T) {
	type Base struct {
		Name2 string
	}

	type NamedArgument struct {
		Name1 string
		Base
	}

	results := []struct {
		SQL          string
		Result       string
		Vars         []interface{}
		ExpectedVars []interface{}
	}{{
		SQL:    "create table ? (? ?, ? ?)",
		Vars:   []interface{}{clause.Table{Name: "users"}, clause.Column{Name: "id"}, clause.Expr{SQL: "int"}, clause.Column{Name: "name"}, clause.Expr{SQL: "text"}},
		Result: "create table `users` (`id` int, `name` text)",
	}, {
		SQL:          "name1 = @name AND name2 = @name",
		Vars:         []interface{}{sql.Named("name", "jinzhu")},
		Result:       "name1 = ? AND name2 = ?",
		ExpectedVars: []interface{}{"jinzhu", "jinzhu"},
	}, {
		SQL:          "name1 = @name AND name2 = @@name",
		Vars:         []interface{}{map[string]interface{}{"name": "jinzhu"}},
		Result:       "name1 = ? AND name2 = @@name",
		ExpectedVars: []interface{}{"jinzhu"},
	}, {
		SQL:          "name1 = @name1 AND name2 = @name2 AND name3 = @name1",
		Vars:         []interface{}{sql.Named("name1", "jinzhu"), sql.Named("name2", "jinzhu2")},
		Result:       "name1 = ? AND name2 = ? AND name3 = ?",
		ExpectedVars: []interface{}{"jinzhu", "jinzhu2", "jinzhu"},
	}, {
		SQL:          "name1 = @name1 AND name2 = @name2 AND name3 = @name1",
		Vars:         []interface{}{map[string]interface{}{"name1": "jinzhu", "name2": "jinzhu2"}},
		Result:       "name1 = ? AND name2 = ? AND name3 = ?",
		ExpectedVars: []interface{}{"jinzhu", "jinzhu2", "jinzhu"},
	}, {
		SQL:          "@@test AND name1 = @name1 AND name2 = @name2 AND name3 = @name1 @notexist",
		Vars:         []interface{}{sql.Named("name1", "jinzhu"), sql.Named("name2", "jinzhu2")},
		Result:       "@@test AND name1 = ? AND name2 = ? AND name3 = ? @notexist",
		ExpectedVars: []interface{}{"jinzhu", "jinzhu2", "jinzhu"},
	}, {
		SQL:          "@@test AND name1 = @Name1 AND name2 = @Name2 AND name3 = @Name1 @notexist",
		Vars:         []interface{}{NamedArgument{Name1: "jinzhu", Base: Base{Name2: "jinzhu2"}}},
		Result:       "@@test AND name1 = ? AND name2 = ? AND name3 = ? @notexist",
		ExpectedVars: []interface{}{"jinzhu", "jinzhu2", "jinzhu"},
	}, {
		SQL:          "name in (@names)",
		Vars:         []interface{}{map[string]interface{}{"names": []interface{}{"jinzhu", "jinzhu2"}}},
		Result:       "name in (?,?)",
		ExpectedVars: []interface{}{"jinzhu", "jinzhu2"},
	}, {
		SQL:          "name in (@names)",
		Vars:         []interface{}{map[string]interface{}{"names": "jinzhu"}},
		Result:       "name in (?)",
		ExpectedVars: []interface{}{"jinzhu"},
	}, {
		SQL:    "create table ? (? ?, ? ?)",
		Vars:   []interface{}{},
		Result: "create table ? (? ?, ? ?)",
	}, {
		SQL:          "name1 = @name AND name2 = @name;",
		Vars:         []interface{}{sql.Named("name", "jinzhu")},
		Result:       "name1 = ? AND name2 = ?;",
		ExpectedVars: []interface{}{"jinzhu", "jinzhu"},
	}, {
		SQL:          "name1 = @name1\r\n AND name2 = @name2",
		Vars:         []interface{}{map[string]interface{}{"name1": "jinzhu", "name2": "jinzhu"}},
		Result:       "name1 = ?\r\n AND name2 = ?",
		ExpectedVars: []interface{}{"jinzhu", "jinzhu"},
	}, {
		SQL:          "name1 = @name1\r AND name2 = @name2",
		Vars:         []interface{}{map[string]interface{}{"name1": "jinzhu", "name2": "jinzhu"}},
		Result:       "name1 = ?\r AND name2 = ?",
		ExpectedVars: []interface{}{"jinzhu", "jinzhu"},
	}, {
		SQL:    "?",
		Vars:   []interface{}{clause.Column{Table: "table", Name: "col"}},
		Result: "`table`.`col`",
	}, {
		SQL:    "?",
		Vars:   []interface{}{clause.Column{Table: "table", Name: "col", Raw: true}},
		Result: "table.col",
	}, {
		SQL:    "?",
		Vars:   []interface{}{clause.Column{Table: "table", Name: clause.PrimaryKey, Raw: true}},
		Result: "table.id",
	}, {
		SQL:    "?",
		Vars:   []interface{}{clause.Column{Table: "table", Name: "col", Alias: "alias"}},
		Result: "`table`.`col` AS `alias`",
	}, {
		SQL:    "?",
		Vars:   []interface{}{clause.Column{Table: "table", Name: "col", Alias: "alias", Raw: true}},
		Result: "table.col AS alias",
	}, {
		SQL:    "?",
		Vars:   []interface{}{clause.Table{Name: "table", Alias: "alias"}},
		Result: "`table` `alias`",
	}, {
		SQL:    "?",
		Vars:   []interface{}{clause.Table{Name: "table", Alias: "alias", Raw: true}},
		Result: "table alias",
	}}

	for idx, result := range results {
		t.Run(fmt.Sprintf("case #%v", idx), func(t *testing.T) {
			user, _ := schema.Parse(&tests.User{}, &sync.Map{}, db.NamingStrategy)
			stmt := &gorm.Statement{DB: db, Table: user.Table, Schema: user, Clauses: map[string]clause.Clause{}}
			clause.NamedExpr{SQL: result.SQL, Vars: result.Vars}.Build(stmt)
			if stmt.SQL.String() != result.Result {
				t.Errorf("generated SQL is not equal, expects %v, but got %v", result.Result, stmt.SQL.String())
			}

			if !reflect.DeepEqual(result.ExpectedVars, stmt.Vars) {
				t.Errorf("generated vars is not equal, expects %v, but got %v", result.ExpectedVars, stmt.Vars)
			}
		})
	}
}

func TestExpression(t *testing.T) {
	column := "column-name"
	results := []struct {
		Expressions  []clause.Expression
		ExpectedVars []interface{}
		Result       string
	}{{
		Expressions: []clause.Expression{
			clause.Eq{Column: column, Value: "column-value"},
		},
		ExpectedVars: []interface{}{"column-value"},
		Result:       "`column-name` = ?",
	}, {
		Expressions: []clause.Expression{
			clause.Eq{Column: column, Value: nil},
			clause.Eq{Column: column, Value: (*string)(nil)},
			clause.Eq{Column: column, Value: (*int)(nil)},
			clause.Eq{Column: column, Value: (*bool)(nil)},
			clause.Eq{Column: column, Value: (interface{})(nil)},
			clause.Eq{Column: column, Value: sql.NullString{String: "", Valid: false}},
		},
		Result: "`column-name` IS NULL",
	}, {
		Expressions: []clause.Expression{
			clause.Neq{Column: column, Value: "column-value"},
		},
		ExpectedVars: []interface{}{"column-value"},
		Result:       "`column-name` <> ?",
	}, {
		Expressions: []clause.Expression{
			clause.Neq{Column: column, Value: nil},
			clause.Neq{Column: column, Value: (*string)(nil)},
			clause.Neq{Column: column, Value: (*int)(nil)},
			clause.Neq{Column: column, Value: (*bool)(nil)},
			clause.Neq{Column: column, Value: (interface{})(nil)},
		},
		Result: "`column-name` IS NOT NULL",
	}, {
		Expressions: []clause.Expression{
			clause.Eq{Column: column, Value: []string{"a", "b"}},
		},
		ExpectedVars: []interface{}{"a", "b"},
		Result:       "`column-name` IN (?,?)",
	}, {
		Expressions: []clause.Expression{
			clause.Neq{Column: column, Value: []string{"a", "b"}},
		},
		ExpectedVars: []interface{}{"a", "b"},
		Result:       "`column-name` NOT IN (?,?)",
	}, {
		Expressions: []clause.Expression{
			clause.Eq{Column: column, Value: []string{}},
		},
		Result: "`column-name` IN (NULL)",
	}, {
		Expressions: []clause.Expression{
			clause.Eq{Column: clause.Expr{SQL: "SUM(?)", Vars: []interface{}{clause.Column{Name: "id"}}}, Value: 100},
		},
		ExpectedVars: []interface{}{100},
		Result:       "SUM(`id`) = ?",
	}, {
		Expressions: []clause.Expression{
			clause.Gte{Column: clause.Expr{SQL: "SUM(?)", Vars: []interface{}{clause.Column{Table: "users", Name: "id"}}}, Value: 100},
		},
		ExpectedVars: []interface{}{100},
		Result:       "SUM(`users`.`id`) >= ?",
	}}

	for idx, result := range results {
		for idy, expression := range result.Expressions {
			t.Run(fmt.Sprintf("case #%v.%v", idx, idy), func(t *testing.T) {
				user, _ := schema.Parse(&tests.User{}, &sync.Map{}, db.NamingStrategy)
				stmt := &gorm.Statement{DB: db, Table: user.Table, Schema: user, Clauses: map[string]clause.Clause{}}
				expression.Build(stmt)
				if stmt.SQL.String() != result.Result {
					t.Errorf("generated SQL is not equal, expects %v, but got %v", result.Result, stmt.SQL.String())
				}

				if !reflect.DeepEqual(result.ExpectedVars, stmt.Vars) {
					t.Errorf("generated vars is not equal, expects %v, but got %v", result.ExpectedVars, stmt.Vars)
				}
			})
		}
	}
}


================================================
FILE: clause/from.go
================================================
package clause

// From from clause
type From struct {
	Tables []Table
	Joins  []Join
}

// Name from clause name
func (from From) Name() string {
	return "FROM"
}

// Build build from clause
func (from From) Build(builder Builder) {
	if len(from.Tables) > 0 {
		for idx, table := range from.Tables {
			if idx > 0 {
				builder.WriteByte(',')
			}

			builder.WriteQuoted(table)
		}
	} else {
		builder.WriteQuoted(currentTable)
	}

	for _, join := range from.Joins {
		builder.WriteByte(' ')
		join.Build(builder)
	}
}

// MergeClause merge from clause
func (from From) MergeClause(clause *Clause) {
	clause.Expression = from
}


================================================
FILE: clause/from_test.go
================================================
package clause_test

import (
	"fmt"
	"testing"

	"gorm.io/gorm/clause"
)

func TestFrom(t *testing.T) {
	results := []struct {
		Clauses []clause.Interface
		Result  string
		Vars    []interface{}
	}{
		{
			[]clause.Interface{clause.Select{}, clause.From{}},
			"SELECT * FROM `users`", nil,
		},
		{
			[]clause.Interface{
				clause.Select{}, clause.From{
					Tables: []clause.Table{{Name: "users"}},
					Joins: []clause.Join{
						{
							Type:  clause.InnerJoin,
							Table: clause.Table{Name: "articles"},
							ON: clause.Where{
								[]clause.Expression{clause.Eq{clause.Column{Table: "articles", Name: "id"}, clause.PrimaryColumn}},
							},
						},
					},
				},
			},
			"SELECT * FROM `users` INNER JOIN `articles` ON `articles`.`id` = `users`.`id`", nil,
		},
		{
			[]clause.Interface{
				clause.Select{}, clause.From{
					Tables: []clause.Table{{Name: "users"}},
					Joins: []clause.Join{
						{
							Type:  clause.RightJoin,
							Table: clause.Table{Name: "profiles"},
							ON: clause.Where{
								[]clause.Expression{clause.Eq{clause.Column{Table: "profiles", Name: "email"}, clause.Column{Table: clause.CurrentTable, Name: "email"}}},
							},
						},
					},
				}, clause.From{
					Joins: []clause.Join{
						{
							Type:  clause.InnerJoin,
							Table: clause.Table{Name: "articles"},
							ON: clause.Where{
								[]clause.Expression{clause.Eq{clause.Column{Table: "articles", Name: "id"}, clause.PrimaryColumn}},
							},
						}, {
							Type:  clause.LeftJoin,
							Table: clause.Table{Name: "companies"},
							Using: []string{"company_name"},
						},
					},
				},
			},
			"SELECT * FROM `users` INNER JOIN `articles` ON `articles`.`id` = `users`.`id` LEFT JOIN `companies` USING (`company_name`)", nil,
		},
	}

	for idx, result := range results {
		t.Run(fmt.Sprintf("case #%v", idx), func(t *testing.T) {
			checkBuildClauses(t, result.Clauses, result.Result, result.Vars)
		})
	}
}


================================================
FILE: clause/group_by.go
================================================
package clause

// GroupBy group by clause
type GroupBy struct {
	Columns []Column
	Having  []Expression
}

// Name from clause name
func (groupBy GroupBy) Name() string {
	return "GROUP BY"
}

// Build build group by clause
func (groupBy GroupBy) Build(builder Builder) {
	for idx, column := range groupBy.Columns {
		if idx > 0 {
			builder.WriteByte(',')
		}

		builder.WriteQuoted(column)
	}

	if len(groupBy.Having) > 0 {
		builder.WriteString(" HAVING ")
		Where{Exprs: groupBy.Having}.Build(builder)
	}
}

// MergeClause merge group by clause
func (groupBy GroupBy) MergeClause(clause *Clause) {
	if v, ok := clause.Expression.(GroupBy); ok {
		copiedColumns := make([]Column, len(v.Columns))
		copy(copiedColumns, v.Columns)
		groupBy.Columns = append(copiedColumns, groupBy.Columns...)

		copiedHaving := make([]Expression, len(v.Having))
		copy(copiedHaving, v.Having)
		groupBy.Having = append(copiedHaving, groupBy.Having...)
	}
	clause.Expression = groupBy

	if len(groupBy.Columns) == 0 {
		clause.Name = ""
	} else {
		clause.Name = groupBy.Name()
	}
}


================================================
FILE: clause/group_by_test.go
================================================
package clause_test

import (
	"fmt"
	"testing"

	"gorm.io/gorm/clause"
)

func TestGroupBy(t *testing.T) {
	results := []struct {
		Clauses []clause.Interface
		Result  string
		Vars    []interface{}
	}{
		{
			[]clause.Interface{clause.Select{}, clause.From{}, clause.GroupBy{
				Columns: []clause.Column{{Name: "role"}},
				Having:  []clause.Expression{clause.Eq{"role", "admin"}},
			}},
			"SELECT * FROM `users` GROUP BY `role` HAVING `role` = ?",
			[]interface{}{"admin"},
		},
		{
			[]clause.Interface{clause.Select{}, clause.From{}, clause.GroupBy{
				Columns: []clause.Column{{Name: "role"}},
				Having:  []clause.Expression{clause.Eq{"role", "admin"}},
			}, clause.GroupBy{
				Columns: []clause.Column{{Name: "gender"}},
				Having:  []clause.Expression{clause.Neq{"gender", "U"}},
			}},
			"SELECT * FROM `users` GROUP BY `role`,`gender` HAVING `role` = ? AND `gender` <> ?",
			[]interface{}{"admin", "U"},
		},
	}

	for idx, result := range results {
		t.Run(fmt.Sprintf("case #%v", idx), func(t *testing.T) {
			checkBuildClauses(t, result.Clauses, result.Result, result.Vars)
		})
	}
}


================================================
FILE: clause/insert.go
================================================
package clause

type Insert struct {
	Table    Table
	Modifier string
}

// Name insert clause name
func (insert Insert) Name() string {
	return "INSERT"
}

// Build build insert clause
func (insert Insert) Build(builder Builder) {
	if insert.Modifier != "" {
		builder.WriteString(insert.Modifier)
		builder.WriteByte(' ')
	}

	builder.WriteString("INTO ")
	if insert.Table.Name == "" {
		builder.WriteQuoted(currentTable)
	} else {
		builder.WriteQuoted(insert.Table)
	}
}

// MergeClause merge insert clause
func (insert Insert) MergeClause(clause *Clause) {
	if v, ok := clause.Expression.(Insert); ok {
		if insert.Modifier == "" {
			insert.Modifier = v.Modifier
		}
		if insert.Table.Name == "" {
			insert.Table = v.Table
		}
	}
	clause.Expression = insert
}


================================================
FILE: clause/insert_test.go
================================================
package clause_test

import (
	"fmt"
	"testing"

	"gorm.io/gorm/clause"
)

func TestInsert(t *testing.T) {
	results := []struct {
		Clauses []clause.Interface
		Result  string
		Vars    []interface{}
	}{
		{
			[]clause.Interface{clause.Insert{}},
			"INSERT INTO `users`", nil,
		},
		{
			[]clause.Interface{clause.Insert{Modifier: "LOW_PRIORITY"}},
			"INSERT LOW_PRIORITY INTO `users`", nil,
		},
		{
			[]clause.Interface{clause.Insert{Table: clause.Table{Name: "products"}, Modifier: "LOW_PRIORITY"}},
			"INSERT LOW_PRIORITY INTO `products`", nil,
		},
	}

	for idx, result := range results {
		t.Run(fmt.Sprintf("case #%v", idx), func(t *testing.T) {
			checkBuildClauses(t, result.Clauses, result.Result, result.Vars)
		})
	}
}


================================================
FILE: clause/joins.go
================================================
package clause

import "gorm.io/gorm/utils"

type JoinType string

const (
	CrossJoin JoinType = "CROSS"
	InnerJoin JoinType = "INNER"
	LeftJoin  JoinType = "LEFT"
	RightJoin JoinType = "RIGHT"
)

type JoinTarget struct {
	Type        JoinType
	Association string
	Subquery    Expression
	Table       string
}

func Has(name string) JoinTarget {
	return JoinTarget{Type: InnerJoin, Association: name}
}

func (jt JoinType) Association(name string) JoinTarget {
	return JoinTarget{Type: jt, Association: name}
}

func (jt JoinType) AssociationFrom(name string, subquery Expression) JoinTarget {
	return JoinTarget{Type: jt, Association: name, Subquery: subquery}
}

func (jt JoinTarget) As(name string) JoinTarget {
	jt.Table = name
	return jt
}

// Join clause for from
type Join struct {
	Type       JoinType
	Table      Table
	ON         Where
	Using      []string
	Expression Expression
}

func JoinTable(names ...string) Table {
	return Table{
		Name: utils.JoinNestedRelationNames(names),
	}
}

func (join Join) Build(builder Builder) {
	if join.Expression != nil {
		join.Expression.Build(builder)
	} else {
		if join.Type != "" {
			builder.WriteString(string(join.Type))
			builder.WriteByte(' ')
		}

		builder.WriteString("JOIN ")
		builder.WriteQuoted(join.Table)

		if len(join.ON.Exprs) > 0 {
			builder.WriteString(" ON ")
			join.ON.Build(builder)
		} else if len(join.Using) > 0 {
			builder.WriteString(" USING (")
			for idx, c := range join.Using {
				if idx > 0 {
					builder.WriteByte(',')
				}
				builder.WriteQuoted(c)
			}
			builder.WriteByte(')')
		}
	}
}


================================================
FILE: clause/joins_test.go
================================================
package clause_test

import (
	"sync"
	"testing"

	"gorm.io/gorm"
	"gorm.io/gorm/clause"
	"gorm.io/gorm/schema"
	"gorm.io/gorm/utils/tests"
)

func TestJoin(t *testing.T) {
	results := []struct {
		name string
		join clause.Join
		sql  string
	}{
		{
			name: "LEFT JOIN",
			join: clause.Join{
				Type:  clause.LeftJoin,
				Table: clause.Table{Name: "user"},
				ON: clause.Where{
					Exprs: []clause.Expression{clause.Eq{clause.Column{Table: "user_info", Name: "user_id"}, clause.PrimaryColumn}},
				},
			},
			sql: "LEFT JOIN `user` ON `user_info`.`user_id` = `users`.`id`",
		},
		{
			name: "RIGHT JOIN",
			join: clause.Join{
				Type:  clause.RightJoin,
				Table: clause.Table{Name: "user"},
				ON: clause.Where{
					Exprs: []clause.Expression{clause.Eq{clause.Column{Table: "user_info", Name: "user_id"}, clause.PrimaryColumn}},
				},
			},
			sql: "RIGHT JOIN `user` ON `user_info`.`user_id` = `users`.`id`",
		},
		{
			name: "INNER JOIN",
			join: clause.Join{
				Type:  clause.InnerJoin,
				Table: clause.Table{Name: "user"},
				ON: clause.Where{
					Exprs: []clause.Expression{clause.Eq{clause.Column{Table: "user_info", Name: "user_id"}, clause.PrimaryColumn}},
				},
			},
			sql: "INNER JOIN `user` ON `user_info`.`user_id` = `users`.`id`",
		},
		{
			name: "CROSS JOIN",
			join: clause.Join{
				Type:  clause.CrossJoin,
				Table: clause.Table{Name: "user"},
				ON: clause.Where{
					Exprs: []clause.Expression{clause.Eq{clause.Column{Table: "user_info", Name: "user_id"}, clause.PrimaryColumn}},
				},
			},
			sql: "CROSS JOIN `user` ON `user_info`.`user_id` = `users`.`id`",
		},
		{
			name: "USING",
			join: clause.Join{
				Type:  clause.InnerJoin,
				Table: clause.Table{Name: "user"},
				Using: []string{"id"},
			},
			sql: "INNER JOIN `user` USING (`id`)",
		},
		{
			name: "Expression",
			join: clause.Join{
				// Invalid
				Type:  clause.LeftJoin,
				Table: clause.Table{Name: "user"},
				ON: clause.Where{
					Exprs: []clause.Expression{clause.Eq{clause.Column{Table: "user_info", Name: "user_id"}, clause.PrimaryColumn}},
				},
				// Valid
				Expression: clause.Join{
					Type:  clause.InnerJoin,
					Table: clause.Table{Name: "user"},
					Using: []string{"id"},
				},
			},
			sql: "INNER JOIN `user` USING (`id`)",
		},
	}
	for _, result := range results {
		t.Run(result.name, func(t *testing.T) {
			user, _ := schema.Parse(&tests.User{}, &sync.Map{}, db.NamingStrategy)
			stmt := &gorm.Statement{DB: db, Table: user.Table, Schema: user, Clauses: map[string]clause.Clause{}}
			result.join.Build(stmt)
			if result.sql != stmt.SQL.String() {
				t.Errorf("want: %s, got: %s", result.sql, stmt.SQL.String())
			}
		})
	}
}


================================================
FILE: clause/limit.go
================================================
package clause

// Limit limit clause
type Limit struct {
	Limit  *int
	Offset int
}

// Name where clause name
func (limit Limit) Name() string {
	return "LIMIT"
}

// Build build where clause
func (limit Limit) Build(builder Builder) {
	if limit.Limit != nil && *limit.Limit >= 0 {
		builder.WriteString("LIMIT ")
		builder.AddVar(builder, *limit.Limit)
	}
	if limit.Offset > 0 {
		if limit.Limit != nil && *limit.Limit >= 0 {
			builder.WriteByte(' ')
		}
		builder.WriteString("OFFSET ")
		builder.AddVar(builder, limit.Offset)
	}
}

// MergeClause merge order by clauses
func (limit Limit) MergeClause(clause *Clause) {
	clause.Name = ""

	if v, ok := clause.Expression.(Limit); ok {
		if (limit.Limit == nil || *limit.Limit == 0) && v.Limit != nil {
			limit.Limit = v.Limit
		}

		if limit.Offset == 0 && v.Offset > 0 {
			limit.Offset = v.Offset
		} else if limit.Offset < 0 {
			limit.Offset = 0
		}
	}

	clause.Expression = limit
}


================================================
FILE: clause/limit_test.go
================================================
package clause_test

import (
	"fmt"
	"testing"

	"gorm.io/gorm/clause"
)

fun
Download .txt
gitextract_lfhwtntz/

├── .github/
│   ├── FUNDING.yml
│   ├── dependabot.yml
│   ├── labels.json
│   ├── release-drafter.yml
│   └── workflows/
│       ├── create-release.yml
│       ├── golangci-lint.yml
│       ├── invalid_question.yml
│       ├── labeler.yml
│       ├── missing_playground.yml
│       ├── stale.yml
│       └── tests.yml
├── .gitignore
├── .golangci.yml
├── CODE_OF_CONDUCT.md
├── LICENSE
├── README.md
├── association.go
├── callbacks/
│   ├── associations.go
│   ├── callbacks.go
│   ├── callmethod.go
│   ├── create.go
│   ├── create_test.go
│   ├── delete.go
│   ├── helper.go
│   ├── helper_test.go
│   ├── interfaces.go
│   ├── preload.go
│   ├── query.go
│   ├── raw.go
│   ├── row.go
│   ├── transaction.go
│   └── update.go
├── callbacks.go
├── chainable_api.go
├── clause/
│   ├── association.go
│   ├── benchmarks_test.go
│   ├── clause.go
│   ├── clause_test.go
│   ├── delete.go
│   ├── delete_test.go
│   ├── expression.go
│   ├── expression_test.go
│   ├── from.go
│   ├── from_test.go
│   ├── group_by.go
│   ├── group_by_test.go
│   ├── insert.go
│   ├── insert_test.go
│   ├── joins.go
│   ├── joins_test.go
│   ├── limit.go
│   ├── limit_test.go
│   ├── locking.go
│   ├── locking_test.go
│   ├── on_conflict.go
│   ├── order_by.go
│   ├── order_by_test.go
│   ├── returning.go
│   ├── returning_test.go
│   ├── select.go
│   ├── select_test.go
│   ├── set.go
│   ├── set_test.go
│   ├── update.go
│   ├── update_test.go
│   ├── values.go
│   ├── values_test.go
│   ├── where.go
│   ├── where_test.go
│   └── with.go
├── errors.go
├── finisher_api.go
├── generics.go
├── go.mod
├── go.sum
├── gorm.go
├── interfaces.go
├── internal/
│   ├── lru/
│   │   └── lru.go
│   └── stmt_store/
│       └── stmt_store.go
├── logger/
│   ├── logger.go
│   ├── slog.go
│   ├── slog_test.go
│   ├── sql.go
│   └── sql_test.go
├── migrator/
│   ├── column_type.go
│   ├── index.go
│   ├── migrator.go
│   └── table_type.go
├── migrator.go
├── model.go
├── prepare_stmt.go
├── scan.go
├── schema/
│   ├── callbacks_test.go
│   ├── constraint.go
│   ├── constraint_test.go
│   ├── field.go
│   ├── field_test.go
│   ├── index.go
│   ├── index_test.go
│   ├── interfaces.go
│   ├── model_test.go
│   ├── naming.go
│   ├── naming_test.go
│   ├── pool.go
│   ├── relationship.go
│   ├── relationship_test.go
│   ├── schema.go
│   ├── schema_helper_test.go
│   ├── schema_test.go
│   ├── serializer.go
│   ├── serializer_test.go
│   ├── utils.go
│   └── utils_test.go
├── soft_delete.go
├── statement.go
├── statement_test.go
├── tests/
│   ├── .gitignore
│   ├── README.md
│   ├── association_generics_test.go
│   ├── associations_belongs_to_test.go
│   ├── associations_has_many_test.go
│   ├── associations_has_one_test.go
│   ├── associations_many2many_test.go
│   ├── associations_test.go
│   ├── benchmark_test.go
│   ├── callbacks_test.go
│   ├── chainable_api_test.go
│   ├── compose.yml
│   ├── connection_test.go
│   ├── connpool_test.go
│   ├── count_test.go
│   ├── create_test.go
│   ├── customize_field_test.go
│   ├── default_value_test.go
│   ├── delete_test.go
│   ├── distinct_test.go
│   ├── embedded_struct_test.go
│   ├── error_translator_test.go
│   ├── gaussdb_test.go
│   ├── generics_test.go
│   ├── go.mod
│   ├── gorm_test.go
│   ├── group_by_test.go
│   ├── helper_test.go
│   ├── hooks_test.go
│   ├── joins_table_test.go
│   ├── joins_test.go
│   ├── lru_test.go
│   ├── main_test.go
│   ├── migrate_test.go
│   ├── multi_primary_keys_test.go
│   ├── named_argument_test.go
│   ├── named_polymorphic_test.go
│   ├── non_std_test.go
│   ├── postgres_test.go
│   ├── preload_suits_test.go
│   ├── preload_test.go
│   ├── prepared_stmt_test.go
│   ├── query_test.go
│   ├── scan_test.go
│   ├── scanner_valuer_test.go
│   ├── scopes_test.go
│   ├── serializer_test.go
│   ├── soft_delete_test.go
│   ├── sql_builder_test.go
│   ├── submodel_test.go
│   ├── table_test.go
│   ├── tests_all.sh
│   ├── tests_test.go
│   ├── tracer_test.go
│   ├── transaction_test.go
│   ├── update_belongs_to_test.go
│   ├── update_has_many_test.go
│   ├── update_has_one_test.go
│   ├── update_many2many_test.go
│   ├── update_test.go
│   └── upsert_test.go
└── utils/
    ├── tests/
    │   ├── dummy_dialecter.go
    │   ├── models.go
    │   └── utils.go
    ├── utils.go
    ├── utils_test.go
    ├── utils_unix_test.go
    └── utils_windows_test.go
Download .txt
SYMBOL INDEX (1607 symbols across 159 files)

FILE: association.go
  type Association (line 14) | type Association struct
    method Unscoped (line 42) | func (association *Association) Unscoped() *Association {
    method Find (line 51) | func (association *Association) Find(out interface{}, conds ...interfa...
    method Append (line 58) | func (association *Association) Append(values ...interface{}) error {
    method Replace (line 75) | func (association *Association) Replace(values ...interface{}) error {
    method Delete (line 199) | func (association *Association) Delete(values ...interface{}) error {
    method Clear (line 367) | func (association *Association) Clear() error {
    method Count (line 371) | func (association *Association) Count() (count int64) {
    method saveAssociation (line 384) | func (association *Association) saveAssociation(clear bool, values ......
    method buildCondition (line 608) | func (association *Association) buildCondition() *DB {
  method Association (line 21) | func (db *DB) Association(column string) *Association {
  type assignBack (line 378) | type assignBack struct
  function expandValues (line 638) | func expandValues(values ...any) (results []any) {

FILE: callbacks.go
  function initializeCallbacks (line 15) | func initializeCallbacks(db *DB) *callbacks {
  type callbacks (line 29) | type callbacks struct
    method Create (line 51) | func (cs *callbacks) Create() *processor {
    method Query (line 55) | func (cs *callbacks) Query() *processor {
    method Update (line 59) | func (cs *callbacks) Update() *processor {
    method Delete (line 63) | func (cs *callbacks) Delete() *processor {
    method Row (line 67) | func (cs *callbacks) Row() *processor {
    method Raw (line 71) | func (cs *callbacks) Raw() *processor {
  type processor (line 33) | type processor struct
    method Execute (line 75) | func (p *processor) Execute(db *DB) *DB {
    method Get (line 161) | func (p *processor) Get(name string) func(*DB) {
    method Before (line 170) | func (p *processor) Before(name string) *callback {
    method After (line 174) | func (p *processor) After(name string) *callback {
    method Match (line 178) | func (p *processor) Match(fc func(*DB) bool) *callback {
    method Register (line 182) | func (p *processor) Register(name string, fn func(*DB)) error {
    method Remove (line 186) | func (p *processor) Remove(name string) error {
    method Replace (line 190) | func (p *processor) Replace(name string, fn func(*DB)) error {
    method compile (line 194) | func (p *processor) compile() (err error) {
  type callback (line 40) | type callback struct
    method Before (line 217) | func (c *callback) Before(name string) *callback {
    method After (line 222) | func (c *callback) After(name string) *callback {
    method Register (line 227) | func (c *callback) Register(name string, fn func(*DB)) error {
    method Remove (line 234) | func (c *callback) Remove(name string) error {
    method Replace (line 242) | func (c *callback) Replace(name string, fn func(*DB)) error {
  function getRIndex (line 252) | func getRIndex(strs []string, str string) int {
  function sortCallbacks (line 261) | func sortCallbacks(cs []*callback) (fns []func(*DB), err error) {
  function removeCallbacks (line 357) | func removeCallbacks(cs []*callback, nameMap map[string]bool) []*callback {

FILE: callbacks/associations.go
  function SaveBeforeAssociations (line 13) | func SaveBeforeAssociations(create bool) func(db *gorm.DB) {
  function SaveAfterAssociations (line 110) | func SaveAfterAssociations(create bool) func(db *gorm.DB) {
  function onConflictOption (line 360) | func onConflictOption(stmt *gorm.Statement, s *schema.Schema, defaultUpd...
  function saveAssociations (line 378) | func saveAssociations(db *gorm.DB, rel *schema.Relationship, rValues ref...
  function checkAssociationsSaved (line 439) | func checkAssociationsSaved(db *gorm.DB, values reflect.Value) bool {

FILE: callbacks/callbacks.go
  type Config (line 14) | type Config struct
  function RegisterDefaultCallbacks (line 22) | func RegisterDefaultCallbacks(db *gorm.DB, config *Config) {

FILE: callbacks/callmethod.go
  function callMethod (line 9) | func callMethod(db *gorm.DB, fc func(value interface{}, tx *gorm.DB) boo...

FILE: callbacks/create.go
  function BeforeCreate (line 15) | func BeforeCreate(db *gorm.DB) {
  function Create (line 37) | func Create(config *Config) func(db *gorm.DB) {
  function AfterCreate (line 223) | func AfterCreate(db *gorm.DB) {
  function ConvertToCreateValues (line 245) | func ConvertToCreateValues(stmt *gorm.Statement) (values clause.Values) {

FILE: callbacks/create_test.go
  function TestConvertToCreateValues_DestType_Slice (line 16) | func TestConvertToCreateValues_DestType_Slice(t *testing.T) {

FILE: callbacks/delete.go
  function BeforeDelete (line 13) | func BeforeDelete(db *gorm.DB) {
  function DeleteBeforeAssociations (line 26) | func DeleteBeforeAssociations(db *gorm.DB) {
  function Delete (line 113) | func Delete(config *Config) func(db *gorm.DB) {
  function AfterDelete (line 185) | func AfterDelete(db *gorm.DB) {

FILE: callbacks/helper.go
  function ConvertMapToValuesForCreate (line 12) | func ConvertMapToValuesForCreate(stmt *gorm.Statement, mapValue map[stri...
  function ConvertSliceOfMapToValuesForCreate (line 43) | func ConvertSliceOfMapToValuesForCreate(stmt *gorm.Statement, mapValues ...
  function hasReturning (line 96) | func hasReturning(tx *gorm.DB, supportReturning bool) (bool, gorm.ScanMo...
  function checkMissingWhereConditions (line 109) | func checkMissingWhereConditions(db *gorm.DB) {
  function loadOrStoreVisitMap (line 128) | func loadOrStoreVisitMap(visitMap *visitMap, v reflect.Value) (loaded bo...

FILE: callbacks/helper_test.go
  function TestLoadOrStoreVisitMap (line 11) | func TestLoadOrStoreVisitMap(t *testing.T) {
  function TestConvertMapToValuesForCreate (line 41) | func TestConvertMapToValuesForCreate(t *testing.T) {
  function TestConvertSliceOfMapToValuesForCreate (line 99) | func TestConvertSliceOfMapToValuesForCreate(t *testing.T) {

FILE: callbacks/interfaces.go
  type BeforeCreateInterface (line 5) | type BeforeCreateInterface interface
  type AfterCreateInterface (line 9) | type AfterCreateInterface interface
  type BeforeUpdateInterface (line 13) | type BeforeUpdateInterface interface
  type AfterUpdateInterface (line 17) | type AfterUpdateInterface interface
  type BeforeSaveInterface (line 21) | type BeforeSaveInterface interface
  type AfterSaveInterface (line 25) | type AfterSaveInterface interface
  type BeforeDeleteInterface (line 29) | type BeforeDeleteInterface interface
  type AfterDeleteInterface (line 33) | type AfterDeleteInterface interface
  type AfterFindInterface (line 37) | type AfterFindInterface interface

FILE: callbacks/preload.go
  function parsePreloadMap (line 38) | func parsePreloadMap(s *schema.Schema, preloads map[string][]interface{}...
  function embeddedValues (line 71) | func embeddedValues(embeddedRelations *schema.Relationships) []string {
  function preloadEntryPoint (line 90) | func preloadEntryPoint(db *gorm.DB, joins []string, relationships *schem...
  function preloadDB (line 169) | func preloadDB(db *gorm.DB, reflectValue reflect.Value, dest interface{}...
  function preload (line 185) | func preload(tx *gorm.DB, rel *schema.Relationship, conds []interface{},...

FILE: callbacks/query.go
  function Query (line 14) | func Query(db *gorm.DB) {
  function BuildQuerySQL (line 36) | func BuildQuerySQL(db *gorm.DB) {
  function Preload (line 277) | func Preload(db *gorm.DB) {
  function AfterQuery (line 298) | func AfterQuery(db *gorm.DB) {

FILE: callbacks/raw.go
  function RawExec (line 7) | func RawExec(db *gorm.DB) {

FILE: callbacks/row.go
  function RowQuery (line 7) | func RowQuery(db *gorm.DB) {

FILE: callbacks/transaction.go
  function BeginTransaction (line 7) | func BeginTransaction(db *gorm.DB) {
  function CommitOrRollbackTransaction (line 20) | func CommitOrRollbackTransaction(db *gorm.DB) {

FILE: callbacks/update.go
  function SetupUpdateReflectValue (line 13) | func SetupUpdateReflectValue(db *gorm.DB) {
  function BeforeUpdate (line 33) | func BeforeUpdate(db *gorm.DB) {
  function Update (line 56) | func Update(config *Config) func(db *gorm.DB) {
  function AfterUpdate (line 117) | func AfterUpdate(db *gorm.DB) {
  function ConvertToAssignments (line 140) | func ConvertToAssignments(stmt *gorm.Statement) (set clause.Set) {

FILE: chainable_api.go
  method Model (line 18) | func (db *DB) Model(value interface{}) (tx *DB) {
  method Clauses (line 38) | func (db *DB) Clauses(conds ...clause.Expression) (tx *DB) {
  method Table (line 64) | func (db *DB) Table(name string, args ...interface{}) (tx *DB) {
  method Distinct (line 94) | func (db *DB) Distinct(args ...interface{}) (tx *DB) {
  method Select (line 112) | func (db *DB) Select(query interface{}, args ...interface{}) (tx *DB) {
  method Omit (line 177) | func (db *DB) Omit(columns ...string) (tx *DB) {
  method MapColumns (line 189) | func (db *DB) MapColumns(m map[string]string) (tx *DB) {
  method Where (line 207) | func (db *DB) Where(query interface{}, args ...interface{}) (tx *DB) {
  method Not (line 221) | func (db *DB) Not(query interface{}, args ...interface{}) (tx *DB) {
  method Or (line 235) | func (db *DB) Or(query interface{}, args ...interface{}) (tx *DB) {
  method Joins (line 248) | func (db *DB) Joins(query string, args ...interface{}) (tx *DB) {
  method InnerJoins (line 254) | func (db *DB) InnerJoins(query string, args ...interface{}) (tx *DB) {
  function joins (line 258) | func joins(db *DB, joinType clause.JoinType, query string, args ...inter...
  method Group (line 283) | func (db *DB) Group(name string) (tx *DB) {
  method Having (line 297) | func (db *DB) Having(query interface{}, args ...interface{}) (tx *DB) {
  method Order (line 313) | func (db *DB) Order(value interface{}) (tx *DB) {
  method Limit (line 343) | func (db *DB) Limit(limit int) (tx *DB) {
  method Offset (line 357) | func (db *DB) Offset(offset int) (tx *DB) {
  method Scopes (line 376) | func (db *DB) Scopes(funcs ...func(*DB) *DB) (tx *DB) {
  method executeScopes (line 382) | func (db *DB) executeScopes() (tx *DB) {
  method Preload (line 395) | func (db *DB) Preload(query string, args ...interface{}) (tx *DB) {
  method Attrs (line 418) | func (db *DB) Attrs(attrs ...interface{}) (tx *DB) {
  method Assign (line 439) | func (db *DB) Assign(attrs ...interface{}) (tx *DB) {
  method Unscoped (line 455) | func (db *DB) Unscoped() (tx *DB) {
  method Raw (line 461) | func (db *DB) Raw(sql string, values ...interface{}) (tx *DB) {

FILE: clause/association.go
  type AssociationOpType (line 4) | type AssociationOpType
  constant OpUnlink (line 7) | OpUnlink AssociationOpType = iota
  constant OpDelete (line 8) | OpDelete
  constant OpUpdate (line 9) | OpUpdate
  constant OpCreate (line 10) | OpCreate
  type Association (line 14) | type Association struct
    method Assignments (line 28) | func (ao Association) Assignments() []Assignment {
    method AssociationAssignments (line 33) | func (ao Association) AssociationAssignments() []Association {
  type AssociationAssigner (line 23) | type AssociationAssigner interface

FILE: clause/benchmarks_test.go
  function BenchmarkSelect (line 13) | func BenchmarkSelect(b *testing.B) {
  function BenchmarkComplexSelect (line 29) | func BenchmarkComplexSelect(b *testing.B) {

FILE: clause/clause.go
  type Interface (line 4) | type Interface interface
  type ClauseBuilder (line 11) | type ClauseBuilder
  type Writer (line 13) | type Writer interface
  type Builder (line 19) | type Builder interface
  type Clause (line 27) | type Clause struct
    method Build (line 37) | func (c Clause) Build(builder Builder) {
  constant PrimaryKey (line 66) | PrimaryKey   string = "~~~py~~~"
  constant CurrentTable (line 67) | CurrentTable string = "~~~ct~~~"
  constant Associations (line 68) | Associations string = "~~~as~~~"
  type Column (line 77) | type Column struct
  type Table (line 85) | type Table struct

FILE: clause/clause_test.go
  function checkBuildClauses (line 17) | func checkBuildClauses(t *testing.T, clauses []clause.Interface, result ...

FILE: clause/delete.go
  type Delete (line 3) | type Delete struct
    method Name (line 7) | func (d Delete) Name() string {
    method Build (line 11) | func (d Delete) Build(builder Builder) {
    method MergeClause (line 20) | func (d Delete) MergeClause(clause *Clause) {

FILE: clause/delete_test.go
  function TestDelete (line 10) | func TestDelete(t *testing.T) {

FILE: clause/expression.go
  type Expression (line 11) | type Expression interface
  type NegationExpressionBuilder (line 16) | type NegationExpressionBuilder interface
  type Expr (line 21) | type Expr struct
    method Build (line 28) | func (expr Expr) Build(builder Builder) {
  type NamedExpr (line 61) | type NamedExpr struct
    method Build (line 67) | func (expr NamedExpr) Build(builder Builder) {
  function processValue (line 161) | func processValue(builder Builder, value interface{}) {
  type IN (line 185) | type IN struct
    method Build (line 190) | func (in IN) Build(builder Builder) {
    method NegationBuild (line 211) | func (in IN) NegationBuild(builder Builder) {
  type Eq (line 232) | type Eq struct
    method Build (line 237) | func (eq Eq) Build(builder Builder) {
    method NegationBuild (line 265) | func (eq Eq) NegationBuild(builder Builder) {
  type Neq (line 270) | type Neq
    method Build (line 272) | func (neq Neq) Build(builder Builder) {
    method NegationBuild (line 296) | func (neq Neq) NegationBuild(builder Builder) {
  type Gt (line 301) | type Gt
    method Build (line 303) | func (gt Gt) Build(builder Builder) {
    method NegationBuild (line 309) | func (gt Gt) NegationBuild(builder Builder) {
  type Gte (line 314) | type Gte
    method Build (line 316) | func (gte Gte) Build(builder Builder) {
    method NegationBuild (line 322) | func (gte Gte) NegationBuild(builder Builder) {
  type Lt (line 327) | type Lt
    method Build (line 329) | func (lt Lt) Build(builder Builder) {
    method NegationBuild (line 335) | func (lt Lt) NegationBuild(builder Builder) {
  type Lte (line 340) | type Lte
    method Build (line 342) | func (lte Lte) Build(builder Builder) {
    method NegationBuild (line 348) | func (lte Lte) NegationBuild(builder Builder) {
  type Like (line 353) | type Like
    method Build (line 355) | func (like Like) Build(builder Builder) {
    method NegationBuild (line 361) | func (like Like) NegationBuild(builder Builder) {
  function eqNil (line 367) | func eqNil(value interface{}) bool {
  function eqNilReflect (line 375) | func eqNilReflect(value interface{}) bool {

FILE: clause/expression_test.go
  function TestExpr (line 16) | func TestExpr(t *testing.T) {
  function TestNamedExpr (line 39) | func TestNamedExpr(t *testing.T) {
  function TestExpression (line 163) | func TestExpression(t *testing.T) {

FILE: clause/from.go
  type From (line 4) | type From struct
    method Name (line 10) | func (from From) Name() string {
    method Build (line 15) | func (from From) Build(builder Builder) {
    method MergeClause (line 35) | func (from From) MergeClause(clause *Clause) {

FILE: clause/from_test.go
  function TestFrom (line 10) | func TestFrom(t *testing.T) {

FILE: clause/group_by.go
  type GroupBy (line 4) | type GroupBy struct
    method Name (line 10) | func (groupBy GroupBy) Name() string {
    method Build (line 15) | func (groupBy GroupBy) Build(builder Builder) {
    method MergeClause (line 31) | func (groupBy GroupBy) MergeClause(clause *Clause) {

FILE: clause/group_by_test.go
  function TestGroupBy (line 10) | func TestGroupBy(t *testing.T) {

FILE: clause/insert.go
  type Insert (line 3) | type Insert struct
    method Name (line 9) | func (insert Insert) Name() string {
    method Build (line 14) | func (insert Insert) Build(builder Builder) {
    method MergeClause (line 29) | func (insert Insert) MergeClause(clause *Clause) {

FILE: clause/insert_test.go
  function TestInsert (line 10) | func TestInsert(t *testing.T) {

FILE: clause/joins.go
  type JoinType (line 5) | type JoinType
    method Association (line 25) | func (jt JoinType) Association(name string) JoinTarget {
    method AssociationFrom (line 29) | func (jt JoinType) AssociationFrom(name string, subquery Expression) J...
  constant CrossJoin (line 8) | CrossJoin JoinType = "CROSS"
  constant InnerJoin (line 9) | InnerJoin JoinType = "INNER"
  constant LeftJoin (line 10) | LeftJoin  JoinType = "LEFT"
  constant RightJoin (line 11) | RightJoin JoinType = "RIGHT"
  type JoinTarget (line 14) | type JoinTarget struct
    method As (line 33) | func (jt JoinTarget) As(name string) JoinTarget {
  function Has (line 21) | func Has(name string) JoinTarget {
  type Join (line 39) | type Join struct
    method Build (line 53) | func (join Join) Build(builder Builder) {
  function JoinTable (line 47) | func JoinTable(names ...string) Table {

FILE: clause/joins_test.go
  function TestJoin (line 13) | func TestJoin(t *testing.T) {

FILE: clause/limit.go
  type Limit (line 4) | type Limit struct
    method Name (line 10) | func (limit Limit) Name() string {
    method Build (line 15) | func (limit Limit) Build(builder Builder) {
    method MergeClause (line 30) | func (limit Limit) MergeClause(clause *Clause) {

FILE: clause/limit_test.go
  function TestLimit (line 10) | func TestLimit(t *testing.T) {

FILE: clause/locking.go
  constant LockingStrengthUpdate (line 4) | LockingStrengthUpdate    = "UPDATE"
  constant LockingStrengthShare (line 5) | LockingStrengthShare     = "SHARE"
  constant LockingOptionsSkipLocked (line 6) | LockingOptionsSkipLocked = "SKIP LOCKED"
  constant LockingOptionsNoWait (line 7) | LockingOptionsNoWait     = "NOWAIT"
  type Locking (line 10) | type Locking struct
    method Name (line 17) | func (locking Locking) Name() string {
    method Build (line 22) | func (locking Locking) Build(builder Builder) {
    method MergeClause (line 36) | func (locking Locking) MergeClause(clause *Clause) {

FILE: clause/locking_test.go
  function TestLocking (line 10) | func TestLocking(t *testing.T) {

FILE: clause/on_conflict.go
  type OnConflict (line 3) | type OnConflict struct
    method Name (line 13) | func (OnConflict) Name() string {
    method Build (line 18) | func (onConflict OnConflict) Build(builder Builder) {
    method MergeClause (line 57) | func (onConflict OnConflict) MergeClause(clause *Clause) {

FILE: clause/order_by.go
  type OrderByColumn (line 3) | type OrderByColumn struct
  type OrderBy (line 9) | type OrderBy struct
    method Name (line 15) | func (orderBy OrderBy) Name() string {
    method Build (line 20) | func (orderBy OrderBy) Build(builder Builder) {
    method MergeClause (line 38) | func (orderBy OrderBy) MergeClause(clause *Clause) {

FILE: clause/order_by_test.go
  function TestOrderBy (line 10) | func TestOrderBy(t *testing.T) {

FILE: clause/returning.go
  type Returning (line 3) | type Returning struct
    method Name (line 8) | func (returning Returning) Name() string {
    method Build (line 13) | func (returning Returning) Build(builder Builder) {
    method MergeClause (line 28) | func (returning Returning) MergeClause(clause *Clause) {

FILE: clause/returning_test.go
  function TestReturning (line 10) | func TestReturning(t *testing.T) {

FILE: clause/select.go
  type Select (line 4) | type Select struct
    method Name (line 10) | func (s Select) Name() string {
    method Build (line 14) | func (s Select) Build(builder Builder) {
    method MergeClause (line 31) | func (s Select) MergeClause(clause *Clause) {
  type CommaExpression (line 48) | type CommaExpression struct
    method Build (line 52) | func (comma CommaExpression) Build(builder Builder) {

FILE: clause/select_test.go
  function TestSelect (line 10) | func TestSelect(t *testing.T) {

FILE: clause/set.go
  type Set (line 5) | type Set
    method Name (line 17) | func (set Set) Name() string {
    method Build (line 21) | func (set Set) Build(builder Builder) {
    method MergeClause (line 39) | func (set Set) MergeClause(clause *Clause) {
    method Assignments (line 46) | func (set Set) Assignments() []Assignment { return []Assignment(set) }
  type Assignment (line 7) | type Assignment struct
    method Assignments (line 71) | func (a Assignment) Assignments() []Assignment { return []Assignment{a} }
  type Assigner (line 13) | type Assigner interface
  function Assignments (line 48) | func Assignments(values map[string]interface{}) Set {
  function AssignmentColumns (line 62) | func AssignmentColumns(values []string) Set {

FILE: clause/set_test.go
  function TestSet (line 18) | func TestSet(t *testing.T) {
  function TestAssignments (line 50) | func TestAssignments(t *testing.T) {

FILE: clause/update.go
  type Update (line 3) | type Update struct
    method Name (line 9) | func (update Update) Name() string {
    method Build (line 14) | func (update Update) Build(builder Builder) {
    method MergeClause (line 28) | func (update Update) MergeClause(clause *Clause) {

FILE: clause/update_test.go
  function TestUpdate (line 10) | func TestUpdate(t *testing.T) {

FILE: clause/values.go
  type Values (line 3) | type Values struct
    method Name (line 9) | func (Values) Name() string {
    method Build (line 14) | func (values Values) Build(builder Builder) {
    method MergeClause (line 42) | func (values Values) MergeClause(clause *Clause) {

FILE: clause/values_test.go
  function TestValues (line 10) | func TestValues(t *testing.T) {

FILE: clause/where.go
  constant AndWithSpace (line 8) | AndWithSpace = " AND "
  constant OrWithSpace (line 9) | OrWithSpace  = " OR "
  type Where (line 13) | type Where struct
    method Name (line 18) | func (where Where) Name() string {
    method Build (line 23) | func (where Where) Build(builder Builder) {
    method MergeClause (line 92) | func (where Where) MergeClause(clause *Clause) {
  function buildExprs (line 43) | func buildExprs(exprs []Expression, builder Builder, joinCond string) {
  function And (line 103) | func And(exprs ...Expression) Expression {
  type AndConditions (line 117) | type AndConditions struct
    method Build (line 121) | func (and AndConditions) Build(builder Builder) {
  function Or (line 131) | func Or(exprs ...Expression) Expression {
  type OrConditions (line 138) | type OrConditions struct
    method Build (line 142) | func (or OrConditions) Build(builder Builder) {
  function Not (line 152) | func Not(exprs ...Expression) Expression {
  type NotConditions (line 164) | type NotConditions struct
    method Build (line 168) | func (not NotConditions) Build(builder Builder) {

FILE: clause/where_test.go
  function TestWhere (line 10) | func TestWhere(t *testing.T) {

FILE: clause/with.go
  type With (line 3) | type With struct

FILE: finisher_api.go
  method Create (line 19) | func (db *DB) Create(value interface{}) (tx *DB) {
  method CreateInBatches (line 30) | func (db *DB) CreateInBatches(value interface{}, batchSize int) (tx *DB) {
  method Save (line 75) | func (db *DB) Save(value interface{}) (tx *DB) {
  method First (line 120) | func (db *DB) First(dest interface{}, conds ...interface{}) (tx *DB) {
  method Take (line 135) | func (db *DB) Take(dest interface{}, conds ...interface{}) (tx *DB) {
  method Last (line 148) | func (db *DB) Last(dest interface{}, conds ...interface{}) (tx *DB) {
  method Find (line 164) | func (db *DB) Find(dest interface{}, conds ...interface{}) (tx *DB) {
  method FindInBatches (line 176) | func (db *DB) FindInBatches(dest interface{}, batchSize int, fc func(tx ...
  method assignInterfacesToValue (line 248) | func (db *DB) assignInterfacesToValue(values ...interface{}) {
  method FirstOrInit (line 309) | func (db *DB) FirstOrInit(dest interface{}, conds ...interface{}) (tx *D...
  method FirstOrCreate (line 348) | func (db *DB) FirstOrCreate(dest interface{}, conds ...interface{}) (tx ...
  method Update (line 403) | func (db *DB) Update(column string, value interface{}) (tx *DB) {
  method Updates (line 410) | func (db *DB) Updates(values interface{}) (tx *DB) {
  method UpdateColumn (line 416) | func (db *DB) UpdateColumn(column string, value interface{}) (tx *DB) {
  method UpdateColumns (line 423) | func (db *DB) UpdateColumns(values interface{}) (tx *DB) {
  method Delete (line 433) | func (db *DB) Delete(value interface{}, conds ...interface{}) (tx *DB) {
  method Count (line 444) | func (db *DB) Count(count *int64) (tx *DB) {
  method Row (line 506) | func (db *DB) Row() *sql.Row {
  method Rows (line 516) | func (db *DB) Rows() (*sql.Rows, error) {
  method Scan (line 527) | func (db *DB) Scan(dest interface{}) (tx *DB) {
  method Pluck (line 556) | func (db *DB) Pluck(column string, dest interface{}) (tx *DB) {
  method ScanRows (line 577) | func (db *DB) ScanRows(rows *sql.Rows, dest interface{}) error {
  method Connection (line 598) | func (db *DB) Connection(fc func(tx *DB) error) (err error) {
  method Transaction (line 622) | func (db *DB) Transaction(fc func(tx *DB) error, opts ...*sql.TxOptions)...
  method Begin (line 665) | func (db *DB) Begin(opts ...*sql.TxOptions) *DB {
  method Commit (line 701) | func (db *DB) Commit() *DB {
  method Rollback (line 711) | func (db *DB) Rollback() *DB {
  method SavePoint (line 722) | func (db *DB) SavePoint(name string) *DB {
  method RollbackTo (line 745) | func (db *DB) RollbackTo(name string) *DB {
  method Exec (line 769) | func (db *DB) Exec(sql string, values ...interface{}) (tx *DB) {

FILE: generics.go
  type result (line 17) | type result struct
    method ModifyStatement (line 22) | func (info *result) ModifyStatement(stmt *Statement) {
    method Build (line 27) | func (result) Build(clause.Builder) {
  function WithResult (line 30) | func WithResult() *result {
  type Interface (line 34) | type Interface interface
  type CreateInterface (line 40) | type CreateInterface interface
  type ChainInterface (line 71) | type ChainInterface interface
  type SetUpdateOnlyInterface (line 100) | type SetUpdateOnlyInterface interface
  type SetCreateOrUpdateInterface (line 105) | type SetCreateOrUpdateInterface interface
  type ExecInterface (line 110) | type ExecInterface interface
  type JoinBuilder (line 121) | type JoinBuilder interface
  type PreloadBuilder (line 129) | type PreloadBuilder interface
  type op (line 141) | type op
  function G (line 143) | func G[T any](db *DB, opts ...clause.Expression) Interface[T] {
  type g (line 163) | type g struct
  method apply (line 169) | func (g *g[T]) apply(ctx context.Context) *DB {
  method Raw (line 181) | func (c *g[T]) Raw(sql string, values ...interface{}) ExecInterface[T] {
  method Exec (line 191) | func (c *g[T]) Exec(ctx context.Context, sql string, values ...interface...
  type createG (line 196) | type createG struct
  method Table (line 200) | func (c createG[T]) Table(name string, args ...interface{}) CreateInterf...
  method Select (line 206) | func (c createG[T]) Select(query string, args ...interface{}) CreateInte...
  method Omit (line 212) | func (c createG[T]) Omit(columns ...string) CreateInterface[T] {
  method Set (line 218) | func (c createG[T]) Set(assignments ...clause.Assigner) SetCreateOrUpdat...
  method Create (line 222) | func (c createG[T]) Create(ctx context.Context, r *T) error {
  method CreateInBatches (line 226) | func (c createG[T]) CreateInBatches(ctx context.Context, r *[]T, batchSi...
  type chainG (line 230) | type chainG struct
  method getInstance (line 234) | func (c chainG[T]) getInstance() *DB {
  method with (line 239) | func (c chainG[T]) with(v op) chainG[T] {
  method Table (line 248) | func (c chainG[T]) Table(name string, args ...interface{}) ChainInterfac...
  method Scopes (line 254) | func (c chainG[T]) Scopes(scopes ...func(db *Statement)) ChainInterface[...
  method Where (line 263) | func (c chainG[T]) Where(query interface{}, args ...interface{}) ChainIn...
  method Not (line 269) | func (c chainG[T]) Not(query interface{}, args ...interface{}) ChainInte...
  method Or (line 275) | func (c chainG[T]) Or(query interface{}, args ...interface{}) ChainInter...
  method Limit (line 281) | func (c chainG[T]) Limit(offset int) ChainInterface[T] {
  method Offset (line 287) | func (c chainG[T]) Offset(offset int) ChainInterface[T] {
  type joinBuilder (line 293) | type joinBuilder struct
    method Where (line 297) | func (q *joinBuilder) Where(query interface{}, args ...interface{}) Jo...
    method Or (line 302) | func (q *joinBuilder) Or(query interface{}, args ...interface{}) JoinB...
    method Not (line 307) | func (q *joinBuilder) Not(query interface{}, args ...interface{}) Join...
    method Select (line 312) | func (q *joinBuilder) Select(columns ...string) JoinBuilder {
    method Omit (line 317) | func (q *joinBuilder) Omit(columns ...string) JoinBuilder {
  type preloadBuilder (line 322) | type preloadBuilder struct
    method Where (line 327) | func (q *preloadBuilder) Where(query interface{}, args ...interface{})...
    method Or (line 332) | func (q *preloadBuilder) Or(query interface{}, args ...interface{}) Pr...
    method Not (line 337) | func (q *preloadBuilder) Not(query interface{}, args ...interface{}) P...
    method Select (line 342) | func (q *preloadBuilder) Select(columns ...string) PreloadBuilder {
    method Omit (line 347) | func (q *preloadBuilder) Omit(columns ...string) PreloadBuilder {
    method Limit (line 352) | func (q *preloadBuilder) Limit(limit int) PreloadBuilder {
    method Offset (line 357) | func (q *preloadBuilder) Offset(offset int) PreloadBuilder {
    method Order (line 362) | func (q *preloadBuilder) Order(value interface{}) PreloadBuilder {
    method LimitPerRecord (line 367) | func (q *preloadBuilder) LimitPerRecord(num int) PreloadBuilder {
  method Joins (line 372) | func (c chainG[T]) Joins(jt clause.JoinTarget, on func(db JoinBuilder, j...
  method Select (line 431) | func (c chainG[T]) Select(query string, args ...interface{}) ChainInterf...
  method Omit (line 437) | func (c chainG[T]) Omit(columns ...string) ChainInterface[T] {
  method MapColumns (line 443) | func (c chainG[T]) MapColumns(m map[string]string) ChainInterface[T] {
  method Set (line 449) | func (c chainG[T]) Set(assignments ...clause.Assigner) SetUpdateOnlyInte...
  method Distinct (line 453) | func (c chainG[T]) Distinct(args ...interface{}) ChainInterface[T] {
  method Group (line 459) | func (c chainG[T]) Group(name string) ChainInterface[T] {
  method Having (line 465) | func (c chainG[T]) Having(query interface{}, args ...interface{}) ChainI...
  method Order (line 471) | func (c chainG[T]) Order(value interface{}) ChainInterface[T] {
  method Preload (line 477) | func (c chainG[T]) Preload(association string, query func(db PreloadBuil...
  method Delete (line 560) | func (c chainG[T]) Delete(ctx context.Context) (rowsAffected int, err er...
  method Update (line 566) | func (c chainG[T]) Update(ctx context.Context, name string, value any) (...
  method Updates (line 572) | func (c chainG[T]) Updates(ctx context.Context, t T) (rowsAffected int, ...
  method Count (line 577) | func (c chainG[T]) Count(ctx context.Context, column string) (result int...
  method Build (line 583) | func (c chainG[T]) Build(builder clause.Builder) {
  type execG (line 620) | type execG struct
  method First (line 624) | func (g execG[T]) First(ctx context.Context) (T, error) {
  method Scan (line 630) | func (g execG[T]) Scan(ctx context.Context, result interface{}) error {
  method Last (line 636) | func (g execG[T]) Last(ctx context.Context) (T, error) {
  method Take (line 642) | func (g execG[T]) Take(ctx context.Context) (T, error) {
  method Find (line 648) | func (g execG[T]) Find(ctx context.Context) ([]T, error) {
  method FindInBatches (line 654) | func (g execG[T]) FindInBatches(ctx context.Context, batchSize int, fc f...
  method Row (line 661) | func (g execG[T]) Row(ctx context.Context) *sql.Row {
  method Rows (line 666) | func (g execG[T]) Rows(ctx context.Context) (*sql.Rows, error) {
  method processSet (line 671) | func (c chainG[T]) processSet(items ...clause.Assigner) setCreateOrUpdat...
  type setCreateOrUpdateG (line 695) | type setCreateOrUpdateG struct
  method Update (line 701) | func (s setCreateOrUpdateG[T]) Update(ctx context.Context) (rowsAffected...
  method Create (line 719) | func (s setCreateOrUpdateG[T]) Create(ctx context.Context) error {
  method executeAssociationOperation (line 741) | func (s setCreateOrUpdateG[T]) executeAssociationOperation(ctx context.C...
  method handleAssociationCreate (line 755) | func (s setCreateOrUpdateG[T]) handleAssociationCreate(ctx context.Conte...
  method handleAssociationForOwners (line 772) | func (s setCreateOrUpdateG[T]) handleAssociationForOwners(base *DB, ctx ...
  method handleAssociation (line 791) | func (s setCreateOrUpdateG[T]) handleAssociation(ctx context.Context, ba...

FILE: gorm.go
  constant preparedStmtDBKey (line 18) | preparedStmtDBKey = "preparedStmt"
  type Config (line 21) | type Config struct
    method Apply (line 78) | func (c *Config) Apply(config *Config) error {
    method AfterInitialize (line 86) | func (c *Config) AfterInitialize(db *DB) error {
  type Option (line 98) | type Option interface
  type DB (line 104) | type DB struct
    method Session (line 255) | func (db *DB) Session(config *Session) *DB {
    method WithContext (line 357) | func (db *DB) WithContext(ctx context.Context) *DB {
    method Debug (line 362) | func (db *DB) Debug() (tx *DB) {
    method Set (line 370) | func (db *DB) Set(key string, value interface{}) *DB {
    method Get (line 377) | func (db *DB) Get(key string) (interface{}, bool) {
    method InstanceSet (line 382) | func (db *DB) InstanceSet(key string, value interface{}) *DB {
    method InstanceGet (line 389) | func (db *DB) InstanceGet(key string) (interface{}, bool) {
    method Callback (line 394) | func (db *DB) Callback() *callbacks {
    method AddError (line 399) | func (db *DB) AddError(err error) error {
    method DB (line 417) | func (db *DB) DB() (*sql.DB, error) {
    method getInstance (line 439) | func (db *DB) getInstance() *DB {
    method SetupJoinTable (line 474) | func (db *DB) SetupJoinTable(model interface{}, field string, joinTabl...
    method Use (line 525) | func (db *DB) Use(plugin Plugin) error {
    method ToSQL (line 545) | func (db *DB) ToSQL(queryFn func(tx *DB) *DB) string {
  type Session (line 113) | type Session struct
  function Open (line 132) | func Open(dialector Dialector, opts ...Option) (db *DB, err error) {
  function Expr (line 469) | func Expr(expr string, args ...interface{}) clause.Expr {

FILE: interfaces.go
  type Dialector (line 12) | type Dialector interface
  type Plugin (line 24) | type Plugin interface
  type ParamsFilter (line 29) | type ParamsFilter interface
  type ConnPool (line 34) | type ConnPool interface
  type SavePointerDialectorInterface (line 42) | type SavePointerDialectorInterface interface
  type TxBeginner (line 48) | type TxBeginner interface
  type ConnPoolBeginner (line 53) | type ConnPoolBeginner interface
  type TxCommitter (line 58) | type TxCommitter interface
  type Tx (line 64) | type Tx interface
  type Valuer (line 71) | type Valuer interface
  type GetDBConnector (line 76) | type GetDBConnector interface
  type Rows (line 81) | type Rows interface
  type ErrorTranslator (line 90) | type ErrorTranslator interface

FILE: internal/lru/lru.go
  type EvictCallback (line 11) | type EvictCallback
  type LRU (line 14) | type LRU struct
  type bucket (line 32) | type bucket struct
  constant noEvictionTTL (line 38) | noEvictionTTL = time.Hour * 24 * 365 * 10
  constant numBuckets (line 42) | numBuckets = 100
  function NewLRU (line 51) | func NewLRU[K comparable, V any](size int, onEvict EvictCallback[K, V], ...
  method Purge (line 97) | func (c *LRU[K, V]) Purge() {
  method Add (line 117) | func (c *LRU[K, V]) Add(key K, value V) (evicted bool) {
  method Get (line 146) | func (c *LRU[K, V]) Get(key K) (value V, ok bool) {
  method Contains (line 163) | func (c *LRU[K, V]) Contains(key K) (ok bool) {
  method Peek (line 172) | func (c *LRU[K, V]) Peek(key K) (value V, ok bool) {
  method Remove (line 188) | func (c *LRU[K, V]) Remove(key K) bool {
  method RemoveOldest (line 199) | func (c *LRU[K, V]) RemoveOldest() (key K, value V, ok bool) {
  method GetOldest (line 210) | func (c *LRU[K, V]) GetOldest() (key K, value V, ok bool) {
  method KeyValues (line 219) | func (c *LRU[K, V]) KeyValues() map[K]V {
  method Keys (line 236) | func (c *LRU[K, V]) Keys() []K {
  method Values (line 252) | func (c *LRU[K, V]) Values() []V {
  method Len (line 267) | func (c *LRU[K, V]) Len() int {
  method Resize (line 274) | func (c *LRU[K, V]) Resize(size int) (evicted int) {
  method removeOldest (line 305) | func (c *LRU[K, V]) removeOldest() {
  method removeElement (line 312) | func (c *LRU[K, V]) removeElement(e *Entry[K, V]) {
  method deleteExpired (line 323) | func (c *LRU[K, V]) deleteExpired() {
  method addToBucket (line 341) | func (c *LRU[K, V]) addToBucket(e *Entry[K, V]) {
  method removeFromBucket (line 351) | func (c *LRU[K, V]) removeFromBucket(e *Entry[K, V]) {
  method Cap (line 356) | func (c *LRU[K, V]) Cap() int {
  type Entry (line 361) | type Entry struct
  method PrevEntry (line 386) | func (e *Entry[K, V]) PrevEntry() *Entry[K, V] {
  type LruList (line 395) | type LruList struct
  method Init (line 401) | func (l *LruList[K, V]) Init() *LruList[K, V] {
  function NewList (line 409) | func NewList[K comparable, V any]() *LruList[K, V] { return new(LruList[...
  method Length (line 413) | func (l *LruList[K, V]) Length() int { return l.len }
  method Back (line 416) | func (l *LruList[K, V]) Back() *Entry[K, V] {
  method lazyInit (line 424) | func (l *LruList[K, V]) lazyInit() {
  method insert (line 431) | func (l *LruList[K, V]) insert(e, at *Entry[K, V]) *Entry[K, V] {
  method insertValue (line 442) | func (l *LruList[K, V]) insertValue(k K, v V, expiresAt time.Time, at *E...
  method Remove (line 447) | func (l *LruList[K, V]) Remove(e *Entry[K, V]) V {
  method move (line 459) | func (l *LruList[K, V]) move(e, at *Entry[K, V]) {
  method PushFront (line 473) | func (l *LruList[K, V]) PushFront(k K, v V) *Entry[K, V] {
  method PushFrontExpirable (line 479) | func (l *LruList[K, V]) PushFrontExpirable(k K, v V, expiresAt time.Time...
  method MoveToFront (line 487) | func (l *LruList[K, V]) MoveToFront(e *Entry[K, V]) {

FILE: internal/stmt_store/stmt_store.go
  type Stmt (line 13) | type Stmt struct
    method Error (line 20) | func (stmt *Stmt) Error() error {
    method Close (line 24) | func (stmt *Stmt) Close() error {
  type Store (line 36) | type Store interface
  constant defaultMaxSize (line 77) | defaultMaxSize = math.MaxInt
  constant defaultTTL (line 80) | defaultTTL = time.Hour * 24
  function New (line 98) | func New(size int, ttl time.Duration) Store {
  type lruStore (line 115) | type lruStore struct
    method Keys (line 119) | func (s *lruStore) Keys() []string {
    method Get (line 123) | func (s *lruStore) Get(key string) (*Stmt, bool) {
    method Set (line 131) | func (s *lruStore) Set(key string, value *Stmt) {
    method Delete (line 135) | func (s *lruStore) Delete(key string) {
    method New (line 157) | func (s *lruStore) New(ctx context.Context, key string, isTransaction ...
  type ConnPool (line 139) | type ConnPool interface

FILE: logger/logger.go
  constant Reset (line 20) | Reset       = "\033[0m"
  constant Red (line 21) | Red         = "\033[31m"
  constant Green (line 22) | Green       = "\033[32m"
  constant Yellow (line 23) | Yellow      = "\033[33m"
  constant Blue (line 24) | Blue        = "\033[34m"
  constant Magenta (line 25) | Magenta     = "\033[35m"
  constant Cyan (line 26) | Cyan        = "\033[36m"
  constant White (line 27) | White       = "\033[37m"
  constant BlueBold (line 28) | BlueBold    = "\033[34;1m"
  constant MagentaBold (line 29) | MagentaBold = "\033[35;1m"
  constant RedBold (line 30) | RedBold     = "\033[31;1m"
  constant YellowBold (line 31) | YellowBold  = "\033[33;1m"
  type LogLevel (line 35) | type LogLevel
  constant Silent (line 39) | Silent LogLevel = iota + 1
  constant Error (line 41) | Error
  constant Warn (line 43) | Warn
  constant Info (line 45) | Info
  type Writer (line 49) | type Writer interface
  type Config (line 54) | type Config struct
  type Interface (line 63) | type Interface interface
  function New (line 91) | func New(writer Writer, config Config) Interface {
  type logger (line 122) | type logger struct
    method LogMode (line 130) | func (l *logger) LogMode(level LogLevel) Interface {
    method Info (line 137) | func (l *logger) Info(ctx context.Context, msg string, data ...interfa...
    method Warn (line 144) | func (l *logger) Warn(ctx context.Context, msg string, data ...interfa...
    method Error (line 151) | func (l *logger) Error(ctx context.Context, msg string, data ...interf...
    method Trace (line 160) | func (l *logger) Trace(ctx context.Context, begin time.Time, fc func()...
    method ParamsFilter (line 193) | func (l *logger) ParamsFilter(ctx context.Context, sql string, params ...
  type traceRecorder (line 200) | type traceRecorder struct
    method New (line 209) | func (l *traceRecorder) New() *traceRecorder {
    method Trace (line 214) | func (l *traceRecorder) Trace(ctx context.Context, begin time.Time, fc...
    method ParamsFilter (line 220) | func (l *traceRecorder) ParamsFilter(ctx context.Context, sql string, ...

FILE: logger/slog.go
  type slogLogger (line 15) | type slogLogger struct
    method LogMode (line 34) | func (l *slogLogger) LogMode(level LogLevel) Interface {
    method Info (line 40) | func (l *slogLogger) Info(ctx context.Context, msg string, data ...int...
    method Warn (line 46) | func (l *slogLogger) Warn(ctx context.Context, msg string, data ...int...
    method Error (line 52) | func (l *slogLogger) Error(ctx context.Context, msg string, data ...in...
    method Trace (line 58) | func (l *slogLogger) Trace(ctx context.Context, begin time.Time, fc fu...
    method log (line 96) | func (l *slogLogger) log(ctx context.Context, level slog.Level, msg st...
    method ParamsFilter (line 111) | func (l *slogLogger) ParamsFilter(ctx context.Context, sql string, par...
  function NewSlogLogger (line 24) | func NewSlogLogger(logger *slog.Logger, config Config) Interface {

FILE: logger/slog_test.go
  function TestSlogLogger (line 14) | func TestSlogLogger(t *testing.T) {

FILE: logger/sql.go
  constant tmFmtWithMS (line 17) | tmFmtWithMS = "2006-01-02 15:04:05.999"
  constant tmFmtZero (line 18) | tmFmtZero   = "0000-00-00 00:00:00"
  constant nullStr (line 19) | nullStr     = "NULL"
  function isPrintable (line 22) | func isPrintable(s string) bool {
  function isNumeric (line 37) | func isNumeric(k reflect.Kind) bool {
  function ExplainSQL (line 51) | func ExplainSQL(sql string, numericPlaceholder *regexp.Regexp, escaper s...

FILE: logger/sql_test.go
  type JSON (line 15) | type JSON
    method Value (line 17) | func (j JSON) Value() (driver.Value, error) {
  type ExampleStruct (line 24) | type ExampleStruct struct
    method Value (line 29) | func (s ExampleStruct) Value() (driver.Value, error) {
  function format (line 33) | func format(v []byte, escaper string) string {
  function TestExplainSQL (line 37) | func TestExplainSQL(t *testing.T) {

FILE: migrator.go
  method Migrator (line 11) | func (db *DB) Migrator() Migrator {
  method AutoMigrate (line 23) | func (db *DB) AutoMigrate(dst ...interface{}) error {
  type ViewOption (line 28) | type ViewOption struct
  type ColumnType (line 35) | type ColumnType interface
  type Index (line 50) | type Index interface
  type TableType (line 60) | type TableType interface
  type Migrator (line 68) | type Migrator interface

FILE: migrator/column_type.go
  type ColumnType (line 9) | type ColumnType struct
    method Name (line 27) | func (ct ColumnType) Name() string {
    method DatabaseTypeName (line 40) | func (ct ColumnType) DatabaseTypeName() string {
    method ColumnType (line 48) | func (ct ColumnType) ColumnType() (columnType string, ok bool) {
    method PrimaryKey (line 53) | func (ct ColumnType) PrimaryKey() (isPrimaryKey bool, ok bool) {
    method AutoIncrement (line 58) | func (ct ColumnType) AutoIncrement() (isAutoIncrement bool, ok bool) {
    method Length (line 63) | func (ct ColumnType) Length() (length int64, ok bool) {
    method DecimalSize (line 71) | func (ct ColumnType) DecimalSize() (precision int64, scale int64, ok b...
    method Nullable (line 79) | func (ct ColumnType) Nullable() (nullable bool, ok bool) {
    method Unique (line 87) | func (ct ColumnType) Unique() (unique bool, ok bool) {
    method ScanType (line 92) | func (ct ColumnType) ScanType() reflect.Type {
    method Comment (line 100) | func (ct ColumnType) Comment() (value string, ok bool) {
    method DefaultValue (line 105) | func (ct ColumnType) DefaultValue() (value string, ok bool) {

FILE: migrator/index.go
  type Index (line 6) | type Index struct
    method Table (line 16) | func (idx Index) Table() string {
    method Name (line 21) | func (idx Index) Name() string {
    method Columns (line 26) | func (idx Index) Columns() []string {
    method PrimaryKey (line 31) | func (idx Index) PrimaryKey() (isPrimaryKey bool, ok bool) {
    method Unique (line 36) | func (idx Index) Unique() (unique bool, ok bool) {
    method Option (line 41) | func (idx Index) Option() string {

FILE: migrator/migrator.go
  type Migrator (line 34) | type Migrator struct
    method RunWithValue (line 61) | func (m Migrator) RunWithValue(value interface{}, fc func(*gorm.Statem...
    method DataTypeOf (line 78) | func (m Migrator) DataTypeOf(field *schema.Field) string {
    method FullDataTypeOf (line 90) | func (m Migrator) FullDataTypeOf(field *schema.Field) (expr clause.Exp...
    method GetQueryAndExecTx (line 110) | func (m Migrator) GetQueryAndExecTx() (queryTx, execTx *gorm.DB) {
    method AutoMigrate (line 121) | func (m Migrator) AutoMigrate(values ...interface{}) error {
    method GetTables (line 208) | func (m Migrator) GetTables() (tableList []string, err error) {
    method CreateTable (line 215) | func (m Migrator) CreateTable(values ...interface{}) error {
    method DropTable (line 319) | func (m Migrator) DropTable(values ...interface{}) error {
    method HasTable (line 333) | func (m Migrator) HasTable(value interface{}) bool {
    method RenameTable (line 345) | func (m Migrator) RenameTable(oldName, newName interface{}) error {
    method AddColumn (line 373) | func (m Migrator) AddColumn(value interface{}, name string) error {
    method DropColumn (line 396) | func (m Migrator) DropColumn(value interface{}, name string) error {
    method AlterColumn (line 411) | func (m Migrator) AlterColumn(value interface{}, field string) error {
    method HasColumn (line 428) | func (m Migrator) HasColumn(value interface{}, field string) bool {
    method RenameColumn (line 449) | func (m Migrator) RenameColumn(value interface{}, oldName, newName str...
    method MigrateColumn (line 469) | func (m Migrator) MigrateColumn(value interface{}, field *schema.Field...
    method MigrateColumnUnique (line 594) | func (m Migrator) MigrateColumnUnique(value interface{}, field *schema...
    method ColumnTypes (line 615) | func (m Migrator) ColumnTypes(value interface{}) ([]gorm.ColumnType, e...
    method CreateView (line 655) | func (m Migrator) CreateView(name string, option gorm.ViewOption) error {
    method DropView (line 679) | func (m Migrator) DropView(name string) error {
    method GuessConstraintAndTable (line 686) | func (m Migrator) GuessConstraintAndTable(stmt *gorm.Statement, name s...
    method GuessConstraintInterfaceAndTable (line 700) | func (m Migrator) GuessConstraintInterfaceAndTable(stmt *gorm.Statemen...
    method CreateConstraint (line 757) | func (m Migrator) CreateConstraint(value interface{}, name string) err...
    method DropConstraint (line 773) | func (m Migrator) DropConstraint(value interface{}, name string) error {
    method HasConstraint (line 784) | func (m Migrator) HasConstraint(value interface{}, name string) bool {
    method BuildIndexOptions (line 803) | func (m Migrator) BuildIndexOptions(opts []schema.IndexOption, stmt *g...
    method CreateIndex (line 830) | func (m Migrator) CreateIndex(value interface{}, name string) error {
    method DropIndex (line 865) | func (m Migrator) DropIndex(value interface{}, name string) error {
    method HasIndex (line 878) | func (m Migrator) HasIndex(value interface{}, name string) bool {
    method RenameIndex (line 898) | func (m Migrator) RenameIndex(value interface{}, oldName, newName stri...
    method CurrentDatabase (line 908) | func (m Migrator) CurrentDatabase() (name string) {
    method ReorderModels (line 914) | func (m Migrator) ReorderModels(values []interface{}, autoAdd bool) (r...
    method CurrentTable (line 1018) | func (m Migrator) CurrentTable(stmt *gorm.Statement) interface{} {
    method GetIndexes (line 1026) | func (m Migrator) GetIndexes(dst interface{}) ([]gorm.Index, error) {
    method GetTypeAliases (line 1031) | func (m Migrator) GetTypeAliases(databaseTypeName string) []string {
    method TableType (line 1036) | func (m Migrator) TableType(dst interface{}) (gorm.TableType, error) {
  type Config (line 39) | type Config struct
  type printSQLLogger (line 45) | type printSQLLogger struct
    method Trace (line 49) | func (l *printSQLLogger) Trace(ctx context.Context, begin time.Time, f...
  type GormDataTypeInterface (line 56) | type GormDataTypeInterface interface
  type BuildIndexOptionsInterface (line 825) | type BuildIndexOptionsInterface interface

FILE: migrator/table_type.go
  type TableType (line 8) | type TableType struct
    method Schema (line 16) | func (ct TableType) Schema() string {
    method Name (line 21) | func (ct TableType) Name() string {
    method Type (line 26) | func (ct TableType) Type() string {
    method Comment (line 31) | func (ct TableType) Comment() (comment string, ok bool) {

FILE: model.go
  type Model (line 11) | type Model struct

FILE: prepare_stmt.go
  type PreparedStmtDB (line 15) | type PreparedStmtDB struct
    method GetDBConn (line 39) | func (db *PreparedStmtDB) GetDBConn() (*sql.DB, error) {
    method Close (line 52) | func (db *PreparedStmtDB) Close() {
    method Reset (line 62) | func (db *PreparedStmtDB) Reset() {
    method prepare (line 66) | func (db *PreparedStmtDB) prepare(ctx context.Context, conn ConnPool, ...
    method BeginTx (line 88) | func (db *PreparedStmtDB) BeginTx(ctx context.Context, opt *sql.TxOpti...
    method ExecContext (line 109) | func (db *PreparedStmtDB) ExecContext(ctx context.Context, query strin...
    method QueryContext (line 120) | func (db *PreparedStmtDB) QueryContext(ctx context.Context, query stri...
    method QueryRowContext (line 131) | func (db *PreparedStmtDB) QueryRowContext(ctx context.Context, query s...
    method Ping (line 139) | func (db *PreparedStmtDB) Ping() error {
  function NewPreparedStmtDB (line 30) | func NewPreparedStmtDB(connPool ConnPool, maxSize int, ttl time.Duration...
  type PreparedStmtTX (line 147) | type PreparedStmtTX struct
    method GetDBConn (line 152) | func (db *PreparedStmtTX) GetDBConn() (*sql.DB, error) {
    method Commit (line 156) | func (tx *PreparedStmtTX) Commit() error {
    method Rollback (line 163) | func (tx *PreparedStmtTX) Rollback() error {
    method ExecContext (line 170) | func (tx *PreparedStmtTX) ExecContext(ctx context.Context, query strin...
    method QueryContext (line 181) | func (tx *PreparedStmtTX) QueryContext(ctx context.Context, query stri...
    method QueryRowContext (line 192) | func (tx *PreparedStmtTX) QueryRowContext(ctx context.Context, query s...
    method Ping (line 200) | func (tx *PreparedStmtTX) Ping() error {

FILE: scan.go
  function prepareValues (line 15) | func prepareValues(values []interface{}, db *DB, columnTypes []*sql.Colu...
  function scanIntoMap (line 39) | func scanIntoMap(mapValue map[string]interface{}, values []interface{}, ...
  method scanIntoStruct (line 54) | func (db *DB) scanIntoStruct(rows Rows, reflectValue reflect.Value, valu...
  type ScanMode (line 116) | type ScanMode
  constant ScanInitialized (line 120) | ScanInitialized         ScanMode = 1 << 0
  constant ScanUpdate (line 121) | ScanUpdate              ScanMode = 1 << 1
  constant ScanOnConflictDoNothing (line 122) | ScanOnConflictDoNothing ScanMode = 1 << 2
  function Scan (line 126) | func Scan(rows Rows, db *DB, mode ScanMode) {

FILE: schema/callbacks_test.go
  type UserWithCallback (line 12) | type UserWithCallback struct
    method BeforeSave (line 14) | func (UserWithCallback) BeforeSave(*gorm.DB) error {
    method AfterCreate (line 18) | func (UserWithCallback) AfterCreate(*gorm.DB) error {
  function TestCallback (line 22) | func TestCallback(t *testing.T) {

FILE: schema/constraint.go
  type CheckConstraint (line 13) | type CheckConstraint struct
    method GetName (line 19) | func (chk *CheckConstraint) GetName() string { return chk.Name }
    method Build (line 21) | func (chk *CheckConstraint) Build() (sql string, vars []interface{}) {
  method ParseCheckConstraints (line 26) | func (schema *Schema) ParseCheckConstraints() map[string]CheckConstraint {
  type UniqueConstraint (line 45) | type UniqueConstraint struct
    method GetName (line 50) | func (uni *UniqueConstraint) GetName() string { return uni.Name }
    method Build (line 52) | func (uni *UniqueConstraint) Build() (sql string, vars []interface{}) {
  method ParseUniqueConstraints (line 57) | func (schema *Schema) ParseUniqueConstraints() map[string]UniqueConstrai...

FILE: schema/constraint_test.go
  type UserCheck (line 12) | type UserCheck struct
  function TestParseCheck (line 18) | func TestParseCheck(t *testing.T) {
  function TestParseUniqueConstraints (line 58) | func TestParseUniqueConstraints(t *testing.T) {

FILE: schema/field.go
  type DataType (line 28) | type DataType
  type TimeType (line 30) | type TimeType
  constant UnixTime (line 35) | UnixTime        TimeType = 1
  constant UnixSecond (line 36) | UnixSecond      TimeType = 2
  constant UnixMillisecond (line 37) | UnixMillisecond TimeType = 3
  constant UnixNanosecond (line 38) | UnixNanosecond  TimeType = 4
  constant Bool (line 43) | Bool   DataType = "bool"
  constant Int (line 44) | Int    DataType = "int"
  constant Uint (line 45) | Uint   DataType = "uint"
  constant Float (line 46) | Float  DataType = "float"
  constant String (line 47) | String DataType = "string"
  constant Time (line 48) | Time   DataType = "time"
  constant Bytes (line 49) | Bytes  DataType = "bytes"
  constant DefaultAutoIncrementIncrement (line 52) | DefaultAutoIncrementIncrement int64 = 1
  type Field (line 55) | type Field struct
    method BindName (line 101) | func (field *Field) BindName() string {
    method setupValuerAndSetter (line 451) | func (field *Field) setupValuerAndSetter(modelType reflect.Type) {
    method setupNewValuePool (line 992) | func (field *Field) setupNewValuePool() {
  method ParseField (line 106) | func (schema *Schema) ParseField(fieldStruct reflect.StructField) *Field {

FILE: schema/field_test.go
  function TestFieldValuerAndSetter (line 16) | func TestFieldValuerAndSetter(t *testing.T) {
  function TestPointerFieldValuerAndSetter (line 92) | func TestPointerFieldValuerAndSetter(t *testing.T) {
  function TestAdvancedDataTypeValuerAndSetter (line 162) | func TestAdvancedDataTypeValuerAndSetter(t *testing.T) {
  type UserWithPermissionControl (line 230) | type UserWithPermissionControl struct
  function TestParseFieldWithPermission (line 242) | func TestParseFieldWithPermission(t *testing.T) {
  type ID (line 266) | type ID
  type INT (line 267) | type INT
  type INT8 (line 268) | type INT8
  type INT16 (line 269) | type INT16
  type INT32 (line 270) | type INT32
  type INT64 (line 271) | type INT64
  type UINT (line 272) | type UINT
  type UINT8 (line 273) | type UINT8
  type UINT16 (line 274) | type UINT16
  type UINT32 (line 275) | type UINT32
  type UINT64 (line 276) | type UINT64
  type FLOAT32 (line 277) | type FLOAT32
  type FLOAT64 (line 278) | type FLOAT64
  type BOOL (line 279) | type BOOL
  type STRING (line 280) | type STRING
  type TIME (line 281) | type TIME
  type BYTES (line 282) | type BYTES
  type TypeAlias (line 284) | type TypeAlias struct
  function TestTypeAliasField (line 305) | func TestTypeAliasField(t *testing.T) {

FILE: schema/index.go
  type Index (line 10) | type Index struct
  type IndexOption (line 20) | type IndexOption struct
  method ParseIndexes (line 30) | func (schema *Schema) ParseIndexes() []*Index {
  method LookIndex (line 80) | func (schema *Schema) LookIndex(name string) *Index {
  function parseFieldIndexes (line 99) | func parseFieldIndexes(field *Field) (indexes []Index, err error) {

FILE: schema/index_test.go
  type UserIndex (line 11) | type UserIndex struct
  type CompIdxLevel1C (line 40) | type CompIdxLevel1C struct
  type CompIdxLevel1B (line 45) | type CompIdxLevel1B struct
  type CompIdxLevel2C (line 49) | type CompIdxLevel2C struct
  type CompIdxLevel2B (line 54) | type CompIdxLevel2B struct
  function TestParseIndex (line 58) | func TestParseIndex(t *testing.T) {
  function TestParseIndexWithUniqueIndexAndUnique (line 174) | func TestParseIndexWithUniqueIndexAndUnique(t *testing.T) {
  function CheckIndices (line 254) | func CheckIndices(t *testing.T, expected, actual []*schema.Index) {

FILE: schema/interfaces.go
  type ConstraintInterface (line 8) | type ConstraintInterface interface
  type GormDataTypeInterface (line 14) | type GormDataTypeInterface interface
  type FieldNewValuePool (line 19) | type FieldNewValuePool interface
  type CreateClausesInterface (line 25) | type CreateClausesInterface interface
  type QueryClausesInterface (line 30) | type QueryClausesInterface interface
  type UpdateClausesInterface (line 35) | type UpdateClausesInterface interface
  type DeleteClausesInterface (line 40) | type DeleteClausesInterface interface

FILE: schema/model_test.go
  type User (line 11) | type User struct
  type mytime (line 30) | type mytime
  type myint (line 31) | type myint
  type AdvancedDataTypeUser (line 35) | type AdvancedDataTypeUser struct
  type BaseModel (line 45) | type BaseModel struct
  type VersionModel (line 54) | type VersionModel struct
  type VersionUser (line 59) | type VersionUser struct

FILE: schema/naming.go
  type Namer (line 16) | type Namer interface
  type Replacer (line 28) | type Replacer interface
  type NamingStrategy (line 35) | type NamingStrategy struct
    method TableName (line 44) | func (ns NamingStrategy) TableName(str string) string {
    method SchemaName (line 52) | func (ns NamingStrategy) SchemaName(table string) string {
    method ColumnName (line 62) | func (ns NamingStrategy) ColumnName(table, column string) string {
    method JoinTableName (line 67) | func (ns NamingStrategy) JoinTableName(str string) string {
    method RelationshipFKName (line 79) | func (ns NamingStrategy) RelationshipFKName(rel Relationship) string {
    method CheckerName (line 84) | func (ns NamingStrategy) CheckerName(table, column string) string {
    method IndexName (line 89) | func (ns NamingStrategy) IndexName(table, column string) string {
    method UniqueName (line 94) | func (ns NamingStrategy) UniqueName(table, column string) string {
    method formatName (line 98) | func (ns NamingStrategy) formatName(prefix, table, name string) string {
    method toDBName (line 131) | func (ns NamingStrategy) toDBName(name string) string {
    method toSchemaName (line 190) | func (ns NamingStrategy) toSchemaName(name string) string {
  function init (line 123) | func init() {

FILE: schema/naming_test.go
  function TestToDBName (line 8) | func TestToDBName(t *testing.T) {
  function TestNamingStrategy (line 58) | func TestNamingStrategy(t *testing.T) {
  type CustomReplacer (line 96) | type CustomReplacer struct
    method Replace (line 100) | func (r CustomReplacer) Replace(name string) string {
  function TestCustomReplacer (line 104) | func TestCustomReplacer(t *testing.T) {
  function TestCustomReplacerWithNoLowerCase (line 148) | func TestCustomReplacerWithNoLowerCase(t *testing.T) {
  function TestFormatNameWithStringLongerThan63Characters (line 192) | func TestFormatNameWithStringLongerThan63Characters(t *testing.T) {
  function TestFormatNameWithStringLongerThan64Characters (line 201) | func TestFormatNameWithStringLongerThan64Characters(t *testing.T) {
  function TestReplaceEmptyTableName (line 210) | func TestReplaceEmptyTableName(t *testing.T) {

FILE: schema/relationship.go
  type RelationshipType (line 18) | type RelationshipType
  constant HasOne (line 21) | HasOne    RelationshipType = "has_one"
  constant HasMany (line 22) | HasMany   RelationshipType = "has_many"
  constant BelongsTo (line 23) | BelongsTo RelationshipType = "belongs_to"
  constant Many2Many (line 24) | Many2Many RelationshipType = "many_to_many"
  constant has (line 25) | has       RelationshipType = "has"
  type Relationships (line 28) | type Relationships struct
  type Relationship (line 40) | type Relationship struct
    method ParseConstraint (line 661) | func (rel *Relationship) ParseConstraint() *Constraint {
    method ToQueryConditions (line 728) | func (rel *Relationship) ToQueryConditions(ctx context.Context, reflec...
  type Polymorphic (line 52) | type Polymorphic struct
  type Reference (line 58) | type Reference struct
  method parseRelation (line 65) | func (schema *Schema) parseRelation(field *Field) *Relationship {
  function hasPolymorphicRelation (line 136) | func hasPolymorphicRelation(tagSettings map[string]string) bool {
  method setRelation (line 147) | func (schema *Schema) setRelation(relation *Relationship) {
  method buildPolymorphicRelation (line 195) | func (schema *Schema) buildPolymorphicRelation(relation *Relationship, f...
  method buildMany2ManyRelation (line 271) | func (schema *Schema) buildMany2ManyRelation(relation *Relationship, fie...
  type guessLevel (line 446) | type guessLevel
  constant guessGuess (line 449) | guessGuess guessLevel = iota
  constant guessBelongs (line 450) | guessBelongs
  constant guessEmbeddedBelongs (line 451) | guessEmbeddedBelongs
  constant guessHas (line 452) | guessHas
  constant guessEmbeddedHas (line 453) | guessEmbeddedHas
  method guessRelation (line 456) | func (schema *Schema) guessRelation(relation *Relationship, field *Field...
  type Constraint (line 625) | type Constraint struct
    method GetName (line 636) | func (constraint *Constraint) GetName() string { return constraint.Name }
    method Build (line 638) | func (constraint *Constraint) Build() (sql string, vars []interface{}) {
  function copyableDataType (line 775) | func copyableDataType(str DataType) bool {

FILE: schema/relationship_test.go
  function checkStructRelation (line 13) | func checkStructRelation(t *testing.T, data interface{}, relations ...Re...
  function TestBelongsToOverrideForeignKey (line 23) | func TestBelongsToOverrideForeignKey(t *testing.T) {
  function TestBelongsToOverrideReferences (line 41) | func TestBelongsToOverrideReferences(t *testing.T) {
  function TestBelongsToWithOnlyReferences (line 60) | func TestBelongsToWithOnlyReferences(t *testing.T) {
  function TestBelongsToWithOnlyReferences2 (line 79) | func TestBelongsToWithOnlyReferences2(t *testing.T) {
  function TestSelfReferentialBelongsTo (line 98) | func TestSelfReferentialBelongsTo(t *testing.T) {
  function TestSelfReferentialBelongsToOverrideReferences (line 112) | func TestSelfReferentialBelongsToOverrideReferences(t *testing.T) {
  function TestBelongsToWithMixin (line 126) | func TestBelongsToWithMixin(t *testing.T) {
  function TestHasOneOverrideForeignKey (line 149) | func TestHasOneOverrideForeignKey(t *testing.T) {
  function TestHasOneOverrideReferences (line 167) | func TestHasOneOverrideReferences(t *testing.T) {
  function TestHasOneOverrideReferences2 (line 186) | func TestHasOneOverrideReferences2(t *testing.T) {
  function TestHasOneWithOnlyReferences (line 204) | func TestHasOneWithOnlyReferences(t *testing.T) {
  function TestHasOneWithOnlyReferences2 (line 223) | func TestHasOneWithOnlyReferences2(t *testing.T) {
  function TestHasManyOverrideForeignKey (line 242) | func TestHasManyOverrideForeignKey(t *testing.T) {
  function TestHasManyOverrideReferences (line 260) | func TestHasManyOverrideReferences(t *testing.T) {
  function TestMany2ManyOverrideForeignKeyAndReferences (line 279) | func TestMany2ManyOverrideForeignKeyAndReferences(t *testing.T) {
  function TestMany2ManyOverrideForeignKey (line 310) | func TestMany2ManyOverrideForeignKey(t *testing.T) {
  function TestMany2ManySharedForeignKey (line 333) | func TestMany2ManySharedForeignKey(t *testing.T) {
  function TestMany2ManyOverrideJoinForeignKey (line 360) | func TestMany2ManyOverrideJoinForeignKey(t *testing.T) {
  function TestBuildReadonlyMany2ManyRelation (line 383) | func TestBuildReadonlyMany2ManyRelation(t *testing.T) {
  function TestMany2ManyWithMultiPrimaryKeys (line 406) | func TestMany2ManyWithMultiPrimaryKeys(t *testing.T) {
  function TestMultipleMany2Many (line 454) | func TestMultipleMany2Many(t *testing.T) {
  function TestSelfReferentialMany2Many (line 485) | func TestSelfReferentialMany2Many(t *testing.T) {
  type CreatedByModel (line 510) | type CreatedByModel struct
  type CreatedUser (line 515) | type CreatedUser struct
  function TestEmbeddedRelation (line 520) | func TestEmbeddedRelation(t *testing.T) {
  function TestEmbeddedHas (line 546) | func TestEmbeddedHas(t *testing.T) {
  function TestPolymorphic (line 605) | func TestPolymorphic(t *testing.T) {
  function TestEmbeddedBelongsTo (line 792) | func TestEmbeddedBelongsTo(t *testing.T) {
  function TestVariableRelation (line 860) | func TestVariableRelation(t *testing.T) {
  function TestSameForeignKey (line 880) | func TestSameForeignKey(t *testing.T) {
  function TestBelongsToSameForeignKey (line 904) | func TestBelongsToSameForeignKey(t *testing.T) {
  function TestHasOneWithSameForeignKey (line 928) | func TestHasOneWithSameForeignKey(t *testing.T) {
  function TestHasManySameForeignKey (line 947) | func TestHasManySameForeignKey(t *testing.T) {
  type Author (line 966) | type Author struct
  type Book (line 970) | type Book struct
    method TableName (line 976) | func (Book) TableName() string {
  function TestParseConstraintNameWithSchemaQualifiedLongTableName (line 980) | func TestParseConstraintNameWithSchemaQualifiedLongTableName(t *testing....
  type InfoRelation (line 1002) | type InfoRelation struct
  type Info1 (line 1009) | type Info1 struct
  type Info2 (line 1016) | type Info2 struct
  function TestDataRace (line 1023) | func TestDataRace(t *testing.T) {

FILE: schema/schema.go
  type callbackType (line 17) | type callbackType
  constant callbackTypeBeforeCreate (line 20) | callbackTypeBeforeCreate callbackType = "BeforeCreate"
  constant callbackTypeBeforeUpdate (line 21) | callbackTypeBeforeUpdate callbackType = "BeforeUpdate"
  constant callbackTypeAfterCreate (line 22) | callbackTypeAfterCreate  callbackType = "AfterCreate"
  constant callbackTypeAfterUpdate (line 23) | callbackTypeAfterUpdate  callbackType = "AfterUpdate"
  constant callbackTypeBeforeSave (line 24) | callbackTypeBeforeSave   callbackType = "BeforeSave"
  constant callbackTypeAfterSave (line 25) | callbackTypeAfterSave    callbackType = "AfterSave"
  constant callbackTypeBeforeDelete (line 26) | callbackTypeBeforeDelete callbackType = "BeforeDelete"
  constant callbackTypeAfterDelete (line 27) | callbackTypeAfterDelete  callbackType = "AfterDelete"
  constant callbackTypeAfterFind (line 28) | callbackTypeAfterFind    callbackType = "AfterFind"
  type Schema (line 34) | type Schema struct
    method String (line 63) | func (schema *Schema) String() string {
    method MakeSlice (line 70) | func (schema *Schema) MakeSlice() reflect.Value {
    method LookUpField (line 78) | func (schema *Schema) LookUpField(name string) *Field {
    method LookUpFieldByBindName (line 106) | func (schema *Schema) LookUpFieldByBindName(bindNames []string, name s...
  type Tabler (line 116) | type Tabler interface
  type TablerWithNamer (line 120) | type TablerWithNamer interface
  function Parse (line 133) | func Parse(dest interface{}, cacheStore *sync.Map, namer Namer) (*Schema...
  function ParseWithSpecialTableName (line 138) | func ParseWithSpecialTableName(dest interface{}, cacheStore *sync.Map, n...
  function getOrParse (line 392) | func getOrParse(dest interface{}, cacheStore *sync.Map, namer Namer) (*S...

FILE: schema/schema_helper_test.go
  function checkSchema (line 14) | func checkSchema(t *testing.T, s *schema.Schema, v *schema.Schema, prima...
  function checkSchemaField (line 39) | func checkSchemaField(t *testing.T, s *schema.Schema, f *schema.Field, f...
  type Relation (line 93) | type Relation struct
  type Polymorphic (line 103) | type Polymorphic struct
  type JoinTable (line 109) | type JoinTable struct
  type Reference (line 115) | type Reference struct
  function checkSchemaRelation (line 124) | func checkSchemaRelation(t *testing.T, s *schema.Schema, relation Relati...
  type EmbeddedRelations (line 204) | type EmbeddedRelations struct
  function checkEmbeddedRelations (line 209) | func checkEmbeddedRelations(t *testing.T, actual map[string]*schema.Rela...
  function checkField (line 235) | func checkField(t *testing.T, s *schema.Schema, value reflect.Value, val...

FILE: schema/schema_test.go
  function TestParseSchema (line 13) | func TestParseSchema(t *testing.T) {
  function TestParseSchemaWithMap (line 22) | func TestParseSchemaWithMap(t *testing.T) {
  function TestParseSchemaWithPointerFields (line 38) | func TestParseSchemaWithPointerFields(t *testing.T) {
  function checkUserSchema (line 47) | func checkUserSchema(t *testing.T, user *schema.Schema) {
  function TestParseSchemaWithAdvancedDataType (line 135) | func TestParseSchemaWithAdvancedDataType(t *testing.T) {
  type CustomizeTable (line 164) | type CustomizeTable struct
    method TableName (line 166) | func (CustomizeTable) TableName() string {
  function TestCustomizeTableName (line 170) | func TestCustomizeTableName(t *testing.T) {
  function TestNestedModel (line 181) | func TestNestedModel(t *testing.T) {
  function TestEmbeddedStruct (line 202) | func TestEmbeddedStruct(t *testing.T) {
  type CustomizedNamingStrategy (line 245) | type CustomizedNamingStrategy struct
    method ColumnName (line 249) | func (ns CustomizedNamingStrategy) ColumnName(table, column string) st...
  function TestEmbeddedStructForCustomizedNamingStrategy (line 270) | func TestEmbeddedStructForCustomizedNamingStrategy(t *testing.T) {
  function TestCompositePrimaryKeyWithAutoIncrement (line 313) | func TestCompositePrimaryKeyWithAutoIncrement(t *testing.T) {

FILE: schema/serializer.go
  function RegisterSerializer (line 21) | func RegisterSerializer(name string, serializer SerializerInterface) {
  function GetSerializer (line 26) | func GetSerializer(name string) (serializer SerializerInterface, ok bool) {
  function init (line 34) | func init() {
  type serializer (line 41) | type serializer struct
    method Scan (line 52) | func (s *serializer) Scan(value interface{}) error {
    method Value (line 58) | func (s serializer) Value() (driver.Value, error) {
  type SerializerInterface (line 63) | type SerializerInterface interface
  type SerializerValuerInterface (line 69) | type SerializerValuerInterface interface
  type JSONSerializer (line 74) | type JSONSerializer struct
    method Scan (line 77) | func (JSONSerializer) Scan(ctx context.Context, field *Field, dst refl...
    method Value (line 104) | func (JSONSerializer) Value(ctx context.Context, field *Field, dst ref...
  type UnixSecondSerializer (line 116) | type UnixSecondSerializer struct
    method Scan (line 119) | func (UnixSecondSerializer) Scan(ctx context.Context, field *Field, ds...
    method Value (line 129) | func (UnixSecondSerializer) Value(ctx context.Context, field *Field, d...
  type GobSerializer (line 161) | type GobSerializer struct
    method Scan (line 164) | func (GobSerializer) Scan(ctx context.Context, field *Field, dst refle...
    method Value (line 185) | func (GobSerializer) Value(ctx context.Context, field *Field, dst refl...

FILE: schema/serializer_test.go
  function TestUnixSecondSerializer_Value (line 11) | func TestUnixSecondSerializer_Value(t *testing.T) {

FILE: schema/utils.go
  function ParseTagSetting (line 16) | func ParseTagSetting(str string, sep string) map[string]string {
  function toColumns (line 45) | func toColumns(val string) (results []string) {
  function removeSettingFromTag (line 54) | func removeSettingFromTag(tag reflect.StructTag, names ...string) reflec...
  function appendSettingFromTag (line 61) | func appendSettingFromTag(tag reflect.StructTag, value string) reflect.S...
  function GetRelationsValues (line 70) | func GetRelationsValues(ctx context.Context, reflectValue reflect.Value,...
  function GetIdentityFieldValuesMap (line 108) | func GetIdentityFieldValuesMap(ctx context.Context, reflectValue reflect...
  function GetIdentityFieldValuesMapFromValues (line 182) | func GetIdentityFieldValuesMapFromValues(ctx context.Context, values []i...
  function ToQueryValues (line 197) | func ToQueryValues(table string, foreignKeys []string, foreignValues [][...
  type embeddedNamer (line 219) | type embeddedNamer struct

FILE: schema/utils_test.go
  function TestRemoveSettingFromTag (line 8) | func TestRemoveSettingFromTag(t *testing.T) {
  function TestParseTagSettingWithDoubleQuoteEscape (line 26) | func TestParseTagSettingWithDoubleQuoteEscape(t *testing.T) {

FILE: soft_delete.go
  type DeletedAt (line 14) | type DeletedAt
    method Scan (line 17) | func (n *DeletedAt) Scan(value interface{}) error {
    method Value (line 22) | func (n DeletedAt) Value() (driver.Value, error) {
    method MarshalJSON (line 29) | func (n DeletedAt) MarshalJSON() ([]byte, error) {
    method UnmarshalJSON (line 36) | func (n *DeletedAt) UnmarshalJSON(b []byte) error {
    method QueryClauses (line 48) | func (DeletedAt) QueryClauses(f *schema.Field) []clause.Interface {
    method UpdateClauses (line 98) | func (DeletedAt) UpdateClauses(f *schema.Field) []clause.Interface {
    method DeleteClauses (line 123) | func (DeletedAt) DeleteClauses(f *schema.Field) []clause.Interface {
  function parseZeroValueTag (line 52) | func parseZeroValueTag(f *schema.Field) sql.NullString {
  type SoftDeleteQueryClause (line 61) | type SoftDeleteQueryClause struct
    method Name (line 66) | func (sd SoftDeleteQueryClause) Name() string {
    method Build (line 70) | func (sd SoftDeleteQueryClause) Build(clause.Builder) {
    method MergeClause (line 73) | func (sd SoftDeleteQueryClause) MergeClause(*clause.Clause) {
    method ModifyStatement (line 76) | func (sd SoftDeleteQueryClause) ModifyStatement(stmt *Statement) {
  type SoftDeleteUpdateClause (line 102) | type SoftDeleteUpdateClause struct
    method Name (line 107) | func (sd SoftDeleteUpdateClause) Name() string {
    method Build (line 111) | func (sd SoftDeleteUpdateClause) Build(clause.Builder) {
    method MergeClause (line 114) | func (sd SoftDeleteUpdateClause) MergeClause(*clause.Clause) {
    method ModifyStatement (line 117) | func (sd SoftDeleteUpdateClause) ModifyStatement(stmt *Statement) {
  type SoftDeleteDeleteClause (line 127) | type SoftDeleteDeleteClause struct
    method Name (line 132) | func (sd SoftDeleteDeleteClause) Name() string {
    method Build (line 136) | func (sd SoftDeleteDeleteClause) Build(clause.Builder) {
    method MergeClause (line 139) | func (sd SoftDeleteDeleteClause) MergeClause(*clause.Clause) {
    method ModifyStatement (line 142) | func (sd SoftDeleteDeleteClause) ModifyStatement(stmt *Statement) {

FILE: statement.go
  type Statement (line 22) | type Statement struct
    method WriteString (line 70) | func (stmt *Statement) WriteString(str string) (int, error) {
    method WriteByte (line 75) | func (stmt *Statement) WriteByte(c byte) error {
    method WriteQuoted (line 80) | func (stmt *Statement) WriteQuoted(value interface{}) {
    method QuoteTo (line 85) | func (stmt *Statement) QuoteTo(writer clause.Writer, field interface{}) {
    method Quote (line 168) | func (stmt *Statement) Quote(field interface{}) string {
    method AddVar (line 175) | func (stmt *Statement) AddVar(writer clause.Writer, vars ...interface{...
    method AddClause (line 272) | func (stmt *Statement) AddClause(v clause.Interface) {
    method AddClauseIfNotExists (line 285) | func (stmt *Statement) AddClauseIfNotExists(v clause.Interface) {
    method BuildCondition (line 292) | func (stmt *Statement) BuildCondition(query interface{}, args ...inter...
    method Build (line 493) | func (stmt *Statement) Build(clauses ...string) {
    method Parse (line 512) | func (stmt *Statement) Parse(value interface{}) (err error) {
    method ParseWithSpecialTableName (line 516) | func (stmt *Statement) ParseWithSpecialTableName(value interface{}, sp...
    method clone (line 529) | func (stmt *Statement) clone() *Statement {
    method SetColumn (line 587) | func (stmt *Statement) SetColumn(name string, value interface{}, fromC...
    method Changed (line 643) | func (stmt *Statement) Changed(fields ...string) bool {
    method SelectAndOmitColumns (line 715) | func (stmt *Statement) SelectAndOmitColumns(requireCreate, requireUpda...
  type join (line 53) | type join struct
  type StatementModifier (line 65) | type StatementModifier interface

FILE: statement_test.go
  function TestWhereCloneCorruption (line 11) | func TestWhereCloneCorruption(t *testing.T) {
  function TestNilCondition (line 38) | func TestNilCondition(t *testing.T) {
  function TestNameMatcher (line 45) | func TestNameMatcher(t *testing.T) {

FILE: tests/association_generics_test.go
  function TestClauseAssociationSetCreateWithOpCreate (line 15) | func TestClauseAssociationSetCreateWithOpCreate(t *testing.T) {
  function TestClauseAssociationSetUpdateWithOpCreate (line 56) | func TestClauseAssociationSetUpdateWithOpCreate(t *testing.T) {
  function TestClauseAssociationSetCreateWithMultipleAssociations (line 112) | func TestClauseAssociationSetCreateWithMultipleAssociations(t *testing.T) {
  function TestClauseAssociationSetUpdateWithMultipleAssociations (line 162) | func TestClauseAssociationSetUpdateWithMultipleAssociations(t *testing.T) {
  function TestClauseAssociationSetUpdateWithOpUnlink (line 219) | func TestClauseAssociationSetUpdateWithOpUnlink(t *testing.T) {
  function TestClauseAssociationSetUpdateWithOpCreateValues (line 281) | func TestClauseAssociationSetUpdateWithOpCreateValues(t *testing.T) {
  function TestClauseAssociationSetCreateWithManyToMany (line 325) | func TestClauseAssociationSetCreateWithManyToMany(t *testing.T) {
  function TestClauseAssociationSetCreateWithBelongsTo (line 371) | func TestClauseAssociationSetCreateWithBelongsTo(t *testing.T) {
  function TestClauseAssociationSetUpdateBelongsToCreateValues (line 406) | func TestClauseAssociationSetUpdateBelongsToCreateValues(t *testing.T) {
  function TestClauseAssociationSetUpdateMixedFieldAndAssociation (line 431) | func TestClauseAssociationSetUpdateMixedFieldAndAssociation(t *testing.T) {
  function TestClauseAssociationSetUpdateHasOneUnlink (line 463) | func TestClauseAssociationSetUpdateHasOneUnlink(t *testing.T) {
  function TestClauseAssociationSetUpdateManyToManyCreateWithSet (line 488) | func TestClauseAssociationSetUpdateManyToManyCreateWithSet(t *testing.T) {
  function TestClauseAssociationSetUpdateManyToManyClear (line 509) | func TestClauseAssociationSetUpdateManyToManyClear(t *testing.T) {
  function TestClauseAssociationSetUpdatePolymorphicTools (line 534) | func TestClauseAssociationSetUpdatePolymorphicTools(t *testing.T) {
  function TestClauseAssociationSetUpdateInvalidAssociation (line 559) | func TestClauseAssociationSetUpdateInvalidAssociation(t *testing.T) {
  function TestClauseAssociationSetUpdateNoOwnerMatch (line 573) | func TestClauseAssociationSetUpdateNoOwnerMatch(t *testing.T) {
  function TestClauseAssociationSetUpdateAndDelete (line 584) | func TestClauseAssociationSetUpdateAndDelete(t *testing.T) {
  function TestClauseAssociationSetUpdateAndDeleteHasOne (line 615) | func TestClauseAssociationSetUpdateAndDeleteHasOne(t *testing.T) {
  function TestAssociationMany2ManyAppendMap_GenericFile (line 644) | func TestAssociationMany2ManyAppendMap_GenericFile(t *testing.T) {
  function TestClauseAssociationSetUpdateAndDeleteBelongsTo (line 668) | func TestClauseAssociationSetUpdateAndDeleteBelongsTo(t *testing.T) {
  function TestClauseAssociationSetUpdateAndDeleteMany2Many (line 717) | func TestClauseAssociationSetUpdateAndDeleteMany2Many(t *testing.T) {
  function TestClauseAssociationSetUpdateAndDeleteManyOwnersHasMany (line 760) | func TestClauseAssociationSetUpdateAndDeleteManyOwnersHasMany(t *testing...
  function TestClauseAssociationSetUpdateAndDeleteManyOwnersBelongsTo (line 803) | func TestClauseAssociationSetUpdateAndDeleteManyOwnersBelongsTo(t *testi...
  function TestClauseAssociationSetUpdateAndDeleteManyOwnersMany2Many (line 869) | func TestClauseAssociationSetUpdateAndDeleteManyOwnersMany2Many(t *testi...
  function TestClauseAssociationSetUpdateHasOneCreateValues (line 913) | func TestClauseAssociationSetUpdateHasOneCreateValues(t *testing.T) {
  function TestClauseAssociationSetUpdateHasManyClear (line 945) | func TestClauseAssociationSetUpdateHasManyClear(t *testing.T) {
  function TestClauseAssociationSetUpdateManyToManyUnlink (line 966) | func TestClauseAssociationSetUpdateManyToManyUnlink(t *testing.T) {
  function TestClauseAssociationSetUpdatePolymorphicCreate (line 999) | func TestClauseAssociationSetUpdatePolymorphicCreate(t *testing.T) {
  function TestClauseAssociationSetUpdateMultipleOwners (line 1021) | func TestClauseAssociationSetUpdateMultipleOwners(t *testing.T) {

FILE: tests/associations_belongs_to_test.go
  function TestBelongsToAssociation (line 10) | func TestBelongsToAssociation(t *testing.T) {
  function TestBelongsToAssociationForSlice (line 146) | func TestBelongsToAssociationForSlice(t *testing.T) {
  function TestBelongsToDefaultValue (line 230) | func TestBelongsToDefaultValue(t *testing.T) {
  function TestBelongsToAssociationUnscoped (line 255) | func TestBelongsToAssociationUnscoped(t *testing.T) {

FILE: tests/associations_has_many_test.go
  function TestHasManyAssociation (line 10) | func TestHasManyAssociation(t *testing.T) {
  function TestSingleTableHasManyAssociation (line 122) | func TestSingleTableHasManyAssociation(t *testing.T) {
  function TestHasManyAssociationForSlice (line 217) | func TestHasManyAssociationForSlice(t *testing.T) {
  function TestSingleTableHasManyAssociationForSlice (line 271) | func TestSingleTableHasManyAssociationForSlice(t *testing.T) {
  function TestPolymorphicHasManyAssociation (line 327) | func TestPolymorphicHasManyAssociation(t *testing.T) {
  function TestPolymorphicHasManyAssociationForSlice (line 422) | func TestPolymorphicHasManyAssociationForSlice(t *testing.T) {
  function TestHasManyAssociationUnscoped (line 485) | func TestHasManyAssociationUnscoped(t *testing.T) {
  function TestHasManyAssociationReplaceWithStructValue (line 558) | func TestHasManyAssociationReplaceWithStructValue(t *testing.T) {

FILE: tests/associations_has_one_test.go
  function TestHasOneAssociation (line 9) | func TestHasOneAssociation(t *testing.T) {
  function TestHasOneAssociationWithSelect (line 86) | func TestHasOneAssociationWithSelect(t *testing.T) {
  function TestHasOneAssociationForSlice (line 100) | func TestHasOneAssociationForSlice(t *testing.T) {
  function TestPolymorphicHasOneAssociation (line 141) | func TestPolymorphicHasOneAssociation(t *testing.T) {
  function TestPolymorphicHasOneAssociationForSlice (line 218) | func TestPolymorphicHasOneAssociationForSlice(t *testing.T) {
  function TestHasOneAssociationReplaceWithNonValidValue (line 259) | func TestHasOneAssociationReplaceWithNonValidValue(t *testing.T) {

FILE: tests/associations_many2many_test.go
  function TestMany2ManyAssociation (line 13) | func TestMany2ManyAssociation(t *testing.T) {
  function TestMany2ManyOmitAssociations (line 100) | func TestMany2ManyOmitAssociations(t *testing.T) {
  function TestMany2ManyAssociationForSlice (line 129) | func TestMany2ManyAssociationForSlice(t *testing.T) {
  function TestSingleTableMany2ManyAssociation (line 199) | func TestSingleTableMany2ManyAssociation(t *testing.T) {
  function TestSingleTableMany2ManyAssociationForSlice (line 280) | func TestSingleTableMany2ManyAssociationForSlice(t *testing.T) {
  function TestDuplicateMany2ManyAssociation (line 334) | func TestDuplicateMany2ManyAssociation(t *testing.T) {
  function TestConcurrentMany2ManyAssociation (line 360) | func TestConcurrentMany2ManyAssociation(t *testing.T) {
  function TestMany2ManyDuplicateBelongsToAssociation (line 397) | func TestMany2ManyDuplicateBelongsToAssociation(t *testing.T) {

FILE: tests/associations_test.go
  function AssertAssociationCount (line 12) | func AssertAssociationCount(t *testing.T, data interface{}, name string,...
  function TestInvalidAssociation (line 31) | func TestInvalidAssociation(t *testing.T) {
  function TestAssociationNotNullClear (line 38) | func TestAssociationNotNullClear(t *testing.T) {
  function TestForeignKeyConstraints (line 73) | func TestForeignKeyConstraints(t *testing.T) {
  function TestForeignKeyConstraintsBelongsTo (line 130) | func TestForeignKeyConstraintsBelongsTo(t *testing.T) {
  function TestFullSaveAssociations (line 186) | func TestFullSaveAssociations(t *testing.T) {
  function TestSaveBelongsCircularReference (line 230) | func TestSaveBelongsCircularReference(t *testing.T) {
  function TestSaveHasManyCircularReference (line 251) | func TestSaveHasManyCircularReference(t *testing.T) {
  function TestAssociationError (line 271) | func TestAssociationError(t *testing.T) {
  type myType (line 295) | type myType
    method QueryClauses (line 301) | func (myType) QueryClauses(f *schema.Field) []clause.Interface {
  type emptyQueryClause (line 296) | type emptyQueryClause struct
    method Name (line 305) | func (sd emptyQueryClause) Name() string {
    method Build (line 309) | func (sd emptyQueryClause) Build(clause.Builder) {
    method MergeClause (line 312) | func (sd emptyQueryClause) MergeClause(*clause.Clause) {
    method ModifyStatement (line 315) | func (sd emptyQueryClause) ModifyStatement(stmt *gorm.Statement) {
  function TestAssociationEmptyQueryClause (line 319) | func TestAssociationEmptyQueryClause(t *testing.T) {
  type AssociationEmptyUser (line 356) | type AssociationEmptyUser struct
  type AssociationEmptyPet (line 362) | type AssociationEmptyPet struct
  function TestAssociationEmptyPrimaryKey (line 367) | func TestAssociationEmptyPrimaryKey(t *testing.T) {
  function TestAssociationMany2ManyAppendMap (line 399) | func TestAssociationMany2ManyAppendMap(t *testing.T) {
  function TestAssociationMany2ManyReplaceMap (line 438) | func TestAssociationMany2ManyReplaceMap(t *testing.T) {

FILE: tests/benchmark_test.go
  function BenchmarkCreate (line 10) | func BenchmarkCreate(b *testing.B) {
  function BenchmarkFind (line 19) | func BenchmarkFind(b *testing.B) {
  function BenchmarkScan (line 28) | func BenchmarkScan(b *testing.B) {
  function BenchmarkScanSlice (line 39) | func BenchmarkScanSlice(b *testing.B) {
  function BenchmarkScanSlicePointer (line 53) | func BenchmarkScanSlicePointer(b *testing.B) {
  function BenchmarkUpdate (line 67) | func BenchmarkUpdate(b *testing.B) {
  function BenchmarkDelete (line 76) | func BenchmarkDelete(b *testing.B) {

FILE: tests/callbacks_test.go
  function assertCallbacks (line 13) | func assertCallbacks(v interface{}, fnames []string) (result bool, msg s...
  function getFuncName (line 26) | func getFuncName(fc interface{}) string {
  function c1 (line 36) | func c1(*gorm.DB) {}
  function c2 (line 37) | func c2(*gorm.DB) {}
  function c3 (line 38) | func c3(*gorm.DB) {}
  function c4 (line 39) | func c4(*gorm.DB) {}
  function c5 (line 40) | func c5(*gorm.DB) {}
  function c6 (line 41) | func c6(*gorm.DB) {}
  function TestCallbacks (line 43) | func TestCallbacks(t *testing.T) {
  function TestPluginCallbacks (line 176) | func TestPluginCallbacks(t *testing.T) {
  function TestCallbacksGet (line 210) | func TestCallbacksGet(t *testing.T) {
  function TestCallbacksRemove (line 225) | func TestCallbacksRemove(t *testing.T) {

FILE: tests/chainable_api_test.go
  type testDialector (line 13) | type testDialector struct
    method Name (line 15) | func (d testDialector) Name() string                                  ...
    method Initialize (line 16) | func (d testDialector) Initialize(*gorm.DB) error                     ...
    method Migrator (line 17) | func (d testDialector) Migrator(db *gorm.DB) gorm.Migrator            ...
    method DataTypeOf (line 18) | func (d testDialector) DataTypeOf(*schema.Field) string               ...
    method DefaultValueOf (line 19) | func (d testDialector) DefaultValueOf(*schema.Field) clause.Expression...
    method BindVarTo (line 20) | func (d testDialector) BindVarTo(writer clause.Writer, stmt *gorm.Stat...
    method QuoteTo (line 24) | func (d testDialector) QuoteTo(writer clause.Writer, s string)        ...
    method Explain (line 25) | func (d testDialector) Explain(sql string, vars ...interface{}) string...
  function newTestDB (line 28) | func newTestDB() *gorm.DB {
  function TestChainableAPI (line 43) | func TestChainableAPI(t *testing.T) {

FILE: tests/connection_test.go
  function TestWithSingleConnection (line 10) | func TestWithSingleConnection(t *testing.T) {
  function getSetSQL (line 38) | func getSetSQL(driverName string) (string, string) {

FILE: tests/connpool_test.go
  type wrapperTx (line 15) | type wrapperTx struct
    method PrepareContext (line 20) | func (c *wrapperTx) PrepareContext(ctx context.Context, query string) ...
    method ExecContext (line 25) | func (c *wrapperTx) ExecContext(ctx context.Context, query string, arg...
    method QueryContext (line 30) | func (c *wrapperTx) QueryContext(ctx context.Context, query string, ar...
    method QueryRowContext (line 35) | func (c *wrapperTx) QueryRowContext(ctx context.Context, query string,...
  type wrapperConnPool (line 40) | type wrapperConnPool struct
    method Ping (line 46) | func (c *wrapperConnPool) Ping() error {
    method BeginTx (line 57) | func (c *wrapperConnPool) BeginTx(ctx context.Context, opts *sql.TxOpt...
    method PrepareContext (line 65) | func (c *wrapperConnPool) PrepareContext(ctx context.Context, query st...
    method ExecContext (line 70) | func (c *wrapperConnPool) ExecContext(ctx context.Context, query strin...
    method QueryContext (line 75) | func (c *wrapperConnPool) QueryContext(ctx context.Context, query stri...
    method QueryRowContext (line 80) | func (c *wrapperConnPool) QueryRowContext(ctx context.Context, query s...
  function TestConnPoolWrapper (line 85) | func TestConnPoolWrapper(t *testing.T) {

FILE: tests/count_test.go
  function TestCountWithGroup (line 13) | func TestCountWithGroup(t *testing.T) {
  function TestCount (line 39) | func TestCount(t *testing.T) {

FILE: tests/create_test.go
  function TestCreate (line 16) | func TestCreate(t *testing.T) {
  function TestCreateInBatches (line 62) | func TestCreateInBatches(t *testing.T) {
  function TestCreateInBatchesWithDefaultSize (line 91) | func TestCreateInBatchesWithDefaultSize(t *testing.T) {
  function TestCreateFromMap (line 120) | func TestCreateFromMap(t *testing.T) {
  function TestCreateWithAssociations (line 159) | func TestCreateWithAssociations(t *testing.T) {
  function TestBulkCreateWithAssociations (line 182) | func TestBulkCreateWithAssociations(t *testing.T) {
  function TestBulkCreatePtrDataWithAssociations (line 213) | func TestBulkCreatePtrDataWithAssociations(t *testing.T) {
  function TestPolymorphicHasOne (line 242) | func TestPolymorphicHasOne(t *testing.T) {
  function TestCreateEmptyStruct (line 353) | func TestCreateEmptyStruct(t *testing.T) {
  function TestCreateEmptySlice (line 368) | func TestCreateEmptySlice(t *testing.T) {
  function TestCreateInvalidSlice (line 380) | func TestCreateInvalidSlice(t *testing.T) {
  function TestCreateWithExistingTimestamp (line 392) | func TestCreateWithExistingTimestamp(t *testing.T) {
  function TestCreateWithNowFuncOverride (line 409) | func TestCreateWithNowFuncOverride(t *testing.T) {
  function TestCreateWithNoGORMPrimaryKey (line 431) | func TestCreateWithNoGORMPrimaryKey(t *testing.T) {
  function TestSelectWithCreate (line 449) | func TestSelectWithCreate(t *testing.T) {
  function TestOmitWithCreate (line 465) | func TestOmitWithCreate(t *testing.T) {
  function TestFirstOrCreateNotExistsTable (line 497) | func TestFirstOrCreateNotExistsTable(t *testing.T) {
  function TestFirstOrCreateWithPrimaryKey (line 504) | func TestFirstOrCreateWithPrimaryKey(t *testing.T) {
  function TestCreateFromSubQuery (line 523) | func TestCreateFromSubQuery(t *testing.T) {
  function TestCreateNilPointer (line 546) | func TestCreateNilPointer(t *testing.T) {
  function TestFirstOrCreateRowsAffected (line 555) | func TestFirstOrCreateRowsAffected(t *testing.T) {
  function TestCreateWithAutoIncrementCompositeKey (line 569) | func TestCreateWithAutoIncrementCompositeKey(t *testing.T) {
  function TestCreateOnConflictWithDefaultNull (line 601) | func TestCreateOnConflictWithDefaultNull(t *testing.T) {
  function TestCreateFromMapWithoutPK (line 637) | func TestCreateFromMapWithoutPK(t *testing.T) {
  function TestCreateFromMapWithTable (line 732) | func TestCreateFromMapWithTable(t *testing.T) {

FILE: tests/customize_field_test.go
  function TestCustomizeColumn (line 11) | func TestCustomizeColumn(t *testing.T) {
  function TestCustomColumnAndIgnoredFieldClash (line 46) | func TestCustomColumnAndIgnoredFieldClash(t *testing.T) {
  function TestCustomizeField (line 61) | func TestCustomizeField(t *testing.T) {

FILE: tests/default_value_test.go
  function TestDefaultValue (line 10) | func TestDefaultValue(t *testing.T) {

FILE: tests/delete_test.go
  function TestDelete (line 12) | func TestDelete(t *testing.T) {
  function TestDeleteWithTable (line 61) | func TestDeleteWithTable(t *testing.T) {
  function TestInlineCondDelete (line 104) | func TestInlineCondDelete(t *testing.T) {
  function TestBlockGlobalDelete (line 122) | func TestBlockGlobalDelete(t *testing.T) {
  function TestDeleteWithAssociations (line 132) | func TestDeleteWithAssociations(t *testing.T) {
  function TestDeleteAssociationsWithUnscoped (line 156) | func TestDeleteAssociationsWithUnscoped(t *testing.T) {
  function TestDeleteSliceWithAssociations (line 180) | func TestDeleteSliceWithAssociations(t *testing.T) {
  function TestSoftDeleteReturning (line 210) | func TestSoftDeleteReturning(t *testing.T) {
  function TestDeleteReturning (line 235) | func TestDeleteReturning(t *testing.T) {

FILE: tests/distinct_test.go
  function TestDistinct (line 11) | func TestDistinct(t *testing.T) {

FILE: tests/embedded_struct_test.go
  function TestEmbeddedStruct (line 15) | func TestEmbeddedStruct(t *testing.T) {
  function TestEmbeddedPointerTypeStruct (line 101) | func TestEmbeddedPointerTypeStruct(t *testing.T) {
  type Content (line 188) | type Content struct
    method Value (line 192) | func (c Content) Value() (driver.Value, error) {
    method Scan (line 198) | func (c *Content) Scan(src interface{}) error {
  function TestEmbeddedScanValuer (line 220) | func TestEmbeddedScanValuer(t *testing.T) {
  function TestEmbeddedRelations (line 238) | func TestEmbeddedRelations(t *testing.T) {
  function TestEmbeddedTagSetting (line 260) | func TestEmbeddedTagSetting(t *testing.T) {

FILE: tests/error_translator_test.go
  function TestDialectorWithErrorTranslatorSupport (line 11) | func TestDialectorWithErrorTranslatorSupport(t *testing.T) {
  function TestSupportedDialectorWithErrDuplicatedKey (line 31) | func TestSupportedDialectorWithErrDuplicatedKey(t *testing.T) {
  function TestSupportedDialectorWithErrForeignKeyViolated (line 64) | func TestSupportedDialectorWithErrForeignKeyViolated(t *testing.T) {

FILE: tests/gaussdb_test.go
  function TestGaussDBReturningIDWhichHasStringType (line 14) | func TestGaussDBReturningIDWhichHasStringType(t *testing.T) {
  function TestGaussDB (line 66) | func TestGaussDB(t *testing.T) {
  function TestGaussDBMany2ManyWithDefaultValueUUID (line 160) | func TestGaussDBMany2ManyWithDefaultValueUUID(t *testing.T) {
  function TestGaussDBOnConstraint (line 186) | func TestGaussDBOnConstraint(t *testing.T) {
  function TestGaussDBAlterColumnDataType (line 237) | func TestGaussDBAlterColumnDataType(t *testing.T) {

FILE: tests/generics_test.go
  function TestGenericsCreate (line 22) | func TestGenericsCreate(t *testing.T) {
  function TestGenericsCreateInBatches (line 104) | func TestGenericsCreateInBatches(t *testing.T) {
  function TestGenericsExecAndUpdate (line 146) | func TestGenericsExecAndUpdate(t *testing.T) {
  function TestGenericsRow (line 192) | func TestGenericsRow(t *testing.T) {
  function TestGenericsDelete (line 272) | func TestGenericsDelete(t *testing.T) {
  function TestGenericsFindInBatches (line 294) | func TestGenericsFindInBatches(t *testing.T) {
  function TestGenericsScopes (line 326) | func TestGenericsScopes(t *testing.T) {
  function TestGenericsJoins (line 362) | func TestGenericsJoins(t *testing.T) {
  function TestGenericsNestedJoins (line 461) | func TestGenericsNestedJoins(t *testing.T) {
  function TestGenericsPreloads (line 537) | func TestGenericsPreloads(t *testing.T) {
  function TestGenericsNestedPreloads (line 658) | func TestGenericsNestedPreloads(t *testing.T) {
  function TestGenericsDistinct (line 709) | func TestGenericsDistinct(t *testing.T) {
  function TestGenericsSetCreate (line 741) | func TestGenericsSetCreate(t *testing.T) {
  function TestGenericsSetUpdate (line 764) | func TestGenericsSetUpdate(t *testing.T) {
  function TestGenericsGroupHaving (line 799) | func TestGenericsGroupHaving(t *testing.T) {
  function TestGenericsSubQuery (line 823) | func TestGenericsSubQuery(t *testing.T) {
  function TestGenericsUpsert (line 855) | func TestGenericsUpsert(t *testing.T) {
  function TestGenericsWithResult (line 892) | func TestGenericsWithResult(t *testing.T) {
  function TestGenericsReuse (line 907) | func TestGenericsReuse(t *testing.T) {
  function TestGenericsWithTransaction (line 946) | func TestGenericsWithTransaction(t *testing.T) {
  function TestGenericsToSQL (line 977) | func TestGenericsToSQL(t *testing.T) {
  function TestGenericsScanUUID (line 989) | func TestGenericsScanUUID(t *testing.T) {
  function TestGenericsCount (line 1011) | func TestGenericsCount(t *testing.T) {
  function TestGenericsUpdate (line 1021) | func TestGenericsUpdate(t *testing.T) {
  function TestGenericsUpdates (line 1031) | func TestGenericsUpdates(t *testing.T) {
  function TestGenericsDeleteAPI (line 1041) | func TestGenericsDeleteAPI(t *testing.T) {
  function TestGenericsAssociation (line 1051) | func TestGenericsAssociation(t *testing.T) {
  function TestGenericsAssociationSlice (line 1101) | func TestGenericsAssociationSlice(t *testing.T) {

FILE: tests/gorm_test.go
  function TestOpen (line 11) | func TestOpen(t *testing.T) {
  function TestReturningWithNullToZeroValues (line 19) | func TestReturningWithNullToZeroValues(t *testing.T) {

FILE: tests/group_by_test.go
  function TestGroupBy (line 9) | func TestGroupBy(t *testing.T) {

FILE: tests/helper_test.go
  type Config (line 16) | type Config struct
  function GetUser (line 29) | func GetUser(name string, config Config) *User {
  function CheckPetUnscoped (line 84) | func CheckPetUnscoped(t *testing.T, pet Pet, expect Pet) {
  function CheckPet (line 88) | func CheckPet(t *testing.T, pet Pet, expect Pet) {
  function doCheckPet (line 92) | func doCheckPet(t *testing.T, pet Pet, expect Pet, unscoped bool) {
  function CheckUserUnscoped (line 112) | func CheckUserUnscoped(t *testing.T, user User, expect User) {
  function CheckUser (line 116) | func CheckUser(t *testing.T, user User, expect User) {
  function doCheckUser (line 120) | func doCheckUser(t *testing.T, user User, expect User, unscoped bool) {
  function tidbSkip (line 270) | func tidbSkip(t *testing.T, reason string) {
  function isTiDB (line 276) | func isTiDB() bool {
  function isMysql (line 280) | func isMysql() bool {
  function isSqlite (line 284) | func isSqlite() bool {
  function db (line 288) | func db(unscoped bool) *gorm.DB {

FILE: tests/hooks_test.go
  type Product (line 15) | type Product struct
    method BeforeCreate (line 31) | func (s *Product) BeforeCreate(tx *gorm.DB) (err error) {
    method BeforeUpdate (line 39) | func (s *Product) BeforeUpdate(tx *gorm.DB) (err error) {
    method BeforeSave (line 47) | func (s *Product) BeforeSave(tx *gorm.DB) (err error) {
    method AfterFind (line 55) | func (s *Product) AfterFind(tx *gorm.DB) (err error) {
    method AfterCreate (line 60) | func (s *Product) AfterCreate(tx *gorm.DB) (err error) {
    method AfterUpdate (line 64) | func (s *Product) AfterUpdate(tx *gorm.DB) (err error) {
    method AfterSave (line 69) | func (s *Product) AfterSave(tx *gorm.DB) (err error) {
    method BeforeDelete (line 77) | func (s *Product) BeforeDelete(tx *gorm.DB) (err error) {
    method AfterDelete (line 85) | func (s *Product) AfterDelete(tx *gorm.DB) (err error) {
    method GetCallTimes (line 93) | func (s *Product) GetCallTimes() []int64 {
  function TestRunCallbacks (line 97) | func TestRunCallbacks(t *testing.T) {
  function TestCallbacksWithErrors (line 149) | func TestCallbacksWithErrors(t *testing.T) {
  type Product2 (line 215) | type Product2 struct
    method BeforeCreate (line 223) | func (s Product2) BeforeCreate(tx *gorm.DB) (err error) {
    method BeforeUpdate (line 238) | func (s *Product2) BeforeUpdate(tx *gorm.DB) (err error) {
  function TestUseDBInHooks (line 243) | func TestUseDBInHooks(t *testing.T) {
  type Product3 (line 300) | type Product3 struct
    method BeforeCreate (line 308) | func (s Product3) BeforeCreate(tx *gorm.DB) (err error) {
    method BeforeUpdate (line 313) | func (s Product3) BeforeUpdate(tx *gorm.DB) (err error) {
  function TestSetColumn (line 325) | func TestSetColumn(t *testing.T) {
  function TestHooksForSlice (line 409) | func TestHooksForSlice(t *testing.T) {
  type Product4 (line 460) | type Product4 struct
  type ProductItem (line 469) | type ProductItem struct
    method BeforeCreate (line 476) | func (pi ProductItem) BeforeCreate(*gorm.DB) error {
    method AfterFind (line 483) | func (pi *ProductItem) AfterFind(*gorm.DB) error {
  function TestFailedToSaveAssociationShouldRollback (line 488) | func TestFailedToSaveAssociationShouldRollback(t *testing.T) {
  type Product5 (line 520) | type Product5 struct
    method BeforeUpdate (line 527) | func (p *Product5) BeforeUpdate(*gorm.DB) error {
  function TestUpdateCallbacks (line 532) | func TestUpdateCallbacks(t *testing.T) {
  type Product6 (line 572) | type Product6 struct
    method BeforeDelete (line 583) | func (p *Product6) BeforeDelete(tx *gorm.DB) error {
  type ProductItem2 (line 578) | type ProductItem2 struct
  function TestPropagateUnscoped (line 590) | func TestPropagateUnscoped(t *testing.T) {

FILE: tests/joins_table_test.go
  type Person (line 11) | type Person struct
  type Address (line 18) | type Address struct
  type PersonAddress (line 23) | type PersonAddress struct
  function TestOverrideJoinTable (line 30) | func TestOverrideJoinTable(t *testing.T) {

FILE: tests/joins_test.go
  function TestJoins (line 14) | func TestJoins(t *testing.T) {
  function TestJoinsForSlice (line 27) | func TestJoinsForSlice(t *testing.T) {
  function TestJoinConds (line 61) | func TestJoinConds(t *testing.T) {
  function TestJoinOn (line 115) | func TestJoinOn(t *testing.T) {
  function TestJoinsWithSelect (line 136) | func TestJoinsWithSelect(t *testing.T) {
  function TestJoinWithOmit (line 163) | func TestJoinWithOmit(t *testing.T) {
  function TestJoinCount (line 179) | func TestJoinCount(t *testing.T) {
  function TestJoinWithSoftDeleted (line 208) | func TestJoinWithSoftDeleted(t *testing.T) {
  function TestInnerJoins (line 237) | func TestInnerJoins(t *testing.T) {
  function TestJoinWithSameColumnName (line 259) | func TestJoinWithSameColumnName(t *testing.T) {
  function TestJoinArgsWithDB (line 290) | func TestJoinArgsWithDB(t *testing.T) {
  function TestNestedJoins (line 333) | func TestNestedJoins(t *testing.T) {
  function TestJoinsPreload_Issue7013 (line 408) | func TestJoinsPreload_Issue7013(t *testing.T) {
  function TestJoinsPreload_Issue7013_RelationEmpty (line 428) | func TestJoinsPreload_Issue7013_RelationEmpty(t *testing.T) {
  function TestJoinsPreload_Issue7013_NoEntries (line 467) | func TestJoinsPreload_Issue7013_NoEntries(t *testing.T) {

FILE: tests/lru_test.go
  function TestLRU_Add_ExistingKey_UpdatesValueAndExpiresAt (line 16) | func TestLRU_Add_ExistingKey_UpdatesValueAndExpiresAt(t *testing.T) {
  function TestLRU_Add_NewKey_AddsEntry (line 26) | func TestLRU_Add_NewKey_AddsEntry(t *testing.T) {
  function TestLRU_Add_ExceedsSize_RemovesOldest (line 35) | func TestLRU_Add_ExceedsSize_RemovesOldest(t *testing.T) {
  function TestLRU_Add_UnlimitedSize_NoEviction (line 46) | func TestLRU_Add_UnlimitedSize_NoEviction(t *testing.T) {
  function TestLRU_Add_Eviction (line 57) | func TestLRU_Add_Eviction(t *testing.T) {
  function BenchmarkLRU_Rand_NoExpire (line 69) | func BenchmarkLRU_Rand_NoExpire(b *testing.B) {
  function BenchmarkLRU_Freq_NoExpire (line 94) | func BenchmarkLRU_Freq_NoExpire(b *testing.B) {
  function BenchmarkLRU_Rand_WithExpire (line 122) | func BenchmarkLRU_Rand_WithExpire(b *testing.B) {
  function BenchmarkLRU_Freq_WithExpire (line 147) | func BenchmarkLRU_Freq_WithExpire(b *testing.B) {
  function TestLRUNoPurge (line 175) | func TestLRUNoPurge(t *testing.T) {
  function TestLRUEdgeCases (line 222) | func TestLRUEdgeCases(t *testing.T) {
  function TestLRU_Values (line 243) | func TestLRU_Values(t *testing.T) {
  function TestLRUWithPurge (line 263) | func TestLRUWithPurge(t *testing.T) {
  function TestLRUWithPurgeEnforcedBySize (line 328) | func TestLRUWithPurgeEnforcedBySize(t *testing.T) {
  function TestLRUConcurrency (line 351) | func TestLRUConcurrency(t *testing.T) {
  function TestLRUInvalidateAndEvict (line 367) | func TestLRUInvalidateAndEvict(t *testing.T) {
  function TestLoadingExpired (line 398) | func TestLoadingExpired(t *testing.T) {
  function TestLRURemoveOldest (line 454) | func TestLRURemoveOldest(t *testing.T) {
  function getRand (line 524) | func getRand(tb testing.TB) int64 {

FILE: tests/main_test.go
  function TestExceptionsWithInvalidSql (line 9) | func TestExceptionsWithInvalidSql(t *testing.T) {
  function TestSetAndGet (line 43) | func TestSetAndGet(t *testing.T) {

FILE: tests/migrate_test.go
  function TestMigrate (line 26) | func TestMigrate(t *testing.T) {
  function TestAutoMigrateInt8PGAndGaussDB (line 86) | func TestAutoMigrateInt8PGAndGaussDB(t *testing.T) {
  function TestAutoMigrateSelfReferential (line 124) | func TestAutoMigrateSelfReferential(t *testing.T) {
  function TestAutoMigrateNullable (line 143) | func TestAutoMigrateNullable(t *testing.T) {
  function TestSmartMigrateColumn (line 185) | func TestSmartMigrateColumn(t *testing.T) {
  function TestSmartMigrateColumnGaussDB (line 272) | func TestSmartMigrateColumnGaussDB(t *testing.T) {
  function TestMigrateWithColumnComment (line 359) | func TestMigrateWithColumnComment(t *testing.T) {
  function TestMigrateWithIndexComment (line 374) | func TestMigrateWithIndexComment(t *testing.T) {
  function TestMigrateWithUniqueIndex (line 393) | func TestMigrateWithUniqueIndex(t *testing.T) {
  function TestMigrateTable (line 423) | func TestMigrateTable(t *testing.T) {
  function TestMigrateWithQuotedIndex (line 456) | func TestMigrateWithQuotedIndex(t *testing.T) {
  function TestMigrateIndexes (line 475) | func TestMigrateIndexes(t *testing.T) {
  function TestTiDBMigrateColumns (line 525) | func TestTiDBMigrateColumns(t *testing.T) {
  function TestMigrateColumns (line 664) | func TestMigrateColumns(t *testing.T) {
  function TestMigrateConstraint (line 804) | func TestMigrateConstraint(t *testing.T) {
  type DynamicUser (line 830) | type DynamicUser struct
  function TestMigrateIndexesWithDynamicTableName (line 838) | func TestMigrateIndexesWithDynamicTableName(t *testing.T) {
  function TestMigrateColumnOrder (line 871) | func TestMigrateColumnOrder(t *testing.T) {
  function TestMigrateSerialColumn (line 940) | func TestMigrateSerialColumn(t *testing.T) {
  function TestMigrateWithSpecialName (line 1002) | func TestMigrateWithSpecialName(t *testing.T) {
  function TestMigrateAutoIncrement (line 1023) | func TestMigrateAutoIncrement(t *testing.T) {
  function TestPrimarykeyID (line 1065) | func TestPrimarykeyID(t *testing.T) {
  function TestPrimarykeyIDGaussDB (line 1100) | func TestPrimarykeyIDGaussDB(t *testing.T) {
  function TestCurrentTimestamp (line 1136) | func TestCurrentTimestamp(t *testing.T) {
  function TestUniqueColumn (line 1163) | func TestUniqueColumn(t *testing.T) {
  function findColumnType (line 1283) | func findColumnType(dest interface{}, columnName string) (
  function TestInvalidCachedPlanSimpleProtocol (line 1301) | func TestInvalidCachedPlanSimpleProtocol(t *testing.T) {
  function TestInvalidCachedPlanSimpleProtocolGaussDB (line 1337) | func TestInvalidCachedPlanSimpleProtocolGaussDB(t *testing.T) {
  function TestDifferentTypeWithoutDeclaredLength (line 1373) | func TestDifferentTypeWithoutDeclaredLength(t *testing.T) {
  function TestMigrateArrayTypeModel (line 1412) | func TestMigrateArrayTypeModel(t *testing.T) {
  type mockMigrator (line 1448) | type mockMigrator struct
    method AlterColumn (line 1452) | func (mm mockMigrator) AlterColumn(dst interface{}, field string) error {
  function TestMigrateDonotAlterColumn (line 1460) | func TestMigrateDonotAlterColumn(t *testing.T) {
  function TestMigrateSameEmbeddedFieldName (line 1492) | func TestMigrateSameEmbeddedFieldName(t *testing.T) {
  function TestMigrateWithDefaultValue (line 1530) | func TestMigrateWithDefaultValue(t *testing.T) {
  function TestMigrateMySQLWithCustomizedTypes (line 1605) | func TestMigrateMySQLWithCustomizedTypes(t *testing.T) {
  function TestMigrateIgnoreRelations (line 1637) | func TestMigrateIgnoreRelations(t *testing.T) {
  function TestMigrateView (line 1701) | func TestMigrateView(t *testing.T) {
  function TestMigrateExistingBoolColumnPGAndGaussDB (line 1735) | func TestMigrateExistingBoolColumnPGAndGaussDB(t *testing.T) {
  function TestTableType (line 1794) | func TestTableType(t *testing.T) {
  function TestMigrateWithUniqueIndexAndUnique (line 1840) | func TestMigrateWithUniqueIndexAndUnique(t *testing.T) {
  function testAutoMigrateDecimal (line 2055) | func testAutoMigrateDecimal(t *testing.T, model1, model2 any) []string {
  function decimalColumnsTest (line 2090) | func decimalColumnsTest[T, T2 any](t *testing.T, expectedSql []string) {
  function TestAutoMigrateDecimal (line 2111) | func TestAutoMigrateDecimal(t *testing.T) {

FILE: tests/multi_primary_keys_test.go
  type Blog (line 12) | type Blog struct
  type Tag (line 22) | type Tag struct
  function compareTags (line 29) | func compareTags(tags []Tag, contents []string) bool {
  function TestManyToManyWithMultiPrimaryKeys (line 39) | func TestManyToManyWithMultiPrimaryKeys(t *testing.T) {
  function TestManyToManyWithCustomizedForeignKeys (line 137) | func TestManyToManyWithCustomizedForeignKeys(t *testing.T) {
  function TestManyToManyWithCustomizedForeignKeys2 (line 265) | func TestManyToManyWithCustomizedForeignKeys2(t *testing.T) {
  function TestCompositePrimaryKeysAssociations (line 422) | func TestCompositePrimaryKeysAssociations(t *testing.T) {

FILE: tests/named_argument_test.go
  function TestNamedArg (line 12) | func TestNamedArg(t *testing.T) {

FILE: tests/named_polymorphic_test.go
  type Hamster (line 9) | type Hamster struct
  function TestNamedPolymorphic (line 16) | func TestNamedPolymorphic(t *testing.T) {

FILE: tests/non_std_test.go
  type Animal (line 8) | type Animal struct
  function TestNonStdPrimaryKeyAndDefaultValues (line 18) | func TestNonStdPrimaryKeyAndDefaultValues(t *testing.T) {

FILE: tests/postgres_test.go
  function TestPostgresReturningIDWhichHasStringType (line 14) | func TestPostgresReturningIDWhichHasStringType(t *testing.T) {
  function TestPostgres (line 64) | func TestPostgres(t *testing.T) {
  type Post (line 156) | type Post struct
  type Category (line 162) | type Category struct
  function TestMany2ManyWithDefaultValueUUID (line 168) | func TestMany2ManyWithDefaultValueUUID(t *testing.T) {
  function TestPostgresOnConstraint (line 193) | func TestPostgresOnConstraint(t *testing.T) {
  type CompanyNew (line 243) | type CompanyNew struct
  function TestAlterColumnDataType (line 248) | func TestAlterColumnDataType(t *testing.T) {

FILE: tests/preload_suits_test.go
  function toJSONString (line 14) | func toJSONString(v interface{}) []byte {
  function TestNestedPreload1 (line 19) | func TestNestedPreload1(t *testing.T) {
  function TestNestedPreload2 (line 61) | func TestNestedPreload2(t *testing.T) {
  function TestNestedPreload3 (line 113) | func TestNestedPreload3(t *testing.T) {
  function TestNestedPreload4 (line 156) | func TestNestedPreload4(t *testing.T) {
  function TestNestedPreload5 (line 202) | func TestNestedPreload5(t *testing.T) {
  function TestNestedPreload6 (line 245) | func TestNestedPreload6(t *testing.T) {
  function TestNestedPreload7 (line 317) | func TestNestedPreload7(t *testing.T) {
  function TestNestedPreload8 (line 371) | func TestNestedPreload8(t *testing.T) {
  function TestNestedPreload9 (line 428) | func TestNestedPreload9(t *testing.T) {
  type LevelA1 (line 522) | type LevelA1 struct
  type LevelA2 (line 527) | type LevelA2 struct
  type LevelA3 (line 533) | type LevelA3 struct
  function TestNestedPreload10 (line 542) | func TestNestedPreload10(t *testing.T) {
  type LevelB1 (line 584) | type LevelB1 struct
  type LevelB2 (line 590) | type LevelB2 struct
  type LevelB3 (line 595) | type LevelB3 struct
  function TestNestedPreload11 (line 603) | func TestNestedPreload11(t *testing.T) {
  type LevelC1 (line 635) | type LevelC1 struct
  type LevelC2 (line 641) | type LevelC2 struct
  type LevelC3 (line 647) | type LevelC3 struct
  function TestNestedPreload12 (line 654) | func TestNestedPreload12(t *testing.T) {
  function TestManyToManyPreloadWithMultiPrimaryKeys (line 694) | func TestManyToManyPreloadWithMultiPrimaryKeys(t *testing.T) {
  function TestManyToManyPreloadForNestedPointer (line 788) | func TestManyToManyPreloadForNestedPointer(t *testing.T) {
  function TestNestedManyToManyPreload (line 889) | func TestNestedManyToManyPreload(t *testing.T) {
  function TestNestedManyToManyPreload2 (line 950) | func TestNestedManyToManyPreload2(t *testing.T) {
  function TestNestedManyToManyPreload3 (line 1005) | func TestNestedManyToManyPreload3(t *testing.T) {
  function TestNestedManyToManyPreload3ForStruct (line 1077) | func TestNestedManyToManyPreload3ForStruct(t *testing.T) {
  function TestNestedManyToManyPreload4 (line 1150) | func TestNestedManyToManyPreload4(t *testing.T) {
  function TestManyToManyPreloadForPointer (line 1204) | func TestManyToManyPreloadForPointer(t *testing.T) {
  function TestNilPointerSlice (line 1286) | func TestNilPointerSlice(t *testing.T) {
  function TestNilPointerSlice2 (line 1350) | func TestNilPointerSlice2(t *testing.T) {
  function TestPrefixedPreloadDuplication (line 1393) | func TestPrefixedPreloadDuplication(t *testing.T) {
  function TestPreloadManyToManyCallbacks (line 1478) | func TestPreloadManyToManyCallbacks(t *testing.T) {

FILE: tests/preload_test.go
  function TestPreloadWithAssociations (line 18) | func TestPreloadWithAssociations(t *testing.T) {
  function TestNestedPreload (line 55) | func TestNestedPreload(t *testing.T) {
  function TestNestedPreloadForSlice (line 79) | func TestNestedPreloadForSlice(t *testing.T) {
  function TestPreloadWithConds (line 109) | func TestPreloadWithConds(t *testing.T) {
  function TestNestedPreloadWithConds (line 167) | func TestNestedPreloadWithConds(t *testing.T) {
  function TestPreloadEmptyData (line 217) | func TestPreloadEmptyData(t *testing.T) {
  function TestPreloadGoroutine (line 239) | func TestPreloadGoroutine(t *testing.T) {
  function TestPreloadWithDiffModel (line 257) | func TestPreloadWithDiffModel(t *testing.T) {
  function TestNestedPreloadWithUnscoped (line 275) | func TestNestedPreloadWithUnscoped(t *testing.T) {
  function TestNestedPreloadWithNestedJoin (line 312) | func TestNestedPreloadWithNestedJoin(t *testing.T) {
  function TestMergeNestedPreloadWithNestedJoin (line 389) | func TestMergeNestedPreloadWithNestedJoin(t *testing.T) {
  function TestNestedPreloadWithPointerJoin (line 443) | func TestNestedPreloadWithPointerJoin(t *testing.T) {
  function TestEmbedPreload (line 495) | func TestEmbedPreload(t *testing.T) {

FILE: tests/prepared_stmt_test.go
  function TestPreparedStmt (line 14) | func TestPreparedStmt(t *testing.T) {
  function TestPreparedStmtFromTransaction (line 56) | func TestPreparedStmtFromTransaction(t *testing.T) {
  function TestPreparedStmtLruFromTransaction (line 94) | func TestPreparedStmtLruFromTransaction(t *testing.T) {
  function TestPreparedStmtDeadlock (line 153) | func TestPreparedStmtDeadlock(t *testing.T) {
  function TestPreparedStmtInTransaction (line 188) | func TestPreparedStmtInTransaction(t *testing.T) {
  function TestPreparedStmtClose (line 204) | func TestPreparedStmtClose(t *testing.T) {
  function isUsingClosedConnError (line 230) | func isUsingClosedConnError(err error) bool {
  function TestPreparedStmtConcurrentClose (line 237) | func TestPreparedStmtConcurrentClose(t *testing.T) {

FILE: tests/query_test.go
  function TestFind (line 20) | func TestFind(t *testing.T) {
  function TestQueryWithAssociation (line 250) | func TestQueryWithAssociation(t *testing.T) {
  function TestFindInBatches (line 268) | func TestFindInBatches(t *testing.T) {
  function TestFindInBatchesWithOffsetLimit (line 320) | func TestFindInBatchesWithOffsetLimit(t *testing.T) {
  function TestFindInBatchesWithError (line 382) | func TestFindInBatchesWithError(t *testing.T) {
  function TestFillSmallerStruct (line 421) | func TestFillSmallerStruct(t *testing.T) {
  function TestFillSmallerStructWithAllFields (line 477) | func TestFillSmallerStructWithAllFields(t *testing.T) {
  function TestNot (line 510) | func TestNot(t *testing.T) {
  function TestNotWithAllFields (line 569) | func TestNotWithAllFields(t *testing.T) {
  function TestOr (line 616) | func TestOr(t *testing.T) {
  function TestOrWithAllFields (line 666) | func TestOrWithAllFields(t *testing.T) {
  type Int64 (line 687) | type Int64
    method Value (line 689) | func (v Int64) Value() (driver.Value, error) {
    method Scan (line 693) | func (f *Int64) Scan(v interface{}) error {
  function TestPluck (line 699) | func TestPluck(t *testing.T) {
  function TestSelect (line 777) | func TestSelect(t *testing.T) {
  function TestOmit (line 839) | func TestOmit(t *testing.T) {
  function TestOmitWithAllFields (line 854) | func TestOmitWithAllFields(t *testing.T) {
  function TestMapColumns (line 878) | func TestMapColumns(t *testing.T) {
  function TestPluckWithSelect (line 900) | func TestPluckWithSelect(t *testing.T) {
  function TestSelectWithVariables (line 919) | func TestSelectWithVariables(t *testing.T) {
  function TestSelectWithArrayInput (line 934) | func TestSelectWithArrayInput(t *testing.T) {
  function TestCustomizedTypePrimaryKey (line 945) | func TestCustomizedTypePrimaryKey(t *testing.T) {
  function TestStringPrimaryKeyForNumericValueStartingWithZero (line 979) | func TestStringPrimaryKeyForNumericValueStartingWithZero(t *testing.T) {
  function TestSearchWithEmptyChain (line 999) | func TestSearchWithEmptyChain(t *testing.T) {
  function TestOrder (line 1019) | func TestOrder(t *testing.T) {
  function TestOrderWithAllFields (line 1052) | func TestOrderWithAllFields(t *testing.T) {
  function TestLimit (line 1077) | func TestLimit(t *testing.T) {
  function TestOffset (line 1097) | func TestOffset(t *testing.T) {
  function TestSearchWithMap (line 1116) | func TestSearchWithMap(t *testing.T) {
  function TestSearchWithStruct (line 1163) | func TestSearchWithStruct(t *testing.T) {
  function TestSubQuery (line 1187) | func TestSubQuery(t *testing.T) {
  function TestSubQueryWithRaw (line 1213) | func TestSubQueryWithRaw(t *testing.T) {
  function TestSubQueryWithHaving (line 1262) | func TestSubQueryWithHaving(t *testing.T) {
  function TestScanNullValue (line 1280) | func TestScanNullValue(t *testing.T) {
  function TestQueryWithTableAndConditions (line 1312) | func TestQueryWithTableAndConditions(t *testing.T) {
  function TestQueryWithTableAndConditionsAndAllFields (line 1320) | func TestQueryWithTableAndConditionsAndAllFields(t *testing.T) {
  type DoubleInt64 (line 1330) | type DoubleInt64 struct
    method Scan (line 1334) | func (t *DoubleInt64) Scan(val interface{}) error {
  function TestQueryScannerWithSingleColumn (line 1345) | func TestQueryScannerWithSingleColumn(t *testing.T) {
  function TestQueryResetNullValue (line 1366) | func TestQueryResetNullValue(t *testing.T) {
  function TestQueryError (line 1443) | func TestQueryError(t *testing.T) {
  function TestQueryScanToArray (line 1457) | func TestQueryScanToArray(t *testing.T) {

FILE: tests/scan_test.go
  type PersonAddressInfo (line 14) | type PersonAddressInfo struct
  function TestScan (line 19) | func TestScan(t *testing.T) {
  function TestScanRows (line 122) | func TestScanRows(t *testing.T) {
  function TestScanRowsNullValuesScanToFieldDefault (line 166) | func TestScanRowsNullValuesScanToFieldDefault(t *testing.T) {
  function TestScanToEmbedded (line 264) | func TestScanToEmbedded(t *testing.T) {

FILE: tests/scanner_valuer_test.go
  function TestScannerValuer (line 21) | func TestScannerValuer(t *testing.T) {
  function TestScannerValuerWithFirstOrCreate (line 68) | func TestScannerValuerWithFirstOrCreate(t *testing.T) {
  function TestInvalidValuer (line 111) | func TestInvalidValuer(t *testing.T) {
  type ScannerValuerStruct (line 143) | type ScannerValuerStruct struct
  type EncryptedData (line 165) | type EncryptedData
    method Scan (line 167) | func (data *EncryptedData) Scan(value interface{}) error {
    method Value (line 183) | func (data EncryptedData) Value() (driver.Value, error) {
  type Num (line 193) | type Num
    method Scan (line 195) | func (i *Num) Scan(src interface{}) error {
  type StringsSlice (line 208) | type StringsSlice
    method Value (line 210) | func (l StringsSlice) Value() (driver.Value, error) {
    method Scan (line 215) | func (l *StringsSlice) Scan(input interface{}) error {
  type ExampleStruct (line 226) | type ExampleStruct struct
    method GormDataType (line 231) | func (ExampleStruct) GormDataType() string {
    method Value (line 235) | func (s ExampleStruct) Value() (driver.Value, error) {
    method Scan (line 244) | func (s *ExampleStruct) Scan(src interface{}) error {
  type StructsSlice (line 255) | type StructsSlice
    method Value (line 257) | func (l StructsSlice) Value() (driver.Value, error) {
    method Scan (line 262) | func (l *StructsSlice) Scan(input interface{}) error {
  type Role (line 273) | type Role struct
    method Scan (line 277) | func (role *Role) Scan(value interface{}) error {
    method Value (line 286) | func (role Role) Value() (driver.Value, error) {
    method IsAdmin (line 290) | func (role Role) IsAdmin() bool {
  type EmptyTime (line 294) | type EmptyTime struct
    method Scan (line 298) | func (t *EmptyTime) Scan(v interface{}) error {
    method Value (line 305) | func (t EmptyTime) Value() (driver.Value, error) {
  type NullString (line 309) | type NullString struct
  type Point (line 313) | type Point struct
    method GormDataType (line 317) | func (point Point) GormDataType() string {
    method GormValue (line 321) | func (point Point) GormValue(ctx context.Context, db *gorm.DB) clause....
  function TestGORMValuer (line 328) | func TestGORMValuer(t *testing.T) {

FILE: tests/scopes_test.go
  function NameIn1And2 (line 11) | func NameIn1And2(d *gorm.DB) *gorm.DB {
  function NameIn2And3 (line 15) | func NameIn2And3(d *gorm.DB) *gorm.DB {
  function NameIn (line 19) | func NameIn(names []string) func(d *gorm.DB) *gorm.DB {
  function TestScopes (line 25) | func TestScopes(t *testing.T) {
  function TestComplexScopes (line 76) | func TestComplexScopes(t *testing.T) {

FILE: tests/serializer_test.go
  type SerializerStruct (line 17) | type SerializerStruct struct
  type SerializerPostgresStruct (line 31) | type SerializerPostgresStruct struct
    method TableName (line 45) | func (*SerializerPostgresStruct) TableName() string { return "serializ...
  function adaptorSerializerModel (line 47) | func adaptorSerializerModel(s *SerializerStruct) interface{} {
  type Roles (line 55) | type Roles
  type Job (line 57) | type Job struct
  type EncryptedString (line 64) | type EncryptedString
    method Scan (line 66) | func (es *EncryptedString) Scan(ctx context.Context, field *schema.Fie...
    method Value (line 78) | func (es EncryptedString) Value(ctx context.Context, field *schema.Fie...
  type CustomSerializer (line 82) | type CustomSerializer struct
    method Scan (line 90) | func (c *CustomSerializer) Scan(ctx context.Context, field *schema.Fie...
    method Value (line 102) | func (c *CustomSerializer) Value(ctx context.Context, field *schema.Fi...
  function NewCustomSerializer (line 86) | func NewCustomSerializer(prefix string) *CustomSerializer {
  function TestSerializer (line 106) | func TestSerializer(t *testing.T) {
  function TestSerializerZeroValue (line 152) | func TestSerializerZeroValue(t *testing.T) {
  function TestSerializerAssignFirstOrCreate (line 181) | func TestSerializerAssignFirstOrCreate(t *testing.T) {
  function TestSerializerWithAnyType (line 232) | func TestSerializerWithAnyType(t *testing.T) {

FILE: tests/soft_delete_test.go
  function TestSoftDelete (line 15) | func TestSoftDelete(t *testing.T) {
  function TestDeletedAtUnMarshal (line 82) | func TestDeletedAtUnMarshal(t *testing.T) {
  function TestDeletedAtOneOr (line 93) | func TestDeletedAtOneOr(t *testing.T) {
  function TestSoftDeleteZeroValue (line 103) | func TestSoftDeleteZeroValue(t *testing.T) {

FILE: tests/sql_builder_test.go
  function TestRow (line 14) | func TestRow(t *testing.T) {
  function TestRows (line 48) | func TestRows(t *testing.T) {
  function TestRaw (line 72) | func TestRaw(t *testing.T) {
  function TestRowsWithGroup (line 113) | func TestRowsWithGroup(t *testing.T) {
  function TestQueryRaw (line 142) | func TestQueryRaw(t *testing.T) {
  function TestDryRun (line 155) | func TestDryRun(t *testing.T) {
  type ageInt (line 171) | type ageInt
    method String (line 173) | func (ageInt) String() string {
  type ageBool (line 177) | type ageBool
    method String (line 179) | func (ageBool) String() string {
  type ageUint64 (line 183) | type ageUint64
    method String (line 185) | func (ageUint64) String() string {
  type ageFloat (line 189) | type ageFloat
    method String (line 191) | func (ageFloat) String() string {
  function TestExplainSQL (line 195) | func TestExplainSQL(t *testing.T) {
  function TestGroupConditions (line 224) | func TestGroupConditions(t *testing.T) {
  function TestCombineStringConditions (line 263) | func TestCombineStringConditions(t *testing.T) {
  function TestFromWithJoins (line 316) | func TestFromWithJoins(t *testing.T) {
  function TestToSQL (line 360) | func TestToSQL(t *testing.T) {
  function assertEqualSQL (line 459) | func assertEqualSQL(t *testing.T, expected string, actually string) {
  function replaceQuoteInSQL (line 484) | func replaceQuoteInSQL(sql string) string {

FILE: tests/submodel_test.go
  type Man (line 9) | type Man struct
    method BeforeUpdate (line 17) | func (m *Man) BeforeUpdate(tx *gorm.DB) (err error) {
  function TestSubModel (line 24) | func TestSubModel(t *testing.T) {

FILE: tests/table_test.go
  type UserWithTable (line 16) | type UserWithTable struct
    method TableName (line 21) | func (UserWithTable) TableName() string {
  function TestTable (line 25) | func TestTable(t *testing.T) {
  function TestTableWithAllFields (line 97) | func TestTableWithAllFields(t *testing.T) {
  type UserWithTableNamer (line 154) | type UserWithTableNamer struct
    method TableName (line 159) | func (UserWithTableNamer) TableName(namer schema.Namer) string {
  function TestTableWithNamer (line 163) | func TestTableWithNamer(t *testing.T) {
  function TestPostgresTableWithIdentifierLength (line 179) | func TestPostgresTableWithIdentifierLength(t *testing.T) {
  function TestGaussDBTableWithIdentifierLength (line 255) | func TestGaussDBTableWithIdentifierLength(t *testing.T) {
  type mockUniqueNamingStrategy (line 331) | type mockUniqueNamingStrategy struct
    method UniqueName (line 336) | func (a mockUniqueNamingStrategy) UniqueName(table, column string) str...

FILE: tests/tests_test.go
  function init (line 30) | func init() {
  function OpenTestConnection (line 52) | func OpenTestConnection(cfg *gorm.Config) (db *gorm.DB, err error) {
  function RunMigrations (line 120) | func RunMigrations() {

FILE: tests/tracer_test.go
  type Tracer (line 10) | type Tracer struct
    method LogMode (line 15) | func (S Tracer) LogMode(level logger.LogLevel) logger.Interface {
    method Info (line 19) | func (S Tracer) Info(ctx context.Context, s string, i ...interface{}) {
    method Warn (line 23) | func (S Tracer) Warn(ctx context.Context, s string, i ...interface{}) {
    method Error (line 27) | func (S Tracer) Error(ctx context.Context, s string, i ...interface{}) {
    method Trace (line 31) | func (S Tracer) Trace(ctx context.Context, begin time.Time, fc func() ...

FILE: tests/transaction_test.go
  function TestTransaction (line 13) | func TestTransaction(t *testing.T) {
  function TestCancelTransaction (line 76) | func TestCancelTransaction(t *testing.T) {
  function TestTransactionWithBlock (line 95) | func TestTransactionWithBlock(t *testing.T) {
  function TestTransactionRaiseErrorOnRollbackAfterCommit (line 165) | func TestTransactionRaiseErrorOnRollbackAfterCommit(t *testing.T) {
  function TestTransactionWithSavePoint (line 181) | func TestTransactionWithSavePoint(t *testing.T) {
  function TestNestedTransactionWithBlock (line 238) | func TestNestedTransactionWithBlock(t *testing.T) {
  function TestDeeplyNestedTransactionWithBlockAndWrappedCallback (line 301) | func TestDeeplyNestedTransactionWithBlockAndWrappedCallback(t *testing.T) {
  function TestDisabledNestedTransaction (line 369) | func TestDisabledNestedTransaction(t *testing.T) {
  function TestTransactionOnClosedConn (line 432) | func TestTransactionOnClosedConn(t *testing.T) {
  function TestTransactionWithHooks (line 453) | func TestTransactionWithHooks(t *testing.T) {
  function TestTransactionWithDefaultTimeout (line 481) | func TestTransactionWithDefaultTimeout(t *testing.T) {

FILE: tests/update_belongs_to_test.go
  function TestUpdateBelongsTo (line 10) | func TestUpdateBelongsTo(t *testing.T) {

FILE: tests/update_has_many_test.go
  function TestUpdateHasManyAssociations (line 10) | func TestUpdateHasManyAssociations(t *testing.T) {

FILE: tests/update_has_one_test.go
  function TestUpdateHasOne (line 12) | func TestUpdateHasOne(t *testing.T) {

FILE: tests/update_many2many_test.go
  function TestUpdateMany2ManyAssociations (line 10) | func TestUpdateMany2ManyAssociations(t *testing.T) {

FILE: tests/update_test.go
  function TestUpdate (line 17) | func TestUpdate(t *testing.T) {
  function TestUpdates (line 135) | func TestUpdates(t *testing.T) {
  function TestUpdateColumn (line 188) | func TestUpdateColumn(t *testing.T) {
  function TestBlockGlobalUpdate (line 244) | func TestBlockGlobalUpdate(t *testing.T) {
  function TestSelectWithUpdate (line 254) | func TestSelectWithUpdate(t *testing.T) {
  function TestSelectWithUpdateWithMap (line 318) | func TestSelectWithUpdateWithMap(t *testing.T) {
  function TestWithUpdateWithInvalidMap (line 366) | func TestWithUpdateWithInvalidMap(t *testing.T) {
  function TestOmitWithUpdate (line 375) | func TestOmitWithUpdate(t *testing.T) {
  function TestOmitWithUpdateWithMap (line 425) | func TestOmitWithUpdateWithMap(t *testing.T) {
  function TestSelectWithUpdateColumn (line 477) | func TestSelectWithUpdateColumn(t *testing.T) {
  function TestOmitWithUpdateColumn (line 502) | func TestOmitWithUpdateColumn(t *testing.T) {
  function TestUpdateColumnsSkipsAssociations (line 520) | func TestUpdateColumnsSkipsAssociations(t *testing.T) {
  function TestUpdatesWithBlankValues (line 547) | func TestUpdatesWithBlankValues(t *testing.T) {
  function TestUpdatesTableWithIgnoredValues (line 563) | func TestUpdatesTableWithIgnoredValues(t *testing.T) {
  function TestUpdateFromSubQuery (line 589) | func TestUpdateFromSubQuery(t *testing.T) {
  function TestIdempotentSave (line 617) | func TestIdempotentSave(t *testing.T) {
  function TestSave (line 636) | func TestSave(t *testing.T) {
  function TestSaveWithPrimaryValue (line 726) | func TestSaveWithPrimaryValue(t *testing.T) {
  function TestUpdateReturning (line 769) | func TestUpdateReturning(t *testing.T) {
  function TestUpdateWithDiffSchema (line 800) | func TestUpdateWithDiffSchema(t *testing.T) {
  type TokenOwner (line 813) | type TokenOwner struct
    method BeforeSave (line 819) | func (t *TokenOwner) BeforeSave(tx *gorm.DB) error {
  type Token (line 824) | type Token struct
    method BeforeSave (line 829) | func (t *Token) BeforeSave(tx *gorm.DB) error {
  function TestSaveWithHooks (line 834) | func TestSaveWithHooks(t *testing.T) {
  function TestUpdateFrom (line 887) | func TestUpdateFrom(t *testing.T) {

FILE: tests/upsert_test.go
  function TestUpsert (line 13) | func TestUpsert(t *testing.T) {
  function TestUpsertSlice (line 91) | func TestUpsertSlice(t *testing.T) {
  function TestUpsertSliceWithReturning (line 138) | func TestUpsertSliceWithReturning(t *testing.T) {
  function TestUpsertWithSave (line 185) | func TestUpsertWithSave(t *testing.T) {
  function TestFindOrInitialize (line 247) | func TestFindOrInitialize(t *testing.T) {
  function TestFindOrCreate (line 294) | func TestFindOrCreate(t *testing.T) {
  function TestUpdateWithMissWhere (line 360) | func TestUpdateWithMissWhere(t *testing.T) {

FILE: utils/tests/dummy_dialecter.go
  type DummyDialector (line 11) | type DummyDialector struct
    method Name (line 15) | func (DummyDialector) Name() string {
    method Initialize (line 19) | func (DummyDialector) Initialize(db *gorm.DB) error {
    method DefaultValueOf (line 30) | func (DummyDialector) DefaultValueOf(field *schema.Field) clause.Expre...
    method Migrator (line 34) | func (DummyDialector) Migrator(*gorm.DB) gorm.Migrator {
    method BindVarTo (line 38) | func (DummyDialector) BindVarTo(writer clause.Writer, stmt *gorm.State...
    method QuoteTo (line 42) | func (DummyDialector) QuoteTo(writer clause.Writer, str string) {
    method Explain (line 90) | func (DummyDialector) Explain(sql string, vars ...interface{}) string {
    method DataTypeOf (line 94) | func (DummyDialector) DataTypeOf(*schema.Field) string {
    method Translate (line 98) | func (d DummyDialector) Translate(err error) error {

FILE: utils/tests/models.go
  type User (line 15) | type User struct
  type Account (line 35) | type Account struct
  type Pet (line 41) | type Pet struct
  type Toy (line 48) | type Toy struct
  type Tools (line 55) | type Tools struct
  type Company (line 62) | type Company struct
  type Language (line 67) | type Language struct
  type Coupon (line 72) | type Coupon struct
  type CouponProduct (line 79) | type CouponProduct struct
  type Order (line 85) | type Order struct
  type Parent (line 92) | type Parent struct
  type Child (line 99) | type Child struct

FILE: utils/tests/utils.go
  function AssertObjEqual (line 14) | func AssertObjEqual(t *testing.T, r, e interface{}, names ...string) {
  function AssertEqual (line 30) | func AssertEqual(t *testing.T, got, expect interface{}) {
  function Now (line 125) | func Now() *time.Time {

FILE: utils/utils.go
  function init (line 16) | func init() {
  function sourceDir (line 22) | func sourceDir(file string) string {
  function CallerFrame (line 38) | func CallerFrame() runtime.Frame {
  function FileWithLineNum (line 56) | func FileWithLineNum() string {
  function IsInvalidDBNameChar (line 65) | func IsInvalidDBNameChar(c rune) bool {
  function CheckTruth (line 70) | func CheckTruth(vals ...string) bool {
  function ToStringKey (line 79) | func ToStringKey(values ...interface{}) string {
  function Contains (line 106) | func Contains(elems []string, elem string) bool {
  function AssertEqual (line 115) | func AssertEqual(x, y interface{}) bool {
  function ToString (line 139) | func ToString(value interface{}) string {
  constant nestedRelationSplit (line 167) | nestedRelationSplit = "__"
  function NestedRelationName (line 170) | func NestedRelationName(prefix, name string) string {
  function SplitNestedRelationName (line 175) | func SplitNestedRelationName(name string) []string {
  function JoinNestedRelationNames (line 180) | func JoinNestedRelationNames(relationNames []string) string {
  function RTrimSlice (line 185) | func RTrimSlice[T any](v []T, trimLen int) []T {

FILE: utils/utils_test.go
  function TestIsInvalidDBNameChar (line 13) | func TestIsInvalidDBNameChar(t *testing.T) {
  function TestCheckTruth (line 21) | func TestCheckTruth(t *testing.T) {
  function TestToStringKey (line 44) | func TestToStringKey(t *testing.T) {
  function TestContains (line 63) | func TestContains(t *testing.T) {
  type ModifyAt (line 82) | type ModifyAt
    method Value (line 85) | func (n ModifyAt) Value() (driver.Value, error) {
  function TestAssertEqual (line 92) | func TestAssertEqual(t *testing.T) {
  function TestToString (line 114) | func TestToString(t *testing.T) {
  function TestRTrimSlice (line 142) | func TestRTrimSlice(t *testing.T) {

FILE: utils/utils_unix_test.go
  function TestSourceDir (line 10) | func TestSourceDir(t *testing.T) {

FILE: utils/utils_windows_test.go
  function TestSourceDir (line 7) | func TestSourceDir(t *testing.T) {
Condensed preview — 184 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,405K chars).
[
  {
    "path": ".github/FUNDING.yml",
    "chars": 102,
    "preview": "# These are supported funding model platforms\n\ngithub: [jinzhu]\npatreon: jinzhu\nopen_collective: gorm\n"
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 287,
    "preview": "---\nversion: 2\nupdates:\n  - package-ecosystem: gomod\n    directory: /\n    schedule:\n      interval: weekly\n  - package-e"
  },
  {
    "path": ".github/labels.json",
    "chars": 3916,
    "preview": "{\n  \"labels\": {\n    \"critical\": {\n      \"name\": \"type:critical\",\n      \"colour\": \"#E84137\",\n      \"description\": \"critic"
  },
  {
    "path": ".github/release-drafter.yml",
    "chars": 416,
    "preview": "name-template: 'v Release $NEXT_PATCH_VERSION 🌈'\ntag-template: 'v$NEXT_PATCH_VERSION'\ncategories:\n  - title: '🚀 Features"
  },
  {
    "path": ".github/workflows/create-release.yml",
    "chars": 663,
    "preview": "name: Create Release\n\non:\n  push:\n    tags:\n      - 'v*.*.*'\n\npermissions:\n  contents: write\n  pull-requests: read\n\njobs"
  },
  {
    "path": ".github/workflows/golangci-lint.yml",
    "chars": 471,
    "preview": "name: golangci-lint\non:\n  push:\n    branches:\n      - main\n      - master\n  pull_request:\n\npermissions:\n  contents: read"
  },
  {
    "path": ".github/workflows/invalid_question.yml",
    "chars": 1251,
    "preview": "name: \"Close invalid questions issues\"\non:\n  schedule:\n  - cron: \"*/10 * * * *\"\n\npermissions:\n  contents: read\n\njobs:\n  "
  },
  {
    "path": ".github/workflows/labeler.yml",
    "chars": 423,
    "preview": "name: \"Issue Labeler\"\non:\n  issues:\n    types: [opened, edited, reopened]\n  pull_request:\n    types: [opened, edited, re"
  },
  {
    "path": ".github/workflows/missing_playground.yml",
    "chars": 1343,
    "preview": "name: \"Close Missing Playground issues\"\non:\n  schedule:\n  - cron: \"*/10 * * * *\"\n\npermissions:\n  contents: read\n\njobs:\n "
  },
  {
    "path": ".github/workflows/stale.yml",
    "chars": 972,
    "preview": "name: \"Stale\"\non:\n  schedule:\n  - cron: \"0 2 * * *\"\n\npermissions:\n  contents: read\n\njobs:\n  stale:\n    permissions:\n    "
  },
  {
    "path": ".github/workflows/tests.yml",
    "chars": 9131,
    "preview": "name: tests\n\non:\n  push:\n    branches-ignore:\n      - 'gh-pages'\n  pull_request:\n    branches-ignore:\n      - 'gh-pages'"
  },
  {
    "path": ".gitignore",
    "chars": 56,
    "preview": "TODO*\ndocuments\ncoverage.txt\n_book\n.idea\nvendor\n.vscode\n"
  },
  {
    "path": ".golangci.yml",
    "chars": 241,
    "preview": "version: \"2\"\n\nlinters:\n  default: standard\n  enable:\n    - cyclop\n    - gocritic\n    - gosec\n    - ineffassign\n    - mis"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 5164,
    "preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to participate in"
  },
  {
    "path": "LICENSE",
    "chars": 1101,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2013-present  Jinzhu <wosmvp@gmail.com>\n\nPermission is hereby granted, free of char"
  },
  {
    "path": "README.md",
    "chars": 1841,
    "preview": "# GORM\n\nThe fantastic ORM library for Golang, aims to be developer friendly.\n\n[![go report card](https://goreportcard.co"
  },
  {
    "path": "association.go",
    "chars": 24214,
    "preview": "package gorm\n\nimport (\n\t\"fmt\"\n\t\"reflect\"\n\t\"strings\"\n\n\t\"gorm.io/gorm/clause\"\n\t\"gorm.io/gorm/schema\"\n\t\"gorm.io/gorm/utils\""
  },
  {
    "path": "callbacks/associations.go",
    "chars": 14712,
    "preview": "package callbacks\n\nimport (\n\t\"reflect\"\n\t\"strings\"\n\n\t\"gorm.io/gorm\"\n\t\"gorm.io/gorm/clause\"\n\t\"gorm.io/gorm/schema\"\n\t\"gorm."
  },
  {
    "path": "callbacks/callbacks.go",
    "chars": 3384,
    "preview": "package callbacks\n\nimport (\n\t\"gorm.io/gorm\"\n)\n\nvar (\n\tcreateClauses = []string{\"INSERT\", \"VALUES\", \"ON CONFLICT\"}\n\tquery"
  },
  {
    "path": "callbacks/callmethod.go",
    "chars": 846,
    "preview": "package callbacks\n\nimport (\n\t\"reflect\"\n\n\t\"gorm.io/gorm\"\n)\n\nfunc callMethod(db *gorm.DB, fc func(value interface{}, tx *g"
  },
  {
    "path": "callbacks/create.go",
    "chars": 13307,
    "preview": "package callbacks\n\nimport (\n\t\"fmt\"\n\t\"reflect\"\n\t\"strings\"\n\n\t\"gorm.io/gorm\"\n\t\"gorm.io/gorm/clause\"\n\t\"gorm.io/gorm/schema\"\n"
  },
  {
    "path": "callbacks/create_test.go",
    "chars": 1428,
    "preview": "package callbacks\n\nimport (\n\t\"reflect\"\n\t\"sync\"\n\t\"testing\"\n\t\"time\"\n\n\t\"gorm.io/gorm\"\n\t\"gorm.io/gorm/clause\"\n\t\"gorm.io/gorm"
  },
  {
    "path": "callbacks/delete.go",
    "chars": 5984,
    "preview": "package callbacks\n\nimport (\n\t\"reflect\"\n\t\"strings\"\n\n\t\"gorm.io/gorm\"\n\t\"gorm.io/gorm/clause\"\n\t\"gorm.io/gorm/schema\"\n\t\"gorm."
  },
  {
    "path": "callbacks/helper.go",
    "chars": 3816,
    "preview": "package callbacks\n\nimport (\n\t\"reflect\"\n\t\"sort\"\n\n\t\"gorm.io/gorm\"\n\t\"gorm.io/gorm/clause\"\n)\n\n// ConvertMapToValuesForCreate"
  },
  {
    "path": "callbacks/helper_test.go",
    "chars": 3490,
    "preview": "package callbacks\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n\n\t\"gorm.io/gorm\"\n\t\"gorm.io/gorm/clause\"\n)\n\nfunc TestLoadOrStoreVisitMa"
  },
  {
    "path": "callbacks/interfaces.go",
    "chars": 667,
    "preview": "package callbacks\n\nimport \"gorm.io/gorm\"\n\ntype BeforeCreateInterface interface {\n\tBeforeCreate(*gorm.DB) error\n}\n\ntype A"
  },
  {
    "path": "callbacks/preload.go",
    "chars": 12012,
    "preview": "package callbacks\n\nimport (\n\t\"fmt\"\n\t\"reflect\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"gorm.io/gorm\"\n\t\"gorm.io/gorm/clause\"\n\t\"gorm.io/gorm/"
  },
  {
    "path": "callbacks/query.go",
    "chars": 10637,
    "preview": "package callbacks\n\nimport (\n\t\"fmt\"\n\t\"reflect\"\n\t\"strings\"\n\n\t\"gorm.io/gorm\"\n\t\"gorm.io/gorm/clause\"\n\t\"gorm.io/gorm/schema\"\n"
  },
  {
    "path": "callbacks/raw.go",
    "chars": 468,
    "preview": "package callbacks\n\nimport (\n\t\"gorm.io/gorm\"\n)\n\nfunc RawExec(db *gorm.DB) {\n\tif db.Error == nil && !db.DryRun {\n\t\tresult,"
  },
  {
    "path": "callbacks/row.go",
    "chars": 581,
    "preview": "package callbacks\n\nimport (\n\t\"gorm.io/gorm\"\n)\n\nfunc RowQuery(db *gorm.DB) {\n\tif db.Error == nil {\n\t\tBuildQuerySQL(db)\n\t\t"
  },
  {
    "path": "callbacks/transaction.go",
    "chars": 675,
    "preview": "package callbacks\n\nimport (\n\t\"gorm.io/gorm\"\n)\n\nfunc BeginTransaction(db *gorm.DB) {\n\tif !db.Config.SkipDefaultTransactio"
  },
  {
    "path": "callbacks/update.go",
    "chars": 9856,
    "preview": "package callbacks\n\nimport (\n\t\"reflect\"\n\t\"sort\"\n\n\t\"gorm.io/gorm\"\n\t\"gorm.io/gorm/clause\"\n\t\"gorm.io/gorm/schema\"\n\t\"gorm.io/"
  },
  {
    "path": "callbacks.go",
    "chars": 9013,
    "preview": "package gorm\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"sort\"\n\t\"time\"\n\n\t\"gorm.io/gorm/schema\"\n\t\"gorm.io/gorm/uti"
  },
  {
    "path": "chainable_api.go",
    "chars": 15133,
    "preview": "package gorm\n\nimport (\n\t\"fmt\"\n\t\"regexp\"\n\t\"strings\"\n\n\t\"gorm.io/gorm/clause\"\n\t\"gorm.io/gorm/utils\"\n)\n\n// Model specify the"
  },
  {
    "path": "clause/association.go",
    "chars": 1268,
    "preview": "package clause\n\n// AssociationOpType represents association operation types\ntype AssociationOpType int\n\nconst (\n\tOpUnlin"
  },
  {
    "path": "clause/benchmarks_test.go",
    "chars": 1902,
    "preview": "package clause_test\n\nimport (\n\t\"sync\"\n\t\"testing\"\n\n\t\"gorm.io/gorm\"\n\t\"gorm.io/gorm/clause\"\n\t\"gorm.io/gorm/schema\"\n\t\"gorm.i"
  },
  {
    "path": "clause/clause.go",
    "chars": 1749,
    "preview": "package clause\n\n// Interface clause interface\ntype Interface interface {\n\tName() string\n\tBuild(Builder)\n\tMergeClause(*Cl"
  },
  {
    "path": "clause/clause_test.go",
    "chars": 1012,
    "preview": "package clause_test\n\nimport (\n\t\"reflect\"\n\t\"strings\"\n\t\"sync\"\n\t\"testing\"\n\n\t\"gorm.io/gorm\"\n\t\"gorm.io/gorm/clause\"\n\t\"gorm.io"
  },
  {
    "path": "clause/delete.go",
    "chars": 359,
    "preview": "package clause\n\ntype Delete struct {\n\tModifier string\n}\n\nfunc (d Delete) Name() string {\n\treturn \"DELETE\"\n}\n\nfunc (d Del"
  },
  {
    "path": "clause/delete_test.go",
    "chars": 608,
    "preview": "package clause_test\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\n\t\"gorm.io/gorm/clause\"\n)\n\nfunc TestDelete(t *testing.T) {\n\tresults := ["
  },
  {
    "path": "clause/expression.go",
    "chars": 8231,
    "preview": "package clause\n\nimport (\n\t\"database/sql\"\n\t\"database/sql/driver\"\n\t\"go/ast\"\n\t\"reflect\"\n)\n\n// Expression expression interfa"
  },
  {
    "path": "clause/expression_test.go",
    "chars": 9063,
    "preview": "package clause_test\n\nimport (\n\t\"database/sql\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"sync\"\n\t\"testing\"\n\n\t\"gorm.io/gorm\"\n\t\"gorm.io/gorm/claus"
  },
  {
    "path": "clause/from.go",
    "chars": 630,
    "preview": "package clause\n\n// From from clause\ntype From struct {\n\tTables []Table\n\tJoins  []Join\n}\n\n// Name from clause name\nfunc ("
  },
  {
    "path": "clause/from_test.go",
    "chars": 1956,
    "preview": "package clause_test\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\n\t\"gorm.io/gorm/clause\"\n)\n\nfunc TestFrom(t *testing.T) {\n\tresults := []s"
  },
  {
    "path": "clause/group_by.go",
    "chars": 1068,
    "preview": "package clause\n\n// GroupBy group by clause\ntype GroupBy struct {\n\tColumns []Column\n\tHaving  []Expression\n}\n\n// Name from"
  },
  {
    "path": "clause/group_by_test.go",
    "chars": 1111,
    "preview": "package clause_test\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\n\t\"gorm.io/gorm/clause\"\n)\n\nfunc TestGroupBy(t *testing.T) {\n\tresults := "
  },
  {
    "path": "clause/insert.go",
    "chars": 767,
    "preview": "package clause\n\ntype Insert struct {\n\tTable    Table\n\tModifier string\n}\n\n// Name insert clause name\nfunc (insert Insert)"
  },
  {
    "path": "clause/insert_test.go",
    "chars": 737,
    "preview": "package clause_test\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\n\t\"gorm.io/gorm/clause\"\n)\n\nfunc TestInsert(t *testing.T) {\n\tresults := ["
  },
  {
    "path": "clause/joins.go",
    "chars": 1586,
    "preview": "package clause\n\nimport \"gorm.io/gorm/utils\"\n\ntype JoinType string\n\nconst (\n\tCrossJoin JoinType = \"CROSS\"\n\tInnerJoin Join"
  },
  {
    "path": "clause/joins_test.go",
    "chars": 2695,
    "preview": "package clause_test\n\nimport (\n\t\"sync\"\n\t\"testing\"\n\n\t\"gorm.io/gorm\"\n\t\"gorm.io/gorm/clause\"\n\t\"gorm.io/gorm/schema\"\n\t\"gorm.i"
  },
  {
    "path": "clause/limit.go",
    "chars": 942,
    "preview": "package clause\n\n// Limit limit clause\ntype Limit struct {\n\tLimit  *int\n\tOffset int\n}\n\n// Name where clause name\nfunc (li"
  },
  {
    "path": "clause/limit_test.go",
    "chars": 2396,
    "preview": "package clause_test\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\n\t\"gorm.io/gorm/clause\"\n)\n\nfunc TestLimit(t *testing.T) {\n\tlimit0 := 0\n\t"
  },
  {
    "path": "clause/locking.go",
    "chars": 773,
    "preview": "package clause\n\nconst (\n\tLockingStrengthUpdate    = \"UPDATE\"\n\tLockingStrengthShare     = \"SHARE\"\n\tLockingOptionsSkipLock"
  },
  {
    "path": "clause/locking_test.go",
    "chars": 1194,
    "preview": "package clause_test\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\n\t\"gorm.io/gorm/clause\"\n)\n\nfunc TestLocking(t *testing.T) {\n\tresults := "
  },
  {
    "path": "clause/on_conflict.go",
    "chars": 1298,
    "preview": "package clause\n\ntype OnConflict struct {\n\tColumns      []Column\n\tWhere        Where\n\tTargetWhere  Where\n\tOnConstraint st"
  },
  {
    "path": "clause/order_by.go",
    "chars": 1114,
    "preview": "package clause\n\ntype OrderByColumn struct {\n\tColumn  Column\n\tDesc    bool\n\tReorder bool\n}\n\ntype OrderBy struct {\n\tColumn"
  },
  {
    "path": "clause/order_by_test.go",
    "chars": 1590,
    "preview": "package clause_test\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\n\t\"gorm.io/gorm/clause\"\n)\n\nfunc TestOrderBy(t *testing.T) {\n\tresults := "
  },
  {
    "path": "clause/returning.go",
    "chars": 777,
    "preview": "package clause\n\ntype Returning struct {\n\tColumns []Column\n}\n\n// Name where clause name\nfunc (returning Returning) Name()"
  },
  {
    "path": "clause/returning_test.go",
    "chars": 1389,
    "preview": "package clause_test\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\n\t\"gorm.io/gorm/clause\"\n)\n\nfunc TestReturning(t *testing.T) {\n\tresults :"
  },
  {
    "path": "clause/select.go",
    "chars": 1096,
    "preview": "package clause\n\n// Select select attrs when querying, updating, creating\ntype Select struct {\n\tDistinct   bool\n\tColumns "
  },
  {
    "path": "clause/select_test.go",
    "chars": 1721,
    "preview": "package clause_test\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\n\t\"gorm.io/gorm/clause\"\n)\n\nfunc TestSelect(t *testing.T) {\n\tresults := ["
  },
  {
    "path": "clause/set.go",
    "chars": 1742,
    "preview": "package clause\n\nimport \"sort\"\n\ntype Set []Assignment\n\ntype Assignment struct {\n\tColumn Column\n\tValue  interface{}\n}\n\n// "
  },
  {
    "path": "clause/set_test.go",
    "chars": 1547,
    "preview": "package clause_test\n\nimport (\n\t\"fmt\"\n\t\"sort\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"gorm.io/gorm/clause\"\n)\n\n// Compile-time assertions"
  },
  {
    "path": "clause/update.go",
    "chars": 737,
    "preview": "package clause\n\ntype Update struct {\n\tModifier string\n\tTable    Table\n}\n\n// Name update clause name\nfunc (update Update)"
  },
  {
    "path": "clause/update_test.go",
    "chars": 722,
    "preview": "package clause_test\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\n\t\"gorm.io/gorm/clause\"\n)\n\nfunc TestUpdate(t *testing.T) {\n\tresults := ["
  },
  {
    "path": "clause/values.go",
    "chars": 849,
    "preview": "package clause\n\ntype Values struct {\n\tColumns []Column\n\tValues  [][]interface{}\n}\n\n// Name from clause name\nfunc (Values"
  },
  {
    "path": "clause/values_test.go",
    "chars": 691,
    "preview": "package clause_test\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\n\t\"gorm.io/gorm/clause\"\n)\n\nfunc TestValues(t *testing.T) {\n\tresults := ["
  },
  {
    "path": "clause/where.go",
    "chars": 5236,
    "preview": "package clause\n\nimport (\n\t\"strings\"\n)\n\nconst (\n\tAndWithSpace = \" AND \"\n\tOrWithSpace  = \" OR \"\n)\n\n// Where where clause\nt"
  },
  {
    "path": "clause/where_test.go",
    "chars": 6328,
    "preview": "package clause_test\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\n\t\"gorm.io/gorm/clause\"\n)\n\nfunc TestWhere(t *testing.T) {\n\tresults := []"
  },
  {
    "path": "clause/with.go",
    "chars": 35,
    "preview": "package clause\n\ntype With struct{}\n"
  },
  {
    "path": "errors.go",
    "chars": 2562,
    "preview": "package gorm\n\nimport (\n\t\"errors\"\n\n\t\"gorm.io/gorm/logger\"\n)\n\nvar (\n\t// ErrRecordNotFound record not found error\n\tErrRecor"
  },
  {
    "path": "finisher_api.go",
    "chars": 23461,
    "preview": "package gorm\n\nimport (\n\t\"context\"\n\t\"database/sql\"\n\t\"errors\"\n\t\"fmt\"\n\t\"hash/maphash\"\n\t\"reflect\"\n\t\"strings\"\n\n\t\"gorm.io/gorm"
  },
  {
    "path": "generics.go",
    "chars": 26550,
    "preview": "package gorm\n\nimport (\n\t\"context\"\n\t\"database/sql\"\n\t\"errors\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"gorm.io/gorm/clause\""
  },
  {
    "path": "go.mod",
    "chars": 241,
    "preview": "module gorm.io/gorm\n\ngo 1.18\n\nrequire (\n\tgithub.com/jinzhu/inflection v1.0.0\n\tgithub.com/jinzhu/now v1.1.5\n\tgolang.org/x"
  },
  {
    "path": "go.sum",
    "chars": 829,
    "preview": "github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=\ngithub.com/jinzhu/inflection v1.0.0/"
  },
  {
    "path": "gorm.go",
    "chars": 13177,
    "preview": "package gorm\n\nimport (\n\t\"context\"\n\t\"database/sql\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"sort\"\n\t\"sync\"\n\t\"time\"\n\n\t\"gorm.io/gorm/clause\"\n\t\"go"
  },
  {
    "path": "interfaces.go",
    "chars": 2216,
    "preview": "package gorm\n\nimport (\n\t\"context\"\n\t\"database/sql\"\n\n\t\"gorm.io/gorm/clause\"\n\t\"gorm.io/gorm/schema\"\n)\n\n// Dialector GORM da"
  },
  {
    "path": "internal/lru/lru.go",
    "chars": 12824,
    "preview": "package lru\n\n// golang -lru\n// https://github.com/hashicorp/golang-lru\nimport (\n\t\"sync\"\n\t\"time\"\n)\n\n// EvictCallback is u"
  },
  {
    "path": "internal/stmt_store/stmt_store.go",
    "chars": 6154,
    "preview": "package stmt_store\n\nimport (\n\t\"context\"\n\t\"database/sql\"\n\t\"math\"\n\t\"sync\"\n\t\"time\"\n\n\t\"gorm.io/gorm/internal/lru\"\n)\n\ntype St"
  },
  {
    "path": "logger/logger.go",
    "chars": 6407,
    "preview": "package logger\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"os\"\n\t\"time\"\n\n\t\"gorm.io/gorm/utils\"\n)\n\n// ErrRecordNo"
  },
  {
    "path": "logger/slog.go",
    "chars": 2927,
    "preview": "//go:build go1.21\n\npackage logger\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"log/slog\"\n\t\"time\"\n\n\t\"gorm.io/gorm/utils\"\n)\n\nty"
  },
  {
    "path": "logger/slog_test.go",
    "chars": 782,
    "preview": "//go:build go1.21\n\npackage logger\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"log/slog\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n)\n\nfunc TestSl"
  },
  {
    "path": "logger/sql.go",
    "chars": 5146,
    "preview": "package logger\n\nimport (\n\t\"database/sql/driver\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\t\"unicode\"\n\n\t\""
  },
  {
    "path": "logger/sql_test.go",
    "chars": 8565,
    "preview": "package logger_test\n\nimport (\n\t\"database/sql/driver\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"regexp\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.c"
  },
  {
    "path": "migrator/column_type.go",
    "chars": 3374,
    "preview": "package migrator\n\nimport (\n\t\"database/sql\"\n\t\"reflect\"\n)\n\n// ColumnType column type implements ColumnType interface\ntype "
  },
  {
    "path": "migrator/index.go",
    "chars": 1023,
    "preview": "package migrator\n\nimport \"database/sql\"\n\n// Index implements gorm.Index interface\ntype Index struct {\n\tTableName       s"
  },
  {
    "path": "migrator/migrator.go",
    "chars": 30371,
    "preview": "package migrator\n\nimport (\n\t\"context\"\n\t\"database/sql\"\n\t\"errors\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time"
  },
  {
    "path": "migrator/table_type.go",
    "chars": 688,
    "preview": "package migrator\n\nimport (\n\t\"database/sql\"\n)\n\n// TableType table type implements TableType interface\ntype TableType stru"
  },
  {
    "path": "migrator.go",
    "chars": 3205,
    "preview": "package gorm\n\nimport (\n\t\"reflect\"\n\n\t\"gorm.io/gorm/clause\"\n\t\"gorm.io/gorm/schema\"\n)\n\n// Migrator returns migrator\nfunc (d"
  },
  {
    "path": "model.go",
    "chars": 396,
    "preview": "package gorm\n\nimport \"time\"\n\n// Model a basic GoLang struct which includes the following fields: ID, CreatedAt, UpdatedA"
  },
  {
    "path": "prepare_stmt.go",
    "chars": 5826,
    "preview": "package gorm\n\nimport (\n\t\"context\"\n\t\"database/sql\"\n\t\"database/sql/driver\"\n\t\"errors\"\n\t\"reflect\"\n\t\"sync\"\n\t\"time\"\n\n\t\"gorm.io"
  },
  {
    "path": "scan.go",
    "chars": 10650,
    "preview": "package gorm\n\nimport (\n\t\"database/sql\"\n\t\"database/sql/driver\"\n\t\"reflect\"\n\t\"strings\"\n\t\"time\"\n\n\t\"gorm.io/gorm/schema\"\n\t\"go"
  },
  {
    "path": "schema/callbacks_test.go",
    "chars": 939,
    "preview": "package schema_test\n\nimport (\n\t\"reflect\"\n\t\"sync\"\n\t\"testing\"\n\n\t\"gorm.io/gorm\"\n\t\"gorm.io/gorm/schema\"\n)\n\ntype UserWithCall"
  },
  {
    "path": "schema/constraint.go",
    "chars": 1984,
    "preview": "package schema\n\nimport (\n\t\"regexp\"\n\t\"strings\"\n\n\t\"gorm.io/gorm/clause\"\n)\n\n// reg match english letters and midline\nvar re"
  },
  {
    "path": "schema/constraint_test.go",
    "chars": 2245,
    "preview": "package schema_test\n\nimport (\n\t\"reflect\"\n\t\"sync\"\n\t\"testing\"\n\n\t\"gorm.io/gorm/schema\"\n\t\"gorm.io/gorm/utils/tests\"\n)\n\ntype "
  },
  {
    "path": "schema/field.go",
    "chars": 32991,
    "preview": "package schema\n\nimport (\n\t\"context\"\n\t\"database/sql\"\n\t\"database/sql/driver\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"strconv\"\n\t\"strings\"\n\t\"syn"
  },
  {
    "path": "schema/field_test.go",
    "chars": 13023,
    "preview": "package schema_test\n\nimport (\n\t\"context\"\n\t\"database/sql\"\n\t\"reflect\"\n\t\"sync\"\n\t\"testing\"\n\t\"time\"\n\n\t\"gorm.io/gorm\"\n\t\"gorm.i"
  },
  {
    "path": "schema/index.go",
    "chars": 3863,
    "preview": "package schema\n\nimport (\n\t\"fmt\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n)\n\ntype Index struct {\n\tName    string\n\tClass   string // "
  },
  {
    "path": "schema/index_test.go",
    "chars": 8140,
    "preview": "package schema_test\n\nimport (\n\t\"sync\"\n\t\"testing\"\n\n\t\"gorm.io/gorm/schema\"\n\t\"gorm.io/gorm/utils/tests\"\n)\n\ntype UserIndex s"
  },
  {
    "path": "schema/interfaces.go",
    "chars": 980,
    "preview": "package schema\n\nimport (\n\t\"gorm.io/gorm/clause\"\n)\n\n// ConstraintInterface database constraint interface\ntype ConstraintI"
  },
  {
    "path": "schema/model_test.go",
    "chars": 1176,
    "preview": "package schema_test\n\nimport (\n\t\"database/sql\"\n\t\"time\"\n\n\t\"gorm.io/gorm\"\n\t\"gorm.io/gorm/utils/tests\"\n)\n\ntype User struct {"
  },
  {
    "path": "schema/naming.go",
    "chars": 5465,
    "preview": "package schema\n\nimport (\n\t\"crypto/sha1\"\n\t\"encoding/hex\"\n\t\"regexp\"\n\t\"strings\"\n\t\"unicode/utf8\"\n\n\t\"github.com/jinzhu/inflec"
  },
  {
    "path": "schema/naming_test.go",
    "chars": 7150,
    "preview": "package schema\n\nimport (\n\t\"strings\"\n\t\"testing\"\n)\n\nfunc TestToDBName(t *testing.T) {\n\tmaps := map[string]string{\n\t\t\"\":   "
  },
  {
    "path": "schema/pool.go",
    "chars": 345,
    "preview": "package schema\n\nimport (\n\t\"reflect\"\n\t\"sync\"\n)\n\n// sync pools\nvar (\n\tnormalPool      sync.Map\n\tpoolInitializer = func(ref"
  },
  {
    "path": "schema/relationship.go",
    "chars": 23677,
    "preview": "package schema\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"github.com/jinzhu/inflection\"\n\t\"golang.org/x"
  },
  {
    "path": "schema/relationship_test.go",
    "chars": 27136,
    "preview": "package schema_test\n\nimport (\n\t\"sync\"\n\t\"testing\"\n\t\"time\"\n\n\t\"gorm.io/gorm\"\n\t\"gorm.io/gorm/schema\"\n\t\"gorm.io/gorm/utils/te"
  },
  {
    "path": "schema/schema.go",
    "chars": 13455,
    "preview": "package schema\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"path\"\n\t\"reflect\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"gorm.io/gorm/cla"
  },
  {
    "path": "schema/schema_helper_test.go",
    "chars": 7705,
    "preview": "package schema_test\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"gorm.io/gorm/schema\"\n\t\"gorm.io/gorm/"
  },
  {
    "path": "schema/schema_test.go",
    "chars": 13610,
    "preview": "package schema_test\n\nimport (\n\t\"strings\"\n\t\"sync\"\n\t\"testing\"\n\n\t\"gorm.io/gorm\"\n\t\"gorm.io/gorm/schema\"\n\t\"gorm.io/gorm/utils"
  },
  {
    "path": "schema/serializer.go",
    "chars": 5190,
    "preview": "package schema\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"database/sql\"\n\t\"database/sql/driver\"\n\t\"encoding/gob\"\n\t\"encoding/json\"\n\t\"f"
  },
  {
    "path": "schema/serializer_test.go",
    "chars": 4866,
    "preview": "package schema\n\nimport (\n\t\"context\"\n\t\"math\"\n\t\"reflect\"\n\t\"testing\"\n\t\"time\"\n)\n\nfunc TestUnixSecondSerializer_Value(t *test"
  },
  {
    "path": "schema/utils.go",
    "chars": 6053,
    "preview": "package schema\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"regexp\"\n\t\"strings\"\n\n\t\"gorm.io/gorm/clause\"\n\t\"gorm.io/gorm/utils\""
  },
  {
    "path": "schema/utils_test.go",
    "chars": 1880,
    "preview": "package schema\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n)\n\nfunc TestRemoveSettingFromTag(t *testing.T) {\n\ttags := map[string]stri"
  },
  {
    "path": "soft_delete.go",
    "chars": 4633,
    "preview": "package gorm\n\nimport (\n\t\"database/sql\"\n\t\"database/sql/driver\"\n\t\"encoding/json\"\n\t\"reflect\"\n\n\t\"github.com/jinzhu/now\"\n\t\"go"
  },
  {
    "path": "statement.go",
    "chars": 21384,
    "preview": "package gorm\n\nimport (\n\t\"context\"\n\t\"database/sql\"\n\t\"database/sql/driver\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"regexp\"\n\t\"sort\"\n\t\"strconv\"\n"
  },
  {
    "path": "statement_test.go",
    "chars": 1930,
    "preview": "package gorm\n\nimport (\n\t\"fmt\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"gorm.io/gorm/clause\"\n)\n\nfunc TestWhereCloneCorruption(t *testing."
  },
  {
    "path": "tests/.gitignore",
    "chars": 7,
    "preview": "go.sum\n"
  },
  {
    "path": "tests/README.md",
    "chars": 110,
    "preview": "# Test Guide\n\n```bash\ncd tests\n# prepare test databases\ndocker-compose up\n\n# run all tests\n./tests_all.sh\n```\n"
  },
  {
    "path": "tests/association_generics_test.go",
    "chars": 38787,
    "preview": "package tests_test\n\nimport (\n\t\"context\"\n\t\"testing\"\n\n\t\"gorm.io/gorm\"\n\t\"gorm.io/gorm/clause\"\n\t. \"gorm.io/gorm/utils/tests\""
  },
  {
    "path": "tests/associations_belongs_to_test.go",
    "chars": 9533,
    "preview": "package tests_test\n\nimport (\n\t\"testing\"\n\n\t\"gorm.io/gorm\"\n\t. \"gorm.io/gorm/utils/tests\"\n)\n\nfunc TestBelongsToAssociation("
  },
  {
    "path": "tests/associations_has_many_test.go",
    "chars": 16650,
    "preview": "package tests_test\n\nimport (\n\t\"testing\"\n\n\t\"gorm.io/gorm\"\n\t. \"gorm.io/gorm/utils/tests\"\n)\n\nfunc TestHasManyAssociation(t "
  },
  {
    "path": "tests/associations_has_one_test.go",
    "chars": 7304,
    "preview": "package tests_test\n\nimport (\n\t\"testing\"\n\n\t. \"gorm.io/gorm/utils/tests\"\n)\n\nfunc TestHasOneAssociation(t *testing.T) {\n\tus"
  },
  {
    "path": "tests/associations_many2many_test.go",
    "chars": 13547,
    "preview": "package tests_test\n\nimport (\n\t\"fmt\"\n\t\"sync\"\n\t\"testing\"\n\n\t\"gorm.io/gorm\"\n\t\"gorm.io/gorm/clause\"\n\t. \"gorm.io/gorm/utils/te"
  },
  {
    "path": "tests/associations_test.go",
    "chars": 13579,
    "preview": "package tests_test\n\nimport (\n\t\"testing\"\n\n\t\"gorm.io/gorm\"\n\t\"gorm.io/gorm/clause\"\n\t\"gorm.io/gorm/schema\"\n\t. \"gorm.io/gorm/"
  },
  {
    "path": "tests/benchmark_test.go",
    "chars": 1523,
    "preview": "package tests_test\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\n\t. \"gorm.io/gorm/utils/tests\"\n)\n\nfunc BenchmarkCreate(b *testing.B) {\n\tu"
  },
  {
    "path": "tests/callbacks_test.go",
    "chars": 7403,
    "preview": "package tests_test\n\nimport (\n\t\"fmt\"\n\t\"reflect\"\n\t\"runtime\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"gorm.io/gorm\"\n)\n\nfunc assertCallbacks"
  },
  {
    "path": "tests/chainable_api_test.go",
    "chars": 3957,
    "preview": "package tests\n\nimport (\n\t\"context\"\n\t\"testing\"\n\n\t\"gorm.io/gorm\"\n\t\"gorm.io/gorm/clause\"\n\t\"gorm.io/gorm/schema\"\n)\n\n// testD"
  },
  {
    "path": "tests/compose.yml",
    "chars": 1924,
    "preview": "services:\n  mysql:\n    image: 'mysql:latest'\n    ports:\n      - \"127.0.0.1:9910:3306\"\n    environment:\n      - MYSQL_DAT"
  },
  {
    "path": "tests/connection_test.go",
    "chars": 943,
    "preview": "package tests_test\n\nimport (\n\t\"testing\"\n\n\t\"gorm.io/driver/mysql\"\n\t\"gorm.io/gorm\"\n)\n\nfunc TestWithSingleConnection(t *tes"
  },
  {
    "path": "tests/connpool_test.go",
    "chars": 5678,
    "preview": "package tests_test\n\nimport (\n\t\"context\"\n\t\"database/sql\"\n\t\"os\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"gorm.io/driver/mysql\"\n\t\"gorm.io/g"
  },
  {
    "path": "tests/count_test.go",
    "chars": 6978,
    "preview": "package tests_test\n\nimport (\n\t\"regexp\"\n\t\"sort\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"gorm.io/gorm\"\n\t. \"gorm.io/gorm/utils/tests\"\n)\n\nf"
  },
  {
    "path": "tests/create_test.go",
    "chars": 27468,
    "preview": "package tests_test\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"regexp\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/jinzhu/now\"\n\t\"gorm.io/gorm\"\n\t\"g"
  },
  {
    "path": "tests/customize_field_test.go",
    "chars": 7049,
    "preview": "package tests_test\n\nimport (\n\t\"testing\"\n\t\"time\"\n\n\t\"gorm.io/gorm\"\n\t. \"gorm.io/gorm/utils/tests\"\n)\n\nfunc TestCustomizeColu"
  },
  {
    "path": "tests/default_value_test.go",
    "chars": 2396,
    "preview": "package tests_test\n\nimport (\n\t\"testing\"\n\t\"time\"\n\n\t\"gorm.io/gorm\"\n)\n\nfunc TestDefaultValue(t *testing.T) {\n\ttype Harumph "
  },
  {
    "path": "tests/delete_test.go",
    "chars": 9696,
    "preview": "package tests_test\n\nimport (\n\t\"errors\"\n\t\"testing\"\n\n\t\"gorm.io/gorm\"\n\t\"gorm.io/gorm/clause\"\n\t. \"gorm.io/gorm/utils/tests\"\n"
  },
  {
    "path": "tests/distinct_test.go",
    "chars": 2581,
    "preview": "package tests_test\n\nimport (\n\t\"regexp\"\n\t\"testing\"\n\n\t\"gorm.io/gorm\"\n\t. \"gorm.io/gorm/utils/tests\"\n)\n\nfunc TestDistinct(t "
  },
  {
    "path": "tests/embedded_struct_test.go",
    "chars": 7495,
    "preview": "package tests_test\n\nimport (\n\t\"database/sql/driver\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"reflect\"\n\t\"testing\"\n\t\"time\"\n\n\t\"gorm.io/"
  },
  {
    "path": "tests/error_translator_test.go",
    "chars": 3170,
    "preview": "package tests_test\n\nimport (\n\t\"errors\"\n\t\"testing\"\n\n\t\"gorm.io/gorm\"\n\t\"gorm.io/gorm/utils/tests\"\n)\n\nfunc TestDialectorWith"
  },
  {
    "path": "tests/gaussdb_test.go",
    "chars": 6788,
    "preview": "package tests_test\n\nimport (\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/google/uuid\"\n\t\"github.com/lib/pq\"\n\t\"gorm.io/gorm\"\n\t\"gorm.i"
  },
  {
    "path": "tests/generics_test.go",
    "chars": 35781,
    "preview": "package tests_test\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"regexp\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n\t\"te"
  },
  {
    "path": "tests/go.mod",
    "chars": 1345,
    "preview": "module gorm.io/gorm/tests\n\ngo 1.24.0\n\nrequire (\n\tgithub.com/google/uuid v1.6.0\n\tgithub.com/jinzhu/now v1.1.5\n\tgithub.com"
  },
  {
    "path": "tests/gorm_test.go",
    "chars": 3362,
    "preview": "package tests_test\n\nimport (\n\t\"testing\"\n\n\t\"gorm.io/driver/mysql\"\n\n\t\"gorm.io/gorm\"\n)\n\nfunc TestOpen(t *testing.T) {\n\tdsn "
  },
  {
    "path": "tests/group_by_test.go",
    "chars": 3374,
    "preview": "package tests_test\n\nimport (\n\t\"testing\"\n\n\t. \"gorm.io/gorm/utils/tests\"\n)\n\nfunc TestGroupBy(t *testing.T) {\n\tusers := []U"
  },
  {
    "path": "tests/helper_test.go",
    "chars": 8178,
    "preview": "package tests_test\n\nimport (\n\t\"os\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t\"gorm.io/gorm\"\n\n\t. \"gorm.io/gorm/u"
  },
  {
    "path": "tests/hooks_test.go",
    "chars": 17095,
    "preview": "package tests_test\n\nimport (\n\t\"errors\"\n\t\"log\"\n\t\"os\"\n\t\"reflect\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"gorm.io/gorm\"\n\t. \"gorm.io/gorm/u"
  },
  {
    "path": "tests/joins_table_test.go",
    "chars": 3537,
    "preview": "package tests_test\n\nimport (\n\t\"testing\"\n\t\"time\"\n\n\t\"gorm.io/gorm\"\n\t\"gorm.io/gorm/clause\"\n)\n\ntype Person struct {\n\tID     "
  },
  {
    "path": "tests/joins_test.go",
    "chars": 15342,
    "preview": "package tests_test\n\nimport (\n\t\"fmt\"\n\t\"regexp\"\n\t\"sort\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"gorm.io/gorm\"\n"
  },
  {
    "path": "tests/lru_test.go",
    "chars": 10630,
    "preview": "package tests_test\n\nimport (\n\t\"crypto/rand\"\n\t\"fmt\"\n\t\"math\"\n\t\"math/big\"\n\t\"reflect\"\n\t\"sync\"\n\t\"testing\"\n\t\"time\"\n\n\t\"gorm.io/"
  },
  {
    "path": "tests/main_test.go",
    "chars": 1399,
    "preview": "package tests_test\n\nimport (\n\t\"testing\"\n\n\t. \"gorm.io/gorm/utils/tests\"\n)\n\nfunc TestExceptionsWithInvalidSql(t *testing.T"
  },
  {
    "path": "tests/migrate_test.go",
    "chars": 66779,
    "preview": "package tests_test\n\nimport (\n\t\"context\"\n\t\"database/sql\"\n\t\"fmt\"\n\t\"math/rand\"\n\t\"reflect\"\n\t\"strconv\"\n\t\"strings\"\n\t\"testing\"\n"
  },
  {
    "path": "tests/multi_primary_keys_test.go",
    "chars": 13444,
    "preview": "package tests_test\n\nimport (\n\t\"reflect\"\n\t\"sort\"\n\t\"testing\"\n\n\t\"gorm.io/gorm\"\n\t. \"gorm.io/gorm/utils/tests\"\n)\n\ntype Blog s"
  },
  {
    "path": "tests/named_argument_test.go",
    "chars": 2789,
    "preview": "package tests_test\n\nimport (\n\t\"database/sql\"\n\t\"errors\"\n\t\"testing\"\n\n\t\"gorm.io/gorm\"\n\t. \"gorm.io/gorm/utils/tests\"\n)\n\nfunc"
  },
  {
    "path": "tests/named_polymorphic_test.go",
    "chars": 4305,
    "preview": "package tests_test\n\nimport (\n\t\"testing\"\n\n\t. \"gorm.io/gorm/utils/tests\"\n)\n\ntype Hamster struct {\n\tId           int\n\tName "
  },
  {
    "path": "tests/non_std_test.go",
    "chars": 1970,
    "preview": "package tests_test\n\nimport (\n\t\"testing\"\n\t\"time\"\n)\n\ntype Animal struct {\n\tCounter    uint64 `gorm:\"primary_key:yes\"`\n\tNam"
  },
  {
    "path": "tests/postgres_test.go",
    "chars": 6576,
    "preview": "package tests_test\n\nimport (\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/google/uuid\"\n\t\"github.com/lib/pq\"\n\t\"gorm.io/gorm\"\n\t\"gorm.i"
  },
  {
    "path": "tests/preload_suits_test.go",
    "chars": 31113,
    "preview": "package tests_test\n\nimport (\n\t\"database/sql\"\n\t\"encoding/json\"\n\t\"reflect\"\n\t\"sort\"\n\t\"sync/atomic\"\n\t\"testing\"\n\n\t\"gorm.io/go"
  },
  {
    "path": "tests/preload_test.go",
    "chars": 16306,
    "preview": "package tests_test\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"regexp\"\n\t\"sort\"\n\t\"strconv\"\n\t\"sync\"\n\t\"testing\"\n\t\"time\"\n\n\t\"gorm"
  },
  {
    "path": "tests/prepared_stmt_test.go",
    "chars": 8216,
    "preview": "package tests_test\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"sync\"\n\t\"testing\"\n\t\"time\"\n\n\t\"gorm.io/gorm\"\n\t. \"gorm.io/gorm/utils/tes"
  },
  {
    "path": "tests/query_test.go",
    "chars": 52228,
    "preview": "package tests_test\n\nimport (\n\t\"database/sql\"\n\t\"database/sql/driver\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"regexp\"\n\t\"sort\"\n\t\"strconv\"\n\t\"str"
  },
  {
    "path": "tests/scan_test.go",
    "chars": 11115,
    "preview": "package tests_test\n\nimport (\n\t\"reflect\"\n\t\"sort\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t\"gorm.io/gorm\"\n\t. \"gorm.io/gorm/utils/te"
  },
  {
    "path": "tests/scanner_valuer_test.go",
    "chars": 10830,
    "preview": "package tests_test\n\nimport (\n\t\"context\"\n\t\"database/sql\"\n\t\"database/sql/driver\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"refle"
  },
  {
    "path": "tests/scopes_test.go",
    "chars": 3429,
    "preview": "package tests_test\n\nimport (\n\t\"context\"\n\t\"testing\"\n\n\t\"gorm.io/gorm\"\n\t. \"gorm.io/gorm/utils/tests\"\n)\n\nfunc NameIn1And2(d "
  },
  {
    "path": "tests/serializer_test.go",
    "chars": 9538,
    "preview": "package tests_test\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t\"gorm.io/gorm\"\n\t\"gorm"
  },
  {
    "path": "tests/soft_delete_test.go",
    "chars": 5799,
    "preview": "package tests_test\n\nimport (\n\t\"database/sql\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"regexp\"\n\t\"testing\"\n\n\t\"github.com/jinzhu/now\"\n\t"
  },
  {
    "path": "tests/sql_builder_test.go",
    "chars": 17071,
    "preview": "package tests_test\n\nimport (\n\t\"regexp\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t\"gorm.io/gorm\"\n\t\"gorm.io/gorm/clause\"\n\t. \"gorm.io"
  },
  {
    "path": "tests/submodel_test.go",
    "chars": 947,
    "preview": "package tests_test\n\nimport (\n\t\"testing\"\n\n\t\"gorm.io/gorm\"\n)\n\ntype Man struct {\n\tID     int\n\tAge    int\n\tName   string\n\tDe"
  },
  {
    "path": "tests/table_test.go",
    "chars": 12979,
    "preview": "package tests_test\n\nimport (\n\t\"regexp\"\n\t\"sync\"\n\t\"testing\"\n\n\t\"gorm.io/driver/gaussdb\"\n\t\"gorm.io/driver/postgres\"\n\t\"gorm.i"
  },
  {
    "path": "tests/tests_all.sh",
    "chars": 1604,
    "preview": "#!/bin/bash -e\n\ndialects=(\"sqlite\" \"mysql\" \"postgres\" \"gaussdb\" \"sqlserver\" \"tidb\")\n\nif [[ $(pwd) == *\"gorm/tests\"* ]]; "
  },
  {
    "path": "tests/tests_test.go",
    "chars": 3828,
    "preview": "//go:debug x509negativeserial=1\npackage tests_test\n\nimport (\n\t\"log\"\n\t\"math/rand\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"time\"\n\n\t\"gorm."
  },
  {
    "path": "tests/tracer_test.go",
    "chars": 830,
    "preview": "package tests_test\n\nimport (\n\t\"context\"\n\t\"time\"\n\n\t\"gorm.io/gorm/logger\"\n)\n\ntype Tracer struct {\n\tLogger logger.Interface"
  },
  {
    "path": "tests/transaction_test.go",
    "chars": 13650,
    "preview": "package tests_test\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"testing\"\n\t\"time\"\n\n\t\"gorm.io/gorm\"\n\t. \"gorm.io/gorm/utils/tests\"\n)\n\nf"
  },
  {
    "path": "tests/update_belongs_to_test.go",
    "chars": 1672,
    "preview": "package tests_test\n\nimport (\n\t\"testing\"\n\n\t\"gorm.io/gorm\"\n\t. \"gorm.io/gorm/utils/tests\"\n)\n\nfunc TestUpdateBelongsTo(t *te"
  },
  {
    "path": "tests/update_has_many_test.go",
    "chars": 2028,
    "preview": "package tests_test\n\nimport (\n\t\"testing\"\n\n\t\"gorm.io/gorm\"\n\t. \"gorm.io/gorm/utils/tests\"\n)\n\nfunc TestUpdateHasManyAssociat"
  },
  {
    "path": "tests/update_has_one_test.go",
    "chars": 3677,
    "preview": "package tests_test\n\nimport (\n\t\"database/sql\"\n\t\"testing\"\n\t\"time\"\n\n\t\"gorm.io/gorm\"\n\t. \"gorm.io/gorm/utils/tests\"\n)\n\nfunc T"
  },
  {
    "path": "tests/update_many2many_test.go",
    "chars": 1377,
    "preview": "package tests_test\n\nimport (\n\t\"testing\"\n\n\t\"gorm.io/gorm\"\n\t. \"gorm.io/gorm/utils/tests\"\n)\n\nfunc TestUpdateMany2ManyAssoci"
  },
  {
    "path": "tests/update_test.go",
    "chars": 31136,
    "preview": "package tests_test\n\nimport (\n\t\"errors\"\n\t\"regexp\"\n\t\"sort\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t\"gorm.io/gorm\"\n\t\"gorm.io/gorm/c"
  },
  {
    "path": "tests/upsert_test.go",
    "chars": 13413,
    "preview": "package tests_test\n\nimport (\n\t\"regexp\"\n\t\"testing\"\n\t\"time\"\n\n\t\"gorm.io/gorm\"\n\t\"gorm.io/gorm/clause\"\n\t. \"gorm.io/gorm/utils"
  },
  {
    "path": "utils/tests/dummy_dialecter.go",
    "chars": 2231,
    "preview": "package tests\n\nimport (\n\t\"gorm.io/gorm\"\n\t\"gorm.io/gorm/callbacks\"\n\t\"gorm.io/gorm/clause\"\n\t\"gorm.io/gorm/logger\"\n\t\"gorm.i"
  },
  {
    "path": "utils/tests/models.go",
    "chars": 2187,
    "preview": "package tests\n\nimport (\n\t\"database/sql\"\n\t\"time\"\n\n\t\"gorm.io/gorm\"\n)\n\n// User has one `Account` (has one), many `Pets` (ha"
  },
  {
    "path": "utils/tests/utils.go",
    "chars": 3963,
    "preview": "package tests\n\nimport (\n\t\"database/sql/driver\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"reflect\"\n\t\"testing\"\n\t\"time\"\n\n\t\"gorm.io/gorm/utils\"\n)\n\n"
  },
  {
    "path": "utils/utils.go",
    "chars": 4635,
    "preview": "package utils\n\nimport (\n\t\"database/sql/driver\"\n\t\"fmt\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"runtime\"\n\t\"strconv\"\n\t\"strings\"\n\t\"uni"
  },
  {
    "path": "utils/utils_test.go",
    "chars": 5021,
    "preview": "package utils\n\nimport (\n\t\"database/sql\"\n\t\"database/sql/driver\"\n\t\"errors\"\n\t\"math\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n)\n\nfunc T"
  },
  {
    "path": "utils/utils_unix_test.go",
    "chars": 731,
    "preview": "//go:build unix\n// +build unix\n\npackage utils\n\nimport (\n\t\"testing\"\n)\n\nfunc TestSourceDir(t *testing.T) {\n\tcases := []str"
  },
  {
    "path": "utils/utils_windows_test.go",
    "chars": 715,
    "preview": "package utils\n\nimport (\n\t\"testing\"\n)\n\nfunc TestSourceDir(t *testing.T) {\n\tcases := []struct {\n\t\tfile string\n\t\twant strin"
  }
]

About this extraction

This page contains the full source code of the go-gorm/gorm GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 184 files (1.2 MB), approximately 367.6k tokens, and a symbol index with 1607 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!