├── .github ├── ops │ └── mysql │ │ └── Dockerfile └── workflows │ ├── cd-docker-push-cockroach_oss.yaml │ ├── cd-docker-push-mysql_oss.yaml │ ├── ci-dialect_oss.yaml │ ├── ci-go_oss.yaml │ └── ci-revisions_oss.yaml ├── .golangci.yml ├── LICENSE ├── README.md ├── cmd └── atlas │ ├── go.mod │ ├── go.sum │ ├── internal │ ├── cloudapi │ │ ├── client.go │ │ ├── client_oss.go │ │ └── client_test.go │ ├── cmdapi │ │ ├── cmdapi.go │ │ ├── cmdapi_oss.go │ │ ├── cmdapi_test.go │ │ ├── migrate.go │ │ ├── migrate_oss.go │ │ ├── migrate_test.go │ │ ├── project.go │ │ ├── project_test.go │ │ ├── schema.go │ │ ├── schema_test.go │ │ ├── testdata │ │ │ ├── baseline1 │ │ │ │ ├── 1_baseline.sql │ │ │ │ └── atlas.sum │ │ │ ├── baseline2 │ │ │ │ ├── 1_baseline.sql │ │ │ │ ├── 20220318104614_initial.sql │ │ │ │ ├── 20220318104615_second.sql │ │ │ │ └── atlas.sum │ │ │ ├── import │ │ │ │ ├── dbmate │ │ │ │ │ ├── 1_initial.sql │ │ │ │ │ └── 2_second_migration.sql │ │ │ │ ├── dbmate_gold │ │ │ │ │ ├── 1_initial.sql │ │ │ │ │ └── 2_second_migration.sql │ │ │ │ ├── flyway │ │ │ │ │ ├── B2__baseline.sql │ │ │ │ │ ├── R__views.sql │ │ │ │ │ ├── U1__initial.sql │ │ │ │ │ ├── V1__initial.sql │ │ │ │ │ ├── V2__second_migration.sql │ │ │ │ │ └── V3__third_migration.sql │ │ │ │ ├── flyway_gold │ │ │ │ │ ├── 2_baseline.sql │ │ │ │ │ ├── 3R_views.sql │ │ │ │ │ └── 3_third_migration.sql │ │ │ │ ├── golang-migrate │ │ │ │ │ ├── 1_initial.down.sql │ │ │ │ │ ├── 1_initial.up.sql │ │ │ │ │ ├── 2_second_migration.down.sql │ │ │ │ │ └── 2_second_migration.up.sql │ │ │ │ ├── golang-migrate_gold │ │ │ │ │ ├── 1_initial.sql │ │ │ │ │ └── 2_second_migration.sql │ │ │ │ ├── goose │ │ │ │ │ ├── 1_initial.sql │ │ │ │ │ └── 2_second_migration.sql │ │ │ │ ├── goose_gold │ │ │ │ │ ├── 1_initial.sql │ │ │ │ │ └── 2_second_migration.sql │ │ │ │ ├── liquibase │ │ │ │ │ ├── 1_initial.sql │ │ │ │ │ └── 2_second_migration.sql │ │ │ │ └── liquibase_gold │ │ │ │ │ ├── 1_initial.sql │ │ │ │ │ └── 2_second_migration.sql │ │ │ ├── mysql │ │ │ │ ├── 20220318104614_initial.sql │ │ │ │ ├── 20220420213403_second.sql │ │ │ │ └── atlas.sum │ │ │ ├── sqlite │ │ │ │ ├── 20220318104614_initial.sql │ │ │ │ ├── 20220318104615_second.sql │ │ │ │ └── atlas.sum │ │ │ ├── sqlite2 │ │ │ │ ├── 20220318104614_initial.sql │ │ │ │ ├── 20220318104615_second.sql │ │ │ │ └── atlas.sum │ │ │ ├── sqlitetx │ │ │ │ ├── 20220925092817_initial.sql │ │ │ │ ├── 20220925094021_second.sql │ │ │ │ ├── 20220925094437_third.sql │ │ │ │ └── atlas.sum │ │ │ ├── sqlitetx2 │ │ │ │ ├── 20220925092817_initial.sql │ │ │ │ ├── 20220925094021_second.sql │ │ │ │ ├── 20220925094437_third.sql │ │ │ │ └── atlas.sum │ │ │ ├── sqlitetx3 │ │ │ │ ├── 20220925092817_initial.sql │ │ │ │ ├── 20220925094021_second.sql │ │ │ │ └── atlas.sum │ │ │ ├── sqlitetx4 │ │ │ │ ├── 20220925092817_initial.sql │ │ │ │ ├── 20220925094021_second.sql │ │ │ │ └── atlas.sum │ │ │ └── templatedir │ │ │ │ ├── 1.sql │ │ │ │ ├── 2.sql │ │ │ │ ├── atlas.sum │ │ │ │ └── shared │ │ │ │ └── users.sql │ │ ├── vercheck │ │ │ ├── notification.tmpl │ │ │ ├── req_oss.go │ │ │ ├── vercheck.go │ │ │ └── vercheck_test.go │ │ ├── version_oss.go │ │ └── version_oss_test.go │ ├── cmdext │ │ ├── cmdext.go │ │ ├── cmdext_oss.go │ │ ├── cmdext_test.go │ │ ├── reader.go │ │ └── reader_test.go │ ├── cmdlog │ │ ├── cmdlog.go │ │ ├── cmdlog_oss.go │ │ └── cmdlog_test.go │ ├── cmdstate │ │ ├── cmdstate.go │ │ └── cmdstate_test.go │ ├── docker │ │ ├── docker.go │ │ └── docker_test.go │ ├── migrate │ │ ├── ent │ │ │ ├── client.go │ │ │ ├── convert.go │ │ │ ├── ent.go │ │ │ ├── entc.go │ │ │ ├── enttest │ │ │ │ └── enttest.go │ │ │ ├── generate.go │ │ │ ├── hook │ │ │ │ └── hook.go │ │ │ ├── internal │ │ │ │ └── schemaconfig.go │ │ │ ├── migrate │ │ │ │ ├── migrate.go │ │ │ │ └── schema.go │ │ │ ├── mutation.go │ │ │ ├── predicate │ │ │ │ └── predicate.go │ │ │ ├── revision.go │ │ │ ├── revision │ │ │ │ ├── revision.go │ │ │ │ └── where.go │ │ │ ├── revision_create.go │ │ │ ├── revision_delete.go │ │ │ ├── revision_query.go │ │ │ ├── revision_update.go │ │ │ ├── runtime.go │ │ │ ├── runtime │ │ │ │ └── runtime.go │ │ │ ├── schema │ │ │ │ └── revision.go │ │ │ ├── template │ │ │ │ └── convert.tmpl │ │ │ └── tx.go │ │ ├── migrate.go │ │ ├── migrate_oss.go │ │ ├── migrate_test.go │ │ └── testdata │ │ │ ├── broken │ │ │ ├── 1.sql │ │ │ ├── 2.sql │ │ │ ├── 3.sql │ │ │ └── atlas.sum │ │ │ └── fixed │ │ │ ├── 1.sql │ │ │ ├── 2.sql │ │ │ ├── 3.sql │ │ │ └── atlas.sum │ ├── migratelint │ │ ├── lint.go │ │ ├── lint_oss.go │ │ └── lint_test.go │ └── sqlparse │ │ ├── myparse │ │ └── myparse_oss.go │ │ ├── parseutil │ │ └── parseutil.go │ │ ├── pgparse │ │ └── pgparse_oss.go │ │ ├── sqliteparse │ │ ├── Lexer.g4 │ │ ├── Parser.g4 │ │ ├── README.md │ │ ├── lexer.go │ │ ├── parser.go │ │ ├── parser_base_listener.go │ │ ├── parser_base_visitor.go │ │ ├── parser_listener.go │ │ ├── parser_visitor.go │ │ └── sqliteparse_oss.go │ │ └── sqlparse.go │ ├── main.go │ └── main_oss.go ├── go.mod ├── go.sum ├── internal ├── ci │ ├── ci_dialect.tmpl │ ├── ci_go.tmpl │ ├── ci_revisions.tmpl │ ├── cockroach │ │ ├── Dockerfile.tmpl │ │ └── main.go │ ├── jobs_oss.go │ └── main.go └── integration │ ├── README.md │ ├── cockroach_test.go │ ├── docker-compose.yaml │ ├── go.mod │ ├── go.sum │ ├── hclsqlspec │ └── hclsqlspec_test.go │ ├── integration_test.go │ ├── mysql_test.go │ ├── postgres_test.go │ ├── script_test.go │ ├── sqlite_test.go │ ├── testdata │ ├── migrations │ │ ├── mysql │ │ │ ├── 1_initial.sql │ │ │ └── atlas.sum │ │ ├── mysqlock │ │ │ ├── 1.sql │ │ │ ├── 2.sql │ │ │ ├── 3.sql │ │ │ └── atlas.sum │ │ └── postgres │ │ │ ├── 1_initial.sql │ │ │ └── atlas.sum │ ├── mysql │ │ ├── autoincrement.txtar │ │ ├── check-maria.txtar │ │ ├── check.txtar │ │ ├── cli-inspect-file.txtar │ │ ├── cli-migrate-apply-datasrc.txtar │ │ ├── cli-migrate-apply.txtar │ │ ├── cli-migrate-diff-format.txtar │ │ ├── cli-migrate-diff-mode-normalized.txtar │ │ ├── cli-migrate-diff.txtar │ │ ├── cli-project-schemas.txtar │ │ ├── cli-project-url-escape.txtar │ │ ├── cli-schema-apply-datasrc.txtar │ │ ├── column-add-drop.txtar │ │ ├── column-bit.txtar │ │ ├── column-bool.txtar │ │ ├── column-charset.txtar │ │ ├── column-default-expr.txtar │ │ ├── column-generated-inspect.txtar │ │ ├── column-generated.txtar │ │ ├── column-json.txtar │ │ ├── column-time-precision-maria.txtar │ │ ├── column-time-precision-mysql.txtar │ │ ├── foreign-key-add.txtar │ │ ├── foreign-key-modify-action.txtar │ │ ├── foreign-key.txtar │ │ ├── index-add-drop.txtar │ │ ├── index-desc.txtar │ │ ├── index-expr.txtar │ │ ├── index-prefix.txtar │ │ ├── index-type.txtar │ │ ├── index-unique.txtar │ │ ├── primary-key-parts.txtar │ │ ├── primary-key.txtar │ │ └── table-engine.txtar │ ├── postgres │ │ ├── cli-inspect-file.txtar │ │ ├── cli-inspect.txtar │ │ ├── cli-migrate-apply-datasrc.txtar │ │ ├── cli-migrate-apply.txtar │ │ ├── cli-migrate-diff-unsupported.txtar │ │ ├── cli-migrate-diff.txtar │ │ ├── cli-migrate-status.txtar │ │ ├── column-array.txtar │ │ ├── column-bit.txtar │ │ ├── column-comment.txtar │ │ ├── column-default.txtar │ │ ├── column-domain.txtar │ │ ├── column-enum-array.txtar │ │ ├── column-enum.txtar │ │ ├── column-float.txtar │ │ ├── column-generated-inspect.txtar │ │ ├── column-identity.txtar │ │ ├── column-interval.txtar │ │ ├── column-numeric.txtar │ │ ├── column-range.txtar │ │ ├── column-serial.txtar │ │ ├── column-textsearch.txtar │ │ ├── column-time-precision.txtar │ │ ├── foreign-key-action.txtar │ │ ├── foreign-key.txtar │ │ ├── index-desc.txtar │ │ ├── index-expr.txtar │ │ ├── index-include.txtar │ │ ├── index-issue-557.txtar │ │ ├── index-nulls-distinct.txtar │ │ ├── index-operator-class.txtar │ │ ├── index-partial.txtar │ │ ├── index-type-brin.txtar │ │ ├── index-type.txtar │ │ ├── index-unique-constraint.txtar │ │ ├── primary-key.txtar │ │ ├── table-checks.txtar │ │ └── table-partition.txtar │ └── sqlite │ │ ├── autoincrement.txtar │ │ ├── cli-apply-multifile.txtar │ │ ├── cli-apply-project-multifile.txtar │ │ ├── cli-apply-vars.txtar │ │ ├── cli-inspect.txtar │ │ ├── cli-migrate-apply.txtar │ │ ├── cli-migrate-diff-datasrc-hcl-paths.txtar │ │ ├── cli-migrate-diff-datasrc-hcl.txtar │ │ ├── cli-migrate-diff-minimal-env.txtar │ │ ├── cli-migrate-diff-multifile.txtar │ │ ├── cli-migrate-diff-sql.txtar │ │ ├── cli-migrate-diff.txtar │ │ ├── cli-migrate-lint-add-notnull.txtar │ │ ├── cli-migrate-lint-destructive.txtar │ │ ├── cli-migrate-lint-ignore.txtar │ │ ├── cli-migrate-lint-minimal-env.txtar │ │ ├── cli-migrate-lint-project.txtar │ │ ├── cli-migrate-project-multifile.txtar │ │ ├── cli-migrate-project.txtar │ │ ├── cli-migrate-set.txtar │ │ ├── cli-project-vars.txtar │ │ ├── cli-schema-project-file.txtar │ │ ├── column-default.txtar │ │ ├── column-generated.txtar │ │ ├── column-user-defined.txtar │ │ ├── index-desc.txtar │ │ ├── index-expr.txtar │ │ ├── index-partial.txtar │ │ └── table-options.txtar │ ├── tidb_test.go │ └── tools.go ├── schemahcl ├── context.go ├── context_test.go ├── extension.go ├── extension_test.go ├── schemahcl.go ├── schemahcl_test.go ├── spec.go ├── spec_test.go ├── stdlib.go ├── stdlib_test.go ├── testdata │ ├── a.hcl │ ├── b.hcl │ ├── nested │ │ └── c.hcl │ └── variables.hcl ├── types.go └── types_test.go └── sql ├── internal ├── spectest │ └── spectest.go ├── specutil │ ├── convert.go │ ├── convert_test.go │ └── spec.go ├── sqltest │ └── sqltest.go └── sqlx │ ├── dev.go │ ├── dev_test.go │ ├── diff.go │ ├── plan.go │ ├── plan_test.go │ ├── sqlx.go │ ├── sqlx_oss.go │ └── sqlx_test.go ├── migrate ├── dir.go ├── dir_test.go ├── lex.go ├── lex_test.go ├── migrate.go ├── migrate_oss.go ├── migrate_test.go └── testdata │ ├── golang-migrate │ └── 1_base.up.sql │ ├── lex │ ├── 1.sql │ ├── 1.sql.golden │ ├── 10_delimiter_comment.sql │ ├── 10_delimiter_comment.sql.golden │ ├── 11_delimiter_mysql_command.sql │ ├── 11_delimiter_mysql_command.sql.golden │ ├── 12_delimiter_mysql_command.sql │ ├── 12_delimiter_mysql_command.sql.golden │ ├── 13_delimiter_mysql_command.sql │ ├── 13_delimiter_mysql_command.sql.golden │ ├── 14_delimiter_mysql_command.sql │ ├── 14_delimiter_mysql_command.sql.golden │ ├── 15_dollar_quote.sql │ ├── 15_dollar_quote.sql.golden │ ├── 16_begin_atomic.sql │ ├── 16_begin_atomic.sql.golden │ ├── 17_paren.sql │ ├── 17_paren.sql.golden │ ├── 18_pg_expr.sql │ ├── 18_pg_expr.sql.golden │ ├── 19_ms_gocmd.sql │ ├── 19_ms_gocmd.sql.golden │ ├── 20_ms_go-delim.sql │ ├── 20_ms_go-delim.sql.golden │ ├── 2_mysql.sql │ ├── 2_mysql.sql.golden │ ├── 3_delimiter.sql │ ├── 3_delimiter.sql.golden │ ├── 4_delimiter.sql │ ├── 4_delimiter.sql.golden │ ├── 5_delimiter.sql │ ├── 5_delimiter.sql.golden │ ├── 6_skip_comment.sql │ ├── 6_skip_comment.sql.golden │ ├── 7_delimiter_2n.sql │ ├── 7_delimiter_2n.sql.golden │ ├── 8_delimiter_3n.sql │ ├── 8_delimiter_3n.sql.golden │ ├── 9_delimiter_3n.sql │ └── 9_delimiter_3n.sql.golden │ ├── lexbegintry │ ├── 1.sql │ └── 1.sql.golden │ ├── lexescaped │ ├── 1.my.sql │ ├── 1.my.sql.golden │ ├── 2.pg.sql │ └── 2.pg.sql.golden │ ├── lexgroup │ ├── 1_trigger.sql │ ├── 1_trigger.sql.golden │ ├── 2_function.sql │ ├── 2_function.sql.golden │ ├── 3_delimiter.sql │ └── 3_delimiter.sql.golden │ ├── migrate │ ├── 1_initial.down.sql │ ├── 1_initial.up.sql │ ├── atlas.sum │ └── sub │ │ ├── 1.a_sub.up.sql │ │ ├── 2.10.x-20_description.sql │ │ ├── 3_partly.sql │ │ └── atlas.sum │ ├── partial-checkpoint │ ├── 1_first.sql │ ├── 2_second.sql │ ├── 3_checkpoint.sql │ ├── 4_fourth.sql │ ├── 5_checkpoint.sql │ ├── 6_sixth.sql │ └── atlas.sum │ └── sqlserver │ ├── 1_return_table.sql │ ├── 1_return_table.sql.golden │ ├── 2_function.sql │ └── 2_function.sql.golden ├── mysql ├── convert.go ├── diff_oss.go ├── diff_oss_test.go ├── driver_oss.go ├── driver_oss_test.go ├── inspect_oss.go ├── inspect_oss_test.go ├── internal │ └── mysqlversion │ │ ├── is │ │ ├── .README.md │ │ ├── charset2collate │ │ ├── charset2collate.maria │ │ ├── collate2charset │ │ └── collate2charset.maria │ │ ├── mysqlversion.go │ │ └── mysqlversion_test.go ├── migrate_oss.go ├── migrate_oss_test.go ├── mysqlcheck │ ├── mysqlcheck.go │ ├── mysqlcheck_oss.go │ └── mysqlcheck_test.go ├── sqlspec_oss.go ├── sqlspec_oss_test.go └── tidb.go ├── postgres ├── convert.go ├── crdb_oss.go ├── diff_oss.go ├── diff_oss_test.go ├── driver_oss.go ├── driver_oss_test.go ├── inspect_oss.go ├── inspect_oss_test.go ├── internal │ └── postgresop │ │ └── postgresop.go ├── migrate_oss.go ├── migrate_oss_test.go ├── postgrescheck │ ├── postgrescheck.go │ ├── postgrescheck_oss.go │ └── postgrescheck_test.go ├── sqlspec_oss.go └── sqlspec_oss_test.go ├── schema ├── changekind_string.go ├── dsl.go ├── dsl_test.go ├── exclude_oss.go ├── inspect.go ├── migrate.go ├── migrate_test.go └── schema.go ├── sqlcheck ├── condrop │ ├── condrop.go │ └── condrop_test.go ├── datadepend │ ├── datadepend.go │ └── datadepend_test.go ├── destructive │ ├── destructive.go │ ├── destructive_oss.go │ └── destructive_test.go ├── incompatible │ ├── incompatible.go │ └── incompatible_test.go └── sqlcheck.go ├── sqlclient ├── client.go └── client_test.go ├── sqlite ├── convert.go ├── diff.go ├── diff_test.go ├── driver.go ├── driver_oss.go ├── driver_test.go ├── inspect.go ├── inspect_test.go ├── migrate.go ├── migrate_test.go ├── sqlitecheck │ ├── sqlitecheck.go │ ├── sqlitecheck_oss.go │ └── sqlitecheck_test.go ├── sqlspec.go └── sqlspec_test.go ├── sqlspec ├── sqlspec.go └── sqlspec_test.go └── sqltool ├── doc.go ├── hidden.go ├── hidden_windows.go ├── testdata ├── dbmate │ ├── 1_initial.sql │ └── 2_second_migration.sql ├── flyway │ ├── B2__baseline.sql │ ├── R__views.sql │ ├── U1__initial.sql │ ├── V1__initial.sql │ ├── V2__second_migration.sql │ ├── V3__third_migration.sql │ └── v3 │ │ └── V3_1__fourth_migration.sql ├── golang-migrate │ ├── 1_initial.down.sql │ ├── 1_initial.up.sql │ ├── 2_second_migration.down.sql │ └── 2_second_migration.up.sql ├── goose │ ├── 1_initial.sql │ └── 2_second_migration.sql └── liquibase │ ├── 1_initial.sql │ └── 2_second_migration.sql ├── tool.go └── tool_test.go /.github/ops/mysql/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG DIALECT=mysql:8.0 2 | 3 | FROM $DIALECT as builder 4 | 5 | ARG SERVER=mysqld 6 | ENV MYSQL_ROOT_PASSWORD=pass 7 | 8 | # Remove the last line of the entry point script, leaving the initialization code but omitting actually starting the db. 9 | RUN sed -i 's/exec "$@"/echo "not running $@"/' /usr/local/bin/docker-entrypoint.sh 10 | RUN /usr/local/bin/docker-entrypoint.sh ${SERVER} 11 | 12 | FROM $DIALECT 13 | 14 | COPY --from=builder /var/lib/mysql /var/lib/mysql 15 | -------------------------------------------------------------------------------- /.github/workflows/cd-docker-push-cockroach_oss.yaml: -------------------------------------------------------------------------------- 1 | name: CD - Build Docker - Cockroach - Community Edition 2 | on: 3 | pull_request: 4 | push: 5 | branches: 6 | - master 7 | 8 | env: 9 | CRDB_VERSIONS: v21.2.11 v22.1.0 10 | 11 | jobs: 12 | build-services: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v4 16 | - uses: actions/setup-go@v5 17 | with: 18 | go-version-file: cmd/atlas/go.mod 19 | - name: Log in to registry 20 | run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin 21 | - name: "build cockroach image" 22 | run: | 23 | VER="${{ env.CRDB_VERSIONS }}" 24 | for i in $VER 25 | do 26 | : 27 | if ! docker manifest inspect ghcr.io/ariga/cockroachdb-single-node:$i; then 28 | go run internal/ci/cockroach/main.go $i > internal/ci/cockroach/Dockerfile 29 | docker build -t ghcr.io/ariga/cockroachdb-single-node:$i internal/ci/cockroach/ 30 | docker push ghcr.io/ariga/cockroachdb-single-node:$i 31 | else 32 | echo image already exists 33 | fi 34 | done -------------------------------------------------------------------------------- /.github/workflows/ci-revisions_oss.yaml: -------------------------------------------------------------------------------- 1 | # # # # # # # # # # # # # # # # 2 | # CODE GENERATED - DO NOT EDIT 3 | # # # # # # # # # # # # # # # # 4 | name: CI - Revisions - Community Edition 5 | on: 6 | pull_request: 7 | paths: 8 | - 'cmd/atlas/internal/migrate/ent/**' 9 | push: 10 | branches: 11 | - master 12 | paths: 13 | - 'cmd/atlas/internal/migrate/ent/**' 14 | concurrency: 15 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 16 | cancel-in-progress: true 17 | jobs: 18 | revisions: 19 | runs-on: ubuntu-latest 20 | steps: 21 | - uses: actions/checkout@v4 22 | with: 23 | fetch-depth: 0 24 | - uses: actions/setup-go@v5 25 | with: 26 | go-version-file: cmd/atlas/go.mod 27 | - name: Checkout origin/master 28 | run: git checkout origin/master 29 | - name: Create revisions from master 30 | run: go run . migrate apply --dir file://internal/cmdapi/testdata/sqlite --url sqlite://db?_fk=1 31 | working-directory: cmd/atlas 32 | - name: Checkout previous HEAD 33 | run: git checkout - 34 | - name: Migrate revisions table to HEAD 35 | run: go run . migrate apply --dir file://internal/cmdapi/testdata/sqlite --url sqlite://db?_fk=1 36 | working-directory: cmd/atlas -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | run: 2 | timeout: 3m 3 | 4 | issues: 5 | include: 6 | - EXC0012 7 | exclude: 8 | - G601 9 | - G404 10 | - redefines-builtin-id 11 | exclude-rules: 12 | - path: _test\.go 13 | linters: 14 | - gosec 15 | - path: sql/migrate/dir.go 16 | linters: 17 | - gosec 18 | - path: sql/migrate/lex.go 19 | linters: 20 | - revive 21 | - path: sql/internal/sqlx/diff.go 22 | linters: 23 | - revive 24 | 25 | linters-settings: 26 | goheader: 27 | template: |- 28 | Copyright 2021-present The Atlas Authors. All rights reserved. 29 | This source code is licensed under the Apache 2.0 license found 30 | in the LICENSE file in the root directory of this source tree. 31 | 32 | linters: 33 | disable-all: true 34 | enable: 35 | - gosec 36 | - revive 37 | - goheader 38 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cloudapi/client_oss.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-present The Atlas Authors. All rights reserved. 2 | // This source code is licensed under the Apache 2.0 license found 3 | // in the LICENSE file in the root directory of this source tree. 4 | 5 | //go:build !ent 6 | 7 | package cloudapi 8 | 9 | import ( 10 | "net/url" 11 | ) 12 | 13 | func testingURL(endpoint string) bool { 14 | u, err := url.Parse(endpoint) 15 | if err != nil { 16 | return false 17 | } 18 | host := u.Hostname() 19 | return host == "localhost" || host == "127.0.0.1" 20 | } 21 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/baseline1/1_baseline.sql: -------------------------------------------------------------------------------- 1 | -- create "baseline" table 2 | CREATE TABLE baseline (`c` int NOT NULL); 3 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/baseline1/atlas.sum: -------------------------------------------------------------------------------- 1 | h1:GqOjMVGk2H0qYhhtJ1SPCyyHEBbWP/LD2ueWQTY4e6A= 2 | 1_baseline.sql h1:rZgkRmNcN2UEKgxru1nHCpBRVn/fjFavyQ4xxPxhrD4= 3 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/baseline2/1_baseline.sql: -------------------------------------------------------------------------------- 1 | -- create "baseline" table 2 | CREATE TABLE baseline (`c` int NOT NULL); 3 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/baseline2/20220318104614_initial.sql: -------------------------------------------------------------------------------- 1 | -- create "tbl" table 2 | CREATE TABLE tbl (`col` int NOT NULL); 3 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/baseline2/20220318104615_second.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE `tbl` ADD `col_2` bigint; 2 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/baseline2/atlas.sum: -------------------------------------------------------------------------------- 1 | h1:sxNQqhuqhm1fLpr3WN9N/M/niaS81Y7k5RrSaKpmBZE= 2 | 1_baseline.sql h1:rZgkRmNcN2UEKgxru1nHCpBRVn/fjFavyQ4xxPxhrD4= 3 | 20220318104614_initial.sql h1:/B1/+IxzgrRc4tCm1tpcpMhocHgqkdWF+iffxuguYaQ= 4 | 20220318104615_second.sql h1:nUc1cUvm8BzjTZdbavM1IRlNpfhtyY3YyZJ8v23K9j4= 5 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/import/dbmate/1_initial.sql: -------------------------------------------------------------------------------- 1 | -- migrate:up 2 | CREATE TABLE post 3 | ( 4 | id int NOT NULL, 5 | title text, 6 | body text, 7 | PRIMARY KEY (id) 8 | ); 9 | 10 | /* 11 | Multiline comment ... 12 | */ 13 | ALTER TABLE post ADD created_at TIMESTAMP NOT NULL; 14 | 15 | -- Normal comment 16 | -- With a second line 17 | INSERT INTO post (title) VALUES ( 18 | 'This is 19 | my multiline 20 | 21 | value'); 22 | 23 | -- migrate:down 24 | 25 | 26 | DROP TABLE post; -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/import/dbmate/2_second_migration.sql: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -- migrate:up 5 | 6 | 7 | 8 | 9 | CREATE TABLE tbl_2 (col INT); -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/import/dbmate_gold/1_initial.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE post 2 | ( 3 | id int NOT NULL, 4 | title text, 5 | body text, 6 | PRIMARY KEY (id) 7 | ); 8 | /* 9 | Multiline comment ... 10 | */ 11 | ALTER TABLE post ADD created_at TIMESTAMP NOT NULL; 12 | -- Normal comment 13 | -- With a second line 14 | INSERT INTO post (title) VALUES ( 15 | 'This is 16 | my multiline 17 | 18 | value'); 19 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/import/dbmate_gold/2_second_migration.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE tbl_2 (col INT); 2 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/import/flyway/B2__baseline.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE post 2 | ( 3 | id int NOT NULL, 4 | title text, 5 | body text, 6 | created_at TIMESTAMP NOT NULL 7 | PRIMARY KEY (id) 8 | ); 9 | 10 | INSERT INTO post (title, created_at) VALUES ( 11 | 'This is 12 | my multiline 13 | 14 | value', NOW()); -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/import/flyway/R__views.sql: -------------------------------------------------------------------------------- 1 | CREATE VIEW `my_view` AS SELECT * FROM `post`; -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/import/flyway/U1__initial.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE tbl; -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/import/flyway/V1__initial.sql: -------------------------------------------------------------------------------- 1 | -- comment 2 | CREATE TABLE post 3 | ( 4 | id int NOT NULL, 5 | title text, 6 | body text, 7 | PRIMARY KEY (id) 8 | ); 9 | 10 | ALTER TABLE post ADD created_at TIMESTAMP NOT NULL; 11 | 12 | INSERT INTO post (title, created_at) VALUES ( 13 | 'This is 14 | my multiline 15 | 16 | value', NOW()); 17 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/import/flyway/V2__second_migration.sql: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -- migrate:up 5 | 6 | 7 | 8 | 9 | CREATE TABLE tbl_2 (col INT); -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/import/flyway/V3__third_migration.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE tbl_2 ADD col_1 INTEGER NOT NULL; -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/import/flyway_gold/2_baseline.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE post 2 | ( 3 | id int NOT NULL, 4 | title text, 5 | body text, 6 | created_at TIMESTAMP NOT NULL 7 | PRIMARY KEY (id) 8 | ); 9 | INSERT INTO post (title, created_at) VALUES ( 10 | 'This is 11 | my multiline 12 | 13 | value', NOW()); 14 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/import/flyway_gold/3R_views.sql: -------------------------------------------------------------------------------- 1 | CREATE VIEW `my_view` AS SELECT * FROM `post`; 2 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/import/flyway_gold/3_third_migration.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE tbl_2 ADD col_1 INTEGER NOT NULL; 2 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/import/golang-migrate/1_initial.down.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE tbl; -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/import/golang-migrate/1_initial.up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE tbl 2 | ( 3 | col INT 4 | ); -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/import/golang-migrate/2_second_migration.down.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE tbl_2; -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/import/golang-migrate/2_second_migration.up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE tbl_2 (col INT); -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/import/golang-migrate_gold/1_initial.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE tbl 2 | ( 3 | col INT 4 | ); 5 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/import/golang-migrate_gold/2_second_migration.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE tbl_2 (col INT); 2 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/import/goose/1_initial.sql: -------------------------------------------------------------------------------- 1 | -- +goose Up 2 | CREATE TABLE post 3 | ( 4 | id int NOT NULL, 5 | title text, 6 | body text, 7 | PRIMARY KEY (id) 8 | ); 9 | 10 | ALTER TABLE post ADD created_at TIMESTAMP NOT NULL; 11 | 12 | INSERT INTO post (title) VALUES ( 13 | 'This is 14 | my multiline 15 | 16 | value'); 17 | 18 | -- +goose Down 19 | DROP TABLE post; -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/import/goose/2_second_migration.sql: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -- +goose Up 5 | 6 | 7 | ALTER TABLE post ADD updated_at TIMESTAMP NOT NULL; 8 | 9 | -- +goose StatementBegin 10 | -- Comment for the function declaration. 11 | CREATE 12 | OR REPLACE FUNCTION histories_partition_creation( DATE, DATE ) 13 | returns void AS $$ 14 | DECLARE 15 | create_query text; 16 | BEGIN 17 | FOR create_query IN 18 | SELECT 'CREATE TABLE IF NOT EXISTS histories_' 19 | || TO_CHAR(d, 'YYYY_MM') 20 | || ' ( CHECK( created_at >= timestamp ''' 21 | || TO_CHAR(d, 'YYYY-MM-DD 00:00:00') 22 | || ''' AND created_at < timestamp ''' 23 | || TO_CHAR(d + INTERVAL '1 month', 'YYYY-MM-DD 00:00:00') 24 | || ''' ) ) inherits ( histories );' 25 | FROM generate_series($1, $2, '1 month') AS d LOOP 26 | EXECUTE create_query; 27 | END LOOP; -- LOOP END 28 | END; -- FUNCTION END 29 | $$ 30 | language plpgsql; 31 | -- +goose StatementEnd -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/import/goose_gold/1_initial.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE post 2 | ( 3 | id int NOT NULL, 4 | title text, 5 | body text, 6 | PRIMARY KEY (id) 7 | ); 8 | ALTER TABLE post ADD created_at TIMESTAMP NOT NULL; 9 | INSERT INTO post (title) VALUES ( 10 | 'This is 11 | my multiline 12 | 13 | value'); 14 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/import/goose_gold/2_second_migration.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE post ADD updated_at TIMESTAMP NOT NULL; 2 | -- Comment for the function declaration. 3 | CREATE 4 | OR REPLACE FUNCTION histories_partition_creation( DATE, DATE ) 5 | returns void AS $$ 6 | DECLARE 7 | create_query text; 8 | BEGIN 9 | FOR create_query IN 10 | SELECT 'CREATE TABLE IF NOT EXISTS histories_' 11 | || TO_CHAR(d, 'YYYY_MM') 12 | || ' ( CHECK( created_at >= timestamp ''' 13 | || TO_CHAR(d, 'YYYY-MM-DD 00:00:00') 14 | || ''' AND created_at < timestamp ''' 15 | || TO_CHAR(d + INTERVAL '1 month', 'YYYY-MM-DD 00:00:00') 16 | || ''' ) ) inherits ( histories );' 17 | FROM generate_series($1, $2, '1 month') AS d LOOP 18 | EXECUTE create_query; 19 | END LOOP; -- LOOP END 20 | END; -- FUNCTION END 21 | $$ 22 | language plpgsql; 23 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/import/liquibase/1_initial.sql: -------------------------------------------------------------------------------- 1 | --liquibase formatted sql 2 | 3 | --changeset atlas:1-1 4 | CREATE TABLE post 5 | ( 6 | id int NOT NULL, 7 | title text, 8 | body text, 9 | PRIMARY KEY (id) 10 | ); 11 | --rollback: DROP TABLE post; 12 | 13 | --changeset atlas:1-2 14 | ALTER TABLE post ADD created_at TIMESTAMP NOT NULL; 15 | --rollback: ALTER TABLE post DROP created_at; 16 | 17 | --changeset atlas:1-3 18 | INSERT INTO post (title) VALUES ( 19 | 'This is 20 | my multiline 21 | 22 | value'); 23 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/import/liquibase/2_second_migration.sql: -------------------------------------------------------------------------------- 1 | --liquibase formatted sql 2 | 3 | --changeset atlas:2-1 4 | CREATE TABLE tbl_2 (col INT); 5 | --rollback DROP TABLE tbl_2; 6 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/import/liquibase_gold/1_initial.sql: -------------------------------------------------------------------------------- 1 | --changeset atlas:1-1 2 | CREATE TABLE post 3 | ( 4 | id int NOT NULL, 5 | title text, 6 | body text, 7 | PRIMARY KEY (id) 8 | ); 9 | --changeset atlas:1-2 10 | ALTER TABLE post ADD created_at TIMESTAMP NOT NULL; 11 | --changeset atlas:1-3 12 | INSERT INTO post (title) VALUES ( 13 | 'This is 14 | my multiline 15 | 16 | value'); 17 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/import/liquibase_gold/2_second_migration.sql: -------------------------------------------------------------------------------- 1 | --changeset atlas:2-1 2 | CREATE TABLE tbl_2 (col INT); 3 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/mysql/20220318104614_initial.sql: -------------------------------------------------------------------------------- 1 | -- add new schema named "atlantis" 2 | CREATE DATABASE `atlantis`; 3 | -- create "tbl" table 4 | CREATE TABLE `atlantis`.`tbl` (`col` int NOT NULL) CHARSET utf8mb4 COLLATE utf8mb4_general_ci; 5 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/mysql/20220420213403_second.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE `atlantis`.`tbl` ADD `col_2` TEXT; 2 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/mysql/atlas.sum: -------------------------------------------------------------------------------- 1 | h1:EGX5/CEEerpLWqYQNHB1veTXon8t05wEGJiX2fOtFXg= 2 | 20220318104614_initial.sql h1:EoDHPlX7fTGn5qiCdR5xhwFh+DrOi3cQ7Y49BsIy97k= 3 | 20220420213403_second.sql h1:cAioQjDgJkOIiMAyEwqaurPs0EHpTeu0CnWlJzNj5SE= 4 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/sqlite/20220318104614_initial.sql: -------------------------------------------------------------------------------- 1 | -- create "tbl" table 2 | CREATE TABLE tbl (`col` int NOT NULL); 3 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/sqlite/20220318104615_second.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE `tbl` ADD `col_2` bigint; 2 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/sqlite/atlas.sum: -------------------------------------------------------------------------------- 1 | h1:GMi7mvWSIHv0I/Wrc2NCGVt9Z5hWZbPa6wL986t7Z2o= 2 | 20220318104614_initial.sql h1:FifWjY2X0g2YVnb18Qm+QBPvoldDOOob7bS0LrFuCXc= 3 | 20220318104615_second.sql h1:wbPDlODOQeixCiopAhlT7W4xOO9TgJxzjYjxf4TA2f4= 4 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/sqlite2/20220318104614_initial.sql: -------------------------------------------------------------------------------- 1 | -- create "tbl" table 2 | CREATE TABLE tbl (`col` int NOT NULL); 3 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/sqlite2/20220318104615_second.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE `tbl` ADD `col_2` bigint; 2 | asdasd ALTER TABLE `tbl` ADD `col_3` bigint; -- will fail 3 | ALTER TABLE `tbl` ADD `col_4` bigint; 4 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/sqlite2/atlas.sum: -------------------------------------------------------------------------------- 1 | h1:lXdG49p5Vr5b9eARNKq3Gkgd+flbQXDM+XDyB6b2nzw= 2 | 20220318104614_initial.sql h1:FifWjY2X0g2YVnb18Qm+QBPvoldDOOob7bS0LrFuCXc= 3 | 20220318104615_second.sql h1:UA1TOODS2yU138E2HBlChe/O8vSmTRxkHs4OJOUK3K8= 4 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/sqlitetx/20220925092817_initial.sql: -------------------------------------------------------------------------------- 1 | -- create "users" table 2 | CREATE TABLE `users` (`id` integer NOT NULL, `name` text NULL, PRIMARY KEY (`id`)); 3 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/sqlitetx/20220925094021_second.sql: -------------------------------------------------------------------------------- 1 | -- create "friendships" table 2 | CREATE TABLE `friendships` (`user_id` integer NOT NULL, `friend_id` integer NOT NULL, PRIMARY KEY (`user_id`, `friend_id`), CONSTRAINT `user_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE, CONSTRAINT `friend_id_fk` FOREIGN KEY (`friend_id`) REFERENCES `users` (`id`) ON DELETE CASCADE); 3 | 4 | INSERT INTO `users` (`id`) VALUES (1), (2); 5 | INSERT INTO `friendships` (`user_id`, `friend_id`) VALUES (1,2), (2,1); 6 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/sqlitetx/20220925094437_third.sql: -------------------------------------------------------------------------------- 1 | -- disable the enforcement of foreign-keys constraints 2 | PRAGMA foreign_keys = off; 3 | -- create "new_users" table 4 | CREATE TABLE `new_users` (`id` integer NOT NULL, PRIMARY KEY (`id`)); 5 | -- copy rows from old table "users" to new temporary table "new_users" 6 | INSERT INTO `new_users` (`id`) SELECT `id` FROM `users`; 7 | -- drop "users" table after copying rows 8 | DROP TABLE `users`; 9 | -- rename temporary table "new_users" to "users" 10 | ALTER TABLE `new_users` RENAME TO `users`; 11 | -- enable back the enforcement of foreign-keys constraints 12 | PRAGMA foreign_keys = on; 13 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/sqlitetx/atlas.sum: -------------------------------------------------------------------------------- 1 | h1:09lkmQGTxdoqPwK0ZXtU4+KHipufkVp1Jlje3t6Opy4= 2 | 20220925092817_initial.sql h1:ZGeLdeqNUMXqJm+hPkhBrhzbtUzSBH8yVTsnSnJo/qU= 3 | 20220925094021_second.sql h1:vcoquz3yk+TlTPiQgW5hHpS/abIvySCM/bzgwYTDoqY= 4 | 20220925094437_third.sql h1:2pbBiUBKsEC5+ppfPPTDr+iwJSgZ2rM4qmHI44/vmnc= 5 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/sqlitetx2/20220925092817_initial.sql: -------------------------------------------------------------------------------- 1 | -- create "users" table 2 | CREATE TABLE `users` (`id` integer NOT NULL, `name` text NULL, PRIMARY KEY (`id`)); 3 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/sqlitetx2/20220925094021_second.sql: -------------------------------------------------------------------------------- 1 | -- create "friendships" table 2 | CREATE TABLE `friendships` (`user_id` integer NOT NULL, `friend_id` integer NOT NULL, PRIMARY KEY (`user_id`, `friend_id`), CONSTRAINT `user_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE, CONSTRAINT `friend_id_fk` FOREIGN KEY (`friend_id`) REFERENCES `users` (`id`) ON DELETE CASCADE); 3 | 4 | INSERT INTO `users` (`id`) VALUES (1), (2); 5 | INSERT INTO `friendships` (`user_id`, `friend_id`) VALUES (1,2), (2,1); 6 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/sqlitetx2/20220925094437_third.sql: -------------------------------------------------------------------------------- 1 | -- disable the enforcement of foreign-keys constraints 2 | PRAGMA foreign_keys = off; 3 | -- create "new_users" table 4 | CREATE TABLE `new_users` (`id` integer NOT NULL, PRIMARY KEY (`id`)); 5 | -- copy rows from old table "users" to new temporary table "new_users" 6 | INSERT INTO `new_users` (`id`) SELECT `id` FROM `users`; 7 | -- drop "users" table after copying rows 8 | DROP TABLE `users`; 9 | -- rename temporary table "new_users" to "users" 10 | ALTER TABLE `new_users` RENAME TO `users`; 11 | -- insert faulty data 12 | INSERT INTO `friendships` (`user_id`, `friend_id`) VALUES (3,2); 13 | -- enable back the enforcement of foreign-keys constraints 14 | PRAGMA foreign_keys = on; 15 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/sqlitetx2/atlas.sum: -------------------------------------------------------------------------------- 1 | h1:eH+7c2mVWbrhky00/3SKYklyHLyz+QzDk1UZJ9+ZJsg= 2 | 20220925092817_initial.sql h1:ZGeLdeqNUMXqJm+hPkhBrhzbtUzSBH8yVTsnSnJo/qU= 3 | 20220925094021_second.sql h1:vcoquz3yk+TlTPiQgW5hHpS/abIvySCM/bzgwYTDoqY= 4 | 20220925094437_third.sql h1:58glD96PVBa0fSu8x/3Gbwbf7N6WjAcVl4jh/XcNXoM= 5 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/sqlitetx3/20220925092817_initial.sql: -------------------------------------------------------------------------------- 1 | -- create "users" table 2 | CREATE TABLE `users` (`id` integer NOT NULL, `name` text NULL, PRIMARY KEY (`id`)); 3 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/sqlitetx3/20220925094021_second.sql: -------------------------------------------------------------------------------- 1 | -- atlas:txmode none 2 | 3 | -- Create a table. 4 | CREATE TABLE t1 (a INTEGER PRIMARY KEY); 5 | 6 | -- Cause migrations to fail. 7 | INSERT INTO t1 VALUES (1), (1); 8 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/sqlitetx3/atlas.sum: -------------------------------------------------------------------------------- 1 | h1:tTdOsRIKj8kX3o4eUQpw6znQsGVorkUrxi2o3C/ELL4= 2 | 20220925092817_initial.sql h1:ZGeLdeqNUMXqJm+hPkhBrhzbtUzSBH8yVTsnSnJo/qU= 3 | 20220925094021_second.sql h1:RTw52JCxOkWfSnY1N/kRZeLkmAFmvY2BXfZKDzhV3QM= 4 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/sqlitetx4/20220925092817_initial.sql: -------------------------------------------------------------------------------- 1 | -- create "users" table 2 | CREATE TABLE `users` (`id` integer NOT NULL, `name` text NULL, PRIMARY KEY (`id`)); 3 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/sqlitetx4/20220925094021_second.sql: -------------------------------------------------------------------------------- 1 | -- atlas:txmode unknown 2 | 3 | -- Create a table. 4 | CREATE TABLE t1 (a INTEGER PRIMARY KEY); 5 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/sqlitetx4/atlas.sum: -------------------------------------------------------------------------------- 1 | h1:RO76A3Kj66lD13e+iIb5lafWPtz4S3ypswaBm5kPRrI= 2 | 20220925092817_initial.sql h1:ZGeLdeqNUMXqJm+hPkhBrhzbtUzSBH8yVTsnSnJo/qU= 3 | 20220925094021_second.sql h1:MH4JwNo3hLxH0rauBusXr3IvJJFm9EC2TPe0DhXbgkE= 4 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/templatedir/1.sql: -------------------------------------------------------------------------------- 1 | {{- if eq .Env "dev" }} 2 | create table dev1 (c text); 3 | {{- else }} 4 | create table prod1 (c text); 5 | {{- end }} -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/templatedir/2.sql: -------------------------------------------------------------------------------- 1 | {{- if eq .Env "dev" }} 2 | create table dev2 (c text); 3 | {{ template "shared/users" "dev2" }} 4 | {{- else }} 5 | create table prod2 (c text); 6 | {{ template "shared/users" "prod2" }} 7 | {{- end }} -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/templatedir/atlas.sum: -------------------------------------------------------------------------------- 1 | h1:qhwlEKNEXRVSUiyBXmbiSiS26un12DoxHCR3WDzrDdA= 2 | 1.sql h1:b/5P45x6+CVoyVbBJ/BVc5Z2cI46XfoW92QH3T1kqxY= 3 | 2.sql h1:El2EOcXWK2PfPV6yJg4hBVtc4aHheV/MFEPjho9SEmQ= 4 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/testdata/templatedir/shared/users.sql: -------------------------------------------------------------------------------- 1 | {{- define "shared/users" }} 2 | create table users_{{ $ }} (c text); 3 | {{- end}} -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/vercheck/notification.tmpl: -------------------------------------------------------------------------------- 1 | {{- with .Advisory -}} 2 | SECURITY ADVISORY 3 | {{ .Text }} 4 | {{- end }} 5 | {{- with .Latest -}} 6 | A new version of Atlas is available ({{ .Version }}){{ with .Link }}: {{ . }} 7 | {{ end }} 8 | {{- with .Summary }} 9 | {{ . }} 10 | {{- end }} 11 | {{- end }} -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/vercheck/req_oss.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-present The Atlas Authors. All rights reserved. 2 | // This source code is licensed under the Apache 2.0 license found 3 | // in the LICENSE file in the root directory of this source tree. 4 | 5 | //go:build !ent 6 | 7 | package vercheck 8 | 9 | import ( 10 | "context" 11 | "net/http" 12 | 13 | "ariga.io/atlas/cmd/atlas/internal/cloudapi" 14 | ) 15 | 16 | func addHeaders(_ context.Context, req *http.Request) { 17 | req.Header.Set("User-Agent", cloudapi.UserAgent()) 18 | } 19 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdapi/version_oss.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-present The Atlas Authors. All rights reserved. 2 | // This source code is licensed under the Apache 2.0 license found 3 | // in the LICENSE file in the root directory of this source tree. 4 | 5 | //go:build !ent && !official 6 | 7 | package cmdapi 8 | 9 | const ( 10 | versionFmt = "atlas unofficial " 11 | versionInfo = "To download an official version, visit: https://atlasgo.io/getting-started#installation\n" 12 | ) 13 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdlog/cmdlog_oss.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-present The Atlas Authors. All rights reserved. 2 | // This source code is licensed under the Apache 2.0 license found 3 | // in the LICENSE file in the root directory of this source tree. 4 | 5 | //go:build !ent 6 | 7 | package cmdlog 8 | 9 | import ( 10 | "context" 11 | 12 | "ariga.io/atlas/sql/migrate" 13 | ) 14 | 15 | // SchemaApply contains a summary of a 'schema apply' execution on a database. 16 | type SchemaApply struct { 17 | ctx context.Context `json:"-"` 18 | Env 19 | Changes Changes `json:"Changes,omitempty"` 20 | // General error that occurred during execution. 21 | // e.g., when committing or rolling back a transaction. 22 | Error string `json:"Error,omitempty"` 23 | } 24 | 25 | // NewSchemaApply returns a SchemaApply. 26 | func NewSchemaApply(ctx context.Context, env Env, applied, pending []*migrate.Change, err *StmtError) *SchemaApply { 27 | return &SchemaApply{ 28 | ctx: ctx, 29 | Env: env, 30 | Changes: Changes{ 31 | Applied: applied, 32 | Pending: pending, 33 | Error: err, 34 | }, 35 | } 36 | } 37 | 38 | // NewSchemaPlan returns a SchemaApply only with pending changes. 39 | func NewSchemaPlan(ctx context.Context, env Env, pending []*migrate.Change, err *StmtError) *SchemaApply { 40 | return NewSchemaApply(ctx, env, nil, pending, err) 41 | } 42 | 43 | func (*MigrateApply) MaskedText(s *migrate.Stmt) string { 44 | return s.Text // Unsupported feature. 45 | } 46 | 47 | // MaskedErrorText returns the masked versioned of the error, if caused by a statement. 48 | func (*MigrateApply) MaskedErrorText(e migrate.LogError) string { 49 | return e.Error.Error() // Unsupported feature. 50 | } 51 | -------------------------------------------------------------------------------- /cmd/atlas/internal/cmdstate/cmdstate_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-present The Atlas Authors. All rights reserved. 2 | // This source code is licensed under the Apache 2.0 license found 3 | // in the LICENSE file in the root directory of this source tree. 4 | 5 | package cmdstate_test 6 | 7 | import ( 8 | "os" 9 | "path/filepath" 10 | "testing" 11 | 12 | "ariga.io/atlas/cmd/atlas/internal/cmdstate" 13 | 14 | "github.com/mitchellh/go-homedir" 15 | "github.com/stretchr/testify/require" 16 | ) 17 | 18 | func TestFile(t *testing.T) { 19 | homedir.DisableCache = true 20 | t.Cleanup(func() { homedir.DisableCache = false }) 21 | 22 | type T struct{ V string } 23 | f := cmdstate.File[T]{Name: "test", Dir: t.TempDir()} 24 | v, err := f.Read() 25 | require.NoError(t, err) 26 | require.Equal(t, T{}, v) 27 | require.NoError(t, f.Write(T{V: "v"})) 28 | v, err = f.Read() 29 | require.NoError(t, err) 30 | require.Equal(t, T{V: "v"}, v) 31 | 32 | home := t.TempDir() 33 | t.Setenv("HOME", home) 34 | f = cmdstate.File[T]{Name: "t"} 35 | _, err = f.Read() 36 | require.NoError(t, err) 37 | dirs, err := os.ReadDir(home) 38 | require.NoError(t, err) 39 | require.Empty(t, dirs) 40 | 41 | require.NoError(t, f.Write(T{V: "v"})) 42 | dirs, err = os.ReadDir(home) 43 | require.NoError(t, err) 44 | require.Len(t, dirs, 1) 45 | require.Equal(t, ".atlas", dirs[0].Name()) 46 | dirs, err = os.ReadDir(filepath.Join(home, ".atlas")) 47 | require.NoError(t, err) 48 | require.Len(t, dirs, 1) 49 | require.Equal(t, "t.json", dirs[0].Name()) 50 | v, err = f.Read() 51 | require.NoError(t, err) 52 | require.Equal(t, T{V: "v"}, v) 53 | } 54 | -------------------------------------------------------------------------------- /cmd/atlas/internal/migrate/ent/convert.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-present The Atlas Authors. All rights reserved. 2 | // This source code is licensed under the Apache 2.0 license found 3 | // in the LICENSE file in the root directory of this source tree. 4 | 5 | // Code generated by entc, DO NOT EDIT. 6 | 7 | package ent 8 | 9 | import "ariga.io/atlas/sql/migrate" 10 | 11 | // SetRevision takes the values for each field from the given migrate.Revision. 12 | func (rc *RevisionCreate) SetRevision(rev *migrate.Revision) *RevisionCreate { 13 | rc.SetID(rev.Version) 14 | rc.SetDescription(rev.Description) 15 | rc.SetType(rev.Type) 16 | rc.SetApplied(rev.Applied) 17 | rc.SetTotal(rev.Total) 18 | rc.SetExecutedAt(rev.ExecutedAt) 19 | rc.SetExecutionTime(rev.ExecutionTime) 20 | rc.SetError(rev.Error) 21 | rc.SetErrorStmt(rev.ErrorStmt) 22 | rc.SetHash(rev.Hash) 23 | rc.SetPartialHashes(rev.PartialHashes) 24 | rc.SetOperatorVersion(rev.OperatorVersion) 25 | return rc 26 | } 27 | 28 | // AtlasRevision returns an migrate.Revision from the current Revision. 29 | func (_m *Revision) AtlasRevision() *migrate.Revision { 30 | return &migrate.Revision{ 31 | Version: _m.ID, 32 | Description: _m.Description, 33 | Type: _m.Type, 34 | Applied: _m.Applied, 35 | Total: _m.Total, 36 | ExecutedAt: _m.ExecutedAt, 37 | ExecutionTime: _m.ExecutionTime, 38 | Error: _m.Error, 39 | ErrorStmt: _m.ErrorStmt, 40 | Hash: _m.Hash, 41 | PartialHashes: _m.PartialHashes, 42 | OperatorVersion: _m.OperatorVersion, 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /cmd/atlas/internal/migrate/ent/entc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-present The Atlas Authors. All rights reserved. 2 | // This source code is licensed under the Apache 2.0 license found 3 | // in the LICENSE file in the root directory of this source tree. 4 | 5 | //go:build ignore 6 | 7 | package main 8 | 9 | import ( 10 | "log" 11 | 12 | "entgo.io/ent/entc" 13 | "entgo.io/ent/entc/gen" 14 | ) 15 | 16 | func main() { 17 | err := entc.Generate("./schema", &gen.Config{ 18 | Header: `// Copyright 2021-present The Atlas Authors. All rights reserved. 19 | // This source code is licensed under the Apache 2.0 license found 20 | // in the LICENSE file in the root directory of this source tree. 21 | 22 | // Code generated by entc, DO NOT EDIT. 23 | `, 24 | Features: []gen.Feature{ 25 | gen.FeatureUpsert, 26 | gen.FeatureExecQuery, 27 | gen.FeatureSchemaConfig, 28 | }, 29 | }, entc.TemplateDir("template")) 30 | if err != nil { 31 | log.Fatalf("running ent codegen: %v", err) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /cmd/atlas/internal/migrate/ent/generate.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-present The Atlas Authors. All rights reserved. 2 | // This source code is licensed under the Apache 2.0 license found 3 | // in the LICENSE file in the root directory of this source tree. 4 | 5 | package ent 6 | 7 | //go:generate go run -mod=mod entc.go 8 | -------------------------------------------------------------------------------- /cmd/atlas/internal/migrate/ent/internal/schemaconfig.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-present The Atlas Authors. All rights reserved. 2 | // This source code is licensed under the Apache 2.0 license found 3 | // in the LICENSE file in the root directory of this source tree. 4 | 5 | // Code generated by entc, DO NOT EDIT. 6 | 7 | package internal 8 | 9 | import "context" 10 | 11 | // SchemaConfig represents alternative schema names for all tables 12 | // that can be passed at runtime. 13 | type SchemaConfig struct { 14 | Revision string // Revision table. 15 | } 16 | 17 | type schemaCtxKey struct{} 18 | 19 | // SchemaConfigFromContext returns a SchemaConfig stored inside a context, or empty if there isn't one. 20 | func SchemaConfigFromContext(ctx context.Context) SchemaConfig { 21 | config, _ := ctx.Value(schemaCtxKey{}).(SchemaConfig) 22 | return config 23 | } 24 | 25 | // NewSchemaConfigContext returns a new context with the given SchemaConfig attached. 26 | func NewSchemaConfigContext(parent context.Context, config SchemaConfig) context.Context { 27 | return context.WithValue(parent, schemaCtxKey{}, config) 28 | } 29 | -------------------------------------------------------------------------------- /cmd/atlas/internal/migrate/ent/migrate/schema.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-present The Atlas Authors. All rights reserved. 2 | // This source code is licensed under the Apache 2.0 license found 3 | // in the LICENSE file in the root directory of this source tree. 4 | 5 | // Code generated by entc, DO NOT EDIT. 6 | 7 | package migrate 8 | 9 | import ( 10 | "entgo.io/ent/dialect/entsql" 11 | "entgo.io/ent/dialect/sql/schema" 12 | "entgo.io/ent/schema/field" 13 | ) 14 | 15 | var ( 16 | // AtlasSchemaRevisionsColumns holds the columns for the "atlas_schema_revisions" table. 17 | AtlasSchemaRevisionsColumns = []*schema.Column{ 18 | {Name: "version", Type: field.TypeString}, 19 | {Name: "description", Type: field.TypeString}, 20 | {Name: "type", Type: field.TypeUint, Default: 2}, 21 | {Name: "applied", Type: field.TypeInt, Default: 0}, 22 | {Name: "total", Type: field.TypeInt, Default: 0}, 23 | {Name: "executed_at", Type: field.TypeTime}, 24 | {Name: "execution_time", Type: field.TypeInt64}, 25 | {Name: "error", Type: field.TypeString, Nullable: true, Size: 2147483647}, 26 | {Name: "error_stmt", Type: field.TypeString, Nullable: true, Size: 2147483647}, 27 | {Name: "hash", Type: field.TypeString}, 28 | {Name: "partial_hashes", Type: field.TypeJSON, Nullable: true}, 29 | {Name: "operator_version", Type: field.TypeString}, 30 | } 31 | // AtlasSchemaRevisionsTable holds the schema information for the "atlas_schema_revisions" table. 32 | AtlasSchemaRevisionsTable = &schema.Table{ 33 | Name: "atlas_schema_revisions", 34 | Columns: AtlasSchemaRevisionsColumns, 35 | PrimaryKey: []*schema.Column{AtlasSchemaRevisionsColumns[0]}, 36 | } 37 | // Tables holds all the tables in the schema. 38 | Tables = []*schema.Table{ 39 | AtlasSchemaRevisionsTable, 40 | } 41 | ) 42 | 43 | func init() { 44 | AtlasSchemaRevisionsTable.Annotation = &entsql.Annotation{ 45 | Table: "atlas_schema_revisions", 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /cmd/atlas/internal/migrate/ent/predicate/predicate.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-present The Atlas Authors. All rights reserved. 2 | // This source code is licensed under the Apache 2.0 license found 3 | // in the LICENSE file in the root directory of this source tree. 4 | 5 | // Code generated by entc, DO NOT EDIT. 6 | 7 | package predicate 8 | 9 | import ( 10 | "entgo.io/ent/dialect/sql" 11 | ) 12 | 13 | // Revision is the predicate function for revision builders. 14 | type Revision func(*sql.Selector) 15 | -------------------------------------------------------------------------------- /cmd/atlas/internal/migrate/ent/runtime.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-present The Atlas Authors. All rights reserved. 2 | // This source code is licensed under the Apache 2.0 license found 3 | // in the LICENSE file in the root directory of this source tree. 4 | 5 | // Code generated by entc, DO NOT EDIT. 6 | 7 | package ent 8 | 9 | import ( 10 | "ariga.io/atlas/cmd/atlas/internal/migrate/ent/revision" 11 | "ariga.io/atlas/cmd/atlas/internal/migrate/ent/schema" 12 | "ariga.io/atlas/sql/migrate" 13 | ) 14 | 15 | // The init function reads all schema descriptors with runtime code 16 | // (default values, validators, hooks and policies) and stitches it 17 | // to their package variables. 18 | func init() { 19 | revisionFields := schema.Revision{}.Fields() 20 | _ = revisionFields 21 | // revisionDescType is the schema descriptor for type field. 22 | revisionDescType := revisionFields[2].Descriptor() 23 | // revision.DefaultType holds the default value on creation for the type field. 24 | revision.DefaultType = migrate.RevisionType(revisionDescType.Default.(uint)) 25 | // revisionDescApplied is the schema descriptor for applied field. 26 | revisionDescApplied := revisionFields[3].Descriptor() 27 | // revision.DefaultApplied holds the default value on creation for the applied field. 28 | revision.DefaultApplied = revisionDescApplied.Default.(int) 29 | // revision.AppliedValidator is a validator for the "applied" field. It is called by the builders before save. 30 | revision.AppliedValidator = revisionDescApplied.Validators[0].(func(int) error) 31 | // revisionDescTotal is the schema descriptor for total field. 32 | revisionDescTotal := revisionFields[4].Descriptor() 33 | // revision.DefaultTotal holds the default value on creation for the total field. 34 | revision.DefaultTotal = revisionDescTotal.Default.(int) 35 | // revision.TotalValidator is a validator for the "total" field. It is called by the builders before save. 36 | revision.TotalValidator = revisionDescTotal.Validators[0].(func(int) error) 37 | } 38 | -------------------------------------------------------------------------------- /cmd/atlas/internal/migrate/ent/runtime/runtime.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-present The Atlas Authors. All rights reserved. 2 | // This source code is licensed under the Apache 2.0 license found 3 | // in the LICENSE file in the root directory of this source tree. 4 | 5 | // Code generated by entc, DO NOT EDIT. 6 | 7 | package runtime 8 | 9 | // The schema-stitching logic is generated in ariga.io/atlas/cmd/atlas/internal/migrate/ent/runtime.go 10 | 11 | const ( 12 | Version = "v0.14.5-0.20250523082027-21ecfa0872d4" // Version of ent codegen. 13 | Sum = "h1:d7UZAvQCnOp1PyiHAWkPCXBEPW3tVjraiK/RZlsW0XY=" // Sum of ent codegen. 14 | ) 15 | -------------------------------------------------------------------------------- /cmd/atlas/internal/migrate/ent/schema/revision.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-present The Atlas Authors. All rights reserved. 2 | // This source code is licensed under the Apache 2.0 license found 3 | // in the LICENSE file in the root directory of this source tree. 4 | 5 | package schema 6 | 7 | import ( 8 | "time" 9 | 10 | "ariga.io/atlas/sql/migrate" 11 | 12 | "entgo.io/ent" 13 | "entgo.io/ent/dialect/entsql" 14 | "entgo.io/ent/schema" 15 | "entgo.io/ent/schema/field" 16 | ) 17 | 18 | // DefaultRevisionSchema is the default schema for storing revisions table. 19 | const DefaultRevisionSchema = "atlas_schema_revisions" 20 | 21 | // Revision holds the schema definition for the Revision entity. 22 | type Revision struct { 23 | ent.Schema 24 | } 25 | 26 | // Fields of the Revision. 27 | func (Revision) Fields() []ent.Field { 28 | return []ent.Field{ 29 | field.String("id"). 30 | StorageKey("version"). 31 | Immutable(), 32 | field.String("description"). 33 | Immutable(), 34 | field.Uint("type"). 35 | GoType(migrate.RevisionType(0)). 36 | Default(uint(migrate.RevisionTypeExecute)), 37 | field.Int("applied"). 38 | NonNegative(). 39 | Default(0), 40 | field.Int("total"). 41 | NonNegative(). 42 | Default(0), 43 | field.Time("executed_at"). 44 | Immutable(), 45 | field.Int64("execution_time"). 46 | GoType(time.Duration(0)), 47 | field.Text("error"). 48 | Optional(), 49 | field.Text("error_stmt"). 50 | Optional(), 51 | field.String("hash"), 52 | field.Strings("partial_hashes"). 53 | Optional(), 54 | field.String("operator_version"), 55 | } 56 | } 57 | 58 | // Annotations of the Revision. 59 | func (Revision) Annotations() []schema.Annotation { 60 | return []schema.Annotation{ 61 | entsql.Annotation{Table: DefaultRevisionSchema}, 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /cmd/atlas/internal/migrate/ent/template/convert.tmpl: -------------------------------------------------------------------------------- 1 | {{/* gotype: entgo.io/ent/entc/gen.Graph */}} 2 | 3 | {{ define "convert" }} 4 | 5 | {{ $pkg := base $.Config.Package }} 6 | {{ template "header" $ }} 7 | 8 | import "ariga.io/atlas/sql/migrate" 9 | 10 | {{ range $n := $.Nodes }} 11 | {{ if eq $n.Name "Revision" }} 12 | {{ $builder := $n.CreateName }} 13 | {{ $receiver := receiver $builder }} 14 | 15 | // SetRevision takes the values for each field from the given migrate.Revision. 16 | func ({{ $receiver }} *{{ $builder }}) SetRevision(rev *migrate.Revision) *{{ $builder }} { 17 | {{ $receiver }}.SetID(rev.Version) 18 | {{- range $f := $n.Fields }} 19 | {{ $receiver }}.Set{{ $f.StructField }}(rev.{{ $f.StructField }}) 20 | {{- end }} 21 | return {{ $receiver }} 22 | } 23 | 24 | // AtlasRevision returns an migrate.Revision from the current Revision. 25 | func({{ $n.Receiver }} *Revision) AtlasRevision() *migrate.Revision { 26 | return &migrate.Revision{ 27 | Version: {{ $n.Receiver }}.ID, 28 | {{- range $f := $n.Fields }} 29 | {{ $f.StructField }}: {{ $n.Receiver }}.{{ $f.StructField }}, 30 | {{- end }} 31 | } 32 | } 33 | {{ end }} 34 | {{ end }} 35 | 36 | {{ end }} 37 | -------------------------------------------------------------------------------- /cmd/atlas/internal/migrate/migrate_oss.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-present The Atlas Authors. All rights reserved. 2 | // This source code is licensed under the Apache 2.0 license found 3 | // in the LICENSE file in the root directory of this source tree. 4 | 5 | //go:build !ent 6 | 7 | package migrate 8 | 9 | import ( 10 | "context" 11 | "fmt" 12 | "net/url" 13 | 14 | "ariga.io/atlas/sql/migrate" 15 | ) 16 | 17 | func openAtlasDir(context.Context, *url.URL) (migrate.Dir, error) { 18 | return nil, fmt.Errorf("atlas remote directory is not supported by this release. See: https://atlasgo.io/getting-started") 19 | } 20 | -------------------------------------------------------------------------------- /cmd/atlas/internal/migrate/testdata/broken/1.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `users` (`id` int NOT NULL PRIMARY KEY); -------------------------------------------------------------------------------- /cmd/atlas/internal/migrate/testdata/broken/2.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE `users` ADD COLUMN `happy` boolean NOT NULL DEFAULT true; -------------------------------------------------------------------------------- /cmd/atlas/internal/migrate/testdata/broken/3.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `pets` (`id` int NOT NULL PRIMARY KEY); 2 | THIS LINE ADDS A SYNTAX ERROR; -------------------------------------------------------------------------------- /cmd/atlas/internal/migrate/testdata/broken/atlas.sum: -------------------------------------------------------------------------------- 1 | h1:0YTkvowN+aAuYuJY5ZANPAq6QAZ0wAXunU9sUXsuZcI= 2 | 1.sql h1:twN+zPVp8JzWEUcPPfNIT6/62Wa08dfxxZhT4gZxBzg= 3 | 2.sql h1:KHLlrSPwSjbp4+KrpQHwYZf8zlSIiAR7MS3H2yd1yeE= 4 | 3.sql h1:iTKab5MEzWsTdVVDkCUWmateRs9XRNpal/cxqlCYsmQ= 5 | -------------------------------------------------------------------------------- /cmd/atlas/internal/migrate/testdata/fixed/1.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `users` (`id` int NOT NULL PRIMARY KEY); -------------------------------------------------------------------------------- /cmd/atlas/internal/migrate/testdata/fixed/2.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE `users` ADD COLUMN `happy` boolean NOT NULL DEFAULT true; -------------------------------------------------------------------------------- /cmd/atlas/internal/migrate/testdata/fixed/3.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `pets` (`id` int NOT NULL PRIMARY KEY); 2 | ALTER TABLE `pets` ADD COLUMN `happy` boolean NULL; -------------------------------------------------------------------------------- /cmd/atlas/internal/migrate/testdata/fixed/atlas.sum: -------------------------------------------------------------------------------- 1 | h1:oNV0f9HzMMCf2pzF+sA6CmsSHGjdkWYmcTjoc/lWxLs= 2 | 1.sql h1:twN+zPVp8JzWEUcPPfNIT6/62Wa08dfxxZhT4gZxBzg= 3 | 2.sql h1:KHLlrSPwSjbp4+KrpQHwYZf8zlSIiAR7MS3H2yd1yeE= 4 | 3.sql h1:osHrPgu8uNgd6j09XCiyBQWWEh9aAmwjRgzdZZgm68M= 5 | -------------------------------------------------------------------------------- /cmd/atlas/internal/sqlparse/myparse/myparse_oss.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-present The Atlas Authors. All rights reserved. 2 | // This source code is licensed under the Apache 2.0 license found 3 | // in the LICENSE file in the root directory of this source tree. 4 | 5 | //go:build !ent 6 | 7 | package myparse 8 | 9 | import ( 10 | "errors" 11 | 12 | "ariga.io/atlas/sql/migrate" 13 | "ariga.io/atlas/sql/schema" 14 | ) 15 | 16 | // Parser for fixing linting changes. 17 | type FileParser struct{} 18 | 19 | // FixChange fixes the changes according to the given statement. 20 | func (*FileParser) FixChange(migrate.Driver, string, schema.Changes) (schema.Changes, error) { 21 | return nil, errors.New("unimplemented") 22 | } 23 | 24 | // ColumnFilledBefore checks if the column was filled with values before the given position in the file. 25 | func (*FileParser) ColumnFilledBefore([]*migrate.Stmt, *schema.Table, *schema.Column, int) (bool, error) { 26 | return false, errors.New("unimplemented") 27 | } 28 | 29 | // CreateViewAfter checks if a view was created after the position with the given name to a table. 30 | func (*FileParser) CreateViewAfter([]*migrate.Stmt, string, string, int) (bool, error) { 31 | return false, errors.New("unimplemented") 32 | } 33 | -------------------------------------------------------------------------------- /cmd/atlas/internal/sqlparse/pgparse/pgparse_oss.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-present The Atlas Authors. All rights reserved. 2 | // This source code is licensed under the Apache 2.0 license found 3 | // in the LICENSE file in the root directory of this source tree. 4 | 5 | //go:build !ent 6 | 7 | package pgparse 8 | 9 | import ( 10 | "errors" 11 | 12 | "ariga.io/atlas/sql/migrate" 13 | "ariga.io/atlas/sql/schema" 14 | ) 15 | 16 | type Parser struct{} 17 | 18 | func (*Parser) ColumnFilledBefore([]*migrate.Stmt, *schema.Table, *schema.Column, int) (bool, error) { 19 | return false, errors.New("unimplemented") 20 | } 21 | 22 | func (*Parser) CreateViewAfter([]*migrate.Stmt, string, string, int) (bool, error) { 23 | return false, errors.New("unimplemented") 24 | } 25 | 26 | func (*Parser) FixChange(_ migrate.Driver, _ string, changes schema.Changes) (schema.Changes, error) { 27 | return changes, nil // Unimplemented. 28 | } 29 | -------------------------------------------------------------------------------- /cmd/atlas/internal/sqlparse/sqliteparse/README.md: -------------------------------------------------------------------------------- 1 | ### SQLite parser based on ANTLR4 2 | 3 | #### Resources 4 | 5 | 1. SQLite syntax: https://www.sqlite.org/syntaxdiagrams.html 6 | 2. Grammar file: https://github.com/antlr/grammars-v4/tree/master/sql/sqlite 7 | 8 | #### Run codegen 9 | 10 | 1. Install `antlr4`: https://github.com/antlr/antlr4/blob/master/doc/getting-started.md#unix 11 | 2. Run: 12 | ```bash 13 | antlr4 -Dlanguage=Go -package sqliteparse -visitor Lexer.g4 Parser.g4 \ 14 | && mv _lexer.go lexer.go \ 15 | && mv _parser.go parser.go \ 16 | && rm *.interp *.tokens 17 | ``` -------------------------------------------------------------------------------- /cmd/atlas/internal/sqlparse/sqliteparse/sqliteparse_oss.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-present The Atlas Authors. All rights reserved. 2 | // This source code is licensed under the Apache 2.0 license found 3 | // in the LICENSE file in the root directory of this source tree. 4 | 5 | //go:build !ent 6 | 7 | package sqliteparse 8 | 9 | import ( 10 | "errors" 11 | 12 | "ariga.io/atlas/sql/migrate" 13 | "ariga.io/atlas/sql/schema" 14 | ) 15 | 16 | type FileParser struct{} 17 | 18 | func (*FileParser) ColumnFilledBefore([]*migrate.Stmt, *schema.Table, *schema.Column, int) (bool, error) { 19 | return false, errors.New("unimplemented") 20 | } 21 | 22 | func (*FileParser) CreateViewAfter([]*migrate.Stmt, string, string, int) (bool, error) { 23 | return false, errors.New("unimplemented") 24 | } 25 | 26 | func (*FileParser) FixChange(_ migrate.Driver, _ string, changes schema.Changes) (schema.Changes, error) { 27 | return changes, nil // Unimplemented. 28 | } 29 | -------------------------------------------------------------------------------- /cmd/atlas/internal/sqlparse/sqlparse.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-present The Atlas Authors. All rights reserved. 2 | // This source code is licensed under the Apache 2.0 license found 3 | // in the LICENSE file in the root directory of this source tree. 4 | 5 | package sqlparse 6 | 7 | import ( 8 | "sync" 9 | 10 | "ariga.io/atlas/cmd/atlas/internal/sqlparse/myparse" 11 | "ariga.io/atlas/cmd/atlas/internal/sqlparse/pgparse" 12 | "ariga.io/atlas/cmd/atlas/internal/sqlparse/sqliteparse" 13 | "ariga.io/atlas/sql/migrate" 14 | "ariga.io/atlas/sql/mysql" 15 | "ariga.io/atlas/sql/postgres" 16 | "ariga.io/atlas/sql/schema" 17 | "ariga.io/atlas/sql/sqlite" 18 | ) 19 | 20 | // A Parser represents an SQL file parser used to fix, search and enrich schema.Changes. 21 | type Parser interface { 22 | // FixChange fixes the changes according to the given statement. 23 | FixChange(d migrate.Driver, stmt string, changes schema.Changes) (schema.Changes, error) 24 | 25 | // ColumnFilledBefore checks if the column was filled with values before the given position 26 | // in the file. For example: 27 | // 28 | // UPDATE SET = 29 | // UPDATE
SET = WHERE IS NULL 30 | // 31 | ColumnFilledBefore([]*migrate.Stmt, *schema.Table, *schema.Column, int) (bool, error) 32 | 33 | // CreateViewAfter checks if a view was created after the position with the given name 34 | // to a table. For example: 35 | // 36 | // ALTER TABLE `users` RENAME TO `Users` 37 | // CREATE VIEW `users` AS SELECT * FROM `Users` 38 | // 39 | CreateViewAfter(stmts []*migrate.Stmt, old, new string, pos int) (bool, error) 40 | } 41 | 42 | // drivers specific fixers. 43 | var drivers sync.Map 44 | 45 | // Register a fixer with the given name. 46 | func Register(name string, f Parser) { 47 | drivers.Store(name, f) 48 | } 49 | 50 | // ParserFor returns a ChangesFixer for the given driver. 51 | func ParserFor(name string) Parser { 52 | f, ok := drivers.Load(name) 53 | if ok { 54 | return f.(Parser) 55 | } 56 | return nil 57 | } 58 | 59 | func init() { 60 | Register(mysql.DriverName, &myparse.FileParser{}) 61 | Register(postgres.DriverName, &pgparse.Parser{}) 62 | Register(sqlite.DriverName, &sqliteparse.FileParser{}) 63 | } 64 | -------------------------------------------------------------------------------- /cmd/atlas/main_oss.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-present The Atlas Authors. All rights reserved. 2 | // This source code is licensed under the Apache 2.0 license found 3 | // in the LICENSE file in the root directory of this source tree. 4 | 5 | //go:build !ent 6 | 7 | package main 8 | 9 | import ( 10 | "context" 11 | ) 12 | 13 | func extendContext(ctx context.Context) (context.Context, error) { 14 | return ctx, nil 15 | } 16 | 17 | func vercheckEndpoint(context.Context) string { 18 | return vercheckURL 19 | } 20 | 21 | // initialize is a no-op for the OSS version. 22 | func initialize(ctx context.Context) (context.Context, func(error)) { 23 | return ctx, func(error) {} 24 | } 25 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module ariga.io/atlas 2 | 3 | go 1.24 4 | 5 | toolchain go1.24.3 6 | 7 | require ( 8 | github.com/DATA-DOG/go-sqlmock v1.5.0 9 | github.com/bmatcuk/doublestar v1.3.4 10 | github.com/go-openapi/inflect v0.19.0 11 | github.com/hashicorp/hcl/v2 v2.13.0 12 | github.com/stretchr/testify v1.8.2 13 | github.com/zclconf/go-cty v1.14.4 14 | github.com/zclconf/go-cty-yaml v1.1.0 15 | golang.org/x/mod v0.24.0 16 | gopkg.in/yaml.v3 v3.0.1 17 | ) 18 | 19 | require ( 20 | github.com/agext/levenshtein v1.2.1 // indirect 21 | github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect 22 | github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect 23 | github.com/davecgh/go-spew v1.1.1 // indirect 24 | github.com/google/go-cmp v0.6.0 // indirect 25 | github.com/kr/text v0.2.0 // indirect 26 | github.com/kylelemons/godebug v1.1.0 // indirect 27 | github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect 28 | github.com/pmezard/go-difflib v1.0.0 // indirect 29 | golang.org/x/text v0.21.0 // indirect 30 | ) 31 | -------------------------------------------------------------------------------- /internal/ci/ci_revisions.tmpl: -------------------------------------------------------------------------------- 1 | # # # # # # # # # # # # # # # # 2 | # CODE GENERATED - DO NOT EDIT 3 | # # # # # # # # # # # # # # # # 4 | name: CI - Revisions{{ with $.Flavor }} - {{ . }} Edition{{ end }} 5 | on: 6 | pull_request: 7 | paths: 8 | - 'cmd/atlas/internal/migrate/ent/**' 9 | push: 10 | branches: 11 | - master 12 | paths: 13 | - 'cmd/atlas/internal/migrate/ent/**' 14 | {{ .Concurrency }} 15 | jobs: 16 | revisions: 17 | runs-on: {{ $.Runner }} 18 | steps: 19 | - uses: actions/checkout@v4 20 | with: 21 | fetch-depth: 0 22 | - uses: actions/setup-go@v5 23 | with: 24 | go-version-file: cmd/atlas/go.mod 25 | {{- with .SharedSteps }} 26 | {{- range . }} 27 | - name: {{ .Name }} 28 | uses: {{ .Action }} 29 | {{- with .With }} 30 | with: 31 | {{- range . }} 32 | {{ . }}{{ end }} 33 | {{- end }} 34 | {{- end }} 35 | {{- end }} 36 | - name: Checkout origin/master 37 | run: git checkout origin/master 38 | - name: Create revisions from master 39 | run: go run {{ with $.Tags }}-tags={{ . }} {{ end }}. migrate apply --dir file://internal/cmdapi/testdata/sqlite --url sqlite://db?_fk=1 40 | working-directory: cmd/atlas 41 | - name: Checkout previous HEAD 42 | run: git checkout - 43 | - name: Migrate revisions table to HEAD 44 | run: go run {{ with $.Tags }}-tags={{ . }} {{ end }}. migrate apply --dir file://internal/cmdapi/testdata/sqlite --url sqlite://db?_fk=1 45 | working-directory: cmd/atlas -------------------------------------------------------------------------------- /internal/ci/cockroach/Dockerfile.tmpl: -------------------------------------------------------------------------------- 1 | FROM cockroachdb/cockroach:{{ .Version}} 2 | 3 | EXPOSE 8080 4 | EXPOSE 26257 5 | 6 | ENTRYPOINT ["/cockroach/cockroach", "start-single-node", "--insecure"] -------------------------------------------------------------------------------- /internal/ci/cockroach/main.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-present The Atlas Authors. All rights reserved. 2 | // This source code is licensed under the Apache 2.0 license found 3 | // in the LICENSE file in the root directory of this source tree. 4 | 5 | package main 6 | 7 | import ( 8 | _ "embed" 9 | "fmt" 10 | "os" 11 | "text/template" 12 | ) 13 | 14 | type params struct { 15 | Version string 16 | } 17 | 18 | //go:embed Dockerfile.tmpl 19 | var dockerTmpl string 20 | 21 | func main() { 22 | if len(os.Args) < 2 { 23 | fmt.Println("please supply version as argument e.g. 'v22.1.0'") 24 | os.Exit(1) 25 | } 26 | 27 | p := params{ 28 | Version: os.Args[1], 29 | } 30 | t, err := template.New("docker").Parse(dockerTmpl) 31 | if err != nil { 32 | panic(err) 33 | } 34 | err = t.Execute(os.Stdout, p) 35 | if err != nil { 36 | panic(err) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /internal/ci/jobs_oss.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-present The Atlas Authors. All rights reserved. 2 | // This source code is licensed under the Apache 2.0 license found 3 | // in the LICENSE file in the root directory of this source tree. 4 | 5 | //go:build !ent 6 | 7 | package main 8 | 9 | //go:generate go run . -flavor Community -suffix oss 10 | 11 | func init() { 12 | data.GoVersions = goVersions{"1.22"} 13 | data.GlobalEnv = []struct{ K, V string }{ 14 | {K: "ATLAS_NO_UPGRADE_SUGGESTIONS", V: "1"}, 15 | } 16 | data.Jobs = append(jobs, 17 | Job{ 18 | Version: "tidb5", 19 | Image: "pingcap/tidb:v5.4.0", 20 | Regex: "TiDB", 21 | Ports: []string{"4309:4000"}, 22 | }, 23 | Job{ 24 | Version: "tidb6", 25 | Image: "pingcap/tidb:v6.0.0", 26 | Regex: "TiDB", 27 | Ports: []string{"4310:4000"}, 28 | }, 29 | Job{ 30 | Version: "cockroach", 31 | Image: "ghcr.io/ariga/cockroachdb-single-node:v21.2.11", 32 | Regex: "Cockroach", 33 | Ports: []string{"26257:26257"}, 34 | }, 35 | ) 36 | } 37 | -------------------------------------------------------------------------------- /internal/integration/README.md: -------------------------------------------------------------------------------- 1 | ### This directory contains all integration tests for Atlas. 2 | 3 | The provided `docker-compose.yaml` file contains images for each database the integration tests are run on. You can 4 | start them by calling: 5 | 6 | ```shell 7 | docker-compose --project-name atlas-integration up -d 8 | ``` 9 | 10 | The whole integration suite is then run by executing within this directory: 11 | 12 | ```shell 13 | go test ./... 14 | ``` 15 | 16 | #### Selectively running tests 17 | 18 | Running all integration tests (and keeping all database containers up all the time) consumes time and resources (and 19 | power). You can execute only some of the tests by using the `-run` and `-dialect` flags: 20 | 21 | The below examples don't require for you to have all docker containers running, instead only the ones used in the tests 22 | have to be up. 23 | 24 | Consider the following test in `mysql_test.go`: 25 | 26 | ```go 27 | func TestMySQL_Executor(t *testing.T) { 28 | myRun(t, func(t *myTest) { 29 | testExecutor(t) 30 | }) 31 | } 32 | ``` 33 | 34 | If you'd wanted to run that test only for mysql56, simply pass its full name into the `-run` flag: 35 | 36 | ```shell 37 | # Run TestMySQL_Executor for all mysql versions 38 | go test -run='MySQL_Executor' ./... 39 | 40 | # Run TestMySQL_Executor for mysql 5.6 only 41 | go test -run='MySQL_Executor/mysql56' ./... 42 | ``` 43 | 44 | If you'd like to run the above for Postgres 10, change the name respectively: 45 | 46 | ```shell 47 | # Run TestPostgres_Executor for all postgres versions 48 | go test -run='Postgres_Executor' ./... 49 | 50 | # Run TestPostgres_Executor for postgres 10 only 51 | go test -run='Postgres_Executor/postgres10' ./... 52 | ``` 53 | 54 | If you want to run all tests for one specific dialect, like only TiDB 5, you can use the `-dialect` flag: 55 | 56 | ```shell 57 | go test -run='TiDB' -dialect='tidb5' ./... 58 | ``` -------------------------------------------------------------------------------- /internal/integration/testdata/migrations/mysql/1_initial.sql: -------------------------------------------------------------------------------- 1 | CREATE SCHEMA IF NOT EXISTS `bc_test`; 2 | CREATE TABLE `bc_test`.`bc_tbl` (`col` INTEGER NULL); -------------------------------------------------------------------------------- /internal/integration/testdata/migrations/mysql/atlas.sum: -------------------------------------------------------------------------------- 1 | h1:FT0VjrL64KJmuOe1Dq4dpbG/50Kwn0lZqfopa6BhJM8= 2 | 1_initial.sql h1:bWUYLjb0oiGQHf45Q08aKFKxVZ3pZBArJnSmuGBw9X4= 3 | -------------------------------------------------------------------------------- /internal/integration/testdata/migrations/mysqlock/1.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `t1` (`id` int); 2 | CREATE TABLE `t2` (`id` int); 3 | select sleep(0.1); 4 | CREATE TABLE `t3` (`id` int); 5 | CREATE TABLE `t4` (`id` int); 6 | CREATE TABLE `t5` (`id` int); 7 | select sleep(0.1); 8 | CREATE TABLE `t6` (`id` int); 9 | -------------------------------------------------------------------------------- /internal/integration/testdata/migrations/mysqlock/2.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE `t1` ADD COLUMN `c1` varchar(255) DEFAULT 'name'; 2 | ALTER TABLE `t2` ADD COLUMN `c1` varchar(255) DEFAULT 'name'; 3 | select sleep(0.1); 4 | ALTER TABLE `t3` ADD COLUMN `c1` varchar(255) DEFAULT 'name'; 5 | ALTER TABLE `t4` ADD COLUMN `c1` varchar(255) DEFAULT 'name'; 6 | select sleep(0.1); 7 | ALTER TABLE `t5` ADD COLUMN `c1` varchar(255) DEFAULT 'name'; 8 | ALTER TABLE `t6` ADD COLUMN `c1` varchar(255) DEFAULT 'name'; 9 | ALTER TABLE `t1` ADD COLUMN `c2` varchar(255) DEFAULT 'name'; 10 | ALTER TABLE `t2` ADD COLUMN `c2` varchar(255) DEFAULT 'name'; 11 | select sleep(0.1); 12 | ALTER TABLE `t3` ADD COLUMN `c2` varchar(255) DEFAULT 'name'; 13 | ALTER TABLE `t4` ADD COLUMN `c2` varchar(255) DEFAULT 'name'; 14 | select sleep(0.1); 15 | ALTER TABLE `t5` ADD COLUMN `c2` varchar(255) DEFAULT 'name'; 16 | ALTER TABLE `t6` ADD COLUMN `c2` varchar(255) DEFAULT 'name'; 17 | -------------------------------------------------------------------------------- /internal/integration/testdata/migrations/mysqlock/3.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `t7` (`id` int); 2 | select sleep(0.1); 3 | CREATE TABLE `t8` (`id` int); 4 | CREATE TABLE `t9` (`id` int); 5 | -------------------------------------------------------------------------------- /internal/integration/testdata/migrations/mysqlock/atlas.sum: -------------------------------------------------------------------------------- 1 | h1:XiFkhbkD+gUR/ry9+AVfyLW4X/tYaVUHFul5q0Kvtpo= 2 | 1.sql h1:+HoZslM3E59DllQlUXd5TFnPw+9de9IBNQEYdn77f7c= 3 | 2.sql h1:OliSiXPsLoVoWixWDC/yBJUtjrxnMMm+hjCf2Sz66Rk= 4 | 3.sql h1:Gb5M9ibe0COwTBrb08v/4VuWXxJ55+D2lSLXHLVa/Po= 5 | -------------------------------------------------------------------------------- /internal/integration/testdata/migrations/postgres/1_initial.sql: -------------------------------------------------------------------------------- 1 | CREATE SCHEMA IF NOT EXISTS "bc_test"; 2 | CREATE TABLE "bc_test"."bc_tbl" ("col" INTEGER NULL); -------------------------------------------------------------------------------- /internal/integration/testdata/migrations/postgres/atlas.sum: -------------------------------------------------------------------------------- 1 | h1:80V3wCzovMg2ot2hR0arbEjEfMfKWDeQNrXZJbFPF10= 2 | 1_initial.sql h1:53poyM34ShPWCVU41ldi4d9LUrzqPiQfBdEq//yH4Jo= 3 | -------------------------------------------------------------------------------- /internal/integration/testdata/mysql/autoincrement.txtar: -------------------------------------------------------------------------------- 1 | apply 1.hcl 2 | cmpshow users 1.sql 3 | 4 | # Setup a custom AUTO_INCREMENT initial value. 5 | apply 2.hcl 6 | cmpshow users 2.sql 7 | 8 | # Increase the AUTO_INCREMENT value. 9 | apply 3.hcl 10 | cmpshow users 3.sql 11 | 12 | -- 1.hcl -- 13 | schema "$db" {} 14 | 15 | table "users" { 16 | schema = schema.$db 17 | column "id" { 18 | null = false 19 | type = bigint 20 | auto_increment = true 21 | } 22 | primary_key { 23 | columns = [column.id] 24 | } 25 | } 26 | 27 | -- 1.sql -- 28 | CREATE TABLE `users` ( 29 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 30 | PRIMARY KEY (`id`) 31 | ) 32 | 33 | -- mysql8/1.sql -- 34 | CREATE TABLE `users` ( 35 | `id` bigint NOT NULL AUTO_INCREMENT, 36 | PRIMARY KEY (`id`) 37 | ) 38 | 39 | -- 2.hcl -- 40 | schema "$db" {} 41 | 42 | table "users" { 43 | schema = schema.$db 44 | column "id" { 45 | null = false 46 | type = bigint 47 | auto_increment = true 48 | } 49 | primary_key { 50 | columns = [column.id] 51 | } 52 | auto_increment = 1000 53 | } 54 | 55 | -- 2.sql -- 56 | CREATE TABLE `users` ( 57 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 58 | PRIMARY KEY (`id`) 59 | ) AUTO_INCREMENT=1000 60 | 61 | -- mysql8/2.sql -- 62 | CREATE TABLE `users` ( 63 | `id` bigint NOT NULL AUTO_INCREMENT, 64 | PRIMARY KEY (`id`) 65 | ) AUTO_INCREMENT=1000 66 | 67 | -- 3.hcl -- 68 | schema "$db" {} 69 | 70 | table "users" { 71 | schema = schema.$db 72 | column "id" { 73 | null = false 74 | type = bigint 75 | auto_increment = true 76 | } 77 | primary_key { 78 | columns = [column.id] 79 | } 80 | auto_increment = 2000 81 | } 82 | 83 | -- 3.sql -- 84 | CREATE TABLE `users` ( 85 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 86 | PRIMARY KEY (`id`) 87 | ) AUTO_INCREMENT=2000 88 | 89 | -- mysql8/3.sql -- 90 | CREATE TABLE `users` ( 91 | `id` bigint NOT NULL AUTO_INCREMENT, 92 | PRIMARY KEY (`id`) 93 | ) AUTO_INCREMENT=2000 -------------------------------------------------------------------------------- /internal/integration/testdata/mysql/cli-inspect-file.txtar: -------------------------------------------------------------------------------- 1 | only mysql8 2 | 3 | # inspect without dev-db will failed 4 | ! atlas schema inspect -u file://a.sql 5 | stderr 'Error: --dev-url cannot be empty' 6 | 7 | # inspect file to HCL 8 | atlas schema inspect -u file://a.sql --dev-url URL > inspected.hcl 9 | cmp inspected.hcl script_cli_inspect.hcl 10 | 11 | # inspect file to SQL 12 | atlas schema inspect -u file://a.sql --dev-url URL --format '{{ sql . }}' > inspected.sql 13 | cmp inspected.sql script_cli_inspect.sql 14 | 15 | -- a.sql -- 16 | create table users ( 17 | id int NOT NULL, 18 | PRIMARY KEY (id) 19 | ) 20 | 21 | -- script_cli_inspect.hcl -- 22 | table "users" { 23 | schema = schema.script_cli_inspect_file 24 | column "id" { 25 | null = false 26 | type = int 27 | } 28 | primary_key { 29 | columns = [column.id] 30 | } 31 | } 32 | schema "script_cli_inspect_file" { 33 | charset = "utf8mb4" 34 | collate = "utf8mb4_0900_ai_ci" 35 | } 36 | -- script_cli_inspect.sql -- 37 | -- Create "users" table 38 | CREATE TABLE `users` (`id` int NOT NULL, PRIMARY KEY (`id`)) CHARSET utf8mb4 COLLATE utf8mb4_0900_ai_ci; 39 | -------------------------------------------------------------------------------- /internal/integration/testdata/mysql/cli-migrate-apply-datasrc.txtar: -------------------------------------------------------------------------------- 1 | only mysql8 2 | 3 | atlas migrate hash 4 | atlas migrate apply --url URL --env dev --var "url=URL" --var "pattern=script_cli_migrate_apply_datasrc" 5 | stdout 'Migrating to version 1 \(1 migrations in total\):' 6 | 7 | -- atlas.hcl -- 8 | variable "url" { 9 | type = string 10 | } 11 | 12 | variable "pattern" { 13 | type = string 14 | } 15 | 16 | data "sql" "tenants" { 17 | url = var.url 18 | query = < out.txt 2 | exec cat out.txt 3 | stdout 'CREATE TABLE `script_cli_project_schemas`' 4 | 5 | -- 1.hcl -- 6 | schema "script_cli_project_schemas" { 7 | } 8 | table "users" { 9 | schema = schema.script_cli_project_schemas 10 | column "id" { 11 | type = bigint 12 | null = false 13 | } 14 | } 15 | -- atlas.hcl -- 16 | env "local" { 17 | url = "URL" 18 | src = "./1.hcl" 19 | schemas = ["script_cli_project_schemas"] 20 | } 21 | -- expected.sql -- 22 | CREATE TABLE `users` ( 23 | `id` bigint NOT NULL 24 | ) 25 | -- 0.hcl -- 26 | schema "$db" { 27 | charset = "$charset" 28 | collate = "$collate" 29 | } -------------------------------------------------------------------------------- /internal/integration/testdata/mysql/cli-project-url-escape.txtar: -------------------------------------------------------------------------------- 1 | only mysql8 2 | 3 | execsql 'CREATE USER IF NOT EXISTS "a8m"@"%" IDENTIFIED BY "&pass?"' 4 | execsql 'GRANT ALL PRIVILEGES ON *.* TO "a8m"@"%" WITH GRANT OPTION' 5 | 6 | atlas schema inspect --env local > got.txt 7 | cmp got.txt want.txt 8 | 9 | ! atlas schema inspect --env failed 10 | stderr 'invalid port ":&pass" after host' 11 | 12 | execsql 'DROP USER "a8m"@"%"' 13 | 14 | -- atlas.hcl -- 15 | variable "pass" { 16 | type = string 17 | default = "&pass?" 18 | } 19 | 20 | locals { 21 | escaped_pass = urlescape(var.pass) 22 | } 23 | 24 | env "local" { 25 | url = "mysql://a8m:${local.escaped_pass}@localhost:3308/script_cli_project_url_escape" 26 | } 27 | 28 | env "failed" { 29 | url = "mysql://a8m:${var.pass}@localhost:3308/script_cli_project_url_escape" 30 | } 31 | 32 | -- want.txt -- 33 | schema "script_cli_project_url_escape" { 34 | charset = "utf8mb4" 35 | collate = "utf8mb4_0900_ai_ci" 36 | } -------------------------------------------------------------------------------- /internal/integration/testdata/mysql/cli-schema-apply-datasrc.txtar: -------------------------------------------------------------------------------- 1 | only mysql8 2 | 3 | atlas schema apply --auto-approve --url URL --env dev --var "url=URL" --var "pattern=script_cli_schema_apply_datasrc" 4 | stdout '\{"Applied":\["CREATE TABLE `users` \(\\n `id` int NOT NULL\\n\);*"\],"Tenant":"script_cli_schema_apply_datasrc"\}' 5 | 6 | -- schema.hcl -- 7 | variable "tenant" { 8 | type = string 9 | } 10 | 11 | schema "test" { 12 | name = var.tenant 13 | } 14 | 15 | table "users" { 16 | schema = schema.test 17 | column "id" { 18 | type = int 19 | } 20 | } 21 | 22 | -- atlas.hcl -- 23 | variable "url" { 24 | type = string 25 | } 26 | 27 | variable "pattern" { 28 | type = string 29 | } 30 | 31 | data "sql" "tenants" { 32 | url = var.url 33 | query = < inspected.hcl 7 | cmp inspected.hcl script_cli_inspect.hcl 8 | 9 | # inspect file to SQL 10 | atlas schema inspect -u file://a.sql --dev-url URL --format '{{ sql . }}' > inspected.sql 11 | cmp inspected.sql script_cli_inspect.sql 12 | 13 | -- a.sql -- 14 | create table users ( 15 | id int NOT NULL, 16 | PRIMARY KEY (id) 17 | ) 18 | 19 | -- script_cli_inspect.hcl -- 20 | table "users" { 21 | schema = schema.script_cli_inspect_file 22 | column "id" { 23 | null = false 24 | type = integer 25 | } 26 | primary_key { 27 | columns = [column.id] 28 | } 29 | } 30 | schema "script_cli_inspect_file" { 31 | } 32 | -- script_cli_inspect.sql -- 33 | -- Create "users" table 34 | CREATE TABLE "users" ("id" integer NOT NULL, PRIMARY KEY ("id")); 35 | -------------------------------------------------------------------------------- /internal/integration/testdata/postgres/cli-inspect.txtar: -------------------------------------------------------------------------------- 1 | apply 1.hcl 2 | 3 | # test url flag 4 | atlas schema inspect -u URL > inspected.hcl 5 | cmp inspected.hcl script_cli_inspect.hcl 6 | 7 | # test exclude flag on table. 8 | atlas schema inspect -u URL --exclude "users" > inspected.hcl 9 | cmp inspected.hcl notable.hcl 10 | 11 | # test exclude flag on column. 12 | atlas schema inspect -u URL --exclude "*.[ab]*" > inspected.hcl 13 | cmp inspected.hcl id.hcl 14 | 15 | # test exclude flag on column. 16 | atlas schema inspect -u URL --exclude "*.*" > inspected.hcl 17 | cmp inspected.hcl nocolumn.hcl 18 | 19 | 20 | -- 1.hcl -- 21 | table "users" { 22 | schema = schema.$db 23 | column "id" { 24 | null = false 25 | type = int 26 | } 27 | column "a" { 28 | null = false 29 | type = int 30 | } 31 | column "b" { 32 | null = false 33 | type = int 34 | } 35 | column "ab" { 36 | null = false 37 | type = int 38 | } 39 | column "ac" { 40 | null = false 41 | type = int4 42 | } 43 | } 44 | schema "$db" { 45 | } 46 | 47 | -- script_cli_inspect.hcl -- 48 | table "users" { 49 | schema = schema.script_cli_inspect 50 | column "id" { 51 | null = false 52 | type = integer 53 | } 54 | column "a" { 55 | null = false 56 | type = integer 57 | } 58 | column "b" { 59 | null = false 60 | type = integer 61 | } 62 | column "ab" { 63 | null = false 64 | type = integer 65 | } 66 | column "ac" { 67 | null = false 68 | type = integer 69 | } 70 | } 71 | schema "script_cli_inspect" { 72 | } 73 | -- empty.hcl -- 74 | -- notable.hcl -- 75 | schema "script_cli_inspect" { 76 | } 77 | -- id.hcl -- 78 | table "users" { 79 | schema = schema.script_cli_inspect 80 | column "id" { 81 | null = false 82 | type = integer 83 | } 84 | } 85 | schema "script_cli_inspect" { 86 | } 87 | -- nocolumn.hcl -- 88 | table "users" { 89 | schema = schema.script_cli_inspect 90 | } 91 | schema "script_cli_inspect" { 92 | } -------------------------------------------------------------------------------- /internal/integration/testdata/postgres/cli-migrate-apply-datasrc.txtar: -------------------------------------------------------------------------------- 1 | only postgres14 2 | 3 | atlas migrate hash 4 | atlas migrate apply --url URL --env dev --var "url=URL" --var "pattern=script_cli_migrate_apply_datasrc" 5 | stdout 'Migrating to version 1 \(1 migrations in total\):' 6 | 7 | -- atlas.hcl -- 8 | variable "url" { 9 | type = string 10 | } 11 | 12 | variable "pattern" { 13 | type = string 14 | } 15 | 16 | data "sql" "tenants" { 17 | url = var.url 18 | query = < 0)' 2 | 3 | apply 1.hcl 4 | cmpshow users 1.sql 5 | cmphcl 1.inspect.hcl 6 | 7 | -- 1.hcl -- 8 | schema "script_column_domain" {} 9 | 10 | table "users" { 11 | schema = schema.script_column_domain 12 | column "c1" { 13 | type = sql("script_column_domain.positive_int") 14 | } 15 | } 16 | 17 | -- 1.sql -- 18 | Table "script_column_domain.users" 19 | Column | Type | Collation | Nullable | Default 20 | --------+-----------------------------------+-----------+----------+--------- 21 | c1 | script_column_domain.positive_int | | not null | 22 | 23 | -- 1.inspect.hcl -- 24 | table "users" { 25 | schema = schema.script_column_domain 26 | column "c1" { 27 | null = false 28 | type = sql("positive_int") 29 | } 30 | } 31 | schema "script_column_domain" { 32 | } -------------------------------------------------------------------------------- /internal/integration/testdata/postgres/column-float.txtar: -------------------------------------------------------------------------------- 1 | apply 1.hcl 2 | cmpshow users 1.sql 3 | 4 | apply 2.hcl 5 | cmpshow users 2.sql 6 | 7 | -- 1.hcl -- 8 | schema "$db" {} 9 | 10 | table "users" { 11 | schema = schema.$db 12 | column "c1" { 13 | type = real 14 | } 15 | column "c2" { 16 | type = double_precision 17 | } 18 | column "c3" { 19 | // Equals to real when precision is between 1 and 24. 20 | type = float(10) 21 | } 22 | column "c4" { 23 | // Equals to double_precision when precision is between 1 and 24. 24 | type = float(30) 25 | } 26 | } 27 | 28 | -- 1.sql -- 29 | Table "script_column_float.users" 30 | Column | Type | Collation | Nullable | Default 31 | --------+------------------+-----------+----------+--------- 32 | c1 | real | | not null | 33 | c2 | double precision | | not null | 34 | c3 | real | | not null | 35 | c4 | double precision | | not null | 36 | 37 | 38 | -- 2.hcl -- 39 | schema "$db" {} 40 | 41 | table "users" { 42 | schema = schema.$db 43 | column "c1" { 44 | type = double_precision 45 | } 46 | column "c2" { 47 | type = real 48 | } 49 | column "c3" { 50 | type = float(30) 51 | } 52 | column "c4" { 53 | type = float(10) 54 | } 55 | } 56 | 57 | -- 2.sql -- 58 | Table "script_column_float.users" 59 | Column | Type | Collation | Nullable | Default 60 | --------+------------------+-----------+----------+--------- 61 | c1 | double precision | | not null | 62 | c2 | real | | not null | 63 | c3 | double precision | | not null | 64 | c4 | real | | not null | -------------------------------------------------------------------------------- /internal/integration/testdata/postgres/column-generated-inspect.txtar: -------------------------------------------------------------------------------- 1 | # Skip PostgreSQL 10, 11 as they do not support generated columns. 2 | ! only postgres10|postgres11 3 | 4 | apply 1.hcl 5 | cmphcl 1.inspect.hcl 6 | 7 | -- 1.hcl -- 8 | schema "$db" {} 9 | 10 | table "users" { 11 | schema = schema.$db 12 | column "a" { 13 | type = int 14 | } 15 | column "b" { 16 | type = int 17 | as = "1" 18 | } 19 | column "c" { 20 | type = int 21 | as { 22 | expr = "2" 23 | type = STORED 24 | } 25 | } 26 | } 27 | 28 | -- 1.inspect.hcl -- 29 | table "users" { 30 | schema = schema.$db 31 | column "a" { 32 | null = false 33 | type = integer 34 | } 35 | column "b" { 36 | null = false 37 | type = integer 38 | as { 39 | expr = "1" 40 | type = STORED 41 | } 42 | } 43 | column "c" { 44 | null = false 45 | type = integer 46 | as { 47 | expr = "2" 48 | type = STORED 49 | } 50 | } 51 | } 52 | schema "$db" { 53 | } 54 | -------------------------------------------------------------------------------- /internal/integration/testdata/postgres/column-identity.txtar: -------------------------------------------------------------------------------- 1 | apply 1.hcl 2 | cmpshow users 1.sql 3 | 4 | # Change identity generation. 5 | apply 2.hcl 6 | cmpshow users 2.sql 7 | 8 | -- 1.hcl -- 9 | schema "$db" {} 10 | 11 | table "users" { 12 | schema = schema.$db 13 | column "name" { 14 | null = false 15 | type = int 16 | identity { 17 | generated = ALWAYS 18 | start = 10 19 | increment = 10 20 | } 21 | } 22 | } 23 | 24 | -- 1.sql -- 25 | Table "script_column_identity.users" 26 | Column | Type | Collation | Nullable | Default 27 | --------+---------+-----------+----------+------------------------------ 28 | name | integer | | not null | generated always as identity 29 | 30 | 31 | -- 2.hcl -- 32 | schema "$db" {} 33 | 34 | table "users" { 35 | schema = schema.$db 36 | column "name" { 37 | null = false 38 | type = int 39 | identity { 40 | generated = BY_DEFAULT 41 | start = 10 42 | increment = 10 43 | } 44 | } 45 | } 46 | 47 | -- 2.sql -- 48 | Table "script_column_identity.users" 49 | Column | Type | Collation | Nullable | Default 50 | --------+---------+-----------+----------+---------------------------------- 51 | name | integer | | not null | generated by default as identity -------------------------------------------------------------------------------- /internal/integration/testdata/postgres/column-interval.txtar: -------------------------------------------------------------------------------- 1 | apply 1.hcl 2 | cmpshow logs 1.sql 3 | cmphcl 1.inspect.hcl 4 | 5 | -- 1.hcl -- 6 | table "logs" { 7 | schema = schema.script_column_interval 8 | column "a" { 9 | null = false 10 | type = interval 11 | default = "3 hours" 12 | } 13 | column "b" { 14 | null = false 15 | type = interval(1) 16 | } 17 | column "c" { 18 | null = false 19 | type = second 20 | } 21 | column "d" { 22 | null = false 23 | type = second(1) 24 | } 25 | column "e" { 26 | null = true 27 | type = day_to_second(4) 28 | } 29 | } 30 | 31 | schema "script_column_interval" {} 32 | 33 | -- 1.sql -- 34 | Table "script_column_interval.logs" 35 | Column | Type | Collation | Nullable | Default 36 | --------+---------------------------+-----------+----------+---------------------- 37 | a | interval | | not null | '03:00:00'::interval 38 | b | interval(1) | | not null | 39 | c | interval second | | not null | 40 | d | interval second(1) | | not null | 41 | e | interval day to second(4) | | | 42 | 43 | 44 | -- 1.inspect.hcl -- 45 | table "logs" { 46 | schema = schema.script_column_interval 47 | column "a" { 48 | null = false 49 | type = interval 50 | default = sql("'03:00:00'::interval") 51 | } 52 | column "b" { 53 | null = false 54 | type = interval(1) 55 | } 56 | column "c" { 57 | null = false 58 | type = second 59 | } 60 | column "d" { 61 | null = false 62 | type = second(1) 63 | } 64 | column "e" { 65 | null = true 66 | type = day_to_second(4) 67 | } 68 | } 69 | schema "script_column_interval" { 70 | } -------------------------------------------------------------------------------- /internal/integration/testdata/postgres/column-range.txtar: -------------------------------------------------------------------------------- 1 | only postgres14 postgres15 2 | 3 | apply 1.hcl 4 | cmpshow t 1.sql 5 | 6 | -- 1.hcl -- 7 | schema "$db" {} 8 | 9 | table "t" { 10 | schema = schema.$db 11 | column "r1" { 12 | type = int4range 13 | } 14 | column "r2" { 15 | type = int8range 16 | } 17 | column "r3" { 18 | type = numrange 19 | } 20 | column "r4" { 21 | type = tsrange 22 | } 23 | column "r5" { 24 | type = tstzrange 25 | } 26 | column "r6" { 27 | type = daterange 28 | } 29 | column "r7" { 30 | type = int4multirange 31 | } 32 | column "r8" { 33 | type = int8multirange 34 | } 35 | column "r9" { 36 | type = nummultirange 37 | } 38 | column "r10" { 39 | type = tsmultirange 40 | } 41 | column "r11" { 42 | type = tstzmultirange 43 | } 44 | column "r12" { 45 | type = datemultirange 46 | } 47 | } 48 | 49 | -- 1.sql -- 50 | Table "script_column_range.t" 51 | Column | Type | Collation | Nullable | Default 52 | --------+----------------+-----------+----------+--------- 53 | r1 | int4range | | not null | 54 | r2 | int8range | | not null | 55 | r3 | numrange | | not null | 56 | r4 | tsrange | | not null | 57 | r5 | tstzrange | | not null | 58 | r6 | daterange | | not null | 59 | r7 | int4multirange | | not null | 60 | r8 | int8multirange | | not null | 61 | r9 | nummultirange | | not null | 62 | r10 | tsmultirange | | not null | 63 | r11 | tstzmultirange | | not null | 64 | r12 | datemultirange | | not null | 65 | -------------------------------------------------------------------------------- /internal/integration/testdata/postgres/column-textsearch.txtar: -------------------------------------------------------------------------------- 1 | apply 1.hcl 2 | cmpshow t 1.sql 3 | cmphcl 1.inspect.hcl 4 | 5 | -- 1.hcl -- 6 | schema "script_column_textsearch" {} 7 | 8 | table "t" { 9 | schema = schema.script_column_textsearch 10 | column "tsv" { 11 | type = tsvector 12 | } 13 | column "tsq" { 14 | type = tsquery 15 | } 16 | index "idx_tsv" { 17 | type = GIN 18 | columns = [column.tsv] 19 | } 20 | } 21 | 22 | -- 1.sql -- 23 | Table "script_column_textsearch.t" 24 | Column | Type | Collation | Nullable | Default 25 | --------+----------+-----------+----------+--------- 26 | tsv | tsvector | | not null | 27 | tsq | tsquery | | not null | 28 | Indexes: 29 | "idx_tsv" gin (tsv) 30 | 31 | 32 | -- 1.inspect.hcl -- 33 | table "t" { 34 | schema = schema.script_column_textsearch 35 | column "tsv" { 36 | null = false 37 | type = tsvector 38 | } 39 | column "tsq" { 40 | null = false 41 | type = tsquery 42 | } 43 | index "idx_tsv" { 44 | columns = [column.tsv] 45 | type = GIN 46 | } 47 | } 48 | schema "script_column_textsearch" { 49 | } -------------------------------------------------------------------------------- /internal/integration/testdata/postgres/index-expr.txtar: -------------------------------------------------------------------------------- 1 | apply 1.hcl 2 | cmpshow users 1.sql 3 | 4 | apply 2.hcl 5 | cmpshow users 2.sql 6 | 7 | -- 1.hcl -- 8 | schema "$db" {} 9 | 10 | table "users" { 11 | schema = schema.$db 12 | column "first_name" { 13 | null = false 14 | type = varchar(128) 15 | } 16 | column "last_name" { 17 | null = false 18 | type = varchar(128) 19 | } 20 | index "full_name" { 21 | on { 22 | expr = "first_name || ' ' || last_name" 23 | } 24 | } 25 | } 26 | 27 | -- 1.sql -- 28 | Table "script_index_expr.users" 29 | Column | Type | Collation | Nullable | Default 30 | ------------+------------------------+-----------+----------+--------- 31 | first_name | character varying(128) | | not null | 32 | last_name | character varying(128) | | not null | 33 | Indexes: 34 | "full_name" btree (((first_name::text || ' '::text) || last_name::text)) 35 | 36 | 37 | -- 2.hcl -- 38 | schema "$db" {} 39 | 40 | table "users" { 41 | schema = schema.$db 42 | column "first_name" { 43 | null = false 44 | type = varchar(128) 45 | } 46 | column "last_name" { 47 | null = false 48 | type = varchar(128) 49 | } 50 | index "full_name" { 51 | on { 52 | expr = "first_name || '''s first name'" 53 | } 54 | } 55 | } 56 | 57 | -- 2.sql -- 58 | Table "script_index_expr.users" 59 | Column | Type | Collation | Nullable | Default 60 | ------------+------------------------+-----------+----------+--------- 61 | first_name | character varying(128) | | not null | 62 | last_name | character varying(128) | | not null | 63 | Indexes: 64 | "full_name" btree ((first_name::text || '''s first name'::text)) -------------------------------------------------------------------------------- /internal/integration/testdata/postgres/index-issue-557.txtar: -------------------------------------------------------------------------------- 1 | apply 1.hcl 2 | cmpshow t1 t2 1.sql 3 | 4 | -- 1.hcl -- 5 | schema "$db" {} 6 | 7 | table "t1" { 8 | schema = schema.$db 9 | column "a" { 10 | null = false 11 | type = uuid 12 | } 13 | column "b" { 14 | null = true 15 | type = timestamp(6) 16 | } 17 | index "t1_a_b" { 18 | on { 19 | column = column.a 20 | } 21 | on { 22 | desc = true 23 | column = column.b 24 | } 25 | unique = true 26 | } 27 | } 28 | 29 | table "t2" { 30 | schema = schema.$db 31 | column "a" { 32 | null = false 33 | type = uuid 34 | } 35 | primary_key { 36 | columns = [column.a] 37 | } 38 | } 39 | 40 | -- 1.sql -- 41 | Table "script_index_issue_557.t1" 42 | Column | Type | Collation | Nullable | Default 43 | --------+-----------------------------+-----------+----------+--------- 44 | a | uuid | | not null | 45 | b | timestamp without time zone | | | 46 | Indexes: 47 | "t1_a_b" UNIQUE, btree (a, b DESC) 48 | 49 | 50 | Table "script_index_issue_557.t2" 51 | Column | Type | Collation | Nullable | Default 52 | --------+------+-----------+----------+--------- 53 | a | uuid | | not null | 54 | Indexes: 55 | "t2_pkey" PRIMARY KEY, btree (a) 56 | -------------------------------------------------------------------------------- /internal/integration/testdata/postgres/index-partial.txtar: -------------------------------------------------------------------------------- 1 | apply 1.hcl 2 | cmpshow users 1.sql 3 | 4 | apply 2.hcl 5 | cmpshow users 2.sql 6 | 7 | -- 1.hcl -- 8 | schema "$db" {} 9 | 10 | table "users" { 11 | schema = schema.$db 12 | column "name" { 13 | null = false 14 | type = text 15 | } 16 | column "active" { 17 | null = true 18 | type = boolean 19 | } 20 | index "users_name" { 21 | columns = [column.name] 22 | where = "active" 23 | } 24 | } 25 | 26 | -- 1.sql -- 27 | Table "script_index_partial.users" 28 | Column | Type | Collation | Nullable | Default 29 | --------+---------+-----------+----------+--------- 30 | name | text | | not null | 31 | active | boolean | | | 32 | Indexes: 33 | "users_name" btree (name) WHERE active 34 | 35 | 36 | -- 2.hcl -- 37 | schema "$db" {} 38 | 39 | table "users" { 40 | schema = schema.$db 41 | column "name" { 42 | null = false 43 | type = text 44 | } 45 | column "active" { 46 | null = true 47 | type = boolean 48 | } 49 | index "users_name" { 50 | columns = [column.name] 51 | where = "active AND name <> ''" 52 | } 53 | } 54 | 55 | -- 2.sql -- 56 | Table "script_index_partial.users" 57 | Column | Type | Collation | Nullable | Default 58 | --------+---------+-----------+----------+--------- 59 | name | text | | not null | 60 | active | boolean | | | 61 | Indexes: 62 | "users_name" btree (name) WHERE active AND name <> ''::text -------------------------------------------------------------------------------- /internal/integration/testdata/postgres/index-type-brin.txtar: -------------------------------------------------------------------------------- 1 | apply 1.hcl 2 | cmpshow users 1.sql 3 | 4 | # Add the "page_per_range" storage parameter. 5 | apply 2.hcl 6 | cmpshow users 2.sql 7 | 8 | # Change the "page_per_range" storage parameter. 9 | apply 3.hcl 10 | cmpshow users 3.sql 11 | 12 | -- 1.hcl -- 13 | schema "$db" {} 14 | 15 | table "users" { 16 | schema = schema.$db 17 | column "c" { 18 | null = false 19 | type = int 20 | } 21 | index "users_c" { 22 | type = BRIN 23 | columns = [column.c] 24 | } 25 | } 26 | 27 | -- 1.sql -- 28 | Table "script_index_type_brin.users" 29 | Column | Type | Collation | Nullable | Default 30 | --------+---------+-----------+----------+--------- 31 | c | integer | | not null | 32 | Indexes: 33 | "users_c" brin (c) 34 | 35 | -- 2.hcl -- 36 | schema "$db" {} 37 | 38 | table "users" { 39 | schema = schema.$db 40 | column "c" { 41 | null = false 42 | type = int 43 | } 44 | index "users_c" { 45 | type = BRIN 46 | columns = [column.c] 47 | page_per_range = 2 48 | } 49 | } 50 | 51 | -- 2.sql -- 52 | Table "script_index_type_brin.users" 53 | Column | Type | Collation | Nullable | Default 54 | --------+---------+-----------+----------+--------- 55 | c | integer | | not null | 56 | Indexes: 57 | "users_c" brin (c) WITH (pages_per_range='2') 58 | 59 | 60 | -- 3.hcl -- 61 | schema "$db" {} 62 | 63 | table "users" { 64 | schema = schema.$db 65 | column "c" { 66 | null = false 67 | type = int 68 | } 69 | index "users_c" { 70 | type = BRIN 71 | columns = [column.c] 72 | page_per_range = 3 73 | } 74 | } 75 | 76 | -- 3.sql -- 77 | Table "script_index_type_brin.users" 78 | Column | Type | Collation | Nullable | Default 79 | --------+---------+-----------+----------+--------- 80 | c | integer | | not null | 81 | Indexes: 82 | "users_c" brin (c) WITH (pages_per_range='3') -------------------------------------------------------------------------------- /internal/integration/testdata/postgres/index-type.txtar: -------------------------------------------------------------------------------- 1 | apply 1.hcl 2 | cmpshow users 1.sql 3 | 4 | # Change index type. 5 | apply 2.hcl 6 | cmpshow users 2.sql 7 | 8 | -- 1.hcl -- 9 | schema "$db" {} 10 | 11 | table "users" { 12 | schema = schema.$db 13 | column "name" { 14 | null = false 15 | type = text 16 | } 17 | column "data" { 18 | null = true 19 | type = jsonb 20 | } 21 | index "users_name" { 22 | type = HASH 23 | columns = [column.name] 24 | } 25 | index "users_data" { 26 | type = GIN 27 | columns = [column.data] 28 | } 29 | } 30 | 31 | -- 1.sql -- 32 | Table "script_index_type.users" 33 | Column | Type | Collation | Nullable | Default 34 | --------+-------+-----------+----------+--------- 35 | name | text | | not null | 36 | data | jsonb | | | 37 | Indexes: 38 | "users_data" gin (data) 39 | "users_name" hash (name) 40 | 41 | -- 2.hcl -- 42 | schema "$db" {} 43 | 44 | table "users" { 45 | schema = schema.$db 46 | column "name" { 47 | null = false 48 | type = text 49 | } 50 | column "data" { 51 | null = true 52 | type = jsonb 53 | } 54 | index "users_name" { 55 | columns = [column.name] 56 | # Index without "using" defaults to BTREE. 57 | } 58 | index "users_data" { 59 | columns = [column.data] 60 | } 61 | } 62 | 63 | -- 2.sql -- 64 | Table "script_index_type.users" 65 | Column | Type | Collation | Nullable | Default 66 | --------+-------+-----------+----------+--------- 67 | name | text | | not null | 68 | data | jsonb | | | 69 | Indexes: 70 | "users_data" btree (data) 71 | "users_name" btree (name) 72 | 73 | -------------------------------------------------------------------------------- /internal/integration/testdata/postgres/primary-key.txtar: -------------------------------------------------------------------------------- 1 | only postgres15 2 | 3 | # Create table. 4 | apply 1.hcl 5 | cmpshow users 1.sql 6 | 7 | # Add a primary-key. 8 | apply 2.hcl 9 | cmpshow users 2.sql 10 | 11 | # Modify the primary-key include columns. 12 | apply 3.hcl 13 | cmpshow users 3.sql 14 | 15 | # Drop the primary-key. 16 | apply 1.hcl 17 | cmpshow users 1.sql 18 | 19 | -- 1.hcl -- 20 | schema "$db" {} 21 | 22 | table "users" { 23 | schema = schema.$db 24 | column "id" { 25 | null = false 26 | type = int 27 | } 28 | column "c" { 29 | null = true 30 | type = int 31 | } 32 | } 33 | 34 | -- 1.sql -- 35 | Table "script_primary_key.users" 36 | Column | Type | Collation | Nullable | Default 37 | --------+---------+-----------+----------+--------- 38 | id | integer | | not null | 39 | c | integer | | | 40 | 41 | -- 2.hcl -- 42 | schema "$db" {} 43 | 44 | table "users" { 45 | schema = schema.$db 46 | column "id" { 47 | null = false 48 | type = int 49 | } 50 | column "c" { 51 | null = true 52 | type = int 53 | } 54 | primary_key { 55 | columns = [column.id] 56 | } 57 | } 58 | 59 | -- 2.sql -- 60 | Table "script_primary_key.users" 61 | Column | Type | Collation | Nullable | Default 62 | --------+---------+-----------+----------+--------- 63 | id | integer | | not null | 64 | c | integer | | | 65 | Indexes: 66 | "users_pkey" PRIMARY KEY, btree (id) 67 | 68 | 69 | -- 3.hcl -- 70 | schema "$db" {} 71 | 72 | table "users" { 73 | schema = schema.$db 74 | column "id" { 75 | null = false 76 | type = int 77 | } 78 | column "c" { 79 | null = true 80 | type = int 81 | } 82 | primary_key { 83 | columns = [column.id] 84 | include = [column.c] 85 | } 86 | } 87 | 88 | -- 3.sql -- 89 | Table "script_primary_key.users" 90 | Column | Type | Collation | Nullable | Default 91 | --------+---------+-----------+----------+--------- 92 | id | integer | | not null | 93 | c | integer | | | 94 | Indexes: 95 | "users_pkey" PRIMARY KEY, btree (id) INCLUDE (c) 96 | 97 | 98 | -------------------------------------------------------------------------------- /internal/integration/testdata/sqlite/autoincrement.txtar: -------------------------------------------------------------------------------- 1 | apply 1.hcl 2 | cmpshow users 1.sql 3 | 4 | -- 1.hcl -- 5 | schema "main" {} 6 | 7 | table "users" { 8 | schema = schema.main 9 | column "id" { 10 | null = false 11 | type = integer 12 | auto_increment = true 13 | } 14 | primary_key { 15 | columns = [column.id] 16 | } 17 | } 18 | 19 | -- 1.sql -- 20 | CREATE TABLE `users` (`id` integer NOT NULL PRIMARY KEY AUTOINCREMENT) -------------------------------------------------------------------------------- /internal/integration/testdata/sqlite/cli-apply-multifile.txtar: -------------------------------------------------------------------------------- 1 | atlas schema apply -f users.hcl -f schema.hcl -u URL --auto-approve 2 | cmpshow users expected.sql 3 | 4 | -- users.hcl -- 5 | table "users" { 6 | schema = schema.main 7 | column "id" { 8 | null = false 9 | type = int 10 | } 11 | column "status" { 12 | null = true 13 | type = text 14 | default = "hello" 15 | } 16 | } 17 | -- schema.hcl -- 18 | schema "main" { 19 | } 20 | -- expected.sql -- 21 | CREATE TABLE `users` ( 22 | `id` int NOT NULL, 23 | `status` text NULL DEFAULT 'hello' 24 | ) -------------------------------------------------------------------------------- /internal/integration/testdata/sqlite/cli-apply-project-multifile.txtar: -------------------------------------------------------------------------------- 1 | atlas schema apply --env local --auto-approve 2 | cmpshow users expected.sql 3 | 4 | -- atlas.hcl -- 5 | env "local" { 6 | url = "URL" 7 | src = "./schema" 8 | def_val = "hello" 9 | } 10 | -- schema/vars.hcl -- 11 | variable "def_val" { 12 | type = string 13 | } 14 | -- schema/table.hcl -- 15 | table "users" { 16 | schema = schema.main 17 | column "id" { 18 | null = false 19 | type = int 20 | } 21 | column "status" { 22 | null = true 23 | type = text 24 | default = var.def_val 25 | } 26 | } 27 | -- schema/schema.hcl -- 28 | schema "main" { 29 | } 30 | -- expected.sql -- 31 | CREATE TABLE `users` ( 32 | `id` int NOT NULL, 33 | `status` text NULL DEFAULT 'hello' 34 | ) -------------------------------------------------------------------------------- /internal/integration/testdata/sqlite/cli-apply-vars.txtar: -------------------------------------------------------------------------------- 1 | ! atlas schema apply --env local --auto-approve 2 | stderr 'missing value for required variable "def_val"' 3 | 4 | atlas schema apply --env local_with_vals --auto-approve 5 | cmpshow users expected.sql 6 | 7 | -- atlas.hcl -- 8 | env "local" { 9 | url = "URL" 10 | src = "./1.hcl" 11 | } 12 | env "local_with_vals" { 13 | url = "URL" 14 | src = "./1.hcl" 15 | 16 | def_val = "hello" 17 | } 18 | -- 1.hcl -- 19 | variable "def_val" { 20 | type = string 21 | } 22 | table "users" { 23 | schema = schema.main 24 | column "id" { 25 | null = false 26 | type = int 27 | } 28 | column "status" { 29 | null = true 30 | type = text 31 | default = var.def_val 32 | } 33 | } 34 | schema "main" { 35 | } 36 | -- expected.sql -- 37 | CREATE TABLE `users` ( 38 | `id` int NOT NULL, 39 | `status` text NULL DEFAULT 'hello' 40 | ) -------------------------------------------------------------------------------- /internal/integration/testdata/sqlite/cli-inspect.txtar: -------------------------------------------------------------------------------- 1 | apply 1.hcl 2 | 3 | # test url flag 4 | atlas schema inspect -u URL > inspected.hcl 5 | cmp inspected.hcl 1.hcl 6 | 7 | # test exclude flag on table. 8 | atlas schema inspect -u URL --exclude "users" > inspected.hcl 9 | cmp inspected.hcl notable.hcl 10 | 11 | # test exclude flag on column. 12 | atlas schema inspect -u URL --exclude "*.[ab]*" > inspected.hcl 13 | cmp inspected.hcl id.hcl 14 | 15 | # test exclude flag on column. 16 | atlas schema inspect -u URL --exclude "*.*" > inspected.hcl 17 | cmp inspected.hcl nocolumn.hcl 18 | 19 | 20 | -- 1.hcl -- 21 | table "users" { 22 | schema = schema.main 23 | column "id" { 24 | null = false 25 | type = int 26 | } 27 | column "a" { 28 | null = false 29 | type = int 30 | } 31 | column "b" { 32 | null = false 33 | type = int 34 | } 35 | column "ab" { 36 | null = false 37 | type = int 38 | } 39 | column "ac" { 40 | null = false 41 | type = uint64 42 | } 43 | } 44 | schema "main" { 45 | } 46 | -- empty.hcl -- 47 | -- notable.hcl -- 48 | schema "main" { 49 | } 50 | -- id.hcl -- 51 | table "users" { 52 | schema = schema.main 53 | column "id" { 54 | null = false 55 | type = int 56 | } 57 | } 58 | schema "main" { 59 | } 60 | -- nocolumn.hcl -- 61 | table "users" { 62 | schema = schema.main 63 | } 64 | schema "main" { 65 | } -------------------------------------------------------------------------------- /internal/integration/testdata/sqlite/cli-migrate-diff-datasrc-hcl-paths.txtar: -------------------------------------------------------------------------------- 1 | atlas migrate diff --env local 2 | cmpmig 0 expected.sql 3 | 4 | -- atlas.hcl -- 5 | data "hcl_schema" "app" { 6 | paths = glob("schema-*.hcl") 7 | vars = { 8 | default_value = "unknown" 9 | } 10 | } 11 | 12 | env "local" { 13 | src = data.hcl_schema.app.url 14 | dev = "sqlite://dev?mode=memory&_fk=1" 15 | } 16 | 17 | -- schema-1.hcl -- 18 | schema "main" {} 19 | 20 | table "pets" { 21 | schema = schema.main 22 | column "name" { 23 | null = false 24 | type = text 25 | default = var.default_value 26 | } 27 | column "owner_id" { 28 | type = integer 29 | } 30 | foreign_key "owner_id" { 31 | columns = [column.owner_id] 32 | ref_columns = [table.users.column.id] 33 | on_update = NO_ACTION 34 | on_delete = NO_ACTION 35 | } 36 | } 37 | 38 | -- schema-2.hcl -- 39 | variable "default_value" { 40 | type = string 41 | } 42 | table "users" { 43 | schema = schema.main 44 | column "id" { 45 | null = true 46 | type = integer 47 | } 48 | column "name" { 49 | null = false 50 | type = text 51 | default = var.default_value 52 | } 53 | } 54 | 55 | -- expected.sql -- 56 | -- Create "pets" table 57 | CREATE TABLE `pets` (`name` text NOT NULL DEFAULT 'unknown', `owner_id` integer NOT NULL, CONSTRAINT `owner_id` FOREIGN KEY (`owner_id`) REFERENCES `users` (`id`) ON UPDATE NO ACTION ON DELETE NO ACTION); 58 | -- Create "users" table 59 | CREATE TABLE `users` (`id` integer NULL, `name` text NOT NULL DEFAULT 'unknown'); 60 | -------------------------------------------------------------------------------- /internal/integration/testdata/sqlite/cli-migrate-diff-datasrc-hcl.txtar: -------------------------------------------------------------------------------- 1 | atlas migrate diff --env local 2 | cmpmig 0 expected.sql 3 | 4 | -- atlas.hcl -- 5 | data "hcl_schema" "app" { 6 | path = "schema.hcl" 7 | vars = { 8 | default_value = "unknown" 9 | } 10 | } 11 | 12 | env "local" { 13 | src = data.hcl_schema.app.url 14 | dev = "sqlite://dev?mode=memory&_fk=1" 15 | } 16 | 17 | -- schema.hcl -- 18 | variable "default_value" { 19 | type = string 20 | } 21 | 22 | schema "main" {} 23 | 24 | table "users" { 25 | schema = schema.main 26 | column "name" { 27 | null = false 28 | type = text 29 | default = var.default_value 30 | } 31 | } 32 | 33 | -- expected.sql -- 34 | -- Create "users" table 35 | CREATE TABLE `users` (`name` text NOT NULL DEFAULT 'unknown'); 36 | -------------------------------------------------------------------------------- /internal/integration/testdata/sqlite/cli-migrate-diff-minimal-env.txtar: -------------------------------------------------------------------------------- 1 | atlas migrate diff --env local 2 | cmpmig 0 diff.sql 3 | -- atlas.hcl -- 4 | env "local" { 5 | src = "1.hcl" 6 | dev = "sqlite://devdb" 7 | } 8 | -- 1.hcl -- 9 | table "users" { 10 | schema = schema.main 11 | column "id" { 12 | null = false 13 | type = int 14 | } 15 | } 16 | schema "main" { 17 | } 18 | -- diff.sql -- 19 | -- Create "users" table 20 | CREATE TABLE `users` (`id` int NOT NULL); -------------------------------------------------------------------------------- /internal/integration/testdata/sqlite/cli-migrate-diff-multifile.txtar: -------------------------------------------------------------------------------- 1 | ! atlas migrate diff --dev-url sqlite://devdb --to file://schema/ --to other://scheme --dir file://migrations 2 | stderr 'got mixed --to url schemes' 3 | 4 | ! atlas migrate diff --dev-url sqlite://devdb --to mysql://localhost/x --to mysql://localhost/y --dir file://migrations 5 | stderr 'got multiple --to urls of scheme' 6 | 7 | atlas migrate diff --dev-url sqlite://devdb --to file://schema/ --dir file://migrations 8 | cmpmig 0 diff.sql 9 | 10 | # reset dir 11 | exec rm -rf migrations/ 12 | 13 | atlas migrate diff --dev-url sqlite://devdb --to file://schema/schema.hcl --to file://schema/table.hcl --dir file://migrations 14 | cmpmig 0 diff.sql 15 | 16 | -- schema/schema.hcl -- 17 | schema "main" { 18 | } 19 | -- schema/table.hcl -- 20 | table "users" { 21 | schema = schema.main 22 | column "id" { 23 | null = false 24 | type = int 25 | } 26 | } 27 | -- diff.sql -- 28 | -- Create "users" table 29 | CREATE TABLE `users` (`id` int NOT NULL); -------------------------------------------------------------------------------- /internal/integration/testdata/sqlite/cli-migrate-diff.txtar: -------------------------------------------------------------------------------- 1 | exec mkdir migrations 2 | 3 | ! atlas migrate diff --to file://1.hcl --dir file://migrations 4 | stderr '"dev-url" not set' 5 | 6 | ! atlas migrate diff --dev-url sqlite://devdb --dir file://migrations 7 | stderr '"to" not set' 8 | 9 | atlas migrate diff --dev-url sqlite://devdb --to file://1.hcl --dir file://migrations 10 | cmpmig 0 diff.sql 11 | -- 1.hcl -- 12 | table "users" { 13 | schema = schema.main 14 | column "id" { 15 | null = false 16 | type = int 17 | } 18 | } 19 | schema "main" { 20 | } 21 | -- diff.sql -- 22 | -- Create "users" table 23 | CREATE TABLE `users` (`id` int NOT NULL); -------------------------------------------------------------------------------- /internal/integration/testdata/sqlite/cli-migrate-lint-add-notnull.txtar: -------------------------------------------------------------------------------- 1 | atlas migrate lint --dir file://migrations --dev-url URL --latest=2 2 | stdout 'Analyzing changes until version 2 \(2 migrations in total\):' 3 | stdout '' 4 | stdout ' -- analyzing version 1' 5 | stdout ' -- no diagnostics found' 6 | stdout ' -- ok \(.+\)' 7 | stdout '' 8 | stdout ' -- analyzing version 2' 9 | stdout ' -- data dependent changes detected:' 10 | stdout ' -- L1: Adding a non-nullable "int" column "c2" will fail in case table "users" is not empty' 11 | stdout ' https://atlasgo.io/lint/analyzers#MF103' 12 | stdout ' -- ok \(.+\)' 13 | stdout '' 14 | stdout ' -------------------------' 15 | stdout ' -- .+' 16 | stdout ' -- 1 version ok, 1 with warnings' 17 | stdout ' -- 4 schema changes' 18 | stdout ' -- 1 diagnostic' 19 | 20 | -- migrations/1.sql -- 21 | CREATE TABLE users (id int); 22 | 23 | /* Adding a not-null column without default to a table created in this file should not report. */ 24 | ALTER TABLE users ADD COLUMN c1 int NOT NULL; 25 | 26 | -- migrations/2.sql -- 27 | ALTER TABLE users ADD COLUMN c2 int NOT NULL; 28 | 29 | ALTER TABLE users ADD COLUMN c3 int NOT NULL DEFAULT 1; 30 | -------------------------------------------------------------------------------- /internal/integration/testdata/sqlite/cli-migrate-lint-destructive.txtar: -------------------------------------------------------------------------------- 1 | # Expect the command to fail; exit code 1. 2 | ! atlas migrate lint --dir file://migrations --dev-url URL --latest=1 3 | stdout 'Analyzing changes from version 2 to 3 \(1 migration in total\):' 4 | stdout '' 5 | stdout ' -- analyzing version 3' 6 | stdout ' -- destructive changes detected:' 7 | stdout ' -- L1: Dropping table "pets" https://atlasgo.io/lint/analyzers#DS102' 8 | stdout ' -- suggested fix:' 9 | stdout ' -> Add a pre-migration check to ensure table "pets" is empty before dropping it' 10 | stdout ' -- ok \(.+\)' 11 | stdout '' 12 | stdout ' -------------------------' 13 | stdout ' -- .+' 14 | stdout ' -- 1 version with errors' 15 | stdout ' -- 1 schema change' 16 | stdout ' -- 1 diagnostic' 17 | 18 | # Expect the command to fail; exit code 1. 19 | ! atlas migrate lint --dir file://migrations --dev-url URL --latest=2 20 | stdout 'Analyzing changes from version 1 to 3 \(2 migrations in total\):' 21 | stdout '' 22 | stdout ' -- analyzing version 2' 23 | stdout ' -- destructive changes detected:' 24 | stdout ' -- L1: Dropping table "users" https://atlasgo.io/lint/analyzers#DS102' 25 | stdout ' -- suggested fix:' 26 | stdout ' -> Add a pre-migration check to ensure table "users" is empty before dropping it' 27 | stdout ' -- ok \(.+\)' 28 | stdout '' 29 | stdout ' -- analyzing version 3' 30 | stdout ' -- destructive changes detected:' 31 | stdout ' -- L1: Dropping table "pets" https://atlasgo.io/lint/analyzers#DS102' 32 | stdout ' -- suggested fix:' 33 | stdout ' -> Add a pre-migration check to ensure table "pets" is empty before dropping it' 34 | stdout ' -- ok \(.+\)' 35 | stdout '' 36 | stdout ' -------------------------' 37 | stdout ' -- .+' 38 | stdout ' -- 2 versions with errors' 39 | stdout ' -- 2 schema changes' 40 | stdout ' -- 2 diagnostics' 41 | 42 | -- migrations/1.sql -- 43 | CREATE TABLE users (id int); 44 | 45 | CREATE TABLE pets (id int); 46 | 47 | ALTER TABLE users RENAME COLUMN id TO oid; 48 | 49 | -- migrations/2.sql -- 50 | DROP TABLE users; 51 | 52 | -- migrations/3.sql -- 53 | DROP TABLE pets; 54 | -------------------------------------------------------------------------------- /internal/integration/testdata/sqlite/cli-migrate-lint-minimal-env.txtar: -------------------------------------------------------------------------------- 1 | # Expect the command to fail; exit code 1. 2 | ! atlas migrate lint --env local --latest=2 3 | stdout 'Analyzing changes until version 2 \(2 migrations in total\):' 4 | stdout '' 5 | stdout ' -- analyzing version 1' 6 | stdout ' -- no diagnostics found' 7 | stdout ' -- ok \(.+\)' 8 | stdout '' 9 | stdout ' -- analyzing version 2' 10 | stdout ' -- destructive changes detected:' 11 | stdout ' -- L1: Dropping table "users" https://atlasgo.io/lint/analyzers#DS102' 12 | stdout ' -- suggested fix:' 13 | stdout ' -> Add a pre-migration check to ensure table "users" is empty before dropping it' 14 | stdout ' -- ok \(.+\)' 15 | stdout '' 16 | stdout ' -------------------------' 17 | stdout ' -- .+' 18 | stdout ' -- 1 version ok, 1 with errors' 19 | stdout ' -- 2 schema changes' 20 | stdout ' -- 1 diagnostic' 21 | 22 | 23 | -- atlas.hcl -- 24 | env "local" { 25 | dev = "URL" 26 | } 27 | -- migrations/1.sql -- 28 | CREATE TABLE users (id int); 29 | -- migrations/2.sql -- 30 | DROP TABLE users; 31 | -------------------------------------------------------------------------------- /internal/integration/testdata/sqlite/cli-migrate-lint-project.txtar: -------------------------------------------------------------------------------- 1 | atlas migrate lint --dir file://migrations --dev-url URL --env=log_name > got.txt 2 | cmp got.txt expected1.txt 3 | 4 | atlas migrate lint --dir file://migrations --dev-url URL --env=log_count > got.txt 5 | cmp got.txt expected2.txt 6 | 7 | -- migrations/1.sql -- 8 | CREATE TABLE users (id int); 9 | 10 | CREATE TABLE pets (id int); 11 | 12 | ALTER TABLE users RENAME COLUMN id TO oid; 13 | 14 | -- migrations/2.sql -- 15 | DROP TABLE users; 16 | 17 | -- migrations/3.sql -- 18 | DROP TABLE pets; 19 | 20 | -- expected1.txt -- 21 | 3.sql 22 | -- expected2.txt -- 23 | 2 24 | -- atlas.hcl -- 25 | lint { 26 | latest = 1 27 | destructive { 28 | error = false 29 | } 30 | } 31 | 32 | env "log_name" { 33 | lint { 34 | log = "{{ range .Files }}{{ println .Name }}{{ end }}" 35 | } 36 | } 37 | 38 | env "log_count" { 39 | lint { 40 | latest = 2 41 | log = "{{ len .Files | println }}" 42 | } 43 | } -------------------------------------------------------------------------------- /internal/integration/testdata/sqlite/cli-migrate-project-multifile.txtar: -------------------------------------------------------------------------------- 1 | atlas migrate diff --env local 2 | cmpmig 0 diff.sql 3 | 4 | # reset 5 | exec rm -rf migrations 6 | 7 | atlas migrate diff --env src_list 8 | cmpmig 0 diff.sql 9 | 10 | # reset 11 | exec rm -rf migrations 12 | 13 | atlas migrate diff --env single_elem 14 | cmpmig 0 diff.sql 15 | -- atlas.hcl -- 16 | env "local" { 17 | url = "URL" 18 | dev = "sqlite://test?mode=memory&_fk=1" 19 | src = "./schema" 20 | migration { 21 | dir = "file://migrations" 22 | format = atlas 23 | } 24 | } 25 | env "src_list" { 26 | url = "URL" 27 | dev = "sqlite://test?mode=memory&_fk=1" 28 | src = [ 29 | "./schema/1.hcl", 30 | "./schema/2.hcl", 31 | ] 32 | migration { 33 | dir = "file://migrations" 34 | format = atlas 35 | } 36 | } 37 | env "single_elem" { 38 | url = "URL" 39 | dev = "sqlite://test?mode=memory&_fk=1" 40 | src = [ 41 | "./schema/", 42 | ] 43 | migration { 44 | dir = "file://migrations" 45 | format = atlas 46 | } 47 | } 48 | -- schema/1.hcl -- 49 | table "users" { 50 | schema = schema.main 51 | column "id" { 52 | null = false 53 | type = int 54 | } 55 | } 56 | -- schema/2.hcl -- 57 | schema "main" { 58 | } 59 | -- diff.sql -- 60 | -- Create "users" table 61 | CREATE TABLE `users` (`id` int NOT NULL); 62 | -- empty.sql -- 63 | -------------------------------------------------------------------------------- /internal/integration/testdata/sqlite/cli-migrate-project.txtar: -------------------------------------------------------------------------------- 1 | exec mkdir migrations 2 | atlas migrate diff --env local 3 | cmpmig 0 diff.sql 4 | 5 | atlas migrate validate --env local 6 | 7 | atlas migrate new 1 --env local 8 | cmpmig 1 empty.sql 9 | 10 | exec touch migrations/2.sql 11 | ! atlas migrate validate --env local 12 | stderr 'Error: checksum mismatch' 13 | 14 | atlas migrate hash --env local 15 | atlas migrate validate --env local 16 | 17 | -- atlas.hcl -- 18 | env "local" { 19 | url = "URL" 20 | dev = "sqlite://test?mode=memory&_fk=1" 21 | src = "./1.hcl" 22 | migration { 23 | dir = "file://migrations" 24 | format = atlas 25 | } 26 | } 27 | -- 1.hcl -- 28 | table "users" { 29 | schema = schema.main 30 | column "id" { 31 | null = false 32 | type = int 33 | } 34 | } 35 | schema "main" { 36 | } 37 | -- diff.sql -- 38 | -- Create "users" table 39 | CREATE TABLE `users` (`id` int NOT NULL); 40 | -- empty.sql -- 41 | -------------------------------------------------------------------------------- /internal/integration/testdata/sqlite/cli-migrate-set.txtar: -------------------------------------------------------------------------------- 1 | ! atlas migrate set 0 2 | stderr 'Error: checksum file not found' 3 | stdout 'You have a checksum error in your migration directory.' 4 | 5 | atlas migrate hash 6 | 7 | ! atlas migrate set --url URL 8 | stderr 'Error: accepts 1 arg\(s\), received 0' 9 | 10 | ! atlas migrate set --url URL foo bar 11 | stderr 'Error: accepts 1 arg\(s\), received 2' 12 | 13 | # Works on fresh database. 14 | atlas migrate set 1 --url URL 15 | atlas migrate apply 1 --url URL --dry-run 16 | stdout 'Migrating to version 2 from 1' 17 | 18 | # Set to second last migration. 19 | atlas migrate set 2 --url URL 20 | atlas migrate apply 1 --url URL --dry-run 21 | stdout 'Migrating to version 3 from 2' 22 | 23 | # Have one migration applied, manual do second, set revision and continue apply. 24 | clearSchema 25 | atlas migrate apply 1 --url URL 26 | stdout 'Migrating to version 1' 27 | atlas migrate set 2 --url URL 28 | atlas migrate apply 1 --url URL --dry-run 29 | stdout 'Migrating to version 3 from 2' 30 | 31 | # Set to non-existing migration requires flag. 32 | ! atlas migrate set 4 --url URL 33 | stderr 'Error: migration with version "4" not found' 34 | 35 | # If set to last version, nothing to do. 36 | atlas migrate set 3 --url URL 37 | atlas migrate apply --url URL 38 | stdout 'No migration files to execute' 39 | 40 | # Partially applied (error), fix with set. 41 | clearSchema 42 | mv broken.sql migrations/4.sql 43 | atlas migrate hash 44 | ! atlas migrate apply --url URL --tx-mode none 45 | stdout 'Migrating to version 4' 46 | atlas migrate set 4 --url URL 47 | atlas migrate apply --url URL 48 | stdout 'No migration files to execute' 49 | 50 | -- migrations/1_first.sql -- 51 | CREATE TABLE `users` (`id` bigint NOT NULL, `age` bigint NOT NULL, `name` varchar(255) NOT NULL, PRIMARY KEY (`id`)); 52 | 53 | -- migrations/2_second.sql -- 54 | ALTER TABLE `users` ADD UNIQUE INDEX `age` (`age`); 55 | 56 | -- migrations/3_third.sql -- 57 | CREATE TABLE `pets` (`id` bigint NOT NULL, `name` varchar(255) NOT NULL, PRIMARY KEY (`id`)); 58 | 59 | -- broken.sql -- 60 | CREATE TABLE `vets` (`id` bigint NOT NULL, `name` varchar(255) NOT NULL, PRIMARY KEY(`id`)); 61 | asdf ALTER TABLE `users` ADD UNIQUE INDEX `name` (`name`); 62 | -------------------------------------------------------------------------------- /internal/integration/testdata/sqlite/cli-project-vars.txtar: -------------------------------------------------------------------------------- 1 | ! atlas schema apply --env local --auto-approve 2 | stderr 'Error: missing value for required variable "user_status_default"' 3 | 4 | atlas schema apply --env local --auto-approve --var user_status_default=hello 5 | cmpshow users expected.sql 6 | 7 | -- atlas.hcl -- 8 | variable "user_status_default" { 9 | type = string 10 | } 11 | env "local" { 12 | url = "URL" 13 | src = "./1.hcl" 14 | def_val = var.user_status_default 15 | } 16 | -- 1.hcl -- 17 | variable "def_val" { 18 | type = string 19 | } 20 | table "users" { 21 | schema = schema.main 22 | column "id" { 23 | null = false 24 | type = int 25 | } 26 | column "status" { 27 | null = true 28 | type = text 29 | default = var.def_val 30 | } 31 | } 32 | schema "main" { 33 | } 34 | -- expected.sql -- 35 | CREATE TABLE `users` ( 36 | `id` int NOT NULL, 37 | `status` text NULL DEFAULT 'hello' 38 | ) -------------------------------------------------------------------------------- /internal/integration/testdata/sqlite/cli-schema-project-file.txtar: -------------------------------------------------------------------------------- 1 | ! atlas schema inspect 2 | stderr '"url" not set' 3 | 4 | ! atlas schema apply -f 1.hcl 5 | stderr '"url" not set' 6 | 7 | ! atlas schema apply --url URL 8 | stderr 'one of flag\(s\) "file" or "to" is required' 9 | 10 | ! atlas schema apply -f atlas.hcl -u URL 11 | stderr 'cannot parse project file' 12 | 13 | # Verify "url" and "src" attributes of the env are used. 14 | atlas schema apply --env local --auto-approve 15 | atlas schema inspect --env local > inspected.hcl 16 | cmp 1.hcl inspected.hcl 17 | 18 | # Verify the precedence of flag over project file. 19 | atlas schema apply --env local --auto-approve -f 2.hcl 20 | atlas schema inspect --env local > inspected.hcl 21 | cmp 2.hcl inspected.hcl 22 | 23 | -- atlas.hcl -- 24 | env "local" { 25 | url = "URL" 26 | src = "./1.hcl" 27 | } 28 | -- 1.hcl -- 29 | table "users" { 30 | schema = schema.main 31 | column "id" { 32 | null = false 33 | type = int 34 | } 35 | } 36 | schema "main" { 37 | } 38 | -- 2.hcl -- 39 | table "other" { 40 | schema = schema.main 41 | column "id" { 42 | null = false 43 | type = int 44 | } 45 | } 46 | schema "main" { 47 | } -------------------------------------------------------------------------------- /internal/integration/testdata/sqlite/column-default.txtar: -------------------------------------------------------------------------------- 1 | execsql 'CREATE TABLE tbl (col)' 2 | cmphcl 1.hcl 3 | 4 | -- 1.hcl -- 5 | table "tbl" { 6 | schema = schema.main 7 | column "col" { 8 | null = true 9 | type = blob 10 | } 11 | } 12 | schema "main" { 13 | } 14 | -------------------------------------------------------------------------------- /internal/integration/testdata/sqlite/column-user-defined.txtar: -------------------------------------------------------------------------------- 1 | # Initial changes. 2 | atlas schema apply --url URL --dev-url DEV_URL --to file://schema.v1.hcl --auto-approve 3 | atlas schema apply --url URL --dev-url DEV_URL --to file://schema.v1.hcl --auto-approve 4 | stdout 'Schema is synced, no changes to be made' 5 | atlas schema inspect --url URL > got 6 | cmp schema.v1.hcl.inspected got 7 | 8 | # Changing user defined type. 9 | atlas schema apply --url URL --dev-url DEV_URL --to file://schema.v2.hcl --auto-approve 10 | atlas schema apply --url URL --dev-url DEV_URL --to file://schema.v2.hcl --auto-approve 11 | stdout 'Schema is synced, no changes to be made' 12 | atlas schema inspect --url URL > got 13 | cmp schema.v2.hcl.inspected got 14 | 15 | -- schema.v1.hcl -- 16 | table "t" { 17 | schema = schema.main 18 | column "c" { 19 | null = true 20 | type = sql("USER_DEFINED") 21 | } 22 | } 23 | schema "main" { 24 | } 25 | -- schema.v1.hcl.inspected -- 26 | table "t" { 27 | schema = schema.main 28 | column "c" { 29 | null = true 30 | type = sql("USER_DEFINED") 31 | } 32 | } 33 | schema "main" { 34 | } 35 | -- schema.v2.hcl -- 36 | table "t" { 37 | schema = schema.main 38 | column "c" { 39 | null = true 40 | type = sql("USER_TYPE") 41 | } 42 | } 43 | schema "main" { 44 | } 45 | -- schema.v2.hcl.inspected -- 46 | table "t" { 47 | schema = schema.main 48 | column "c" { 49 | null = true 50 | type = sql("USER_TYPE") 51 | } 52 | } 53 | schema "main" { 54 | } -------------------------------------------------------------------------------- /internal/integration/testdata/sqlite/index-desc.txtar: -------------------------------------------------------------------------------- 1 | apply 1.hcl 2 | cmpshow users 1.sql 3 | 4 | # Drop the "DESC" option from the key part. 5 | apply 2.hcl 6 | cmpshow users 2.sql 7 | # Use of "columns" instead of "on" should not trigger a change. 8 | synced 2-no-change.hcl 9 | 10 | apply 3.hcl 11 | cmpshow users 3.sql 12 | 13 | -- 1.hcl -- 14 | schema "main" {} 15 | 16 | table "users" { 17 | schema = schema.main 18 | column "rank" { 19 | type = int 20 | } 21 | index "rank_idx" { 22 | on { 23 | desc = true 24 | column = table.users.column.rank 25 | } 26 | } 27 | } 28 | 29 | -- 1.sql -- 30 | CREATE TABLE `users` (`rank` int NOT NULL) 31 | CREATE INDEX `rank_idx` ON `users` (`rank` DESC) 32 | 33 | -- 2.hcl -- 34 | schema "main" {} 35 | 36 | table "users" { 37 | schema = schema.main 38 | column "rank" { 39 | type = int 40 | } 41 | index "rank_idx" { 42 | on { 43 | column = table.users.column.rank 44 | } 45 | } 46 | } 47 | 48 | -- 2.sql -- 49 | CREATE TABLE "users" (`rank` int NOT NULL) 50 | CREATE INDEX `rank_idx` ON `users` (`rank`) 51 | 52 | -- 2-no-change.hcl -- 53 | schema "main" {} 54 | 55 | table "users" { 56 | schema = schema.main 57 | column "rank" { 58 | type = int 59 | } 60 | index "rank_idx" { 61 | columns = [ 62 | table.users.column.rank, 63 | ] 64 | } 65 | } 66 | 67 | -- 3.hcl -- 68 | schema "main" {} 69 | 70 | table "users" { 71 | schema = schema.main 72 | column "rank" { 73 | type = int 74 | } 75 | column "score" { 76 | type = int 77 | } 78 | index "rank_score_idx" { 79 | on { 80 | column = table.users.column.rank 81 | } 82 | on { 83 | column = table.users.column.score 84 | desc = true 85 | } 86 | } 87 | } 88 | 89 | -- 3.sql -- 90 | CREATE TABLE "users" (`rank` int NOT NULL, `score` int NOT NULL) 91 | CREATE INDEX `rank_score_idx` ON `users` (`rank`, `score` DESC) -------------------------------------------------------------------------------- /internal/integration/testdata/sqlite/index-expr.txtar: -------------------------------------------------------------------------------- 1 | apply 1.hcl 2 | cmpshow users 1.sql 3 | 4 | apply 2.hcl 5 | cmpshow users 2.sql 6 | 7 | -- 1.hcl -- 8 | schema "main" {} 9 | 10 | table "users" { 11 | schema = schema.main 12 | column "first_name" { 13 | null = false 14 | type = text 15 | } 16 | column "last_name" { 17 | null = false 18 | type = text 19 | } 20 | index "full_name" { 21 | on { 22 | expr = "first_name || ' ' || last_name" 23 | } 24 | } 25 | } 26 | 27 | -- 1.sql -- 28 | CREATE TABLE `users` (`first_name` text NOT NULL, `last_name` text NOT NULL) 29 | CREATE INDEX `full_name` ON `users` ((first_name || ' ' || last_name)) 30 | 31 | -- 2.hcl -- 32 | schema "main" {} 33 | 34 | table "users" { 35 | schema = schema.main 36 | column "first_name" { 37 | null = false 38 | type = text 39 | } 40 | index "full_name" { 41 | on { 42 | expr = "lower(first_name) || '''s first name'" 43 | } 44 | } 45 | } 46 | 47 | -- 2.sql -- 48 | CREATE TABLE "users" (`first_name` text NOT NULL) 49 | CREATE INDEX `full_name` ON `users` ((lower(first_name) || '''s first name')) -------------------------------------------------------------------------------- /internal/integration/testdata/sqlite/index-partial.txtar: -------------------------------------------------------------------------------- 1 | apply 1.hcl 2 | cmpshow users 1.sql 3 | 4 | apply 2.hcl 5 | cmpshow users 2.sql 6 | 7 | -- 1.hcl -- 8 | schema "main" {} 9 | 10 | table "users" { 11 | schema = schema.main 12 | column "name" { 13 | null = false 14 | type = text 15 | } 16 | column "active" { 17 | null = true 18 | type = boolean 19 | } 20 | index "users_name" { 21 | columns = [column.name] 22 | where = "active" 23 | } 24 | } 25 | 26 | -- 1.sql -- 27 | CREATE TABLE `users` (`name` text NOT NULL, `active` boolean NULL) 28 | CREATE INDEX `users_name` ON `users` (`name`) WHERE active 29 | 30 | -- 2.hcl -- 31 | schema "main" {} 32 | 33 | table "users" { 34 | schema = schema.main 35 | column "name" { 36 | null = false 37 | type = text 38 | } 39 | column "active" { 40 | null = true 41 | type = boolean 42 | } 43 | index "users_name" { 44 | columns = [column.name] 45 | where = "active AND name <> ''" 46 | } 47 | } 48 | 49 | -- 2.sql -- 50 | CREATE TABLE "users" (`name` text NOT NULL, `active` boolean NULL) 51 | CREATE INDEX `users_name` ON `users` (`name`) WHERE active AND name <> '' -------------------------------------------------------------------------------- /internal/integration/testdata/sqlite/table-options.txtar: -------------------------------------------------------------------------------- 1 | apply 1.hcl 2 | cmpshow t1 1.sql 3 | cmpshow t2 2.sql 4 | cmpshow t3 3.sql 5 | 6 | # Drop options. 7 | apply 2.hcl 8 | cmpshow t1 11.sql 9 | 10 | -- 1.hcl -- 11 | schema "main" {} 12 | 13 | table "t1" { 14 | schema = schema.main 15 | column "id" { 16 | null = false 17 | type = integer 18 | } 19 | primary_key { 20 | columns = [column.id] 21 | } 22 | strict = true 23 | without_rowid = true 24 | } 25 | 26 | table "t2" { 27 | schema = schema.main 28 | column "id" { 29 | null = false 30 | type = integer 31 | } 32 | primary_key { 33 | columns = [column.id] 34 | } 35 | strict = true 36 | } 37 | 38 | table "t3" { 39 | schema = schema.main 40 | column "id" { 41 | null = false 42 | type = integer 43 | } 44 | primary_key { 45 | columns = [column.id] 46 | } 47 | without_rowid = true 48 | } 49 | 50 | -- 1.sql -- 51 | CREATE TABLE `t1` (`id` integer NOT NULL, PRIMARY KEY (`id`)) WITHOUT ROWID, STRICT 52 | 53 | -- 2.sql -- 54 | CREATE TABLE `t2` (`id` integer NOT NULL, PRIMARY KEY (`id`)) STRICT 55 | 56 | -- 3.sql -- 57 | CREATE TABLE `t3` (`id` integer NOT NULL, PRIMARY KEY (`id`)) WITHOUT ROWID 58 | 59 | -- 2.hcl -- 60 | schema "main" {} 61 | 62 | table "t1" { 63 | schema = schema.main 64 | column "id" { 65 | null = false 66 | type = integer 67 | } 68 | primary_key { 69 | columns = [column.id] 70 | } 71 | } 72 | 73 | -- 11.sql -- 74 | CREATE TABLE "t1" (`id` integer NOT NULL, PRIMARY KEY (`id`)) 75 | -------------------------------------------------------------------------------- /internal/integration/tools.go: -------------------------------------------------------------------------------- 1 | //go:build tools 2 | // +build tools 3 | 4 | package main 5 | 6 | import ( 7 | _ "ariga.io/atlas/cmd/atlas" 8 | ) 9 | -------------------------------------------------------------------------------- /schemahcl/testdata/a.hcl: -------------------------------------------------------------------------------- 1 | person "rotemtam" { 2 | hobby = var.hobby 3 | } -------------------------------------------------------------------------------- /schemahcl/testdata/b.hcl: -------------------------------------------------------------------------------- 1 | person "tzuri" { 2 | hobby = "ice-cream" 3 | parent = person.rotemtam 4 | } -------------------------------------------------------------------------------- /schemahcl/testdata/nested/c.hcl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ariga/atlas/907691a43e4d4571fb8dcbacedf0da15a0f5180a/schemahcl/testdata/nested/c.hcl -------------------------------------------------------------------------------- /schemahcl/testdata/variables.hcl: -------------------------------------------------------------------------------- 1 | variable "hobby" { 2 | type = string 3 | } -------------------------------------------------------------------------------- /sql/migrate/migrate_oss.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-present The Atlas Authors. All rights reserved. 2 | // This source code is licensed under the Apache 2.0 license found 3 | // in the LICENSE file in the root directory of this source tree. 4 | 5 | //go:build !ent 6 | 7 | package migrate 8 | 9 | import ( 10 | "context" 11 | "fmt" 12 | ) 13 | 14 | // IsCheckpoint reports whether the file is a checkpoint file. 15 | func (f *LocalFile) IsCheckpoint() bool { 16 | return f.isCheckpoint() 17 | } 18 | 19 | // CheckpointTag returns the tag of the checkpoint file, if defined. 20 | func (f *LocalFile) CheckpointTag() (string, error) { 21 | return f.checkpointTag() 22 | } 23 | 24 | // fileStmts returns the statements defined in the given file. 25 | func (e *Executor) fileStmts(f File) ([]*Stmt, error) { 26 | return FileStmtDecls(e.drv, f) 27 | } 28 | 29 | func (e *Executor) fileChecks(context.Context, File, *Revision) error { 30 | return nil // unimplemented 31 | } 32 | 33 | // ValidateDir before operating on it. 34 | func (e *Executor) ValidateDir(context.Context) error { 35 | if err := Validate(e.dir); err != nil { 36 | return fmt.Errorf("sql/migrate: validate migration directory: %w", err) 37 | } 38 | return nil 39 | } 40 | 41 | func (e *StmtExecError) Error() string { 42 | return fmt.Sprintf("sql/migrate: executing statement %q from version %q: %v", e.Stmt.Text, e.Version, e.Err) 43 | } 44 | -------------------------------------------------------------------------------- /sql/migrate/testdata/golang-migrate/1_base.up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE t(c int); -------------------------------------------------------------------------------- /sql/migrate/testdata/lex/1.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE t1(id int); 2 | 3 | 4 | CREATE TABLE t2(id int); 5 | 6 | CREATE TABLE t3(id int); 7 | 8 | CREATE TABLE t4( 9 | id int, 10 | name varchar(255) 11 | ); 12 | 13 | CREATE TABLE t4( 14 | id int, 15 | `name` varchar(255) DEFAULT ';' 16 | ) ENGINE=InnoDB; 17 | 18 | CREATE TABLE t5( 19 | id int 20 | /* comment */ 21 | -- comment 22 | ) ENGINE=InnoDB; -------------------------------------------------------------------------------- /sql/migrate/testdata/lex/1.sql.golden: -------------------------------------------------------------------------------- 1 | CREATE TABLE t1(id int); 2 | -- end -- 3 | CREATE TABLE t2(id int); 4 | -- end -- 5 | CREATE TABLE t3(id int); 6 | -- end -- 7 | CREATE TABLE t4( 8 | id int, 9 | name varchar(255) 10 | ); 11 | -- end -- 12 | CREATE TABLE t4( 13 | id int, 14 | `name` varchar(255) DEFAULT ';' 15 | ) ENGINE=InnoDB; 16 | -- end -- 17 | CREATE TABLE t5( 18 | id int 19 | /* comment */ 20 | -- comment 21 | ) ENGINE=InnoDB; -------------------------------------------------------------------------------- /sql/migrate/testdata/lex/10_delimiter_comment.sql: -------------------------------------------------------------------------------- 1 | -- atlas:delimiter -- end 2 | 3 | CREATE PROCEDURE dorepeat(p1 INT) 4 | BEGIN 5 | SET @x = 0; 6 | REPEAT SET @x = @x + 1; UNTIL @x > p1 END REPEAT; 7 | END; 8 | -- end 9 | CALL dorepeat(1000); 10 | -------------------------------------------------------------------------------- /sql/migrate/testdata/lex/10_delimiter_comment.sql.golden: -------------------------------------------------------------------------------- 1 | CREATE PROCEDURE dorepeat(p1 INT) 2 | BEGIN 3 | SET @x = 0; 4 | REPEAT SET @x = @x + 1; UNTIL @x > p1 END REPEAT; 5 | END; 6 | -- end -- 7 | CALL dorepeat(1000); -------------------------------------------------------------------------------- /sql/migrate/testdata/lex/11_delimiter_mysql_command.sql: -------------------------------------------------------------------------------- 1 | -- An example for supporting MySQL client delimiters. 2 | 3 | DELIMITER $$ 4 | 5 | CREATE OR REPLACE FUNCTION gen_uuid() RETURNS VARCHAR(22) 6 | BEGIN 7 | RETURN concat( 8 | date_format(NOW(6), '%Y%m%d%i%s%f'), 9 | ROUND(1 + RAND() * (100 - 2)) 10 | ); 11 | END;$$ 12 | 13 | DELIMITER ; 14 | 15 | CALL gen_uuid(); 16 | -------------------------------------------------------------------------------- /sql/migrate/testdata/lex/11_delimiter_mysql_command.sql.golden: -------------------------------------------------------------------------------- 1 | CREATE OR REPLACE FUNCTION gen_uuid() RETURNS VARCHAR(22) 2 | BEGIN 3 | RETURN concat( 4 | date_format(NOW(6), '%Y%m%d%i%s%f'), 5 | ROUND(1 + RAND() * (100 - 2)) 6 | ); 7 | END; 8 | -- end -- 9 | CALL gen_uuid(); -------------------------------------------------------------------------------- /sql/migrate/testdata/lex/12_delimiter_mysql_command.sql: -------------------------------------------------------------------------------- 1 | delimiter // 2 | create table t2 (a int) // 3 | 4 | delimiter ; 5 | delimiter // 6 | 7 | create table t3 (a int) // 8 | delimiter ; 9 | 10 | show tables; 11 | drop table t2, t3; 12 | -------------------------------------------------------------------------------- /sql/migrate/testdata/lex/12_delimiter_mysql_command.sql.golden: -------------------------------------------------------------------------------- 1 | create table t2 (a int) 2 | -- end -- 3 | create table t3 (a int) 4 | -- end -- 5 | show tables; 6 | -- end -- 7 | drop table t2, t3; -------------------------------------------------------------------------------- /sql/migrate/testdata/lex/13_delimiter_mysql_command.sql: -------------------------------------------------------------------------------- 1 | # Test delimiter : 2 | select "Test delimiter :" as " "; 3 | delimiter : 4 | select * from t1: 5 | /* Delimiter commands can have comments */ 6 | delimiter ; 7 | select 'End test :'; 8 | 9 | /* Test delimiter :; */ 10 | select "Test delimiter :;" as " "; 11 | delimiter :; 12 | select * from t1 :; 13 | delimiter ; 14 | select 'End test :;'; 15 | 16 | -- Test delimiter // 17 | select "Test delimiter //" as " "; 18 | delimiter // 19 | select * from t1// 20 | delimiter ; 21 | select 'End test //'; 22 | 23 | # Test delimiter 'MySQL' 24 | select "Test delimiter MySQL" as " "; 25 | delimiter 'MySQL' 26 | select * from t1MySQL 27 | delimiter ; 28 | select 'End test MySQL'; 29 | 30 | # Test delimiter 'delimiter' 31 | select "Test delimiter delimiter" as " "; 32 | delimiter delimiter 33 | select * from t1delimiter 34 | delimiter ; 35 | select 'End test delimiter'; 36 | 37 | # Test delimiter @@ 38 | select "Test delimiter @@" as " "; 39 | delimiter @@ 40 | select * from t1 @@ 41 | select * from t2@@ 42 | alter table t add column c@@ 43 | delimiter ; 44 | select 'End test @@'; 45 | 46 | # Test delimiter \n\n 47 | select "Test delimiter \n\n" as " "; 48 | delimiter \n\n 49 | select * from t1 50 | 51 | select * from t2 52 | 53 | delimiter ; 54 | select 'End test \\n\\n'; -------------------------------------------------------------------------------- /sql/migrate/testdata/lex/13_delimiter_mysql_command.sql.golden: -------------------------------------------------------------------------------- 1 | select "Test delimiter :" as " "; 2 | -- end -- 3 | select * from t1 4 | -- end -- 5 | select 'End test :'; 6 | -- end -- 7 | select "Test delimiter :;" as " "; 8 | -- end -- 9 | select * from t1 10 | -- end -- 11 | select 'End test :;'; 12 | -- end -- 13 | select "Test delimiter //" as " "; 14 | -- end -- 15 | select * from t1 16 | -- end -- 17 | select 'End test //'; 18 | -- end -- 19 | select "Test delimiter MySQL" as " "; 20 | -- end -- 21 | select * from t1 22 | -- end -- 23 | select 'End test MySQL'; 24 | -- end -- 25 | select "Test delimiter delimiter" as " "; 26 | -- end -- 27 | select * from t1 28 | -- end -- 29 | select 'End test delimiter'; 30 | -- end -- 31 | select "Test delimiter @@" as " "; 32 | -- end -- 33 | select * from t1 34 | -- end -- 35 | select * from t2 36 | -- end -- 37 | alter table t add column c 38 | -- end -- 39 | select 'End test @@'; 40 | -- end -- 41 | select "Test delimiter \n\n" as " "; 42 | -- end -- 43 | select * from t1 44 | -- end -- 45 | select * from t2 46 | -- end -- 47 | select 'End test \\n\\n'; -------------------------------------------------------------------------------- /sql/migrate/testdata/lex/14_delimiter_mysql_command.sql: -------------------------------------------------------------------------------- 1 | DELIMITER // 2 | CREATE PROCEDURE dorepeat(p1 INT) 3 | BEGIN 4 | SET @x = 0; 5 | REPEAT SET @x = @x + 1; UNTIL @x > p1 END REPEAT; 6 | END 7 | // 8 | DELIMITER ; 9 | CALL dorepeat(100) -------------------------------------------------------------------------------- /sql/migrate/testdata/lex/14_delimiter_mysql_command.sql.golden: -------------------------------------------------------------------------------- 1 | CREATE PROCEDURE dorepeat(p1 INT) 2 | BEGIN 3 | SET @x = 0; 4 | REPEAT SET @x = @x + 1; UNTIL @x > p1 END REPEAT; 5 | END 6 | -- end -- 7 | CALL dorepeat(100) -------------------------------------------------------------------------------- /sql/migrate/testdata/lex/16_begin_atomic.sql: -------------------------------------------------------------------------------- 1 | CREATE FUNCTION functest_S_1(a text, b date) RETURNS boolean 2 | LANGUAGE SQL 3 | RETURN a = 'abcd' AND b > '2001-01-01'; 4 | CREATE FUNCTION functest_S_2(a text[]) RETURNS int 5 | RETURN a[1]::int; 6 | CREATE FUNCTION functest_S_3() RETURNS boolean 7 | RETURN false; 8 | CREATE FUNCTION functest_S_10(a text, b date) RETURNS boolean 9 | LANGUAGE SQL 10 | BEGIN ATOMIC 11 | SELECT a = 'abcd' AND b > '2001-01-01'; 12 | END; 13 | CREATE FUNCTION functest_S_13() RETURNS boolean 14 | BEGIN ATOMIC 15 | SELECT 1; 16 | SELECT false; 17 | END; 18 | CREATE FUNCTION functest_S_15(x int) RETURNS boolean 19 | LANGUAGE SQL 20 | BEGIN ATOMIC 21 | select case when x % 2 = 0 then true else false end; -- tricky parsing 22 | END; 23 | CREATE FUNCTION functest_sri2() RETURNS SETOF int 24 | LANGUAGE SQL 25 | STABLE 26 | BEGIN ATOMIC 27 | SELECT * FROM functest3; 28 | END; 29 | CREATE TABLE functest1 (i int); 30 | CREATE FUNCTION functest_S_16(a int, b int) RETURNS void 31 | LANGUAGE SQL 32 | BEGIN ATOMIC 33 | INSERT INTO functest1 SELECT a + $2; 34 | END; 35 | 36 | CREATE FUNCTION functest_S_15(x int) RETURNS boolean 37 | LANGUAGE SQL 38 | BEGIN ATOMIC 39 | select case when x % 2 = 0 then true else false end; 40 | select case when x % 2 = 0 then true else false end; 41 | select case when x % 2 = 0 then true else false end; 42 | select case when x % 2 = 0 then true else false end; 43 | END; 44 | 45 | CREATE FUNCTION "functest_s_15" ("x" integer) RETURNS boolean LANGUAGE SQL BEGIN ATOMIC 46 | SELECT 47 | CASE 48 | WHEN ((x % 2) = 0) THEN true 49 | ELSE false 50 | END AS "case"; 51 | END; -------------------------------------------------------------------------------- /sql/migrate/testdata/lex/16_begin_atomic.sql.golden: -------------------------------------------------------------------------------- 1 | CREATE FUNCTION functest_S_1(a text, b date) RETURNS boolean 2 | LANGUAGE SQL 3 | RETURN a = 'abcd' AND b > '2001-01-01'; 4 | -- end -- 5 | CREATE FUNCTION functest_S_2(a text[]) RETURNS int 6 | RETURN a[1]::int; 7 | -- end -- 8 | CREATE FUNCTION functest_S_3() RETURNS boolean 9 | RETURN false; 10 | -- end -- 11 | CREATE FUNCTION functest_S_10(a text, b date) RETURNS boolean 12 | LANGUAGE SQL 13 | BEGIN ATOMIC 14 | SELECT a = 'abcd' AND b > '2001-01-01'; 15 | END; 16 | -- end -- 17 | CREATE FUNCTION functest_S_13() RETURNS boolean 18 | BEGIN ATOMIC 19 | SELECT 1; 20 | SELECT false; 21 | END; 22 | -- end -- 23 | CREATE FUNCTION functest_S_15(x int) RETURNS boolean 24 | LANGUAGE SQL 25 | BEGIN ATOMIC 26 | select case when x % 2 = 0 then true else false end; -- tricky parsing 27 | END; 28 | -- end -- 29 | CREATE FUNCTION functest_sri2() RETURNS SETOF int 30 | LANGUAGE SQL 31 | STABLE 32 | BEGIN ATOMIC 33 | SELECT * FROM functest3; 34 | END; 35 | -- end -- 36 | CREATE TABLE functest1 (i int); 37 | -- end -- 38 | CREATE FUNCTION functest_S_16(a int, b int) RETURNS void 39 | LANGUAGE SQL 40 | BEGIN ATOMIC 41 | INSERT INTO functest1 SELECT a + $2; 42 | END; 43 | -- end -- 44 | CREATE FUNCTION functest_S_15(x int) RETURNS boolean 45 | LANGUAGE SQL 46 | BEGIN ATOMIC 47 | select case when x % 2 = 0 then true else false end; 48 | select case when x % 2 = 0 then true else false end; 49 | select case when x % 2 = 0 then true else false end; 50 | select case when x % 2 = 0 then true else false end; 51 | END; 52 | -- end -- 53 | CREATE FUNCTION "functest_s_15" ("x" integer) RETURNS boolean LANGUAGE SQL BEGIN ATOMIC 54 | SELECT 55 | CASE 56 | WHEN ((x % 2) = 0) THEN true 57 | ELSE false 58 | END AS "case"; 59 | END; -------------------------------------------------------------------------------- /sql/migrate/testdata/lex/17_paren.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE ONLY t ADD CONSTRAINT name1 EXCLUDE USING gist (id WITH =, cid WITH -|-); 2 | ALTER TABLE ONLY t 3 | ADD CONSTRAINT name2 EXCLUDE USING gist (id WITH =, cid WITH -|-); 4 | ALTER TABLE ONLY t 5 | ADD CONSTRAINT name3 EXCLUDE USING gist (id WITH =, cid WITH -|-), 6 | ADD CONSTRAINT name4 EXCLUDE USING gist (id WITH =, cid WITH -|-); 7 | -------------------------------------------------------------------------------- /sql/migrate/testdata/lex/17_paren.sql.golden: -------------------------------------------------------------------------------- 1 | ALTER TABLE ONLY t ADD CONSTRAINT name1 EXCLUDE USING gist (id WITH =, cid WITH -|-); 2 | -- end -- 3 | ALTER TABLE ONLY t 4 | ADD CONSTRAINT name2 EXCLUDE USING gist (id WITH =, cid WITH -|-); 5 | -- end -- 6 | ALTER TABLE ONLY t 7 | ADD CONSTRAINT name3 EXCLUDE USING gist (id WITH =, cid WITH -|-), 8 | ADD CONSTRAINT name4 EXCLUDE USING gist (id WITH =, cid WITH -|-); -------------------------------------------------------------------------------- /sql/migrate/testdata/lex/18_pg_expr.sql: -------------------------------------------------------------------------------- 1 | -- Comment 1. 2 | CREATE INDEX "i" ON "s"."t" (((c #>> '{a,b,c}'::text[]))); 3 | 4 | /* 5 | Comment 2. 6 | */ 7 | SELECT name 8 | FROM company.employees 9 | WHERE info #>> '{department, name}' = 'Engineering'; 10 | 11 | /* 12 | SELECT name 13 | FROM company.employees 14 | WHERE info #>> '{contact, email}' = 'alice@company.com'; 15 | */ 16 | SELECT name 17 | FROM company.employees 18 | WHERE info #>> '{contact, email}' = 'alice@company.com'; 19 | 20 | -- Comment 3. 21 | CREATE INDEX "idx_emp_department" ON "company"."employees" ( 22 | (info #>> '{department, name}') 23 | ); 24 | 25 | /* 26 | 27 | CREATE INDEX "idx_emp_contact" ON "company"."employees" ( 28 | LOWER(info #>> '{contact, email}') 29 | ); 30 | */ 31 | CREATE INDEX "idx_emp_contact" ON "company"."employees" ( 32 | LOWER(info #>> '{contact, email}') 33 | ); 34 | 35 | /** 36 | SELECT 37 | info #>> '{department, name}' AS department, 38 | COUNT(*) AS emp_count 39 | FROM company.employees 40 | GROUP BY info #>> '{department, name}'; 41 | */ 42 | SELECT 43 | info #>> '{department, name}' AS department, 44 | COUNT(*) AS emp_count 45 | FROM company.employees 46 | GROUP BY info #>> '{department, name}'; 47 | 48 | /** 49 | SELECT 50 | info #>> '{department, name}' AS department, 51 | COUNT(*) AS emp_count 52 | FROM company.employees 53 | GROUP BY info #>> '{department, name}'; 54 | */ 55 | /** 56 | SELECT 57 | info #>> '{department, name}' AS department, 58 | COUNT(*) AS emp_count 59 | FROM company.employees 60 | GROUP BY info #>> '{department, name}'; 61 | */ 62 | SELECT name 63 | FROM company.employees 64 | WHERE (info #>> '{department, name}' = 'Engineering' 65 | OR info #>> '{department, location}' = 'Building A') 66 | AND info #>> '{contact, email}' LIKE '%@company.com'; -------------------------------------------------------------------------------- /sql/migrate/testdata/lex/18_pg_expr.sql.golden: -------------------------------------------------------------------------------- 1 | CREATE INDEX "i" ON "s"."t" (((c #>> '{a,b,c}'::text[]))); 2 | -- end -- 3 | SELECT name 4 | FROM company.employees 5 | WHERE info #>> '{department, name}' = 'Engineering'; 6 | -- end -- 7 | SELECT name 8 | FROM company.employees 9 | WHERE info #>> '{contact, email}' = 'alice@company.com'; 10 | -- end -- 11 | CREATE INDEX "idx_emp_department" ON "company"."employees" ( 12 | (info #>> '{department, name}') 13 | ); 14 | -- end -- 15 | CREATE INDEX "idx_emp_contact" ON "company"."employees" ( 16 | LOWER(info #>> '{contact, email}') 17 | ); 18 | -- end -- 19 | SELECT 20 | info #>> '{department, name}' AS department, 21 | COUNT(*) AS emp_count 22 | FROM company.employees 23 | GROUP BY info #>> '{department, name}'; 24 | -- end -- 25 | SELECT name 26 | FROM company.employees 27 | WHERE (info #>> '{department, name}' = 'Engineering' 28 | OR info #>> '{department, location}' = 'Building A') 29 | AND info #>> '{contact, email}' LIKE '%@company.com'; -------------------------------------------------------------------------------- /sql/migrate/testdata/lex/19_ms_gocmd.sql: -------------------------------------------------------------------------------- 1 | go 2 | SELECT 1 3 | -- comment here 4 | GO 5 | SELECT 2 -- another comment 6 | GO 7 | SELECT 3 GO 8 | GO 9 | SELECT 4 10 | GOTO 11 | SELECT 5 12 | GO 11 13 | SELECT 6 14 | GO -------------------------------------------------------------------------------- /sql/migrate/testdata/lex/19_ms_gocmd.sql.golden: -------------------------------------------------------------------------------- 1 | 2 | -- end -- 3 | SELECT 1 4 | -- comment here 5 | -- end -- 6 | SELECT 2 -- another comment 7 | -- end -- 8 | SELECT 3 GO 9 | -- end -- 10 | SELECT 4 11 | GOTO 12 | SELECT 5 13 | -- end -- 14 | SELECT 6 -------------------------------------------------------------------------------- /sql/migrate/testdata/lex/20_ms_go-delim.sql: -------------------------------------------------------------------------------- 1 | -- atlas:delimiter \nGO 2 | 3 | go 4 | SELECT 1 5 | -- comment here 6 | GO 7 | SELECT 2 -- another comment 8 | GO 9 | SELECT 3 GO 10 | gO 11 | SELECT 4 12 | GOTO -- this command is truncated by delimiter 13 | SELECT 5 14 | GO 11 15 | SELECT 6 16 | GO -------------------------------------------------------------------------------- /sql/migrate/testdata/lex/20_ms_go-delim.sql.golden: -------------------------------------------------------------------------------- 1 | 2 | -- end -- 3 | SELECT 1 4 | -- comment here 5 | -- end -- 6 | SELECT 2 -- another comment 7 | -- end -- 8 | SELECT 3 GO 9 | -- end -- 10 | SELECT 4 11 | -- end -- 12 | TO -- this command is truncated by delimiter 13 | SELECT 5 14 | -- end -- 15 | SELECT 6 -------------------------------------------------------------------------------- /sql/migrate/testdata/lex/2_mysql.sql: -------------------------------------------------------------------------------- 1 | create table t1 (b char(0)); 2 | create table t1 (b char(0) not null); 3 | create table if not exists t1 (b char(0) not null); 4 | create table t2 engine=heap select * from t1; 5 | create table t1 (ordid int(8) not null auto_increment, ord varchar(50) not null, primary key (ord,ordid)) engine=heap; 6 | create table mysqltest.$test1 (a$1 int, $b int, c$ int); 7 | create table t2 (b int) select a as b, a+1 as b from t1; 8 | create table t1 select if('2002'='2002','Y','N'); 9 | create table t1 ( k1 varchar(2), k2 int, primary key(k1,k2)); 10 | insert into t1 values ("a", 1), ("b", 2); 11 | create table t2 12 | select 13 | a, 14 | ifnull(b,cast(-7 as signed)) as b, 15 | ifnull(c,cast(7 as unsigned)) as c, 16 | ifnull(d,cast('2000-01-01' as date)) as d, 17 | ifnull(e,cast('b' as char)) as e, 18 | ifnull(f,cast('2000-01-01' as datetime)) as f, 19 | ifnull(g,cast('5:4:3' as time)) as g, 20 | ifnull(h,cast('yet another binary data' as binary)) as h, 21 | addtime(cast('1:0:0' as time),cast('1:0:0' as time)) as dd 22 | from t1; 23 | CREATE TABLE t1(id varchar(10) NOT NULL PRIMARY KEY, dsc longtext); 24 | INSERT INTO t1 VALUES ('5000000001', NULL),('5000000003', 'Test'),('5000000004', NULL); 25 | create table t1 ( 26 | a varchar(112) charset utf8 collate utf8_bin not null, 27 | primary key (a) 28 | ) select 'test' as a ; 29 | create table טבלה_של_אריאל 30 | ( 31 | כמות int 32 | ); 33 | 34 | 35 | 36 | CREATE TABLE t1( 37 | c1 INT DEFAULT 12 COMMENT 'column1', 38 | c2 INT NULL COMMENT 'column2', 39 | c3 INT NOT NULL COMMENT 'column3', 40 | c4 VARCHAR(255) CHARACTER SET utf8 NOT NULL DEFAULT 'a', 41 | c5 VARCHAR(255) COLLATE utf8_unicode_ci NULL DEFAULT 'b', 42 | c6 VARCHAR(255)) 43 | COLLATE latin1_bin; -------------------------------------------------------------------------------- /sql/migrate/testdata/lex/2_mysql.sql.golden: -------------------------------------------------------------------------------- 1 | create table t1 (b char(0)); 2 | -- end -- 3 | create table t1 (b char(0) not null); 4 | -- end -- 5 | create table if not exists t1 (b char(0) not null); 6 | -- end -- 7 | create table t2 engine=heap select * from t1; 8 | -- end -- 9 | create table t1 (ordid int(8) not null auto_increment, ord varchar(50) not null, primary key (ord,ordid)) engine=heap; 10 | -- end -- 11 | create table mysqltest.$test1 (a$1 int, $b int, c$ int); 12 | -- end -- 13 | create table t2 (b int) select a as b, a+1 as b from t1; 14 | -- end -- 15 | create table t1 select if('2002'='2002','Y','N'); 16 | -- end -- 17 | create table t1 ( k1 varchar(2), k2 int, primary key(k1,k2)); 18 | -- end -- 19 | insert into t1 values ("a", 1), ("b", 2); 20 | -- end -- 21 | create table t2 22 | select 23 | a, 24 | ifnull(b,cast(-7 as signed)) as b, 25 | ifnull(c,cast(7 as unsigned)) as c, 26 | ifnull(d,cast('2000-01-01' as date)) as d, 27 | ifnull(e,cast('b' as char)) as e, 28 | ifnull(f,cast('2000-01-01' as datetime)) as f, 29 | ifnull(g,cast('5:4:3' as time)) as g, 30 | ifnull(h,cast('yet another binary data' as binary)) as h, 31 | addtime(cast('1:0:0' as time),cast('1:0:0' as time)) as dd 32 | from t1; 33 | -- end -- 34 | CREATE TABLE t1(id varchar(10) NOT NULL PRIMARY KEY, dsc longtext); 35 | -- end -- 36 | INSERT INTO t1 VALUES ('5000000001', NULL),('5000000003', 'Test'),('5000000004', NULL); 37 | -- end -- 38 | create table t1 ( 39 | a varchar(112) charset utf8 collate utf8_bin not null, 40 | primary key (a) 41 | ) select 'test' as a ; 42 | -- end -- 43 | create table טבלה_של_אריאל 44 | ( 45 | כמות int 46 | ); 47 | -- end -- 48 | CREATE TABLE t1( 49 | c1 INT DEFAULT 12 COMMENT 'column1', 50 | c2 INT NULL COMMENT 'column2', 51 | c3 INT NOT NULL COMMENT 'column3', 52 | c4 VARCHAR(255) CHARACTER SET utf8 NOT NULL DEFAULT 'a', 53 | c5 VARCHAR(255) COLLATE utf8_unicode_ci NULL DEFAULT 'b', 54 | c6 VARCHAR(255)) 55 | COLLATE latin1_bin; -------------------------------------------------------------------------------- /sql/migrate/testdata/lex/3_delimiter.sql: -------------------------------------------------------------------------------- 1 | -- atlas:delimiter \n\n 2 | 3 | CREATE INDEX i1 ON t1(c1) 4 | 5 | CREATE INDEX i2 ON t2(c2) -------------------------------------------------------------------------------- /sql/migrate/testdata/lex/3_delimiter.sql.golden: -------------------------------------------------------------------------------- 1 | CREATE INDEX i1 ON t1(c1) 2 | -- end -- 3 | CREATE INDEX i2 ON t2(c2) -------------------------------------------------------------------------------- /sql/migrate/testdata/lex/4_delimiter.sql: -------------------------------------------------------------------------------- 1 | -- atlas:delimiter \n---\n 2 | 3 | CREATE INDEX i1 ON t1(c1) 4 | --- 5 | CREATE INDEX i2 ON t2(c2) -------------------------------------------------------------------------------- /sql/migrate/testdata/lex/4_delimiter.sql.golden: -------------------------------------------------------------------------------- 1 | CREATE INDEX i1 ON t1(c1) 2 | -- end -- 3 | CREATE INDEX i2 ON t2(c2) -------------------------------------------------------------------------------- /sql/migrate/testdata/lex/5_delimiter.sql: -------------------------------------------------------------------------------- 1 | -- atlas:delimiter \n-- end --\n 2 | 3 | CREATE DEFINER='boring' PROCEDURE proc () 4 | COMMENT 'ATLAS_DELIMITER' 5 | SQL SECURITY INVOKER 6 | NOT DETERMINISTIC 7 | MODIFIES SQL DATA 8 | BEGIN 9 | UPDATE performance_schema.threads 10 | SET instrumented = 'YES' 11 | WHERE type = 'BACKGROUND'; 12 | 13 | SELECT CONCAT('Enabled ', @rows := ROW_COUNT(), ' background thread', IF(@rows != 1, 's', '')) AS summary; 14 | END 15 | 16 | -- end -- 17 | 18 | CALL proc(); -------------------------------------------------------------------------------- /sql/migrate/testdata/lex/5_delimiter.sql.golden: -------------------------------------------------------------------------------- 1 | CREATE DEFINER='boring' PROCEDURE proc () 2 | COMMENT 'ATLAS_DELIMITER' 3 | SQL SECURITY INVOKER 4 | NOT DETERMINISTIC 5 | MODIFIES SQL DATA 6 | BEGIN 7 | UPDATE performance_schema.threads 8 | SET instrumented = 'YES' 9 | WHERE type = 'BACKGROUND'; 10 | 11 | SELECT CONCAT('Enabled ', @rows := ROW_COUNT(), ' background thread', IF(@rows != 1, 's', '')) AS summary; 12 | END 13 | -- end -- 14 | CALL proc(); -------------------------------------------------------------------------------- /sql/migrate/testdata/lex/6_skip_comment.sql: -------------------------------------------------------------------------------- 1 | -- comment 1 2 | CREATE TABLE t1(id int); 3 | # CREATE TABLE t1(id int); 4 | 5 | -- comment 2 6 | # CREATE TABLE t2(id int); 7 | CREATE TABLE t2(id int); 8 | -- comment 3 9 | CREATE TABLE t3(id int); 10 | 11 | # CREATE TABLE t3(id int); 12 | 13 | /* comment 4 */ 14 | CREATE TABLE t4( 15 | id int 16 | /* comment */ 17 | -- comment 18 | ) ENGINE=InnoDB; 19 | 20 | /* comment 5 21 | */ 22 | CREATE TABLE t5( 23 | id int 24 | /* comment */ 25 | -- comment 26 | ) ENGINE=InnoDB; 27 | 28 | SELECT * FROM ( 29 | SELECT * FROM t1 # comment 30 | ); 31 | 32 | # This is a statement's comment. 33 | SELECT * FROM t2; -------------------------------------------------------------------------------- /sql/migrate/testdata/lex/6_skip_comment.sql.golden: -------------------------------------------------------------------------------- 1 | CREATE TABLE t1(id int); 2 | -- end -- 3 | CREATE TABLE t2(id int); 4 | -- end -- 5 | CREATE TABLE t3(id int); 6 | -- end -- 7 | CREATE TABLE t4( 8 | id int 9 | /* comment */ 10 | -- comment 11 | ) ENGINE=InnoDB; 12 | -- end -- 13 | CREATE TABLE t5( 14 | id int 15 | /* comment */ 16 | -- comment 17 | ) ENGINE=InnoDB; 18 | -- end -- 19 | SELECT * FROM ( 20 | SELECT * FROM t1 # comment 21 | ); 22 | -- end -- 23 | SELECT * FROM t2; -------------------------------------------------------------------------------- /sql/migrate/testdata/lex/7_delimiter_2n.sql: -------------------------------------------------------------------------------- 1 | -- atlas:delimiter \n\n 2 | 3 | CREATE EXTENSION IF NOT EXISTS unaccent; 4 | 5 | CREATE OR REPLACE FUNCTION public.slugify( 6 | v TEXT 7 | ) RETURNS TEXT STRICT IMMUTABLE AS $$ 8 | BEGIN 9 | RETURN trim(BOTH '-' FROM regexp_replace(lower(unaccent(trim(v))), '[^a-z0-9\\-_]+', '-', 'gi')); 10 | END; 11 | LANGUAGE plpgsql; 12 | 13 | -------------------------------------------------------------------------------- /sql/migrate/testdata/lex/7_delimiter_2n.sql.golden: -------------------------------------------------------------------------------- 1 | CREATE EXTENSION IF NOT EXISTS unaccent; 2 | -- end -- 3 | CREATE OR REPLACE FUNCTION public.slugify( 4 | v TEXT 5 | ) RETURNS TEXT STRICT IMMUTABLE AS $$ 6 | BEGIN 7 | RETURN trim(BOTH '-' FROM regexp_replace(lower(unaccent(trim(v))), '[^a-z0-9\\-_]+', '-', 'gi')); 8 | END; 9 | LANGUAGE plpgsql; -------------------------------------------------------------------------------- /sql/migrate/testdata/lex/8_delimiter_3n.sql: -------------------------------------------------------------------------------- 1 | -- atlas:delimiter \n\n\n 2 | 3 | CREATE EXTENSION IF NOT EXISTS unaccent; 4 | 5 | 6 | CREATE OR REPLACE FUNCTION public.slugify( 7 | v TEXT 8 | ) RETURNS TEXT STRICT IMMUTABLE AS $$ 9 | BEGIN 10 | RETURN trim(BOTH '-' FROM regexp_replace(lower(unaccent(trim(v))), '[^a-z0-9\\-_]+', '-', 'gi')); 11 | END; 12 | LANGUAGE plpgsql; 13 | -------------------------------------------------------------------------------- /sql/migrate/testdata/lex/8_delimiter_3n.sql.golden: -------------------------------------------------------------------------------- 1 | CREATE EXTENSION IF NOT EXISTS unaccent; 2 | -- end -- 3 | CREATE OR REPLACE FUNCTION public.slugify( 4 | v TEXT 5 | ) RETURNS TEXT STRICT IMMUTABLE AS $$ 6 | BEGIN 7 | RETURN trim(BOTH '-' FROM regexp_replace(lower(unaccent(trim(v))), '[^a-z0-9\\-_]+', '-', 'gi')); 8 | END; 9 | LANGUAGE plpgsql; -------------------------------------------------------------------------------- /sql/migrate/testdata/lex/9_delimiter_3n.sql: -------------------------------------------------------------------------------- 1 | -- atlas:delimiter \n\n\n 2 | 3 | CREATE PROCEDURE dorepeat(p1 INT) 4 | BEGIN 5 | SET @x = 0; 6 | REPEAT SET @x = @x + 1; UNTIL @x > p1 END REPEAT; 7 | END; 8 | 9 | 10 | CALL dorepeat(1000); 11 | -------------------------------------------------------------------------------- /sql/migrate/testdata/lex/9_delimiter_3n.sql.golden: -------------------------------------------------------------------------------- 1 | CREATE PROCEDURE dorepeat(p1 INT) 2 | BEGIN 3 | SET @x = 0; 4 | REPEAT SET @x = @x + 1; UNTIL @x > p1 END REPEAT; 5 | END; 6 | -- end -- 7 | CALL dorepeat(1000); -------------------------------------------------------------------------------- /sql/migrate/testdata/lexescaped/1.my.sql: -------------------------------------------------------------------------------- 1 | create table t (c text default '\\'); 2 | create table t (c text default "\\"); 3 | create table t (c text default "\""); 4 | create table t (c text default "\"" + '\''); 5 | -------------------------------------------------------------------------------- /sql/migrate/testdata/lexescaped/1.my.sql.golden: -------------------------------------------------------------------------------- 1 | create table t (c text default '\\'); 2 | -- end -- 3 | create table t (c text default "\\"); 4 | -- end -- 5 | create table t (c text default "\""); 6 | -- end -- 7 | create table t (c text default "\"" + '\''); -------------------------------------------------------------------------------- /sql/migrate/testdata/lexescaped/2.pg.sql: -------------------------------------------------------------------------------- 1 | create table t1 (c text default '\'); 2 | create table t1 (c text default E'\\'); 3 | create table t1 (c text default '\A\'); 4 | create table t1 (c text default e'\\A\\'); -------------------------------------------------------------------------------- /sql/migrate/testdata/lexescaped/2.pg.sql.golden: -------------------------------------------------------------------------------- 1 | create table t1 (c text default '\'); 2 | -- end -- 3 | create table t1 (c text default E'\\'); 4 | -- end -- 5 | create table t1 (c text default '\A\'); 6 | -- end -- 7 | create table t1 (c text default e'\\A\\'); -------------------------------------------------------------------------------- /sql/migrate/testdata/lexgroup/3_delimiter.sql: -------------------------------------------------------------------------------- 1 | -- delimiter should not conflict with compound statements scanning. 2 | 3 | create function `add2` (a int, b int) returns int deterministic no sql return a + b; 4 | create function `add3` (a int, b int, c int) returns int deterministic no sql return a + b + c; 5 | delimiter | 6 | -- error 1418 7 | create function fn1(x int) returns int deterministic 8 | begin 9 | insert into t1 values (x); 10 | return x+2; 11 | end| 12 | create function fn2(x int) returns int deterministic 13 | begin 14 | insert into t1 values (x); 15 | return x+2; 16 | end| 17 | delimiter ; 18 | create function `add4` (a int, b int, c int, d int) returns int deterministic no sql return a + b + c + d; -------------------------------------------------------------------------------- /sql/migrate/testdata/lexgroup/3_delimiter.sql.golden: -------------------------------------------------------------------------------- 1 | create function `add2` (a int, b int) returns int deterministic no sql return a + b; 2 | -- end -- 3 | create function `add3` (a int, b int, c int) returns int deterministic no sql return a + b + c; 4 | -- end -- 5 | create function fn1(x int) returns int deterministic 6 | begin 7 | insert into t1 values (x); 8 | return x+2; 9 | end 10 | -- end -- 11 | create function fn2(x int) returns int deterministic 12 | begin 13 | insert into t1 values (x); 14 | return x+2; 15 | end 16 | -- end -- 17 | create function `add4` (a int, b int, c int, d int) returns int deterministic no sql return a + b + c + d; -------------------------------------------------------------------------------- /sql/migrate/testdata/migrate/1_initial.down.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS t; -------------------------------------------------------------------------------- /sql/migrate/testdata/migrate/1_initial.up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE t(c int); -------------------------------------------------------------------------------- /sql/migrate/testdata/migrate/atlas.sum: -------------------------------------------------------------------------------- 1 | h1:M74RrNK69S2pj6C541LR1ew5O32/i0WoyNgsJmyuiUk= 2 | 1_initial.down.sql h1:0zypK43rgPbgvVUgVJABGN25VgM1QSeU+LJDBb8cEQI= 3 | 1_initial.up.sql h1:hFhs5XhRml4KTWGF5td6h1s7xNqAFnaEBbC5Y/NF7i4= 4 | -------------------------------------------------------------------------------- /sql/migrate/testdata/migrate/sub/1.a_sub.up.sql: -------------------------------------------------------------------------------- 1 | -- create table "t_sub" 2 | CREATE TABLE t_sub(c int); 3 | -- add c1 column 4 | ALTER TABLE t_sub ADD c1 int; -------------------------------------------------------------------------------- /sql/migrate/testdata/migrate/sub/2.10.x-20_description.sql: -------------------------------------------------------------------------------- 1 | -- add c2 column 2 | ALTER TABLE t_sub ADD c2 int; -------------------------------------------------------------------------------- /sql/migrate/testdata/migrate/sub/3_partly.sql: -------------------------------------------------------------------------------- 1 | -- add c3 column 2 | ALTER TABLE t_sub ADD c3 int; 3 | -- add c4 column 4 | ALTER TABLE t_sub ADD c4 int; -------------------------------------------------------------------------------- /sql/migrate/testdata/migrate/sub/atlas.sum: -------------------------------------------------------------------------------- 1 | h1:VpH77zWOBMwX5QhvnQo0XQvXCrOYZg4h1o0XlJTQnl0= 2 | 1.a_sub.up.sql h1:nXyZR020M/mH7LxkoTkJr7BcQkipVg90imQ9I4595dw= 3 | 2.10.x-20_description.sql h1:wQB3Vh3PHVXQg9OD3Gn7TBxbZN3r1Qb7TtAE1g3q9mQ= 4 | 3_partly.sql h1:lHlMz6mEvBfvjry5lFXjs2vi6Et9xb9CWicaOXD42Qc= 5 | -------------------------------------------------------------------------------- /sql/migrate/testdata/partial-checkpoint/1_first.sql: -------------------------------------------------------------------------------- 1 | create table `tbl_1` (`col` int); 2 | -------------------------------------------------------------------------------- /sql/migrate/testdata/partial-checkpoint/2_second.sql: -------------------------------------------------------------------------------- 1 | create table `tbl_2` (`col` int); 2 | -------------------------------------------------------------------------------- /sql/migrate/testdata/partial-checkpoint/3_checkpoint.sql: -------------------------------------------------------------------------------- 1 | -- atlas:checkpoint 2 | 3 | CREATE TABLE `tbl_1` (`col` int); 4 | CREATE TABLE `tbl_2` (`col` int); 5 | -------------------------------------------------------------------------------- /sql/migrate/testdata/partial-checkpoint/4_fourth.sql: -------------------------------------------------------------------------------- 1 | create table `tbl_3` (`col` int); 2 | -------------------------------------------------------------------------------- /sql/migrate/testdata/partial-checkpoint/5_checkpoint.sql: -------------------------------------------------------------------------------- 1 | -- atlas:checkpoint 2 | 3 | CREATE TABLE `tbl_1` (`col` int); 4 | CREATE TABLE `tbl_2` (`col` int); 5 | create table `tbl_3` (`col` int); 6 | -------------------------------------------------------------------------------- /sql/migrate/testdata/partial-checkpoint/6_sixth.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `tbl_4` (`col` int); 2 | -------------------------------------------------------------------------------- /sql/migrate/testdata/partial-checkpoint/atlas.sum: -------------------------------------------------------------------------------- 1 | h1:POfbsH2G2GIXAZQ2CdPa5ufTxcLpcnperz/gX0Vw6Uk= 2 | 1_first.sql h1:uJ2MyyeTqXx4rCqtRMQAvRrfsvdwmvsZ3LcadVvCdOc= 3 | 2_second.sql h1:TLO00GtsqSi8o0ySoaofBqxemrElL8fHOs3IRnqYvB8= 4 | 3_checkpoint.sql h1:LR4UjDYVtrRuHLN5GQwLAYnXrSf/iO70psY8hTmLmjw= 5 | 4_fourth.sql h1:QvaneqKxg+3R+zNzCP/wW43XkECdHkUwEpxJKPICEP8= 6 | 5_checkpoint.sql h1:syyuaJb/hoMRO7MJlv4AMhYqMCoSb8ZgcHENO8RqN3I= 7 | 6_sixth.sql h1:JNhpyBtH7XKqGBNRHQ+AvM9IDpO08C3G/swWPHfLkfw= 8 | -------------------------------------------------------------------------------- /sql/migrate/testdata/sqlserver/1_return_table.sql: -------------------------------------------------------------------------------- 1 | CREATE FUNCTION [f2](@a as INT, @b as INT = 1) 2 | RETURNS TABLE 3 | AS RETURN SELECT @a as [a], @b as [b], (@a+@b)*2 as [p], @a*@b as [s]; 4 | CREATE FUNCTION [f3] (@a int, @b int = 1) RETURNS @t1 TABLE ([c1] int NOT NULL, [c2] nvarchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, [c3] nvarchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS DEFAULT N'G' NULL, [c4] int NOT NULL, PRIMARY KEY CLUSTERED ([c1] ASC), INDEX [idx] NONCLUSTERED ([c2] ASC), UNIQUE NONCLUSTERED ([c2] ASC, [c3] DESC), UNIQUE NONCLUSTERED ([c3] DESC, [c4] ASC), CHECK ([c4]>(0))) AS BEGIN 5 | INSERT @t1 6 | SELECT 1 AS [c1], 'A' AS [c2], NULL AS [c3], @a * @a + @b AS [c4]; 7 | RETURN 8 | END 9 | -------------------------------------------------------------------------------- /sql/migrate/testdata/sqlserver/1_return_table.sql.golden: -------------------------------------------------------------------------------- 1 | CREATE FUNCTION [f2](@a as INT, @b as INT = 1) 2 | RETURNS TABLE 3 | AS RETURN SELECT @a as [a], @b as [b], (@a+@b)*2 as [p], @a*@b as [s]; 4 | -- end -- 5 | CREATE FUNCTION [f3] (@a int, @b int = 1) RETURNS @t1 TABLE ([c1] int NOT NULL, [c2] nvarchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, [c3] nvarchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS DEFAULT N'G' NULL, [c4] int NOT NULL, PRIMARY KEY CLUSTERED ([c1] ASC), INDEX [idx] NONCLUSTERED ([c2] ASC), UNIQUE NONCLUSTERED ([c2] ASC, [c3] DESC), UNIQUE NONCLUSTERED ([c3] DESC, [c4] ASC), CHECK ([c4]>(0))) AS BEGIN 6 | INSERT @t1 7 | SELECT 1 AS [c1], 'A' AS [c2], NULL AS [c3], @a * @a + @b AS [c4]; 8 | RETURN 9 | END -------------------------------------------------------------------------------- /sql/migrate/testdata/sqlserver/2_function.sql: -------------------------------------------------------------------------------- 1 | -- atlas:delimiter \nGO 2 | 3 | CREATE FUNCTION [f3] (@a int, @b int = 1) RETURNS @t1 TABLE ([c1] int NOT NULL, [c2] nvarchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, [c3] nvarchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS DEFAULT N'G' NULL, [c4] int NOT NULL, PRIMARY KEY CLUSTERED ([c1] ASC), INDEX [idx] NONCLUSTERED ([c2] ASC), UNIQUE NONCLUSTERED ([c2] ASC, [c3] DESC), UNIQUE NONCLUSTERED ([c3] DESC, [c4] ASC), CHECK ([c4]>(0))) AS BEGIN 4 | INSERT @t1 5 | SELECT 1 AS [c1], 'A' AS [c2], NULL AS [c3], @a * @a + @b AS [c4]; 6 | RETURN 7 | END 8 | GO 9 | CREATE FUNCTION [f3] (@a int, @b int = 1) RETURNS @t1 TABLE ([c1] int NOT NULL, [c2] nvarchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, [c3] nvarchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS DEFAULT N'G' NULL, [c4] int NOT NULL, PRIMARY KEY CLUSTERED ([c1] ASC), INDEX [idx] NONCLUSTERED ([c2] ASC), UNIQUE NONCLUSTERED ([c2] ASC, [c3] DESC), UNIQUE NONCLUSTERED ([c3] DESC, [c4] ASC), CHECK ([c4]>(0))) AS BEGIN 10 | INSERT @t1 11 | SELECT 1 AS [c1], 'A' AS [c2], NULL AS [c3], @a * @a + @b AS [c4]; 12 | RETURN 13 | END 14 | GO 15 | CREATE FUNCTION [f3] (@a int, @b int = 1) RETURNS @t1 TABLE ([c1] int NOT NULL, [c2] nvarchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, [c3] nvarchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS DEFAULT N'G' NULL, [c4] int NOT NULL, PRIMARY KEY CLUSTERED ([c1] ASC), INDEX [idx] NONCLUSTERED ([c2] ASC), UNIQUE NONCLUSTERED ([c2] ASC, [c3] DESC), UNIQUE NONCLUSTERED ([c3] DESC, [c4] ASC), CHECK ([c4]>(0))) AS BEGIN 16 | INSERT @t1 17 | SELECT 1 AS [c1], 'A' AS [c2], NULL AS [c3], @a * @a + @b AS [c4]; 18 | RETURN 19 | END -------------------------------------------------------------------------------- /sql/migrate/testdata/sqlserver/2_function.sql.golden: -------------------------------------------------------------------------------- 1 | CREATE FUNCTION [f3] (@a int, @b int = 1) RETURNS @t1 TABLE ([c1] int NOT NULL, [c2] nvarchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, [c3] nvarchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS DEFAULT N'G' NULL, [c4] int NOT NULL, PRIMARY KEY CLUSTERED ([c1] ASC), INDEX [idx] NONCLUSTERED ([c2] ASC), UNIQUE NONCLUSTERED ([c2] ASC, [c3] DESC), UNIQUE NONCLUSTERED ([c3] DESC, [c4] ASC), CHECK ([c4]>(0))) AS BEGIN 2 | INSERT @t1 3 | SELECT 1 AS [c1], 'A' AS [c2], NULL AS [c3], @a * @a + @b AS [c4]; 4 | RETURN 5 | END 6 | -- end -- 7 | CREATE FUNCTION [f3] (@a int, @b int = 1) RETURNS @t1 TABLE ([c1] int NOT NULL, [c2] nvarchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, [c3] nvarchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS DEFAULT N'G' NULL, [c4] int NOT NULL, PRIMARY KEY CLUSTERED ([c1] ASC), INDEX [idx] NONCLUSTERED ([c2] ASC), UNIQUE NONCLUSTERED ([c2] ASC, [c3] DESC), UNIQUE NONCLUSTERED ([c3] DESC, [c4] ASC), CHECK ([c4]>(0))) AS BEGIN 8 | INSERT @t1 9 | SELECT 1 AS [c1], 'A' AS [c2], NULL AS [c3], @a * @a + @b AS [c4]; 10 | RETURN 11 | END 12 | -- end -- 13 | CREATE FUNCTION [f3] (@a int, @b int = 1) RETURNS @t1 TABLE ([c1] int NOT NULL, [c2] nvarchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, [c3] nvarchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS DEFAULT N'G' NULL, [c4] int NOT NULL, PRIMARY KEY CLUSTERED ([c1] ASC), INDEX [idx] NONCLUSTERED ([c2] ASC), UNIQUE NONCLUSTERED ([c2] ASC, [c3] DESC), UNIQUE NONCLUSTERED ([c3] DESC, [c4] ASC), CHECK ([c4]>(0))) AS BEGIN 14 | INSERT @t1 15 | SELECT 1 AS [c1], 'A' AS [c2], NULL AS [c3], @a * @a + @b AS [c4]; 16 | RETURN 17 | END -------------------------------------------------------------------------------- /sql/mysql/internal/mysqlversion/is/.README.md: -------------------------------------------------------------------------------- 1 | ## Charset and Collation of MySQL and MariaDB latest versions 2 | 3 | `collate2charset` and `collate2charset.maria` hold a mapping from the collation to their charset. 4 | 5 | ```sql 6 | select json_objectagg(collation_name, character_set_name) from information_schema.collations\G; 7 | ``` 8 | 9 | `charset2collate` and `charset2collate.maria` hold a mapping from the charset to its default collation extracted 10 | by the following query: 11 | 12 | ```sql 13 | select json_objectagg(character_set_name, default_collate_name) from information_schema.character_sets\G; 14 | ``` -------------------------------------------------------------------------------- /sql/mysql/internal/mysqlversion/is/charset2collate: -------------------------------------------------------------------------------- 1 | {"gbk": "gbk_chinese_ci", "hp8": "hp8_english_ci", "big5": "big5_chinese_ci", "dec8": "dec8_swedish_ci", "sjis": "sjis_japanese_ci", "swe7": "swe7_swedish_ci", "ucs2": "ucs2_general_ci", "ujis": "ujis_japanese_ci", "ascii": "ascii_general_ci", "cp850": "cp850_general_ci", "cp852": "cp852_general_ci", "cp866": "cp866_general_ci", "cp932": "cp932_japanese_ci", "euckr": "euckr_korean_ci", "greek": "greek_general_ci", "koi8r": "koi8r_general_ci", "koi8u": "koi8u_general_ci", "macce": "macce_general_ci", "utf16": "utf16_general_ci", "utf32": "utf32_general_ci", "binary": "binary", "cp1250": "cp1250_general_ci", "cp1251": "cp1251_general_ci", "cp1256": "cp1256_general_ci", "cp1257": "cp1257_general_ci", "gb2312": "gb2312_chinese_ci", "hebrew": "hebrew_general_ci", "latin1": "latin1_swedish_ci", "latin2": "latin2_general_ci", "latin5": "latin5_turkish_ci", "latin7": "latin7_general_ci", "tis620": "tis620_thai_ci", "eucjpms": "eucjpms_japanese_ci", "gb18030": "gb18030_chinese_ci", "geostd8": "geostd8_general_ci", "keybcs2": "keybcs2_general_ci", "utf16le": "utf16le_general_ci", "utf8mb3": "utf8mb3_general_ci", "utf8mb4": "utf8mb4_0900_ai_ci", "armscii8": "armscii8_general_ci", "macroman": "macroman_general_ci","utf8": "utf8_general_ci"} -------------------------------------------------------------------------------- /sql/mysql/internal/mysqlversion/is/charset2collate.maria: -------------------------------------------------------------------------------- 1 | {"big5":"big5_chinese_ci", "dec8":"dec8_swedish_ci", "cp850":"cp850_general_ci", "hp8":"hp8_english_ci", "koi8r":"koi8r_general_ci", "latin1":"latin1_swedish_ci", "latin2":"latin2_general_ci", "swe7":"swe7_swedish_ci", "ascii":"ascii_general_ci", "ujis":"ujis_japanese_ci", "sjis":"sjis_japanese_ci", "hebrew":"hebrew_general_ci", "tis620":"tis620_thai_ci", "euckr":"euckr_korean_ci", "koi8u":"koi8u_general_ci", "gb2312":"gb2312_chinese_ci", "greek":"greek_general_ci", "cp1250":"cp1250_general_ci", "gbk":"gbk_chinese_ci", "latin5":"latin5_turkish_ci", "armscii8":"armscii8_general_ci", "utf8mb3":"utf8mb3_general_ci", "ucs2":"ucs2_general_ci", "cp866":"cp866_general_ci", "keybcs2":"keybcs2_general_ci", "macce":"macce_general_ci", "macroman":"macroman_general_ci", "cp852":"cp852_general_ci", "latin7":"latin7_general_ci", "utf8mb4":"utf8mb4_general_ci", "cp1251":"cp1251_general_ci", "utf16":"utf16_general_ci", "utf16le":"utf16le_general_ci", "cp1256":"cp1256_general_ci", "cp1257":"cp1257_general_ci", "utf32":"utf32_general_ci", "binary":"binary", "geostd8":"geostd8_general_ci", "cp932":"cp932_japanese_ci", "eucjpms":"eucjpms_japanese_ci"} -------------------------------------------------------------------------------- /sql/mysql/internal/mysqlversion/mysqlversion_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-present The Atlas Authors. All rights reserved. 2 | // This source code is licensed under the Apache 2.0 license found 3 | // in the LICENSE file in the root directory of this source tree. 4 | 5 | package mysqlversion_test 6 | 7 | import ( 8 | "testing" 9 | 10 | "ariga.io/atlas/sql/mysql/internal/mysqlversion" 11 | "github.com/DATA-DOG/go-sqlmock" 12 | "github.com/stretchr/testify/require" 13 | ) 14 | 15 | func TestV_SupportsGeneratedColumns(t *testing.T) { 16 | tests := []struct { 17 | v string 18 | want bool 19 | }{ 20 | {"5.6", false}, 21 | {"5.7", true}, 22 | {"5.7.0", true}, 23 | {"5.7.40-0ubuntu0.18.04.1", true}, 24 | {"8.0.0", true}, 25 | {"10.1.1-MariaDB", false}, 26 | {"10.2.1-MariaDB-10.2.1+maria~bionic", true}, 27 | {"10.3.1-MariaDB-10.2.1+maria~bionic-log", true}, 28 | } 29 | for _, tt := range tests { 30 | t.Run(tt.v, func(t *testing.T) { 31 | if got := mysqlversion.V(tt.v).SupportsGeneratedColumns(); got != tt.want { 32 | t.Errorf("V.SupportsGeneratedColumns() = %v, want %v", got, tt.want) 33 | } 34 | }) 35 | } 36 | } 37 | 38 | func TestV_CollateToCharset(t *testing.T) { 39 | c2c, err := mysqlversion.V("8.0.0").CollateToCharset(nil) 40 | require.NoError(t, err) 41 | require.Equal(t, "utf8mb4", c2c["utf8mb4_general_ci"]) 42 | require.Empty(t, c2c["custom"]) 43 | 44 | db, mk, err := sqlmock.New() 45 | require.NoError(t, err) 46 | mk.ExpectQuery("SELECT COLLATION_NAME, CHARACTER_SET_NAME FROM INFORMATION_SCHEMA.COLLATIONS"). 47 | WillReturnRows(sqlmock.NewRows([]string{"COLLATION_NAME", "CHARACTER_SET_NAME"}).AddRow("custom", "unknown")) 48 | c2c, err = mysqlversion.V("8.0.0").CollateToCharset(db) 49 | require.NoError(t, err) 50 | require.Equal(t, "unknown", c2c["custom"]) 51 | } 52 | -------------------------------------------------------------------------------- /sql/mysql/mysqlcheck/mysqlcheck_oss.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-present The Atlas Authors. All rights reserved. 2 | // This source code is licensed under the Apache 2.0 license found 3 | // in the LICENSE file in the root directory of this source tree. 4 | 5 | //go:build !ent 6 | 7 | package mysqlcheck 8 | 9 | import ( 10 | "ariga.io/atlas/sql/mysql" 11 | "ariga.io/atlas/sql/sqlcheck" 12 | ) 13 | 14 | func init() { 15 | sqlcheck.Register(mysql.DriverName, analyzers) 16 | } 17 | -------------------------------------------------------------------------------- /sql/postgres/postgrescheck/postgrescheck.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-present The Atlas Authors. All rights reserved. 2 | // This source code is licensed under the Apache 2.0 license found 3 | // in the LICENSE file in the root directory of this source tree. 4 | 5 | package postgrescheck 6 | 7 | import ( 8 | "fmt" 9 | 10 | "ariga.io/atlas/schemahcl" 11 | "ariga.io/atlas/sql/postgres" 12 | "ariga.io/atlas/sql/sqlcheck" 13 | "ariga.io/atlas/sql/sqlcheck/condrop" 14 | "ariga.io/atlas/sql/sqlcheck/datadepend" 15 | "ariga.io/atlas/sql/sqlcheck/destructive" 16 | "ariga.io/atlas/sql/sqlcheck/incompatible" 17 | ) 18 | 19 | func addNotNull(p *datadepend.ColumnPass) (diags []sqlcheck.Diagnostic, err error) { 20 | tt, err := postgres.FormatType(p.Column.Type.Type) 21 | if err != nil { 22 | return nil, err 23 | } 24 | return []sqlcheck.Diagnostic{ 25 | { 26 | Pos: p.Change.Stmt.Pos, 27 | Text: fmt.Sprintf( 28 | "Adding a non-nullable %q column %q will fail in case table %q is not empty", 29 | tt, p.Column.Name, p.Table.Name, 30 | ), 31 | }, 32 | }, nil 33 | } 34 | 35 | func analyzers(r *schemahcl.Resource) ([]sqlcheck.Analyzer, error) { 36 | ds, err := destructive.New(r) 37 | if err != nil { 38 | return nil, err 39 | } 40 | cd, err := condrop.New(r) 41 | if err != nil { 42 | return nil, err 43 | } 44 | dd, err := datadepend.New(r, datadepend.Handler{ 45 | AddNotNull: addNotNull, 46 | }) 47 | if err != nil { 48 | return nil, err 49 | } 50 | bc, err := incompatible.New(r) 51 | if err != nil { 52 | return nil, err 53 | } 54 | return []sqlcheck.Analyzer{ds, dd, cd, bc}, nil 55 | } 56 | -------------------------------------------------------------------------------- /sql/postgres/postgrescheck/postgrescheck_oss.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-present The Atlas Authors. All rights reserved. 2 | // This source code is licensed under the Apache 2.0 license found 3 | // in the LICENSE file in the root directory of this source tree. 4 | 5 | //go:build !ent 6 | 7 | package postgrescheck 8 | 9 | import ( 10 | "ariga.io/atlas/sql/postgres" 11 | "ariga.io/atlas/sql/sqlcheck" 12 | ) 13 | 14 | func init() { 15 | sqlcheck.Register(postgres.DriverName, analyzers) 16 | } 17 | -------------------------------------------------------------------------------- /sql/postgres/postgrescheck/postgrescheck_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-present The Atlas Authors. All rights reserved. 2 | // This source code is licensed under the Apache 2.0 license found 3 | // in the LICENSE file in the root directory of this source tree. 4 | 5 | package postgrescheck_test 6 | 7 | import ( 8 | "context" 9 | "testing" 10 | 11 | "ariga.io/atlas/sql/migrate" 12 | "ariga.io/atlas/sql/postgres" 13 | _ "ariga.io/atlas/sql/postgres/postgrescheck" 14 | "ariga.io/atlas/sql/schema" 15 | "ariga.io/atlas/sql/sqlcheck" 16 | 17 | "github.com/stretchr/testify/require" 18 | ) 19 | 20 | func TestDataDepend_MightFail(t *testing.T) { 21 | var ( 22 | report *sqlcheck.Report 23 | pass = &sqlcheck.Pass{ 24 | File: &sqlcheck.File{ 25 | File: testFile{name: "1.sql"}, 26 | Changes: []*sqlcheck.Change{ 27 | { 28 | Stmt: &migrate.Stmt{ 29 | Text: "ALTER TABLE users", 30 | }, 31 | Changes: schema.Changes{ 32 | &schema.ModifyTable{ 33 | T: schema.NewTable("users"). 34 | SetSchema(schema.New("test")). 35 | AddColumns( 36 | schema.NewIntColumn("a", postgres.TypeInt), 37 | schema.NewIntColumn("b", postgres.TypeInt), 38 | ), 39 | Changes: []schema.Change{ 40 | &schema.AddColumn{C: schema.NewTimeColumn("b", postgres.TypeInt)}, 41 | }, 42 | }, 43 | }, 44 | }, 45 | }, 46 | }, 47 | Reporter: sqlcheck.ReportWriterFunc(func(r sqlcheck.Report) { 48 | report = &r 49 | }), 50 | } 51 | ) 52 | azs, err := sqlcheck.AnalyzerFor(postgres.DriverName, nil) 53 | require.NoError(t, err) 54 | require.NoError(t, sqlcheck.Analyzers(azs).Analyze(context.Background(), pass)) 55 | require.Equal(t, report.Diagnostics[0].Text, `Adding a non-nullable "int" column "b" will fail in case table "users" is not empty`) 56 | } 57 | 58 | type testFile struct { 59 | name string 60 | migrate.File 61 | } 62 | 63 | func (t testFile) Name() string { 64 | return t.name 65 | } 66 | -------------------------------------------------------------------------------- /sql/schema/changekind_string.go: -------------------------------------------------------------------------------- 1 | // Code generated by "stringer -type ChangeKind"; DO NOT EDIT. 2 | 3 | package schema 4 | 5 | import "strconv" 6 | 7 | func _() { 8 | // An "invalid array index" compiler error signifies that the constant values have changed. 9 | // Re-run the stringer command to generate them again. 10 | var x [1]struct{} 11 | _ = x[NoChange-0] 12 | _ = x[ChangeAttr-1] 13 | _ = x[ChangeCharset-2] 14 | _ = x[ChangeCollate-4] 15 | _ = x[ChangeComment-8] 16 | _ = x[ChangeNull-16] 17 | _ = x[ChangeType-32] 18 | _ = x[ChangeDefault-64] 19 | _ = x[ChangeGenerated-128] 20 | _ = x[ChangeUnique-256] 21 | _ = x[ChangeParts-512] 22 | _ = x[ChangeColumn-1024] 23 | _ = x[ChangeRefColumn-2048] 24 | _ = x[ChangeRefTable-4096] 25 | _ = x[ChangeUpdateAction-8192] 26 | _ = x[ChangeDeleteAction-16384] 27 | } 28 | 29 | const _ChangeKind_name = "NoChangeChangeAttrChangeCharsetChangeCollateChangeCommentChangeNullChangeTypeChangeDefaultChangeGeneratedChangeUniqueChangePartsChangeColumnChangeRefColumnChangeRefTableChangeUpdateActionChangeDeleteAction" 30 | 31 | var _ChangeKind_map = map[ChangeKind]string{ 32 | 0: _ChangeKind_name[0:8], 33 | 1: _ChangeKind_name[8:18], 34 | 2: _ChangeKind_name[18:31], 35 | 4: _ChangeKind_name[31:44], 36 | 8: _ChangeKind_name[44:57], 37 | 16: _ChangeKind_name[57:67], 38 | 32: _ChangeKind_name[67:77], 39 | 64: _ChangeKind_name[77:90], 40 | 128: _ChangeKind_name[90:105], 41 | 256: _ChangeKind_name[105:117], 42 | 512: _ChangeKind_name[117:128], 43 | 1024: _ChangeKind_name[128:140], 44 | 2048: _ChangeKind_name[140:155], 45 | 4096: _ChangeKind_name[155:169], 46 | 8192: _ChangeKind_name[169:187], 47 | 16384: _ChangeKind_name[187:205], 48 | } 49 | 50 | func (i ChangeKind) String() string { 51 | if str, ok := _ChangeKind_map[i]; ok { 52 | return str 53 | } 54 | return "ChangeKind(" + strconv.FormatInt(int64(i), 10) + ")" 55 | } 56 | -------------------------------------------------------------------------------- /sql/sqlcheck/destructive/destructive_oss.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-present The Atlas Authors. All rights reserved. 2 | // This source code is licensed under the Apache 2.0 license found 3 | // in the LICENSE file in the root directory of this source tree. 4 | 5 | //go:build !ent 6 | 7 | package destructive 8 | 9 | import ( 10 | "errors" 11 | 12 | "ariga.io/atlas/sql/migrate" 13 | "ariga.io/atlas/sql/schema" 14 | "ariga.io/atlas/sql/sqlcheck" 15 | ) 16 | 17 | func (*Analyzer) hasEmptyTableCheck(*sqlcheck.Pass, *schema.Table) bool { 18 | return false // unimplemented. 19 | } 20 | 21 | func (*Analyzer) hasEmptyColumnCheck(*sqlcheck.Pass, *schema.Table, *schema.Column) bool { 22 | return false // unimplemented. 23 | } 24 | 25 | func (*Analyzer) emptyTableCheckStmt(*sqlcheck.Pass, *schema.Table) (*migrate.Stmt, error) { 26 | return nil, errors.New("unimplemented") 27 | } 28 | 29 | func (*Analyzer) emptyColumnCheckStmt(*sqlcheck.Pass, *schema.Table, string) (*migrate.Stmt, error) { 30 | return nil, errors.New("unimplemented") 31 | } 32 | 33 | func withSuggestion(_ *sqlcheck.Pass, r sqlcheck.Report, _ []*migrate.Stmt) sqlcheck.Report { 34 | return r // unimplemented. 35 | } 36 | -------------------------------------------------------------------------------- /sql/sqlite/sqlitecheck/sqlitecheck_oss.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-present The Atlas Authors. All rights reserved. 2 | // This source code is licensed under the Apache 2.0 license found 3 | // in the LICENSE file in the root directory of this source tree. 4 | 5 | //go:build !ent 6 | 7 | package sqlitecheck 8 | 9 | import ( 10 | "ariga.io/atlas/sql/sqlcheck" 11 | "ariga.io/atlas/sql/sqlite" 12 | ) 13 | 14 | func init() { 15 | sqlcheck.Register(sqlite.DriverName, analyzers) 16 | } 17 | -------------------------------------------------------------------------------- /sql/sqltool/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-present The Atlas Authors. All rights reserved. 2 | // This source code is licensed under the Apache 2.0 license found 3 | // in the LICENSE file in the root directory of this source tree. 4 | 5 | // Package sqltool contains logic to integrate existing tools like Flyway or Liquibase with the Atlas CLI. 6 | package sqltool 7 | -------------------------------------------------------------------------------- /sql/sqltool/hidden.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-present The Atlas Authors. All rights reserved. 2 | // This source code is licensed under the Apache 2.0 license found 3 | // in the LICENSE file in the root directory of this source tree. 4 | 5 | //go:build !windows 6 | 7 | package sqltool 8 | 9 | import "path/filepath" 10 | 11 | func hidden(path string) (bool, error) { 12 | return filepath.Base(path)[0] == '.', nil 13 | } 14 | -------------------------------------------------------------------------------- /sql/sqltool/hidden_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-present The Atlas Authors. All rights reserved. 2 | // This source code is licensed under the Apache 2.0 license found 3 | // in the LICENSE file in the root directory of this source tree. 4 | 5 | package sqltool 6 | 7 | import ( 8 | "path/filepath" 9 | "syscall" 10 | ) 11 | 12 | func hidden(path string) (bool, error) { 13 | abs, err := filepath.Abs(path) 14 | if err != nil { 15 | return false, err 16 | } 17 | p, err := syscall.UTF16PtrFromString(abs) 18 | if err != nil { 19 | return false, err 20 | } 21 | attr, err := syscall.GetFileAttributes(p) 22 | if err != nil { 23 | return false, err 24 | } 25 | return attr&syscall.FILE_ATTRIBUTE_HIDDEN != 0, nil 26 | } 27 | -------------------------------------------------------------------------------- /sql/sqltool/testdata/dbmate/1_initial.sql: -------------------------------------------------------------------------------- 1 | -- migrate:up 2 | CREATE TABLE post 3 | ( 4 | id int NOT NULL, 5 | title text, 6 | body text, 7 | PRIMARY KEY (id) 8 | ); 9 | 10 | /* 11 | Multiline comment ... 12 | */ 13 | ALTER TABLE post ADD created_at TIMESTAMP NOT NULL; 14 | 15 | INSERT INTO post (title) VALUES ( 16 | 'This is 17 | my multiline 18 | 19 | value'); 20 | 21 | -- migrate:down 22 | 23 | 24 | DROP TABLE post; -------------------------------------------------------------------------------- /sql/sqltool/testdata/dbmate/2_second_migration.sql: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -- migrate:up 5 | 6 | 7 | 8 | 9 | CREATE TABLE tbl_2 (col INT); -------------------------------------------------------------------------------- /sql/sqltool/testdata/flyway/B2__baseline.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE post 2 | ( 3 | id int NOT NULL, 4 | title text, 5 | body text, 6 | created_at TIMESTAMP NOT NULL 7 | PRIMARY KEY (id) 8 | ); 9 | 10 | INSERT INTO post (title, created_at) VALUES ( 11 | 'This is 12 | my multiline 13 | 14 | value', NOW()); -------------------------------------------------------------------------------- /sql/sqltool/testdata/flyway/R__views.sql: -------------------------------------------------------------------------------- 1 | CREATE VIEW `my_view` AS SELECT * FROM `post`; -------------------------------------------------------------------------------- /sql/sqltool/testdata/flyway/U1__initial.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE tbl; -------------------------------------------------------------------------------- /sql/sqltool/testdata/flyway/V1__initial.sql: -------------------------------------------------------------------------------- 1 | -- comment 2 | CREATE TABLE post 3 | ( 4 | id int NOT NULL, 5 | title text, 6 | body text, 7 | PRIMARY KEY (id) 8 | ); 9 | 10 | ALTER TABLE post ADD created_at TIMESTAMP NOT NULL; 11 | 12 | INSERT INTO post (title, created_at) VALUES ( 13 | 'This is 14 | my multiline 15 | 16 | value', NOW()); 17 | -------------------------------------------------------------------------------- /sql/sqltool/testdata/flyway/V2__second_migration.sql: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -- migrate:up 5 | 6 | 7 | 8 | 9 | CREATE TABLE tbl_2 (col INT); -------------------------------------------------------------------------------- /sql/sqltool/testdata/flyway/V3__third_migration.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE tbl_2 ADD col_1 INTEGER NOT NULL; -------------------------------------------------------------------------------- /sql/sqltool/testdata/flyway/v3/V3_1__fourth_migration.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE tbl_2 ADD col_2 INTEGER NOT NULL; -------------------------------------------------------------------------------- /sql/sqltool/testdata/golang-migrate/1_initial.down.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE tbl; -------------------------------------------------------------------------------- /sql/sqltool/testdata/golang-migrate/1_initial.up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE tbl 2 | ( 3 | col INT 4 | ); -------------------------------------------------------------------------------- /sql/sqltool/testdata/golang-migrate/2_second_migration.down.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE tbl_2; -------------------------------------------------------------------------------- /sql/sqltool/testdata/golang-migrate/2_second_migration.up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE tbl_2 (col INT); -------------------------------------------------------------------------------- /sql/sqltool/testdata/goose/1_initial.sql: -------------------------------------------------------------------------------- 1 | -- +goose Up 2 | CREATE TABLE post 3 | ( 4 | id int NOT NULL, 5 | title text, 6 | body text, 7 | PRIMARY KEY (id) 8 | ); 9 | 10 | ALTER TABLE post ADD created_at TIMESTAMP NOT NULL; 11 | 12 | INSERT INTO post (title) VALUES ( 13 | 'This is 14 | my multiline 15 | 16 | value'); 17 | 18 | -- +goose Down 19 | DROP TABLE post; -------------------------------------------------------------------------------- /sql/sqltool/testdata/goose/2_second_migration.sql: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -- +goose Up 5 | 6 | 7 | ALTER TABLE post ADD updated_at TIMESTAMP NOT NULL; 8 | 9 | -- +goose StatementBegin 10 | -- Comment for the function declaration. 11 | CREATE 12 | OR REPLACE FUNCTION histories_partition_creation( DATE, DATE ) 13 | returns void AS $$ 14 | DECLARE 15 | create_query text; 16 | BEGIN 17 | FOR create_query IN 18 | SELECT 'CREATE TABLE IF NOT EXISTS histories_' 19 | || TO_CHAR(d, 'YYYY_MM') 20 | || ' ( CHECK( created_at >= timestamp ''' 21 | || TO_CHAR(d, 'YYYY-MM-DD 00:00:00') 22 | || ''' AND created_at < timestamp ''' 23 | || TO_CHAR(d + INTERVAL '1 month', 'YYYY-MM-DD 00:00:00') 24 | || ''' ) ) inherits ( histories );' 25 | FROM generate_series($1, $2, '1 month') AS d LOOP 26 | EXECUTE create_query; 27 | END LOOP; -- LOOP END 28 | END; -- FUNCTION END 29 | $$ 30 | language plpgsql; 31 | -- +goose StatementEnd -------------------------------------------------------------------------------- /sql/sqltool/testdata/liquibase/1_initial.sql: -------------------------------------------------------------------------------- 1 | --liquibase formatted sql 2 | 3 | --changeset atlas:1-1 4 | CREATE TABLE post 5 | ( 6 | id int NOT NULL, 7 | title text, 8 | body text, 9 | PRIMARY KEY (id) 10 | ); 11 | --rollback: DROP TABLE post; 12 | 13 | --changeset atlas:1-2 14 | ALTER TABLE post ADD created_at TIMESTAMP NOT NULL; 15 | --rollback: ALTER TABLE post DROP created_at; 16 | 17 | --changeset atlas:1-3 18 | INSERT INTO post (title) VALUES ( 19 | 'This is 20 | my multiline 21 | 22 | value'); 23 | -------------------------------------------------------------------------------- /sql/sqltool/testdata/liquibase/2_second_migration.sql: -------------------------------------------------------------------------------- 1 | --liquibase formatted sql 2 | 3 | --changeset atlas:2-1 4 | CREATE TABLE tbl_2 (col INT); 5 | --rollback DROP TABLE tbl_2; 6 | --------------------------------------------------------------------------------