databaseChangeLog:
  - property:
      name: timestamp_type
      value: timestamp with time zone
      dbms: postgresql,h2
  - property:
      name: timestamp_type
      value: timestamp(6)
      dbms: mysql,mariadb
  - property:
      name: blob.type
      value: blob
      dbms: mysql,h2,mariadb
  - property:
      name: blob.type
      value: bytea
      dbms: postgresql
  # In MySQL, use LONGTEXT instead of TEXT (#7006)
  - property:
      name: text.type
      value: text
      dbms: postgresql,h2
  - property:
      name: text.type
      value: longtext
      dbms: mysql,mariadb
  # databasechangelog is uppercase in MySQL and H2 but lower-case in Postgres for reasons
  - property:
      name: databasechangelog.name
      value: DATABASECHANGELOG
      dbms: h2,mysql,mariadb
  - property:
      name: databasechangelog.name
      value: databasechangelog
      dbms: postgresql

  - objectQuotingStrategy: QUOTE_ALL_OBJECTS

  - changeSet:
      id: '1'
      author: agilliland
      validCheckSum: ANY
      changes:
      - createTable:
          columns:
          - column:
              autoIncrement: true
              constraints:
                nullable: false
                primaryKey: true
              name: id
              type: int
          - column:
              constraints:
                nullable: false
                unique: true
              name: slug
              type: varchar(254)
          - column:
              constraints:
                nullable: false
              name: name
              type: varchar(254)
          - column:
              name: description
              type: text
          - column:
              name: logo_url
              type: varchar(254)
          - column:
              constraints:
                nullable: false
              name: inherits
              type: boolean
          tableName: core_organization
      - createTable:
          columns:
          - column:
              autoIncrement: true
              constraints:
                nullable: false
                primaryKey: true
              name: id
              type: int
          - column:
              constraints:
                nullable: false
                unique: true
              name: email
              type: varchar(254)
          - column:
              constraints:
                nullable: false
              name: first_name
              type: varchar(254)
          - column:
              constraints:
                nullable: false
              name: last_name
              type: varchar(254)
          - column:
              constraints:
                nullable: false
              name: password
              type: varchar(254)
          - column:
              constraints:
                nullable: false
              defaultValue: default
              name: password_salt
              type: varchar(254)
          - column:
              constraints:
                nullable: false
              name: date_joined
              type: DATETIME
          - column:
              constraints:
                nullable: true
              name: last_login
              type: DATETIME
          - column:
              constraints:
                nullable: false
              name: is_staff
              type: boolean
          - column:
              constraints:
                nullable: false
              name: is_superuser
              type: boolean
          - column:
              constraints:
                nullable: false
              name: is_active
              type: boolean
          - column:
              name: reset_token
              type: varchar(254)
          - column:
              name: reset_triggered
              type: BIGINT
          tableName: core_user
      - createTable:
          columns:
          - column:
              autoIncrement: true
              constraints:
                nullable: false
                primaryKey: true
              name: id
              type: int
          - column:
              constraints:
                nullable: false
              name: admin
              type: boolean
          - column:
              constraints:
                deferrable: false
                foreignKeyName: fk_userorgperm_ref_user_id
                initiallyDeferred: false
                nullable: false
                referencedTableName: core_user
                referencedColumnNames: id
              name: user_id
              type: int
          - column:
              constraints:
                deferrable: false
                foreignKeyName: fk_userorgperm_ref_organization_id
                initiallyDeferred: false
                nullable: false
                referencedTableName: core_organization
                referencedColumnNames: id
              name: organization_id
              type: int
          tableName: core_userorgperm
      - addUniqueConstraint:
          columnNames: user_id, organization_id
          constraintName: idx_unique_user_id_organization_id
          tableName: core_userorgperm
      - createIndex:
          columns:
          - column:
              name: user_id
              type: int
          indexName: idx_userorgperm_user_id
          tableName: core_userorgperm
      - createIndex:
          columns:
          - column:
              name: organization_id
              type: int
          indexName: idx_userorgperm_organization_id
          tableName: core_userorgperm
      - createTable:
          columns:
          - column:
              autoIncrement: true
              constraints:
                nullable: false
                primaryKey: true
              name: id
              type: int
          - column:
              constraints:
                nullable: false
              name: url
              type: varchar(254)
          - column:
              constraints:
                nullable: false
              name: timestamp
              type: DATETIME
          - column:
              constraints:
                deferrable: false
                foreignKeyName: fk_permissionviolation_ref_user_id
                initiallyDeferred: false
                nullable: false
                referencedTableName: core_user
                referencedColumnNames: id
              name: user_id
              type: int
          tableName: core_permissionsviolation
      - createIndex:
          columns:
          - column:
              name: user_id
              type: int
          indexName: idx_permissionsviolation_user_id
          tableName: core_permissionsviolation
      - createTable:
          columns:
          - column:
              autoIncrement: true
              constraints:
                nullable: false
                primaryKey: true
              name: id
              type: int
          - column:
              constraints:
                nullable: false
              name: created_at
              type: DATETIME
          - column:
              constraints:
                nullable: false
              name: updated_at
              type: DATETIME
          - column:
              constraints:
                nullable: false
              name: name
              type: varchar(254)
          - column:
              name: description
              type: text
          - column:
              constraints:
                deferrable: false
                foreignKeyName: fk_database_ref_organization_id
                initiallyDeferred: false
                nullable: false
                referencedTableName: core_organization
                referencedColumnNames: id
              name: organization_id
              type: int
          - column:
              name: details
              type: text
          - column:
              constraints:
                nullable: false
              name: engine
              type: varchar(254)
          tableName: metabase_database
      - createIndex:
          columns:
          - column:
              name: organization_id
          indexName: idx_database_organization_id
          tableName: metabase_database
      - createTable:
          columns:
          - column:
              autoIncrement: true
              constraints:
                nullable: false
                primaryKey: true
              name: id
              type: int
          - column:
              constraints:
                nullable: false
              name: created_at
              type: DATETIME
          - column:
              constraints:
                nullable: false
              name: updated_at
              type: DATETIME
          - column:
              constraints:
                nullable: false
              name: name
              type: varchar(254)
          - column:
              name: rows
              type: int
          - column:
              name: description
              type: text
          - column:
              name: entity_name
              type: varchar(254)
          - column:
              name: entity_type
              type: varchar(254)
          - column:
              constraints:
                nullable: false
              name: active
              type: boolean
          - column:
              constraints:
                deferrable: false
                foreignKeyName: fk_table_ref_database_id
                initiallyDeferred: false
                nullable: false
                referencedTableName: metabase_database
                referencedColumnNames: id
              name: db_id
              type: int
          tableName: metabase_table
      - createIndex:
          columns:
          - column:
              name: db_id
          indexName: idx_table_db_id
          tableName: metabase_table
      - createTable:
          columns:
          - column:
              autoIncrement: true
              constraints:
                nullable: false
                primaryKey: true
              name: id
              type: int
          - column:
              constraints:
                nullable: false
              name: created_at
              type: DATETIME
          - column:
              constraints:
                nullable: false
              name: updated_at
              type: DATETIME
          - column:
              constraints:
                nullable: false
              name: name
              type: varchar(254)
          - column:
              constraints:
                nullable: false
              name: base_type
              type: varchar(255)
          - column:
              name: special_type
              type: varchar(255)
          - column:
              constraints:
                nullable: false
              name: active
              type: boolean
          - column:
              name: description
              type: text
          - column:
              constraints:
                nullable: false
              name: preview_display
              type: boolean
          - column:
              constraints:
                nullable: false
              name: position
              type: int
          - column:
              constraints:
                deferrable: false
                foreignKeyName: fk_field_ref_table_id
                initiallyDeferred: false
                nullable: false
                referencedTableName: metabase_table
                referencedColumnNames: id
              name: table_id
              type: int
          - column:
              constraints:
                nullable: false
              name: field_type
              type: varchar(254)
          tableName: metabase_field
      - createIndex:
          columns:
          - column:
              name: table_id
          indexName: idx_field_table_id
          tableName: metabase_field
      - createTable:
          columns:
          - column:
              autoIncrement: true
              constraints:
                nullable: false
                primaryKey: true
              name: id
              type: int
          - column:
              constraints:
                nullable: false
              name: created_at
              type: DATETIME
          - column:
              constraints:
                nullable: false
              name: updated_at
              type: DATETIME
          - column:
              constraints:
                nullable: false
              name: relationship
              type: varchar(254)
          - column:
              constraints:
                deferrable: false
                foreignKeyName: fk_foreignkey_dest_ref_field_id
                initiallyDeferred: false
                nullable: false
                referencedTableName: metabase_field
                referencedColumnNames: id
              name: destination_id
              type: int
          - column:
              constraints:
                deferrable: false
                foreignKeyName: fk_foreignkey_origin_ref_field_id
                initiallyDeferred: false
                nullable: false
                referencedTableName: metabase_field
                referencedColumnNames: id
              name: origin_id
              type: int
          tableName: metabase_foreignkey
      - createIndex:
          columns:
          - column:
              name: destination_id
          indexName: idx_foreignkey_destination_id
          tableName: metabase_foreignkey
      - createIndex:
          columns:
          - column:
              name: origin_id
          indexName: idx_foreignkey_origin_id
          tableName: metabase_foreignkey
      - createTable:
          columns:
          - column:
              autoIncrement: true
              constraints:
                nullable: false
                primaryKey: true
              name: id
              type: int
          - column:
              constraints:
                nullable: false
              name: created_at
              type: DATETIME
          - column:
              constraints:
                nullable: false
              name: updated_at
              type: DATETIME
          - column:
              name: values
              type: text
          - column:
              name: human_readable_values
              type: text
          - column:
              constraints:
                deferrable: false
                foreignKeyName: fk_fieldvalues_ref_field_id
                initiallyDeferred: false
                nullable: false
                referencedTableName: metabase_field
                referencedColumnNames: id
              name: field_id
              type: int
          tableName: metabase_fieldvalues
      - createIndex:
          columns:
          - column:
              name: field_id
          indexName: idx_fieldvalues_field_id
          tableName: metabase_fieldvalues
      - createTable:
          columns:
          - column:
              autoIncrement: true
              constraints:
                nullable: false
                primaryKey: true
              name: id
              type: int
          - column:
              constraints:
                nullable: false
              name: created_at
              type: DATETIME
          - column:
              constraints:
                nullable: false
              name: updated_at
              type: DATETIME
          - column:
              constraints:
                nullable: false
              name: name
              type: varchar(254)
          - column:
              constraints:
                deferrable: false
                foreignKeyName: fk_tablesegment_ref_table_id
                initiallyDeferred: false
                nullable: false
                referencedTableName: metabase_table
                referencedColumnNames: id
              name: table_id
              type: int
          - column:
              constraints:
                nullable: false
              name: filter_clause
              type: text
          tableName: metabase_tablesegment
      - createIndex:
          columns:
          - column:
              name: table_id
          indexName: idx_tablesegment_table_id
          tableName: metabase_tablesegment
      - createTable:
          columns:
          - column:
              autoIncrement: true
              constraints:
                nullable: false
                primaryKey: true
              name: id
              type: int
          - column:
              constraints:
                nullable: false
              name: created_at
              type: DATETIME
          - column:
              constraints:
                nullable: false
              name: updated_at
              type: DATETIME
          - column:
              constraints:
                nullable: false
              name: name
              type: varchar(254)
          - column:
              constraints:
                nullable: false
              name: type
              type: varchar(254)
          - column:
              constraints:
                nullable: false
              name: details
              type: text
          - column:
              constraints:
                nullable: false
              name: version
              type: int
          - column:
              constraints:
                nullable: false
              name: public_perms
              type: int
          - column:
              constraints:
                deferrable: false
                foreignKeyName: fk_query_ref_user_id
                initiallyDeferred: false
                nullable: false
                referencedTableName: core_user
                referencedColumnNames: id
              name: creator_id
              type: int
          - column:
              constraints:
                deferrable: false
                foreignKeyName: fk_query_ref_database_id
                initiallyDeferred: false
                nullable: false
                referencedTableName: metabase_database
                referencedColumnNames: id
              name: database_id
              type: int
          tableName: query_query
      - createIndex:
          columns:
          - column:
              name: creator_id
          indexName: idx_query_creator_id
          tableName: query_query
      - createIndex:
          columns:
          - column:
              name: database_id
          indexName: idx_query_database_id
          tableName: query_query
      - createTable:
          columns:
          - column:
              autoIncrement: true
              constraints:
                nullable: false
                primaryKey: true
              name: id
              type: int
          - column:
              constraints:
                nullable: false
                unique: true
              name: uuid
              type: varchar(254)
          - column:
              constraints:
                nullable: false
              name: version
              type: int
          - column:
              constraints:
                nullable: false
              name: json_query
              type: text
          - column:
              constraints:
                nullable: false
              name: raw_query
              type: text
          - column:
              constraints:
                nullable: false
              name: status
              type: varchar(254)
          - column:
              constraints:
                nullable: false
              name: started_at
              type: DATETIME
          - column:
              name: finished_at
              type: DATETIME
          - column:
              constraints:
                nullable: false
              name: running_time
              type: int
          - column:
              constraints:
                nullable: false
              name: error
              type: text
          - column:
              constraints:
                nullable: false
              name: result_file
              type: varchar(254)
          - column:
              constraints:
                nullable: false
              name: result_rows
              type: int
          - column:
              constraints:
                nullable: false
              name: result_data
              type: text
          - column:
              constraints:
                deferrable: false
                foreignKeyName: fk_queryexecution_ref_query_id
                initiallyDeferred: false
                nullable: true
                referencedTableName: query_query
                referencedColumnNames: id
              name: query_id
              type: int
          - column:
              constraints:
                nullable: false
              name: additional_info
              type: text
          - column:
              constraints:
                deferrable: false
                foreignKeyName: fk_queryexecution_ref_user_id
                initiallyDeferred: false
                nullable: false
                referencedTableName: core_user
                referencedColumnNames: id
              name: executor_id
              type: int
          tableName: query_queryexecution
      - createIndex:
          columns:
          - column:
              name: query_id
          indexName: idx_queryexecution_query_id
          tableName: query_queryexecution
      - createIndex:
          columns:
          - column:
              name: executor_id
          indexName: idx_queryexecution_executor_id
          tableName: query_queryexecution
      - createTable:
          columns:
          - column:
              autoIncrement: true
              constraints:
                nullable: false
                primaryKey: true
              name: id
              type: int
          - column:
              constraints:
                nullable: false
              name: created_at
              type: DATETIME
          - column:
              constraints:
                nullable: false
              name: updated_at
              type: DATETIME
          - column:
              constraints:
                nullable: false
              name: name
              type: varchar(254)
          - column:
              name: description
              type: text
          - column:
              constraints:
                nullable: false
              name: display
              type: varchar(254)
          - column:
              constraints:
                nullable: false
              name: public_perms
              type: int
          - column:
              constraints:
                nullable: false
              name: dataset_query
              type: text
          - column:
              constraints:
                nullable: false
              name: visualization_settings
              type: text
          - column:
              constraints:
                deferrable: false
                foreignKeyName: fk_card_ref_user_id
                initiallyDeferred: false
                nullable: false
                referencedTableName: core_user
                referencedColumnNames: id
              name: creator_id
              type: int
          - column:
              constraints:
                deferrable: false
                foreignKeyName: fk_card_ref_organization_id
                initiallyDeferred: false
                nullable: false
                referencedTableName: core_organization
                referencedColumnNames: id
              name: organization_id
              type: int
          tableName: report_card
      - createIndex:
          columns:
          - column:
              name: creator_id
          indexName: idx_card_creator_id
          tableName: report_card
      - createIndex:
          columns:
          - column:
              name: organization_id
          indexName: idx_card_organization_id
          tableName: report_card
      - createTable:
          columns:
          - column:
              autoIncrement: true
              constraints:
                nullable: false
                primaryKey: true
              name: id
              type: int
          - column:
              constraints:
                nullable: false
              name: created_at
              type: DATETIME
          - column:
              constraints:
                nullable: false
              name: updated_at
              type: DATETIME
          - column:
              constraints:
                deferrable: false
                foreignKeyName: fk_cardfavorite_ref_card_id
                initiallyDeferred: false
                nullable: false
                referencedTableName: report_card
                referencedColumnNames: id
              name: card_id
              type: int
          - column:
              constraints:
                deferrable: false
                foreignKeyName: fk_cardfavorite_ref_user_id
                initiallyDeferred: false
                nullable: false
                referencedTableName: core_user
                referencedColumnNames: id
              name: owner_id
              type: int
          tableName: report_cardfavorite
      - addUniqueConstraint:
          columnNames: card_id, owner_id
          constraintName: idx_unique_cardfavorite_card_id_owner_id
          tableName: report_cardfavorite
      - createIndex:
          columns:
          - column:
              name: card_id
          indexName: idx_cardfavorite_card_id
          tableName: report_cardfavorite
      - createIndex:
          columns:
          - column:
              name: owner_id
          indexName: idx_cardfavorite_owner_id
          tableName: report_cardfavorite
      - createTable:
          columns:
          - column:
              autoIncrement: true
              constraints:
                nullable: false
                primaryKey: true
              name: id
              type: int
          - column:
              constraints:
                nullable: false
              name: created_at
              type: DATETIME
          - column:
              constraints:
                nullable: false
              name: updated_at
              type: DATETIME
          - column:
              constraints:
                nullable: false
              name: name
              type: varchar(254)
          - column:
              name: description
              type: text
          - column:
              constraints:
                nullable: false
              name: public_perms
              type: int
          - column:
              constraints:
                deferrable: false
                foreignKeyName: fk_dashboard_ref_user_id
                initiallyDeferred: false
                nullable: false
                referencedTableName: core_user
                referencedColumnNames: id
              name: creator_id
              type: int
          - column:
              constraints:
                deferrable: false
                foreignKeyName: fk_dashboard_ref_organization_id
                initiallyDeferred: false
                nullable: false
                referencedTableName: core_organization
                referencedColumnNames: id
              name: organization_id
              type: int
          tableName: report_dashboard
      - createIndex:
          columns:
          - column:
              name: creator_id
          indexName: idx_dashboard_creator_id
          tableName: report_dashboard
      - createIndex:
          columns:
          - column:
              name: organization_id
          indexName: idx_dashboard_organization_id
          tableName: report_dashboard
      - createTable:
          columns:
          - column:
              autoIncrement: true
              constraints:
                nullable: false
                primaryKey: true
              name: id
              type: int
          - column:
              constraints:
                nullable: false
              name: created_at
              type: DATETIME
          - column:
              constraints:
                nullable: false
              name: updated_at
              type: DATETIME
          - column:
              constraints:
                nullable: false
              name: sizeX
              type: int
          - column:
              constraints:
                nullable: false
              name: sizeY
              type: int
          - column:
              name: row
              type: int
          - column:
              name: col
              type: int
          - column:
              constraints:
                deferrable: false
                foreignKeyName: fk_dashboardcard_ref_card_id
                initiallyDeferred: false
                nullable: false
                referencedTableName: report_card
                referencedColumnNames: id
              name: card_id
              type: int
          - column:
              constraints:
                deferrable: false
                foreignKeyName: fk_dashboardcard_ref_dashboard_id
                initiallyDeferred: false
                nullable: false
                referencedTableName: report_dashboard
                referencedColumnNames: id
              name: dashboard_id
              type: int
          tableName: report_dashboardcard
      - createIndex:
          columns:
          - column:
              name: card_id
          indexName: idx_dashboardcard_card_id
          tableName: report_dashboardcard
      - createIndex:
          columns:
          - column:
              name: dashboard_id
          indexName: idx_dashboardcard_dashboard_id
          tableName: report_dashboardcard
      - createTable:
          columns:
          - column:
              autoIncrement: true
              constraints:
                nullable: false
                primaryKey: true
              name: id
              type: int
          - column:
              constraints:
                deferrable: false
                foreignKeyName: fk_dashboardsubscription_ref_dashboard_id
                initiallyDeferred: false
                nullable: false
                referencedTableName: report_dashboard
                referencedColumnNames: id
              name: dashboard_id
              type: int
          - column:
              constraints:
                deferrable: false
                foreignKeyName: fk_dashboardsubscription_ref_user_id
                initiallyDeferred: false
                nullable: false
                referencedTableName: core_user
                referencedColumnNames: id
              name: user_id
              type: int
          tableName: report_dashboardsubscription
      - addUniqueConstraint:
          columnNames: dashboard_id, user_id
          constraintName: idx_uniq_dashsubscrip_dashboard_id_user_id
          tableName: report_dashboardsubscription
      - createIndex:
          columns:
          - column:
              name: dashboard_id
          indexName: idx_dashboardsubscription_dashboard_id
          tableName: report_dashboardsubscription
      - createIndex:
          columns:
          - column:
              name: user_id
          indexName: idx_dashboardsubscription_user_id
          tableName: report_dashboardsubscription
      - createTable:
          columns:
          - column:
              autoIncrement: true
              constraints:
                nullable: false
                primaryKey: true
              name: id
              type: int
          - column:
              constraints:
                nullable: false
              name: created_at
              type: DATETIME
          - column:
              constraints:
                nullable: false
              name: updated_at
              type: DATETIME
          - column:
              constraints:
                nullable: false
              name: name
              type: varchar(254)
          - column:
              name: description
              type: text
          - column:
              constraints:
                nullable: false
              name: public_perms
              type: int
          - column:
              constraints:
                nullable: false
              name: mode
              type: int
          - column:
              constraints:
                nullable: false
              name: version
              type: int
          - column:
              constraints:
                nullable: false
              name: dataset_query
              type: text
          - column:
              name: email_addresses
              type: text
          - column:
              constraints:
                deferrable: false
                foreignKeyName: fk_emailreport_ref_user_id
                initiallyDeferred: false
                nullable: false
                referencedTableName: core_user
                referencedColumnNames: id
              name: creator_id
              type: int
          - column:
              constraints:
                deferrable: false
                foreignKeyName: fk_emailreport_ref_organization_id
                initiallyDeferred: false
                nullable: false
                referencedTableName: core_organization
                referencedColumnNames: id
              name: organization_id
              type: int
          - column:
              constraints:
                nullable: false
              name: schedule
              type: text
          tableName: report_emailreport
      - createIndex:
          columns:
          - column:
              name: creator_id
          indexName: idx_emailreport_creator_id
          tableName: report_emailreport
      - createIndex:
          columns:
          - column:
              name: organization_id
          indexName: idx_emailreport_organization_id
          tableName: report_emailreport
      - createTable:
          columns:
          - column:
              autoIncrement: true
              constraints:
                nullable: false
                primaryKey: true
              name: id
              type: int
          - column:
              constraints:
                deferrable: false
                foreignKeyName: fk_emailreport_recipients_ref_emailreport_id
                initiallyDeferred: false
                nullable: false
                referencedTableName: report_emailreport
                referencedColumnNames: id
              name: emailreport_id
              type: int
          - column:
              constraints:
                deferrable: false
                foreignKeyName: fk_emailreport_recipients_ref_user_id
                initiallyDeferred: false
                nullable: false
                referencedTableName: core_user
                referencedColumnNames: id
              name: user_id
              type: int
          tableName: report_emailreport_recipients
      - addUniqueConstraint:
          columnNames: emailreport_id, user_id
          constraintName: idx_uniq_emailreportrecip_emailreport_id_user_id
          tableName: report_emailreport_recipients
      - createIndex:
          columns:
          - column:
              name: emailreport_id
          indexName: idx_emailreport_recipients_emailreport_id
          tableName: report_emailreport_recipients
      - createIndex:
          columns:
          - column:
              name: user_id
          indexName: idx_emailreport_recipients_user_id
          tableName: report_emailreport_recipients
      - createTable:
          columns:
          - column:
              autoIncrement: true
              constraints:
                nullable: false
                primaryKey: true
              name: id
              type: int
          - column:
              constraints:
                nullable: false
              name: details
              type: text
          - column:
              constraints:
                nullable: false
              name: status
              type: varchar(254)
          - column:
              constraints:
                nullable: false
              name: created_at
              type: DATETIME
          - column:
              name: started_at
              type: DATETIME
          - column:
              name: finished_at
              type: DATETIME
          - column:
              constraints:
                nullable: false
              name: error
              type: text
          - column:
              constraints:
                nullable: false
              name: sent_email
              type: text
          - column:
              constraints:
                deferrable: false
                foreignKeyName: fk_emailreportexecutions_ref_organization_id
                initiallyDeferred: false
                nullable: false
                referencedTableName: core_organization
                referencedColumnNames: id
              name: organization_id
              type: int
          - column:
              constraints:
                deferrable: false
                foreignKeyName: fk_emailreportexecutions_ref_report_id
                initiallyDeferred: false
                nullable: true
                referencedTableName: report_emailreport
                referencedColumnNames: id
              name: report_id
              type: int
          tableName: report_emailreportexecutions
      - createIndex:
          columns:
          - column:
              name: organization_id
          indexName: idx_emailreportexecutions_organization_id
          tableName: report_emailreportexecutions
      - createIndex:
          columns:
          - column:
              name: report_id
          indexName: idx_emailreportexecutions_report_id
          tableName: report_emailreportexecutions
      - createTable:
          columns:
          - column:
              autoIncrement: true
              constraints:
                nullable: false
                primaryKey: true
              name: id
              type: int
          - column:
              constraints:
                nullable: false
              name: created_at
              type: DATETIME
          - column:
              constraints:
                nullable: false
              name: updated_at
              type: DATETIME
          - column:
              constraints:
                nullable: false
              name: start
              type: DATETIME
          - column:
              constraints:
                nullable: false
              name: end
              type: DATETIME
          - column:
              name: title
              type: TEXT
          - column:
              constraints:
                nullable: false
              name: body
              type: TEXT
          - column:
              constraints:
                nullable: false
              name: annotation_type
              type: int
          - column:
              constraints:
                nullable: false
              name: edit_count
              type: int
          - column:
              constraints:
                nullable: false
              name: object_type_id
              type: int
          - column:
              constraints:
                nullable: false
              name: object_id
              type: int
          - column:
              constraints:
                deferrable: false
                foreignKeyName: fk_annotation_ref_user_id
                initiallyDeferred: false
                nullable: false
                referencedTableName: core_user
                referencedColumnNames: id
              name: author_id
              type: int
          - column:
              constraints:
                deferrable: false
                foreignKeyName: fk_annotation_ref_organization_id
                initiallyDeferred: false
                nullable: false
                referencedTableName: core_organization
                referencedColumnNames: id
              name: organization_id
              type: int
          tableName: annotation_annotation
      - createIndex:
          columns:
          - column:
              name: author_id
          indexName: idx_annotation_author_id
          tableName: annotation_annotation
      - createIndex:
          columns:
          - column:
              name: organization_id
          indexName: idx_annotation_organization_id
          tableName: annotation_annotation
      - createIndex:
          columns:
          - column:
              name: object_type_id
          indexName: idx_annotation_object_type_id
          tableName: annotation_annotation
      - createIndex:
          columns:
          - column:
              name: object_id
          indexName: idx_annotation_object_id
          tableName: annotation_annotation
      - modifySql:
          dbms: postgresql
          replace:
            replace: WITHOUT
            with: WITH
  - changeSet:
      id: '2'
      author: agilliland
      validCheckSum: ANY
      changes:
      - createTable:
          columns:
          - column:
              constraints:
                nullable: false
                primaryKey: true
              name: id
              type: varchar(254)
          - column:
              constraints:
                deferrable: false
                foreignKeyName: fk_session_ref_user_id
                initiallyDeferred: false
                nullable: false
                referencedTableName: core_user
                referencedColumnNames: id
              name: user_id
              type: int
          - column:
              constraints:
                nullable: false
              name: created_at
              type: DATETIME
          tableName: core_session
      - modifySql:
          dbms: postgresql
          replace:
            replace: WITHOUT
            with: WITH
  - changeSet:
      id: '4'
      author: cammsaul
      changes:
      - createTable:
          columns:
          - column:
              constraints:
                nullable: false
                primaryKey: true
              name: key
              type: varchar(254)
          - column:
              constraints:
                nullable: false
              name: value
              type: varchar(254)
          tableName: setting
  - changeSet:
      id: '5'
      author: agilliland
      changes:
      - addColumn:
          columns:
          - column:
              name: report_timezone
              type: varchar(254)
          tableName: core_organization
  - changeSet:
      id: '6'
      author: agilliland
      changes:
      - dropNotNullConstraint:
          columnDataType: int
          columnName: organization_id
          tableName: metabase_database
      - dropForeignKeyConstraint:
          baseTableName: metabase_database
          constraintName: fk_database_ref_organization_id
      - dropNotNullConstraint:
          columnDataType: int
          columnName: organization_id
          tableName: report_card
      - dropForeignKeyConstraint:
          baseTableName: report_card
          constraintName: fk_card_ref_organization_id
      - dropNotNullConstraint:
          columnDataType: int
          columnName: organization_id
          tableName: report_dashboard
      - dropForeignKeyConstraint:
          baseTableName: report_dashboard
          constraintName: fk_dashboard_ref_organization_id
      - dropNotNullConstraint:
          columnDataType: int
          columnName: organization_id
          tableName: report_emailreport
      - dropForeignKeyConstraint:
          baseTableName: report_emailreport
          constraintName: fk_emailreport_ref_organization_id
      - dropNotNullConstraint:
          columnDataType: int
          columnName: organization_id
          tableName: report_emailreportexecutions
      - dropForeignKeyConstraint:
          baseTableName: report_emailreportexecutions
          constraintName: fk_emailreportexecutions_ref_organization_id
      - dropNotNullConstraint:
          columnDataType: int
          columnName: organization_id
          tableName: annotation_annotation
      - dropForeignKeyConstraint:
          baseTableName: annotation_annotation
          constraintName: fk_annotation_ref_organization_id
  - changeSet:
      id: '7'
      author: cammsaul
      validCheckSum: ANY
      changes:
      - addColumn:
          columns:
          - column:
              constraints:
                foreignKeyName: fk_field_parent_ref_field_id
                nullable: true
                referencedTableName: metabase_field
                referencedColumnNames: id
              name: parent_id
              type: int
          tableName: metabase_field
  - changeSet:
      id: '8'
      author: tlrobinson
      changes:
      - addColumn:
          columns:
          - column:
              name: display_name
              type: varchar(254)
          tableName: metabase_table
      - addColumn:
          columns:
          - column:
              name: display_name
              type: varchar(254)
          tableName: metabase_field
  - changeSet:
      id: '9'
      author: tlrobinson
      changes:
      - addColumn:
          columns:
          - column:
              name: visibility_type
              type: varchar(254)
          tableName: metabase_table
  - changeSet:
      id: 10
      author: cammsaul
      validCheckSum: ANY
      changes:
        - createTable:
            tableName: revision
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: model
                  type: varchar(16)
                  constraints:
                    nullable: false
              - column:
                  name: model_id
                  type: int
                  constraints:
                    nullable: false
              - column:
                  name: user_id
                  type: int
                  constraints:
                    nullable: false
                    referencedTableName: core_user
                    referencedColumnNames: id
                    foreignKeyName: fk_revision_ref_user_id
                    deferrable: false
                    initiallyDeferred: false
              - column:
                  name: timestamp
                  type: DATETIME
                  constraints:
                    nullable: false
              - column:
                  name: object
                  type: ${text.type}
                  constraints:
                    nullable: false
              - column:
                  name: is_reversion
                  type: boolean
                  defaultValueBoolean: false
                  constraints:
                    nullable: false
        - createIndex:
            tableName: revision
            indexName: idx_revision_model_model_id
            columns:
              - column:
                  name: model
              - column:
                  name: model_id
        - modifySql:
            dbms: postgresql
            replace:
              replace: WITHOUT
              with: WITH
        - modifySql:
            dbms: mysql,mariadb
            replace:
              replace: object VARCHAR
              with: object TEXT
  - changeSet:
      id: 11
      author: agilliland
      changes:
        - sql:
            sql: update report_dashboard set public_perms = 2 where public_perms = 1
  - changeSet:
      id: 12
      author: agilliland
      validCheckSum: ANY
      changes:
        - addColumn:
            tableName: report_card
            columns:
              - column:
                  name: database_id
                  type: int
                  constraints:
                    nullable: true
                    referencedTableName: metabase_database
                    referencedColumnNames: id
                    foreignKeyName: fk_report_card_ref_database_id
                    deferrable: false
                    initiallyDeferred: false
        - addColumn:
            tableName: report_card
            columns:
              - column:
                  name: table_id
                  type: int
                  constraints:
                    nullable: true
                    referencedTableName: metabase_table
                    referencedColumnNames: id
                    foreignKeyName: fk_report_card_ref_table_id
                    deferrable: false
                    initiallyDeferred: false
        - addColumn:
            tableName: report_card
            columns:
              - column:
                  name: query_type
                  type: varchar(16)
                  constraints:
                    nullable: true
  - changeSet:
      id: 13
      author: agilliland
      validCheckSum: ANY
      changes:
        - createTable:
            tableName: activity
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: topic
                  type: varchar(32)
                  constraints:
                    nullable: false
              - column:
                  name: timestamp
                  type: DATETIME
                  constraints:
                    nullable: false
              - column:
                  name: user_id
                  type: int
                  constraints:
                    nullable: true
                    referencedTableName: core_user
                    referencedColumnNames: id
                    foreignKeyName: fk_activity_ref_user_id
                    deferrable: false
                    initiallyDeferred: false
              - column:
                  name: model
                  type: varchar(16)
                  constraints:
                    nullable: true
              - column:
                  name: model_id
                  type: int
                  constraints:
                    nullable: true
              - column:
                  name: database_id
                  type: int
                  constraints:
                    nullable: true
              - column:
                  name: table_id
                  type: int
                  constraints:
                    nullable: true
              - column:
                  name: custom_id
                  type: varchar(48)
                  constraints:
                    nullable: true
              - column:
                  name: details
                  type: ${text.type}
                  constraints:
                    nullable: false
        - createIndex:
            tableName: activity
            indexName: idx_activity_timestamp
            columns:
              column:
                name: timestamp
        - createIndex:
            tableName: activity
            indexName: idx_activity_user_id
            columns:
              column:
                name: user_id
        - createIndex:
            tableName: activity
            indexName: idx_activity_custom_id
            columns:
              column:
                name: custom_id
        - modifySql:
            dbms: postgresql
            replace:
              replace: WITHOUT
              with: WITH
        - modifySql:
            dbms: mysql,mariadb
            replace:
              replace: details VARCHAR
              with: details TEXT
  - changeSet:
      id: 14
      author: agilliland
      validCheckSum: ANY
      changes:
        - createTable:
            tableName: view_log
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: user_id
                  type: int
                  constraints:
                    nullable: true
                    referencedTableName: core_user
                    referencedColumnNames: id
                    foreignKeyName: fk_view_log_ref_user_id
                    deferrable: false
                    initiallyDeferred: false
              - column:
                  name: model
                  type: varchar(16)
                  constraints:
                    nullable: false
              - column:
                  name: model_id
                  type: int
                  constraints:
                    nullable: false
              - column:
                  name: timestamp
                  type: DATETIME
                  constraints:
                    nullable: false
        - createIndex:
            tableName: view_log
            indexName: idx_view_log_user_id
            columns:
              column:
                name: user_id
        - createIndex:
            tableName: view_log
            indexName: idx_view_log_timestamp
            columns:
              column:
                name: model_id
        - modifySql:
            dbms: postgresql
            replace:
              replace: WITHOUT
              with: WITH
  - changeSet:
      id: 15
      author: agilliland
      changes:
        - addColumn:
            tableName: revision
            columns:
              - column:
                  name: is_creation
                  type: boolean
                  defaultValueBoolean: false
                  constraints:
                    nullable: false
  - changeSet:
      id: 16
      author: agilliland
      changes:
        - dropNotNullConstraint:
            tableName: core_user
            columnName: last_login
            columnDataType: DATETIME
        - modifySql:
            dbms: postgresql
            replace:
              replace: WITHOUT
              with: WITH
  - changeSet:
      id: 17
      author: agilliland
      changes:
        - addColumn:
            tableName: metabase_database
            columns:
              - column:
                  name: is_sample
                  type: boolean
                  defaultValueBoolean: false
                  constraints:
                    nullable: false
        - sql:
            sql: update metabase_database set is_sample = true where name = 'Sample Dataset'
  - changeSet:
      id: 18
      author: camsaul
      validCheckSum: ANY
      changes:
        - createTable:
            tableName: data_migrations
            columns:
              - column:
                  name: id
                  type: VARCHAR(254)
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: timestamp
                  type: DATETIME
                  constraints:
                    nullable: false
        - createIndex:
            tableName: data_migrations
            indexName: idx_data_migrations_id
            columns:
              column:
                name: id
  - changeSet:
      id: 19
      author: camsaul
      changes:
        - addColumn:
            tableName: metabase_table
            columns:
              - column:
                  name: schema
                  type: VARCHAR(256)
  - changeSet:
      id: 20
      author: agilliland
      validCheckSum: ANY
      changes:
        - createTable:
            tableName: pulse
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: creator_id
                  type: int
                  constraints:
                    nullable: false
                    referencedTableName: core_user
                    referencedColumnNames: id
                    foreignKeyName: fk_pulse_ref_creator_id
                    deferrable: false
                    initiallyDeferred: false
              - column:
                  name: name
                  type: varchar(254)
                  constraints:
                    nullable: false
              - column:
                  name: public_perms
                  type: int
                  constraints:
                    nullable: false
              - column:
                  name: created_at
                  type: DATETIME
                  constraints:
                    nullable: false
              - column:
                  name: updated_at
                  type: DATETIME
                  constraints:
                    nullable: false
        - createIndex:
            tableName: pulse
            indexName: idx_pulse_creator_id
            columns:
              column:
                name: creator_id
        - createTable:
            tableName: pulse_card
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: pulse_id
                  type: int
                  constraints:
                    nullable: false
                    referencedTableName: pulse
                    referencedColumnNames: id
                    foreignKeyName: fk_pulse_card_ref_pulse_id
                    deferrable: false
                    initiallyDeferred: false
              - column:
                  name: card_id
                  type: int
                  constraints:
                    nullable: false
                    referencedTableName: report_card
                    referencedColumnNames: id
                    foreignKeyName: fk_pulse_card_ref_card_id
                    deferrable: false
                    initiallyDeferred: false
              - column:
                  name: position
                  type: int
                  constraints:
                    nullable: false
        - createIndex:
            tableName: pulse_card
            indexName: idx_pulse_card_pulse_id
            columns:
              column:
                name: pulse_id
        - createIndex:
            tableName: pulse_card
            indexName: idx_pulse_card_card_id
            columns:
              column:
                name: card_id
        - createTable:
            tableName: pulse_channel
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: pulse_id
                  type: int
                  constraints:
                    nullable: false
                    referencedTableName: pulse
                    referencedColumnNames: id
                    foreignKeyName: fk_pulse_channel_ref_pulse_id
                    deferrable: false
                    initiallyDeferred: false
              - column:
                  name: channel_type
                  type: varchar(32)
                  constraints:
                    nullable: false
              - column:
                  name: details
                  type: text
                  constraints:
                    nullable: false
              - column:
                  name: schedule_type
                  type: varchar(32)
                  constraints:
                    nullable: false
              - column:
                  name: schedule_hour
                  type: int
                  constraints:
                    nullable: true
              - column:
                  name: schedule_day
                  type: varchar(64)
                  constraints:
                    nullable: true
              - column:
                  name: created_at
                  type: DATETIME
                  constraints:
                    nullable: false
              - column:
                  name: updated_at
                  type: DATETIME
                  constraints:
                    nullable: false
        - createIndex:
            tableName: pulse_channel
            indexName: idx_pulse_channel_pulse_id
            columns:
              column:
                name: pulse_id
        - createIndex:
            tableName: pulse_channel
            indexName: idx_pulse_channel_schedule_type
            columns:
              column:
                name: schedule_type
        - createTable:
            tableName: pulse_channel_recipient
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: pulse_channel_id
                  type: int
                  constraints:
                    nullable: false
                    referencedTableName: pulse_channel
                    referencedColumnNames: id
                    foreignKeyName: fk_pulse_channel_recipient_ref_pulse_channel_id
                    deferrable: false
                    initiallyDeferred: false
              - column:
                  name: user_id
                  type: int
                  constraints:
                    nullable: false
                    referencedTableName: core_user
                    referencedColumnNames: id
                    foreignKeyName: fk_pulse_channel_recipient_ref_user_id
                    deferrable: false
                    initiallyDeferred: false
        - modifySql:
            dbms: postgresql
            replace:
              replace: WITHOUT
              with: WITH
  - changeSet:
      id: 21
      author: agilliland
      validCheckSum: ANY
      changes:
        - createTable:
            tableName: segment
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: table_id
                  type: int
                  constraints:
                    nullable: false
                    referencedTableName: metabase_table
                    referencedColumnNames: id
                    foreignKeyName: fk_segment_ref_table_id
                    deferrable: false
                    initiallyDeferred: false
              - column:
                  name: creator_id
                  type: int
                  constraints:
                    nullable: false
                    referencedTableName: core_user
                    referencedColumnNames: id
                    foreignKeyName: fk_segment_ref_creator_id
                    deferrable: false
                    initiallyDeferred: false
              - column:
                  name: name
                  type: varchar(254)
                  constraints:
                    nullable: false
              - column:
                  name: description
                  type: text
                  constraints:
                    nullable: true
              - column:
                  name: is_active
                  type: boolean
                  defaultValueBoolean: true
                  constraints:
                    nullable: false
              - column:
                  name: definition
                  type: text
                  constraints:
                    nullable: false
              - column:
                  name: created_at
                  type: DATETIME
                  constraints:
                    nullable: false
              - column:
                  name: updated_at
                  type: DATETIME
                  constraints:
                    nullable: false
        - createIndex:
            tableName: segment
            indexName: idx_segment_creator_id
            columns:
              column:
                name: creator_id
        - createIndex:
            tableName: segment
            indexName: idx_segment_table_id
            columns:
              column:
                name: table_id
        - modifySql:
            dbms: postgresql
            replace:
              replace: WITHOUT
              with: WITH
  - changeSet:
      id: 22
      author: agilliland
      changes:
        - addColumn:
            tableName: revision
            columns:
              - column:
                  name: message
                  type: text
                  constraints:
                    nullable: true
  - changeSet:
      id: 23
      author: agilliland
      changes:
        - modifyDataType:
            tableName: metabase_table
            columnName: rows
            newDataType: BIGINT
  - changeSet:
      id: 24
      author: agilliland
      changes:
        - createTable:
            tableName: dependency
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: model
                  type: varchar(32)
                  constraints:
                    nullable: false
              - column:
                  name: model_id
                  type: int
                  constraints:
                    nullable: false
              - column:
                  name: dependent_on_model
                  type: varchar(32)
                  constraints:
                    nullable: false
              - column:
                  name: dependent_on_id
                  type: int
                  constraints:
                    nullable: false
              - column:
                  name: created_at
                  type: DATETIME
                  constraints:
                    nullable: false
        - createIndex:
            tableName: dependency
            indexName: idx_dependency_model
            columns:
              column:
                name: model
        - createIndex:
            tableName: dependency
            indexName: idx_dependency_model_id
            columns:
              column:
                name: model_id
        - createIndex:
            tableName: dependency
            indexName: idx_dependency_dependent_on_model
            columns:
              column:
                name: dependent_on_model
        - createIndex:
            tableName: dependency
            indexName: idx_dependency_dependent_on_id
            columns:
              column:
                name: dependent_on_id
        - modifySql:
            dbms: postgresql
            replace:
              replace: WITHOUT
              with: WITH
  - changeSet:
      id: 25
      author: agilliland
      validCheckSum: ANY
      changes:
        - createTable:
            tableName: metric
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: table_id
                  type: int
                  constraints:
                    nullable: false
                    referencedTableName: metabase_table
                    referencedColumnNames: id
                    foreignKeyName: fk_metric_ref_table_id
                    deferrable: false
                    initiallyDeferred: false
              - column:
                  name: creator_id
                  type: int
                  constraints:
                    nullable: false
                    referencedTableName: core_user
                    referencedColumnNames: id
                    foreignKeyName: fk_metric_ref_creator_id
                    deferrable: false
                    initiallyDeferred: false
              - column:
                  name: name
                  type: varchar(254)
                  constraints:
                    nullable: false
              - column:
                  name: description
                  type: text
                  constraints:
                    nullable: true
              - column:
                  name: is_active
                  type: boolean
                  defaultValueBoolean: true
                  constraints:
                    nullable: false
              - column:
                  name: definition
                  type: text
                  constraints:
                    nullable: false
              - column:
                  name: created_at
                  type: DATETIME
                  constraints:
                    nullable: false
              - column:
                  name: updated_at
                  type: DATETIME
                  constraints:
                    nullable: false
        - createIndex:
            tableName: metric
            indexName: idx_metric_creator_id
            columns:
              column:
                name: creator_id
        - createIndex:
            tableName: metric
            indexName: idx_metric_table_id
            columns:
              column:
                name: table_id
        - modifySql:
            dbms: postgresql
            replace:
              replace: WITHOUT
              with: WITH
  - changeSet:
      id: 26
      author: agilliland
      changes:
        - addColumn:
            tableName: metabase_database
            columns:
              - column:
                  name: is_full_sync
                  type: boolean
                  defaultValueBoolean: true
                  constraints:
                    nullable: false
        - sql:
            sql: update metabase_database set is_full_sync = true
  - changeSet:
      id: 27
      author: agilliland
      validCheckSum: ANY
      changes:
        - createTable:
            tableName: dashboardcard_series
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: dashboardcard_id
                  type: int
                  constraints:
                    nullable: false
                    referencedTableName: report_dashboardcard
                    referencedColumnNames: id
                    foreignKeyName: fk_dashboardcard_series_ref_dashboardcard_id
                    deferrable: false
                    initiallyDeferred: false
              - column:
                  name: card_id
                  type: int
                  constraints:
                    nullable: false
                    referencedTableName: report_card
                    referencedColumnNames: id
                    foreignKeyName: fk_dashboardcard_series_ref_card_id
                    deferrable: false
                    initiallyDeferred: false
              - column:
                  name: position
                  type: int
                  constraints:
                    nullable: false
        - createIndex:
            tableName: dashboardcard_series
            indexName: idx_dashboardcard_series_dashboardcard_id
            columns:
              column:
                name: dashboardcard_id
        - createIndex:
            tableName: dashboardcard_series
            indexName: idx_dashboardcard_series_card_id
            columns:
              column:
                name: card_id
        - modifySql:
            dbms: postgresql
            replace:
              replace: WITHOUT
              with: WITH
  - changeSet:
      id: 28
      author: agilliland
      changes:
        - addColumn:
            tableName: core_user
            columns:
              - column:
                  name: is_qbnewb
                  type: boolean
                  defaultValueBoolean: true
                  constraints:
                    nullable: false
  - changeSet:
      id: 29
      author: agilliland
      changes:
        - addColumn:
            tableName: pulse_channel
            columns:
              - column:
                  name: schedule_frame
                  type: varchar(32)
                  constraints:
                    nullable: true
  - changeSet:
      id: 30
      author: agilliland
      changes:
        - addColumn:
            tableName: metabase_field
            columns:
              - column:
                  name: visibility_type
                  type: varchar(32)
                  constraints:
                    nullable: true
                    deferrable: false
                    initiallyDeferred: false
        - addNotNullConstraint:
            columnDataType: varchar(32)
            columnName: visibility_type
            defaultNullValue: unset
            tableName: metabase_field

  - changeSet:
      id: 31
      author: agilliland
      changes:
        - addColumn:
            tableName: metabase_field
            columns:
              - column:
                  name: fk_target_field_id
                  type: int
                  constraints:
                    nullable: true
                    deferrable: false
                    initiallyDeferred: false
  - changeSet:
      id: 32
      author: camsaul
      validCheckSum: ANY
      changes:
        ######################################## label table ########################################
        - createTable:
            tableName: label
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: name
                  type: VARCHAR(254)
                  constraints:
                    nullable: false
              - column:
                  name: slug
                  type: VARCHAR(254)
                  constraints:
                    nullable: false
                    unique: true
              - column:
                  name: icon
                  type: VARCHAR(128)
        - createIndex:
            tableName: label
            indexName: idx_label_slug
            columns:
              column:
                name: slug
        ######################################## card_label table ########################################
        - createTable:
            tableName: card_label
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: card_id
                  type: int
                  constraints:
                    nullable: false
                    referencedTableName: report_card
                    referencedColumnNames: id
                    foreignKeyName: fk_card_label_ref_card_id
                    deferrable: false
                    initiallyDeferred: false
              - column:
                  name: label_id
                  type: int
                  constraints:
                    nullable: false
                    referencedTableName: label
                    referencedColumnNames: id
                    foreignKeyName: fk_card_label_ref_label_id
                    deferrable: false
                    initiallyDeferred: false
        - addUniqueConstraint:
            tableName: card_label
            columnNames: card_id, label_id
            constraintName: unique_card_label_card_id_label_id
        - createIndex:
            tableName: card_label
            indexName: idx_card_label_card_id
            columns:
              column:
                name: card_id
        - createIndex:
            tableName: card_label
            indexName: idx_card_label_label_id
            columns:
              column:
                name: label_id
        ######################################## add archived column to report_card ########################################
        - addColumn:
            tableName: report_card
            columns:
              - column:
                  name: archived
                  type: boolean
                  defaultValueBoolean: false
                  constraints:
                    nullable: false
  - changeSet:
      id: 32
      author: agilliland
      validCheckSum: ANY
      changes:
        - createTable:
            tableName: raw_table
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: database_id
                  type: int
                  constraints:
                    nullable: false
                    referencedTableName: metabase_database
                    referencedColumnNames: id
                    foreignKeyName: fk_rawtable_ref_database
                    deferrable: false
                    initiallyDeferred: false
              - column:
                  name: active
                  type: boolean
                  constraints:
                    nullable: false
              - column:
                  name: schema
                  type: varchar(255)
                  constraints:
                    nullable: true
              - column:
                  name: name
                  type: varchar(255)
                  constraints:
                    nullable: false
              - column:
                  name: details
                  type: text
                  constraints:
                    nullable: false
              - column:
                  name: created_at
                  type: DATETIME
                  constraints:
                    nullable: false
              - column:
                  name: updated_at
                  type: DATETIME
                  constraints:
                    nullable: false
        - createIndex:
            tableName: raw_table
            indexName: idx_rawtable_database_id
            columns:
              column:
                name: database_id
        - addUniqueConstraint:
            tableName: raw_table
            columnNames: database_id, schema, name
            constraintName: uniq_raw_table_db_schema_name
        - createTable:
            tableName: raw_column
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: raw_table_id
                  type: int
                  constraints:
                    nullable: false
                    referencedTableName: raw_table
                    referencedColumnNames: id
                    foreignKeyName: fk_rawcolumn_tableid_ref_rawtable
                    deferrable: false
                    initiallyDeferred: false
              - column:
                  name: active
                  type: boolean
                  constraints:
                    nullable: false
              - column:
                  name: name
                  type: varchar(255)
                  constraints:
                    nullable: false
              - column:
                  name: column_type
                  type: varchar(128)
                  constraints:
                    nullable: true
              - column:
                  name: is_pk
                  type: boolean
                  constraints:
                    nullable: false
              - column:
                  name: fk_target_column_id
                  type: int
                  constraints:
                    nullable: true
                    referencedTableName: raw_column
                    referencedColumnNames: id
                    foreignKeyName: fk_rawcolumn_fktarget_ref_rawcolumn
                    deferrable: false
                    initiallyDeferred: false
              - column:
                  name: details
                  type: text
                  constraints:
                    nullable: false
              - column:
                  name: created_at
                  type: DATETIME
                  constraints:
                    nullable: false
              - column:
                  name: updated_at
                  type: DATETIME
                  constraints:
                    nullable: false
        - createIndex:
            tableName: raw_column
            indexName: idx_rawcolumn_raw_table_id
            columns:
              column:
                name: raw_table_id
        - addUniqueConstraint:
            tableName: raw_column
            columnNames: raw_table_id, name
            constraintName: uniq_raw_column_table_name
        - addColumn:
            tableName: metabase_table
            columns:
              - column:
                  name: raw_table_id
                  type: int
                  constraints:
                    nullable: true
                    deferrable: false
                    initiallyDeferred: false
        - addColumn:
            tableName: metabase_field
            columns:
              - column:
                  name: raw_column_id
                  type: int
                  constraints:
                    nullable: true
                    deferrable: false
                    initiallyDeferred: false
        - addColumn:
            tableName: metabase_field
            columns:
              - column:
                  name: last_analyzed
                  type: DATETIME
                  constraints:
                    nullable: true
                    deferrable: false
                    initiallyDeferred: false
        - modifySql:
            dbms: postgresql
            replace:
              replace: WITHOUT
              with: WITH
  - changeSet:
      id: 34
      author: tlrobinson
      changes:
        ######################################## add enabled column to pulse_channel ########################################
        - addColumn:
            tableName: pulse_channel
            columns:
              - column:
                  name: enabled
                  type: boolean
                  defaultValueBoolean: true
                  constraints:
                    nullable: false
  - changeSet:
      id: 35
      author: agilliland
      changes:
        - modifyDataType:
            tableName: setting
            columnName: value
            newDataType: TEXT
        - addNotNullContstraint:
            tableName: setting
            columnNames: value
  - changeSet:
      id: 36
      author: agilliland
      changes:
        - addColumn:
            tableName: report_dashboard
            columns:
              - column:
                  name: parameters
                  type: text
                  constraints:
                    nullable: true
                    deferrable: false
                    initiallyDeferred: false
        - addNotNullConstraint:
            columnDataType: text
            columnName: parameters
            defaultNullValue: '[]'
            tableName: report_dashboard
        - addColumn:
            tableName: report_dashboardcard
            columns:
              - column:
                  name: parameter_mappings
                  type: text
                  constraints:
                    nullable: true
                    deferrable: false
                    initiallyDeferred: false
        - addNotNullConstraint:
            columnDataType: text
            columnName: parameter_mappings
            defaultNullValue: '[]'
            tableName: report_dashboardcard
  - changeSet:
      id: 37
      author: tlrobinson
      changes:
        - addColumn:
            tableName: query_queryexecution
            columns:
              - column:
                  name: query_hash
                  type: int
                  constraints:
                    nullable: true
        - addNotNullConstraint:
            tableName: query_queryexecution
            columnName: query_hash
            columnDataType: int
            defaultNullValue: 0
        - createIndex:
            tableName: query_queryexecution
            indexName: idx_query_queryexecution_query_hash
            columns:
              column:
                name: query_hash
        - createIndex:
            tableName: query_queryexecution
            indexName: idx_query_queryexecution_started_at
            columns:
              column:
                name: started_at
  - changeSet:
      id: 38
      author: camsaul
      validCheckSum: ANY
      changes:
        ######################################## Add "points_of_interest" metadata column to various models ########################################
        - addColumn:
            tableName: metabase_database
            columns:
              - column:
                  name: points_of_interest
                  type: text
        - addColumn:
            tableName: metabase_table
            columns:
              - column:
                  name: points_of_interest
                  type: text
        - addColumn:
            tableName: metabase_field
            columns:
              - column:
                  name: points_of_interest
                  type: text
        - addColumn:
            tableName: report_dashboard
            columns:
              - column:
                  name: points_of_interest
                  type: text
        - addColumn:
            tableName: metric
            columns:
              - column:
                  name: points_of_interest
                  type: text
        - addColumn:
            tableName: segment
            columns:
              - column:
                  name: points_of_interest
                  type: text
        ######################################## Add "caveats" metadata column to various models ########################################
        - addColumn:
            tableName: metabase_database
            columns:
              - column:
                  name: caveats
                  type: text
        - addColumn:
            tableName: metabase_table
            columns:
              - column:
                  name: caveats
                  type: text
        - addColumn:
            tableName: metabase_field
            columns:
              - column:
                  name: caveats
                  type: text
        - addColumn:
            tableName: report_dashboard
            columns:
              - column:
                  name: caveats
                  type: text
        - addColumn:
            tableName: metric
            columns:
              - column:
                  name: caveats
                  type: text
        - addColumn:
            tableName: segment
            columns:
              - column:
                  name: caveats
                  type: text
        ######################################## Add "how_is_this_calculated" to metric ########################################
        - addColumn:
            tableName: metric
            columns:
              - column:
                  name: how_is_this_calculated
                  type: text
        ######################################## Add "most important dashboard" (0 or 1 dashboards) ########################################
        - addColumn:
            tableName: report_dashboard
            columns:
              - column:
                  name: show_in_getting_started
                  type: boolean
                  defaultValueBoolean: false
                  constraints:
                    nullable: false
        - createIndex:
            tableName: report_dashboard
            indexName: idx_report_dashboard_show_in_getting_started
            columns:
              column:
                name: show_in_getting_started
        ######################################## Add "most important metrics" (0+ metrics) ########################################
        - addColumn:
            tableName: metric
            columns:
              - column:
                  name: show_in_getting_started
                  type: boolean
                  defaultValueBoolean: false
                  constraints:
                    nullable: false
        - createIndex:
            tableName: metric
            indexName: idx_metric_show_in_getting_started
            columns:
              column:
                name: show_in_getting_started
        ######################################## Add "most important tables (0+ tables) ########################################
        - addColumn:
            tableName: metabase_table
            columns:
              - column:
                  name: show_in_getting_started
                  type: boolean
                  defaultValueBoolean: false
                  constraints:
                    nullable: false
        - createIndex:
            tableName: metabase_table
            indexName: idx_metabase_table_show_in_getting_started
            columns:
              column:
                name: show_in_getting_started
        ######################################## Add "most important segments" (0+ segments) ########################################
        - addColumn:
            tableName: segment
            columns:
              - column:
                  name: show_in_getting_started
                  type: boolean
                  defaultValueBoolean: false
                  constraints:
                    nullable: false
        - createIndex:
            tableName: segment
            indexName: idx_segment_show_in_getting_started
            columns:
              column:
                name: show_in_getting_started
        ######################################## Add "metric_important_field" table ########################################
        - createTable:
            tableName: metric_important_field
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: metric_id
                  type: int
                  constraints:
                    nullable: false
                    referencedTableName: metric
                    referencedColumnNames: id
                    foreignKeyName: fk_metric_important_field_metric_id
              - column:
                  name: field_id
                  type: int
                  constraints:
                    nullable: false
                    referencedTableName: metabase_field
                    referencedColumnNames: id
                    foreignKeyName: fk_metric_important_field_metabase_field_id
        - addUniqueConstraint:
            tableName: metric_important_field
            columnNames: metric_id, field_id
            constraintName: unique_metric_important_field_metric_id_field_id
        - createIndex:
            tableName: metric_important_field
            indexName: idx_metric_important_field_metric_id
            columns:
              column:
                name: metric_id
        - createIndex:
            tableName: metric_important_field
            indexName: idx_metric_important_field_field_id
            columns:
              column:
                name: field_id
  - changeSet:
      id: 39
      author: camsaul
      changes:
        - addColumn:
            tableName: core_user
            columns:
              - column:
                  name: google_auth
                  type: boolean
                  defaultValueBoolean: false
                  constraints:
                    nullable: false
  - changeSet:
      id: 40
      author: camsaul
      validCheckSum: ANY
      changes:
        ############################################################ add PermissionsGroup table ############################################################
        - createTable:
            tableName: permissions_group
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              # TODO - it would be nice to make this a case-insensitive unique constraint / index?
              - column:
                  name: name
                  type: varchar(255)
                  constraints:
                    nullable: false
                    unique: true
                    uniqueConstraintName: unique_permissions_group_name
        - createIndex:
            tableName: permissions_group
            indexName: idx_permissions_group_name
            columns:
              column:
                name: name
        ############################################################ add PermissionsGroupMembership table ############################################################
        - createTable:
            tableName: permissions_group_membership
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: user_id
                  type: int
                  constraints:
                    nullable: false
                    referencedTableName: core_user
                    referencedColumnNames: id
                    foreignKeyName: fk_permissions_group_membership_user_id
              - column:
                  name: group_id
                  type: int
                  constraints:
                    nullable: false
                    referencedTableName: permissions_group
                    referencedColumnNames: id
                    foreignKeyName: fk_permissions_group_group_id
        - addUniqueConstraint:
            tableName: permissions_group_membership
            columnNames: user_id, group_id
            constraintName: unique_permissions_group_membership_user_id_group_id
        # for things like all users in a given group
        - createIndex:
            tableName: permissions_group_membership
            indexName: idx_permissions_group_membership_group_id
            columns:
              column:
                name: group_id
        # for things like all groups a user belongs to
        - createIndex:
            tableName: permissions_group_membership
            indexName: idx_permissions_group_membership_user_id
            columns:
              column:
                name: user_id
        # for things like is given user a member of a given group (TODO - not sure we need this)
        - createIndex:
            tableName: permissions_group_membership
            indexName: idx_permissions_group_membership_group_id_user_id
            columns:
              - column:
                  name: group_id
              - column:
                  name: user_id
        ############################################################ add Permissions table ############################################################
        - createTable:
            tableName: permissions
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: object
                  type: varchar(254)
                  constraints:
                    nullable: false
              - column:
                  name: group_id
                  type: int
                  constraints:
                    nullable: false
                    referencedTableName: permissions_group
                    referencedColumnNames: id
                    foreignKeyName: fk_permissions_group_id
        - createIndex:
            tableName: permissions
            indexName: idx_permissions_group_id
            columns:
              column:
                name: group_id
        - createIndex:
            tableName: permissions
            indexName: idx_permissions_object
            columns:
              column:
                name: object
        - createIndex:
            tableName: permissions
            indexName: idx_permissions_group_id_object
            columns:
              - column:
                  name: group_id
              - column:
                  name: object
        - addUniqueConstraint:
            tableName: permissions
            columnNames: group_id, object
        ############################################################ Tweaks to metabase_table ############################################################
        # Modify the length of metabase_table.schema from 256 -> 254
        # It turns out MySQL InnoDB indices have to be 767 bytes or less (at least for older versions of MySQL)
        # and 'utf8' text columns can use up to 3 bytes per character in MySQL -- see http://stackoverflow.com/a/22515986/1198455
        # So 256 * 3 = 768 bytes (too large to index / add unique constraints)
        # Drop this to 254; 254 * 3 = 762, which should give us room to index it along with a 4-byte integer as well if need be
        # Hoping this doesn't break anyone's existing databases. Hopefully there aren't any schemas that are 255 or 256 bytes long out there; any longer
        # and it would have already broke; any shorter and there's not problem.
        # Anyway, better to break it now than to leave it as-is and have and break permissions where the columns have to be 254 characters wide
        - modifyDataType:
            tableName: metabase_table
            columnName: schema
            newDataType: varchar(254)
        # Add index: this is for doing things like getting all the tables that belong to a given schema
        - createIndex:
            tableName: metabase_table
            indexName: idx_metabase_table_db_id_schema
            columns:
              - column:
                  name: db_id
              - column:
                  name: schema
  - changeSet:
      id: 41
      author: camsaul
      changes:
        - dropColumn:
            tableName: metabase_field
            columnName: field_type
        - addDefaultValue:
            tableName: metabase_field
            columnName: active
            defaultValueBoolean: true
        - addDefaultValue:
            tableName: metabase_field
            columnName: preview_display
            defaultValueBoolean: true
        - addDefaultValue:
            tableName: metabase_field
            columnName: position
            defaultValueNumeric: 0
        - addDefaultValue:
            tableName: metabase_field
            columnName: visibility_type
            defaultValue: "normal"
  - changeSet:
      id: 42
      author: camsaul
      changes:
        - dropForeignKeyConstraint:
            baseTableName: query_queryexecution
            constraintName: fk_queryexecution_ref_query_id
        - dropColumn:
            tableName: query_queryexecution
            columnName: query_id
        - dropColumn:
            tableName: core_user
            columnName: is_staff
        - dropColumn:
            tableName: metabase_database
            columnName: organization_id
        - dropColumn:
            tableName: report_card
            columnName: organization_id
        - dropColumn:
            tableName: report_dashboard
            columnName: organization_id
        - dropTable:
            tableName: annotation_annotation
        - dropTable:
            tableName: core_permissionsviolation
        - dropTable:
            tableName: core_userorgperm
        - dropTable:
            tableName: core_organization
        - dropTable:
            tableName: metabase_foreignkey
        - dropTable:
            tableName: metabase_tablesegment
        - dropTable:
            tableName: query_query
        - dropTable:
            tableName: report_dashboardsubscription
        - dropTable:
            tableName: report_emailreport_recipients
        - dropTable:
            tableName: report_emailreportexecutions
        - dropTable:
            tableName: report_emailreport
  - changeSet:
      id: 43
      author: camsaul
      validCheckSum: ANY
      changes:
        - createTable:
            tableName: permissions_revision
            remarks: 'Used to keep track of changes made to permissions.'
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: before
                  type: text
                  remarks: 'Serialized JSON of the permissions before the changes.'
                  constraints:
                    nullable: false
              - column:
                  name: after
                  type: text
                  remarks: 'Serialized JSON of the permissions after the changes.'
                  constraints:
                    nullable: false
              - column:
                  name: user_id
                  type: int
                  remarks: 'The ID of the admin who made this set of changes.'
                  constraints:
                    nullable: false
                    referencedTableName: core_user
                    referencedColumnNames: id
                    foreignKeyName: fk_permissions_revision_user_id
              - column:
                  name: created_at
                  type: datetime
                  remarks: 'The timestamp of when these changes were made.'
                  constraints:
                    nullable: false
              - column:
                  name: remark
                  type: text
                  remarks: 'Optional remarks explaining why these changes were made.'
  - changeSet:
      id: 44
      author: camsaul
      changes:
        - dropColumn:
            tableName: report_card
            columnName: public_perms
        - dropColumn:
            tableName: report_dashboard
            columnName: public_perms
        - dropColumn:
            tableName: pulse
            columnName: public_perms
  - changeSet:
      id: 45
      author: tlrobinson
      changes:
        - addColumn:
            tableName: report_dashboardcard
            columns:
              - column:
                  name: visualization_settings
                  type: text
        - addNotNullConstraint:
            tableName: report_dashboardcard
            columnName: visualization_settings
            columnDataType: text
            defaultNullValue: '{}'
  - changeSet:
      id: 46
      author: camsaul
      changes:
        - addNotNullConstraint:
            tableName: report_dashboardcard
            columnName: row
            columnDataType: integer
            defaultNullValue: 0
        - addNotNullConstraint:
            tableName: report_dashboardcard
            columnName: col
            columnDataType: integer
            defaultNullValue: 0
        - addDefaultValue:
            tableName: report_dashboardcard
            columnName: row
            defaultValueNumeric: 0
        - addDefaultValue:
            tableName: report_dashboardcard
            columnName: col
            defaultValueNumeric: 0
  - changeSet:
      id: 47
      author: camsaul
      validCheckSum: ANY
      changes:
        ######################################## collection table ########################################
        - createTable:
            tableName: collection
            remarks: 'Collections are an optional way to organize Cards and handle permissions for them.'
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: name
                  type: text
                  remarks: 'The unique, user-facing name of this Collection.'
                  constraints:
                    nullable: false
              - column:
                  name: slug
                  type: varchar(254)
                  remarks: 'URL-friendly, sluggified, indexed version of name.'
                  constraints:
                    nullable: false
                    unique: true
              - column:
                  name: description
                  type: text
                  remarks: 'Optional description for this Collection.'
              - column:
                  name: color
                  type: char(7)
                  remarks: 'Seven-character hex color for this Collection, including the preceding hash sign.'
                  constraints:
                    nullable: false
              - column:
                  name: archived
                  type: boolean
                  remarks: 'Whether this Collection has been archived and should be hidden from users.'
                  defaultValueBoolean: false
                  constraints:
                    nullable: false
        - createIndex:
            tableName: collection
            indexName: idx_collection_slug
            columns:
              column:
                name: slug
        ######################################## add collection_id to report_card ########################################
        - addColumn:
            tableName: report_card
            columns:
              - column:
                  name: collection_id
                  type: int
                  remarks: 'Optional ID of Collection this Card belongs to.'
                  constraints:
                    referencedTableName: collection
                    referencedColumnNames: id
                    foreignKeyName: fk_card_collection_id
        - createIndex:
            tableName: report_card
            indexName: idx_card_collection_id
            columns:
              column:
                name: collection_id
  - changeSet:
      id: 48
      author: camsaul
      validCheckSum: ANY
      changes:
        - createTable:
            tableName: collection_revision
            remarks: 'Used to keep track of changes made to collections.'
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: before
                  type: text
                  remarks: 'Serialized JSON of the collections graph before the changes.'
                  constraints:
                    nullable: false
              - column:
                  name: after
                  type: text
                  remarks: 'Serialized JSON of the collections graph after the changes.'
                  constraints:
                    nullable: false
              - column:
                  name: user_id
                  type: int
                  remarks: 'The ID of the admin who made this set of changes.'
                  constraints:
                    nullable: false
                    referencedTableName: core_user
                    referencedColumnNames: id
                    foreignKeyName: fk_collection_revision_user_id
              - column:
                  name: created_at
                  type: datetime
                  remarks: 'The timestamp of when these changes were made.'
                  constraints:
                    nullable: false
              - column:
                  name: remark
                  type: text
                  remarks: 'Optional remarks explaining why these changes were made.'
  - changeSet:
      id: 49
      author: camsaul
      validCheckSum: ANY
      changes:
        ######################################## Card public_uuid & indices ########################################
        - addColumn:
            tableName: report_card
            columns:
              - column:
                  name: public_uuid
                  type: char(36)
                  remarks: 'Unique UUID used to in publically-accessible links to this Card.'
                  constraints:
                    unique: true
        - addColumn:
            tableName: report_card
            columns:
              - column:
                  name: made_public_by_id
                  type: int
                  remarks: 'The ID of the User who first publically shared this Card.'
                  constraints:
                    referencedTableName: core_user
                    referencedColumnNames: id
                    foreignKeyName: fk_card_made_public_by_id
        - createIndex:
            tableName: report_card
            indexName: idx_card_public_uuid
            columns:
              column:
                name: public_uuid
        ######################################## Dashboard public_uuid & indices ########################################
        - addColumn:
            tableName: report_dashboard
            columns:
              - column:
                  name: public_uuid
                  type: char(36)
                  remarks: 'Unique UUID used to in publically-accessible links to this Dashboard.'
                  constraints:
                    unique: true
        - addColumn:
            tableName: report_dashboard
            columns:
              - column:
                  name: made_public_by_id
                  type: int
                  remarks: 'The ID of the User who first publically shared this Dashboard.'
                  constraints:
                    referencedTableName: core_user
                    referencedColumnNames: id
                    foreignKeyName: fk_dashboard_made_public_by_id
        - createIndex:
            tableName: report_dashboard
            indexName: idx_dashboard_public_uuid
            columns:
              column:
                name: public_uuid
        ######################################## make query_queryexecution.executor_id nullable ########################################
        - dropNotNullConstraint:
            tableName: query_queryexecution
            columnName: executor_id
            columnDataType: int
  - changeSet:
      id: 50
      author: camsaul
      validCheckSum: ANY
      changes:
        ######################################## new Card columns ########################################
        - addColumn:
            tableName: report_card
            columns:
              - column:
                  name: enable_embedding
                  type: boolean
                  remarks: 'Is this Card allowed to be embedded in different websites (using a signed JWT)?'
                  defaultValueBoolean: false
                  constraints:
                    nullable: false
        - addColumn:
            tableName: report_card
            columns:
              - column:
                  name: embedding_params
                  type: text
                  remarks: 'Serialized JSON containing information about required parameters that must be supplied when embedding this Card.'
          ######################################## new Card columns ########################################
        - addColumn:
            tableName: report_dashboard
            columns:
              - column:
                  name: enable_embedding
                  type: boolean
                  remarks: 'Is this Dashboard allowed to be embedded in different websites (using a signed JWT)?'
                  defaultValueBoolean: false
                  constraints:
                    nullable: false
        - addColumn:
            tableName: report_dashboard
            columns:
              - column:
                  name: embedding_params
                  type: text
                  remarks: 'Serialized JSON containing information about required parameters that must be supplied when embedding this Dashboard.'
  - changeSet:
      id: 51
      author: camsaul
      validCheckSum: ANY
      changes:
        - createTable:
            tableName: query_execution
            remarks: 'A log of executed queries, used for calculating historic execution times, auditing, and other purposes.'
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: hash
                  type: binary(32)
                  remarks: 'The hash of the query dictionary. This is a 256-bit SHA3 hash of the query.'
                  constraints:
                    nullable: false
              - column:
                  name: started_at
                  type: datetime
                  remarks: 'Timestamp of when this query started running.'
                  constraints:
                    nullable: false
              - column:
                  name: running_time
                  type: integer
                  remarks: 'The time, in milliseconds, this query took to complete.'
                  constraints:
                    nullable: false
              - column:
                  name: result_rows
                  type: integer
                  remarks: 'Number of rows in the query results.'
                  constraints:
                    nullable: false
              - column:
                  name: native
                  type: boolean
                  remarks: 'Whether the query was a native query, as opposed to an MBQL one (e.g., created with the GUI).'
                  constraints:
                    nullable: false
              - column:
                  name: context
                  type: varchar(32)
                  remarks: 'Short string specifying how this query was executed, e.g. in a Dashboard or Pulse.'
              - column:
                  name: error
                  type: text
                  remarks: 'Error message returned by failed query, if any.'
              # The following columns are foreign keys, but we don't keep FK constraints on them for a few reasons:
              # - We don't want to keep indexes on these columns since they wouldn't be generally useful and for size and performance reasons
              # - If a related object (e.g. a Dashboard) is deleted, we don't want to delete the related entries in the QueryExecution log.
              #   We could do something like make the constraint ON DELETE SET NULL, but that would require a full table scan to handle;
              #   If the QueryExecution log became tens of millions of rows large it would take a very long time to scan and update records
              - column:
                  name: executor_id
                  type: integer
                  remarks: 'The ID of the User who triggered this query execution, if any.'
              - column:
                  name: card_id
                  type: integer
                  remarks: 'The ID of the Card (Question) associated with this query execution, if any.'
              - column:
                  name: dashboard_id
                  type: integer
                  remarks: 'The ID of the Dashboard associated with this query execution, if any.'
              - column:
                  name: pulse_id
                  type: integer
                  remarks: 'The ID of the Pulse associated with this query execution, if any.'
        # For things like auditing recently executed queries
        - createIndex:
            tableName: query_execution
            indexName: idx_query_execution_started_at
            columns:
              column:
                name: started_at
        # For things like seeing the 10 most recent executions of a certain query
        - createIndex:
            tableName: query_execution
            indexName: idx_query_execution_query_hash_started_at
            columns:
              - column:
                  name: hash
              - column:
                  name: started_at
  - changeSet:
      id: 52
      author: camsaul
      changes:
        - createTable:
            tableName: query_cache
            remarks: 'Cached results of queries are stored here when using the DB-based query cache.'
            columns:
              - column:
                  name: query_hash
                  type: binary(32)
                  remarks: 'The hash of the query dictionary. (This is a 256-bit SHA3 hash of the query dict).'
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: updated_at
                  type: datetime
                  remarks: 'The timestamp of when these query results were last refreshed.'
                  constraints:
                    nullable: false
              - column:
                  name: results
                  type: ${blob.type}
                  remarks: 'Cached, compressed results of running the query with the given hash.'
                  constraints:
                    nullable: false
        - createIndex:
            tableName: query_cache
            indexName: idx_query_cache_updated_at
            columns:
              column:
                name: updated_at
        - addColumn:
            tableName: report_card
            columns:
              - column:
                  name: cache_ttl
                  type: int
                  remarks: 'The maximum time, in seconds, to return cached results for this Card rather than running a new query.'
  - changeSet:
      id: 53
      author: camsaul
      changes:
        - createTable:
            tableName: query
            remarks: 'Information (such as average execution time) for different queries that have been previously ran.'
            columns:
              - column:
                  name: query_hash
                  type: binary(32)
                  remarks: 'The hash of the query dictionary. (This is a 256-bit SHA3 hash of the query dict.)'
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: average_execution_time
                  type: int
                  remarks: 'Average execution time for the query, round to nearest number of milliseconds. This is updated as a rolling average.'
                  constraints:
                    nullable: false
  - changeSet:
      id: 54
      author: tlrobinson
      validCheckSum: ANY
      changes:
        - addColumn:
            tableName: pulse
            columns:
              - column:
                  name: skip_if_empty
                  type: boolean
                  remarks: 'Skip a scheduled Pulse if none of its questions have any results'
                  defaultValueBoolean: false
                  constraints:
                    nullable: false
  - changeSet:
      id: 55
      author: camsaul
      validCheckSum: ANY
      changes:
        - addColumn:
            tableName: report_dashboard
            columns:
              - column:
                  name: archived
                  type: boolean
                  remarks: 'Is this Dashboard archived (effectively treated as deleted?)'
                  defaultValueBoolean: false
                  constraints:
                    nullable: false
        - addColumn:
            tableName: report_dashboard
            columns:
              - column:
                  name: position
                  type: integer
                  remarks: 'The position this Dashboard should appear in the Dashboards list, lower-numbered positions appearing before higher numbered ones.'
        - createTable:
            tableName: dashboard_favorite
            remarks: 'Presence of a row here indicates a given User has favorited a given Dashboard.'
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: user_id
                  type: int
                  remarks: 'ID of the User who favorited the Dashboard.'
                  constraints:
                    nullable: false
                    referencedTableName: core_user
                    referencedColumnNames: id
                    foreignKeyName: fk_dashboard_favorite_user_id
                    deleteCascade: true
              - column:
                  name: dashboard_id
                  type: int
                  remarks: 'ID of the Dashboard favorited by the User.'
                  constraints:
                    nullable: false
                    referencedTableName: report_dashboard
                    referencedColumnNames: id
                    foreignKeyName: fk_dashboard_favorite_dashboard_id
                    deleteCascade: true
        - addUniqueConstraint:
            tableName: dashboard_favorite
            columnNames: user_id, dashboard_id
            constraintName: unique_dashboard_favorite_user_id_dashboard_id
        - createIndex:
            tableName: dashboard_favorite
            indexName: idx_dashboard_favorite_user_id
            columns:
              - column:
                  name: user_id
        - createIndex:
            tableName: dashboard_favorite
            indexName: idx_dashboard_favorite_dashboard_id
            columns:
              - column:
                  name: dashboard_id
  - changeSet:
      id: 56
      author: wwwiiilll
      comment: 'Added 0.25.0'
      changes:
        - addColumn:
            tableName: core_user
            columns:
              - column:
                  name: ldap_auth
                  type: boolean
                  defaultValueBoolean: false
                  constraints:
                    nullable: false
  - changeSet:
      id: 57
      author: camsaul
      comment: 'Added 0.25.0'
      changes:
        - addColumn:
            tableName: report_card
            columns:
              - column:
                  name: result_metadata
                  type: text
                  remarks: 'Serialized JSON containing metadata about the result columns from running the query.'
  - changeSet:
      id: 58
      author: senior
      validCheckSum: ANY
      comment: 'Added 0.25.0'
      changes:
        - createTable:
            tableName: dimension
            remarks: 'Stores references to alternate views of existing fields, such as remapping an integer to a description, like an enum'
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: field_id
                  type: int
                  remarks: 'ID of the field this dimension row applies to'
                  constraints:
                    deferrable: false
                    foreignKeyName: fk_dimension_ref_field_id
                    initiallyDeferred: false
                    nullable: false
                    referencedTableName: metabase_field
                    referencedColumnNames: id
                    deleteCascade: true
              - column:
                  name: name
                  type: VARCHAR(254)
                  remarks: 'Short description used as the display name of this new column'
                  constraints:
                    nullable: false
              - column:
                  name: type
                  type: varchar(254)
                  remarks: 'Either internal for a user defined remapping or external for a foreign key based remapping'
                  constraints:
                    nullable: false
              - column:
                  name: human_readable_field_id
                  type: int
                  remarks: 'Only used with external type remappings. Indicates which field on the FK related table to use for display'
                  constraints:
                    deferrable: false
                    foreignKeyName: fk_dimension_displayfk_ref_field_id
                    initiallyDeferred: false
                    nullable: true
                    referencedTableName: metabase_field
                    referencedColumnNames: id
                    deleteCascade: true
              - column:
                  name: created_at
                  type: DATETIME
                  remarks: 'The timestamp of when the dimension was created.'
                  constraints:
                    nullable: false
              - column:
                  name: updated_at
                  type: DATETIME
                  remarks: 'The timestamp of when these dimension was last updated.'
                  constraints:
                    nullable: false
        - addUniqueConstraint:
            tableName: dimension
            columnNames: field_id, name
            constraintName: unique_dimension_field_id_name
        - createIndex:
            tableName: dimension
            indexName: idx_dimension_field_id
            columns:
              - column:
                  name: field_id
  - changeSet:
      id: 59
      author: camsaul
      comment: 'Added 0.26.0'
      changes:
        - addColumn:
            tableName: metabase_field
            columns:
              - column:
                  name: fingerprint
                  type: text
                  remarks: 'Serialized JSON containing non-identifying information about this Field, such as min, max, and percent JSON. Used for classification.'
  - changeSet:
      id: 60
      author: camsaul
      validCheckSum: ANY
      comment: 'Added 0.26.0'
      changes:
        - addColumn:
            tableName: metabase_database
            columns:
              - column:
                  name: metadata_sync_schedule
                  type: varchar(254)
                  remarks: 'The cron schedule string for when this database should undergo the metadata sync process (and analysis for new fields).'
                  defaultValue: '0 50 * * * ? *' # run at the end of every hour
                  constraints:
                    nullable: false
        - addColumn:
            tableName: metabase_database
            columns:
              - column:
                  name: cache_field_values_schedule
                  type: varchar(254)
                  remarks: 'The cron schedule string for when FieldValues for eligible Fields should be updated.'
                  defaultValue: '0 50 0 * * ? *' # run at 12:50 AM
                  constraints:
                    nullable: false
  - changeSet:
      id: 61
      author: camsaul
      comment: 'Added 0.26.0'
      changes:
        - addColumn:
            tableName: metabase_field
            columns:
              - column:
                  name: fingerprint_version
                  type: int
                  remarks: 'The version of the fingerprint for this Field. Used so we can keep track of which Fields need to be analyzed again when new things are added to fingerprints.'
                  defaultValue: 0
                  constraints:
                    nullable: false
  - changeSet:
      id: 62
      author: senior
      comment: 'Added 0.26.0'
      changes:
        - addColumn:
            tableName: metabase_database
            columns:
              - column:
                  name: timezone
                  type: VARCHAR(254)
                  remarks: 'Timezone identifier for the database, set by the sync process'
  - changeSet:
      id: 63
      author: camsaul
      comment: 'Added 0.26.0'
      changes:
        - addColumn:
            tableName: metabase_database
            columns:
              - column:
                  name: is_on_demand
                  type: boolean
                  remarks: 'Whether we should do On-Demand caching of FieldValues for this DB. This means FieldValues are updated when their Field is used in a Dashboard or Card param.'
                  defaultValue: false
                  constraints:
                    nullable: false
  - changeSet:
      id: 64
      author: senior
      comment: 'Added 0.26.0'
      changes:
      - dropForeignKeyConstraint:
          baseTableName: raw_table
          constraintName: fk_rawtable_ref_database
          remarks: 'This FK prevents deleting databases even though RAW_TABLE is no longer used. The table is still around to support downgrades, but the FK reference is no longer needed.'
# Changeset 65 was accidentally released in 0.26.0.RC2. The changeset has been removed from the migrations list so that
# users that haven't ran the migration (i.e. they didn't run 0.26.0.RC2) won't waste time running it just to have it
# reversed. For 0.26.0.RC2 users, the below changeset will remove those tables if they are present
  - changeSet:
      id: 66
      author: senior
      comment: 'Added 0.26.0'
      validCheckSum: ANY
      changes:
        - sql:
            sql: drop table if exists computation_job_result cascade
        - sql:
            sql: drop table if exists computation_job cascade
# NOTE Atte Keinänen 9/28/17: This was originally in changeset 65 as explained above
  - changeSet:
      id: 67
      author: attekei
      validCheckSum: ANY
      comment: 'Added 0.27.0'
      changes:
        - createTable:
            tableName: computation_job
            remarks: 'Stores submitted async computation jobs.'
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  constraints:
                    deferrable: false
                    foreignKeyName: fk_computation_job_ref_user_id
                    initiallyDeferred: false
                    referencedTableName: core_user
                    referencedColumnNames: id
                  name: creator_id
                  type: int
              - column:
                  name: created_at
                  type: DATETIME
                  constraints:
                    nullable: false
              - column:
                  name: updated_at
                  type: DATETIME
                  constraints:
                    nullable: false
              - column:
                  name: type
                  type: varchar(254)
                  constraints:
                    nullable: false
              - column:
                  name: status
                  type: varchar(254)
                  constraints:
                    nullable: false
        - createTable:
            tableName: computation_job_result
            remarks: 'Stores results of async computation jobs.'
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  constraints:
                    deferrable: false
                    foreignKeyName: fk_computation_result_ref_job_id
                    initiallyDeferred: false
                    nullable: false
                    referencedTableName: computation_job
                    referencedColumnNames: id
                  name: job_id
                  type: int
              - column:
                  name: created_at
                  type: DATETIME
                  constraints:
                    nullable: false
              - column:
                  name: updated_at
                  type: DATETIME
                  constraints:
                    nullable: false
              - column:
                  name: permanence
                  type: varchar(254)
                  constraints:
                    nullable: false
              - column:
                  name: payload
                  type: text
                  constraints:
                    nullable: false
  - changeSet:
      id: 68
      author: sbelak
      comment: 'Added 0.27.0'
      validCheckSum: ANY
      changes:
        - addColumn:
            tableName: computation_job
            columns:
              - column:
                  name: context
                  type: text
        - addColumn:
            tableName: computation_job
            columns:
              - column:
                  name: ended_at
                  type: DATETIME
  - changeSet:
      id: 69
      author: senior
      validCheckSum: ANY
      comment: 'Added 0.27.0'
      remarks: 'Add columns to the pulse table for alerts'
      changes:
        - addColumn:
            tableName: pulse
            columns:
              - column:
                  name: alert_condition
                  type: varchar(254)
                  remarks: 'Condition (i.e. "rows" or "goal") used as a guard for alerts'
        - addColumn:
            tableName: pulse
            columns:
              - column:
                  name: alert_first_only
                  type: boolean
                  remarks: 'True if the alert should be disabled after the first notification'
        - addColumn:
            tableName: pulse
            columns:
              - column:
                  name: alert_above_goal
                  type: boolean
                  remarks: 'For a goal condition, alert when above the goal'
        # There is no name for an alert, so this column is only required for pulses
        - dropNotNullConstraint:
            tableName: pulse
            columnName: name
            columnDataType: varchar(254)
  - changeSet:
      id: 70
      author: camsaul
      comment: 'Added 0.28.0'
      changes:
        - addColumn:
            tableName: metabase_field
            columns:
              - column:
                  name: database_type
                  type: varchar(255)
                  remarks: 'The actual type of this column in the database. e.g. VARCHAR or TEXT.'
        # We want to enforce NOT NULL right away for all columns going forward so just put some sort of
        # placeholder in place for existing columns.
        - addNotNullConstraint:
            tableName: metabase_field
            columnName: database_type
            columnDataType: varchar(255)
            defaultNullValue: '?'
  - changeSet:
      id: 71
      author: camsaul
      comment: 'Added 0.28.0'
      changes:
        # drop the NOT NULL constraint on DashboardCard.card_id since we're now letting you add things other than Cards
        # to Dashboards, for example static text cards
        - dropNotNullConstraint:
            tableName: report_dashboardcard
            columnName: card_id
            columnDataType: int
  - changeSet:
      id: 72
      author: senior
      validCheckSum: ANY
      comment: 'Added 0.28.0'
      changes:
        - addColumn:
            tableName: pulse_card
            columns:
              - column:
                  name: include_csv
                  type: boolean
                  defaultValueBoolean: false
                  remarks: 'True if a CSV of the data should be included for this pulse card'
                  constraints:
                    nullable: false
        - addColumn:
            tableName: pulse_card
            columns:
              - column:
                  name: include_xls
                  type: boolean
                  defaultValueBoolean: false
                  remarks: 'True if a XLS of the data should be included for this pulse card'
                  constraints:
                    nullable: false
  - changeSet:
      id: 73
      author: camsaul
      comment: 'Added 0.29.0'
      changes:
        # add a new 'options' (serialized JSON) column to Database to store things like whether we should default to
        # making string searches case-insensitive
        - addColumn:
            tableName: metabase_database
            columns:
              - column:
                  name: options
                  type: text
                  remarks: 'Serialized JSON containing various options like QB behavior.'
  - changeSet:
      id: 74
      author: camsaul
      comment: 'Added 0.29.0'
      changes:
        - addColumn:
            tableName: metabase_field
            columns:
              - column:
                  name: has_field_values
                  type: text
                  remarks: 'Whether we have FieldValues ("list"), should ad-hoc search ("search"), disable entirely ("none"), or infer dynamically (null)"'
  - changeSet:
      id: 75
      author: camsaul
      comment: 'Added 0.28.2'
      changes:
        - addColumn:
            tableName: report_card
            columns:
              - column:
                  name: read_permissions
                  type: text
                  remarks: 'Permissions required to view this Card and run its query.'
  - changeSet:
      id: 76
      author: senior
      comment: 'Added 0.30.0'
      changes:
        - addColumn:
            tableName: metabase_table
            columns:
              - column:
                  name: fields_hash
                  type: text
                  remarks: 'Computed hash of all of the fields associated to this table'
  - changeSet:
      id: 77
      author: senior
      comment: 'Added 0.30.0'
      changes:
        - addColumn:
            tableName: core_user
            columns:
              - column:
                  name: login_attributes
                  type: text
                  remarks: 'JSON serialized map with attributes used for row level permissions'
  - changeSet:
      id: 78
      author: camsaul
      validCheckSum: ANY
      comment: 'Added 0.30.0'
      changes:
        - createTable:
            tableName: group_table_access_policy
            remarks: 'Records that a given Card (Question) should automatically replace a given Table as query source for a given a Perms Group.'
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: group_id
                  type: int
                  remarks: 'ID of the Permissions Group this policy affects.'
                  constraints:
                    nullable: false
                    referencedTableName: permissions_group
                    referencedColumnNames: id
                    foreignKeyName: fk_gtap_group_id
                    deleteCascade: true
              - column:
                  name: table_id
                  type: int
                  remarks: 'ID of the Table that should get automatically replaced as query source for the Permissions Group.'
                  constraints:
                    nullable: false
                    referencedTableName: metabase_table
                    referencedColumnNames: id
                    foreignKeyName: fk_gtap_table_id
                    deleteCascade: true
              - column:
                  name: card_id
                  type: int
                  remarks: 'ID of the Card (Question) to be used to replace the Table.'
                  constraints:
                    nullable: false
                    referencedTableName: report_card
                    referencedColumnNames: id
                    foreignKeyName: fk_gtap_card_id
              - column:
                  name: attribute_remappings
                  type: text
                  remarks: 'JSON-encoded map of user attribute identifier to the param name used in the Card.'
              # TODO - do we also want to include `created_at` and `updated_at` columns here? We can add them later if needed
        # Add an index on table_id + group_id since that is what the Query Processor is going to be looking up 99% of
        # the time in order to get the corresponding Card ID for query-rewriting purposes
        #
        # TODO - do we want indexes on any of the other FKs? Are we going to be looking up all the GTAPs for a given
        # Table or for a given Group with enough regularity we would want to put indexes on those columns?
        - createIndex:
            indexName: idx_gtap_table_id_group_id
            tableName: group_table_access_policy
            columns:
              - column:
                  name: table_id
              - column:
                  name: group_id
        # There should only ever be one GTAP entry for a give Group + Table combination.
        - addUniqueConstraint:
            tableName: group_table_access_policy
            columnNames: table_id, group_id
            constraintName: unique_gtap_table_id_group_id
  - changeSet:
      id: 79
      author: camsaul
      validCheckSum: ANY
      comment: 'Added 0.30.0'
      changes:
        - addColumn:
            tableName: report_dashboard
            columns:
              - column:
                  name: collection_id
                  type: int
                  remarks: 'Optional ID of Collection this Dashboard belongs to.'
                  constraints:
                    referencedTableName: collection
                    referencedColumnNames: id
                    foreignKeyName: fk_dashboard_collection_id
              # TODO - if someone deletes a collection, what should happen to the Dashboards that are in it? Should they
              # get deleted as well? Or should collection_id be cleared, effectively putting them in the so-called
              # "root" collection?
        - createIndex:
            tableName: report_dashboard
            indexName: idx_dashboard_collection_id
            columns:
              - column:
                  name: collection_id
        - addColumn:
            tableName: pulse
            columns:
              - column:
                  name: collection_id
                  type: int
                  remarks: 'Options ID of Collection this Pulse belongs to.'
                  constraints:
                    referencedTableName: collection
                    referencedColumnNames: id
                    foreignKeyName: fk_pulse_collection_id
        - createIndex:
            tableName: pulse
            indexName: idx_pulse_collection_id
            columns:
              - column:
                  name: collection_id
  - changeSet:
      id: 80
      author: camsaul
      changes:
        - addColumn:
            tableName: collection
            columns:
              - column:
                  name: location
                  type: varchar(254)
                  remarks: 'Directory-structure path of ancestor Collections. e.g. "/1/2/" means our Parent is Collection 2, and their parent is Collection 1.'
                  constraints:
                    nullable: false
                  defaultValue: "/"
        - createIndex:
            tableName: collection
            indexName: idx_collection_location
            columns:
              - column:
                  name: location
  - changeSet:
      id: 81
      author: camsaul
      comment: 'Added 0.30.0'
      changes:
        - addColumn:
            tableName: report_dashboard
            columns:
              - column:
                  name: collection_position
                  type: smallint
                  remarks: 'Optional pinned position for this item in its Collection. NULL means item is not pinned.'
        - addColumn:
            tableName: report_card
            columns:
              - column:
                  name: collection_position
                  type: smallint
                  remarks: 'Optional pinned position for this item in its Collection. NULL means item is not pinned.'
        - addColumn:
            tableName: pulse
            columns:
              - column:
                  name: collection_position
                  type: smallint
                  remarks: 'Optional pinned position for this item in its Collection. NULL means item is not pinned.'
  - changeSet:
      id: 82
      author: senior
      comment: 'Added 0.30.0'
      changes:
        - addColumn:
            tableName: core_user
            columns:
              - column:
                  name: updated_at
                  type: datetime
                  remarks: 'When was this User last updated?'
        - sql:
            sql: update core_user set updated_at=date_joined
# Remove the GTAP card_id constraint. When not included, will default to querying against the GTAP table_id.
  - changeSet:
      id: 83
      author: senior
      comment: 'Added 0.30.0'
      changes:
        - dropNotNullConstraint:
            tableName: group_table_access_policy
            columnName: card_id
            columnDataType: int
# Switch the logic for metric/segment archiving to be more consistent with other entities in the model.
# Similarly, add the archived flag to pulses which doesn't have one.
  - changeSet:
      id: 84
      author: senior
      comment: 'Added 0.30.0'
      changes:
        - renameColumn:
            tableName: metric
            columnDataType: boolean
            newColumnName: archived
            oldColumnName: is_active
        - addDefaultValue:
            tableName: metric
            columnDataType: boolean
            columnName: archived
            defaultValueBoolean: false
        - renameColumn:
            tableName: segment
            columnDataType: boolean
            newColumnName: archived
            oldColumnName: is_active
        - addDefaultValue:
            tableName: segment
            columnDataType: boolean
            columnName: archived
            defaultValueBoolean: false
        - addColumn:
            tableName: pulse
            columns:
              - column:
                  name: archived
                  type: boolean
                  remarks: 'Has this pulse been archived?'
                  defaultValueBoolean: false
        # Before this change, metrics/segments had opposite logic, rather than marking something as archived
        # it was marked as active. Since the column is now an archived column, flip the boolean value
        #
        # As you may have noticed, we're not flipping the value for Metric here. @senior originally intended to do so,
        # but the YAML was off slightly. We have corrected this issue at a later date -- see migration #100
        - sql:
            sql: update segment set archived = not(archived)
  # Personal Collections, and removing Collection's unique constraint and index on slug
  - changeSet:
      id: 85
      author: camsaul
      validCheckSum: ANY
      comment: 'Added 0.30.0'
      changes:
        - addColumn:
            tableName: collection
            columns:
              - column:
                  name: personal_owner_id
                  type: int
                  remarks: 'If set, this Collection is a personal Collection, for exclusive use of the User with this ID.'
                  constraints:
                    referencedTableName: core_user
                    referencedColumnNames: id
                    foreignKeyName: fk_collection_personal_owner_id
                    unique: true
                    uniqueConstraintName: unique_collection_personal_owner_id
                    deleteCascade: true
        # Needed so we can efficiently look up the Collection belonging to a User, and so we can efficiently enforce the
        # unique constraint
        - createIndex:
            tableName: collection
            indexName: idx_collection_personal_owner_id
            columns:
              - column:
                  name: personal_owner_id
        # We're no longer enforcing unique constraints on Collection slugs or using them directly in the URLs, so let's
        # go ahead and remove stuff related to that...
        #
        # It's easier to just copy the value of slug to a new column and drop the old one than to try to deduce what the
        # unique constraint is named locally across all of our different DBMSes
        # (For example see https://stackoverflow.com/questions/10008476/dropping-unique-constraint-for-column-in-h2)
        #
        # Here's the plan: add new column _slug; copy values of slug into _slug; remove slug; rename _slug to slug
        - addColumn:
            tableName: collection
            columns:
              - column:
                  name: _slug
                  type: varchar(254)
                  remarks: 'Sluggified version of the Collection name. Used only for display purposes in URL; not unique or indexed.'
        # I don't know of an easy way to copy existing values of slug to _slug with Liquibase as we create the column so
        # just have to do it this way instead
        - sql:
            sql: UPDATE collection SET _slug = slug
        - addNotNullConstraint:
            tableName: collection
            columnName: _slug
            columnDataType: varchar(254)
        - dropColumn:
            tableName: collection
            columnName: slug
        - renameColumn:
            tableName: collection
            oldColumnName: _slug
            newColumnName: slug
            columnDataType: varchar(254)
        # Let's try to make sure the comments on the name column of Collection actually reflect reality
        - sql:
            dbms: postgresql,h2
            sql: "COMMENT ON COLUMN collection.name IS 'The user-facing name of this Collection.'"
        - sql:
            dbms: mysql,mariadb
            sql: "ALTER TABLE `collection` CHANGE `name` `name` TEXT NOT NULL COMMENT 'The user-facing name of this Collection.'"

# In 0.30.0 we finally removed the long-deprecated native read permissions. Since they're no longer considered valid by
# our permissions code, remove any entries for them so they don't cause problems.
  - changeSet:
      id: 86
      author: camsaul
      comment: 'Added 0.30.0'
      changes:
        - sql:
            sql: DELETE FROM permissions WHERE object LIKE '%/native/read/'

# Time to finally get rid of the RawTable and RawColumn tables. Bye Felicia!
  - changeSet:
      id: 87
      author: camsaul
      comment: 'Added 0.30.0'
      changes:
        - dropTable:
            tableName: raw_column
        - dropTable:
            tableName: raw_table
  - changeSet:
      id: 88
      author: senior
      comment: 'Added 0.30.0'
      changes:
        - addColumn:
            tableName: core_user
            columns:
              - column:
                  name: saml_auth
                  type: boolean
                  defaultValueBoolean: false
                  constraints:
                    nullable: false
                  remarks: 'Boolean to indicate if this user is authenticated via SAML'

# The Quartz Task Scheduler can use a DB to 'cluster' tasks and make sure they are only ran by a single instance where
# using a multi-instance Metabase setup.

# Quartz identifiers are upper-case in MySQL and H2 but lower-case in PostgreSQL for reasons... so we'll have to
# define properties for EVERYTHING and use the correct identifiers

  - property: {name: quartz.blob_data.name,                         dbms: "postgresql",       value: blob_data}
  - property: {name: quartz.blob_data.name,                         dbms: "mysql,mariadb,h2", value: BLOB_DATA}
  - property: {name: quartz.bool_prop_1.name,                       dbms: "postgresql",       value: bool_prop_1}
  - property: {name: quartz.bool_prop_1.name,                       dbms: "mysql,mariadb,h2", value: BOOL_PROP_1}
  - property: {name: quartz.bool_prop_2.name,                       dbms: "postgresql",       value: bool_prop_2}
  - property: {name: quartz.bool_prop_2.name,                       dbms: "mysql,mariadb,h2", value: BOOL_PROP_2}
  - property: {name: quartz.calendar.name,                          dbms: "postgresql",       value: calendar}
  - property: {name: quartz.calendar.name,                          dbms: "mysql,mariadb,h2", value: CALENDAR}
  - property: {name: quartz.calendar_name.name,                     dbms: "postgresql",       value: calendar_name}
  - property: {name: quartz.calendar_name.name,                     dbms: "mysql,mariadb,h2", value: CALENDAR_NAME}
  - property: {name: quartz.checkin_interval.name,                  dbms: "postgresql",       value: checkin_interval}
  - property: {name: quartz.checkin_interval.name,                  dbms: "mysql,mariadb,h2", value: CHECKIN_INTERVAL}
  - property: {name: quartz.cron_expression.name,                   dbms: "postgresql",       value: cron_expression}
  - property: {name: quartz.cron_expression.name,                   dbms: "mysql,mariadb,h2", value: CRON_EXPRESSION}
  - property: {name: quartz.dec_prop_1.name,                        dbms: "postgresql",       value: dec_prop_1}
  - property: {name: quartz.dec_prop_1.name,                        dbms: "mysql,mariadb,h2", value: DEC_PROP_1}
  - property: {name: quartz.dec_prop_2.name,                        dbms: "postgresql",       value: dec_prop_2}
  - property: {name: quartz.dec_prop_2.name,                        dbms: "mysql,mariadb,h2", value: DEC_PROP_2}
  - property: {name: quartz.description.name,                       dbms: "postgresql",       value: description}
  - property: {name: quartz.description.name,                       dbms: "mysql,mariadb,h2", value: DESCRIPTION}
  - property: {name: quartz.end_time.name,                          dbms: "postgresql",       value: end_time}
  - property: {name: quartz.end_time.name,                          dbms: "mysql,mariadb,h2", value: END_TIME}
  - property: {name: quartz.entry_id.name,                          dbms: "postgresql",       value: entry_id}
  - property: {name: quartz.entry_id.name,                          dbms: "mysql,mariadb,h2", value: ENTRY_ID}
  - property: {name: quartz.fired_time.name,                        dbms: "postgresql",       value: fired_time}
  - property: {name: quartz.fired_time.name,                        dbms: "mysql,mariadb,h2", value: FIRED_TIME}
  - property: {name: quartz.fk_qrtz_blob_triggers_triggers.name,    dbms: "postgresql",       value: fk_qrtz_blob_triggers_triggers}
  - property: {name: quartz.fk_qrtz_blob_triggers_triggers.name,    dbms: "mysql,mariadb,h2", value: FK_QRTZ_BLOB_TRIGGERS_TRIGGERS}
  - property: {name: quartz.fk_qrtz_cron_triggers_triggers.name,    dbms: "postgresql",       value: fk_qrtz_cron_triggers_triggers}
  - property: {name: quartz.fk_qrtz_cron_triggers_triggers.name,    dbms: "mysql,mariadb,h2", value: FK_QRTZ_CRON_TRIGGERS_TRIGGERS}
  - property: {name: quartz.fk_qrtz_simple_triggers_triggers.name,  dbms: "postgresql",       value: fk_qrtz_simple_triggers_triggers}
  - property: {name: quartz.fk_qrtz_simple_triggers_triggers.name,  dbms: "mysql,mariadb,h2", value: FK_QRTZ_SIMPLE_TRIGGERS_TRIGGERS}
  - property: {name: quartz.fk_qrtz_simprop_triggers_triggers.name, dbms: "postgresql",       value: fk_qrtz_simprop_triggers_triggers}
  - property: {name: quartz.fk_qrtz_simprop_triggers_triggers.name, dbms: "mysql,mariadb,h2", value: FK_QRTZ_SIMPROP_TRIGGERS_TRIGGERS}
  - property: {name: quartz.fk_qrtz_triggers_job_details.name,      dbms: "postgresql",       value: fk_qrtz_triggers_job_details}
  - property: {name: quartz.fk_qrtz_triggers_job_details.name,      dbms: "mysql,mariadb,h2", value: FK_QRTZ_TRIGGERS_JOB_DETAILS}
  - property: {name: quartz.idx_qrtz_ft_inst_job_req_rcvry.name,    dbms: "postgresql",       value: idx_qrtz_ft_inst_job_req_rcvry}
  - property: {name: quartz.idx_qrtz_ft_inst_job_req_rcvry.name,    dbms: "mysql,mariadb,h2", value: IDX_QRTZ_FT_INST_JOB_REQ_RCVRY}
  - property: {name: quartz.idx_qrtz_ft_jg.name,                    dbms: "postgresql",       value: idx_qrtz_ft_jg}
  - property: {name: quartz.idx_qrtz_ft_jg.name,                    dbms: "mysql,mariadb,h2", value: IDX_QRTZ_FT_JG}
  - property: {name: quartz.idx_qrtz_ft_j_g.name,                   dbms: "postgresql",       value: idx_qrtz_ft_j_g}
  - property: {name: quartz.idx_qrtz_ft_j_g.name,                   dbms: "mysql,mariadb,h2", value: IDX_QRTZ_FT_J_G}
  - property: {name: quartz.idx_qrtz_ft_tg.name,                    dbms: "postgresql",       value: idx_qrtz_ft_tg}
  - property: {name: quartz.idx_qrtz_ft_tg.name,                    dbms: "mysql,mariadb,h2", value: IDX_QRTZ_FT_TG}
  - property: {name: quartz.idx_qrtz_ft_trig_inst_name.name,        dbms: "postgresql",       value: idx_qrtz_ft_trig_inst_name}
  - property: {name: quartz.idx_qrtz_ft_trig_inst_name.name,        dbms: "mysql,mariadb,h2", value: IDX_QRTZ_FT_TRIG_INST_NAME}
  - property: {name: quartz.idx_qrtz_ft_t_g.name,                   dbms: "postgresql",       value: idx_qrtz_ft_t_g}
  - property: {name: quartz.idx_qrtz_ft_t_g.name,                   dbms: "mysql,mariadb,h2", value: IDX_QRTZ_FT_T_G}
  - property: {name: quartz.idx_qrtz_j_grp.name,                    dbms: "postgresql",       value: idx_qrtz_j_grp}
  - property: {name: quartz.idx_qrtz_j_grp.name,                    dbms: "mysql,mariadb,h2", value: IDX_QRTZ_J_GRP}
  - property: {name: quartz.idx_qrtz_j_req_recovery.name,           dbms: "postgresql",       value: idx_qrtz_j_req_recovery}
  - property: {name: quartz.idx_qrtz_j_req_recovery.name,           dbms: "mysql,mariadb,h2", value: IDX_QRTZ_J_REQ_RECOVERY}
  - property: {name: quartz.idx_qrtz_t_c.name,                      dbms: "postgresql",       value: idx_qrtz_t_c}
  - property: {name: quartz.idx_qrtz_t_c.name,                      dbms: "mysql,mariadb,h2", value: IDX_QRTZ_T_C}
  - property: {name: quartz.idx_qrtz_t_g.name,                      dbms: "postgresql",       value: idx_qrtz_t_g}
  - property: {name: quartz.idx_qrtz_t_g.name,                      dbms: "mysql,mariadb,h2", value: IDX_QRTZ_T_G}
  - property: {name: quartz.idx_qrtz_t_j.name,                      dbms: "postgresql",       value: idx_qrtz_t_j}
  - property: {name: quartz.idx_qrtz_t_j.name,                      dbms: "mysql,mariadb,h2", value: IDX_QRTZ_T_J}
  - property: {name: quartz.idx_qrtz_t_jg.name,                     dbms: "postgresql",       value: idx_qrtz_t_jg}
  - property: {name: quartz.idx_qrtz_t_jg.name,                     dbms: "mysql,mariadb,h2", value: IDX_QRTZ_T_JG}
  - property: {name: quartz.idx_qrtz_t_next_fire_time.name,         dbms: "postgresql",       value: idx_qrtz_t_next_fire_time}
  - property: {name: quartz.idx_qrtz_t_next_fire_time.name,         dbms: "mysql,mariadb,h2", value: IDX_QRTZ_T_NEXT_FIRE_TIME}
  - property: {name: quartz.idx_qrtz_t_nft_misfire.name,            dbms: "postgresql",       value: idx_qrtz_t_nft_misfire}
  - property: {name: quartz.idx_qrtz_t_nft_misfire.name,            dbms: "mysql,mariadb,h2", value: IDX_QRTZ_T_NFT_MISFIRE}
  - property: {name: quartz.idx_qrtz_t_nft_st.name,                 dbms: "postgresql",       value: idx_qrtz_t_nft_st}
  - property: {name: quartz.idx_qrtz_t_nft_st.name,                 dbms: "mysql,mariadb,h2", value: IDX_QRTZ_T_NFT_ST}
  - property: {name: quartz.idx_qrtz_t_nft_st_misfire.name,         dbms: "postgresql",       value: idx_qrtz_t_nft_st_misfire}
  - property: {name: quartz.idx_qrtz_t_nft_st_misfire.name,         dbms: "mysql,mariadb,h2", value: IDX_QRTZ_T_NFT_ST_MISFIRE}
  - property: {name: quartz.idx_qrtz_t_nft_st_misfire_grp.name,     dbms: "postgresql",       value: idx_qrtz_t_nft_st_misfire_grp}
  - property: {name: quartz.idx_qrtz_t_nft_st_misfire_grp.name,     dbms: "mysql,mariadb,h2", value: IDX_QRTZ_T_NFT_ST_MISFIRE_GRP}
  - property: {name: quartz.idx_qrtz_t_n_g_state.name,              dbms: "postgresql",       value: idx_qrtz_t_n_g_state}
  - property: {name: quartz.idx_qrtz_t_n_g_state.name,              dbms: "mysql,mariadb,h2", value: IDX_QRTZ_T_N_G_STATE}
  - property: {name: quartz.idx_qrtz_t_n_state.name,                dbms: "postgresql",       value: idx_qrtz_t_n_state}
  - property: {name: quartz.idx_qrtz_t_n_state.name,                dbms: "mysql,mariadb,h2", value: IDX_QRTZ_T_N_STATE}
  - property: {name: quartz.idx_qrtz_t_state.name,                  dbms: "postgresql",       value: idx_qrtz_t_state}
  - property: {name: quartz.idx_qrtz_t_state.name,                  dbms: "mysql,mariadb,h2", value: IDX_QRTZ_T_STATE}
  - property: {name: quartz.instance_name.name,                     dbms: "postgresql",       value: instance_name}
  - property: {name: quartz.instance_name.name,                     dbms: "mysql,mariadb,h2", value: INSTANCE_NAME}
  - property: {name: quartz.int_prop_1.name,                        dbms: "postgresql",       value: int_prop_1}
  - property: {name: quartz.int_prop_1.name,                        dbms: "mysql,mariadb,h2", value: INT_PROP_1}
  - property: {name: quartz.int_prop_2.name,                        dbms: "postgresql",       value: int_prop_2}
  - property: {name: quartz.int_prop_2.name,                        dbms: "mysql,mariadb,h2", value: INT_PROP_2}
  - property: {name: quartz.is_durable.name,                        dbms: "postgresql",       value: is_durable}
  - property: {name: quartz.is_durable.name,                        dbms: "mysql,mariadb,h2", value: IS_DURABLE}
  - property: {name: quartz.is_nonconcurrent.name,                  dbms: "postgresql",       value: is_nonconcurrent}
  - property: {name: quartz.is_nonconcurrent.name,                  dbms: "mysql,mariadb,h2", value: IS_NONCONCURRENT}
  - property: {name: quartz.is_update_data.name,                    dbms: "postgresql",       value: is_update_data}
  - property: {name: quartz.is_update_data.name,                    dbms: "mysql,mariadb,h2", value: IS_UPDATE_DATA}
  - property: {name: quartz.job_class_name.name,                    dbms: "postgresql",       value: job_class_name}
  - property: {name: quartz.job_class_name.name,                    dbms: "mysql,mariadb,h2", value: JOB_CLASS_NAME}
  - property: {name: quartz.job_data.name,                          dbms: "postgresql",       value: job_data}
  - property: {name: quartz.job_data.name,                          dbms: "mysql,mariadb,h2", value: JOB_DATA}
  - property: {name: quartz.job_group.name,                         dbms: "postgresql",       value: job_group}
  - property: {name: quartz.job_group.name,                         dbms: "mysql,mariadb,h2", value: JOB_GROUP}
  - property: {name: quartz.job_name.name,                          dbms: "postgresql",       value: job_name}
  - property: {name: quartz.job_name.name,                          dbms: "mysql,mariadb,h2", value: JOB_NAME}
  - property: {name: quartz.last_checkin_time.name,                 dbms: "postgresql",       value: last_checkin_time}
  - property: {name: quartz.last_checkin_time.name,                 dbms: "mysql,mariadb,h2", value: LAST_CHECKIN_TIME}
  - property: {name: quartz.lock_name.name,                         dbms: "postgresql",       value: lock_name}
  - property: {name: quartz.lock_name.name,                         dbms: "mysql,mariadb,h2", value: LOCK_NAME}
  - property: {name: quartz.long_prop_1.name,                       dbms: "postgresql",       value: long_prop_1}
  - property: {name: quartz.long_prop_1.name,                       dbms: "mysql,mariadb,h2", value: LONG_PROP_1}
  - property: {name: quartz.long_prop_2.name,                       dbms: "postgresql",       value: long_prop_2}
  - property: {name: quartz.long_prop_2.name,                       dbms: "mysql,mariadb,h2", value: LONG_PROP_2}
  - property: {name: quartz.misfire_instr.name,                     dbms: "postgresql",       value: misfire_instr}
  - property: {name: quartz.misfire_instr.name,                     dbms: "mysql,mariadb,h2", value: MISFIRE_INSTR}
  - property: {name: quartz.next_fire_time.name,                    dbms: "postgresql",       value: next_fire_time}
  - property: {name: quartz.next_fire_time.name,                    dbms: "mysql,mariadb,h2", value: NEXT_FIRE_TIME}
  - property: {name: quartz.pk_qrtz_blob_triggers.name,             dbms: "postgresql",       value: pk_qrtz_blob_triggers}
  - property: {name: quartz.pk_qrtz_blob_triggers.name,             dbms: "mysql,mariadb,h2", value: PK_QRTZ_BLOB_TRIGGERS}
  - property: {name: quartz.pk_qrtz_calendars.name,                 dbms: "postgresql",       value: pk_qrtz_calendars}
  - property: {name: quartz.pk_qrtz_calendars.name,                 dbms: "mysql,mariadb,h2", value: PK_QRTZ_CALENDARS}
  - property: {name: quartz.pk_qrtz_cron_triggers.name,             dbms: "postgresql",       value: pk_qrtz_cron_triggers}
  - property: {name: quartz.pk_qrtz_cron_triggers.name,             dbms: "mysql,mariadb,h2", value: PK_QRTZ_CRON_TRIGGERS}
  - property: {name: quartz.pk_qrtz_fired_triggers.name,            dbms: "postgresql",       value: pk_qrtz_fired_triggers}
  - property: {name: quartz.pk_qrtz_fired_triggers.name,            dbms: "mysql,mariadb,h2", value: PK_QRTZ_FIRED_TRIGGERS}
  - property: {name: quartz.pk_qrtz_job_details.name,               dbms: "postgresql",       value: pk_qrtz_job_details}
  - property: {name: quartz.pk_qrtz_job_details.name,               dbms: "mysql,mariadb,h2", value: PK_QRTZ_JOB_DETAILS}
  - property: {name: quartz.pk_qrtz_locks.name,                     dbms: "postgresql",       value: pk_qrtz_locks}
  - property: {name: quartz.pk_qrtz_locks.name,                     dbms: "mysql,mariadb,h2", value: PK_QRTZ_LOCKS}
  - property: {name: quartz.pk_qrtz_scheduler_state.name,           dbms: "postgresql",       value: pk_qrtz_scheduler_state}
  - property: {name: quartz.pk_qrtz_scheduler_state.name,           dbms: "mysql,mariadb,h2", value: PK_QRTZ_SCHEDULER_STATE}
  - property: {name: quartz.pk_qrtz_simple_triggers.name,           dbms: "postgresql",       value: pk_qrtz_simple_triggers}
  - property: {name: quartz.pk_qrtz_simple_triggers.name,           dbms: "mysql,mariadb,h2", value: PK_QRTZ_SIMPLE_TRIGGERS}
  - property: {name: quartz.pk_qrtz_simprop_triggers.name,          dbms: "postgresql",       value: pk_qrtz_simprop_triggers}
  - property: {name: quartz.pk_qrtz_simprop_triggers.name,          dbms: "mysql,mariadb,h2", value: PK_QRTZ_SIMPROP_TRIGGERS}
  - property: {name: quartz.pk_qrtz_triggers.name,                  dbms: "postgresql",       value: pk_qrtz_triggers}
  - property: {name: quartz.pk_qrtz_triggers.name,                  dbms: "mysql,mariadb,h2", value: PK_QRTZ_TRIGGERS}
  - property: {name: quartz.pk_sched_name.name,                     dbms: "postgresql",       value: pk_sched_name}
  - property: {name: quartz.pk_sched_name.name,                     dbms: "mysql,mariadb,h2", value: PK_SCHED_NAME}
  - property: {name: quartz.prev_fire_time.name,                    dbms: "postgresql",       value: prev_fire_time}
  - property: {name: quartz.prev_fire_time.name,                    dbms: "mysql,mariadb,h2", value: PREV_FIRE_TIME}
  - property: {name: quartz.priority.name,                          dbms: "postgresql",       value: priority}
  - property: {name: quartz.priority.name,                          dbms: "mysql,mariadb,h2", value: PRIORITY}
  - property: {name: quartz.qrtz_blob_triggers.name,                dbms: "postgresql",       value: qrtz_blob_triggers}
  - property: {name: quartz.qrtz_blob_triggers.name,                dbms: "mysql,mariadb,h2", value: QRTZ_BLOB_TRIGGERS}
  - property: {name: quartz.qrtz_calendars.name,                    dbms: "postgresql",       value: qrtz_calendars}
  - property: {name: quartz.qrtz_calendars.name,                    dbms: "mysql,mariadb,h2", value: QRTZ_CALENDARS}
  - property: {name: quartz.qrtz_cron_triggers.name,                dbms: "postgresql",       value: qrtz_cron_triggers}
  - property: {name: quartz.qrtz_cron_triggers.name,                dbms: "mysql,mariadb,h2", value: QRTZ_CRON_TRIGGERS}
  - property: {name: quartz.qrtz_fired_triggers.name,               dbms: "postgresql",       value: qrtz_fired_triggers}
  - property: {name: quartz.qrtz_fired_triggers.name,               dbms: "mysql,mariadb,h2", value: QRTZ_FIRED_TRIGGERS}
  - property: {name: quartz.qrtz_job_details.name,                  dbms: "postgresql",       value: qrtz_job_details}
  - property: {name: quartz.qrtz_job_details.name,                  dbms: "mysql,mariadb,h2", value: QRTZ_JOB_DETAILS}
  - property: {name: quartz.qrtz_locks.name,                        dbms: "postgresql",       value: qrtz_locks}
  - property: {name: quartz.qrtz_locks.name,                        dbms: "mysql,mariadb,h2", value: QRTZ_LOCKS}
  - property: {name: quartz.qrtz_paused_trigger_grps.name,          dbms: "postgresql",       value: qrtz_paused_trigger_grps}
  - property: {name: quartz.qrtz_paused_trigger_grps.name,          dbms: "mysql,mariadb,h2", value: QRTZ_PAUSED_TRIGGER_GRPS}
  - property: {name: quartz.qrtz_scheduler_state.name,              dbms: "postgresql",       value: qrtz_scheduler_state}
  - property: {name: quartz.qrtz_scheduler_state.name,              dbms: "mysql,mariadb,h2", value: QRTZ_SCHEDULER_STATE}
  - property: {name: quartz.qrtz_simple_triggers.name,              dbms: "postgresql",       value: qrtz_simple_triggers}
  - property: {name: quartz.qrtz_simple_triggers.name,              dbms: "mysql,mariadb,h2", value: QRTZ_SIMPLE_TRIGGERS}
  - property: {name: quartz.qrtz_simprop_triggers.name,             dbms: "postgresql",       value: qrtz_simprop_triggers}
  - property: {name: quartz.qrtz_simprop_triggers.name,             dbms: "mysql,mariadb,h2", value: QRTZ_SIMPROP_TRIGGERS}
  - property: {name: quartz.qrtz_triggers.name,                     dbms: "postgresql",       value: qrtz_triggers}
  - property: {name: quartz.qrtz_triggers.name,                     dbms: "mysql,mariadb,h2", value: QRTZ_TRIGGERS}
  - property: {name: quartz.repeat_count.name,                      dbms: "postgresql",       value: repeat_count}
  - property: {name: quartz.repeat_count.name,                      dbms: "mysql,mariadb,h2", value: REPEAT_COUNT}
  - property: {name: quartz.repeat_interval.name,                   dbms: "postgresql",       value: repeat_interval}
  - property: {name: quartz.repeat_interval.name,                   dbms: "mysql,mariadb,h2", value: REPEAT_INTERVAL}
  - property: {name: quartz.requests_recovery.name,                 dbms: "postgresql",       value: requests_recovery}
  - property: {name: quartz.requests_recovery.name,                 dbms: "mysql,mariadb,h2", value: REQUESTS_RECOVERY}
  - property: {name: quartz.sched_name.name,                        dbms: "postgresql",       value: sched_name}
  - property: {name: quartz.sched_name.name,                        dbms: "mysql,mariadb,h2", value: SCHED_NAME}
  - property: {name: quartz.sched_time.name,                        dbms: "postgresql",       value: sched_time}
  - property: {name: quartz.sched_time.name,                        dbms: "mysql,mariadb,h2", value: SCHED_TIME}
  - property: {name: quartz.start_time.name,                        dbms: "postgresql",       value: start_time}
  - property: {name: quartz.start_time.name,                        dbms: "mysql,mariadb,h2", value: START_TIME}
  - property: {name: quartz.state.name,                             dbms: "postgresql",       value: state}
  - property: {name: quartz.state.name,                             dbms: "mysql,mariadb,h2", value: STATE}
  - property: {name: quartz.str_prop_1.name,                        dbms: "postgresql",       value: str_prop_1}
  - property: {name: quartz.str_prop_1.name,                        dbms: "mysql,mariadb,h2", value: STR_PROP_1}
  - property: {name: quartz.str_prop_2.name,                        dbms: "postgresql",       value: str_prop_2}
  - property: {name: quartz.str_prop_2.name,                        dbms: "mysql,mariadb,h2", value: STR_PROP_2}
  - property: {name: quartz.str_prop_3.name,                        dbms: "postgresql",       value: str_prop_3}
  - property: {name: quartz.str_prop_3.name,                        dbms: "mysql,mariadb,h2", value: STR_PROP_3}
  - property: {name: quartz.times_triggered.name,                   dbms: "postgresql",       value: times_triggered}
  - property: {name: quartz.times_triggered.name,                   dbms: "mysql,mariadb,h2", value: TIMES_TRIGGERED}
  - property: {name: quartz.time_zone_id.name,                      dbms: "postgresql",       value: time_zone_id}
  - property: {name: quartz.time_zone_id.name,                      dbms: "mysql,mariadb,h2", value: TIME_ZONE_ID}
  - property: {name: quartz.trigger_group.name,                     dbms: "postgresql",       value: trigger_group}
  - property: {name: quartz.trigger_group.name,                     dbms: "mysql,mariadb,h2", value: TRIGGER_GROUP}
  - property: {name: quartz.trigger_name.name,                      dbms: "postgresql",       value: trigger_name}
  - property: {name: quartz.trigger_name.name,                      dbms: "mysql,mariadb,h2", value: TRIGGER_NAME}
  - property: {name: quartz.trigger_state.name,                     dbms: "postgresql",       value: trigger_state}
  - property: {name: quartz.trigger_state.name,                     dbms: "mysql,mariadb,h2", value: TRIGGER_STATE}
  - property: {name: quartz.trigger_type.name,                      dbms: "postgresql",       value: trigger_type}
  - property: {name: quartz.trigger_type.name,                      dbms: "mysql,mariadb,h2", value: TRIGGER_TYPE}

  - changeSet:
      id: 89
      author: camsaul
      comment: Added 0.30.0
      validCheckSum: ANY
      changes:
        - createTable:
            tableName: ${quartz.qrtz_job_details.name}
            remarks: Used for Quartz scheduler.
            columns:
              - column:
                  name: ${quartz.sched_name.name}
                  type: varchar(120)
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.job_name.name}
                  type: varchar(200)
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.job_group.name}
                  type: varchar(200)
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.description.name}
                  type: varchar(250)
              - column:
                  name: ${quartz.job_class_name.name}
                  type: varchar(250)
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.is_durable.name}
                  type: bool
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.is_nonconcurrent.name}
                  type: bool
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.is_update_data.name}
                  type: bool
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.requests_recovery.name}
                  type: bool
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.job_data.name}
                  type: ${blob.type}
        - addPrimaryKey:
            tableName: ${quartz.qrtz_job_details.name}
            columnNames: ${quartz.sched_name.name}, ${quartz.job_name.name}, ${quartz.job_group.name}
            constraintName: ${quartz.pk_qrtz_job_details.name}
        - createTable:
            tableName: ${quartz.qrtz_triggers.name}
            remarks: Used for Quartz scheduler.
            columns:
              - column:
                  name: ${quartz.sched_name.name}
                  type: varchar(120)
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.trigger_name.name}
                  type: varchar(200)
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.trigger_group.name}
                  type: varchar(200)
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.job_name.name}
                  type: varchar(200)
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.job_group.name}
                  type: varchar(200)
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.description.name}
                  type: varchar(250)
              - column:
                  name: ${quartz.next_fire_time.name}
                  type: bigint
              - column:
                  name: ${quartz.prev_fire_time.name}
                  type: bigint
              - column:
                  name: ${quartz.priority.name}
                  type: integer
              - column:
                  name: ${quartz.trigger_state.name}
                  type: varchar(16)
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.trigger_type.name}
                  type: varchar(8)
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.start_time.name}
                  type: bigint
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.end_time.name}
                  type: bigint
              - column:
                  name: ${quartz.calendar_name.name}
                  type: varchar(200)
              - column:
                  name: ${quartz.misfire_instr.name}
                  type: smallint
              - column:
                  name: ${quartz.job_data.name}
                  type: ${blob.type}
        - addPrimaryKey:
            tableName: ${quartz.qrtz_triggers.name}
            columnNames: ${quartz.sched_name.name}, ${quartz.trigger_name.name}, ${quartz.trigger_group.name}
            constraintName: ${quartz.pk_qrtz_triggers.name}
        - addForeignKeyConstraint:
            baseTableName: ${quartz.qrtz_triggers.name}
            baseColumnNames: ${quartz.sched_name.name}, ${quartz.job_name.name}, ${quartz.job_group.name}
            referencedTableName: ${quartz.qrtz_job_details.name}
            referencedColumnNames: ${quartz.sched_name.name}, ${quartz.job_name.name}, ${quartz.job_group.name}
            constraintName: ${quartz.fk_qrtz_triggers_job_details.name}
        - createTable:
            tableName: ${quartz.qrtz_simple_triggers.name}
            remarks: Used for Quartz scheduler.
            columns:
              - column:
                  name: ${quartz.sched_name.name}
                  type: varchar(120)
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.trigger_name.name}
                  type: varchar(200)
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.trigger_group.name}
                  type: varchar(200)
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.repeat_count.name}
                  type: bigint
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.repeat_interval.name}
                  type: bigint
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.times_triggered.name}
                  type: bigint
                  constraints:
                    nullable: false
        - addPrimaryKey:
            tableName: ${quartz.qrtz_simple_triggers.name}
            columnNames: ${quartz.sched_name.name}, ${quartz.trigger_name.name}, ${quartz.trigger_group.name}
            constraintName: ${quartz.pk_qrtz_simple_triggers.name}
        - addForeignKeyConstraint:
            baseTableName: ${quartz.qrtz_simple_triggers.name}
            baseColumnNames: ${quartz.sched_name.name}, ${quartz.trigger_name.name}, ${quartz.trigger_group.name}
            referencedTableName: ${quartz.qrtz_triggers.name}
            referencedColumnNames: ${quartz.sched_name.name}, ${quartz.trigger_name.name}, ${quartz.trigger_group.name}
            constraintName: ${quartz.fk_qrtz_simple_triggers_triggers.name}
        - createTable:
            tableName: ${quartz.qrtz_cron_triggers.name}
            remarks: Used for Quartz scheduler.
            columns:
              - column:
                  name: ${quartz.sched_name.name}
                  type: varchar(120)
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.trigger_name.name}
                  type: varchar(200)
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.trigger_group.name}
                  type: varchar(200)
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.cron_expression.name}
                  type: varchar(120)
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.time_zone_id.name}
                  type: varchar(80)
        - addPrimaryKey:
            tableName: ${quartz.qrtz_cron_triggers.name}
            columnNames: ${quartz.sched_name.name}, ${quartz.trigger_name.name}, ${quartz.trigger_group.name}
            constraintName: ${quartz.pk_qrtz_cron_triggers.name}
        - addForeignKeyConstraint:
            baseTableName: ${quartz.qrtz_cron_triggers.name}
            baseColumnNames: ${quartz.sched_name.name}, ${quartz.trigger_name.name}, ${quartz.trigger_group.name}
            referencedTableName: ${quartz.qrtz_triggers.name}
            referencedColumnNames: ${quartz.sched_name.name}, ${quartz.trigger_name.name}, ${quartz.trigger_group.name}
            constraintName: ${quartz.fk_qrtz_cron_triggers_triggers.name}
        - createTable:
            tableName: ${quartz.qrtz_simprop_triggers.name}
            remarks: Used for Quartz scheduler.
            columns:
              - column:
                  name: ${quartz.sched_name.name}
                  type: varchar(120)
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.trigger_name.name}
                  type: varchar(200)
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.trigger_group.name}
                  type: varchar(200)
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.str_prop_1.name}
                  type: varchar(512)
              - column:
                  name: ${quartz.str_prop_2.name}
                  type: varchar(512)
              - column:
                  name: ${quartz.str_prop_3.name}
                  type: varchar(512)
              - column:
                  name: ${quartz.int_prop_1.name}
                  type: int
              - column:
                  name: ${quartz.int_prop_2.name}
                  type: int
              - column:
                  name: ${quartz.long_prop_1.name}
                  type: bigint
              - column:
                  name: ${quartz.long_prop_2.name}
                  type: bigint
              - column:
                  name: ${quartz.dec_prop_1.name}
                  type: numeric(13,4)
              - column:
                  name: ${quartz.dec_prop_2.name}
                  type: numeric(13,4)
              - column:
                  name: ${quartz.bool_prop_1.name}
                  type: bool
              - column:
                  name: ${quartz.bool_prop_2.name}
                  type: bool
        - addPrimaryKey:
            tableName: ${quartz.qrtz_simprop_triggers.name}
            columnNames: ${quartz.sched_name.name}, ${quartz.trigger_name.name}, ${quartz.trigger_group.name}
            constraintName: ${quartz.pk_qrtz_simprop_triggers.name}
        - addForeignKeyConstraint:
            baseTableName: ${quartz.qrtz_simprop_triggers.name}
            baseColumnNames: ${quartz.sched_name.name}, ${quartz.trigger_name.name}, ${quartz.trigger_group.name}
            referencedTableName: ${quartz.qrtz_triggers.name}
            referencedColumnNames: ${quartz.sched_name.name}, ${quartz.trigger_name.name}, ${quartz.trigger_group.name}
            constraintName: ${quartz.fk_qrtz_simprop_triggers_triggers.name}
        - createTable:
            tableName: ${quartz.qrtz_blob_triggers.name}
            remarks: Used for Quartz scheduler.
            columns:
              - column:
                  name: ${quartz.sched_name.name}
                  type: varchar(120)
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.trigger_name.name}
                  type: varchar(200)
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.trigger_group.name}
                  type: varchar(200)
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.blob_data.name}
                  type: ${blob.type}
        - addPrimaryKey:
            tableName: ${quartz.qrtz_blob_triggers.name}
            columnNames: ${quartz.sched_name.name}, ${quartz.trigger_name.name}, ${quartz.trigger_group.name}
            constraintName: ${quartz.pk_qrtz_blob_triggers.name}
        - addForeignKeyConstraint:
            baseTableName: ${quartz.qrtz_blob_triggers.name}
            baseColumnNames: ${quartz.sched_name.name}, ${quartz.trigger_name.name}, ${quartz.trigger_group.name}
            referencedTableName: ${quartz.qrtz_triggers.name}
            referencedColumnNames: ${quartz.sched_name.name}, ${quartz.trigger_name.name}, ${quartz.trigger_group.name}
            constraintName: ${quartz.fk_qrtz_blob_triggers_triggers.name}
        - createTable:
            tableName: ${quartz.qrtz_calendars.name}
            remarks: Used for Quartz scheduler.
            columns:
              - column:
                  name: ${quartz.sched_name.name}
                  type: varchar(120)
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.calendar_name.name}
                  type: varchar(200)
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.calendar.name}
                  type: ${blob.type}
                  constraints:
                    nullable: false
        - addPrimaryKey:
            tableName: ${quartz.qrtz_calendars.name}
            columnNames: ${quartz.sched_name.name}, ${quartz.calendar_name.name}
            constraintName: ${quartz.pk_qrtz_calendars.name}
        - createTable:
            tableName: ${quartz.qrtz_paused_trigger_grps.name}
            remarks: Used for Quartz scheduler.
            columns:
              - column:
                  name: ${quartz.sched_name.name}
                  type: varchar(120)
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.trigger_group.name}
                  type: varchar(200)
                  constraints:
                    nullable: false
        - addPrimaryKey:
            tableName: ${quartz.qrtz_paused_trigger_grps.name}
            columnNames: ${quartz.sched_name.name}, ${quartz.trigger_group.name}
            constraintName: ${quartz.pk_sched_name.name}
        - createTable:
            tableName: ${quartz.qrtz_fired_triggers.name}
            remarks: Used for Quartz scheduler.
            columns:
              - column:
                  name: ${quartz.sched_name.name}
                  type: varchar(120)
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.entry_id.name}
                  type: varchar(95)
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.trigger_name.name}
                  type: varchar(200)
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.trigger_group.name}
                  type: varchar(200)
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.instance_name.name}
                  type: varchar(200)
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.fired_time.name}
                  type: bigint
                  constraints:
                    nullable: false
# Note: this column is not used on Quartz 2.1.x; it is used in 2.2.x, which recommends making it NOT NULL. I've made it
# nullable since at the time of this migration we're still using 2.1.7; including it gives us an easy upgrade path in
# the future.
              - column:
                  name: ${quartz.sched_time.name}
                  type: bigint
              - column:
                  name: ${quartz.priority.name}
                  type: integer
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.state.name}
                  type: varchar(16)
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.job_name.name}
                  type: varchar(200)
              - column:
                  name: ${quartz.job_group.name}
                  type: varchar(200)
              - column:
                  name: ${quartz.is_nonconcurrent.name}
                  type: bool
              - column:
                  name: ${quartz.requests_recovery.name}
                  type: bool
        - addPrimaryKey:
            tableName: ${quartz.qrtz_fired_triggers.name}
            columnNames: ${quartz.sched_name.name}, ${quartz.entry_id.name}
            constraintName: ${quartz.pk_qrtz_fired_triggers.name}
        - createTable:
            tableName: ${quartz.qrtz_scheduler_state.name}
            remarks: Used for Quartz scheduler.
            columns:
              - column:
                  name: ${quartz.sched_name.name}
                  type: varchar(120)
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.instance_name.name}
                  type: varchar(200)
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.last_checkin_time.name}
                  type: bigint
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.checkin_interval.name}
                  type: bigint
                  constraints:
                    nullable: false
        - addPrimaryKey:
            tableName: ${quartz.qrtz_scheduler_state.name}
            columnNames: ${quartz.sched_name.name}, ${quartz.instance_name.name}
            constraintName: ${quartz.pk_qrtz_scheduler_state.name}
        - createTable:
            tableName: ${quartz.qrtz_locks.name}
            remarks: Used for Quartz scheduler.
            columns:
              - column:
                  name: ${quartz.sched_name.name}
                  type: varchar(120)
                  constraints:
                    nullable: false
              - column:
                  name: ${quartz.lock_name.name}
                  type: varchar(40)
                  constraints:
                    nullable: false
        - addPrimaryKey:
            tableName: ${quartz.qrtz_locks.name}
            columnNames: ${quartz.sched_name.name}, ${quartz.lock_name.name}
            constraintName: ${quartz.pk_qrtz_locks.name}
        - createIndex:
            indexName: ${quartz.idx_qrtz_j_req_recovery.name}
            tableName: ${quartz.qrtz_job_details.name}
            columns:
              - column:
                  name: ${quartz.sched_name.name}
              - column:
                  name: ${quartz.requests_recovery.name}
        - createIndex:
            indexName: ${quartz.idx_qrtz_j_grp.name}
            tableName: ${quartz.qrtz_job_details.name}
            columns:
              - column:
                  name: ${quartz.sched_name.name}
              - column:
                  name: ${quartz.job_group.name}
        - createIndex:
            indexName: ${quartz.idx_qrtz_t_j.name}
            tableName: ${quartz.qrtz_triggers.name}
            columns:
              - column:
                  name: ${quartz.sched_name.name}
              - column:
                  name: ${quartz.job_name.name}
              - column:
                  name: ${quartz.job_group.name}
        - createIndex:
            indexName: ${quartz.idx_qrtz_t_jg.name}
            tableName: ${quartz.qrtz_triggers.name}
            columns:
              - column:
                  name: ${quartz.sched_name.name}
              - column:
                  name: ${quartz.job_group.name}
        - createIndex:
            indexName: ${quartz.idx_qrtz_t_c.name}
            tableName: ${quartz.qrtz_triggers.name}
            columns:
              - column:
                  name: ${quartz.sched_name.name}
              - column:
                  name: ${quartz.calendar_name.name}
        - createIndex:
            indexName: ${quartz.idx_qrtz_t_g.name}
            tableName: ${quartz.qrtz_triggers.name}
            columns:
              - column:
                  name: ${quartz.sched_name.name}
              - column:
                  name: ${quartz.trigger_group.name}
        - createIndex:
            indexName: ${quartz.idx_qrtz_t_state.name}
            tableName: ${quartz.qrtz_triggers.name}
            columns:
              - column:
                  name: ${quartz.sched_name.name}
              - column:
                  name: ${quartz.trigger_state.name}
        - createIndex:
            indexName: ${quartz.idx_qrtz_t_n_state.name}
            tableName: ${quartz.qrtz_triggers.name}
            columns:
              - column:
                  name: ${quartz.sched_name.name}
              - column:
                  name: ${quartz.trigger_name.name}
              - column:
                  name: ${quartz.trigger_group.name}
              - column:
                  name: ${quartz.trigger_state.name}
        - createIndex:
            indexName: ${quartz.idx_qrtz_t_n_g_state.name}
            tableName: ${quartz.qrtz_triggers.name}
            columns:
              - column:
                  name: ${quartz.sched_name.name}
              - column:
                  name: ${quartz.trigger_group.name}
              - column:
                  name: ${quartz.trigger_state.name}
        - createIndex:
            indexName: ${quartz.idx_qrtz_t_next_fire_time.name}
            tableName: ${quartz.qrtz_triggers.name}
            columns:
              - column:
                  name: ${quartz.sched_name.name}
              - column:
                  name: ${quartz.next_fire_time.name}
        - createIndex:
            indexName: ${quartz.idx_qrtz_t_nft_st.name}
            tableName: ${quartz.qrtz_triggers.name}
            columns:
              - column:
                  name: ${quartz.sched_name.name}
              - column:
                  name: ${quartz.trigger_state.name}
              - column:
                  name: ${quartz.next_fire_time.name}
        - createIndex:
            indexName: ${quartz.idx_qrtz_t_nft_misfire.name}
            tableName: ${quartz.qrtz_triggers.name}
            columns:
              - column:
                  name: ${quartz.sched_name.name}
              - column:
                  name: ${quartz.misfire_instr.name}
              - column:
                  name: ${quartz.next_fire_time.name}
        - createIndex:
            indexName: ${quartz.idx_qrtz_t_nft_st_misfire.name}
            tableName: ${quartz.qrtz_triggers.name}
            columns:
              - column:
                  name: ${quartz.sched_name.name}
              - column:
                  name: ${quartz.misfire_instr.name}
              - column:
                  name: ${quartz.next_fire_time.name}
              - column:
                  name: ${quartz.trigger_state.name}
        - createIndex:
            indexName: ${quartz.idx_qrtz_t_nft_st_misfire_grp.name}
            tableName: ${quartz.qrtz_triggers.name}
            columns:
              - column:
                  name: ${quartz.sched_name.name}
              - column:
                  name: ${quartz.misfire_instr.name}
              - column:
                  name: ${quartz.next_fire_time.name}
              - column:
                  name: ${quartz.trigger_group.name}
              - column:
                  name: ${quartz.trigger_state.name}
        - createIndex:
            indexName: ${quartz.idx_qrtz_ft_trig_inst_name.name}
            tableName: ${quartz.qrtz_fired_triggers.name}
            columns:
              - column:
                  name: ${quartz.sched_name.name}
              - column:
                  name: ${quartz.instance_name.name}
        - createIndex:
            indexName: ${quartz.idx_qrtz_ft_inst_job_req_rcvry.name}
            tableName: ${quartz.qrtz_fired_triggers.name}
            columns:
              - column:
                  name: ${quartz.sched_name.name}
              - column:
                  name: ${quartz.instance_name.name}
              - column:
                  name: ${quartz.requests_recovery.name}
        - createIndex:
            indexName: ${quartz.idx_qrtz_ft_j_g.name}
            tableName: ${quartz.qrtz_fired_triggers.name}
            columns:
              - column:
                  name: ${quartz.sched_name.name}
              - column:
                  name: ${quartz.job_name.name}
              - column:
                  name: ${quartz.job_group.name}
        - createIndex:
            indexName: ${quartz.idx_qrtz_ft_jg.name}
            tableName: ${quartz.qrtz_fired_triggers.name}
            columns:
              - column:
                  name: ${quartz.sched_name.name}
              - column:
                  name: ${quartz.job_group.name}
        - createIndex:
            indexName: ${quartz.idx_qrtz_ft_t_g.name}
            tableName: ${quartz.qrtz_fired_triggers.name}
            columns:
              - column:
                  name: ${quartz.sched_name.name}
              - column:
                  name: ${quartz.trigger_name.name}
              - column:
                  name: ${quartz.trigger_group.name}
        - createIndex:
            indexName: ${quartz.idx_qrtz_ft_tg.name}
            tableName: ${quartz.qrtz_fired_triggers.name}
            columns:
              - column:
                  name: ${quartz.sched_name.name}
              - column:
                  name: ${quartz.trigger_group.name}

  - changeSet:
      id: 90
      author: senior
      comment: 'Added 0.30.0'
      changes:
        - addColumn:
            tableName: core_user
            columns:
              - column:
                  name: sso_source
                  type: varchar(254)
                  remarks: 'String to indicate the SSO backend the user is from'
        - sql:
            sql: update core_user set sso_source='saml' where saml_auth=true
        - dropColumn:
            tableName: core_user
            columnName: saml_auth

# Forgot to get rid of the raw_table_id and raw_column_id columns when we dropped the tables they referenced in migration 87.

  - changeSet:
      id: 91
      author: camsaul
      comment: 'Added 0.30.0'
      changes:
        - dropColumn:
            tableName: metabase_table
            columnName: raw_table_id
        - dropColumn:
            tableName: metabase_field
            columnName: raw_column_id

# Add database_id column to query_execution

  - changeSet:
      id: 92
      author: camsaul
      comment: 'Added 0.31.0'
      validCheckSum: ANY
      changes:
        - addColumn:
            tableName: query_execution
            columns:
              - column:
                  name: database_id
                  type: integer
                  remarks: 'ID of the database this query was ran against.'

# Start recording the actual query dictionary that's been executed

  - changeSet:
      id: 93
      author: camsaul
      comment: 'Added 0.31.0'
      changes:
        - addColumn:
            tableName: query
            columns:
              - column:
                  name: query
                  type: text
                  remarks: 'The actual "query dictionary" for this query.'

# Create the TaskHistory table, intended to provide debugging info on our background/quartz processes
  - changeSet:
      id: 94
      author: senior
      comment: 'Added 0.31.0'
      changes:
        - createTable:
            tableName: task_history
            remarks: 'Timing and metadata info about background/quartz processes'
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: task
                  type: VARCHAR(254)
                  remarks: 'Name of the task'
                  constraints:
                    nullable: false
              # The sync tasks all have a db_id, but there are others that won't, such as the pulses
              # task or task history cleanup. The way around this is to create a join table between
              # TASK_HISTORY and METABASE_DATABASE, but that doesn't seem worth it right now.
              - column:
                  name: db_id
                  type: integer
              - column:
                  name: started_at
                  type: datetime
                  constraints:
                    nullable: false
              - column:
                  name: ended_at
                  type: datetime
                  constraints:
                    nullable: false
              - column:
                  name: duration
                  type: int
                  constraints:
                    nullable: false
              - column:
                  name: task_details
                  remarks: 'JSON string with additional info on the task'
                  type: text
        - createIndex:
            indexName: idx_task_history_end_time
            tableName: task_history
            columns:
              - column:
                  name: ended_at
        - createIndex:
            indexName: idx_task_history_db_id
            tableName: task_history
            columns:
              - column:
                  name: db_id
# Before this changeset, the databasechangelog table didn't include any uniqueness constraing for the databasechangelog
# table. Not having anything that uniquely identifies a row can cause issues for database replication. In earlier
# versions of Liquibase the uniquenes constraint was (ID, AUTHOR, FILENAME) but that was dropped
# (https://liquibase.jira.com/browse/CORE-1909) as some as the combination of the three columns caused issues on some
# databases. We only support PostgreSQL, MySQL and H2 which doesn't have that issue. This changeset puts back that
# uniqueness constraint since the issue shouldn't affect us and it will allow replication without the user needed to
# add their own constraint.
  - changeSet:
      id: 95
      author: senior
      comment: 'Added 0.31.0'
      validCheckSum: ANY
      # Don't add the constraint if there are already duplicates in the database change log! Migrations will fail!
      # See #8909
      preConditions:
        - onFail: MARK_RAN
        # If we're dumping the migration as a SQL file or trying to force-migrate we can't check the preconditions
        # so just go ahead and skip the entire thing. This is a non-critical migration
        - onUpdateSQL: IGNORE
        - sqlCheck:
            expectedResult: 0
            sql: SELECT count(*) FROM (SELECT count(*) FROM DATABASECHANGELOG GROUP BY ID, AUTHOR, FILENAME HAVING count(*) > 1) t1
      changes:
        - addUniqueConstraint:
            columnNames: id, author, filename
            constraintName: idx_databasechangelog_id_author_filename
            tableName: ${databasechangelog.name}
#
# ADD Field.settings COLUMN
#
  - changeSet:
      id: 96
      author: camsaul
      comment: 'Added 0.31.0'
      changes:
        - addColumn:
            tableName: metabase_field
            columns:
              - column:
                  name: settings
                  type: text
                  remarks: 'Serialized JSON FE-specific settings like formatting, etc. Scope of what is stored here may increase in future.'
#
# Change MySQL/Maria's blob type to LONGBLOB to more closely match what H2 and PostgreSQL support for size limits
#
  - changeSet:
      id: 97
      author: senior
      comment: 'Added 0.32.0'
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb
      changes:
        - modifyDataType:
            tableName: query_cache
            columnName: results
            newDataType: longblob

#
# Add unique constraints for (Field name + table_id + parent_id) and for (Table name + schema + db_id) unless for one
# reason or another those would-be constraints are already violated. This is to fix issue where sometimes the same Field
# or Table is synced more than once (see #669, #8950, #9048)
#
# Note that the SQL standard says unique constraints should not apply to columns with NULL values. Consider the following:
#
# INSERT INTO metabase_table (db_id, schema, name) VALUES (1, 'PUBLIC', 'my_table');
# INSERT INTO metabase_table (db_id, schema, name) VALUES (1, 'PUBLIC', 'my_table'); -- fails: violates UNIQUE constraint
#
# INSERT INTO metabase_table (db_id, schema, name) VALUES (1, NULL, 'my_table');
# INSERT INTO metabase_table (db_id, schema, name) VALUES (1, NULL, 'my_table'); -- succeeds: because schema is NULL constraint does not apply
#
# Thus these constraints won't work if the data warehouse DB in question doesn't use schemas (e.g. MySQL or MongoDB). It
# will work for other data warehouse types.
#
# Luckily Postgres (but not H2 or MySQL) supports constraints that only apply to columns matching conditions, so we can
# add additional constraints to properly handle those cases.
  - changeSet:
      id: 98
      author: camsaul
      comment: 'Added 0.32.0'
      preConditions:
        - onFail: MARK_RAN
        - onUpdateSQL: IGNORE
        - or:
            - and:
                - dbms:
                    type: mysql,mariadb
                - sqlCheck:
                    expectedResult: 0
                    sql: SELECT count(*) FROM (SELECT count(*) FROM `metabase_table` GROUP BY `db_id`, `schema`, `name` HAVING count(*) > 1) t1
            - and:
                - dbms:
                    type: h2,postgresql
                - sqlCheck:
                    expectedResult: 0
                    sql: SELECT count(*) FROM (SELECT count(*) FROM METABASE_TABLE GROUP BY DB_ID, SCHEMA, NAME HAVING count(*) > 1) t1
      changes:
        - addUniqueConstraint:
            tableName: metabase_table
            columnNames: db_id, schema, name
            constraintName: idx_uniq_table_db_id_schema_name
        # For Postgres, add additional constraint to apply if schema is NULL
        - sql:
            dbms: postgresql
            sql: CREATE UNIQUE INDEX idx_uniq_table_db_id_schema_name_2col ON "metabase_table" ("db_id", "name") WHERE "schema" IS NULL

  - changeSet:
      id: 99
      author: camsaul
      comment: 'Added 0.32.0'
      preConditions:
        - onFail: MARK_RAN
        - onUpdateSQL: IGNORE
        - or:
            - and:
                - dbms:
                    type: mysql,mariadb
                - sqlCheck:
                    expectedResult: 0
                    sql: SELECT count(*) FROM (SELECT count(*) FROM `metabase_field` GROUP BY `table_id`, `parent_id`, `name` HAVING count(*) > 1) t1
            - and:
                - dbms:
                    type: h2,postgresql
                - sqlCheck:
                    expectedResult: 0
                    sql: SELECT count(*) FROM (SELECT count(*) FROM METABASE_FIELD GROUP BY TABLE_ID, PARENT_ID, NAME HAVING count(*) > 1) t1
      changes:
        - addUniqueConstraint:
            tableName: metabase_field
            columnNames: table_id, parent_id, name
            constraintName: idx_uniq_field_table_id_parent_id_name
        # For Postgres, add additional constraint to apply if schema is NULL
        - sql:
            dbms: postgresql
            sql: CREATE UNIQUE INDEX idx_uniq_field_table_id_parent_id_name_2col ON "metabase_field" ("table_id", "name") WHERE "parent_id" IS NULL

#
# Migration 84 was written slightly incorrectly and did not correctly migrate the values of is_active -> archived for
# METRICS. If you look at the migration you will notice the raw SQL part is a `sql` map with 2 `sql` keys. The first key
# is ignored, and that statement was never ran.
#
# To fix this we will migrate any metrics that haven't been updated since that migration ran and fix their archived
# status
  - changeSet:
      id: 100
      author: camsaul
      comment: 'Added 0.32.0'
      validCheckSum: ANY
      changes:
        # databasechangelog is upper-case in MySQL and MariaDB (and H2 for that matter, but H2 will upper-case the
        # unquoted identifier)
        - sql:
            dbms: postgresql,h2
            sql: >-
              UPDATE metric
              SET archived = NOT archived
              WHERE EXISTS (
                SELECT *
                FROM databasechangelog dbcl
                WHERE dbcl.id = '84'
                  AND metric.updated_at < dbcl.dateexecuted
              )
        - sql:
            dbms: mysql,mariadb
            sql: >-
              UPDATE metric
              SET archived = NOT archived
              WHERE EXISTS (
                SELECT *
                FROM `DATABASECHANGELOG` dbcl
                WHERE dbcl.id = '84'
                  AND metric.updated_at < dbcl.dateexecuted
              )

# Very helpful for performance reasons. See #9519
  - changeSet:
      id: 101
      author: camsaul
      comment: 'Added 0.32.0'
      changes:
        - createIndex:
            indexName: idx_field_parent_id
            tableName: metabase_field
            columns:
              - column:
                  name: parent_id

# A per-Database setting for the new Query Builder 3.0.
  - changeSet:
      id: 103
      author: camsaul
      comment: 'Added 0.32.10'
      changes:
        - addColumn:
            tableName: metabase_database
            columns:
              - column:
                  name: auto_run_queries
                  remarks: 'Whether to automatically run queries when doing simple filtering and summarizing in the Query Builder.'
                  type: boolean
                  constraints:
                    nullable: false
                  defaultValueBoolean: true


  # To fix EE full-app embedding without compromising security. Full-app embed sessions cannot have `SameSite` attributes in their cookies.
  - changeSet:
      id: 104
      author: camsaul
      comment: 'Added EE 1.1.6/CE 0.33.0'
      changes:
        - addColumn:
            tableName: core_session
            columns:
              - column:
                  name: anti_csrf_token
                  type: text
                  remarks: 'Anti-CSRF token for full-app embed sessions.'

#
# Change `metabase_field.database_type` to `text` to accomodate more exotic field types (enums in Clickhouse, rows in Presto, ...)
#
  - changeSet:
      id: 106
      author: sb
      comment: 'Added 0.33.5'
      changes:
        - modifyDataType:
            tableName: metabase_field
            columnName: database_type
            newDataType: text

#
#  Migrations 107-160 are used to convert a MySQL or MariaDB database to utf8mb4 on launch -- see #11753 for a detailed explanation of these migrations
#

  - changeSet:
        id: 107
        author: camsaul
        comment: Added 0.34.2
        # If this migration fails for any reason continue with the next migration; do not fail the entire process if this one fails
        failOnError: false
        preConditions:
          # If preconditions fail (i.e., dbms is not mysql or mariadb) then mark this migration as 'ran'
          - onFail: MARK_RAN
          # If we're generating SQL output for migrations instead of running via liquibase, fail the preconditions which means these migrations will be skipped
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER DATABASE CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
  - changeSet:
        id: 108
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `DATABASECHANGELOG` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 109
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `DATABASECHANGELOGLOCK` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 110
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `QRTZ_CALENDARS` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 111
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `QRTZ_FIRED_TRIGGERS` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 112
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `QRTZ_JOB_DETAILS` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 113
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `QRTZ_LOCKS` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 114
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `QRTZ_PAUSED_TRIGGER_GRPS` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 115
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `QRTZ_SCHEDULER_STATE` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 116
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `core_user` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 117
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `data_migrations` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 118
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `dependency` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 119
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `label` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 120
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `metabase_database` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 121
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `permissions_group` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 122
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `query` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 123
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `query_cache` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 124
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `query_execution` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 125
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `setting` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 126
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `task_history` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 127
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `QRTZ_TRIGGERS` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 128
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `activity` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 129
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `collection` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 130
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `collection_revision` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 131
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `computation_job` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 132
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `core_session` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 133
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `metabase_table` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 134
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `permissions` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 135
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `permissions_revision` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 136
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `revision` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 137
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `view_log` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 138
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `QRTZ_BLOB_TRIGGERS` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 139
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `QRTZ_CRON_TRIGGERS` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 140
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `QRTZ_SIMPLE_TRIGGERS` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 141
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `QRTZ_SIMPROP_TRIGGERS` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 142
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `computation_job_result` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 143
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `metabase_field` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 144
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `permissions_group_membership` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 145
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `pulse` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 146
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `report_dashboard` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 147
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `dashboard_favorite` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 148
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `dimension` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 149
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `metabase_fieldvalues` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 150
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `metric` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 151
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `pulse_channel` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 152
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `segment` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 153
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `pulse_channel_recipient` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 154
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `report_card` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 155
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `metric_important_field` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 156
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `report_cardfavorite` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 157
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `card_label` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 158
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `pulse_card` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 159
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `report_dashboardcard` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  - changeSet:
        id: 160
        author: camsaul
        comment: Added 0.34.2
        failOnError: false
        preConditions:
          - onFail: MARK_RAN
          - onSqlOutput: FAIL
          - or:
              - dbms:
                    type: mysql
              - dbms:
                    type: mariadb
        changes:
          - sql:
                sql: ALTER TABLE `dashboardcard_series` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

# [161 has been removed. Superceded by 166]

# Drop the old query_queryexecution table if present. This was replaced by query_execution in 0.23.0. This was
# formerly a data migration but was converted to a Liquibase migration so people running migrations manually will
# still have the Table dropped.

  - changeSet:
      id: 162
      author: camsaul
      comment: 'Added 0.23.0 as a data migration; converted to Liquibase migration in 0.35.0'
      preConditions:
        - onFail: MARK_RAN
        - tableExists:
            tableName: query_queryexecution
      changes:
        - dropTable:
            tableName: query_queryexecution

# Drop Card.read_permissions. Prior to 0.30.0 Card permissions were always based on the Database/Table(s) being
# queried (i.e., the permissions model we use for ad-hoc queries). These permissions were calculated and stored in
# `read_permissions` for performance reasons. In 0.30.0, we switched to having Card permissions always be inherited
# from their parent Collection, and the column hasn't been used since then. Time to let it go.

  - changeSet:
      id: 163
      author: camsaul
      comment: 'Added 0.35.0'
      changes:
        - dropColumn:
            tableName: report_card
            columnName: read_permissions

# Add User `locale` -- when set, this User will see the Metabase in this Locale rather than the system default Locale
# (the `site-locale` Setting).

  - changeSet:
      id: 164
      author: camsaul
      comment: 'Added 0.35.0'
      changes:
        - addColumn:
            tableName: core_user
            columns:
              - column:
                  name: locale
                  remarks: 'Preferred ISO locale (language/country) code, e.g "en" or "en-US", for this User. Overrides site default.'
                  type: varchar(5)

# Add Field `database_position` to keep the order in which fields are ordered in the DB, `custom_position` for custom
# position; and Table `field_order` setting.

  - changeSet:
      id: 165
      author: sb
      comment: 'Added field_order to Table and database_position to Field'
      validCheckSum: ANY
      changes:
        - addColumn:
            tableName: metabase_field
            columns:
              - column:
                  name: database_position
                  type: int
                  defaultValueNumeric: 0
                  constraints:
                    nullable: false
        - addColumn:
            tableName: metabase_field
            columns:
              - column:
                  name: custom_position
                  type: int
                  defaultValueNumeric: 0
                  constraints:
                    nullable: false
        - addColumn:
            tableName: metabase_table
            columns:
              - column:
                  name: field_order
                  type: varchar(254)
                  defaultValue: database
                  constraints:
                    nullable: false
        - sql:
            sql: update metabase_field set database_position = id

# Change field_values.updated_at and query_cache.updated_at from datetime to timestamp [with time zone] to get >
# second resolution on MySQL.
#
# query_cache.updated_at was originally converted to a timestamp in 161, but we used `timestamp` instead of
# `timestamp(6)`. It is converted correctly here.

  - changeSet:
      id: 166
      author: camsaul
      comment: Added 0.36.0/1.35.4
      changes:
        - modifyDataType:
            tableName: metabase_fieldvalues
            columnName: updated_at
            newDataType: ${timestamp_type}
        - modifyDataType:
            tableName: query_cache
            columnName: updated_at
            newDataType: ${timestamp_type}

# Create the native query snippets table, intended to store snippets and their metadata
  - changeSet:
      id: 167
      author: walterl, camsaul
      validCheckSum: ANY
      comment: 'Added 0.36.0'
      changes:
        # If an older version of this Table was created locally (during dev) drop it, we have an updated definition
        - sql:
            sql: drop table if exists native_query_snippet
        - createTable:
            tableName: native_query_snippet
            remarks: 'Query snippets (raw text) to be substituted in native queries'
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: name
                  type: VARCHAR(254)
                  remarks: 'Name of the query snippet'
                  constraints:
                    nullable: false
                    unique: true
              - column:
                  name: description
                  type: text
              - column:
                  name: content
                  type: text
                  remarks: 'Raw query snippet'
                  constraints:
                    nullable: false
              - column:
                  name: creator_id
                  type: int
                  constraints:
                    nullable: false
                    referencedTableName: core_user
                    referencedColumnNames: id
                    foreignKeyName: fk_snippet_creator_id
                    # This primarily affects tests because under normal
                    # circumstances we don't delete Users, we just archive them
                    deleteCascade: true
              - column:
                  name: archived
                  type: boolean
                  defaultValueBoolean: false
                  constraints:
                    nullable: false
              - column:
                  name: created_at
                  type: ${timestamp_type}
                  # it seems like defaultValueComputed actaully just ends
                  # getting ignored anyway -- see
                  # https://stackoverflow.com/questions/58816496/force-liquibase-to-current-timestamp-instead-of-now
                  # We set a custom value for MySQL/MariaDB in MetabaseMySqlCreateTableSqlGenerator.java
                  defaultValueComputed: current_timestamp
                  constraints:
                    nullable: false
              - column:
                  name: updated_at
                  type: ${timestamp_type}
                  defaultValueComputed: current_timestamp
                  constraints:
                    nullable: false
        # Needed to efficiently enforce the unique constraint on name and so we can lookup by name as well.
        - createIndex:
            tableName: native_query_snippet
            indexName: idx_snippet_name
            columns:
              - column:
                  name: name

# Convert query execution from DATETIME to TIMESTAMP(6) so have normalize TZ
# offset and so MySQL/MariaDB has better than second precision

  - changeSet:
      id: 168
      author: camsaul
      comment: Added 0.36.0
      changes:
        - modifyDataType:
            tableName: query_execution
            columnName: started_at
            newDataType: ${timestamp_type}

# Remove `Table.rows`, which hasn't been used for years now. Older versions of Metabase used to store the row count in
# this column but we disabled it a long time ago for performance reasons. Now it's time to remove it entirely.

  - changeSet:
      id: 169
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropColumn:
            tableName: metabase_table
            columnName: rows

# Remove fields_hash from Table model, as we no longer skip sync steps if metadata
# hash hasn't changed.

  - changeSet:
      id: 170
      author: sb
      comment: Added 0.36.0
      changes:
        - dropColumn:
            tableName: metabase_table
            columnName: fields_hash

# In EE, NativeQuerySnippets have a permissions system based on "snippet folders" which are Collections under the
# hood. However, these Collections live in a separate "namespace" -- a completely separate hierarchy of Collections.

  - changeSet:
      id: 171
      author: camsaul
      validCheckSum: ANY
      comment: Added 0.36.0
      changes:
        - addColumn:
            tableName: native_query_snippet
            columns:
              - column:
                  name: collection_id
                  type: int
                  remarks: 'ID of the Snippet Folder (Collection) this Snippet is in, if any'
                  constraints:
                    nullable: true
                    referencedTableName: collection
                    referencedColumnNames: id
                    foreignKeyName: fk_snippet_collection_id
        - createIndex:
            tableName: native_query_snippet
            indexName: idx_snippet_collection_id
            columns:
              - column:
                  name: collection_id

  - changeSet:
      id: 172
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addColumn:
            tableName: collection
            columns:
              - column:
                  name: namespace
                  type: varchar(254)
                  remarks: 'The namespace (hierachy) this Collection belongs to. NULL means the Collection is in the default namespace.'
                  constraints:
                    nullable: true

# These migrations convert various FK constraints in the DB to ones with ON DELETE CASCADE so the DB can handle this
# instead of relying on Toucan pre-delete methods to do it, which are subject to race conditions.

  # activity.user_id -> core_user.id
  - changeSet:
      id: 173
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: activity
            constraintName: fk_activity_ref_user_id

  - changeSet:
      id: 174
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: activity
            baseColumnNames: user_id
            referencedTableName: core_user
            referencedColumnNames: id
            constraintName: fk_activity_ref_user_id
            onDelete: CASCADE

  # card_label.card_id -> report_card.id
  - changeSet:
      id: 175
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: card_label
            constraintName: fk_card_label_ref_card_id

  - changeSet:
      id: 176
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: card_label
            baseColumnNames: card_id
            referencedTableName: report_card
            referencedColumnNames: id
            constraintName: fk_card_label_ref_card_id
            onDelete: CASCADE

  # card_label.label_id -> label.id
  - changeSet:
      id: 177
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: card_label
            constraintName: fk_card_label_ref_label_id

  - changeSet:
      id: 178
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: card_label
            baseColumnNames: label_id
            referencedTableName: label
            referencedColumnNames: id
            constraintName: fk_card_label_ref_label_id
            onDelete: CASCADE

  # collection.personal_owner_id -> core_user.id
  - changeSet:
      id: 179
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: collection
            constraintName: fk_collection_personal_owner_id

  - changeSet:
      id: 180
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: collection
            baseColumnNames: personal_owner_id
            referencedTableName: core_user
            referencedColumnNames: id
            constraintName: fk_collection_personal_owner_id
            onDelete: CASCADE

  # collection_revision.user_id -> core_user.id
  - changeSet:
      id: 181
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: collection_revision
            constraintName: fk_collection_revision_user_id

  - changeSet:
      id: 182
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: collection_revision
            baseColumnNames: user_id
            referencedTableName: core_user
            referencedColumnNames: id
            constraintName: fk_collection_revision_user_id
            onDelete: CASCADE

  # computation_job.creator_id -> core_user.id
  - changeSet:
      id: 183
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: computation_job
            constraintName: fk_computation_job_ref_user_id

  - changeSet:
      id: 184
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: computation_job
            baseColumnNames: creator_id
            referencedTableName: core_user
            referencedColumnNames: id
            constraintName: fk_computation_job_ref_user_id
            onDelete: CASCADE

  # computation_job_result.job_id -> computation_job.id
  - changeSet:
      id: 185
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: computation_job_result
            constraintName: fk_computation_result_ref_job_id

  - changeSet:
      id: 186
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: computation_job_result
            baseColumnNames: job_id
            referencedTableName: computation_job
            referencedColumnNames: id
            constraintName: fk_computation_result_ref_job_id
            onDelete: CASCADE

  # core_session.user_id -> core_user.id
  - changeSet:
      id: 187
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: core_session
            constraintName: fk_session_ref_user_id

  - changeSet:
      id: 188
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: core_session
            baseColumnNames: user_id
            referencedTableName: core_user
            referencedColumnNames: id
            constraintName: fk_session_ref_user_id
            onDelete: CASCADE

  # dashboardcard_series.card_id -> report_card.id
  - changeSet:
      id: 189
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: dashboardcard_series
            constraintName: fk_dashboardcard_series_ref_card_id

  - changeSet:
      id: 190
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: dashboardcard_series
            baseColumnNames: card_id
            referencedTableName: report_card
            referencedColumnNames: id
            constraintName: fk_dashboardcard_series_ref_card_id
            onDelete: CASCADE

  # dashboardcard_series.dashboardcard_id -> report_dashboardcard.id
  - changeSet:
      id: 191
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: dashboardcard_series
            constraintName: fk_dashboardcard_series_ref_dashboardcard_id

  - changeSet:
      id: 192
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: dashboardcard_series
            baseColumnNames: dashboardcard_id
            referencedTableName: report_dashboardcard
            referencedColumnNames: id
            constraintName: fk_dashboardcard_series_ref_dashboardcard_id
            onDelete: CASCADE

  # group_table_access_policy.card_id -> report_card.id
  - changeSet:
      id: 193
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: group_table_access_policy
            constraintName: fk_gtap_card_id

  - changeSet:
      id: 194
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: group_table_access_policy
            baseColumnNames: card_id
            referencedTableName: report_card
            referencedColumnNames: id
            constraintName: fk_gtap_card_id
            onDelete: CASCADE

  # metabase_field.parent_id -> metabase_field.id
  - changeSet:
      id: 195
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: metabase_field
            constraintName: fk_field_parent_ref_field_id

  - changeSet:
      id: 196
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: metabase_field
            baseColumnNames: parent_id
            referencedTableName: metabase_field
            referencedColumnNames: id
            constraintName: fk_field_parent_ref_field_id
            onDelete: CASCADE

  # metabase_field.table_id -> metabase_table.id
  - changeSet:
      id: 197
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: metabase_field
            constraintName: fk_field_ref_table_id

  - changeSet:
      id: 198
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: metabase_field
            baseColumnNames: table_id
            referencedTableName: metabase_table
            referencedColumnNames: id
            constraintName: fk_field_ref_table_id
            onDelete: CASCADE

  # metabase_fieldvalues.field_id -> metabase_field.id
  - changeSet:
      id: 199
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: metabase_fieldvalues
            constraintName: fk_fieldvalues_ref_field_id

  - changeSet:
      id: 200
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: metabase_fieldvalues
            baseColumnNames: field_id
            referencedTableName: metabase_field
            referencedColumnNames: id
            constraintName: fk_fieldvalues_ref_field_id
            onDelete: CASCADE

  # metabase_table.db_id -> metabase_database.id
  - changeSet:
      id: 201
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: metabase_table
            constraintName: fk_table_ref_database_id

  - changeSet:
      id: 202
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: metabase_table
            baseColumnNames: db_id
            referencedTableName: metabase_database
            referencedColumnNames: id
            constraintName: fk_table_ref_database_id
            onDelete: CASCADE

  # metric.creator_id -> core_user.id
  - changeSet:
      id: 203
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: metric
            constraintName: fk_metric_ref_creator_id

  - changeSet:
      id: 204
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: metric
            baseColumnNames: creator_id
            referencedTableName: core_user
            referencedColumnNames: id
            constraintName: fk_metric_ref_creator_id
            onDelete: CASCADE

  # metric.table_id -> metabase_table.id
  - changeSet:
      id: 205
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: metric
            constraintName: fk_metric_ref_table_id

  - changeSet:
      id: 206
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: metric
            baseColumnNames: table_id
            referencedTableName: metabase_table
            referencedColumnNames: id
            constraintName: fk_metric_ref_table_id
            onDelete: CASCADE

  # metric_important_field.field_id -> metabase_field.id
  - changeSet:
      id: 207
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: metric_important_field
            constraintName: fk_metric_important_field_metabase_field_id

  - changeSet:
      id: 208
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: metric_important_field
            baseColumnNames: field_id
            referencedTableName: metabase_field
            referencedColumnNames: id
            constraintName: fk_metric_important_field_metabase_field_id
            onDelete: CASCADE

  # metric_important_field.metric_id -> metric.id
  - changeSet:
      id: 209
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: metric_important_field
            constraintName: fk_metric_important_field_metric_id

  - changeSet:
      id: 210
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: metric_important_field
            baseColumnNames: metric_id
            referencedTableName: metric
            referencedColumnNames: id
            constraintName: fk_metric_important_field_metric_id
            onDelete: CASCADE

  # native_query_snippet.collection_id -> collection.id
  - changeSet:
      id: 211
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: native_query_snippet
            constraintName: fk_snippet_collection_id

  - changeSet:
      id: 212
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: native_query_snippet
            baseColumnNames: collection_id
            referencedTableName: collection
            referencedColumnNames: id
            constraintName: fk_snippet_collection_id
            onDelete: SET NULL

  # permissions.group_id -> permissions_group.id
  - changeSet:
      id: 213
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: permissions
            constraintName: fk_permissions_group_id

  - changeSet:
      id: 214
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: permissions
            baseColumnNames: group_id
            referencedTableName: permissions_group
            referencedColumnNames: id
            constraintName: fk_permissions_group_id
            onDelete: CASCADE

  # permissions_group_membership.group_id -> permissions_group.id
  - changeSet:
      id: 215
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: permissions_group_membership
            constraintName: fk_permissions_group_group_id

  - changeSet:
      id: 216
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: permissions_group_membership
            baseColumnNames: group_id
            referencedTableName: permissions_group
            referencedColumnNames: id
            constraintName: fk_permissions_group_group_id
            onDelete: CASCADE

  # permissions_group_membership.user_id -> core_user.id
  - changeSet:
      id: 217
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: permissions_group_membership
            constraintName: fk_permissions_group_membership_user_id

  - changeSet:
      id: 218
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: permissions_group_membership
            baseColumnNames: user_id
            referencedTableName: core_user
            referencedColumnNames: id
            constraintName: fk_permissions_group_membership_user_id
            onDelete: CASCADE

  # permissions_revision.user_id -> core_user.id
  - changeSet:
      id: 219
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: permissions_revision
            constraintName: fk_permissions_revision_user_id

  - changeSet:
      id: 220
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: permissions_revision
            baseColumnNames: user_id
            referencedTableName: core_user
            referencedColumnNames: id
            constraintName: fk_permissions_revision_user_id
            onDelete: CASCADE

  # pulse.collection_id -> collection.id
  - changeSet:
      id: 221
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: pulse
            constraintName: fk_pulse_collection_id

  - changeSet:
      id: 222
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: pulse
            baseColumnNames: collection_id
            referencedTableName: collection
            referencedColumnNames: id
            constraintName: fk_pulse_collection_id
            onDelete: SET NULL

  # pulse.creator_id -> core_user.id
  - changeSet:
      id: 223
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: pulse
            constraintName: fk_pulse_ref_creator_id

  - changeSet:
      id: 224
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: pulse
            baseColumnNames: creator_id
            referencedTableName: core_user
            referencedColumnNames: id
            constraintName: fk_pulse_ref_creator_id
            onDelete: CASCADE

  # pulse_card.card_id -> report_card.id
  - changeSet:
      id: 225
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: pulse_card
            constraintName: fk_pulse_card_ref_card_id

  - changeSet:
      id: 226
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: pulse_card
            baseColumnNames: card_id
            referencedTableName: report_card
            referencedColumnNames: id
            constraintName: fk_pulse_card_ref_card_id
            onDelete: CASCADE

  # pulse_card.pulse_id -> pulse.id
  - changeSet:
      id: 227
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: pulse_card
            constraintName: fk_pulse_card_ref_pulse_id

  - changeSet:
      id: 228
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: pulse_card
            baseColumnNames: pulse_id
            referencedTableName: pulse
            referencedColumnNames: id
            constraintName: fk_pulse_card_ref_pulse_id
            onDelete: CASCADE

  # pulse_channel.pulse_id -> pulse.id
  - changeSet:
      id: 229
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: pulse_channel
            constraintName: fk_pulse_channel_ref_pulse_id

  - changeSet:
      id: 230
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: pulse_channel
            baseColumnNames: pulse_id
            referencedTableName: pulse
            referencedColumnNames: id
            constraintName: fk_pulse_channel_ref_pulse_id
            onDelete: CASCADE

  # pulse_channel_recipient.pulse_channel_id -> pulse_channel.id
  - changeSet:
      id: 231
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: pulse_channel_recipient
            constraintName: fk_pulse_channel_recipient_ref_pulse_channel_id

  - changeSet:
      id: 232
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: pulse_channel_recipient
            baseColumnNames: pulse_channel_id
            referencedTableName: pulse_channel
            referencedColumnNames: id
            constraintName: fk_pulse_channel_recipient_ref_pulse_channel_id
            onDelete: CASCADE

  # pulse_channel_recipient.user_id -> core_user.id
  - changeSet:
      id: 233
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: pulse_channel_recipient
            constraintName: fk_pulse_channel_recipient_ref_user_id

  - changeSet:
      id: 234
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: pulse_channel_recipient
            baseColumnNames: user_id
            referencedTableName: core_user
            referencedColumnNames: id
            constraintName: fk_pulse_channel_recipient_ref_user_id
            onDelete: CASCADE

  # report_card.collection_id -> collection.id
  - changeSet:
      id: 235
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: report_card
            constraintName: fk_card_collection_id

  - changeSet:
      id: 236
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: report_card
            baseColumnNames: collection_id
            referencedTableName: collection
            referencedColumnNames: id
            constraintName: fk_card_collection_id
            onDelete: SET NULL

  # report_card.made_public_by_id -> core_user.id
  - changeSet:
      id: 237
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: report_card
            constraintName: fk_card_made_public_by_id

  - changeSet:
      id: 238
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: report_card
            baseColumnNames: made_public_by_id
            referencedTableName: core_user
            referencedColumnNames: id
            constraintName: fk_card_made_public_by_id
            onDelete: CASCADE

  # report_card.creator_id -> core_user.id
  - changeSet:
      id: 239
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: report_card
            constraintName: fk_card_ref_user_id

  - changeSet:
      id: 240
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: report_card
            baseColumnNames: creator_id
            referencedTableName: core_user
            referencedColumnNames: id
            constraintName: fk_card_ref_user_id
            onDelete: CASCADE

  # report_card.database_id -> metabase_database.id
  - changeSet:
      id: 241
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: report_card
            constraintName: fk_report_card_ref_database_id

  - changeSet:
      id: 242
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: report_card
            baseColumnNames: database_id
            referencedTableName: metabase_database
            referencedColumnNames: id
            constraintName: fk_report_card_ref_database_id
            onDelete: CASCADE

  # report_card.table_id -> metabase_table.id
  - changeSet:
      id: 243
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: report_card
            constraintName: fk_report_card_ref_table_id

  - changeSet:
      id: 244
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: report_card
            baseColumnNames: table_id
            referencedTableName: metabase_table
            referencedColumnNames: id
            constraintName: fk_report_card_ref_table_id
            onDelete: CASCADE

  # report_cardfavorite.card_id -> report_card.id
  - changeSet:
      id: 245
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: report_cardfavorite
            constraintName: fk_cardfavorite_ref_card_id

  - changeSet:
      id: 246
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: report_cardfavorite
            baseColumnNames: card_id
            referencedTableName: report_card
            referencedColumnNames: id
            constraintName: fk_cardfavorite_ref_card_id
            onDelete: CASCADE

  # report_cardfavorite.owner_id -> core_user.id
  - changeSet:
      id: 247
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: report_cardfavorite
            constraintName: fk_cardfavorite_ref_user_id

  - changeSet:
      id: 248
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: report_cardfavorite
            baseColumnNames: owner_id
            referencedTableName: core_user
            referencedColumnNames: id
            constraintName: fk_cardfavorite_ref_user_id
            onDelete: CASCADE

  # report_dashboard.collection_id -> collection.id
  - changeSet:
      id: 249
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: report_dashboard
            constraintName: fk_dashboard_collection_id

  - changeSet:
      id: 250
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: report_dashboard
            baseColumnNames: collection_id
            referencedTableName: collection
            referencedColumnNames: id
            constraintName: fk_dashboard_collection_id
            onDelete: SET NULL

  # report_dashboard.made_public_by_id -> core_user.id
  - changeSet:
      id: 251
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: report_dashboard
            constraintName: fk_dashboard_made_public_by_id

  - changeSet:
      id: 252
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: report_dashboard
            baseColumnNames: made_public_by_id
            referencedTableName: core_user
            referencedColumnNames: id
            constraintName: fk_dashboard_made_public_by_id
            onDelete: CASCADE

  # report_dashboard.creator_id -> core_user.id
  - changeSet:
      id: 253
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: report_dashboard
            constraintName: fk_dashboard_ref_user_id

  - changeSet:
      id: 254
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: report_dashboard
            baseColumnNames: creator_id
            referencedTableName: core_user
            referencedColumnNames: id
            constraintName: fk_dashboard_ref_user_id
            onDelete: CASCADE

  # report_dashboardcard.card_id -> report_card.id
  - changeSet:
      id: 255
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: report_dashboardcard
            constraintName: fk_dashboardcard_ref_card_id

  - changeSet:
      id: 256
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: report_dashboardcard
            baseColumnNames: card_id
            referencedTableName: report_card
            referencedColumnNames: id
            constraintName: fk_dashboardcard_ref_card_id
            onDelete: CASCADE

  # report_dashboardcard.dashboard_id -> report_dashboard.id
  - changeSet:
      id: 257
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: report_dashboardcard
            constraintName: fk_dashboardcard_ref_dashboard_id

  - changeSet:
      id: 258
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: report_dashboardcard
            baseColumnNames: dashboard_id
            referencedTableName: report_dashboard
            referencedColumnNames: id
            constraintName: fk_dashboardcard_ref_dashboard_id
            onDelete: CASCADE

  # revision.user_id -> core_user.id
  - changeSet:
      id: 259
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: revision
            constraintName: fk_revision_ref_user_id

  - changeSet:
      id: 260
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: revision
            baseColumnNames: user_id
            referencedTableName: core_user
            referencedColumnNames: id
            constraintName: fk_revision_ref_user_id
            onDelete: CASCADE

  # segment.creator_id -> core_user.id
  - changeSet:
      id: 261
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: segment
            constraintName: fk_segment_ref_creator_id

  - changeSet:
      id: 262
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: segment
            baseColumnNames: creator_id
            referencedTableName: core_user
            referencedColumnNames: id
            constraintName: fk_segment_ref_creator_id
            onDelete: CASCADE

  # segment.table_id -> metabase_table.id
  - changeSet:
      id: 263
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: segment
            constraintName: fk_segment_ref_table_id

  - changeSet:
      id: 264
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: segment
            baseColumnNames: table_id
            referencedTableName: metabase_table
            referencedColumnNames: id
            constraintName: fk_segment_ref_table_id
            onDelete: CASCADE

  # view_log.user_id -> core_user.id
  - changeSet:
      id: 265
      author: camsaul
      comment: Added 0.36.0
      changes:
        - dropForeignKeyConstraint:
            baseTableName: view_log
            constraintName: fk_view_log_ref_user_id

  - changeSet:
      id: 266
      author: camsaul
      comment: Added 0.36.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: view_log
            baseColumnNames: user_id
            referencedTableName: core_user
            referencedColumnNames: id
            constraintName: fk_view_log_ref_user_id
            onDelete: CASCADE

# changesets 268-272 allow for handling user account emails in lowercase (GH issue 3047)
  - changeSet:
      id: 268
      author: rlotun
      comment: Added 0.37.0  # create index on lower(email), for performance reasons (not availble on h2 and only on more recent versions of mysql)
      failOnError: false
      preConditions:
        - onFail: MARK_RAN
        - and:
            - dbms:
                type: postgresql
      # This has maybe never succeeded in creating the index because (at least with the current DB versions)
      # the syntax was wrong on all requested databases (postgresql, mysql and mariadb). Since this change is
      # not critical it's OK to ignore it.
      validCheckSum: 8:9da2f706a7cd42b5101601e0106fa929
      changes:
        - createIndex:
            columns:
             - column:
                 name: lower(email)
                 computed: true
                 type: varchar(254)
            tableName: core_user
            indexName: idx_lower_email
  - changeSet:
      id: 269
      author: rlotun
      comment: Added 0.37.0  # set email values to lower(email) but do so defensively and in a way that works on postgres and mysql - skip over those that would introduce duplicates (e.g. Reza@email.com and reza@email.com)
      changes:
        - sql :
            sql : UPDATE core_user SET email = lower(email) WHERE lower(email) NOT IN (SELECT * FROM (SELECT lower(email) FROM core_user GROUP BY lower(email) HAVING count(email) > 1) as e)
  - changeSet:
      id: 270
      author: rlotun
      comment: Added 0.37.0 # try to install citext extension on posgres (user requires privileges on postgres)
      failOnError: false
      preConditions:
        - onFail: MARK_RAN
        - or:
            - dbms:
                type: postgresql
      changes:
        - sql :
            sql : CREATE EXTENSION IF NOT EXISTS citext
  - changeSet:
      id: 271
      author: rlotun
      comment: Added 0.37.0 # try to convert email column to citext on postgres, if citext extension installed
      failOnError: false
      preConditions:
        - onFail: MARK_RAN
        - and:
            - dbms:
                type: postgresql
            - sqlCheck:
                expectedResult: 1
                sql: SELECT count(*) FROM pg_extension WHERE extname = 'citext'
      changes:
        - modifyDataType:
            tableName: core_user
            columnName: email
            newDataType: citext
  - changeSet:
      id: 272
      author: rlotun
      comment: Added 0.37.0 # for H2 convert column to VARCHAR_IGNORECASE
      failOnError: false
      preConditions:
         - onFail: MARK_RAN
         - or:
             - dbms:
                   type: h2
      changes:
        - modifyDataType:
            tableName: core_user
            columnName: email
            newDataType: varchar_ignorecase(254)

  - changeSet:
      id: 273
      author: camsaul
      comment: Added 0.37.1
      changes:
        - addDefaultValue:
            tableName: core_user
            columnName: is_superuser
            columnDataType: boolean
            defaultValueBoolean: false

  - changeSet:
      id: 274
      author: camsaul
      comment: Added 0.37.1
      changes:
        - addDefaultValue:
            tableName: core_user
            columnName: is_active
            columnDataType: boolean
            defaultValueBoolean: true

 # Add refingerprint to database to mark if fingerprinting or
 # not. Nullable in first pass so can be opt in and then in a
 # subsequent pass can be globally turned on where null, respecting
 # people who turned it on and then off.

  - changeSet:
      id: 275
      author: dpsutton
      comment: 'Added 0.38.0 refingerprint to Database'
      validCheckSum: ANY
      changes:
        - addColumn:
            tableName: metabase_database
            columns:
              - column:
                  name: refingerprint
                  type: boolean
                  remarks: 'Whether or not to enable periodic refingerprinting for this Database.'
                  constraints:
                    nullable: true
  - changeSet:
      id: 276
      author: robroland
      comment: Added 0.38.0 - Dashboard subscriptions
      validCheckSum: ANY
      changes:
        - addColumn:
            tableName: pulse_card
            columns:
            - column:
                name: dashboard_card_id
                type: int
                remarks: 'If this Pulse is a Dashboard subscription, the ID of the DashboardCard that corresponds to this PulseCard.'
                constraints:
                  nullable: true
                  referencedTableName: report_dashboardcard
                  referencedColumnNames: id
                  foreignKeyName: fk_pulse_card_ref_pulse_card_id
                  deferrable: false
                  initiallyDeferred: false

  - changeSet:
      id: 277
      author: tsmacdonald
      comment: Added 0.38.0 - Dashboard subscriptions
      changes:
        - dropForeignKeyConstraint:
            baseTableName: pulse_card
            constraintName: fk_pulse_card_ref_pulse_card_id

  - changeSet:
      id: 278
      author: tsmacdonald
      comment: Added 0.38.0 - Dashboard subscrptions
      changes:
        - addForeignKeyConstraint:
            baseTableName: pulse_card
            baseColumnNames: dashboard_card_id
            referencedTableName: report_dashboardcard
            referencedColumnNames: id
            constraintName: fk_pulse_card_ref_pulse_card_id
            onDelete: CASCADE

  - changeSet:
      id: 279
      author: camsaul
      comment: Added 0.38.0 - Dashboard subscriptions
      changes:
        - addColumn:
            tableName: pulse
            columns:
              - column:
                  name: dashboard_id
                  type: int
                  remarks: 'ID of the Dashboard if this Pulse is a Dashboard Subscription.'

  # FK constraint is added separately because deleteCascade doesn't work in addColumn -- see #14321
  - changeSet:
      id: 280
      author: camsaul
      comment: Added 0.38.0 - Dashboard subscriptions
      changes:
        - addForeignKeyConstraint:
            baseTableName: pulse
            baseColumnNames: dashboard_id
            referencedTableName: report_dashboard
            referencedColumnNames: id
            constraintName: fk_pulse_ref_dashboard_id
            onDelete: CASCADE

  - changeSet:
      id: 281
      author: dpsutton
      comment: Added 0.39 - Semantic type system - rename special_type
      changes:
        - renameColumn:
            tableName: metabase_field
            oldColumnName: special_type
            newColumnName: semantic_type
            columnDataType: varchar(255)

  # Change the TaskHistory timestamp columns to higher-resolution columns: on MySQL, they previously only had *second*
  # resolution, which caused annoying test failures and made it hard to correctly sort tasks that happened in quick
  # succession.
  #
  # We have to give these columns default values as well, or MySQL is going to be very fussy about having two
  # NOT NULL timestamp columns without default values at the same time.
  #
  # This is done in raw SQL because AFAIK there's no way in Liquibase to change a column type and give it a default
  # value in a single statement, which we have to do to make MySQL happy.
  - changeSet:
      id: 282
      author: camsaul
      comment: Added 0.39.0
      changes:
        - sql:
            dbms: h2
            sql: |
              ALTER TABLE task_history
              ALTER COLUMN started_at timestamp with time zone DEFAULT current_timestamp NOT NULL;
        - sql:
            dbms: postgresql
            sql: |
              ALTER TABLE task_history
              ALTER COLUMN started_at TYPE timestamp with time zone,
              ALTER COLUMN started_at SET DEFAULT current_timestamp;
        - sql:
            dbms: mysql,mariadb
            sql: |
              ALTER TABLE task_history
              MODIFY started_at timestamp(6) DEFAULT current_timestamp(6) NOT NULL;

  - changeSet:
      id: 283
      author: camsaul
      comment: Added 0.39.0
      changes:
        - sql:
            dbms: h2
            sql: |
              ALTER TABLE task_history
              ALTER COLUMN ended_at timestamp with time zone DEFAULT current_timestamp NOT NULL;
        - sql:
            dbms: postgresql
            sql: |
              ALTER TABLE task_history
              ALTER COLUMN ended_at TYPE timestamp with time zone,
              ALTER COLUMN ended_at SET DEFAULT current_timestamp;
        - sql:
            dbms: mysql,mariadb
            sql: |
              ALTER TABLE task_history
              MODIFY ended_at timestamp(6) DEFAULT current_timestamp(6) NOT NULL;
  - changeSet:
      id: 284
      author: dpsutton
      comment: Added 0.39 - Semantic type system - add effective type
      changes:
        - addColumn:
            tableName: metabase_field
            columns:
              - column:
                  name: effective_type
                  type: varchar(255)
                  remarks: 'The effective type of the field after any coercions.'
  - changeSet:
      id: 285
      author: dpsutton
      comment: Added 0.39 - Semantic type system - add coercion column
      changes:
        - addColumn:
            tableName: metabase_field
            columns:
              - column:
                  name: coercion_strategy
                  type: varchar(255)
                  remarks: 'A strategy to coerce the base_type into the effective_type.'
  - changeSet:
      id: 286
      author: dpsutton
      comment: Added 0.39 - Semantic type system - set effective_type default
      changes:
        - sql:
            sql: UPDATE metabase_field set effective_type = base_type
  - changeSet:
      id: 287
      author: dpsutton
      comment: Added 0.39 - Semantic type system - migrate ISO8601 strings
      validCheckSum: ANY
      changes:
        - sql:
            sql: >-
              UPDATE metabase_field
              SET effective_type    = (CASE semantic_type
                                         WHEN 'type/ISO8601DateTimeString' THEN 'type/DateTime'
                                         WHEN 'type/ISO8601TimeString'     THEN 'type/Time'
                                         WHEN 'type/ISO8601DateString'     THEN 'type/Date'
                                       END),
                  coercion_strategy = (CASE semantic_type
                                        WHEN 'type/ISO8601DateTimeString' THEN 'Coercion/ISO8601->DateTime'
                                        WHEN 'type/ISO8601TimeString'     THEN 'Coercion/ISO8601->Time'
                                        WHEN 'type/ISO8601DateString'     THEN 'Coercion/ISO8601->Date'
                                       END)
              WHERE semantic_type IN ('type/ISO8601DateTimeString',
                                      'type/ISO8601TimeString',
                                      'type/ISO8601DateString');
  ## This includes values 'timestamp_milliseconds' and 'timestamp_seconds'. These are old "special_types" that were
  ## migrated in a data migration for version 0.20. But these migrations occur after all liquibase migrations so
  ## it would be possible for another type/UNIXTimestampSeconds to pop up after this migration that supposedly
  ## got rid of them all
  - changeSet:
      id: 288
      author: dpsutton
      comment: Added 0.39 - Semantic type system - migrate unix timestamps
      validCheckSum: ANY
      changes:
        - sql:
              sql: >-
                UPDATE metabase_field
                set effective_type    = 'type/Instant',
                    coercion_strategy = (case semantic_type
                                          WHEN 'type/UNIXTimestampSeconds'      THEN 'Coercion/UNIXSeconds->DateTime'
                                          WHEN 'timestamp_seconds'              THEN 'Coercion/UNIXSeconds->DateTime'
                                          WHEN 'type/UNIXTimestampMilliSeconds' THEN 'Coercion/UNIXMilliSeconds->DateTime'
                                          WHEN 'timestamp_milliseconds'         THEN 'Coercion/UNIXMilliSeconds->DateTime'
                                          WHEN 'type/UNIXTimestampMicroSeconds' THEN 'Coercion/UNIXMicroSeconds->DateTime'
                                         END)
                WHERE semantic_type IN ('type/UNIXTimestampSeconds',
                                        'type/UNIXTimestampMilliSeconds',
                                        'type/UNIXTimestampMicroSeconds',
                                        'timestamp_seconds',
                                        'timestamp_milliseconds');

  - changeSet:
      id: 289
      author: dpsutton
      comment: Added 0.39 - Semantic type system - migrate unix timestamps (corrects typo- seconds was migrated correctly, not millis and micros)
      validCheckSum: ANY
      changes:
        - sql:
              sql: >-
                UPDATE metabase_field
                set effective_type    = 'type/Instant',
                    coercion_strategy = (case semantic_type
                                          WHEN 'type/UNIXTimestampMilliseconds' THEN 'Coercion/UNIXMilliSeconds->DateTime'
                                          WHEN 'type/UNIXTimestampMicroseconds' THEN 'Coercion/UNIXMicroSeconds->DateTime'
                                         END)
                WHERE semantic_type IN ('type/UNIXTimestampMilliseconds',
                                        'type/UNIXTimestampMicroseconds')

  - changeSet:
      id: 290
      author: dpsutton
      comment: Added 0.39 - Semantic type system - Clobber semantic_type where there was a coercion
      changes:
        - sql:
              sql: UPDATE metabase_field set semantic_type = null where coercion_strategy is not null

# 291-297 create the new login history Table

  - changeSet:
      id: 291
      author: camsaul
      validCheckSum: ANY
      comment: Added 0.39.0
      changes:
        - createTable:
            tableName: login_history
            remarks: "Keeps track of various logins for different users and additional info such as location and device"
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: timestamp
                  type: ${timestamp_type}
                  remarks: "When this login occurred."
                  defaultValueComputed: current_timestamp
                  constraints:
                    nullable: false
              - column:
                  name: user_id
                  type: int
                  remarks: "ID of the User that logged in."
                  constraints:
                    foreignKeyName: fk_login_history_user_id
                    referencedTableName: core_user
                    referencedColumnNames: id
                    nullable: false
                    deleteCascade: true
              # FK constraint is created later, because we can't create it inline with ON DELETE SET NULL
              - column:
                  name: session_id
                  type: varchar(254)
                  remarks: "ID of the Session created by this login if one is currently active. NULL if Session is no longer active."
              - column:
                  name: device_id
                  type: char(36)
                  remarks: "Cookie-based unique identifier for the device/browser the user logged in from."
                  constraints:
                    nullable: false
              - column:
                  name: device_description
                  type: text
                  remarks: "Description of the device that login happened from, for example a user-agent string, but this might be something different if we support alternative auth mechanisms in the future."
                  constraints:
                    nullable: false
              - column:
                  name: ip_address
                  type: text
                  remarks: "IP address of the device that login happened from, so we can geocode it and determine approximate location."
                  constraints:
                    nullable: false

  - changeSet:
      id: 292
      author: camsaul
      comment: Added 0.39.0
      changes:
        - createIndex:
            tableName: login_history
            indexName: idx_user_id
            columns:
              - column:
                  name: user_id

  - changeSet:
      id: 293
      author: camsaul
      comment: Added 0.39.0
      changes:
        - addForeignKeyConstraint:
            baseTableName: login_history
            baseColumnNames: session_id
            referencedTableName: core_session
            referencedColumnNames: id
            constraintName: fk_login_history_session_id
            onDelete: SET NULL

  - changeSet:
      id: 294
      author: camsaul
      comment: Added 0.39.0
      changes:
        - createIndex:
            tableName: login_history
            indexName: idx_session_id
            columns:
              - column:
                  name: session_id

  # index on login history timestamp -- so admin can see *all* recent logins, or we can delete login history after a certain age
  - changeSet:
      id: 295
      author: camsaul
      comment: Added 0.39.0
      changes:
        - createIndex:
            tableName: login_history
            indexName: idx_timestamp
            columns:
              - column:
                  name: timestamp

  # index on login history user_id + device_id -- so we can easily see if this is the first time a device is used
  - changeSet:
      id: 296
      author: camsaul
      comment: Added 0.39.0
      changes:
        - createIndex:
            tableName: login_history
            indexName: idx_user_id_device_id
            columns:
              - column:
                  name: session_id
              - column:
                  name: device_id

  # index on login history user_id + timestamp -- so we can easily see recent logins for a user
  - changeSet:
      id: 297
      author: camsaul
      comment: Added 0.39.0
      changes:
        - createIndex:
            tableName: login_history
            indexName: idx_user_id_timestamp
            columns:
              - column:
                  name: user_id
              - column:
                  name: timestamp

  # Add parameter columns to pulses so that dashboard subscriptions can have their own filters
  - changeSet:
      id: 298
      author: tsmacdonald
      comment: Added 0.39.0
      changes:
        - addColumn:
            tableName: pulse
            columns:
              - column:
                  name: parameters
                  type: text
                  remarks: "Let dashboard subscriptions have their own filters"
                  constraints:
                    nullable: true
                    deferrable: false
                    initiallyDeferred: false
  - changeSet:
      id: 299
      author: tsmacdonald
      comment: Added 0.39.0
      changes:
        - addNotNullConstraint:
            columnDataType: text
            columnName: parameters
            defaultNullValue: '[]'
            tableName: pulse
  - changeSet:
      id: 300
      author: dpsutton
      comment: Added 0.40.0
      changes:
        - renameTable:
            oldTableName: collection_revision
            newTableName: collection_permission_graph_revision
  - changeSet:
      id: 301
      author: dpsutton
      comment: Added 0.40.0 renaming collection_revision to collection_permission_graph_revision
      failOnError: false # mysql and h2 don't have this sequence
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: postgresql
      changes:
        - sql:
            - sql: ALTER SEQUENCE collection_revision_id_seq RENAME TO collection_permission_graph_revision_id_seq

  - changeSet:
      id: 303
      author: tsmacdonald
      comment: Added 0.40.0
      changes:
        - createTable:
            tableName: moderation_review
            remarks: "Reviews (from moderators) for a given question/dashboard (BUCM)"
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: updated_at
                  type: ${timestamp_type}
                  defaultValueComputed: current_timestamp
                  remarks: "most recent modification time"
                  constraints:
                    nullable: false
              - column:
                  name: created_at
                  type: ${timestamp_type}
                  defaultValueComputed: current_timestamp
                  remarks: "creation time"
                  constraints:
                    nullable: false
              - column:
                  name: status
                  type: varchar(255)
                  remarks: "verified, misleading, confusing, not_misleading, pending"
              - column:
                  name: text
                  type: text
                  remarks: "Explanation of the review"
                  # I don't think it needs to be non-nullable
              - column:
                  name: moderated_item_id
                  type: int
                  remarks: "either a document or question ID; the item that needs review"
                  constraints:
                    nullable: false
              - column:
                  name: moderated_item_type
                  type: varchar(255)
                  remarks: "whether it's a question or dashboard"
                  constraints:
                    nullable: false
              - column:
                  name: moderator_id
                  type: int
                  remarks: "ID of the user who did the review"
                  constraints:
                    nullable: false
              - column:
                  name: most_recent
                  type: boolean
                  remarks: "tag for most recent review"
                  constraints:
                    nullable: false

  - changeSet:
      id: 304
      author: camsaul
      comment: Added 0.40.0 (replaces a data migration dating back to 0.20.0)
      changes:
        - sql:
              sql: >-
                UPDATE metabase_field
                SET semantic_type = (CASE semantic_type
                                      WHEN 'avatar'    THEN 'type/AvatarURL'
                                      WHEN 'category'  THEN 'type/Category'
                                      WHEN 'city'      THEN 'type/City'
                                      WHEN 'country'   THEN 'type/Country'
                                      WHEN 'desc'      THEN 'type/Description'
                                      WHEN 'fk'        THEN 'type/FK'
                                      WHEN 'id'        THEN 'type/PK'
                                      WHEN 'image'     THEN 'type/ImageURL'
                                      WHEN 'json'      THEN 'type/SerializedJSON'
                                      WHEN 'latitude'  THEN 'type/Latitude'
                                      WHEN 'longitude' THEN 'type/Longitude'
                                      WHEN 'name'      THEN 'type/Name'
                                      WHEN 'number'    THEN 'type/Number'
                                      WHEN 'state'     THEN 'type/State'
                                      WHEN 'url'       THEN 'type/URL'
                                      WHEN 'zip_code'  THEN 'type/ZipCode'
                                     END)
                WHERE semantic_type IN ('avatar', 'category', 'city', 'country', 'desc', 'fk', 'id', 'image',
                                        'json', 'latitude', 'longitude', 'name', 'number', 'state', 'url',
                                        'zip_code');

  - changeSet:
      id: 305
      author: camsaul
      comment: Added 0.40.0 (replaces a data migration dating back to 0.20.0)
      changes:
        - sql:
            sql: >-
              UPDATE metabase_field
              SET base_type = (CASE base_type
                                WHEN 'ArrayField'      THEN 'type/Array'
                                WHEN 'BigIntegerField' THEN 'type/BigInteger'
                                WHEN 'BooleanField'    THEN 'type/Boolean'
                                WHEN 'CharField'       THEN 'type/Text'
                                WHEN 'DateField'       THEN 'type/Date'
                                WHEN 'DateTimeField'   THEN 'type/DateTime'
                                WHEN 'DecimalField'    THEN 'type/Decimal'
                                WHEN 'DictionaryField' THEN 'type/Dictionary'
                                WHEN 'FloatField'      THEN 'type/Float'
                                WHEN 'IntegerField'    THEN 'type/Integer'
                                WHEN 'TextField'       THEN 'type/Text'
                                WHEN 'TimeField'       THEN 'type/Time'
                                WHEN 'UUIDField'       THEN 'type/UUID'
                                WHEN 'UnknownField'    THEN 'type/*'
                               END)
              WHERE base_type IN ('ArrayField', 'BigIntegerField', 'BooleanField', 'CharField', 'DateField',
                                  'DateTimeField', 'DecimalField', 'DictionaryField', 'FloatField', 'IntegerField',
                                  'TextField', 'TimeField', 'UUIDField', 'UnknownField');
  - changeSet:
      id: 308
      author: howonlee
      comment: Added 0.40.0 Track cache hits in query_execution table
      changes:
        - addColumn:
            tableName: query_execution
            columns:
              - column:
                  name: cache_hit
                  type: boolean
                  remarks: "Cache hit on query execution"
                  constraints:
                    nullable: true


  - changeSet:
      id: 309
      author: dpsutton
      comment: 'Added 0.40.0 - Add type to collections'
      changes:
        - addColumn:
            tableName: collection
            columns:
              - column:
                  name: authority_level
                  type: varchar(255)
                  remarks: 'Nullable column to incidate collection''s authority level. Initially values are "official" and nil.'
                  constraints:
                    nullable: true


  - changeSet:
      id: 311
      author: howonlee
      comment: Added 0.40.0 Migrate friendly field names, not noop
      validCheckSum: ANY # Quoting changes for H2.
      changes:
        - sql:
            dbms: mariadb,mysql
            sql: |
                UPDATE setting SET value='simple' WHERE `key`='humanization-strategy'
                AND value='advanced'
        - sql:
            dbms: postgresql
            sql: |
                UPDATE setting SET value='simple' WHERE key='humanization-strategy'
                AND value='advanced'
        - sql:
            dbms: h2
            sql: |
                UPDATE setting SET "VALUE"='simple' WHERE "KEY"='humanization-strategy'
                AND "VALUE"='advanced'

  - changeSet:
      id: 312
      author: noahmoss
      comment: Added 0.41.0 Backfill collection_id for dashboard subscriptions
      changes:
        - sql:
            dbms: mariadb,mysql
            sql: >-
              UPDATE pulse p
              INNER JOIN report_dashboard d
              ON p.dashboard_id = d.id
              SET p.collection_id = d.collection_id;
        - sql:
            dbms: postgresql
            sql: >-
              UPDATE pulse p
              SET collection_id = d.collection_id
              FROM report_dashboard d
              WHERE p.dashboard_id = d.id
              AND p.dashboard_id IS NOT NULL;
        - sql:
            dbms: h2
            sql: >-
              UPDATE pulse p
              SET collection_id = (
                SELECT d.collection_id
                FROM report_dashboard d
                WHERE d.id = p.dashboard_id
              )
              WHERE dashboard_id IS NOT NULL;

  - changeSet:
      id: 313
      author: jeff303
      comment: Added 0.42.0 - Secret domain object.
      validCheckSum: ANY
      changes:
        - createTable:
            tableName: secret
            remarks: Storage for managed secrets (passwords, binary data, etc.)
            columns:
              - column:
                  autoIncrement: true
                  constraints:
                    nullable: false
                    primaryKey: true
                  name: id
                  remarks: Part of composite primary key for secret; this is the uniquely generted ID column
                  type: int
              - column:
                  constraints:
                    nullable: false
                    primaryKey: true
                  name: version
                  defaultValue: 1
                  remarks: Part of composite primary key for secret; this is the version column
                  type: int
              - column:
                  constraints:
                    deferrable: false
                    foreignKeyName: fk_secret_ref_user_id
                    initiallyDeferred: false
                    nullable: true
                    referencedTableName: core_user
                    referencedColumnNames: id
                  name: creator_id
                  remarks: User ID who created this secret instance
                  type: int
              - column:
                  constraints:
                    nullable: false
                  name: created_at
                  remarks: Timestamp for when this secret instance was created
                  type: ${timestamp_type}
              - column:
                  constraints:
                    nullable: true
                  name: updated_at
                  remarks: >-
                    Timestamp for when this secret record was updated. Only relevant when non-value field changes
                    since a value change will result in a new version being inserted.
                  type: ${timestamp_type}
              - column:
                  constraints:
                    nullable: false
                  name: name
                  remarks: The name of this secret record.
                  type: varchar(254)
              - column:
                  constraints:
                    # TODO: do we want to constrain this field or leave open for extension? or separate table with FK?
                    nullable: false
                  name: kind
                  remarks: >-
                    The kind of secret this record represents; the value is interpreted as a Clojure keyword with a
                    hierarchy. Ex: 'bytes' means generic binary data, 'jks-keystore' extends 'bytes' but has a specific
                    meaning.
                  type: varchar(254)
              - column:
                  constraints:
                    # TODO: similar question to above?
                    nullable: true
                  name: source
                  remarks: >-
                    The source of secret record, which controls how Metabase interprets the value (ex: 'file-path'
                    means the 'simple_value' is not the real value, but a pointer to a file that contains the value).
                  type: varchar(254)
              - column:
                  constraints:
                    nullable: false
                  name: value
                  remarks: The base64 encoded binary value of this secret record. If encryption is enabled, this will
                    be the output of the encryption procedure on the plaintext. If not, it will be the base64 encoded
                    plaintext.
                  type: ${blob.type}

  - changeSet:
      id: 314
      author: howonlee
      comment: Added 0.41.0 Fine grained caching controls
      changes:
        - addColumn:
            tableName: metabase_database
            columns:
              - column:
                  name: cache_ttl
                  type: integer
                  remarks: "Granular cache TTL for specific database."
                  constraints:
                    nullable: true

  - changeSet:
      id: 315
      author: howonlee
      comment: Added 0.41.0 Fine grained caching controls, pt 2
      changes:
        - addColumn:
            tableName: report_dashboard
            columns:
              - column:
                  name: cache_ttl
                  type: integer
                  remarks: "Granular cache TTL for specific dashboard."
                  constraints:
                    nullable: true

  - changeSet:
      id: 316
      author: howonlee
      comment: Added 0.41.0 Fine grained caching controls, pt 3
      changes:
        - addColumn:
            tableName: view_log
            columns:
              - column:
                  name: metadata
                  type: text
                  remarks: "Serialized JSON corresponding to metadata for view."
                  constraints:
                    nullable: true

  - changeSet:
      id: 381
      author: camsaul
      comment: Added 0.41.2 Add index to QueryExecution card_id to fix performance issues (#18759)
      changes:
        - createIndex:
            tableName: query_execution
            indexName: idx_query_execution_card_id
            columns:
              - column:
                  name: card_id

  - changeSet:
      id: 382
      author: camsaul
      comment: Added 0.41.2 Add index to ModerationReview moderated_item_type + moderated_item_id to fix performance issues (#18759)
      changes:
        - createIndex:
            tableName: moderation_review
            indexName: idx_moderation_review_item_type_item_id
            columns:
              - column:
                  name: moderated_item_type
              - column:
                  name: moderated_item_id

  - changeSet:
      id: 383
      author: camsaul
      comment: Added 0.41.3 -- Add index to QueryExecution card_id + started_at to fix performance issue #19053
      changes:
        - createIndex:
            tableName: query_execution
            indexName: idx_query_execution_card_id_started_at
            columns:
              - column:
                  name: card_id
              - column:
                  name: started_at

  - changeSet:
      id: v42.00-000
      author: camsaul
      comment: Added 0.42.0 Remove unused column (#5240)
      # this migration was previously numbered 317 and merged into master before we adopted the 0.42.0+ migration ID
      # numbering scheme. See #18821 for more info.
      preConditions:
        - onFail: MARK_RAN
        - or:
            # For some insane reason databasechangelog is upper-case in MySQL and MariaDB.
            - and:
                - dbms:
                    type: postgresql,h2
                - sqlCheck:
                    expectedResult: 0
                    sql: SELECT count(*) FROM databasechangelog WHERE id = '317';
            - and:
                - dbms:
                    type: mysql,mariadb
                - sqlCheck:
                    expectedResult: 0
                    sql: SELECT count(*) FROM `DATABASECHANGELOG` WHERE id = '317';

      changes:
        - dropColumn:
            tableName: metabase_table
            columnName: entity_name


  - changeSet:
      id: v42.00-001
      author: camsaul
      comment: Added 0.42.0 Attempt to add Card.database_id (by parsing query) to rows that are missing it (#5999)
      # If this migration fails for any reason continue with the next migration; do not fail the entire process if this one fails
      failOnError: false
      # Don't run for H2 -- the version of H2 we're using doesn't support JSON stuff.
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: postgresql,mysql,mariadb
      # The basic idea below is to parse the `database_id` from the JSON string query dictionary and use it to set the
      # database_id column as needed. We do an INNER JOIN against the Database table to make sure that Database
      # actually exists (so we don't attempt to set an invalid database_id)
      changes:
        - sql:
            dbms: postgresql
            sql: >-
              WITH c2 AS (
                SELECT *, (dataset_query::json->>'database')::integer AS query_database_id
                FROM report_card
              )
              UPDATE report_card c
              SET database_id = c2.query_database_id
              FROM c2
              INNER JOIN metabase_database db
                ON db.id = c2.query_database_id
              WHERE c.database_id IS NULL
                AND c.id = c2.id
                AND c2.query_database_id IS NOT NULL;
        # MySQL and MariaDB are exactly the same other than different function names: json_value (for MariaDB) vs
        # json_extract (for MySQL)
        - sql:
            dbms: mariadb
            sql: >-
              UPDATE report_card c
              JOIN (
                SELECT *, cast(json_value(dataset_query, '$.database') AS signed) AS query_database_id
                FROM report_card
                ) c2
                ON c.id = c2.id
              INNER JOIN metabase_database db ON c2.query_database_id = db.id
              SET c.database_id = c2.query_database_id
              WHERE c.database_id IS NULL
                AND c2.query_database_id IS NOT NULL;
        - sql:
            dbms: mysql
            sql: >-
              UPDATE report_card c
              JOIN (
                SELECT *, cast(json_extract(dataset_query, '$.database') AS signed) AS query_database_id
                FROM report_card
                ) c2
                ON c.id = c2.id
              INNER JOIN metabase_database db ON c2.query_database_id = db.id
              SET c.database_id = c2.query_database_id
              WHERE c.database_id IS NULL
                AND c2.query_database_id IS NOT NULL;

  - changeSet:
      id: v42.00-002
      author: camsaul
      comment: Added 0.42.0 Added constraint we should have had all along (#5999)
      preConditions:
        - onFail: MARK_RAN
        # If we're dumping the migration as a SQL file or trying to force-migrate we can't check the preconditions
        # so just go ahead and skip the entire thing. This is a non-critical migration
        - onUpdateSQL: IGNORE
        - sqlCheck:
            expectedResult: 0
            sql: SELECT count(*) FROM report_card WHERE database_id IS NULL
      changes:
        - addNotNullConstraint:
            columnDataType: int
            tableName: report_card
            columnName: database_id

  - changeSet:
      id: v42.00-003
      author: dpsutton
      comment: Added 0.42.0 Initial support for datasets based on questions
      # this migration was previously numbered 320 and merged into master before we adopted the 0.42.0+ migration ID
      # numbering scheme. See #18821 for more info.
      preConditions:
        - onFail: MARK_RAN
        - or:
            - and:
                - dbms:
                    type: postgresql,h2
                - sqlCheck:
                    expectedResult: 0
                    sql: SELECT count(*) FROM databasechangelog WHERE id = '320';
            - and:
                - dbms:
                    type: mysql,mariadb
                - sqlCheck:
                    expectedResult: 0
                    sql: SELECT count(*) FROM `DATABASECHANGELOG` WHERE id = '320';
      changes:
        - addColumn:
            tableName: report_card
            columns:
              - column:
                  name: dataset
                  type: boolean
                  remarks: "Indicate whether question is a dataset"
                  constraints:
                    nullable: false
                  defaultValue: false

  - changeSet:    # this one is run unconditionally so unify the type to ${text.type} across ALL dbs
      id: v42.00-004 # this differentiation was first done under changeSet 13 above
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of activity.details from text to ${text.type}
      changes:
        - modifyDataType:
            tableName: activity
            columnName: details
            newDataType: ${text.type}

  - changeSet:
      id: v42.00-005
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of collection.description from text to ${text.type}
        on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: collection
            columnName: description
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-006
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of collection.name from text to ${text.type}
        on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: collection
            columnName: name
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-007
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of computation_job.context from text to ${text.type}
        on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: computation_job
            columnName: context
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-008
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of computation_job_result.payload from text
        to ${text.type} on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: computation_job_result
            columnName: payload
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-009
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of core_session.anti_csrf_token from text
        to ${text.type} on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: core_session
            columnName: anti_csrf_token
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-010
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of core_user.login_attributes from text to
        ${text.type} on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: core_user
            columnName: login_attributes
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-011
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of group_table_access_policy.attribute_remappings
        from text to ${text.type} on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: group_table_access_policy
            columnName: attribute_remappings
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-012
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of login_history.device_description from text
        to ${text.type} on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: login_history
            columnName: device_description
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-013
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of login_history.ip_address from text to ${text.type}
        on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: login_history
            columnName: ip_address
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-014
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of metabase_database.caveats from text to
        ${text.type} on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: metabase_database
            columnName: caveats
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-015
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of metabase_database.description from text
        to ${text.type} on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: metabase_database
            columnName: description
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-016
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of metabase_database.details from text to
        ${text.type} on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: metabase_database
            columnName: details
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-017
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of metabase_database.options from text to
        ${text.type} on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: metabase_database
            columnName: options
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-018
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of metabase_database.points_of_interest from
        text to ${text.type} on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: metabase_database
            columnName: points_of_interest
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-019
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of metabase_field.caveats from text to ${text.type}
        on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: metabase_field
            columnName: caveats
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-020
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of metabase_field.database_type from text
        to ${text.type} on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: metabase_field
            columnName: database_type
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-021
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of metabase_field.description from text to
        ${text.type} on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: metabase_field
            columnName: description
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-022
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of metabase_field.fingerprint from text to
        ${text.type} on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: metabase_field
            columnName: fingerprint
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-023
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of metabase_field.has_field_values from text
        to ${text.type} on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: metabase_field
            columnName: has_field_values
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-024
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of metabase_field.points_of_interest from
        text to ${text.type} on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: metabase_field
            columnName: points_of_interest
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-025
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of metabase_field.settings from text to ${text.type}
        on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: metabase_field
            columnName: settings
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-026
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of metabase_fieldvalues.human_readable_values
        from text to ${text.type} on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: metabase_fieldvalues
            columnName: human_readable_values
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-027
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of metabase_fieldvalues.values from text to
        ${text.type} on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: metabase_fieldvalues
            columnName: values
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-028
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of metabase_table.caveats from text to ${text.type}
        on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: metabase_table
            columnName: caveats
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-029
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of metabase_table.description from text to
        ${text.type} on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: metabase_table
            columnName: description
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-030
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of metabase_table.points_of_interest from
        text to ${text.type} on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: metabase_table
            columnName: points_of_interest
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-031
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of metric.caveats from text to ${text.type}
        on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: metric
            columnName: caveats
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-032
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of metric.definition from text to ${text.type}
        on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: metric
            columnName: definition
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-033
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of metric.description from text to ${text.type}
        on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: metric
            columnName: description
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-034
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of metric.how_is_this_calculated from text
        to ${text.type} on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: metric
            columnName: how_is_this_calculated
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-035
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of metric.points_of_interest from text to
        ${text.type} on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: metric
            columnName: points_of_interest
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-036
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of moderation_review.text from text to ${text.type}
        on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: moderation_review
            columnName: text
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-037
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of native_query_snippet.content from text
        to ${text.type} on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: native_query_snippet
            columnName: content
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-038
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of native_query_snippet.description from text
        to ${text.type} on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: native_query_snippet
            columnName: description
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-039
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of pulse.parameters from text to ${text.type}
        on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: pulse
            columnName: parameters
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-040
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of pulse_channel.details from text to ${text.type}
        on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: pulse_channel
            columnName: details
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-041
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of query.query from text to ${text.type} on
        mysql,mariadb
      changes:
        - modifyDataType:
            tableName: query
            columnName: query
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-042
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of query_execution.error from text to ${text.type}
        on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: query_execution
            columnName: error
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-043
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of report_card.dataset_query from text to
        ${text.type} on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: report_card
            columnName: dataset_query
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-044
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of report_card.description from text to ${text.type}
        on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: report_card
            columnName: description
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-045
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of report_card.embedding_params from text
        to ${text.type} on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: report_card
            columnName: embedding_params
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-046
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of report_card.result_metadata from text to
        ${text.type} on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: report_card
            columnName: result_metadata
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-047
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of report_card.visualization_settings from
        text to ${text.type} on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: report_card
            columnName: visualization_settings
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-048
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of report_dashboard.caveats from text to ${text.type}
        on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: report_dashboard
            columnName: caveats
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-049
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of report_dashboard.description from text
        to ${text.type} on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: report_dashboard
            columnName: description
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-050
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of report_dashboard.embedding_params from
        text to ${text.type} on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: report_dashboard
            columnName: embedding_params
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-051
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of report_dashboard.parameters from text to
        ${text.type} on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: report_dashboard
            columnName: parameters
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-052
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of report_dashboard.points_of_interest from
        text to ${text.type} on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: report_dashboard
            columnName: points_of_interest
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-053
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of report_dashboardcard.parameter_mappings
        from text to ${text.type} on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: report_dashboardcard
            columnName: parameter_mappings
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-054
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of report_dashboardcard.visualization_settings
        from text to ${text.type} on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: report_dashboardcard
            columnName: visualization_settings
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-055
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of revision.message from text to ${text.type}
        on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: revision
            columnName: message
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:    # this one is run unconditionally so unify the type to ${text.type} across ALL dbs
      id: v42.00-056 # this differentiation was first done under changeSet 10 above
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of revision.object from text to ${text.type}
      changes:
        - modifyDataType:
            tableName: revision
            columnName: object
            newDataType: ${text.type}

  - changeSet:
      id: v42.00-057
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of segment.caveats from text to ${text.type}
        on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: segment
            columnName: caveats
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-058
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of segment.definition from text to ${text.type}
        on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: segment
            columnName: definition
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-059
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of segment.description from text to ${text.type}
        on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: segment
            columnName: description
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-060
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of segment.points_of_interest from text to
        ${text.type} on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: segment
            columnName: points_of_interest
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-061
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of setting.value from text to ${text.type}
        on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: setting
            columnName: value
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-062
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of task_history.task_details from text to
        ${text.type} on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: task_history
            columnName: task_details
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-063
      author: jeff303
      comment: >-
        Added 0.42.0 - modify type of view_log.metadata from text to ${text.type}
        on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: view_log
            columnName: metadata
            newDataType: ${text.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v42.00-064
      author: jeff303
      comment: "Added 0.42.0 - fix type of query_cache.results on upgrade (in case changeSet 97 was run before #16095)"
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb
      changes:
        - modifyDataType:
            tableName: query_cache
            columnName: results
            newDataType: longblob

  - changeSet:
      id: v42.00-065
      author: dpsutton
      comment: >-
        Added 0.42.0 - Another modal dismissed state on user. Retaining the same suffix and boolean style to ease an
        eventual migration.
      changes:
        - addColumn:
            tableName: core_user
            columns:
              - column:
                  name: is_datasetnewb
                  type: boolean
                  remarks: "Boolean flag to indicate if the dataset info modal has been dismissed."
                  defaultValueBoolean: true
                  constraints:
                    nullable: false

  - changeSet:
      id: v42.00-066
      author: noahmoss
      comment: >-
        Added 0.42.0 - new columns for initial DB sync progress UX. Indicates whether a database has succesfully synced
        at least one time.
      changes:
        - addColumn:
            tableName: metabase_database
            columns:
              - column:
                  name: initial_sync_status
                  type: varchar(32)
                  remarks: "String indicating whether a database has completed its initial sync and is ready to use"
                  defaultValue: "complete"
                  constraints:
                    nullable: false

  - changeSet:
      id: v42.00-067
      author: noahmoss
      comment: >-
        Added 0.42.0 - new columns for initial DB sync progress UX. Indicates whether a table has succesfully synced
        at least one time.
      changes:
        - addColumn:
            tableName: metabase_table
            columns:
              - column:
                  name: initial_sync_status
                  type: varchar(32)
                  remarks: "String indicating whether a table has completed its initial sync and is ready to use"
                  defaultValue: "complete"
                  constraints:
                    nullable: false

  - changeSet:
      id: v42.00-068
      author: noahmoss
      comment: >-
        Added 0.42.0 - new columns for initial DB sync progress UX. Records the ID of the admin who added a database.
        May be null for the sample dataset, or for databases added prior to 0.42.0.
      changes:
        - addColumn:
            tableName: metabase_database
            columns:
              - column:
                  name: creator_id
                  type: int
                  remarks: "ID of the admin who added the database"
                  constraints:
                    nullable: true

  - changeSet:
      id: v42.00-069
      author: noahmoss
      comment: >-
        Added 0.42.0 - adds FK constraint for creator_id column, containing the ID of the admin who added a database.
      changes:
        - addForeignKeyConstraint:
            baseTableName: metabase_database
            baseColumnNames: creator_id
            referencedTableName: core_user
            referencedColumnNames: id
            constraintName: fk_database_creator_id
            onDelete: SET NULL

  - changeSet:
      id: v42.00-070
      author: camsaul
      comment: >-
        Added 0.42.0 - add Database.settings column to implement Database-local Settings
      # This migration was originally misnumbered, so now that it has a correct number it may get triggered a second
      # time. That's fine
      preConditions:
        - onFail: MARK_RAN
        - not:
            - columnExists:
                tableName: metabase_database
                columnName: settings
      changes:
        - addColumn:
            tableName: metabase_database
            columns:
              - column:
                  name: settings
                  type: ${text.type}
                  remarks: "Serialized JSON containing Database-local Settings for this Database"

  - changeSet:
      id: v42.00-071
      author: noahmoss
      comment: >-
        Added 0.42.0 - migrates the Sample Dataset to the name "Sample Database"
      changes:
        - sql:
            sql: UPDATE metabase_database SET name='Sample Database' WHERE is_sample=true

  - changeSet:
      id: v43.00-001
      author: jeff303
      comment: >-
        Added 0.43.0 - migrates any Database using the old bigquery driver to bigquery-cloud-sdk instead
      changes:
        - sql:
            sql: UPDATE metabase_database SET engine = 'bigquery-cloud-sdk' WHERE engine = 'bigquery'


  #
  # The next few migrations replace metabase.db.data-migrations/add-users-to-default-permissions-groups from 0.20.0
  #

  # Create the magic Permissions Groups if they don't already exist.

  # [add-users-to-default-permissions-groups 1 of 4]
  - changeSet:
      id: v43.00-002
      author: camsaul
      comment: >-
        Added 0.43.0. Create magic 'All Users' Permissions Group if it does not already exist.
      preConditions:
        - onFail: MARK_RAN
        - sqlCheck:
            expectedResult: 0
            sql: >-
              SELECT count(*) FROM permissions_group WHERE name = 'All Users';
      changes:
        - sql:
            sql: >-
              INSERT INTO permissions_group (name)
              VALUES
              ('All Users')

  # [add-users-to-default-permissions-groups 2 of 4]
  - changeSet:
      id: v43.00-003
      author: camsaul
      comment: >-
        Added 0.43.0. Create magic 'Administrators' Permissions Group if it does not already exist.
      preConditions:
        - onFail: MARK_RAN
        - sqlCheck:
            expectedResult: 0
            sql: >-
              SELECT count(*) FROM permissions_group WHERE name = 'Administrators';
      changes:
        - sql:
            sql: >-
              INSERT INTO permissions_group (name)
              VALUES
              ('Administrators')

  # Add existing Users to the magic Permissions Groups if needed.

  # [add-users-to-default-permissions-groups 3 of 4]
  - changeSet:
      id: v43.00-004
      author: camsaul
      comment: >-
        Added 0.43.0. Add existing Users to 'All Users' magic Permissions Group if needed.
      changes:
        - sql:
            sql: >-
              INSERT INTO permissions_group_membership (user_id, group_id)
              SELECT
                u.id AS user_id,
                all_users_group.id AS group_id
                FROM core_user u
                LEFT JOIN (
                  SELECT *
                  FROM permissions_group
                  WHERE name = 'All Users'
                ) all_users_group
                  ON true
                LEFT JOIN permissions_group_membership pgm
                       ON u.id = pgm.user_id
                      AND all_users_group.id = pgm.group_id
                WHERE pgm.id IS NULL;

  # [add-users-to-default-permissions-groups 4 of 4]
  - changeSet:
      id: v43.00-005
      author: camsaul
      comment: >-
        Added 0.43.0. Add existing Users with 'is_superuser' flag to 'Administrators' magic Permissions Group if needed.
      changes:
        - sql:
            sql: >-
              INSERT INTO permissions_group_membership (user_id, group_id)
              SELECT
                u.id AS user_id,
                admin_group.id AS group_id
                FROM core_user u
                LEFT JOIN (
                  SELECT *
                  FROM permissions_group
                  WHERE name = 'Administrators'
                ) admin_group
                  ON true
                LEFT JOIN permissions_group_membership pgm
                       ON u.id = pgm.user_id
                      AND admin_group.id = pgm.group_id
                WHERE u.is_superuser = true
                  AND pgm.id IS NULL;

  #
  # This migration replaces metabase.db.data-migrations/add-admin-group-root-entry, added 0.20.0
  #
  # Create root permissions entry for admin magic Permissions Group. Admin Group has a single entry that lets it
  # access to everything
  - changeSet:
      id: v43.00-006
      author: camsaul
      comment: >-
        Added 0.43.0. Create root '/' permissions entry for the 'Administrators' magic Permissions Group if needed.
      changes:
        - sql:
            sql: >-
              INSERT INTO permissions (group_id, object)
              SELECT
                admin_group.id AS group_id,
                '/' AS object
              FROM (
                SELECT id
                FROM permissions_group
                WHERE name = 'Administrators'
              ) admin_group
              LEFT JOIN permissions p
                     ON admin_group.id = p.group_id
                    AND p.object = '/'
              WHERE p.object IS NULL;

  #
  # The following migration replaces metabase.db.data-migrations/add-databases-to-magic-permissions-groups, added 0.20.0
  #

  # Add permissions entries for 'All Users' for all Databases created BEFORE we created the 'All Users' Permissions
  # Group. This replaces the old 'add-databases-to-magic-permissions-groups' Clojure-land data migration. Only run
  # this migration if that one hasn't been run yet.
  - changeSet:
      id: v43.00-007
      author: camsaul
      comment: >-
        Added 0.43.0. Grant permissions for existing Databases to 'All Users' permissions group.
      preConditions:
        - onFail: MARK_RAN
        - sqlCheck:
            expectedResult: 0
            sql: >-
              SELECT count(*)
              FROM data_migrations
              WHERE id = 'add-databases-to-magic-permissions-groups';
      changes:
        - sql:
            sql: >-
              INSERT INTO permissions (object, group_id)
              SELECT db.object, all_users.id AS group_id
              FROM (
                SELECT concat('/db/', id, '/') AS object
                FROM metabase_database
              ) db
              LEFT JOIN (
                SELECT id
                FROM permissions_group
                WHERE name = 'All Users'
              ) all_users
                ON true
              LEFT JOIN permissions p
                     ON p.group_id = all_users.id
                    AND db.object = p.object
              WHERE p.object IS NULL;

  #
  # The following migration replaces metabase.db.migrations/copy-site-url-setting-and-remove-trailing-slashes, added 0.23.0
  #
  # Copy the value of the old setting `-site-url` to the new `site-url` if applicable. (`site-url` used to be stored
  # internally as `-site-url`; this was confusing, see #4188 for details.) Make sure `site-url` has no trailing slashes
  # originally fixed in #4123.
  - changeSet:
      id: v43.00-008
      author: camsaul
      comment: >-
        Added 0.43.0. Migrate legacy '-site-url' Setting to 'site-url'. Trim trailing slashes.
      validCheckSum: ANY # Quoting changes in H2 don't need to be re-run
      preConditions:
        - onFail: MARK_RAN
        - or:
            - and:
                - dbms:
                    type: postgresql
                - sqlCheck:
                    expectedResult: 0
                    sql: SELECT count(*) FROM setting WHERE key = 'site-url';
            - and:
                - dbms:
                    type: h2
                - sqlCheck:
                    expectedResult: 0
                    sql: SELECT count(*) FROM setting WHERE "KEY" = 'site-url';
            - and:
                - dbms:
                    type: mysql,mariadb
                - sqlCheck:
                    expectedResult: 0
                    sql: SELECT count(*) FROM setting WHERE `key` = 'site-url';
      changes:
        - sql:
            dbms: h2
            sql: >-
              INSERT INTO setting ("KEY", "VALUE")
              SELECT
                'site-url' AS "KEY",
                regexp_replace("VALUE", '/$', '') AS "VALUE"
              FROM setting
              WHERE "KEY" = '-site-url';
        - sql:
            dbms: postgresql
            sql: >-
              INSERT INTO setting (key, value)
              SELECT
                'site-url' AS key,
                regexp_replace(value, '/$', '') AS value
              FROM setting
              WHERE key = '-site-url';
        - sql:
            dbms: mysql,mariadb
            # MySQL 5.7 doesn't support regexp_replace :(
            # 'key' has to be quoted in MySQL
            sql: >-
              INSERT INTO setting (`key`, value)
              SELECT
                'site-url' AS `key`,
                CASE
                  WHEN value LIKE '%/'
                    THEN substring(value, 1, length(value) - 1)
                  ELSE
                    value
                  END
                AS value
              FROM setting
              WHERE `key` = '-site-url';

  #
  # The following migration replaces metabase.db.migrations/ensure-protocol-specified-in-site-url, added in 0.25.1
  #
  # There's a window on in the 0.23.0 and 0.23.1 releases that the site-url could be persisted without a protocol
  # specified. Other areas of the application expect that site-url will always include http/https. This migration
  # ensures that if we have a site-url stored it has the current defaulting logic applied to it
  - changeSet:
      id: v43.00-009
      author: camsaul
      comment: >-
        Added 0.43.0. Make sure 'site-url' Setting includes protocol.
      validCheckSum: ANY # Quoting changes in H2 don't need to be re-run
      changes:
        - sql:
            dbms: postgresql
            sql: >-
              UPDATE setting
              SET value = concat('http://', value)
              WHERE key = 'site-url'
                AND value NOT LIKE 'http%';
        - sql:
            dbms: h2
            sql: >-
              UPDATE setting
              SET "VALUE" = concat('http://', "VALUE")
              WHERE "KEY" = 'site-url'
                AND "VALUE" NOT LIKE 'http%';
        - sql:
            dbms: mysql,mariadb
            sql: >-
              UPDATE setting
              SET value = concat('http://', value)
              WHERE `key` = 'site-url'
                AND value NOT LIKE 'http%';

  #
  # The following migrations replace metabase.db.migrations/migrate-humanization-setting, added in 0.28.0
  #
  # Prior to version 0.28.0 humanization was configured using the boolean setting `enable-advanced-humanization`.
  # `true` meant "use advanced humanization", while `false` meant "use simple humanization". In 0.28.0, this Setting
  # was replaced by the `humanization-strategy` Setting, which (at the time of this writing) allows for a choice
  # between three options: advanced, simple, or none. Migrate any values of the old Setting, if set, to the new one.

  # [migrate-humanization-setting part 1 of 2]
  - changeSet:
      id: v43.00-010
      author: camsaul
      comment: >-
        Added 0.43.0. Migrates value of legacy enable-advanced-humanization Setting to humanization-strategy Setting added in 0.28.0.
      validCheckSum: ANY # Quoting changes in H2 don't need to be re-run
      preConditions:
        - onFail: MARK_RAN
        - or:
            - and:
                - dbms:
                    type: postgresql
                - sqlCheck:
                    expectedResult: 0
                    sql: SELECT count(*) FROM setting WHERE key = 'humanization-strategy';
            - and:
                - dbms:
                    type: h2
                - sqlCheck:
                    expectedResult: 0
                    sql: SELECT count(*) FROM setting WHERE "KEY" = 'humanization-strategy';
            - and:
                - dbms:
                    type: mysql,mariadb
                - sqlCheck:
                    expectedResult: 0
                    sql: SELECT count(*) FROM setting WHERE `key` = 'humanization-strategy';
      changes:
        - sql:
            dbms: postgresql
            sql: >-
              INSERT INTO setting (key, value)
              SELECT
                'humanization-strategy'                                      AS key,
                (CASE WHEN value = 'true' THEN 'advanced' ELSE 'simple' END) AS value
              FROM setting
              WHERE key = 'enable-advanced-humanization';
        # key and value have to be quoted in H2
        - sql:
            dbms: h2
            sql: >-
              INSERT INTO setting ("KEY", "VALUE")
              SELECT
                'humanization-strategy'                                      AS "KEY",
                (CASE WHEN "VALUE" = 'true' THEN 'advanced' ELSE 'simple' END) AS "VALUE"
              FROM setting
              WHERE "KEY" = 'enable-advanced-humanization';
        # key has to be quoted in MySQL/MariaDB
        - sql:
            dbms: mysql,mariadb
            sql: >-
              INSERT INTO setting (`key`, value)
              SELECT
                'humanization-strategy'                                      AS `key`,
                (CASE WHEN value = 'true' THEN 'advanced' ELSE 'simple' END) AS value
              FROM setting
              WHERE `key` = 'enable-advanced-humanization';

  # [migrate-humanization-setting part 2 of 2]
  - changeSet:
      id: v43.00-011
      author: camsaul
      comment: >-
        Added 0.43.0. Remove legacy enable-advanced-humanization Setting.
      validCheckSum: ANY # Quoting changes in H2 don't need to be re-run
      changes:
        - sql:
            dbms: postgresql
            sql: >-
              DELETE FROM setting WHERE key = 'enable-advanced-humanization';
        # key has to be quoted in H2
        - sql:
            dbms: h2
            sql: >-
              DELETE FROM setting WHERE "KEY" = 'enable-advanced-humanization';
        # key has to be quoted in MySQL/MariaDB
        - sql:
            dbms: mysql,mariadb
            sql: >-
              DELETE FROM setting WHERE `key` = 'enable-advanced-humanization';

  #
  # The following migration replaces metabase.db.migrations/mark-category-fields-as-list, added in 0.29.0
  #
  # Starting in version 0.29.0 we switched the way we decide which Fields should get FieldValues. Prior to 29, Fields
  # would be marked as special type Category if they should have FieldValues. In 29+, the Category special type no
  # longer has any meaning as far as the backend is concerned. Instead, we use the new `has_field_values` column to
  # keep track of these things. Fields whose value for `has_field_values` is `list` is the equiavalent of the old
  # meaning of the Category special type.
  #
  # Note that in 0.39.0 special type was renamed to semantic type
  - changeSet:
      id: v43.00-012
      author: camsaul
      comment: >-
        Added 0.43.0. Set Field.has_field_values to 'list' if semantic_type derives from :type/Category.
      preConditions:
        - onFail: MARK_RAN
        - sqlCheck:
            expectedResult: 0
            sql: >-
              SELECT count(*)
              FROM data_migrations
              WHERE id = 'mark-category-fields-as-list';
      changes:
        - sql:
            # This is a snapshot of all the descendants of `:type/Category` at the time this migration was written. We
            # don't need to worry about new types being added in the future, since the purpose of this migration is
            # only to update old columns.
            sql: >-
              UPDATE metabase_field
              SET has_field_values = 'list'
              WHERE has_field_values IS NULL
                AND active = true
                AND semantic_type IN (
                  'type/Category',
                  'type/City',
                  'type/Company',
                  'type/Country',
                  'type/Name',
                  'type/Product',
                  'type/Source',
                  'type/State',
                  'type/Subscription',
                  'type/Title'
                );

  #
  # The following migrations replace metabase.db.migrations/add-migrated-collections, added in 0.30.0
  #
  # In 0.30 dashboards and pulses will be saved in collections rather than on separate list pages. Additionally, there
  # will no longer be any notion of saved questions existing outside of a collection (i.e. in the weird "Everything
  # Else" area where they can currently be saved).
  #
  # Consequently we'll need to move existing dashboards, pulses, and questions-not-in-a-collection to a new location
  # when users upgrade their instance to 0.30 from a previous version.
  #
  # The user feedback we've received points to a UX that would do the following:
  #
  # 1. Set permissions to the Root Collection to readwrite perms access for *all* Groups.
  #
  # 2. Create three new collections within the root collection: "Migrated dashboards," "Migrated pulses," and "Migrated
  #    questions."
  #
  # 3. The permissions settings for these new collections should be set to No Access for all user groups except
  #    Administrators.
  #
  # 4. Existing Dashboards, Pulses, and Questions from the "Everything Else" area should now be present within these
  #    new collections.

  # [add-migrated-collections part 1 of 7] Create 'Migrated Dashboards' Collection if needed
  - changeSet:
      id: v43.00-014
      author: camsaul
      comment: >-
        Added 0.43.0. Add 'Migrated Dashboards' Collection if needed and there are any Dashboards not in a Collection.
      preConditions:
        - onFail: MARK_RAN
        - and:
            - sqlCheck:
                expectedResult: 0
                sql: >-
                  SELECT count(*)
                  FROM data_migrations
                  WHERE id = 'add-migrated-collections';
            - sqlCheck:
                expectedResult: 0
                sql: >-
                  SELECT count(*)
                  FROM collection
                  WHERE name = 'Migrated Dashboards';
            - not:
                - sqlCheck:
                    expectedResult: 0
                    sql: >-
                      SELECT count(*)
                      FROM report_dashboard
                      WHERE collection_id IS NULL;
      changes:
        - sql:
            # #509ee3 is the MB brand color
            sql: >-
              INSERT INTO collection (name, color, slug)
              VALUES
              ('Migrated Dashboards', '#509ee3', 'migrated_dashboards');

  # [add-migrated-collections part 2 of 7] Create 'Migrated Pulses' Collection if needed
  - changeSet:
      id: v43.00-015
      author: camsaul
      comment: >-
        Added 0.43.0. Add 'Migrated Pulses' Collection if needed and there are any Pulses not in a Collection.
      preConditions:
        - onFail: MARK_RAN
        - and:
            - sqlCheck:
                expectedResult: 0
                sql: >-
                  SELECT count(*)
                  FROM data_migrations
                  WHERE id = 'add-migrated-collections';
            - sqlCheck:
                expectedResult: 0
                sql: >-
                  SELECT count(*)
                  FROM collection
                  WHERE name = 'Migrated Pulses';
            - not:
                - sqlCheck:
                    expectedResult: 0
                    sql: >-
                      SELECT count(*)
                      FROM pulse
                      WHERE collection_id IS NULL;
      changes:
        - sql:
            # #509ee3 is the MB brand color
            sql: >-
              INSERT INTO collection (name, color, slug)
              VALUES
              ('Migrated Pulses', '#509ee3', 'migrated_pulses');

  # [add-migrated-collections part 3 of 7] Create 'Migrated Questions' Collection if needed
  - changeSet:
      id: v43.00-016
      author: camsaul
      comment: >-
        Added 0.43.0. Add 'Migrated Questions' Collection if needed and there are any Cards not in a Collection.
      preConditions:
        - onFail: MARK_RAN
        - and:
            - sqlCheck:
                expectedResult: 0
                sql: >-
                  SELECT count(*)
                  FROM data_migrations
                  WHERE id = 'add-migrated-collections';
            - sqlCheck:
                expectedResult: 0
                sql: >-
                  SELECT count(*)
                  FROM collection
                  WHERE name = 'Migrated Questions';
            - not:
                - sqlCheck:
                    expectedResult: 0
                    sql: >-
                      SELECT count(*)
                      FROM report_card
                      WHERE collection_id IS NULL;
      changes:
        - sql:
            # #509ee3 is the MB brand color
            sql: >-
              INSERT INTO collection (name, color, slug)
              VALUES
              ('Migrated Questions', '#509ee3', 'migrated_questions');

  # [add-migrated-collections part 4 of 7] Move Dashboards not in a Collection to 'Migrated Dashboards'
  - changeSet:
      id: v43.00-017
      author: camsaul
      comment: >-
        Added 0.43.0. Move Dashboards not in a Collection to 'Migrated Dashboards'.
      preConditions:
        - onFail: MARK_RAN
        - sqlCheck:
            expectedResult: 0
            sql: >-
              SELECT count(*)
              FROM data_migrations
              WHERE id = 'add-migrated-collections';
      changes:
        - sql:
            sql: >-
              UPDATE report_dashboard
              SET collection_id = (SELECT id FROM collection WHERE name = 'Migrated Dashboards')
              WHERE collection_id IS NULL;


  # [add-migrated-collections part 5 of 7] Move Pulses not in a Collection to 'Migrated Pulses'
  - changeSet:
      id: v43.00-018
      author: camsaul
      comment: >-
        Added 0.43.0. Move Pulses not in a Collection to 'Migrated Pulses'.
      preConditions:
        - onFail: MARK_RAN
        - sqlCheck:
            expectedResult: 0
            sql: >-
              SELECT count(*)
              FROM data_migrations
              WHERE id = 'add-migrated-collections';
      changes:
        - sql:
            sql: >-
              UPDATE pulse
              SET collection_id = (SELECT id FROM collection WHERE name = 'Migrated Pulses')
              WHERE collection_id IS NULL;

  # [add-migrated-collections part 6 of 7] Move Cards not in a Collection to 'Migrated Questions'
  - changeSet:
      id: v43.00-019
      author: camsaul
      comment: >-
        Added 0.43.0. Move Cards not in a Collection to 'Migrated Questions'.
      preConditions:
        - onFail: MARK_RAN
        - sqlCheck:
            expectedResult: 0
            sql: >-
              SELECT count(*)
              FROM data_migrations
              WHERE id = 'add-migrated-collections';
      changes:
        - sql:
            sql: >-
              UPDATE report_card
              SET collection_id = (SELECT id FROM collection WHERE name = 'Migrated Questions')
              WHERE collection_id IS NULL;

  # [add-migrated-collections part 7 of 7] Grant All Users readwrite perms for the Root Collection.
  - changeSet:
      id: v43.00-020
      author: camsaul
      comment: >-
        Added 0.43.0. Grant the 'All Users' Permissions Group readwrite perms for the Root Collection.
      preConditions:
        - onFail: MARK_RAN
        - and:
            - sqlCheck:
                expectedResult: 0
                sql: >-
                  SELECT count(*)
                  FROM data_migrations
                  WHERE id = 'add-migrated-collections';
      changes:
        - sql:
            sql: >-
              INSERT INTO permissions (group_id, object)
              SELECT
                all_users_group.id AS group_id,
                '/collection/root/' AS object
              FROM (
                SELECT id
                FROM permissions_group
                WHERE name = 'All Users'
              ) all_users_group
              LEFT JOIN permissions p
                     ON all_users_group.id = p.group_id
                    AND p.object = '/collection/root/'
              WHERE p.object IS NULL;

  - changeSet:
      id: v43.00-021
      author: adam-james
      comment: Added 0.43.0 - Timeline table for Events
      changes:
        - createTable:
            tableName: timeline
            remarks: Timeline table to organize events
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    nullable: false
                    primaryKey: true
              - column:
                  remarks: Name of the timeline
                  name: name
                  type: varchar(255)
                  constraints:
                    nullable: false
              - column:
                  remarks: Optional description of the timeline
                  name: description
                  type: varchar(255)
                  constraints:
                    nullable: true
              - column:
                  name: icon
                  type: varchar(128)
                  constraints:
                    nullable: true
                  remarks: the icon to use when displaying the event
              - column:
                  remarks: ID of the collection containing the timeline
                  name: collection_id
                  type: int
                  constraints:
                    nullable: true
                    references: collection(id)
                    foreignKeyName: fk_timeline_collection_id
                    deleteCascade: true
              - column:
                  remarks: Whether or not the timeline has been archived
                  name: archived
                  type: boolean
                  defaultValueBoolean: false
                  constraints:
                    nullable: false
              - column:
                  remarks: ID of the user who created the timeline
                  name: creator_id
                  type: int
                  constraints:
                    nullable: false
                    references: core_user(id)
                    foreignKeyName: fk_timeline_creator_id
                    deleteCascade: true
              - column:
                  remarks: The timestamp of when the timeline was created
                  name: created_at
                  type: ${timestamp_type}
                  defaultValueComputed: current_timestamp
                  constraints:
                    nullable: false
              - column:
                  remarks: The timestamp of when the timeline was updated
                  name: updated_at
                  type: ${timestamp_type}
                  defaultValueComputed: current_timestamp
                  constraints:
                    nullable: false

  - changeSet:
      id: v43.00-022
      author: adam-james
      comment: Added 0.43.0 - Events table
      changes:
        - createTable:
            tableName: timeline_event
            remarks: Events table
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    nullable: false
                    primaryKey: true
              - column:
                  remarks: ID of the timeline containing the event
                  name: timeline_id
                  type: int
                  constraints:
                    nullable: false
                    references: timeline(id)
                    foreignKeyName: fk_events_timeline_id
                    deleteCascade: true
              - column:
                  remarks: Name of the event
                  name: name
                  type: varchar(255)
                  constraints:
                    nullable: false
              - column:
                  remarks: Optional markdown description of the event
                  name: description
                  type: varchar(255)
                  constraints:
                    nullable: true
              - column:
                  name: timestamp
                  type: ${timestamp_type}
                  constraints:
                    nullable: false
                  remarks: When the event happened
              - column:
                  name: time_matters
                  type: boolean
                  constraints:
                    nullable: false
                  remarks: >-
                     Indicate whether the time component matters or if the timestamp should just serve to indicate the
                     day of the event without any time associated to it.
              - column:
                  name: timezone
                  constraints:
                    nullable: false
                  type: varchar(255)
                  remarks: Timezone to display the underlying UTC timestamp in for the client
              - column:
                  name: icon
                  type: varchar(128)
                  constraints:
                    nullable: true
                  remarks: the icon to use when displaying the event
              - column:
                  remarks: Whether or not the event has been archived
                  name: archived
                  type: boolean
                  defaultValueBoolean: false
                  constraints:
                    nullable: false
              - column:
                  remarks: ID of the user who created the event
                  name: creator_id
                  type: int
                  constraints:
                    nullable: false
                    references: core_user(id)
                    foreignKeyName: fk_event_creator_id
                    deleteCascade: true
              - column:
                  remarks: The timestamp of when the event was created
                  name: created_at
                  type: ${timestamp_type}
                  defaultValueComputed: current_timestamp
                  constraints:
                    nullable: false
              - column:
                  remarks: The timestamp of when the event was modified
                  name: updated_at
                  type: ${timestamp_type}
                  defaultValueComputed: current_timestamp
                  constraints:
                    nullable: false

  - changeSet:
      id: v43.00-023
      author: dpsutton
      comment: Added 0.43.0 - Index on timeline collection_id
      changes:
        - createIndex:
            tableName: timeline
            indexName: idx_timeline_collection_id
            columns:
              - column:
                  name: collection_id

  - changeSet:
      id: v43.00-024
      author: dpsutton
      comment: Added 0.43.0 - Index on timeline_event timeline_id
      changes:
        - createIndex:
            tableName: timeline_event
            indexName: idx_timeline_event_timeline_id
            columns:
              - column:
                  name: timeline_id

  - changeSet:
      id: v43.00-025
      author: dpsutton
      comment: Added 0.43.0 - Index on timeline timestamp
      changes:
        - createIndex:
            tableName: timeline_event
            indexName: idx_timeline_event_timeline_id_timestamp
            columns:
              - column:
                  name: timeline_id
              - column:
                  name: timestamp

  - changeSet:
      id: v43.00-026
      author: noahmoss
      comment: >-
        Added 0.43.0 - adds User.settings column to implement User-local Settings
      changes:
        - addColumn:
            tableName: core_user
            columns:
              - column:
                  name: settings
                  type: ${text.type}
                  remarks: "Serialized JSON containing User-local Settings for this User"

  - changeSet:
      id: v43.00-027
      author: camsaul
      comment: Added 0.43.0. Drop NOT NULL constraint for core_user.password
      changes:
        - dropNotNullConstraint:
            tableName: core_user
            columnName: password
            columnDataType: varchar(254)

  - changeSet:
      id: v43.00-028
      author: camsaul
      comment: Added 0.43.0. Drop NOT NULL constraint for core_user.password_salt
      changes:
        - dropNotNullConstraint:
            tableName: core_user
            columnName: password_salt
            columnDataType: varchar(254)

  #
  # The following migration replaces metabase.db.data-migrations/clear-ldap-user-local-passwords, added 0.30.0
  #
  # Before 0.30.0, we were storing the LDAP user's password in the core_user table (though it wasn't used). This
  # migration clears those passwords out, disabling password-based login.
  - changeSet:
      id: v43.00-029
      author: camsaul
      comment: Added 0.43.0. Clear local password for Users using LDAP auth.
      changes:
        - sql:
            sql: >-
              UPDATE core_user
              SET
                password = NULL,
                password_salt = NULL
              WHERE ldap_auth IS TRUE;

  - changeSet:
      id: v43.00-030
      author: dpsutton
      comment: Added 0.43.0 - Dashboard bookmarks table
      changes:
        - createTable:
            tableName: dashboard_bookmark
            remarks: Table holding bookmarks on dashboards
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: user_id
                  type: int
                  remarks: 'ID of the User who bookmarked the Dashboard'
                  constraints:
                    nullable: false
                    references: core_user(id)
                    foreignKeyName: fk_dashboard_bookmark_user_id
                    deleteCascade: true
              - column:
                  name: dashboard_id
                  type: int
                  remarks: 'ID of the Dashboard bookmarked by the user'
                  constraints:
                    nullable: false
                    references: report_dashboard(id)
                    foreignKeyName: fk_dashboard_bookmark_dashboard_id
                    deleteCascade: true
              - column:
                  remarks: The timestamp of when the bookmark was created
                  name: created_at
                  type: ${timestamp_type}
                  defaultValueComputed: current_timestamp
                  constraints:
                    nullable: false
  - changeSet:
      id: v43.00-031
      author: dpsutton
      comment: Added 0.43.0 - Dashboard bookmarks table unique constraint
      changes:
        - addUniqueConstraint:
            tableName: dashboard_bookmark
            columnNames: user_id, dashboard_id
            constraintName: unique_dashboard_bookmark_user_id_dashboard_id
  - changeSet:
      id: v43.00-032
      author: dpsutton
      comment: Added 0.43.0 - Dashboard bookmarks table index on user_id
      changes:
        - createIndex:
            tableName: dashboard_bookmark
            columns:
              - column:
                  name: user_id
            indexName: idx_dashboard_bookmark_user_id
  - changeSet:
      id: v43.00-033
      author: dpsutton
      comment: Added 0.43.0 - Dashboard bookmarks table index on dashboard_id
      changes:
        - createIndex:
            tableName: dashboard_bookmark
            columns:
              - column:
                  name: dashboard_id
            indexName: idx_dashboard_bookmark_dashboard_id

  - changeSet:
      id: v43.00-034
      author: dpsutton
      comment: Added 0.43.0 - Card bookmarks table
      changes:
        - createTable:
            tableName: card_bookmark
            remarks: Table holding bookmarks on cards
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: user_id
                  type: int
                  remarks: 'ID of the User who bookmarked the Card'
                  constraints:
                    nullable: false
                    references: core_user(id)
                    foreignKeyName: fk_card_bookmark_user_id
                    deleteCascade: true
              - column:
                  name: card_id
                  type: int
                  remarks: 'ID of the Card bookmarked by the user'
                  constraints:
                    nullable: false
                    references: report_card(id)
                    foreignKeyName: fk_card_bookmark_dashboard_id
                    deleteCascade: true
              - column:
                  remarks: The timestamp of when the bookmark was created
                  name: created_at
                  type: ${timestamp_type}
                  defaultValueComputed: current_timestamp
                  constraints:
                    nullable: false
  - changeSet:
      id: v43.00-035
      author: dpsutton
      comment: Added 0.43.0 - Card bookmarks table unique constraint
      changes:
        - addUniqueConstraint:
            tableName: card_bookmark
            columnNames: user_id, card_id
            constraintName: unique_card_bookmark_user_id_card_id
  - changeSet:
      id: v43.00-036
      author: dpsutton
      comment: Added 0.43.0 - Card bookmarks table index on user_id
      changes:
        - createIndex:
            tableName: card_bookmark
            columns:
              - column:
                  name: user_id
            indexName: idx_card_bookmark_user_id
  - changeSet:
      id: v43.00-037
      author: dpsutton
      comment: Added 0.43.0 - Card bookmarks table index on card_id
      changes:
        - createIndex:
            tableName: card_bookmark
            columns:
              - column:
                  name: card_id
            indexName: idx_card_bookmark_card_id

  - changeSet:
      id: v43.00-038
      author: dpsutton
      comment: Added 0.43.0 - Collection bookmarks table
      changes:
        - createTable:
            tableName: collection_bookmark
            remarks: Table holding bookmarks on collections
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: user_id
                  type: int
                  remarks: 'ID of the User who bookmarked the Collection'
                  constraints:
                    nullable: false
                    references: core_user(id)
                    foreignKeyName: fk_collection_bookmark_user_id
                    deleteCascade: true
              - column:
                  name: collection_id
                  type: int
                  remarks: 'ID of the Card bookmarked by the user'
                  constraints:
                    nullable: false
                    references: collection(id)
                    foreignKeyName: fk_collection_bookmark_collection_id
                    deleteCascade: true
              - column:
                  remarks: The timestamp of when the bookmark was created
                  name: created_at
                  type: ${timestamp_type}
                  defaultValueComputed: current_timestamp
                  constraints:
                    nullable: false
  - changeSet:
      id: v43.00-039
      author: dpsutton
      comment: Added 0.43.0 - Collection bookmarks table unique constraint
      changes:
        - addUniqueConstraint:
            tableName: collection_bookmark
            columnNames: user_id, collection_id
            constraintName: unique_collection_bookmark_user_id_collection_id
  - changeSet:
      id: v43.00-040
      author: dpsutton
      comment: Added 0.43.0 - Collection bookmarks table index on user_id
      changes:
        - createIndex:
            tableName: collection_bookmark
            columns:
              - column:
                  name: user_id
            indexName: idx_collection_bookmark_user_id
  - changeSet:
      id: v43.00-041
      author: dpsutton
      comment: Added 0.43.0 - Collection bookmarks table index on collection_id
      changes:
        - createIndex:
            tableName: collection_bookmark
            columns:
              - column:
                  name: collection_id
            indexName: idx_collection_bookmark_collection_id

  - changeSet:
      id: v43.00-042
      author: noahmoss
      comment: >-
        Added 0.43.0. Grant download permissions for existing Databases to 'All Users' permissions group
      changes:
        - sql:
            sql: >-
              INSERT INTO permissions (object, group_id)
              SELECT db.object, all_users.id AS group_id
              FROM (
                SELECT concat('/download/db/', id, '/') AS object
                FROM metabase_database
              ) db
              LEFT JOIN (
                SELECT id
                FROM permissions_group
                WHERE name = 'All Users'
              ) all_users
                ON true
              LEFT JOIN permissions p
                     ON p.group_id = all_users.id
                    AND db.object = p.object
              WHERE p.object IS NULL;

  - changeSet:
      id: v43.00-043
      author: howonlee
      comment: Added 0.43.0 - Nested field columns in fields
      changes:
        - addColumn:
            columns:
            - column:
                remarks: Nested field column paths, flattened
                name: nfc_path
                type: varchar(254)
                constraints:
                  nullable: true
            tableName: metabase_field

  - changeSet:
      id: v43.00-044
      author: noahmoss
      comment: Added 0.43.0 - Removes MetaBot permissions group
      changes:
        - sql:
            sql: DELETE FROM permissions_group WHERE name = 'MetaBot'

  - changeSet:
      id: v43.00-046
      author: qnkhuat
      comment: Added 0.43.0 - create General Permission Revision table
      changes:
        - createTable:
            tableName: general_permissions_revision
            remarks: 'Used to keep track of changes made to general permissions.'
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: before
                  type: ${text.type}
                  remarks: 'Serialized JSON of the permission graph before the changes.'
                  constraints:
                    nullable: false
              - column:
                  name: after
                  type: ${text.type}
                  remarks: 'Serialized JSON of the changes in permission graph.'
                  constraints:
                    nullable: false
              - column:
                  name: user_id
                  type: int
                  remarks: 'The ID of the admin who made this set of changes.'
                  constraints:
                    nullable: false
                    referencedTableName: core_user
                    referencedColumnNames: id
                    foreignKeyName: fk_general_permissions_revision_user_id
              - column:
                  name: created_at
                  type: datetime
                  remarks: 'The timestamp of when these changes were made.'
                  constraints:
                    nullable: false
              - column:
                  name: remark
                  type: ${text.type}
                  remarks: 'Optional remarks explaining why these changes were made.'

  - changeSet:
      id: v43.00-047
      author: qnkhuat
      comment: Added 0.43.0. Grant the 'All Users' Group permissions to create/edit subscriptions and alerts
      changes:
        - sql:
            sql: >-
              INSERT INTO permissions (group_id, object)
              SELECT
                all_users_group.id AS group_id,
                '/general/subscription/' AS object
              FROM (
                SELECT id
                FROM permissions_group
                WHERE name = 'All Users'
              ) all_users_group
              LEFT JOIN permissions p
                ON all_users_group.id = p.group_id
                AND p.object = '/general/subscription/'
              WHERE p.object IS NULL;

  - changeSet:
      id: v43.00-049
      author: dpsutton
      comment: Added 0.43.0 - Unify datatype with query_execution.started_at so comparable (see 168).
      changes:
        - modifyDataType:
            tableName: view_log
            columnName: timestamp
            newDataType: ${timestamp_type}

  - changeSet:
        id: v43.00-050
        author: qnkhuat
        comment: Added 0.43.0. Add permissions_group_membership.is_group_manager
        changes:
          - addColumn:
              columns:
              - column:
                  remarks: Boolean flag to indicate whether user is a group's manager.
                  name: is_group_manager
                  type: boolean
                  constraints:
                    nullable: false
                  defaultValue: false
              tableName: permissions_group_membership

  - changeSet:
      id: v43.00-051
      author: adam-james
      comment: Added 0.43.0 - default boolean on timelines to indicate default timeline for a collection
      changes:
        - addColumn:
            columns:
            - column:
                remarks: Boolean value indicating if the timeline is the default one for the containing Collection
                name: default
                type: boolean
                defaultValue: false
                constraints:
                  nullable: false
            tableName: timeline

  - changeSet:
      id: v43.00-052
      author: snoe
      comment: Added 0.43.0 - bookmark ordering
      changes:
        - createTable:
            tableName: bookmark_ordering
            remarks: Table holding ordering information for various bookmark tables
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: user_id
                  type: int
                  remarks: 'ID of the User who ordered bookmarks'
                  constraints:
                    nullable: false
                    references: core_user(id)
                    foreignKeyName: fk_bookmark_ordering_user_id
                    deleteCascade: true
              - column:
                  name: type
                  type: varchar(255)
                  remarks: 'type of the Bookmark'
                  constraints:
                    nullable: false
              - column:
                  name: item_id
                  type: int
                  remarks: 'id of the item being bookmarked (Card, Collection, Dashboard, ...) no FK, so may no longer exist'
                  constraints:
                    nullable: false
              - column:
                  name: ordering
                  type: int
                  remarks: 'order of bookmark for user'
                  constraints:
                    nullable: false
  - changeSet:
      id: v43.00-053
      author: snoe
      comment: Added 0.43.0 - bookmark ordering
      changes:
        - addUniqueConstraint:
            tableName: bookmark_ordering
            columnNames: user_id, type, item_id
            constraintName: unique_bookmark_user_id_type_item_id
  - changeSet:
      id: v43.00-054
      author: snoe
      comment: Added 0.43.0 - bookmark ordering
      changes:
        - addUniqueConstraint:
            tableName: bookmark_ordering
            columnNames: user_id, ordering
            constraintName: unique_bookmark_user_id_ordering
  - changeSet:
      id: v43.00-055
      author: snoe
      comment: Added 0.43.0 - bookmark ordering
      changes:
        - createIndex:
            tableName: bookmark_ordering
            columns:
              - column:
                  name: user_id
            indexName: idx_bookmark_ordering_user_id

  - changeSet:
      id: v43.00-056
      author: qnkhuat
      comment: >-
        Added 0.43.0 - Rename general permission revision table
        It's safe to rename this table without breaking downgrades compatibility because this table was also added in 0.43.0.
      changes:
        - renameTable:
            oldTableName: general_permissions_revision
            newTableName: application_permissions_revision

  - changeSet:
      id: v43.00-057
      author: qnkhuat
      comment: Added 0.43.0 - Rename general_permissions_revision_id_seq
      failOnError: false # mysql and h2 don't have this sequence
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: postgresql
      changes:
        - sql:
            - sql: ALTER SEQUENCE general_permissions_revision_id_seq RENAME TO application_permissions_revision_id_seq;

  - changeSet:
      id: v43.00-058
      author: qnkhuat
      comment: Added 0.43.0 - Rename general permissios to application permissions
      changes:
        - sql:
            sql: >-
              UPDATE permissions
              SET object = REPLACE(object, '/general/', '/application/')
              WHERE object LIKE '/general/%';

  - changeSet:
      id: v43.00-059
      author: adam-james
      comment: Added 0.43.0 - disallow nil timeline icons
      changes:
        - addNotNullConstraint:
            columnDataType: varchar(128)
            tableName: timeline
            columnName: icon
            defaultNullValue: "star"
  - changeSet:
      id: v43.00-060
      author: adam-james
      comment: Added 0.43.0 - disallow nil timeline event icons
      changes:
        - addNotNullConstraint:
            columnDataType: varchar(128)
            tableName: timeline_event
            columnName: icon
            defaultNullValue: "star"

  - changeSet:
      id: v43.00-062
      author: snoe
      comment: Added 0.43.0 - Unify datatype with revision.timestamp for timezone info (see 17829).
      changes:
        - modifyDataType:
            tableName: revision
            columnName: timestamp
            newDataType: ${timestamp_type}

  - changeSet:
      id: v44.00-000
      author: dpsutton
      comment: Added 0.44.0 - Persisted Info for models
      changes:
        - createTable:
            tableName: persisted_info
            remarks: Table holding information about persisted models
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: database_id
                  type: int
                  remarks: 'ID of the database associated to the persisted card'
                  constraints:
                    nullable: false
                    referencedTableName: metabase_database
                    referencedColumnNames: id
                    foreignKeyName: fk_persisted_info_database_id
                    deleteCascade: true
              - column:
                  name: card_id
                  type: int
                  remarks: 'ID of the Card model persisted'
                  constraints:
                    nullable: false
                    unique: true
                    referencedTableName: report_card
                    referencedColumnNames: id
                    foreignKeyName: fk_persisted_info_card_id
                    deleteCascade: true
              - column:
                  remarks: Slug of the card which will form the persisted table name
                  name: question_slug
                  type: ${text.type}
                  constraints:
                    nullable: false
              - column:
                  remarks: Name of the table persisted
                  name: table_name
                  type: ${text.type}
                  constraints:
                    nullable: false
              - column:
                  remarks: JSON object that captures the state of the table when we persisted
                  name: definition
                  type: ${text.type}
                  constraints:
                    nullable: true
              - column:
                  remarks: Hash of the query persisted
                  name: query_hash
                  type: ${text.type}
                  constraints:
                    nullable: true
              - column:
                  remarks: Indicating whether the persisted table is active and can be swapped
                  name: active
                  type: boolean
                  defaultValueBoolean: false
                  constraints:
                    nullable: false
              - column:
                  remarks: Persisted table state (creating, persisted, refreshing, deleted)
                  name: state
                  type: ${text.type}
                  constraints:
                    nullable: false
              - column:
                  remarks: The timestamp of when the most recent refresh was started
                  name: refresh_begin
                  type: ${timestamp_type}
                  constraints:
                    nullable: false
              - column:
                  remarks: The timestamp of when the most recent refresh ended
                  name: refresh_end
                  type: ${timestamp_type}
                  constraints:
                    nullable: true
              - column:
                  remarks: The timestamp of when the most recent state changed
                  name: state_change_at
                  type: ${timestamp_type}
                  constraints:
                    nullable: true
              - column:
                  remarks: Error message from persisting if applicable
                  name: error
                  type: ${text.type}
                  constraints:
                    nullable: true
              - column:
                  remarks: The timestamp of when the model was first persisted
                  name: created_at
                  type: ${timestamp_type}
                  defaultValueComputed: current_timestamp
                  constraints:
                    nullable: false
              - column:
                  name: creator_id
                  type: int
                  remarks: The person who persisted a model
                  constraints:
                    nullable: false
                    referencedTableName: core_user
                    referencedColumnNames: id
                    foreignKeyName: fk_persisted_info_ref_creator_id
                    deferrable: false
                    initiallyDeferred: false
  - changeSet:
      id: v44.00-001
      author: snoe
      comment: Added 0.44.0 - Remove not null constraint from persisted_info.creator_id
      changes:
        - dropNotNullConstraint:
            tableName: persisted_info
            columnName: creator_id
            columnDataType: int

  # v44.00-002 through -011 add entity_id columns to several internal entities.
  # These are fixed-width string fields populated with a random 21-character
  # NanoID value, and used by the serialization system to de-duplicate entities
  # in a portable way. See the serialization design doc in the design repo.
  - changeSet:
      id: v44.00-002
      author: braden
      comment: Added 0.44.0 - add entity_id column to all internal entities
      changes:
        - addColumn:
            columns:
            - column:
                remarks: Random NanoID tag for unique identity.
                name: entity_id
                type: char(21)
                constraints:
                  nullable: true
                  unique: true
            tableName: metric
  - changeSet:
      id: v44.00-003
      author: braden
      comment: Added 0.44.0 - add entity_id column to all internal entities
      changes:
        - addColumn:
            columns:
            - column:
                remarks: Random NanoID tag for unique identity.
                name: entity_id
                type: char(21)
                constraints:
                  nullable: true
                  unique: true
            tableName: segment
  - changeSet:
      id: v44.00-004
      author: braden
      comment: Added 0.44.0 - add entity_id column to all internal entities
      changes:
        - addColumn:
            columns:
            - column:
                remarks: Random NanoID tag for unique identity.
                name: entity_id
                type: char(21)
                constraints:
                  nullable: true
                  unique: true
            tableName: collection
  - changeSet:
      id: v44.00-005
      author: braden
      comment: Added 0.44.0 - add entity_id column to all internal entities
      changes:
        - addColumn:
            columns:
            - column:
                remarks: Random NanoID tag for unique identity.
                name: entity_id
                type: char(21)
                constraints:
                  nullable: true
                  unique: true
            tableName: report_dashboard
  - changeSet:
      id: v44.00-006
      author: braden
      comment: Added 0.44.0 - add entity_id column to all internal entities
      changes:
        - addColumn:
            columns:
            - column:
                remarks: Random NanoID tag for unique identity.
                name: entity_id
                type: char(21)
                constraints:
                  nullable: true
                  unique: true
            tableName: dimension
  - changeSet:
      id: v44.00-007
      author: braden
      comment: Added 0.44.0 - add entity_id column to all internal entities
      changes:
        - addColumn:
            columns:
            - column:
                remarks: Random NanoID tag for unique identity.
                name: entity_id
                type: char(21)
                constraints:
                  nullable: true
                  unique: true
            tableName: pulse
  - changeSet:
      id: v44.00-008
      author: braden
      comment: Added 0.44.0 - add entity_id column to all internal entities
      changes:
        - addColumn:
            columns:
            - column:
                remarks: Random NanoID tag for unique identity.
                name: entity_id
                type: char(21)
                constraints:
                  nullable: true
                  unique: true
            tableName: report_card
  - changeSet:
      id: v44.00-009
      author: braden
      comment: Added 0.44.0 - add entity_id column to all internal entities
      changes:
        - addColumn:
            columns:
            - column:
                remarks: Random NanoID tag for unique identity.
                name: entity_id
                type: char(21)
                constraints:
                  nullable: true
                  unique: true
            tableName: native_query_snippet
  - changeSet:
      id: v44.00-010
      author: braden
      comment: Added 0.44.0 - add entity_id column to all internal entities
      changes:
        - addColumn:
            columns:
            - column:
                remarks: Random NanoID tag for unique identity.
                name: entity_id
                type: char(21)
                constraints:
                  nullable: true
                  unique: true
            tableName: timeline
  - changeSet:
      id: v44.00-011
      author: braden
      comment: Added 0.44.0 - add entity_id column to all internal entities
      changes:
        - addColumn:
            columns:
            - column:
                remarks: Random NanoID tag for unique identity.
                name: entity_id
                type: char(21)
                constraints:
                  nullable: true
                  unique: true
            tableName: report_dashboardcard

# Migrations v44.00-012 thru v44.00-022 have been moved to v45.00-001 thru v45.00-011

  - changeSet:
      id: v44.00-023
      author: qnkhuat
      comment: Added 0.44.0 - Add parameters to report_card
      validCheckSum: ANY
      changes:
        - addColumn:
            tableName: report_card
            columns:
              - column:
                  name: parameters
                  type: ${text.type}
                  remarks: List of parameter associated to a card
                  constraints:
                    nullable: true
  - changeSet:
      id: v44.00-025
      author: qnkhuat
      comment: Added 0.44.0 - Add parameter_mappings to report_card
      validCheckSum: ANY
      changes:
        - addColumn:
            tableName: report_card
            columns:
              - column:
                  name: parameter_mappings
                  type: ${text.type}
                  remarks: List of parameter associated to a card
                  constraints:
                    nullable: true
  - changeSet:
      id: v44.00-027
      author: adam-james
      comment: Added 0.44.0. Drop NOT NULL constraint for core_user.first_name
      changes:
        - dropNotNullConstraint:
            tableName: core_user
            columnName: first_name
            columnDataType: varchar(254)
  - changeSet:
      id: v44.00-028
      author: adam-james
      comment: Added 0.44.0. Drop NOT NULL constraint for core_user.last_name
      changes:
        - dropNotNullConstraint:
            tableName: core_user
            columnName: last_name
            columnDataType: varchar(254)
  - changeSet:
      id: v44.00-029
      author: qnkhuat
      comment: Added 0.44.0 - Add has_more_values to metabase_fieldvalues
      changes:
        - addColumn:
            tableName: metabase_fieldvalues
            columns:
              - column:
                  name: has_more_values
                  type: boolean
                  remarks: true if the stored values list is a subset of all possible values
                  defaultValueBoolean: false

  - changeSet:
      id: v44.00-030
      author: snoe
      comment: Added 0.44.0 - Add database_required to metabase_field
      changes:
        - addColumn:
            tableName: metabase_field
            columns:
              - column:
                  name: database_required
                  type: boolean
                  remarks: Indicates this field is required by the database for new records. Usually not null and without a default.
                  defaultValueBoolean: false
                  constraints:
                    nullable: false

# Migrations v44.00-031 and v44.00-032 were moved to v45.00-012 and v45.00-013 respectively

  - changeSet:
      id: v44.00-033
      author: qnkhuat
      comment: >-
        Added 0.43.0. Grant the 'All Users' Permissions Group readwrite perms for the Root Snippets Collection.
      preConditions:
        - onFail: MARK_RAN
          # HACK: only run this on new instances (#21940)
        - sqlCheck:
            expectedResult: 0
            sql: >-
              SELECT count(*) AS user_count FROM core_user
      changes:
        - sql:
            sql: >-
              INSERT INTO permissions (group_id, object)
              SELECT
                all_users_group.id AS group_id,
                '/collection/namespace/snippets/root/' AS object
              FROM (
                SELECT id
                FROM permissions_group
                WHERE name = 'All Users'
              ) all_users_group
              LEFT JOIN permissions p
                      ON all_users_group.id = p.group_id
                    AND p.object = '/collection/namespace/snippets/root/'
              WHERE p.object IS NULL;

  - changeSet:
      id: v44.00-035
      author: qnkhuat
      comment: Added 0.44.0. Add type to fieldvalues
      validCheckSum: ANY
      changes:
        - addColumn:
            tableName: metabase_fieldvalues
            columns:
              - column:
                  name: type
                  type: varchar(32)
                  defaultValue: 'full'
                  remarks: Type of FieldValues
                  constraints:
                    nullable: false
  - changeSet:
      id: v44.00-037
      author: qnkhuat
      comment: Added 0.44.0. Add type to fieldvalues
      changes:
        - addColumn:
            tableName: metabase_fieldvalues
            columns:
              - column:
                  name: hash_key
                  type: ${text.type}
                  remarks: Hash key for a cached fieldvalues
                  constraints:
                    nullable: true

  - changeSet:
      id: v44.00-038
      author: metamben
      comment: Added 0.44.0 - Add collection_preview to report_card
      changes:
        - addColumn:
            tableName: report_card
            columns:
              - column:
                  name: collection_preview
                  type: boolean
                  remarks: Indicating whether the card should be visualized in the collection preview
                  defaultValueBoolean: true
                  constraints:
                    nullable: false

  - changeSet:
      id: v44.00-039
      author: qnkhuat
      comment: Added 0.44.0 - Add template_tags to native_query_snippet
      changes:
        - addColumn:
            tableName: native_query_snippet
            columns:
              - column:
                  name: template_tags
                  type: ${text.type}
                  remarks: Template tags for a snippet
                  constraints:
                    nullable: true

  - changeSet:
      id: v44.00-041
      author: braden
      comment: Added 0.44.0 - add entity_id column to PulseCard, PulseChannel
      changes:
        - addColumn:
            columns:
            - column:
                remarks: Random NanoID tag for unique identity.
                name: entity_id
                type: char(21)
                constraints:
                  nullable: true
                  unique: true
            tableName: pulse_card

  - changeSet:
      id: v44.00-042
      author: braden
      comment: Added 0.44.0 - add entity_id column to PulseCard, PulseChannel
      changes:
        - addColumn:
            columns:
            - column:
                remarks: Random NanoID tag for unique identity.
                name: entity_id
                type: char(21)
                constraints:
                  nullable: true
                  unique: true
            tableName: pulse_channel

  - changeSet:
      id: v44.00-044
      author: qnkhuat
      comment: Added 0.44.0 - drop native_query_snippet.template_tags added in v44.00-039
      changes:
        - dropColumn:
            tableName: native_query_snippet
            columnName: template_tags

##
## Metabase 45
##

# Note on rollback: migrations for v45 onwards should always include a rollback key unless they are supported
# by Liquibase Auto Rollback. Most common changes are supported. See docs here:
#
#  https://docs.liquibase.com/workflows/liquibase-community/liquibase-auto-rollback.html

  - changeSet:
      id: v45.00-001
      author: snoe
      comment: Added 0.44.0 - writeback
      # This migration was previously numbered v44.00-012 but ultimately was not shipped with 44.
      preConditions:
        - onFail: MARK_RAN
        - or:
            # For some insane reason databasechangelog is upper-case in MySQL and MariaDB.
            - and:
                - dbms:
                    type: postgresql,h2
                - sqlCheck:
                    expectedResult: 0
                    sql: SELECT count(*) FROM databasechangelog WHERE id = 'v44.00-012';
            - and:
                - dbms:
                    type: mysql,mariadb
                - sqlCheck:
                    expectedResult: 0
                    sql: SELECT count(*) FROM `DATABASECHANGELOG` WHERE id = 'v44.00-012';
      changes:
        - createTable:
            tableName: action
            remarks: An action is something you can do, such as run a readwrite query
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  remarks: The timestamp of when the action was created
                  name: created_at
                  type: ${timestamp_type}
                  defaultValueComputed: current_timestamp
                  constraints:
                    nullable: false
              - column:
                  remarks: The timestamp of when the action was updated
                  name: updated_at
                  type: ${timestamp_type}
                  defaultValueComputed: current_timestamp
                  constraints:
                    nullable: false
              - column:
                  remarks: Type of action
                  name: type
                  type: ${text.type}
                  constraints:
                    nullable: false

  - changeSet:
      id: v45.00-002
      author: snoe
      comment: Added 0.44.0 - writeback
      # This migration was previously numbered v44.00-013 but ultimately was not shipped with 44.
      preConditions:
        - onFail: MARK_RAN
        - or:
            # For some insane reason databasechangelog is upper-case in MySQL and MariaDB.
            - and:
                - dbms:
                    type: postgresql,h2
                - sqlCheck:
                    expectedResult: 0
                    sql: SELECT count(*) FROM databasechangelog WHERE id = 'v44.00-013';
            - and:
                - dbms:
                    type: mysql,mariadb
                - sqlCheck:
                    expectedResult: 0
                    sql: SELECT count(*) FROM `DATABASECHANGELOG` WHERE id = 'v44.00-013';
      changes:
        - createTable:
            tableName: query_action
            remarks: A readwrite query type of action
            columns:
              - column:
                  name: action_id
                  type: int
                  remarks: The related action
                  constraints:
                    nullable: false
                    referencedTableName: action
                    referencedColumnNames: id
                    foreignKeyName: fk_query_action_ref_action_id
                    deleteCascade: true
              - column:
                  name: card_id
                  type: int
                  remarks: The related card
                  constraints:
                    nullable: false
                    referencedTableName: report_card
                    referencedColumnNames: id
                    foreignKeyName: fk_query_action_ref_card_id
                    deleteCascade: true

  - changeSet:
      id: v45.00-003
      author: snoe
      comment: Added 0.44.0 - writeback
      # This migration was previously numbered v44.00-014 but ultimately was not shipped with 44.
      preConditions:
        - onFail: MARK_RAN
        - or:
            # For some insane reason databasechangelog is upper-case in MySQL and MariaDB.
            - and:
                - dbms:
                    type: postgresql,h2
                - sqlCheck:
                    expectedResult: 0
                    sql: SELECT count(*) FROM databasechangelog WHERE id = 'v44.00-014';
            - and:
                - dbms:
                    type: mysql,mariadb
                - sqlCheck:
                    expectedResult: 0
                    sql: SELECT count(*) FROM `DATABASECHANGELOG` WHERE id = 'v44.00-014';
      changes:
        - addPrimaryKey:
            tableName: query_action
            columnNames: action_id, card_id
            constraintName: pk_query_action
      rollback: # will be deleted when table is deleted

  # note: some migrations which only added and deleted tables within v45 were removed, hence an ID gap here

  - changeSet:
      id: v45.00-011
      author: snoe
      comment: Added 0.44.0 - writeback
      # This migration was previously numbered v44.00-022 but ultimately was not shipped with 44.
      preConditions:
        - onFail: MARK_RAN
        - or:
            # For some insane reason databasechangelog is upper-case in MySQL and MariaDB.
            - and:
                - dbms:
                    type: postgresql,h2
                - sqlCheck:
                    expectedResult: 0
                    sql: SELECT count(*) FROM databasechangelog WHERE id = 'v44.00-022';
            - and:
                - dbms:
                    type: mysql,mariadb
                - sqlCheck:
                    expectedResult: 0
                    sql: SELECT count(*) FROM `DATABASECHANGELOG` WHERE id = 'v44.00-022';
      changes:
        - addColumn:
            columns:
              - column:
                  name: is_write
                  type: boolean
                  defaultValueBoolean: false
                  remarks: Indicates that this query will perform writes to a db
                  constraints:
                    nullable: false
            tableName: report_card

  - changeSet:
      id: v45.00-012
      author: snoe
      comment: Added 0.44.0 - writeback
      # This migration was previously numbered v44.00-031 but ultimately was not shipped with 44.
      preConditions:
        - onFail: MARK_RAN
        - or:
            # For some insane reason databasechangelog is upper-case in MySQL and MariaDB.
            - and:
                - dbms:
                    type: postgresql,h2
                - sqlCheck:
                    expectedResult: 0
                    sql: SELECT count(*) FROM databasechangelog WHERE id = 'v44.00-031';
            - and:
                - dbms:
                    type: mysql,mariadb
                - sqlCheck:
                    expectedResult: 0
                    sql: SELECT count(*) FROM `DATABASECHANGELOG` WHERE id = 'v44.00-031';
      changes:
        - createTable:
            tableName: http_action
            remarks: An http api call type of action
            columns:
              - column:
                  name: action_id
                  type: int
                  remarks: The related action
                  constraints:
                    nullable: false
                    referencedTableName: action
                    referencedColumnNames: id
                    foreignKeyName: fk_http_action_ref_action_id
                    deleteCascade: true
              - column:
                  name: name
                  type: varchar(254)
                  remarks: The name of this action
                  constraints:
                    nullable: false
              - column:
                  name: description
                  type: ${text.type}
                  remarks: An optional description for this action
              - column:
                  name: template
                  type: ${text.type}
                  remarks: A template that defines method,url,body,headers required to make an api call
                  constraints:
                    nullable: false
              - column:
                  name: response_handle
                  type: ${text.type}
                  remarks: A program to take an api response and transform to an appropriate response for emitters
              - column:
                  name: error_handle
                  type: ${text.type}
                  remarks: A program to take an api response to determine if an error occurred

  - changeSet:
      id: v45.00-013
      author: snoe
      comment: Added 0.44.0 - writeback
      # This migration was previously numbered v44.00-032 but ultimately was not shipped with 44.
      preConditions:
        - onFail: MARK_RAN
        - or:
            # For some insane reason databasechangelog is upper-case in MySQL and MariaDB.
            - and:
                - dbms:
                    type: postgresql,h2
                - sqlCheck:
                    expectedResult: 0
                    sql: SELECT count(*) FROM databasechangelog WHERE id = 'v44.00-032';
            - and:
                - dbms:
                    type: mysql,mariadb
                - sqlCheck:
                    expectedResult: 0
                    sql: SELECT count(*) FROM `DATABASECHANGELOG` WHERE id = 'v44.00-032';
      changes:
        - addPrimaryKey:
            tableName: http_action
            columnNames: action_id
            constraintName: pk_http_action
      rollback: # no rollback needed, will be deleted with table


  # note: some migrations which only added and deleted tables within v45 were removed, hence an ID gap here

  - changeSet:
      id: v45.00-022
      author: snoe
      comment: Added 0.45.0 - add app container
      changes:
        - createTable:
            tableName: app
            remarks: Defines top level concerns for App
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: entity_id
                  type: char(21)
                  remarks: Random NanoID tag for unique identity.
                  constraints:
                    nullable: false
                    unique: true
              - column:
                  name: collection_id
                  type: int
                  remarks: The associated collection
                  constraints:
                    nullable: false
                    referencedTableName: collection
                    referencedColumnNames: id
                    foreignKeyName: fk_app_ref_collection_id
                    deleteCascade: true
                    unique: true
              - column:
                  name: dashboard_id
                  type: int
                  remarks: The homepage of the app
              - column:
                  remarks: JSON for the navigation items of the app
                  name: nav_items
                  type: ${text.type}
              - column:
                  remarks: JSON for frontend related additions, such as styling
                  name: options
                  type: ${text.type}
              - column:
                  remarks: The timestamp of when the app was created
                  name: created_at
                  type: ${timestamp_type}
                  defaultValueComputed: current_timestamp
                  constraints:
                    nullable: false
              - column:
                  remarks: The timestamp of when the app was updated
                  name: updated_at
                  type: ${timestamp_type}
                  defaultValueComputed: current_timestamp
                  constraints:
                    nullable: false

  - changeSet:
      id: v45.00-023
      author: snoe
      comment: Added 0.45.0 - add app container
      changes:
        - addForeignKeyConstraint:
            baseTableName: app
            baseColumnNames: dashboard_id
            referencedTableName: report_dashboard
            referencedColumnNames: id
            constraintName: fk_app_ref_dashboard_id
            onDelete: SET NULL

  - changeSet:
      id: v45.00-025
      author: metamben
      comment: Added 0.45.0 - mark app pages
      changes:
        - addColumn:
            columns:
              - column:
                  name: is_app_page
                  type: boolean
                  defaultValueBoolean: false
                  remarks: Indicates that this dashboard serves as a page of an app
                  constraints:
                    nullable: false
            tableName: report_dashboard

  - changeSet:
      id: v45.00-026
      author: snoe
      comment: Added 0.45.0 - apps add action_id to report_dashboardcard
      changes:
        - addColumn:
            columns:
              - column:
                  name: action_id
                  type: int
                  remarks: The related action
            tableName: report_dashboardcard

  # FK constraint is added separately because deleteCascade doesn't work in addColumn -- see #14321
  - changeSet:
      id: v45.00-027
      author: snoe
      comment: Added 0.45.0 - apps add fk for action_id to report_dashboardcard
      changes:
        - addForeignKeyConstraint:
            baseTableName: report_dashboardcard
            baseColumnNames: action_id
            referencedTableName: action
            referencedColumnNames: id
            constraintName: fk_report_dashboardcard_ref_action_id
            onDelete: CASCADE

  - changeSet:
      id: v45.00-028
      author: camsaul
      comment: Added 0.45.0 -- rename DashboardCard sizeX to size_x. See https://github.com/metabase/metabase/issues/16344
      changes:
        - renameColumn:
            tableName: report_dashboardcard
            columnDataType: int
            oldColumnName: sizeX
            newColumnName: size_x

  - changeSet:
      id: v45.00-029
      author: camsaul
      comment: Added 0.45.0 -- rename DashboardCard size_y to size_y. See https://github.com/metabase/metabase/issues/16344
      changes:
        - renameColumn:
            tableName: report_dashboardcard
            columnDataType: int
            oldColumnName: sizeY
            newColumnName: size_y

  - changeSet:
      id: v45.00-030
      author: camsaul
      comment: Added 0.45.0 -- add default value to DashboardCard size_x -- this was previously done by Toucan
      changes:
        - addDefaultValue:
            tableName: report_dashboardcard
            columnName: size_x
            defaultValue: 2

  - changeSet:
      id: v45.00-031
      author: camsaul
      comment: Added 0.45.0 -- add default value to DashboardCard size_y -- this was previously done by Toucan
      changes:
        - addDefaultValue:
            tableName: report_dashboardcard
            columnName: size_y
            defaultValue: 2

  - changeSet:
      id: v45.00-032
      author: camsaul
      comment: Added 0.45.0 -- add default value for DashboardCard created_at (Postgres/H2)
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: postgresql,h2
      changes:
        - addDefaultValue:
            tableName: report_dashboardcard
            columnName: created_at
            columnDataType: ${timestamp_type}
            defaultValueComputed: current_timestamp

    # addDefaultValue with defaultValueComputed doesn't work for MySQL/MariaDB so we have to do this the hard way.
  - changeSet:
      id: v45.00-033
      author: camsaul
      comment: Added 0.45.0 -- add default value for DashboardCard created_at (MySQL/MariaDB)
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb
      changes:
        - sql:
            sql: >-
              ALTER TABLE report_dashboardcard
              CHANGE created_at
              created_at timestamp(6) NOT NULL DEFAULT current_timestamp(6);
      rollback: # nothing to do, but required for sql

  - changeSet:
      id: v45.00-034
      author: camsaul
      comment: Added 0.45.0 -- add default value for DashboardCard updated_at (Postgres/H2)
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: postgresql,h2
      changes:
        - addDefaultValue:
            tableName: report_dashboardcard
            columnName: updated_at
            columnDataType: ${timestamp_type}
            defaultValueComputed: current_timestamp

  - changeSet:
      id: v45.00-035
      author: camsaul
      comment: Added 0.45.0 -- add default value for DashboardCard updated_at (MySQL/MariaDB)
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb
      changes:
        - sql:
            sql: >-
              ALTER TABLE report_dashboardcard
              CHANGE updated_at
              updated_at timestamp(6) NOT NULL DEFAULT current_timestamp(6);
      rollback: # nothing to do

  - changeSet:
      id: v45.00-036
      author: snoe
      comment: Added 0.45.0 - add model action table
      changes:
        - createTable:
            tableName: model_action
            remarks: Ties actions to models
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: entity_id
                  type: char(21)
                  remarks: Random NanoID tag for unique identity.
                  constraints:
                    nullable: false
                    unique: true
              - column:
                  name: slug
                  type: varchar(254)
                  remarks: The referenceable name for this action
                  constraints:
                    nullable: false
              - column:
                  name: card_id
                  type: int
                  remarks: The associated model
                  constraints:
                    nullable: false
                    referencedTableName: report_card
                    referencedColumnNames: id
                    foreignKeyName: fk_model_action_ref_card_id
                    deleteCascade: true
              - column:
                  name: action_id
                  type: int
                  remarks: The associated action
                  constraints:
                    nullable: true
                    referencedTableName: action
                    referencedColumnNames: id
                    foreignKeyName: fk_model_action_ref_action_id
                    deleteCascade: true
              - column:
                  name: requires_pk
                  remarks: Indicates that the primary key(s) need to be passed in as parameters
                  type: boolean
                  defaultValueBoolean: false
                  constraints:
                    nullable: false
              - column:
                  name: parameter_mappings
                  type: ${text.type}
                  remarks: Mappings for primary keys to action parameters
              - column:
                  name: visualization_settings
                  type: ${text.type}
                  remarks: Settings for rendering the action
  - changeSet:
      id: v45.00-037
      author: snoe
      comment: Added 0.45.0 - model action
      changes:
        - addUniqueConstraint:
            tableName: model_action
            columnNames: card_id, slug
            constraintName: unique_model_action_card_id_slug
      rollback: # will be deleted with table

  # The next 4 values add default values for Database `created_at` and `updated_at`; previously this was handled by
  # Toucan but it's more convenient to do this at the application database level instead -- it facilitates stuff like
  # schema migration tests that don't use Toucan, or other manual scripting
  - changeSet:
      id: v45.00-038
      author: camsaul
      comment: Added 0.45.0 -- add default value for Database created_at (Postgres/H2)
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: postgresql,h2
      changes:
        - addDefaultValue:
            tableName: metabase_database
            columnName: created_at
            columnDataType: ${timestamp_type}
            defaultValueComputed: current_timestamp

    # addDefaultValue with defaultValueComputed doesn't work for MySQL/MariaDB so we have to do this the hard way.
  - changeSet:
      id: v45.00-039
      author: camsaul
      comment: Added 0.45.0 -- add default value for Database created_at (MySQL/MariaDB)
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb
      changes:
        - sql:
            sql: >-
              ALTER TABLE metabase_database
              CHANGE created_at
              created_at timestamp(6) NOT NULL DEFAULT current_timestamp(6);
      rollback: # nothing to do

  - changeSet:
      id: v45.00-040
      author: camsaul
      comment: Added 0.45.0 -- add default value for Database updated_at (Postgres/H2)
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: postgresql,h2
      changes:
        - addDefaultValue:
            tableName: metabase_database
            columnName: updated_at
            columnDataType: ${timestamp_type}
            defaultValueComputed: current_timestamp

  - changeSet:
      id: v45.00-041
      author: camsaul
      comment: Added 0.45.0 -- add default value for Database updated_at (MySQL/MariaDB)
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb
      changes:
        - sql:
            sql: >-
              ALTER TABLE metabase_database
              CHANGE updated_at
              updated_at timestamp(6) NOT NULL DEFAULT current_timestamp(6);
      rollback: # nothing to do

  # It was probably an oversight, but while we validated Database `details` in the API layer it was not a required/NOT
  # NULL column in the application Database itself. No problem; let's add it now that we've noticed it.
  #
  # MySQL (at least 5.7) won't let us have nice things:
  #
  # https://dev.mysql.com/doc/refman/5.7/en/data-type-defaults.html
  #
  # The BLOB, TEXT, GEOMETRY, and JSON data types cannot be assigned a default value.
  #
  # Because of this restriction we will just have to update existing NULL values in SQL and then add a NOT NULL
  # restriction separately; we can use Toucan `pre-insert` to set defaults values when saving things.
  - changeSet:
      id: v45.00-042
      author: camsaul
      comment: Added 0.45.0 -- add default value for Database with NULL details
      changes:
        - sql:
            sql: >-
              UPDATE metabase_database SET details = '{}' WHERE details IS NULL;
      rollback: # nothing to do, since a '{}' is okay for v44

  - changeSet:
      id: v45.00-043
      author: camsaul
      comment: Added 0.45.0 -- make Database details NOT NULL
      changes:
        - addNotNullConstraint:
            columnDataType: ${text.type}
            tableName: metabase_database
            columnName: details

  - changeSet:
      id: v45.00-044
      author: metamben
      comment: Added 0.45.0 -- create app permission graph revision table
      changes:
        - createTable:
            tableName: app_permission_graph_revision
            remarks: 'Used to keep track of changes made to app permissions.'
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: before
                  type: ${text.type}
                  remarks: 'Serialized JSON of the apps graph before the changes.'
                  constraints:
                    nullable: false
              - column:
                  name: after
                  type: ${text.type}
                  remarks: 'Serialized JSON of the apps graph after the changes.'
                  constraints:
                    nullable: false
              - column:
                  name: user_id
                  type: int
                  remarks: 'The ID of the admin who made this set of changes.'
                  constraints:
                    nullable: false
                    referencedTableName: core_user
                    referencedColumnNames: id
                    foreignKeyName: fk_app_permission_graph_revision_user_id
              - column:
                  name: created_at
                  type: ${timestamp_type}
                  remarks: 'The timestamp of when these changes were made.'
                  defaultValueComputed: current_timestamp
                  constraints:
                    nullable: false
              - column:
                  name: remark
                  type: ${text.type}
                  remarks: 'Optional remarks explaining why these changes were made.'

  # note: some migrations which only added and deleted tables within v45 were removed, hence an ID gap here

  # Add created_at to Collection
  - changeSet:
      id: v45.00-048
      author: camsaul
      comment: Added 0.45.0 -- add created_at to Collection
      changes:
        - addColumn:
            tableName: collection
            columns:
              - column:
                  name: created_at
                  type: ${timestamp_type}
                  remarks: Timestamp of when this Collection was created.
                  constraints:
                    nullable: false
                  defaultValueComputed: current_timestamp

  # Seed Collection created_at for Personal Collections with the date_joined of the User that owns them.
  - changeSet:
      id: v45.00-049
      author: camsaul
      comment: Added 0.45.0 -- set Collection.created_at to User.date_joined for Personal Collections
      changes:
        - sql:
            dbms: postgresql
            sql: >-
              UPDATE collection c
              SET created_at = u.date_joined
              FROM core_user u
              WHERE c.personal_owner_id = u.id;
        - sql:
            dbms: mysql,mariadb
            sql: >-
              UPDATE collection c
              INNER JOIN core_user u
              ON c.personal_owner_id = u.id
              SET c.created_at = u.date_joined;
        - sql:
            dbms: h2
            sql: >-
              UPDATE collection c
              SET created_at = (
                SELECT u.date_joined
                FROM core_user u
                WHERE c.personal_owner_id = u.id
              )
              WHERE c.personal_owner_id IS NOT NULL;
      rollback: # nothing to roll back, but required for sql change types

  # seed Collection created_at based on the max created at of child objects
  #
  # At the time of this writing, the following Models can appear in a Collection:
  #
  # - App
  # - Card
  # - Dashboard
  # - Pulse
  # - Timeline
  # - NativeQuerySnippet
  - changeSet:
      id: v45.00-050
      author: camsaul
      validCheckSum: ANY
      comment: Added 0.45.0 -- seed Collection.created_at with value of oldest item for non-Personal Collections
      changes:
        - sql:
            dbms: postgresql
            sql: >-
              UPDATE collection c
              SET created_at = created_ats.created_at
              FROM (
                SELECT min(created_at) AS created_at, collection_id
                FROM (
                  SELECT created_at, collection_id FROM app                  UNION ALL
                  SELECT created_at, collection_id FROM report_card          UNION ALL
                  SELECT created_at, collection_id FROM report_dashboard     UNION ALL
                  SELECT created_at, collection_id FROM pulse                UNION ALL
                  SELECT created_at, collection_id FROM timeline             UNION ALL
                  SELECT created_at, collection_id FROM native_query_snippet
                ) created_ats
                GROUP BY collection_id
              ) created_ats
              WHERE c.id = created_ats.collection_id
                AND c.personal_owner_id IS NULL;
        - sql:
            dbms: mysql,mariadb
            sql: >-
              UPDATE collection c
              LEFT JOIN (
                SELECT min(created_at) AS created_at, collection_id
                FROM (
                  SELECT created_at, collection_id FROM app                  UNION ALL
                  SELECT created_at, collection_id FROM report_card          UNION ALL
                  SELECT created_at, collection_id FROM report_dashboard     UNION ALL
                  SELECT created_at, collection_id FROM pulse                UNION ALL
                  SELECT created_at, collection_id FROM timeline             UNION ALL
                  SELECT created_at, collection_id FROM native_query_snippet
                ) created_ats
                GROUP BY collection_id
              ) created_ats
              ON c.id = created_ats.collection_id
              SET c.created_at = created_ats.created_at
              WHERE c.personal_owner_id IS NULL
                AND created_ats.created_at IS NOT NULL;
        - sql:
            dbms: h2
            # I would have preferred using MERGE ... USING instead of WHERE EXISTS ... but it's broken in 1.4.197
            # because of https://github.com/h2database/h2database/issues/1034, which is fixed in 1.4.198. So this will
            # have to do for now, even if it's a little ugly.
            sql: >-
              WITH created_ats AS (
                SELECT min(created_at) AS created_at, collection_id
                FROM (
                  SELECT created_at, collection_id FROM app                  UNION ALL
                  SELECT created_at, collection_id FROM report_card          UNION ALL
                  SELECT created_at, collection_id FROM report_dashboard     UNION ALL
                  SELECT created_at, collection_id FROM pulse                UNION ALL
                  SELECT created_at, collection_id FROM timeline             UNION ALL
                  SELECT created_at, collection_id FROM native_query_snippet
                ) created_ats
                GROUP BY collection_id
              )
              UPDATE collection c
              SET created_at = (
                SELECT created_ats.created_at
                FROM created_ats
                WHERE created_ats.collection_id = c.id
              )
              WHERE EXISTS (
                SELECT created_ats.collection_id
                FROM created_ats
                WHERE c.id = created_ats.collection_id
                  AND c.personal_owner_id IS NULL
              );
      rollback: # rollback is a no-op for most seed migrations, but required for sql change type

  - changeSet:
      id: v45.00-051
      author: qnkhuat
      comment: >-
        Added 0.45.0 - modify type of collection_permission_graph_revision.after from text to ${text.type}
        on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: collection_permission_graph_revision
            columnName: after
            newDataType: ${text.type}
      rollback:
        - modifyDataType:
            tableName: collection_permission_graph_revision
            columnName: after
            newDataType: text
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v45.00-052
      author: qnkhuat
      comment: >-
        Added 0.45.0 - modify type of collection_permission_graph_revision.before from text to ${text.type}
        on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: collection_permission_graph_revision
            columnName: before
            newDataType: ${text.type}
      rollback:
        - modifyDataType:
            tableName: collection_permission_graph_revision
            columnName: before
            newDataType: text
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v45.00-053
      author: qnkhuat
      comment: >-
        Added 0.45.0 - modify type of collection_permission_graph_revision.remark from text to ${text.type}
        on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: collection_permission_graph_revision
            columnName: remark
            newDataType: ${text.type}
      rollback:
        - modifyDataType:
            tableName: collection_permission_graph_revision
            columnName: remark
            newDataType: text
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v45.00-054
      author: qnkhuat
      comment: >-
        Added 0.45.0 - modify type of permissions_revision.after from text to ${text.type}
        on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: permissions_revision
            columnName: after
            newDataType: ${text.type}
      rollback:
        - modifyDataType:
            tableName: permissions_revision
            columnName: after
            newDataType: text
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v45.00-055
      author: qnkhuat
      comment: >-
        Added 0.45.0 - modify type of permissions_revision.before from text to ${text.type}
        on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: permissions_revision
            columnName: before
            newDataType: ${text.type}
      rollback:
        - modifyDataType:
            tableName: permissions_revision
            columnName: before
            newDataType: text
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v45.00-056
      author: qnkhuat
      comment: >-
        Added 0.45.0 - modify type of permissions_revision.remark from text to ${text.type}
        on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: permissions_revision
            columnName: remark
            newDataType: ${text.type}
      rollback:
        - modifyDataType:
            tableName: permissions_revision
            columnName: remark
            newDataType: text
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v45.00-057
      author: qnkhuat
      comment: >-
        Added 0.45.0 - modify type of secret.value from blob to longblob
        on mysql,mariadb
      changes:
        - modifyDataType:
            tableName: secret
            columnName: value
            newDataType: longblob
      rollback:
        - modifyDataType:
            tableName: secret
            columnName: value
            newDataType: ${blob.type}
      preConditions:
        - onFail: MARK_RAN
        - dbms:
            type: mysql,mariadb

  - changeSet:
      id: v46.00-000
      author: snoe
      comment: Added 0.46.0 - Unify action representation
      changes:
        - createTable:
            tableName: implicit_action
            remarks: An action with dynamic parameters based on the underlying model
            columns:
              - column:
                  name: action_id
                  type: int
                  remarks: The associated action
                  constraints:
                    nullable: false
                    referencedTableName: action
                    referencedColumnNames: id
                    foreignKeyName: fk_implicit_action_action_id
                    deleteCascade: true
              - column:
                  name: kind
                  type: ${text.type}
                  remarks: The kind of implicit action create/update/delete
                  constraints:
                    nullable: false

  - changeSet:
      id: v46.00-001
      author: snoe
      comment: Added 0.46.0 - Unify action representation
      changes:
        - addColumn:
            tableName: action
            columns:
              - column:
                  name: model_id
                  remarks: The associated model
                  type: int

  - changeSet:
      id: v46.00-002
      author: snoe
      comment: Added 0.46.0 - Unify action representation
      changes:
        - addColumn:
            tableName: action
            columns:
              - column:
                  name: name
                  remarks: The name of the action
                  type: varchar(254)

  - changeSet:
      id: v46.00-003
      author: snoe
      comment: Added 0.46.0 - Unify action representation
      changes:
        - addColumn:
            tableName: action
            columns:
              - column:
                  name: description
                  remarks: The description of the action
                  type: ${text.type}

  - changeSet:
      id: v46.00-004
      author: snoe
      comment: Added 0.46.0 - Unify action representation
      changes:
        - addColumn:
            tableName: action
            columns:
              - column:
                  name: parameters
                  remarks: The saved parameters for this action
                  type: ${text.type}

  - changeSet:
      id: v46.00-005
      author: snoe
      comment: Added 0.46.0 - Unify action representation
      changes:
        - addColumn:
            tableName: action
            columns:
              - column:
                  name: parameter_mappings
                  remarks: The saved parameter mappings for this action
                  type: ${text.type}
  - changeSet:
      id: v46.00-006
      author: snoe
      comment: Added 0.46.0 - Unify action representation
      changes:
        - addColumn:
            tableName: action
            columns:
              - column:
                  name: visualization_settings
                  remarks: The UI visualization_settings for this action
                  type: ${text.type}

  - changeSet:
      id: v46.00-007
      author: snoe
      comment: Added 0.46.0 - Unify action representation
      changes:
        - addForeignKeyConstraint:
            baseTableName: action
            baseColumnNames: model_id
            referencedTableName: report_card
            referencedColumnNames: id
            constraintName: fk_action_model_id

  - changeSet:
      id: v46.00-008
      author: snoe
      comment: Added 0.46.0 - Unify action representation
      changes:
        - addColumn:
            tableName: query_action
            columns:
              - column:
                  name: database_id
                  remarks: The associated database
                  type: int

  - changeSet:
      id: v46.00-009
      author: snoe
      comment: Added 0.46.0 - Unify action representation
      changes:
        - addColumn:
            tableName: query_action
            columns:
              - column:
                  name: dataset_query
                  remarks: The MBQL writeback query
                  type: ${text.type}

  - changeSet:
      id: v46.00-010
      author: snoe
      comment: Added 0.46.0 - Unify action representation
      changes:
        - addForeignKeyConstraint:
            baseTableName: query_action
            baseColumnNames: database_id
            referencedTableName: metabase_database
            referencedColumnNames: id
            constraintName: fk_query_action_database_id
            onDelete: CASCADE

  - changeSet:
      id: v46.00-011
      author: snoe
      validCheckSum: ANY
      comment: Added 0.46.0 - Unify action representation
      changes:
        - sql:
            dbms: mysql,mariadb
            sql: >-
              ALTER TABLE query_action DROP PRIMARY KEY, ADD PRIMARY KEY pk_query_action (action_id);
        - sql:
            dbms: h2
            sql: >-
              ALTER TABLE query_action DROP PRIMARY KEY;
              ALTER TABLE query_action ADD CONSTRAINT pk_query_action PRIMARY KEY (action_id);
        - sql:
            dbms: postgresql
            sql: >-
              ALTER TABLE query_action DROP CONSTRAINT pk_query_action;
              ALTER TABLE query_action ADD CONSTRAINT pk_query_action PRIMARY KEY (action_id);
      rollback:
        - sql:
            dbms: mysql,mariadb
            sql: >-
              ALTER TABLE query_action DROP PRIMARY KEY, ADD PRIMARY KEY pk_query_action (action_id, card_id);
        - sql:
            dbms: h2
            sql: >-
              ALTER TABLE query_action DROP CONSTRAINT fk_query_action_ref_action_id;
              ALTER TABLE query_action DROP PRIMARY KEY;
              ALTER TABLE query_action ADD CONSTRAINT fk_query_action_ref_action_id FOREIGN KEY (action_id) REFERENCES action(id) ON DELETE CASCADE;
              ALTER TABLE query_action ADD CONSTRAINT pk_query_action PRIMARY KEY (action_id, card_id);
        - sql:
            dbms: postgresql
            sql: >-
              ALTER TABLE query_action DROP CONSTRAINT pk_query_action;
              ALTER TABLE query_action ADD CONSTRAINT pk_query_action PRIMARY KEY (action_id, card_id);

  - changeSet:
      id: v46.00-012
      author: snoe
      comment: Added 0.46.0 - Unify action representation
      changes:
        - dropNotNullConstraint:
            tableName: query_action
            columnDataType: int
            columnName: card_id

  # migration for developers and internal use of actions created in 45 during a short period.
  - changeSet:
      id: v46.00-013
      author: snoe
      comment: Added 0.46.0 - Unify action representation
      validCheckSum: ANY
      changes:
        - sql:
            sql: >-
              INSERT INTO action (type, model_id, name)
              SELECT 'implicit', card_id, slug
              FROM model_action
              WHERE action_id is null AND slug in ('insert','update','delete');

              INSERT INTO implicit_action (action_id, kind)
              SELECT
                id,
                case name
                  when 'insert' then 'row/create'
                  when 'update' then 'row/update'
                  when 'delete' then 'row/delete'
                end
              FROM action
              WHERE type = 'implicit';

              UPDATE action
              SET model_id = (SELECT card_id
                              FROM model_action
                              WHERE model_action.action_id = action.id)
              WHERE model_id is null;

              DELETE FROM action WHERE model_id is null;

              UPDATE report_dashboardcard
              SET action_id = (SELECT action.id
                               FROM action
                               LEFT JOIN implicit_action ON implicit_action.action_id = action.id
                               WHERE action.model_id = report_dashboardcard.card_id
                               AND coalesce((
                                  CASE implicit_action.kind
                                     WHEN 'row/create' THEN 'insert'
                                     WHEN 'row/delete' THEN 'delete'
                                     WHEN 'row/update' THEN 'update'
                                  END), ('action_' || action.id)) =
                                  substring(report_dashboardcard.visualization_settings,
                                    position('"action_slug":"' in report_dashboardcard.visualization_settings)+15,
                                    position('"' in
                                      substring(report_dashboardcard.visualization_settings,
                                        position('"action_slug":"' in visualization_settings)+15)) - 1))
              WHERE report_dashboardcard.visualization_settings like '%action_slug%';

              UPDATE query_action SET
                dataset_query = (select dataset_query from report_card where report_card.id = query_action.card_id),
                database_id = (select database_id from report_card where report_card.id = query_action.card_id);

              UPDATE action SET
                name = (
                  select name
                  from query_action
                  inner join report_card on report_card.id = query_action.card_id
                  where query_action.action_id = action.id),
                description = (
                  select description
                  from query_action
                  inner join report_card on report_card.id = query_action.card_id
                  where query_action.action_id = action.id),
                parameters = (
                  select parameters
                  from query_action
                  inner join report_card on report_card.id = query_action.card_id
                  where query_action.action_id = action.id),
                parameter_mappings = (
                  select parameter_mappings
                  from query_action
                  inner join report_card on report_card.id = query_action.card_id
                  where query_action.action_id = action.id),
                visualization_settings = (
                  select visualization_settings
                  from query_action
                  inner join report_card on report_card.id = query_action.card_id
                  where query_action.action_id = action.id)
              WHERE type = 'query';
      rollback: # no-op, we do not care to preserve actions from 46->45

  - changeSet:
      id: v46.00-014
      author: snoe
      comment: Added 0.46.0 - Unify action representation
      changes:
        - dropForeignKeyConstraint:
            baseTableName: query_action
            constraintName: fk_query_action_ref_card_id
      rollback:

  - changeSet:
      id: v46.00-015
      author: snoe
      comment: Added 0.46.0 - Unify action representation
      changes:
        - dropColumn:
            tableName: query_action
            columnName: card_id

      rollback:
        - addColumn:
            tableName: query_action
            columns:
              - column:
                  name: card_id
                  type: int
                  remarks: The related card
                  constraints:
                    nullable: false
                    referencedTableName: report_card
                    referencedColumnNames: id
                    foreignKeyName: fk_query_action_ref_card_id
                    deleteCascade: true

  - changeSet:
      id: v46.00-016
      author: snoe
      comment: Added 0.46.0 - Unify action representation
      changes:
        - sql:
            sql: >-
              DELETE FROM report_card
              WHERE is_write = true;

              DELETE FROM model_action;
      rollback: # we do not care to preserve actions from 46->45
        - sql:
            sql: >-
              DELETE FROM report_dashboardcard WHERE action_id is not null;
              DELETE FROM action;

  - changeSet:
      id: v46.00-017
      author: snoe
      comment: Added 0.46.0 - Unify action representation
      changes:
        - dropColumn:
            tableName: http_action
            columnName: name
      rollback:
        - addColumn:
            tableName: http_action
            columns:
              - column:
                  name: name
                  type: varchar(254)
                  remarks: The name of this action
                  constraints:
                    nullable: false

  - changeSet:
      id: v46.00-018
      author: snoe
      comment: Added 0.46.0 - Unify action representation
      changes:
        - dropColumn:
            tableName: http_action
            columnName: description
      rollback:
        - addColumn:
            tableName: http_action
            columns:
              - column:
                  name: description
                  type: ${text.type}
                  remarks: An optional description for this action

  - changeSet:
      id: v46.00-019
      author: snoe
      comment: Added 0.46.0 - Unify action representation
      changes:
        - dropColumn:
            tableName: report_card
            columnName: is_write
      rollback:
        - addColumn:
            columns:
              - column:
                  name: is_write
                  type: boolean
                  defaultValueBoolean: false
                  remarks: Indicates that this query will perform writes to a db
                  constraints:
                    nullable: false
            tableName: report_card

  - changeSet:
      id: v46.00-020
      author: snoe
      comment: Added 0.46.0 - Unify action representation
      changes:
        - addNotNullConstraint:
            tableName: query_action
            columnName: database_id
            columnDataType: int

  - changeSet:
      id: v46.00-021
      author: snoe
      comment: Added 0.46.0 - Unify action representation
      changes:
        - addNotNullConstraint:
            tableName: query_action
            columnName: dataset_query
            columnDataType: ${text.type}

  - changeSet:
      id: v46.00-022
      author: snoe
      comment: Added 0.46.0 - Unify action representation
      changes:
        - addNotNullConstraint:
            tableName: query_action
            columnName: dataset_query
            columnDataType: ${text.type}

  - changeSet:
      id: v46.00-023
      author: snoe
      comment: Added 0.46.0 - Unify action representation
      changes:
        - addNotNullConstraint:
            tableName: action
            columnName: model_id
            columnDataType: int

  - changeSet:
      id: v46.00-024
      author: snoe
      comment: Added 0.46.0 - Unify action representation
      changes:
        - addNotNullConstraint:
            tableName: action
            columnName: name
            columnDataType: varchar(254)

  - changeSet:
      id: v46.00-025
      author: snoe
      comment: Added 0.46.0 - Unify action representation
      changes:
        - dropTable:
            tableName: model_action
      rollback:
        - createTable:
            tableName: model_action
            remarks: Ties actions to models
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: entity_id
                  type: char(21)
                  remarks: Random NanoID tag for unique identity.
                  constraints:
                    nullable: false
                    unique: true
              - column:
                  name: slug
                  type: varchar(254)
                  remarks: The referenceable name for this action
                  constraints:
                    nullable: false
              - column:
                  name: card_id
                  type: int
                  remarks: The associated model
                  constraints:
                    nullable: false
                    referencedTableName: report_card
                    referencedColumnNames: id
                    foreignKeyName: fk_model_action_ref_card_id
                    deleteCascade: true
              - column:
                  name: action_id
                  type: int
                  remarks: The associated action
                  constraints:
                    nullable: true
                    referencedTableName: action
                    referencedColumnNames: id
                    foreignKeyName: fk_model_action_ref_action_id
                    deleteCascade: true
              - column:
                  name: requires_pk
                  remarks: Indicates that the primary key(s) need to be passed in as parameters
                  type: boolean
                  defaultValueBoolean: false
                  constraints:
                    nullable: false
              - column:
                  name: parameter_mappings
                  type: ${text.type}
                  remarks: Mappings for primary keys to action parameters
              - column:
                  name: visualization_settings
                  type: ${text.type}
                  remarks: Settings for rendering the action

  - changeSet:
      id: v46.00-026
      author: metamben
      comment: Added 0.46.0 -- add field for tracking DBMS versions
      changes:
        - addColumn:
            tableName: metabase_database
            columns:
              - column:
                  name: dbms_version
                  type: ${text.type}
                  remarks: 'A JSON object describing the flavor and version of the DBMS.'

  - changeSet:
      id: v46.00-027
      author: snoe
      comment: Added 0.46.0 -- add last_used_at to FieldValues
      changes:
        - addColumn:
            tableName: metabase_fieldvalues
            columns:
              - column:
                  name: last_used_at
                  type: ${timestamp_type}
                  remarks: Timestamp of when these FieldValues were last used.
                  constraints:
                    nullable: false
                  defaultValueComputed: current_timestamp

  - changeSet:
      id: v46.00-028
      author: tsmacdonald
      comment: Added 0.46.0 -- Join table connecting cards to dashboards/cards's parameters that need custom filter values from the card
      changes:
        - createTable:
            tableName: parameter_card
            remarks: "Join table connecting cards to entities (dashboards, other cards, etc.) that use the values generated by the card for filter values"
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: updated_at
                  type: ${timestamp_type}
                  defaultValueComputed: current_timestamp
                  remarks: "most recent modification time"
                  constraints:
                    nullable: false
              - column:
                  name: created_at
                  type: ${timestamp_type}
                  defaultValueComputed: current_timestamp
                  remarks: "creation time"
                  constraints:
                    nullable: false
              - column:
                  name: card_id
                  type: int
                  remarks: "ID of the card generating the values"
                  constraints:
                    nullable: false
              - column:
                  name: parameterized_object_type
                  type: varchar(32)
                  remarks: "Type of the entity consuming the values (dashboard, card, etc.)"
                  constraints:
                    nullable: false
              - column:
                  name: parameterized_object_id
                  type: int
                  remarks: "ID of the entity consuming the values"
                  constraints:
                    nullable: false
              - column:
                  name: parameter_id
                  type: varchar(32)
                  remarks: "The parameter ID"
                  constraints:
                    nullable: false

  # Make Dimension <=> Field a 1t1 relationship. Replace unique field_id + name with unique field_id.
  # See issue #27054.
  - changeSet:
      id: v46.00-029
      author: camsaul
      comment: Make Dimension <=> Field a 1t1 relationship. Drop unique constraint on field_id + name. (1/3)
      changes:
        - dropUniqueConstraint:
            tableName: dimension
            constraintName: unique_dimension_field_id_name
      rollback:
        - addUniqueConstraint:
            tableName: dimension
            constraintName: unique_dimension_field_id_name
            columnNames: field_id, name

  - changeSet:
      id: v46.00-030
      author: camsaul
      comment: Make Dimension <=> Field a 1t1 relationship. Delete duplicate entries. (2/3)
      changes:
        - sql:
            # Which rows to keep is not 100% clear. I decided to keep newer entries, by ID. I considered keeping new
            # entries by `updated_at` but the SQL for doing that across the three databases was such a hairball and
            # having duplicates in the first place was such an edge case I decided this approach is fine for now. The
            # `row_number()` window function would have made this easier to do but we haven't merged H2 v2 yet.
            #
            # Writing the query with these unnecessary subselects is stupid, but MySQL 5.7 doesn't work without them.
            # See https://metaboat.slack.com/archives/CKZEMT1MJ/p1670624514320419 for more info
            sql: >-
              DELETE FROM dimension
              WHERE field_id IN (
                SELECT field_id
                FROM (
                  SELECT field_id
                  FROM dimension
                  GROUP BY field_id
                  HAVING COUNT(*) > 1
                ) duplicates
              )
              AND id NOT IN (
                SELECT id FROM (
                  SELECT max(id) AS id
                  FROM dimension
                  GROUP BY field_id
                ) most_recents
              );
      rollback: # don't need to roll back anything, deleting duplicate entries doesn't need to be reversed.

  - changeSet:
      id: v46.00-031
      author: camsaul
      comment: Make Dimension <=> Field a 1t1 relationship. Add unique constraint on field_id. (3/3)
      changes:
        - addUniqueConstraint:
            tableName: dimension
            columnNames: field_id
            constraintName: unique_dimension_field_id
        # this change can roll back automatically.

  - changeSet:
      id: v46.00-032
      author: tsmacdonald
      comment: Added 0.46.0 -- Unique parameter_card
      changes:
        - addUniqueConstraint:
            tableName: parameter_card
            columnNames: parameterized_object_id, parameterized_object_type, parameter_id
            constraintName: unique_parameterized_object_card_parameter

  - changeSet:
      id: v46.00-033
      author: tsmacdonald
      comment: Added 0.46.0 -- parameter_card index on connected object
      changes:
        - createIndex:
            tableName: parameter_card
            columns:
              - column:
                  name: parameterized_object_id
            indexName: idx_parameter_card_parameterized_object_id

  - changeSet:
      id: v46.00-034
      author: tsmacdonald
      comment: Added 0.46.0 -- parameter_card index on connected card
      changes:
        - createIndex:
            tableName: parameter_card
            columns:
              - column:
                  name: card_id
            indexName: idx_parameter_card_card_id

  - changeSet:
      id: v46.00-035
      author: tsmacdonald
      comment: Added 0.46.0 - parameter_card.card_id foreign key
      changes:
        - addForeignKeyConstraint:
            baseTableName: parameter_card
            baseColumnNames: card_id
            referencedTableName: report_card
            referencedColumnNames: id
            constraintName: fk_parameter_card_ref_card_id
            onDelete: CASCADE

  - changeSet:
      id: v46.00-036
      author: metamben
      comment: App containers are removed in 0.46.0
      changes:
        - dropTable:
            tableName: app_permission_graph_revision
      rollback:
        - createTable:
            tableName: app_permission_graph_revision
            remarks: 'Used to keep track of changes made to app permissions.'
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: before
                  type: ${text.type}
                  remarks: 'Serialized JSON of the apps graph before the changes.'
                  constraints:
                    nullable: false
              - column:
                  name: after
                  type: ${text.type}
                  remarks: 'Serialized JSON of the apps graph after the changes.'
                  constraints:
                    nullable: false
              - column:
                  name: user_id
                  type: int
                  remarks: 'The ID of the admin who made this set of changes.'
                  constraints:
                    nullable: false
                    referencedTableName: core_user
                    referencedColumnNames: id
                    foreignKeyName: fk_app_permission_graph_revision_user_id
              - column:
                  name: created_at
                  type: ${timestamp_type}
                  remarks: 'The timestamp of when these changes were made.'
                  defaultValueComputed: current_timestamp
                  constraints:
                    nullable: false
              - column:
                  name: remark
                  type: ${text.type}
                  remarks: 'Optional remarks explaining why these changes were made.'

  - changeSet:
      id: v46.00-037
      author: metamben
      comment: App pages are removed in 0.46.0
      changes:
        - dropColumn:
            tableName: report_dashboard
            columnName: is_app_page
      rollback:
        - addColumn:
            columns:
              - column:
                  name: is_app_page
                  type: boolean
                  defaultValueBoolean: false
                  remarks: Indicates that this dashboard serves as a page of an app
                  constraints:
                    nullable: false
            tableName: report_dashboard

  - changeSet:
      id: v46.00-038
      author: metamben
      comment: App containers are removed in 0.46.0
      changes:
        - dropTable:
            tableName: app
      rollback:
        - createTable:
            tableName: app
            remarks: Defines top level concerns for App
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: entity_id
                  type: char(21)
                  remarks: Random NanoID tag for unique identity.
                  constraints:
                    nullable: false
                    unique: true
              - column:
                  name: collection_id
                  type: int
                  remarks: The associated collection
                  constraints:
                    nullable: false
                    referencedTableName: collection
                    referencedColumnNames: id
                    foreignKeyName: fk_app_ref_collection_id
                    deleteCascade: true
                    unique: true
              - column:
                  name: dashboard_id
                  type: int
                  remarks: The homepage of the app
              - column:
                  remarks: JSON for the navigation items of the app
                  name: nav_items
                  type: ${text.type}
              - column:
                  remarks: JSON for frontend related additions, such as styling
                  name: options
                  type: ${text.type}
              - column:
                  remarks: The timestamp of when the app was created
                  name: created_at
                  type: ${timestamp_type}
                  defaultValueComputed: current_timestamp
                  constraints:
                    nullable: false
              - column:
                  remarks: The timestamp of when the app was updated
                  name: updated_at
                  type: ${timestamp_type}
                  defaultValueComputed: current_timestamp
                  constraints:
                    nullable: false
        - addForeignKeyConstraint:
            baseTableName: app
            baseColumnNames: dashboard_id
            referencedTableName: report_dashboard
            referencedColumnNames: id
            constraintName: fk_app_ref_dashboard_id
            onDelete: SET NULL

  - changeSet:
      id: v46.00-039
      author: qnkhuat
      comment: Added 0.46.0 - add entity_id to parameter_card
      changes:
        - addColumn:
            columns:
            - column:
                remarks: Random NanoID tag for unique identity.
                name: entity_id
                type: char(21)
                constraints:
                  nullable: true
                  unique: true
            tableName: parameter_card

  - changeSet:
      id: v46.00-040
      author: tsmacdonald
      comment: Added 0.46.0 -- Bump default dashcard size to 4x4
      changes:
        - addDefaultValue:
            tableName: report_dashboardcard
            columnName: size_x
            defaultValue: 4

  - changeSet:
      id: v46.00-041
      author: tsmacdonald
      comment: Added 0.46.0 -- Bump default dashcard size to 4x4
      changes:
        - addDefaultValue:
            tableName: report_dashboardcard
            columnName: size_y
            defaultValue: 4

  - changeSet:
      id: v46.00-042
      author: tsmacdonald
      comment: Added 0.46.0 -- index query_execution.executor_id
      changes:
        - createIndex:
            tableName: query_execution
            columns:
              - column:
                  name: executor_id
            indexName: idx_query_execution_executor_id

  - changeSet:
      id: v46.00-043
      author: tsmacdonald
      comment: Added 0.46.0 -- index query_execution.context
      changes:
        - createIndex:
            tableName: query_execution
            columns:
              - column:
                  name: context
            indexName: idx_query_execution_context

  - changeSet:
      id: v46.00-045
      author: calherries
      comment: Added 0.46.0 -- add public_uuid to action.
      changes:
        - addColumn:
            tableName: action
            columns:
              - column:
                  name: public_uuid
                  type: char(36)
                  remarks: 'Unique UUID used to in publically-accessible links to this Action.'
                  constraints:
                    unique: true

  - changeSet:
      id: v46.00-051
      author: calherries
      comment: Added 0.46.0 -- drop defaults for dashcard's position and size
      changes:
        - dropDefaultValue:
            tableName: report_dashboardcard
            columnName: row
      rollback:
        - addDefaultValue:
            tableName: report_dashboardcard
            columnName: row
            defaultValueNumeric: 4

  - changeSet:
      id: v46.00-052
      author: calherries
      comment: Added 0.46.0 -- drop defaults for dashcard's position and size
      changes:
        - dropDefaultValue:
            tableName: report_dashboardcard
            columnName: col
      rollback:
        - addDefaultValue:
            tableName: report_dashboardcard
            columnName: col
            defaultValueNumeric: 4

  - changeSet:
      id: v46.00-053
      author: calherries
      comment: Added 0.46.0 -- drop defaults for dashcard's position and size
      changes:
        - dropDefaultValue:
            tableName: report_dashboardcard
            columnName: size_x
      rollback:
        - addDefaultValue:
            tableName: report_dashboardcard
            columnName: size_x
            defaultValueNumeric: 4

  - changeSet:
      id: v46.00-054
      author: calherries
      comment: Added 0.46.0 -- drop defaults for dashcard's position and size
      changes:
        - dropDefaultValue:
            tableName: report_dashboardcard
            columnName: size_y
      rollback:
        - addDefaultValue:
            tableName: report_dashboardcard
            columnName: size_y
            defaultValueNumeric: 4

  - changeSet:
      id: v46.00-055
      author: calherries
      comment: Added 0.46.0 -- add made_public_by_id
      changes:
        - addColumn:
            tableName: action
            columns:
              - column:
                  name: made_public_by_id
                  type: int
                  remarks: 'The ID of the User who first publically shared this Action.'

  - changeSet:
      id: v46.00-056
      author: calherries
      comment: Added 0.46.0 -- add public_uuid and made_public_by_id to action. public_uuid is indexed
      changes:
        - createIndex:
            tableName: action
            indexName: idx_action_public_uuid
            columns:
              column:
                name: public_uuid

  - changeSet:
      id: v46.00-057
      author: dpsutton
      comment: Added 0.46.0 -- parameter_card.parameter_id long enough to hold a uuid
      changes:
        - modifyDataType:
            tableName: parameter_card
            columnName: parameter_id
            newDataType: varchar(36)
      rollback: #nothing to do, char(32) or char(36) are equivalent

  - changeSet:
      id: v46.00-058
      author: calherries
      comment: Added 0.46.0 -- add FK constraint for action.made_public_by_id with core_user.id
      changes:
        - addForeignKeyConstraint:
            baseTableName: action
            baseColumnNames: made_public_by_id
            referencedTableName: core_user
            referencedColumnNames: id
            constraintName: fk_action_made_public_by_id
            onDelete: CASCADE

  - changeSet:
      id: v46.00-059
      author: tsmacdonald
      comment: Added 0.46.0 -- add actions.creator_id
      changes:
        - addColumn:
            tableName: action
            columns:
              - column:
                  name: creator_id
                  type: int
                  remarks: 'The user who created the action'
      rollback:
        - dropColumn:
            tableName: action
            columnName: creator_id

  - changeSet:
      id: v46.00-060
      author: tsmacdonald
      comment: Added 0.46.0 -- action.creator_id index
      changes:
        - createIndex:
            tableName: action
            columns:
              - column:
                  name: creator_id
            indexName: idx_action_creator_id
      rollback:
        - dropIndex:
            tableName: action
            indexName: idx_action_creator_id

  - changeSet:
      id: v46.00-061
      author: tsmacdonald
      comment: Added 0.46.0 -- action.creator_id index
      changes:
        - addForeignKeyConstraint:
            baseTableName: action
            baseColumnNames: creator_id
            referencedTableName: core_user
            referencedColumnNames: id
            constraintName: fk_action_creator_id
            nullable: false

  - changeSet:
      id: v46.00-062
      author: tsmacdonald
      comment: Added 0.46.0 -- add actions.archived
      changes:
        - addColumn:
            tableName: action
            columns:
              - column:
                  name: archived
                  type: boolean
                  defaultValueBoolean: false
                  remarks: 'Whether or not the action has been archived'
                  constraints:
                    nullable: false
      rollback:
        - dropColumn:
            tableName: action
            columnName: archived

  - changeSet:
      id: v46.00-064
      author: noahmoss
      comment: Added 0.46.0 -- rename `group_table_access_policy` to `sandboxes`
      changes:
        - renameTable:
            newTableName: sandboxes
            oldTableName: group_table_access_policy

  - changeSet:
      id: v46.00-065
      author: noahmoss
      comment: Added 0.46.0 -- add `permission_id` to `sandboxes`
      changes:
      - addColumn:
          tableName: sandboxes
          columns:
          - column:
              name: permission_id
              type: int
              remarks: The ID of the corresponding permissions path for this sandbox

  - changeSet:
      id: v46.00-070
      author: calherries
      comment: Added 0.46.0 - add entity_id column to action
      changes:
        - addColumn:
            columns:
            - column:
                remarks: Random NanoID tag for unique identity.
                name: entity_id
                type: char(21)
                constraints:
                  nullable: true
                  unique: true
            tableName: action

  - changeSet:
      id: v46.00-074
      author: metamben
      comment: Added 0.46.0 -- increase precision of updated_at of report_card
      changes:
        - modifyDataType:
            tableName: report_card
            columnName: updated_at
            newDataType: ${timestamp_type}
      rollback:
        - modifyDataType:
            tableName: report_card
            columnName: updated_at
            newDataType: DATETIME

  - changeSet:
      id: v46.00-079
      author: john-metabase
      comment: Added 0.46.0 -- migrates Databases using deprecated and removed presto driver to presto-jdbc
      changes:
        - sql: UPDATE metabase_database SET engine = 'presto-jdbc' WHERE engine = 'presto'
      rollback: # nothing to do, since we don't know which drivers used to be presto

  - changeSet:
      id: v46.00-080
      author: noahmoss
      comment: Migrate data permission paths from v1 to v2 (splitting them into separate data and query permissions)
      changes:
        - customChange:
            class: "metabase.db.custom_migrations.SplitDataPermissions"

  - changeSet:
      id: v46.00-084
      author: qnkhuat
      comment: Added 0.46.0 - CASCADE delete for action.model_id
      changes:
        - dropForeignKeyConstraint:
            baseTableName: action
            constraintName: fk_action_model_id
      rollback:
        - addForeignKeyConstraint:
            baseTableName: action
            baseColumnNames: model_id
            referencedTableName: report_card
            referencedColumnNames: id
            constraintName: fk_action_model_id
            onDelete: CASCADE

  - changeSet:
      id: v46.00-085
      author: qnkhuat
      comment: Added 0.46.0 - CASCADE delete for action.model_id
      changes:
        - addForeignKeyConstraint:
            baseTableName: action
            baseColumnNames: model_id
            referencedTableName: report_card
            referencedColumnNames: id
            constraintName: fk_action_model_id
            onDelete: CASCADE

  - changeSet:
      id: v46.00-086
      author: calherries
      comment: Added 0.46.0 - Delete the abandonment email task
      changes:
        - customChange:
            class: "metabase.db.custom_migrations.DeleteAbandonmentEmailTask"

  - changeSet:
      id: v46.00-088
      author: noahmoss
      comment: Added 0.46.5 -- backfill `permission_id` values in `sandboxes`. This is a fixed verison of v46.00-066
               which has been removed, since it had a bug that blocked a customer from upgrading.
      changes:
        - sql: >-
            UPDATE sandboxes s
            SET permission_id = (
              SELECT p.id
              FROM permissions p
              WHERE
                p.object = CONCAT('/db/',
                                  (SELECT t.db_id FROM metabase_table t WHERE t.id = s.table_id),
                                  '/schema/',
                                  (SELECT t.schema FROM metabase_table t WHERE t.id = s.table_id),
                                  '/table/',
                                  s.table_id,
                                  '/query/segmented/')
                AND p.group_id = s.group_id
              LIMIT 1
            )
            WHERE permission_id IS NULL;
      rollback:
        # not required, new values added here do not need to be dropped

  - changeSet:
      id: v46.00-089
      author: noahmoss
      comment: Added 0.46.5 -- remove orphaned entries in `sandboxes`
      changes:
        - sql: >-
            DELETE FROM sandboxes
            WHERE permission_id IS NULL;
      rollback: # not required, orphaned sandboxes should not be re-added to the DB

  - changeSet:
      id: v46.00-090
      author: noahmoss
      comment: Add foreign key constraint on sandboxes.permission_id
      # This is a revised version of a prior migration (v46.00-075) so it may fail due to the FK constriant already existing
      failOnError: false
      changes:
        - addForeignKeyConstraint:
            baseTableName: sandboxes
            baseColumnNames: permission_id
            referencedTableName: permissions
            referencedColumnNames: id
            constraintName: fk_sandboxes_ref_permissions
            onDelete: CASCADE

  - changeSet:
      id: v47.00-004
      author: qnkhuat
      comment: Added 0.47.0 - Add auto_incremented to metabase_field
      changes:
        - addColumn:
            tableName: metabase_field
            columns:
              - column:
                  name: database_is_auto_increment
                  type: boolean
                  remarks: Indicates this field is auto incremented
                  defaultValueBoolean: false
                  constraints:
                    nullable: false

# >>>>>>>>>> DO NOT ADD NEW MIGRATIONS BELOW THIS LINE! ADD THEM ABOVE <<<<<<<<<<

########################################################################################################################
#
# ADVICE:
#
# 1) Run ./bin/lint-migrations-file.sh to run core.spec checks against any changes you make here. Liquibase is pretty
#    forgiving and won't complain if you accidentally mix up things like deleteCascade and onDelete: CASCADE. CI runs
#    this check but it's nicer to know now instead of waiting for CI.
#
#   1a) Ensure your changes are compatible with Liquibase rollback. See comments starting with
#       0.45 migrations for more notes. Rollback to 0.44 and forwards to the latest migration is tested
#       automatically and the migrations linter will check for the presence of rollback where required as
#       much as possible.
#
# 2) Please post a message in the Metabase Slack #migrations channel to let others know you are creating a new
#    migration so someone else doesn't steal your ID number
#
# 3) Migrations IDs should follow the format
#
#    vMM.mm-NNN
#
#    where
#
#    M = major version
#    m = minor version
#    N = migration number relative to that major+minor version
#
#   e.g. the first migration added to 0.42.0 should be numbered v42.00-000 and the second migration should be numbered
#   v42.00-001. The first migration for 0.42.1 should be numbered v42.01-000, and so forth.
#
#   This numbering scheme was adopted beginning with version 0.42.0 so that we could go back and add migrations to patch
#   releases without the ID sequence getting wildly out of order. See PR #18821 for more information.
#
# PLEASE KEEP THIS MESSAGE AT THE BOTTOM OF THIS FILE!!!!! Add new migrations above the message.
#
########################################################################################################################
