diff --git a/.prettierignore b/.prettierignore index 79569dff409..82e264fea6a 100644 --- a/.prettierignore +++ b/.prettierignore @@ -7,7 +7,7 @@ client/browser/build **/coverage internal/database/schema*.md internal/database/schema*.json -internal/database/migration/shared/upgradedata/stitched-migration-graph.json +internal/database/migration/shared/data/**/*.json cmd/xlang-python/python-langserver/ package-lock.json package.json diff --git a/doc/dev/background-information/oobmigrations.md b/doc/dev/background-information/oobmigrations.md index 87553c5a3fb..6a74aa5b4c0 100644 --- a/doc/dev/background-information/oobmigrations.md +++ b/doc/dev/background-information/oobmigrations.md @@ -314,7 +314,7 @@ Note that it is not advised to set the deprecated version to the minor release o #### Step 6: Deprecation -Despite an out of band migration being marked deprecated, it may still need to be executed by multi-version upgrades in a later version. For this reason it is not safe to delete any code from the out of band migrations until _after_ the deprecation version falls out of the [supported multi-version upgrade window](https://sourcegraph.com/github.com/sourcegraph/sourcegraph@39996f3159a0466624bc3a57689560c6bdebb60c/-/blob/internal/database/migration/shared/upgradedata/cmd/generator/consts.go?L24). +Despite an out of band migration being marked deprecated, it may still need to be executed by multi-version upgrades in a later version. For this reason it is not safe to delete any code from the out of band migrations until _after_ the deprecation version falls out of the [supported multi-version upgrade window](https://sourcegraph.com/github.com/sourcegraph/sourcegraph@39996f3159a0466624bc3a57689560c6bdebb60c/-/blob/internal/database/migration/shared/data/cmd/generator/consts.go?L24). As an alternative to deleting the code, the out of band migration can be isolated from any dependencies outside of the out of band migration. For example copying any types, functions, and other code that is used to execute the migration. Once isolated, the migration can be considered frozen and effectively ignored. To see an example, [see the Code Insights settings migration](https://sourcegraph.com/github.com/sourcegraph/sourcegraph@39996f3159a0466624bc3a57689560c6bdebb60c/-/tree/enterprise/internal/oobmigration/migrations/insights) diff --git a/enterprise/internal/oobmigration/migrations/codeintel/scip_migrator_test.go b/enterprise/internal/oobmigration/migrations/codeintel/scip_migrator_test.go index 33c604defdb..ac96d446a58 100644 --- a/enterprise/internal/oobmigration/migrations/codeintel/scip_migrator_test.go +++ b/enterprise/internal/oobmigration/migrations/codeintel/scip_migrator_test.go @@ -21,7 +21,9 @@ func init() { func TestSCIPMigrator(t *testing.T) { logger := logtest.Scoped(t) + // TODO - use the AtRev constructor after this has been deprecated rawDB := dbtest.NewDB(logger, t) + // rawDB := dbtest.NewDBAtRev(logger, t, "4.3.0") db := database.NewDB(logger, rawDB) codeIntelDB := stores.NewCodeIntelDB(logger, rawDB) store := basestore.NewWithHandle(db.Handle()) diff --git a/internal/database/dbtest/dbtest.go b/internal/database/dbtest/dbtest.go index 8bc6b98922a..3566c01b8a7 100644 --- a/internal/database/dbtest/dbtest.go +++ b/internal/database/dbtest/dbtest.go @@ -4,6 +4,7 @@ import ( crand "crypto/rand" "database/sql" "encoding/binary" + "fmt" "hash/fnv" "math/rand" "net/url" @@ -60,49 +61,67 @@ var rng = rand.New(rand.NewSource(func() int64 { }())) var rngLock sync.Mutex -var dbTemplateOnce sync.Once - // NewDB returns a connection to a clean, new temporary testing database with // the same schema as Sourcegraph's production Postgres database. func NewDB(logger log.Logger, t testing.TB) *sql.DB { - if testing.Short() { - t.Skip("DB tests disabled since go test -short is specified") - } - - dbTemplateOnce.Do(func() { - initTemplateDB(logger, t, "migrated", []*schemas.Schema{schemas.Frontend, schemas.CodeIntel}) - }) - - return newFromDSN(logger, t, "migrated") + return newDB(logger, t, "migrated", schemas.Frontend, schemas.CodeIntel) } -var insightsTemplateOnce sync.Once +// NewDBAtRev returns a connection to a clean, new temporary testing database with +// the same schema as Sourcegraph's production Postgres database at the given revision. +func NewDBAtRev(logger log.Logger, t testing.TB, rev string) *sql.DB { + return newDB( + logger, + t, + fmt.Sprintf("migrated-%s", rev), + getSchemaAtRev(t, "frontend", rev), + getSchemaAtRev(t, "codeintel", rev), + ) +} + +func getSchemaAtRev(t testing.TB, name, rev string) *schemas.Schema { + schema, err := schemas.ResolveSchemaAtRev(name, rev) + if err != nil { + t.Fatalf("failed to resolve %q schema: %s", name, err) + } + + return schema +} // NewInsightsDB returns a connection to a clean, new temporary testing database with // the same schema as Sourcegraph's CodeInsights production Postgres database. func NewInsightsDB(logger log.Logger, t testing.TB) *sql.DB { - if testing.Short() { - t.Skip("DB tests disabled since go test -short is specified") - } - - insightsTemplateOnce.Do(func() { - initTemplateDB(logger, t, "insights", []*schemas.Schema{schemas.CodeInsights}) - }) - return newFromDSN(logger, t, "insights") + return newDB(logger, t, "insights", schemas.CodeInsights) } -var rawTemplateOnce sync.Once - // NewRawDB returns a connection to a clean, new temporary testing database. func NewRawDB(logger log.Logger, t testing.TB) *sql.DB { + return newDB(logger, t, "raw") +} + +func newDB(logger log.Logger, t testing.TB, name string, schemas ...*schemas.Schema) *sql.DB { if testing.Short() { t.Skip("DB tests disabled since go test -short is specified") } - rawTemplateOnce.Do(func() { - initTemplateDB(logger, t, "raw", nil) - }) - return newFromDSN(logger, t, "raw") + onceByName(name).Do(func() { initTemplateDB(logger, t, name, schemas) }) + return newFromDSN(logger, t, name) +} + +var onceByNameMap = map[string]*sync.Once{} +var onceByNameMutex sync.Mutex + +func onceByName(name string) *sync.Once { + onceByNameMutex.Lock() + defer onceByNameMutex.Unlock() + + if once, ok := onceByNameMap[name]; ok { + return once + } + + once := new(sync.Once) + onceByNameMap[name] = once + return once } func newFromDSN(logger log.Logger, t testing.TB, templateNamespace string) *sql.DB { diff --git a/internal/database/migration/runner/helpers_test.go b/internal/database/migration/runner/helpers_test.go index 836ee1c6a62..97ab5443b7f 100644 --- a/internal/database/migration/runner/helpers_test.go +++ b/internal/database/migration/runner/helpers_test.go @@ -35,7 +35,6 @@ func makeTestSchema(t *testing.T, name string) *schemas.Schema { return &schemas.Schema{ Name: name, MigrationsTableName: fmt.Sprintf("%s_migrations_table", name), - FS: fs, Definitions: definitions, } } diff --git a/internal/database/migration/schemas/schema.go b/internal/database/migration/schemas/schema.go index e08b9e163d4..325d055afad 100644 --- a/internal/database/migration/schemas/schema.go +++ b/internal/database/migration/schemas/schema.go @@ -1,8 +1,6 @@ package schemas import ( - "io/fs" - "github.com/sourcegraph/sourcegraph/internal/database/migration/definition" ) @@ -14,9 +12,6 @@ type Schema struct { // MigrationsTableName is the name of the table that tracks the schema version. MigrationsTableName string - // FS describes the raw migration assets of the schema. - FS fs.FS - // Definitions describes the parsed migration assets of the schema. Definitions *definition.Definitions } diff --git a/internal/database/migration/schemas/schemas.go b/internal/database/migration/schemas/schemas.go index 27bc5c58574..f88671b12e0 100644 --- a/internal/database/migration/schemas/schemas.go +++ b/internal/database/migration/schemas/schemas.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/sourcegraph/sourcegraph/internal/database/migration/definition" + "github.com/sourcegraph/sourcegraph/internal/database/migration/shared" "github.com/sourcegraph/sourcegraph/lib/errors" "github.com/sourcegraph/sourcegraph/migrations" ) @@ -46,7 +47,19 @@ func ResolveSchema(fs fs.FS, name string) (*Schema, error) { return &Schema{ Name: name, MigrationsTableName: MigrationsTableName(name), - FS: fs, + Definitions: definitions, + }, nil +} + +func ResolveSchemaAtRev(name, rev string) (*Schema, error) { + definitions, err := shared.GetFrozenDefinitions(name, rev) + if err != nil { + return nil, err + } + + return &Schema{ + Name: name, + MigrationsTableName: MigrationsTableName(name), Definitions: definitions, }, nil } diff --git a/internal/database/migration/shared/upgradedata/cmd/generator/consts.go b/internal/database/migration/shared/data/cmd/generator/consts.go similarity index 59% rename from internal/database/migration/shared/upgradedata/cmd/generator/consts.go rename to internal/database/migration/shared/data/cmd/generator/consts.go index 64189a83acb..cbefd8a8355 100644 --- a/internal/database/migration/shared/upgradedata/cmd/generator/consts.go +++ b/internal/database/migration/shared/data/cmd/generator/consts.go @@ -6,9 +6,8 @@ import ( "github.com/sourcegraph/sourcegraph/internal/oobmigration" ) -// NOTE: This should be kept up-to-date with cmd/migrator/build.sh -// so that we "bake in" fallback schemas everything we support migrating -// to. +// NOTE: This should be kept up-to-date with cmd/migrator/build.sh so that we "bake in" +// fallback schemas everything we support migrating to. const maxVersionString = "4.3.0" // MaxVersion is the highest known released version at the time the migrator was built. @@ -20,5 +19,13 @@ var MaxVersion = func() oobmigration.Version { panic(fmt.Sprintf("malformed maxVersionString %q", maxVersionString)) }() -// MinVersion is the minimum version a migrator can support upgrading to a newer version of Sourcegraph. +// MinVersion is the minimum version a migrator can support upgrading to a newer version of +// Sourcegraph. var MinVersion = oobmigration.NewVersion(3, 20) + +// FrozenRevisions are schemas at a point-in-time for which out-of-band migration unit tests +// can continue to run on their last pre-deprecation version. This code is still ran by the +// migrator, but only on a schema shape that existed in the past. +var FrozenRevisions = []string{ + "4.3.0", +} diff --git a/internal/database/migration/shared/upgradedata/cmd/generator/main.go b/internal/database/migration/shared/data/cmd/generator/main.go similarity index 71% rename from internal/database/migration/shared/upgradedata/cmd/generator/main.go rename to internal/database/migration/shared/data/cmd/generator/main.go index 7639d3df201..fede6fcc6c5 100644 --- a/internal/database/migration/shared/upgradedata/cmd/generator/main.go +++ b/internal/database/migration/shared/data/cmd/generator/main.go @@ -19,26 +19,41 @@ func main() { } func mainErr() error { - // This script is invoked via a go:generate directive in - // internal/database/migration/shared (embed.go) wd, err := os.Getwd() if err != nil { return err } - + // This script is invoked via a go:generate directive in internal/database/migration/shared (embed.go) repoRoot := filepath.Join(wd, "..", "..", "..", "..") - filepath := filepath.Join(wd, "upgradedata", "stitched-migration-graph.json") + + // + // Write stitched migrations versions, err := oobmigration.UpgradeRange(MinVersion, MaxVersion) if err != nil { return err } - versionTags := make([]string, 0, len(versions)) for _, version := range versions { versionTags = append(versionTags, version.GitTag()) } + if err := stitchAndWrite(repoRoot, filepath.Join(wd, "data", "stitched-migration-graph.json"), versionTags); err != nil { + return err + } + // + // Write frozen migrations + + for _, rev := range FrozenRevisions { + if err := stitchAndWrite(repoRoot, filepath.Join(wd, "data", "frozen", fmt.Sprintf("%s.json", rev)), []string{rev}); err != nil { + return err + } + } + + return nil +} + +func stitchAndWrite(repoRoot, filepath string, versionTags []string) error { stitchedMigrationBySchemaName := map[string]shared.StitchedMigration{} for _, schemaName := range schemas.SchemaNames { stitched, err := stitch.StitchDefinitions(schemaName, repoRoot, versionTags) diff --git a/internal/database/migration/shared/data/frozen/3.34.2.json b/internal/database/migration/shared/data/frozen/3.34.2.json new file mode 100755 index 00000000000..5365f7b3e48 --- /dev/null +++ b/internal/database/migration/shared/data/frozen/3.34.2.json @@ -0,0 +1,2089 @@ +{ + "codeinsights": { + "Definitions": [ + { + "ID": -1000000000, + "Name": "squashed migrations (privileged)", + "UpQuery": "", + "DownQuery": "", + "Privileged": true, + "NonIdempotent": false, + "Parents": null, + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000000, + "Name": "squashed migrations", + "UpQuery": "-- empty migration", + "DownQuery": "-- empty migration", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + -1000000000 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000001, + "Name": "initial schema", + "UpQuery": "CREATE EXTENSION IF NOT EXISTS timescaledb;\nCREATE EXTENSION IF NOT EXISTS pg_trgm;\nCREATE EXTENSION IF NOT EXISTS citext;\n\n-- Records repository names, both historical and present, using a unique repository _name_ ID\n-- (unrelated to the repository ID.)\nCREATE TABLE repo_names (\n -- The repository _name_ ID.\n id bigserial NOT NULL PRIMARY KEY,\n\n -- The name, trigram-indexed for fast e.g. regexp filtering.\n name citext NOT NULL,\n\n CONSTRAINT check_name_nonempty CHECK ((name OPERATOR(\u003c\u003e) ''::citext))\n);\n\n-- Enforce that names are unique.\nCREATE UNIQUE INDEX repo_names_name_unique_idx ON repo_names(name);\n\n-- Create trigram indexes for repository name filtering based on e.g. regexps.\nCREATE INDEX repo_names_name_trgm ON repo_names USING gin (lower((name)::text) gin_trgm_ops);\n\n\n-- Records arbitrary metadata about events. Stored in a separate table as it is often repeated\n-- for multiple events.\nCREATE TABLE metadata (\n -- The metadata ID.\n id bigserial NOT NULL PRIMARY KEY,\n\n -- Metadata about this event, this can be any arbitrary JSON metadata which will be returned\n -- when querying events, and can be filtered on and grouped using jsonb operators ?, ?\u0026, ?|,\n -- and @\u003e. This should be small data only, primary use case is small lists such as:\n --\n -- {\"java_versions\": [...]}\n -- {\"languages\": [...]}\n -- {\"pull_requests\": [...]}\n -- {\"annotations\": [...]}\n --\n metadata jsonb NOT NULL\n);\n\n-- Enforce that metadata is unique.\nCREATE UNIQUE INDEX metadata_metadata_unique_idx ON metadata(metadata);\n\n-- Index metadata to optimize WHERE clauses with jsonb ?, ?\u0026, ?|, and @\u003e operators.\nCREATE INDEX metadata_metadata_gin ON metadata USING GIN (metadata);\n\n-- Records events over time associated with a repository (or none, i.e. globally) where a single\n-- numerical value is going arbitrarily up and down.\n--\n-- Repository association is based on both repository ID and name. The ID can be used to refer to\n-- a specific repository, or lookup the current name of a repository after it has been e.g. renamed.\n-- The name can be used to refer to the name of the repository at the time of the event's creation,\n-- for example to trace the change in a gauge back to a repository being renamed.\nCREATE TABLE series_points (\n -- A unique identifier for the series of data being recorded. This is not an ID from another\n -- table, but rather just a unique identifier.\n series_id integer,\n\n -- The timestamp of the recorded event.\n time TIMESTAMPTZ NOT NULL,\n\n -- The floating point value at the time of the event.\n value double precision NOT NULL,\n\n -- Associated metadata for this event, if any.\n metadata_id integer,\n\n -- The repository ID (from the main application DB) at the time the event was created. Note\n -- that the repository may no longer exist / be valid at query time, however.\n --\n -- null if the event was not for a single repository (i.e. a global gauge).\n repo_id integer,\n\n -- The most recently known name for the repository, updated periodically to account for e.g.\n -- repository renames. If the repository was deleted, this is still the most recently known\n -- name.\n --\n -- null if the event was not for a single repository (i.e. a global gauge).\n repo_name_id integer,\n\n -- The repository name as it was known at the time the event was created. It may have been renamed\n -- since.\n original_repo_name_id integer,\n\n -- Ensure if one repo association field is specified, all are.\n CONSTRAINT check_repo_fields_specifity CHECK (\n ((repo_id IS NULL) AND (repo_name_id IS NULL) AND (original_repo_name_id IS NULL))\n OR\n ((repo_id IS NOT NULL) AND (repo_name_id IS NOT NULL) AND (original_repo_name_id IS NOT NULL))\n ),\n\n FOREIGN KEY (metadata_id) REFERENCES metadata(id) ON DELETE CASCADE DEFERRABLE,\n FOREIGN KEY (repo_name_id) REFERENCES repo_names(id) ON DELETE CASCADE DEFERRABLE,\n FOREIGN KEY (original_repo_name_id) REFERENCES repo_names(id) ON DELETE CASCADE DEFERRABLE\n);\n\n-- Create hypertable, partitioning events by time.\n-- See https://docs.timescale.com/latest/using-timescaledb/hypertables\nSELECT create_hypertable('series_points', 'time');\n\n-- Create btree indexes for repository filtering.\nCREATE INDEX series_points_repo_id_btree ON series_points USING btree (repo_id);\nCREATE INDEX series_points_repo_name_id_btree ON series_points USING btree (repo_name_id);\nCREATE INDEX series_points_original_repo_name_id_btree ON series_points USING btree (original_repo_name_id);", + "DownQuery": "DROP TABLE IF EXISTS series_points;\nDROP TABLE IF EXISTS repo_names;\nDROP TABLE IF EXISTS metadata;", + "Privileged": true, + "NonIdempotent": false, + "Parents": [ + 1000000000 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000002, + "Name": "comments", + "UpQuery": "COMMENT ON TABLE repo_names IS 'Records repository names, both historical and present, using a unique repository _name_ ID (unrelated to the repository ID.)';\nCOMMENT ON COLUMN repo_names.id IS 'The repository _name_ ID.';\nCOMMENT ON COLUMN repo_names.name IS 'The repository name string, with unique constraint for table entry deduplication and trigram index for e.g. regex filtering.';\n\nCOMMENT ON TABLE metadata IS 'Records arbitrary metadata about events. Stored in a separate table as it is often repeated for multiple events.';\nCOMMENT ON COLUMN metadata.id IS 'The metadata ID.';\nCOMMENT ON COLUMN metadata.metadata IS 'Metadata about some event, this can be any arbitrary JSON emtadata which will be returned when querying events, and can be filtered on and grouped using jsonb operators ?, ?\u0026, ?|, and @\u003e. This should be small data only.';\n\nCOMMENT ON TABLE series_points IS 'Records events over time associated with a repository (or none, i.e. globally) where a single numerical value is going arbitrarily up and down. Repository association is based on both repository ID and name. The ID can be used to refer toa specific repository, or lookup the current name of a repository after it has been e.g. renamed. The name can be used to refer to the name of the repository at the time of the events creation, for example to trace the change in a gauge back to a repository being renamed.';\nCOMMENT ON COLUMN series_points.series_id IS 'A unique identifier for the series of data being recorded. This is not an ID from another table, but rather just a unique identifier.';\nCOMMENT ON COLUMN series_points.time IS 'The timestamp of the recorded event.';\nCOMMENT ON COLUMN series_points.value IS 'The floating point value at the time of the event.';\nCOMMENT ON COLUMN series_points.metadata_id IS 'Associated metadata for this event, if any.';\nCOMMENT ON COLUMN series_points.repo_id IS 'The repository ID (from the main application DB) at the time the event was created. Note that the repository may no longer exist / be valid at query time, however.';\nCOMMENT ON COLUMN series_points.repo_name_id IS 'The most recently known name for the repository, updated periodically to account for e.g. repository renames. If the repository was deleted, this is still the most recently known name. null if the event was not for a single repository (i.e. a global gauge).';\nCOMMENT ON COLUMN series_points.original_repo_name_id IS 'The repository name as it was known at the time the event was created. It may have been renamed since.';", + "DownQuery": "-- Insert migration here. See README.md. Highlights:\n-- * Always use IF EXISTS. eg: DROP TABLE IF EXISTS global_dep_private;\n-- * All migrations must be backward-compatible. Old versions of Sourcegraph\n-- need to be able to read/write post migration.\n-- * Historically we advised against transactions since we thought the\n-- migrate library handled it. However, it does not! /facepalm", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1000000001 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000003, + "Name": "insights series id", + "UpQuery": "DELETE FROM series_points; -- affects dev environments only, others never had data in this table.\nALTER TABLE series_points ALTER COLUMN series_id TYPE text;\nALTER TABLE series_points ALTER COLUMN series_id SET NOT NULL;\n\n-- Give series_id a btree index since we'll be filtering on it very frequently.\nCREATE INDEX series_points_series_id_btree ON series_points USING btree (series_id);", + "DownQuery": "", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1000000002 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000004, + "Name": "no telemetry", + "UpQuery": "-- Disables TimescaleDB telemetry, which we cannot easily ship with Sourcegraph\n-- in a reasonable way (requires fairly in-depth analysis of what gets sent, etc.)\n-- See https://docs.timescale.com/latest/using-timescaledb/telemetry\n--\n-- Cannot be run inside of a transaction block.", + "DownQuery": "-- Insert migration here. See README.md. Highlights:\n-- * Always use IF EXISTS. eg: DROP TABLE IF EXISTS global_dep_private;\n-- * All migrations must be backward-compatible. Old versions of Sourcegraph\n-- need to be able to read/write post migration.\n-- * Historically we advised against transactions since we thought the\n-- migrate library handled it. However, it does not! /facepalm", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1000000003 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000005, + "Name": "wipe data", + "UpQuery": "-- We changed the default timeframe that the historical insights builder produces from:\n--\n-- 1 data point per week, for the last 52 weeks\n--\n-- To:\n--\n-- 1 data point per month, for the last 6 months\n--\n-- To avoid any confusion and just start fresh, we wipe all data here for now. This isn't\n-- needed in general when making this change, but is useful in this specific situation.\nDELETE FROM series_points;", + "DownQuery": "-- Insert migration here. See README.md. Highlights:\n-- * Always use IF EXISTS. eg: DROP TABLE IF EXISTS global_dep_private;\n-- * All migrations must be backward-compatible. Old versions of Sourcegraph\n-- need to be able to read/write post migration.\n-- * Historically we advised against transactions since we thought the\n-- migrate library handled it. However, it does not! /facepalm", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1000000004 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000006, + "Name": "commit index", + "UpQuery": "CREATE TABLE commit_index\n(\n\tcommitted_at TIMESTAMPTZ NOT NULL,\n\trepo_id INT NOT NULL,\n\tcommit_bytea bytea NOT NULL,\n\n\tPRIMARY KEY (committed_at, repo_id, commit_bytea)\n);\n\nCREATE INDEX commit_index_repo_id_idx ON commit_index USING btree (repo_id, committed_at);\n\nCREATE TABLE commit_index_metadata\n(\n repo_id INT NOT NULL PRIMARY KEY,\n enabled BOOLEAN NOT NULL DEFAULT 'y',\n last_indexed_at TIMESTAMPTZ NOT NULL DEFAULT '1900-01-01'\n);", + "DownQuery": "DROP TABLE IF EXISTS commit_index;\nDROP TABLE IF EXISTS commit_index_metadata;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1000000005 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000007, + "Name": "series points index", + "UpQuery": "CREATE INDEX IF NOT EXISTS series_points_series_id_repo_id_time_idx ON series_points (series_id, repo_id, time);", + "DownQuery": "DROP INDEX IF EXISTS series_points_series_id_repo_id_time_idx;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1000000006 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000008, + "Name": "insights views series", + "UpQuery": "CREATE TABLE insight_series\n(\n id SERIAL NOT NULL PRIMARY KEY,\n series_id TEXT NOT NULL,\n query TEXT NOT NULL,\n created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n oldest_historical_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP - INTERVAL '1 year',\n last_recorded_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP - INTERVAL '10 year',\n next_recording_after TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n recording_interval_days INT NOT NULL DEFAULT 1,\n deleted_at TIMESTAMP\n);\n\ncomment on table insight_series is 'Data series that comprise code insights.';\n\ncomment on column insight_series.id is 'Primary key ID of this series';\ncomment on column insight_series.series_id is 'Unique Series ID represents a globally unique identifier for this series.';\ncomment on column insight_series.query is 'Query string that generates this series';\ncomment on column insight_series.created_at is 'Timestamp when this series was created';\ncomment on column insight_series.oldest_historical_at is 'Timestamp representing the oldest point of which this series is backfilled.';\ncomment on column insight_series.last_recorded_at is 'Timestamp when this series was last recorded (non-historical).';\ncomment on column insight_series.next_recording_after is 'Timestamp when this series should next record (non-historical).';\ncomment on column insight_series.recording_interval_days is 'Number of days that should pass between recordings (non-historical)';\ncomment on column insight_series.deleted_at is 'Timestamp of a soft-delete of this row.';\n\nCREATE UNIQUE INDEX insight_series_series_id_unique_idx ON insight_series (series_id);\nCREATE INDEX insight_series_deleted_at_idx ON insight_series (deleted_at);\nCREATE INDEX insight_series_next_recording_after_idx ON insight_series (next_recording_after);\n\nCREATE TABLE insight_view\n(\n id SERIAL NOT NULL PRIMARY KEY,\n title TEXT,\n description TEXT,\n unique_id TEXT NOT NULL\n);\n\ncomment on table insight_view is 'Views for insight data series. An insight view is an abstraction on top of an insight data series that allows for lightweight modifications to filters or metadata without regenerating the underlying series.';\n\ncomment on column insight_view.id is 'Primary key ID for this view';\ncomment on column insight_view.title is 'Title of the view. This may render in a chart depending on the view type.';\ncomment on column insight_view.description is 'Description of the view. This may render in a chart depending on the view type.';\ncomment on column insight_view.unique_id is 'Globally unique identifier for this view that is externally referencable.';\n\nCREATE UNIQUE INDEX insight_view_unique_id_unique_idx ON insight_view (unique_id);\n\nCREATE TABLE insight_view_series\n(\n insight_view_id INT NOT NULL,\n insight_series_id INT NOT NULL,\n label TEXT,\n stroke TEXT,\n PRIMARY KEY (insight_view_id, insight_series_id)\n);\n\ncomment on table insight_view_series is 'Join table to correlate data series with insight views';\ncomment on column insight_view_series.insight_view_id is 'Foreign key to insight view.';\ncomment on column insight_view_series.insight_series_id is 'Foreign key to insight data series.';\ncomment on column insight_view_series.label is 'Label text for this data series. This may render in a chart depending on the view type.';\ncomment on column insight_view_series.stroke is 'Stroke color metadata for this data series. This may render in a chart depending on the view type.';\n\nALTER TABLE insight_view_series\n ADD FOREIGN KEY (insight_view_id) REFERENCES insight_view (id);\n\nALTER TABLE insight_view_series\n ADD FOREIGN KEY (insight_series_id) REFERENCES insight_series (id);", + "DownQuery": "DROP TABLE IF EXISTS insight_view_series;\nDROP TABLE IF EXISTS insight_view;\nDROP TABLE IF EXISTS insight_series;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1000000007 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000009, + "Name": "backfiller state", + "UpQuery": "-- Insert migration here. See README.md. Highlights:\n-- * Always use IF EXISTS. eg: DROP TABLE IF EXISTS global_dep_private;\n-- * All migrations must be backward-compatible. Old versions of Sourcegraph\n-- need to be able to read/write post migration.\n-- * Historically we advised against transactions since we thought the\n-- migrate library handled it. However, it does not! /facepalm\n\nALTER TABLE insight_series ADD COLUMN backfill_queued_at TIMESTAMP;\nCOMMENT ON COLUMN insight_series.series_id IS\n 'Timestamp that this series completed a full repository iteration for backfill. This flag has limited semantic value, and only means it tried to queue up queries for each repository. It does not guarantee success on those queries.';", + "DownQuery": "-- Insert migration here. See README.md. Highlights:\n-- * Always use IF EXISTS. eg: DROP TABLE IF EXISTS global_dep_private;\n-- * All migrations must be backward-compatible. Old versions of Sourcegraph\n-- need to be able to read/write post migration.\n-- * Historically we advised against transactions since we thought the\n-- migrate library handled it. However, it does not! /facepalm\n\nALTER TABLE insight_series DROP COLUMN IF EXISTS backfill_queued_at;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1000000008 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000010, + "Name": "series points reset", + "UpQuery": "-- Insert migration here. See README.md. Highlights:\n-- * Always use IF EXISTS. eg: DROP TABLE IF EXISTS global_dep_private;\n-- * All migrations must be backward-compatible. Old versions of Sourcegraph\n-- need to be able to read/write post migration.\n-- * Historically we advised against transactions since we thought the\n-- migrate library handled it. However, it does not! /facepalm\n\n-- Prior to 3.31 this table stored points in two formats. Historical points were stored in a compressed\n-- format where samples were only recorded if the underlying repository changed. After 3.31 we are changing\n-- the semantic to require full vectors for each data point. To avoid any incompatibilities and to prepare for beta\n-- we are going to reset the stored data and all of the underlying Timescale chunks back to zero.\n-- Note: This data is by design reproducible, so there is no risk of permanent data loss here. Any and all data\n-- will be queued and regenerated as soon as code insights starts up.\n\n-- Drop all Timescale chunks prior to now. This will reduce a bloated number of partitions caused by old\n-- data generation patterns. This is a Timescale specific thing.\nSELECT drop_chunks('series_points', CURRENT_TIMESTAMP::DATE);\n\n-- Clean up the remaining records if any exist.\nTRUNCATE series_points CASCADE;\n\n-- There is the possibility that the commit index has fallen out of sync with the primary postgres database in 3.30 due\n-- to a data corruption issue. We will regenerate it to be sure it is healthy for beta.\nTRUNCATE commit_index;\nTRUNCATE commit_index_metadata;\n\n-- Update all of the underlying insights that may have been synced to reset metadata and rebuild their data.\nupdate insight_series set created_at = current_timestamp, backfill_queued_at = null, next_recording_after = date_trunc('month', current_date) + interval '1 month';", + "DownQuery": "-- Insert migration here. See README.md. Highlights:\n-- * Always use IF EXISTS. eg: DROP TABLE IF EXISTS global_dep_private;\n-- * All migrations must be backward-compatible. Old versions of Sourcegraph\n-- need to be able to read/write post migration.\n-- * Historically we advised against transactions since we thought the\n-- migrate library handled it. However, it does not! /facepalm", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1000000009 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000011, + "Name": "insights dirty queries", + "UpQuery": "-- Insert migration here. See README.md. Highlights:\n-- * Always use IF EXISTS. eg: DROP TABLE IF EXISTS global_dep_private;\n-- * All migrations must be backward-compatible. Old versions of Sourcegraph\n-- need to be able to read/write post migration.\n-- * Historically we advised against transactions since we thought the\n-- migrate library handled it. However, it does not! /facepalm\n\nCREATE TABLE insight_dirty_queries\n(\n id SERIAL NOT NULL,\n insight_series_id INT,\n query TEXT NOT NULL,\n dirty_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n reason TEXT NOT NULL,\n for_time TIMESTAMP NOT NULL,\n PRIMARY KEY (id),\n FOREIGN KEY (insight_series_id) REFERENCES insight_series(id)\n);\n\nCREATE INDEX insight_dirty_queries_insight_series_id_fk_idx ON insight_dirty_queries (insight_series_id);\n\nCOMMENT ON TABLE insight_dirty_queries IS 'Stores queries that were unsuccessful or otherwise flagged as incomplete or incorrect.';\n\nCOMMENT ON COLUMN insight_dirty_queries.query IS 'Sourcegraph query string that was executed.';\nCOMMENT ON COLUMN insight_dirty_queries.dirty_at IS 'Timestamp when this query was marked dirty.';\nCOMMENT ON COLUMN insight_dirty_queries.reason IS 'Human readable string indicating the reason the query was marked dirty.';\nCOMMENT ON COLUMN insight_dirty_queries.for_time IS 'Timestamp for which the original data point was recorded or intended to be recorded.';", + "DownQuery": "-- Insert migration here. See README.md. Highlights:\n-- * Always use IF EXISTS. eg: DROP TABLE IF EXISTS global_dep_private;\n-- * All migrations must be backward-compatible. Old versions of Sourcegraph\n-- need to be able to read/write post migration.\n-- * Historically we advised against transactions since we thought the\n-- migrate library handled it. However, it does not! /facepalm\nDROP TABLE IF EXISTS insight_dirty_queries;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1000000010 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000012, + "Name": "insights snapshots", + "UpQuery": "-- Insert migration here. See README.md. Highlights:\n-- * Always use IF EXISTS. eg: DROP TABLE IF EXISTS global_dep_private;\n-- * All migrations must be backward-compatible. Old versions of Sourcegraph\n-- need to be able to read/write post migration.\n-- * Historically we advised against transactions since we thought the\n-- migrate library handled it. However, it does not! /facepalm\n\nCREATE TABLE series_points_snapshots\n(\n LIKE series_points INCLUDING DEFAULTS INCLUDING CONSTRAINTS INCLUDING INDEXES\n);\n\nCOMMENT ON TABLE series_points_snapshots is 'Stores ephemeral snapshot data of insight recordings.';\n\nalter table insight_series\n add last_snapshot_at timestamp default (CURRENT_TIMESTAMP - '10 years'::interval);\n\nalter table insight_series\n add next_snapshot_after timestamp default CURRENT_TIMESTAMP;", + "DownQuery": "-- Insert migration here. See README.md. Highlights:\n-- * Always use IF EXISTS. eg: DROP TABLE IF EXISTS global_dep_private;\n-- * All migrations must be backward-compatible. Old versions of Sourcegraph\n-- need to be able to read/write post migration.\n-- * Historically we advised against transactions since we thought the\n-- migrate library handled it. However, it does not! /facepalm\n\nDROP TABLE series_points_snapshots;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1000000011 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000013, + "Name": "insights view grants", + "UpQuery": "CREATE TABLE IF NOT EXISTS insight_view_grants\n(\n id SERIAL\n CONSTRAINT insight_view_grants_pk\n PRIMARY KEY,\n insight_view_id INTEGER NOT NULL\n CONSTRAINT insight_view_grants_insight_view_id_fk\n REFERENCES insight_view\n ON DELETE CASCADE, -- These grants only have meaning in the context of a parent view.\n user_id INTEGER,\n org_id INTEGER,\n global BOOLEAN\n);\n\nCOMMENT ON TABLE insight_view_grants IS 'Permission grants for insight views. Each row should represent a unique principal (user, org, etc).';\nCOMMENT ON COLUMN insight_view_grants.user_id IS 'User ID that that receives this grant.';\nCOMMENT ON COLUMN insight_view_grants.org_id IS 'Org ID that that receives this grant.';\nCOMMENT ON COLUMN insight_view_grants.global IS 'Grant that does not belong to any specific principal and is granted to all users.';\n\nCREATE INDEX IF NOT EXISTS insight_view_grants_insight_view_id_index\n ON insight_view_grants (insight_view_id);\n\nCREATE INDEX IF NOT EXISTS insight_view_grants_user_id_idx\n ON insight_view_grants (user_id);\n\nCREATE INDEX IF NOT EXISTS insight_view_grants_org_id_idx\n ON insight_view_grants (org_id);\n\nCREATE INDEX IF NOT EXISTS insight_view_grants_global_idx\n ON insight_view_grants (global) WHERE global IS TRUE;\n\n\n-- This series join table is completely dependent on the existence of a parent view. So to simplify db operations\n-- and avoid dangling rows, adding cascade deletes to the insight view FK.\nALTER TABLE insight_view_series\n DROP CONSTRAINT IF EXISTS insight_view_series_insight_view_id_fkey;\n\nALTER TABLE insight_view_series\n ADD CONSTRAINT insight_view_series_insight_view_id_fkey\n FOREIGN KEY (insight_view_id) REFERENCES insight_view\n ON DELETE CASCADE;", + "DownQuery": "DROP TABLE IF EXISTS insight_view_grants;\n\nALTER TABLE insight_view_series\n DROP CONSTRAINT IF EXISTS insight_view_series_insight_view_id_fkey;\n\nALTER TABLE insight_view_series\n ADD CONSTRAINT insight_view_series_insight_view_id_fkey\n FOREIGN KEY (insight_view_id) REFERENCES insight_view;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1000000012 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000014, + "Name": "dashboards", + "UpQuery": "CREATE TABLE IF NOT EXISTS dashboard\n(\n id SERIAL NOT NULL CONSTRAINT dashboard_pk PRIMARY KEY,\n title TEXT,\n created_at TIMESTAMP DEFAULT NOW() NOT NULL,\n created_by_user_id INT,\n last_updated_at TIMESTAMP DEFAULT NOW() NOT NULL,\n deleted_at TIMESTAMP\n);\n\nCOMMENT ON TABLE dashboard IS 'Metadata for dashboards of insights';\n\nCOMMENT ON COLUMN dashboard.title IS 'Title of the dashboard';\n\nCOMMENT ON COLUMN dashboard.created_at IS 'Timestamp the dashboard was initially created.';\n\nCOMMENT ON COLUMN dashboard.created_by_user_id IS 'User that created the dashboard, if available.';\n\nCOMMENT ON COLUMN dashboard.last_updated_at IS 'Time the dashboard was last updated, either metadata or insights.';\n\nCOMMENT ON COLUMN dashboard.deleted_at IS 'Set to the time the dashboard was soft deleted.';\n\n\n\nCREATE TABLE IF NOT EXISTS dashboard_grants\n(\n id SERIAL CONSTRAINT dashboard_grants_pk PRIMARY KEY,\n dashboard_id INTEGER NOT NULL CONSTRAINT dashboard_grants_dashboard_id_fk REFERENCES dashboard ON DELETE CASCADE, -- These grants only have meaning in the context of a parent dashboard.\n user_id INTEGER,\n org_id INTEGER,\n global BOOLEAN\n);\n\nCOMMENT ON TABLE dashboard_grants IS 'Permission grants for dashboards. Each row should represent a unique principal (user, org, etc).';\nCOMMENT ON COLUMN dashboard_grants.user_id IS 'User ID that that receives this grant.';\nCOMMENT ON COLUMN dashboard_grants.org_id IS 'Org ID that that receives this grant.';\nCOMMENT ON COLUMN dashboard_grants.global IS 'Grant that does not belong to any specific principal and is granted to all users.';\n\nCREATE INDEX IF NOT EXISTS dashboard_grants_dashboard_id_index\n ON dashboard_grants (dashboard_id);\n\nCREATE INDEX IF NOT EXISTS dashboard_grants_user_id_idx\n ON dashboard_grants (user_id);\n\nCREATE INDEX IF NOT EXISTS dashboard_grants_org_id_idx\n ON dashboard_grants (org_id);\n\nCREATE INDEX IF NOT EXISTS dashboard_grants_global_idx\n ON dashboard_grants (global) WHERE global IS TRUE;\n\nCREATE TABLE dashboard_insight_view\n(\n id SERIAL NOT NULL CONSTRAINT dashboard_insight_view_pk PRIMARY KEY,\n dashboard_id INT NOT NULL CONSTRAINT dashboard_insight_view_dashboard_id_fk REFERENCES dashboard (id) ON DELETE CASCADE,\n insight_view_id INT NOT NULL CONSTRAINT dashboard_insight_view_insight_view_id_fk REFERENCES insight_view (id) ON DELETE CASCADE\n);\n\nCREATE INDEX IF NOT EXISTS dashboard_insight_view_insight_view_id_fk_idx ON dashboard_insight_view (insight_view_id);\nCREATE INDEX IF NOT EXISTS dashboard_insight_view_dashboard_id_fk_idx ON dashboard_insight_view (dashboard_id);", + "DownQuery": "DROP TABLE IF EXISTS dashboard_grants;\n\t\t\tDROP TABLE IF EXISTS dashboard_insight_view;\n\t\t\tDROP TABLE IF EXISTS dashboard;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1000000013 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000015, + "Name": "dashboard save", + "UpQuery": "ALTER TABLE dashboard ADD COLUMN IF NOT EXISTS save BOOLEAN NOT NULL DEFAULT FALSE;\n\nCOMMENT ON COLUMN dashboard.save IS 'TEMPORARY Do not delete this dashboard when migrating settings.';", + "DownQuery": "ALTER TABLE dashboard\nDROP COLUMN IF EXISTS save;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1000000014 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000016, + "Name": "unique insights on dashboard", + "UpQuery": "-- Remove any already existing duplicates.\nDELETE FROM\n dashboard_insight_view a\n USING dashboard_insight_view b\nWHERE\n\ta.id \u003e b.id\n AND a.dashboard_id = b.dashboard_id\n AND a.insight_view_id = b.insight_view_id;\n\nALTER TABLE dashboard_insight_view\nADD CONSTRAINT unique_dashboard_id_insight_view_id\nUNIQUE (dashboard_id, insight_view_id);", + "DownQuery": "ALTER TABLE dashboard_insight_view\nDROP CONSTRAINT unique_dashboard_id_insight_view_id;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1000000015 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000017, + "Name": "insight api", + "UpQuery": "CREATE TYPE time_unit AS ENUM ('HOUR', 'DAY', 'WEEK', 'MONTH', 'YEAR');\nALTER TABLE insight_series\n DROP COLUMN IF EXISTS recording_interval_days,\n ADD COLUMN repositories TEXT[],\n ADD COLUMN sample_interval_unit time_unit,\n ADD COLUMN sample_interval_value int\n;\n\nALTER TABLE insight_view\n ADD COLUMN default_filter_include_repo_regex text,\n ADD COLUMN default_filter_exclude_repo_regex text\n;", + "DownQuery": "-- Insert migration here. See README.md. Highlights:\n-- * Always use IF EXISTS. eg: DROP TABLE IF EXISTS global_dep_private;\n-- * All migrations must be backward-compatible. Old versions of Sourcegraph\n-- need to be able to read/write post migration.\n-- * Historically we advised against transactions since we thought the\n-- migrate library handled it. However, it does not! /facepalm\n\nALTER TABLE insight_series\n DROP COLUMN IF EXISTS repositories,\n DROP COLUMN IF EXISTS sample_interval_unit,\n DROP COLUMN IF EXISTS sample_interval_value,\n ADD COLUMN IF NOT EXISTS recording_interval_days int;\n\nALTER TABLE insight_view\n DROP COLUMN IF EXISTS default_filter_include_repo_regex,\n DROP COLUMN IF EXISTS default_filter_exclude_repo_regex;\nDROP TYPE IF EXISTS time_unit;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1000000016 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000018, + "Name": "interval defaults", + "UpQuery": "UPDATE insight_series\nSET sample_interval_unit = 'MONTH'\nWHERE sample_interval_unit IS NULL;\n\nUPDATE insight_series\nSET sample_interval_value = 1\nWHERE sample_interval_value IS NULL;\n\nALTER TABLE insight_series\n ALTER COLUMN sample_interval_unit SET DEFAULT 'MONTH',\n ALTER COLUMN sample_interval_unit SET NOT NULL,\n ALTER COLUMN sample_interval_value SET DEFAULT '1',\n ALTER COLUMN sample_interval_value SET NOT NULL;", + "DownQuery": "ALTER TABLE IF EXISTS insight_series\n ALTER COLUMN sample_interval_unit DROP DEFAULT,\n ALTER COLUMN sample_interval_unit DROP NOT NULL,\n ALTER COLUMN sample_interval_value DROP DEFAULT,\n ALTER COLUMN sample_interval_value DROP NOT NULL;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1000000017 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000019, + "Name": "other threshold", + "UpQuery": "ALTER TABLE insight_view\n ADD COLUMN IF NOT EXISTS other_threshold FLOAT4;\n\nCOMMENT ON COLUMN insight_view.other_threshold IS 'Percent threshold for grouping series under \"other\"';", + "DownQuery": "ALTER TABLE insight_view\nDROP COLUMN IF EXISTS other_threshold;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1000000018 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000020, + "Name": "presentation type", + "UpQuery": "CREATE TYPE presentation_type_enum AS ENUM ('LINE', 'PIE');\nALTER TABLE insight_view\n ADD COLUMN IF NOT EXISTS presentation_type presentation_type_enum NOT NULL DEFAULT 'LINE',\n ALTER COLUMN other_threshold type FLOAT8; -- Changing this because the GraphQL float type is a float64.\n\nCOMMENT ON COLUMN insight_view.presentation_type IS 'The basic presentation type for the insight view. (e.g Line, Pie, etc.)';", + "DownQuery": "ALTER TABLE insight_view\n ALTER COLUMN other_threshold TYPE FLOAT4,\n DROP COLUMN IF EXISTS presentation_type;\n\nDROP TYPE presentation_type_enum;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1000000019 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000021, + "Name": "add dirty query cascade", + "UpQuery": "ALTER TABLE insight_dirty_queries\n DROP CONSTRAINT insight_dirty_queries_insight_series_id_fkey,\n ADD CONSTRAINT insight_dirty_queries_insight_series_id_fkey FOREIGN KEY (insight_series_id) REFERENCES insight_series (id) ON DELETE CASCADE;", + "DownQuery": "ALTER TABLE insight_dirty_queries\n DROP CONSTRAINT insight_dirty_queries_insight_series_id_fkey,\n ADD CONSTRAINT insight_dirty_queries_insight_series_id_fkey FOREIGN KEY (insight_series_id) REFERENCES insight_series (id);", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1000000020 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + } + ], + "BoundsByRev": { + "3.34.2": { + "RootID": -1000000000, + "LeafIDs": [ + 1000000021 + ], + "PreCreation": false + } + } + }, + "codeintel": { + "Definitions": [ + { + "ID": -1000000015, + "Name": "squashed migrations (privileged)", + "UpQuery": "CREATE EXTENSION IF NOT EXISTS pg_stat_statements;\n\nCOMMENT ON EXTENSION pg_stat_statements IS 'track execution statistics of all SQL statements executed';", + "DownQuery": "", + "Privileged": true, + "NonIdempotent": false, + "Parents": null, + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000015, + "Name": "squashed migrations", + "UpQuery": "CREATE FUNCTION update_lsif_data_definitions_schema_versions_insert() RETURNS trigger\n LANGUAGE plpgsql\n AS $$ BEGIN\n INSERT INTO\n lsif_data_definitions_schema_versions\n SELECT\n dump_id,\n MIN(schema_version) as min_schema_version,\n MAX(schema_version) as max_schema_version\n FROM\n newtab\n GROUP BY\n dump_id\n ON CONFLICT (dump_id) DO UPDATE SET\n -- Update with min(old_min, new_min) and max(old_max, new_max)\n min_schema_version = LEAST(lsif_data_definitions_schema_versions.min_schema_version, EXCLUDED.min_schema_version),\n max_schema_version = GREATEST(lsif_data_definitions_schema_versions.max_schema_version, EXCLUDED.max_schema_version);\n\n RETURN NULL;\nEND $$;\n\nCREATE FUNCTION update_lsif_data_documents_schema_versions_insert() RETURNS trigger\n LANGUAGE plpgsql\n AS $$ BEGIN\n INSERT INTO\n lsif_data_documents_schema_versions\n SELECT\n dump_id,\n MIN(schema_version) as min_schema_version,\n MAX(schema_version) as max_schema_version\n FROM\n newtab\n GROUP BY\n dump_id\n ON CONFLICT (dump_id) DO UPDATE SET\n -- Update with min(old_min, new_min) and max(old_max, new_max)\n min_schema_version = LEAST(lsif_data_documents_schema_versions.min_schema_version, EXCLUDED.min_schema_version),\n max_schema_version = GREATEST(lsif_data_documents_schema_versions.max_schema_version, EXCLUDED.max_schema_version);\n\n RETURN NULL;\nEND $$;\n\nCREATE FUNCTION update_lsif_data_references_schema_versions_insert() RETURNS trigger\n LANGUAGE plpgsql\n AS $$ BEGIN\n INSERT INTO\n lsif_data_references_schema_versions\n SELECT\n dump_id,\n MIN(schema_version) as min_schema_version,\n MAX(schema_version) as max_schema_version\n FROM\n newtab\n GROUP BY\n dump_id\n ON CONFLICT (dump_id) DO UPDATE SET\n -- Update with min(old_min, new_min) and max(old_max, new_max)\n min_schema_version = LEAST(lsif_data_references_schema_versions.min_schema_version, EXCLUDED.min_schema_version),\n max_schema_version = GREATEST(lsif_data_references_schema_versions.max_schema_version, EXCLUDED.max_schema_version);\n\n RETURN NULL;\nEND $$;\n\nCREATE TABLE lsif_data_definitions (\n dump_id integer NOT NULL,\n scheme text NOT NULL,\n identifier text NOT NULL,\n data bytea,\n schema_version integer NOT NULL,\n num_locations integer NOT NULL\n);\n\nCOMMENT ON TABLE lsif_data_definitions IS 'Associates (document, range) pairs with the import monikers attached to the range.';\n\nCOMMENT ON COLUMN lsif_data_definitions.dump_id IS 'The identifier of the associated dump in the lsif_uploads table (state=completed).';\n\nCOMMENT ON COLUMN lsif_data_definitions.scheme IS 'The moniker scheme.';\n\nCOMMENT ON COLUMN lsif_data_definitions.identifier IS 'The moniker identifier.';\n\nCOMMENT ON COLUMN lsif_data_definitions.data IS 'A gob-encoded payload conforming to an array of [LocationData](https://sourcegraph.com/github.com/sourcegraph/sourcegraph@3.26/-/blob/enterprise/lib/codeintel/semantic/types.go#L106:6) types.';\n\nCOMMENT ON COLUMN lsif_data_definitions.schema_version IS 'The schema version of this row - used to determine presence and encoding of data.';\n\nCOMMENT ON COLUMN lsif_data_definitions.num_locations IS 'The number of locations stored in the data field.';\n\nCREATE TABLE lsif_data_definitions_schema_versions (\n dump_id integer NOT NULL,\n min_schema_version integer,\n max_schema_version integer\n);\n\nCOMMENT ON TABLE lsif_data_definitions_schema_versions IS 'Tracks the range of schema_versions for each upload in the lsif_data_definitions table.';\n\nCOMMENT ON COLUMN lsif_data_definitions_schema_versions.dump_id IS 'The identifier of the associated dump in the lsif_uploads table.';\n\nCOMMENT ON COLUMN lsif_data_definitions_schema_versions.min_schema_version IS 'A lower-bound on the `lsif_data_definitions.schema_version` where `lsif_data_definitions.dump_id = dump_id`.';\n\nCOMMENT ON COLUMN lsif_data_definitions_schema_versions.max_schema_version IS 'An upper-bound on the `lsif_data_definitions.schema_version` where `lsif_data_definitions.dump_id = dump_id`.';\n\nCREATE TABLE lsif_data_documentation_pages (\n dump_id integer NOT NULL,\n path_id text NOT NULL,\n data bytea\n);\n\nCOMMENT ON TABLE lsif_data_documentation_pages IS 'Associates documentation pathIDs to their documentation page hierarchy chunk.';\n\nCOMMENT ON COLUMN lsif_data_documentation_pages.dump_id IS 'The identifier of the associated dump in the lsif_uploads table (state=completed).';\n\nCOMMENT ON COLUMN lsif_data_documentation_pages.path_id IS 'The documentation page path ID, see see GraphQL codeintel.schema:documentationPage for what this is.';\n\nCOMMENT ON COLUMN lsif_data_documentation_pages.data IS 'A gob-encoded payload conforming to a `type DocumentationPageData struct` pointer (lib/codeintel/semantic/types.go)';\n\nCREATE TABLE lsif_data_documents (\n dump_id integer NOT NULL,\n path text NOT NULL,\n data bytea,\n schema_version integer NOT NULL,\n num_diagnostics integer NOT NULL,\n ranges bytea,\n hovers bytea,\n monikers bytea,\n packages bytea,\n diagnostics bytea\n);\n\nCOMMENT ON TABLE lsif_data_documents IS 'Stores reference, hover text, moniker, and diagnostic data about a particular text document witin a dump.';\n\nCOMMENT ON COLUMN lsif_data_documents.dump_id IS 'The identifier of the associated dump in the lsif_uploads table (state=completed).';\n\nCOMMENT ON COLUMN lsif_data_documents.path IS 'The path of the text document relative to the associated dump root.';\n\nCOMMENT ON COLUMN lsif_data_documents.data IS 'A gob-encoded payload conforming to the [DocumentData](https://sourcegraph.com/github.com/sourcegraph/sourcegraph@3.26/-/blob/enterprise/lib/codeintel/semantic/types.go#L13:6) type. This field is being migrated across ranges, hovers, monikers, packages, and diagnostics columns and will be removed in a future release of Sourcegraph.';\n\nCOMMENT ON COLUMN lsif_data_documents.schema_version IS 'The schema version of this row - used to determine presence and encoding of data.';\n\nCOMMENT ON COLUMN lsif_data_documents.num_diagnostics IS 'The number of diagnostics stored in the data field.';\n\nCOMMENT ON COLUMN lsif_data_documents.ranges IS 'A gob-encoded payload conforming to the [Ranges](https://sourcegraph.com/github.com/sourcegraph/sourcegraph@3.26/-/blob/enterprise/lib/codeintel/semantic/types.go#L14:2) field of the DocumentDatatype.';\n\nCOMMENT ON COLUMN lsif_data_documents.hovers IS 'A gob-encoded payload conforming to the [HoversResults](https://sourcegraph.com/github.com/sourcegraph/sourcegraph@3.26/-/blob/enterprise/lib/codeintel/semantic/types.go#L15:2) field of the DocumentDatatype.';\n\nCOMMENT ON COLUMN lsif_data_documents.monikers IS 'A gob-encoded payload conforming to the [Monikers](https://sourcegraph.com/github.com/sourcegraph/sourcegraph@3.26/-/blob/enterprise/lib/codeintel/semantic/types.go#L16:2) field of the DocumentDatatype.';\n\nCOMMENT ON COLUMN lsif_data_documents.packages IS 'A gob-encoded payload conforming to the [PackageInformation](https://sourcegraph.com/github.com/sourcegraph/sourcegraph@3.26/-/blob/enterprise/lib/codeintel/semantic/types.go#L17:2) field of the DocumentDatatype.';\n\nCOMMENT ON COLUMN lsif_data_documents.diagnostics IS 'A gob-encoded payload conforming to the [Diagnostics](https://sourcegraph.com/github.com/sourcegraph/sourcegraph@3.26/-/blob/enterprise/lib/codeintel/semantic/types.go#L18:2) field of the DocumentDatatype.';\n\nCREATE TABLE lsif_data_documents_schema_versions (\n dump_id integer NOT NULL,\n min_schema_version integer,\n max_schema_version integer\n);\n\nCOMMENT ON TABLE lsif_data_documents_schema_versions IS 'Tracks the range of schema_versions for each upload in the lsif_data_documents table.';\n\nCOMMENT ON COLUMN lsif_data_documents_schema_versions.dump_id IS 'The identifier of the associated dump in the lsif_uploads table.';\n\nCOMMENT ON COLUMN lsif_data_documents_schema_versions.min_schema_version IS 'A lower-bound on the `lsif_data_documents.schema_version` where `lsif_data_documents.dump_id = dump_id`.';\n\nCOMMENT ON COLUMN lsif_data_documents_schema_versions.max_schema_version IS 'An upper-bound on the `lsif_data_documents.schema_version` where `lsif_data_documents.dump_id = dump_id`.';\n\nCREATE TABLE lsif_data_metadata (\n dump_id integer NOT NULL,\n num_result_chunks integer\n);\n\nCOMMENT ON TABLE lsif_data_metadata IS 'Stores the number of result chunks associated with a dump.';\n\nCOMMENT ON COLUMN lsif_data_metadata.dump_id IS 'The identifier of the associated dump in the lsif_uploads table (state=completed).';\n\nCOMMENT ON COLUMN lsif_data_metadata.num_result_chunks IS 'A bound of populated indexes in the lsif_data_result_chunks table for the associated dump. This value is used to hash identifiers into the result chunk index to which they belong.';\n\nCREATE TABLE lsif_data_references (\n dump_id integer NOT NULL,\n scheme text NOT NULL,\n identifier text NOT NULL,\n data bytea,\n schema_version integer NOT NULL,\n num_locations integer NOT NULL\n);\n\nCOMMENT ON TABLE lsif_data_references IS 'Associates (document, range) pairs with the export monikers attached to the range.';\n\nCOMMENT ON COLUMN lsif_data_references.dump_id IS 'The identifier of the associated dump in the lsif_uploads table (state=completed).';\n\nCOMMENT ON COLUMN lsif_data_references.scheme IS 'The moniker scheme.';\n\nCOMMENT ON COLUMN lsif_data_references.identifier IS 'The moniker identifier.';\n\nCOMMENT ON COLUMN lsif_data_references.data IS 'A gob-encoded payload conforming to an array of [LocationData](https://sourcegraph.com/github.com/sourcegraph/sourcegraph@3.26/-/blob/enterprise/lib/codeintel/semantic/types.go#L106:6) types.';\n\nCOMMENT ON COLUMN lsif_data_references.schema_version IS 'The schema version of this row - used to determine presence and encoding of data.';\n\nCOMMENT ON COLUMN lsif_data_references.num_locations IS 'The number of locations stored in the data field.';\n\nCREATE TABLE lsif_data_references_schema_versions (\n dump_id integer NOT NULL,\n min_schema_version integer,\n max_schema_version integer\n);\n\nCOMMENT ON TABLE lsif_data_references_schema_versions IS 'Tracks the range of schema_versions for each upload in the lsif_data_references table.';\n\nCOMMENT ON COLUMN lsif_data_references_schema_versions.dump_id IS 'The identifier of the associated dump in the lsif_uploads table.';\n\nCOMMENT ON COLUMN lsif_data_references_schema_versions.min_schema_version IS 'A lower-bound on the `lsif_data_references.schema_version` where `lsif_data_references.dump_id = dump_id`.';\n\nCOMMENT ON COLUMN lsif_data_references_schema_versions.max_schema_version IS 'An upper-bound on the `lsif_data_references.schema_version` where `lsif_data_references.dump_id = dump_id`.';\n\nCREATE TABLE lsif_data_result_chunks (\n dump_id integer NOT NULL,\n idx integer NOT NULL,\n data bytea\n);\n\nCOMMENT ON TABLE lsif_data_result_chunks IS 'Associates result set identifiers with the (document path, range identifier) pairs that compose the set.';\n\nCOMMENT ON COLUMN lsif_data_result_chunks.dump_id IS 'The identifier of the associated dump in the lsif_uploads table (state=completed).';\n\nCOMMENT ON COLUMN lsif_data_result_chunks.idx IS 'The unique result chunk index within the associated dump. Every result set identifier present should hash to this index (modulo lsif_data_metadata.num_result_chunks).';\n\nCOMMENT ON COLUMN lsif_data_result_chunks.data IS 'A gob-encoded payload conforming to the [ResultChunkData](https://sourcegraph.com/github.com/sourcegraph/sourcegraph@3.26/-/blob/enterprise/lib/codeintel/semantic/types.go#L76:6) type.';\n\nALTER TABLE ONLY lsif_data_definitions\n ADD CONSTRAINT lsif_data_definitions_pkey PRIMARY KEY (dump_id, scheme, identifier);\n\nALTER TABLE ONLY lsif_data_definitions_schema_versions\n ADD CONSTRAINT lsif_data_definitions_schema_versions_pkey PRIMARY KEY (dump_id);\n\nALTER TABLE ONLY lsif_data_documentation_pages\n ADD CONSTRAINT lsif_data_documentation_pages_pkey PRIMARY KEY (dump_id, path_id);\n\nALTER TABLE ONLY lsif_data_documents\n ADD CONSTRAINT lsif_data_documents_pkey PRIMARY KEY (dump_id, path);\n\nALTER TABLE ONLY lsif_data_documents_schema_versions\n ADD CONSTRAINT lsif_data_documents_schema_versions_pkey PRIMARY KEY (dump_id);\n\nALTER TABLE ONLY lsif_data_metadata\n ADD CONSTRAINT lsif_data_metadata_pkey PRIMARY KEY (dump_id);\n\nALTER TABLE ONLY lsif_data_references\n ADD CONSTRAINT lsif_data_references_pkey PRIMARY KEY (dump_id, scheme, identifier);\n\nALTER TABLE ONLY lsif_data_references_schema_versions\n ADD CONSTRAINT lsif_data_references_schema_versions_pkey PRIMARY KEY (dump_id);\n\nALTER TABLE ONLY lsif_data_result_chunks\n ADD CONSTRAINT lsif_data_result_chunks_pkey PRIMARY KEY (dump_id, idx);\n\nCREATE INDEX lsif_data_definitions_dump_id_schema_version ON lsif_data_definitions USING btree (dump_id, schema_version);\n\nCREATE INDEX lsif_data_definitions_schema_versions_dump_id_schema_version_bo ON lsif_data_definitions_schema_versions USING btree (dump_id, min_schema_version, max_schema_version);\n\nCREATE INDEX lsif_data_documents_dump_id_schema_version ON lsif_data_documents USING btree (dump_id, schema_version);\n\nCREATE INDEX lsif_data_documents_schema_versions_dump_id_schema_version_boun ON lsif_data_documents_schema_versions USING btree (dump_id, min_schema_version, max_schema_version);\n\nCREATE INDEX lsif_data_references_dump_id_schema_version ON lsif_data_references USING btree (dump_id, schema_version);\n\nCREATE INDEX lsif_data_references_schema_versions_dump_id_schema_version_bou ON lsif_data_references_schema_versions USING btree (dump_id, min_schema_version, max_schema_version);\n\nCREATE TRIGGER lsif_data_definitions_schema_versions_insert AFTER INSERT ON lsif_data_definitions REFERENCING NEW TABLE AS newtab FOR EACH STATEMENT EXECUTE FUNCTION update_lsif_data_definitions_schema_versions_insert();\n\nCREATE TRIGGER lsif_data_documents_schema_versions_insert AFTER INSERT ON lsif_data_documents REFERENCING NEW TABLE AS newtab FOR EACH STATEMENT EXECUTE FUNCTION update_lsif_data_documents_schema_versions_insert();\n\nCREATE TRIGGER lsif_data_references_schema_versions_insert AFTER INSERT ON lsif_data_references REFERENCING NEW TABLE AS newtab FOR EACH STATEMENT EXECUTE FUNCTION update_lsif_data_references_schema_versions_insert();", + "DownQuery": "-- Nothing", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + -1000000015 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000016, + "Name": "apidocs clean", + "UpQuery": "-- PR #22080 landed a number of backwards-incompatible API docs data changes and given how early\n-- stages API docs is, we don't care to maintain backwards compat with the old data and choose to\n-- instead start from scratch with indexing again (not many repos have been indexed with API docs,\n-- anyway.)\nTRUNCATE lsif_data_documentation_pages;", + "DownQuery": "-- Insert migration here. See README.md. Highlights:\n-- * Always use IF EXISTS. eg: DROP TABLE IF EXISTS global_dep_private;\n-- * All migrations must be backward-compatible. Old versions of Sourcegraph\n-- need to be able to read/write post migration.\n-- * Historically we advised against transactions since we thought the\n-- migrate library handled it. However, it does not! /facepalm", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1000000015 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000017, + "Name": "lsif documentation path info", + "UpQuery": "CREATE TABLE IF NOT EXISTS lsif_data_documentation_path_info (\n dump_id integer NOT NULL,\n path_id TEXT,\n data bytea\n);\n\nALTER TABLE lsif_data_documentation_path_info ADD PRIMARY KEY (dump_id, path_id);\n\nCOMMENT ON TABLE lsif_data_documentation_path_info IS 'Associates documentation page pathIDs to information about what is at that pathID, its immediate children, etc.';\nCOMMENT ON COLUMN lsif_data_documentation_path_info.dump_id IS 'The identifier of the associated dump in the lsif_uploads table (state=completed).';\nCOMMENT ON COLUMN lsif_data_documentation_path_info.path_id IS 'The documentation page path ID, see see GraphQL codeintel.schema:documentationPage for what this is.';\nCOMMENT ON COLUMN lsif_data_documentation_path_info.data IS 'A gob-encoded payload conforming to a `type DocumentationPathInoData struct` pointer (lib/codeintel/semantic/types.go)';", + "DownQuery": "DROP TABLE IF EXISTS lsif_data_documentation_path_info;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1000000016 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000018, + "Name": "lsif documentation mappings", + "UpQuery": "CREATE TABLE IF NOT EXISTS lsif_data_documentation_mappings (\n dump_id integer NOT NULL,\n path_id TEXT NOT NULL,\n result_id integer NOT NULL\n);\n\nALTER TABLE lsif_data_documentation_mappings ADD PRIMARY KEY (dump_id, path_id);\n\nCREATE UNIQUE INDEX lsif_data_documentation_mappings_inverse_unique_idx ON lsif_data_documentation_mappings(dump_id, result_id);\n\nCOMMENT ON TABLE lsif_data_documentation_mappings IS 'Maps documentation path IDs to their corresponding integral documentationResult vertex IDs, which are unique within a dump.';\nCOMMENT ON COLUMN lsif_data_documentation_mappings.dump_id IS 'The identifier of the associated dump in the lsif_uploads table (state=completed).';\nCOMMENT ON COLUMN lsif_data_documentation_mappings.path_id IS 'The documentation page path ID, see see GraphQL codeintel.schema:documentationPage for what this is.';\nCOMMENT ON COLUMN lsif_data_documentation_mappings.result_id IS 'The documentationResult vertex ID.';", + "DownQuery": "DROP TABLE IF EXISTS lsif_data_documentation_mappings;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1000000017 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000019, + "Name": "documentation path mapping", + "UpQuery": "-- Add nullable file_path column, for mapping documentationResult ID -\u003e file_path\nALTER TABLE lsif_data_documentation_mappings ADD COLUMN file_path text;\nCOMMENT ON COLUMN lsif_data_documentation_mappings.file_path IS 'The document file path for the documentationResult, if any. e.g. the path to the file where the symbol described by this documentationResult is located, if it is a symbol.';", + "DownQuery": "ALTER TABLE lsif_data_documentation_mappings DROP COLUMN file_path;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1000000018 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000020, + "Name": "lsif data documentation search", + "UpQuery": "CREATE EXTENSION IF NOT EXISTS pg_trgm;\n\nALTER TABLE lsif_data_documentation_pages ADD COLUMN search_indexed boolean DEFAULT 'false';\n\n-- We're going to create the new lsif_data_documentation_search_* tables. These tables will have a\n-- trigram index and will be data decoded from the GOB encoded lsif_data_documentation_pages.data\n-- field, hence an OOB migration is needed as that table is quite large and not decodable in SQL\n-- alone.\nCREATE TABLE IF NOT EXISTS lsif_data_documentation_search_public (\n -- Metadata fields\n dump_id integer NOT NULL,\n repo_id integer NOT NULL,\n path_id TEXT NOT NULL,\n detail TEXT NOT NULL,\n\n -- FTS-enabled fields\n lang TEXT NOT NULL,\n repo_name TEXT NOT NULL,\n search_key TEXT NOT NULL,\n label TEXT NOT NULL,\n tags TEXT NOT NULL\n);\n\nALTER TABLE lsif_data_documentation_search_public ADD PRIMARY KEY (dump_id, path_id);\n\nCREATE INDEX lsif_data_documentation_search_public_repo_id_idx ON lsif_data_documentation_search_public USING BTREE(repo_id);\nCREATE INDEX lsif_data_documentation_search_public_lang_trgm ON lsif_data_documentation_search_public USING gin(lang gin_trgm_ops);\nCREATE INDEX lsif_data_documentation_search_public_repo_name_trgm ON lsif_data_documentation_search_public USING gin(repo_name gin_trgm_ops);\nCREATE INDEX lsif_data_documentation_search_public_search_key_trgm ON lsif_data_documentation_search_public USING gin(search_key gin_trgm_ops);\nCREATE INDEX lsif_data_documentation_search_public_label_trgm ON lsif_data_documentation_search_public USING gin(label gin_trgm_ops);\nCREATE INDEX lsif_data_documentation_search_public_tags_trgm ON lsif_data_documentation_search_public USING gin(tags gin_trgm_ops);\n\nCOMMENT ON TABLE lsif_data_documentation_search_public IS 'A trigram index over documentation for search (public repos only)';\nCOMMENT ON COLUMN lsif_data_documentation_search_public.dump_id IS 'The identifier of the associated dump in the lsif_uploads table (state=completed).';\nCOMMENT ON COLUMN lsif_data_documentation_search_public.repo_id IS 'The repo ID, from the main app DB repo table. Used to search over a select set of repos by ID.';\nCOMMENT ON COLUMN lsif_data_documentation_search_public.path_id IS 'The fully qualified documentation page path ID, e.g. including \"#section\". See GraphQL codeintel.schema:documentationPage for what this is.';\n\nCOMMENT ON COLUMN lsif_data_documentation_search_public.lang IS 'The lowercase language name (go, java, etc.) OR, if unknown, the LSIF indexer name';\nCOMMENT ON COLUMN lsif_data_documentation_search_public.repo_name IS 'The name of the repository containing this search key.';\nCOMMENT ON COLUMN lsif_data_documentation_search_public.search_key IS 'The search key generated by the indexer, e.g. mux.Router.ServeHTTP. It is language-specific, and likely unique within a repository (but not always.) See protocol/documentation.go:Documentation.SearchKey';\nCOMMENT ON COLUMN lsif_data_documentation_search_public.label IS 'The label string of the result, e.g. a one-line function signature. See protocol/documentation.go:Documentation';\nCOMMENT ON COLUMN lsif_data_documentation_search_public.detail IS 'The detail string (e.g. the full function signature and its docs). See protocol/documentation.go:Documentation';\nCOMMENT ON COLUMN lsif_data_documentation_search_public.tags IS 'A space separated list of tags from the documentation node. See protocol/documentation.go:Documentation';\n\n-- Same exact thing as above, but for \"_private\" repos.\nCREATE TABLE IF NOT EXISTS lsif_data_documentation_search_private (\n -- Metadata fields\n dump_id integer NOT NULL,\n repo_id integer NOT NULL,\n path_id TEXT NOT NULL,\n detail TEXT NOT NULL,\n\n -- FTS-enabled fields\n lang TEXT NOT NULL,\n repo_name TEXT NOT NULL,\n search_key TEXT NOT NULL,\n label TEXT NOT NULL,\n tags TEXT NOT NULL\n);\n\nALTER TABLE lsif_data_documentation_search_private ADD PRIMARY KEY (dump_id, path_id);\n\nCREATE INDEX lsif_data_documentation_search_private_repo_id_idx ON lsif_data_documentation_search_private USING BTREE(repo_id);\nCREATE INDEX lsif_data_documentation_search_private_lang_trgm ON lsif_data_documentation_search_private USING gin(lang gin_trgm_ops);\nCREATE INDEX lsif_data_documentation_search_private_repo_name_trgm ON lsif_data_documentation_search_private USING gin(repo_name gin_trgm_ops);\nCREATE INDEX lsif_data_documentation_search_private_search_key_trgm ON lsif_data_documentation_search_private USING gin(search_key gin_trgm_ops);\nCREATE INDEX lsif_data_documentation_search_private_label_trgm ON lsif_data_documentation_search_private USING gin(label gin_trgm_ops);\nCREATE INDEX lsif_data_documentation_search_private_tags_trgm ON lsif_data_documentation_search_private USING gin(tags gin_trgm_ops);\n\nCOMMENT ON TABLE lsif_data_documentation_search_private IS 'A trigram index over documentation for search (private repos only)';\nCOMMENT ON COLUMN lsif_data_documentation_search_private.dump_id IS 'The identifier of the associated dump in the lsif_uploads table (state=completed).';\nCOMMENT ON COLUMN lsif_data_documentation_search_private.repo_id IS 'The repo ID, from the main app DB repo table. Used to search over a select set of repos by ID.';\nCOMMENT ON COLUMN lsif_data_documentation_search_private.path_id IS 'The fully qualified documentation page path ID, e.g. including \"#section\". See GraphQL codeintel.schema:documentationPage for what this is.';\n\nCOMMENT ON COLUMN lsif_data_documentation_search_private.lang IS 'The lowercase language name (go, java, etc.) OR, if unknown, the LSIF indexer name';\nCOMMENT ON COLUMN lsif_data_documentation_search_private.repo_name IS 'The name of the repository containing this search key.';\nCOMMENT ON COLUMN lsif_data_documentation_search_private.search_key IS 'The search key generated by the indexer, e.g. mux.Router.ServeHTTP. It is language-specific, and likely unique within a repository (but not always.) See protocol/documentation.go:Documentation.SearchKey';\nCOMMENT ON COLUMN lsif_data_documentation_search_private.label IS 'The label string of the result, e.g. a one-line function signature. See protocol/documentation.go:Documentation';\nCOMMENT ON COLUMN lsif_data_documentation_search_private.detail IS 'The detail string (e.g. the full function signature and its docs). See protocol/documentation.go:Documentation';\nCOMMENT ON COLUMN lsif_data_documentation_search_private.tags IS 'A space separated list of tags from the documentation node. See protocol/documentation.go:Documentation';", + "DownQuery": "ALTER TABLE lsif_data_documentation_pages DROP COLUMN search_indexed;\nDROP TABLE IF EXISTS lsif_data_documentation_search;", + "Privileged": true, + "NonIdempotent": false, + "Parents": [ + 1000000019 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000021, + "Name": "reverted", + "UpQuery": "-- Empty migration, this migration was reverted: https://github.com/sourcegraph/sourcegraph/pull/25715", + "DownQuery": "-- Empty migration, this migration was reverted: https://github.com/sourcegraph/sourcegraph/pull/25715", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1000000020 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000022, + "Name": "undo apidocs root column", + "UpQuery": "-- Undo the changes corresponding to https://github.com/sourcegraph/sourcegraph/pull/25715\nALTER TABLE lsif_data_documentation_search_public DROP COLUMN IF EXISTS dump_root;\nALTER TABLE lsif_data_documentation_search_private DROP COLUMN IF EXISTS dump_root;", + "DownQuery": "-- Nothing to do, the up migration undid changes previously made.", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1000000021 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000023, + "Name": "apidocs add dump root column", + "UpQuery": "ALTER TABLE lsif_data_documentation_search_public ADD COLUMN dump_root TEXT NOT NULL DEFAULT '';\nCOMMENT ON COLUMN lsif_data_documentation_search_public.dump_root IS 'Identical to lsif_dumps.root; The working directory of the indexer image relative to the repository root.';\nCREATE INDEX lsif_data_documentation_search_public_dump_root_idx ON lsif_data_documentation_search_public USING BTREE(dump_root);\n\nALTER TABLE lsif_data_documentation_search_private ADD COLUMN dump_root TEXT NOT NULL DEFAULT '';\nCOMMENT ON COLUMN lsif_data_documentation_search_private.dump_root IS 'Identical to lsif_dumps.root; The working directory of the indexer image relative to the repository root.';\nCREATE INDEX lsif_data_documentation_search_private_dump_root_idx ON lsif_data_documentation_search_public USING BTREE(dump_root);\n\n-- Truncate both tables; we don't care about reindexing given so little has been indexed to date.\nTRUNCATE lsif_data_documentation_search_public;\nTRUNCATE lsif_data_documentation_search_private;", + "DownQuery": "ALTER TABLE lsif_data_documentation_search_public DROP COLUMN IF EXISTS dump_root;\nALTER TABLE lsif_data_documentation_search_private DROP COLUMN IF EXISTS dump_root;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1000000022 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000024, + "Name": "apidocs search to tsvector", + "UpQuery": "-- We're completely changing the API docs search table schema, so we'll reindex everything\n-- from scratch. Reset our OOB migration's progress entirely.\n--\n-- IMPORTANT: Dropping the column and recreating it is nearly instant, updating the table\n-- to set the column to 'false' again can take several minutes.\nALTER TABLE lsif_data_documentation_pages DROP COLUMN search_indexed;\nALTER TABLE lsif_data_documentation_pages ADD COLUMN search_indexed boolean DEFAULT 'false';\n\n-- We're completely redefining the table.\nDROP TABLE IF EXISTS lsif_data_documentation_search_public;\n\n-- Each unique language name being stored in the search index.\n--\n-- Contains a tsvector index for matching a logical OR of query terms against the language name\n-- (e.g. \"http router go\" to match \"go\" without knowing if \"http\", \"router\", or \"go\" are actually\n-- a language name or not.)\nCREATE TABLE lsif_data_docs_search_lang_names_public (\n id BIGSERIAL PRIMARY KEY,\n lang_name TEXT NOT NULL UNIQUE,\n tsv TSVECTOR NOT NULL\n);\nCREATE INDEX lsif_data_docs_search_lang_names_public_tsv_idx ON lsif_data_docs_search_lang_names_public USING GIN(tsv);\n\nCOMMENT ON TABLE lsif_data_docs_search_lang_names_public IS 'Each unique language name being stored in the API docs search index.';\nCOMMENT ON COLUMN lsif_data_docs_search_lang_names_public.id IS 'The ID of the language name.';\nCOMMENT ON COLUMN lsif_data_docs_search_lang_names_public.lang_name IS 'The lowercase language name (go, java, etc.) OR, if unknown, the LSIF indexer name.';\nCOMMENT ON COLUMN lsif_data_docs_search_lang_names_public.tsv IS 'Indexed tsvector for the lang_name field. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\n\n-- Each unique repository name being stored in the search index.\n--\n-- Contains a tsvector index for matching against repository names, with both prefix and suffix\n-- (reverse prefix) matching within lexemes (words).\nCREATE TABLE lsif_data_docs_search_repo_names_public (\n id BIGSERIAL PRIMARY KEY,\n repo_name TEXT NOT NULL UNIQUE,\n tsv TSVECTOR NOT NULL,\n reverse_tsv TSVECTOR NOT NULL\n);\nCREATE INDEX lsif_data_docs_search_repo_names_public_tsv_idx ON lsif_data_docs_search_repo_names_public USING GIN(tsv);\nCREATE INDEX lsif_data_docs_search_repo_names_public_reverse_tsv_idx ON lsif_data_docs_search_repo_names_public USING GIN(reverse_tsv);\n\nCOMMENT ON TABLE lsif_data_docs_search_repo_names_public IS 'Each unique repository name being stored in the API docs search index.';\nCOMMENT ON COLUMN lsif_data_docs_search_repo_names_public.id IS 'The ID of the repository name.';\nCOMMENT ON COLUMN lsif_data_docs_search_repo_names_public.repo_name IS 'The fully qualified name of the repository.';\nCOMMENT ON COLUMN lsif_data_docs_search_repo_names_public.tsv IS 'Indexed tsvector for the lang_name field. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\nCOMMENT ON COLUMN lsif_data_docs_search_repo_names_public.reverse_tsv IS 'Indexed tsvector for the reverse of the lang_name field, for suffix lexeme/word matching. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\n\n-- Each unique sequence of space-separated tags being stored in the search index. This could be as\n-- many rows as the search table itself, because in theory each result could have a unique string\n-- of tags. In practice, though, they are frequently similar sequences.\n--\n-- The space separated tags have a tsvector for matching a logcal OR of query terms against, for\n-- the same reason as the lang_names table. e.g. so that we can have a query for \"go private function net router\"\n-- match the tags string \"private function\" without knowing which query terms are tags or not.\n--\n-- The entire sequence of space-separated tags are stored, in part so that lookups in the search table\n-- are faster (single ID lookup rather than array ALL lookup) and partly to allow for more complex\n-- tag matching options in the future.\nCREATE TABLE lsif_data_docs_search_tags_public (\n id BIGSERIAL PRIMARY KEY,\n tags TEXT NOT NULL UNIQUE,\n tsv TSVECTOR NOT NULL\n);\nCREATE INDEX lsif_data_docs_search_tags_public_tsv_idx ON lsif_data_docs_search_tags_public USING GIN(tsv);\n\nCOMMENT ON TABLE lsif_data_docs_search_tags_public IS 'Each uniques sequence of space-separated tags being stored in the API docs search index.';\nCOMMENT ON COLUMN lsif_data_docs_search_tags_public.id IS 'The ID of the tags.';\nCOMMENT ON COLUMN lsif_data_docs_search_tags_public.tags IS 'The full sequence of space-separated tags. See protocol/documentation.go:Documentation';\nCOMMENT ON COLUMN lsif_data_docs_search_tags_public.tsv IS 'Indexed tsvector for the tags field. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\n\n-- The actual search index over API docs, one entry per symbol/section of API docs.\nCREATE TABLE lsif_data_docs_search_public (\n -- Metadata fields\n id BIGSERIAL PRIMARY KEY,\n repo_id INTEGER NOT NULL,\n dump_id INTEGER NOT NULL,\n dump_root TEXT NOT NULL,\n path_id TEXT NOT NULL,\n detail TEXT NOT NULL,\n lang_name_id INTEGER NOT NULL,\n repo_name_id INTEGER NOT NULL,\n tags_id INTEGER NOT NULL,\n\n -- FTS-enabled fields\n search_key TEXT NOT NULL,\n search_key_tsv TSVECTOR NOT NULL,\n search_key_reverse_tsv TSVECTOR NOT NULL,\n\n label TEXT NOT NULL,\n label_tsv TSVECTOR NOT NULL,\n label_reverse_tsv TSVECTOR NOT NULL,\n\n CONSTRAINT lsif_data_docs_search_public_lang_name_id_fk FOREIGN KEY(lang_name_id) REFERENCES lsif_data_docs_search_lang_names_public(id),\n CONSTRAINT lsif_data_docs_search_public_repo_name_id_fk FOREIGN KEY(repo_name_id) REFERENCES lsif_data_docs_search_repo_names_public(id),\n CONSTRAINT lsif_data_docs_search_public_tags_id_fk FOREIGN KEY(tags_id) REFERENCES lsif_data_docs_search_tags_public(id)\n);\n\n-- This pair of fields is used to purge stale data from the search index, so use a btree index on it.\nCREATE INDEX lsif_data_docs_search_public_repo_id_idx ON lsif_data_docs_search_public USING BTREE(repo_id);\nCREATE INDEX lsif_data_docs_search_public_dump_id_idx ON lsif_data_docs_search_public USING BTREE(dump_id);\nCREATE INDEX lsif_data_docs_search_public_dump_root_idx ON lsif_data_docs_search_public USING BTREE(dump_root);\n\n-- tsvector indexes\nCREATE INDEX lsif_data_docs_search_public_search_key_tsv_idx ON lsif_data_docs_search_public USING BTREE(search_key_tsv);\nCREATE INDEX lsif_data_docs_search_public_search_key_reverse_tsv_idx ON lsif_data_docs_search_public USING BTREE(search_key_reverse_tsv);\nCREATE INDEX lsif_data_docs_search_public_label_tsv_idx ON lsif_data_docs_search_public USING BTREE(label_tsv);\nCREATE INDEX lsif_data_docs_search_public_label_reverse_tsv_idx ON lsif_data_docs_search_public USING BTREE(label_reverse_tsv);\n\nCOMMENT ON TABLE lsif_data_docs_search_public IS 'A tsvector search index over API documentation (public repos only)';\nCOMMENT ON COLUMN lsif_data_docs_search_public.id IS 'The row ID of the search result.';\nCOMMENT ON COLUMN lsif_data_docs_search_public.repo_id IS 'The repo ID, from the main app DB repo table. Used to search over a select set of repos by ID.';\nCOMMENT ON COLUMN lsif_data_docs_search_public.dump_id IS 'The identifier of the associated dump in the lsif_uploads table (state=completed).';\nCOMMENT ON COLUMN lsif_data_docs_search_public.dump_root IS 'Identical to lsif_dumps.root; The working directory of the indexer image relative to the repository root.';\nCOMMENT ON COLUMN lsif_data_docs_search_public.path_id IS 'The fully qualified documentation page path ID, e.g. including \"#section\". See GraphQL codeintel.schema:documentationPage for what this is.';\nCOMMENT ON COLUMN lsif_data_docs_search_public.detail IS 'The detail string (e.g. the full function signature and its docs). See protocol/documentation.go:Documentation';\nCOMMENT ON COLUMN lsif_data_docs_search_public.lang_name_id IS 'The programming language (or indexer name) that produced the result. Foreign key into lsif_data_docs_search_lang_names_public.';\nCOMMENT ON COLUMN lsif_data_docs_search_public.repo_name_id IS 'The repository name that produced the result. Foreign key into lsif_data_docs_search_repo_names_public.';\nCOMMENT ON COLUMN lsif_data_docs_search_public.tags_id IS 'The tags from the documentation node. Foreign key into lsif_data_docs_search_tags_public.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_public.search_key IS 'The search key generated by the indexer, e.g. mux.Router.ServeHTTP. It is language-specific, and likely unique within a repository (but not always.) See protocol/documentation.go:Documentation.SearchKey';\nCOMMENT ON COLUMN lsif_data_docs_search_public.search_key_tsv IS 'Indexed tsvector for the search_key field. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\nCOMMENT ON COLUMN lsif_data_docs_search_public.search_key_reverse_tsv IS 'Indexed tsvector for the reverse of the search_key field, for suffix lexeme/word matching. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_public.label IS 'The label string of the result, e.g. a one-line function signature. See protocol/documentation.go:Documentation';\nCOMMENT ON COLUMN lsif_data_docs_search_public.label_tsv IS 'Indexed tsvector for the label field. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\nCOMMENT ON COLUMN lsif_data_docs_search_public.label_reverse_tsv IS 'Indexed tsvector for the reverse of the label field, for suffix lexeme/word matching. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\n\n-- ************************************************************************************************\n-- Below here is a direct copy of the above, but with \"public\" replaced with \"private\" for the *\n-- private variant of the table. *\n-- ************************************************************************************************\n\n-- We're completely redefining the table.\nDROP TABLE IF EXISTS lsif_data_documentation_search_private;\n\n-- Each unique language name being stored in the search index.\n--\n-- Contains a tsvector index for matching a logical OR of query terms against the language name\n-- (e.g. \"http router go\" to match \"go\" without knowing if \"http\", \"router\", or \"go\" are actually\n-- a language name or not.)\nCREATE TABLE lsif_data_docs_search_lang_names_private (\n id BIGSERIAL PRIMARY KEY,\n lang_name TEXT NOT NULL UNIQUE,\n tsv TSVECTOR NOT NULL\n);\nCREATE INDEX lsif_data_docs_search_lang_names_private_tsv_idx ON lsif_data_docs_search_lang_names_private USING GIN(tsv);\n\nCOMMENT ON TABLE lsif_data_docs_search_lang_names_private IS 'Each unique language name being stored in the API docs search index.';\nCOMMENT ON COLUMN lsif_data_docs_search_lang_names_private.id IS 'The ID of the language name.';\nCOMMENT ON COLUMN lsif_data_docs_search_lang_names_private.lang_name IS 'The lowercase language name (go, java, etc.) OR, if unknown, the LSIF indexer name.';\nCOMMENT ON COLUMN lsif_data_docs_search_lang_names_private.tsv IS 'Indexed tsvector for the lang_name field. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\n\n-- Each unique repository name being stored in the search index.\n--\n-- Contains a tsvector index for matching against repository names, with both prefix and suffix\n-- (reverse prefix) matching within lexemes (words).\nCREATE TABLE lsif_data_docs_search_repo_names_private (\n id BIGSERIAL PRIMARY KEY,\n repo_name TEXT NOT NULL UNIQUE,\n tsv TSVECTOR NOT NULL,\n reverse_tsv TSVECTOR NOT NULL\n);\nCREATE INDEX lsif_data_docs_search_repo_names_private_tsv_idx ON lsif_data_docs_search_repo_names_private USING GIN(tsv);\nCREATE INDEX lsif_data_docs_search_repo_names_private_reverse_tsv_idx ON lsif_data_docs_search_repo_names_private USING GIN(reverse_tsv);\n\nCOMMENT ON TABLE lsif_data_docs_search_repo_names_private IS 'Each unique repository name being stored in the API docs search index.';\nCOMMENT ON COLUMN lsif_data_docs_search_repo_names_private.id IS 'The ID of the repository name.';\nCOMMENT ON COLUMN lsif_data_docs_search_repo_names_private.repo_name IS 'The fully qualified name of the repository.';\nCOMMENT ON COLUMN lsif_data_docs_search_repo_names_private.tsv IS 'Indexed tsvector for the lang_name field. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\nCOMMENT ON COLUMN lsif_data_docs_search_repo_names_private.reverse_tsv IS 'Indexed tsvector for the reverse of the lang_name field, for suffix lexeme/word matching. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\n\n-- Each unique sequence of space-separated tags being stored in the search index. This could be as\n-- many rows as the search table itself, because in theory each result could have a unique string\n-- of tags. In practice, though, they are frequently similar sequences.\n--\n-- The space separated tags have a tsvector for matching a logcal OR of query terms against, for\n-- the same reason as the lang_names table. e.g. so that we can have a query for \"go private function net router\"\n-- match the tags string \"private function\" without knowing which query terms are tags or not.\n--\n-- The entire sequence of space-separated tags are stored, in part so that lookups in the search table\n-- are faster (single ID lookup rather than array ALL lookup) and partly to allow for more complex\n-- tag matching options in the future.\nCREATE TABLE lsif_data_docs_search_tags_private (\n id BIGSERIAL PRIMARY KEY,\n tags TEXT NOT NULL UNIQUE,\n tsv TSVECTOR NOT NULL\n);\nCREATE INDEX lsif_data_docs_search_tags_private_tsv_idx ON lsif_data_docs_search_tags_private USING GIN(tsv);\n\nCOMMENT ON TABLE lsif_data_docs_search_tags_private IS 'Each uniques sequence of space-separated tags being stored in the API docs search index.';\nCOMMENT ON COLUMN lsif_data_docs_search_tags_private.id IS 'The ID of the tags.';\nCOMMENT ON COLUMN lsif_data_docs_search_tags_private.tags IS 'The full sequence of space-separated tags. See protocol/documentation.go:Documentation';\nCOMMENT ON COLUMN lsif_data_docs_search_tags_private.tsv IS 'Indexed tsvector for the tags field. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\n\n-- The actual search index over API docs, one entry per symbol/section of API docs.\nCREATE TABLE lsif_data_docs_search_private (\n -- Metadata fields\n id BIGSERIAL PRIMARY KEY,\n repo_id INTEGER NOT NULL,\n dump_id INTEGER NOT NULL,\n dump_root TEXT NOT NULL,\n path_id TEXT NOT NULL,\n detail TEXT NOT NULL,\n lang_name_id INTEGER NOT NULL,\n repo_name_id INTEGER NOT NULL,\n tags_id INTEGER NOT NULL,\n\n -- FTS-enabled fields\n search_key TEXT NOT NULL,\n search_key_tsv TSVECTOR NOT NULL,\n search_key_reverse_tsv TSVECTOR NOT NULL,\n\n label TEXT NOT NULL,\n label_tsv TSVECTOR NOT NULL,\n label_reverse_tsv TSVECTOR NOT NULL,\n\n CONSTRAINT lsif_data_docs_search_private_lang_name_id_fk FOREIGN KEY(lang_name_id) REFERENCES lsif_data_docs_search_lang_names_private(id),\n CONSTRAINT lsif_data_docs_search_private_repo_name_id_fk FOREIGN KEY(repo_name_id) REFERENCES lsif_data_docs_search_repo_names_private(id),\n CONSTRAINT lsif_data_docs_search_private_tags_id_fk FOREIGN KEY(tags_id) REFERENCES lsif_data_docs_search_tags_private(id)\n);\n\n-- This pair of fields is used to purge stale data from the search index, so use a btree index on it.\nCREATE INDEX lsif_data_docs_search_private_repo_id_idx ON lsif_data_docs_search_private USING BTREE(repo_id);\nCREATE INDEX lsif_data_docs_search_private_dump_id_idx ON lsif_data_docs_search_private USING BTREE(dump_id);\nCREATE INDEX lsif_data_docs_search_private_dump_root_idx ON lsif_data_docs_search_private USING BTREE(dump_root);\n\n-- tsvector indexes\nCREATE INDEX lsif_data_docs_search_private_search_key_tsv_idx ON lsif_data_docs_search_private USING BTREE(search_key_tsv);\nCREATE INDEX lsif_data_docs_search_private_search_key_reverse_tsv_idx ON lsif_data_docs_search_private USING BTREE(search_key_reverse_tsv);\nCREATE INDEX lsif_data_docs_search_private_label_tsv_idx ON lsif_data_docs_search_private USING BTREE(label_tsv);\nCREATE INDEX lsif_data_docs_search_private_label_reverse_tsv_idx ON lsif_data_docs_search_private USING BTREE(label_reverse_tsv);\n\nCOMMENT ON TABLE lsif_data_docs_search_private IS 'A tsvector search index over API documentation (private repos only)';\nCOMMENT ON COLUMN lsif_data_docs_search_private.id IS 'The row ID of the search result.';\nCOMMENT ON COLUMN lsif_data_docs_search_private.repo_id IS 'The repo ID, from the main app DB repo table. Used to search over a select set of repos by ID.';\nCOMMENT ON COLUMN lsif_data_docs_search_private.dump_id IS 'The identifier of the associated dump in the lsif_uploads table (state=completed).';\nCOMMENT ON COLUMN lsif_data_docs_search_private.dump_root IS 'Identical to lsif_dumps.root; The working directory of the indexer image relative to the repository root.';\nCOMMENT ON COLUMN lsif_data_docs_search_private.path_id IS 'The fully qualified documentation page path ID, e.g. including \"#section\". See GraphQL codeintel.schema:documentationPage for what this is.';\nCOMMENT ON COLUMN lsif_data_docs_search_private.detail IS 'The detail string (e.g. the full function signature and its docs). See protocol/documentation.go:Documentation';\nCOMMENT ON COLUMN lsif_data_docs_search_private.lang_name_id IS 'The programming language (or indexer name) that produced the result. Foreign key into lsif_data_docs_search_lang_names_private.';\nCOMMENT ON COLUMN lsif_data_docs_search_private.repo_name_id IS 'The repository name that produced the result. Foreign key into lsif_data_docs_search_repo_names_private.';\nCOMMENT ON COLUMN lsif_data_docs_search_private.tags_id IS 'The tags from the documentation node. Foreign key into lsif_data_docs_search_tags_private.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_private.search_key IS 'The search key generated by the indexer, e.g. mux.Router.ServeHTTP. It is language-specific, and likely unique within a repository (but not always.) See protocol/documentation.go:Documentation.SearchKey';\nCOMMENT ON COLUMN lsif_data_docs_search_private.search_key_tsv IS 'Indexed tsvector for the search_key field. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\nCOMMENT ON COLUMN lsif_data_docs_search_private.search_key_reverse_tsv IS 'Indexed tsvector for the reverse of the search_key field, for suffix lexeme/word matching. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_private.label IS 'The label string of the result, e.g. a one-line function signature. See protocol/documentation.go:Documentation';\nCOMMENT ON COLUMN lsif_data_docs_search_private.label_tsv IS 'Indexed tsvector for the label field. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\nCOMMENT ON COLUMN lsif_data_docs_search_private.label_reverse_tsv IS 'Indexed tsvector for the reverse of the label field, for suffix lexeme/word matching. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';", + "DownQuery": "-- We've alterd tables beyond rollback in our up migration. The best we can do for a down migration\n-- is bring back the old schema so the previous version of Sourcegraph runs properly.\nDROP TABLE IF EXISTS lsif_data_docs_search_public;\nDROP TABLE IF EXISTS lsif_data_docs_search_lang_names_public;\nDROP TABLE IF EXISTS lsif_data_docs_search_repo_names_public;\nDROP TABLE IF EXISTS lsif_data_docs_search_tags_public;\n\nCREATE TABLE IF NOT EXISTS lsif_data_documentation_search_public (\n -- Metadata fields\n dump_id integer NOT NULL,\n repo_id integer NOT NULL,\n path_id TEXT NOT NULL,\n detail TEXT NOT NULL,\n\n -- FTS-enabled fields\n lang TEXT NOT NULL,\n repo_name TEXT NOT NULL,\n search_key TEXT NOT NULL,\n label TEXT NOT NULL,\n tags TEXT NOT NULL\n);\n\nALTER TABLE lsif_data_documentation_search_public ADD PRIMARY KEY (dump_id, path_id);\n\nCREATE INDEX lsif_data_documentation_search_public_repo_id_idx ON lsif_data_documentation_search_public USING BTREE(repo_id);\nCREATE INDEX lsif_data_documentation_search_public_lang_trgm ON lsif_data_documentation_search_public USING gin(lang gin_trgm_ops);\nCREATE INDEX lsif_data_documentation_search_public_repo_name_trgm ON lsif_data_documentation_search_public USING gin(repo_name gin_trgm_ops);\nCREATE INDEX lsif_data_documentation_search_public_search_key_trgm ON lsif_data_documentation_search_public USING gin(search_key gin_trgm_ops);\nCREATE INDEX lsif_data_documentation_search_public_label_trgm ON lsif_data_documentation_search_public USING gin(label gin_trgm_ops);\nCREATE INDEX lsif_data_documentation_search_public_tags_trgm ON lsif_data_documentation_search_public USING gin(tags gin_trgm_ops);\n\nCOMMENT ON TABLE lsif_data_documentation_search_public IS 'A trigram index over documentation for search (public repos only)';\nCOMMENT ON COLUMN lsif_data_documentation_search_public.dump_id IS 'The identifier of the associated dump in the lsif_uploads table (state=completed).';\nCOMMENT ON COLUMN lsif_data_documentation_search_public.repo_id IS 'The repo ID, from the main app DB repo table. Used to search over a select set of repos by ID.';\nCOMMENT ON COLUMN lsif_data_documentation_search_public.path_id IS 'The fully qualified documentation page path ID, e.g. including \"#section\". See GraphQL codeintel.schema:documentationPage for what this is.';\n\nCOMMENT ON COLUMN lsif_data_documentation_search_public.lang IS 'The lowercase language name (go, java, etc.) OR, if unknown, the LSIF indexer name';\nCOMMENT ON COLUMN lsif_data_documentation_search_public.repo_name IS 'The name of the repository containing this search key.';\nCOMMENT ON COLUMN lsif_data_documentation_search_public.search_key IS 'The search key generated by the indexer, e.g. mux.Router.ServeHTTP. It is language-specific, and likely unique within a repository (but not always.) See protocol/documentation.go:Documentation.SearchKey';\nCOMMENT ON COLUMN lsif_data_documentation_search_public.label IS 'The label string of the result, e.g. a one-line function signature. See protocol/documentation.go:Documentation';\nCOMMENT ON COLUMN lsif_data_documentation_search_public.detail IS 'The detail string (e.g. the full function signature and its docs). See protocol/documentation.go:Documentation';\nCOMMENT ON COLUMN lsif_data_documentation_search_public.tags IS 'A space separated list of tags from the documentation node. See protocol/documentation.go:Documentation';\n\nALTER TABLE lsif_data_documentation_search_public ADD COLUMN dump_root TEXT NOT NULL DEFAULT '';\nCOMMENT ON COLUMN lsif_data_documentation_search_public.dump_root IS 'Identical to lsif_dumps.root; The working directory of the indexer image relative to the repository root.';\nCREATE INDEX lsif_data_documentation_search_public_dump_root_idx ON lsif_data_documentation_search_public USING BTREE(dump_root);\n\n-- ************************************************************************************************\n-- Below here is a direct copy of the above, but with \"public\" replaced with \"private\" for the *\n-- private variant of the table. *\n-- ************************************************************************************************\n\n-- We've alterd tables beyond rollback in our up migration. The best we can do for a down migration\n-- is bring back the old schema so the previous version of Sourcegraph runs properly.\nDROP TABLE IF EXISTS lsif_data_docs_search_private;\nDROP TABLE IF EXISTS lsif_data_docs_search_lang_names_private;\nDROP TABLE IF EXISTS lsif_data_docs_search_repo_names_private;\nDROP TABLE IF EXISTS lsif_data_docs_search_tags_private;\n\nCREATE TABLE IF NOT EXISTS lsif_data_documentation_search_private (\n -- Metadata fields\n dump_id integer NOT NULL,\n repo_id integer NOT NULL,\n path_id TEXT NOT NULL,\n detail TEXT NOT NULL,\n\n -- FTS-enabled fields\n lang TEXT NOT NULL,\n repo_name TEXT NOT NULL,\n search_key TEXT NOT NULL,\n label TEXT NOT NULL,\n tags TEXT NOT NULL\n);\n\nALTER TABLE lsif_data_documentation_search_private ADD PRIMARY KEY (dump_id, path_id);\n\nCREATE INDEX lsif_data_documentation_search_private_repo_id_idx ON lsif_data_documentation_search_private USING BTREE(repo_id);\nCREATE INDEX lsif_data_documentation_search_private_lang_trgm ON lsif_data_documentation_search_private USING gin(lang gin_trgm_ops);\nCREATE INDEX lsif_data_documentation_search_private_repo_name_trgm ON lsif_data_documentation_search_private USING gin(repo_name gin_trgm_ops);\nCREATE INDEX lsif_data_documentation_search_private_search_key_trgm ON lsif_data_documentation_search_private USING gin(search_key gin_trgm_ops);\nCREATE INDEX lsif_data_documentation_search_private_label_trgm ON lsif_data_documentation_search_private USING gin(label gin_trgm_ops);\nCREATE INDEX lsif_data_documentation_search_private_tags_trgm ON lsif_data_documentation_search_private USING gin(tags gin_trgm_ops);\n\nCOMMENT ON TABLE lsif_data_documentation_search_private IS 'A trigram index over documentation for search (private repos only)';\nCOMMENT ON COLUMN lsif_data_documentation_search_private.dump_id IS 'The identifier of the associated dump in the lsif_uploads table (state=completed).';\nCOMMENT ON COLUMN lsif_data_documentation_search_private.repo_id IS 'The repo ID, from the main app DB repo table. Used to search over a select set of repos by ID.';\nCOMMENT ON COLUMN lsif_data_documentation_search_private.path_id IS 'The fully qualified documentation page path ID, e.g. including \"#section\". See GraphQL codeintel.schema:documentationPage for what this is.';\n\nCOMMENT ON COLUMN lsif_data_documentation_search_private.lang IS 'The lowercase language name (go, java, etc.) OR, if unknown, the LSIF indexer name';\nCOMMENT ON COLUMN lsif_data_documentation_search_private.repo_name IS 'The name of the repository containing this search key.';\nCOMMENT ON COLUMN lsif_data_documentation_search_private.search_key IS 'The search key generated by the indexer, e.g. mux.Router.ServeHTTP. It is language-specific, and likely unique within a repository (but not always.) See protocol/documentation.go:Documentation.SearchKey';\nCOMMENT ON COLUMN lsif_data_documentation_search_private.label IS 'The label string of the result, e.g. a one-line function signature. See protocol/documentation.go:Documentation';\nCOMMENT ON COLUMN lsif_data_documentation_search_private.detail IS 'The detail string (e.g. the full function signature and its docs). See protocol/documentation.go:Documentation';\nCOMMENT ON COLUMN lsif_data_documentation_search_private.tags IS 'A space separated list of tags from the documentation node. See protocol/documentation.go:Documentation';\n\nALTER TABLE lsif_data_documentation_search_private ADD COLUMN dump_root TEXT NOT NULL DEFAULT '';\nCOMMENT ON COLUMN lsif_data_documentation_search_private.dump_root IS 'Identical to lsif_dumps.root; The working directory of the indexer image relative to the repository root.';\nCREATE INDEX lsif_data_documentation_search_private_dump_root_idx ON lsif_data_documentation_search_private USING BTREE(dump_root);", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1000000023 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000025, + "Name": "apidocs materialized stats", + "UpQuery": "--------------------------------------------------------\n-- Stats for the lsif_data_documentation_pages table. --\n--------------------------------------------------------\nCREATE TABLE lsif_data_apidocs_num_pages AS SELECT count(*) FROM lsif_data_documentation_pages;\nCREATE TABLE lsif_data_apidocs_num_dumps AS SELECT count(DISTINCT dump_id) FROM lsif_data_documentation_pages;\nCREATE TABLE lsif_data_apidocs_num_dumps_indexed AS SELECT count(DISTINCT dump_id) FROM lsif_data_documentation_pages WHERE search_indexed='true';\n\nCREATE OR REPLACE FUNCTION lsif_data_documentation_pages_delete()\nRETURNS TRIGGER LANGUAGE plpgsql\nAS $$\nBEGIN\nUPDATE lsif_data_apidocs_num_pages SET count = count - (select count(*) from oldtbl);\nUPDATE lsif_data_apidocs_num_dumps SET count = count - (select count(DISTINCT dump_id) from oldtbl);\nUPDATE lsif_data_apidocs_num_dumps_indexed SET count = count - (select count(DISTINCT dump_id) from oldtbl WHERE search_indexed='true');\nRETURN NULL;\nEND $$;\n\nCREATE TRIGGER lsif_data_documentation_pages_delete\nAFTER DELETE ON lsif_data_documentation_pages\nREFERENCING OLD TABLE AS oldtbl\nFOR EACH STATEMENT EXECUTE PROCEDURE lsif_data_documentation_pages_delete();\n\nCREATE OR REPLACE FUNCTION lsif_data_documentation_pages_insert()\nRETURNS TRIGGER LANGUAGE plpgsql\nAS $$\nBEGIN\nUPDATE lsif_data_apidocs_num_pages SET count = count + (select count(*) from newtbl);\nUPDATE lsif_data_apidocs_num_dumps SET count = count + (select count(DISTINCT dump_id) from newtbl);\nUPDATE lsif_data_apidocs_num_dumps_indexed SET count = count + (select count(DISTINCT dump_id) from newtbl WHERE search_indexed='true');\nRETURN NULL;\nEND $$;\n\nCREATE TRIGGER lsif_data_documentation_pages_insert\nAFTER INSERT ON lsif_data_documentation_pages\nREFERENCING NEW TABLE AS newtbl\nFOR EACH STATEMENT EXECUTE PROCEDURE lsif_data_documentation_pages_insert();\n\nCREATE OR REPLACE FUNCTION lsif_data_documentation_pages_update()\nRETURNS TRIGGER LANGUAGE plpgsql\nAS $$\nBEGIN\nWITH\n beforeIndexed AS (SELECT count(DISTINCT dump_id) FROM oldtbl WHERE search_indexed='true'),\n afterIndexed AS (SELECT count(DISTINCT dump_id) FROM newtbl WHERE search_indexed='true')\nUPDATE lsif_data_apidocs_num_dumps_indexed SET count=count + ((select * from afterIndexed) - (select * from beforeIndexed));\nRETURN NULL;\nEND $$;\n\nCREATE TRIGGER lsif_data_documentation_pages_update\nAFTER UPDATE ON lsif_data_documentation_pages\nREFERENCING OLD TABLE AS oldtbl NEW TABLE AS newtbl\nFOR EACH STATEMENT EXECUTE PROCEDURE lsif_data_documentation_pages_update();\n\n-------------------------------------------------------\n-- Stats for the lsif_data_docs_search_public table. --\n-------------------------------------------------------\nCREATE TABLE lsif_data_apidocs_num_search_results_public AS SELECT count(*) FROM lsif_data_docs_search_public;\n\nCREATE OR REPLACE FUNCTION lsif_data_docs_search_public_delete()\nRETURNS TRIGGER LANGUAGE plpgsql\nAS $$\nBEGIN\nUPDATE lsif_data_apidocs_num_search_results_public SET count = count - (select count(*) from oldtbl);\nRETURN NULL;\nEND $$;\n\nCREATE TRIGGER lsif_data_docs_search_public_delete\nAFTER DELETE\nON lsif_data_docs_search_public\nREFERENCING OLD TABLE AS oldtbl\nFOR EACH STATEMENT EXECUTE PROCEDURE lsif_data_docs_search_public_delete();\n\nCREATE OR REPLACE FUNCTION lsif_data_docs_search_public_insert()\nRETURNS TRIGGER LANGUAGE plpgsql\nAS $$\nBEGIN\nUPDATE lsif_data_apidocs_num_search_results_public SET count = count + (select count(*) from newtbl);\nRETURN NULL;\nEND $$;\n\nCREATE TRIGGER lsif_data_docs_search_public_insert\nAFTER INSERT\nON lsif_data_docs_search_public\nREFERENCING NEW TABLE AS newtbl\nFOR EACH STATEMENT EXECUTE PROCEDURE lsif_data_docs_search_public_insert();\n\n-------------------------------------------------------\n-- Stats for the lsif_data_docs_search_private table. --\n-------------------------------------------------------\nCREATE TABLE lsif_data_apidocs_num_search_results_private AS SELECT count(*) FROM lsif_data_docs_search_private;\n\nCREATE OR REPLACE FUNCTION lsif_data_docs_search_private_delete()\nRETURNS TRIGGER LANGUAGE plpgsql\nAS $$\nBEGIN\nUPDATE lsif_data_apidocs_num_search_results_private SET count = count - (select count(*) from oldtbl);\nRETURN NULL;\nEND $$;\n\nCREATE TRIGGER lsif_data_docs_search_private_delete\nAFTER DELETE\nON lsif_data_docs_search_private\nREFERENCING OLD TABLE AS oldtbl\nFOR EACH STATEMENT EXECUTE PROCEDURE lsif_data_docs_search_private_delete();\n\nCREATE OR REPLACE FUNCTION lsif_data_docs_search_private_insert()\nRETURNS TRIGGER LANGUAGE plpgsql\nAS $$\nBEGIN\nUPDATE lsif_data_apidocs_num_search_results_private SET count = count + (select count(*) from newtbl);\nRETURN NULL;\nEND $$;\n\nCREATE TRIGGER lsif_data_docs_search_private_insert\nAFTER INSERT\nON lsif_data_docs_search_private\nREFERENCING NEW TABLE AS newtbl\nFOR EACH STATEMENT EXECUTE PROCEDURE lsif_data_docs_search_private_insert();", + "DownQuery": "DROP TABLE lsif_data_apidocs_num_pages;\nDROP TABLE lsif_data_apidocs_num_dumps;\nDROP TABLE lsif_data_apidocs_num_dumps_indexed;\nDROP TRIGGER lsif_data_documentation_pages_delete ON lsif_data_documentation_pages;\nDROP TRIGGER lsif_data_documentation_pages_insert ON lsif_data_documentation_pages;\nDROP TRIGGER lsif_data_documentation_pages_update ON lsif_data_documentation_pages;\nDROP FUNCTION lsif_data_documentation_pages_delete;\nDROP FUNCTION lsif_data_documentation_pages_insert;\nDROP FUNCTION lsif_data_documentation_pages_update;\n\nDROP TABLE lsif_data_apidocs_num_search_results_public;\nDROP TRIGGER lsif_data_docs_search_public_delete ON lsif_data_docs_search_public;\nDROP TRIGGER lsif_data_docs_search_public_insert ON lsif_data_docs_search_public;\nDROP FUNCTION lsif_data_docs_search_public_delete;\nDROP FUNCTION lsif_data_docs_search_public_insert;\n\nDROP TABLE lsif_data_apidocs_num_search_results_private;\nDROP TRIGGER lsif_data_docs_search_private_delete ON lsif_data_docs_search_private;\nDROP TRIGGER lsif_data_docs_search_private_insert ON lsif_data_docs_search_private;\nDROP FUNCTION lsif_data_docs_search_private_delete;\nDROP FUNCTION lsif_data_docs_search_private_insert;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1000000024 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000026, + "Name": "add lsif data docs search current", + "UpQuery": "CREATE TABLE IF NOT EXISTS lsif_data_docs_search_current_public (\n repo_id INTEGER NOT NULL,\n dump_root TEXT NOT NULL,\n lang_name_id INTEGER NOT NULL,\n dump_id INTEGER NOT NULL,\n last_cleanup_scan_at timestamp with time zone NOT NULL,\n\n PRIMARY KEY (repo_id, dump_root, lang_name_id)\n);\n\nCOMMENT ON TABLE lsif_data_docs_search_current_public IS 'A table indicating the most current search index for a unique repository, root, and language.';\nCOMMENT ON COLUMN lsif_data_docs_search_current_public.repo_id IS 'The repository identifier of the associated dump.';\nCOMMENT ON COLUMN lsif_data_docs_search_current_public.dump_root IS 'The root of the associated dump.';\nCOMMENT ON COLUMN lsif_data_docs_search_current_public.lang_name_id IS 'The interned index name of the associated dump.';\nCOMMENT ON COLUMN lsif_data_docs_search_current_public.dump_id IS 'The most recent dump identifier for this key. See associated content in the lsif_data_docs_search_public table.';\nCOMMENT ON COLUMN lsif_data_docs_search_current_public.last_cleanup_scan_at IS 'The last time outdated records in the lsif_data_docs_search_public table have been cleaned.';\n\nCREATE TABLE IF NOT EXISTS lsif_data_docs_search_current_private (\n repo_id INTEGER NOT NULL,\n dump_root TEXT NOT NULL,\n lang_name_id INTEGER NOT NULL,\n dump_id INTEGER NOT NULL,\n last_cleanup_scan_at timestamp with time zone NOT NULL,\n\n PRIMARY KEY (repo_id, dump_root, lang_name_id)\n);\n\nCOMMENT ON TABLE lsif_data_docs_search_current_private IS 'A table indicating the most current search index for a unique repository, root, and language.';\nCOMMENT ON COLUMN lsif_data_docs_search_current_private.repo_id IS 'The repository identifier of the associated dump.';\nCOMMENT ON COLUMN lsif_data_docs_search_current_private.dump_root IS 'The root of the associated dump.';\nCOMMENT ON COLUMN lsif_data_docs_search_current_private.lang_name_id IS 'The interned index name of the associated dump.';\nCOMMENT ON COLUMN lsif_data_docs_search_current_private.dump_id IS 'The most recent dump identifier for this key. See associated content in the lsif_data_docs_search_private table.';\nCOMMENT ON COLUMN lsif_data_docs_search_current_private.last_cleanup_scan_at IS 'The last time outdated records in the lsif_data_docs_search_private table have been cleaned.';", + "DownQuery": "DROP TABLE IF EXISTS lsif_data_docs_search_current_public;\nDROP TABLE IF EXISTS lsif_data_docs_search_current_private;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1000000025 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000027, + "Name": "add search repo names index", + "UpQuery": "CREATE INDEX IF NOT EXISTS lsif_data_documentation_pages_dump_id_unindexed ON lsif_data_documentation_pages(dump_id) WHERE NOT search_indexed;", + "DownQuery": "DROP INDEX lsif_data_documentation_pages_dump_id_unindexed;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1000000026 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000028, + "Name": "lsif non unique docs search current tables", + "UpQuery": "--\n-- Public\n\n-- Change comment\nCOMMENT ON COLUMN lsif_data_docs_search_current_public.dump_id IS 'The associated dump identifier.';\n\n-- Create new created_at column to decide a leader\nALTER TABLE lsif_data_docs_search_current_public ADD COLUMN IF NOT EXISTS created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW();\nCOMMENT ON COLUMN lsif_data_docs_search_current_public.created_at IS 'The time this record was inserted. The records with the latest created_at value for the same repository, root, and language is the only visible one and others will be deleted asynchronously.';\n\n-- Add default to last_cleanup_scan_at column\nALTER TABLE lsif_data_docs_search_current_public ALTER COLUMN last_cleanup_scan_at SET DEFAULT NOW();\nCOMMENT ON COLUMN lsif_data_docs_search_current_public.last_cleanup_scan_at IS 'The last time this record was checked as part of a data retention scan.';\n\n-- Create new indexes\nCREATE INDEX IF NOT EXISTS lsif_data_docs_search_current_public_lookup\nON lsif_data_docs_search_current_public(repo_id, dump_root, lang_name_id, created_at)\nINCLUDE (dump_id);\n\nCREATE INDEX IF NOT EXISTS lsif_data_docs_search_current_public_last_cleanup_scan_at ON lsif_data_docs_search_current_public(last_cleanup_scan_at);\n\n-- Drop existing primary key\nALTER TABLE lsif_data_docs_search_current_public DROP CONSTRAINT IF EXISTS lsif_data_docs_search_current_public_pkey;\n\n-- Create new serial primary key\nALTER TABLE lsif_data_docs_search_current_public ADD COLUMN IF NOT EXISTS id SERIAL PRIMARY KEY;\n\n--\n-- Private\n\n-- Change comment\nCOMMENT ON COLUMN lsif_data_docs_search_current_private.dump_id IS 'The associated dump identifier.';\n\n-- Create new created_at column to decide a leader\nALTER TABLE lsif_data_docs_search_current_private ADD COLUMN IF NOT EXISTS created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW();\nCOMMENT ON COLUMN lsif_data_docs_search_current_private.created_at IS 'The time this record was inserted. The records with the latest created_at value for the same repository, root, and language is the only visible one and others will be deleted asynchronously.';\n\n-- Add default to last_cleanup_scan_at column\nALTER TABLE lsif_data_docs_search_current_private ALTER COLUMN last_cleanup_scan_at SET DEFAULT NOW();\nCOMMENT ON COLUMN lsif_data_docs_search_current_private.last_cleanup_scan_at IS 'The last time this record was checked as part of a data retention scan.';\n\n-- Add index to last_cleanup_scan_at\n\n\n-- Create new indexes\nCREATE INDEX IF NOT EXISTS lsif_data_docs_search_current_private_lookup\nON lsif_data_docs_search_current_private(repo_id, dump_root, lang_name_id, created_at)\nINCLUDE (dump_id);\n\nCREATE INDEX IF NOT EXISTS lsif_data_docs_search_current_private_last_cleanup_scan_at ON lsif_data_docs_search_current_private(last_cleanup_scan_at);\n\n-- Drop existing primary key\nALTER TABLE lsif_data_docs_search_current_private DROP CONSTRAINT IF EXISTS lsif_data_docs_search_current_private_pkey;\n\n-- Create new serial primary key\nALTER TABLE lsif_data_docs_search_current_private ADD COLUMN IF NOT EXISTS id SERIAL PRIMARY KEY;", + "DownQuery": "--\n-- Public\n\n-- De-duplicate records before adding the unique index\nDELETE FROM lsif_data_docs_search_current_public WHERE id NOT IN (\n SELECT MAX(id) as max_id\n FROM lsif_data_docs_search_current_public\n GROUP BY repo_id, dump_root, lang_name_id\n);\n\n-- Drop new columns\nALTER TABLE lsif_data_docs_search_current_public DROP COLUMN IF EXISTS id;\nALTER TABLE lsif_data_docs_search_current_public DROP COLUMN IF EXISTS created_at;\n\n-- Drop new index\nDROP INDEX IF EXISTS lsif_data_docs_search_current_public_last_cleanup_scan_at;\n\n-- Re-create old primary key\nALTER TABLE lsif_data_docs_search_current_public ADD PRIMARY KEY (repo_id, dump_root, lang_name_id);\n\n-- Restore old comment\nCOMMENT ON COLUMN lsif_data_docs_search_current_public.dump_id IS 'The most recent dump identifier for this key. See associated content in the lsif_data_docs_search_public table.';\n\n-- Restore old last_cleanup_scan_at column\nCOMMENT ON COLUMN lsif_data_docs_search_current_public.last_cleanup_scan_at IS 'The last time outdated records in the lsif_data_docs_search_public table have been cleaned.';\nALTER TABLE lsif_data_docs_search_current_public ALTER COLUMN last_cleanup_scan_at DROP DEFAULT;\n\n--\n-- Private\n\n-- De-duplicate records before adding the unique index\nDELETE FROM lsif_data_docs_search_current_private WHERE id NOT IN (\n SELECT MAX(id) as max_id\n FROM lsif_data_docs_search_current_private\n GROUP BY repo_id, dump_root, lang_name_id\n);\n\n-- Drop new columns\nALTER TABLE lsif_data_docs_search_current_private DROP COLUMN IF EXISTS id;\nALTER TABLE lsif_data_docs_search_current_private DROP COLUMN IF EXISTS created_at;\n\n-- Drop new index\nDROP INDEX IF EXISTS lsif_data_docs_search_current_private_last_cleanup_scan_at;\n\n-- Re-create old primary key\nALTER TABLE lsif_data_docs_search_current_private ADD PRIMARY KEY (repo_id, dump_root, lang_name_id);\n\n-- Restore old comment\nCOMMENT ON COLUMN lsif_data_docs_search_current_private.dump_id IS 'The most recent dump identifier for this key. See associated content in the lsif_data_docs_search_public table.';\n\n-- Restore old last_cleanup_scan_at column\nCOMMENT ON COLUMN lsif_data_docs_search_current_private.last_cleanup_scan_at IS 'The last time outdated records in the lsif_data_docs_search_public table have been cleaned.';\nALTER TABLE lsif_data_docs_search_current_private ALTER COLUMN last_cleanup_scan_at DROP DEFAULT;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1000000027 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000029, + "Name": "apidocs missing fts indexes", + "UpQuery": "-- Drop the btree indexes that we intended to be GIN indexes.\n-- btree indexes are no where near as performant for tsvector indexing.\nDROP INDEX IF EXISTS lsif_data_docs_search_public_search_key_tsv_idx;\nDROP INDEX IF EXISTS lsif_data_docs_search_public_search_key_reverse_tsv_idx;\nDROP INDEX IF EXISTS lsif_data_docs_search_public_label_tsv_idx;\nDROP INDEX IF EXISTS lsif_data_docs_search_public_label_reverse_tsv_idx;\n\nDROP INDEX IF EXISTS lsif_data_docs_search_private_search_key_tsv_idx;\nDROP INDEX IF EXISTS lsif_data_docs_search_private_search_key_reverse_tsv_idx;\nDROP INDEX IF EXISTS lsif_data_docs_search_private_label_tsv_idx;\nDROP INDEX IF EXISTS lsif_data_docs_search_private_label_reverse_tsv_idx;\n\n-- Recreate indexes with GIN instead.\nCREATE INDEX IF NOT EXISTS lsif_data_docs_search_public_search_key_tsv_idx ON lsif_data_docs_search_public USING GIN (search_key_tsv);\nCREATE INDEX IF NOT EXISTS lsif_data_docs_search_public_search_key_reverse_tsv_idx ON lsif_data_docs_search_public USING GIN (search_key_reverse_tsv);\nCREATE INDEX IF NOT EXISTS lsif_data_docs_search_public_label_tsv_idx ON lsif_data_docs_search_public USING GIN (label_tsv);\nCREATE INDEX IF NOT EXISTS lsif_data_docs_search_public_label_reverse_tsv_idx ON lsif_data_docs_search_public USING GIN (label_reverse_tsv);\n\nCREATE INDEX IF NOT EXISTS lsif_data_docs_search_private_search_key_tsv_idx ON lsif_data_docs_search_private USING GIN (search_key_tsv);\nCREATE INDEX IF NOT EXISTS lsif_data_docs_search_private_search_key_reverse_tsv_idx ON lsif_data_docs_search_private USING GIN (search_key_reverse_tsv);\nCREATE INDEX IF NOT EXISTS lsif_data_docs_search_private_label_tsv_idx ON lsif_data_docs_search_private USING GIN (label_tsv);\nCREATE INDEX IF NOT EXISTS lsif_data_docs_search_private_label_reverse_tsv_idx ON lsif_data_docs_search_private USING GIN (label_reverse_tsv);", + "DownQuery": "DROP INDEX IF EXISTS lsif_data_docs_search_public_search_key_tsv_idx;\nDROP INDEX IF EXISTS lsif_data_docs_search_public_search_key_reverse_tsv_idx;\nDROP INDEX IF EXISTS lsif_data_docs_search_public_label_tsv_idx;\nDROP INDEX IF EXISTS lsif_data_docs_search_public_label_reverse_tsv_idx;\n\nDROP INDEX IF EXISTS lsif_data_docs_search_private_search_key_tsv_idx;\nDROP INDEX IF EXISTS lsif_data_docs_search_private_search_key_reverse_tsv_idx;\nDROP INDEX IF EXISTS lsif_data_docs_search_private_label_tsv_idx;\nDROP INDEX IF EXISTS lsif_data_docs_search_private_label_reverse_tsv_idx;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1000000028 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000030, + "Name": "lsif data implementations", + "UpQuery": "CREATE TABLE lsif_data_implementations (\n dump_id INTEGER NOT NULL,\n scheme TEXT NOT NULL,\n identifier TEXT NOT NULL,\n data BYTEA ,\n schema_version INTEGER NOT NULL,\n num_locations INTEGER NOT NULL\n);\n\nCOMMENT ON TABLE lsif_data_implementations IS 'Associates (document, range) pairs with the implementation monikers attached to the range.';\nCOMMENT ON COLUMN lsif_data_implementations.dump_id IS 'The identifier of the associated dump in the lsif_uploads table (state=completed).';\nCOMMENT ON COLUMN lsif_data_implementations.scheme IS 'The moniker scheme.';\nCOMMENT ON COLUMN lsif_data_implementations.identifier IS 'The moniker identifier.';\nCOMMENT ON COLUMN lsif_data_implementations.data IS 'A gob-encoded payload conforming to an array of [LocationData](https://sourcegraph.com/github.com/sourcegraph/sourcegraph@3.26/-/blob/enterprise/lib/codeintel/semantic/types.go#L106:6) types.';\nCOMMENT ON COLUMN lsif_data_implementations.schema_version IS 'The schema version of this row - used to determine presence and encoding of data.';\nCOMMENT ON COLUMN lsif_data_implementations.num_locations IS 'The number of locations stored in the data field.';\n\nALTER TABLE ONLY lsif_data_implementations ADD CONSTRAINT lsif_data_implementations_pkey PRIMARY KEY (dump_id, scheme, identifier);\n\nCREATE INDEX lsif_data_implementations_dump_id_schema_version ON lsif_data_implementations (dump_id, schema_version);\n\nCREATE TABLE lsif_data_implementations_schema_versions (\n dump_id INTEGER NOT NULL,\n min_schema_version INTEGER ,\n max_schema_version INTEGER\n);\n\nCOMMENT ON TABLE lsif_data_implementations_schema_versions IS 'Tracks the range of schema_versions for each upload in the lsif_data_implementations table.';\nCOMMENT ON COLUMN lsif_data_implementations_schema_versions.dump_id IS 'The identifier of the associated dump in the lsif_uploads table.';\nCOMMENT ON COLUMN lsif_data_implementations_schema_versions.min_schema_version IS 'A lower-bound on the `lsif_data_implementations.schema_version` where `lsif_data_implementations.dump_id = dump_id`.';\nCOMMENT ON COLUMN lsif_data_implementations_schema_versions.max_schema_version IS 'An upper-bound on the `lsif_data_implementations.schema_version` where `lsif_data_implementations.dump_id = dump_id`.';\n\nALTER TABLE ONLY lsif_data_implementations_schema_versions ADD CONSTRAINT lsif_data_implementations_schema_versions_pkey PRIMARY KEY (dump_id);\n\nCREATE INDEX lsif_data_implementations_schema_versions_dump_id_schema_version_bounds ON lsif_data_implementations_schema_versions (dump_id, min_schema_version, max_schema_version);\n\n-- On every insert into lsif_data_implementations, we need to make sure we have an associated row in the\n-- lsif_data_implementations_schema_versions table. We do not currently care about cleaning the table up\n-- (we will do this asynchronously).\n--\n-- We use FOR EACH STATEMENT here because we batch insert into this table. Running the trigger per\n-- statement rather than per row will save a ton of extra work. Running over batch inserts lets us\n-- do a GROUP BY on the new table and effectively upsert our new ranges.\n--\n-- Note that the only places where data is _modified_ in this database is during migrations, which\n-- will necessarily update this table's bounds for any migrated index records.\n\nCREATE OR REPLACE FUNCTION update_lsif_data_implementations_schema_versions_insert() RETURNS trigger AS $$ BEGIN\n INSERT INTO\n lsif_data_implementations_schema_versions\n SELECT\n dump_id,\n MIN(schema_version) as min_schema_version,\n MAX(schema_version) as max_schema_version\n FROM\n newtab\n GROUP BY\n dump_id\n ON CONFLICT (dump_id) DO UPDATE SET\n -- Update with min(old_min, new_min) and max(old_max, new_max)\n min_schema_version = LEAST (lsif_data_implementations_schema_versions.min_schema_version, EXCLUDED.min_schema_version),\n max_schema_version = GREATEST(lsif_data_implementations_schema_versions.max_schema_version, EXCLUDED.max_schema_version);\n\n RETURN NULL;\nEND $$ LANGUAGE plpgsql;\n\nCREATE TRIGGER lsif_data_implementations_schema_versions_insert\n AFTER INSERT ON lsif_data_implementations REFERENCING NEW TABLE AS newtab\n FOR EACH STATEMENT EXECUTE PROCEDURE update_lsif_data_implementations_schema_versions_insert();", + "DownQuery": "DROP TABLE lsif_data_implementations_schema_versions;\nDROP TRIGGER lsif_data_implementations_schema_versions_insert ON lsif_data_implementations;\nDROP FUNCTION update_lsif_data_implementations_schema_versions_insert;\n\nDROP TABLE lsif_data_implementations;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1000000029 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + } + ], + "BoundsByRev": { + "3.34.2": { + "RootID": -1000000015, + "LeafIDs": [ + 1000000030 + ], + "PreCreation": false + } + } + }, + "frontend": { + "Definitions": [ + { + "ID": -1528395834, + "Name": "squashed migrations (privileged)", + "UpQuery": "CREATE EXTENSION IF NOT EXISTS citext;\n\nCOMMENT ON EXTENSION citext IS 'data type for case-insensitive character strings';\n\nCREATE EXTENSION IF NOT EXISTS hstore;\n\nCOMMENT ON EXTENSION hstore IS 'data type for storing sets of (key, value) pairs';\n\nCREATE EXTENSION IF NOT EXISTS intarray;\n\nCOMMENT ON EXTENSION intarray IS 'functions, operators, and index support for 1-D arrays of integers';\n\nCREATE EXTENSION IF NOT EXISTS pg_stat_statements;\n\nCOMMENT ON EXTENSION pg_stat_statements IS 'track execution statistics of all SQL statements executed';\n\nCREATE EXTENSION IF NOT EXISTS pg_trgm;\n\nCOMMENT ON EXTENSION pg_trgm IS 'text similarity measurement and index searching based on trigrams';", + "DownQuery": "", + "Privileged": true, + "NonIdempotent": false, + "Parents": null, + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395834, + "Name": "squashed migrations", + "UpQuery": "CREATE TYPE cm_email_priority AS ENUM (\n 'NORMAL',\n 'CRITICAL'\n);\n\nCREATE TYPE critical_or_site AS ENUM (\n 'critical',\n 'site'\n);\n\nCREATE TYPE feature_flag_type AS ENUM (\n 'bool',\n 'rollout'\n);\n\nCREATE TYPE lsif_index_state AS ENUM (\n 'queued',\n 'processing',\n 'completed',\n 'errored',\n 'failed'\n);\n\nCREATE TYPE lsif_upload_state AS ENUM (\n 'uploading',\n 'queued',\n 'processing',\n 'completed',\n 'errored',\n 'deleted',\n 'failed'\n);\n\nCREATE FUNCTION delete_batch_change_reference_on_changesets() RETURNS trigger\n LANGUAGE plpgsql\n AS $$\n BEGIN\n UPDATE\n changesets\n SET\n batch_change_ids = changesets.batch_change_ids - OLD.id::text\n WHERE\n changesets.batch_change_ids ? OLD.id::text;\n\n RETURN OLD;\n END;\n$$;\n\nCREATE FUNCTION delete_repo_ref_on_external_service_repos() RETURNS trigger\n LANGUAGE plpgsql\n AS $$\n BEGIN\n -- if a repo is soft-deleted, delete every row that references that repo\n IF (OLD.deleted_at IS NULL AND NEW.deleted_at IS NOT NULL) THEN\n DELETE FROM\n external_service_repos\n WHERE\n repo_id = OLD.id;\n END IF;\n\n RETURN OLD;\n END;\n$$;\n\nCREATE FUNCTION invalidate_session_for_userid_on_password_change() RETURNS trigger\n LANGUAGE plpgsql\n AS $$\n BEGIN\n IF OLD.passwd != NEW.passwd THEN\n NEW.invalidated_sessions_at = now() + (1 * interval '1 second');\n RETURN NEW;\n END IF;\n RETURN NEW;\n END;\n$$;\n\nCREATE FUNCTION soft_delete_orphan_repo_by_external_service_repos() RETURNS void\n LANGUAGE plpgsql\n AS $$\nBEGIN\n -- When an external service is soft or hard-deleted,\n -- performs a clean up to soft-delete orphan repositories.\n UPDATE\n repo\n SET\n name = soft_deleted_repository_name(name),\n deleted_at = transaction_timestamp()\n WHERE\n deleted_at IS NULL\n AND NOT EXISTS (\n SELECT FROM external_service_repos WHERE repo_id = repo.id\n );\nEND;\n$$;\n\nCREATE FUNCTION soft_delete_user_reference_on_external_service() RETURNS trigger\n LANGUAGE plpgsql\n AS $$\nBEGIN\n -- If a user is soft-deleted, delete every row that references that user\n IF (OLD.deleted_at IS NULL AND NEW.deleted_at IS NOT NULL) THEN\n UPDATE external_services\n SET deleted_at = NOW()\n WHERE namespace_user_id = OLD.id;\n END IF;\n\n RETURN OLD;\nEND;\n$$;\n\nCREATE FUNCTION soft_deleted_repository_name(name text) RETURNS text\n LANGUAGE plpgsql STRICT\n AS $$\nBEGIN\n RETURN 'DELETED-' || extract(epoch from transaction_timestamp()) || '-' || name;\nEND;\n$$;\n\nCREATE FUNCTION versions_insert_row_trigger() RETURNS trigger\n LANGUAGE plpgsql\n AS $$\nBEGIN\n NEW.first_version = NEW.version;\n RETURN NEW;\nEND $$;\n\nCREATE TABLE access_tokens (\n id bigint NOT NULL,\n subject_user_id integer NOT NULL,\n value_sha256 bytea NOT NULL,\n note text NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n last_used_at timestamp with time zone,\n deleted_at timestamp with time zone,\n creator_user_id integer NOT NULL,\n scopes text[] NOT NULL\n);\n\nCREATE SEQUENCE access_tokens_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE access_tokens_id_seq OWNED BY access_tokens.id;\n\nCREATE TABLE batch_changes (\n id bigint NOT NULL,\n name text NOT NULL,\n description text,\n initial_applier_id integer,\n namespace_user_id integer,\n namespace_org_id integer,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n closed_at timestamp with time zone,\n batch_spec_id bigint NOT NULL,\n last_applier_id bigint,\n last_applied_at timestamp with time zone NOT NULL,\n CONSTRAINT batch_changes_has_1_namespace CHECK (((namespace_user_id IS NULL) \u003c\u003e (namespace_org_id IS NULL))),\n CONSTRAINT batch_changes_name_not_blank CHECK ((name \u003c\u003e ''::text))\n);\n\nCREATE SEQUENCE batch_changes_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE batch_changes_id_seq OWNED BY batch_changes.id;\n\nCREATE TABLE batch_changes_site_credentials (\n id bigint NOT NULL,\n external_service_type text NOT NULL,\n external_service_id text NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n credential bytea NOT NULL,\n encryption_key_id text DEFAULT ''::text NOT NULL\n);\n\nCREATE SEQUENCE batch_changes_site_credentials_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE batch_changes_site_credentials_id_seq OWNED BY batch_changes_site_credentials.id;\n\nCREATE TABLE batch_specs (\n id bigint NOT NULL,\n rand_id text NOT NULL,\n raw_spec text NOT NULL,\n spec jsonb DEFAULT '{}'::jsonb NOT NULL,\n namespace_user_id integer,\n namespace_org_id integer,\n user_id integer,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n CONSTRAINT batch_specs_has_1_namespace CHECK (((namespace_user_id IS NULL) \u003c\u003e (namespace_org_id IS NULL)))\n);\n\nCREATE SEQUENCE batch_specs_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE batch_specs_id_seq OWNED BY batch_specs.id;\n\nCREATE TABLE changeset_specs (\n id bigint NOT NULL,\n rand_id text NOT NULL,\n raw_spec text NOT NULL,\n spec jsonb DEFAULT '{}'::jsonb NOT NULL,\n batch_spec_id bigint,\n repo_id integer NOT NULL,\n user_id integer,\n diff_stat_added integer,\n diff_stat_changed integer,\n diff_stat_deleted integer,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n head_ref text,\n title text,\n external_id text\n);\n\nCREATE TABLE changesets (\n id bigint NOT NULL,\n batch_change_ids jsonb DEFAULT '{}'::jsonb NOT NULL,\n repo_id integer NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n metadata jsonb DEFAULT '{}'::jsonb,\n external_id text,\n external_service_type text NOT NULL,\n external_deleted_at timestamp with time zone,\n external_branch text,\n external_updated_at timestamp with time zone,\n external_state text,\n external_review_state text,\n external_check_state text,\n diff_stat_added integer,\n diff_stat_changed integer,\n diff_stat_deleted integer,\n sync_state jsonb DEFAULT '{}'::jsonb NOT NULL,\n current_spec_id bigint,\n previous_spec_id bigint,\n publication_state text DEFAULT 'UNPUBLISHED'::text,\n owned_by_batch_change_id bigint,\n reconciler_state text DEFAULT 'queued'::text,\n failure_message text,\n started_at timestamp with time zone,\n finished_at timestamp with time zone,\n process_after timestamp with time zone,\n num_resets integer DEFAULT 0 NOT NULL,\n closing boolean DEFAULT false NOT NULL,\n num_failures integer DEFAULT 0 NOT NULL,\n log_contents text,\n execution_logs json[],\n syncer_error text,\n external_title text,\n CONSTRAINT changesets_batch_change_ids_check CHECK ((jsonb_typeof(batch_change_ids) = 'object'::text)),\n CONSTRAINT changesets_external_id_check CHECK ((external_id \u003c\u003e ''::text)),\n CONSTRAINT changesets_external_service_type_not_blank CHECK ((external_service_type \u003c\u003e ''::text)),\n CONSTRAINT changesets_metadata_check CHECK ((jsonb_typeof(metadata) = 'object'::text)),\n CONSTRAINT external_branch_ref_prefix CHECK ((external_branch ~~ 'refs/heads/%'::text))\n);\n\nCOMMENT ON COLUMN changesets.external_title IS 'Normalized property generated on save using Changeset.Title()';\n\nCREATE TABLE repo (\n id integer NOT NULL,\n name citext NOT NULL,\n description text,\n fork boolean,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone,\n external_id text,\n external_service_type text,\n external_service_id text,\n archived boolean DEFAULT false NOT NULL,\n uri citext,\n deleted_at timestamp with time zone,\n metadata jsonb DEFAULT '{}'::jsonb NOT NULL,\n private boolean DEFAULT false NOT NULL,\n cloned boolean DEFAULT false NOT NULL,\n stars integer,\n CONSTRAINT check_name_nonempty CHECK ((name OPERATOR(\u003c\u003e) ''::citext)),\n CONSTRAINT repo_metadata_check CHECK ((jsonb_typeof(metadata) = 'object'::text))\n);\n\nCREATE VIEW branch_changeset_specs_and_changesets AS\n SELECT changeset_specs.id AS changeset_spec_id,\n COALESCE(changesets.id, (0)::bigint) AS changeset_id,\n changeset_specs.repo_id,\n changeset_specs.batch_spec_id,\n changesets.owned_by_batch_change_id AS owner_batch_change_id,\n repo.name AS repo_name,\n changeset_specs.title AS changeset_name,\n changesets.external_state,\n changesets.publication_state,\n changesets.reconciler_state\n FROM ((changeset_specs\n LEFT JOIN changesets ON (((changesets.repo_id = changeset_specs.repo_id) AND (changesets.current_spec_id IS NOT NULL) AND (EXISTS ( SELECT 1\n FROM changeset_specs changeset_specs_1\n WHERE ((changeset_specs_1.id = changesets.current_spec_id) AND (changeset_specs_1.head_ref = changeset_specs.head_ref)))))))\n JOIN repo ON ((changeset_specs.repo_id = repo.id)))\n WHERE ((changeset_specs.external_id IS NULL) AND (repo.deleted_at IS NULL));\n\nCREATE TABLE changeset_events (\n id bigint NOT NULL,\n changeset_id bigint NOT NULL,\n kind text NOT NULL,\n key text NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n metadata jsonb DEFAULT '{}'::jsonb NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n CONSTRAINT changeset_events_key_check CHECK ((key \u003c\u003e ''::text)),\n CONSTRAINT changeset_events_kind_check CHECK ((kind \u003c\u003e ''::text)),\n CONSTRAINT changeset_events_metadata_check CHECK ((jsonb_typeof(metadata) = 'object'::text))\n);\n\nCREATE SEQUENCE changeset_events_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE changeset_events_id_seq OWNED BY changeset_events.id;\n\nCREATE TABLE changeset_jobs (\n id bigint NOT NULL,\n bulk_group text NOT NULL,\n user_id integer NOT NULL,\n batch_change_id integer NOT NULL,\n changeset_id integer NOT NULL,\n job_type text NOT NULL,\n payload jsonb DEFAULT '{}'::jsonb,\n state text DEFAULT 'queued'::text,\n failure_message text,\n started_at timestamp with time zone,\n finished_at timestamp with time zone,\n process_after timestamp with time zone,\n num_resets integer DEFAULT 0 NOT NULL,\n num_failures integer DEFAULT 0 NOT NULL,\n execution_logs json[],\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n CONSTRAINT changeset_jobs_payload_check CHECK ((jsonb_typeof(payload) = 'object'::text))\n);\n\nCREATE SEQUENCE changeset_jobs_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE changeset_jobs_id_seq OWNED BY changeset_jobs.id;\n\nCREATE SEQUENCE changeset_specs_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE changeset_specs_id_seq OWNED BY changeset_specs.id;\n\nCREATE SEQUENCE changesets_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE changesets_id_seq OWNED BY changesets.id;\n\nCREATE TABLE cm_action_jobs (\n id integer NOT NULL,\n email bigint NOT NULL,\n state text DEFAULT 'queued'::text,\n failure_message text,\n started_at timestamp with time zone,\n finished_at timestamp with time zone,\n process_after timestamp with time zone,\n num_resets integer DEFAULT 0 NOT NULL,\n num_failures integer DEFAULT 0 NOT NULL,\n log_contents text,\n trigger_event integer\n);\n\nCREATE SEQUENCE cm_action_jobs_id_seq\n AS integer\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE cm_action_jobs_id_seq OWNED BY cm_action_jobs.id;\n\nCREATE TABLE cm_emails (\n id bigint NOT NULL,\n monitor bigint NOT NULL,\n enabled boolean NOT NULL,\n priority cm_email_priority NOT NULL,\n header text NOT NULL,\n created_by integer NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n changed_by integer NOT NULL,\n changed_at timestamp with time zone DEFAULT now() NOT NULL\n);\n\nCREATE SEQUENCE cm_emails_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE cm_emails_id_seq OWNED BY cm_emails.id;\n\nCREATE TABLE cm_monitors (\n id bigint NOT NULL,\n created_by integer NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n description text NOT NULL,\n changed_at timestamp with time zone DEFAULT now() NOT NULL,\n changed_by integer NOT NULL,\n enabled boolean DEFAULT true NOT NULL,\n namespace_user_id integer,\n namespace_org_id integer\n);\n\nCREATE SEQUENCE cm_monitors_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE cm_monitors_id_seq OWNED BY cm_monitors.id;\n\nCREATE TABLE cm_queries (\n id bigint NOT NULL,\n monitor bigint NOT NULL,\n query text NOT NULL,\n created_by integer NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n changed_by integer NOT NULL,\n changed_at timestamp with time zone DEFAULT now() NOT NULL,\n next_run timestamp with time zone DEFAULT now(),\n latest_result timestamp with time zone\n);\n\nCREATE SEQUENCE cm_queries_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE cm_queries_id_seq OWNED BY cm_queries.id;\n\nCREATE TABLE cm_recipients (\n id bigint NOT NULL,\n email bigint NOT NULL,\n namespace_user_id integer,\n namespace_org_id integer\n);\n\nCREATE SEQUENCE cm_recipients_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE cm_recipients_id_seq OWNED BY cm_recipients.id;\n\nCREATE TABLE cm_trigger_jobs (\n id integer NOT NULL,\n query bigint NOT NULL,\n state text DEFAULT 'queued'::text,\n failure_message text,\n started_at timestamp with time zone,\n finished_at timestamp with time zone,\n process_after timestamp with time zone,\n num_resets integer DEFAULT 0 NOT NULL,\n num_failures integer DEFAULT 0 NOT NULL,\n log_contents text,\n query_string text,\n results boolean,\n num_results integer\n);\n\nCREATE SEQUENCE cm_trigger_jobs_id_seq\n AS integer\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE cm_trigger_jobs_id_seq OWNED BY cm_trigger_jobs.id;\n\nCREATE TABLE critical_and_site_config (\n id integer NOT NULL,\n type critical_or_site NOT NULL,\n contents text NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL\n);\n\nCREATE SEQUENCE critical_and_site_config_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE critical_and_site_config_id_seq OWNED BY critical_and_site_config.id;\n\nCREATE TABLE default_repos (\n repo_id integer NOT NULL\n);\n\nCREATE TABLE discussion_comments (\n id bigint NOT NULL,\n thread_id bigint NOT NULL,\n author_user_id integer NOT NULL,\n contents text NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n deleted_at timestamp with time zone,\n reports text[] DEFAULT '{}'::text[] NOT NULL\n);\n\nCREATE SEQUENCE discussion_comments_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE discussion_comments_id_seq OWNED BY discussion_comments.id;\n\nCREATE TABLE discussion_mail_reply_tokens (\n token text NOT NULL,\n user_id integer NOT NULL,\n thread_id bigint NOT NULL,\n deleted_at timestamp with time zone\n);\n\nCREATE TABLE discussion_threads (\n id bigint NOT NULL,\n author_user_id integer NOT NULL,\n title text,\n target_repo_id bigint,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n archived_at timestamp with time zone,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n deleted_at timestamp with time zone\n);\n\nCREATE SEQUENCE discussion_threads_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE discussion_threads_id_seq OWNED BY discussion_threads.id;\n\nCREATE TABLE discussion_threads_target_repo (\n id bigint NOT NULL,\n thread_id bigint NOT NULL,\n repo_id integer NOT NULL,\n path text,\n branch text,\n revision text,\n start_line integer,\n end_line integer,\n start_character integer,\n end_character integer,\n lines_before text,\n lines text,\n lines_after text\n);\n\nCREATE SEQUENCE discussion_threads_target_repo_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE discussion_threads_target_repo_id_seq OWNED BY discussion_threads_target_repo.id;\n\nCREATE TABLE event_logs (\n id bigint NOT NULL,\n name text NOT NULL,\n url text NOT NULL,\n user_id integer NOT NULL,\n anonymous_user_id text NOT NULL,\n source text NOT NULL,\n argument jsonb NOT NULL,\n version text NOT NULL,\n \"timestamp\" timestamp with time zone NOT NULL,\n feature_flags jsonb,\n CONSTRAINT event_logs_check_has_user CHECK ((((user_id = 0) AND (anonymous_user_id \u003c\u003e ''::text)) OR ((user_id \u003c\u003e 0) AND (anonymous_user_id = ''::text)) OR ((user_id \u003c\u003e 0) AND (anonymous_user_id \u003c\u003e ''::text)))),\n CONSTRAINT event_logs_check_name_not_empty CHECK ((name \u003c\u003e ''::text)),\n CONSTRAINT event_logs_check_source_not_empty CHECK ((source \u003c\u003e ''::text)),\n CONSTRAINT event_logs_check_version_not_empty CHECK ((version \u003c\u003e ''::text))\n);\n\nCREATE SEQUENCE event_logs_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE event_logs_id_seq OWNED BY event_logs.id;\n\nCREATE TABLE external_service_repos (\n external_service_id bigint NOT NULL,\n repo_id integer NOT NULL,\n clone_url text NOT NULL,\n user_id integer\n);\n\nCREATE SEQUENCE external_service_sync_jobs_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nCREATE TABLE external_service_sync_jobs (\n id integer DEFAULT nextval('external_service_sync_jobs_id_seq'::regclass) NOT NULL,\n state text DEFAULT 'queued'::text NOT NULL,\n failure_message text,\n started_at timestamp with time zone,\n finished_at timestamp with time zone,\n process_after timestamp with time zone,\n num_resets integer DEFAULT 0 NOT NULL,\n external_service_id bigint,\n num_failures integer DEFAULT 0 NOT NULL,\n log_contents text,\n execution_logs json[]\n);\n\nCREATE TABLE external_services (\n id bigint NOT NULL,\n kind text NOT NULL,\n display_name text NOT NULL,\n config text NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n deleted_at timestamp with time zone,\n last_sync_at timestamp with time zone,\n next_sync_at timestamp with time zone,\n namespace_user_id integer,\n unrestricted boolean DEFAULT false NOT NULL,\n cloud_default boolean DEFAULT false NOT NULL,\n encryption_key_id text DEFAULT ''::text NOT NULL,\n CONSTRAINT check_non_empty_config CHECK ((btrim(config) \u003c\u003e ''::text))\n);\n\nCREATE VIEW external_service_sync_jobs_with_next_sync_at AS\n SELECT j.id,\n j.state,\n j.failure_message,\n j.started_at,\n j.finished_at,\n j.process_after,\n j.num_resets,\n j.num_failures,\n j.execution_logs,\n j.external_service_id,\n e.next_sync_at\n FROM (external_services e\n JOIN external_service_sync_jobs j ON ((e.id = j.external_service_id)));\n\nCREATE SEQUENCE external_services_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE external_services_id_seq OWNED BY external_services.id;\n\nCREATE TABLE feature_flag_overrides (\n namespace_org_id integer,\n namespace_user_id integer,\n flag_name text NOT NULL,\n flag_value boolean NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n deleted_at timestamp with time zone,\n CONSTRAINT feature_flag_overrides_has_org_or_user_id CHECK (((namespace_org_id IS NOT NULL) OR (namespace_user_id IS NOT NULL)))\n);\n\nCREATE TABLE feature_flags (\n flag_name text NOT NULL,\n flag_type feature_flag_type NOT NULL,\n bool_value boolean,\n rollout integer,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n deleted_at timestamp with time zone,\n CONSTRAINT feature_flags_rollout_check CHECK (((rollout \u003e= 0) AND (rollout \u003c= 10000))),\n CONSTRAINT required_bool_fields CHECK ((1 =\nCASE\n WHEN ((flag_type = 'bool'::feature_flag_type) AND (bool_value IS NULL)) THEN 0\n WHEN ((flag_type \u003c\u003e 'bool'::feature_flag_type) AND (bool_value IS NOT NULL)) THEN 0\n ELSE 1\nEND)),\n CONSTRAINT required_rollout_fields CHECK ((1 =\nCASE\n WHEN ((flag_type = 'rollout'::feature_flag_type) AND (rollout IS NULL)) THEN 0\n WHEN ((flag_type \u003c\u003e 'rollout'::feature_flag_type) AND (rollout IS NOT NULL)) THEN 0\n ELSE 1\nEND))\n);\n\nCOMMENT ON COLUMN feature_flags.bool_value IS 'Bool value only defined when flag_type is bool';\n\nCOMMENT ON COLUMN feature_flags.rollout IS 'Rollout only defined when flag_type is rollout. Increments of 0.01%';\n\nCOMMENT ON CONSTRAINT required_bool_fields ON feature_flags IS 'Checks that bool_value is set IFF flag_type = bool';\n\nCOMMENT ON CONSTRAINT required_rollout_fields ON feature_flags IS 'Checks that rollout is set IFF flag_type = rollout';\n\nCREATE TABLE gitserver_repos (\n repo_id integer NOT NULL,\n clone_status text DEFAULT 'not_cloned'::text NOT NULL,\n last_external_service bigint,\n shard_id text NOT NULL,\n last_error text,\n updated_at timestamp with time zone DEFAULT now() NOT NULL\n);\n\nCREATE TABLE global_state (\n site_id uuid NOT NULL,\n initialized boolean DEFAULT false NOT NULL\n);\n\nCREATE TABLE insights_query_runner_jobs (\n id integer NOT NULL,\n series_id text NOT NULL,\n search_query text NOT NULL,\n state text DEFAULT 'queued'::text,\n failure_message text,\n started_at timestamp with time zone,\n finished_at timestamp with time zone,\n process_after timestamp with time zone,\n num_resets integer DEFAULT 0 NOT NULL,\n num_failures integer DEFAULT 0 NOT NULL,\n execution_logs json[],\n record_time timestamp with time zone\n);\n\nCOMMENT ON TABLE insights_query_runner_jobs IS 'See [enterprise/internal/insights/background/queryrunner/worker.go:Job](https://sourcegraph.com/search?q=repo:%5Egithub%5C.com/sourcegraph/sourcegraph%24+file:enterprise/internal/insights/background/queryrunner/worker.go+type+Job\u0026patternType=literal)';\n\nCREATE SEQUENCE insights_query_runner_jobs_id_seq\n AS integer\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE insights_query_runner_jobs_id_seq OWNED BY insights_query_runner_jobs.id;\n\nCREATE TABLE lsif_dependency_indexing_jobs (\n id integer NOT NULL,\n state text DEFAULT 'queued'::text NOT NULL,\n failure_message text,\n queued_at timestamp with time zone DEFAULT now() NOT NULL,\n started_at timestamp with time zone,\n finished_at timestamp with time zone,\n process_after timestamp with time zone,\n num_resets integer DEFAULT 0 NOT NULL,\n num_failures integer DEFAULT 0 NOT NULL,\n execution_logs json[],\n upload_id integer\n);\n\nCOMMENT ON TABLE lsif_dependency_indexing_jobs IS 'Tracks jobs that scan imports of indexes to schedule auto-index jobs.';\n\nCOMMENT ON COLUMN lsif_dependency_indexing_jobs.upload_id IS 'The identifier of the triggering upload record.';\n\nCREATE SEQUENCE lsif_dependency_indexing_jobs_id_seq\n AS integer\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE lsif_dependency_indexing_jobs_id_seq OWNED BY lsif_dependency_indexing_jobs.id;\n\nCREATE TABLE lsif_dirty_repositories (\n repository_id integer NOT NULL,\n dirty_token integer NOT NULL,\n update_token integer NOT NULL,\n updated_at timestamp with time zone\n);\n\nCOMMENT ON TABLE lsif_dirty_repositories IS 'Stores whether or not the nearest upload data for a repository is out of date (when update_token \u003e dirty_token).';\n\nCOMMENT ON COLUMN lsif_dirty_repositories.dirty_token IS 'Set to the value of update_token visible to the transaction that updates the commit graph. Updates of dirty_token during this time will cause a second update.';\n\nCOMMENT ON COLUMN lsif_dirty_repositories.update_token IS 'This value is incremented on each request to update the commit graph for the repository.';\n\nCOMMENT ON COLUMN lsif_dirty_repositories.updated_at IS 'The time the update_token value was last updated.';\n\nCREATE TABLE lsif_uploads (\n id integer NOT NULL,\n commit text NOT NULL,\n root text DEFAULT ''::text NOT NULL,\n uploaded_at timestamp with time zone DEFAULT now() NOT NULL,\n state text DEFAULT 'queued'::text NOT NULL,\n failure_message text,\n started_at timestamp with time zone,\n finished_at timestamp with time zone,\n repository_id integer NOT NULL,\n indexer text NOT NULL,\n num_parts integer NOT NULL,\n uploaded_parts integer[] NOT NULL,\n process_after timestamp with time zone,\n num_resets integer DEFAULT 0 NOT NULL,\n upload_size bigint,\n num_failures integer DEFAULT 0 NOT NULL,\n associated_index_id bigint,\n committed_at timestamp with time zone,\n commit_last_checked_at timestamp with time zone,\n CONSTRAINT lsif_uploads_commit_valid_chars CHECK ((commit ~ '^[a-z0-9]{40}$'::text))\n);\n\nCOMMENT ON TABLE lsif_uploads IS 'Stores metadata about an LSIF index uploaded by a user.';\n\nCOMMENT ON COLUMN lsif_uploads.id IS 'Used as a logical foreign key with the (disjoint) codeintel database.';\n\nCOMMENT ON COLUMN lsif_uploads.commit IS 'A 40-char revhash. Note that this commit may not be resolvable in the future.';\n\nCOMMENT ON COLUMN lsif_uploads.root IS 'The path for which the index can resolve code intelligence relative to the repository root.';\n\nCOMMENT ON COLUMN lsif_uploads.indexer IS 'The name of the indexer that produced the index file. If not supplied by the user it will be pulled from the index metadata.';\n\nCOMMENT ON COLUMN lsif_uploads.num_parts IS 'The number of parts src-cli split the upload file into.';\n\nCOMMENT ON COLUMN lsif_uploads.uploaded_parts IS 'The index of parts that have been successfully uploaded.';\n\nCOMMENT ON COLUMN lsif_uploads.upload_size IS 'The size of the index file (in bytes).';\n\nCREATE VIEW lsif_dumps AS\n SELECT u.id,\n u.commit,\n u.root,\n u.uploaded_at,\n u.state,\n u.failure_message,\n u.started_at,\n u.finished_at,\n u.repository_id,\n u.indexer,\n u.num_parts,\n u.uploaded_parts,\n u.process_after,\n u.num_resets,\n u.upload_size,\n u.num_failures,\n u.associated_index_id,\n u.finished_at AS processed_at\n FROM lsif_uploads u\n WHERE (u.state = 'completed'::text);\n\nCREATE SEQUENCE lsif_dumps_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE lsif_dumps_id_seq OWNED BY lsif_uploads.id;\n\nCREATE VIEW lsif_dumps_with_repository_name AS\n SELECT u.id,\n u.commit,\n u.root,\n u.uploaded_at,\n u.state,\n u.failure_message,\n u.started_at,\n u.finished_at,\n u.repository_id,\n u.indexer,\n u.num_parts,\n u.uploaded_parts,\n u.process_after,\n u.num_resets,\n u.upload_size,\n u.num_failures,\n u.associated_index_id,\n u.processed_at,\n r.name AS repository_name\n FROM (lsif_dumps u\n JOIN repo r ON ((r.id = u.repository_id)))\n WHERE (r.deleted_at IS NULL);\n\nCREATE TABLE lsif_index_configuration (\n id bigint NOT NULL,\n repository_id integer NOT NULL,\n data bytea NOT NULL,\n autoindex_enabled boolean DEFAULT true NOT NULL\n);\n\nCOMMENT ON TABLE lsif_index_configuration IS 'Stores the configuration used for code intel index jobs for a repository.';\n\nCOMMENT ON COLUMN lsif_index_configuration.data IS 'The raw user-supplied [configuration](https://sourcegraph.com/github.com/sourcegraph/sourcegraph@3.23/-/blob/enterprise/internal/codeintel/autoindex/config/types.go#L3:6) (encoded in JSONC).';\n\nCOMMENT ON COLUMN lsif_index_configuration.autoindex_enabled IS 'Whether or not auto-indexing should be attempted on this repo. Index jobs may be inferred from the repository contents if data is empty.';\n\nCREATE SEQUENCE lsif_index_configuration_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE lsif_index_configuration_id_seq OWNED BY lsif_index_configuration.id;\n\nCREATE TABLE lsif_indexable_repositories (\n id integer NOT NULL,\n repository_id integer NOT NULL,\n search_count integer DEFAULT 0 NOT NULL,\n precise_count integer DEFAULT 0 NOT NULL,\n last_index_enqueued_at timestamp with time zone,\n last_updated_at timestamp with time zone DEFAULT now() NOT NULL,\n enabled boolean\n);\n\nCOMMENT ON TABLE lsif_indexable_repositories IS 'Stores the number of code intel events for repositories. Used for auto-index scheduling heursitics Sourcegraph Cloud.';\n\nCOMMENT ON COLUMN lsif_indexable_repositories.search_count IS 'The number of search-based code intel events for the repository in the past week.';\n\nCOMMENT ON COLUMN lsif_indexable_repositories.precise_count IS 'The number of precise code intel events for the repository in the past week.';\n\nCOMMENT ON COLUMN lsif_indexable_repositories.last_index_enqueued_at IS 'The last time an index for the repository was enqueued (for basic rate limiting).';\n\nCOMMENT ON COLUMN lsif_indexable_repositories.last_updated_at IS 'The last time the event counts were updated for this repository.';\n\nCOMMENT ON COLUMN lsif_indexable_repositories.enabled IS '**Column unused.**';\n\nCREATE SEQUENCE lsif_indexable_repositories_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE lsif_indexable_repositories_id_seq OWNED BY lsif_indexable_repositories.id;\n\nCREATE TABLE lsif_indexes (\n id bigint NOT NULL,\n commit text NOT NULL,\n queued_at timestamp with time zone DEFAULT now() NOT NULL,\n state text DEFAULT 'queued'::text NOT NULL,\n failure_message text,\n started_at timestamp with time zone,\n finished_at timestamp with time zone,\n repository_id integer NOT NULL,\n process_after timestamp with time zone,\n num_resets integer DEFAULT 0 NOT NULL,\n num_failures integer DEFAULT 0 NOT NULL,\n docker_steps jsonb[] NOT NULL,\n root text NOT NULL,\n indexer text NOT NULL,\n indexer_args text[] NOT NULL,\n outfile text NOT NULL,\n log_contents text,\n execution_logs json[],\n local_steps text[] NOT NULL,\n commit_last_checked_at timestamp with time zone,\n CONSTRAINT lsif_uploads_commit_valid_chars CHECK ((commit ~ '^[a-z0-9]{40}$'::text))\n);\n\nCOMMENT ON TABLE lsif_indexes IS 'Stores metadata about a code intel index job.';\n\nCOMMENT ON COLUMN lsif_indexes.commit IS 'A 40-char revhash. Note that this commit may not be resolvable in the future.';\n\nCOMMENT ON COLUMN lsif_indexes.docker_steps IS 'An array of pre-index [steps](https://sourcegraph.com/github.com/sourcegraph/sourcegraph@3.23/-/blob/enterprise/internal/codeintel/stores/dbstore/docker_step.go#L9:6) to run.';\n\nCOMMENT ON COLUMN lsif_indexes.root IS 'The working directory of the indexer image relative to the repository root.';\n\nCOMMENT ON COLUMN lsif_indexes.indexer IS 'The docker image used to run the index command (e.g. sourcegraph/lsif-go).';\n\nCOMMENT ON COLUMN lsif_indexes.indexer_args IS 'The command run inside the indexer image to produce the index file (e.g. [''lsif-node'', ''-p'', ''.''])';\n\nCOMMENT ON COLUMN lsif_indexes.outfile IS 'The path to the index file produced by the index command relative to the working directory.';\n\nCOMMENT ON COLUMN lsif_indexes.log_contents IS '**Column deprecated in favor of execution_logs.**';\n\nCOMMENT ON COLUMN lsif_indexes.execution_logs IS 'An array of [log entries](https://sourcegraph.com/github.com/sourcegraph/sourcegraph@3.23/-/blob/internal/workerutil/store.go#L48:6) (encoded as JSON) from the most recent execution.';\n\nCOMMENT ON COLUMN lsif_indexes.local_steps IS 'A list of commands to run inside the indexer image prior to running the indexer command.';\n\nCREATE SEQUENCE lsif_indexes_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE lsif_indexes_id_seq OWNED BY lsif_indexes.id;\n\nCREATE VIEW lsif_indexes_with_repository_name AS\n SELECT u.id,\n u.commit,\n u.queued_at,\n u.state,\n u.failure_message,\n u.started_at,\n u.finished_at,\n u.repository_id,\n u.process_after,\n u.num_resets,\n u.num_failures,\n u.docker_steps,\n u.root,\n u.indexer,\n u.indexer_args,\n u.outfile,\n u.log_contents,\n u.execution_logs,\n u.local_steps,\n r.name AS repository_name\n FROM (lsif_indexes u\n JOIN repo r ON ((r.id = u.repository_id)))\n WHERE (r.deleted_at IS NULL);\n\nCREATE TABLE lsif_nearest_uploads (\n repository_id integer NOT NULL,\n commit_bytea bytea NOT NULL,\n uploads jsonb NOT NULL\n);\n\nCOMMENT ON TABLE lsif_nearest_uploads IS 'Associates commits with the complete set of uploads visible from that commit. Every commit with upload data is present in this table.';\n\nCOMMENT ON COLUMN lsif_nearest_uploads.commit_bytea IS 'A 40-char revhash. Note that this commit may not be resolvable in the future.';\n\nCOMMENT ON COLUMN lsif_nearest_uploads.uploads IS 'Encodes an {upload_id =\u003e distance} map that includes an entry for every upload visible from the commit. There is always at least one entry with a distance of zero.';\n\nCREATE TABLE lsif_nearest_uploads_links (\n repository_id integer NOT NULL,\n commit_bytea bytea NOT NULL,\n ancestor_commit_bytea bytea NOT NULL,\n distance integer NOT NULL\n);\n\nCOMMENT ON TABLE lsif_nearest_uploads_links IS 'Associates commits with the closest ancestor commit with usable upload data. Together, this table and lsif_nearest_uploads cover all commits with resolvable code intelligence.';\n\nCOMMENT ON COLUMN lsif_nearest_uploads_links.commit_bytea IS 'A 40-char revhash. Note that this commit may not be resolvable in the future.';\n\nCOMMENT ON COLUMN lsif_nearest_uploads_links.ancestor_commit_bytea IS 'The 40-char revhash of the ancestor. Note that this commit may not be resolvable in the future.';\n\nCOMMENT ON COLUMN lsif_nearest_uploads_links.distance IS 'The distance bewteen the commits. Parent = 1, Grandparent = 2, etc.';\n\nCREATE TABLE lsif_packages (\n id integer NOT NULL,\n scheme text NOT NULL,\n name text NOT NULL,\n version text,\n dump_id integer NOT NULL\n);\n\nCOMMENT ON TABLE lsif_packages IS 'Associates an upload with the set of packages they provide within a given packages management scheme.';\n\nCOMMENT ON COLUMN lsif_packages.scheme IS 'The (export) moniker scheme.';\n\nCOMMENT ON COLUMN lsif_packages.name IS 'The package name.';\n\nCOMMENT ON COLUMN lsif_packages.version IS 'The package version.';\n\nCOMMENT ON COLUMN lsif_packages.dump_id IS 'The identifier of the upload that provides the package.';\n\nCREATE SEQUENCE lsif_packages_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE lsif_packages_id_seq OWNED BY lsif_packages.id;\n\nCREATE TABLE lsif_references (\n id integer NOT NULL,\n scheme text NOT NULL,\n name text NOT NULL,\n version text,\n filter bytea NOT NULL,\n dump_id integer NOT NULL\n);\n\nCOMMENT ON TABLE lsif_references IS 'Associates an upload with the set of packages they require within a given packages management scheme.';\n\nCOMMENT ON COLUMN lsif_references.scheme IS 'The (import) moniker scheme.';\n\nCOMMENT ON COLUMN lsif_references.name IS 'The package name.';\n\nCOMMENT ON COLUMN lsif_references.version IS 'The package version.';\n\nCOMMENT ON COLUMN lsif_references.filter IS 'A [bloom filter](https://sourcegraph.com/github.com/sourcegraph/sourcegraph@3.23/-/blob/enterprise/internal/codeintel/bloomfilter/bloom_filter.go#L27:6) encoded as gzipped JSON. This bloom filter stores the set of identifiers imported from the package.';\n\nCOMMENT ON COLUMN lsif_references.dump_id IS 'The identifier of the upload that references the package.';\n\nCREATE SEQUENCE lsif_references_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE lsif_references_id_seq OWNED BY lsif_references.id;\n\nCREATE TABLE lsif_uploads_visible_at_tip (\n repository_id integer NOT NULL,\n upload_id integer NOT NULL\n);\n\nCOMMENT ON TABLE lsif_uploads_visible_at_tip IS 'Associates a repository with the set of LSIF upload identifiers that can serve intelligence for the tip of the default branch.';\n\nCOMMENT ON COLUMN lsif_uploads_visible_at_tip.upload_id IS 'The identifier of an upload visible at the tip of the default branch.';\n\nCREATE VIEW lsif_uploads_with_repository_name AS\n SELECT u.id,\n u.commit,\n u.root,\n u.uploaded_at,\n u.state,\n u.failure_message,\n u.started_at,\n u.finished_at,\n u.repository_id,\n u.indexer,\n u.num_parts,\n u.uploaded_parts,\n u.process_after,\n u.num_resets,\n u.upload_size,\n u.num_failures,\n u.associated_index_id,\n r.name AS repository_name\n FROM (lsif_uploads u\n JOIN repo r ON ((r.id = u.repository_id)))\n WHERE (r.deleted_at IS NULL);\n\nCREATE TABLE names (\n name citext NOT NULL,\n user_id integer,\n org_id integer,\n CONSTRAINT names_check CHECK (((user_id IS NOT NULL) OR (org_id IS NOT NULL)))\n);\n\nCREATE TABLE org_invitations (\n id bigint NOT NULL,\n org_id integer NOT NULL,\n sender_user_id integer NOT NULL,\n recipient_user_id integer NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n notified_at timestamp with time zone,\n responded_at timestamp with time zone,\n response_type boolean,\n revoked_at timestamp with time zone,\n deleted_at timestamp with time zone,\n CONSTRAINT check_atomic_response CHECK (((responded_at IS NULL) = (response_type IS NULL))),\n CONSTRAINT check_single_use CHECK ((((responded_at IS NULL) AND (response_type IS NULL)) OR (revoked_at IS NULL)))\n);\n\nCREATE SEQUENCE org_invitations_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE org_invitations_id_seq OWNED BY org_invitations.id;\n\nCREATE TABLE org_members (\n id integer NOT NULL,\n org_id integer NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n user_id integer NOT NULL\n);\n\nCREATE TABLE org_members_bkup_1514536731 (\n id integer,\n org_id integer,\n user_id_old text,\n created_at timestamp with time zone,\n updated_at timestamp with time zone,\n user_id integer\n);\n\nCREATE SEQUENCE org_members_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE org_members_id_seq OWNED BY org_members.id;\n\nCREATE TABLE orgs (\n id integer NOT NULL,\n name citext NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n display_name text,\n slack_webhook_url text,\n deleted_at timestamp with time zone,\n CONSTRAINT orgs_display_name_max_length CHECK ((char_length(display_name) \u003c= 255)),\n CONSTRAINT orgs_name_max_length CHECK ((char_length((name)::text) \u003c= 255)),\n CONSTRAINT orgs_name_valid_chars CHECK ((name OPERATOR(~) '^[a-zA-Z0-9](?:[a-zA-Z0-9]|[-.](?=[a-zA-Z0-9]))*-?$'::citext))\n);\n\nCREATE SEQUENCE orgs_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE orgs_id_seq OWNED BY orgs.id;\n\nCREATE TABLE out_of_band_migrations (\n id integer NOT NULL,\n team text NOT NULL,\n component text NOT NULL,\n description text NOT NULL,\n progress double precision DEFAULT 0 NOT NULL,\n created timestamp with time zone DEFAULT now() NOT NULL,\n last_updated timestamp with time zone,\n non_destructive boolean NOT NULL,\n apply_reverse boolean DEFAULT false NOT NULL,\n is_enterprise boolean DEFAULT false NOT NULL,\n introduced_version_major integer NOT NULL,\n introduced_version_minor integer NOT NULL,\n deprecated_version_major integer,\n deprecated_version_minor integer,\n CONSTRAINT out_of_band_migrations_component_nonempty CHECK ((component \u003c\u003e ''::text)),\n CONSTRAINT out_of_band_migrations_description_nonempty CHECK ((description \u003c\u003e ''::text)),\n CONSTRAINT out_of_band_migrations_progress_range CHECK (((progress \u003e= (0)::double precision) AND (progress \u003c= (1)::double precision))),\n CONSTRAINT out_of_band_migrations_team_nonempty CHECK ((team \u003c\u003e ''::text))\n);\n\nCOMMENT ON TABLE out_of_band_migrations IS 'Stores metadata and progress about an out-of-band migration routine.';\n\nCOMMENT ON COLUMN out_of_band_migrations.id IS 'A globally unique primary key for this migration. The same key is used consistently across all Sourcegraph instances for the same migration.';\n\nCOMMENT ON COLUMN out_of_band_migrations.team IS 'The name of the engineering team responsible for the migration.';\n\nCOMMENT ON COLUMN out_of_band_migrations.component IS 'The name of the component undergoing a migration.';\n\nCOMMENT ON COLUMN out_of_band_migrations.description IS 'A brief description about the migration.';\n\nCOMMENT ON COLUMN out_of_band_migrations.progress IS 'The percentage progress in the up direction (0=0%, 1=100%).';\n\nCOMMENT ON COLUMN out_of_band_migrations.created IS 'The date and time the migration was inserted into the database (via an upgrade).';\n\nCOMMENT ON COLUMN out_of_band_migrations.last_updated IS 'The date and time the migration was last updated.';\n\nCOMMENT ON COLUMN out_of_band_migrations.non_destructive IS 'Whether or not this migration alters data so it can no longer be read by the previous Sourcegraph instance.';\n\nCOMMENT ON COLUMN out_of_band_migrations.apply_reverse IS 'Whether this migration should run in the opposite direction (to support an upcoming downgrade).';\n\nCOMMENT ON COLUMN out_of_band_migrations.is_enterprise IS 'When true, these migrations are invisible to OSS mode.';\n\nCOMMENT ON COLUMN out_of_band_migrations.introduced_version_major IS 'The Sourcegraph version (major component) in which this migration was first introduced.';\n\nCOMMENT ON COLUMN out_of_band_migrations.introduced_version_minor IS 'The Sourcegraph version (minor component) in which this migration was first introduced.';\n\nCOMMENT ON COLUMN out_of_band_migrations.deprecated_version_major IS 'The lowest Sourcegraph version (major component) that assumes the migration has completed.';\n\nCOMMENT ON COLUMN out_of_band_migrations.deprecated_version_minor IS 'The lowest Sourcegraph version (minor component) that assumes the migration has completed.';\n\nCREATE TABLE out_of_band_migrations_errors (\n id integer NOT NULL,\n migration_id integer NOT NULL,\n message text NOT NULL,\n created timestamp with time zone DEFAULT now() NOT NULL,\n CONSTRAINT out_of_band_migrations_errors_message_nonempty CHECK ((message \u003c\u003e ''::text))\n);\n\nCOMMENT ON TABLE out_of_band_migrations_errors IS 'Stores errors that occurred while performing an out-of-band migration.';\n\nCOMMENT ON COLUMN out_of_band_migrations_errors.id IS 'A unique identifer.';\n\nCOMMENT ON COLUMN out_of_band_migrations_errors.migration_id IS 'The identifier of the migration.';\n\nCOMMENT ON COLUMN out_of_band_migrations_errors.message IS 'The error message.';\n\nCOMMENT ON COLUMN out_of_band_migrations_errors.created IS 'The date and time the error occurred.';\n\nCREATE SEQUENCE out_of_band_migrations_errors_id_seq\n AS integer\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE out_of_band_migrations_errors_id_seq OWNED BY out_of_band_migrations_errors.id;\n\nCREATE SEQUENCE out_of_band_migrations_id_seq\n AS integer\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE out_of_band_migrations_id_seq OWNED BY out_of_band_migrations.id;\n\nCREATE TABLE phabricator_repos (\n id integer NOT NULL,\n callsign citext NOT NULL,\n repo_name citext NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n deleted_at timestamp with time zone,\n url text DEFAULT ''::text NOT NULL\n);\n\nCREATE SEQUENCE phabricator_repos_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE phabricator_repos_id_seq OWNED BY phabricator_repos.id;\n\nCREATE TABLE product_licenses (\n id uuid NOT NULL,\n product_subscription_id uuid NOT NULL,\n license_key text NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL\n);\n\nCREATE TABLE product_subscriptions (\n id uuid NOT NULL,\n user_id integer NOT NULL,\n billing_subscription_id text,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n archived_at timestamp with time zone\n);\n\nCREATE TABLE query_runner_state (\n query text,\n last_executed timestamp with time zone,\n latest_result timestamp with time zone,\n exec_duration_ns bigint\n);\n\nCREATE TABLE users (\n id integer NOT NULL,\n username citext NOT NULL,\n display_name text,\n avatar_url text,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n deleted_at timestamp with time zone,\n invite_quota integer DEFAULT 15 NOT NULL,\n passwd text,\n passwd_reset_code text,\n passwd_reset_time timestamp with time zone,\n site_admin boolean DEFAULT false NOT NULL,\n page_views integer DEFAULT 0 NOT NULL,\n search_queries integer DEFAULT 0 NOT NULL,\n tags text[] DEFAULT '{}'::text[],\n billing_customer_id text,\n invalidated_sessions_at timestamp with time zone DEFAULT now() NOT NULL,\n CONSTRAINT users_display_name_max_length CHECK ((char_length(display_name) \u003c= 255)),\n CONSTRAINT users_username_max_length CHECK ((char_length((username)::text) \u003c= 255)),\n CONSTRAINT users_username_valid_chars CHECK ((username OPERATOR(~) '^[a-zA-Z0-9](?:[a-zA-Z0-9]|[-.](?=[a-zA-Z0-9]))*-?$'::citext))\n);\n\nCREATE VIEW reconciler_changesets AS\n SELECT c.id,\n c.batch_change_ids,\n c.repo_id,\n c.created_at,\n c.updated_at,\n c.metadata,\n c.external_id,\n c.external_service_type,\n c.external_deleted_at,\n c.external_branch,\n c.external_updated_at,\n c.external_state,\n c.external_review_state,\n c.external_check_state,\n c.diff_stat_added,\n c.diff_stat_changed,\n c.diff_stat_deleted,\n c.sync_state,\n c.current_spec_id,\n c.previous_spec_id,\n c.publication_state,\n c.owned_by_batch_change_id,\n c.reconciler_state,\n c.failure_message,\n c.started_at,\n c.finished_at,\n c.process_after,\n c.num_resets,\n c.closing,\n c.num_failures,\n c.log_contents,\n c.execution_logs,\n c.syncer_error,\n c.external_title\n FROM (changesets c\n JOIN repo r ON ((r.id = c.repo_id)))\n WHERE ((r.deleted_at IS NULL) AND (EXISTS ( SELECT 1\n FROM ((batch_changes\n LEFT JOIN users namespace_user ON ((batch_changes.namespace_user_id = namespace_user.id)))\n LEFT JOIN orgs namespace_org ON ((batch_changes.namespace_org_id = namespace_org.id)))\n WHERE ((c.batch_change_ids ? (batch_changes.id)::text) AND (namespace_user.deleted_at IS NULL) AND (namespace_org.deleted_at IS NULL)))));\n\nCREATE TABLE registry_extension_releases (\n id bigint NOT NULL,\n registry_extension_id integer NOT NULL,\n creator_user_id integer NOT NULL,\n release_version citext,\n release_tag citext NOT NULL,\n manifest jsonb NOT NULL,\n bundle text,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n deleted_at timestamp with time zone,\n source_map text\n);\n\nCREATE SEQUENCE registry_extension_releases_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE registry_extension_releases_id_seq OWNED BY registry_extension_releases.id;\n\nCREATE TABLE registry_extensions (\n id integer NOT NULL,\n uuid uuid NOT NULL,\n publisher_user_id integer,\n publisher_org_id integer,\n name citext NOT NULL,\n manifest text,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n deleted_at timestamp with time zone,\n CONSTRAINT registry_extensions_name_length CHECK (((char_length((name)::text) \u003e 0) AND (char_length((name)::text) \u003c= 128))),\n CONSTRAINT registry_extensions_name_valid_chars CHECK ((name OPERATOR(~) '^[a-zA-Z0-9](?:[a-zA-Z0-9]|[_.-](?=[a-zA-Z0-9]))*$'::citext)),\n CONSTRAINT registry_extensions_single_publisher CHECK (((publisher_user_id IS NULL) \u003c\u003e (publisher_org_id IS NULL)))\n);\n\nCREATE SEQUENCE registry_extensions_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE registry_extensions_id_seq OWNED BY registry_extensions.id;\n\nCREATE SEQUENCE repo_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE repo_id_seq OWNED BY repo.id;\n\nCREATE TABLE repo_pending_permissions (\n repo_id integer NOT NULL,\n permission text NOT NULL,\n user_ids bytea DEFAULT '\\x'::bytea NOT NULL,\n updated_at timestamp with time zone NOT NULL,\n user_ids_ints integer[] DEFAULT '{}'::integer[] NOT NULL\n);\n\nCREATE TABLE repo_permissions (\n repo_id integer NOT NULL,\n permission text NOT NULL,\n user_ids bytea DEFAULT '\\x'::bytea NOT NULL,\n updated_at timestamp with time zone NOT NULL,\n synced_at timestamp with time zone,\n user_ids_ints integer[] DEFAULT '{}'::integer[] NOT NULL\n);\n\nCREATE TABLE saved_searches (\n id integer NOT NULL,\n description text NOT NULL,\n query text NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n notify_owner boolean NOT NULL,\n notify_slack boolean NOT NULL,\n user_id integer,\n org_id integer,\n slack_webhook_url text,\n CONSTRAINT user_or_org_id_not_null CHECK ((((user_id IS NOT NULL) AND (org_id IS NULL)) OR ((org_id IS NOT NULL) AND (user_id IS NULL))))\n);\n\nCREATE SEQUENCE saved_searches_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE saved_searches_id_seq OWNED BY saved_searches.id;\n\nCREATE TABLE search_context_repos (\n search_context_id bigint NOT NULL,\n repo_id integer NOT NULL,\n revision text NOT NULL\n);\n\nCREATE TABLE search_contexts (\n id bigint NOT NULL,\n name citext NOT NULL,\n description text NOT NULL,\n public boolean NOT NULL,\n namespace_user_id integer,\n namespace_org_id integer,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n deleted_at timestamp with time zone,\n CONSTRAINT search_contexts_has_one_or_no_namespace CHECK (((namespace_user_id IS NULL) OR (namespace_org_id IS NULL)))\n);\n\nCREATE SEQUENCE search_contexts_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE search_contexts_id_seq OWNED BY search_contexts.id;\n\nCREATE TABLE security_event_logs (\n id bigint NOT NULL,\n name text NOT NULL,\n url text NOT NULL,\n user_id integer NOT NULL,\n anonymous_user_id text NOT NULL,\n source text NOT NULL,\n argument jsonb NOT NULL,\n version text NOT NULL,\n \"timestamp\" timestamp with time zone NOT NULL,\n CONSTRAINT security_event_logs_check_has_user CHECK ((((user_id = 0) AND (anonymous_user_id \u003c\u003e ''::text)) OR ((user_id \u003c\u003e 0) AND (anonymous_user_id = ''::text)) OR ((user_id \u003c\u003e 0) AND (anonymous_user_id \u003c\u003e ''::text)))),\n CONSTRAINT security_event_logs_check_name_not_empty CHECK ((name \u003c\u003e ''::text)),\n CONSTRAINT security_event_logs_check_source_not_empty CHECK ((source \u003c\u003e ''::text)),\n CONSTRAINT security_event_logs_check_version_not_empty CHECK ((version \u003c\u003e ''::text))\n);\n\nCOMMENT ON TABLE security_event_logs IS 'Contains security-relevant events with a long time horizon for storage.';\n\nCOMMENT ON COLUMN security_event_logs.name IS 'The event name as a CAPITALIZED_SNAKE_CASE string.';\n\nCOMMENT ON COLUMN security_event_logs.url IS 'The URL within the Sourcegraph app which generated the event.';\n\nCOMMENT ON COLUMN security_event_logs.user_id IS 'The ID of the actor associated with the event.';\n\nCOMMENT ON COLUMN security_event_logs.anonymous_user_id IS 'The UUID of the actor associated with the event.';\n\nCOMMENT ON COLUMN security_event_logs.source IS 'The site section (WEB, BACKEND, etc.) that generated the event.';\n\nCOMMENT ON COLUMN security_event_logs.argument IS 'An arbitrary JSON blob containing event data.';\n\nCOMMENT ON COLUMN security_event_logs.version IS 'The version of Sourcegraph which generated the event.';\n\nCREATE SEQUENCE security_event_logs_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE security_event_logs_id_seq OWNED BY security_event_logs.id;\n\nCREATE TABLE settings (\n id integer NOT NULL,\n org_id integer,\n contents text,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n user_id integer,\n author_user_id integer\n);\n\nCREATE TABLE settings_bkup_1514702776 (\n id integer,\n org_id integer,\n author_user_id_old text,\n contents text,\n created_at timestamp with time zone,\n user_id integer,\n author_user_id integer\n);\n\nCREATE SEQUENCE settings_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE settings_id_seq OWNED BY settings.id;\n\nCREATE VIEW site_config AS\n SELECT global_state.site_id,\n global_state.initialized\n FROM global_state;\n\nCREATE TABLE survey_responses (\n id bigint NOT NULL,\n user_id integer,\n email text,\n score integer NOT NULL,\n reason text,\n better text,\n created_at timestamp with time zone DEFAULT now() NOT NULL\n);\n\nCREATE SEQUENCE survey_responses_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE survey_responses_id_seq OWNED BY survey_responses.id;\n\nCREATE VIEW tracking_changeset_specs_and_changesets AS\n SELECT changeset_specs.id AS changeset_spec_id,\n COALESCE(changesets.id, (0)::bigint) AS changeset_id,\n changeset_specs.repo_id,\n changeset_specs.batch_spec_id,\n repo.name AS repo_name,\n COALESCE((changesets.metadata -\u003e\u003e 'Title'::text), (changesets.metadata -\u003e\u003e 'title'::text)) AS changeset_name,\n changesets.external_state,\n changesets.publication_state,\n changesets.reconciler_state\n FROM ((changeset_specs\n LEFT JOIN changesets ON (((changesets.repo_id = changeset_specs.repo_id) AND (changesets.external_id = changeset_specs.external_id))))\n JOIN repo ON ((changeset_specs.repo_id = repo.id)))\n WHERE ((changeset_specs.external_id IS NOT NULL) AND (repo.deleted_at IS NULL));\n\nCREATE TABLE user_credentials (\n id bigint NOT NULL,\n domain text NOT NULL,\n user_id integer NOT NULL,\n external_service_type text NOT NULL,\n external_service_id text NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n credential bytea NOT NULL,\n ssh_migration_applied boolean DEFAULT false NOT NULL,\n encryption_key_id text DEFAULT ''::text NOT NULL\n);\n\nCREATE SEQUENCE user_credentials_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE user_credentials_id_seq OWNED BY user_credentials.id;\n\nCREATE TABLE user_emails (\n user_id integer NOT NULL,\n email citext NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n verification_code text,\n verified_at timestamp with time zone,\n last_verification_sent_at timestamp with time zone,\n is_primary boolean DEFAULT false NOT NULL\n);\n\nCREATE TABLE user_external_accounts (\n id integer NOT NULL,\n user_id integer NOT NULL,\n service_type text NOT NULL,\n service_id text NOT NULL,\n account_id text NOT NULL,\n auth_data text,\n account_data text,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n deleted_at timestamp with time zone,\n client_id text NOT NULL,\n expired_at timestamp with time zone,\n last_valid_at timestamp with time zone,\n encryption_key_id text DEFAULT ''::text NOT NULL\n);\n\nCREATE SEQUENCE user_external_accounts_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE user_external_accounts_id_seq OWNED BY user_external_accounts.id;\n\nCREATE TABLE user_pending_permissions (\n id integer NOT NULL,\n bind_id text NOT NULL,\n permission text NOT NULL,\n object_type text NOT NULL,\n object_ids bytea DEFAULT '\\x'::bytea NOT NULL,\n updated_at timestamp with time zone NOT NULL,\n service_type text NOT NULL,\n service_id text NOT NULL,\n object_ids_ints integer[] DEFAULT '{}'::integer[] NOT NULL\n);\n\nCREATE SEQUENCE user_pending_permissions_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE user_pending_permissions_id_seq OWNED BY user_pending_permissions.id;\n\nCREATE TABLE user_permissions (\n user_id integer NOT NULL,\n permission text NOT NULL,\n object_type text NOT NULL,\n object_ids bytea DEFAULT '\\x'::bytea NOT NULL,\n updated_at timestamp with time zone NOT NULL,\n synced_at timestamp with time zone,\n object_ids_ints integer[] DEFAULT '{}'::integer[] NOT NULL\n);\n\nCREATE TABLE user_public_repos (\n user_id integer NOT NULL,\n repo_uri text NOT NULL,\n repo_id integer NOT NULL\n);\n\nCREATE SEQUENCE users_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE users_id_seq OWNED BY users.id;\n\nCREATE TABLE versions (\n service text NOT NULL,\n version text NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n first_version text NOT NULL\n);\n\nALTER TABLE ONLY access_tokens ALTER COLUMN id SET DEFAULT nextval('access_tokens_id_seq'::regclass);\n\nALTER TABLE ONLY batch_changes ALTER COLUMN id SET DEFAULT nextval('batch_changes_id_seq'::regclass);\n\nALTER TABLE ONLY batch_changes_site_credentials ALTER COLUMN id SET DEFAULT nextval('batch_changes_site_credentials_id_seq'::regclass);\n\nALTER TABLE ONLY batch_specs ALTER COLUMN id SET DEFAULT nextval('batch_specs_id_seq'::regclass);\n\nALTER TABLE ONLY changeset_events ALTER COLUMN id SET DEFAULT nextval('changeset_events_id_seq'::regclass);\n\nALTER TABLE ONLY changeset_jobs ALTER COLUMN id SET DEFAULT nextval('changeset_jobs_id_seq'::regclass);\n\nALTER TABLE ONLY changeset_specs ALTER COLUMN id SET DEFAULT nextval('changeset_specs_id_seq'::regclass);\n\nALTER TABLE ONLY changesets ALTER COLUMN id SET DEFAULT nextval('changesets_id_seq'::regclass);\n\nALTER TABLE ONLY cm_action_jobs ALTER COLUMN id SET DEFAULT nextval('cm_action_jobs_id_seq'::regclass);\n\nALTER TABLE ONLY cm_emails ALTER COLUMN id SET DEFAULT nextval('cm_emails_id_seq'::regclass);\n\nALTER TABLE ONLY cm_monitors ALTER COLUMN id SET DEFAULT nextval('cm_monitors_id_seq'::regclass);\n\nALTER TABLE ONLY cm_queries ALTER COLUMN id SET DEFAULT nextval('cm_queries_id_seq'::regclass);\n\nALTER TABLE ONLY cm_recipients ALTER COLUMN id SET DEFAULT nextval('cm_recipients_id_seq'::regclass);\n\nALTER TABLE ONLY cm_trigger_jobs ALTER COLUMN id SET DEFAULT nextval('cm_trigger_jobs_id_seq'::regclass);\n\nALTER TABLE ONLY critical_and_site_config ALTER COLUMN id SET DEFAULT nextval('critical_and_site_config_id_seq'::regclass);\n\nALTER TABLE ONLY discussion_comments ALTER COLUMN id SET DEFAULT nextval('discussion_comments_id_seq'::regclass);\n\nALTER TABLE ONLY discussion_threads ALTER COLUMN id SET DEFAULT nextval('discussion_threads_id_seq'::regclass);\n\nALTER TABLE ONLY discussion_threads_target_repo ALTER COLUMN id SET DEFAULT nextval('discussion_threads_target_repo_id_seq'::regclass);\n\nALTER TABLE ONLY event_logs ALTER COLUMN id SET DEFAULT nextval('event_logs_id_seq'::regclass);\n\nALTER TABLE ONLY external_services ALTER COLUMN id SET DEFAULT nextval('external_services_id_seq'::regclass);\n\nALTER TABLE ONLY insights_query_runner_jobs ALTER COLUMN id SET DEFAULT nextval('insights_query_runner_jobs_id_seq'::regclass);\n\nALTER TABLE ONLY lsif_dependency_indexing_jobs ALTER COLUMN id SET DEFAULT nextval('lsif_dependency_indexing_jobs_id_seq'::regclass);\n\nALTER TABLE ONLY lsif_index_configuration ALTER COLUMN id SET DEFAULT nextval('lsif_index_configuration_id_seq'::regclass);\n\nALTER TABLE ONLY lsif_indexable_repositories ALTER COLUMN id SET DEFAULT nextval('lsif_indexable_repositories_id_seq'::regclass);\n\nALTER TABLE ONLY lsif_indexes ALTER COLUMN id SET DEFAULT nextval('lsif_indexes_id_seq'::regclass);\n\nALTER TABLE ONLY lsif_packages ALTER COLUMN id SET DEFAULT nextval('lsif_packages_id_seq'::regclass);\n\nALTER TABLE ONLY lsif_references ALTER COLUMN id SET DEFAULT nextval('lsif_references_id_seq'::regclass);\n\nALTER TABLE ONLY lsif_uploads ALTER COLUMN id SET DEFAULT nextval('lsif_dumps_id_seq'::regclass);\n\nALTER TABLE ONLY org_invitations ALTER COLUMN id SET DEFAULT nextval('org_invitations_id_seq'::regclass);\n\nALTER TABLE ONLY org_members ALTER COLUMN id SET DEFAULT nextval('org_members_id_seq'::regclass);\n\nALTER TABLE ONLY orgs ALTER COLUMN id SET DEFAULT nextval('orgs_id_seq'::regclass);\n\nALTER TABLE ONLY out_of_band_migrations ALTER COLUMN id SET DEFAULT nextval('out_of_band_migrations_id_seq'::regclass);\n\nALTER TABLE ONLY out_of_band_migrations_errors ALTER COLUMN id SET DEFAULT nextval('out_of_band_migrations_errors_id_seq'::regclass);\n\nALTER TABLE ONLY phabricator_repos ALTER COLUMN id SET DEFAULT nextval('phabricator_repos_id_seq'::regclass);\n\nALTER TABLE ONLY registry_extension_releases ALTER COLUMN id SET DEFAULT nextval('registry_extension_releases_id_seq'::regclass);\n\nALTER TABLE ONLY registry_extensions ALTER COLUMN id SET DEFAULT nextval('registry_extensions_id_seq'::regclass);\n\nALTER TABLE ONLY repo ALTER COLUMN id SET DEFAULT nextval('repo_id_seq'::regclass);\n\nALTER TABLE ONLY saved_searches ALTER COLUMN id SET DEFAULT nextval('saved_searches_id_seq'::regclass);\n\nALTER TABLE ONLY search_contexts ALTER COLUMN id SET DEFAULT nextval('search_contexts_id_seq'::regclass);\n\nALTER TABLE ONLY security_event_logs ALTER COLUMN id SET DEFAULT nextval('security_event_logs_id_seq'::regclass);\n\nALTER TABLE ONLY settings ALTER COLUMN id SET DEFAULT nextval('settings_id_seq'::regclass);\n\nALTER TABLE ONLY survey_responses ALTER COLUMN id SET DEFAULT nextval('survey_responses_id_seq'::regclass);\n\nALTER TABLE ONLY user_credentials ALTER COLUMN id SET DEFAULT nextval('user_credentials_id_seq'::regclass);\n\nALTER TABLE ONLY user_external_accounts ALTER COLUMN id SET DEFAULT nextval('user_external_accounts_id_seq'::regclass);\n\nALTER TABLE ONLY user_pending_permissions ALTER COLUMN id SET DEFAULT nextval('user_pending_permissions_id_seq'::regclass);\n\nALTER TABLE ONLY users ALTER COLUMN id SET DEFAULT nextval('users_id_seq'::regclass);\n\nALTER TABLE ONLY access_tokens\n ADD CONSTRAINT access_tokens_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY access_tokens\n ADD CONSTRAINT access_tokens_value_sha256_key UNIQUE (value_sha256);\n\nALTER TABLE ONLY batch_changes\n ADD CONSTRAINT batch_changes_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY batch_changes_site_credentials\n ADD CONSTRAINT batch_changes_site_credentials_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY batch_specs\n ADD CONSTRAINT batch_specs_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY changeset_events\n ADD CONSTRAINT changeset_events_changeset_id_kind_key_unique UNIQUE (changeset_id, kind, key);\n\nALTER TABLE ONLY changeset_events\n ADD CONSTRAINT changeset_events_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY changeset_jobs\n ADD CONSTRAINT changeset_jobs_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY changeset_specs\n ADD CONSTRAINT changeset_specs_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY changesets\n ADD CONSTRAINT changesets_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY changesets\n ADD CONSTRAINT changesets_repo_external_id_unique UNIQUE (repo_id, external_id);\n\nALTER TABLE ONLY cm_action_jobs\n ADD CONSTRAINT cm_action_jobs_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY cm_emails\n ADD CONSTRAINT cm_emails_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY cm_monitors\n ADD CONSTRAINT cm_monitors_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY cm_queries\n ADD CONSTRAINT cm_queries_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY cm_recipients\n ADD CONSTRAINT cm_recipients_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY cm_trigger_jobs\n ADD CONSTRAINT cm_trigger_jobs_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY critical_and_site_config\n ADD CONSTRAINT critical_and_site_config_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY default_repos\n ADD CONSTRAINT default_repos_pkey PRIMARY KEY (repo_id);\n\nALTER TABLE ONLY discussion_comments\n ADD CONSTRAINT discussion_comments_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY discussion_mail_reply_tokens\n ADD CONSTRAINT discussion_mail_reply_tokens_pkey PRIMARY KEY (token);\n\nALTER TABLE ONLY discussion_threads\n ADD CONSTRAINT discussion_threads_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY discussion_threads_target_repo\n ADD CONSTRAINT discussion_threads_target_repo_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY event_logs\n ADD CONSTRAINT event_logs_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY external_service_repos\n ADD CONSTRAINT external_service_repos_repo_id_external_service_id_unique UNIQUE (repo_id, external_service_id);\n\nALTER TABLE ONLY external_services\n ADD CONSTRAINT external_services_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY feature_flag_overrides\n ADD CONSTRAINT feature_flag_overrides_unique_org_flag UNIQUE (namespace_org_id, flag_name);\n\nALTER TABLE ONLY feature_flag_overrides\n ADD CONSTRAINT feature_flag_overrides_unique_user_flag UNIQUE (namespace_user_id, flag_name);\n\nALTER TABLE ONLY feature_flags\n ADD CONSTRAINT feature_flags_pkey PRIMARY KEY (flag_name);\n\nALTER TABLE ONLY gitserver_repos\n ADD CONSTRAINT gitserver_repos_pkey PRIMARY KEY (repo_id);\n\nALTER TABLE ONLY global_state\n ADD CONSTRAINT global_state_pkey PRIMARY KEY (site_id);\n\nALTER TABLE ONLY insights_query_runner_jobs\n ADD CONSTRAINT insights_query_runner_jobs_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY lsif_dependency_indexing_jobs\n ADD CONSTRAINT lsif_dependency_indexing_jobs_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY lsif_dirty_repositories\n ADD CONSTRAINT lsif_dirty_repositories_pkey PRIMARY KEY (repository_id);\n\nALTER TABLE ONLY lsif_index_configuration\n ADD CONSTRAINT lsif_index_configuration_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY lsif_index_configuration\n ADD CONSTRAINT lsif_index_configuration_repository_id_key UNIQUE (repository_id);\n\nALTER TABLE ONLY lsif_indexable_repositories\n ADD CONSTRAINT lsif_indexable_repositories_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY lsif_indexable_repositories\n ADD CONSTRAINT lsif_indexable_repositories_repository_id_key UNIQUE (repository_id);\n\nALTER TABLE ONLY lsif_indexes\n ADD CONSTRAINT lsif_indexes_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY lsif_packages\n ADD CONSTRAINT lsif_packages_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY lsif_references\n ADD CONSTRAINT lsif_references_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY lsif_uploads\n ADD CONSTRAINT lsif_uploads_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY names\n ADD CONSTRAINT names_pkey PRIMARY KEY (name);\n\nALTER TABLE ONLY org_invitations\n ADD CONSTRAINT org_invitations_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY org_members\n ADD CONSTRAINT org_members_org_id_user_id_key UNIQUE (org_id, user_id);\n\nALTER TABLE ONLY org_members\n ADD CONSTRAINT org_members_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY orgs\n ADD CONSTRAINT orgs_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY out_of_band_migrations_errors\n ADD CONSTRAINT out_of_band_migrations_errors_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY out_of_band_migrations\n ADD CONSTRAINT out_of_band_migrations_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY phabricator_repos\n ADD CONSTRAINT phabricator_repos_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY phabricator_repos\n ADD CONSTRAINT phabricator_repos_repo_name_key UNIQUE (repo_name);\n\nALTER TABLE ONLY product_licenses\n ADD CONSTRAINT product_licenses_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY product_subscriptions\n ADD CONSTRAINT product_subscriptions_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY registry_extension_releases\n ADD CONSTRAINT registry_extension_releases_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY registry_extensions\n ADD CONSTRAINT registry_extensions_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY repo\n ADD CONSTRAINT repo_name_unique UNIQUE (name) DEFERRABLE;\n\nALTER TABLE ONLY repo_pending_permissions\n ADD CONSTRAINT repo_pending_permissions_perm_unique UNIQUE (repo_id, permission);\n\nALTER TABLE ONLY repo_permissions\n ADD CONSTRAINT repo_permissions_perm_unique UNIQUE (repo_id, permission);\n\nALTER TABLE ONLY repo\n ADD CONSTRAINT repo_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY saved_searches\n ADD CONSTRAINT saved_searches_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY search_context_repos\n ADD CONSTRAINT search_context_repos_search_context_id_repo_id_revision_unique UNIQUE (search_context_id, repo_id, revision);\n\nALTER TABLE ONLY search_contexts\n ADD CONSTRAINT search_contexts_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY security_event_logs\n ADD CONSTRAINT security_event_logs_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY settings\n ADD CONSTRAINT settings_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY survey_responses\n ADD CONSTRAINT survey_responses_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY user_credentials\n ADD CONSTRAINT user_credentials_domain_user_id_external_service_type_exter_key UNIQUE (domain, user_id, external_service_type, external_service_id);\n\nALTER TABLE ONLY user_credentials\n ADD CONSTRAINT user_credentials_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY user_emails\n ADD CONSTRAINT user_emails_no_duplicates_per_user UNIQUE (user_id, email);\n\nALTER TABLE ONLY user_emails\n ADD CONSTRAINT user_emails_unique_verified_email EXCLUDE USING btree (email WITH OPERATOR(=)) WHERE ((verified_at IS NOT NULL));\n\nALTER TABLE ONLY user_external_accounts\n ADD CONSTRAINT user_external_accounts_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY user_pending_permissions\n ADD CONSTRAINT user_pending_permissions_service_perm_object_unique UNIQUE (service_type, service_id, permission, object_type, bind_id);\n\nALTER TABLE ONLY user_permissions\n ADD CONSTRAINT user_permissions_perm_object_unique UNIQUE (user_id, permission, object_type);\n\nALTER TABLE ONLY user_public_repos\n ADD CONSTRAINT user_public_repos_user_id_repo_id_key UNIQUE (user_id, repo_id);\n\nALTER TABLE ONLY users\n ADD CONSTRAINT users_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY versions\n ADD CONSTRAINT versions_pkey PRIMARY KEY (service);\n\nCREATE INDEX access_tokens_lookup ON access_tokens USING hash (value_sha256) WHERE (deleted_at IS NULL);\n\nCREATE INDEX batch_changes_namespace_org_id ON batch_changes USING btree (namespace_org_id);\n\nCREATE INDEX batch_changes_namespace_user_id ON batch_changes USING btree (namespace_user_id);\n\nCREATE INDEX batch_changes_site_credentials_credential_idx ON batch_changes_site_credentials USING btree (((encryption_key_id = ANY (ARRAY[''::text, 'previously-migrated'::text]))));\n\nCREATE UNIQUE INDEX batch_changes_site_credentials_unique ON batch_changes_site_credentials USING btree (external_service_type, external_service_id);\n\nCREATE INDEX batch_specs_rand_id ON batch_specs USING btree (rand_id);\n\nCREATE INDEX changeset_jobs_bulk_group_idx ON changeset_jobs USING btree (bulk_group);\n\nCREATE INDEX changeset_jobs_state_idx ON changeset_jobs USING btree (state);\n\nCREATE INDEX changeset_specs_external_id ON changeset_specs USING btree (external_id);\n\nCREATE INDEX changeset_specs_head_ref ON changeset_specs USING btree (head_ref);\n\nCREATE INDEX changeset_specs_rand_id ON changeset_specs USING btree (rand_id);\n\nCREATE INDEX changeset_specs_title ON changeset_specs USING btree (title);\n\nCREATE INDEX changesets_batch_change_ids ON changesets USING gin (batch_change_ids);\n\nCREATE INDEX changesets_external_state_idx ON changesets USING btree (external_state);\n\nCREATE INDEX changesets_external_title_idx ON changesets USING btree (external_title);\n\nCREATE INDEX changesets_publication_state_idx ON changesets USING btree (publication_state);\n\nCREATE INDEX changesets_reconciler_state_idx ON changesets USING btree (reconciler_state);\n\nCREATE UNIQUE INDEX critical_and_site_config_unique ON critical_and_site_config USING btree (id, type);\n\nCREATE INDEX discussion_comments_author_user_id_idx ON discussion_comments USING btree (author_user_id);\n\nCREATE INDEX discussion_comments_reports_array_length_idx ON discussion_comments USING btree (array_length(reports, 1));\n\nCREATE INDEX discussion_comments_thread_id_idx ON discussion_comments USING btree (thread_id);\n\nCREATE INDEX discussion_mail_reply_tokens_user_id_thread_id_idx ON discussion_mail_reply_tokens USING btree (user_id, thread_id);\n\nCREATE INDEX discussion_threads_author_user_id_idx ON discussion_threads USING btree (author_user_id);\n\nCREATE INDEX discussion_threads_target_repo_repo_id_path_idx ON discussion_threads_target_repo USING btree (repo_id, path);\n\nCREATE INDEX event_logs_anonymous_user_id ON event_logs USING btree (anonymous_user_id);\n\nCREATE INDEX event_logs_name ON event_logs USING btree (name);\n\nCREATE INDEX event_logs_source ON event_logs USING btree (source);\n\nCREATE INDEX event_logs_timestamp ON event_logs USING btree (\"timestamp\");\n\nCREATE INDEX event_logs_timestamp_at_utc ON event_logs USING btree (date(timezone('UTC'::text, \"timestamp\")));\n\nCREATE INDEX event_logs_user_id ON event_logs USING btree (user_id);\n\nCREATE INDEX external_service_repos_external_service_id ON external_service_repos USING btree (external_service_id);\n\nCREATE INDEX external_service_repos_idx ON external_service_repos USING btree (external_service_id, repo_id);\n\nCREATE INDEX external_service_sync_jobs_state_idx ON external_service_sync_jobs USING btree (state);\n\nCREATE INDEX external_service_user_repos_idx ON external_service_repos USING btree (user_id, repo_id) WHERE (user_id IS NOT NULL);\n\nCREATE INDEX external_services_namespace_user_id_idx ON external_services USING btree (namespace_user_id);\n\nCREATE INDEX feature_flag_overrides_org_id ON feature_flag_overrides USING btree (namespace_org_id) WHERE (namespace_org_id IS NOT NULL);\n\nCREATE INDEX feature_flag_overrides_user_id ON feature_flag_overrides USING btree (namespace_user_id) WHERE (namespace_user_id IS NOT NULL);\n\nCREATE INDEX gitserver_repos_cloned_status_idx ON gitserver_repos USING btree (repo_id) WHERE (clone_status = 'cloned'::text);\n\nCREATE INDEX gitserver_repos_cloning_status_idx ON gitserver_repos USING btree (repo_id) WHERE (clone_status = 'cloning'::text);\n\nCREATE INDEX gitserver_repos_last_error_idx ON gitserver_repos USING btree (last_error) WHERE (last_error IS NOT NULL);\n\nCREATE INDEX gitserver_repos_not_cloned_status_idx ON gitserver_repos USING btree (repo_id) WHERE (clone_status = 'not_cloned'::text);\n\nCREATE INDEX insights_query_runner_jobs_state_btree ON insights_query_runner_jobs USING btree (state);\n\nCREATE UNIQUE INDEX kind_cloud_default ON external_services USING btree (kind, cloud_default) WHERE ((cloud_default = true) AND (deleted_at IS NULL));\n\nCREATE INDEX lsif_indexes_commit_last_checked_at ON lsif_indexes USING btree (commit_last_checked_at) WHERE (state \u003c\u003e 'deleted'::text);\n\nCREATE INDEX lsif_nearest_uploads_links_repository_id_commit_bytea ON lsif_nearest_uploads_links USING btree (repository_id, commit_bytea);\n\nCREATE INDEX lsif_nearest_uploads_repository_id_commit_bytea ON lsif_nearest_uploads USING btree (repository_id, commit_bytea);\n\nCREATE INDEX lsif_packages_scheme_name_version ON lsif_packages USING btree (scheme, name, version);\n\nCREATE INDEX lsif_references_package ON lsif_references USING btree (scheme, name, version);\n\nCREATE INDEX lsif_uploads_associated_index_id ON lsif_uploads USING btree (associated_index_id);\n\nCREATE INDEX lsif_uploads_commit_last_checked_at ON lsif_uploads USING btree (commit_last_checked_at) WHERE (state \u003c\u003e 'deleted'::text);\n\nCREATE INDEX lsif_uploads_committed_at ON lsif_uploads USING btree (committed_at) WHERE (state = 'completed'::text);\n\nCREATE UNIQUE INDEX lsif_uploads_repository_id_commit_root_indexer ON lsif_uploads USING btree (repository_id, commit, root, indexer) WHERE (state = 'completed'::text);\n\nCREATE INDEX lsif_uploads_state ON lsif_uploads USING btree (state);\n\nCREATE INDEX lsif_uploads_uploaded_at ON lsif_uploads USING btree (uploaded_at);\n\nCREATE INDEX lsif_uploads_visible_at_tip_repository_id_upload_id ON lsif_uploads_visible_at_tip USING btree (repository_id, upload_id);\n\nCREATE INDEX org_invitations_org_id ON org_invitations USING btree (org_id) WHERE (deleted_at IS NULL);\n\nCREATE INDEX org_invitations_recipient_user_id ON org_invitations USING btree (recipient_user_id) WHERE (deleted_at IS NULL);\n\nCREATE UNIQUE INDEX org_invitations_singleflight ON org_invitations USING btree (org_id, recipient_user_id) WHERE ((responded_at IS NULL) AND (revoked_at IS NULL) AND (deleted_at IS NULL));\n\nCREATE UNIQUE INDEX orgs_name ON orgs USING btree (name) WHERE (deleted_at IS NULL);\n\nCREATE INDEX registry_extension_releases_registry_extension_id ON registry_extension_releases USING btree (registry_extension_id, release_tag, created_at DESC) WHERE (deleted_at IS NULL);\n\nCREATE UNIQUE INDEX registry_extension_releases_version ON registry_extension_releases USING btree (registry_extension_id, release_version) WHERE (release_version IS NOT NULL);\n\nCREATE UNIQUE INDEX registry_extensions_publisher_name ON registry_extensions USING btree (COALESCE(publisher_user_id, 0), COALESCE(publisher_org_id, 0), name) WHERE (deleted_at IS NULL);\n\nCREATE UNIQUE INDEX registry_extensions_uuid ON registry_extensions USING btree (uuid);\n\nCREATE INDEX repo_archived ON repo USING btree (archived);\n\nCREATE INDEX repo_cloned ON repo USING btree (cloned);\n\nCREATE INDEX repo_created_at ON repo USING btree (created_at);\n\nCREATE UNIQUE INDEX repo_external_unique_idx ON repo USING btree (external_service_type, external_service_id, external_id);\n\nCREATE INDEX repo_fork ON repo USING btree (fork);\n\nCREATE INDEX repo_metadata_gin_idx ON repo USING gin (metadata);\n\nCREATE INDEX repo_name_idx ON repo USING btree (lower((name)::text) COLLATE \"C\");\n\nCREATE INDEX repo_name_trgm ON repo USING gin (lower((name)::text) gin_trgm_ops);\n\nCREATE INDEX repo_private ON repo USING btree (private);\n\nCREATE INDEX repo_stars_idx ON repo USING btree (stars DESC NULLS LAST);\n\nCREATE INDEX repo_uri_idx ON repo USING btree (uri);\n\nCREATE UNIQUE INDEX search_contexts_name_namespace_org_id_unique ON search_contexts USING btree (name, namespace_org_id) WHERE (namespace_org_id IS NOT NULL);\n\nCREATE UNIQUE INDEX search_contexts_name_namespace_user_id_unique ON search_contexts USING btree (name, namespace_user_id) WHERE (namespace_user_id IS NOT NULL);\n\nCREATE UNIQUE INDEX search_contexts_name_without_namespace_unique ON search_contexts USING btree (name) WHERE ((namespace_user_id IS NULL) AND (namespace_org_id IS NULL));\n\nCREATE INDEX security_event_logs_anonymous_user_id ON security_event_logs USING btree (anonymous_user_id);\n\nCREATE INDEX security_event_logs_name ON security_event_logs USING btree (name);\n\nCREATE INDEX security_event_logs_source ON security_event_logs USING btree (source);\n\nCREATE INDEX security_event_logs_timestamp ON security_event_logs USING btree (\"timestamp\");\n\nCREATE INDEX security_event_logs_timestamp_at_utc ON security_event_logs USING btree (date(timezone('UTC'::text, \"timestamp\")));\n\nCREATE INDEX security_event_logs_user_id ON security_event_logs USING btree (user_id);\n\nCREATE INDEX settings_org_id_idx ON settings USING btree (org_id);\n\nCREATE INDEX user_credentials_credential_idx ON user_credentials USING btree (((encryption_key_id = ANY (ARRAY[''::text, 'previously-migrated'::text]))));\n\nCREATE UNIQUE INDEX user_emails_user_id_is_primary_idx ON user_emails USING btree (user_id, is_primary) WHERE (is_primary = true);\n\nCREATE UNIQUE INDEX user_external_accounts_account ON user_external_accounts USING btree (service_type, service_id, client_id, account_id) WHERE (deleted_at IS NULL);\n\nCREATE INDEX user_external_accounts_user_id ON user_external_accounts USING btree (user_id) WHERE (deleted_at IS NULL);\n\nCREATE UNIQUE INDEX users_billing_customer_id ON users USING btree (billing_customer_id) WHERE (deleted_at IS NULL);\n\nCREATE INDEX users_created_at_idx ON users USING btree (created_at);\n\nCREATE UNIQUE INDEX users_username ON users USING btree (username) WHERE (deleted_at IS NULL);\n\nCREATE TRIGGER trig_delete_batch_change_reference_on_changesets AFTER DELETE ON batch_changes FOR EACH ROW EXECUTE FUNCTION delete_batch_change_reference_on_changesets();\n\nCREATE TRIGGER trig_delete_repo_ref_on_external_service_repos AFTER UPDATE OF deleted_at ON repo FOR EACH ROW EXECUTE FUNCTION delete_repo_ref_on_external_service_repos();\n\nCREATE TRIGGER trig_invalidate_session_on_password_change BEFORE UPDATE OF passwd ON users FOR EACH ROW EXECUTE FUNCTION invalidate_session_for_userid_on_password_change();\n\nCREATE TRIGGER trig_soft_delete_user_reference_on_external_service AFTER UPDATE OF deleted_at ON users FOR EACH ROW EXECUTE FUNCTION soft_delete_user_reference_on_external_service();\n\nCREATE TRIGGER versions_insert BEFORE INSERT ON versions FOR EACH ROW EXECUTE FUNCTION versions_insert_row_trigger();\n\nALTER TABLE ONLY access_tokens\n ADD CONSTRAINT access_tokens_creator_user_id_fkey FOREIGN KEY (creator_user_id) REFERENCES users(id);\n\nALTER TABLE ONLY access_tokens\n ADD CONSTRAINT access_tokens_subject_user_id_fkey FOREIGN KEY (subject_user_id) REFERENCES users(id);\n\nALTER TABLE ONLY batch_changes\n ADD CONSTRAINT batch_changes_batch_spec_id_fkey FOREIGN KEY (batch_spec_id) REFERENCES batch_specs(id) DEFERRABLE;\n\nALTER TABLE ONLY batch_changes\n ADD CONSTRAINT batch_changes_initial_applier_id_fkey FOREIGN KEY (initial_applier_id) REFERENCES users(id) ON DELETE SET NULL DEFERRABLE;\n\nALTER TABLE ONLY batch_changes\n ADD CONSTRAINT batch_changes_last_applier_id_fkey FOREIGN KEY (last_applier_id) REFERENCES users(id) ON DELETE SET NULL DEFERRABLE;\n\nALTER TABLE ONLY batch_changes\n ADD CONSTRAINT batch_changes_namespace_org_id_fkey FOREIGN KEY (namespace_org_id) REFERENCES orgs(id) ON DELETE CASCADE DEFERRABLE;\n\nALTER TABLE ONLY batch_changes\n ADD CONSTRAINT batch_changes_namespace_user_id_fkey FOREIGN KEY (namespace_user_id) REFERENCES users(id) ON DELETE CASCADE DEFERRABLE;\n\nALTER TABLE ONLY batch_specs\n ADD CONSTRAINT batch_specs_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL DEFERRABLE;\n\nALTER TABLE ONLY changeset_events\n ADD CONSTRAINT changeset_events_changeset_id_fkey FOREIGN KEY (changeset_id) REFERENCES changesets(id) ON DELETE CASCADE DEFERRABLE;\n\nALTER TABLE ONLY changeset_jobs\n ADD CONSTRAINT changeset_jobs_batch_change_id_fkey FOREIGN KEY (batch_change_id) REFERENCES batch_changes(id) ON DELETE CASCADE DEFERRABLE;\n\nALTER TABLE ONLY changeset_jobs\n ADD CONSTRAINT changeset_jobs_changeset_id_fkey FOREIGN KEY (changeset_id) REFERENCES changesets(id) ON DELETE CASCADE DEFERRABLE;\n\nALTER TABLE ONLY changeset_jobs\n ADD CONSTRAINT changeset_jobs_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE DEFERRABLE;\n\nALTER TABLE ONLY changeset_specs\n ADD CONSTRAINT changeset_specs_batch_spec_id_fkey FOREIGN KEY (batch_spec_id) REFERENCES batch_specs(id) DEFERRABLE;\n\nALTER TABLE ONLY changeset_specs\n ADD CONSTRAINT changeset_specs_repo_id_fkey FOREIGN KEY (repo_id) REFERENCES repo(id) DEFERRABLE;\n\nALTER TABLE ONLY changeset_specs\n ADD CONSTRAINT changeset_specs_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL DEFERRABLE;\n\nALTER TABLE ONLY changesets\n ADD CONSTRAINT changesets_changeset_spec_id_fkey FOREIGN KEY (current_spec_id) REFERENCES changeset_specs(id) DEFERRABLE;\n\nALTER TABLE ONLY changesets\n ADD CONSTRAINT changesets_owned_by_batch_spec_id_fkey FOREIGN KEY (owned_by_batch_change_id) REFERENCES batch_changes(id) ON DELETE SET NULL DEFERRABLE;\n\nALTER TABLE ONLY changesets\n ADD CONSTRAINT changesets_previous_spec_id_fkey FOREIGN KEY (previous_spec_id) REFERENCES changeset_specs(id) DEFERRABLE;\n\nALTER TABLE ONLY changesets\n ADD CONSTRAINT changesets_repo_id_fkey FOREIGN KEY (repo_id) REFERENCES repo(id) ON DELETE CASCADE DEFERRABLE;\n\nALTER TABLE ONLY cm_action_jobs\n ADD CONSTRAINT cm_action_jobs_email_fk FOREIGN KEY (email) REFERENCES cm_emails(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_action_jobs\n ADD CONSTRAINT cm_action_jobs_trigger_event_fk FOREIGN KEY (trigger_event) REFERENCES cm_trigger_jobs(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_emails\n ADD CONSTRAINT cm_emails_changed_by_fk FOREIGN KEY (changed_by) REFERENCES users(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_emails\n ADD CONSTRAINT cm_emails_created_by_fk FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_emails\n ADD CONSTRAINT cm_emails_monitor FOREIGN KEY (monitor) REFERENCES cm_monitors(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_monitors\n ADD CONSTRAINT cm_monitors_changed_by_fk FOREIGN KEY (changed_by) REFERENCES users(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_monitors\n ADD CONSTRAINT cm_monitors_created_by_fk FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_monitors\n ADD CONSTRAINT cm_monitors_org_id_fk FOREIGN KEY (namespace_org_id) REFERENCES orgs(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_monitors\n ADD CONSTRAINT cm_monitors_user_id_fk FOREIGN KEY (namespace_user_id) REFERENCES users(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_recipients\n ADD CONSTRAINT cm_recipients_emails FOREIGN KEY (email) REFERENCES cm_emails(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_recipients\n ADD CONSTRAINT cm_recipients_org_id_fk FOREIGN KEY (namespace_org_id) REFERENCES orgs(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_recipients\n ADD CONSTRAINT cm_recipients_user_id_fk FOREIGN KEY (namespace_user_id) REFERENCES users(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_trigger_jobs\n ADD CONSTRAINT cm_trigger_jobs_query_fk FOREIGN KEY (query) REFERENCES cm_queries(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_queries\n ADD CONSTRAINT cm_triggers_changed_by_fk FOREIGN KEY (changed_by) REFERENCES users(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_queries\n ADD CONSTRAINT cm_triggers_created_by_fk FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_queries\n ADD CONSTRAINT cm_triggers_monitor FOREIGN KEY (monitor) REFERENCES cm_monitors(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY default_repos\n ADD CONSTRAINT default_repos_repo_id_fkey FOREIGN KEY (repo_id) REFERENCES repo(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY discussion_comments\n ADD CONSTRAINT discussion_comments_author_user_id_fkey FOREIGN KEY (author_user_id) REFERENCES users(id) ON DELETE RESTRICT;\n\nALTER TABLE ONLY discussion_comments\n ADD CONSTRAINT discussion_comments_thread_id_fkey FOREIGN KEY (thread_id) REFERENCES discussion_threads(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY discussion_mail_reply_tokens\n ADD CONSTRAINT discussion_mail_reply_tokens_thread_id_fkey FOREIGN KEY (thread_id) REFERENCES discussion_threads(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY discussion_mail_reply_tokens\n ADD CONSTRAINT discussion_mail_reply_tokens_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE RESTRICT;\n\nALTER TABLE ONLY discussion_threads\n ADD CONSTRAINT discussion_threads_author_user_id_fkey FOREIGN KEY (author_user_id) REFERENCES users(id) ON DELETE RESTRICT;\n\nALTER TABLE ONLY discussion_threads\n ADD CONSTRAINT discussion_threads_target_repo_id_fk FOREIGN KEY (target_repo_id) REFERENCES discussion_threads_target_repo(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY discussion_threads_target_repo\n ADD CONSTRAINT discussion_threads_target_repo_repo_id_fkey FOREIGN KEY (repo_id) REFERENCES repo(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY discussion_threads_target_repo\n ADD CONSTRAINT discussion_threads_target_repo_thread_id_fkey FOREIGN KEY (thread_id) REFERENCES discussion_threads(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY external_service_repos\n ADD CONSTRAINT external_service_repos_external_service_id_fkey FOREIGN KEY (external_service_id) REFERENCES external_services(id) ON DELETE CASCADE DEFERRABLE;\n\nALTER TABLE ONLY external_service_repos\n ADD CONSTRAINT external_service_repos_repo_id_fkey FOREIGN KEY (repo_id) REFERENCES repo(id) ON DELETE CASCADE DEFERRABLE;\n\nALTER TABLE ONLY external_service_repos\n ADD CONSTRAINT external_service_repos_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE DEFERRABLE;\n\nALTER TABLE ONLY external_service_sync_jobs\n ADD CONSTRAINT external_services_id_fk FOREIGN KEY (external_service_id) REFERENCES external_services(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY external_services\n ADD CONSTRAINT external_services_namepspace_user_id_fkey FOREIGN KEY (namespace_user_id) REFERENCES users(id) ON DELETE CASCADE DEFERRABLE;\n\nALTER TABLE ONLY feature_flag_overrides\n ADD CONSTRAINT feature_flag_overrides_flag_name_fkey FOREIGN KEY (flag_name) REFERENCES feature_flags(flag_name) ON DELETE CASCADE;\n\nALTER TABLE ONLY feature_flag_overrides\n ADD CONSTRAINT feature_flag_overrides_namespace_org_id_fkey FOREIGN KEY (namespace_org_id) REFERENCES orgs(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY feature_flag_overrides\n ADD CONSTRAINT feature_flag_overrides_namespace_user_id_fkey FOREIGN KEY (namespace_user_id) REFERENCES users(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY gitserver_repos\n ADD CONSTRAINT gitserver_repos_repo_id_fkey FOREIGN KEY (repo_id) REFERENCES repo(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY lsif_dependency_indexing_jobs\n ADD CONSTRAINT lsif_dependency_indexing_jobs_upload_id_fkey FOREIGN KEY (upload_id) REFERENCES lsif_uploads(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY lsif_index_configuration\n ADD CONSTRAINT lsif_index_configuration_repository_id_fkey FOREIGN KEY (repository_id) REFERENCES repo(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY lsif_packages\n ADD CONSTRAINT lsif_packages_dump_id_fkey FOREIGN KEY (dump_id) REFERENCES lsif_uploads(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY lsif_references\n ADD CONSTRAINT lsif_references_dump_id_fkey FOREIGN KEY (dump_id) REFERENCES lsif_uploads(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY names\n ADD CONSTRAINT names_org_id_fkey FOREIGN KEY (org_id) REFERENCES orgs(id) ON UPDATE CASCADE ON DELETE CASCADE;\n\nALTER TABLE ONLY names\n ADD CONSTRAINT names_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON UPDATE CASCADE ON DELETE CASCADE;\n\nALTER TABLE ONLY org_invitations\n ADD CONSTRAINT org_invitations_org_id_fkey FOREIGN KEY (org_id) REFERENCES orgs(id);\n\nALTER TABLE ONLY org_invitations\n ADD CONSTRAINT org_invitations_recipient_user_id_fkey FOREIGN KEY (recipient_user_id) REFERENCES users(id);\n\nALTER TABLE ONLY org_invitations\n ADD CONSTRAINT org_invitations_sender_user_id_fkey FOREIGN KEY (sender_user_id) REFERENCES users(id);\n\nALTER TABLE ONLY org_members\n ADD CONSTRAINT org_members_references_orgs FOREIGN KEY (org_id) REFERENCES orgs(id) ON DELETE RESTRICT;\n\nALTER TABLE ONLY org_members\n ADD CONSTRAINT org_members_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE RESTRICT;\n\nALTER TABLE ONLY out_of_band_migrations_errors\n ADD CONSTRAINT out_of_band_migrations_errors_migration_id_fkey FOREIGN KEY (migration_id) REFERENCES out_of_band_migrations(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY product_licenses\n ADD CONSTRAINT product_licenses_product_subscription_id_fkey FOREIGN KEY (product_subscription_id) REFERENCES product_subscriptions(id);\n\nALTER TABLE ONLY product_subscriptions\n ADD CONSTRAINT product_subscriptions_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id);\n\nALTER TABLE ONLY registry_extension_releases\n ADD CONSTRAINT registry_extension_releases_creator_user_id_fkey FOREIGN KEY (creator_user_id) REFERENCES users(id);\n\nALTER TABLE ONLY registry_extension_releases\n ADD CONSTRAINT registry_extension_releases_registry_extension_id_fkey FOREIGN KEY (registry_extension_id) REFERENCES registry_extensions(id) ON UPDATE CASCADE ON DELETE CASCADE;\n\nALTER TABLE ONLY registry_extensions\n ADD CONSTRAINT registry_extensions_publisher_org_id_fkey FOREIGN KEY (publisher_org_id) REFERENCES orgs(id);\n\nALTER TABLE ONLY registry_extensions\n ADD CONSTRAINT registry_extensions_publisher_user_id_fkey FOREIGN KEY (publisher_user_id) REFERENCES users(id);\n\nALTER TABLE ONLY saved_searches\n ADD CONSTRAINT saved_searches_org_id_fkey FOREIGN KEY (org_id) REFERENCES orgs(id);\n\nALTER TABLE ONLY saved_searches\n ADD CONSTRAINT saved_searches_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id);\n\nALTER TABLE ONLY search_context_repos\n ADD CONSTRAINT search_context_repos_repo_id_fk FOREIGN KEY (repo_id) REFERENCES repo(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY search_context_repos\n ADD CONSTRAINT search_context_repos_search_context_id_fk FOREIGN KEY (search_context_id) REFERENCES search_contexts(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY search_contexts\n ADD CONSTRAINT search_contexts_namespace_org_id_fk FOREIGN KEY (namespace_org_id) REFERENCES orgs(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY search_contexts\n ADD CONSTRAINT search_contexts_namespace_user_id_fk FOREIGN KEY (namespace_user_id) REFERENCES users(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY settings\n ADD CONSTRAINT settings_author_user_id_fkey FOREIGN KEY (author_user_id) REFERENCES users(id) ON DELETE RESTRICT;\n\nALTER TABLE ONLY settings\n ADD CONSTRAINT settings_references_orgs FOREIGN KEY (org_id) REFERENCES orgs(id) ON DELETE RESTRICT;\n\nALTER TABLE ONLY settings\n ADD CONSTRAINT settings_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE RESTRICT;\n\nALTER TABLE ONLY survey_responses\n ADD CONSTRAINT survey_responses_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id);\n\nALTER TABLE ONLY user_credentials\n ADD CONSTRAINT user_credentials_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE DEFERRABLE;\n\nALTER TABLE ONLY user_emails\n ADD CONSTRAINT user_emails_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id);\n\nALTER TABLE ONLY user_external_accounts\n ADD CONSTRAINT user_external_accounts_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id);\n\nALTER TABLE ONLY user_public_repos\n ADD CONSTRAINT user_public_repos_repo_id_fkey FOREIGN KEY (repo_id) REFERENCES repo(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY user_public_repos\n ADD CONSTRAINT user_public_repos_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;\n\nINSERT INTO out_of_band_migrations VALUES (3, 'core-application', 'frontend-db.external-services', 'Encrypt configuration', 0, '2021-10-08 16:09:36.889968+00', NULL, true, false, false, 3, 26, NULL, NULL);\nINSERT INTO out_of_band_migrations VALUES (6, 'core-application', 'frontend-db.external-accounts', 'Encrypt auth data', 0, '2021-10-08 16:09:36.986936+00', NULL, true, false, false, 3, 26, NULL, NULL);\nINSERT INTO out_of_band_migrations VALUES (1, 'code-intelligence', 'codeintel-db.lsif_data_documents', 'Populate num_diagnostics from gob-encoded payload', 0, '2021-06-03 23:21:34.031614+00', NULL, true, false, true, 3, 25, NULL, NULL);\nINSERT INTO out_of_band_migrations VALUES (2, 'campaigns', 'frontend-db.authenticators', 'Prepare for SSH pushes to code hosts', 0, '2021-10-08 16:09:36.662797+00', NULL, true, false, true, 3, 26, NULL, NULL);\nINSERT INTO out_of_band_migrations VALUES (4, 'code-intelligence', 'codeintel-db.lsif_data_definitions', 'Populate num_locations from gob-encoded payload', 0, '2021-10-08 16:09:36.958858+00', NULL, true, false, true, 3, 26, NULL, NULL);\nINSERT INTO out_of_band_migrations VALUES (5, 'code-intelligence', 'codeintel-db.lsif_data_references', 'Populate num_locations from gob-encoded payload', 0, '2021-10-08 16:09:36.958858+00', NULL, true, false, true, 3, 26, NULL, NULL);\nINSERT INTO out_of_band_migrations VALUES (7, 'code-intelligence', 'codeintel-db.lsif_data_documents', 'Split payload into multiple columns', 0, '2021-10-08 16:09:36.999803+00', NULL, false, false, true, 3, 27, NULL, NULL);\nINSERT INTO out_of_band_migrations VALUES (8, 'code-intelligence', 'frontend-db.lsif_uploads', 'Backfill committed_at', 0, '2021-10-08 16:09:37.097218+00', NULL, true, false, true, 3, 28, NULL, NULL);\nINSERT INTO out_of_band_migrations VALUES (9, 'batch-changes', 'frontend-db.user-credentials', 'Encrypt batch changes user credentials', 0, '2021-10-08 16:09:37.127756+00', NULL, false, false, true, 3, 28, NULL, NULL);\nINSERT INTO out_of_band_migrations VALUES (10, 'batch-changes', 'frontend-db.site-credentials', 'Encrypt batch changes site credentials', 0, '2021-10-08 16:09:37.157552+00', NULL, false, false, true, 3, 28, NULL, NULL);\n\nSELECT pg_catalog.setval('out_of_band_migrations_id_seq', 1, false);", + "DownQuery": "-- Nothing", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + -1528395834 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395835, + "Name": "cohort id", + "UpQuery": "ALTER TABLE event_logs\nADD COLUMN cohort_id date;", + "DownQuery": "ALTER TABLE event_logs\nDROP COLUMN cohort_id;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395834 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395836, + "Name": "dbworkers worker hostname", + "UpQuery": "-- Note that we have to regenerate the reconciler_changesets view, as the SELECT\n-- c.* in the view definition isn't refreshed when the fields change within the\n-- changesets table.\nDROP VIEW IF EXISTS\n reconciler_changesets;\n\nALTER TABLE changesets ADD COLUMN IF NOT EXISTS worker_hostname text NOT NULL DEFAULT '';\n\nCREATE VIEW reconciler_changesets AS\n SELECT c.* FROM changesets c\n INNER JOIN repo r on r.id = c.repo_id\n WHERE\n r.deleted_at IS NULL AND\n EXISTS (\n SELECT 1 FROM batch_changes\n LEFT JOIN users namespace_user ON batch_changes.namespace_user_id = namespace_user.id\n LEFT JOIN orgs namespace_org ON batch_changes.namespace_org_id = namespace_org.id\n WHERE\n c.batch_change_ids ? batch_changes.id::text AND\n namespace_user.deleted_at IS NULL AND\n namespace_org.deleted_at IS NULL\n )\n;\n\nALTER TABLE changeset_jobs ADD COLUMN worker_hostname text NOT NULL DEFAULT '';\nALTER TABLE cm_action_jobs ADD COLUMN IF NOT EXISTS worker_hostname text NOT NULL DEFAULT '';\nALTER TABLE cm_trigger_jobs ADD COLUMN IF NOT EXISTS worker_hostname text NOT NULL DEFAULT '';\nALTER TABLE external_service_sync_jobs ADD COLUMN IF NOT EXISTS worker_hostname text NOT NULL DEFAULT '';\nALTER TABLE insights_query_runner_jobs ADD COLUMN IF NOT EXISTS worker_hostname text NOT NULL DEFAULT '';\nALTER TABLE lsif_dependency_indexing_jobs ADD COLUMN IF NOT EXISTS worker_hostname text NOT NULL DEFAULT '';\nALTER TABLE lsif_indexes ADD COLUMN IF NOT EXISTS worker_hostname text NOT NULL DEFAULT '';\nALTER TABLE lsif_uploads ADD COLUMN IF NOT EXISTS worker_hostname text NOT NULL DEFAULT '';", + "DownQuery": "-- Note that we have to regenerate the reconciler_changesets view, as the SELECT\n-- c.* in the view definition isn't refreshed when the fields change within the\n-- changesets table.\nDROP VIEW IF EXISTS\n reconciler_changesets;\n\nALTER TABLE changesets DROP COLUMN IF EXISTS worker_hostname;\n\nCREATE VIEW reconciler_changesets AS\n SELECT c.* FROM changesets c\n INNER JOIN repo r on r.id = c.repo_id\n WHERE\n r.deleted_at IS NULL AND\n EXISTS (\n SELECT 1 FROM batch_changes\n LEFT JOIN users namespace_user ON batch_changes.namespace_user_id = namespace_user.id\n LEFT JOIN orgs namespace_org ON batch_changes.namespace_org_id = namespace_org.id\n WHERE\n c.batch_change_ids ? batch_changes.id::text AND\n namespace_user.deleted_at IS NULL AND\n namespace_org.deleted_at IS NULL\n )\n;\n\nALTER TABLE changeset_jobs DROP COLUMN IF EXISTS worker_hostname;\nALTER TABLE cm_action_jobs DROP COLUMN IF EXISTS worker_hostname;\nALTER TABLE cm_trigger_jobs DROP COLUMN IF EXISTS worker_hostname;\nALTER TABLE external_service_sync_jobs DROP COLUMN IF EXISTS worker_hostname;\nALTER TABLE insights_query_runner_jobs DROP COLUMN IF EXISTS worker_hostname;\nALTER TABLE lsif_dependency_indexing_jobs DROP COLUMN IF EXISTS worker_hostname;\nALTER TABLE lsif_indexes DROP COLUMN IF EXISTS worker_hostname;\nALTER TABLE lsif_uploads DROP COLUMN IF EXISTS worker_hostname;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395835 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395837, + "Name": "mark unmigrated credentials", + "UpQuery": "-- Previously, we conflated unmigrated user and site credentials with\n-- unencrypted ones. Instead, we should separate these states with a placeholder\n-- so the out of band migration responsible for encrypting credentials reports\n-- its progress correctly.\n\nUPDATE\n user_credentials\nSET\n encryption_key_id = 'unmigrated'\nWHERE\n encryption_key_id = '';\n\nUPDATE\n batch_changes_site_credentials\nSET\n encryption_key_id = 'unmigrated'\nWHERE\n encryption_key_id = '';", + "DownQuery": "UPDATE\n user_credentials\nSET\n encryption_key_id = ''\nWHERE\n encryption_key_id = 'unmigrated';\n\nUPDATE\n batch_changes_site_credentials\nSET\n encryption_key_id = ''\nWHERE\n encryption_key_id = 'unmigrated';", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395836 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395838, + "Name": "add blocked column to repo table", + "UpQuery": "ALTER TABLE IF EXISTS repo ADD COLUMN blocked jsonb;\n\nCREATE OR REPLACE FUNCTION repo_block(reason text, at timestamptz) RETURNS jsonb AS\n$$\nSELECT jsonb_build_object(\n 'reason', reason,\n 'at', extract(epoch from timezone('utc', at))::bigint\n);\n$$ LANGUAGE SQL STRICT IMMUTABLE;\n\nCREATE INDEX repo_blocked_idx ON repo USING BTREE ((blocked IS NOT NULL));\nCREATE INDEX repo_is_not_blocked_idx ON repo USING BTREE ((blocked IS NULL));", + "DownQuery": "DROP INDEX IF EXISTS repo_is_blocked_idx;\nDROP INDEX IF EXISTS repo_is_not_blocked_idx;\n\nDROP FUNCTION IF EXISTS repo_block;\n\nALTER TABLE IF EXISTS repo DROP COLUMN IF EXISTS blocked;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395837 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395839, + "Name": "ui publish state", + "UpQuery": "CREATE TYPE\n batch_changes_changeset_ui_publication_state\nAS ENUM (\n 'UNPUBLISHED',\n 'DRAFT',\n 'PUBLISHED'\n);\n\n-- Note that we have to regenerate the reconciler_changesets view, as the SELECT\n-- c.* in the view definition isn't refreshed when the fields change within the\n-- changesets table.\nDROP VIEW IF EXISTS\n reconciler_changesets;\n\nALTER TABLE\n changesets\nADD COLUMN IF NOT EXISTS\n ui_publication_state batch_changes_changeset_ui_publication_state NULL DEFAULT NULL;\n\nCREATE VIEW reconciler_changesets AS\n SELECT c.* FROM changesets c\n INNER JOIN repo r on r.id = c.repo_id\n WHERE\n r.deleted_at IS NULL AND\n EXISTS (\n SELECT 1 FROM batch_changes\n LEFT JOIN users namespace_user ON batch_changes.namespace_user_id = namespace_user.id\n LEFT JOIN orgs namespace_org ON batch_changes.namespace_org_id = namespace_org.id\n WHERE\n c.batch_change_ids ? batch_changes.id::text AND\n namespace_user.deleted_at IS NULL AND\n namespace_org.deleted_at IS NULL\n )\n;", + "DownQuery": "-- Note that we have to regenerate the reconciler_changesets view, as the SELECT\n-- c.* in the view definition isn't refreshed when the fields change within the\n-- changesets table.\nDROP VIEW IF EXISTS\n reconciler_changesets;\n\nALTER TABLE\n changesets\nDROP COLUMN IF EXISTS\n ui_publication_state;\n\nDROP TYPE IF EXISTS\n batch_changes_changeset_ui_publication_state;\n\nCREATE VIEW reconciler_changesets AS\n SELECT c.* FROM changesets c\n INNER JOIN repo r on r.id = c.repo_id\n WHERE\n r.deleted_at IS NULL AND\n EXISTS (\n SELECT 1 FROM batch_changes\n LEFT JOIN users namespace_user ON batch_changes.namespace_user_id = namespace_user.id\n LEFT JOIN orgs namespace_org ON batch_changes.namespace_org_id = namespace_org.id\n WHERE\n c.batch_change_ids ? batch_changes.id::text AND\n namespace_user.deleted_at IS NULL AND\n namespace_org.deleted_at IS NULL\n )\n;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395838 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395840, + "Name": "create sg service role", + "UpQuery": "-- We encountered performance issues for our use cases when we deployed\n-- RLS to production. We made the decision to back that approach out and\n-- solve the security concerns in application-level code instead.\n--\n-- ref migrations/frontend/1528395860_remove_repo_table_policy.up.sql\n-- ref migrations/frontend/1528395861_remove_sg_service_grants.up.sql\n-- ref migrations/frontend/1528395862_remove_sg_service_role.up.sql", + "DownQuery": "-- We encountered performance issues for our use cases when we deployed\n-- RLS to production. We made the decision to back that approach out and\n-- solve the security concerns in application-level code instead.\n--\n-- ref migrations/frontend/1528395860_remove_repo_table_policy.up.sql\n-- ref migrations/frontend/1528395861_remove_sg_service_grants.up.sql\n-- ref migrations/frontend/1528395862_remove_sg_service_role.up.sql", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395839 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395841, + "Name": "add repo table policy", + "UpQuery": "-- We encountered performance issues for our use cases when we deployed\n-- RLS to production. We made the decision to back that approach out and\n-- solve the security concerns in application-level code instead.\n--\n-- ref migrations/frontend/1528395860_remove_repo_table_policy.up.sql\n-- ref migrations/frontend/1528395861_remove_sg_service_grants.up.sql\n-- ref migrations/frontend/1528395862_remove_sg_service_role.up.sql", + "DownQuery": "-- We encountered performance issues for our use cases when we deployed\n-- RLS to production. We made the decision to back that approach out and\n-- solve the security concerns in application-level code instead.\n--\n-- ref migrations/frontend/1528395860_remove_repo_table_policy.up.sql\n-- ref migrations/frontend/1528395861_remove_sg_service_grants.up.sql\n-- ref migrations/frontend/1528395862_remove_sg_service_role.up.sql", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395840 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395842, + "Name": "add settings user id index", + "UpQuery": "CREATE INDEX IF NOT EXISTS settings_user_id_idx ON settings USING BTREE (user_id);", + "DownQuery": "DROP INDEX IF EXISTS settings_user_id_idx;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395841 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395843, + "Name": "batch spec executions table", + "UpQuery": "CREATE TABLE IF NOT EXISTS batch_spec_executions (\n id BIGSERIAL PRIMARY KEY,\n state TEXT DEFAULT 'queued',\n failure_message TEXT,\n started_at TIMESTAMP WITH TIME ZONE,\n finished_at TIMESTAMP WITH TIME ZONE,\n process_after TIMESTAMP WITH TIME ZONE,\n num_resets INTEGER NOT NULL DEFAULT 0,\n num_failures INTEGER NOT NULL DEFAULT 0,\n execution_logs JSON[],\n worker_hostname TEXT NOT NULL DEFAULT '',\n\n created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),\n updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),\n\n batch_spec TEXT NOT NULL,\n batch_spec_id integer REFERENCES batch_specs(id)\n);", + "DownQuery": "DROP TABLE IF EXISTS batch_spec_executions;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395842 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395844, + "Name": "add user id to bach spec executions", + "UpQuery": "ALTER TABLE IF EXISTS batch_spec_executions ADD COLUMN IF NOT EXISTS user_id int REFERENCES users(id) DEFERRABLE;", + "DownQuery": "ALTER TABLE IF EXISTS batch_spec_executions DROP COLUMN IF EXISTS user_id;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395843 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395845, + "Name": "batch spec execution namespace", + "UpQuery": "ALTER TABLE IF EXISTS batch_spec_executions ADD COLUMN IF NOT EXISTS namespace_user_id integer REFERENCES users(id) DEFERRABLE;\nALTER TABLE IF EXISTS batch_spec_executions ADD COLUMN IF NOT EXISTS namespace_org_id integer REFERENCES orgs(id) DEFERRABLE;\nUPDATE batch_spec_executions SET namespace_user_id = user_id;\nALTER TABLE IF EXISTS batch_spec_executions ADD CONSTRAINT batch_spec_executions_has_1_namespace CHECK ((namespace_user_id IS NULL) \u003c\u003e (namespace_org_id IS NULL));", + "DownQuery": "ALTER TABLE IF EXISTS batch_spec_executions DROP CONSTRAINT batch_spec_executions_has_1_namespace;\nALTER TABLE IF EXISTS batch_spec_executions DROP COLUMN IF EXISTS namespace_user_id;\nALTER TABLE IF EXISTS batch_spec_executions DROP COLUMN IF EXISTS namespace_org_id;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395844 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395846, + "Name": "expand visible lsif uploads", + "UpQuery": "ALTER TABLE lsif_uploads_visible_at_tip ADD COLUMN branch_or_tag_name text NOT NULL DEFAULT '';\nALTER TABLE lsif_uploads_visible_at_tip ADD COLUMN is_default_branch boolean NOT NULL DEFAULT false;\n\nCOMMENT ON COLUMN lsif_uploads_visible_at_tip.upload_id IS 'The identifier of the upload visible from the tip of the specified branch or tag.';\nCOMMENT ON COLUMN lsif_uploads_visible_at_tip.branch_or_tag_name IS 'The name of the branch or tag.';\nCOMMENT ON COLUMN lsif_uploads_visible_at_tip.is_default_branch IS 'Whether the specified branch is the default of the repository. Always false for tags.';\n\n-- Update all existing visible uploads to be the default branch, which is true until\n-- we start recalcaulting the commit graph with tags and non-default branches.\nUPDATE lsif_uploads_visible_at_tip SET is_default_branch = true;\n\n-- Mark every graph as dirty so we recalculate retention correctly once the instance\n-- boots up.\nUPDATE lsif_dirty_repositories SET dirty_token = dirty_token + 1;", + "DownQuery": "ALTER TABLE lsif_uploads_visible_at_tip DROP COLUMN branch_or_tag_name;\nALTER TABLE lsif_uploads_visible_at_tip DROP COLUMN is_default_branch;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395845 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395847, + "Name": "codeintel eviction ages", + "UpQuery": "CREATE TABLE lsif_retention_configuration (\n id serial PRIMARY KEY,\n repository_id integer UNIQUE NOT NULL REFERENCES repo(id) ON DELETE CASCADE,\n max_age_for_non_stale_branches_seconds integer NOT NULL,\n max_age_for_non_stale_tags_seconds integer NOT NULL\n);\n\nCOMMENT ON TABLE lsif_retention_configuration IS 'Stores the retention policy of code intellience data for a repository.';\nCOMMENT ON COLUMN lsif_retention_configuration.max_age_for_non_stale_branches_seconds IS 'The number of seconds since the last modification of a branch until it is considered stale.';\nCOMMENT ON COLUMN lsif_retention_configuration.max_age_for_non_stale_tags_seconds IS 'The nujmber of seconds since the commit date of a tagged commit until it is considered stale.';", + "DownQuery": "DROP TABLE lsif_retention_configuration;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395846 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395848, + "Name": "drop default repos", + "UpQuery": "DROP TABLE IF EXISTS default_repos;", + "DownQuery": "CREATE TABLE default_repos (\n repo_id integer NOT NULL\n);", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395847 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395849, + "Name": "drop unused indexes", + "UpQuery": "-- Covered by external_service_repos_idx (external_service_id, repo_id)\nDROP INDEX IF EXISTS external_service_repos_external_service_id;", + "DownQuery": "CREATE INDEX external_service_repos_external_service_id ON external_service_repos USING btree (external_service_id);", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395848 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395850, + "Name": "add rand id to batch spec executions", + "UpQuery": "ALTER TABLE IF EXISTS batch_spec_executions ADD COLUMN IF NOT EXISTS rand_id text NOT NULL;\n\nCREATE INDEX batch_spec_executions_rand_id ON batch_spec_executions USING btree (rand_id);", + "DownQuery": "DROP INDEX IF EXISTS batch_spec_executions_rand_id;\n\nALTER TABLE IF EXISTS batch_spec_executions DROP COLUMN IF EXISTS rand_id;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395849 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395851, + "Name": "workerutil last updated at", + "UpQuery": "ALTER TABLE batch_spec_executions ADD COLUMN last_heartbeat_at timestamp with time zone;\nALTER TABLE changeset_jobs ADD COLUMN last_heartbeat_at timestamp with time zone;\nALTER TABLE changesets ADD COLUMN last_heartbeat_at timestamp with time zone;\nALTER TABLE cm_action_jobs ADD COLUMN last_heartbeat_at timestamp with time zone;\nALTER TABLE cm_trigger_jobs ADD COLUMN last_heartbeat_at timestamp with time zone;\nALTER TABLE external_service_sync_jobs ADD COLUMN last_heartbeat_at timestamp with time zone;\nALTER TABLE insights_query_runner_jobs ADD COLUMN last_heartbeat_at timestamp with time zone;\nALTER TABLE lsif_dependency_indexing_jobs ADD COLUMN last_heartbeat_at timestamp with time zone;\nALTER TABLE lsif_indexes ADD COLUMN last_heartbeat_at timestamp with time zone;\nALTER TABLE lsif_uploads ADD COLUMN last_heartbeat_at timestamp with time zone;", + "DownQuery": "ALTER TABLE batch_spec_executions DROP COLUMN last_heartbeat_at;\nALTER TABLE changeset_jobs DROP COLUMN last_heartbeat_at;\nALTER TABLE changesets DROP COLUMN last_heartbeat_at;\nALTER TABLE cm_action_jobs DROP COLUMN last_heartbeat_at;\nALTER TABLE cm_trigger_jobs DROP COLUMN last_heartbeat_at;\nALTER TABLE external_service_sync_jobs DROP COLUMN last_heartbeat_at;\nALTER TABLE insights_query_runner_jobs DROP COLUMN last_heartbeat_at;\nALTER TABLE lsif_dependency_indexing_jobs DROP COLUMN last_heartbeat_at;\nALTER TABLE lsif_indexes DROP COLUMN last_heartbeat_at;\nALTER TABLE lsif_uploads DROP COLUMN last_heartbeat_at;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395850 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395852, + "Name": "lsif add covering index", + "UpQuery": "CREATE INDEX lsif_packages_scheme_name_version_dump_id ON lsif_packages(scheme, name, version, dump_id);\nDROP INDEX lsif_packages_scheme_name_version;\n\nCREATE INDEX lsif_references_scheme_name_version_dump_id ON lsif_references(scheme, name, version, dump_id);\nDROP INDEX lsif_references_package;", + "DownQuery": "CREATE INDEX lsif_packages_scheme_name_version ON lsif_packages(scheme, name, version);\nDROP INDEX lsif_packages_scheme_name_version_dump_id;\n\nCREATE INDEX lsif_references_package ON lsif_references(scheme, name, version);\nDROP INDEX lsif_references_scheme_name_version_dump_id;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395851 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395853, + "Name": "add deleting state", + "UpQuery": "DROP VIEW lsif_dumps_with_repository_name;\nDROP VIEW lsif_dumps;\n\nCREATE VIEW lsif_dumps AS SELECT u.id,\n u.commit,\n u.root,\n u.uploaded_at,\n u.state,\n u.failure_message,\n u.started_at,\n u.finished_at,\n u.repository_id,\n u.indexer,\n u.num_parts,\n u.uploaded_parts,\n u.process_after,\n u.num_resets,\n u.upload_size,\n u.num_failures,\n u.associated_index_id,\n u.finished_at AS processed_at\nFROM lsif_uploads u\nWHERE u.state = 'completed'::text OR u.state = 'deleting';\n\nCREATE VIEW lsif_dumps_with_repository_name AS SELECT u.id,\n u.commit,\n u.root,\n u.uploaded_at,\n u.state,\n u.failure_message,\n u.started_at,\n u.finished_at,\n u.repository_id,\n u.indexer,\n u.num_parts,\n u.uploaded_parts,\n u.process_after,\n u.num_resets,\n u.upload_size,\n u.num_failures,\n u.associated_index_id,\n u.processed_at,\n r.name AS repository_name\nFROM lsif_dumps u\nJOIN repo r ON r.id = u.repository_id\nWHERE r.deleted_at IS NULL;", + "DownQuery": "DROP VIEW lsif_dumps_with_repository_name;\nDROP VIEW lsif_dumps;\n\nCREATE VIEW lsif_dumps AS SELECT u.id,\n u.commit,\n u.root,\n u.uploaded_at,\n u.state,\n u.failure_message,\n u.started_at,\n u.finished_at,\n u.repository_id,\n u.indexer,\n u.num_parts,\n u.uploaded_parts,\n u.process_after,\n u.num_resets,\n u.upload_size,\n u.num_failures,\n u.associated_index_id,\n u.finished_at AS processed_at\nFROM lsif_uploads u WHERE u.state = 'completed'::text;\n\nCREATE VIEW lsif_dumps_with_repository_name AS SELECT u.id,\n u.commit,\n u.root,\n u.uploaded_at,\n u.state,\n u.failure_message,\n u.started_at,\n u.finished_at,\n u.repository_id,\n u.indexer,\n u.num_parts,\n u.uploaded_parts,\n u.process_after,\n u.num_resets,\n u.upload_size,\n u.num_failures,\n u.associated_index_id,\n u.processed_at,\n r.name AS repository_name\nFROM lsif_dumps u JOIN repo r ON r.id = u.repository_id WHERE r.deleted_at IS NULL;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395852 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395854, + "Name": "add priority insights queryrunner", + "UpQuery": "ALTER TABLE insights_query_runner_jobs\n ADD COLUMN priority INT NOT NULL DEFAULT 1;\n\nALTER TABLE insights_query_runner_jobs\n ADD COLUMN cost INT NOT NULL DEFAULT 500;\n\nCOMMENT ON COLUMN insights_query_runner_jobs.priority IS 'Integer representing a category of priority for this query. Priority in this context is ambiguously defined for consumers to decide an interpretation.';\nCOMMENT ON COLUMN insights_query_runner_jobs.cost IS 'Integer representing a cost approximation of executing this search query.';\n\nCREATE INDEX insights_query_runner_jobs_priority_idx on insights_query_runner_jobs(priority);\nCREATE INDEX insights_query_runner_jobs_cost_idx on insights_query_runner_jobs(cost);", + "DownQuery": "ALTER TABLE insights_query_runner_jobs\n DROP COLUMN priority;\n\nALTER TABLE insights_query_runner_jobs\n DROP COLUMN cost;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395853 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395855, + "Name": "add-missing-execution-logs-cols", + "UpQuery": "ALTER TABLE IF EXISTS cm_trigger_jobs ADD COLUMN IF NOT EXISTS execution_logs JSON[];\nALTER TABLE IF EXISTS cm_action_jobs ADD COLUMN IF NOT EXISTS execution_logs JSON[];", + "DownQuery": "ALTER TABLE IF EXISTS cm_trigger_jobs DROP COLUMN IF EXISTS execution_logs;\nALTER TABLE IF EXISTS cm_action_jobs DROP COLUMN IF EXISTS execution_logs;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395854 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395856, + "Name": "add missing execution logs cols for real", + "UpQuery": "ALTER TABLE IF EXISTS lsif_uploads ADD COLUMN IF NOT EXISTS execution_logs JSON[];", + "DownQuery": "ALTER TABLE IF EXISTS lsif_uploads DROP COLUMN IF EXISTS execution_logs;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395855 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395857, + "Name": "last fetched", + "UpQuery": "ALTER TABLE gitserver_repos ADD COLUMN last_fetched TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now();", + "DownQuery": "ALTER TABLE gitserver_repos DROP COLUMN last_fetched;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395856 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395858, + "Name": "drop lsif indexable repositories", + "UpQuery": "DROP TABLE IF EXISTS lsif_indexable_repositories;", + "DownQuery": "CREATE TABLE lsif_indexable_repositories (\n id SERIAL PRIMARY KEY NOT NULL,\n repository_id integer NOT NULL,\n search_count integer DEFAULT 0 NOT NULL,\n precise_count integer DEFAULT 0 NOT NULL,\n last_index_enqueued_at timestamp with time zone,\n last_updated_at timestamp with time zone DEFAULT now() NOT NULL,\n enabled boolean\n);\n\nCREATE UNIQUE INDEX lsif_indexable_repositories_repository_id_key ON lsif_indexable_repositories (repository_id);", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395857 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395859, + "Name": "make batch spec executions batch spec id deferrable", + "UpQuery": "ALTER TABLE IF EXISTS batch_spec_executions ALTER CONSTRAINT batch_spec_executions_batch_spec_id_fkey DEFERRABLE;", + "DownQuery": "ALTER TABLE IF EXISTS batch_spec_executions ALTER CONSTRAINT batch_spec_executions_batch_spec_id_fkey NOT DEFERRABLE;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395858 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395860, + "Name": "remove repo table policy", + "UpQuery": "-- This removes the row-level security policy (if present), and disables RLS on\n-- the repo table. Both operations are idempotent.\nDROP POLICY IF EXISTS sg_repo_access_policy ON repo;\nALTER TABLE repo DISABLE ROW LEVEL SECURITY;", + "DownQuery": "-- We do not recreate the policy, as we've shifted our strategy away from row-\n-- level security to application-level code. Prior migrations that created the\n-- policy have also been removed.", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395859 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395861, + "Name": "remove sg service grants", + "UpQuery": "DO $$\nBEGIN\n REVOKE ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public FROM sg_service;\n REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA public FROM sg_service;\n REVOKE USAGE ON SCHEMA public FROM sg_service;\nEXCEPTION WHEN undefined_object THEN\n -- Roles are visible across databases within a server, and we use templated\n -- databases for test parallelism, so it's possible in some cases for the\n -- tests to hit a case where the role can't be dropped because one of the\n -- test databases still has objects that depend on it.\nEND;\n$$;", + "DownQuery": "-- We do not recreate the grants, as we've shifted our strategy away from row-\n-- level security to application-level code. Prior migrations that created the\n-- grants have also been removed.", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395860 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395862, + "Name": "remove sg service role", + "UpQuery": "DO $$\nBEGIN\n DROP ROLE IF EXISTS sg_service;\nEXCEPTION WHEN dependent_objects_still_exist THEN\n -- Roles are visible across databases within a server, and we use templated\n -- databases for test parallelism, so it's possible in some cases for the\n -- tests to hit a case where the role can't be dropped because one of the\n -- test databases still has objects that depend on it.\nEND;\n$$;", + "DownQuery": "-- We do not recreate the role, as we've shifted our strategy away from row-\n-- level security to application-level code. Prior migrations that created the\n-- role have also been removed.", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395861 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395863, + "Name": "event logs public properties column", + "UpQuery": "ALTER TABLE IF EXISTS event_logs ADD COLUMN IF NOT EXISTS public_argument JSONB DEFAULT '{}'::jsonb NOT NULL;", + "DownQuery": "ALTER TABLE IF EXISTS event_logs DROP COLUMN IF EXISTS public_argument;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395862 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395864, + "Name": "create temporary settings", + "UpQuery": "CREATE TABLE IF NOT EXISTS temporary_settings (\n id serial NOT NULL PRIMARY KEY,\n user_id integer NOT NULL UNIQUE,\n contents jsonb,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n\n FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE\n);\n\nCOMMENT ON TABLE temporary_settings IS 'Stores per-user temporary settings used in the UI, for example, which modals have been dimissed or what theme is preferred.';\nCOMMENT ON COLUMN temporary_settings.user_id IS 'The ID of the user the settings will be saved for.';\nCOMMENT ON COLUMN temporary_settings.contents IS 'JSON-encoded temporary settings.';", + "DownQuery": "DROP TABLE IF EXISTS temporary_settings;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395863 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395865, + "Name": "insights job dependencies", + "UpQuery": "-- Insert migration here. See README.md. Highlights:\n-- * Always use IF EXISTS. eg: DROP TABLE IF EXISTS global_dep_private;\n-- * All migrations must be backward-compatible. Old versions of Sourcegraph\n-- need to be able to read/write post migration.\n-- * Historically we advised against transactions since we thought the\n-- migrate library handled it. However, it does not! /facepalm\n\nCREATE TABLE insights_query_runner_jobs_dependencies\n(\n id SERIAL NOT NULL,\n job_id INT NOT NULL,\n recording_time TIMESTAMP NOT NULL,\n PRIMARY KEY (id),\n -- The delete cascade is intentional, these records only have meaning in context of the related job row.\n CONSTRAINT insights_query_runner_jobs_dependencies_fk_job_id FOREIGN KEY (job_id) REFERENCES insights_query_runner_jobs (id) ON DELETE CASCADE\n);\n\nCOMMENT ON TABLE insights_query_runner_jobs_dependencies IS 'Stores data points for a code insight that do not need to be queried directly, but depend on the result of a query at a different point';\n\nCOMMENT ON COLUMN insights_query_runner_jobs_dependencies.job_id IS 'Foreign key to the job that owns this record.';\nCOMMENT ON COLUMN insights_query_runner_jobs_dependencies.recording_time IS 'The time for which this dependency should be recorded at using the parents value.';", + "DownQuery": "-- Insert migration here. See README.md. Highlights:\n-- * Always use IF EXISTS. eg: DROP TABLE IF EXISTS global_dep_private;\n-- * All migrations must be backward-compatible. Old versions of Sourcegraph\n-- need to be able to read/write post migration.\n-- * Historically we advised against transactions since we thought the\n-- migrate library handled it. However, it does not! /facepalm\n\nDROP TABLE IF EXISTS insights_query_runner_jobs_dependencies;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395864 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395866, + "Name": "insights queue reset", + "UpQuery": "-- Insert migration here. See README.md. Highlights:\n-- * Always use IF EXISTS. eg: DROP TABLE IF EXISTS global_dep_private;\n-- * All migrations must be backward-compatible. Old versions of Sourcegraph\n-- need to be able to read/write post migration.\n-- * Historically we advised against transactions since we thought the\n-- migrate library handled it. However, it does not! /facepalm\n\n-- This table is a queue of records that need processing for code insights. Historically this queue grows\n-- unbounded because the historical backfiller operated without state - every time it executed it would\n-- requeue all of the work again. Since then we have added enough state to the backfiller to remove this problem,\n-- but customer instances are going to be full of millions of records that will need processing before we can start\n-- fresh. To avoid this problem, we are going to ship a 'reset' in 3.31 that will clear this queue entirely.\n-- Note: This data is by design ephemeral, so there is no risk of permanent data loss here.\n\nTRUNCATE insights_query_runner_jobs CASCADE;", + "DownQuery": "-- Insert migration here. See README.md. Highlights:\n-- * Always use IF EXISTS. eg: DROP TABLE IF EXISTS global_dep_private;\n-- * All migrations must be backward-compatible. Old versions of Sourcegraph\n-- need to be able to read/write post migration.\n-- * Historically we advised against transactions since we thought the\n-- migrate library handled it. However, it does not! /facepalm", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395865 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395867, + "Name": "batch-spec-executions-cancel", + "UpQuery": "ALTER TABLE IF EXISTS batch_spec_executions ADD COLUMN IF NOT EXISTS cancel BOOL DEFAULT FALSE;", + "DownQuery": "ALTER TABLE IF EXISTS batch_spec_executions DROP COLUMN IF EXISTS cancel;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395866 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395868, + "Name": "insights queue dependencies index", + "UpQuery": "-- Insert migration here. See README.md. Highlights:\n-- * Always use IF EXISTS. eg: DROP TABLE IF EXISTS global_dep_private;\n-- * All migrations must be backward-compatible. Old versions of Sourcegraph\n-- need to be able to read/write post migration.\n-- * Historically we advised against transactions since we thought the\n-- migrate library handled it. However, it does not! /facepalm\n\nCREATE INDEX insights_query_runner_jobs_dependencies_job_id_fk_idx ON insights_query_runner_jobs_dependencies(job_id);", + "DownQuery": "-- Insert migration here. See README.md. Highlights:\n-- * Always use IF EXISTS. eg: DROP TABLE IF EXISTS global_dep_private;\n-- * All migrations must be backward-compatible. Old versions of Sourcegraph\n-- need to be able to read/write post migration.\n-- * Historically we advised against transactions since we thought the\n-- migrate library handled it. However, it does not! /facepalm\n\nDROP INDEX IF EXISTS insights_query_runner_jobs_dependencies_job_id_fk_idx;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395867 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395869, + "Name": "add lsif configuration policy", + "UpQuery": "CREATE TABLE lsif_configuration_policies (\n id SERIAL PRIMARY KEY,\n repository_id int,\n name text,\n type text NOT NULL,\n pattern text NOT NULL,\n retention_enabled boolean NOT NULL,\n retention_duration_hours int,\n retain_intermediate_commits boolean NOT NULL,\n indexing_enabled boolean NOT NULL,\n index_commit_max_age_hours int,\n index_intermediate_commits boolean NOT NULL\n);\n\nCREATE INDEX lsif_configuration_policies_repository_id ON lsif_configuration_policies(repository_id);\n\nCOMMENT ON COLUMN lsif_configuration_policies.repository_id IS 'The identifier of the repository to which this configuration policy applies. If absent, this policy is applied globally.';\nCOMMENT ON COLUMN lsif_configuration_policies.type IS 'The type of Git object (e.g., COMMIT, BRANCH, TAG).';\nCOMMENT ON COLUMN lsif_configuration_policies.pattern IS 'A pattern used to match` names of the associated Git object type.';\nCOMMENT ON COLUMN lsif_configuration_policies.retention_enabled IS 'Whether or not this configuration policy affects data retention rules.';\nCOMMENT ON COLUMN lsif_configuration_policies.retention_duration_hours IS 'The max age of data retained by this configuration policy. If null, the age is unbounded.';\nCOMMENT ON COLUMN lsif_configuration_policies.retain_intermediate_commits IS 'If the matching Git object is a branch, setting this value to true will also retain all data used to resolve queries for any commit on the matching branches. Setting this value to false will only consider the tip of the branch.';\nCOMMENT ON COLUMN lsif_configuration_policies.indexing_enabled IS 'Whether or not this configuration policy affects auto-indexing schedules.';\nCOMMENT ON COLUMN lsif_configuration_policies.index_commit_max_age_hours IS 'The max age of commits indexed by this configuration policy. If null, the age is unbounded.';\nCOMMENT ON COLUMN lsif_configuration_policies.index_intermediate_commits IS 'If the matching Git object is a branch, setting this value to true will also index all commits on the matching branches. Setting this value to false will only consider the tip of the branch.';", + "DownQuery": "DROP TABLE IF EXISTS lsif_configuration_policies;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395868 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395870, + "Name": "codeintel dependency repos", + "UpQuery": "CREATE TABLE IF NOT EXISTS lsif_dependency_repos (\n id bigserial NOT NULL PRIMARY KEY,\n name text NOT NULL,\n version text NOT NULL,\n scheme text NOT NULL,\n CONSTRAINT lsif_dependency_repos_unique_triplet\n UNIQUE (scheme, name, version)\n);", + "DownQuery": "DROP TABLE IF EXISTS lsif_dependency_repos;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395869 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395871, + "Name": "insights queue state index", + "UpQuery": "-- Insert migration here. See README.md. Highlights:\n-- * Always use IF EXISTS. eg: DROP TABLE IF EXISTS global_dep_private;\n-- * All migrations must be backward-compatible. Old versions of Sourcegraph\n-- need to be able to read/write post migration.\n-- * Historically we advised against transactions since we thought the\n-- migrate library handled it. However, it does not! /facepalm\nCREATE INDEX IF NOT EXISTS insights_query_runner_jobs_processable_priority_id ON insights_query_runner_jobs (priority, id) WHERE state = 'queued' OR state = 'errored';", + "DownQuery": "-- Insert migration here. See README.md. Highlights:\n-- * Always use IF EXISTS. eg: DROP TABLE IF EXISTS global_dep_private;\n-- * All migrations must be backward-compatible. Old versions of Sourcegraph\n-- need to be able to read/write post migration.\n-- * Historically we advised against transactions since we thought the\n-- migrate library handled it. However, it does not! /facepalm\n\ndrop index if exists insights_query_runner_jobs_processable_priority_id;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395870 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395872, + "Name": "lsif upload reference counts", + "UpQuery": "ALTER TABLE lsif_uploads ADD COLUMN num_references int;\nCOMMENT ON COLUMN lsif_uploads.num_references IS 'The number of references to this upload data from other upload records (via lsif_references).';", + "DownQuery": "ALTER TABLE lsif_uploads DROP COLUMN num_references;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395871 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395873, + "Name": "lsif upload reference counts oob migration", + "UpQuery": "INSERT INTO out_of_band_migrations (id, team, component, description, introduced_version_major, introduced_version_minor, non_destructive)\nVALUES (11, 'code-intelligence', 'lsif_uploads.num_references', 'Backfill LSIF upload reference counts', 3, 22, true)\nON CONFLICT DO NOTHING;", + "DownQuery": "-- Do not remove oob migration when downgrading", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395872 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395874, + "Name": "lsif nearest uploads indexes", + "UpQuery": "-- Allow for lookup from upload id to commits that the upload can resolve queries for.\nCREATE INDEX lsif_nearest_uploads_uploads ON lsif_nearest_uploads USING GIN(uploads);\n\n-- Allow for lookup from commit to the set of commits that have analogous nearest uploads.\nCREATE INDEX lsif_nearest_uploads_links_repository_id_ancestor_commit_bytea ON lsif_nearest_uploads_links(repository_id, ancestor_commit_bytea);", + "DownQuery": "DROP INDEX lsif_nearest_uploads_uploads;\nDROP INDEX lsif_nearest_uploads_links_repository_id_ancestor_commit_bytea;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395873 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395875, + "Name": "lsif upload expired flag", + "UpQuery": "-- Drop dependent views\nDROP VIEW lsif_dumps_with_repository_name;\nDROP VIEW lsif_dumps;\nDROP VIEW lsif_uploads_with_repository_name;\n\n-- Add new column\nALTER TABLE lsif_uploads ADD COLUMN expired boolean not null default false;\nCOMMENT ON COLUMN lsif_uploads.expired IS 'Whether or not this upload data is no longer protected by any data retention policy.';\n\n-- Update view definitions to include new fields\nCREATE VIEW lsif_uploads_with_repository_name AS\n SELECT u.id,\n u.commit,\n u.root,\n u.uploaded_at,\n u.state,\n u.failure_message,\n u.started_at,\n u.finished_at,\n u.repository_id,\n u.indexer,\n u.num_parts,\n u.uploaded_parts,\n u.process_after,\n u.num_resets,\n u.upload_size,\n u.num_failures,\n u.associated_index_id,\n u.expired,\n r.name AS repository_name\n FROM lsif_uploads u\n JOIN repo r ON r.id = u.repository_id\n WHERE r.deleted_at IS NULL;\n\nCREATE VIEW lsif_dumps AS\n SELECT u.id,\n u.commit,\n u.root,\n u.uploaded_at,\n u.state,\n u.failure_message,\n u.started_at,\n u.finished_at,\n u.repository_id,\n u.indexer,\n u.num_parts,\n u.uploaded_parts,\n u.process_after,\n u.num_resets,\n u.upload_size,\n u.num_failures,\n u.associated_index_id,\n u.expired,\n u.finished_at AS processed_at\n FROM lsif_uploads u\n WHERE u.state = 'completed'::text OR u.state = 'deleting'::text;\n\nCREATE VIEW lsif_dumps_with_repository_name AS\n SELECT u.id,\n u.commit,\n u.root,\n u.uploaded_at,\n u.state,\n u.failure_message,\n u.started_at,\n u.finished_at,\n u.repository_id,\n u.indexer,\n u.num_parts,\n u.uploaded_parts,\n u.process_after,\n u.num_resets,\n u.upload_size,\n u.num_failures,\n u.associated_index_id,\n u.expired,\n u.processed_at,\n r.name AS repository_name\n FROM lsif_dumps u\n JOIN repo r ON r.id = u.repository_id\n WHERE r.deleted_at IS NULL;", + "DownQuery": "-- Drop dependent views\nDROP VIEW lsif_dumps_with_repository_name;\nDROP VIEW lsif_dumps;\nDROP VIEW lsif_uploads_with_repository_name;\n\n-- Drop new column\nALTER TABLE lsif_uploads DROP COLUMN expired;\n\n-- Restore old views\nCREATE VIEW lsif_uploads_with_repository_name AS\n SELECT u.id,\n u.commit,\n u.root,\n u.uploaded_at,\n u.state,\n u.failure_message,\n u.started_at,\n u.finished_at,\n u.repository_id,\n u.indexer,\n u.num_parts,\n u.uploaded_parts,\n u.process_after,\n u.num_resets,\n u.upload_size,\n u.num_failures,\n u.associated_index_id,\n r.name AS repository_name\n FROM lsif_uploads u\n JOIN repo r ON r.id = u.repository_id\n WHERE r.deleted_at IS NULL;\n\nCREATE VIEW lsif_dumps AS\n SELECT u.id,\n u.commit,\n u.root,\n u.uploaded_at,\n u.state,\n u.failure_message,\n u.started_at,\n u.finished_at,\n u.repository_id,\n u.indexer,\n u.num_parts,\n u.uploaded_parts,\n u.process_after,\n u.num_resets,\n u.upload_size,\n u.num_failures,\n u.associated_index_id,\n u.finished_at AS processed_at\n FROM lsif_uploads u\n WHERE u.state = 'completed'::text OR u.state = 'deleting'::text;\n\nCREATE VIEW lsif_dumps_with_repository_name AS\n SELECT u.id,\n u.commit,\n u.root,\n u.uploaded_at,\n u.state,\n u.failure_message,\n u.started_at,\n u.finished_at,\n u.repository_id,\n u.indexer,\n u.num_parts,\n u.uploaded_parts,\n u.process_after,\n u.num_resets,\n u.upload_size,\n u.num_failures,\n u.associated_index_id,\n u.processed_at,\n r.name AS repository_name\n FROM lsif_dumps u\n JOIN repo r ON r.id = u.repository_id\n WHERE r.deleted_at IS NULL;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395874 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395876, + "Name": "lsif last retention scan", + "UpQuery": "-- Drop dependent views\nDROP VIEW lsif_dumps_with_repository_name;\nDROP VIEW lsif_dumps;\nDROP VIEW lsif_uploads_with_repository_name;\n\n-- Create table to rate limit data retention scans of a repository\nCREATE TABLE lsif_last_retention_scan (\n repository_id int NOT NULL,\n last_retention_scan_at timestamp with time zone NOT NULL,\n\n PRIMARY KEY(repository_id)\n);\nCOMMENT ON TABLE lsif_last_retention_scan IS 'Tracks the last time uploads a repository were checked against data retention policies.';\nCOMMENT ON COLUMN lsif_last_retention_scan.last_retention_scan_at IS 'The last time uploads of this repository were checked against data retention policies.';\n\n-- Add column to rate limit scanning of individual upload records\nALTER TABLE lsif_uploads ADD COLUMN last_retention_scan_at timestamp with time zone;\nCOMMENT ON COLUMN lsif_uploads.last_retention_scan_at IS 'The last time this upload was checked against data retention policies.';\n\n-- Update view definitions to include new fields\nCREATE VIEW lsif_uploads_with_repository_name AS\n SELECT u.id,\n u.commit,\n u.root,\n u.uploaded_at,\n u.state,\n u.failure_message,\n u.started_at,\n u.finished_at,\n u.repository_id,\n u.indexer,\n u.num_parts,\n u.uploaded_parts,\n u.process_after,\n u.num_resets,\n u.upload_size,\n u.num_failures,\n u.associated_index_id,\n u.expired,\n r.name AS repository_name\n FROM lsif_uploads u\n JOIN repo r ON r.id = u.repository_id\n WHERE r.deleted_at IS NULL;\n\nCREATE VIEW lsif_dumps AS\n SELECT u.id,\n u.commit,\n u.root,\n u.uploaded_at,\n u.state,\n u.failure_message,\n u.started_at,\n u.finished_at,\n u.repository_id,\n u.indexer,\n u.num_parts,\n u.uploaded_parts,\n u.process_after,\n u.num_resets,\n u.upload_size,\n u.num_failures,\n u.associated_index_id,\n u.expired,\n u.finished_at AS processed_at\n FROM lsif_uploads u\n WHERE u.state = 'completed'::text OR u.state = 'deleting'::text;\n\nCREATE VIEW lsif_dumps_with_repository_name AS\n SELECT u.id,\n u.commit,\n u.root,\n u.uploaded_at,\n u.state,\n u.failure_message,\n u.started_at,\n u.finished_at,\n u.repository_id,\n u.indexer,\n u.num_parts,\n u.uploaded_parts,\n u.process_after,\n u.num_resets,\n u.upload_size,\n u.num_failures,\n u.associated_index_id,\n u.expired,\n u.processed_at,\n r.name AS repository_name\n FROM lsif_dumps u\n JOIN repo r ON r.id = u.repository_id\n WHERE r.deleted_at IS NULL;", + "DownQuery": "-- Drop dependent views\nDROP VIEW lsif_dumps_with_repository_name;\nDROP VIEW lsif_dumps;\nDROP VIEW lsif_uploads_with_repository_name;\n\n-- Drop new column and table\nALTER TABLE lsif_uploads DROP COLUMN last_retention_scan_at;\nDROP TABLE lsif_last_retention_scan;\n\n-- Restore old views\nCREATE VIEW lsif_uploads_with_repository_name AS\n SELECT u.id,\n u.commit,\n u.root,\n u.uploaded_at,\n u.state,\n u.failure_message,\n u.started_at,\n u.finished_at,\n u.repository_id,\n u.indexer,\n u.num_parts,\n u.uploaded_parts,\n u.process_after,\n u.num_resets,\n u.upload_size,\n u.num_failures,\n u.associated_index_id,\n r.name AS repository_name\n FROM lsif_uploads u\n JOIN repo r ON r.id = u.repository_id\n WHERE r.deleted_at IS NULL;\n\nCREATE VIEW lsif_dumps AS\n SELECT u.id,\n u.commit,\n u.root,\n u.uploaded_at,\n u.state,\n u.failure_message,\n u.started_at,\n u.finished_at,\n u.repository_id,\n u.indexer,\n u.num_parts,\n u.uploaded_parts,\n u.process_after,\n u.num_resets,\n u.upload_size,\n u.num_failures,\n u.associated_index_id,\n u.finished_at AS processed_at\n FROM lsif_uploads u\n WHERE u.state = 'completed'::text OR u.state = 'deleting'::text;\n\nCREATE VIEW lsif_dumps_with_repository_name AS\n SELECT u.id,\n u.commit,\n u.root,\n u.uploaded_at,\n u.state,\n u.failure_message,\n u.started_at,\n u.finished_at,\n u.repository_id,\n u.indexer,\n u.num_parts,\n u.uploaded_parts,\n u.process_after,\n u.num_resets,\n u.upload_size,\n u.num_failures,\n u.associated_index_id,\n u.processed_at,\n r.name AS repository_name\n FROM lsif_dumps u\n JOIN repo r ON r.id = u.repository_id\n WHERE r.deleted_at IS NULL;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395875 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395877, + "Name": "index-lsif-uploads-repo", + "UpQuery": "CREATE INDEX CONCURRENTLY IF NOT EXISTS lsif_uploads_repository_id ON lsif_uploads (repository_id);", + "DownQuery": "DROP INDEX IF EXISTS lsif_uploads_repository_id;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395876 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "lsif_uploads", + "IndexName": "lsif_uploads_repository_id" + } + }, + { + "ID": 1528395878, + "Name": "index-lsif-indexes-repo", + "UpQuery": "CREATE INDEX CONCURRENTLY IF NOT EXISTS lsif_indexes_repository_id_commit ON lsif_indexes (repository_id, commit);", + "DownQuery": "DROP INDEX IF EXISTS lsif_indexes_repository_id_commit;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395877 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "lsif_indexes", + "IndexName": "lsif_indexes_repository_id_commit" + } + }, + { + "ID": 1528395879, + "Name": "repair lsif configuration policies", + "UpQuery": "DROP TABLE lsif_configuration_policies;\n\nCREATE TABLE lsif_configuration_policies (\n id SERIAL PRIMARY KEY,\n repository_id int,\n name text,\n type text NOT NULL,\n pattern text NOT NULL,\n retention_enabled boolean NOT NULL,\n retention_duration_hours int,\n retain_intermediate_commits boolean NOT NULL,\n indexing_enabled boolean NOT NULL,\n index_commit_max_age_hours int,\n index_intermediate_commits boolean NOT NULL\n);\n\nCREATE INDEX lsif_configuration_policies_repository_id ON lsif_configuration_policies(repository_id);\n\nCOMMENT ON COLUMN lsif_configuration_policies.repository_id IS 'The identifier of the repository to which this configuration policy applies. If absent, this policy is applied globally.';\nCOMMENT ON COLUMN lsif_configuration_policies.type IS 'The type of Git object (e.g., COMMIT, BRANCH, TAG).';\nCOMMENT ON COLUMN lsif_configuration_policies.pattern IS 'A pattern used to match` names of the associated Git object type.';\nCOMMENT ON COLUMN lsif_configuration_policies.retention_enabled IS 'Whether or not this configuration policy affects data retention rules.';\nCOMMENT ON COLUMN lsif_configuration_policies.retention_duration_hours IS 'The max age of data retained by this configuration policy. If null, the age is unbounded.';\nCOMMENT ON COLUMN lsif_configuration_policies.retain_intermediate_commits IS 'If the matching Git object is a branch, setting this value to true will also retain all data used to resolve queries for any commit on the matching branches. Setting this value to false will only consider the tip of the branch.';\nCOMMENT ON COLUMN lsif_configuration_policies.indexing_enabled IS 'Whether or not this configuration policy affects auto-indexing schedules.';\nCOMMENT ON COLUMN lsif_configuration_policies.index_commit_max_age_hours IS 'The max age of commits indexed by this configuration policy. If null, the age is unbounded.';\nCOMMENT ON COLUMN lsif_configuration_policies.index_intermediate_commits IS 'If the matching Git object is a branch, setting this value to true will also index all commits on the matching branches. Setting this value to false will only consider the tip of the branch.';", + "DownQuery": "-- Nothing on down", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395878 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395880, + "Name": "insights queue persist mode", + "UpQuery": "-- Insert migration here. See README.md. Highlights:\n-- * Always use IF EXISTS. eg: DROP TABLE IF EXISTS global_dep_private;\n-- * All migrations must be backward-compatible. Old versions of Sourcegraph\n-- need to be able to read/write post migration.\n-- * Historically we advised against transactions since we thought the\n-- migrate library handled it. However, it does not! /facepalm\n\nCREATE TYPE PersistMode AS ENUM ('record', 'snapshot');\n\nALTER TABLE insights_query_runner_jobs\n ADD persist_mode PersistMode DEFAULT 'record' NOT NULL;\n\nCOMMENT ON COLUMN insights_query_runner_jobs.persist_mode IS 'The persistence level for this query. This value will determine the lifecycle of the resulting value.';", + "DownQuery": "-- Insert migration here. See README.md. Highlights:\n-- * Always use IF EXISTS. eg: DROP TABLE IF EXISTS global_dep_private;\n-- * All migrations must be backward-compatible. Old versions of Sourcegraph\n-- need to be able to read/write post migration.\n-- * Historically we advised against transactions since we thought the\n-- migrate library handled it. However, it does not! /facepalm\n\nALTER TABLE insights_query_runner_jobs\n DROP COLUMN persist_mode;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395879 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395881, + "Name": "add batch spec workspaces", + "UpQuery": "CREATE TABLE IF NOT EXISTS batch_spec_resolution_jobs (\n id BIGSERIAL PRIMARY KEY,\n\n batch_spec_id INTEGER REFERENCES batch_specs(id) ON DELETE CASCADE DEFERRABLE,\n allow_unsupported BOOLEAN NOT NULL DEFAULT FALSE,\n allow_ignored BOOLEAN NOT NULL DEFAULT FALSE,\n\n state TEXT DEFAULT 'queued',\n failure_message TEXT,\n started_at TIMESTAMP WITH TIME ZONE,\n finished_at TIMESTAMP WITH TIME ZONE,\n process_after TIMESTAMP WITH TIME ZONE,\n num_resets INTEGER NOT NULL DEFAULT 0,\n num_failures INTEGER NOT NULL DEFAULT 0,\n execution_logs JSON[],\n worker_hostname TEXT NOT NULL DEFAULT '',\n last_heartbeat_at TIMESTAMP WITH TIME ZONE,\n\n created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),\n updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()\n);\n\nCREATE TABLE IF NOT EXISTS batch_spec_workspaces (\n id BIGSERIAL PRIMARY KEY,\n\n batch_spec_id INTEGER REFERENCES batch_specs(id) ON DELETE CASCADE DEFERRABLE,\n changeset_spec_ids JSONB DEFAULT '{}'::jsonb,\n\n repo_id integer REFERENCES repo(id) DEFERRABLE,\n branch TEXT NOT NULL,\n commit TEXT NOT NULL,\n path TEXT NOT NULL,\n file_matches TEXT[] NOT NULL,\n only_fetch_workspace BOOLEAN NOT NULL DEFAULT FALSE,\n steps JSONB DEFAULT '[]'::jsonb CHECK (jsonb_typeof(steps) = 'array'),\n\n created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),\n updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()\n);\n\nCREATE TABLE IF NOT EXISTS batch_spec_workspace_execution_jobs (\n id BIGSERIAL PRIMARY KEY,\n\n batch_spec_workspace_id INTEGER REFERENCES batch_spec_workspaces(id) ON DELETE CASCADE DEFERRABLE,\n\n state TEXT DEFAULT 'queued',\n failure_message TEXT,\n started_at TIMESTAMP WITH TIME ZONE,\n finished_at TIMESTAMP WITH TIME ZONE,\n process_after TIMESTAMP WITH TIME ZONE,\n num_resets INTEGER NOT NULL DEFAULT 0,\n num_failures INTEGER NOT NULL DEFAULT 0,\n execution_logs JSON[],\n worker_hostname TEXT NOT NULL DEFAULT '',\n last_heartbeat_at TIMESTAMP WITH TIME ZONE,\n\n created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),\n updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()\n);", + "DownQuery": "DROP TABLE IF EXISTS batch_spec_workspace_execution_jobs;\nDROP TABLE IF EXISTS batch_spec_workspaces;\nDROP TABLE IF EXISTS batch_spec_resolution_jobs;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395880 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395882, + "Name": "lsif configuration protected policies", + "UpQuery": "ALTER TABLE lsif_configuration_policies ADD COLUMN protected boolean DEFAULT false;\nUPDATE lsif_configuration_policies SET protected = false;\nALTER TABLE lsif_configuration_policies ALTER COLUMN protected SET NOT NULL;\n\nCOMMENT ON COLUMN lsif_configuration_policies.protected IS 'Whether or not this configuration policy is protected from modification of its data retention behavior (except for duration).';", + "DownQuery": "ALTER TABLE lsif_configuration_policies DROP COLUMN protected;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395881 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395883, + "Name": "default lsif configuration policies", + "UpQuery": "INSERT INTO lsif_configuration_policies\n (\n name,\n protected, pattern, type,\n retention_enabled, retain_intermediate_commits, retention_duration_hours,\n indexing_enabled, index_intermediate_commits, index_commit_max_age_hours\n )\nVALUES\n (\n 'Default tip-of-branch retention policy',\n true, '*', 'GIT_TREE',\n true, false, 2016, -- 3 months ~= 2016 hours = 1 week (168 hours) * 4 * 3\n false, false, 0\n ), (\n 'Default tag retention policy',\n true, '*', 'GIT_TAG',\n true, false, 8064, -- 12 months ~= 8064 hours = 1 week (168 hours) * 4 * 12\n false, false, 0\n );", + "DownQuery": "-- Nothing on down", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395882 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395884, + "Name": "add cancel to batch spec workspace execution jobs", + "UpQuery": "ALTER TABLE IF EXISTS batch_spec_workspace_execution_jobs\n ADD COLUMN IF NOT EXISTS cancel boolean DEFAULT false NOT NULL;\n\nCREATE INDEX IF NOT EXISTS batch_spec_workspace_execution_jobs_cancel\n ON batch_spec_workspace_execution_jobs (cancel);", + "DownQuery": "DROP INDEX IF EXISTS batch_spec_workspace_execution_jobs_cancel;\n\nALTER TABLE IF EXISTS batch_spec_workspace_execution_jobs\n DROP COLUMN IF EXISTS cancel;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395883 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395885, + "Name": "lsif last retention scan views", + "UpQuery": "DROP VIEW lsif_dumps_with_repository_name;\nDROP VIEW lsif_dumps;\nDROP VIEW lsif_uploads_with_repository_name;\n\nCREATE VIEW lsif_uploads_with_repository_name AS\n SELECT u.id,\n u.commit,\n u.root,\n u.uploaded_at,\n u.state,\n u.failure_message,\n u.started_at,\n u.finished_at,\n u.repository_id,\n u.indexer,\n u.num_parts,\n u.uploaded_parts,\n u.process_after,\n u.num_resets,\n u.upload_size,\n u.num_failures,\n u.associated_index_id,\n u.expired,\n u.last_retention_scan_at,\n r.name AS repository_name\n FROM lsif_uploads u\n JOIN repo r ON r.id = u.repository_id\n WHERE r.deleted_at IS NULL;\n\nCREATE VIEW lsif_dumps AS\n SELECT u.id,\n u.commit,\n u.root,\n u.uploaded_at,\n u.state,\n u.failure_message,\n u.started_at,\n u.finished_at,\n u.repository_id,\n u.indexer,\n u.num_parts,\n u.uploaded_parts,\n u.process_after,\n u.num_resets,\n u.upload_size,\n u.num_failures,\n u.associated_index_id,\n u.expired,\n u.last_retention_scan_at,\n u.finished_at AS processed_at\n FROM lsif_uploads u\n WHERE u.state = 'completed'::text OR u.state = 'deleting'::text;\n\nCREATE VIEW lsif_dumps_with_repository_name AS\n SELECT u.id,\n u.commit,\n u.root,\n u.uploaded_at,\n u.state,\n u.failure_message,\n u.started_at,\n u.finished_at,\n u.repository_id,\n u.indexer,\n u.num_parts,\n u.uploaded_parts,\n u.process_after,\n u.num_resets,\n u.upload_size,\n u.num_failures,\n u.associated_index_id,\n u.expired,\n u.last_retention_scan_at,\n u.processed_at,\n r.name AS repository_name\n FROM lsif_dumps u\n JOIN repo r ON r.id = u.repository_id\n WHERE r.deleted_at IS NULL;", + "DownQuery": "DROP VIEW lsif_dumps_with_repository_name;\nDROP VIEW lsif_dumps;\nDROP VIEW lsif_uploads_with_repository_name;\n\nCREATE VIEW lsif_uploads_with_repository_name AS\n SELECT u.id,\n u.commit,\n u.root,\n u.uploaded_at,\n u.state,\n u.failure_message,\n u.started_at,\n u.finished_at,\n u.repository_id,\n u.indexer,\n u.num_parts,\n u.uploaded_parts,\n u.process_after,\n u.num_resets,\n u.upload_size,\n u.num_failures,\n u.associated_index_id,\n u.expired,\n r.name AS repository_name\n FROM lsif_uploads u\n JOIN repo r ON r.id = u.repository_id\n WHERE r.deleted_at IS NULL;\n\nCREATE VIEW lsif_dumps AS\n SELECT u.id,\n u.commit,\n u.root,\n u.uploaded_at,\n u.state,\n u.failure_message,\n u.started_at,\n u.finished_at,\n u.repository_id,\n u.indexer,\n u.num_parts,\n u.uploaded_parts,\n u.process_after,\n u.num_resets,\n u.upload_size,\n u.num_failures,\n u.associated_index_id,\n u.expired,\n u.finished_at AS processed_at\n FROM lsif_uploads u\n WHERE u.state = 'completed'::text OR u.state = 'deleting'::text;\n\nCREATE VIEW lsif_dumps_with_repository_name AS\n SELECT u.id,\n u.commit,\n u.root,\n u.uploaded_at,\n u.state,\n u.failure_message,\n u.started_at,\n u.finished_at,\n u.repository_id,\n u.indexer,\n u.num_parts,\n u.uploaded_parts,\n u.process_after,\n u.num_resets,\n u.upload_size,\n u.num_failures,\n u.associated_index_id,\n u.expired,\n u.processed_at,\n r.name AS repository_name\n FROM lsif_dumps u\n JOIN repo r ON r.id = u.repository_id\n WHERE r.deleted_at IS NULL;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395884 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395886, + "Name": "add missing fk indexes1", + "UpQuery": "CREATE INDEX CONCURRENTLY IF NOT EXISTS lsif_dependency_indexing_jobs_upload_id ON lsif_dependency_indexing_jobs(upload_id);", + "DownQuery": "DROP INDEX IF EXISTS lsif_dependency_indexing_jobs_upload_id;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395885 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "lsif_dependency_indexing_jobs", + "IndexName": "lsif_dependency_indexing_jobs_upload_id" + } + }, + { + "ID": 1528395887, + "Name": "add missing fk indexes2", + "UpQuery": "CREATE INDEX CONCURRENTLY IF NOT EXISTS lsif_packages_dump_id ON lsif_packages(dump_id);", + "DownQuery": "DROP INDEX IF EXISTS lsif_packages_dump_id;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395886 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "lsif_packages", + "IndexName": "lsif_packages_dump_id" + } + }, + { + "ID": 1528395888, + "Name": "add missing fk indexes3", + "UpQuery": "CREATE INDEX CONCURRENTLY IF NOT EXISTS lsif_references_dump_id ON lsif_references(dump_id);", + "DownQuery": "DROP INDEX IF EXISTS lsif_references_dump_id;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395887 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "lsif_references", + "IndexName": "lsif_references_dump_id" + } + }, + { + "ID": 1528395889, + "Name": "add metadata column to oobmigration", + "UpQuery": "ALTER TABLE\n out_of_band_migrations\nADD COLUMN IF NOT EXISTS\n metadata jsonb NOT NULL DEFAULT '{}'::jsonb;", + "DownQuery": "ALTER TABLE\n out_of_band_migrations\nDROP COLUMN IF EXISTS metadata;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395888 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395890, + "Name": "drop repo cloned", + "UpQuery": "ALTER TABLE\n repo\nDROP COLUMN IF EXISTS cloned;", + "DownQuery": "-- This migration is destructive since the column has been\n-- deprecated since 3.26\nALTER TABLE\n repo\nADD COLUMN IF NOT EXISTS\n cloned bool NOT NULL DEFAULT false;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395889 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395891, + "Name": "lsif dependency indexing queueing", + "UpQuery": "ALTER TABLE lsif_dependency_indexing_jobs\nRENAME TO lsif_dependency_syncing_jobs;\n\nCREATE TABLE IF NOT EXISTS lsif_dependency_indexing_jobs (\n id serial PRIMARY KEY,\n state text DEFAULT 'queued' NOT NULL,\n failure_message text,\n queued_at timestamp with time zone DEFAULT NOW() NOT NULL,\n started_at timestamp with time zone,\n finished_at timestamp with time zone,\n process_after timestamp with time zone,\n num_resets integer DEFAULT 0 NOT NULL,\n num_failures integer DEFAULT 0 NOT NULL,\n execution_logs json[],\n last_heartbeat_at timestamp with time zone,\n worker_hostname text NOT NULL DEFAULT '',\n upload_id integer REFERENCES lsif_uploads(id) ON DELETE CASCADE,\n external_service_kind text NOT NULL DEFAULT '',\n external_service_sync timestamp with time zone\n);\n\nCOMMENT ON COLUMN lsif_dependency_indexing_jobs.external_service_kind IS 'Filter the external services for this kind to wait to have synced. If empty, external_service_sync is ignored and no external services are polled for their last sync time.';\nCOMMENT ON COLUMN lsif_dependency_indexing_jobs.external_service_sync IS 'The sync time after which external services of the given kind will have synced/created any repositories referenced by the LSIF upload that are resolvable.';", + "DownQuery": "DROP TABLE IF EXISTS lsif_dependency_indexing_jobs;\n\nALTER TABLE lsif_dependency_syncing_jobs\nRENAME TO lsif_dependency_indexing_jobs;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395890 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395892, + "Name": "drop batch spec executions", + "UpQuery": "DROP TABLE IF EXISTS batch_spec_executions;", + "DownQuery": "CREATE TABLE IF NOT EXISTS batch_spec_executions (\n id BIGSERIAL PRIMARY KEY,\n rand_id TEXT NOT NULL,\n\n state TEXT DEFAULT 'queued',\n failure_message TEXT,\n process_after TIMESTAMP WITH TIME ZONE,\n started_at TIMESTAMP WITH TIME ZONE,\n finished_at TIMESTAMP WITH TIME ZONE,\n last_heartbeat_at TIMESTAMP WITH TIME ZONE,\n num_resets INTEGER NOT NULL DEFAULT 0,\n num_failures INTEGER NOT NULL DEFAULT 0,\n execution_logs JSON[],\n worker_hostname TEXT NOT NULL DEFAULT '',\n cancel BOOL DEFAULT FALSE,\n\n created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),\n updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),\n\n batch_spec TEXT NOT NULL,\n batch_spec_id integer REFERENCES batch_specs(id) DEFERRABLE,\n\n user_id INTEGER REFERENCES users(id),\n namespace_org_id INTEGER REFERENCES orgs(id),\n namespace_user_id INTEGER REFERENCES users(id)\n);\n\nALTER TABLE IF EXISTS batch_spec_executions ADD CONSTRAINT batch_spec_executions_has_1_namespace CHECK ((namespace_user_id IS NULL) \u003c\u003e (namespace_org_id IS NULL));\nCREATE INDEX IF NOT EXISTS batch_spec_executions_rand_id ON batch_spec_executions USING btree (rand_id);", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395891 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395893, + "Name": "fix repo index part one", + "UpQuery": "-- We have a hand-created but non-codified index in our Cloud environment\n-- called repo_deleted_at_idx which is a partial btree index over deleted_at\n-- where deleted_at is null. This effectively creates a btree index whose only\n-- value is NULL.\n--\n-- Instead, we'll make a partial index on useful fields that can at least help\n-- cover queries that select only/filter by id and/or name.\n\nCREATE INDEX CONCURRENTLY IF NOT EXISTS repo_non_deleted_id_name_idx ON repo(id, name) WHERE deleted_at IS NULL;", + "DownQuery": "DROP INDEX IF EXISTS repo_non_deleted_id_name_idx;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395892 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "repo", + "IndexName": "repo_non_deleted_id_name_idx" + } + }, + { + "ID": 1528395894, + "Name": "gitserver repo shard id index", + "UpQuery": "-- This speeds up IterateRepoGitserverStatus\nCREATE INDEX CONCURRENTLY IF NOT EXISTS gitserver_repos_shard_id ON gitserver_repos(shard_id, repo_id);", + "DownQuery": "DROP INDEX IF EXISTS gitserver_repos_shard_id;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395893 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "gitserver_repos", + "IndexName": "gitserver_repos_shard_id" + } + }, + { + "ID": 1528395895, + "Name": "gitserver repos lasterror idx", + "UpQuery": "DROP INDEX IF EXISTS gitserver_repos_last_error_idx;", + "DownQuery": "CREATE INDEX gitserver_repos_last_error_idx ON gitserver_repos(last_error) WHERE last_error IS NOT NULL;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395894 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395896, + "Name": "gitserver repos new lasterror idx", + "UpQuery": "CREATE INDEX CONCURRENTLY gitserver_repos_last_error_idx ON gitserver_repos(repo_id) WHERE last_error IS NOT NULL;", + "DownQuery": "DROP INDEX IF EXISTS gitserver_repos_last_error_idx;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395895 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "gitserver_repos", + "IndexName": "gitserver_repos_last_error_idx" + } + }, + { + "ID": 1528395897, + "Name": "extensions list missing index", + "UpQuery": "CREATE INDEX CONCURRENTLY IF NOT EXISTS registry_extension_releases_registry_extension_id_created_at ON registry_extension_releases(registry_extension_id, created_at) WHERE deleted_at IS NULL;", + "DownQuery": "DROP INDEX IF EXISTS registry_extension_releases_registry_extension_id_created_at;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395896 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "registry_extension_releases", + "IndexName": "registry_extension_releases_registry_extension_id_created_at" + } + }, + { + "ID": 1528395898, + "Name": "codehost connection owned by org", + "UpQuery": "-- Adds support for organization owning a codehost connection\nBEGIN;\n\nALTER TABLE IF EXISTS external_services ADD COLUMN IF NOT EXISTS namespace_org_id integer REFERENCES orgs(id) ON DELETE CASCADE DEFERRABLE;\nALTER TABLE IF EXISTS external_services ADD CONSTRAINT external_services_max_1_namespace CHECK ((namespace_user_id IS NULL AND namespace_org_id IS NULL) OR ((namespace_user_id IS NULL) \u003c\u003e (namespace_org_id IS NULL)));\nCREATE INDEX external_services_namespace_org_id_idx ON external_services USING btree (namespace_org_id);\n\nEND;", + "DownQuery": "ALTER TABLE IF EXISTS external_services DROP COLUMN IF EXISTS namespace_org_id;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395897 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395899, + "Name": "add index for lsif indexes state", + "UpQuery": "CREATE INDEX CONCURRENTLY IF NOT EXISTS lsif_indexes_state ON lsif_indexes(state);", + "DownQuery": "DROP INDEX IF EXISTS lsif_indexes_state;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395898 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "lsif_indexes", + "IndexName": "lsif_indexes_state" + } + }, + { + "ID": 1528395900, + "Name": "add commit to lsif uploads repository index", + "UpQuery": "CREATE INDEX CONCURRENTLY IF NOT EXISTS lsif_uploads_repository_id_commit ON lsif_uploads(repository_id, commit);", + "DownQuery": "DROP INDEX IF EXISTS lsif_uploads_repository_id_commit;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395899 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "lsif_uploads", + "IndexName": "lsif_uploads_repository_id_commit" + } + }, + { + "ID": 1528395901, + "Name": "remove duplicate index", + "UpQuery": "DROP INDEX IF EXISTS lsif_uploads_repository_id;", + "DownQuery": "CREATE INDEX IF NOT EXISTS lsif_uploads_repository_id ON lsif_uploads(repository_id);", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395900 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395902, + "Name": "drop unused security events index 0", + "UpQuery": "DROP INDEX IF EXISTS security_event_logs_anonymous_user_id;", + "DownQuery": "CREATE INDEX IF NOT EXISTS security_event_logs_anonymous_user_id ON security_event_logs USING btree (anonymous_user_id);", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395901 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395903, + "Name": "drop unused security events index 1", + "UpQuery": "DROP INDEX IF EXISTS security_event_logs_user_id;", + "DownQuery": "CREATE INDEX IF NOT EXISTS security_event_logs_user_id ON security_event_logs USING btree (user_id);", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395902 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395904, + "Name": "drop unused security events index 2", + "UpQuery": "DROP INDEX IF EXISTS security_event_logs_name;", + "DownQuery": "CREATE INDEX IF NOT EXISTS security_event_logs_name ON security_event_logs USING btree (name);", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395903 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395905, + "Name": "drop unused security events index 3", + "UpQuery": "DROP INDEX IF EXISTS security_event_logs_source;", + "DownQuery": "CREATE INDEX IF NOT EXISTS security_event_logs_source ON security_event_logs USING btree (source);", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395904 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395906, + "Name": "drop unused security events index 4", + "UpQuery": "DROP INDEX IF EXISTS security_event_logs_timestamp_at_utc;", + "DownQuery": "CREATE INDEX IF NOT EXISTS security_event_logs_timestamp_at_utc ON security_event_logs USING btree (date(timezone('UTC'::text, \"timestamp\")));", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395905 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395907, + "Name": "more default lsif configuration policies", + "UpQuery": "INSERT INTO lsif_configuration_policies\n (\n name,\n protected, pattern, type,\n retention_enabled, retain_intermediate_commits, retention_duration_hours,\n indexing_enabled, index_intermediate_commits, index_commit_max_age_hours\n )\nVALUES\n (\n 'Default commit retention policy',\n true, '*', 'GIT_TREE',\n true, true, 168, -- 1 week (168 hours) * 4 * 3\n false, false, 0\n );", + "DownQuery": "-- Nothing on down", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395906 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395908, + "Name": "reverted", + "UpQuery": "-- Empty migration, this migration was reverted: https://github.com/sourcegraph/sourcegraph/pull/25715", + "DownQuery": "-- Empty migration, this migration was reverted: https://github.com/sourcegraph/sourcegraph/pull/25715", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395907 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395909, + "Name": "undo apidocs oob migration", + "UpQuery": "-- Undo the changes corresponding to https://github.com/sourcegraph/sourcegraph/pull/25715\nDELETE FROM out_of_band_migrations WHERE id=12 AND team='apidocs';", + "DownQuery": "-- Nothing to do, the up migration undid changes previously made.", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395908 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395910, + "Name": "gitserver last changed", + "UpQuery": "ALTER TABLE gitserver_repos ADD COLUMN IF NOT EXISTS last_changed TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now();", + "DownQuery": "ALTER TABLE gitserver_repos DROP COLUMN last_changed;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395909 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395911, + "Name": "add access token id to batch spec workspace execution jobs", + "UpQuery": "ALTER TABLE IF EXISTS batch_spec_workspace_execution_jobs\n ADD COLUMN IF NOT EXISTS access_token_id bigint REFERENCES access_tokens(id) ON DELETE SET NULL DEFERRABLE DEFAULT NULL;\n\nALTER TABLE IF EXISTS access_tokens\n ADD COLUMN IF NOT EXISTS internal boolean DEFAULT FALSE;", + "DownQuery": "ALTER TABLE IF EXISTS batch_spec_workspace_execution_jobs\n DROP COLUMN IF EXISTS access_token_id;\n\nALTER TABLE IF EXISTS access_tokens\n DROP COLUMN IF EXISTS internal;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395910 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395912, + "Name": "apidocs oob search indexing", + "UpQuery": "-- Create the OOB migration according to doc/dev/background-information/oobmigrations.md\nINSERT INTO out_of_band_migrations (id, team, component, description, introduced_version_major, introduced_version_minor, non_destructive)\nVALUES (\n 12, -- This must be consistent across all Sourcegraph instances\n 'apidocs', -- Team owning migration\n 'codeintel-db.lsif_data_documentation_search', -- Component being migrated\n 'Index API docs for search', -- Description\n 3, -- The next minor release (major version)\n 32, -- The next minor release (minor version)\n true -- Can be read with previous version without down migration\n)\nON CONFLICT DO NOTHING;", + "DownQuery": "-- The OOB migration doesn't add any new tables or columns or anything, so we don't need to do\n-- anything on down migration. It migrates data from lsif_data_documentation_pages -\u003e the new\n-- lsif_data_documentation_search_* tables - but it's fine to just leave those.", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395911 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395913, + "Name": "add unique constraint on batch spec resolution jobs", + "UpQuery": "ALTER TABLE IF EXISTS batch_spec_resolution_jobs\n ADD CONSTRAINT batch_spec_resolution_jobs_batch_spec_id_unique UNIQUE (batch_spec_id);", + "DownQuery": "ALTER TABLE IF EXISTS batch_spec_resolution_jobs\n DROP CONSTRAINT IF EXISTS batch_spec_resolution_jobs_batch_spec_id_unique;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395912 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395914, + "Name": "add created from raw to batch specs", + "UpQuery": "ALTER TABLE batch_specs\n ADD COLUMN IF NOT EXISTS created_from_raw boolean DEFAULT FALSE NOT NULL;", + "DownQuery": "ALTER TABLE batch_specs\n DROP COLUMN IF EXISTS created_from_raw;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395913 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395915, + "Name": "remove raw changeset spec", + "UpQuery": "ALTER TABLE\n changeset_specs\nDROP COLUMN IF EXISTS\n raw_spec;", + "DownQuery": "-- We don't need to reconstruct the contents of the raw_spec column (and,\n-- indeed, we can't), so we'll just leave it with empty strings.\n\nALTER TABLE\n changeset_specs\nADD COLUMN IF NOT EXISTS\n raw_spec TEXT NOT NULL DEFAULT '';", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395914 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395916, + "Name": "add external service repos org id", + "UpQuery": "ALTER TABLE external_service_repos ADD COLUMN IF NOT EXISTS org_id INTEGER REFERENCES orgs(id) ON DELETE CASCADE;", + "DownQuery": "ALTER TABLE external_service_repos DROP COLUMN IF EXISTS org_id;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395915 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395917, + "Name": "add index rate limit", + "UpQuery": "-- Create table to rate limit indexing scans of a repository\nCREATE TABLE lsif_last_index_scan (\n repository_id int NOT NULL,\n last_index_scan_at timestamp with time zone NOT NULL,\n\n PRIMARY KEY(repository_id)\n);\nCOMMENT ON TABLE lsif_last_index_scan IS 'Tracks the last time repository was checked for auto-indexing job scheduling.';\nCOMMENT ON COLUMN lsif_last_index_scan.last_index_scan_at IS 'The last time uploads of this repository were considered for auto-indexing job scheduling.';", + "DownQuery": "DROP TABLE IF EXISTS lsif_last_index_scan;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395916 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395918, + "Name": "update batch spec workspaces to persist all", + "UpQuery": "ALTER TABLE batch_spec_workspaces\n ADD COLUMN IF NOT EXISTS ignored BOOLEAN NOT NULL DEFAULT FALSE,\n ADD COLUMN IF NOT EXISTS unsupported BOOLEAN NOT NULL DEFAULT FALSE,\n ADD COLUMN IF NOT EXISTS skipped BOOLEAN NOT NULL DEFAULT FALSE;\n\nALTER TABLE batch_specs\n ADD COLUMN IF NOT EXISTS allow_unsupported BOOLEAN NOT NULL DEFAULT FALSE,\n ADD COLUMN IF NOT EXISTS allow_ignored BOOLEAN NOT NULL DEFAULT FALSE;\n\nALTER TABLE batch_spec_resolution_jobs\n DROP COLUMN IF EXISTS allow_unsupported,\n DROP COLUMN IF EXISTS allow_ignored;", + "DownQuery": "ALTER TABLE batch_spec_workspaces\n DROP COLUMN IF EXISTS ignored,\n DROP COLUMN IF EXISTS unsupported,\n DROP COLUMN IF EXISTS skipped;\n\nALTER TABLE batch_specs\n DROP COLUMN IF EXISTS allow_unsupported,\n DROP COLUMN IF EXISTS allow_ignored;\n\nALTER TABLE batch_spec_resolution_jobs\n ADD COLUMN IF NOT EXISTS allow_unsupported BOOLEAN NOT NULL DEFAULT FALSE,\n ADD COLUMN IF NOT EXISTS allow_ignored BOOLEAN NOT NULL DEFAULT FALSE;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395917 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395919, + "Name": "drop soft delete search contexts", + "UpQuery": "DELETE FROM search_contexts WHERE deleted_at IS NOT NULL;\n\nCOMMENT ON COLUMN search_contexts.deleted_at IS 'This column is unused as of Sourcegraph 3.34. Do not refer to it anymore. It will be dropped in a future version.';\n\nALTER TABLE search_context_repos ADD CONSTRAINT search_context_repos_unique UNIQUE (repo_id, search_context_id, revision);\n\nALTER TABLE search_context_repos DROP CONSTRAINT IF EXISTS search_context_repos_search_context_id_repo_id_revision_unique;", + "DownQuery": "ALTER TABLE search_context_repos ADD CONSTRAINT search_context_repos_search_context_id_repo_id_revision_unique UNIQUE (search_context_id, repo_id, revision);\n\nALTER TABLE search_context_repos DROP CONSTRAINT IF EXISTS search_context_repos_unique;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395918 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395920, + "Name": "create sub repo permissions table", + "UpQuery": "create table sub_repo_permissions\n(\n repo_id integer not null\n constraint sub_repo_permissions_repo_id_fk\n references repo\n on delete cascade,\n user_id integer not null\n constraint sub_repo_permissions_users_id_fk\n references users\n on delete cascade,\n version int default 1 not null,\n path_includes text[],\n path_excludes text[],\n updated_at timestamp with time zone default now() not null\n);\n\ncomment on table sub_repo_permissions is 'Responsible for storing permissions at a finer granularity than repo';\n\ncreate unique index sub_repo_permissions_repo_id_user_id_uindex\n on sub_repo_permissions (repo_id, user_id);\n\ncreate index sub_repo_perms_user_id ON sub_repo_permissions (user_id);\ncreate index sub_repo_perms_repo_id ON sub_repo_permissions (repo_id);", + "DownQuery": "DROP TABLE IF EXISTS sub_repo_permissions;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395919 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395921, + "Name": "add version index sub repo permissions", + "UpQuery": "drop index if exists sub_repo_permissions_repo_id_user_id_uindex;\n\ncreate unique index sub_repo_permissions_repo_id_user_id_version_uindex\n on sub_repo_permissions (repo_id, user_id, version);\n\ncreate index sub_repo_perms_version ON sub_repo_permissions (version);", + "DownQuery": "drop index if exists sub_repo_permissions_repo_id_user_id_version_uindex;\ndrop index if exists sub_repo_perms_version;\n\ncreate unique index sub_repo_permissions_repo_id_user_id_uindex\n on sub_repo_permissions (repo_id, user_id);", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395920 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395922, + "Name": "add external service repos org id index", + "UpQuery": "CREATE INDEX IF NOT EXISTS external_service_repos_org_id_idx ON external_service_repos USING btree (org_id) WHERE org_id IS NOT NULL;", + "DownQuery": "DROP INDEX IF EXISTS external_service_repos_org_id_idx;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395921 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395923, + "Name": "add has webhooks", + "UpQuery": "ALTER TABLE\n external_services\nADD COLUMN IF NOT EXISTS\n has_webhooks BOOLEAN NULL DEFAULT NULL;\n\nCREATE INDEX\n external_services_has_webhooks_idx\nON\n external_services (has_webhooks);\n\nINSERT INTO\n out_of_band_migrations (\n id,\n team,\n component,\n description,\n introduced_version_major,\n introduced_version_minor,\n non_destructive\n )\nVALUES (\n 13,\n 'batch-changes',\n 'frontend-db.external_services',\n 'Calculate the webhook state of each external service',\n 3,\n 34,\n true\n)\nON CONFLICT\n DO NOTHING\n;", + "DownQuery": "-- We don't remove the out of band migration when moving down.\n\nALTER TABLE\n external_services\nDROP COLUMN IF EXISTS\n has_webhooks;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395922 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395924, + "Name": "lsif configuration policies repository pattern lookup", + "UpQuery": "-- Create lookup table for repository pattern matching\nCREATE TABLE IF NOT EXISTS lsif_configuration_policies_repository_pattern_lookup (\n policy_id INTEGER NOT NULL,\n repo_id INTEGER NOT NULL,\n PRIMARY KEY (policy_id, repo_id)\n);\n\nCOMMENT ON TABLE lsif_configuration_policies_repository_pattern_lookup IS 'A lookup table to get all the repository patterns by repository id that apply to a configuration policy.';\nCOMMENT ON COLUMN lsif_configuration_policies_repository_pattern_lookup.policy_id IS 'The policy identifier associated with the repository.';\nCOMMENT ON COLUMN lsif_configuration_policies_repository_pattern_lookup.repo_id IS 'The repository identifier associated with the policy.';\n\n-- Add glob pattern column\nALTER TABLE lsif_configuration_policies ADD COLUMN repository_patterns TEXT[];\nCOMMENT ON COLUMN lsif_configuration_policies.repository_patterns IS 'The name pattern matching repositories to which this configuration policy applies. If absent, all repositories are matched.';\n\n-- Add column to determine the last update of the associated records in lsif_configuration_policies_repository_pattern_lookup\nALTER TABLE lsif_configuration_policies ADD COLUMN last_resolved_at TIMESTAMP WITH TIME ZONE DEFAULT NULL;", + "DownQuery": "-- Drop new table\nDROP TABLE IF EXISTS lsif_configuration_policies_repository_pattern_lookup;\n\n-- Drop new columns\nALTER TABLE lsif_configuration_policies DROP COLUMN last_resolved_at;\nALTER TABLE lsif_configuration_policies DROP COLUMN repository_patterns;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395923 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395925, + "Name": "settings global index", + "UpQuery": "CREATE INDEX IF NOT EXISTS settings_global_id ON settings (id DESC) WHERE user_id IS NULL AND org_id IS NULL;", + "DownQuery": "DROP INDEX IF EXISTS settings_global_id;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395924 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395926, + "Name": "drop redundant sub repo perms index", + "UpQuery": "DROP INDEX IF EXISTS sub_repo_perms_repo_id;\n\nDROP INDEX IF EXISTS sub_repo_perms_user_id;\n\nDROP INDEX IF EXISTS sub_repo_perms_version;", + "DownQuery": "CREATE INDEX sub_repo_perms_repo_id ON sub_repo_permissions (repo_id);\n\nCREATE INDEX sub_repo_perms_user_id ON sub_repo_permissions (user_id);\n\nCREATE INDEX sub_repo_perms_version ON sub_repo_permissions (version);", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395925 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395927, + "Name": "webhook logs", + "UpQuery": "CREATE TABLE IF NOT EXISTS webhook_logs (\n id BIGSERIAL PRIMARY KEY,\n received_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),\n external_service_id INTEGER NULL REFERENCES external_services (id) ON DELETE CASCADE ON UPDATE CASCADE,\n status_code INTEGER NOT NULL,\n request BYTEA NOT NULL,\n response BYTEA NOT NULL,\n encryption_key_id TEXT NOT NULL\n);\n\nCREATE INDEX IF NOT EXISTS\n webhook_logs_received_at_idx\nON\n webhook_logs (received_at);\n\nCREATE INDEX IF NOT EXISTS\n webhook_logs_external_service_id_idx\nON\n webhook_logs (external_service_id);\n\nCREATE INDEX IF NOT EXISTS\n webhook_logs_status_code_idx\nON\n webhook_logs (status_code);", + "DownQuery": "DROP TABLE IF EXISTS webhook_logs;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395926 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395928, + "Name": "add batch spec execution cache entries", + "UpQuery": "CREATE TABLE IF NOT EXISTS batch_spec_execution_cache_entries (\n id BIGSERIAL PRIMARY KEY,\n\n key TEXT NOT NULL,\n value TEXT NOT NULL,\n\n version INTEGER NOT NULL,\n\n last_used_at TIMESTAMP WITH TIME ZONE,\n created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()\n);", + "DownQuery": "DROP TABLE IF EXISTS batch_spec_execution_cache_entries;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395927 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395929, + "Name": "external service repos clone url", + "UpQuery": "CREATE INDEX IF NOT EXISTS external_service_repos_clone_url_idx ON external_service_repos (clone_url);", + "DownQuery": "DROP INDEX IF EXISTS external_service_repos_clone_url_idx;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395928 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395930, + "Name": "drop unused column object ids from user permissions table", + "UpQuery": "ALTER TABLE IF EXISTS user_permissions DROP COLUMN IF EXISTS object_ids;", + "DownQuery": "ALTER TABLE IF EXISTS user_permissions ADD COLUMN object_ids bytea NOT NULL default '\\x';", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395929 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395931, + "Name": "drop unused column user ids from repo permissions table", + "UpQuery": "ALTER TABLE IF EXISTS repo_permissions DROP COLUMN IF EXISTS user_ids;", + "DownQuery": "ALTER TABLE IF EXISTS repo_permissions ADD COLUMN user_ids bytea NOT NULL default '\\x';", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395930 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395932, + "Name": "add cache entry id to batch spec workspaces", + "UpQuery": "ALTER TABLE batch_spec_workspaces\n ADD COLUMN IF NOT EXISTS batch_spec_execution_cache_entry_id INTEGER REFERENCES batch_spec_execution_cache_entries(id) DEFERRABLE;", + "DownQuery": "ALTER TABLE batch_spec_workspaces\n DROP COLUMN IF EXISTS batch_spec_execution_cache_entry_id;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395931 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395933, + "Name": "add cached result found to batch spec workspaces", + "UpQuery": "ALTER TABLE batch_spec_workspaces\n ADD COLUMN IF NOT EXISTS cached_result_found BOOLEAN NOT NULL DEFAULT FALSE;\n\nUPDATE\n batch_spec_workspaces\nSET\n cached_result_found = true\nWHERE\n batch_spec_execution_cache_entry_id IS NOT NULL;\n\nALTER TABLE batch_spec_workspaces\n DROP COLUMN IF EXISTS batch_spec_execution_cache_entry_id;\n\nDELETE FROM\n batch_spec_execution_cache_entries e1\nWHERE\n EXISTS (SELECT 1 FROM batch_spec_execution_cache_entries e2 WHERE e1.key = e2.key AND e1.id != e2.id);\n\nALTER TABLE batch_spec_execution_cache_entries\n ADD CONSTRAINT batch_spec_execution_cache_entries_key_unique UNIQUE (key);", + "DownQuery": "ALTER TABLE batch_spec_workspaces\n ADD COLUMN IF NOT EXISTS batch_spec_execution_cache_entry_id INTEGER REFERENCES batch_spec_execution_cache_entries(id) DEFERRABLE;\n\nALTER TABLE batch_spec_workspaces\n DROP COLUMN IF EXISTS cached_result_found;\n\nALTER TABLE batch_spec_execution_cache_entries\n DROP CONSTRAINT IF EXISTS batch_spec_execution_cache_entries_key_unique;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395932 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395934, + "Name": "lsif upload reference counts", + "UpQuery": "ALTER TABLE lsif_uploads ADD COLUMN reference_count int;\nCOMMENT ON COLUMN lsif_uploads.reference_count IS 'The number of references to this upload data from other upload records (via lsif_references).';\nCOMMENT ON COLUMN lsif_uploads.num_references IS 'Deprecated in favor of reference_count.';", + "DownQuery": "-- Drop new column\nALTER TABLE lsif_uploads DROP COLUMN reference_count;\n\n-- Restore old comment on deprecated column\nCOMMENT ON COLUMN lsif_uploads.num_references IS 'The number of references to this upload data from other upload records (via lsif_references).';", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395933 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395935, + "Name": "repo stars desc id desc index", + "UpQuery": "CREATE INDEX CONCURRENTLY IF NOT EXISTS repo_stars_desc_id_desc_idx\n ON repo USING btree (stars DESC NULLS LAST, id DESC) WHERE deleted_at IS NULL AND blocked IS NULL;", + "DownQuery": "DROP INDEX IF EXISTS repo_stars_desc_id_desc_idx;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395934 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "repo", + "IndexName": "repo_stars_desc_id_desc_idx" + } + }, + { + "ID": 1528395936, + "Name": "repo name case sensitive trgm idx", + "UpQuery": "CREATE INDEX CONCURRENTLY IF NOT EXISTS repo_name_case_sensitive_trgm_idx ON repo USING gin ((name::text) gin_trgm_ops);", + "DownQuery": "DROP INDEX IF EXISTS repo_name_case_sensitive_trgm_idx;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395935 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "repo", + "IndexName": "repo_name_case_sensitive_trgm_idx" + } + }, + { + "ID": 1528395937, + "Name": "codemonitor webhooks", + "UpQuery": "-- Begin cm_webhooks\nCREATE TABLE IF NOT EXISTS cm_webhooks (\n\tid BIGSERIAL PRIMARY KEY,\n\tmonitor BIGINT NOT NULL REFERENCES cm_monitors(id) ON DELETE CASCADE,\n\turl TEXT NOT NULL,\n\tenabled BOOLEAN NOT NULL,\n\tcreated_by INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,\n\tcreated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),\n\tchanged_by INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,\n\tchanged_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()\n);\n\nCREATE INDEX IF NOT EXISTS cm_webhooks_monitor ON cm_webhooks (monitor);\n\nCOMMENT ON TABLE cm_webhooks IS 'Webhook actions configured on code monitors';\nCOMMENT ON COLUMN cm_webhooks.monitor IS 'The code monitor that the action is defined on';\nCOMMENT ON COLUMN cm_webhooks.url IS 'The webhook URL we send the code monitor event to';\nCOMMENT ON COLUMN cm_webhooks.enabled IS 'Whether this webhook action is enabled. When not enabled, the action will not be run when its code monitor generates events';\n-- End cm_webhooks\n\n-- Begin cm_slack_webhooks\nCREATE TABLE IF NOT EXISTS cm_slack_webhooks (\n\tid BIGSERIAL PRIMARY KEY,\n\tmonitor BIGINT NOT NULL REFERENCES cm_monitors(id) ON DELETE CASCADE,\n\turl TEXT NOT NULL,\n\tenabled BOOLEAN NOT NULL,\n\tcreated_by INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,\n\tcreated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),\n\tchanged_by INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,\n\tchanged_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()\n);\n\nCREATE INDEX IF NOT EXISTS cm_slack_webhooks_monitor ON cm_slack_webhooks (monitor);\n\nCOMMENT ON TABLE cm_slack_webhooks IS 'Slack webhook actions configured on code monitors';\nCOMMENT ON COLUMN cm_slack_webhooks.monitor IS 'The code monitor that the action is defined on';\nCOMMENT ON COLUMN cm_slack_webhooks.url IS 'The Slack webhook URL we send the code monitor event to';\nCOMMENT ON COLUMN cm_webhooks.enabled IS 'Whether this Slack webhook action is enabled. When not enabled, the action will not be run when its code monitor generates events';\n-- End cm_slack_webhooks\n\n-- Begin add non-email actions to cm_triggers\nALTER TABLE cm_action_jobs\n\tALTER COLUMN email DROP NOT NULL, -- make email nullable (drop the not null constraint)\n\tADD COLUMN IF NOT EXISTS webhook BIGINT -- create a nullable webhook column\n\t\tREFERENCES cm_webhooks(id) ON DELETE CASCADE,\n\tADD COLUMN IF NOT EXISTS slack_webhook BIGINT --create a nullable slack webhook column\n\t\tREFERENCES cm_slack_webhooks(id) ON DELETE CASCADE,\n\tADD CONSTRAINT cm_action_jobs_only_one_action_type CHECK ( -- constrain that only one of email, webhook, and slack_webhook is non-null\n\t\t( \n\t\t\tCASE WHEN email IS NULL THEN 0 ELSE 1 END\n\t\t\t+ CASE WHEN webhook IS NULL THEN 0 ELSE 1 END \n\t\t\t+ CASE WHEN slack_webhook IS NULL THEN 0 ELSE 1 END \n\t\t) = 1\n\t);\n\nCOMMENT ON COLUMN cm_action_jobs.email IS 'The ID of the cm_emails action to execute if this is an email job. Mutually exclusive with webhook and slack_webhook';\nCOMMENT ON COLUMN cm_action_jobs.webhook IS 'The ID of the cm_webhooks action to execute if this is a webhook job. Mutually exclusive with email and slack_webhook';\nCOMMENT ON COLUMN cm_action_jobs.slack_webhook IS 'The ID of the cm_slack_webhook action to execute if this is a slack webhook job. Mutually exclusive with email and webhook';\nCOMMENT ON CONSTRAINT cm_action_jobs_only_one_action_type ON cm_action_jobs IS 'Constrains that each queued code monitor action has exactly one action type';\n-- End add non-email actions to cm_triggers", + "DownQuery": "ALTER TABLE cm_action_jobs\n\tDROP CONSTRAINT IF EXISTS cm_action_jobs_only_one_action_type,\n\tDROP COLUMN IF EXISTS slack_webhook,\n\tDROP COLUMN IF EXISTS webhook,\n\tALTER COLUMN email SET NOT NULL;\n\nDROP TABLE IF EXISTS cm_slack_webhooks;\nDROP TABLE IF EXISTS cm_webhooks;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395936 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395938, + "Name": "batch spec no cache", + "UpQuery": "ALTER TABLE batch_specs ADD COLUMN IF NOT EXISTS no_cache BOOLEAN NOT NULL DEFAULT FALSE;", + "DownQuery": "ALTER TABLE batch_specs DROP COLUMN IF EXISTS no_cache;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395937 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395939, + "Name": "batch specs changeset specs delete cascade", + "UpQuery": "ALTER TABLE changeset_specs\n DROP CONSTRAINT changeset_specs_batch_spec_id_fkey,\n ADD CONSTRAINT changeset_specs_batch_spec_id_fkey FOREIGN KEY (batch_spec_id) REFERENCES batch_specs (id) ON DELETE CASCADE DEFERRABLE;", + "DownQuery": "ALTER TABLE changeset_specs\n DROP CONSTRAINT changeset_specs_batch_spec_id_fkey,\n ADD CONSTRAINT changeset_specs_batch_spec_id_fkey FOREIGN KEY (batch_spec_id) REFERENCES batch_specs (id) DEFERRABLE;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395938 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395940, + "Name": "executor heartbeats", + "UpQuery": "CREATE TABLE IF NOT EXISTS executor_heartbeats (\n id SERIAL PRIMARY KEY,\n hostname TEXT NOT NULL UNIQUE,\n queue_name TEXT NOT NULL,\n os TEXT NOT NULL,\n architecture TEXT NOT NULL,\n docker_version TEXT NOT NULL,\n executor_version TEXT NOT NULL,\n git_version TEXT NOT NULL,\n ignite_version TEXT NOT NULL,\n src_cli_version TEXT NOT NULL,\n first_seen_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),\n last_seen_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()\n);\n\nCOMMENT ON TABLE executor_heartbeats IS 'Tracks the most recent activity of executors attached to this Sourcegraph instance.';\nCOMMENT ON COLUMN executor_heartbeats.hostname IS 'The uniquely identifying name of the executor.';\nCOMMENT ON COLUMN executor_heartbeats.queue_name IS 'The queue name that the executor polls for work.';\nCOMMENT ON COLUMN executor_heartbeats.os IS 'The operating system running the executor.';\nCOMMENT ON COLUMN executor_heartbeats.architecture IS 'The machine architure running the executor.';\nCOMMENT ON COLUMN executor_heartbeats.docker_version IS 'The version of Docker used by the executor.';\nCOMMENT ON COLUMN executor_heartbeats.executor_version IS 'The version of the executor.';\nCOMMENT ON COLUMN executor_heartbeats.git_version IS 'The version of Git used by the executor.';\nCOMMENT ON COLUMN executor_heartbeats.ignite_version IS 'The version of Ignite used by the executor.';\nCOMMENT ON COLUMN executor_heartbeats.src_cli_version IS 'The version of src-cli used by the executor.';\nCOMMENT ON COLUMN executor_heartbeats.first_seen_at IS 'The first time a heartbeat from the executor was received.';\nCOMMENT ON COLUMN executor_heartbeats.last_seen_at IS 'The last time a heartbeat from the executor was received.';", + "DownQuery": "DROP TABLE IF EXISTS executor_heartbeats;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395939 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395941, + "Name": "remove-org-monitors", + "UpQuery": "DELETE FROM cm_monitors WHERE namespace_user_id IS NULL;\nCOMMENT ON COLUMN cm_monitors.namespace_org_id IS 'DEPRECATED: code monitors cannot be owned by an org';\n\nALTER TABLE cm_monitors \n\tALTER COLUMN namespace_user_id SET NOT NULL;", + "DownQuery": "ALTER TABLE cm_monitors\n\tALTER COLUMN namespace_user_id DROP NOT NULL;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395940 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395942, + "Name": "remove-org-saved-searches", + "UpQuery": "-- NOTE: this migration deleted saved searches belonging to orgs when what we should have done\n-- was remove notifications from saved searches. Saved searches are still used (and useful) as\n-- a bookmarking feature, and are not deprecated. Saved search notifications, however, are\n-- deprecated, and will be removed in v3.34.0 by removing the query runner service. \n\n-- DELETE FROM saved_searches WHERE user_id IS NULL;\n\n-- ALTER TABLE saved_searches\n-- \tALTER COLUMN user_id SET NOT NULL;\n\n-- COMMENT ON COLUMN saved_searches.org_id IS 'DEPRECATED: saved searches must be owned by a user';", + "DownQuery": "-- ALTER TABLE saved_searches\n-- \tALTER COLUMN user_id DROP NOT NULL;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395941 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395943, + "Name": "disable-saved-search-notifications", + "UpQuery": "UPDATE saved_searches\nSET (notify_owner, notify_slack) = (false, false);\n\nALTER TABLE saved_searches\n\tADD CONSTRAINT saved_searches_notifications_disabled CHECK (\n\t\tnotify_owner = false\n\t\tAND notify_slack = false\n\t);\n\nALTER TABLE IF EXISTS saved_searches\n\tALTER COLUMN user_id DROP NOT NULL;", + "DownQuery": "ALTER TABLE IF EXISTS saved_searches\n\tDROP CONSTRAINT IF EXISTS saved_searches_notifications_disabled;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395942 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395944, + "Name": "reenable-code-monitors", + "UpQuery": "-- If code monitors were disabled by a manual step, make\n\t-- it possible to re-enable them by removing the constraint.\n\t-- If an admin wants to restore the previous enabled state\n\t-- from the backup table, they can run something like the following:\n\t-- UPDATE cm_monitors\n\t-- SET enabled = cm_monitors_enabled_backup.enabled\n\t-- FROM cm_monitors_enabled_backup\n\t-- WHERE cm_monitors.id = cm_monitors_enabled_backup.id;\n\tALTER TABLE cm_monitors\n\tDROP CONSTRAINT IF EXISTS cm_monitors_cannot_be_enabled;", + "DownQuery": "", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395943 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395945, + "Name": "repo stars null to zero", + "UpQuery": "CREATE OR REPLACE PROCEDURE set_repo_stars_null_to_zero() AS\n$BODY$\nDECLARE\n done boolean;\n total integer = 0;\n updated integer = 0;\n\nBEGIN\n SELECT COUNT(*) INTO total FROM repo WHERE stars IS NULL;\n\n RAISE NOTICE 'repo_stars_null_to_zero: updating % rows', total;\n\n done := total = 0;\n\n WHILE NOT done LOOP\n UPDATE repo SET stars = 0\n FROM (\n SELECT id FROM repo\n WHERE stars IS NULL\n LIMIT 10000\n FOR UPDATE SKIP LOCKED\n ) s\n WHERE repo.id = s.id;\n\n COMMIT;\n\n SELECT COUNT(*) = 0 INTO done FROM repo WHERE stars IS NULL LIMIT 1;\n\n updated := updated + 10000;\n\n RAISE NOTICE 'repo_stars_null_to_zero: updated % of % rows', updated, total;\n END LOOP;\nEND\n$BODY$\nLANGUAGE plpgsql;", + "DownQuery": "DROP PROCEDURE IF EXISTS set_repo_stars_null_to_zero;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395944 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395946, + "Name": "repo stars call nulls to zero", + "UpQuery": "CALL set_repo_stars_null_to_zero();", + "DownQuery": "", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395945 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1528395947, + "Name": "repo stars not null", + "UpQuery": "ALTER TABLE repo\n ALTER COLUMN stars SET NOT NULL,\n ALTER COLUMN stars SET DEFAULT 0;", + "DownQuery": "ALTER TABLE repo\n ALTER COLUMN stars DROP NOT NULL,\n ALTER COLUMN stars DROP DEFAULT;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1528395946 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + } + ], + "BoundsByRev": { + "3.34.2": { + "RootID": -1528395834, + "LeafIDs": [ + 1528395947 + ], + "PreCreation": false + } + } + } +} diff --git a/internal/database/migration/shared/data/frozen/4.3.0.json b/internal/database/migration/shared/data/frozen/4.3.0.json new file mode 100755 index 00000000000..0e49c96c612 --- /dev/null +++ b/internal/database/migration/shared/data/frozen/4.3.0.json @@ -0,0 +1,2540 @@ +{ + "codeinsights": { + "Definitions": [ + { + "ID": 1000000027, + "Name": "squashed migrations (privileged)", + "UpQuery": "CREATE EXTENSION IF NOT EXISTS citext;\n\nCOMMENT ON EXTENSION citext IS 'data type for case-insensitive character strings';\n\nCREATE EXTENSION IF NOT EXISTS pg_trgm;\n\nCOMMENT ON EXTENSION pg_trgm IS 'text similarity measurement and index searching based on trigrams';", + "DownQuery": "-- Nothing", + "Privileged": true, + "NonIdempotent": true, + "Parents": [], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1646761143, + "Name": "squashed migrations (unprivileged)", + "UpQuery": "CREATE TYPE presentation_type_enum AS ENUM (\n 'LINE',\n 'PIE'\n);\n\nCREATE TYPE time_unit AS ENUM (\n 'HOUR',\n 'DAY',\n 'WEEK',\n 'MONTH',\n 'YEAR'\n);\n\nCREATE TABLE commit_index (\n committed_at timestamp with time zone NOT NULL,\n repo_id integer NOT NULL,\n commit_bytea bytea NOT NULL,\n indexed_at timestamp without time zone DEFAULT CURRENT_TIMESTAMP,\n debug_field text\n);\n\nCREATE TABLE commit_index_metadata (\n repo_id integer NOT NULL,\n enabled boolean DEFAULT true NOT NULL,\n last_indexed_at timestamp with time zone DEFAULT '1900-01-01 00:00:00+00'::timestamp with time zone NOT NULL\n);\n\nCREATE TABLE dashboard (\n id integer NOT NULL,\n title text,\n created_at timestamp without time zone DEFAULT now() NOT NULL,\n created_by_user_id integer,\n last_updated_at timestamp without time zone DEFAULT now() NOT NULL,\n deleted_at timestamp without time zone,\n save boolean DEFAULT false NOT NULL\n);\n\nCOMMENT ON TABLE dashboard IS 'Metadata for dashboards of insights';\n\nCOMMENT ON COLUMN dashboard.title IS 'Title of the dashboard';\n\nCOMMENT ON COLUMN dashboard.created_at IS 'Timestamp the dashboard was initially created.';\n\nCOMMENT ON COLUMN dashboard.created_by_user_id IS 'User that created the dashboard, if available.';\n\nCOMMENT ON COLUMN dashboard.last_updated_at IS 'Time the dashboard was last updated, either metadata or insights.';\n\nCOMMENT ON COLUMN dashboard.deleted_at IS 'Set to the time the dashboard was soft deleted.';\n\nCOMMENT ON COLUMN dashboard.save IS 'TEMPORARY Do not delete this dashboard when migrating settings.';\n\nCREATE TABLE dashboard_grants (\n id integer NOT NULL,\n dashboard_id integer NOT NULL,\n user_id integer,\n org_id integer,\n global boolean\n);\n\nCOMMENT ON TABLE dashboard_grants IS 'Permission grants for dashboards. Each row should represent a unique principal (user, org, etc).';\n\nCOMMENT ON COLUMN dashboard_grants.user_id IS 'User ID that that receives this grant.';\n\nCOMMENT ON COLUMN dashboard_grants.org_id IS 'Org ID that that receives this grant.';\n\nCOMMENT ON COLUMN dashboard_grants.global IS 'Grant that does not belong to any specific principal and is granted to all users.';\n\nCREATE SEQUENCE dashboard_grants_id_seq\n AS integer\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE dashboard_grants_id_seq OWNED BY dashboard_grants.id;\n\nCREATE SEQUENCE dashboard_id_seq\n AS integer\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE dashboard_id_seq OWNED BY dashboard.id;\n\nCREATE TABLE dashboard_insight_view (\n id integer NOT NULL,\n dashboard_id integer NOT NULL,\n insight_view_id integer NOT NULL\n);\n\nCREATE SEQUENCE dashboard_insight_view_id_seq\n AS integer\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE dashboard_insight_view_id_seq OWNED BY dashboard_insight_view.id;\n\nCREATE TABLE insight_dirty_queries (\n id integer NOT NULL,\n insight_series_id integer,\n query text NOT NULL,\n dirty_at timestamp without time zone DEFAULT CURRENT_TIMESTAMP NOT NULL,\n reason text NOT NULL,\n for_time timestamp without time zone NOT NULL\n);\n\nCOMMENT ON TABLE insight_dirty_queries IS 'Stores queries that were unsuccessful or otherwise flagged as incomplete or incorrect.';\n\nCOMMENT ON COLUMN insight_dirty_queries.query IS 'Sourcegraph query string that was executed.';\n\nCOMMENT ON COLUMN insight_dirty_queries.dirty_at IS 'Timestamp when this query was marked dirty.';\n\nCOMMENT ON COLUMN insight_dirty_queries.reason IS 'Human readable string indicating the reason the query was marked dirty.';\n\nCOMMENT ON COLUMN insight_dirty_queries.for_time IS 'Timestamp for which the original data point was recorded or intended to be recorded.';\n\nCREATE SEQUENCE insight_dirty_queries_id_seq\n AS integer\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE insight_dirty_queries_id_seq OWNED BY insight_dirty_queries.id;\n\nCREATE TABLE insight_series (\n id integer NOT NULL,\n series_id text NOT NULL,\n query text NOT NULL,\n created_at timestamp without time zone DEFAULT CURRENT_TIMESTAMP NOT NULL,\n oldest_historical_at timestamp without time zone DEFAULT (CURRENT_TIMESTAMP - '1 year'::interval) NOT NULL,\n last_recorded_at timestamp without time zone DEFAULT (CURRENT_TIMESTAMP - '10 years'::interval) NOT NULL,\n next_recording_after timestamp without time zone DEFAULT CURRENT_TIMESTAMP NOT NULL,\n deleted_at timestamp without time zone,\n backfill_queued_at timestamp without time zone,\n last_snapshot_at timestamp without time zone DEFAULT (CURRENT_TIMESTAMP - '10 years'::interval),\n next_snapshot_after timestamp without time zone DEFAULT CURRENT_TIMESTAMP,\n repositories text[],\n sample_interval_unit time_unit DEFAULT 'MONTH'::time_unit NOT NULL,\n sample_interval_value integer DEFAULT 1 NOT NULL,\n generated_from_capture_groups boolean DEFAULT false NOT NULL,\n generation_method text NOT NULL,\n just_in_time boolean DEFAULT false NOT NULL\n);\n\nCOMMENT ON TABLE insight_series IS 'Data series that comprise code insights.';\n\nCOMMENT ON COLUMN insight_series.id IS 'Primary key ID of this series';\n\nCOMMENT ON COLUMN insight_series.series_id IS 'Timestamp that this series completed a full repository iteration for backfill. This flag has limited semantic value, and only means it tried to queue up queries for each repository. It does not guarantee success on those queries.';\n\nCOMMENT ON COLUMN insight_series.query IS 'Query string that generates this series';\n\nCOMMENT ON COLUMN insight_series.created_at IS 'Timestamp when this series was created';\n\nCOMMENT ON COLUMN insight_series.oldest_historical_at IS 'Timestamp representing the oldest point of which this series is backfilled.';\n\nCOMMENT ON COLUMN insight_series.last_recorded_at IS 'Timestamp when this series was last recorded (non-historical).';\n\nCOMMENT ON COLUMN insight_series.next_recording_after IS 'Timestamp when this series should next record (non-historical).';\n\nCOMMENT ON COLUMN insight_series.deleted_at IS 'Timestamp of a soft-delete of this row.';\n\nCOMMENT ON COLUMN insight_series.generation_method IS 'Specifies the execution method for how this series is generated. This helps the system understand how to generate the time series data.';\n\nCOMMENT ON COLUMN insight_series.just_in_time IS 'Specifies if the series should be resolved just in time at query time, or recorded in background processing.';\n\nCREATE SEQUENCE insight_series_id_seq\n AS integer\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE insight_series_id_seq OWNED BY insight_series.id;\n\nCREATE TABLE insight_view (\n id integer NOT NULL,\n title text,\n description text,\n unique_id text NOT NULL,\n default_filter_include_repo_regex text,\n default_filter_exclude_repo_regex text,\n other_threshold double precision,\n presentation_type presentation_type_enum DEFAULT 'LINE'::presentation_type_enum NOT NULL,\n is_frozen boolean DEFAULT false NOT NULL\n);\n\nCOMMENT ON TABLE insight_view IS 'Views for insight data series. An insight view is an abstraction on top of an insight data series that allows for lightweight modifications to filters or metadata without regenerating the underlying series.';\n\nCOMMENT ON COLUMN insight_view.id IS 'Primary key ID for this view';\n\nCOMMENT ON COLUMN insight_view.title IS 'Title of the view. This may render in a chart depending on the view type.';\n\nCOMMENT ON COLUMN insight_view.description IS 'Description of the view. This may render in a chart depending on the view type.';\n\nCOMMENT ON COLUMN insight_view.unique_id IS 'Globally unique identifier for this view that is externally referencable.';\n\nCOMMENT ON COLUMN insight_view.other_threshold IS 'Percent threshold for grouping series under \"other\"';\n\nCOMMENT ON COLUMN insight_view.presentation_type IS 'The basic presentation type for the insight view. (e.g Line, Pie, etc.)';\n\nCREATE TABLE insight_view_grants (\n id integer NOT NULL,\n insight_view_id integer NOT NULL,\n user_id integer,\n org_id integer,\n global boolean\n);\n\nCOMMENT ON TABLE insight_view_grants IS 'Permission grants for insight views. Each row should represent a unique principal (user, org, etc).';\n\nCOMMENT ON COLUMN insight_view_grants.user_id IS 'User ID that that receives this grant.';\n\nCOMMENT ON COLUMN insight_view_grants.org_id IS 'Org ID that that receives this grant.';\n\nCOMMENT ON COLUMN insight_view_grants.global IS 'Grant that does not belong to any specific principal and is granted to all users.';\n\nCREATE SEQUENCE insight_view_grants_id_seq\n AS integer\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE insight_view_grants_id_seq OWNED BY insight_view_grants.id;\n\nCREATE SEQUENCE insight_view_id_seq\n AS integer\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE insight_view_id_seq OWNED BY insight_view.id;\n\nCREATE TABLE insight_view_series (\n insight_view_id integer NOT NULL,\n insight_series_id integer NOT NULL,\n label text,\n stroke text\n);\n\nCOMMENT ON TABLE insight_view_series IS 'Join table to correlate data series with insight views';\n\nCOMMENT ON COLUMN insight_view_series.insight_view_id IS 'Foreign key to insight view.';\n\nCOMMENT ON COLUMN insight_view_series.insight_series_id IS 'Foreign key to insight data series.';\n\nCOMMENT ON COLUMN insight_view_series.label IS 'Label text for this data series. This may render in a chart depending on the view type.';\n\nCOMMENT ON COLUMN insight_view_series.stroke IS 'Stroke color metadata for this data series. This may render in a chart depending on the view type.';\n\nCREATE TABLE metadata (\n id bigint NOT NULL,\n metadata jsonb NOT NULL\n);\n\nCOMMENT ON TABLE metadata IS 'Records arbitrary metadata about events. Stored in a separate table as it is often repeated for multiple events.';\n\nCOMMENT ON COLUMN metadata.id IS 'The metadata ID.';\n\nCOMMENT ON COLUMN metadata.metadata IS 'Metadata about some event, this can be any arbitrary JSON emtadata which will be returned when querying events, and can be filtered on and grouped using jsonb operators ?, ?\u0026, ?|, and @\u003e. This should be small data only.';\n\nCREATE SEQUENCE metadata_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE metadata_id_seq OWNED BY metadata.id;\n\nCREATE TABLE repo_names (\n id bigint NOT NULL,\n name citext NOT NULL,\n CONSTRAINT check_name_nonempty CHECK ((name OPERATOR(\u003c\u003e) ''::citext))\n);\n\nCOMMENT ON TABLE repo_names IS 'Records repository names, both historical and present, using a unique repository _name_ ID (unrelated to the repository ID.)';\n\nCOMMENT ON COLUMN repo_names.id IS 'The repository _name_ ID.';\n\nCOMMENT ON COLUMN repo_names.name IS 'The repository name string, with unique constraint for table entry deduplication and trigram index for e.g. regex filtering.';\n\nCREATE SEQUENCE repo_names_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE repo_names_id_seq OWNED BY repo_names.id;\n\nCREATE TABLE series_points (\n series_id text NOT NULL,\n \"time\" timestamp with time zone NOT NULL,\n value double precision NOT NULL,\n metadata_id integer,\n repo_id integer,\n repo_name_id integer,\n original_repo_name_id integer,\n capture text,\n CONSTRAINT check_repo_fields_specifity CHECK ((((repo_id IS NULL) AND (repo_name_id IS NULL) AND (original_repo_name_id IS NULL)) OR ((repo_id IS NOT NULL) AND (repo_name_id IS NOT NULL) AND (original_repo_name_id IS NOT NULL))))\n);\n\nCOMMENT ON TABLE series_points IS 'Records events over time associated with a repository (or none, i.e. globally) where a single numerical value is going arbitrarily up and down. Repository association is based on both repository ID and name. The ID can be used to refer toa specific repository, or lookup the current name of a repository after it has been e.g. renamed. The name can be used to refer to the name of the repository at the time of the events creation, for example to trace the change in a gauge back to a repository being renamed.';\n\nCOMMENT ON COLUMN series_points.series_id IS 'A unique identifier for the series of data being recorded. This is not an ID from another table, but rather just a unique identifier.';\n\nCOMMENT ON COLUMN series_points.\"time\" IS 'The timestamp of the recorded event.';\n\nCOMMENT ON COLUMN series_points.value IS 'The floating point value at the time of the event.';\n\nCOMMENT ON COLUMN series_points.metadata_id IS 'Associated metadata for this event, if any.';\n\nCOMMENT ON COLUMN series_points.repo_id IS 'The repository ID (from the main application DB) at the time the event was created. Note that the repository may no longer exist / be valid at query time, however.';\n\nCOMMENT ON COLUMN series_points.repo_name_id IS 'The most recently known name for the repository, updated periodically to account for e.g. repository renames. If the repository was deleted, this is still the most recently known name. null if the event was not for a single repository (i.e. a global gauge).';\n\nCOMMENT ON COLUMN series_points.original_repo_name_id IS 'The repository name as it was known at the time the event was created. It may have been renamed since.';\n\nCREATE TABLE series_points_snapshots (\n series_id text NOT NULL,\n \"time\" timestamp with time zone NOT NULL,\n value double precision NOT NULL,\n metadata_id integer,\n repo_id integer,\n repo_name_id integer,\n original_repo_name_id integer,\n capture text,\n CONSTRAINT check_repo_fields_specifity CHECK ((((repo_id IS NULL) AND (repo_name_id IS NULL) AND (original_repo_name_id IS NULL)) OR ((repo_id IS NOT NULL) AND (repo_name_id IS NOT NULL) AND (original_repo_name_id IS NOT NULL))))\n);\n\nCOMMENT ON TABLE series_points_snapshots IS 'Stores ephemeral snapshot data of insight recordings.';\n\nALTER TABLE ONLY dashboard ALTER COLUMN id SET DEFAULT nextval('dashboard_id_seq'::regclass);\n\nALTER TABLE ONLY dashboard_grants ALTER COLUMN id SET DEFAULT nextval('dashboard_grants_id_seq'::regclass);\n\nALTER TABLE ONLY dashboard_insight_view ALTER COLUMN id SET DEFAULT nextval('dashboard_insight_view_id_seq'::regclass);\n\nALTER TABLE ONLY insight_dirty_queries ALTER COLUMN id SET DEFAULT nextval('insight_dirty_queries_id_seq'::regclass);\n\nALTER TABLE ONLY insight_series ALTER COLUMN id SET DEFAULT nextval('insight_series_id_seq'::regclass);\n\nALTER TABLE ONLY insight_view ALTER COLUMN id SET DEFAULT nextval('insight_view_id_seq'::regclass);\n\nALTER TABLE ONLY insight_view_grants ALTER COLUMN id SET DEFAULT nextval('insight_view_grants_id_seq'::regclass);\n\nALTER TABLE ONLY metadata ALTER COLUMN id SET DEFAULT nextval('metadata_id_seq'::regclass);\n\nALTER TABLE ONLY repo_names ALTER COLUMN id SET DEFAULT nextval('repo_names_id_seq'::regclass);\n\nALTER TABLE ONLY commit_index_metadata\n ADD CONSTRAINT commit_index_metadata_pkey PRIMARY KEY (repo_id);\n\nALTER TABLE ONLY commit_index\n ADD CONSTRAINT commit_index_pkey PRIMARY KEY (committed_at, repo_id, commit_bytea);\n\nALTER TABLE ONLY dashboard_grants\n ADD CONSTRAINT dashboard_grants_pk PRIMARY KEY (id);\n\nALTER TABLE ONLY dashboard_insight_view\n ADD CONSTRAINT dashboard_insight_view_pk PRIMARY KEY (id);\n\nALTER TABLE ONLY dashboard\n ADD CONSTRAINT dashboard_pk PRIMARY KEY (id);\n\nALTER TABLE ONLY insight_dirty_queries\n ADD CONSTRAINT insight_dirty_queries_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY insight_series\n ADD CONSTRAINT insight_series_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY insight_view_grants\n ADD CONSTRAINT insight_view_grants_pk PRIMARY KEY (id);\n\nALTER TABLE ONLY insight_view\n ADD CONSTRAINT insight_view_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY insight_view_series\n ADD CONSTRAINT insight_view_series_pkey PRIMARY KEY (insight_view_id, insight_series_id);\n\nALTER TABLE ONLY metadata\n ADD CONSTRAINT metadata_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY repo_names\n ADD CONSTRAINT repo_names_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY dashboard_insight_view\n ADD CONSTRAINT unique_dashboard_id_insight_view_id UNIQUE (dashboard_id, insight_view_id);\n\nCREATE INDEX commit_index_repo_id_idx ON commit_index USING btree (repo_id, committed_at);\n\nCREATE INDEX dashboard_grants_dashboard_id_index ON dashboard_grants USING btree (dashboard_id);\n\nCREATE INDEX dashboard_grants_global_idx ON dashboard_grants USING btree (global) WHERE (global IS TRUE);\n\nCREATE INDEX dashboard_grants_org_id_idx ON dashboard_grants USING btree (org_id);\n\nCREATE INDEX dashboard_grants_user_id_idx ON dashboard_grants USING btree (user_id);\n\nCREATE INDEX dashboard_insight_view_dashboard_id_fk_idx ON dashboard_insight_view USING btree (dashboard_id);\n\nCREATE INDEX dashboard_insight_view_insight_view_id_fk_idx ON dashboard_insight_view USING btree (insight_view_id);\n\nCREATE INDEX insight_dirty_queries_insight_series_id_fk_idx ON insight_dirty_queries USING btree (insight_series_id);\n\nCREATE INDEX insight_series_deleted_at_idx ON insight_series USING btree (deleted_at);\n\nCREATE INDEX insight_series_next_recording_after_idx ON insight_series USING btree (next_recording_after);\n\nCREATE UNIQUE INDEX insight_series_series_id_unique_idx ON insight_series USING btree (series_id);\n\nCREATE INDEX insight_view_grants_global_idx ON insight_view_grants USING btree (global) WHERE (global IS TRUE);\n\nCREATE INDEX insight_view_grants_insight_view_id_index ON insight_view_grants USING btree (insight_view_id);\n\nCREATE INDEX insight_view_grants_org_id_idx ON insight_view_grants USING btree (org_id);\n\nCREATE INDEX insight_view_grants_user_id_idx ON insight_view_grants USING btree (user_id);\n\nCREATE UNIQUE INDEX insight_view_unique_id_unique_idx ON insight_view USING btree (unique_id);\n\nCREATE INDEX metadata_metadata_gin ON metadata USING gin (metadata);\n\nCREATE UNIQUE INDEX metadata_metadata_unique_idx ON metadata USING btree (metadata);\n\nCREATE INDEX repo_names_name_trgm ON repo_names USING gin (lower((name)::text) gin_trgm_ops);\n\nCREATE UNIQUE INDEX repo_names_name_unique_idx ON repo_names USING btree (name);\n\nCREATE INDEX series_points_original_repo_name_id_btree ON series_points USING btree (original_repo_name_id);\n\nCREATE INDEX series_points_repo_id_btree ON series_points USING btree (repo_id);\n\nCREATE INDEX series_points_repo_name_id_btree ON series_points USING btree (repo_name_id);\n\nCREATE INDEX series_points_series_id_btree ON series_points USING btree (series_id);\n\nCREATE INDEX series_points_series_id_repo_id_time_idx ON series_points USING btree (series_id, repo_id, \"time\");\n\nCREATE INDEX series_points_snapshots_original_repo_name_id_idx ON series_points_snapshots USING btree (original_repo_name_id);\n\nCREATE INDEX series_points_snapshots_repo_id_idx ON series_points_snapshots USING btree (repo_id);\n\nCREATE INDEX series_points_snapshots_repo_name_id_idx ON series_points_snapshots USING btree (repo_name_id);\n\nCREATE INDEX series_points_snapshots_series_id_idx ON series_points_snapshots USING btree (series_id);\n\nCREATE INDEX series_points_snapshots_series_id_repo_id_time_idx ON series_points_snapshots USING btree (series_id, repo_id, \"time\");\n\nALTER TABLE ONLY dashboard_grants\n ADD CONSTRAINT dashboard_grants_dashboard_id_fk FOREIGN KEY (dashboard_id) REFERENCES dashboard(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY dashboard_insight_view\n ADD CONSTRAINT dashboard_insight_view_dashboard_id_fk FOREIGN KEY (dashboard_id) REFERENCES dashboard(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY dashboard_insight_view\n ADD CONSTRAINT dashboard_insight_view_insight_view_id_fk FOREIGN KEY (insight_view_id) REFERENCES insight_view(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY insight_dirty_queries\n ADD CONSTRAINT insight_dirty_queries_insight_series_id_fkey FOREIGN KEY (insight_series_id) REFERENCES insight_series(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY insight_view_grants\n ADD CONSTRAINT insight_view_grants_insight_view_id_fk FOREIGN KEY (insight_view_id) REFERENCES insight_view(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY insight_view_series\n ADD CONSTRAINT insight_view_series_insight_series_id_fkey FOREIGN KEY (insight_series_id) REFERENCES insight_series(id);\n\nALTER TABLE ONLY insight_view_series\n ADD CONSTRAINT insight_view_series_insight_view_id_fkey FOREIGN KEY (insight_view_id) REFERENCES insight_view(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY series_points\n ADD CONSTRAINT series_points_metadata_id_fkey FOREIGN KEY (metadata_id) REFERENCES metadata(id) ON DELETE CASCADE DEFERRABLE;\n\nALTER TABLE ONLY series_points\n ADD CONSTRAINT series_points_original_repo_name_id_fkey FOREIGN KEY (original_repo_name_id) REFERENCES repo_names(id) ON DELETE CASCADE DEFERRABLE;\n\nALTER TABLE ONLY series_points\n ADD CONSTRAINT series_points_repo_name_id_fkey FOREIGN KEY (repo_name_id) REFERENCES repo_names(id) ON DELETE CASCADE DEFERRABLE;", + "DownQuery": "-- Nothing", + "Privileged": false, + "NonIdempotent": true, + "Parents": [ + 1000000027 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1647894746, + "Name": "dashboard_type", + "UpQuery": "ALTER TABLE IF EXISTS dashboard ADD COLUMN IF NOT EXISTS type TEXT DEFAULT 'standard'::text NOT NULL;", + "DownQuery": "ALTER TABLE IF EXISTS dashboard DROP COLUMN IF EXISTS type;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1646761143 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1649801281, + "Name": "context_filters", + "UpQuery": "ALTER TABLE IF EXISTS insight_view ADD COLUMN IF NOT EXISTS default_filter_search_contexts TEXT[];", + "DownQuery": "ALTER TABLE IF EXISTS insight_view DROP COLUMN IF EXISTS default_filter_search_contexts;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1647894746 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1651021000, + "Name": "sort_series", + "UpQuery": "DO $$\nBEGIN\n CREATE TYPE series_sort_mode_enum AS ENUM (\n 'RESULT_COUNT',\n 'LEXICOGRAPHICAL',\n 'DATE_ADDED'\n );\nEXCEPTION\n WHEN duplicate_object THEN null;\nEND $$;\n\nDO $$\nBEGIN\n CREATE TYPE series_sort_direction_enum AS ENUM (\n 'ASC',\n 'DESC'\n );\nEXCEPTION\n WHEN duplicate_object THEN null;\nEND $$;\n\nALTER TABLE IF EXISTS insight_view\n ADD COLUMN IF NOT EXISTS series_sort_mode series_sort_mode_enum,\n ADD COLUMN IF NOT EXISTS series_sort_direction series_sort_direction_enum,\n ADD COLUMN IF NOT EXISTS series_limit INT;", + "DownQuery": "ALTER TABLE IF EXISTS insight_view\n DROP COLUMN IF EXISTS series_sort_mode,\n DROP COLUMN IF EXISTS series_sort_direction,\n DROP COLUMN IF EXISTS series_limit;\n\nDROP TYPE IF EXISTS series_sort_mode_enum;\nDROP TYPE IF EXISTS series_sort_direction_enum;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1649801281 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1652289966, + "Name": "deprecate-search-stream-generation-method", + "UpQuery": "UPDATE insight_series\n SET generation_method = 'search'\n WHERE generation_method = 'search-stream';", + "DownQuery": "-- Update cannot be reverted, but this has minimal impact.", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1649801281 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1656517037, + "Name": "group_by", + "UpQuery": "ALTER TABLE IF EXISTS insight_series ADD COLUMN IF NOT EXISTS group_by TEXT;", + "DownQuery": "ALTER TABLE IF EXISTS insight_series DROP COLUMN IF EXISTS group_by;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1651021000, + 1652289966 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1656608833, + "Name": "track_backfill_attempts", + "UpQuery": "-- Perform migration here.\n--\nALTER TABLE IF EXISTS insight_series\n ADD COLUMN IF NOT EXISTS backfill_attempts INT NOT NULL DEFAULT 0;", + "DownQuery": "-- Undo the changes made in the up migration\nALTER TABLE IF EXISTS insight_series DROP COLUMN IF EXISTS backfill_attempts;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1651021000, + 1652289966 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1659572248, + "Name": "refresh_scoped_insights", + "UpQuery": "ALTER TABLE IF EXISTS insight_series\n ADD COLUMN IF NOT EXISTS needs_migration bool;\n\n\nupdate insight_series\nset needs_migration = true\nwhere cardinality(repositories) \u003e 0 AND generation_method in ('search', 'search-compute') AND needs_migration is NULL;", + "DownQuery": "-- take no action on down so that the next up will not trigger another refreshing of series data.", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1656517037, + 1656608833 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1663626068, + "Name": "backfill_completed_at", + "UpQuery": "ALTER TABLE IF EXISTS insight_series\n ADD COLUMN IF NOT EXISTS backfill_completed_at TIMESTAMP;", + "DownQuery": "ALTER TABLE IF EXISTS insight_series DROP COLUMN IF EXISTS backfill_completed_at;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1659572248 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1664984848, + "Name": "insights_scheduler_table", + "UpQuery": "CREATE TABLE IF NOT EXISTS insights_background_jobs (\n id SERIAL PRIMARY KEY,\n state text DEFAULT 'queued',\n failure_message text,\n queued_at timestamp with time zone DEFAULT NOW(),\n started_at timestamp with time zone,\n finished_at timestamp with time zone,\n process_after timestamp with time zone,\n num_resets integer not null default 0,\n num_failures integer not null default 0,\n last_heartbeat_at timestamp with time zone,\n execution_logs json[],\n worker_hostname text not null default '',\n cancel boolean not null default false\n);\n\nCREATE INDEX IF NOT EXISTS insights_jobs_state_idx ON insights_background_jobs(state);", + "DownQuery": "DROP TABLE IF EXISTS insights_background_jobs;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1663626068 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1665003565, + "Name": "insights_backfill_scheduler_state", + "UpQuery": "CREATE TABLE IF NOT EXISTS repo_iterator\n(\n id SERIAL\n CONSTRAINT repo_iterator_pk PRIMARY KEY,\n created_at TIMESTAMP DEFAULT NOW(),\n started_at TIMESTAMP,\n completed_at TIMESTAMP,\n last_updated_at TIMESTAMP NOT NULL DEFAULT NOW(),\n runtime_duration BIGINT NOT NULL DEFAULT 0,\n percent_complete DOUBLE PRECISION NOT NULL DEFAULT 0,\n total_count INT NOT NULL DEFAULT 0,\n success_count INT NOT NULL DEFAULT 0,\n repos INT[],\n repo_cursor INT DEFAULT 0\n);\n\nCREATE TABLE IF NOT EXISTS repo_iterator_errors\n(\n id SERIAL\n CONSTRAINT repo_iterator_errors_pk PRIMARY KEY,\n repo_iterator_id INT NOT NULL,\n repo_id INT NOT NULL,\n error_message TEXT[] NOT NULL,\n failure_count INT DEFAULT 1,\n\n CONSTRAINT repo_iterator_fk FOREIGN KEY (repo_iterator_id) REFERENCES repo_iterator (id)\n);\n\nCREATE INDEX IF NOT EXISTS repo_iterator_errors_fk_idx\n ON repo_iterator_errors (repo_iterator_id);", + "DownQuery": "drop table if exists repo_iterator CASCADE;\ndrop table if exists repo_iterator_errors;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1664984848 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1665616961, + "Name": "backfill_table", + "UpQuery": "CREATE TABLE IF NOT EXISTS insight_series_backfill\n(\n id SERIAL\n CONSTRAINT insight_series_backfill_pk PRIMARY KEY,\n series_id INT NOT NULL,\n repo_iterator_id INT,\n estimated_cost DOUBLE PRECISION,\n state TEXT NOT NULL DEFAULT 'new',\n\n CONSTRAINT insight_series_backfill_series_id_fk\n FOREIGN KEY (series_id) REFERENCES insight_series (id) ON DELETE CASCADE\n);\n\nALTER TABLE insights_background_jobs\n ADD COLUMN IF NOT EXISTS backfill_id INT REFERENCES insight_series_backfill(id) ON DELETE CASCADE;\n\nCREATE OR REPLACE VIEW insights_jobs_backfill_in_progress AS\nSELECT jobs.*, isb.state AS backfill_state, isb.estimated_cost\nFROM insights_background_jobs jobs\n JOIN insight_series_backfill isb ON jobs.backfill_id = isb.id\nWHERE isb.state = 'processing';\n\nCREATE OR REPLACE VIEW insights_jobs_backfill_new AS\nSELECT jobs.*, isb.state AS backfill_state, isb.estimated_cost\nFROM insights_background_jobs jobs\n JOIN insight_series_backfill isb ON jobs.backfill_id = isb.id\nWHERE isb.state = 'new';", + "DownQuery": "DROP VIEW IF EXISTS insights_jobs_backfill_in_progress;\n\nDROP VIEW IF EXISTS insights_jobs_backfill_new;\n\nALTER TABLE insights_background_jobs\n DROP COLUMN IF EXISTS backfill_id;\n\nDROP TABLE IF EXISTS insight_series_backfill;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1665003565 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1665053848, + "Name": "add_insight_series_recording_times", + "UpQuery": "CREATE TABLE IF NOT EXISTS insight_series_recording_times (\n\tinsight_series_id int,\n\trecording_time timestamptz,\n\tsnapshot bool,\n\tUNIQUE (insight_series_id, recording_time),\n\tCONSTRAINT insight_series_id_fkey FOREIGN KEY (insight_series_id) REFERENCES insight_series (id) ON DELETE CASCADE\n);", + "DownQuery": "DROP TABLE IF EXISTS insight_series_recording_times;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1664984848 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1666632478, + "Name": "add_supports_augmentation_column", + "UpQuery": "ALTER TABLE IF EXISTS insight_series\n\tADD COLUMN IF NOT EXISTS supports_augmentation BOOLEAN NOT NULL DEFAULT TRUE;\n\nUPDATE insight_series SET supports_augmentation = FALSE;", + "DownQuery": "ALTER TABLE IF EXISTS insight_series DROP COLUMN IF EXISTS supports_augmentation;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1665053848, + 1665616961 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1666729025, + "Name": "incomplete_points", + "UpQuery": "CREATE TABLE IF NOT EXISTS insight_series_incomplete_points\n(\n id SERIAL CONSTRAINT insight_series_incomplete_points_pk PRIMARY KEY,\n series_id INT NOT NULL,\n reason TEXT NOT NULL,\n time TIMESTAMP WITHOUT TIME ZONE NOT NULL,\n repo_id INT,\n\n CONSTRAINT insight_series_incomplete_points_series_id_fk\n FOREIGN KEY (series_id) REFERENCES insight_series (id) ON DELETE CASCADE\n);\n\nCREATE UNIQUE INDEX IF NOT EXISTS insight_series_incomplete_points_unique_idx\n ON insight_series_incomplete_points (series_id, reason, time, repo_id);", + "DownQuery": "DROP TABLE IF EXISTS insight_series_incomplete_points;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1666632478 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1667309737, + "Name": "backfill cost groups", + "UpQuery": "CREATE OR REPLACE VIEW insights_jobs_backfill_in_progress AS\nSELECT\n jobs.*,\n isb.state AS backfill_state,\n isb.estimated_cost,\n width_bucket(isb.estimated_cost, 0, max(isb.estimated_cost+1) over (), 4) cost_bucket\nFROM insights_background_jobs jobs\n JOIN insight_series_backfill isb ON jobs.backfill_id = isb.id\nWHERE isb.state = 'processing';", + "DownQuery": "-- Undo the changes made in the up migration\ndrop view if exists insights_jobs_backfill_in_progress;\n\nCREATE OR REPLACE VIEW insights_jobs_backfill_in_progress AS\nSELECT jobs.*, isb.state AS backfill_state, isb.estimated_cost\nFROM insights_background_jobs jobs\n JOIN insight_series_backfill isb ON jobs.backfill_id = isb.id\nWHERE isb.state = 'processing';", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1666632478 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + } + ], + "BoundsByRev": { + "4.3.0": { + "RootID": 1000000027, + "LeafIDs": [ + 1666729025, + 1667309737 + ], + "PreCreation": false + } + } + }, + "codeintel": { + "Definitions": [ + { + "ID": 1000000033, + "Name": "squashed migrations (privileged)", + "UpQuery": "CREATE EXTENSION IF NOT EXISTS intarray;\n\nCOMMENT ON EXTENSION intarray IS 'functions, operators, and index support for 1-D arrays of integers';\n\nCREATE EXTENSION IF NOT EXISTS pg_stat_statements;\n\nCOMMENT ON EXTENSION pg_stat_statements IS 'track execution statistics of all SQL statements executed';\n\nCREATE EXTENSION IF NOT EXISTS pg_trgm;\n\nCOMMENT ON EXTENSION pg_trgm IS 'text similarity measurement and index searching based on trigrams';", + "DownQuery": "-- Nothing", + "Privileged": true, + "NonIdempotent": true, + "Parents": [], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1000000034, + "Name": "squashed migrations (unprivileged)", + "UpQuery": "CREATE FUNCTION get_file_extension(path text) RETURNS text\n LANGUAGE plpgsql IMMUTABLE\n AS $_$ BEGIN\n RETURN substring(path FROM '\\.([^\\.]*)$');\nEND; $_$;\n\nCREATE FUNCTION lsif_data_docs_search_private_delete() RETURNS trigger\n LANGUAGE plpgsql\n AS $$\nBEGIN\nUPDATE lsif_data_apidocs_num_search_results_private SET count = count - (select count(*) from oldtbl);\nRETURN NULL;\nEND $$;\n\nCREATE FUNCTION lsif_data_docs_search_private_insert() RETURNS trigger\n LANGUAGE plpgsql\n AS $$\nBEGIN\nUPDATE lsif_data_apidocs_num_search_results_private SET count = count + (select count(*) from newtbl);\nRETURN NULL;\nEND $$;\n\nCREATE FUNCTION lsif_data_docs_search_public_delete() RETURNS trigger\n LANGUAGE plpgsql\n AS $$\nBEGIN\nUPDATE lsif_data_apidocs_num_search_results_public SET count = count - (select count(*) from oldtbl);\nRETURN NULL;\nEND $$;\n\nCREATE FUNCTION lsif_data_docs_search_public_insert() RETURNS trigger\n LANGUAGE plpgsql\n AS $$\nBEGIN\nUPDATE lsif_data_apidocs_num_search_results_public SET count = count + (select count(*) from newtbl);\nRETURN NULL;\nEND $$;\n\nCREATE FUNCTION lsif_data_documentation_pages_delete() RETURNS trigger\n LANGUAGE plpgsql\n AS $$\nBEGIN\nUPDATE lsif_data_apidocs_num_pages SET count = count - (select count(*) from oldtbl);\nUPDATE lsif_data_apidocs_num_dumps SET count = count - (select count(DISTINCT dump_id) from oldtbl);\nUPDATE lsif_data_apidocs_num_dumps_indexed SET count = count - (select count(DISTINCT dump_id) from oldtbl WHERE search_indexed='true');\nRETURN NULL;\nEND $$;\n\nCREATE FUNCTION lsif_data_documentation_pages_insert() RETURNS trigger\n LANGUAGE plpgsql\n AS $$\nBEGIN\nUPDATE lsif_data_apidocs_num_pages SET count = count + (select count(*) from newtbl);\nUPDATE lsif_data_apidocs_num_dumps SET count = count + (select count(DISTINCT dump_id) from newtbl);\nUPDATE lsif_data_apidocs_num_dumps_indexed SET count = count + (select count(DISTINCT dump_id) from newtbl WHERE search_indexed='true');\nRETURN NULL;\nEND $$;\n\nCREATE FUNCTION lsif_data_documentation_pages_update() RETURNS trigger\n LANGUAGE plpgsql\n AS $$\nBEGIN\nWITH\n beforeIndexed AS (SELECT count(DISTINCT dump_id) FROM oldtbl WHERE search_indexed='true'),\n afterIndexed AS (SELECT count(DISTINCT dump_id) FROM newtbl WHERE search_indexed='true')\nUPDATE lsif_data_apidocs_num_dumps_indexed SET count=count + ((select * from afterIndexed) - (select * from beforeIndexed));\nRETURN NULL;\nEND $$;\n\nCREATE FUNCTION path_prefixes(path text) RETURNS text[]\n LANGUAGE plpgsql IMMUTABLE\n AS $$ BEGIN\n RETURN (\n SELECT array_agg(array_to_string(components[:len], '/')) prefixes\n FROM\n (SELECT regexp_split_to_array(path, E'/') components) t,\n generate_series(1, array_length(components, 1)) AS len\n );\nEND; $$;\n\nCREATE FUNCTION singleton(value text) RETURNS text[]\n LANGUAGE plpgsql IMMUTABLE\n AS $$ BEGIN\n RETURN ARRAY[value];\nEND; $$;\n\nCREATE FUNCTION singleton_integer(value integer) RETURNS integer[]\n LANGUAGE plpgsql IMMUTABLE\n AS $$ BEGIN\n RETURN ARRAY[value];\nEND; $$;\n\nCREATE FUNCTION update_lsif_data_definitions_schema_versions_insert() RETURNS trigger\n LANGUAGE plpgsql\n AS $$ BEGIN\n INSERT INTO\n lsif_data_definitions_schema_versions\n SELECT\n dump_id,\n MIN(schema_version) as min_schema_version,\n MAX(schema_version) as max_schema_version\n FROM\n newtab\n GROUP BY\n dump_id\n ON CONFLICT (dump_id) DO UPDATE SET\n -- Update with min(old_min, new_min) and max(old_max, new_max)\n min_schema_version = LEAST(lsif_data_definitions_schema_versions.min_schema_version, EXCLUDED.min_schema_version),\n max_schema_version = GREATEST(lsif_data_definitions_schema_versions.max_schema_version, EXCLUDED.max_schema_version);\n\n RETURN NULL;\nEND $$;\n\nCREATE FUNCTION update_lsif_data_documents_schema_versions_insert() RETURNS trigger\n LANGUAGE plpgsql\n AS $$ BEGIN\n INSERT INTO\n lsif_data_documents_schema_versions\n SELECT\n dump_id,\n MIN(schema_version) as min_schema_version,\n MAX(schema_version) as max_schema_version\n FROM\n newtab\n GROUP BY\n dump_id\n ON CONFLICT (dump_id) DO UPDATE SET\n -- Update with min(old_min, new_min) and max(old_max, new_max)\n min_schema_version = LEAST(lsif_data_documents_schema_versions.min_schema_version, EXCLUDED.min_schema_version),\n max_schema_version = GREATEST(lsif_data_documents_schema_versions.max_schema_version, EXCLUDED.max_schema_version);\n\n RETURN NULL;\nEND $$;\n\nCREATE FUNCTION update_lsif_data_implementations_schema_versions_insert() RETURNS trigger\n LANGUAGE plpgsql\n AS $$ BEGIN\n INSERT INTO\n lsif_data_implementations_schema_versions\n SELECT\n dump_id,\n MIN(schema_version) as min_schema_version,\n MAX(schema_version) as max_schema_version\n FROM\n newtab\n GROUP BY\n dump_id\n ON CONFLICT (dump_id) DO UPDATE SET\n -- Update with min(old_min, new_min) and max(old_max, new_max)\n min_schema_version = LEAST (lsif_data_implementations_schema_versions.min_schema_version, EXCLUDED.min_schema_version),\n max_schema_version = GREATEST(lsif_data_implementations_schema_versions.max_schema_version, EXCLUDED.max_schema_version);\n\n RETURN NULL;\nEND $$;\n\nCREATE FUNCTION update_lsif_data_references_schema_versions_insert() RETURNS trigger\n LANGUAGE plpgsql\n AS $$ BEGIN\n INSERT INTO\n lsif_data_references_schema_versions\n SELECT\n dump_id,\n MIN(schema_version) as min_schema_version,\n MAX(schema_version) as max_schema_version\n FROM\n newtab\n GROUP BY\n dump_id\n ON CONFLICT (dump_id) DO UPDATE SET\n -- Update with min(old_min, new_min) and max(old_max, new_max)\n min_schema_version = LEAST(lsif_data_references_schema_versions.min_schema_version, EXCLUDED.min_schema_version),\n max_schema_version = GREATEST(lsif_data_references_schema_versions.max_schema_version, EXCLUDED.max_schema_version);\n\n RETURN NULL;\nEND $$;\n\nCREATE TABLE lsif_data_apidocs_num_dumps (\n count bigint\n);\n\nCREATE TABLE lsif_data_apidocs_num_dumps_indexed (\n count bigint\n);\n\nCREATE TABLE lsif_data_apidocs_num_pages (\n count bigint\n);\n\nCREATE TABLE lsif_data_apidocs_num_search_results_private (\n count bigint\n);\n\nCREATE TABLE lsif_data_apidocs_num_search_results_public (\n count bigint\n);\n\nCREATE TABLE lsif_data_definitions (\n dump_id integer NOT NULL,\n scheme text NOT NULL,\n identifier text NOT NULL,\n data bytea,\n schema_version integer NOT NULL,\n num_locations integer NOT NULL\n);\n\nCOMMENT ON TABLE lsif_data_definitions IS 'Associates (document, range) pairs with the import monikers attached to the range.';\n\nCOMMENT ON COLUMN lsif_data_definitions.dump_id IS 'The identifier of the associated dump in the lsif_uploads table (state=completed).';\n\nCOMMENT ON COLUMN lsif_data_definitions.scheme IS 'The moniker scheme.';\n\nCOMMENT ON COLUMN lsif_data_definitions.identifier IS 'The moniker identifier.';\n\nCOMMENT ON COLUMN lsif_data_definitions.data IS 'A gob-encoded payload conforming to an array of [LocationData](https://sourcegraph.com/github.com/sourcegraph/sourcegraph@3.26/-/blob/enterprise/lib/codeintel/semantic/types.go#L106:6) types.';\n\nCOMMENT ON COLUMN lsif_data_definitions.schema_version IS 'The schema version of this row - used to determine presence and encoding of data.';\n\nCOMMENT ON COLUMN lsif_data_definitions.num_locations IS 'The number of locations stored in the data field.';\n\nCREATE TABLE lsif_data_definitions_schema_versions (\n dump_id integer NOT NULL,\n min_schema_version integer,\n max_schema_version integer\n);\n\nCOMMENT ON TABLE lsif_data_definitions_schema_versions IS 'Tracks the range of schema_versions for each upload in the lsif_data_definitions table.';\n\nCOMMENT ON COLUMN lsif_data_definitions_schema_versions.dump_id IS 'The identifier of the associated dump in the lsif_uploads table.';\n\nCOMMENT ON COLUMN lsif_data_definitions_schema_versions.min_schema_version IS 'A lower-bound on the `lsif_data_definitions.schema_version` where `lsif_data_definitions.dump_id = dump_id`.';\n\nCOMMENT ON COLUMN lsif_data_definitions_schema_versions.max_schema_version IS 'An upper-bound on the `lsif_data_definitions.schema_version` where `lsif_data_definitions.dump_id = dump_id`.';\n\nCREATE TABLE lsif_data_docs_search_current_private (\n repo_id integer NOT NULL,\n dump_root text NOT NULL,\n lang_name_id integer NOT NULL,\n dump_id integer NOT NULL,\n last_cleanup_scan_at timestamp with time zone DEFAULT now() NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n id integer NOT NULL\n);\n\nCOMMENT ON TABLE lsif_data_docs_search_current_private IS 'A table indicating the most current search index for a unique repository, root, and language.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_current_private.repo_id IS 'The repository identifier of the associated dump.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_current_private.dump_root IS 'The root of the associated dump.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_current_private.lang_name_id IS 'The interned index name of the associated dump.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_current_private.dump_id IS 'The associated dump identifier.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_current_private.last_cleanup_scan_at IS 'The last time this record was checked as part of a data retention scan.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_current_private.created_at IS 'The time this record was inserted. The records with the latest created_at value for the same repository, root, and language is the only visible one and others will be deleted asynchronously.';\n\nCREATE SEQUENCE lsif_data_docs_search_current_private_id_seq\n AS integer\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE lsif_data_docs_search_current_private_id_seq OWNED BY lsif_data_docs_search_current_private.id;\n\nCREATE TABLE lsif_data_docs_search_current_public (\n repo_id integer NOT NULL,\n dump_root text NOT NULL,\n lang_name_id integer NOT NULL,\n dump_id integer NOT NULL,\n last_cleanup_scan_at timestamp with time zone DEFAULT now() NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n id integer NOT NULL\n);\n\nCOMMENT ON TABLE lsif_data_docs_search_current_public IS 'A table indicating the most current search index for a unique repository, root, and language.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_current_public.repo_id IS 'The repository identifier of the associated dump.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_current_public.dump_root IS 'The root of the associated dump.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_current_public.lang_name_id IS 'The interned index name of the associated dump.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_current_public.dump_id IS 'The associated dump identifier.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_current_public.last_cleanup_scan_at IS 'The last time this record was checked as part of a data retention scan.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_current_public.created_at IS 'The time this record was inserted. The records with the latest created_at value for the same repository, root, and language is the only visible one and others will be deleted asynchronously.';\n\nCREATE SEQUENCE lsif_data_docs_search_current_public_id_seq\n AS integer\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE lsif_data_docs_search_current_public_id_seq OWNED BY lsif_data_docs_search_current_public.id;\n\nCREATE TABLE lsif_data_docs_search_lang_names_private (\n id bigint NOT NULL,\n lang_name text NOT NULL,\n tsv tsvector NOT NULL\n);\n\nCOMMENT ON TABLE lsif_data_docs_search_lang_names_private IS 'Each unique language name being stored in the API docs search index.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_lang_names_private.id IS 'The ID of the language name.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_lang_names_private.lang_name IS 'The lowercase language name (go, java, etc.) OR, if unknown, the LSIF indexer name.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_lang_names_private.tsv IS 'Indexed tsvector for the lang_name field. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\n\nCREATE SEQUENCE lsif_data_docs_search_lang_names_private_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE lsif_data_docs_search_lang_names_private_id_seq OWNED BY lsif_data_docs_search_lang_names_private.id;\n\nCREATE TABLE lsif_data_docs_search_lang_names_public (\n id bigint NOT NULL,\n lang_name text NOT NULL,\n tsv tsvector NOT NULL\n);\n\nCOMMENT ON TABLE lsif_data_docs_search_lang_names_public IS 'Each unique language name being stored in the API docs search index.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_lang_names_public.id IS 'The ID of the language name.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_lang_names_public.lang_name IS 'The lowercase language name (go, java, etc.) OR, if unknown, the LSIF indexer name.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_lang_names_public.tsv IS 'Indexed tsvector for the lang_name field. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\n\nCREATE SEQUENCE lsif_data_docs_search_lang_names_public_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE lsif_data_docs_search_lang_names_public_id_seq OWNED BY lsif_data_docs_search_lang_names_public.id;\n\nCREATE TABLE lsif_data_docs_search_private (\n id bigint NOT NULL,\n repo_id integer NOT NULL,\n dump_id integer NOT NULL,\n dump_root text NOT NULL,\n path_id text NOT NULL,\n detail text NOT NULL,\n lang_name_id integer NOT NULL,\n repo_name_id integer NOT NULL,\n tags_id integer NOT NULL,\n search_key text NOT NULL,\n search_key_tsv tsvector NOT NULL,\n search_key_reverse_tsv tsvector NOT NULL,\n label text NOT NULL,\n label_tsv tsvector NOT NULL,\n label_reverse_tsv tsvector NOT NULL\n);\n\nCOMMENT ON TABLE lsif_data_docs_search_private IS 'A tsvector search index over API documentation (private repos only)';\n\nCOMMENT ON COLUMN lsif_data_docs_search_private.id IS 'The row ID of the search result.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_private.repo_id IS 'The repo ID, from the main app DB repo table. Used to search over a select set of repos by ID.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_private.dump_id IS 'The identifier of the associated dump in the lsif_uploads table (state=completed).';\n\nCOMMENT ON COLUMN lsif_data_docs_search_private.dump_root IS 'Identical to lsif_dumps.root; The working directory of the indexer image relative to the repository root.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_private.path_id IS 'The fully qualified documentation page path ID, e.g. including \"#section\". See GraphQL codeintel.schema:documentationPage for what this is.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_private.detail IS 'The detail string (e.g. the full function signature and its docs). See protocol/documentation.go:Documentation';\n\nCOMMENT ON COLUMN lsif_data_docs_search_private.lang_name_id IS 'The programming language (or indexer name) that produced the result. Foreign key into lsif_data_docs_search_lang_names_private.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_private.repo_name_id IS 'The repository name that produced the result. Foreign key into lsif_data_docs_search_repo_names_private.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_private.tags_id IS 'The tags from the documentation node. Foreign key into lsif_data_docs_search_tags_private.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_private.search_key IS 'The search key generated by the indexer, e.g. mux.Router.ServeHTTP. It is language-specific, and likely unique within a repository (but not always.) See protocol/documentation.go:Documentation.SearchKey';\n\nCOMMENT ON COLUMN lsif_data_docs_search_private.search_key_tsv IS 'Indexed tsvector for the search_key field. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_private.search_key_reverse_tsv IS 'Indexed tsvector for the reverse of the search_key field, for suffix lexeme/word matching. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_private.label IS 'The label string of the result, e.g. a one-line function signature. See protocol/documentation.go:Documentation';\n\nCOMMENT ON COLUMN lsif_data_docs_search_private.label_tsv IS 'Indexed tsvector for the label field. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_private.label_reverse_tsv IS 'Indexed tsvector for the reverse of the label field, for suffix lexeme/word matching. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\n\nCREATE SEQUENCE lsif_data_docs_search_private_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE lsif_data_docs_search_private_id_seq OWNED BY lsif_data_docs_search_private.id;\n\nCREATE TABLE lsif_data_docs_search_public (\n id bigint NOT NULL,\n repo_id integer NOT NULL,\n dump_id integer NOT NULL,\n dump_root text NOT NULL,\n path_id text NOT NULL,\n detail text NOT NULL,\n lang_name_id integer NOT NULL,\n repo_name_id integer NOT NULL,\n tags_id integer NOT NULL,\n search_key text NOT NULL,\n search_key_tsv tsvector NOT NULL,\n search_key_reverse_tsv tsvector NOT NULL,\n label text NOT NULL,\n label_tsv tsvector NOT NULL,\n label_reverse_tsv tsvector NOT NULL\n);\n\nCOMMENT ON TABLE lsif_data_docs_search_public IS 'A tsvector search index over API documentation (public repos only)';\n\nCOMMENT ON COLUMN lsif_data_docs_search_public.id IS 'The row ID of the search result.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_public.repo_id IS 'The repo ID, from the main app DB repo table. Used to search over a select set of repos by ID.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_public.dump_id IS 'The identifier of the associated dump in the lsif_uploads table (state=completed).';\n\nCOMMENT ON COLUMN lsif_data_docs_search_public.dump_root IS 'Identical to lsif_dumps.root; The working directory of the indexer image relative to the repository root.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_public.path_id IS 'The fully qualified documentation page path ID, e.g. including \"#section\". See GraphQL codeintel.schema:documentationPage for what this is.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_public.detail IS 'The detail string (e.g. the full function signature and its docs). See protocol/documentation.go:Documentation';\n\nCOMMENT ON COLUMN lsif_data_docs_search_public.lang_name_id IS 'The programming language (or indexer name) that produced the result. Foreign key into lsif_data_docs_search_lang_names_public.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_public.repo_name_id IS 'The repository name that produced the result. Foreign key into lsif_data_docs_search_repo_names_public.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_public.tags_id IS 'The tags from the documentation node. Foreign key into lsif_data_docs_search_tags_public.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_public.search_key IS 'The search key generated by the indexer, e.g. mux.Router.ServeHTTP. It is language-specific, and likely unique within a repository (but not always.) See protocol/documentation.go:Documentation.SearchKey';\n\nCOMMENT ON COLUMN lsif_data_docs_search_public.search_key_tsv IS 'Indexed tsvector for the search_key field. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_public.search_key_reverse_tsv IS 'Indexed tsvector for the reverse of the search_key field, for suffix lexeme/word matching. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_public.label IS 'The label string of the result, e.g. a one-line function signature. See protocol/documentation.go:Documentation';\n\nCOMMENT ON COLUMN lsif_data_docs_search_public.label_tsv IS 'Indexed tsvector for the label field. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_public.label_reverse_tsv IS 'Indexed tsvector for the reverse of the label field, for suffix lexeme/word matching. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\n\nCREATE SEQUENCE lsif_data_docs_search_public_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE lsif_data_docs_search_public_id_seq OWNED BY lsif_data_docs_search_public.id;\n\nCREATE TABLE lsif_data_docs_search_repo_names_private (\n id bigint NOT NULL,\n repo_name text NOT NULL,\n tsv tsvector NOT NULL,\n reverse_tsv tsvector NOT NULL\n);\n\nCOMMENT ON TABLE lsif_data_docs_search_repo_names_private IS 'Each unique repository name being stored in the API docs search index.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_repo_names_private.id IS 'The ID of the repository name.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_repo_names_private.repo_name IS 'The fully qualified name of the repository.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_repo_names_private.tsv IS 'Indexed tsvector for the lang_name field. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_repo_names_private.reverse_tsv IS 'Indexed tsvector for the reverse of the lang_name field, for suffix lexeme/word matching. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\n\nCREATE SEQUENCE lsif_data_docs_search_repo_names_private_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE lsif_data_docs_search_repo_names_private_id_seq OWNED BY lsif_data_docs_search_repo_names_private.id;\n\nCREATE TABLE lsif_data_docs_search_repo_names_public (\n id bigint NOT NULL,\n repo_name text NOT NULL,\n tsv tsvector NOT NULL,\n reverse_tsv tsvector NOT NULL\n);\n\nCOMMENT ON TABLE lsif_data_docs_search_repo_names_public IS 'Each unique repository name being stored in the API docs search index.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_repo_names_public.id IS 'The ID of the repository name.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_repo_names_public.repo_name IS 'The fully qualified name of the repository.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_repo_names_public.tsv IS 'Indexed tsvector for the lang_name field. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_repo_names_public.reverse_tsv IS 'Indexed tsvector for the reverse of the lang_name field, for suffix lexeme/word matching. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\n\nCREATE SEQUENCE lsif_data_docs_search_repo_names_public_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE lsif_data_docs_search_repo_names_public_id_seq OWNED BY lsif_data_docs_search_repo_names_public.id;\n\nCREATE TABLE lsif_data_docs_search_tags_private (\n id bigint NOT NULL,\n tags text NOT NULL,\n tsv tsvector NOT NULL\n);\n\nCOMMENT ON TABLE lsif_data_docs_search_tags_private IS 'Each uniques sequence of space-separated tags being stored in the API docs search index.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_tags_private.id IS 'The ID of the tags.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_tags_private.tags IS 'The full sequence of space-separated tags. See protocol/documentation.go:Documentation';\n\nCOMMENT ON COLUMN lsif_data_docs_search_tags_private.tsv IS 'Indexed tsvector for the tags field. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\n\nCREATE SEQUENCE lsif_data_docs_search_tags_private_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE lsif_data_docs_search_tags_private_id_seq OWNED BY lsif_data_docs_search_tags_private.id;\n\nCREATE TABLE lsif_data_docs_search_tags_public (\n id bigint NOT NULL,\n tags text NOT NULL,\n tsv tsvector NOT NULL\n);\n\nCOMMENT ON TABLE lsif_data_docs_search_tags_public IS 'Each uniques sequence of space-separated tags being stored in the API docs search index.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_tags_public.id IS 'The ID of the tags.';\n\nCOMMENT ON COLUMN lsif_data_docs_search_tags_public.tags IS 'The full sequence of space-separated tags. See protocol/documentation.go:Documentation';\n\nCOMMENT ON COLUMN lsif_data_docs_search_tags_public.tsv IS 'Indexed tsvector for the tags field. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\n\nCREATE SEQUENCE lsif_data_docs_search_tags_public_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE lsif_data_docs_search_tags_public_id_seq OWNED BY lsif_data_docs_search_tags_public.id;\n\nCREATE TABLE lsif_data_documentation_mappings (\n dump_id integer NOT NULL,\n path_id text NOT NULL,\n result_id integer NOT NULL,\n file_path text\n);\n\nCOMMENT ON TABLE lsif_data_documentation_mappings IS 'Maps documentation path IDs to their corresponding integral documentationResult vertex IDs, which are unique within a dump.';\n\nCOMMENT ON COLUMN lsif_data_documentation_mappings.dump_id IS 'The identifier of the associated dump in the lsif_uploads table (state=completed).';\n\nCOMMENT ON COLUMN lsif_data_documentation_mappings.path_id IS 'The documentation page path ID, see see GraphQL codeintel.schema:documentationPage for what this is.';\n\nCOMMENT ON COLUMN lsif_data_documentation_mappings.result_id IS 'The documentationResult vertex ID.';\n\nCOMMENT ON COLUMN lsif_data_documentation_mappings.file_path IS 'The document file path for the documentationResult, if any. e.g. the path to the file where the symbol described by this documentationResult is located, if it is a symbol.';\n\nCREATE TABLE lsif_data_documentation_pages (\n dump_id integer NOT NULL,\n path_id text NOT NULL,\n data bytea,\n search_indexed boolean DEFAULT false\n);\n\nCOMMENT ON TABLE lsif_data_documentation_pages IS 'Associates documentation pathIDs to their documentation page hierarchy chunk.';\n\nCOMMENT ON COLUMN lsif_data_documentation_pages.dump_id IS 'The identifier of the associated dump in the lsif_uploads table (state=completed).';\n\nCOMMENT ON COLUMN lsif_data_documentation_pages.path_id IS 'The documentation page path ID, see see GraphQL codeintel.schema:documentationPage for what this is.';\n\nCOMMENT ON COLUMN lsif_data_documentation_pages.data IS 'A gob-encoded payload conforming to a `type DocumentationPageData struct` pointer (lib/codeintel/semantic/types.go)';\n\nCREATE TABLE lsif_data_documentation_path_info (\n dump_id integer NOT NULL,\n path_id text NOT NULL,\n data bytea\n);\n\nCOMMENT ON TABLE lsif_data_documentation_path_info IS 'Associates documentation page pathIDs to information about what is at that pathID, its immediate children, etc.';\n\nCOMMENT ON COLUMN lsif_data_documentation_path_info.dump_id IS 'The identifier of the associated dump in the lsif_uploads table (state=completed).';\n\nCOMMENT ON COLUMN lsif_data_documentation_path_info.path_id IS 'The documentation page path ID, see see GraphQL codeintel.schema:documentationPage for what this is.';\n\nCOMMENT ON COLUMN lsif_data_documentation_path_info.data IS 'A gob-encoded payload conforming to a `type DocumentationPathInoData struct` pointer (lib/codeintel/semantic/types.go)';\n\nCREATE TABLE lsif_data_documents (\n dump_id integer NOT NULL,\n path text NOT NULL,\n data bytea,\n schema_version integer NOT NULL,\n num_diagnostics integer NOT NULL,\n ranges bytea,\n hovers bytea,\n monikers bytea,\n packages bytea,\n diagnostics bytea\n);\n\nCOMMENT ON TABLE lsif_data_documents IS 'Stores reference, hover text, moniker, and diagnostic data about a particular text document witin a dump.';\n\nCOMMENT ON COLUMN lsif_data_documents.dump_id IS 'The identifier of the associated dump in the lsif_uploads table (state=completed).';\n\nCOMMENT ON COLUMN lsif_data_documents.path IS 'The path of the text document relative to the associated dump root.';\n\nCOMMENT ON COLUMN lsif_data_documents.data IS 'A gob-encoded payload conforming to the [DocumentData](https://sourcegraph.com/github.com/sourcegraph/sourcegraph@3.26/-/blob/enterprise/lib/codeintel/semantic/types.go#L13:6) type. This field is being migrated across ranges, hovers, monikers, packages, and diagnostics columns and will be removed in a future release of Sourcegraph.';\n\nCOMMENT ON COLUMN lsif_data_documents.schema_version IS 'The schema version of this row - used to determine presence and encoding of data.';\n\nCOMMENT ON COLUMN lsif_data_documents.num_diagnostics IS 'The number of diagnostics stored in the data field.';\n\nCOMMENT ON COLUMN lsif_data_documents.ranges IS 'A gob-encoded payload conforming to the [Ranges](https://sourcegraph.com/github.com/sourcegraph/sourcegraph@3.26/-/blob/enterprise/lib/codeintel/semantic/types.go#L14:2) field of the DocumentDatatype.';\n\nCOMMENT ON COLUMN lsif_data_documents.hovers IS 'A gob-encoded payload conforming to the [HoversResults](https://sourcegraph.com/github.com/sourcegraph/sourcegraph@3.26/-/blob/enterprise/lib/codeintel/semantic/types.go#L15:2) field of the DocumentDatatype.';\n\nCOMMENT ON COLUMN lsif_data_documents.monikers IS 'A gob-encoded payload conforming to the [Monikers](https://sourcegraph.com/github.com/sourcegraph/sourcegraph@3.26/-/blob/enterprise/lib/codeintel/semantic/types.go#L16:2) field of the DocumentDatatype.';\n\nCOMMENT ON COLUMN lsif_data_documents.packages IS 'A gob-encoded payload conforming to the [PackageInformation](https://sourcegraph.com/github.com/sourcegraph/sourcegraph@3.26/-/blob/enterprise/lib/codeintel/semantic/types.go#L17:2) field of the DocumentDatatype.';\n\nCOMMENT ON COLUMN lsif_data_documents.diagnostics IS 'A gob-encoded payload conforming to the [Diagnostics](https://sourcegraph.com/github.com/sourcegraph/sourcegraph@3.26/-/blob/enterprise/lib/codeintel/semantic/types.go#L18:2) field of the DocumentDatatype.';\n\nCREATE TABLE lsif_data_documents_schema_versions (\n dump_id integer NOT NULL,\n min_schema_version integer,\n max_schema_version integer\n);\n\nCOMMENT ON TABLE lsif_data_documents_schema_versions IS 'Tracks the range of schema_versions for each upload in the lsif_data_documents table.';\n\nCOMMENT ON COLUMN lsif_data_documents_schema_versions.dump_id IS 'The identifier of the associated dump in the lsif_uploads table.';\n\nCOMMENT ON COLUMN lsif_data_documents_schema_versions.min_schema_version IS 'A lower-bound on the `lsif_data_documents.schema_version` where `lsif_data_documents.dump_id = dump_id`.';\n\nCOMMENT ON COLUMN lsif_data_documents_schema_versions.max_schema_version IS 'An upper-bound on the `lsif_data_documents.schema_version` where `lsif_data_documents.dump_id = dump_id`.';\n\nCREATE TABLE lsif_data_implementations (\n dump_id integer NOT NULL,\n scheme text NOT NULL,\n identifier text NOT NULL,\n data bytea,\n schema_version integer NOT NULL,\n num_locations integer NOT NULL\n);\n\nCOMMENT ON TABLE lsif_data_implementations IS 'Associates (document, range) pairs with the implementation monikers attached to the range.';\n\nCOMMENT ON COLUMN lsif_data_implementations.dump_id IS 'The identifier of the associated dump in the lsif_uploads table (state=completed).';\n\nCOMMENT ON COLUMN lsif_data_implementations.scheme IS 'The moniker scheme.';\n\nCOMMENT ON COLUMN lsif_data_implementations.identifier IS 'The moniker identifier.';\n\nCOMMENT ON COLUMN lsif_data_implementations.data IS 'A gob-encoded payload conforming to an array of [LocationData](https://sourcegraph.com/github.com/sourcegraph/sourcegraph@3.26/-/blob/enterprise/lib/codeintel/semantic/types.go#L106:6) types.';\n\nCOMMENT ON COLUMN lsif_data_implementations.schema_version IS 'The schema version of this row - used to determine presence and encoding of data.';\n\nCOMMENT ON COLUMN lsif_data_implementations.num_locations IS 'The number of locations stored in the data field.';\n\nCREATE TABLE lsif_data_implementations_schema_versions (\n dump_id integer NOT NULL,\n min_schema_version integer,\n max_schema_version integer\n);\n\nCOMMENT ON TABLE lsif_data_implementations_schema_versions IS 'Tracks the range of schema_versions for each upload in the lsif_data_implementations table.';\n\nCOMMENT ON COLUMN lsif_data_implementations_schema_versions.dump_id IS 'The identifier of the associated dump in the lsif_uploads table.';\n\nCOMMENT ON COLUMN lsif_data_implementations_schema_versions.min_schema_version IS 'A lower-bound on the `lsif_data_implementations.schema_version` where `lsif_data_implementations.dump_id = dump_id`.';\n\nCOMMENT ON COLUMN lsif_data_implementations_schema_versions.max_schema_version IS 'An upper-bound on the `lsif_data_implementations.schema_version` where `lsif_data_implementations.dump_id = dump_id`.';\n\nCREATE TABLE lsif_data_metadata (\n dump_id integer NOT NULL,\n num_result_chunks integer\n);\n\nCOMMENT ON TABLE lsif_data_metadata IS 'Stores the number of result chunks associated with a dump.';\n\nCOMMENT ON COLUMN lsif_data_metadata.dump_id IS 'The identifier of the associated dump in the lsif_uploads table (state=completed).';\n\nCOMMENT ON COLUMN lsif_data_metadata.num_result_chunks IS 'A bound of populated indexes in the lsif_data_result_chunks table for the associated dump. This value is used to hash identifiers into the result chunk index to which they belong.';\n\nCREATE TABLE lsif_data_references (\n dump_id integer NOT NULL,\n scheme text NOT NULL,\n identifier text NOT NULL,\n data bytea,\n schema_version integer NOT NULL,\n num_locations integer NOT NULL\n);\n\nCOMMENT ON TABLE lsif_data_references IS 'Associates (document, range) pairs with the export monikers attached to the range.';\n\nCOMMENT ON COLUMN lsif_data_references.dump_id IS 'The identifier of the associated dump in the lsif_uploads table (state=completed).';\n\nCOMMENT ON COLUMN lsif_data_references.scheme IS 'The moniker scheme.';\n\nCOMMENT ON COLUMN lsif_data_references.identifier IS 'The moniker identifier.';\n\nCOMMENT ON COLUMN lsif_data_references.data IS 'A gob-encoded payload conforming to an array of [LocationData](https://sourcegraph.com/github.com/sourcegraph/sourcegraph@3.26/-/blob/enterprise/lib/codeintel/semantic/types.go#L106:6) types.';\n\nCOMMENT ON COLUMN lsif_data_references.schema_version IS 'The schema version of this row - used to determine presence and encoding of data.';\n\nCOMMENT ON COLUMN lsif_data_references.num_locations IS 'The number of locations stored in the data field.';\n\nCREATE TABLE lsif_data_references_schema_versions (\n dump_id integer NOT NULL,\n min_schema_version integer,\n max_schema_version integer\n);\n\nCOMMENT ON TABLE lsif_data_references_schema_versions IS 'Tracks the range of schema_versions for each upload in the lsif_data_references table.';\n\nCOMMENT ON COLUMN lsif_data_references_schema_versions.dump_id IS 'The identifier of the associated dump in the lsif_uploads table.';\n\nCOMMENT ON COLUMN lsif_data_references_schema_versions.min_schema_version IS 'A lower-bound on the `lsif_data_references.schema_version` where `lsif_data_references.dump_id = dump_id`.';\n\nCOMMENT ON COLUMN lsif_data_references_schema_versions.max_schema_version IS 'An upper-bound on the `lsif_data_references.schema_version` where `lsif_data_references.dump_id = dump_id`.';\n\nCREATE TABLE lsif_data_result_chunks (\n dump_id integer NOT NULL,\n idx integer NOT NULL,\n data bytea\n);\n\nCOMMENT ON TABLE lsif_data_result_chunks IS 'Associates result set identifiers with the (document path, range identifier) pairs that compose the set.';\n\nCOMMENT ON COLUMN lsif_data_result_chunks.dump_id IS 'The identifier of the associated dump in the lsif_uploads table (state=completed).';\n\nCOMMENT ON COLUMN lsif_data_result_chunks.idx IS 'The unique result chunk index within the associated dump. Every result set identifier present should hash to this index (modulo lsif_data_metadata.num_result_chunks).';\n\nCOMMENT ON COLUMN lsif_data_result_chunks.data IS 'A gob-encoded payload conforming to the [ResultChunkData](https://sourcegraph.com/github.com/sourcegraph/sourcegraph@3.26/-/blob/enterprise/lib/codeintel/semantic/types.go#L76:6) type.';\n\nCREATE TABLE rockskip_ancestry (\n id integer NOT NULL,\n repo_id integer NOT NULL,\n commit_id character varying(40) NOT NULL,\n height integer NOT NULL,\n ancestor integer NOT NULL\n);\n\nCREATE SEQUENCE rockskip_ancestry_id_seq\n AS integer\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE rockskip_ancestry_id_seq OWNED BY rockskip_ancestry.id;\n\nCREATE TABLE rockskip_repos (\n id integer NOT NULL,\n repo text NOT NULL,\n last_accessed_at timestamp with time zone NOT NULL\n);\n\nCREATE SEQUENCE rockskip_repos_id_seq\n AS integer\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE rockskip_repos_id_seq OWNED BY rockskip_repos.id;\n\nCREATE TABLE rockskip_symbols (\n id integer NOT NULL,\n added integer[] NOT NULL,\n deleted integer[] NOT NULL,\n repo_id integer NOT NULL,\n path text NOT NULL,\n name text NOT NULL\n);\n\nCREATE SEQUENCE rockskip_symbols_id_seq\n AS integer\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE rockskip_symbols_id_seq OWNED BY rockskip_symbols.id;\n\nALTER TABLE ONLY lsif_data_docs_search_current_private ALTER COLUMN id SET DEFAULT nextval('lsif_data_docs_search_current_private_id_seq'::regclass);\n\nALTER TABLE ONLY lsif_data_docs_search_current_public ALTER COLUMN id SET DEFAULT nextval('lsif_data_docs_search_current_public_id_seq'::regclass);\n\nALTER TABLE ONLY lsif_data_docs_search_lang_names_private ALTER COLUMN id SET DEFAULT nextval('lsif_data_docs_search_lang_names_private_id_seq'::regclass);\n\nALTER TABLE ONLY lsif_data_docs_search_lang_names_public ALTER COLUMN id SET DEFAULT nextval('lsif_data_docs_search_lang_names_public_id_seq'::regclass);\n\nALTER TABLE ONLY lsif_data_docs_search_private ALTER COLUMN id SET DEFAULT nextval('lsif_data_docs_search_private_id_seq'::regclass);\n\nALTER TABLE ONLY lsif_data_docs_search_public ALTER COLUMN id SET DEFAULT nextval('lsif_data_docs_search_public_id_seq'::regclass);\n\nALTER TABLE ONLY lsif_data_docs_search_repo_names_private ALTER COLUMN id SET DEFAULT nextval('lsif_data_docs_search_repo_names_private_id_seq'::regclass);\n\nALTER TABLE ONLY lsif_data_docs_search_repo_names_public ALTER COLUMN id SET DEFAULT nextval('lsif_data_docs_search_repo_names_public_id_seq'::regclass);\n\nALTER TABLE ONLY lsif_data_docs_search_tags_private ALTER COLUMN id SET DEFAULT nextval('lsif_data_docs_search_tags_private_id_seq'::regclass);\n\nALTER TABLE ONLY lsif_data_docs_search_tags_public ALTER COLUMN id SET DEFAULT nextval('lsif_data_docs_search_tags_public_id_seq'::regclass);\n\nALTER TABLE ONLY rockskip_ancestry ALTER COLUMN id SET DEFAULT nextval('rockskip_ancestry_id_seq'::regclass);\n\nALTER TABLE ONLY rockskip_repos ALTER COLUMN id SET DEFAULT nextval('rockskip_repos_id_seq'::regclass);\n\nALTER TABLE ONLY rockskip_symbols ALTER COLUMN id SET DEFAULT nextval('rockskip_symbols_id_seq'::regclass);\n\nALTER TABLE ONLY lsif_data_definitions\n ADD CONSTRAINT lsif_data_definitions_pkey PRIMARY KEY (dump_id, scheme, identifier);\n\nALTER TABLE ONLY lsif_data_definitions_schema_versions\n ADD CONSTRAINT lsif_data_definitions_schema_versions_pkey PRIMARY KEY (dump_id);\n\nALTER TABLE ONLY lsif_data_docs_search_current_private\n ADD CONSTRAINT lsif_data_docs_search_current_private_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY lsif_data_docs_search_current_public\n ADD CONSTRAINT lsif_data_docs_search_current_public_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY lsif_data_docs_search_lang_names_private\n ADD CONSTRAINT lsif_data_docs_search_lang_names_private_lang_name_key UNIQUE (lang_name);\n\nALTER TABLE ONLY lsif_data_docs_search_lang_names_private\n ADD CONSTRAINT lsif_data_docs_search_lang_names_private_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY lsif_data_docs_search_lang_names_public\n ADD CONSTRAINT lsif_data_docs_search_lang_names_public_lang_name_key UNIQUE (lang_name);\n\nALTER TABLE ONLY lsif_data_docs_search_lang_names_public\n ADD CONSTRAINT lsif_data_docs_search_lang_names_public_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY lsif_data_docs_search_private\n ADD CONSTRAINT lsif_data_docs_search_private_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY lsif_data_docs_search_public\n ADD CONSTRAINT lsif_data_docs_search_public_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY lsif_data_docs_search_repo_names_private\n ADD CONSTRAINT lsif_data_docs_search_repo_names_private_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY lsif_data_docs_search_repo_names_private\n ADD CONSTRAINT lsif_data_docs_search_repo_names_private_repo_name_key UNIQUE (repo_name);\n\nALTER TABLE ONLY lsif_data_docs_search_repo_names_public\n ADD CONSTRAINT lsif_data_docs_search_repo_names_public_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY lsif_data_docs_search_repo_names_public\n ADD CONSTRAINT lsif_data_docs_search_repo_names_public_repo_name_key UNIQUE (repo_name);\n\nALTER TABLE ONLY lsif_data_docs_search_tags_private\n ADD CONSTRAINT lsif_data_docs_search_tags_private_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY lsif_data_docs_search_tags_private\n ADD CONSTRAINT lsif_data_docs_search_tags_private_tags_key UNIQUE (tags);\n\nALTER TABLE ONLY lsif_data_docs_search_tags_public\n ADD CONSTRAINT lsif_data_docs_search_tags_public_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY lsif_data_docs_search_tags_public\n ADD CONSTRAINT lsif_data_docs_search_tags_public_tags_key UNIQUE (tags);\n\nALTER TABLE ONLY lsif_data_documentation_mappings\n ADD CONSTRAINT lsif_data_documentation_mappings_pkey PRIMARY KEY (dump_id, path_id);\n\nALTER TABLE ONLY lsif_data_documentation_pages\n ADD CONSTRAINT lsif_data_documentation_pages_pkey PRIMARY KEY (dump_id, path_id);\n\nALTER TABLE ONLY lsif_data_documentation_path_info\n ADD CONSTRAINT lsif_data_documentation_path_info_pkey PRIMARY KEY (dump_id, path_id);\n\nALTER TABLE ONLY lsif_data_documents\n ADD CONSTRAINT lsif_data_documents_pkey PRIMARY KEY (dump_id, path);\n\nALTER TABLE ONLY lsif_data_documents_schema_versions\n ADD CONSTRAINT lsif_data_documents_schema_versions_pkey PRIMARY KEY (dump_id);\n\nALTER TABLE ONLY lsif_data_implementations\n ADD CONSTRAINT lsif_data_implementations_pkey PRIMARY KEY (dump_id, scheme, identifier);\n\nALTER TABLE ONLY lsif_data_implementations_schema_versions\n ADD CONSTRAINT lsif_data_implementations_schema_versions_pkey PRIMARY KEY (dump_id);\n\nALTER TABLE ONLY lsif_data_metadata\n ADD CONSTRAINT lsif_data_metadata_pkey PRIMARY KEY (dump_id);\n\nALTER TABLE ONLY lsif_data_references\n ADD CONSTRAINT lsif_data_references_pkey PRIMARY KEY (dump_id, scheme, identifier);\n\nALTER TABLE ONLY lsif_data_references_schema_versions\n ADD CONSTRAINT lsif_data_references_schema_versions_pkey PRIMARY KEY (dump_id);\n\nALTER TABLE ONLY lsif_data_result_chunks\n ADD CONSTRAINT lsif_data_result_chunks_pkey PRIMARY KEY (dump_id, idx);\n\nALTER TABLE ONLY rockskip_ancestry\n ADD CONSTRAINT rockskip_ancestry_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY rockskip_ancestry\n ADD CONSTRAINT rockskip_ancestry_repo_id_commit_id_key UNIQUE (repo_id, commit_id);\n\nALTER TABLE ONLY rockskip_repos\n ADD CONSTRAINT rockskip_repos_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY rockskip_repos\n ADD CONSTRAINT rockskip_repos_repo_key UNIQUE (repo);\n\nALTER TABLE ONLY rockskip_symbols\n ADD CONSTRAINT rockskip_symbols_pkey PRIMARY KEY (id);\n\nCREATE INDEX lsif_data_definitions_dump_id_schema_version ON lsif_data_definitions USING btree (dump_id, schema_version);\n\nCREATE INDEX lsif_data_definitions_schema_versions_dump_id_schema_version_bo ON lsif_data_definitions_schema_versions USING btree (dump_id, min_schema_version, max_schema_version);\n\nCREATE INDEX lsif_data_docs_search_current_private_last_cleanup_scan_at ON lsif_data_docs_search_current_private USING btree (last_cleanup_scan_at);\n\nCREATE INDEX lsif_data_docs_search_current_private_lookup ON lsif_data_docs_search_current_private USING btree (repo_id, dump_root, lang_name_id, created_at) INCLUDE (dump_id);\n\nCREATE INDEX lsif_data_docs_search_current_public_last_cleanup_scan_at ON lsif_data_docs_search_current_public USING btree (last_cleanup_scan_at);\n\nCREATE INDEX lsif_data_docs_search_current_public_lookup ON lsif_data_docs_search_current_public USING btree (repo_id, dump_root, lang_name_id, created_at) INCLUDE (dump_id);\n\nCREATE INDEX lsif_data_docs_search_lang_names_private_tsv_idx ON lsif_data_docs_search_lang_names_private USING gin (tsv);\n\nCREATE INDEX lsif_data_docs_search_lang_names_public_tsv_idx ON lsif_data_docs_search_lang_names_public USING gin (tsv);\n\nCREATE INDEX lsif_data_docs_search_private_dump_id_idx ON lsif_data_docs_search_private USING btree (dump_id);\n\nCREATE INDEX lsif_data_docs_search_private_dump_root_idx ON lsif_data_docs_search_private USING btree (dump_root);\n\nCREATE INDEX lsif_data_docs_search_private_label_reverse_tsv_idx ON lsif_data_docs_search_private USING gin (label_reverse_tsv);\n\nCREATE INDEX lsif_data_docs_search_private_label_tsv_idx ON lsif_data_docs_search_private USING gin (label_tsv);\n\nCREATE INDEX lsif_data_docs_search_private_repo_id_idx ON lsif_data_docs_search_private USING btree (repo_id);\n\nCREATE INDEX lsif_data_docs_search_private_search_key_reverse_tsv_idx ON lsif_data_docs_search_private USING gin (search_key_reverse_tsv);\n\nCREATE INDEX lsif_data_docs_search_private_search_key_tsv_idx ON lsif_data_docs_search_private USING gin (search_key_tsv);\n\nCREATE INDEX lsif_data_docs_search_public_dump_id_idx ON lsif_data_docs_search_public USING btree (dump_id);\n\nCREATE INDEX lsif_data_docs_search_public_dump_root_idx ON lsif_data_docs_search_public USING btree (dump_root);\n\nCREATE INDEX lsif_data_docs_search_public_label_reverse_tsv_idx ON lsif_data_docs_search_public USING gin (label_reverse_tsv);\n\nCREATE INDEX lsif_data_docs_search_public_label_tsv_idx ON lsif_data_docs_search_public USING gin (label_tsv);\n\nCREATE INDEX lsif_data_docs_search_public_repo_id_idx ON lsif_data_docs_search_public USING btree (repo_id);\n\nCREATE INDEX lsif_data_docs_search_public_search_key_reverse_tsv_idx ON lsif_data_docs_search_public USING gin (search_key_reverse_tsv);\n\nCREATE INDEX lsif_data_docs_search_public_search_key_tsv_idx ON lsif_data_docs_search_public USING gin (search_key_tsv);\n\nCREATE INDEX lsif_data_docs_search_repo_names_private_reverse_tsv_idx ON lsif_data_docs_search_repo_names_private USING gin (reverse_tsv);\n\nCREATE INDEX lsif_data_docs_search_repo_names_private_tsv_idx ON lsif_data_docs_search_repo_names_private USING gin (tsv);\n\nCREATE INDEX lsif_data_docs_search_repo_names_public_reverse_tsv_idx ON lsif_data_docs_search_repo_names_public USING gin (reverse_tsv);\n\nCREATE INDEX lsif_data_docs_search_repo_names_public_tsv_idx ON lsif_data_docs_search_repo_names_public USING gin (tsv);\n\nCREATE INDEX lsif_data_docs_search_tags_private_tsv_idx ON lsif_data_docs_search_tags_private USING gin (tsv);\n\nCREATE INDEX lsif_data_docs_search_tags_public_tsv_idx ON lsif_data_docs_search_tags_public USING gin (tsv);\n\nCREATE UNIQUE INDEX lsif_data_documentation_mappings_inverse_unique_idx ON lsif_data_documentation_mappings USING btree (dump_id, result_id);\n\nCREATE INDEX lsif_data_documentation_pages_dump_id_unindexed ON lsif_data_documentation_pages USING btree (dump_id) WHERE (NOT search_indexed);\n\nCREATE INDEX lsif_data_documents_dump_id_schema_version ON lsif_data_documents USING btree (dump_id, schema_version);\n\nCREATE INDEX lsif_data_documents_schema_versions_dump_id_schema_version_boun ON lsif_data_documents_schema_versions USING btree (dump_id, min_schema_version, max_schema_version);\n\nCREATE INDEX lsif_data_implementations_dump_id_schema_version ON lsif_data_implementations USING btree (dump_id, schema_version);\n\nCREATE INDEX lsif_data_implementations_schema_versions_dump_id_schema_versio ON lsif_data_implementations_schema_versions USING btree (dump_id, min_schema_version, max_schema_version);\n\nCREATE INDEX lsif_data_references_dump_id_schema_version ON lsif_data_references USING btree (dump_id, schema_version);\n\nCREATE INDEX lsif_data_references_schema_versions_dump_id_schema_version_bou ON lsif_data_references_schema_versions USING btree (dump_id, min_schema_version, max_schema_version);\n\nCREATE INDEX rockskip_ancestry_repo_commit_id ON rockskip_ancestry USING btree (repo_id, commit_id);\n\nCREATE INDEX rockskip_repos_last_accessed_at ON rockskip_repos USING btree (last_accessed_at);\n\nCREATE INDEX rockskip_repos_repo ON rockskip_repos USING btree (repo);\n\nCREATE INDEX rockskip_symbols_gin ON rockskip_symbols USING gin (singleton_integer(repo_id) gin__int_ops, added gin__int_ops, deleted gin__int_ops, name gin_trgm_ops, singleton(name), singleton(lower(name)), path gin_trgm_ops, singleton(path), path_prefixes(path), singleton(lower(path)), path_prefixes(lower(path)), singleton(get_file_extension(path)), singleton(get_file_extension(lower(path))));\n\nCREATE INDEX rockskip_symbols_repo_id_path_name ON rockskip_symbols USING btree (repo_id, path, name);\n\nCREATE TRIGGER lsif_data_definitions_schema_versions_insert AFTER INSERT ON lsif_data_definitions REFERENCING NEW TABLE AS newtab FOR EACH STATEMENT EXECUTE FUNCTION update_lsif_data_definitions_schema_versions_insert();\n\nCREATE TRIGGER lsif_data_docs_search_private_delete AFTER DELETE ON lsif_data_docs_search_private REFERENCING OLD TABLE AS oldtbl FOR EACH STATEMENT EXECUTE FUNCTION lsif_data_docs_search_private_delete();\n\nCREATE TRIGGER lsif_data_docs_search_private_insert AFTER INSERT ON lsif_data_docs_search_private REFERENCING NEW TABLE AS newtbl FOR EACH STATEMENT EXECUTE FUNCTION lsif_data_docs_search_private_insert();\n\nCREATE TRIGGER lsif_data_docs_search_public_delete AFTER DELETE ON lsif_data_docs_search_public REFERENCING OLD TABLE AS oldtbl FOR EACH STATEMENT EXECUTE FUNCTION lsif_data_docs_search_public_delete();\n\nCREATE TRIGGER lsif_data_docs_search_public_insert AFTER INSERT ON lsif_data_docs_search_public REFERENCING NEW TABLE AS newtbl FOR EACH STATEMENT EXECUTE FUNCTION lsif_data_docs_search_public_insert();\n\nCREATE TRIGGER lsif_data_documentation_pages_delete AFTER DELETE ON lsif_data_documentation_pages REFERENCING OLD TABLE AS oldtbl FOR EACH STATEMENT EXECUTE FUNCTION lsif_data_documentation_pages_delete();\n\nCREATE TRIGGER lsif_data_documentation_pages_insert AFTER INSERT ON lsif_data_documentation_pages REFERENCING NEW TABLE AS newtbl FOR EACH STATEMENT EXECUTE FUNCTION lsif_data_documentation_pages_insert();\n\nCREATE TRIGGER lsif_data_documentation_pages_update AFTER UPDATE ON lsif_data_documentation_pages REFERENCING OLD TABLE AS oldtbl NEW TABLE AS newtbl FOR EACH STATEMENT EXECUTE FUNCTION lsif_data_documentation_pages_update();\n\nCREATE TRIGGER lsif_data_documents_schema_versions_insert AFTER INSERT ON lsif_data_documents REFERENCING NEW TABLE AS newtab FOR EACH STATEMENT EXECUTE FUNCTION update_lsif_data_documents_schema_versions_insert();\n\nCREATE TRIGGER lsif_data_implementations_schema_versions_insert AFTER INSERT ON lsif_data_implementations REFERENCING NEW TABLE AS newtab FOR EACH STATEMENT EXECUTE FUNCTION update_lsif_data_implementations_schema_versions_insert();\n\nCREATE TRIGGER lsif_data_references_schema_versions_insert AFTER INSERT ON lsif_data_references REFERENCING NEW TABLE AS newtab FOR EACH STATEMENT EXECUTE FUNCTION update_lsif_data_references_schema_versions_insert();\n\nALTER TABLE ONLY lsif_data_docs_search_private\n ADD CONSTRAINT lsif_data_docs_search_private_lang_name_id_fk FOREIGN KEY (lang_name_id) REFERENCES lsif_data_docs_search_lang_names_private(id);\n\nALTER TABLE ONLY lsif_data_docs_search_private\n ADD CONSTRAINT lsif_data_docs_search_private_repo_name_id_fk FOREIGN KEY (repo_name_id) REFERENCES lsif_data_docs_search_repo_names_private(id);\n\nALTER TABLE ONLY lsif_data_docs_search_private\n ADD CONSTRAINT lsif_data_docs_search_private_tags_id_fk FOREIGN KEY (tags_id) REFERENCES lsif_data_docs_search_tags_private(id);\n\nALTER TABLE ONLY lsif_data_docs_search_public\n ADD CONSTRAINT lsif_data_docs_search_public_lang_name_id_fk FOREIGN KEY (lang_name_id) REFERENCES lsif_data_docs_search_lang_names_public(id);\n\nALTER TABLE ONLY lsif_data_docs_search_public\n ADD CONSTRAINT lsif_data_docs_search_public_repo_name_id_fk FOREIGN KEY (repo_name_id) REFERENCES lsif_data_docs_search_repo_names_public(id);\n\nALTER TABLE ONLY lsif_data_docs_search_public\n ADD CONSTRAINT lsif_data_docs_search_public_tags_id_fk FOREIGN KEY (tags_id) REFERENCES lsif_data_docs_search_tags_public(id);\n\nINSERT INTO lsif_data_apidocs_num_dumps VALUES (0);\nINSERT INTO lsif_data_apidocs_num_dumps_indexed VALUES (0);\nINSERT INTO lsif_data_apidocs_num_pages VALUES (0);\nINSERT INTO lsif_data_apidocs_num_search_results_private VALUES (0);\nINSERT INTO lsif_data_apidocs_num_search_results_public VALUES (0);", + "DownQuery": "-- Nothing", + "Privileged": false, + "NonIdempotent": true, + "Parents": [ + 1000000033 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1665531314, + "Name": "Remove API docs tables", + "UpQuery": "DROP TRIGGER IF EXISTS lsif_data_docs_search_private_delete ON lsif_data_docs_search_private;\n\nDROP TRIGGER IF EXISTS lsif_data_docs_search_private_insert ON lsif_data_docs_search_private;\n\nDROP TRIGGER IF EXISTS lsif_data_docs_search_public_delete ON lsif_data_docs_search_public;\n\nDROP TRIGGER IF EXISTS lsif_data_docs_search_public_insert ON lsif_data_docs_search_public;\n\nDROP TRIGGER IF EXISTS lsif_data_documentation_pages_delete ON lsif_data_documentation_pages;\n\nDROP TRIGGER IF EXISTS lsif_data_documentation_pages_insert ON lsif_data_documentation_pages;\n\nDROP TRIGGER IF EXISTS lsif_data_documentation_pages_update ON lsif_data_documentation_pages;\n\nDROP FUNCTION IF EXISTS lsif_data_docs_search_private_delete();\n\nDROP FUNCTION IF EXISTS lsif_data_docs_search_private_insert();\n\nDROP FUNCTION IF EXISTS lsif_data_docs_search_public_delete();\n\nDROP FUNCTION IF EXISTS lsif_data_docs_search_public_insert();\n\nDROP FUNCTION IF EXISTS lsif_data_documentation_pages_delete();\n\nDROP FUNCTION IF EXISTS lsif_data_documentation_pages_insert();\n\nDROP FUNCTION IF EXISTS lsif_data_documentation_pages_update();\n\nDROP TABLE IF EXISTS lsif_data_apidocs_num_dumps CASCADE;\n\nDROP TABLE IF EXISTS lsif_data_apidocs_num_dumps_indexed CASCADE;\n\nDROP TABLE IF EXISTS lsif_data_apidocs_num_pages CASCADE;\n\nDROP TABLE IF EXISTS lsif_data_apidocs_num_search_results_private CASCADE;\n\nDROP TABLE IF EXISTS lsif_data_apidocs_num_search_results_public CASCADE;\n\nDROP TABLE IF EXISTS lsif_data_docs_search_current_private CASCADE;\n\nDROP TABLE IF EXISTS lsif_data_docs_search_current_public CASCADE;\n\nDROP TABLE IF EXISTS lsif_data_docs_search_lang_names_private CASCADE;\n\nDROP TABLE IF EXISTS lsif_data_docs_search_lang_names_public CASCADE;\n\nDROP TABLE IF EXISTS lsif_data_docs_search_private CASCADE;\n\nDROP TABLE IF EXISTS lsif_data_docs_search_public CASCADE;\n\nDROP TABLE IF EXISTS lsif_data_docs_search_repo_names_private CASCADE;\n\nDROP TABLE IF EXISTS lsif_data_docs_search_repo_names_public CASCADE;\n\nDROP TABLE IF EXISTS lsif_data_docs_search_tags_private CASCADE;\n\nDROP TABLE IF EXISTS lsif_data_docs_search_tags_public CASCADE;\n\nDROP TABLE IF EXISTS lsif_data_documentation_mappings CASCADE;\n\nDROP TABLE IF EXISTS lsif_data_documentation_pages CASCADE;\n\nDROP TABLE IF EXISTS lsif_data_documentation_path_info CASCADE;", + "DownQuery": "CREATE OR REPLACE FUNCTION lsif_data_docs_search_private_delete() RETURNS trigger\n LANGUAGE plpgsql\n AS $$\nBEGIN\nUPDATE lsif_data_apidocs_num_search_results_private SET count = count - (select count(*) from oldtbl);\nRETURN NULL;\nEND $$;\n\nCREATE OR REPLACE FUNCTION lsif_data_docs_search_private_insert() RETURNS trigger\n LANGUAGE plpgsql\n AS $$\nBEGIN\nUPDATE lsif_data_apidocs_num_search_results_private SET count = count + (select count(*) from newtbl);\nRETURN NULL;\nEND $$;\n\nCREATE OR REPLACE FUNCTION lsif_data_docs_search_public_delete() RETURNS trigger\n LANGUAGE plpgsql\n AS $$\nBEGIN\nUPDATE lsif_data_apidocs_num_search_results_public SET count = count - (select count(*) from oldtbl);\nRETURN NULL;\nEND $$;\n\nCREATE OR REPLACE FUNCTION lsif_data_docs_search_public_insert() RETURNS trigger\n LANGUAGE plpgsql\n AS $$\nBEGIN\nUPDATE lsif_data_apidocs_num_search_results_public SET count = count + (select count(*) from newtbl);\nRETURN NULL;\nEND $$;\n\nCREATE OR REPLACE FUNCTION lsif_data_documentation_pages_delete() RETURNS trigger\n LANGUAGE plpgsql\n AS $$\nBEGIN\nUPDATE lsif_data_apidocs_num_pages SET count = count - (select count(*) from oldtbl);\nUPDATE lsif_data_apidocs_num_dumps SET count = count - (select count(DISTINCT dump_id) from oldtbl);\nUPDATE lsif_data_apidocs_num_dumps_indexed SET count = count - (select count(DISTINCT dump_id) from oldtbl WHERE search_indexed='true');\nRETURN NULL;\nEND $$;\n\nCREATE OR REPLACE FUNCTION lsif_data_documentation_pages_insert() RETURNS trigger\n LANGUAGE plpgsql\n AS $$\nBEGIN\nUPDATE lsif_data_apidocs_num_pages SET count = count + (select count(*) from newtbl);\nUPDATE lsif_data_apidocs_num_dumps SET count = count + (select count(DISTINCT dump_id) from newtbl);\nUPDATE lsif_data_apidocs_num_dumps_indexed SET count = count + (select count(DISTINCT dump_id) from newtbl WHERE search_indexed='true');\nRETURN NULL;\nEND $$;\n\nCREATE OR REPLACE FUNCTION lsif_data_documentation_pages_update() RETURNS trigger\n LANGUAGE plpgsql\n AS $$\nBEGIN\nWITH\n beforeIndexed AS (SELECT count(DISTINCT dump_id) FROM oldtbl WHERE search_indexed='true'),\n afterIndexed AS (SELECT count(DISTINCT dump_id) FROM newtbl WHERE search_indexed='true')\nUPDATE lsif_data_apidocs_num_dumps_indexed SET count=count + ((select * from afterIndexed) - (select * from beforeIndexed));\nRETURN NULL;\nEND $$;\n\nCREATE TABLE IF NOT EXISTS lsif_data_apidocs_num_dumps (count bigint);\nCREATE TABLE IF NOT EXISTS lsif_data_apidocs_num_dumps_indexed (count bigint);\nCREATE TABLE IF NOT EXISTS lsif_data_apidocs_num_pages (count bigint);\nCREATE TABLE IF NOT EXISTS lsif_data_apidocs_num_search_results_private (count bigint);\nCREATE TABLE IF NOT EXISTS lsif_data_apidocs_num_search_results_public (count bigint);\n\nINSERT INTO lsif_data_apidocs_num_dumps VALUES (0);\nINSERT INTO lsif_data_apidocs_num_dumps_indexed VALUES (0);\nINSERT INTO lsif_data_apidocs_num_pages VALUES (0);\nINSERT INTO lsif_data_apidocs_num_search_results_private VALUES (0);\nINSERT INTO lsif_data_apidocs_num_search_results_public VALUES (0);\n\nCREATE TABLE IF NOT EXISTS lsif_data_docs_search_current_private (\n repo_id integer NOT NULL,\n dump_root text NOT NULL,\n lang_name_id integer NOT NULL,\n dump_id integer NOT NULL,\n last_cleanup_scan_at timestamp with time zone DEFAULT now() NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n id BIGSERIAL,\n PRIMARY KEY(id)\n);\n\nCREATE TABLE IF NOT EXISTS lsif_data_docs_search_current_public (\n repo_id integer NOT NULL,\n dump_root text NOT NULL,\n lang_name_id integer NOT NULL,\n dump_id integer NOT NULL,\n last_cleanup_scan_at timestamp with time zone DEFAULT now() NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n id BIGSERIAL,\n PRIMARY KEY(id)\n);\n\nCREATE TABLE IF NOT EXISTS lsif_data_docs_search_lang_names_private (\n id BIGSERIAL,\n lang_name text NOT NULL,\n tsv tsvector NOT NULL,\n PRIMARY KEY(id),\n UNIQUE(lang_name)\n);\n\nCREATE TABLE IF NOT EXISTS lsif_data_docs_search_lang_names_public (\n id BIGSERIAL,\n lang_name text NOT NULL,\n tsv tsvector NOT NULL,\n PRIMARY KEY(id),\n UNIQUE(lang_name)\n);\n\nCREATE TABLE IF NOT EXISTS lsif_data_docs_search_private (\n id BIGSERIAL,\n repo_id integer NOT NULL,\n dump_id integer NOT NULL,\n dump_root text NOT NULL,\n path_id text NOT NULL,\n detail text NOT NULL,\n lang_name_id integer NOT NULL,\n repo_name_id integer NOT NULL,\n tags_id integer NOT NULL,\n search_key text NOT NULL,\n search_key_tsv tsvector NOT NULL,\n search_key_reverse_tsv tsvector NOT NULL,\n label text NOT NULL,\n label_tsv tsvector NOT NULL,\n label_reverse_tsv tsvector NOT NULL,\n PRIMARY KEY(id)\n);\n\nCREATE TABLE IF NOT EXISTS lsif_data_docs_search_public (\n id BIGSERIAL,\n repo_id integer NOT NULL,\n dump_id integer NOT NULL,\n dump_root text NOT NULL,\n path_id text NOT NULL,\n detail text NOT NULL,\n lang_name_id integer NOT NULL,\n repo_name_id integer NOT NULL,\n tags_id integer NOT NULL,\n search_key text NOT NULL,\n search_key_tsv tsvector NOT NULL,\n search_key_reverse_tsv tsvector NOT NULL,\n label text NOT NULL,\n label_tsv tsvector NOT NULL,\n label_reverse_tsv tsvector NOT NULL,\n PRIMARY KEY(id)\n);\n\nCREATE TABLE IF NOT EXISTS lsif_data_docs_search_repo_names_private (\n id BIGSERIAL,\n repo_name text NOT NULL,\n tsv tsvector NOT NULL,\n reverse_tsv tsvector NOT NULL,\n PRIMARY KEY(id),\n UNIQUE(repo_name)\n);\n\nCREATE TABLE IF NOT EXISTS lsif_data_docs_search_repo_names_public (\n id BIGSERIAL,\n repo_name text NOT NULL,\n tsv tsvector NOT NULL,\n reverse_tsv tsvector NOT NULL,\n PRIMARY KEY(id),\n UNIQUE(repo_name)\n);\n\nCREATE TABLE IF NOT EXISTS lsif_data_docs_search_tags_private (\n id BIGSERIAL,\n tags text NOT NULL UNIQUE,\n tsv tsvector NOT NULL,\n PRIMARY KEY(id)\n);\n\nCREATE TABLE IF NOT EXISTS lsif_data_docs_search_tags_public (\n id BIGSERIAL,\n tags text NOT NULL UNIQUE,\n tsv tsvector NOT NULL,\n PRIMARY KEY(id),\n UNIQUE(tags)\n);\n\nCREATE TABLE IF NOT EXISTS lsif_data_documentation_mappings (\n dump_id integer NOT NULL,\n path_id text NOT NULL,\n result_id integer NOT NULL,\n file_path text,\n PRIMARY KEY(dump_id, path_id)\n);\n\nCREATE TABLE IF NOT EXISTS lsif_data_documentation_pages (\n dump_id integer NOT NULL,\n path_id text NOT NULL,\n data bytea,\n search_indexed boolean DEFAULT false,\n PRIMARY KEY(dump_id, path_id)\n);\n\nCREATE TABLE IF NOT EXISTS lsif_data_documentation_path_info (\n dump_id integer NOT NULL,\n path_id text NOT NULL,\n data bytea,\n PRIMARY KEY(dump_id, path_id)\n);\n\nCREATE INDEX IF NOT EXISTS lsif_data_docs_search_current_private_last_cleanup_scan_at ON lsif_data_docs_search_current_private USING btree (last_cleanup_scan_at);\nCREATE INDEX IF NOT EXISTS lsif_data_docs_search_current_private_lookup ON lsif_data_docs_search_current_private USING btree (repo_id, dump_root, lang_name_id, created_at) INCLUDE (dump_id);\nCREATE INDEX IF NOT EXISTS lsif_data_docs_search_current_public_last_cleanup_scan_at ON lsif_data_docs_search_current_public USING btree (last_cleanup_scan_at);\nCREATE INDEX IF NOT EXISTS lsif_data_docs_search_current_public_lookup ON lsif_data_docs_search_current_public USING btree (repo_id, dump_root, lang_name_id, created_at) INCLUDE (dump_id);\nCREATE INDEX IF NOT EXISTS lsif_data_docs_search_lang_names_private_tsv_idx ON lsif_data_docs_search_lang_names_private USING gin (tsv);\nCREATE INDEX IF NOT EXISTS lsif_data_docs_search_lang_names_public_tsv_idx ON lsif_data_docs_search_lang_names_public USING gin (tsv);\nCREATE INDEX IF NOT EXISTS lsif_data_docs_search_private_dump_id_idx ON lsif_data_docs_search_private USING btree (dump_id);\nCREATE INDEX IF NOT EXISTS lsif_data_docs_search_private_dump_root_idx ON lsif_data_docs_search_private USING btree (dump_root);\nCREATE INDEX IF NOT EXISTS lsif_data_docs_search_private_label_reverse_tsv_idx ON lsif_data_docs_search_private USING gin (label_reverse_tsv);\nCREATE INDEX IF NOT EXISTS lsif_data_docs_search_private_label_tsv_idx ON lsif_data_docs_search_private USING gin (label_tsv);\nCREATE INDEX IF NOT EXISTS lsif_data_docs_search_private_repo_id_idx ON lsif_data_docs_search_private USING btree (repo_id);\nCREATE INDEX IF NOT EXISTS lsif_data_docs_search_private_search_key_reverse_tsv_idx ON lsif_data_docs_search_private USING gin (search_key_reverse_tsv);\nCREATE INDEX IF NOT EXISTS lsif_data_docs_search_private_search_key_tsv_idx ON lsif_data_docs_search_private USING gin (search_key_tsv);\nCREATE INDEX IF NOT EXISTS lsif_data_docs_search_public_dump_id_idx ON lsif_data_docs_search_public USING btree (dump_id);\nCREATE INDEX IF NOT EXISTS lsif_data_docs_search_public_dump_root_idx ON lsif_data_docs_search_public USING btree (dump_root);\nCREATE INDEX IF NOT EXISTS lsif_data_docs_search_public_label_reverse_tsv_idx ON lsif_data_docs_search_public USING gin (label_reverse_tsv);\nCREATE INDEX IF NOT EXISTS lsif_data_docs_search_public_label_tsv_idx ON lsif_data_docs_search_public USING gin (label_tsv);\nCREATE INDEX IF NOT EXISTS lsif_data_docs_search_public_repo_id_idx ON lsif_data_docs_search_public USING btree (repo_id);\nCREATE INDEX IF NOT EXISTS lsif_data_docs_search_public_search_key_reverse_tsv_idx ON lsif_data_docs_search_public USING gin (search_key_reverse_tsv);\nCREATE INDEX IF NOT EXISTS lsif_data_docs_search_public_search_key_tsv_idx ON lsif_data_docs_search_public USING gin (search_key_tsv);\nCREATE INDEX IF NOT EXISTS lsif_data_docs_search_repo_names_private_reverse_tsv_idx ON lsif_data_docs_search_repo_names_private USING gin (reverse_tsv);\nCREATE INDEX IF NOT EXISTS lsif_data_docs_search_repo_names_private_tsv_idx ON lsif_data_docs_search_repo_names_private USING gin (tsv);\nCREATE INDEX IF NOT EXISTS lsif_data_docs_search_repo_names_public_reverse_tsv_idx ON lsif_data_docs_search_repo_names_public USING gin (reverse_tsv);\nCREATE INDEX IF NOT EXISTS lsif_data_docs_search_repo_names_public_tsv_idx ON lsif_data_docs_search_repo_names_public USING gin (tsv);\nCREATE INDEX IF NOT EXISTS lsif_data_docs_search_tags_private_tsv_idx ON lsif_data_docs_search_tags_private USING gin (tsv);\nCREATE INDEX IF NOT EXISTS lsif_data_docs_search_tags_public_tsv_idx ON lsif_data_docs_search_tags_public USING gin (tsv);\nCREATE UNIQUE INDEX IF NOT EXISTS lsif_data_documentation_mappings_inverse_unique_idx ON lsif_data_documentation_mappings USING btree (dump_id, result_id);\nCREATE INDEX IF NOT EXISTS lsif_data_documentation_pages_dump_id_unindexed ON lsif_data_documentation_pages USING btree (dump_id) WHERE (NOT search_indexed);\n\nDROP TRIGGER IF EXISTS lsif_data_docs_search_private_delete ON lsif_data_docs_search_private;\nCREATE TRIGGER lsif_data_docs_search_private_delete AFTER DELETE ON lsif_data_docs_search_private REFERENCING OLD TABLE AS oldtbl FOR EACH STATEMENT EXECUTE FUNCTION lsif_data_docs_search_private_delete();\nDROP TRIGGER IF EXISTS lsif_data_docs_search_private_insert ON lsif_data_docs_search_private;\nCREATE TRIGGER lsif_data_docs_search_private_insert AFTER INSERT ON lsif_data_docs_search_private REFERENCING NEW TABLE AS newtbl FOR EACH STATEMENT EXECUTE FUNCTION lsif_data_docs_search_private_insert();\nDROP TRIGGER IF EXISTS lsif_data_docs_search_public_delete ON lsif_data_docs_search_public;\nCREATE TRIGGER lsif_data_docs_search_public_delete AFTER DELETE ON lsif_data_docs_search_public REFERENCING OLD TABLE AS oldtbl FOR EACH STATEMENT EXECUTE FUNCTION lsif_data_docs_search_public_delete();\nDROP TRIGGER IF EXISTS lsif_data_docs_search_public_insert ON lsif_data_docs_search_public;\nCREATE TRIGGER lsif_data_docs_search_public_insert AFTER INSERT ON lsif_data_docs_search_public REFERENCING NEW TABLE AS newtbl FOR EACH STATEMENT EXECUTE FUNCTION lsif_data_docs_search_public_insert();\nDROP TRIGGER IF EXISTS lsif_data_documentation_pages_delete ON lsif_data_documentation_pages;\nCREATE TRIGGER lsif_data_documentation_pages_delete AFTER DELETE ON lsif_data_documentation_pages REFERENCING OLD TABLE AS oldtbl FOR EACH STATEMENT EXECUTE FUNCTION lsif_data_documentation_pages_delete();\nDROP TRIGGER IF EXISTS lsif_data_documentation_pages_insert ON lsif_data_documentation_pages;\nCREATE TRIGGER lsif_data_documentation_pages_insert AFTER INSERT ON lsif_data_documentation_pages REFERENCING NEW TABLE AS newtbl FOR EACH STATEMENT EXECUTE FUNCTION lsif_data_documentation_pages_insert();\nDROP TRIGGER IF EXISTS lsif_data_documentation_pages_update ON lsif_data_documentation_pages;\nCREATE TRIGGER lsif_data_documentation_pages_update AFTER UPDATE ON lsif_data_documentation_pages REFERENCING OLD TABLE AS oldtbl NEW TABLE AS newtbl FOR EACH STATEMENT EXECUTE FUNCTION lsif_data_documentation_pages_update();\n\nCOMMENT ON TABLE lsif_data_docs_search_current_private IS 'A table indicating the most current search index for a unique repository, root, and language.';\nCOMMENT ON COLUMN lsif_data_docs_search_current_private.repo_id IS 'The repository identifier of the associated dump.';\nCOMMENT ON COLUMN lsif_data_docs_search_current_private.dump_root IS 'The root of the associated dump.';\nCOMMENT ON COLUMN lsif_data_docs_search_current_private.lang_name_id IS 'The interned index name of the associated dump.';\nCOMMENT ON COLUMN lsif_data_docs_search_current_private.dump_id IS 'The associated dump identifier.';\nCOMMENT ON COLUMN lsif_data_docs_search_current_private.last_cleanup_scan_at IS 'The last time this record was checked as part of a data retention scan.';\nCOMMENT ON COLUMN lsif_data_docs_search_current_private.created_at IS 'The time this record was inserted. The records with the latest created_at value for the same repository, root, and language is the only visible one and others will be deleted asynchronously.';\n\nCOMMENT ON TABLE lsif_data_docs_search_current_public IS 'A table indicating the most current search index for a unique repository, root, and language.';\nCOMMENT ON COLUMN lsif_data_docs_search_current_public.repo_id IS 'The repository identifier of the associated dump.';\nCOMMENT ON COLUMN lsif_data_docs_search_current_public.dump_root IS 'The root of the associated dump.';\nCOMMENT ON COLUMN lsif_data_docs_search_current_public.lang_name_id IS 'The interned index name of the associated dump.';\nCOMMENT ON COLUMN lsif_data_docs_search_current_public.dump_id IS 'The associated dump identifier.';\nCOMMENT ON COLUMN lsif_data_docs_search_current_public.last_cleanup_scan_at IS 'The last time this record was checked as part of a data retention scan.';\nCOMMENT ON COLUMN lsif_data_docs_search_current_public.created_at IS 'The time this record was inserted. The records with the latest created_at value for the same repository, root, and language is the only visible one and others will be deleted asynchronously.';\n\nCOMMENT ON TABLE lsif_data_docs_search_lang_names_private IS 'Each unique language name being stored in the API docs search index.';\nCOMMENT ON COLUMN lsif_data_docs_search_lang_names_private.id IS 'The ID of the language name.';\nCOMMENT ON COLUMN lsif_data_docs_search_lang_names_private.lang_name IS 'The lowercase language name (go, java, etc.) OR, if unknown, the LSIF indexer name.';\nCOMMENT ON COLUMN lsif_data_docs_search_lang_names_private.tsv IS 'Indexed tsvector for the lang_name field. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\n\nCOMMENT ON TABLE lsif_data_docs_search_lang_names_public IS 'Each unique language name being stored in the API docs search index.';\nCOMMENT ON COLUMN lsif_data_docs_search_lang_names_public.id IS 'The ID of the language name.';\nCOMMENT ON COLUMN lsif_data_docs_search_lang_names_public.lang_name IS 'The lowercase language name (go, java, etc.) OR, if unknown, the LSIF indexer name.';\nCOMMENT ON COLUMN lsif_data_docs_search_lang_names_public.tsv IS 'Indexed tsvector for the lang_name field. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\n\nCOMMENT ON TABLE lsif_data_docs_search_private IS 'A tsvector search index over API documentation (private repos only)';\nCOMMENT ON COLUMN lsif_data_docs_search_private.id IS 'The row ID of the search result.';\nCOMMENT ON COLUMN lsif_data_docs_search_private.repo_id IS 'The repo ID, from the main app DB repo table. Used to search over a select set of repos by ID.';\nCOMMENT ON COLUMN lsif_data_docs_search_private.dump_id IS 'The identifier of the associated dump in the lsif_uploads table (state=completed).';\nCOMMENT ON COLUMN lsif_data_docs_search_private.dump_root IS 'Identical to lsif_dumps.root; The working directory of the indexer image relative to the repository root.';\nCOMMENT ON COLUMN lsif_data_docs_search_private.path_id IS 'The fully qualified documentation page path ID, e.g. including \"#section\". See GraphQL codeintel.schema:documentationPage for what this is.';\nCOMMENT ON COLUMN lsif_data_docs_search_private.detail IS 'The detail string (e.g. the full function signature and its docs). See protocol/documentation.go:Documentation';\nCOMMENT ON COLUMN lsif_data_docs_search_private.lang_name_id IS 'The programming language (or indexer name) that produced the result. Foreign key into lsif_data_docs_search_lang_names_private.';\nCOMMENT ON COLUMN lsif_data_docs_search_private.repo_name_id IS 'The repository name that produced the result. Foreign key into lsif_data_docs_search_repo_names_private.';\nCOMMENT ON COLUMN lsif_data_docs_search_private.tags_id IS 'The tags from the documentation node. Foreign key into lsif_data_docs_search_tags_private.';\nCOMMENT ON COLUMN lsif_data_docs_search_private.search_key IS 'The search key generated by the indexer, e.g. mux.Router.ServeHTTP. It is language-specific, and likely unique within a repository (but not always.) See protocol/documentation.go:Documentation.SearchKey';\nCOMMENT ON COLUMN lsif_data_docs_search_private.search_key_tsv IS 'Indexed tsvector for the search_key field. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\nCOMMENT ON COLUMN lsif_data_docs_search_private.search_key_reverse_tsv IS 'Indexed tsvector for the reverse of the search_key field, for suffix lexeme/word matching. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\nCOMMENT ON COLUMN lsif_data_docs_search_private.label IS 'The label string of the result, e.g. a one-line function signature. See protocol/documentation.go:Documentation';\nCOMMENT ON COLUMN lsif_data_docs_search_private.label_tsv IS 'Indexed tsvector for the label field. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\nCOMMENT ON COLUMN lsif_data_docs_search_private.label_reverse_tsv IS 'Indexed tsvector for the reverse of the label field, for suffix lexeme/word matching. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\n\nCOMMENT ON TABLE lsif_data_docs_search_public IS 'A tsvector search index over API documentation (public repos only)';\nCOMMENT ON COLUMN lsif_data_docs_search_public.id IS 'The row ID of the search result.';\nCOMMENT ON COLUMN lsif_data_docs_search_public.repo_id IS 'The repo ID, from the main app DB repo table. Used to search over a select set of repos by ID.';\nCOMMENT ON COLUMN lsif_data_docs_search_public.dump_id IS 'The identifier of the associated dump in the lsif_uploads table (state=completed).';\nCOMMENT ON COLUMN lsif_data_docs_search_public.dump_root IS 'Identical to lsif_dumps.root; The working directory of the indexer image relative to the repository root.';\nCOMMENT ON COLUMN lsif_data_docs_search_public.path_id IS 'The fully qualified documentation page path ID, e.g. including \"#section\". See GraphQL codeintel.schema:documentationPage for what this is.';\nCOMMENT ON COLUMN lsif_data_docs_search_public.detail IS 'The detail string (e.g. the full function signature and its docs). See protocol/documentation.go:Documentation';\nCOMMENT ON COLUMN lsif_data_docs_search_public.lang_name_id IS 'The programming language (or indexer name) that produced the result. Foreign key into lsif_data_docs_search_lang_names_public.';\nCOMMENT ON COLUMN lsif_data_docs_search_public.repo_name_id IS 'The repository name that produced the result. Foreign key into lsif_data_docs_search_repo_names_public.';\nCOMMENT ON COLUMN lsif_data_docs_search_public.tags_id IS 'The tags from the documentation node. Foreign key into lsif_data_docs_search_tags_public.';\nCOMMENT ON COLUMN lsif_data_docs_search_public.search_key IS 'The search key generated by the indexer, e.g. mux.Router.ServeHTTP. It is language-specific, and likely unique within a repository (but not always.) See protocol/documentation.go:Documentation.SearchKey';\nCOMMENT ON COLUMN lsif_data_docs_search_public.search_key_tsv IS 'Indexed tsvector for the search_key field. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\nCOMMENT ON COLUMN lsif_data_docs_search_public.search_key_reverse_tsv IS 'Indexed tsvector for the reverse of the search_key field, for suffix lexeme/word matching. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\nCOMMENT ON COLUMN lsif_data_docs_search_public.label IS 'The label string of the result, e.g. a one-line function signature. See protocol/documentation.go:Documentation';\nCOMMENT ON COLUMN lsif_data_docs_search_public.label_tsv IS 'Indexed tsvector for the label field. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\nCOMMENT ON COLUMN lsif_data_docs_search_public.label_reverse_tsv IS 'Indexed tsvector for the reverse of the label field, for suffix lexeme/word matching. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\n\nCOMMENT ON TABLE lsif_data_docs_search_repo_names_private IS 'Each unique repository name being stored in the API docs search index.';\nCOMMENT ON COLUMN lsif_data_docs_search_repo_names_private.id IS 'The ID of the repository name.';\nCOMMENT ON COLUMN lsif_data_docs_search_repo_names_private.repo_name IS 'The fully qualified name of the repository.';\nCOMMENT ON COLUMN lsif_data_docs_search_repo_names_private.tsv IS 'Indexed tsvector for the lang_name field. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\nCOMMENT ON COLUMN lsif_data_docs_search_repo_names_private.reverse_tsv IS 'Indexed tsvector for the reverse of the lang_name field, for suffix lexeme/word matching. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\n\nCOMMENT ON TABLE lsif_data_docs_search_repo_names_public IS 'Each unique repository name being stored in the API docs search index.';\nCOMMENT ON COLUMN lsif_data_docs_search_repo_names_public.id IS 'The ID of the repository name.';\nCOMMENT ON COLUMN lsif_data_docs_search_repo_names_public.repo_name IS 'The fully qualified name of the repository.';\nCOMMENT ON COLUMN lsif_data_docs_search_repo_names_public.tsv IS 'Indexed tsvector for the lang_name field. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\nCOMMENT ON COLUMN lsif_data_docs_search_repo_names_public.reverse_tsv IS 'Indexed tsvector for the reverse of the lang_name field, for suffix lexeme/word matching. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\n\nCOMMENT ON TABLE lsif_data_docs_search_tags_private IS 'Each uniques sequence of space-separated tags being stored in the API docs search index.';\nCOMMENT ON COLUMN lsif_data_docs_search_tags_private.id IS 'The ID of the tags.';\nCOMMENT ON COLUMN lsif_data_docs_search_tags_private.tags IS 'The full sequence of space-separated tags. See protocol/documentation.go:Documentation';\nCOMMENT ON COLUMN lsif_data_docs_search_tags_private.tsv IS 'Indexed tsvector for the tags field. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\n\nCOMMENT ON TABLE lsif_data_docs_search_tags_public IS 'Each uniques sequence of space-separated tags being stored in the API docs search index.';\nCOMMENT ON COLUMN lsif_data_docs_search_tags_public.id IS 'The ID of the tags.';\nCOMMENT ON COLUMN lsif_data_docs_search_tags_public.tags IS 'The full sequence of space-separated tags. See protocol/documentation.go:Documentation';\nCOMMENT ON COLUMN lsif_data_docs_search_tags_public.tsv IS 'Indexed tsvector for the tags field. Crafted for ordered, case, and punctuation sensitivity, see data_write_documentation.go:textSearchVector.';\n\nCOMMENT ON TABLE lsif_data_documentation_mappings IS 'Maps documentation path IDs to their corresponding integral documentationResult vertex IDs, which are unique within a dump.';\nCOMMENT ON COLUMN lsif_data_documentation_mappings.dump_id IS 'The identifier of the associated dump in the lsif_uploads table (state=completed).';\nCOMMENT ON COLUMN lsif_data_documentation_mappings.path_id IS 'The documentation page path ID, see see GraphQL codeintel.schema:documentationPage for what this is.';\nCOMMENT ON COLUMN lsif_data_documentation_mappings.result_id IS 'The documentationResult vertex ID.';\nCOMMENT ON COLUMN lsif_data_documentation_mappings.file_path IS 'The document file path for the documentationResult, if any. e.g. the path to the file where the symbol described by this documentationResult is located, if it is a symbol.';\n\nCOMMENT ON TABLE lsif_data_documentation_pages IS 'Associates documentation pathIDs to their documentation page hierarchy chunk.';\nCOMMENT ON COLUMN lsif_data_documentation_pages.dump_id IS 'The identifier of the associated dump in the lsif_uploads table (state=completed).';\nCOMMENT ON COLUMN lsif_data_documentation_pages.path_id IS 'The documentation page path ID, see see GraphQL codeintel.schema:documentationPage for what this is.';\nCOMMENT ON COLUMN lsif_data_documentation_pages.data IS 'A gob-encoded payload conforming to a `type DocumentationPageData struct` pointer (lib/codeintel/semantic/types.go)';\n\nCOMMENT ON TABLE lsif_data_documentation_path_info IS 'Associates documentation page pathIDs to information about what is at that pathID, its immediate children, etc.';\nCOMMENT ON COLUMN lsif_data_documentation_path_info.dump_id IS 'The identifier of the associated dump in the lsif_uploads table (state=completed).';\nCOMMENT ON COLUMN lsif_data_documentation_path_info.path_id IS 'The documentation page path ID, see see GraphQL codeintel.schema:documentationPage for what this is.';\nCOMMENT ON COLUMN lsif_data_documentation_path_info.data IS 'A gob-encoded payload conforming to a `type DocumentationPathInoData struct` pointer (lib/codeintel/semantic/types.go)';", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1000000034 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1666727108, + "Name": "Add codeintel_last_reconcile table", + "UpQuery": "CREATE TABLE IF NOT EXISTS codeintel_last_reconcile (\n dump_id integer NOT NULL UNIQUE,\n last_reconcile_at timestamp with time zone NOT NULL\n);\n\nCOMMENT ON TABLE codeintel_last_reconcile IS 'Stores the last time processed LSIF data was reconciled with the other database.';\n\nCREATE INDEX IF NOT EXISTS codeintel_last_reconcile_last_reconcile_at_dump_id ON codeintel_last_reconcile(last_reconcile_at, dump_id);", + "DownQuery": "DROP TABLE IF EXISTS codeintel_last_reconcile;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1665531314 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1669075922, + "Name": "Add SCIP tables", + "UpQuery": "CREATE TABLE IF NOT EXISTS codeintel_scip_metadata (\n id bigserial,\n upload_id integer NOT NULL,\n tool_name text NOT NULL,\n tool_version text NOT NULL,\n tool_arguments text[] NOT NULL,\n PRIMARY KEY(id)\n);\n\nCOMMENT ON TABLE codeintel_scip_metadata IS 'Global metadatadata about a single processed upload.';\nCOMMENT ON COLUMN codeintel_scip_metadata.id IS 'An auto-generated identifier.';\nCOMMENT ON COLUMN codeintel_scip_metadata.upload_id IS 'The identifier of the upload that provided this SCIP index.';\nCOMMENT ON COLUMN codeintel_scip_metadata.tool_name IS 'Name of the indexer that produced this index.';\nCOMMENT ON COLUMN codeintel_scip_metadata.tool_version IS 'Version of the indexer that produced this index.';\nCOMMENT ON COLUMN codeintel_scip_metadata.tool_arguments IS 'Command-line arguments that were used to invoke this indexer.';\n\nCREATE TABLE IF NOT EXISTS codeintel_scip_documents(\n id bigserial,\n payload_hash bytea NOT NULL UNIQUE,\n schema_version integer NOT NULL,\n raw_scip_payload bytea NOT NULL,\n PRIMARY KEY(id)\n);\n\nCOMMENT ON TABLE codeintel_scip_documents IS 'A lookup of SCIP [Document](https://sourcegraph.com/search?q=context:%40sourcegraph/all+repo:%5Egithub%5C.com/sourcegraph/scip%24+file:%5Escip%5C.proto+message+Document\u0026patternType=standard) payloads by their hash.';\nCOMMENT ON COLUMN codeintel_scip_documents.id IS 'An auto-generated identifier. This column is used as a foreign key target to reduce occurrences of the full payload hash value.';\nCOMMENT ON COLUMN codeintel_scip_documents.payload_hash IS 'A deterministic hash of the raw SCIP payload. We use this as a unique value to enforce deduplication between indexes with the same document data.';\nCOMMENT ON COLUMN codeintel_scip_documents.schema_version IS 'The schema version of this row - used to determine presence and encoding of (future) denormalized data.';\nCOMMENT ON COLUMN codeintel_scip_documents.raw_scip_payload IS 'The raw, canonicalized SCIP [Document](https://sourcegraph.com/search?q=context:%40sourcegraph/all+repo:%5Egithub%5C.com/sourcegraph/scip%24+file:%5Escip%5C.proto+message+Document\u0026patternType=standard) payload.';\n\nCREATE TABLE IF NOT EXISTS codeintel_scip_document_lookup(\n id bigserial,\n upload_id integer NOT NULL,\n document_path text NOT NULL,\n document_id bigint NOT NULL,\n PRIMARY KEY (id),\n UNIQUE (upload_id, document_path),\n CONSTRAINT codeintel_scip_document_lookup_document_id_fk FOREIGN KEY(document_id) REFERENCES codeintel_scip_documents(id)\n);\n\nCREATE INDEX IF NOT EXISTS codeintel_scip_document_lookup_document_id ON codeintel_scip_document_lookup USING hash(document_id);\n\nCOMMENT ON TABLE codeintel_scip_document_lookup IS 'A mapping from file paths to document references within a particular SCIP index.';\nCOMMENT ON COLUMN codeintel_scip_document_lookup.id IS 'An auto-generated identifier. This column is used as a foreign key target to reduce occurrences of the full document path value.';\nCOMMENT ON COLUMN codeintel_scip_document_lookup.upload_id IS 'The identifier of the upload that provided this SCIP index.';\nCOMMENT ON COLUMN codeintel_scip_document_lookup.document_path IS 'The file path to the document relative to the root of the index.';\nCOMMENT ON COLUMN codeintel_scip_document_lookup.document_id IS 'The foreign key to the shared document payload (see the table [`codeintel_scip_document_lookup`](#table-publiccodeintel_scip_document_lookup)).';\n\nCREATE TABLE IF NOT EXISTS codeintel_scip_document_lookup_schema_versions (\n upload_id integer NOT NULL,\n min_schema_version integer,\n max_schema_version integer,\n PRIMARY KEY(upload_id)\n);\n\nCOMMENT ON TABLE codeintel_scip_document_lookup_schema_versions IS 'Tracks the range of `schema_versions` values associated with each SCIP index in the [`codeintel_scip_document_lookup`](#table-publiccodeintel_scip_document_lookup) table.';\nCOMMENT ON COLUMN codeintel_scip_document_lookup_schema_versions.upload_id IS 'The identifier of the associated SCIP index.';\nCOMMENT ON COLUMN codeintel_scip_document_lookup_schema_versions.min_schema_version IS 'A lower-bound on the `schema_version` values of the records in the table [`codeintel_scip_document_lookup`](#table-publiccodeintel_scip_document_lookup) where the `upload_id` column matches the associated SCIP index.';\nCOMMENT ON COLUMN codeintel_scip_document_lookup_schema_versions.max_schema_version IS 'An upper-bound on the `schema_version` values of the records in the table [`codeintel_scip_document_lookup`](#table-publiccodeintel_scip_document_lookup) where the `upload_id` column matches the associated SCIP index.';\n\nCREATE OR REPLACE FUNCTION update_codeintel_scip_document_lookup_schema_versions_insert() RETURNS trigger\n LANGUAGE plpgsql\n AS $$ BEGIN\n INSERT INTO codeintel_scip_document_lookup_schema_versions\n SELECT\n upload_id,\n MIN(documents.schema_version) as min_schema_version,\n MAX(documents.schema_version) as max_schema_version\n FROM newtab\n JOIN codeintel_scip_documents ON codeintel_scip_documents.id = newtab.document_id\n GROUP BY newtab.upload_id\n ON CONFLICT (upload_id) DO UPDATE SET\n -- Update with min(old_min, new_min) and max(old_max, new_max)\n min_schema_version = LEAST(codeintel_scip_document_lookup_schema_versions.min_schema_version, EXCLUDED.min_schema_version),\n max_schema_version = GREATEST(codeintel_scip_document_lookup_schema_versions.max_schema_version, EXCLUDED.max_schema_version);\n RETURN NULL;\nEND $$;\n\nDROP TRIGGER IF EXISTS codeintel_scip_document_lookup_schema_versions_insert ON codeintel_scip_document_lookup_schema_versions;\nCREATE TRIGGER codeintel_scip_document_lookup_schema_versions_insert AFTER INSERT ON codeintel_scip_document_lookup_schema_versions\nREFERENCING NEW TABLE AS newtab FOR EACH STATEMENT EXECUTE FUNCTION update_codeintel_scip_document_lookup_schema_versions_insert();\n\nCREATE TABLE IF NOT EXISTS codeintel_scip_symbols(\n upload_id integer NOT NULL,\n symbol_name text NOT NULL,\n document_lookup_id bigint NOT NULL,\n schema_version integer NOT NULL,\n definition_ranges bytea,\n reference_ranges bytea,\n implementation_ranges bytea,\n type_definition_ranges bytea,\n PRIMARY KEY (upload_id, symbol_name, document_lookup_id),\n CONSTRAINT codeintel_scip_symbols_document_lookup_id_fk FOREIGN KEY(document_lookup_id) REFERENCES codeintel_scip_document_lookup(id) ON DELETE CASCADE\n);\n\nCOMMENT ON TABLE codeintel_scip_symbols IS 'A mapping from SCIP [Symbol names](https://sourcegraph.com/search?q=context:%40sourcegraph/all+repo:%5Egithub%5C.com/sourcegraph/scip%24+file:%5Escip%5C.proto+message+Symbol\u0026patternType=standard) to path and ranges where that symbol occurs within a particular SCIP index.';\nCOMMENT ON COLUMN codeintel_scip_symbols.upload_id IS 'The identifier of the upload that provided this SCIP index.';\nCOMMENT ON COLUMN codeintel_scip_symbols.symbol_name IS 'The SCIP [Symbol names](https://sourcegraph.com/search?q=context:%40sourcegraph/all+repo:%5Egithub%5C.com/sourcegraph/scip%24+file:%5Escip%5C.proto+message+Symbol\u0026patternType=standard).';\nCOMMENT ON COLUMN codeintel_scip_symbols.document_lookup_id IS 'A reference to the `id` column of [`codeintel_scip_document_lookup`](#table-publiccodeintel_scip_document_lookup). Joining on this table yields the document path relative to the index root.';\nCOMMENT ON COLUMN codeintel_scip_symbols.schema_version IS 'The schema version of this row - used to determine presence and encoding of denormalized data.';\nCOMMENT ON COLUMN codeintel_scip_symbols.definition_ranges IS 'An encoded set of ranges within the associated document that have a **definition** relationship to the associated symbol.';\nCOMMENT ON COLUMN codeintel_scip_symbols.reference_ranges IS 'An encoded set of ranges within the associated document that have a **reference** relationship to the associated symbol.';\nCOMMENT ON COLUMN codeintel_scip_symbols.implementation_ranges IS 'An encoded set of ranges within the associated document that have a **implementation** relationship to the associated symbol.';\nCOMMENT ON COLUMN codeintel_scip_symbols.type_definition_ranges IS 'An encoded set of ranges within the associated document that have a **type definition** relationship to the associated symbol.';\n\nCREATE TABLE IF NOT EXISTS codeintel_scip_symbols_schema_versions (\n upload_id integer NOT NULL,\n min_schema_version integer,\n max_schema_version integer,\n PRIMARY KEY(upload_id)\n);\n\nCOMMENT ON TABLE codeintel_scip_symbols_schema_versions IS 'Tracks the range of `schema_versions` for each index in the [`codeintel_scip_symbols`](#table-publiccodeintel_scip_symbols) table.';\nCOMMENT ON COLUMN codeintel_scip_symbols_schema_versions.upload_id IS 'The identifier of the associated SCIP index.';\nCOMMENT ON COLUMN codeintel_scip_symbols_schema_versions.min_schema_version IS 'A lower-bound on the `schema_version` values of the records in the table [`codeintel_scip_symbols`](#table-publiccodeintel_scip_symbols) where the `upload_id` column matches the associated SCIP index.';\nCOMMENT ON COLUMN codeintel_scip_symbols_schema_versions.max_schema_version IS 'An upper-bound on the `schema_version` values of the records in the table [`codeintel_scip_symbols`](#table-publiccodeintel_scip_symbols) where the `upload_id` column matches the associated SCIP index.';\n\nCREATE OR REPLACE FUNCTION update_codeintel_scip_symbols_schema_versions_insert() RETURNS trigger\n LANGUAGE plpgsql\n AS $$ BEGIN\n INSERT INTO codeintel_scip_symbols_schema_versions\n SELECT\n upload_id,\n MIN(schema_version) as min_schema_version,\n MAX(schema_version) as max_schema_version\n FROM newtab\n GROUP BY upload_id\n ON CONFLICT (upload_id) DO UPDATE SET\n -- Update with min(old_min, new_min) and max(old_max, new_max)\n min_schema_version = LEAST(codeintel_scip_symbols_schema_versions.min_schema_version, EXCLUDED.min_schema_version),\n max_schema_version = GREATEST(codeintel_scip_symbols_schema_versions.max_schema_version, EXCLUDED.max_schema_version);\n RETURN NULL;\nEND $$;\n\nDROP TRIGGER IF EXISTS codeintel_scip_symbols_schema_versions_insert ON codeintel_scip_symbols_schema_versions;\nCREATE TRIGGER codeintel_scip_symbols_schema_versions_insert AFTER INSERT ON codeintel_scip_symbols_schema_versions\nREFERENCING NEW TABLE AS newtab FOR EACH STATEMENT EXECUTE FUNCTION update_codeintel_scip_symbols_schema_versions_insert();", + "DownQuery": "DROP TRIGGER IF EXISTS codeintel_scip_symbols_schema_versions_insert ON codeintel_scip_symbols_schema_versions;\nDROP FUNCTION IF EXISTS update_codeintel_scip_symbols_schema_versions_insert();\nDROP TABLE IF EXISTS codeintel_scip_symbols_schema_versions;\n\nDROP TRIGGER IF EXISTS codeintel_scip_document_lookup_schema_versions_insert ON codeintel_scip_document_lookup_schema_versions;\nDROP FUNCTION IF EXISTS update_codeintel_scip_document_lookup_schema_versions_insert();\nDROP TABLE IF EXISTS codeintel_scip_document_lookup_schema_versions;\n\nDROP TABLE IF EXISTS codeintel_scip_symbols;\nDROP TABLE IF EXISTS codeintel_scip_document_lookup;\nDROP TABLE IF EXISTS codeintel_scip_documents;\nDROP TABLE IF EXISTS codeintel_scip_metadata;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1666727108 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1669842405, + "Name": "Add additional metadata fields", + "UpQuery": "ALTER TABLE codeintel_scip_metadata ADD COLUMN IF NOT EXISTS text_document_encoding text NOT NULL;\nALTER TABLE codeintel_scip_metadata ADD COLUMN IF NOT EXISTS protocol_version integer NOT NULL;\n\nCOMMENT ON COLUMN codeintel_scip_metadata.text_document_encoding IS 'The encoding of the text documents within this index. May affect range boundaries.';\nCOMMENT ON COLUMN codeintel_scip_metadata.protocol_version IS 'The version of the SCIP protocol used to encode this index.';", + "DownQuery": "ALTER TABLE codeintel_scip_metadata DROP COLUMN IF EXISTS text_document_encoding;\nALTER TABLE codeintel_scip_metadata DROP COLUMN IF EXISTS protocol_version;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1669075922 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1669934289, + "Name": "Add scip document schema versions table", + "UpQuery": "CREATE TABLE IF NOT EXISTS codeintel_scip_documents_schema_versions (\n upload_id integer NOT NULL,\n min_schema_version integer,\n max_schema_version integer,\n PRIMARY KEY(upload_id)\n);\n\nCOMMENT ON TABLE codeintel_scip_documents_schema_versions IS 'Tracks the range of `schema_versions` values associated with each SCIP index in the [`codeintel_scip_documents`](#table-publiccodeintel_scip_documents) table.';\nCOMMENT ON COLUMN codeintel_scip_documents_schema_versions.upload_id IS 'The identifier of the associated SCIP index.';\nCOMMENT ON COLUMN codeintel_scip_documents_schema_versions.min_schema_version IS 'A lower-bound on the `schema_version` values of the records in the table [`codeintel_scip_documents`](#table-publiccodeintel_scip_documents) where the `upload_id` column matches the associated SCIP index.';\nCOMMENT ON COLUMN codeintel_scip_documents_schema_versions.max_schema_version IS 'An upper-bound on the `schema_version` values of the records in the table [`codeintel_scip_documents`](#table-publiccodeintel_scip_documents) where the `upload_id` column matches the associated SCIP index.';\n\nCREATE OR REPLACE FUNCTION update_codeintel_scip_documents_schema_versions_insert() RETURNS trigger\n LANGUAGE plpgsql\n AS $$ BEGIN\n INSERT INTO codeintel_scip_documents_schema_versions\n SELECT\n upload_id,\n MIN(documents.schema_version) as min_schema_version,\n MAX(documents.schema_version) as max_schema_version\n FROM newtab\n JOIN codeintel_scip_documents ON codeintel_scip_documents.id = newtab.document_id\n GROUP BY newtab.upload_id\n ON CONFLICT (upload_id) DO UPDATE SET\n -- Update with min(old_min, new_min) and max(old_max, new_max)\n min_schema_version = LEAST(codeintel_scip_documents_schema_versions.min_schema_version, EXCLUDED.min_schema_version),\n max_schema_version = GREATEST(codeintel_scip_documents_schema_versions.max_schema_version, EXCLUDED.max_schema_version);\n RETURN NULL;\nEND $$;\n\nDROP TRIGGER IF EXISTS codeintel_scip_documents_schema_versions_insert ON codeintel_scip_documents_schema_versions;\nCREATE TRIGGER codeintel_scip_documents_schema_versions_insert AFTER INSERT ON codeintel_scip_documents_schema_versions\nREFERENCING NEW TABLE AS newtab FOR EACH STATEMENT EXECUTE FUNCTION update_codeintel_scip_documents_schema_versions_insert();", + "DownQuery": "DROP TRIGGER IF EXISTS codeintel_scip_documents_schema_versions_insert ON codeintel_scip_documents_schema_versions;\nDROP FUNCTION IF EXISTS update_codeintel_scip_documents_schema_versions_insert();\nDROP TABLE IF EXISTS codeintel_scip_documents_schema_versions;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1669842405 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1670001463, + "Name": "Add missing index for cascading deletes", + "UpQuery": "CREATE INDEX IF NOT EXISTS codeintel_scip_symbols_document_lookup_id ON codeintel_scip_symbols(document_lookup_id);", + "DownQuery": "DROP INDEX IF EXISTS codeintel_scip_symbols_document_lookup_id;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1669934289 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1670363942, + "Name": "Fix SCIP schema version triggers", + "UpQuery": "DROP TRIGGER IF EXISTS codeintel_scip_documents_schema_versions_insert ON codeintel_scip_documents;\nDROP TRIGGER IF EXISTS codeintel_scip_documents_schema_versions_insert ON codeintel_scip_documents_schema_versions;\nDROP FUNCTION IF EXISTS update_codeintel_scip_documents_schema_versions_insert();\n\nDROP TRIGGER IF EXISTS codeintel_scip_document_lookup_schema_versions_insert ON codeintel_scip_document_lookup;\nDROP TRIGGER IF EXISTS codeintel_scip_document_lookup_schema_versions_insert ON codeintel_scip_document_lookup_schema_versions;\nCREATE TRIGGER codeintel_scip_document_lookup_schema_versions_insert AFTER INSERT ON codeintel_scip_document_lookup\nREFERENCING NEW TABLE AS newtab FOR EACH STATEMENT EXECUTE FUNCTION update_codeintel_scip_document_lookup_schema_versions_insert();\n\nDROP TRIGGER IF EXISTS codeintel_scip_symbols_schema_versions_insert ON codeintel_scip_symbols;\nDROP TRIGGER IF EXISTS codeintel_scip_symbols_schema_versions_insert ON codeintel_scip_symbols_schema_versions;\nCREATE TRIGGER codeintel_scip_symbols_schema_versions_insert AFTER INSERT ON codeintel_scip_symbols\nREFERENCING NEW TABLE AS newtab FOR EACH STATEMENT EXECUTE FUNCTION update_codeintel_scip_symbols_schema_versions_insert();\n\nCREATE OR REPLACE FUNCTION update_codeintel_scip_document_lookup_schema_versions_insert() RETURNS trigger\n LANGUAGE plpgsql\n AS $$ BEGIN\n INSERT INTO codeintel_scip_document_lookup_schema_versions\n SELECT\n upload_id,\n MIN(schema_version) as min_schema_version,\n MAX(schema_version) as max_schema_version\n FROM newtab\n JOIN codeintel_scip_documents ON codeintel_scip_documents.id = newtab.document_id\n GROUP BY newtab.upload_id\n ON CONFLICT (upload_id) DO UPDATE SET\n -- Update with min(old_min, new_min) and max(old_max, new_max)\n min_schema_version = LEAST(codeintel_scip_document_lookup_schema_versions.min_schema_version, EXCLUDED.min_schema_version),\n max_schema_version = GREATEST(codeintel_scip_document_lookup_schema_versions.max_schema_version, EXCLUDED.max_schema_version);\n RETURN NULL;\nEND $$;\n\nCREATE OR REPLACE FUNCTION update_codeintel_scip_symbols_schema_versions_insert() RETURNS trigger\n LANGUAGE plpgsql\n AS $$ BEGIN\n INSERT INTO codeintel_scip_symbols_schema_versions\n SELECT\n upload_id,\n MIN(schema_version) as min_schema_version,\n MAX(schema_version) as max_schema_version\n FROM newtab\n GROUP BY upload_id\n ON CONFLICT (upload_id) DO UPDATE SET\n -- Update with min(old_min, new_min) and max(old_max, new_max)\n min_schema_version = LEAST(codeintel_scip_symbols_schema_versions.min_schema_version, EXCLUDED.min_schema_version),\n max_schema_version = GREATEST(codeintel_scip_symbols_schema_versions.max_schema_version, EXCLUDED.max_schema_version);\n RETURN NULL;\nEND $$;", + "DownQuery": "--\n-- Restore some gibberish I guess?\n--\n\nCREATE OR REPLACE FUNCTION update_codeintel_scip_documents_schema_versions_insert() RETURNS trigger\n LANGUAGE plpgsql\n AS $$ BEGIN\n INSERT INTO codeintel_scip_documents_schema_versions\n SELECT\n upload_id,\n MIN(documents.schema_version) as min_schema_version,\n MAX(documents.schema_version) as max_schema_version\n FROM newtab\n JOIN codeintel_scip_documents ON codeintel_scip_documents.id = newtab.document_id\n GROUP BY newtab.upload_id\n ON CONFLICT (upload_id) DO UPDATE SET\n -- Update with min(old_min, new_min) and max(old_max, new_max)\n min_schema_version = LEAST(codeintel_scip_documents_schema_versions.min_schema_version, EXCLUDED.min_schema_version),\n max_schema_version = GREATEST(codeintel_scip_documents_schema_versions.max_schema_version, EXCLUDED.max_schema_version);\n RETURN NULL;\nEND $$;\n\nCREATE OR REPLACE FUNCTION update_codeintel_scip_document_lookup_schema_versions_insert() RETURNS trigger\n LANGUAGE plpgsql\n AS $$ BEGIN\n INSERT INTO codeintel_scip_document_lookup_schema_versions\n SELECT\n upload_id,\n MIN(documents.schema_version) as min_schema_version,\n MAX(documents.schema_version) as max_schema_version\n FROM newtab\n JOIN codeintel_scip_documents ON codeintel_scip_documents.id = newtab.document_id\n GROUP BY newtab.upload_id\n ON CONFLICT (upload_id) DO UPDATE SET\n -- Update with min(old_min, new_min) and max(old_max, new_max)\n min_schema_version = LEAST(codeintel_scip_document_lookup_schema_versions.min_schema_version, EXCLUDED.min_schema_version),\n max_schema_version = GREATEST(codeintel_scip_document_lookup_schema_versions.max_schema_version, EXCLUDED.max_schema_version);\n RETURN NULL;\nEND $$;\n\nCREATE OR REPLACE FUNCTION update_codeintel_scip_symbols_schema_versions_insert() RETURNS trigger\n LANGUAGE plpgsql\n AS $$ BEGIN\n INSERT INTO codeintel_scip_symbols_schema_versions\n SELECT\n upload_id,\n MIN(schema_version) as min_schema_version,\n MAX(schema_version) as max_schema_version\n FROM newtab\n GROUP BY upload_id\n ON CONFLICT (upload_id) DO UPDATE SET\n -- Update with min(old_min, new_min) and max(old_max, new_max)\n min_schema_version = LEAST(codeintel_scip_symbols_schema_versions.min_schema_version, EXCLUDED.min_schema_version),\n max_schema_version = GREATEST(codeintel_scip_symbols_schema_versions.max_schema_version, EXCLUDED.max_schema_version);\n RETURN NULL;\nEND $$;\n\n--\n-- Actual triggers\n--\n\nDROP TRIGGER IF EXISTS codeintel_scip_documents_schema_versions_insert ON codeintel_scip_documents;\nDROP TRIGGER IF EXISTS codeintel_scip_documents_schema_versions_insert ON codeintel_scip_documents_schema_versions;\nCREATE TRIGGER codeintel_scip_documents_schema_versions_insert AFTER INSERT ON codeintel_scip_documents_schema_versions\nREFERENCING NEW TABLE AS newtab FOR EACH STATEMENT EXECUTE FUNCTION update_codeintel_scip_documents_schema_versions_insert();\n\nDROP TRIGGER IF EXISTS codeintel_scip_document_lookup_schema_versions_insert ON codeintel_scip_document_lookup;\nDROP TRIGGER IF EXISTS codeintel_scip_document_lookup_schema_versions_insert ON codeintel_scip_document_lookup_schema_versions;\nCREATE TRIGGER codeintel_scip_document_lookup_schema_versions_insert AFTER INSERT ON codeintel_scip_document_lookup_schema_versions\nREFERENCING NEW TABLE AS newtab FOR EACH STATEMENT EXECUTE FUNCTION update_codeintel_scip_document_lookup_schema_versions_insert();\n\nDROP TRIGGER IF EXISTS codeintel_scip_symbols_schema_versions_insert ON codeintel_scip_symbols;\nDROP TRIGGER IF EXISTS codeintel_scip_symbols_schema_versions_insert ON codeintel_scip_symbols_schema_versions;\nCREATE TRIGGER codeintel_scip_symbols_schema_versions_insert AFTER INSERT ON codeintel_scip_symbols_schema_versions\nREFERENCING NEW TABLE AS newtab FOR EACH STATEMENT EXECUTE FUNCTION update_codeintel_scip_symbols_schema_versions_insert();", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1670001463 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1670365552, + "Name": "Fix SCIP document schema counting", + "UpQuery": "-- Add shard id to documents\nALTER TABLE codeintel_scip_documents ADD COLUMN IF NOT EXISTS metadata_shard_id integer NOT NULL DEFAULT floor(random() * 128 + 1)::integer;\nCOMMENT ON COLUMN codeintel_scip_documents.metadata_shard_id IS 'A randomly generated integer used to arbitrarily bucket groups of documents for things like expiration checks and data migrations.';\n\n-- Replace table and triggers\nDROP TABLE IF EXISTS codeintel_scip_documents_schema_versions;\nCREATE TABLE codeintel_scip_documents_schema_versions (\n metadata_shard_id integer NOT NULL,\n min_schema_version integer,\n max_schema_version integer,\n PRIMARY KEY(metadata_shard_id)\n);\n\nCOMMENT ON TABLE codeintel_scip_documents_schema_versions IS 'Tracks the range of `schema_versions` values associated with each document metadata shard in the [`codeintel_scip_documents`](#table-publiccodeintel_scip_documents) table.';\nCOMMENT ON COLUMN codeintel_scip_documents_schema_versions.metadata_shard_id IS 'The identifier of the associated document metadata shard.';\nCOMMENT ON COLUMN codeintel_scip_documents_schema_versions.min_schema_version IS 'A lower-bound on the `schema_version` values of the records in the table [`codeintel_scip_documents`](#table-publiccodeintel_scip_documents) where the `metadata_shard_id` column matches the associated document metadata shard.';\nCOMMENT ON COLUMN codeintel_scip_documents_schema_versions.max_schema_version IS 'An upper-bound on the `schema_version` values of the records in the table [`codeintel_scip_documents`](#table-publiccodeintel_scip_documents) where the `metadata_shard_id` column matches the associated document metadata shard.';\n\nCREATE OR REPLACE FUNCTION update_codeintel_scip_documents_schema_versions_insert() RETURNS trigger\n LANGUAGE plpgsql\n AS $$ BEGIN\n INSERT INTO codeintel_scip_documents_schema_versions\n SELECT\n newtab.metadata_shard_id,\n MIN(codeintel_scip_documents.schema_version) as min_schema_version,\n MAX(codeintel_scip_documents.schema_version) as max_schema_version\n FROM newtab\n JOIN codeintel_scip_documents ON codeintel_scip_documents.metadata_shard_id = newtab.metadata_shard_id\n GROUP BY newtab.metadata_shard_id\n ON CONFLICT (metadata_shard_id) DO UPDATE SET\n -- Update with min(old_min, new_min) and max(old_max, new_max)\n min_schema_version = LEAST(codeintel_scip_documents_schema_versions.min_schema_version, EXCLUDED.min_schema_version),\n max_schema_version = GREATEST(codeintel_scip_documents_schema_versions.max_schema_version, EXCLUDED.max_schema_version);\n RETURN NULL;\nEND $$;\n\nDROP TRIGGER IF EXISTS codeintel_scip_documents_schema_versions_insert ON codeintel_scip_documents;\nDROP TRIGGER IF EXISTS codeintel_scip_documents_schema_versions_insert ON codeintel_scip_documents_schema_versions;\nCREATE TRIGGER codeintel_scip_documents_schema_versions_insert AFTER INSERT ON codeintel_scip_documents\nREFERENCING NEW TABLE AS newtab FOR EACH STATEMENT EXECUTE FUNCTION update_codeintel_scip_documents_schema_versions_insert();", + "DownQuery": "-- Restore table and triggers\nDROP TABLE codeintel_scip_documents_schema_versions;\nCREATE TABLE IF NOT EXISTS codeintel_scip_documents_schema_versions (\n upload_id integer NOT NULL,\n min_schema_version integer,\n max_schema_version integer,\n PRIMARY KEY(upload_id)\n);\n\nCOMMENT ON TABLE codeintel_scip_documents_schema_versions IS 'Tracks the range of `schema_versions` values associated with each SCIP index in the [`codeintel_scip_documents`](#table-publiccodeintel_scip_documents) table.';\nCOMMENT ON COLUMN codeintel_scip_documents_schema_versions.upload_id IS 'The identifier of the associated SCIP index.';\nCOMMENT ON COLUMN codeintel_scip_documents_schema_versions.min_schema_version IS 'A lower-bound on the `schema_version` values of the records in the table [`codeintel_scip_documents`](#table-publiccodeintel_scip_documents) where the `upload_id` column matches the associated SCIP index.';\nCOMMENT ON COLUMN codeintel_scip_documents_schema_versions.max_schema_version IS 'An upper-bound on the `schema_version` values of the records in the table [`codeintel_scip_documents`](#table-publiccodeintel_scip_documents) where the `upload_id` column matches the associated SCIP index.';\n\nCREATE OR REPLACE FUNCTION update_codeintel_scip_documents_schema_versions_insert() RETURNS trigger\n LANGUAGE plpgsql\n AS $$ BEGIN\n INSERT INTO codeintel_scip_documents_schema_versions\n SELECT\n upload_id,\n MIN(documents.schema_version) as min_schema_version,\n MAX(documents.schema_version) as max_schema_version\n FROM newtab\n JOIN codeintel_scip_documents ON codeintel_scip_documents.id = newtab.document_id\n GROUP BY newtab.upload_id\n ON CONFLICT (upload_id) DO UPDATE SET\n -- Update with min(old_min, new_min) and max(old_max, new_max)\n min_schema_version = LEAST(codeintel_scip_documents_schema_versions.min_schema_version, EXCLUDED.min_schema_version),\n max_schema_version = GREATEST(codeintel_scip_documents_schema_versions.max_schema_version, EXCLUDED.max_schema_version);\n RETURN NULL;\nEND $$;\n\nDROP TRIGGER IF EXISTS codeintel_scip_documents_schema_versions_insert ON codeintel_scip_documents;\nDROP TRIGGER IF EXISTS codeintel_scip_documents_schema_versions_insert ON codeintel_scip_documents_schema_versions;\nCREATE TRIGGER codeintel_scip_documents_schema_versions_insert AFTER INSERT ON codeintel_scip_documents_schema_versions\nREFERENCING NEW TABLE AS newtab FOR EACH STATEMENT EXECUTE FUNCTION update_codeintel_scip_documents_schema_versions_insert();\n\n-- Restore documents table\nALTER TABLE codeintel_scip_documents DROP COLUMN IF EXISTS metadata_shard_id;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1670363942 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1670370058, + "Name": "Process unreferenced documents", + "UpQuery": "CREATE TABLE IF NOT EXISTS codeintel_scip_documents_dereference_logs (\n id bigserial,\n document_id bigint NOT NULL,\n last_removal_time timestamp with time zone NOT NULL DEFAULT NOW(),\n PRIMARY KEY(id)\n);\n\nCOMMENT ON TABLE codeintel_scip_documents_dereference_logs IS 'A list of document rows that were recently dereferenced by the deletion of an index.';\nCOMMENT ON COLUMN codeintel_scip_documents_dereference_logs.document_id IS 'The identifier of the document that was dereferenced.';\nCOMMENT ON COLUMN codeintel_scip_documents_dereference_logs.last_removal_time IS 'The time that the log entry was inserted.';\n\nCREATE INDEX IF NOT EXISTS codeintel_scip_documents_dereference_logs_last_removal_time_document_id ON codeintel_scip_documents_dereference_logs(last_removal_time, document_id);\n\nCREATE OR REPLACE FUNCTION update_codeintel_scip_documents_dereference_logs_delete() RETURNS trigger\n LANGUAGE plpgsql\n AS $$ BEGIN\n INSERT INTO codeintel_scip_documents_dereference_logs (document_id)\n SELECT document_id FROM oldtab;\n RETURN NULL;\nEND $$;\n\nDROP TRIGGER IF EXISTS codeintel_scip_documents_dereference_logs_insert ON codeintel_scip_document_lookup;\nCREATE TRIGGER codeintel_scip_documents_dereference_logs_insert AFTER DELETE ON codeintel_scip_document_lookup\nREFERENCING OLD TABLE AS oldtab FOR EACH STATEMENT EXECUTE FUNCTION update_codeintel_scip_documents_dereference_logs_delete();", + "DownQuery": "DROP TRIGGER IF EXISTS codeintel_scip_documents_dereference_logs_insert ON codeintel_scip_document_lookup;\nDROP FUNCTION IF EXISTS update_codeintel_scip_documents_dereference_logs_delete;\nDROP TABlE IF EXISTS codeintel_scip_documents_dereference_logs;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1670365552 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + } + ], + "BoundsByRev": { + "4.3.0": { + "RootID": 1000000033, + "LeafIDs": [ + 1670370058 + ], + "PreCreation": false + } + } + }, + "frontend": { + "Definitions": [ + { + "ID": 1648051770, + "Name": "squashed migrations (privileged)", + "UpQuery": "CREATE EXTENSION IF NOT EXISTS citext;\n\nCOMMENT ON EXTENSION citext IS 'data type for case-insensitive character strings';\n\nCREATE EXTENSION IF NOT EXISTS hstore;\n\nCOMMENT ON EXTENSION hstore IS 'data type for storing sets of (key, value) pairs';\n\nCREATE EXTENSION IF NOT EXISTS intarray;\n\nCOMMENT ON EXTENSION intarray IS 'functions, operators, and index support for 1-D arrays of integers';\n\nCREATE EXTENSION IF NOT EXISTS pg_stat_statements;\n\nCOMMENT ON EXTENSION pg_stat_statements IS 'track execution statistics of all SQL statements executed';\n\nCREATE EXTENSION IF NOT EXISTS pg_trgm;\n\nCOMMENT ON EXTENSION pg_trgm IS 'text similarity measurement and index searching based on trigrams';\n\nCREATE EXTENSION IF NOT EXISTS pgcrypto;\n\nCOMMENT ON EXTENSION pgcrypto IS 'cryptographic functions';", + "DownQuery": "-- Nothing", + "Privileged": true, + "NonIdempotent": true, + "Parents": [], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1648195639, + "Name": "squashed migrations (unprivileged)", + "UpQuery": "CREATE TYPE batch_changes_changeset_ui_publication_state AS ENUM (\n 'UNPUBLISHED',\n 'DRAFT',\n 'PUBLISHED'\n);\n\nCREATE TYPE cm_email_priority AS ENUM (\n 'NORMAL',\n 'CRITICAL'\n);\n\nCREATE TYPE critical_or_site AS ENUM (\n 'critical',\n 'site'\n);\n\nCREATE TYPE feature_flag_type AS ENUM (\n 'bool',\n 'rollout'\n);\n\nCREATE TYPE lsif_index_state AS ENUM (\n 'queued',\n 'processing',\n 'completed',\n 'errored',\n 'failed'\n);\n\nCREATE TYPE lsif_upload_state AS ENUM (\n 'uploading',\n 'queued',\n 'processing',\n 'completed',\n 'errored',\n 'deleted',\n 'failed'\n);\n\nCREATE TYPE persistmode AS ENUM (\n 'record',\n 'snapshot'\n);\n\nCREATE FUNCTION delete_batch_change_reference_on_changesets() RETURNS trigger\n LANGUAGE plpgsql\n AS $$\n BEGIN\n UPDATE\n changesets\n SET\n batch_change_ids = changesets.batch_change_ids - OLD.id::text\n WHERE\n changesets.batch_change_ids ? OLD.id::text;\n\n RETURN OLD;\n END;\n$$;\n\nCREATE FUNCTION delete_repo_ref_on_external_service_repos() RETURNS trigger\n LANGUAGE plpgsql\n AS $$\n BEGIN\n -- if a repo is soft-deleted, delete every row that references that repo\n IF (OLD.deleted_at IS NULL AND NEW.deleted_at IS NOT NULL) THEN\n DELETE FROM\n external_service_repos\n WHERE\n repo_id = OLD.id;\n END IF;\n\n RETURN OLD;\n END;\n$$;\n\nCREATE FUNCTION invalidate_session_for_userid_on_password_change() RETURNS trigger\n LANGUAGE plpgsql\n AS $$\n BEGIN\n IF OLD.passwd != NEW.passwd THEN\n NEW.invalidated_sessions_at = now() + (1 * interval '1 second');\n RETURN NEW;\n END IF;\n RETURN NEW;\n END;\n$$;\n\nCREATE FUNCTION repo_block(reason text, at timestamp with time zone) RETURNS jsonb\n LANGUAGE sql IMMUTABLE STRICT\n AS $$\nSELECT jsonb_build_object(\n 'reason', reason,\n 'at', extract(epoch from timezone('utc', at))::bigint\n);\n$$;\n\nCREATE PROCEDURE set_repo_stars_null_to_zero()\n LANGUAGE plpgsql\n AS $$\nDECLARE\n done boolean;\n total integer = 0;\n updated integer = 0;\n\nBEGIN\n SELECT COUNT(*) INTO total FROM repo WHERE stars IS NULL;\n\n RAISE NOTICE 'repo_stars_null_to_zero: updating % rows', total;\n\n done := total = 0;\n\n WHILE NOT done LOOP\n UPDATE repo SET stars = 0\n FROM (\n SELECT id FROM repo\n WHERE stars IS NULL\n LIMIT 10000\n FOR UPDATE SKIP LOCKED\n ) s\n WHERE repo.id = s.id;\n\n COMMIT;\n\n SELECT COUNT(*) = 0 INTO done FROM repo WHERE stars IS NULL LIMIT 1;\n\n updated := updated + 10000;\n\n RAISE NOTICE 'repo_stars_null_to_zero: updated % of % rows', updated, total;\n END LOOP;\nEND\n$$;\n\nCREATE FUNCTION soft_delete_orphan_repo_by_external_service_repos() RETURNS void\n LANGUAGE plpgsql\n AS $$\nBEGIN\n -- When an external service is soft or hard-deleted,\n -- performs a clean up to soft-delete orphan repositories.\n UPDATE\n repo\n SET\n name = soft_deleted_repository_name(name),\n deleted_at = transaction_timestamp()\n WHERE\n deleted_at IS NULL\n AND NOT EXISTS (\n SELECT FROM external_service_repos WHERE repo_id = repo.id\n );\nEND;\n$$;\n\nCREATE FUNCTION soft_delete_user_reference_on_external_service() RETURNS trigger\n LANGUAGE plpgsql\n AS $$\nBEGIN\n -- If a user is soft-deleted, delete every row that references that user\n IF (OLD.deleted_at IS NULL AND NEW.deleted_at IS NOT NULL) THEN\n UPDATE external_services\n SET deleted_at = NOW()\n WHERE namespace_user_id = OLD.id;\n END IF;\n\n RETURN OLD;\nEND;\n$$;\n\nCREATE FUNCTION soft_deleted_repository_name(name text) RETURNS text\n LANGUAGE plpgsql STRICT\n AS $$\nBEGIN\n RETURN 'DELETED-' || extract(epoch from transaction_timestamp()) || '-' || name;\nEND;\n$$;\n\nCREATE FUNCTION versions_insert_row_trigger() RETURNS trigger\n LANGUAGE plpgsql\n AS $$\nBEGIN\n NEW.first_version = NEW.version;\n RETURN NEW;\nEND $$;\n\nCREATE TABLE access_tokens (\n id bigint NOT NULL,\n subject_user_id integer NOT NULL,\n value_sha256 bytea NOT NULL,\n note text NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n last_used_at timestamp with time zone,\n deleted_at timestamp with time zone,\n creator_user_id integer NOT NULL,\n scopes text[] NOT NULL,\n internal boolean DEFAULT false\n);\n\nCREATE SEQUENCE access_tokens_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE access_tokens_id_seq OWNED BY access_tokens.id;\n\nCREATE TABLE batch_changes (\n id bigint NOT NULL,\n name text NOT NULL,\n description text,\n creator_id integer,\n namespace_user_id integer,\n namespace_org_id integer,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n closed_at timestamp with time zone,\n batch_spec_id bigint NOT NULL,\n last_applier_id bigint,\n last_applied_at timestamp with time zone,\n CONSTRAINT batch_changes_has_1_namespace CHECK (((namespace_user_id IS NULL) \u003c\u003e (namespace_org_id IS NULL))),\n CONSTRAINT batch_changes_name_not_blank CHECK ((name \u003c\u003e ''::text))\n);\n\nCREATE SEQUENCE batch_changes_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE batch_changes_id_seq OWNED BY batch_changes.id;\n\nCREATE TABLE batch_changes_site_credentials (\n id bigint NOT NULL,\n external_service_type text NOT NULL,\n external_service_id text NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n credential bytea NOT NULL,\n encryption_key_id text DEFAULT ''::text NOT NULL\n);\n\nCREATE SEQUENCE batch_changes_site_credentials_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE batch_changes_site_credentials_id_seq OWNED BY batch_changes_site_credentials.id;\n\nCREATE TABLE batch_spec_execution_cache_entries (\n id bigint NOT NULL,\n key text NOT NULL,\n value text NOT NULL,\n version integer NOT NULL,\n last_used_at timestamp with time zone,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n user_id integer NOT NULL\n);\n\nCREATE SEQUENCE batch_spec_execution_cache_entries_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE batch_spec_execution_cache_entries_id_seq OWNED BY batch_spec_execution_cache_entries.id;\n\nCREATE TABLE batch_spec_resolution_jobs (\n id bigint NOT NULL,\n batch_spec_id integer,\n state text DEFAULT 'queued'::text,\n failure_message text,\n started_at timestamp with time zone,\n finished_at timestamp with time zone,\n process_after timestamp with time zone,\n num_resets integer DEFAULT 0 NOT NULL,\n num_failures integer DEFAULT 0 NOT NULL,\n execution_logs json[],\n worker_hostname text DEFAULT ''::text NOT NULL,\n last_heartbeat_at timestamp with time zone,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n queued_at timestamp with time zone DEFAULT now()\n);\n\nCREATE SEQUENCE batch_spec_resolution_jobs_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE batch_spec_resolution_jobs_id_seq OWNED BY batch_spec_resolution_jobs.id;\n\nCREATE TABLE batch_spec_workspace_execution_jobs (\n id bigint NOT NULL,\n batch_spec_workspace_id integer,\n state text DEFAULT 'queued'::text,\n failure_message text,\n started_at timestamp with time zone,\n finished_at timestamp with time zone,\n process_after timestamp with time zone,\n num_resets integer DEFAULT 0 NOT NULL,\n num_failures integer DEFAULT 0 NOT NULL,\n execution_logs json[],\n worker_hostname text DEFAULT ''::text NOT NULL,\n last_heartbeat_at timestamp with time zone,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n cancel boolean DEFAULT false NOT NULL,\n access_token_id bigint,\n queued_at timestamp with time zone DEFAULT now()\n);\n\nCREATE SEQUENCE batch_spec_workspace_execution_jobs_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE batch_spec_workspace_execution_jobs_id_seq OWNED BY batch_spec_workspace_execution_jobs.id;\n\nCREATE TABLE batch_spec_workspaces (\n id bigint NOT NULL,\n batch_spec_id integer,\n changeset_spec_ids jsonb DEFAULT '{}'::jsonb,\n repo_id integer,\n branch text NOT NULL,\n commit text NOT NULL,\n path text NOT NULL,\n file_matches text[] NOT NULL,\n only_fetch_workspace boolean DEFAULT false NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n ignored boolean DEFAULT false NOT NULL,\n unsupported boolean DEFAULT false NOT NULL,\n skipped boolean DEFAULT false NOT NULL,\n cached_result_found boolean DEFAULT false NOT NULL,\n step_cache_results jsonb DEFAULT '{}'::jsonb NOT NULL\n);\n\nCREATE SEQUENCE batch_spec_workspaces_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE batch_spec_workspaces_id_seq OWNED BY batch_spec_workspaces.id;\n\nCREATE TABLE batch_specs (\n id bigint NOT NULL,\n rand_id text NOT NULL,\n raw_spec text NOT NULL,\n spec jsonb DEFAULT '{}'::jsonb NOT NULL,\n namespace_user_id integer,\n namespace_org_id integer,\n user_id integer,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n created_from_raw boolean DEFAULT false NOT NULL,\n allow_unsupported boolean DEFAULT false NOT NULL,\n allow_ignored boolean DEFAULT false NOT NULL,\n no_cache boolean DEFAULT false NOT NULL,\n CONSTRAINT batch_specs_has_1_namespace CHECK (((namespace_user_id IS NULL) \u003c\u003e (namespace_org_id IS NULL)))\n);\n\nCREATE SEQUENCE batch_specs_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE batch_specs_id_seq OWNED BY batch_specs.id;\n\nCREATE TABLE changeset_specs (\n id bigint NOT NULL,\n rand_id text NOT NULL,\n spec jsonb DEFAULT '{}'::jsonb NOT NULL,\n batch_spec_id bigint,\n repo_id integer NOT NULL,\n user_id integer,\n diff_stat_added integer,\n diff_stat_changed integer,\n diff_stat_deleted integer,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n head_ref text,\n title text,\n external_id text,\n fork_namespace citext\n);\n\nCREATE TABLE changesets (\n id bigint NOT NULL,\n batch_change_ids jsonb DEFAULT '{}'::jsonb NOT NULL,\n repo_id integer NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n metadata jsonb DEFAULT '{}'::jsonb,\n external_id text,\n external_service_type text NOT NULL,\n external_deleted_at timestamp with time zone,\n external_branch text,\n external_updated_at timestamp with time zone,\n external_state text,\n external_review_state text,\n external_check_state text,\n diff_stat_added integer,\n diff_stat_changed integer,\n diff_stat_deleted integer,\n sync_state jsonb DEFAULT '{}'::jsonb NOT NULL,\n current_spec_id bigint,\n previous_spec_id bigint,\n publication_state text DEFAULT 'UNPUBLISHED'::text,\n owned_by_batch_change_id bigint,\n reconciler_state text DEFAULT 'queued'::text,\n failure_message text,\n started_at timestamp with time zone,\n finished_at timestamp with time zone,\n process_after timestamp with time zone,\n num_resets integer DEFAULT 0 NOT NULL,\n closing boolean DEFAULT false NOT NULL,\n num_failures integer DEFAULT 0 NOT NULL,\n log_contents text,\n execution_logs json[],\n syncer_error text,\n external_title text,\n worker_hostname text DEFAULT ''::text NOT NULL,\n ui_publication_state batch_changes_changeset_ui_publication_state,\n last_heartbeat_at timestamp with time zone,\n external_fork_namespace citext,\n queued_at timestamp with time zone DEFAULT now(),\n CONSTRAINT changesets_batch_change_ids_check CHECK ((jsonb_typeof(batch_change_ids) = 'object'::text)),\n CONSTRAINT changesets_external_id_check CHECK ((external_id \u003c\u003e ''::text)),\n CONSTRAINT changesets_external_service_type_not_blank CHECK ((external_service_type \u003c\u003e ''::text)),\n CONSTRAINT changesets_metadata_check CHECK ((jsonb_typeof(metadata) = 'object'::text)),\n CONSTRAINT external_branch_ref_prefix CHECK ((external_branch ~~ 'refs/heads/%'::text))\n);\n\nCOMMENT ON COLUMN changesets.external_title IS 'Normalized property generated on save using Changeset.Title()';\n\nCREATE TABLE repo (\n id integer NOT NULL,\n name citext NOT NULL,\n description text,\n fork boolean,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone,\n external_id text,\n external_service_type text,\n external_service_id text,\n archived boolean DEFAULT false NOT NULL,\n uri citext,\n deleted_at timestamp with time zone,\n metadata jsonb DEFAULT '{}'::jsonb NOT NULL,\n private boolean DEFAULT false NOT NULL,\n stars integer DEFAULT 0 NOT NULL,\n blocked jsonb,\n CONSTRAINT check_name_nonempty CHECK ((name OPERATOR(\u003c\u003e) ''::citext)),\n CONSTRAINT repo_metadata_check CHECK ((jsonb_typeof(metadata) = 'object'::text))\n);\n\nCREATE VIEW branch_changeset_specs_and_changesets AS\n SELECT changeset_specs.id AS changeset_spec_id,\n COALESCE(changesets.id, (0)::bigint) AS changeset_id,\n changeset_specs.repo_id,\n changeset_specs.batch_spec_id,\n changesets.owned_by_batch_change_id AS owner_batch_change_id,\n repo.name AS repo_name,\n changeset_specs.title AS changeset_name,\n changesets.external_state,\n changesets.publication_state,\n changesets.reconciler_state\n FROM ((changeset_specs\n LEFT JOIN changesets ON (((changesets.repo_id = changeset_specs.repo_id) AND (changesets.current_spec_id IS NOT NULL) AND (EXISTS ( SELECT 1\n FROM changeset_specs changeset_specs_1\n WHERE ((changeset_specs_1.id = changesets.current_spec_id) AND (changeset_specs_1.head_ref = changeset_specs.head_ref)))))))\n JOIN repo ON ((changeset_specs.repo_id = repo.id)))\n WHERE ((changeset_specs.external_id IS NULL) AND (repo.deleted_at IS NULL));\n\nCREATE TABLE changeset_events (\n id bigint NOT NULL,\n changeset_id bigint NOT NULL,\n kind text NOT NULL,\n key text NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n metadata jsonb DEFAULT '{}'::jsonb NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n CONSTRAINT changeset_events_key_check CHECK ((key \u003c\u003e ''::text)),\n CONSTRAINT changeset_events_kind_check CHECK ((kind \u003c\u003e ''::text)),\n CONSTRAINT changeset_events_metadata_check CHECK ((jsonb_typeof(metadata) = 'object'::text))\n);\n\nCREATE SEQUENCE changeset_events_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE changeset_events_id_seq OWNED BY changeset_events.id;\n\nCREATE TABLE changeset_jobs (\n id bigint NOT NULL,\n bulk_group text NOT NULL,\n user_id integer NOT NULL,\n batch_change_id integer NOT NULL,\n changeset_id integer NOT NULL,\n job_type text NOT NULL,\n payload jsonb DEFAULT '{}'::jsonb,\n state text DEFAULT 'queued'::text,\n failure_message text,\n started_at timestamp with time zone,\n finished_at timestamp with time zone,\n process_after timestamp with time zone,\n num_resets integer DEFAULT 0 NOT NULL,\n num_failures integer DEFAULT 0 NOT NULL,\n execution_logs json[],\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n worker_hostname text DEFAULT ''::text NOT NULL,\n last_heartbeat_at timestamp with time zone,\n queued_at timestamp with time zone DEFAULT now(),\n CONSTRAINT changeset_jobs_payload_check CHECK ((jsonb_typeof(payload) = 'object'::text))\n);\n\nCREATE SEQUENCE changeset_jobs_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE changeset_jobs_id_seq OWNED BY changeset_jobs.id;\n\nCREATE SEQUENCE changeset_specs_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE changeset_specs_id_seq OWNED BY changeset_specs.id;\n\nCREATE SEQUENCE changesets_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE changesets_id_seq OWNED BY changesets.id;\n\nCREATE TABLE cm_action_jobs (\n id integer NOT NULL,\n email bigint,\n state text DEFAULT 'queued'::text,\n failure_message text,\n started_at timestamp with time zone,\n finished_at timestamp with time zone,\n process_after timestamp with time zone,\n num_resets integer DEFAULT 0 NOT NULL,\n num_failures integer DEFAULT 0 NOT NULL,\n log_contents text,\n trigger_event integer,\n worker_hostname text DEFAULT ''::text NOT NULL,\n last_heartbeat_at timestamp with time zone,\n execution_logs json[],\n webhook bigint,\n slack_webhook bigint,\n queued_at timestamp with time zone DEFAULT now(),\n CONSTRAINT cm_action_jobs_only_one_action_type CHECK ((((\nCASE\n WHEN (email IS NULL) THEN 0\n ELSE 1\nEND +\nCASE\n WHEN (webhook IS NULL) THEN 0\n ELSE 1\nEND) +\nCASE\n WHEN (slack_webhook IS NULL) THEN 0\n ELSE 1\nEND) = 1))\n);\n\nCOMMENT ON COLUMN cm_action_jobs.email IS 'The ID of the cm_emails action to execute if this is an email job. Mutually exclusive with webhook and slack_webhook';\n\nCOMMENT ON COLUMN cm_action_jobs.webhook IS 'The ID of the cm_webhooks action to execute if this is a webhook job. Mutually exclusive with email and slack_webhook';\n\nCOMMENT ON COLUMN cm_action_jobs.slack_webhook IS 'The ID of the cm_slack_webhook action to execute if this is a slack webhook job. Mutually exclusive with email and webhook';\n\nCOMMENT ON CONSTRAINT cm_action_jobs_only_one_action_type ON cm_action_jobs IS 'Constrains that each queued code monitor action has exactly one action type';\n\nCREATE SEQUENCE cm_action_jobs_id_seq\n AS integer\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE cm_action_jobs_id_seq OWNED BY cm_action_jobs.id;\n\nCREATE TABLE cm_emails (\n id bigint NOT NULL,\n monitor bigint NOT NULL,\n enabled boolean NOT NULL,\n priority cm_email_priority NOT NULL,\n header text NOT NULL,\n created_by integer NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n changed_by integer NOT NULL,\n changed_at timestamp with time zone DEFAULT now() NOT NULL,\n include_results boolean DEFAULT false NOT NULL\n);\n\nCREATE SEQUENCE cm_emails_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE cm_emails_id_seq OWNED BY cm_emails.id;\n\nCREATE TABLE cm_last_searched (\n monitor_id bigint NOT NULL,\n args_hash bigint NOT NULL,\n commit_oids text[] NOT NULL\n);\n\nCOMMENT ON TABLE cm_last_searched IS 'The last searched commit hashes for the given code monitor and unique set of search arguments';\n\nCOMMENT ON COLUMN cm_last_searched.args_hash IS 'A unique hash of the gitserver search arguments to identify this search job';\n\nCOMMENT ON COLUMN cm_last_searched.commit_oids IS 'The set of commit OIDs that was previously successfully searched and should be excluded on the next run';\n\nCREATE TABLE cm_monitors (\n id bigint NOT NULL,\n created_by integer NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n description text NOT NULL,\n changed_at timestamp with time zone DEFAULT now() NOT NULL,\n changed_by integer NOT NULL,\n enabled boolean DEFAULT true NOT NULL,\n namespace_user_id integer NOT NULL,\n namespace_org_id integer\n);\n\nCOMMENT ON COLUMN cm_monitors.namespace_org_id IS 'DEPRECATED: code monitors cannot be owned by an org';\n\nCREATE SEQUENCE cm_monitors_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE cm_monitors_id_seq OWNED BY cm_monitors.id;\n\nCREATE TABLE cm_queries (\n id bigint NOT NULL,\n monitor bigint NOT NULL,\n query text NOT NULL,\n created_by integer NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n changed_by integer NOT NULL,\n changed_at timestamp with time zone DEFAULT now() NOT NULL,\n next_run timestamp with time zone DEFAULT now(),\n latest_result timestamp with time zone\n);\n\nCREATE SEQUENCE cm_queries_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE cm_queries_id_seq OWNED BY cm_queries.id;\n\nCREATE TABLE cm_recipients (\n id bigint NOT NULL,\n email bigint NOT NULL,\n namespace_user_id integer,\n namespace_org_id integer\n);\n\nCREATE SEQUENCE cm_recipients_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE cm_recipients_id_seq OWNED BY cm_recipients.id;\n\nCREATE TABLE cm_slack_webhooks (\n id bigint NOT NULL,\n monitor bigint NOT NULL,\n url text NOT NULL,\n enabled boolean NOT NULL,\n created_by integer NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n changed_by integer NOT NULL,\n changed_at timestamp with time zone DEFAULT now() NOT NULL,\n include_results boolean DEFAULT false NOT NULL\n);\n\nCOMMENT ON TABLE cm_slack_webhooks IS 'Slack webhook actions configured on code monitors';\n\nCOMMENT ON COLUMN cm_slack_webhooks.monitor IS 'The code monitor that the action is defined on';\n\nCOMMENT ON COLUMN cm_slack_webhooks.url IS 'The Slack webhook URL we send the code monitor event to';\n\nCREATE SEQUENCE cm_slack_webhooks_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE cm_slack_webhooks_id_seq OWNED BY cm_slack_webhooks.id;\n\nCREATE TABLE cm_trigger_jobs (\n id integer NOT NULL,\n query bigint NOT NULL,\n state text DEFAULT 'queued'::text,\n failure_message text,\n started_at timestamp with time zone,\n finished_at timestamp with time zone,\n process_after timestamp with time zone,\n num_resets integer DEFAULT 0 NOT NULL,\n num_failures integer DEFAULT 0 NOT NULL,\n log_contents text,\n query_string text,\n results boolean,\n num_results integer,\n worker_hostname text DEFAULT ''::text NOT NULL,\n last_heartbeat_at timestamp with time zone,\n execution_logs json[],\n search_results jsonb,\n queued_at timestamp with time zone DEFAULT now(),\n CONSTRAINT search_results_is_array CHECK ((jsonb_typeof(search_results) = 'array'::text))\n);\n\nCOMMENT ON COLUMN cm_trigger_jobs.results IS 'DEPRECATED: replaced by len(search_results) \u003e 0. Can be removed after version 3.37 release cut';\n\nCOMMENT ON COLUMN cm_trigger_jobs.num_results IS 'DEPRECATED: replaced by len(search_results). Can be removed after version 3.37 release cut';\n\nCREATE SEQUENCE cm_trigger_jobs_id_seq\n AS integer\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE cm_trigger_jobs_id_seq OWNED BY cm_trigger_jobs.id;\n\nCREATE TABLE cm_webhooks (\n id bigint NOT NULL,\n monitor bigint NOT NULL,\n url text NOT NULL,\n enabled boolean NOT NULL,\n created_by integer NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n changed_by integer NOT NULL,\n changed_at timestamp with time zone DEFAULT now() NOT NULL,\n include_results boolean DEFAULT false NOT NULL\n);\n\nCOMMENT ON TABLE cm_webhooks IS 'Webhook actions configured on code monitors';\n\nCOMMENT ON COLUMN cm_webhooks.monitor IS 'The code monitor that the action is defined on';\n\nCOMMENT ON COLUMN cm_webhooks.url IS 'The webhook URL we send the code monitor event to';\n\nCOMMENT ON COLUMN cm_webhooks.enabled IS 'Whether this Slack webhook action is enabled. When not enabled, the action will not be run when its code monitor generates events';\n\nCREATE SEQUENCE cm_webhooks_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE cm_webhooks_id_seq OWNED BY cm_webhooks.id;\n\nCREATE TABLE critical_and_site_config (\n id integer NOT NULL,\n type critical_or_site NOT NULL,\n contents text NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL\n);\n\nCREATE SEQUENCE critical_and_site_config_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE critical_and_site_config_id_seq OWNED BY critical_and_site_config.id;\n\nCREATE TABLE discussion_comments (\n id bigint NOT NULL,\n thread_id bigint NOT NULL,\n author_user_id integer NOT NULL,\n contents text NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n deleted_at timestamp with time zone,\n reports text[] DEFAULT '{}'::text[] NOT NULL\n);\n\nCREATE SEQUENCE discussion_comments_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE discussion_comments_id_seq OWNED BY discussion_comments.id;\n\nCREATE TABLE discussion_mail_reply_tokens (\n token text NOT NULL,\n user_id integer NOT NULL,\n thread_id bigint NOT NULL,\n deleted_at timestamp with time zone\n);\n\nCREATE TABLE discussion_threads (\n id bigint NOT NULL,\n author_user_id integer NOT NULL,\n title text,\n target_repo_id bigint,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n archived_at timestamp with time zone,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n deleted_at timestamp with time zone\n);\n\nCREATE SEQUENCE discussion_threads_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE discussion_threads_id_seq OWNED BY discussion_threads.id;\n\nCREATE TABLE discussion_threads_target_repo (\n id bigint NOT NULL,\n thread_id bigint NOT NULL,\n repo_id integer NOT NULL,\n path text,\n branch text,\n revision text,\n start_line integer,\n end_line integer,\n start_character integer,\n end_character integer,\n lines_before text,\n lines text,\n lines_after text\n);\n\nCREATE SEQUENCE discussion_threads_target_repo_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE discussion_threads_target_repo_id_seq OWNED BY discussion_threads_target_repo.id;\n\nCREATE TABLE event_logs (\n id bigint NOT NULL,\n name text NOT NULL,\n url text NOT NULL,\n user_id integer NOT NULL,\n anonymous_user_id text NOT NULL,\n source text NOT NULL,\n argument jsonb NOT NULL,\n version text NOT NULL,\n \"timestamp\" timestamp with time zone NOT NULL,\n feature_flags jsonb,\n cohort_id date,\n public_argument jsonb DEFAULT '{}'::jsonb NOT NULL,\n CONSTRAINT event_logs_check_has_user CHECK ((((user_id = 0) AND (anonymous_user_id \u003c\u003e ''::text)) OR ((user_id \u003c\u003e 0) AND (anonymous_user_id = ''::text)) OR ((user_id \u003c\u003e 0) AND (anonymous_user_id \u003c\u003e ''::text)))),\n CONSTRAINT event_logs_check_name_not_empty CHECK ((name \u003c\u003e ''::text)),\n CONSTRAINT event_logs_check_source_not_empty CHECK ((source \u003c\u003e ''::text)),\n CONSTRAINT event_logs_check_version_not_empty CHECK ((version \u003c\u003e ''::text))\n);\n\nCREATE SEQUENCE event_logs_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE event_logs_id_seq OWNED BY event_logs.id;\n\nCREATE TABLE executor_heartbeats (\n id integer NOT NULL,\n hostname text NOT NULL,\n queue_name text NOT NULL,\n os text NOT NULL,\n architecture text NOT NULL,\n docker_version text NOT NULL,\n executor_version text NOT NULL,\n git_version text NOT NULL,\n ignite_version text NOT NULL,\n src_cli_version text NOT NULL,\n first_seen_at timestamp with time zone DEFAULT now() NOT NULL,\n last_seen_at timestamp with time zone DEFAULT now() NOT NULL\n);\n\nCOMMENT ON TABLE executor_heartbeats IS 'Tracks the most recent activity of executors attached to this Sourcegraph instance.';\n\nCOMMENT ON COLUMN executor_heartbeats.hostname IS 'The uniquely identifying name of the executor.';\n\nCOMMENT ON COLUMN executor_heartbeats.queue_name IS 'The queue name that the executor polls for work.';\n\nCOMMENT ON COLUMN executor_heartbeats.os IS 'The operating system running the executor.';\n\nCOMMENT ON COLUMN executor_heartbeats.architecture IS 'The machine architure running the executor.';\n\nCOMMENT ON COLUMN executor_heartbeats.docker_version IS 'The version of Docker used by the executor.';\n\nCOMMENT ON COLUMN executor_heartbeats.executor_version IS 'The version of the executor.';\n\nCOMMENT ON COLUMN executor_heartbeats.git_version IS 'The version of Git used by the executor.';\n\nCOMMENT ON COLUMN executor_heartbeats.ignite_version IS 'The version of Ignite used by the executor.';\n\nCOMMENT ON COLUMN executor_heartbeats.src_cli_version IS 'The version of src-cli used by the executor.';\n\nCOMMENT ON COLUMN executor_heartbeats.first_seen_at IS 'The first time a heartbeat from the executor was received.';\n\nCOMMENT ON COLUMN executor_heartbeats.last_seen_at IS 'The last time a heartbeat from the executor was received.';\n\nCREATE SEQUENCE executor_heartbeats_id_seq\n AS integer\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE executor_heartbeats_id_seq OWNED BY executor_heartbeats.id;\n\nCREATE TABLE external_service_repos (\n external_service_id bigint NOT NULL,\n repo_id integer NOT NULL,\n clone_url text NOT NULL,\n user_id integer,\n org_id integer,\n created_at timestamp with time zone DEFAULT transaction_timestamp() NOT NULL\n);\n\nCREATE SEQUENCE external_service_sync_jobs_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nCREATE TABLE external_service_sync_jobs (\n id integer DEFAULT nextval('external_service_sync_jobs_id_seq'::regclass) NOT NULL,\n state text DEFAULT 'queued'::text NOT NULL,\n failure_message text,\n started_at timestamp with time zone,\n finished_at timestamp with time zone,\n process_after timestamp with time zone,\n num_resets integer DEFAULT 0 NOT NULL,\n external_service_id bigint,\n num_failures integer DEFAULT 0 NOT NULL,\n log_contents text,\n execution_logs json[],\n worker_hostname text DEFAULT ''::text NOT NULL,\n last_heartbeat_at timestamp with time zone,\n queued_at timestamp with time zone DEFAULT now()\n);\n\nCREATE TABLE external_services (\n id bigint NOT NULL,\n kind text NOT NULL,\n display_name text NOT NULL,\n config text NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n deleted_at timestamp with time zone,\n last_sync_at timestamp with time zone,\n next_sync_at timestamp with time zone,\n namespace_user_id integer,\n unrestricted boolean DEFAULT false NOT NULL,\n cloud_default boolean DEFAULT false NOT NULL,\n encryption_key_id text DEFAULT ''::text NOT NULL,\n namespace_org_id integer,\n has_webhooks boolean,\n token_expires_at timestamp with time zone,\n CONSTRAINT check_non_empty_config CHECK ((btrim(config) \u003c\u003e ''::text)),\n CONSTRAINT external_services_max_1_namespace CHECK ((((namespace_user_id IS NULL) AND (namespace_org_id IS NULL)) OR ((namespace_user_id IS NULL) \u003c\u003e (namespace_org_id IS NULL))))\n);\n\nCREATE VIEW external_service_sync_jobs_with_next_sync_at AS\n SELECT j.id,\n j.state,\n j.failure_message,\n j.queued_at,\n j.started_at,\n j.finished_at,\n j.process_after,\n j.num_resets,\n j.num_failures,\n j.execution_logs,\n j.external_service_id,\n e.next_sync_at\n FROM (external_services e\n JOIN external_service_sync_jobs j ON ((e.id = j.external_service_id)));\n\nCREATE SEQUENCE external_services_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE external_services_id_seq OWNED BY external_services.id;\n\nCREATE TABLE feature_flag_overrides (\n namespace_org_id integer,\n namespace_user_id integer,\n flag_name text NOT NULL,\n flag_value boolean NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n deleted_at timestamp with time zone,\n CONSTRAINT feature_flag_overrides_has_org_or_user_id CHECK (((namespace_org_id IS NOT NULL) OR (namespace_user_id IS NOT NULL)))\n);\n\nCREATE TABLE feature_flags (\n flag_name text NOT NULL,\n flag_type feature_flag_type NOT NULL,\n bool_value boolean,\n rollout integer,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n deleted_at timestamp with time zone,\n CONSTRAINT feature_flags_rollout_check CHECK (((rollout \u003e= 0) AND (rollout \u003c= 10000))),\n CONSTRAINT required_bool_fields CHECK ((1 =\nCASE\n WHEN ((flag_type = 'bool'::feature_flag_type) AND (bool_value IS NULL)) THEN 0\n WHEN ((flag_type \u003c\u003e 'bool'::feature_flag_type) AND (bool_value IS NOT NULL)) THEN 0\n ELSE 1\nEND)),\n CONSTRAINT required_rollout_fields CHECK ((1 =\nCASE\n WHEN ((flag_type = 'rollout'::feature_flag_type) AND (rollout IS NULL)) THEN 0\n WHEN ((flag_type \u003c\u003e 'rollout'::feature_flag_type) AND (rollout IS NOT NULL)) THEN 0\n ELSE 1\nEND))\n);\n\nCOMMENT ON COLUMN feature_flags.bool_value IS 'Bool value only defined when flag_type is bool';\n\nCOMMENT ON COLUMN feature_flags.rollout IS 'Rollout only defined when flag_type is rollout. Increments of 0.01%';\n\nCOMMENT ON CONSTRAINT required_bool_fields ON feature_flags IS 'Checks that bool_value is set IFF flag_type = bool';\n\nCOMMENT ON CONSTRAINT required_rollout_fields ON feature_flags IS 'Checks that rollout is set IFF flag_type = rollout';\n\nCREATE TABLE gitserver_localclone_jobs (\n id integer NOT NULL,\n state text DEFAULT 'queued'::text,\n failure_message text,\n started_at timestamp with time zone,\n finished_at timestamp with time zone,\n process_after timestamp with time zone,\n num_resets integer DEFAULT 0 NOT NULL,\n num_failures integer DEFAULT 0 NOT NULL,\n last_heartbeat_at timestamp with time zone,\n execution_logs json[],\n worker_hostname text DEFAULT ''::text NOT NULL,\n repo_id integer NOT NULL,\n source_hostname text NOT NULL,\n dest_hostname text NOT NULL,\n delete_source boolean DEFAULT false NOT NULL,\n queued_at timestamp with time zone DEFAULT now()\n);\n\nCREATE SEQUENCE gitserver_localclone_jobs_id_seq\n AS integer\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE gitserver_localclone_jobs_id_seq OWNED BY gitserver_localclone_jobs.id;\n\nCREATE VIEW gitserver_localclone_jobs_with_repo_name AS\n SELECT glj.id,\n glj.state,\n glj.failure_message,\n glj.started_at,\n glj.finished_at,\n glj.process_after,\n glj.num_resets,\n glj.num_failures,\n glj.last_heartbeat_at,\n glj.execution_logs,\n glj.worker_hostname,\n glj.repo_id,\n glj.source_hostname,\n glj.dest_hostname,\n glj.delete_source,\n glj.queued_at,\n r.name AS repo_name\n FROM (gitserver_localclone_jobs glj\n JOIN repo r ON ((r.id = glj.repo_id)));\n\nCREATE TABLE gitserver_repos (\n repo_id integer NOT NULL,\n clone_status text DEFAULT 'not_cloned'::text NOT NULL,\n shard_id text NOT NULL,\n last_error text,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n last_fetched timestamp with time zone DEFAULT now() NOT NULL,\n last_changed timestamp with time zone DEFAULT now() NOT NULL,\n repo_size_bytes bigint\n);\n\nCREATE TABLE global_state (\n site_id uuid NOT NULL,\n initialized boolean DEFAULT false NOT NULL\n);\n\nCREATE TABLE insights_query_runner_jobs (\n id integer NOT NULL,\n series_id text NOT NULL,\n search_query text NOT NULL,\n state text DEFAULT 'queued'::text,\n failure_message text,\n started_at timestamp with time zone,\n finished_at timestamp with time zone,\n process_after timestamp with time zone,\n num_resets integer DEFAULT 0 NOT NULL,\n num_failures integer DEFAULT 0 NOT NULL,\n execution_logs json[],\n record_time timestamp with time zone,\n worker_hostname text DEFAULT ''::text NOT NULL,\n last_heartbeat_at timestamp with time zone,\n priority integer DEFAULT 1 NOT NULL,\n cost integer DEFAULT 500 NOT NULL,\n persist_mode persistmode DEFAULT 'record'::persistmode NOT NULL,\n queued_at timestamp with time zone DEFAULT now()\n);\n\nCOMMENT ON TABLE insights_query_runner_jobs IS 'See [enterprise/internal/insights/background/queryrunner/worker.go:Job](https://sourcegraph.com/search?q=repo:%5Egithub%5C.com/sourcegraph/sourcegraph%24+file:enterprise/internal/insights/background/queryrunner/worker.go+type+Job\u0026patternType=literal)';\n\nCOMMENT ON COLUMN insights_query_runner_jobs.priority IS 'Integer representing a category of priority for this query. Priority in this context is ambiguously defined for consumers to decide an interpretation.';\n\nCOMMENT ON COLUMN insights_query_runner_jobs.cost IS 'Integer representing a cost approximation of executing this search query.';\n\nCOMMENT ON COLUMN insights_query_runner_jobs.persist_mode IS 'The persistence level for this query. This value will determine the lifecycle of the resulting value.';\n\nCREATE TABLE insights_query_runner_jobs_dependencies (\n id integer NOT NULL,\n job_id integer NOT NULL,\n recording_time timestamp without time zone NOT NULL\n);\n\nCOMMENT ON TABLE insights_query_runner_jobs_dependencies IS 'Stores data points for a code insight that do not need to be queried directly, but depend on the result of a query at a different point';\n\nCOMMENT ON COLUMN insights_query_runner_jobs_dependencies.job_id IS 'Foreign key to the job that owns this record.';\n\nCOMMENT ON COLUMN insights_query_runner_jobs_dependencies.recording_time IS 'The time for which this dependency should be recorded at using the parents value.';\n\nCREATE SEQUENCE insights_query_runner_jobs_dependencies_id_seq\n AS integer\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE insights_query_runner_jobs_dependencies_id_seq OWNED BY insights_query_runner_jobs_dependencies.id;\n\nCREATE SEQUENCE insights_query_runner_jobs_id_seq\n AS integer\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE insights_query_runner_jobs_id_seq OWNED BY insights_query_runner_jobs.id;\n\nCREATE TABLE insights_settings_migration_jobs (\n id integer NOT NULL,\n user_id integer,\n org_id integer,\n global boolean,\n settings_id integer NOT NULL,\n total_insights integer DEFAULT 0 NOT NULL,\n migrated_insights integer DEFAULT 0 NOT NULL,\n total_dashboards integer DEFAULT 0 NOT NULL,\n migrated_dashboards integer DEFAULT 0 NOT NULL,\n runs integer DEFAULT 0 NOT NULL,\n completed_at timestamp without time zone\n);\n\nCREATE SEQUENCE insights_settings_migration_jobs_id_seq\n AS integer\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE insights_settings_migration_jobs_id_seq OWNED BY insights_settings_migration_jobs.id;\n\nCREATE TABLE lsif_configuration_policies (\n id integer NOT NULL,\n repository_id integer,\n name text,\n type text NOT NULL,\n pattern text NOT NULL,\n retention_enabled boolean NOT NULL,\n retention_duration_hours integer,\n retain_intermediate_commits boolean NOT NULL,\n indexing_enabled boolean NOT NULL,\n index_commit_max_age_hours integer,\n index_intermediate_commits boolean NOT NULL,\n protected boolean DEFAULT false NOT NULL,\n repository_patterns text[],\n last_resolved_at timestamp with time zone\n);\n\nCOMMENT ON COLUMN lsif_configuration_policies.repository_id IS 'The identifier of the repository to which this configuration policy applies. If absent, this policy is applied globally.';\n\nCOMMENT ON COLUMN lsif_configuration_policies.type IS 'The type of Git object (e.g., COMMIT, BRANCH, TAG).';\n\nCOMMENT ON COLUMN lsif_configuration_policies.pattern IS 'A pattern used to match` names of the associated Git object type.';\n\nCOMMENT ON COLUMN lsif_configuration_policies.retention_enabled IS 'Whether or not this configuration policy affects data retention rules.';\n\nCOMMENT ON COLUMN lsif_configuration_policies.retention_duration_hours IS 'The max age of data retained by this configuration policy. If null, the age is unbounded.';\n\nCOMMENT ON COLUMN lsif_configuration_policies.retain_intermediate_commits IS 'If the matching Git object is a branch, setting this value to true will also retain all data used to resolve queries for any commit on the matching branches. Setting this value to false will only consider the tip of the branch.';\n\nCOMMENT ON COLUMN lsif_configuration_policies.indexing_enabled IS 'Whether or not this configuration policy affects auto-indexing schedules.';\n\nCOMMENT ON COLUMN lsif_configuration_policies.index_commit_max_age_hours IS 'The max age of commits indexed by this configuration policy. If null, the age is unbounded.';\n\nCOMMENT ON COLUMN lsif_configuration_policies.index_intermediate_commits IS 'If the matching Git object is a branch, setting this value to true will also index all commits on the matching branches. Setting this value to false will only consider the tip of the branch.';\n\nCOMMENT ON COLUMN lsif_configuration_policies.protected IS 'Whether or not this configuration policy is protected from modification of its data retention behavior (except for duration).';\n\nCOMMENT ON COLUMN lsif_configuration_policies.repository_patterns IS 'The name pattern matching repositories to which this configuration policy applies. If absent, all repositories are matched.';\n\nCREATE SEQUENCE lsif_configuration_policies_id_seq\n AS integer\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE lsif_configuration_policies_id_seq OWNED BY lsif_configuration_policies.id;\n\nCREATE TABLE lsif_configuration_policies_repository_pattern_lookup (\n policy_id integer NOT NULL,\n repo_id integer NOT NULL\n);\n\nCOMMENT ON TABLE lsif_configuration_policies_repository_pattern_lookup IS 'A lookup table to get all the repository patterns by repository id that apply to a configuration policy.';\n\nCOMMENT ON COLUMN lsif_configuration_policies_repository_pattern_lookup.policy_id IS 'The policy identifier associated with the repository.';\n\nCOMMENT ON COLUMN lsif_configuration_policies_repository_pattern_lookup.repo_id IS 'The repository identifier associated with the policy.';\n\nCREATE TABLE lsif_dependency_indexing_jobs (\n id integer NOT NULL,\n state text DEFAULT 'queued'::text NOT NULL,\n failure_message text,\n queued_at timestamp with time zone DEFAULT now() NOT NULL,\n started_at timestamp with time zone,\n finished_at timestamp with time zone,\n process_after timestamp with time zone,\n num_resets integer DEFAULT 0 NOT NULL,\n num_failures integer DEFAULT 0 NOT NULL,\n execution_logs json[],\n last_heartbeat_at timestamp with time zone,\n worker_hostname text DEFAULT ''::text NOT NULL,\n upload_id integer,\n external_service_kind text DEFAULT ''::text NOT NULL,\n external_service_sync timestamp with time zone\n);\n\nCOMMENT ON COLUMN lsif_dependency_indexing_jobs.external_service_kind IS 'Filter the external services for this kind to wait to have synced. If empty, external_service_sync is ignored and no external services are polled for their last sync time.';\n\nCOMMENT ON COLUMN lsif_dependency_indexing_jobs.external_service_sync IS 'The sync time after which external services of the given kind will have synced/created any repositories referenced by the LSIF upload that are resolvable.';\n\nCREATE TABLE lsif_dependency_syncing_jobs (\n id integer NOT NULL,\n state text DEFAULT 'queued'::text NOT NULL,\n failure_message text,\n queued_at timestamp with time zone DEFAULT now() NOT NULL,\n started_at timestamp with time zone,\n finished_at timestamp with time zone,\n process_after timestamp with time zone,\n num_resets integer DEFAULT 0 NOT NULL,\n num_failures integer DEFAULT 0 NOT NULL,\n execution_logs json[],\n upload_id integer,\n worker_hostname text DEFAULT ''::text NOT NULL,\n last_heartbeat_at timestamp with time zone\n);\n\nCOMMENT ON TABLE lsif_dependency_syncing_jobs IS 'Tracks jobs that scan imports of indexes to schedule auto-index jobs.';\n\nCOMMENT ON COLUMN lsif_dependency_syncing_jobs.upload_id IS 'The identifier of the triggering upload record.';\n\nCREATE SEQUENCE lsif_dependency_indexing_jobs_id_seq\n AS integer\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE lsif_dependency_indexing_jobs_id_seq OWNED BY lsif_dependency_syncing_jobs.id;\n\nCREATE SEQUENCE lsif_dependency_indexing_jobs_id_seq1\n AS integer\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE lsif_dependency_indexing_jobs_id_seq1 OWNED BY lsif_dependency_indexing_jobs.id;\n\nCREATE TABLE lsif_dependency_repos (\n id bigint NOT NULL,\n name text NOT NULL,\n version text NOT NULL,\n scheme text NOT NULL\n);\n\nCREATE SEQUENCE lsif_dependency_repos_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE lsif_dependency_repos_id_seq OWNED BY lsif_dependency_repos.id;\n\nCREATE TABLE lsif_dirty_repositories (\n repository_id integer NOT NULL,\n dirty_token integer NOT NULL,\n update_token integer NOT NULL,\n updated_at timestamp with time zone\n);\n\nCOMMENT ON TABLE lsif_dirty_repositories IS 'Stores whether or not the nearest upload data for a repository is out of date (when update_token \u003e dirty_token).';\n\nCOMMENT ON COLUMN lsif_dirty_repositories.dirty_token IS 'Set to the value of update_token visible to the transaction that updates the commit graph. Updates of dirty_token during this time will cause a second update.';\n\nCOMMENT ON COLUMN lsif_dirty_repositories.update_token IS 'This value is incremented on each request to update the commit graph for the repository.';\n\nCOMMENT ON COLUMN lsif_dirty_repositories.updated_at IS 'The time the update_token value was last updated.';\n\nCREATE TABLE lsif_uploads (\n id integer NOT NULL,\n commit text NOT NULL,\n root text DEFAULT ''::text NOT NULL,\n uploaded_at timestamp with time zone DEFAULT now() NOT NULL,\n state text DEFAULT 'queued'::text NOT NULL,\n failure_message text,\n started_at timestamp with time zone,\n finished_at timestamp with time zone,\n repository_id integer NOT NULL,\n indexer text NOT NULL,\n num_parts integer NOT NULL,\n uploaded_parts integer[] NOT NULL,\n process_after timestamp with time zone,\n num_resets integer DEFAULT 0 NOT NULL,\n upload_size bigint,\n num_failures integer DEFAULT 0 NOT NULL,\n associated_index_id bigint,\n committed_at timestamp with time zone,\n commit_last_checked_at timestamp with time zone,\n worker_hostname text DEFAULT ''::text NOT NULL,\n last_heartbeat_at timestamp with time zone,\n execution_logs json[],\n num_references integer,\n expired boolean DEFAULT false NOT NULL,\n last_retention_scan_at timestamp with time zone,\n reference_count integer,\n indexer_version text,\n queued_at timestamp with time zone,\n CONSTRAINT lsif_uploads_commit_valid_chars CHECK ((commit ~ '^[a-z0-9]{40}$'::text))\n);\n\nCOMMENT ON TABLE lsif_uploads IS 'Stores metadata about an LSIF index uploaded by a user.';\n\nCOMMENT ON COLUMN lsif_uploads.id IS 'Used as a logical foreign key with the (disjoint) codeintel database.';\n\nCOMMENT ON COLUMN lsif_uploads.commit IS 'A 40-char revhash. Note that this commit may not be resolvable in the future.';\n\nCOMMENT ON COLUMN lsif_uploads.root IS 'The path for which the index can resolve code intelligence relative to the repository root.';\n\nCOMMENT ON COLUMN lsif_uploads.indexer IS 'The name of the indexer that produced the index file. If not supplied by the user it will be pulled from the index metadata.';\n\nCOMMENT ON COLUMN lsif_uploads.num_parts IS 'The number of parts src-cli split the upload file into.';\n\nCOMMENT ON COLUMN lsif_uploads.uploaded_parts IS 'The index of parts that have been successfully uploaded.';\n\nCOMMENT ON COLUMN lsif_uploads.upload_size IS 'The size of the index file (in bytes).';\n\nCOMMENT ON COLUMN lsif_uploads.num_references IS 'Deprecated in favor of reference_count.';\n\nCOMMENT ON COLUMN lsif_uploads.expired IS 'Whether or not this upload data is no longer protected by any data retention policy.';\n\nCOMMENT ON COLUMN lsif_uploads.last_retention_scan_at IS 'The last time this upload was checked against data retention policies.';\n\nCOMMENT ON COLUMN lsif_uploads.reference_count IS 'The number of references to this upload data from other upload records (via lsif_references).';\n\nCOMMENT ON COLUMN lsif_uploads.indexer_version IS 'The version of the indexer that produced the index file. If not supplied by the user it will be pulled from the index metadata.';\n\nCREATE VIEW lsif_dumps AS\n SELECT u.id,\n u.commit,\n u.root,\n u.queued_at,\n u.uploaded_at,\n u.state,\n u.failure_message,\n u.started_at,\n u.finished_at,\n u.repository_id,\n u.indexer,\n u.indexer_version,\n u.num_parts,\n u.uploaded_parts,\n u.process_after,\n u.num_resets,\n u.upload_size,\n u.num_failures,\n u.associated_index_id,\n u.expired,\n u.last_retention_scan_at,\n u.finished_at AS processed_at\n FROM lsif_uploads u\n WHERE ((u.state = 'completed'::text) OR (u.state = 'deleting'::text));\n\nCREATE SEQUENCE lsif_dumps_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE lsif_dumps_id_seq OWNED BY lsif_uploads.id;\n\nCREATE VIEW lsif_dumps_with_repository_name AS\n SELECT u.id,\n u.commit,\n u.root,\n u.queued_at,\n u.uploaded_at,\n u.state,\n u.failure_message,\n u.started_at,\n u.finished_at,\n u.repository_id,\n u.indexer,\n u.indexer_version,\n u.num_parts,\n u.uploaded_parts,\n u.process_after,\n u.num_resets,\n u.upload_size,\n u.num_failures,\n u.associated_index_id,\n u.expired,\n u.last_retention_scan_at,\n u.processed_at,\n r.name AS repository_name\n FROM (lsif_dumps u\n JOIN repo r ON ((r.id = u.repository_id)))\n WHERE (r.deleted_at IS NULL);\n\nCREATE TABLE lsif_index_configuration (\n id bigint NOT NULL,\n repository_id integer NOT NULL,\n data bytea NOT NULL,\n autoindex_enabled boolean DEFAULT true NOT NULL\n);\n\nCOMMENT ON TABLE lsif_index_configuration IS 'Stores the configuration used for code intel index jobs for a repository.';\n\nCOMMENT ON COLUMN lsif_index_configuration.data IS 'The raw user-supplied [configuration](https://sourcegraph.com/github.com/sourcegraph/sourcegraph@3.23/-/blob/enterprise/internal/codeintel/autoindex/config/types.go#L3:6) (encoded in JSONC).';\n\nCOMMENT ON COLUMN lsif_index_configuration.autoindex_enabled IS 'Whether or not auto-indexing should be attempted on this repo. Index jobs may be inferred from the repository contents if data is empty.';\n\nCREATE SEQUENCE lsif_index_configuration_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE lsif_index_configuration_id_seq OWNED BY lsif_index_configuration.id;\n\nCREATE TABLE lsif_indexes (\n id bigint NOT NULL,\n commit text NOT NULL,\n queued_at timestamp with time zone DEFAULT now() NOT NULL,\n state text DEFAULT 'queued'::text NOT NULL,\n failure_message text,\n started_at timestamp with time zone,\n finished_at timestamp with time zone,\n repository_id integer NOT NULL,\n process_after timestamp with time zone,\n num_resets integer DEFAULT 0 NOT NULL,\n num_failures integer DEFAULT 0 NOT NULL,\n docker_steps jsonb[] NOT NULL,\n root text NOT NULL,\n indexer text NOT NULL,\n indexer_args text[] NOT NULL,\n outfile text NOT NULL,\n log_contents text,\n execution_logs json[],\n local_steps text[] NOT NULL,\n commit_last_checked_at timestamp with time zone,\n worker_hostname text DEFAULT ''::text NOT NULL,\n last_heartbeat_at timestamp with time zone,\n CONSTRAINT lsif_uploads_commit_valid_chars CHECK ((commit ~ '^[a-z0-9]{40}$'::text))\n);\n\nCOMMENT ON TABLE lsif_indexes IS 'Stores metadata about a code intel index job.';\n\nCOMMENT ON COLUMN lsif_indexes.commit IS 'A 40-char revhash. Note that this commit may not be resolvable in the future.';\n\nCOMMENT ON COLUMN lsif_indexes.docker_steps IS 'An array of pre-index [steps](https://sourcegraph.com/github.com/sourcegraph/sourcegraph@3.23/-/blob/enterprise/internal/codeintel/stores/dbstore/docker_step.go#L9:6) to run.';\n\nCOMMENT ON COLUMN lsif_indexes.root IS 'The working directory of the indexer image relative to the repository root.';\n\nCOMMENT ON COLUMN lsif_indexes.indexer IS 'The docker image used to run the index command (e.g. sourcegraph/lsif-go).';\n\nCOMMENT ON COLUMN lsif_indexes.indexer_args IS 'The command run inside the indexer image to produce the index file (e.g. [''lsif-node'', ''-p'', ''.''])';\n\nCOMMENT ON COLUMN lsif_indexes.outfile IS 'The path to the index file produced by the index command relative to the working directory.';\n\nCOMMENT ON COLUMN lsif_indexes.log_contents IS '**Column deprecated in favor of execution_logs.**';\n\nCOMMENT ON COLUMN lsif_indexes.execution_logs IS 'An array of [log entries](https://sourcegraph.com/github.com/sourcegraph/sourcegraph@3.23/-/blob/internal/workerutil/store.go#L48:6) (encoded as JSON) from the most recent execution.';\n\nCOMMENT ON COLUMN lsif_indexes.local_steps IS 'A list of commands to run inside the indexer image prior to running the indexer command.';\n\nCREATE SEQUENCE lsif_indexes_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE lsif_indexes_id_seq OWNED BY lsif_indexes.id;\n\nCREATE VIEW lsif_indexes_with_repository_name AS\n SELECT u.id,\n u.commit,\n u.queued_at,\n u.state,\n u.failure_message,\n u.started_at,\n u.finished_at,\n u.repository_id,\n u.process_after,\n u.num_resets,\n u.num_failures,\n u.docker_steps,\n u.root,\n u.indexer,\n u.indexer_args,\n u.outfile,\n u.log_contents,\n u.execution_logs,\n u.local_steps,\n r.name AS repository_name\n FROM (lsif_indexes u\n JOIN repo r ON ((r.id = u.repository_id)))\n WHERE (r.deleted_at IS NULL);\n\nCREATE TABLE lsif_last_index_scan (\n repository_id integer NOT NULL,\n last_index_scan_at timestamp with time zone NOT NULL\n);\n\nCOMMENT ON TABLE lsif_last_index_scan IS 'Tracks the last time repository was checked for auto-indexing job scheduling.';\n\nCOMMENT ON COLUMN lsif_last_index_scan.last_index_scan_at IS 'The last time uploads of this repository were considered for auto-indexing job scheduling.';\n\nCREATE TABLE lsif_last_retention_scan (\n repository_id integer NOT NULL,\n last_retention_scan_at timestamp with time zone NOT NULL\n);\n\nCOMMENT ON TABLE lsif_last_retention_scan IS 'Tracks the last time uploads a repository were checked against data retention policies.';\n\nCOMMENT ON COLUMN lsif_last_retention_scan.last_retention_scan_at IS 'The last time uploads of this repository were checked against data retention policies.';\n\nCREATE TABLE lsif_nearest_uploads (\n repository_id integer NOT NULL,\n commit_bytea bytea NOT NULL,\n uploads jsonb NOT NULL\n);\n\nCOMMENT ON TABLE lsif_nearest_uploads IS 'Associates commits with the complete set of uploads visible from that commit. Every commit with upload data is present in this table.';\n\nCOMMENT ON COLUMN lsif_nearest_uploads.commit_bytea IS 'A 40-char revhash. Note that this commit may not be resolvable in the future.';\n\nCOMMENT ON COLUMN lsif_nearest_uploads.uploads IS 'Encodes an {upload_id =\u003e distance} map that includes an entry for every upload visible from the commit. There is always at least one entry with a distance of zero.';\n\nCREATE TABLE lsif_nearest_uploads_links (\n repository_id integer NOT NULL,\n commit_bytea bytea NOT NULL,\n ancestor_commit_bytea bytea NOT NULL,\n distance integer NOT NULL\n);\n\nCOMMENT ON TABLE lsif_nearest_uploads_links IS 'Associates commits with the closest ancestor commit with usable upload data. Together, this table and lsif_nearest_uploads cover all commits with resolvable code intelligence.';\n\nCOMMENT ON COLUMN lsif_nearest_uploads_links.commit_bytea IS 'A 40-char revhash. Note that this commit may not be resolvable in the future.';\n\nCOMMENT ON COLUMN lsif_nearest_uploads_links.ancestor_commit_bytea IS 'The 40-char revhash of the ancestor. Note that this commit may not be resolvable in the future.';\n\nCOMMENT ON COLUMN lsif_nearest_uploads_links.distance IS 'The distance bewteen the commits. Parent = 1, Grandparent = 2, etc.';\n\nCREATE TABLE lsif_packages (\n id integer NOT NULL,\n scheme text NOT NULL,\n name text NOT NULL,\n version text,\n dump_id integer NOT NULL\n);\n\nCOMMENT ON TABLE lsif_packages IS 'Associates an upload with the set of packages they provide within a given packages management scheme.';\n\nCOMMENT ON COLUMN lsif_packages.scheme IS 'The (export) moniker scheme.';\n\nCOMMENT ON COLUMN lsif_packages.name IS 'The package name.';\n\nCOMMENT ON COLUMN lsif_packages.version IS 'The package version.';\n\nCOMMENT ON COLUMN lsif_packages.dump_id IS 'The identifier of the upload that provides the package.';\n\nCREATE SEQUENCE lsif_packages_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE lsif_packages_id_seq OWNED BY lsif_packages.id;\n\nCREATE TABLE lsif_references (\n id integer NOT NULL,\n scheme text NOT NULL,\n name text NOT NULL,\n version text,\n filter bytea NOT NULL,\n dump_id integer NOT NULL\n);\n\nCOMMENT ON TABLE lsif_references IS 'Associates an upload with the set of packages they require within a given packages management scheme.';\n\nCOMMENT ON COLUMN lsif_references.scheme IS 'The (import) moniker scheme.';\n\nCOMMENT ON COLUMN lsif_references.name IS 'The package name.';\n\nCOMMENT ON COLUMN lsif_references.version IS 'The package version.';\n\nCOMMENT ON COLUMN lsif_references.filter IS 'A [bloom filter](https://sourcegraph.com/github.com/sourcegraph/sourcegraph@3.23/-/blob/enterprise/internal/codeintel/bloomfilter/bloom_filter.go#L27:6) encoded as gzipped JSON. This bloom filter stores the set of identifiers imported from the package.';\n\nCOMMENT ON COLUMN lsif_references.dump_id IS 'The identifier of the upload that references the package.';\n\nCREATE SEQUENCE lsif_references_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE lsif_references_id_seq OWNED BY lsif_references.id;\n\nCREATE TABLE lsif_retention_configuration (\n id integer NOT NULL,\n repository_id integer NOT NULL,\n max_age_for_non_stale_branches_seconds integer NOT NULL,\n max_age_for_non_stale_tags_seconds integer NOT NULL\n);\n\nCOMMENT ON TABLE lsif_retention_configuration IS 'Stores the retention policy of code intellience data for a repository.';\n\nCOMMENT ON COLUMN lsif_retention_configuration.max_age_for_non_stale_branches_seconds IS 'The number of seconds since the last modification of a branch until it is considered stale.';\n\nCOMMENT ON COLUMN lsif_retention_configuration.max_age_for_non_stale_tags_seconds IS 'The nujmber of seconds since the commit date of a tagged commit until it is considered stale.';\n\nCREATE SEQUENCE lsif_retention_configuration_id_seq\n AS integer\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE lsif_retention_configuration_id_seq OWNED BY lsif_retention_configuration.id;\n\nCREATE TABLE lsif_uploads_visible_at_tip (\n repository_id integer NOT NULL,\n upload_id integer NOT NULL,\n branch_or_tag_name text DEFAULT ''::text NOT NULL,\n is_default_branch boolean DEFAULT false NOT NULL\n);\n\nCOMMENT ON TABLE lsif_uploads_visible_at_tip IS 'Associates a repository with the set of LSIF upload identifiers that can serve intelligence for the tip of the default branch.';\n\nCOMMENT ON COLUMN lsif_uploads_visible_at_tip.upload_id IS 'The identifier of the upload visible from the tip of the specified branch or tag.';\n\nCOMMENT ON COLUMN lsif_uploads_visible_at_tip.branch_or_tag_name IS 'The name of the branch or tag.';\n\nCOMMENT ON COLUMN lsif_uploads_visible_at_tip.is_default_branch IS 'Whether the specified branch is the default of the repository. Always false for tags.';\n\nCREATE VIEW lsif_uploads_with_repository_name AS\n SELECT u.id,\n u.commit,\n u.root,\n u.queued_at,\n u.uploaded_at,\n u.state,\n u.failure_message,\n u.started_at,\n u.finished_at,\n u.repository_id,\n u.indexer,\n u.indexer_version,\n u.num_parts,\n u.uploaded_parts,\n u.process_after,\n u.num_resets,\n u.upload_size,\n u.num_failures,\n u.associated_index_id,\n u.expired,\n u.last_retention_scan_at,\n r.name AS repository_name\n FROM (lsif_uploads u\n JOIN repo r ON ((r.id = u.repository_id)))\n WHERE (r.deleted_at IS NULL);\n\nCREATE TABLE names (\n name citext NOT NULL,\n user_id integer,\n org_id integer,\n CONSTRAINT names_check CHECK (((user_id IS NOT NULL) OR (org_id IS NOT NULL)))\n);\n\nCREATE TABLE notebook_stars (\n notebook_id integer NOT NULL,\n user_id integer NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL\n);\n\nCREATE TABLE notebooks (\n id bigint NOT NULL,\n title text NOT NULL,\n blocks jsonb DEFAULT '[]'::jsonb NOT NULL,\n public boolean NOT NULL,\n creator_user_id integer,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n blocks_tsvector tsvector GENERATED ALWAYS AS (jsonb_to_tsvector('english'::regconfig, blocks, '[\"string\"]'::jsonb)) STORED,\n namespace_user_id integer,\n namespace_org_id integer,\n updater_user_id integer,\n CONSTRAINT blocks_is_array CHECK ((jsonb_typeof(blocks) = 'array'::text)),\n CONSTRAINT notebooks_has_max_1_namespace CHECK ((((namespace_user_id IS NULL) AND (namespace_org_id IS NULL)) OR ((namespace_user_id IS NULL) \u003c\u003e (namespace_org_id IS NULL))))\n);\n\nCREATE SEQUENCE notebooks_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE notebooks_id_seq OWNED BY notebooks.id;\n\nCREATE TABLE org_invitations (\n id bigint NOT NULL,\n org_id integer NOT NULL,\n sender_user_id integer NOT NULL,\n recipient_user_id integer,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n notified_at timestamp with time zone,\n responded_at timestamp with time zone,\n response_type boolean,\n revoked_at timestamp with time zone,\n deleted_at timestamp with time zone,\n recipient_email citext,\n expires_at timestamp with time zone,\n CONSTRAINT check_atomic_response CHECK (((responded_at IS NULL) = (response_type IS NULL))),\n CONSTRAINT check_single_use CHECK ((((responded_at IS NULL) AND (response_type IS NULL)) OR (revoked_at IS NULL))),\n CONSTRAINT either_user_id_or_email_defined CHECK (((recipient_user_id IS NULL) \u003c\u003e (recipient_email IS NULL)))\n);\n\nCREATE SEQUENCE org_invitations_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE org_invitations_id_seq OWNED BY org_invitations.id;\n\nCREATE TABLE org_members (\n id integer NOT NULL,\n org_id integer NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n user_id integer NOT NULL\n);\n\nCREATE SEQUENCE org_members_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE org_members_id_seq OWNED BY org_members.id;\n\nCREATE TABLE org_stats (\n org_id integer NOT NULL,\n code_host_repo_count integer DEFAULT 0,\n updated_at timestamp with time zone DEFAULT now() NOT NULL\n);\n\nCOMMENT ON TABLE org_stats IS 'Business statistics for organizations';\n\nCOMMENT ON COLUMN org_stats.org_id IS 'Org ID that the stats relate to.';\n\nCOMMENT ON COLUMN org_stats.code_host_repo_count IS 'Count of repositories accessible on all code hosts for this organization.';\n\nCREATE TABLE orgs (\n id integer NOT NULL,\n name citext NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n display_name text,\n slack_webhook_url text,\n deleted_at timestamp with time zone,\n CONSTRAINT orgs_display_name_max_length CHECK ((char_length(display_name) \u003c= 255)),\n CONSTRAINT orgs_name_max_length CHECK ((char_length((name)::text) \u003c= 255)),\n CONSTRAINT orgs_name_valid_chars CHECK ((name OPERATOR(~) '^[a-zA-Z0-9](?:[a-zA-Z0-9]|[-.](?=[a-zA-Z0-9]))*-?$'::citext))\n);\n\nCREATE SEQUENCE orgs_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE orgs_id_seq OWNED BY orgs.id;\n\nCREATE TABLE orgs_open_beta_stats (\n id uuid DEFAULT gen_random_uuid() NOT NULL,\n user_id integer,\n org_id integer,\n created_at timestamp with time zone DEFAULT now(),\n data jsonb DEFAULT '{}'::jsonb NOT NULL\n);\n\nCREATE TABLE out_of_band_migrations (\n id integer NOT NULL,\n team text NOT NULL,\n component text NOT NULL,\n description text NOT NULL,\n progress double precision DEFAULT 0 NOT NULL,\n created timestamp with time zone DEFAULT now() NOT NULL,\n last_updated timestamp with time zone,\n non_destructive boolean NOT NULL,\n apply_reverse boolean DEFAULT false NOT NULL,\n is_enterprise boolean DEFAULT false NOT NULL,\n introduced_version_major integer NOT NULL,\n introduced_version_minor integer NOT NULL,\n deprecated_version_major integer,\n deprecated_version_minor integer,\n metadata jsonb DEFAULT '{}'::jsonb NOT NULL,\n CONSTRAINT out_of_band_migrations_component_nonempty CHECK ((component \u003c\u003e ''::text)),\n CONSTRAINT out_of_band_migrations_description_nonempty CHECK ((description \u003c\u003e ''::text)),\n CONSTRAINT out_of_band_migrations_progress_range CHECK (((progress \u003e= (0)::double precision) AND (progress \u003c= (1)::double precision))),\n CONSTRAINT out_of_band_migrations_team_nonempty CHECK ((team \u003c\u003e ''::text))\n);\n\nCOMMENT ON TABLE out_of_band_migrations IS 'Stores metadata and progress about an out-of-band migration routine.';\n\nCOMMENT ON COLUMN out_of_band_migrations.id IS 'A globally unique primary key for this migration. The same key is used consistently across all Sourcegraph instances for the same migration.';\n\nCOMMENT ON COLUMN out_of_band_migrations.team IS 'The name of the engineering team responsible for the migration.';\n\nCOMMENT ON COLUMN out_of_band_migrations.component IS 'The name of the component undergoing a migration.';\n\nCOMMENT ON COLUMN out_of_band_migrations.description IS 'A brief description about the migration.';\n\nCOMMENT ON COLUMN out_of_band_migrations.progress IS 'The percentage progress in the up direction (0=0%, 1=100%).';\n\nCOMMENT ON COLUMN out_of_band_migrations.created IS 'The date and time the migration was inserted into the database (via an upgrade).';\n\nCOMMENT ON COLUMN out_of_band_migrations.last_updated IS 'The date and time the migration was last updated.';\n\nCOMMENT ON COLUMN out_of_band_migrations.non_destructive IS 'Whether or not this migration alters data so it can no longer be read by the previous Sourcegraph instance.';\n\nCOMMENT ON COLUMN out_of_band_migrations.apply_reverse IS 'Whether this migration should run in the opposite direction (to support an upcoming downgrade).';\n\nCOMMENT ON COLUMN out_of_band_migrations.is_enterprise IS 'When true, these migrations are invisible to OSS mode.';\n\nCOMMENT ON COLUMN out_of_band_migrations.introduced_version_major IS 'The Sourcegraph version (major component) in which this migration was first introduced.';\n\nCOMMENT ON COLUMN out_of_band_migrations.introduced_version_minor IS 'The Sourcegraph version (minor component) in which this migration was first introduced.';\n\nCOMMENT ON COLUMN out_of_band_migrations.deprecated_version_major IS 'The lowest Sourcegraph version (major component) that assumes the migration has completed.';\n\nCOMMENT ON COLUMN out_of_band_migrations.deprecated_version_minor IS 'The lowest Sourcegraph version (minor component) that assumes the migration has completed.';\n\nCREATE TABLE out_of_band_migrations_errors (\n id integer NOT NULL,\n migration_id integer NOT NULL,\n message text NOT NULL,\n created timestamp with time zone DEFAULT now() NOT NULL,\n CONSTRAINT out_of_band_migrations_errors_message_nonempty CHECK ((message \u003c\u003e ''::text))\n);\n\nCOMMENT ON TABLE out_of_band_migrations_errors IS 'Stores errors that occurred while performing an out-of-band migration.';\n\nCOMMENT ON COLUMN out_of_band_migrations_errors.id IS 'A unique identifer.';\n\nCOMMENT ON COLUMN out_of_band_migrations_errors.migration_id IS 'The identifier of the migration.';\n\nCOMMENT ON COLUMN out_of_band_migrations_errors.message IS 'The error message.';\n\nCOMMENT ON COLUMN out_of_band_migrations_errors.created IS 'The date and time the error occurred.';\n\nCREATE SEQUENCE out_of_band_migrations_errors_id_seq\n AS integer\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE out_of_band_migrations_errors_id_seq OWNED BY out_of_band_migrations_errors.id;\n\nCREATE SEQUENCE out_of_band_migrations_id_seq\n AS integer\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE out_of_band_migrations_id_seq OWNED BY out_of_band_migrations.id;\n\nCREATE TABLE phabricator_repos (\n id integer NOT NULL,\n callsign citext NOT NULL,\n repo_name citext NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n deleted_at timestamp with time zone,\n url text DEFAULT ''::text NOT NULL\n);\n\nCREATE SEQUENCE phabricator_repos_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE phabricator_repos_id_seq OWNED BY phabricator_repos.id;\n\nCREATE TABLE product_licenses (\n id uuid NOT NULL,\n product_subscription_id uuid NOT NULL,\n license_key text NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL\n);\n\nCREATE TABLE product_subscriptions (\n id uuid NOT NULL,\n user_id integer NOT NULL,\n billing_subscription_id text,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n archived_at timestamp with time zone\n);\n\nCREATE TABLE query_runner_state (\n query text,\n last_executed timestamp with time zone,\n latest_result timestamp with time zone,\n exec_duration_ns bigint\n);\n\nCREATE TABLE users (\n id integer NOT NULL,\n username citext NOT NULL,\n display_name text,\n avatar_url text,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n deleted_at timestamp with time zone,\n invite_quota integer DEFAULT 15 NOT NULL,\n passwd text,\n passwd_reset_code text,\n passwd_reset_time timestamp with time zone,\n site_admin boolean DEFAULT false NOT NULL,\n page_views integer DEFAULT 0 NOT NULL,\n search_queries integer DEFAULT 0 NOT NULL,\n tags text[] DEFAULT '{}'::text[],\n billing_customer_id text,\n invalidated_sessions_at timestamp with time zone DEFAULT now() NOT NULL,\n tos_accepted boolean DEFAULT false NOT NULL,\n searchable boolean DEFAULT true NOT NULL,\n CONSTRAINT users_display_name_max_length CHECK ((char_length(display_name) \u003c= 255)),\n CONSTRAINT users_username_max_length CHECK ((char_length((username)::text) \u003c= 255)),\n CONSTRAINT users_username_valid_chars CHECK ((username OPERATOR(~) '^[a-zA-Z0-9](?:[a-zA-Z0-9]|[-.](?=[a-zA-Z0-9]))*-?$'::citext))\n);\n\nCREATE VIEW reconciler_changesets AS\n SELECT c.id,\n c.batch_change_ids,\n c.repo_id,\n c.queued_at,\n c.created_at,\n c.updated_at,\n c.metadata,\n c.external_id,\n c.external_service_type,\n c.external_deleted_at,\n c.external_branch,\n c.external_updated_at,\n c.external_state,\n c.external_review_state,\n c.external_check_state,\n c.diff_stat_added,\n c.diff_stat_changed,\n c.diff_stat_deleted,\n c.sync_state,\n c.current_spec_id,\n c.previous_spec_id,\n c.publication_state,\n c.owned_by_batch_change_id,\n c.reconciler_state,\n c.failure_message,\n c.started_at,\n c.finished_at,\n c.process_after,\n c.num_resets,\n c.closing,\n c.num_failures,\n c.log_contents,\n c.execution_logs,\n c.syncer_error,\n c.external_title,\n c.worker_hostname,\n c.ui_publication_state,\n c.last_heartbeat_at,\n c.external_fork_namespace\n FROM (changesets c\n JOIN repo r ON ((r.id = c.repo_id)))\n WHERE ((r.deleted_at IS NULL) AND (EXISTS ( SELECT 1\n FROM ((batch_changes\n LEFT JOIN users namespace_user ON ((batch_changes.namespace_user_id = namespace_user.id)))\n LEFT JOIN orgs namespace_org ON ((batch_changes.namespace_org_id = namespace_org.id)))\n WHERE ((c.batch_change_ids ? (batch_changes.id)::text) AND (namespace_user.deleted_at IS NULL) AND (namespace_org.deleted_at IS NULL)))));\n\nCREATE TABLE registry_extension_releases (\n id bigint NOT NULL,\n registry_extension_id integer NOT NULL,\n creator_user_id integer NOT NULL,\n release_version citext,\n release_tag citext NOT NULL,\n manifest jsonb NOT NULL,\n bundle text,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n deleted_at timestamp with time zone,\n source_map text\n);\n\nCREATE SEQUENCE registry_extension_releases_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE registry_extension_releases_id_seq OWNED BY registry_extension_releases.id;\n\nCREATE TABLE registry_extensions (\n id integer NOT NULL,\n uuid uuid NOT NULL,\n publisher_user_id integer,\n publisher_org_id integer,\n name citext NOT NULL,\n manifest text,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n deleted_at timestamp with time zone,\n CONSTRAINT registry_extensions_name_length CHECK (((char_length((name)::text) \u003e 0) AND (char_length((name)::text) \u003c= 128))),\n CONSTRAINT registry_extensions_name_valid_chars CHECK ((name OPERATOR(~) '^[a-zA-Z0-9](?:[a-zA-Z0-9]|[_.-](?=[a-zA-Z0-9]))*$'::citext)),\n CONSTRAINT registry_extensions_single_publisher CHECK (((publisher_user_id IS NULL) \u003c\u003e (publisher_org_id IS NULL)))\n);\n\nCREATE SEQUENCE registry_extensions_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE registry_extensions_id_seq OWNED BY registry_extensions.id;\n\nCREATE SEQUENCE repo_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE repo_id_seq OWNED BY repo.id;\n\nCREATE TABLE repo_pending_permissions (\n repo_id integer NOT NULL,\n permission text NOT NULL,\n updated_at timestamp with time zone NOT NULL,\n user_ids_ints integer[] DEFAULT '{}'::integer[] NOT NULL\n);\n\nCREATE TABLE repo_permissions (\n repo_id integer NOT NULL,\n permission text NOT NULL,\n updated_at timestamp with time zone NOT NULL,\n synced_at timestamp with time zone,\n user_ids_ints integer[] DEFAULT '{}'::integer[] NOT NULL\n);\n\nCREATE TABLE saved_searches (\n id integer NOT NULL,\n description text NOT NULL,\n query text NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n notify_owner boolean NOT NULL,\n notify_slack boolean NOT NULL,\n user_id integer,\n org_id integer,\n slack_webhook_url text,\n CONSTRAINT saved_searches_notifications_disabled CHECK (((notify_owner = false) AND (notify_slack = false))),\n CONSTRAINT user_or_org_id_not_null CHECK ((((user_id IS NOT NULL) AND (org_id IS NULL)) OR ((org_id IS NOT NULL) AND (user_id IS NULL))))\n);\n\nCREATE SEQUENCE saved_searches_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE saved_searches_id_seq OWNED BY saved_searches.id;\n\nCREATE TABLE search_context_repos (\n search_context_id bigint NOT NULL,\n repo_id integer NOT NULL,\n revision text NOT NULL\n);\n\nCREATE TABLE search_contexts (\n id bigint NOT NULL,\n name citext NOT NULL,\n description text NOT NULL,\n public boolean NOT NULL,\n namespace_user_id integer,\n namespace_org_id integer,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n deleted_at timestamp with time zone,\n query text,\n CONSTRAINT search_contexts_has_one_or_no_namespace CHECK (((namespace_user_id IS NULL) OR (namespace_org_id IS NULL)))\n);\n\nCOMMENT ON COLUMN search_contexts.deleted_at IS 'This column is unused as of Sourcegraph 3.34. Do not refer to it anymore. It will be dropped in a future version.';\n\nCREATE SEQUENCE search_contexts_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE search_contexts_id_seq OWNED BY search_contexts.id;\n\nCREATE TABLE security_event_logs (\n id bigint NOT NULL,\n name text NOT NULL,\n url text NOT NULL,\n user_id integer NOT NULL,\n anonymous_user_id text NOT NULL,\n source text NOT NULL,\n argument jsonb NOT NULL,\n version text NOT NULL,\n \"timestamp\" timestamp with time zone NOT NULL,\n CONSTRAINT security_event_logs_check_has_user CHECK ((((user_id = 0) AND (anonymous_user_id \u003c\u003e ''::text)) OR ((user_id \u003c\u003e 0) AND (anonymous_user_id = ''::text)) OR ((user_id \u003c\u003e 0) AND (anonymous_user_id \u003c\u003e ''::text)))),\n CONSTRAINT security_event_logs_check_name_not_empty CHECK ((name \u003c\u003e ''::text)),\n CONSTRAINT security_event_logs_check_source_not_empty CHECK ((source \u003c\u003e ''::text)),\n CONSTRAINT security_event_logs_check_version_not_empty CHECK ((version \u003c\u003e ''::text))\n);\n\nCOMMENT ON TABLE security_event_logs IS 'Contains security-relevant events with a long time horizon for storage.';\n\nCOMMENT ON COLUMN security_event_logs.name IS 'The event name as a CAPITALIZED_SNAKE_CASE string.';\n\nCOMMENT ON COLUMN security_event_logs.url IS 'The URL within the Sourcegraph app which generated the event.';\n\nCOMMENT ON COLUMN security_event_logs.user_id IS 'The ID of the actor associated with the event.';\n\nCOMMENT ON COLUMN security_event_logs.anonymous_user_id IS 'The UUID of the actor associated with the event.';\n\nCOMMENT ON COLUMN security_event_logs.source IS 'The site section (WEB, BACKEND, etc.) that generated the event.';\n\nCOMMENT ON COLUMN security_event_logs.argument IS 'An arbitrary JSON blob containing event data.';\n\nCOMMENT ON COLUMN security_event_logs.version IS 'The version of Sourcegraph which generated the event.';\n\nCREATE SEQUENCE security_event_logs_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE security_event_logs_id_seq OWNED BY security_event_logs.id;\n\nCREATE TABLE settings (\n id integer NOT NULL,\n org_id integer,\n contents text DEFAULT '{}'::text NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n user_id integer,\n author_user_id integer,\n CONSTRAINT settings_no_empty_contents CHECK ((contents \u003c\u003e ''::text))\n);\n\nCREATE SEQUENCE settings_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE settings_id_seq OWNED BY settings.id;\n\nCREATE VIEW site_config AS\n SELECT global_state.site_id,\n global_state.initialized\n FROM global_state;\n\nCREATE TABLE sub_repo_permissions (\n repo_id integer NOT NULL,\n user_id integer NOT NULL,\n version integer DEFAULT 1 NOT NULL,\n path_includes text[],\n path_excludes text[],\n updated_at timestamp with time zone DEFAULT now() NOT NULL\n);\n\nCOMMENT ON TABLE sub_repo_permissions IS 'Responsible for storing permissions at a finer granularity than repo';\n\nCREATE TABLE survey_responses (\n id bigint NOT NULL,\n user_id integer,\n email text,\n score integer NOT NULL,\n reason text,\n better text,\n created_at timestamp with time zone DEFAULT now() NOT NULL\n);\n\nCREATE SEQUENCE survey_responses_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE survey_responses_id_seq OWNED BY survey_responses.id;\n\nCREATE TABLE temporary_settings (\n id integer NOT NULL,\n user_id integer NOT NULL,\n contents jsonb,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL\n);\n\nCOMMENT ON TABLE temporary_settings IS 'Stores per-user temporary settings used in the UI, for example, which modals have been dimissed or what theme is preferred.';\n\nCOMMENT ON COLUMN temporary_settings.user_id IS 'The ID of the user the settings will be saved for.';\n\nCOMMENT ON COLUMN temporary_settings.contents IS 'JSON-encoded temporary settings.';\n\nCREATE SEQUENCE temporary_settings_id_seq\n AS integer\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE temporary_settings_id_seq OWNED BY temporary_settings.id;\n\nCREATE VIEW tracking_changeset_specs_and_changesets AS\n SELECT changeset_specs.id AS changeset_spec_id,\n COALESCE(changesets.id, (0)::bigint) AS changeset_id,\n changeset_specs.repo_id,\n changeset_specs.batch_spec_id,\n repo.name AS repo_name,\n COALESCE((changesets.metadata -\u003e\u003e 'Title'::text), (changesets.metadata -\u003e\u003e 'title'::text)) AS changeset_name,\n changesets.external_state,\n changesets.publication_state,\n changesets.reconciler_state\n FROM ((changeset_specs\n LEFT JOIN changesets ON (((changesets.repo_id = changeset_specs.repo_id) AND (changesets.external_id = changeset_specs.external_id))))\n JOIN repo ON ((changeset_specs.repo_id = repo.id)))\n WHERE ((changeset_specs.external_id IS NOT NULL) AND (repo.deleted_at IS NULL));\n\nCREATE TABLE user_credentials (\n id bigint NOT NULL,\n domain text NOT NULL,\n user_id integer NOT NULL,\n external_service_type text NOT NULL,\n external_service_id text NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n credential bytea NOT NULL,\n ssh_migration_applied boolean DEFAULT false NOT NULL,\n encryption_key_id text DEFAULT ''::text NOT NULL\n);\n\nCREATE SEQUENCE user_credentials_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE user_credentials_id_seq OWNED BY user_credentials.id;\n\nCREATE TABLE user_emails (\n user_id integer NOT NULL,\n email citext NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n verification_code text,\n verified_at timestamp with time zone,\n last_verification_sent_at timestamp with time zone,\n is_primary boolean DEFAULT false NOT NULL\n);\n\nCREATE TABLE user_external_accounts (\n id integer NOT NULL,\n user_id integer NOT NULL,\n service_type text NOT NULL,\n service_id text NOT NULL,\n account_id text NOT NULL,\n auth_data text,\n account_data text,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n deleted_at timestamp with time zone,\n client_id text NOT NULL,\n expired_at timestamp with time zone,\n last_valid_at timestamp with time zone,\n encryption_key_id text DEFAULT ''::text NOT NULL\n);\n\nCREATE SEQUENCE user_external_accounts_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE user_external_accounts_id_seq OWNED BY user_external_accounts.id;\n\nCREATE TABLE user_pending_permissions (\n id integer NOT NULL,\n bind_id text NOT NULL,\n permission text NOT NULL,\n object_type text NOT NULL,\n updated_at timestamp with time zone NOT NULL,\n service_type text NOT NULL,\n service_id text NOT NULL,\n object_ids_ints integer[] DEFAULT '{}'::integer[] NOT NULL\n);\n\nCREATE SEQUENCE user_pending_permissions_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE user_pending_permissions_id_seq OWNED BY user_pending_permissions.id;\n\nCREATE TABLE user_permissions (\n user_id integer NOT NULL,\n permission text NOT NULL,\n object_type text NOT NULL,\n updated_at timestamp with time zone NOT NULL,\n synced_at timestamp with time zone,\n object_ids_ints integer[] DEFAULT '{}'::integer[] NOT NULL\n);\n\nCREATE TABLE user_public_repos (\n user_id integer NOT NULL,\n repo_uri text NOT NULL,\n repo_id integer NOT NULL\n);\n\nCREATE SEQUENCE users_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE users_id_seq OWNED BY users.id;\n\nCREATE TABLE versions (\n service text NOT NULL,\n version text NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n first_version text NOT NULL\n);\n\nCREATE TABLE webhook_logs (\n id bigint NOT NULL,\n received_at timestamp with time zone DEFAULT now() NOT NULL,\n external_service_id integer,\n status_code integer NOT NULL,\n request bytea NOT NULL,\n response bytea NOT NULL,\n encryption_key_id text NOT NULL\n);\n\nCREATE SEQUENCE webhook_logs_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nALTER SEQUENCE webhook_logs_id_seq OWNED BY webhook_logs.id;\n\nALTER TABLE ONLY access_tokens ALTER COLUMN id SET DEFAULT nextval('access_tokens_id_seq'::regclass);\n\nALTER TABLE ONLY batch_changes ALTER COLUMN id SET DEFAULT nextval('batch_changes_id_seq'::regclass);\n\nALTER TABLE ONLY batch_changes_site_credentials ALTER COLUMN id SET DEFAULT nextval('batch_changes_site_credentials_id_seq'::regclass);\n\nALTER TABLE ONLY batch_spec_execution_cache_entries ALTER COLUMN id SET DEFAULT nextval('batch_spec_execution_cache_entries_id_seq'::regclass);\n\nALTER TABLE ONLY batch_spec_resolution_jobs ALTER COLUMN id SET DEFAULT nextval('batch_spec_resolution_jobs_id_seq'::regclass);\n\nALTER TABLE ONLY batch_spec_workspace_execution_jobs ALTER COLUMN id SET DEFAULT nextval('batch_spec_workspace_execution_jobs_id_seq'::regclass);\n\nALTER TABLE ONLY batch_spec_workspaces ALTER COLUMN id SET DEFAULT nextval('batch_spec_workspaces_id_seq'::regclass);\n\nALTER TABLE ONLY batch_specs ALTER COLUMN id SET DEFAULT nextval('batch_specs_id_seq'::regclass);\n\nALTER TABLE ONLY changeset_events ALTER COLUMN id SET DEFAULT nextval('changeset_events_id_seq'::regclass);\n\nALTER TABLE ONLY changeset_jobs ALTER COLUMN id SET DEFAULT nextval('changeset_jobs_id_seq'::regclass);\n\nALTER TABLE ONLY changeset_specs ALTER COLUMN id SET DEFAULT nextval('changeset_specs_id_seq'::regclass);\n\nALTER TABLE ONLY changesets ALTER COLUMN id SET DEFAULT nextval('changesets_id_seq'::regclass);\n\nALTER TABLE ONLY cm_action_jobs ALTER COLUMN id SET DEFAULT nextval('cm_action_jobs_id_seq'::regclass);\n\nALTER TABLE ONLY cm_emails ALTER COLUMN id SET DEFAULT nextval('cm_emails_id_seq'::regclass);\n\nALTER TABLE ONLY cm_monitors ALTER COLUMN id SET DEFAULT nextval('cm_monitors_id_seq'::regclass);\n\nALTER TABLE ONLY cm_queries ALTER COLUMN id SET DEFAULT nextval('cm_queries_id_seq'::regclass);\n\nALTER TABLE ONLY cm_recipients ALTER COLUMN id SET DEFAULT nextval('cm_recipients_id_seq'::regclass);\n\nALTER TABLE ONLY cm_slack_webhooks ALTER COLUMN id SET DEFAULT nextval('cm_slack_webhooks_id_seq'::regclass);\n\nALTER TABLE ONLY cm_trigger_jobs ALTER COLUMN id SET DEFAULT nextval('cm_trigger_jobs_id_seq'::regclass);\n\nALTER TABLE ONLY cm_webhooks ALTER COLUMN id SET DEFAULT nextval('cm_webhooks_id_seq'::regclass);\n\nALTER TABLE ONLY critical_and_site_config ALTER COLUMN id SET DEFAULT nextval('critical_and_site_config_id_seq'::regclass);\n\nALTER TABLE ONLY discussion_comments ALTER COLUMN id SET DEFAULT nextval('discussion_comments_id_seq'::regclass);\n\nALTER TABLE ONLY discussion_threads ALTER COLUMN id SET DEFAULT nextval('discussion_threads_id_seq'::regclass);\n\nALTER TABLE ONLY discussion_threads_target_repo ALTER COLUMN id SET DEFAULT nextval('discussion_threads_target_repo_id_seq'::regclass);\n\nALTER TABLE ONLY event_logs ALTER COLUMN id SET DEFAULT nextval('event_logs_id_seq'::regclass);\n\nALTER TABLE ONLY executor_heartbeats ALTER COLUMN id SET DEFAULT nextval('executor_heartbeats_id_seq'::regclass);\n\nALTER TABLE ONLY external_services ALTER COLUMN id SET DEFAULT nextval('external_services_id_seq'::regclass);\n\nALTER TABLE ONLY gitserver_localclone_jobs ALTER COLUMN id SET DEFAULT nextval('gitserver_localclone_jobs_id_seq'::regclass);\n\nALTER TABLE ONLY insights_query_runner_jobs ALTER COLUMN id SET DEFAULT nextval('insights_query_runner_jobs_id_seq'::regclass);\n\nALTER TABLE ONLY insights_query_runner_jobs_dependencies ALTER COLUMN id SET DEFAULT nextval('insights_query_runner_jobs_dependencies_id_seq'::regclass);\n\nALTER TABLE ONLY insights_settings_migration_jobs ALTER COLUMN id SET DEFAULT nextval('insights_settings_migration_jobs_id_seq'::regclass);\n\nALTER TABLE ONLY lsif_configuration_policies ALTER COLUMN id SET DEFAULT nextval('lsif_configuration_policies_id_seq'::regclass);\n\nALTER TABLE ONLY lsif_dependency_indexing_jobs ALTER COLUMN id SET DEFAULT nextval('lsif_dependency_indexing_jobs_id_seq1'::regclass);\n\nALTER TABLE ONLY lsif_dependency_repos ALTER COLUMN id SET DEFAULT nextval('lsif_dependency_repos_id_seq'::regclass);\n\nALTER TABLE ONLY lsif_dependency_syncing_jobs ALTER COLUMN id SET DEFAULT nextval('lsif_dependency_indexing_jobs_id_seq'::regclass);\n\nALTER TABLE ONLY lsif_index_configuration ALTER COLUMN id SET DEFAULT nextval('lsif_index_configuration_id_seq'::regclass);\n\nALTER TABLE ONLY lsif_indexes ALTER COLUMN id SET DEFAULT nextval('lsif_indexes_id_seq'::regclass);\n\nALTER TABLE ONLY lsif_packages ALTER COLUMN id SET DEFAULT nextval('lsif_packages_id_seq'::regclass);\n\nALTER TABLE ONLY lsif_references ALTER COLUMN id SET DEFAULT nextval('lsif_references_id_seq'::regclass);\n\nALTER TABLE ONLY lsif_retention_configuration ALTER COLUMN id SET DEFAULT nextval('lsif_retention_configuration_id_seq'::regclass);\n\nALTER TABLE ONLY lsif_uploads ALTER COLUMN id SET DEFAULT nextval('lsif_dumps_id_seq'::regclass);\n\nALTER TABLE ONLY notebooks ALTER COLUMN id SET DEFAULT nextval('notebooks_id_seq'::regclass);\n\nALTER TABLE ONLY org_invitations ALTER COLUMN id SET DEFAULT nextval('org_invitations_id_seq'::regclass);\n\nALTER TABLE ONLY org_members ALTER COLUMN id SET DEFAULT nextval('org_members_id_seq'::regclass);\n\nALTER TABLE ONLY orgs ALTER COLUMN id SET DEFAULT nextval('orgs_id_seq'::regclass);\n\nALTER TABLE ONLY out_of_band_migrations ALTER COLUMN id SET DEFAULT nextval('out_of_band_migrations_id_seq'::regclass);\n\nALTER TABLE ONLY out_of_band_migrations_errors ALTER COLUMN id SET DEFAULT nextval('out_of_band_migrations_errors_id_seq'::regclass);\n\nALTER TABLE ONLY phabricator_repos ALTER COLUMN id SET DEFAULT nextval('phabricator_repos_id_seq'::regclass);\n\nALTER TABLE ONLY registry_extension_releases ALTER COLUMN id SET DEFAULT nextval('registry_extension_releases_id_seq'::regclass);\n\nALTER TABLE ONLY registry_extensions ALTER COLUMN id SET DEFAULT nextval('registry_extensions_id_seq'::regclass);\n\nALTER TABLE ONLY repo ALTER COLUMN id SET DEFAULT nextval('repo_id_seq'::regclass);\n\nALTER TABLE ONLY saved_searches ALTER COLUMN id SET DEFAULT nextval('saved_searches_id_seq'::regclass);\n\nALTER TABLE ONLY search_contexts ALTER COLUMN id SET DEFAULT nextval('search_contexts_id_seq'::regclass);\n\nALTER TABLE ONLY security_event_logs ALTER COLUMN id SET DEFAULT nextval('security_event_logs_id_seq'::regclass);\n\nALTER TABLE ONLY settings ALTER COLUMN id SET DEFAULT nextval('settings_id_seq'::regclass);\n\nALTER TABLE ONLY survey_responses ALTER COLUMN id SET DEFAULT nextval('survey_responses_id_seq'::regclass);\n\nALTER TABLE ONLY temporary_settings ALTER COLUMN id SET DEFAULT nextval('temporary_settings_id_seq'::regclass);\n\nALTER TABLE ONLY user_credentials ALTER COLUMN id SET DEFAULT nextval('user_credentials_id_seq'::regclass);\n\nALTER TABLE ONLY user_external_accounts ALTER COLUMN id SET DEFAULT nextval('user_external_accounts_id_seq'::regclass);\n\nALTER TABLE ONLY user_pending_permissions ALTER COLUMN id SET DEFAULT nextval('user_pending_permissions_id_seq'::regclass);\n\nALTER TABLE ONLY users ALTER COLUMN id SET DEFAULT nextval('users_id_seq'::regclass);\n\nALTER TABLE ONLY webhook_logs ALTER COLUMN id SET DEFAULT nextval('webhook_logs_id_seq'::regclass);\n\nALTER TABLE ONLY access_tokens\n ADD CONSTRAINT access_tokens_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY access_tokens\n ADD CONSTRAINT access_tokens_value_sha256_key UNIQUE (value_sha256);\n\nALTER TABLE ONLY batch_changes\n ADD CONSTRAINT batch_changes_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY batch_changes_site_credentials\n ADD CONSTRAINT batch_changes_site_credentials_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY batch_spec_execution_cache_entries\n ADD CONSTRAINT batch_spec_execution_cache_entries_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY batch_spec_execution_cache_entries\n ADD CONSTRAINT batch_spec_execution_cache_entries_user_id_key_unique UNIQUE (user_id, key);\n\nALTER TABLE ONLY batch_spec_resolution_jobs\n ADD CONSTRAINT batch_spec_resolution_jobs_batch_spec_id_unique UNIQUE (batch_spec_id);\n\nALTER TABLE ONLY batch_spec_resolution_jobs\n ADD CONSTRAINT batch_spec_resolution_jobs_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY batch_spec_workspace_execution_jobs\n ADD CONSTRAINT batch_spec_workspace_execution_jobs_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY batch_spec_workspaces\n ADD CONSTRAINT batch_spec_workspaces_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY batch_specs\n ADD CONSTRAINT batch_specs_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY changeset_events\n ADD CONSTRAINT changeset_events_changeset_id_kind_key_unique UNIQUE (changeset_id, kind, key);\n\nALTER TABLE ONLY changeset_events\n ADD CONSTRAINT changeset_events_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY changeset_jobs\n ADD CONSTRAINT changeset_jobs_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY changeset_specs\n ADD CONSTRAINT changeset_specs_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY changesets\n ADD CONSTRAINT changesets_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY changesets\n ADD CONSTRAINT changesets_repo_external_id_unique UNIQUE (repo_id, external_id);\n\nALTER TABLE ONLY cm_action_jobs\n ADD CONSTRAINT cm_action_jobs_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY cm_emails\n ADD CONSTRAINT cm_emails_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY cm_last_searched\n ADD CONSTRAINT cm_last_searched_pkey PRIMARY KEY (monitor_id, args_hash);\n\nALTER TABLE ONLY cm_monitors\n ADD CONSTRAINT cm_monitors_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY cm_queries\n ADD CONSTRAINT cm_queries_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY cm_recipients\n ADD CONSTRAINT cm_recipients_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY cm_slack_webhooks\n ADD CONSTRAINT cm_slack_webhooks_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY cm_trigger_jobs\n ADD CONSTRAINT cm_trigger_jobs_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY cm_webhooks\n ADD CONSTRAINT cm_webhooks_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY critical_and_site_config\n ADD CONSTRAINT critical_and_site_config_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY discussion_comments\n ADD CONSTRAINT discussion_comments_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY discussion_mail_reply_tokens\n ADD CONSTRAINT discussion_mail_reply_tokens_pkey PRIMARY KEY (token);\n\nALTER TABLE ONLY discussion_threads\n ADD CONSTRAINT discussion_threads_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY discussion_threads_target_repo\n ADD CONSTRAINT discussion_threads_target_repo_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY event_logs\n ADD CONSTRAINT event_logs_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY executor_heartbeats\n ADD CONSTRAINT executor_heartbeats_hostname_key UNIQUE (hostname);\n\nALTER TABLE ONLY executor_heartbeats\n ADD CONSTRAINT executor_heartbeats_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY external_service_repos\n ADD CONSTRAINT external_service_repos_repo_id_external_service_id_unique UNIQUE (repo_id, external_service_id);\n\nALTER TABLE ONLY external_services\n ADD CONSTRAINT external_services_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY feature_flag_overrides\n ADD CONSTRAINT feature_flag_overrides_unique_org_flag UNIQUE (namespace_org_id, flag_name);\n\nALTER TABLE ONLY feature_flag_overrides\n ADD CONSTRAINT feature_flag_overrides_unique_user_flag UNIQUE (namespace_user_id, flag_name);\n\nALTER TABLE ONLY feature_flags\n ADD CONSTRAINT feature_flags_pkey PRIMARY KEY (flag_name);\n\nALTER TABLE ONLY gitserver_localclone_jobs\n ADD CONSTRAINT gitserver_localclone_jobs_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY gitserver_repos\n ADD CONSTRAINT gitserver_repos_pkey PRIMARY KEY (repo_id);\n\nALTER TABLE ONLY global_state\n ADD CONSTRAINT global_state_pkey PRIMARY KEY (site_id);\n\nALTER TABLE ONLY insights_query_runner_jobs_dependencies\n ADD CONSTRAINT insights_query_runner_jobs_dependencies_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY insights_query_runner_jobs\n ADD CONSTRAINT insights_query_runner_jobs_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY lsif_configuration_policies\n ADD CONSTRAINT lsif_configuration_policies_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY lsif_configuration_policies_repository_pattern_lookup\n ADD CONSTRAINT lsif_configuration_policies_repository_pattern_lookup_pkey PRIMARY KEY (policy_id, repo_id);\n\nALTER TABLE ONLY lsif_dependency_syncing_jobs\n ADD CONSTRAINT lsif_dependency_indexing_jobs_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY lsif_dependency_indexing_jobs\n ADD CONSTRAINT lsif_dependency_indexing_jobs_pkey1 PRIMARY KEY (id);\n\nALTER TABLE ONLY lsif_dependency_repos\n ADD CONSTRAINT lsif_dependency_repos_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY lsif_dependency_repos\n ADD CONSTRAINT lsif_dependency_repos_unique_triplet UNIQUE (scheme, name, version);\n\nALTER TABLE ONLY lsif_dirty_repositories\n ADD CONSTRAINT lsif_dirty_repositories_pkey PRIMARY KEY (repository_id);\n\nALTER TABLE ONLY lsif_index_configuration\n ADD CONSTRAINT lsif_index_configuration_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY lsif_index_configuration\n ADD CONSTRAINT lsif_index_configuration_repository_id_key UNIQUE (repository_id);\n\nALTER TABLE ONLY lsif_indexes\n ADD CONSTRAINT lsif_indexes_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY lsif_last_index_scan\n ADD CONSTRAINT lsif_last_index_scan_pkey PRIMARY KEY (repository_id);\n\nALTER TABLE ONLY lsif_last_retention_scan\n ADD CONSTRAINT lsif_last_retention_scan_pkey PRIMARY KEY (repository_id);\n\nALTER TABLE ONLY lsif_packages\n ADD CONSTRAINT lsif_packages_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY lsif_references\n ADD CONSTRAINT lsif_references_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY lsif_retention_configuration\n ADD CONSTRAINT lsif_retention_configuration_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY lsif_retention_configuration\n ADD CONSTRAINT lsif_retention_configuration_repository_id_key UNIQUE (repository_id);\n\nALTER TABLE ONLY lsif_uploads\n ADD CONSTRAINT lsif_uploads_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY names\n ADD CONSTRAINT names_pkey PRIMARY KEY (name);\n\nALTER TABLE ONLY notebook_stars\n ADD CONSTRAINT notebook_stars_pkey PRIMARY KEY (notebook_id, user_id);\n\nALTER TABLE ONLY notebooks\n ADD CONSTRAINT notebooks_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY org_invitations\n ADD CONSTRAINT org_invitations_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY org_members\n ADD CONSTRAINT org_members_org_id_user_id_key UNIQUE (org_id, user_id);\n\nALTER TABLE ONLY org_members\n ADD CONSTRAINT org_members_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY org_stats\n ADD CONSTRAINT org_stats_pkey PRIMARY KEY (org_id);\n\nALTER TABLE ONLY orgs_open_beta_stats\n ADD CONSTRAINT orgs_open_beta_stats_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY orgs\n ADD CONSTRAINT orgs_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY out_of_band_migrations_errors\n ADD CONSTRAINT out_of_band_migrations_errors_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY out_of_band_migrations\n ADD CONSTRAINT out_of_band_migrations_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY phabricator_repos\n ADD CONSTRAINT phabricator_repos_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY phabricator_repos\n ADD CONSTRAINT phabricator_repos_repo_name_key UNIQUE (repo_name);\n\nALTER TABLE ONLY product_licenses\n ADD CONSTRAINT product_licenses_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY product_subscriptions\n ADD CONSTRAINT product_subscriptions_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY registry_extension_releases\n ADD CONSTRAINT registry_extension_releases_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY registry_extensions\n ADD CONSTRAINT registry_extensions_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY repo\n ADD CONSTRAINT repo_name_unique UNIQUE (name) DEFERRABLE;\n\nALTER TABLE ONLY repo_pending_permissions\n ADD CONSTRAINT repo_pending_permissions_perm_unique UNIQUE (repo_id, permission);\n\nALTER TABLE ONLY repo_permissions\n ADD CONSTRAINT repo_permissions_perm_unique UNIQUE (repo_id, permission);\n\nALTER TABLE ONLY repo\n ADD CONSTRAINT repo_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY saved_searches\n ADD CONSTRAINT saved_searches_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY search_context_repos\n ADD CONSTRAINT search_context_repos_unique UNIQUE (repo_id, search_context_id, revision);\n\nALTER TABLE ONLY search_contexts\n ADD CONSTRAINT search_contexts_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY security_event_logs\n ADD CONSTRAINT security_event_logs_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY settings\n ADD CONSTRAINT settings_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY survey_responses\n ADD CONSTRAINT survey_responses_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY temporary_settings\n ADD CONSTRAINT temporary_settings_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY temporary_settings\n ADD CONSTRAINT temporary_settings_user_id_key UNIQUE (user_id);\n\nALTER TABLE ONLY user_credentials\n ADD CONSTRAINT user_credentials_domain_user_id_external_service_type_exter_key UNIQUE (domain, user_id, external_service_type, external_service_id);\n\nALTER TABLE ONLY user_credentials\n ADD CONSTRAINT user_credentials_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY user_emails\n ADD CONSTRAINT user_emails_no_duplicates_per_user UNIQUE (user_id, email);\n\nALTER TABLE ONLY user_emails\n ADD CONSTRAINT user_emails_unique_verified_email EXCLUDE USING btree (email WITH OPERATOR(=)) WHERE ((verified_at IS NOT NULL));\n\nALTER TABLE ONLY user_external_accounts\n ADD CONSTRAINT user_external_accounts_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY user_pending_permissions\n ADD CONSTRAINT user_pending_permissions_service_perm_object_unique UNIQUE (service_type, service_id, permission, object_type, bind_id);\n\nALTER TABLE ONLY user_permissions\n ADD CONSTRAINT user_permissions_perm_object_unique UNIQUE (user_id, permission, object_type);\n\nALTER TABLE ONLY user_public_repos\n ADD CONSTRAINT user_public_repos_user_id_repo_id_key UNIQUE (user_id, repo_id);\n\nALTER TABLE ONLY users\n ADD CONSTRAINT users_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY versions\n ADD CONSTRAINT versions_pkey PRIMARY KEY (service);\n\nALTER TABLE ONLY webhook_logs\n ADD CONSTRAINT webhook_logs_pkey PRIMARY KEY (id);\n\nCREATE INDEX access_tokens_lookup ON access_tokens USING hash (value_sha256) WHERE (deleted_at IS NULL);\n\nCREATE INDEX batch_changes_namespace_org_id ON batch_changes USING btree (namespace_org_id);\n\nCREATE INDEX batch_changes_namespace_user_id ON batch_changes USING btree (namespace_user_id);\n\nCREATE INDEX batch_changes_site_credentials_credential_idx ON batch_changes_site_credentials USING btree (((encryption_key_id = ANY (ARRAY[''::text, 'previously-migrated'::text]))));\n\nCREATE UNIQUE INDEX batch_changes_site_credentials_unique ON batch_changes_site_credentials USING btree (external_service_type, external_service_id);\n\nCREATE UNIQUE INDEX batch_changes_unique_org_id ON batch_changes USING btree (name, namespace_org_id) WHERE (namespace_org_id IS NOT NULL);\n\nCREATE UNIQUE INDEX batch_changes_unique_user_id ON batch_changes USING btree (name, namespace_user_id) WHERE (namespace_user_id IS NOT NULL);\n\nCREATE INDEX batch_spec_workspace_execution_jobs_cancel ON batch_spec_workspace_execution_jobs USING btree (cancel);\n\nCREATE INDEX batch_specs_rand_id ON batch_specs USING btree (rand_id);\n\nCREATE INDEX changeset_jobs_bulk_group_idx ON changeset_jobs USING btree (bulk_group);\n\nCREATE INDEX changeset_jobs_state_idx ON changeset_jobs USING btree (state);\n\nCREATE INDEX changeset_specs_external_id ON changeset_specs USING btree (external_id);\n\nCREATE INDEX changeset_specs_head_ref ON changeset_specs USING btree (head_ref);\n\nCREATE INDEX changeset_specs_rand_id ON changeset_specs USING btree (rand_id);\n\nCREATE INDEX changeset_specs_title ON changeset_specs USING btree (title);\n\nCREATE INDEX changesets_batch_change_ids ON changesets USING gin (batch_change_ids);\n\nCREATE INDEX changesets_external_state_idx ON changesets USING btree (external_state);\n\nCREATE INDEX changesets_external_title_idx ON changesets USING btree (external_title);\n\nCREATE INDEX changesets_publication_state_idx ON changesets USING btree (publication_state);\n\nCREATE INDEX changesets_reconciler_state_idx ON changesets USING btree (reconciler_state);\n\nCREATE INDEX cm_slack_webhooks_monitor ON cm_slack_webhooks USING btree (monitor);\n\nCREATE INDEX cm_webhooks_monitor ON cm_webhooks USING btree (monitor);\n\nCREATE UNIQUE INDEX critical_and_site_config_unique ON critical_and_site_config USING btree (id, type);\n\nCREATE INDEX discussion_comments_author_user_id_idx ON discussion_comments USING btree (author_user_id);\n\nCREATE INDEX discussion_comments_reports_array_length_idx ON discussion_comments USING btree (array_length(reports, 1));\n\nCREATE INDEX discussion_comments_thread_id_idx ON discussion_comments USING btree (thread_id);\n\nCREATE INDEX discussion_mail_reply_tokens_user_id_thread_id_idx ON discussion_mail_reply_tokens USING btree (user_id, thread_id);\n\nCREATE INDEX discussion_threads_author_user_id_idx ON discussion_threads USING btree (author_user_id);\n\nCREATE INDEX discussion_threads_target_repo_repo_id_path_idx ON discussion_threads_target_repo USING btree (repo_id, path);\n\nCREATE INDEX event_logs_anonymous_user_id ON event_logs USING btree (anonymous_user_id);\n\nCREATE INDEX event_logs_name ON event_logs USING btree (name);\n\nCREATE INDEX event_logs_source ON event_logs USING btree (source);\n\nCREATE INDEX event_logs_timestamp ON event_logs USING btree (\"timestamp\");\n\nCREATE INDEX event_logs_timestamp_at_utc ON event_logs USING btree (date(timezone('UTC'::text, \"timestamp\")));\n\nCREATE INDEX event_logs_user_id ON event_logs USING btree (user_id);\n\nCREATE INDEX external_service_repos_clone_url_idx ON external_service_repos USING btree (clone_url);\n\nCREATE INDEX external_service_repos_idx ON external_service_repos USING btree (external_service_id, repo_id);\n\nCREATE INDEX external_service_repos_org_id_idx ON external_service_repos USING btree (org_id) WHERE (org_id IS NOT NULL);\n\nCREATE INDEX external_service_sync_jobs_state_idx ON external_service_sync_jobs USING btree (state);\n\nCREATE INDEX external_service_user_repos_idx ON external_service_repos USING btree (user_id, repo_id) WHERE (user_id IS NOT NULL);\n\nCREATE INDEX external_services_has_webhooks_idx ON external_services USING btree (has_webhooks);\n\nCREATE INDEX external_services_namespace_org_id_idx ON external_services USING btree (namespace_org_id);\n\nCREATE INDEX external_services_namespace_user_id_idx ON external_services USING btree (namespace_user_id);\n\nCREATE INDEX feature_flag_overrides_org_id ON feature_flag_overrides USING btree (namespace_org_id) WHERE (namespace_org_id IS NOT NULL);\n\nCREATE INDEX feature_flag_overrides_user_id ON feature_flag_overrides USING btree (namespace_user_id) WHERE (namespace_user_id IS NOT NULL);\n\nCREATE INDEX gitserver_repos_cloned_status_idx ON gitserver_repos USING btree (repo_id) WHERE (clone_status = 'cloned'::text);\n\nCREATE INDEX gitserver_repos_cloning_status_idx ON gitserver_repos USING btree (repo_id) WHERE (clone_status = 'cloning'::text);\n\nCREATE INDEX gitserver_repos_last_error_idx ON gitserver_repos USING btree (repo_id) WHERE (last_error IS NOT NULL);\n\nCREATE INDEX gitserver_repos_not_cloned_status_idx ON gitserver_repos USING btree (repo_id) WHERE (clone_status = 'not_cloned'::text);\n\nCREATE INDEX gitserver_repos_shard_id ON gitserver_repos USING btree (shard_id, repo_id);\n\nCREATE INDEX insights_query_runner_jobs_cost_idx ON insights_query_runner_jobs USING btree (cost);\n\nCREATE INDEX insights_query_runner_jobs_dependencies_job_id_fk_idx ON insights_query_runner_jobs_dependencies USING btree (job_id);\n\nCREATE INDEX insights_query_runner_jobs_priority_idx ON insights_query_runner_jobs USING btree (priority);\n\nCREATE INDEX insights_query_runner_jobs_processable_priority_id ON insights_query_runner_jobs USING btree (priority, id) WHERE ((state = 'queued'::text) OR (state = 'errored'::text));\n\nCREATE INDEX insights_query_runner_jobs_state_btree ON insights_query_runner_jobs USING btree (state);\n\nCREATE UNIQUE INDEX kind_cloud_default ON external_services USING btree (kind, cloud_default) WHERE ((cloud_default = true) AND (deleted_at IS NULL));\n\nCREATE INDEX lsif_configuration_policies_repository_id ON lsif_configuration_policies USING btree (repository_id);\n\nCREATE INDEX lsif_dependency_indexing_jobs_upload_id ON lsif_dependency_syncing_jobs USING btree (upload_id);\n\nCREATE INDEX lsif_indexes_commit_last_checked_at ON lsif_indexes USING btree (commit_last_checked_at) WHERE (state \u003c\u003e 'deleted'::text);\n\nCREATE INDEX lsif_indexes_repository_id_commit ON lsif_indexes USING btree (repository_id, commit);\n\nCREATE INDEX lsif_indexes_state ON lsif_indexes USING btree (state);\n\nCREATE INDEX lsif_nearest_uploads_links_repository_id_ancestor_commit_bytea ON lsif_nearest_uploads_links USING btree (repository_id, ancestor_commit_bytea);\n\nCREATE INDEX lsif_nearest_uploads_links_repository_id_commit_bytea ON lsif_nearest_uploads_links USING btree (repository_id, commit_bytea);\n\nCREATE INDEX lsif_nearest_uploads_repository_id_commit_bytea ON lsif_nearest_uploads USING btree (repository_id, commit_bytea);\n\nCREATE INDEX lsif_nearest_uploads_uploads ON lsif_nearest_uploads USING gin (uploads);\n\nCREATE INDEX lsif_packages_dump_id ON lsif_packages USING btree (dump_id);\n\nCREATE INDEX lsif_packages_scheme_name_version_dump_id ON lsif_packages USING btree (scheme, name, version, dump_id);\n\nCREATE INDEX lsif_references_dump_id ON lsif_references USING btree (dump_id);\n\nCREATE INDEX lsif_references_scheme_name_version_dump_id ON lsif_references USING btree (scheme, name, version, dump_id);\n\nCREATE INDEX lsif_uploads_associated_index_id ON lsif_uploads USING btree (associated_index_id);\n\nCREATE INDEX lsif_uploads_commit_last_checked_at ON lsif_uploads USING btree (commit_last_checked_at) WHERE (state \u003c\u003e 'deleted'::text);\n\nCREATE INDEX lsif_uploads_committed_at ON lsif_uploads USING btree (committed_at) WHERE (state = 'completed'::text);\n\nCREATE INDEX lsif_uploads_repository_id_commit ON lsif_uploads USING btree (repository_id, commit);\n\nCREATE UNIQUE INDEX lsif_uploads_repository_id_commit_root_indexer ON lsif_uploads USING btree (repository_id, commit, root, indexer) WHERE (state = 'completed'::text);\n\nCREATE INDEX lsif_uploads_state ON lsif_uploads USING btree (state);\n\nCREATE INDEX lsif_uploads_uploaded_at ON lsif_uploads USING btree (uploaded_at);\n\nCREATE INDEX lsif_uploads_visible_at_tip_repository_id_upload_id ON lsif_uploads_visible_at_tip USING btree (repository_id, upload_id);\n\nCREATE INDEX notebook_stars_user_id_idx ON notebook_stars USING btree (user_id);\n\nCREATE INDEX notebooks_blocks_tsvector_idx ON notebooks USING gin (blocks_tsvector);\n\nCREATE INDEX notebooks_namespace_org_id_idx ON notebooks USING btree (namespace_org_id);\n\nCREATE INDEX notebooks_namespace_user_id_idx ON notebooks USING btree (namespace_user_id);\n\nCREATE INDEX notebooks_title_trgm_idx ON notebooks USING gin (title gin_trgm_ops);\n\nCREATE INDEX org_invitations_org_id ON org_invitations USING btree (org_id) WHERE (deleted_at IS NULL);\n\nCREATE INDEX org_invitations_recipient_user_id ON org_invitations USING btree (recipient_user_id) WHERE (deleted_at IS NULL);\n\nCREATE UNIQUE INDEX orgs_name ON orgs USING btree (name) WHERE (deleted_at IS NULL);\n\nCREATE INDEX registry_extension_releases_registry_extension_id ON registry_extension_releases USING btree (registry_extension_id, release_tag, created_at DESC) WHERE (deleted_at IS NULL);\n\nCREATE INDEX registry_extension_releases_registry_extension_id_created_at ON registry_extension_releases USING btree (registry_extension_id, created_at) WHERE (deleted_at IS NULL);\n\nCREATE UNIQUE INDEX registry_extension_releases_version ON registry_extension_releases USING btree (registry_extension_id, release_version) WHERE (release_version IS NOT NULL);\n\nCREATE UNIQUE INDEX registry_extensions_publisher_name ON registry_extensions USING btree (COALESCE(publisher_user_id, 0), COALESCE(publisher_org_id, 0), name) WHERE (deleted_at IS NULL);\n\nCREATE UNIQUE INDEX registry_extensions_uuid ON registry_extensions USING btree (uuid);\n\nCREATE INDEX repo_archived ON repo USING btree (archived);\n\nCREATE INDEX repo_blocked_idx ON repo USING btree (((blocked IS NOT NULL)));\n\nCREATE INDEX repo_created_at ON repo USING btree (created_at);\n\nCREATE UNIQUE INDEX repo_external_unique_idx ON repo USING btree (external_service_type, external_service_id, external_id);\n\nCREATE INDEX repo_fork ON repo USING btree (fork);\n\nCREATE INDEX repo_hashed_name_idx ON repo USING btree (sha256((lower((name)::text))::bytea)) WHERE (deleted_at IS NULL);\n\nCREATE INDEX repo_is_not_blocked_idx ON repo USING btree (((blocked IS NULL)));\n\nCREATE INDEX repo_metadata_gin_idx ON repo USING gin (metadata);\n\nCREATE INDEX repo_name_case_sensitive_trgm_idx ON repo USING gin (((name)::text) gin_trgm_ops);\n\nCREATE INDEX repo_name_idx ON repo USING btree (lower((name)::text) COLLATE \"C\");\n\nCREATE INDEX repo_name_trgm ON repo USING gin (lower((name)::text) gin_trgm_ops);\n\nCREATE INDEX repo_non_deleted_id_name_idx ON repo USING btree (id, name) WHERE (deleted_at IS NULL);\n\nCREATE INDEX repo_private ON repo USING btree (private);\n\nCREATE INDEX repo_stars_desc_id_desc_idx ON repo USING btree (stars DESC NULLS LAST, id DESC) WHERE ((deleted_at IS NULL) AND (blocked IS NULL));\n\nCREATE INDEX repo_stars_idx ON repo USING btree (stars DESC NULLS LAST);\n\nCREATE INDEX repo_uri_idx ON repo USING btree (uri);\n\nCREATE UNIQUE INDEX search_contexts_name_namespace_org_id_unique ON search_contexts USING btree (name, namespace_org_id) WHERE (namespace_org_id IS NOT NULL);\n\nCREATE UNIQUE INDEX search_contexts_name_namespace_user_id_unique ON search_contexts USING btree (name, namespace_user_id) WHERE (namespace_user_id IS NOT NULL);\n\nCREATE UNIQUE INDEX search_contexts_name_without_namespace_unique ON search_contexts USING btree (name) WHERE ((namespace_user_id IS NULL) AND (namespace_org_id IS NULL));\n\nCREATE INDEX search_contexts_query_idx ON search_contexts USING btree (query);\n\nCREATE INDEX security_event_logs_timestamp ON security_event_logs USING btree (\"timestamp\");\n\nCREATE INDEX settings_global_id ON settings USING btree (id DESC) WHERE ((user_id IS NULL) AND (org_id IS NULL));\n\nCREATE INDEX settings_org_id_idx ON settings USING btree (org_id);\n\nCREATE INDEX settings_user_id_idx ON settings USING btree (user_id);\n\nCREATE UNIQUE INDEX sub_repo_permissions_repo_id_user_id_version_uindex ON sub_repo_permissions USING btree (repo_id, user_id, version);\n\nCREATE INDEX sub_repo_perms_user_id ON sub_repo_permissions USING btree (user_id);\n\nCREATE INDEX user_credentials_credential_idx ON user_credentials USING btree (((encryption_key_id = ANY (ARRAY[''::text, 'previously-migrated'::text]))));\n\nCREATE UNIQUE INDEX user_emails_user_id_is_primary_idx ON user_emails USING btree (user_id, is_primary) WHERE (is_primary = true);\n\nCREATE UNIQUE INDEX user_external_accounts_account ON user_external_accounts USING btree (service_type, service_id, client_id, account_id) WHERE (deleted_at IS NULL);\n\nCREATE INDEX user_external_accounts_user_id ON user_external_accounts USING btree (user_id) WHERE (deleted_at IS NULL);\n\nCREATE UNIQUE INDEX users_billing_customer_id ON users USING btree (billing_customer_id) WHERE (deleted_at IS NULL);\n\nCREATE INDEX users_created_at_idx ON users USING btree (created_at);\n\nCREATE UNIQUE INDEX users_username ON users USING btree (username) WHERE (deleted_at IS NULL);\n\nCREATE INDEX webhook_logs_external_service_id_idx ON webhook_logs USING btree (external_service_id);\n\nCREATE INDEX webhook_logs_received_at_idx ON webhook_logs USING btree (received_at);\n\nCREATE INDEX webhook_logs_status_code_idx ON webhook_logs USING btree (status_code);\n\nCREATE TRIGGER trig_delete_batch_change_reference_on_changesets AFTER DELETE ON batch_changes FOR EACH ROW EXECUTE FUNCTION delete_batch_change_reference_on_changesets();\n\nCREATE TRIGGER trig_delete_repo_ref_on_external_service_repos AFTER UPDATE OF deleted_at ON repo FOR EACH ROW EXECUTE FUNCTION delete_repo_ref_on_external_service_repos();\n\nCREATE TRIGGER trig_invalidate_session_on_password_change BEFORE UPDATE OF passwd ON users FOR EACH ROW EXECUTE FUNCTION invalidate_session_for_userid_on_password_change();\n\nCREATE TRIGGER trig_soft_delete_user_reference_on_external_service AFTER UPDATE OF deleted_at ON users FOR EACH ROW EXECUTE FUNCTION soft_delete_user_reference_on_external_service();\n\nCREATE TRIGGER versions_insert BEFORE INSERT ON versions FOR EACH ROW EXECUTE FUNCTION versions_insert_row_trigger();\n\nALTER TABLE ONLY access_tokens\n ADD CONSTRAINT access_tokens_creator_user_id_fkey FOREIGN KEY (creator_user_id) REFERENCES users(id);\n\nALTER TABLE ONLY access_tokens\n ADD CONSTRAINT access_tokens_subject_user_id_fkey FOREIGN KEY (subject_user_id) REFERENCES users(id);\n\nALTER TABLE ONLY batch_changes\n ADD CONSTRAINT batch_changes_batch_spec_id_fkey FOREIGN KEY (batch_spec_id) REFERENCES batch_specs(id) DEFERRABLE;\n\nALTER TABLE ONLY batch_changes\n ADD CONSTRAINT batch_changes_initial_applier_id_fkey FOREIGN KEY (creator_id) REFERENCES users(id) ON DELETE SET NULL DEFERRABLE;\n\nALTER TABLE ONLY batch_changes\n ADD CONSTRAINT batch_changes_last_applier_id_fkey FOREIGN KEY (last_applier_id) REFERENCES users(id) ON DELETE SET NULL DEFERRABLE;\n\nALTER TABLE ONLY batch_changes\n ADD CONSTRAINT batch_changes_namespace_org_id_fkey FOREIGN KEY (namespace_org_id) REFERENCES orgs(id) ON DELETE CASCADE DEFERRABLE;\n\nALTER TABLE ONLY batch_changes\n ADD CONSTRAINT batch_changes_namespace_user_id_fkey FOREIGN KEY (namespace_user_id) REFERENCES users(id) ON DELETE CASCADE DEFERRABLE;\n\nALTER TABLE ONLY batch_spec_execution_cache_entries\n ADD CONSTRAINT batch_spec_execution_cache_entries_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE DEFERRABLE;\n\nALTER TABLE ONLY batch_spec_resolution_jobs\n ADD CONSTRAINT batch_spec_resolution_jobs_batch_spec_id_fkey FOREIGN KEY (batch_spec_id) REFERENCES batch_specs(id) ON DELETE CASCADE DEFERRABLE;\n\nALTER TABLE ONLY batch_spec_workspace_execution_jobs\n ADD CONSTRAINT batch_spec_workspace_execution_job_batch_spec_workspace_id_fkey FOREIGN KEY (batch_spec_workspace_id) REFERENCES batch_spec_workspaces(id) ON DELETE CASCADE DEFERRABLE;\n\nALTER TABLE ONLY batch_spec_workspace_execution_jobs\n ADD CONSTRAINT batch_spec_workspace_execution_jobs_access_token_id_fkey FOREIGN KEY (access_token_id) REFERENCES access_tokens(id) ON DELETE SET NULL DEFERRABLE;\n\nALTER TABLE ONLY batch_spec_workspaces\n ADD CONSTRAINT batch_spec_workspaces_batch_spec_id_fkey FOREIGN KEY (batch_spec_id) REFERENCES batch_specs(id) ON DELETE CASCADE DEFERRABLE;\n\nALTER TABLE ONLY batch_spec_workspaces\n ADD CONSTRAINT batch_spec_workspaces_repo_id_fkey FOREIGN KEY (repo_id) REFERENCES repo(id) DEFERRABLE;\n\nALTER TABLE ONLY batch_specs\n ADD CONSTRAINT batch_specs_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL DEFERRABLE;\n\nALTER TABLE ONLY changeset_events\n ADD CONSTRAINT changeset_events_changeset_id_fkey FOREIGN KEY (changeset_id) REFERENCES changesets(id) ON DELETE CASCADE DEFERRABLE;\n\nALTER TABLE ONLY changeset_jobs\n ADD CONSTRAINT changeset_jobs_batch_change_id_fkey FOREIGN KEY (batch_change_id) REFERENCES batch_changes(id) ON DELETE CASCADE DEFERRABLE;\n\nALTER TABLE ONLY changeset_jobs\n ADD CONSTRAINT changeset_jobs_changeset_id_fkey FOREIGN KEY (changeset_id) REFERENCES changesets(id) ON DELETE CASCADE DEFERRABLE;\n\nALTER TABLE ONLY changeset_jobs\n ADD CONSTRAINT changeset_jobs_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE DEFERRABLE;\n\nALTER TABLE ONLY changeset_specs\n ADD CONSTRAINT changeset_specs_batch_spec_id_fkey FOREIGN KEY (batch_spec_id) REFERENCES batch_specs(id) ON DELETE CASCADE DEFERRABLE;\n\nALTER TABLE ONLY changeset_specs\n ADD CONSTRAINT changeset_specs_repo_id_fkey FOREIGN KEY (repo_id) REFERENCES repo(id) DEFERRABLE;\n\nALTER TABLE ONLY changeset_specs\n ADD CONSTRAINT changeset_specs_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL DEFERRABLE;\n\nALTER TABLE ONLY changesets\n ADD CONSTRAINT changesets_changeset_spec_id_fkey FOREIGN KEY (current_spec_id) REFERENCES changeset_specs(id) DEFERRABLE;\n\nALTER TABLE ONLY changesets\n ADD CONSTRAINT changesets_owned_by_batch_spec_id_fkey FOREIGN KEY (owned_by_batch_change_id) REFERENCES batch_changes(id) ON DELETE SET NULL DEFERRABLE;\n\nALTER TABLE ONLY changesets\n ADD CONSTRAINT changesets_previous_spec_id_fkey FOREIGN KEY (previous_spec_id) REFERENCES changeset_specs(id) DEFERRABLE;\n\nALTER TABLE ONLY changesets\n ADD CONSTRAINT changesets_repo_id_fkey FOREIGN KEY (repo_id) REFERENCES repo(id) ON DELETE CASCADE DEFERRABLE;\n\nALTER TABLE ONLY cm_action_jobs\n ADD CONSTRAINT cm_action_jobs_email_fk FOREIGN KEY (email) REFERENCES cm_emails(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_action_jobs\n ADD CONSTRAINT cm_action_jobs_slack_webhook_fkey FOREIGN KEY (slack_webhook) REFERENCES cm_slack_webhooks(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_action_jobs\n ADD CONSTRAINT cm_action_jobs_trigger_event_fk FOREIGN KEY (trigger_event) REFERENCES cm_trigger_jobs(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_action_jobs\n ADD CONSTRAINT cm_action_jobs_webhook_fkey FOREIGN KEY (webhook) REFERENCES cm_webhooks(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_emails\n ADD CONSTRAINT cm_emails_changed_by_fk FOREIGN KEY (changed_by) REFERENCES users(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_emails\n ADD CONSTRAINT cm_emails_created_by_fk FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_emails\n ADD CONSTRAINT cm_emails_monitor FOREIGN KEY (monitor) REFERENCES cm_monitors(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_last_searched\n ADD CONSTRAINT cm_last_searched_monitor_id_fkey FOREIGN KEY (monitor_id) REFERENCES cm_monitors(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_monitors\n ADD CONSTRAINT cm_monitors_changed_by_fk FOREIGN KEY (changed_by) REFERENCES users(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_monitors\n ADD CONSTRAINT cm_monitors_created_by_fk FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_monitors\n ADD CONSTRAINT cm_monitors_org_id_fk FOREIGN KEY (namespace_org_id) REFERENCES orgs(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_monitors\n ADD CONSTRAINT cm_monitors_user_id_fk FOREIGN KEY (namespace_user_id) REFERENCES users(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_recipients\n ADD CONSTRAINT cm_recipients_emails FOREIGN KEY (email) REFERENCES cm_emails(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_recipients\n ADD CONSTRAINT cm_recipients_org_id_fk FOREIGN KEY (namespace_org_id) REFERENCES orgs(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_recipients\n ADD CONSTRAINT cm_recipients_user_id_fk FOREIGN KEY (namespace_user_id) REFERENCES users(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_slack_webhooks\n ADD CONSTRAINT cm_slack_webhooks_changed_by_fkey FOREIGN KEY (changed_by) REFERENCES users(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_slack_webhooks\n ADD CONSTRAINT cm_slack_webhooks_created_by_fkey FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_slack_webhooks\n ADD CONSTRAINT cm_slack_webhooks_monitor_fkey FOREIGN KEY (monitor) REFERENCES cm_monitors(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_trigger_jobs\n ADD CONSTRAINT cm_trigger_jobs_query_fk FOREIGN KEY (query) REFERENCES cm_queries(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_queries\n ADD CONSTRAINT cm_triggers_changed_by_fk FOREIGN KEY (changed_by) REFERENCES users(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_queries\n ADD CONSTRAINT cm_triggers_created_by_fk FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_queries\n ADD CONSTRAINT cm_triggers_monitor FOREIGN KEY (monitor) REFERENCES cm_monitors(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_webhooks\n ADD CONSTRAINT cm_webhooks_changed_by_fkey FOREIGN KEY (changed_by) REFERENCES users(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_webhooks\n ADD CONSTRAINT cm_webhooks_created_by_fkey FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY cm_webhooks\n ADD CONSTRAINT cm_webhooks_monitor_fkey FOREIGN KEY (monitor) REFERENCES cm_monitors(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY discussion_comments\n ADD CONSTRAINT discussion_comments_author_user_id_fkey FOREIGN KEY (author_user_id) REFERENCES users(id) ON DELETE RESTRICT;\n\nALTER TABLE ONLY discussion_comments\n ADD CONSTRAINT discussion_comments_thread_id_fkey FOREIGN KEY (thread_id) REFERENCES discussion_threads(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY discussion_mail_reply_tokens\n ADD CONSTRAINT discussion_mail_reply_tokens_thread_id_fkey FOREIGN KEY (thread_id) REFERENCES discussion_threads(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY discussion_mail_reply_tokens\n ADD CONSTRAINT discussion_mail_reply_tokens_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE RESTRICT;\n\nALTER TABLE ONLY discussion_threads\n ADD CONSTRAINT discussion_threads_author_user_id_fkey FOREIGN KEY (author_user_id) REFERENCES users(id) ON DELETE RESTRICT;\n\nALTER TABLE ONLY discussion_threads\n ADD CONSTRAINT discussion_threads_target_repo_id_fk FOREIGN KEY (target_repo_id) REFERENCES discussion_threads_target_repo(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY discussion_threads_target_repo\n ADD CONSTRAINT discussion_threads_target_repo_repo_id_fkey FOREIGN KEY (repo_id) REFERENCES repo(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY discussion_threads_target_repo\n ADD CONSTRAINT discussion_threads_target_repo_thread_id_fkey FOREIGN KEY (thread_id) REFERENCES discussion_threads(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY external_service_repos\n ADD CONSTRAINT external_service_repos_external_service_id_fkey FOREIGN KEY (external_service_id) REFERENCES external_services(id) ON DELETE CASCADE DEFERRABLE;\n\nALTER TABLE ONLY external_service_repos\n ADD CONSTRAINT external_service_repos_org_id_fkey FOREIGN KEY (org_id) REFERENCES orgs(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY external_service_repos\n ADD CONSTRAINT external_service_repos_repo_id_fkey FOREIGN KEY (repo_id) REFERENCES repo(id) ON DELETE CASCADE DEFERRABLE;\n\nALTER TABLE ONLY external_service_repos\n ADD CONSTRAINT external_service_repos_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE DEFERRABLE;\n\nALTER TABLE ONLY external_service_sync_jobs\n ADD CONSTRAINT external_services_id_fk FOREIGN KEY (external_service_id) REFERENCES external_services(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY external_services\n ADD CONSTRAINT external_services_namepspace_user_id_fkey FOREIGN KEY (namespace_user_id) REFERENCES users(id) ON DELETE CASCADE DEFERRABLE;\n\nALTER TABLE ONLY external_services\n ADD CONSTRAINT external_services_namespace_org_id_fkey FOREIGN KEY (namespace_org_id) REFERENCES orgs(id) ON DELETE CASCADE DEFERRABLE;\n\nALTER TABLE ONLY feature_flag_overrides\n ADD CONSTRAINT feature_flag_overrides_flag_name_fkey FOREIGN KEY (flag_name) REFERENCES feature_flags(flag_name) ON UPDATE CASCADE ON DELETE CASCADE;\n\nALTER TABLE ONLY feature_flag_overrides\n ADD CONSTRAINT feature_flag_overrides_namespace_org_id_fkey FOREIGN KEY (namespace_org_id) REFERENCES orgs(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY feature_flag_overrides\n ADD CONSTRAINT feature_flag_overrides_namespace_user_id_fkey FOREIGN KEY (namespace_user_id) REFERENCES users(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY gitserver_repos\n ADD CONSTRAINT gitserver_repos_repo_id_fkey FOREIGN KEY (repo_id) REFERENCES repo(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY insights_query_runner_jobs_dependencies\n ADD CONSTRAINT insights_query_runner_jobs_dependencies_fk_job_id FOREIGN KEY (job_id) REFERENCES insights_query_runner_jobs(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY lsif_dependency_syncing_jobs\n ADD CONSTRAINT lsif_dependency_indexing_jobs_upload_id_fkey FOREIGN KEY (upload_id) REFERENCES lsif_uploads(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY lsif_dependency_indexing_jobs\n ADD CONSTRAINT lsif_dependency_indexing_jobs_upload_id_fkey1 FOREIGN KEY (upload_id) REFERENCES lsif_uploads(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY lsif_index_configuration\n ADD CONSTRAINT lsif_index_configuration_repository_id_fkey FOREIGN KEY (repository_id) REFERENCES repo(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY lsif_packages\n ADD CONSTRAINT lsif_packages_dump_id_fkey FOREIGN KEY (dump_id) REFERENCES lsif_uploads(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY lsif_references\n ADD CONSTRAINT lsif_references_dump_id_fkey FOREIGN KEY (dump_id) REFERENCES lsif_uploads(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY lsif_retention_configuration\n ADD CONSTRAINT lsif_retention_configuration_repository_id_fkey FOREIGN KEY (repository_id) REFERENCES repo(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY names\n ADD CONSTRAINT names_org_id_fkey FOREIGN KEY (org_id) REFERENCES orgs(id) ON UPDATE CASCADE ON DELETE CASCADE;\n\nALTER TABLE ONLY names\n ADD CONSTRAINT names_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON UPDATE CASCADE ON DELETE CASCADE;\n\nALTER TABLE ONLY notebook_stars\n ADD CONSTRAINT notebook_stars_notebook_id_fkey FOREIGN KEY (notebook_id) REFERENCES notebooks(id) ON DELETE CASCADE DEFERRABLE;\n\nALTER TABLE ONLY notebook_stars\n ADD CONSTRAINT notebook_stars_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE DEFERRABLE;\n\nALTER TABLE ONLY notebooks\n ADD CONSTRAINT notebooks_creator_user_id_fkey FOREIGN KEY (creator_user_id) REFERENCES users(id) ON DELETE SET NULL DEFERRABLE;\n\nALTER TABLE ONLY notebooks\n ADD CONSTRAINT notebooks_namespace_org_id_fkey FOREIGN KEY (namespace_org_id) REFERENCES orgs(id) ON DELETE SET NULL DEFERRABLE;\n\nALTER TABLE ONLY notebooks\n ADD CONSTRAINT notebooks_namespace_user_id_fkey FOREIGN KEY (namespace_user_id) REFERENCES users(id) ON DELETE SET NULL DEFERRABLE;\n\nALTER TABLE ONLY notebooks\n ADD CONSTRAINT notebooks_updater_user_id_fkey FOREIGN KEY (updater_user_id) REFERENCES users(id) ON DELETE SET NULL DEFERRABLE;\n\nALTER TABLE ONLY org_invitations\n ADD CONSTRAINT org_invitations_org_id_fkey FOREIGN KEY (org_id) REFERENCES orgs(id);\n\nALTER TABLE ONLY org_invitations\n ADD CONSTRAINT org_invitations_recipient_user_id_fkey FOREIGN KEY (recipient_user_id) REFERENCES users(id);\n\nALTER TABLE ONLY org_invitations\n ADD CONSTRAINT org_invitations_sender_user_id_fkey FOREIGN KEY (sender_user_id) REFERENCES users(id);\n\nALTER TABLE ONLY org_members\n ADD CONSTRAINT org_members_references_orgs FOREIGN KEY (org_id) REFERENCES orgs(id) ON DELETE RESTRICT;\n\nALTER TABLE ONLY org_members\n ADD CONSTRAINT org_members_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE RESTRICT;\n\nALTER TABLE ONLY org_stats\n ADD CONSTRAINT org_stats_org_id_fkey FOREIGN KEY (org_id) REFERENCES orgs(id) ON DELETE CASCADE DEFERRABLE;\n\nALTER TABLE ONLY out_of_band_migrations_errors\n ADD CONSTRAINT out_of_band_migrations_errors_migration_id_fkey FOREIGN KEY (migration_id) REFERENCES out_of_band_migrations(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY product_licenses\n ADD CONSTRAINT product_licenses_product_subscription_id_fkey FOREIGN KEY (product_subscription_id) REFERENCES product_subscriptions(id);\n\nALTER TABLE ONLY product_subscriptions\n ADD CONSTRAINT product_subscriptions_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id);\n\nALTER TABLE ONLY registry_extension_releases\n ADD CONSTRAINT registry_extension_releases_creator_user_id_fkey FOREIGN KEY (creator_user_id) REFERENCES users(id);\n\nALTER TABLE ONLY registry_extension_releases\n ADD CONSTRAINT registry_extension_releases_registry_extension_id_fkey FOREIGN KEY (registry_extension_id) REFERENCES registry_extensions(id) ON UPDATE CASCADE ON DELETE CASCADE;\n\nALTER TABLE ONLY registry_extensions\n ADD CONSTRAINT registry_extensions_publisher_org_id_fkey FOREIGN KEY (publisher_org_id) REFERENCES orgs(id);\n\nALTER TABLE ONLY registry_extensions\n ADD CONSTRAINT registry_extensions_publisher_user_id_fkey FOREIGN KEY (publisher_user_id) REFERENCES users(id);\n\nALTER TABLE ONLY saved_searches\n ADD CONSTRAINT saved_searches_org_id_fkey FOREIGN KEY (org_id) REFERENCES orgs(id);\n\nALTER TABLE ONLY saved_searches\n ADD CONSTRAINT saved_searches_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id);\n\nALTER TABLE ONLY search_context_repos\n ADD CONSTRAINT search_context_repos_repo_id_fk FOREIGN KEY (repo_id) REFERENCES repo(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY search_context_repos\n ADD CONSTRAINT search_context_repos_search_context_id_fk FOREIGN KEY (search_context_id) REFERENCES search_contexts(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY search_contexts\n ADD CONSTRAINT search_contexts_namespace_org_id_fk FOREIGN KEY (namespace_org_id) REFERENCES orgs(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY search_contexts\n ADD CONSTRAINT search_contexts_namespace_user_id_fk FOREIGN KEY (namespace_user_id) REFERENCES users(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY settings\n ADD CONSTRAINT settings_author_user_id_fkey FOREIGN KEY (author_user_id) REFERENCES users(id) ON DELETE RESTRICT;\n\nALTER TABLE ONLY settings\n ADD CONSTRAINT settings_references_orgs FOREIGN KEY (org_id) REFERENCES orgs(id) ON DELETE RESTRICT;\n\nALTER TABLE ONLY settings\n ADD CONSTRAINT settings_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE RESTRICT;\n\nALTER TABLE ONLY sub_repo_permissions\n ADD CONSTRAINT sub_repo_permissions_repo_id_fk FOREIGN KEY (repo_id) REFERENCES repo(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY sub_repo_permissions\n ADD CONSTRAINT sub_repo_permissions_users_id_fk FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY survey_responses\n ADD CONSTRAINT survey_responses_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id);\n\nALTER TABLE ONLY temporary_settings\n ADD CONSTRAINT temporary_settings_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY user_credentials\n ADD CONSTRAINT user_credentials_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE DEFERRABLE;\n\nALTER TABLE ONLY user_emails\n ADD CONSTRAINT user_emails_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id);\n\nALTER TABLE ONLY user_external_accounts\n ADD CONSTRAINT user_external_accounts_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id);\n\nALTER TABLE ONLY user_public_repos\n ADD CONSTRAINT user_public_repos_repo_id_fkey FOREIGN KEY (repo_id) REFERENCES repo(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY user_public_repos\n ADD CONSTRAINT user_public_repos_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY webhook_logs\n ADD CONSTRAINT webhook_logs_external_service_id_fkey FOREIGN KEY (external_service_id) REFERENCES external_services(id) ON UPDATE CASCADE ON DELETE CASCADE;\n\nINSERT INTO lsif_configuration_policies VALUES (1, NULL, 'Default tip-of-branch retention policy', 'GIT_TREE', '*', true, 2016, false, false, 0, false, true, NULL, NULL);\nINSERT INTO lsif_configuration_policies VALUES (2, NULL, 'Default tag retention policy', 'GIT_TAG', '*', true, 8064, false, false, 0, false, true, NULL, NULL);\nINSERT INTO lsif_configuration_policies VALUES (3, NULL, 'Default commit retention policy', 'GIT_TREE', '*', true, 168, true, false, 0, false, true, NULL, NULL);\n\nSELECT pg_catalog.setval('lsif_configuration_policies_id_seq', 3, true);", + "DownQuery": "-- Nothing", + "Privileged": false, + "NonIdempotent": true, + "Parents": [ + 1648051770 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1648524019, + "Name": "int64-ids-user-pending-permissions", + "UpQuery": "TRUNCATE TABLE user_pending_permissions;\nTRUNCATE TABLE repo_pending_permissions;\n\nALTER TABLE IF EXISTS user_pending_permissions ALTER COLUMN id TYPE BIGINT;\nALTER TABLE IF EXISTS repo_pending_permissions ALTER COLUMN user_ids_ints TYPE BIGINT[];\n\nALTER SEQUENCE IF EXISTS user_pending_permissions_id_seq RESTART;", + "DownQuery": "TRUNCATE TABLE user_pending_permissions;\nTRUNCATE TABLE repo_pending_permissions;\n\nALTER TABLE IF EXISTS user_pending_permissions ALTER COLUMN id TYPE int;\nALTER TABLE IF EXISTS repo_pending_permissions ALTER COLUMN user_ids_ints TYPE int[];\n\nALTER SEQUENCE IF EXISTS user_pending_permissions_id_seq RESTART;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1648195639 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1648628900, + "Name": "rename_localclone_worker_table", + "UpQuery": "-- drop view\nDROP VIEW IF EXISTS gitserver_localclone_jobs_with_repo_name;\n\n-- drop the table\nDROP TABLE IF EXISTS gitserver_localclone_jobs;\n\n-- create the new table\nCREATE TABLE IF NOT EXISTS gitserver_relocator_jobs (\n id SERIAL PRIMARY KEY,\n state text DEFAULT 'queued',\n queued_at timestamptz DEFAULT NOW(),\n failure_message text,\n started_at timestamp with time zone,\n finished_at timestamp with time zone,\n process_after timestamp with time zone,\n num_resets integer not null DEFAULT 0,\n num_failures integer not null DEFAULT 0,\n last_heartbeat_at timestamp with time zone,\n execution_logs json[],\n worker_hostname text not null DEFAULT '',\n\n repo_id integer not null,\n source_hostname text not null,\n dest_hostname text not null,\n delete_source boolean not null DEFAULT false\n);\n\n-- create the view\nCREATE OR REPLACE VIEW gitserver_relocator_jobs_with_repo_name AS\n SELECT glj.*, r.name AS repo_name\n FROM gitserver_relocator_jobs glj\n JOIN repo r ON r.id = glj.repo_id;", + "DownQuery": "-- drop view\nDROP VIEW IF EXISTS gitserver_relocator_jobs_with_repo_name;\n\n-- drop the table\nDROP TABLE IF EXISTS gitserver_relocator_jobs;\n\n-- create the old table\nCREATE TABLE IF NOT EXISTS gitserver_localclone_jobs (\n id SERIAL PRIMARY KEY,\n state text DEFAULT 'queued',\n queued_at timestamptz DEFAULT NOW(),\n failure_message text,\n started_at timestamp with time zone,\n finished_at timestamp with time zone,\n process_after timestamp with time zone,\n num_resets integer not null DEFAULT 0,\n num_failures integer not null DEFAULT 0,\n last_heartbeat_at timestamp with time zone,\n execution_logs json[],\n worker_hostname text not null DEFAULT '',\n\n repo_id integer not null,\n source_hostname text not null,\n dest_hostname text not null,\n delete_source boolean not null DEFAULT false\n);\n\n-- create the old view\nCREATE OR REPLACE VIEW gitserver_localclone_jobs_with_repo_name AS\n SELECT glj.*, r.name AS repo_name\n FROM gitserver_localclone_jobs glj\n JOIN repo r ON r.id = glj.repo_id;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1648195639 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1649159359, + "Name": "batch_spec_resolution_user_id", + "UpQuery": "ALTER TABLE batch_spec_resolution_jobs\n ADD COLUMN IF NOT EXISTS initiator_id integer,\n ADD FOREIGN KEY (initiator_id) REFERENCES users(id) ON UPDATE CASCADE ON DELETE NO ACTION DEFERRABLE;\n\nUPDATE batch_spec_resolution_jobs SET initiator_id = (SELECT bs.user_id FROM batch_specs bs WHERE bs.id = batch_spec_id);", + "DownQuery": "ALTER TABLE batch_spec_resolution_jobs\n DROP COLUMN IF EXISTS initiator_id;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1648524019, + 1648628900 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1649269601, + "Name": "remove unused code monitor columns", + "UpQuery": "-- Perform migration here.\n--\n-- See /migrations/README.md. Highlights:\n-- * Make migrations idempotent (use IF EXISTS)\n-- * Make migrations backwards-compatible (old readers/writers must continue to work)\n-- * If you are using CREATE INDEX CONCURRENTLY, then make sure that only one statement\n-- is defined per file, and that each such statement is NOT wrapped in a transaction.\n-- Each such migration must also declare \"createIndexConcurrently: true\" in their\n-- associated metadata.yaml file.\n-- * If you are modifying Postgres extensions, you must also declare \"privileged: true\"\n-- in the associated metadata.yaml file.\n\nALTER TABLE cm_trigger_jobs\n DROP COLUMN IF EXISTS results;\nALTER TABLE cm_trigger_jobs\n DROP COLUMN IF EXISTS num_results;", + "DownQuery": "-- Undo the changes made in the up migration\n\nALTER TABLE cm_trigger_jobs\n ADD COLUMN IF NOT EXISTS results BOOLEAN;\nALTER TABLE cm_trigger_jobs\n ADD COLUMN IF NOT EXISTS num_results INTEGER;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1648524019, + 1648628900 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1649441222, + "Name": "lsif_uploads_audit_logging", + "UpQuery": "CREATE TABLE IF NOT EXISTS lsif_uploads_audit_logs (\n -- log entry columns\n log_timestamp timestamptz DEFAULT NOW(),\n record_deleted_at timestamptz,\n -- associated object columns\n upload_id integer not null,\n commit text not null,\n root text not null,\n repository_id integer not null,\n uploaded_at timestamptz not null,\n indexer text not null,\n indexer_version text,\n upload_size integer,\n associated_index_id integer,\n committed_at timestamptz,\n transition_columns hstore[]\n);\n\nCOMMENT ON COLUMN lsif_uploads_audit_logs.log_timestamp IS 'Timestamp for this log entry.';\nCOMMENT ON COLUMN lsif_uploads_audit_logs.record_deleted_at IS 'Set once the upload this entry is associated with is deleted. Once NOW() - record_deleted_at is above a certain threshold, this log entry will be deleted.';\nCOMMENT ON COLUMN lsif_uploads_audit_logs.transition_columns IS 'Array of changes that occurred to the upload for this entry, in the form of {\"column\"=\u003e\"\u003ccolumn name\u003e\", \"old\"=\u003e\"\u003cprevious value\u003e\", \"new\"=\u003e\"\u003cnew value\u003e\"}.';\n\nCREATE INDEX IF NOT EXISTS lsif_uploads_audit_logs_upload_id ON lsif_uploads_audit_logs USING btree (upload_id);\nCREATE INDEX IF NOT EXISTS lsif_uploads_audit_logs_timestamp ON lsif_uploads_audit_logs USING brin (log_timestamp);\n\n-- CREATE TYPE IF NOT EXISTS is not a thing, so we must drop it here,\n-- but also all the functions that reference the type...\nDROP FUNCTION IF EXISTS func_row_to_lsif_uploads_transition_columns;\nDROP FUNCTION IF EXISTS func_lsif_uploads_transition_columns_diff;\nDROP TYPE IF EXISTS lsif_uploads_transition_columns;\n\nCREATE TYPE lsif_uploads_transition_columns AS (\n state text,\n expired boolean,\n num_resets integer,\n num_failures integer,\n worker_hostname text,\n committed_at timestamptz\n);\n\nCOMMENT ON TYPE lsif_uploads_transition_columns IS 'A type containing the columns that make-up the set of tracked transition columns. Primarily used to create a nulled record due to `OLD` being unset in INSERT queries, and creating a nulled record with a subquery is not allowed.';\n\nCREATE OR REPLACE FUNCTION func_lsif_uploads_update() RETURNS TRIGGER AS $$\n BEGIN\n INSERT INTO lsif_uploads_audit_logs\n (upload_id, commit, root, repository_id, uploaded_at,\n indexer, indexer_version, upload_size, associated_index_id,\n committed_at, transition_columns)\n VALUES (\n NEW.id, NEW.commit, NEW.root, NEW.repository_id, NEW.uploaded_at,\n NEW.indexer, NEW.indexer_version, NEW.upload_size, NEW.associated_index_id,\n NEW.committed_at, func_lsif_uploads_transition_columns_diff(\n func_row_to_lsif_uploads_transition_columns(OLD),\n func_row_to_lsif_uploads_transition_columns(NEW)\n )\n );\n\n RETURN NEW;\n END;\n$$ LANGUAGE plpgsql;\n\nCREATE OR REPLACE FUNCTION func_lsif_uploads_delete() RETURNS TRIGGER AS $$\n BEGIN\n UPDATE lsif_uploads_audit_logs\n SET record_deleted_at = NOW()\n WHERE upload_id IN (\n SELECT id FROM OLD\n );\n\n RETURN NULL;\n END;\n$$ LANGUAGE plpgsql;\n\nCREATE OR REPLACE FUNCTION func_lsif_uploads_insert() RETURNS TRIGGER AS $$\n BEGIN\n INSERT INTO lsif_uploads_audit_logs\n (upload_id, commit, root, repository_id, uploaded_at,\n indexer, indexer_version, upload_size, associated_index_id,\n committed_at, transition_columns)\n VALUES (\n NEW.id, NEW.commit, NEW.root, NEW.repository_id, NEW.uploaded_at,\n NEW.indexer, NEW.indexer_version, NEW.upload_size, NEW.associated_index_id,\n NEW.committed_at, func_lsif_uploads_transition_columns_diff(\n (NULL, NULL, NULL, NULL, NULL, NULL),\n func_row_to_lsif_uploads_transition_columns(NEW)\n )\n );\n RETURN NULL;\n END;\n$$ LANGUAGE plpgsql;\n\nCREATE OR REPLACE FUNCTION func_row_to_lsif_uploads_transition_columns(\n rec record\n) RETURNS lsif_uploads_transition_columns AS $$\n BEGIN\n RETURN (rec.state, rec.expired, rec.num_resets, rec.num_failures, rec.worker_hostname, rec.committed_at);\n END;\n$$ LANGUAGE plpgsql;\n\nCOMMENT ON FUNCTION func_lsif_uploads_insert IS 'Transforms a record from the lsif_uploads table into an `lsif_uploads_transition_columns` type variable.';\n\nCREATE OR REPLACE FUNCTION func_lsif_uploads_transition_columns_diff(\n old lsif_uploads_transition_columns, new lsif_uploads_transition_columns\n) RETURNS hstore[] AS $$\n BEGIN\n -- array || NULL should be a noop, but that doesn't seem to be happening\n -- hence array_remove here\n RETURN array_remove(\n ARRAY[]::hstore[] ||\n CASE WHEN old.state IS DISTINCT FROM new.state THEN\n hstore(ARRAY['column', 'state', 'old', old.state, 'new', new.state])\n ELSE NULL\n END ||\n CASE WHEN old.expired IS DISTINCT FROM new.expired THEN\n hstore(ARRAY['column', 'expired', 'old', old.expired::text, 'new', new.expired::text])\n ELSE NULL\n END ||\n CASE WHEN old.num_resets IS DISTINCT FROM new.num_resets THEN\n hstore(ARRAY['column', 'num_resets', 'old', old.num_resets::text, 'new', new.num_resets::text])\n ELSE NULL\n END ||\n CASE WHEN old.num_failures IS DISTINCT FROM new.num_failures THEN\n hstore(ARRAY['column', 'num_failures', 'old', old.num_failures::text, 'new', new.num_failures::text])\n ELSE NULL\n END ||\n CASE WHEN old.worker_hostname IS DISTINCT FROM new.worker_hostname THEN\n hstore(ARRAY['column', 'worker_hostname', 'old', old.worker_hostname, 'new', new.worker_hostname])\n ELSE NULL\n END ||\n CASE WHEN old.committed_at IS DISTINCT FROM new.committed_at THEN\n hstore(ARRAY['column', 'committed_at', 'old', old.committed_at::text, 'new', new.committed_at::text])\n ELSE NULL\n END,\n NULL);\n END;\n$$ LANGUAGE plpgsql;\n\nCOMMENT ON FUNCTION func_lsif_uploads_transition_columns_diff IS 'Diffs two `lsif_uploads_transition_columns` values into an array of hstores, where each hstore is in the format {\"column\"=\u003e\"\u003ccolumn name\u003e\", \"old\"=\u003e\"\u003cprevious value\u003e\", \"new\"=\u003e\"\u003cnew value\u003e\"}.';\n\n-- CREATE OR REPLACE only supported in Postgres 14+\nDROP TRIGGER IF EXISTS trigger_lsif_uploads_update ON lsif_uploads;\nDROP TRIGGER IF EXISTS trigger_lsif_uploads_delete ON lsif_uploads;\nDROP TRIGGER IF EXISTS trigger_lsif_uploads_insert ON lsif_uploads;\n\nCREATE TRIGGER trigger_lsif_uploads_update\nBEFORE UPDATE OF state, num_resets, num_failures, worker_hostname, expired, committed_at\nON lsif_uploads\nFOR EACH ROW\nEXECUTE FUNCTION func_lsif_uploads_update();\n\nCREATE TRIGGER trigger_lsif_uploads_delete\nAFTER DELETE\nON lsif_uploads\nREFERENCING OLD TABLE AS OLD\nFOR EACH STATEMENT\nEXECUTE FUNCTION func_lsif_uploads_delete();\n\nCREATE TRIGGER trigger_lsif_uploads_insert\nAFTER INSERT\nON lsif_uploads\nFOR EACH ROW\nEXECUTE FUNCTION func_lsif_uploads_insert();", + "DownQuery": "DROP TRIGGER IF EXISTS trigger_lsif_uploads_update ON lsif_uploads;\nDROP TRIGGER IF EXISTS trigger_lsif_uploads_delete ON lsif_uploads;\nDROP TRIGGER IF EXISTS trigger_lsif_uploads_insert ON lsif_uploads;\n\nDROP FUNCTION IF EXISTS func_lsif_uploads_update;\nDROP FUNCTION IF EXISTS func_lsif_uploads_delete;\nDROP FUNCTION IF EXISTS func_lsif_uploads_insert;\nDROP FUNCTION IF EXISTS func_lsif_uploads_transition_columns_diff;\nDROP FUNCTION IF EXISTS func_row_to_lsif_uploads_transition_columns;\n\nDROP TABLE IF EXISTS lsif_uploads_audit_logs;\n\nDROP INDEX IF EXISTS lsif_uploads_audit_logs_upload_id;\nDROP INDEX IF EXISTS lsif_uploads_audit_logs_timestamp;\n\nDROP TYPE IF EXISTS lsif_uploads_transition_columns;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1649269601 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1649759318, + "Name": "change_default_invite_quota", + "UpQuery": "ALTER TABLE IF EXISTS users ALTER COLUMN invite_quota SET DEFAULT 100;", + "DownQuery": "-- Undo the changes made in the up migration\nALTER TABLE IF EXISTS users ALTER COLUMN invite_quota SET DEFAULT 15;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1649269601 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1649432863, + "Name": "no hash for code monitor last searched", + "UpQuery": "-- Perform migration here.\n--\n-- See /migrations/README.md. Highlights:\n-- * Make migrations idempotent (use IF EXISTS)\n-- * Make migrations backwards-compatible (old readers/writers must continue to work)\n-- * If you are using CREATE INDEX CONCURRENTLY, then make sure that only one statement\n-- is defined per file, and that each such statement is NOT wrapped in a transaction.\n-- Each such migration must also declare \"createIndexConcurrently: true\" in their\n-- associated metadata.yaml file.\n-- * If you are modifying Postgres extensions, you must also declare \"privileged: true\"\n-- in the associated metadata.yaml file.\n\nDELETE FROM cm_last_searched;\nALTER TABLE cm_last_searched\n DROP CONSTRAINT IF EXISTS cm_last_searched_pkey,\n DROP COLUMN IF EXISTS args_hash,\n ADD COLUMN IF NOT EXISTS repo_id INTEGER NOT NULL REFERENCES repo(id) ON DELETE CASCADE,\n ADD PRIMARY KEY (monitor_id, repo_id);", + "DownQuery": "-- Undo the changes made in the up migration\n\nALTER TABLE cm_last_searched\n DROP CONSTRAINT IF EXISTS cm_last_searched_pkey,\n DROP COLUMN IF EXISTS repo_id,\n ADD COLUMN IF NOT EXISTS args_hash bigint NOT NULL,\n ADD PRIMARY KEY (monitor_id, args_hash);", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1648524019, + 1648628900 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1650456734, + "Name": "configuration_policies_audit_logging", + "UpQuery": "CREATE TABLE IF NOT EXISTS configuration_policies_audit_logs (\n -- log entry columns\n log_timestamp timestamptz DEFAULT clock_timestamp(),\n record_deleted_at timestamptz,\n -- associated object columns\n policy_id integer not null,\n transition_columns hstore[]\n);\n\nCOMMENT ON COLUMN configuration_policies_audit_logs.log_timestamp IS 'Timestamp for this log entry.';\nCOMMENT ON COLUMN configuration_policies_audit_logs.record_deleted_at IS 'Set once the upload this entry is associated with is deleted. Once NOW() - record_deleted_at is above a certain threshold, this log entry will be deleted.';\nCOMMENT ON COLUMN configuration_policies_audit_logs.transition_columns IS 'Array of changes that occurred to the upload for this entry, in the form of {\"column\"=\u003e\"\u003ccolumn name\u003e\", \"old\"=\u003e\"\u003cprevious value\u003e\", \"new\"=\u003e\"\u003cnew value\u003e\"}.';\n\nCREATE INDEX IF NOT EXISTS configuration_policies_audit_logs_policy_id ON configuration_policies_audit_logs USING btree (policy_id);\nCREATE INDEX IF NOT EXISTS configuration_policies_audit_logs_timestamp ON configuration_policies_audit_logs USING brin (log_timestamp);\n\n-- CREATE TYPE IF NOT EXISTS is not a thing, so we must drop it here,\n-- but also all the functions that reference the type...\nDROP FUNCTION IF EXISTS func_row_to_configuration_policies_transition_columns;\nDROP FUNCTION IF EXISTS func_configuration_policies_transition_columns_diff;\nDROP TYPE IF EXISTS configuration_policies_transition_columns;\n\nCREATE TYPE configuration_policies_transition_columns AS (\n name text,\n type text,\n pattern text,\n retention_enabled boolean,\n retention_duration_hours integer,\n retain_intermediate_commits boolean,\n indexing_enabled boolean,\n index_commit_max_age_hours integer,\n index_intermediate_commits boolean,\n protected boolean,\n repository_patterns text[]\n);\n\nCOMMENT ON TYPE configuration_policies_transition_columns IS 'A type containing the columns that make-up the set of tracked transition columns. Primarily used to create a nulled record due to `OLD` being unset in INSERT queries, and creating a nulled record with a subquery is not allowed.';\n\nCREATE OR REPLACE FUNCTION func_configuration_policies_update() RETURNS TRIGGER AS $$\n DECLARE\n diff hstore[];\n BEGIN\n diff = func_configuration_policies_transition_columns_diff(\n func_row_to_configuration_policies_transition_columns(OLD),\n func_row_to_configuration_policies_transition_columns(NEW)\n );\n\n IF (array_length(diff, 1) \u003e 0) THEN\n INSERT INTO configuration_policies_audit_logs\n (policy_id, transition_columns)\n VALUES (\n NEW.id,\n diff\n );\n END IF;\n\n RETURN NEW;\n END;\n$$ LANGUAGE plpgsql;\n\nCREATE OR REPLACE FUNCTION func_configuration_policies_delete() RETURNS TRIGGER AS $$\n BEGIN\n UPDATE configuration_policies_audit_logs\n SET record_deleted_at = NOW()\n WHERE policy_id IN (\n SELECT id FROM OLD\n );\n\n RETURN NULL;\n END;\n$$ LANGUAGE plpgsql;\n\nCREATE OR REPLACE FUNCTION func_configuration_policies_insert() RETURNS TRIGGER AS $$\n BEGIN\n INSERT INTO configuration_policies_audit_logs\n (policy_id, transition_columns)\n VALUES (\n NEW.id,\n func_configuration_policies_transition_columns_diff(\n (NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),\n func_row_to_configuration_policies_transition_columns(NEW)\n )\n );\n RETURN NULL;\n END;\n$$ LANGUAGE plpgsql;\n\n\nCREATE OR REPLACE FUNCTION func_row_to_configuration_policies_transition_columns(\n rec record\n) RETURNS configuration_policies_transition_columns AS $$\n BEGIN\n RETURN (\n rec.name, rec.type, rec.pattern,\n rec.retention_enabled, rec.retention_duration_hours, rec.retain_intermediate_commits,\n rec.indexing_enabled, rec.index_commit_max_age_hours, rec.index_intermediate_commits,\n rec.protected, rec.repository_patterns);\n END;\n$$ LANGUAGE plpgsql;\n\nCOMMENT ON FUNCTION func_configuration_policies_insert IS 'Transforms a record from the configuration_policies table into an `configuration_policies_transition_columns` type variable.';\n\nCREATE OR REPLACE FUNCTION func_configuration_policies_transition_columns_diff(\n old configuration_policies_transition_columns, new configuration_policies_transition_columns\n) RETURNS hstore[] AS $$\n BEGIN\n -- array || NULL should be a noop, but that doesn't seem to be happening\n -- hence array_remove here\n RETURN array_remove(\n ARRAY[]::hstore[] ||\n CASE WHEN old.name IS DISTINCT FROM new.name THEN\n hstore(ARRAY['column', 'name', 'old', old.name, 'new', new.name])\n ELSE NULL\n END ||\n CASE WHEN old.type IS DISTINCT FROM new.type THEN\n hstore(ARRAY['column', 'type', 'old', old.type, 'new', new.type])\n ELSE NULL\n END ||\n CASE WHEN old.pattern IS DISTINCT FROM new.pattern THEN\n hstore(ARRAY['column', 'pattern', 'old', old.pattern, 'new', new.pattern])\n ELSE NULL\n END ||\n CASE WHEN old.retention_enabled IS DISTINCT FROM new.retention_enabled THEN\n hstore(ARRAY['column', 'retention_enabled', 'old', old.retention_enabled::text, 'new', new.retention_enabled::text])\n ELSE NULL\n END ||\n CASE WHEN old.retention_duration_hours IS DISTINCT FROM new.retention_duration_hours THEN\n hstore(ARRAY['column', 'retention_duration_hours', 'old', old.retention_duration_hours::text, 'new', new.retention_duration_hours::text])\n ELSE NULL\n END ||\n CASE WHEN old.indexing_enabled IS DISTINCT FROM new.indexing_enabled THEN\n hstore(ARRAY['column', 'indexing_enabled', 'old', old.indexing_enabled::text, 'new', new.indexing_enabled::text])\n ELSE NULL\n END ||\n CASE WHEN old.index_commit_max_age_hours IS DISTINCT FROM new.index_commit_max_age_hours THEN\n hstore(ARRAY['column', 'index_commit_max_age_hours', 'old', old.index_commit_max_age_hours::text, 'new', new.index_commit_max_age_hours::text])\n ELSE NULL\n END ||\n CASE WHEN old.index_intermediate_commits IS DISTINCT FROM new.index_intermediate_commits THEN\n hstore(ARRAY['column', 'index_intermediate_commits', 'old', old.index_intermediate_commits::text, 'new', new.index_intermediate_commits::text])\n ELSE NULL\n END ||\n CASE WHEN old.protected IS DISTINCT FROM new.protected THEN\n hstore(ARRAY['column', 'protected', 'old', old.protected::text, 'new', new.protected::text])\n ELSE NULL\n END ||\n CASE WHEN old.repository_patterns IS DISTINCT FROM new.repository_patterns THEN\n hstore(ARRAY['column', 'repository_patterns', 'old', old.repository_patterns::text, 'new', new.repository_patterns::text])\n ELSE NULL\n END,\n NULL);\n END;\n$$ LANGUAGE plpgsql;\n\nCOMMENT ON FUNCTION func_configuration_policies_transition_columns_diff IS 'Diffs two `configuration_policies_transition_columns` values into an array of hstores, where each hstore is in the format {\"column\"=\u003e\"\u003ccolumn name\u003e\", \"old\"=\u003e\"\u003cprevious value\u003e\", \"new\"=\u003e\"\u003cnew value\u003e\"}.';\n\n-- CREATE OR REPLACE only supported in Postgres 14+\nDROP TRIGGER IF EXISTS trigger_configuration_policies_update ON lsif_configuration_policies;\nDROP TRIGGER IF EXISTS trigger_configuration_policies_delete ON lsif_configuration_policies;\nDROP TRIGGER IF EXISTS trigger_configuration_policies_insert ON lsif_configuration_policies;\n\nCREATE TRIGGER trigger_configuration_policies_update\nBEFORE UPDATE OF name, pattern, retention_enabled, retention_duration_hours, type, retain_intermediate_commits\nON lsif_configuration_policies\nFOR EACH ROW\nEXECUTE FUNCTION func_configuration_policies_update();\n\nCREATE TRIGGER trigger_configuration_policies_delete\nAFTER DELETE\nON lsif_configuration_policies\nREFERENCING OLD TABLE AS OLD\nFOR EACH STATEMENT\nEXECUTE FUNCTION func_configuration_policies_delete();\n\nCREATE TRIGGER trigger_configuration_policies_insert\nAFTER INSERT\nON lsif_configuration_policies\nFOR EACH ROW\nEXECUTE FUNCTION func_configuration_policies_insert();", + "DownQuery": "DROP TRIGGER IF EXISTS trigger_configuration_policies_update ON lsif_configuration_policies;\nDROP TRIGGER IF EXISTS trigger_configuration_policies_delete ON lsif_configuration_policies;\nDROP TRIGGER IF EXISTS trigger_configuration_policies_insert ON lsif_configuration_policies;\n\nDROP FUNCTION IF EXISTS func_configuration_policies_update;\nDROP FUNCTION IF EXISTS func_configuration_policies_delete;\nDROP FUNCTION IF EXISTS func_configuration_policies_insert;\nDROP FUNCTION IF EXISTS func_configuration_policies_transition_columns_diff;\nDROP FUNCTION IF EXISTS func_row_to_configuration_policies_transition_columns;\n\nDROP TABLE IF EXISTS configuration_policies_audit_logs;\n\nDROP INDEX IF EXISTS configuration_policies_audit_logs_upload_id;\nDROP INDEX IF EXISTS configuration_policies_audit_logs_timestamp;\n\nDROP TYPE IF EXISTS configuration_policies_transition_columns;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1649432863, + 1649441222, + 1649759318 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1650637472, + "Name": "Add codeintel_langugage_support_requests table", + "UpQuery": "CREATE TABLE IF NOT EXISTS codeintel_langugage_support_requests (\n id SERIAL,\n user_id integer NOT NULL,\n language_id text NOT NULL\n);\n\nCREATE UNIQUE INDEX IF NOT EXISTS codeintel_langugage_support_requests_user_id_language ON codeintel_langugage_support_requests(user_id, language_id);", + "DownQuery": "DROP TABLE IF EXISTS codeintel_langugage_support_requests;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1649159359, + 1649432863, + 1649441222, + 1649759318 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1651061363, + "Name": "lsif_uploads_audit_logging_reason", + "UpQuery": "ALTER TABLE lsif_uploads_audit_logs\nADD COLUMN IF NOT EXISTS reason text DEFAULT '',\nDROP COLUMN IF EXISTS committed_at;\n\nCOMMENT ON COLUMN lsif_uploads_audit_logs.reason IS 'The reason/source for this entry.';\n\nCREATE OR REPLACE FUNCTION func_lsif_uploads_update() RETURNS TRIGGER AS $$\n DECLARE\n diff hstore[];\n BEGIN\n diff = func_lsif_uploads_transition_columns_diff(\n func_row_to_lsif_uploads_transition_columns(OLD),\n func_row_to_lsif_uploads_transition_columns(NEW)\n );\n\n IF (array_length(diff, 1) \u003e 0) THEN\n INSERT INTO lsif_uploads_audit_logs\n (reason, upload_id, commit, root, repository_id, uploaded_at,\n indexer, indexer_version, upload_size, associated_index_id,\n transition_columns)\n VALUES (\n COALESCE(current_setting('codeintel.lsif_uploads_audit.reason', true), ''),\n NEW.id, NEW.commit, NEW.root, NEW.repository_id, NEW.uploaded_at,\n NEW.indexer, NEW.indexer_version, NEW.upload_size, NEW.associated_index_id,\n diff\n );\n END IF;\n\n RETURN NEW;\n END;\n$$ LANGUAGE plpgsql;\n\nCREATE OR REPLACE FUNCTION func_lsif_uploads_insert() RETURNS TRIGGER AS $$\n BEGIN\n INSERT INTO lsif_uploads_audit_logs\n (upload_id, commit, root, repository_id, uploaded_at,\n indexer, indexer_version, upload_size, associated_index_id,\n transition_columns)\n VALUES (\n NEW.id, NEW.commit, NEW.root, NEW.repository_id, NEW.uploaded_at,\n NEW.indexer, NEW.indexer_version, NEW.upload_size, NEW.associated_index_id,\n func_lsif_uploads_transition_columns_diff(\n (NULL, NULL, NULL, NULL, NULL, NULL),\n func_row_to_lsif_uploads_transition_columns(NEW)\n )\n );\n RETURN NULL;\n END;\n$$ LANGUAGE plpgsql;\n\n\n-- CREATE OR REPLACE only supported in Postgres 14+\nDROP TRIGGER IF EXISTS trigger_lsif_uploads_update ON lsif_uploads;\nDROP TRIGGER IF EXISTS trigger_lsif_uploads_insert ON lsif_uploads;\n\nCREATE TRIGGER trigger_lsif_uploads_update\nBEFORE UPDATE OF state, num_resets, num_failures, worker_hostname, expired, committed_at\nON lsif_uploads\nFOR EACH ROW\nEXECUTE FUNCTION func_lsif_uploads_update();\n\nCREATE TRIGGER trigger_lsif_uploads_insert\nAFTER INSERT\nON lsif_uploads\nFOR EACH ROW\nEXECUTE FUNCTION func_lsif_uploads_insert();", + "DownQuery": "ALTER TABLE\n IF EXISTS lsif_uploads_audit_logs\n DROP COLUMN IF EXISTS reason,\n ADD COLUMN IF NOT EXISTS committed_at timestamptz;\n\n-- Revert functions to previous version\n\nCREATE OR REPLACE FUNCTION func_lsif_uploads_update() RETURNS TRIGGER AS $$\n BEGIN\n INSERT INTO lsif_uploads_audit_logs\n (upload_id, commit, root, repository_id, uploaded_at,\n indexer, indexer_version, upload_size, associated_index_id,\n committed_at, transition_columns)\n VALUES (\n NEW.id, NEW.commit, NEW.root, NEW.repository_id, NEW.uploaded_at,\n NEW.indexer, NEW.indexer_version, NEW.upload_size, NEW.associated_index_id,\n NEW.committed_at, func_lsif_uploads_transition_columns_diff(\n func_row_to_lsif_uploads_transition_columns(OLD),\n func_row_to_lsif_uploads_transition_columns(NEW)\n )\n );\n\n RETURN NEW;\n END;\n$$ LANGUAGE plpgsql;\n\nCREATE OR REPLACE FUNCTION func_lsif_uploads_insert() RETURNS TRIGGER AS $$\n BEGIN\n INSERT INTO lsif_uploads_audit_logs\n (upload_id, commit, root, repository_id, uploaded_at,\n indexer, indexer_version, upload_size, associated_index_id,\n committed_at, transition_columns)\n VALUES (\n NEW.id, NEW.commit, NEW.root, NEW.repository_id, NEW.uploaded_at,\n NEW.indexer, NEW.indexer_version, NEW.upload_size, NEW.associated_index_id,\n NEW.committed_at, func_lsif_uploads_transition_columns_diff(\n (NULL, NULL, NULL, NULL, NULL, NULL),\n func_row_to_lsif_uploads_transition_columns(NEW)\n )\n );\n RETURN NULL;\n END;\n$$ LANGUAGE plpgsql;\n\n-- CREATE OR REPLACE only supported in Postgres 14+\nDROP TRIGGER IF EXISTS trigger_lsif_uploads_update ON lsif_uploads;\nDROP TRIGGER IF EXISTS trigger_lsif_uploads_insert ON lsif_uploads;\n\nCREATE TRIGGER trigger_lsif_uploads_update\nBEFORE UPDATE OF state, num_resets, num_failures, worker_hostname, expired, committed_at\nON lsif_uploads\nFOR EACH ROW\nEXECUTE FUNCTION func_lsif_uploads_update();\n\nCREATE TRIGGER trigger_lsif_uploads_insert\nAFTER INSERT\nON lsif_uploads\nFOR EACH ROW\nEXECUTE FUNCTION func_lsif_uploads_insert();", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1650637472 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1651077257, + "Name": "lsif_dirty_repo_timestamp", + "UpQuery": "ALTER TABLE\n lsif_dirty_repositories\nADD\n COLUMN IF NOT EXISTS set_dirty_at timestamptz NOT NULL DEFAULT NOW();", + "DownQuery": "ALTER TABLE\n IF EXISTS lsif_dirty_repositories DROP COLUMN IF EXISTS set_dirty_at;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1650637472 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1651159431, + "Name": "fix-maven-dependency-repos-name", + "UpQuery": "UPDATE lsif_dependency_repos\nSET name = replace(regexp_replace(name, '^maven/', ''), '/', ':')\nWHERE scheme = 'semanticdb'\nAND name LIKE 'maven/%';\n\nDELETE FROM lsif_dependency_repos\nWHERE scheme = 'semanticdb'\nAND (name LIKE '%:%:%' OR name LIKE 'jdk:%' OR name LIKE 'jdk/%');", + "DownQuery": "-- Undo the changes made in the up migration", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1651077257 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1652143849, + "Name": "drop_constraint_from_filter_column_in_lsif_references_table", + "UpQuery": "ALTER TABLE IF EXISTS lsif_references\n ALTER COLUMN filter DROP NOT NULL;", + "DownQuery": "-- Undo the changes made in the up migration\nALTER TABLE IF EXISTS lsif_references\n ALTER COLUMN filter SET NOT NULL;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1650456734, + 1651061363, + 1651159431 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1652175864, + "Name": "add-unrestricted-to-repo-permissions", + "UpQuery": "ALTER TABLE\n repo_permissions\nADD\n COLUMN IF NOT EXISTS unrestricted boolean NOT NULL DEFAULT false;\n\nCREATE INDEX IF NOT EXISTS repo_permissions_unrestricted_true_idx ON repo_permissions\n USING btree (unrestricted) WHERE unrestricted;", + "DownQuery": "ALTER TABLE\n repo_permissions\n DROP\n COLUMN IF EXISTS unrestricted;\n\nDROP INDEX IF EXISTS repo_permissions_unrestricted_true_idx;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1650456734, + 1651061363, + 1651159431 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1652228814, + "Name": "index_bitbucket_cloud_commit", + "UpQuery": "CREATE INDEX IF NOT EXISTS\n changesets_bitbucket_cloud_metadata_source_commit_idx\nON\n changesets ((metadata-\u003e'source'-\u003e'commit'-\u003e\u003e'hash'))", + "DownQuery": "DROP INDEX IF EXISTS\n changesets_bitbucket_cloud_metadata_source_commit_idx;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1652175864 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1652189866, + "Name": "Add lockfiles tables", + "UpQuery": "CREATE TABLE IF NOT EXISTS codeintel_lockfiles (\n id SERIAL PRIMARY KEY,\n repository_id integer NOT NULL,\n commit_bytea bytea NOT NULL,\n codeintel_lockfile_reference_ids integer [] NOT NULL\n);\n\nCREATE UNIQUE INDEX IF NOT EXISTS codeintel_lockfiles_repository_id_commit_bytea ON codeintel_lockfiles USING btree (repository_id, commit_bytea);\n\nCREATE INDEX IF NOT EXISTS codeintel_lockfiles_codeintel_lockfile_reference_ids ON codeintel_lockfiles USING GIN (\n codeintel_lockfile_reference_ids gin__int_ops\n);\n\nCOMMENT ON TABLE codeintel_lockfiles IS 'Associates a repository-commit pair with the set of repository-level dependencies parsed from lockfiles.';\n\nCOMMENT ON COLUMN codeintel_lockfiles.commit_bytea IS 'A 40-char revhash. Note that this commit may not be resolvable in the future.';\n\nCOMMENT ON COLUMN codeintel_lockfiles.codeintel_lockfile_reference_ids IS 'A key to a resolved repository name-revspec pair. Not all repository names and revspecs are resolvable.';\n\nCREATE TABLE IF NOT EXISTS codeintel_lockfile_references (\n id SERIAL PRIMARY KEY,\n repository_name text NOT NULL,\n revspec text NOT NULL,\n package_scheme text NOT NULL,\n package_name text NOT NULL,\n package_version text NOT NULL,\n repository_id integer,\n commit_bytea bytea\n);\n\nCREATE UNIQUE INDEX IF NOT EXISTS codeintel_lockfile_references_repository_name_revspec_package ON codeintel_lockfile_references USING btree (\n repository_name,\n revspec,\n package_scheme,\n package_name,\n package_version\n);\n\nCREATE UNIQUE INDEX IF NOT EXISTS codeintel_lockfile_references_repository_id_commit_bytea ON codeintel_lockfile_references USING btree (repository_id, commit_bytea)\nWHERE\n repository_id IS NOT NULL\n AND commit_bytea IS NOT NULL;\n\nCOMMENT ON TABLE codeintel_lockfile_references IS 'Tracks a lockfile dependency that might be resolvable to a specific repository-commit pair.';\n\nCOMMENT ON COLUMN codeintel_lockfile_references.repository_name IS 'Encodes `reposource.PackageDependency.RepoName`. A name that is \"globally unique\" for a Sourcegraph instance. Used in `repo:...` queries.';\n\nCOMMENT ON COLUMN codeintel_lockfile_references.revspec IS 'Encodes `reposource.PackageDependency.GitTagFromVersion`. Returns the git tag associated with the given dependency version, used in `rev:` or `repo:foo@rev` queries.';\n\nCOMMENT ON COLUMN codeintel_lockfile_references.package_scheme IS 'Encodes `reposource.PackageDependency.Scheme`. The scheme of the dependency (e.g., semanticdb, npm).';\n\nCOMMENT ON COLUMN codeintel_lockfile_references.package_name IS 'Encodes `reposource.PackageDependency.PackageSyntax`. The name of the dependency as used by the package manager, excluding version information.';\n\nCOMMENT ON COLUMN codeintel_lockfile_references.package_version IS 'Encodes `reposource.PackageDependency.PackageVersion`. The version of the package.';\n\nCOMMENT ON COLUMN codeintel_lockfile_references.repository_id IS 'The identifier of the repo that resolves the associated name, if it is resolvable on this instance.';\n\nCOMMENT ON COLUMN codeintel_lockfile_references.commit_bytea IS 'The resolved 40-char revhash of the associated revspec, if it is resolvable on this instance.';", + "DownQuery": "DROP TABLE IF EXISTS codeintel_lockfile_references;\n\nDROP TABLE IF EXISTS codeintel_lockfiles;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1650456734, + 1651061363, + 1651159431 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1652707934, + "Name": "add last_check_at to codeintel_lockfile_references", + "UpQuery": "DROP INDEX IF EXISTS codeintel_lockfile_references_repository_id_commit_bytea;\n\nCREATE INDEX IF NOT EXISTS codeintel_lockfile_references_repository_id_commit_bytea ON codeintel_lockfile_references USING btree (repository_id, commit_bytea)\nWHERE\n repository_id IS NOT NULL\n AND commit_bytea IS NOT NULL;\n\nALTER TABLE\n codeintel_lockfile_references\nADD\n COLUMN IF NOT EXISTS last_check_at timestamptz;\n\nCOMMENT ON COLUMN codeintel_lockfile_references.last_check_at IS 'Timestamp when background job last checked this row for repository resolution';\n\nCREATE INDEX IF NOT EXISTS codeintel_lockfile_references_last_check_at ON codeintel_lockfile_references USING btree (last_check_at);", + "DownQuery": "ALTER TABLE\n codeintel_lockfile_references\nDROP\n COLUMN IF EXISTS last_check_at;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1652143849, + 1652175864, + 1652189866 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1652946496, + "Name": "add_trigger_to_insert_gitserver_repo", + "UpQuery": "-- batch insert repos which don't have a corresponding row in gitserver_repos table\nINSERT INTO gitserver_repos(repo_id, shard_id)\nSELECT repo.id, ''\nFROM repo\nLEFT JOIN gitserver_repos gr\nON repo.id = gr.repo_id\nWHERE gr.repo_id IS NULL\nON CONFLICT (repo_id) DO NOTHING;\n\nCREATE OR REPLACE FUNCTION func_insert_gitserver_repo() RETURNS TRIGGER AS $$\nBEGIN\nINSERT INTO gitserver_repos\n(repo_id, shard_id)\nVALUES (NEW.id, '');\nRETURN NULL;\nEND;\n$$ LANGUAGE plpgsql;\n\nDROP TRIGGER IF EXISTS trigger_gitserver_repo_insert on repo;\n\nCREATE TRIGGER trigger_gitserver_repo_insert\n AFTER INSERT\n ON repo\n FOR EACH ROW\n EXECUTE FUNCTION func_insert_gitserver_repo();", + "DownQuery": "DROP TRIGGER IF EXISTS trigger_gitserver_repo_insert ON repo;\nDROP FUNCTION IF EXISTS func_insert_gitserver_repo;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1652228814, + 1652707934 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1652964210, + "Name": "add last_lockfile_scan table", + "UpQuery": "CREATE TABLE IF NOT EXISTS last_lockfile_scan (\n repository_id integer NOT NULL PRIMARY KEY,\n last_lockfile_scan_at timestamp with time zone NOT NULL\n);\n\nCOMMENT ON TABLE last_lockfile_scan IS 'Tracks the last time repository was checked for lockfile indexing.';\n\nCOMMENT ON COLUMN last_lockfile_scan.last_lockfile_scan_at IS 'The last time this repository was considered for lockfile indexing.';", + "DownQuery": "DROP TABLE IF EXISTS last_lockfile_scan;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1652228814, + 1652707934 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1653334014, + "Name": "Remove default from out_of_band_migrations created timestamp", + "UpQuery": "ALTER TABLE\n out_of_band_migrations\nALTER COLUMN\n created DROP DEFAULT;", + "DownQuery": "ALTER TABLE\n out_of_band_migrations\nALTER COLUMN\n created\nSET\n DEFAULT NOW();", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1652964210 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1653472246, + "Name": "add_nps_survey_fields", + "UpQuery": "ALTER TABLE survey_responses\n ADD COLUMN IF NOT EXISTS use_cases text[],\n ADD COLUMN IF NOT EXISTS other_use_case text;", + "DownQuery": "ALTER TABLE survey_responses\n DROP COLUMN IF EXISTS use_cases,\n DROP COLUMN IF EXISTS other_use_case;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1652946496, + 1653334014 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1653479179, + "Name": "audit_log_op_and_seq", + "UpQuery": "DO $$\nBEGIN\n IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'audit_log_operation') THEN\n -- delete is known by record_deleted_at\n CREATE TYPE audit_log_operation AS ENUM('create', 'modify', 'delete');\n END IF;\nEND\n$$;\n\nCREATE SEQUENCE IF NOT EXISTS lsif_uploads_audit_logs_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\nCREATE SEQUENCE IF NOT EXISTS configuration_policies_audit_logs_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\n-- table not been used yet\nTRUNCATE TABLE lsif_uploads_audit_logs;\nTRUNCATE TABLE configuration_policies_audit_logs;\n\nALTER TABLE lsif_uploads_audit_logs\nADD COLUMN IF NOT EXISTS sequence BIGINT NOT NULL DEFAULT nextval('lsif_uploads_audit_logs_seq'::regclass),\nADD COLUMN IF NOT EXISTS operation audit_log_operation NOT NULL;\n\nALTER TABLE configuration_policies_audit_logs\nADD COLUMN IF NOT EXISTS sequence BIGINT NOT NULL DEFAULT nextval('configuration_policies_audit_logs_seq'::regclass),\nADD COLUMN IF NOT EXISTS operation audit_log_operation NOT NULL;\n\nALTER SEQUENCE lsif_uploads_audit_logs_seq OWNED BY lsif_uploads_audit_logs.sequence;\nALTER SEQUENCE configuration_policies_audit_logs_seq OWNED BY configuration_policies_audit_logs.sequence;\n\n-- Start replace triggers\n\nCREATE OR REPLACE FUNCTION func_lsif_uploads_update() RETURNS TRIGGER AS $$\n DECLARE\n diff hstore[];\n BEGIN\n diff = func_lsif_uploads_transition_columns_diff(\n func_row_to_lsif_uploads_transition_columns(OLD),\n func_row_to_lsif_uploads_transition_columns(NEW)\n );\n\n IF (array_length(diff, 1) \u003e 0) THEN\n INSERT INTO lsif_uploads_audit_logs\n (reason, upload_id, commit, root, repository_id, uploaded_at,\n indexer, indexer_version, upload_size, associated_index_id,\n operation, transition_columns)\n VALUES (\n COALESCE(current_setting('codeintel.lsif_uploads_audit.reason', true), ''),\n NEW.id, NEW.commit, NEW.root, NEW.repository_id, NEW.uploaded_at,\n NEW.indexer, NEW.indexer_version, NEW.upload_size, NEW.associated_index_id,\n 'modify', diff\n );\n END IF;\n\n RETURN NEW;\n END;\n$$ LANGUAGE plpgsql;\n\nCREATE OR REPLACE FUNCTION func_lsif_uploads_insert() RETURNS TRIGGER AS $$\n BEGIN\n INSERT INTO lsif_uploads_audit_logs\n (upload_id, commit, root, repository_id, uploaded_at,\n indexer, indexer_version, upload_size, associated_index_id,\n operation, transition_columns)\n VALUES (\n NEW.id, NEW.commit, NEW.root, NEW.repository_id, NEW.uploaded_at,\n NEW.indexer, NEW.indexer_version, NEW.upload_size, NEW.associated_index_id,\n 'create', func_lsif_uploads_transition_columns_diff(\n (NULL, NULL, NULL, NULL, NULL, NULL),\n func_row_to_lsif_uploads_transition_columns(NEW)\n )\n );\n RETURN NULL;\n END;\n$$ LANGUAGE plpgsql;\n\nCREATE OR REPLACE FUNCTION func_configuration_policies_update() RETURNS TRIGGER AS $$\n DECLARE\n diff hstore[];\n BEGIN\n diff = func_configuration_policies_transition_columns_diff(\n func_row_to_configuration_policies_transition_columns(OLD),\n func_row_to_configuration_policies_transition_columns(NEW)\n );\n\n IF (array_length(diff, 1) \u003e 0) THEN\n INSERT INTO configuration_policies_audit_logs\n (policy_id, operation, transition_columns)\n VALUES (NEW.id, 'modify', diff);\n END IF;\n\n RETURN NEW;\n END;\n$$ LANGUAGE plpgsql;\n\nCREATE OR REPLACE FUNCTION func_configuration_policies_insert() RETURNS TRIGGER AS $$\n BEGIN\n INSERT INTO configuration_policies_audit_logs\n (policy_id, operation, transition_columns)\n VALUES (\n NEW.id, 'create',\n func_configuration_policies_transition_columns_diff(\n (NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),\n func_row_to_configuration_policies_transition_columns(NEW)\n )\n );\n RETURN NULL;\n END;\n$$ LANGUAGE plpgsql;\n\n-- End replace triggers", + "DownQuery": "ALTER TABLE lsif_uploads_audit_logs\nDROP COLUMN IF EXISTS sequence,\nDROP COLUMN IF EXISTS operation;\n\nDROP SEQUENCE IF EXISTS lsif_uploads_audit_logs_seq;\n\nALTER TABLE configuration_policies_audit_logs\nDROP COLUMN IF EXISTS sequence,\nDROP COLUMN IF EXISTS operation;\n\nDROP SEQUENCE IF EXISTS configuration_policies_audit_logs_seq;\n\nDROP TYPE IF EXISTS audit_log_operation;\n\nCREATE OR REPLACE FUNCTION func_configuration_policies_update() RETURNS TRIGGER AS $$\n DECLARE\n diff hstore[];\n BEGIN\n diff = func_configuration_policies_transition_columns_diff(\n func_row_to_configuration_policies_transition_columns(OLD),\n func_row_to_configuration_policies_transition_columns(NEW)\n );\n\n IF (array_length(diff, 1) \u003e 0) THEN\n INSERT INTO configuration_policies_audit_logs\n (policy_id, transition_columns)\n VALUES (\n NEW.id,\n diff\n );\n END IF;\n\n RETURN NEW;\n END;\n$$ LANGUAGE plpgsql;\n\nCREATE OR REPLACE FUNCTION func_configuration_policies_insert() RETURNS TRIGGER AS $$\n BEGIN\n INSERT INTO configuration_policies_audit_logs\n (policy_id, transition_columns)\n VALUES (\n NEW.id,\n func_configuration_policies_transition_columns_diff(\n (NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),\n func_row_to_configuration_policies_transition_columns(NEW)\n )\n );\n RETURN NULL;\n END;\n$$ LANGUAGE plpgsql;\n\nCREATE OR REPLACE FUNCTION func_lsif_uploads_update() RETURNS TRIGGER AS $$\n DECLARE\n diff hstore[];\n BEGIN\n diff = func_lsif_uploads_transition_columns_diff(\n func_row_to_lsif_uploads_transition_columns(OLD),\n func_row_to_lsif_uploads_transition_columns(NEW)\n );\n\n IF (array_length(diff, 1) \u003e 0) THEN\n INSERT INTO lsif_uploads_audit_logs\n (reason, upload_id, commit, root, repository_id, uploaded_at,\n indexer, indexer_version, upload_size, associated_index_id,\n transition_columns)\n VALUES (\n COALESCE(current_setting('codeintel.lsif_uploads_audit.reason', true), ''),\n NEW.id, NEW.commit, NEW.root, NEW.repository_id, NEW.uploaded_at,\n NEW.indexer, NEW.indexer_version, NEW.upload_size, NEW.associated_index_id,\n diff\n );\n END IF;\n\n RETURN NEW;\n END;\n$$ LANGUAGE plpgsql;\n\nCREATE OR REPLACE FUNCTION func_lsif_uploads_insert() RETURNS TRIGGER AS $$\n BEGIN\n INSERT INTO lsif_uploads_audit_logs\n (upload_id, commit, root, repository_id, uploaded_at,\n indexer, indexer_version, upload_size, associated_index_id,\n transition_columns)\n VALUES (\n NEW.id, NEW.commit, NEW.root, NEW.repository_id, NEW.uploaded_at,\n NEW.indexer, NEW.indexer_version, NEW.upload_size, NEW.associated_index_id,\n func_lsif_uploads_transition_columns_diff(\n (NULL, NULL, NULL, NULL, NULL, NULL),\n func_row_to_lsif_uploads_transition_columns(NEW)\n )\n );\n RETURN NULL;\n END;\n$$ LANGUAGE plpgsql;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1652946496, + 1653334014 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1649253538, + "Name": "batch_spec_resolution_user_id_non_null", + "UpQuery": "UPDATE batch_spec_resolution_jobs SET initiator_id = (SELECT bs.user_id FROM batch_specs bs WHERE bs.id = batch_spec_id);\n\nALTER TABLE batch_spec_resolution_jobs ALTER COLUMN initiator_id SET NOT NULL;", + "DownQuery": "ALTER TABLE batch_spec_resolution_jobs ALTER COLUMN initiator_id DROP NOT NULL;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1653479179 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1654116265, + "Name": "add_unique_index_to_external_services", + "UpQuery": "CREATE UNIQUE INDEX IF NOT EXISTS external_services_unique_kind_org_id ON external_services (kind, namespace_org_id) WHERE (deleted_at IS NULL AND namespace_user_id IS NULL AND namespace_org_id IS NOT NULL);\nCREATE UNIQUE INDEX IF NOT EXISTS external_services_unique_kind_user_id ON external_services (kind, namespace_user_id) WHERE (deleted_at IS NULL AND namespace_org_id IS NULL AND namespace_user_id IS NOT NULL);", + "DownQuery": "DROP INDEX IF EXISTS external_services_unique_kind_org_id;\nDROP INDEX IF EXISTS external_services_unique_kind_user_id;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1653479179 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1654168174, + "Name": "add_explicit_permissions_bitbucket_projects_jobs_table", + "UpQuery": "CREATE TABLE IF NOT EXISTS explicit_permissions_bitbucket_projects_jobs (\n id SERIAL PRIMARY KEY,\n state text DEFAULT 'queued',\n failure_message text,\n queued_at timestamp with time zone DEFAULT NOW(),\n started_at timestamp with time zone,\n finished_at timestamp with time zone,\n process_after timestamp with time zone,\n num_resets integer not null default 0,\n num_failures integer not null default 0,\n last_heartbeat_at timestamp with time zone,\n execution_logs json [],\n worker_hostname text not null default '',\n -- additional columns\n project_key text not null,\n external_service_id integer not null,\n permissions json [],\n unrestricted boolean not null default false,\n CHECK (\n (\n permissions IS NOT NULL\n AND unrestricted IS false\n )\n OR (\n permissions IS NULL\n AND unrestricted IS true\n )\n )\n);", + "DownQuery": "DROP TABLE IF EXISTS explicit_permissions_bitbucket_projects_jobs;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1653479179 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1655226733, + "Name": "hstore_aggregate_func", + "UpQuery": "CREATE OR REPLACE FUNCTION merge_audit_log_transitions(internal hstore, arrayhstore hstore[]) RETURNS hstore AS $$\n DECLARE\n trans hstore;\n BEGIN\n FOREACH trans IN ARRAY arrayhstore\n LOOP\n internal := internal || hstore(trans-\u003e'column', trans-\u003e'new');\n END LOOP;\n\n RETURN internal;\n END;\n$$ LANGUAGE plpgsql IMMUTABLE;\n\nCREATE OR REPLACE AGGREGATE snapshot_transition_columns(HSTORE[]) (\n SFUNC = merge_audit_log_transitions,\n STYPE = HSTORE,\n INITCOND = ''\n);", + "DownQuery": "DROP AGGREGATE IF EXISTS snapshot_transition_columns(HSTORE[]);\n\nDROP FUNCTION IF EXISTS merge_audit_log_transitions;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1654116265, + 1654168174 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1653524883, + "Name": "Create view for batch spec workspace execution worker", + "UpQuery": "ALTER TABLE batch_spec_workspace_execution_jobs ADD COLUMN IF NOT EXISTS user_id INTEGER;\n\nUPDATE batch_spec_workspace_execution_jobs exec SET user_id = (\n SELECT spec.user_id\n FROM batch_spec_workspaces AS workspace\n JOIN batch_specs spec ON spec.id = workspace.batch_spec_id\n WHERE workspace.id = exec.batch_spec_workspace_id\n);\n\nCREATE INDEX IF NOT EXISTS batch_spec_workspace_execution_jobs_user_id ON batch_spec_workspace_execution_jobs (user_id);\n\nCREATE INDEX IF NOT EXISTS batch_spec_workspace_execution_jobs_state ON batch_spec_workspace_execution_jobs (state);\n\nDROP VIEW IF EXISTS batch_spec_workspace_execution_queue;\nCREATE VIEW batch_spec_workspace_execution_queue AS\nWITH user_queues AS (\n SELECT\n exec.user_id,\n MAX(exec.started_at) AS latest_dequeue\n FROM batch_spec_workspace_execution_jobs AS exec\n GROUP BY exec.user_id\n),\n-- We are creating this materialized CTE because PostgreSQL doesn't allow `FOR UPDATE` with window functions.\n-- Materializing it makes sure that the view query is not inlined into the FOR UPDATE select the Dequeue method\n-- performs.\nmaterialized_queue_candidates AS MATERIALIZED (\n SELECT\n exec.*,\n RANK() OVER (\n PARTITION BY queue.user_id\n -- Make sure the jobs are still fulfilled in timely order, and that the ordering is stable.\n ORDER BY exec.created_at ASC, exec.id ASC\n ) AS place_in_user_queue\n FROM batch_spec_workspace_execution_jobs exec\n JOIN user_queues queue ON queue.user_id = exec.user_id\n WHERE\n \t-- Only queued records should get a rank.\n exec.state = 'queued'\n ORDER BY\n -- Round-robin let users dequeue jobs.\n place_in_user_queue,\n -- And ensure the user who dequeued the longest ago is next.\n queue.latest_dequeue ASC NULLS FIRST\n)\nSELECT\n ROW_NUMBER() OVER () AS place_in_global_queue, materialized_queue_candidates.*\nFROM materialized_queue_candidates;", + "DownQuery": "DROP VIEW IF EXISTS batch_spec_workspace_execution_queue;\n\nALTER TABLE batch_spec_workspace_execution_jobs DROP COLUMN IF EXISTS user_id;\n\nDROP INDEX IF EXISTS batch_spec_workspace_execution_jobs_user_id;\n\nDROP INDEX IF EXISTS batch_spec_workspace_execution_jobs_state;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1653334014, + 1653479179 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1654770608, + "Name": "workspace_user_id_non_nullable", + "UpQuery": "UPDATE batch_spec_workspace_execution_jobs exec SET user_id = (\n SELECT spec.user_id\n FROM batch_spec_workspaces AS workspace\n JOIN batch_specs spec ON spec.id = workspace.batch_spec_id\n WHERE workspace.id = exec.batch_spec_workspace_id\n);\n\nALTER TABLE batch_spec_workspace_execution_jobs ALTER COLUMN user_id SET NOT NULL;", + "DownQuery": "ALTER TABLE batch_spec_workspace_execution_jobs ALTER COLUMN user_id DROP NOT NULL;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1653524883, + 1654116265, + 1654168174 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1654848945, + "Name": "add_explicit_permissions_bitbucket_projects_jobs_index", + "UpQuery": "CREATE INDEX IF NOT EXISTS explicit_permissions_bitbucket_projects_jobs_project_key_external_service_id_state_idx ON explicit_permissions_bitbucket_projects_jobs (project_key, external_service_id, state);", + "DownQuery": "DROP INDEX IF EXISTS explicit_permissions_bitbucket_projects_jobs_project_key_external_service_id_state_idx;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1653524883, + 1654116265, + 1654168174 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1654872407, + "Name": "fast_cascade_delete_batch_specs_1", + "UpQuery": "-- Create index for foreign key reverse lookups. This is required for cascading deletes.\nCREATE INDEX CONCURRENTLY IF NOT EXISTS changeset_specs_batch_spec_id ON changeset_specs (batch_spec_id);", + "DownQuery": "DROP INDEX IF EXISTS changeset_specs_batch_spec_id;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1654848945 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "changeset_specs", + "IndexName": "changeset_specs_batch_spec_id" + } + }, + { + "ID": 1654874148, + "Name": "fast_cascade_delete_batch_specs_2", + "UpQuery": "-- Create index for foreign key reverse lookups. This is required for cascading deletes.\nCREATE INDEX CONCURRENTLY IF NOT EXISTS batch_spec_workspaces_batch_spec_id ON batch_spec_workspaces (batch_spec_id);", + "DownQuery": "DROP INDEX IF EXISTS batch_spec_workspaces_batch_spec_id;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1654872407 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "batch_spec_workspaces", + "IndexName": "batch_spec_workspaces_batch_spec_id" + } + }, + { + "ID": 1654874153, + "Name": "fast_cascade_delete_batch_specs_3", + "UpQuery": "-- Create index for foreign key reverse lookups. This is required for cascading deletes.\nCREATE INDEX CONCURRENTLY IF NOT EXISTS batch_spec_workspace_execution_jobs_batch_spec_workspace_id ON batch_spec_workspace_execution_jobs (batch_spec_workspace_id);", + "DownQuery": "DROP INDEX IF EXISTS batch_spec_workspace_execution_jobs_batch_spec_workspace_id;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1654874148 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "batch_spec_workspace_execution_jobs", + "IndexName": "batch_spec_workspace_execution_jobs_batch_spec_workspace_id" + } + }, + { + "ID": 1655037388, + "Name": "faster_changeset_spec_cleanup_1", + "UpQuery": "CREATE INDEX CONCURRENTLY IF NOT EXISTS changeset_specs_created_at ON changeset_specs (created_at);", + "DownQuery": "DROP INDEX IF EXISTS changeset_specs_created_at;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1654874153 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "changeset_specs", + "IndexName": "changeset_specs_created_at" + } + }, + { + "ID": 1655037391, + "Name": "faster_changeset_spec_cleanup_2", + "UpQuery": "CREATE INDEX CONCURRENTLY IF NOT EXISTS changesets_changeset_specs ON changesets (current_spec_id, previous_spec_id);", + "DownQuery": "DROP INDEX IF EXISTS changesets_changeset_specs;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1655037388 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "changesets", + "IndexName": "changesets_changeset_specs" + } + }, + { + "ID": 1655067139, + "Name": "fixup_worker_fairness_view", + "UpQuery": "DROP VIEW IF EXISTS batch_spec_workspace_execution_jobs_with_rank;\nDROP VIEW IF EXISTS batch_spec_workspace_execution_queue;\n\nCREATE VIEW batch_spec_workspace_execution_queue AS\nWITH user_queues AS (\n SELECT\n exec.user_id,\n MAX(exec.started_at) AS latest_dequeue\n FROM batch_spec_workspace_execution_jobs AS exec\n GROUP BY exec.user_id\n),\nqueue_candidates AS (\n SELECT\n exec.id,\n RANK() OVER (\n PARTITION BY queue.user_id\n -- Make sure the jobs are still fulfilled in timely order, and that the ordering is stable.\n ORDER BY exec.created_at ASC, exec.id ASC\n ) AS place_in_user_queue\n FROM batch_spec_workspace_execution_jobs exec\n JOIN user_queues queue ON queue.user_id = exec.user_id\n WHERE\n \t-- Only queued records should get a rank.\n exec.state = 'queued'\n ORDER BY\n -- Round-robin let users dequeue jobs.\n place_in_user_queue,\n -- And ensure the user who dequeued the longest ago is next.\n queue.latest_dequeue ASC NULLS FIRST\n)\nSELECT\n queue_candidates.id, ROW_NUMBER() OVER () AS place_in_global_queue, queue_candidates.place_in_user_queue\nFROM queue_candidates;\n\nCREATE VIEW batch_spec_workspace_execution_jobs_with_rank AS (\n SELECT\n j.*,\n q.place_in_global_queue,\n q.place_in_user_queue\n FROM\n batch_spec_workspace_execution_jobs j\n LEFT JOIN batch_spec_workspace_execution_queue q ON j.id = q.id\n);", + "DownQuery": "DROP VIEW IF EXISTS batch_spec_workspace_execution_jobs_with_rank;\nDROP VIEW IF EXISTS batch_spec_workspace_execution_queue;\n\nCREATE VIEW batch_spec_workspace_execution_queue AS\nWITH user_queues AS (\n SELECT\n exec.user_id,\n MAX(exec.started_at) AS latest_dequeue\n FROM batch_spec_workspace_execution_jobs AS exec\n GROUP BY exec.user_id\n),\n-- We are creating this materialized CTE because PostgreSQL doesn't allow `FOR UPDATE` with window functions.\n-- Materializing it makes sure that the view query is not inlined into the FOR UPDATE select the Dequeue method\n-- performs.\nmaterialized_queue_candidates AS MATERIALIZED (\n SELECT\n exec.*,\n RANK() OVER (\n PARTITION BY queue.user_id\n -- Make sure the jobs are still fulfilled in timely order, and that the ordering is stable.\n ORDER BY exec.created_at ASC, exec.id ASC\n ) AS place_in_user_queue\n FROM batch_spec_workspace_execution_jobs exec\n JOIN user_queues queue ON queue.user_id = exec.user_id\n WHERE\n \t-- Only queued records should get a rank.\n exec.state = 'queued'\n ORDER BY\n -- Round-robin let users dequeue jobs.\n place_in_user_queue,\n -- And ensure the user who dequeued the longest ago is next.\n queue.latest_dequeue ASC NULLS FIRST\n)\nSELECT\n ROW_NUMBER() OVER () AS place_in_global_queue, materialized_queue_candidates.*\nFROM materialized_queue_candidates;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1654874153 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1655128668, + "Name": "add indices to explicit_permissions_bitbucket_projects_jobs table", + "UpQuery": "CREATE INDEX IF NOT EXISTS explicit_permissions_bitbucket_projects_jobs_queued_at_idx ON explicit_permissions_bitbucket_projects_jobs (queued_at);\nCREATE INDEX IF NOT EXISTS explicit_permissions_bitbucket_projects_jobs_state_idx ON explicit_permissions_bitbucket_projects_jobs (state);", + "DownQuery": "DROP INDEX IF EXISTS explicit_permissions_bitbucket_projects_jobs_queued_at_idx;\nDROP INDEX IF EXISTS explicit_permissions_bitbucket_projects_jobs_state_idx;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1654874153 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1655328928, + "Name": "fix_code_insights_failed_tcp_error", + "UpQuery": "-- In 3.40 one transient error was accidentally flagged as non-retryable and would terminally fail. This simply\n-- resets these jobs in the queue to try again after 3.41 ships.\nupdate insights_query_runner_jobs set state = 'queued', failure_message = null, num_failures = 0\nwhere state = 'failed' and failure_message like '%dial tcp%';", + "DownQuery": "-- Nothing to do in this down migration.", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1649253538, + 1655037391, + 1655067139, + 1655128668 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1655412173, + "Name": "code_insights_queue_missing_index", + "UpQuery": "CREATE INDEX IF NOT EXISTS process_after_insights_query_runner_jobs_idx\n ON insights_query_runner_jobs (process_after);\n\nCREATE INDEX IF NOT EXISTS finished_at_insights_query_runner_jobs_idx\n ON insights_query_runner_jobs (finished_at);", + "DownQuery": "DROP INDEX IF EXISTS process_after_insights_query_runner_jobs_idx;\nDROP INDEX IF EXISTS finished_at_insights_query_runner_jobs_idx;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1655328928 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1655481894, + "Name": "faster_ssbc_dequeue", + "UpQuery": "CREATE INDEX CONCURRENTLY IF NOT EXISTS batch_spec_workspace_execution_jobs_last_dequeue ON batch_spec_workspace_execution_jobs (user_id, started_at DESC);", + "DownQuery": "DROP INDEX IF EXISTS batch_spec_workspace_execution_jobs_last_dequeue;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1655412173 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "batch_spec_workspace_execution_jobs", + "IndexName": "batch_spec_workspace_execution_jobs_last_dequeue" + } + }, + { + "ID": 1655737737, + "Name": "drop_unused_idx_batch_spec_workspace_execution_jobs_user_id", + "UpQuery": "DROP INDEX IF EXISTS batch_spec_workspace_execution_jobs_user_id;", + "DownQuery": "CREATE INDEX IF NOT EXISTS batch_spec_workspace_execution_jobs_user_id ON batch_spec_workspace_execution_jobs (user_id);", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1655481894 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1655763641, + "Name": "faster_workspace_batch_spec_lookup", + "UpQuery": "CREATE INDEX CONCURRENTLY IF NOT EXISTS batch_spec_workspaces_id_batch_spec_id ON batch_spec_workspaces(id, batch_spec_id);", + "DownQuery": "DROP INDEX IF EXISTS batch_spec_workspaces_id_batch_spec_id;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1655481894 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "batch_spec_workspaces", + "IndexName": "batch_spec_workspaces_id_batch_spec_id" + } + }, + { + "ID": 1655843069, + "Name": "insights_faster_job_status", + "UpQuery": "CREATE INDEX CONCURRENTLY IF NOT EXISTS insights_query_runner_jobs_series_id_state ON insights_query_runner_jobs (series_id, state);", + "DownQuery": "DROP INDEX IF EXISTS insights_query_runner_jobs_series_id_state;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1655737737, + 1655763641 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "insights_query_runner_jobs", + "IndexName": "insights_query_runner_jobs_series_id_state" + } + }, + { + "ID": 1655157509, + "Name": "no_more_ssbc_access_tokens", + "UpQuery": "DELETE FROM access_tokens WHERE internal and note = 'batch-spec-execution';\n\nDROP VIEW IF EXISTS batch_spec_workspace_execution_jobs_with_rank;\nCREATE VIEW batch_spec_workspace_execution_jobs_with_rank AS (\n SELECT\n j.id,\n j.batch_spec_workspace_id,\n j.state,\n j.failure_message,\n j.started_at,\n j.finished_at,\n j.process_after,\n j.num_resets,\n j.num_failures,\n j.execution_logs,\n j.worker_hostname,\n j.last_heartbeat_at,\n j.created_at,\n j.updated_at,\n j.cancel,\n j.queued_at,\n j.user_id,\n q.place_in_global_queue,\n q.place_in_user_queue\n FROM\n batch_spec_workspace_execution_jobs j\n LEFT JOIN batch_spec_workspace_execution_queue q ON j.id = q.id\n);\n\nALTER TABLE batch_spec_workspace_execution_jobs DROP COLUMN IF EXISTS access_token_id;", + "DownQuery": "ALTER TABLE batch_spec_workspace_execution_jobs ADD COLUMN IF NOT EXISTS access_token_id integer REFERENCES access_tokens(id);\n\nDROP VIEW IF EXISTS batch_spec_workspace_execution_jobs_with_rank;\nCREATE VIEW batch_spec_workspace_execution_jobs_with_rank AS (\n SELECT\n j.*,\n q.place_in_global_queue,\n q.place_in_user_queue\n FROM\n batch_spec_workspace_execution_jobs j\n LEFT JOIN batch_spec_workspace_execution_queue q ON j.id = q.id\n);", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1649253538, + 1654874153 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1655105391, + "Name": "lockfile_dependency_graph", + "UpQuery": "DELETE FROM codeintel_lockfiles;\nDELETE FROM codeintel_lockfile_references;\n\nALTER TABLE codeintel_lockfiles\n ADD COLUMN IF NOT EXISTS lockfile text;\n\n-- This is a backwards incompatible change. See dev/ci/go-backcompat/flakefiles/v3.41.0.json for details.\nDROP INDEX IF EXISTS codeintel_lockfiles_repository_id_commit_bytea;\nCREATE UNIQUE INDEX IF NOT EXISTS codeintel_lockfiles_repository_id_commit_bytea_lockfile ON codeintel_lockfiles USING btree (repository_id, commit_bytea, lockfile);\n\nCOMMENT ON COLUMN codeintel_lockfiles.lockfile IS 'Relative path of a lockfile in the given repository and the given commit.';\n\nALTER TABLE codeintel_lockfile_references\n -- We can't make them non-nullable to stay backwards compatible\n ADD COLUMN IF NOT EXISTS depends_on integer[] DEFAULT '{}',\n ADD COLUMN IF NOT EXISTS resolution_lockfile text,\n ADD COLUMN IF NOT EXISTS resolution_repository_id integer,\n ADD COLUMN IF NOT EXISTS resolution_commit_bytea bytea;\n\nCOMMENT ON COLUMN codeintel_lockfile_references.depends_on IS 'IDs of other `codeintel_lockfile_references` this package depends on in the context of this `codeintel_lockfile_references.resolution_id`.';\nCOMMENT ON COLUMN codeintel_lockfile_references.resolution_lockfile IS 'Relative path of lockfile in which this package was referenced. Corresponds to `codeintel_lockfiles.lockfile`.';\nCOMMENT ON COLUMN codeintel_lockfile_references.resolution_repository_id IS 'ID of the repository in which lockfile was resolved. Corresponds to `codeintel_lockfiles.repository_id`.';\nCOMMENT ON COLUMN codeintel_lockfile_references.resolution_commit_bytea IS 'Commit at which lockfile was resolved. Corresponds to `codeintel_lockfiles.commit_bytea`.';\n\nCREATE INDEX IF NOT EXISTS codeintel_lockfiles_references_depends_on\nON codeintel_lockfile_references USING GIN (depends_on gin__int_ops);\n\n-- This is a backwards incompatible change. See dev/ci/go-backcompat/flakefiles/v3.41.0.json for details.\nDROP INDEX IF EXISTS codeintel_lockfile_references_repository_name_revspec_package;\nCREATE UNIQUE INDEX IF NOT EXISTS codeintel_lockfile_references_repository_name_revspec_package_resolution ON codeintel_lockfile_references USING btree (\n repository_name,\n revspec,\n package_scheme,\n package_name,\n package_version,\n resolution_lockfile,\n resolution_repository_id,\n resolution_commit_bytea\n);", + "DownQuery": "ALTER TABLE codeintel_lockfiles\n DROP COLUMN IF EXISTS lockfile;\n\nDROP INDEX IF EXISTS codeintel_lockfiles_repository_id_commit_bytea_lockfile;\nCREATE UNIQUE INDEX IF NOT EXISTS codeintel_lockfiles_repository_id_commit_bytea ON codeintel_lockfiles USING btree (repository_id, commit_bytea);\n\nALTER TABLE codeintel_lockfile_references\n DROP COLUMN IF EXISTS depends_on,\n DROP COLUMN IF EXISTS resolution_lockfile,\n DROP COLUMN IF EXISTS resolution_repository_id,\n DROP COLUMN IF EXISTS resolution_commit_bytea;\n\nDROP INDEX IF EXISTS codeintel_lockfile_references_repository_name_revspec_package_resolution;\nCREATE UNIQUE INDEX IF NOT EXISTS codeintel_lockfile_references_repository_name_revspec_package ON codeintel_lockfile_references USING btree (\n repository_name,\n revspec,\n package_scheme,\n package_name,\n package_version\n);", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1654848945 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1655454264, + "Name": "add_lockfile_indexing_enabled_to_policy", + "UpQuery": "ALTER TABLE lsif_configuration_policies\n ADD COLUMN IF NOT EXISTS lockfile_indexing_enabled boolean NOT NULL DEFAULT false;\n\nCOMMENT ON COLUMN lsif_configuration_policies.lockfile_indexing_enabled IS 'Whether to index the lockfiles in the repositories matched by this policy';", + "DownQuery": "ALTER TABLE lsif_configuration_policies\n DROP COLUMN IF EXISTS lockfile_indexing_enabled;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1655105391 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1656447205, + "Name": "create_repo_description_trgm_idx", + "UpQuery": "CREATE INDEX CONCURRENTLY IF NOT EXISTS repo_description_trgm_idx ON repo USING GIN (lower(description) gin_trgm_ops);", + "DownQuery": "DROP INDEX IF EXISTS repo_description_trgm_idx;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1655454264, + 1655843069 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "repo", + "IndexName": "repo_description_trgm_idx" + } + }, + { + "ID": 1657106983, + "Name": "faster_failure_msg_query", + "UpQuery": "CREATE INDEX CONCURRENTLY IF NOT EXISTS external_service_sync_jobs_state_external_service_id ON external_service_sync_jobs (state, external_service_id) INCLUDE (finished_at);", + "DownQuery": "DROP INDEX IF EXISTS external_service_sync_jobs_state_external_service_id;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1653472246, + 1655157509, + 1655226733, + 1655454264, + 1655843069 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "external_service_sync_jobs", + "IndexName": "external_service_sync_jobs_state_external_service_id" + } + }, + { + "ID": 1657107627, + "Name": "drop_duplicate_index_sync_jobs_state", + "UpQuery": "DROP INDEX IF EXISTS external_service_sync_jobs_state_idx;", + "DownQuery": "CREATE INDEX IF NOT EXISTS external_service_sync_jobs_state_idx ON external_service_sync_jobs (state);", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1657106983 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1657279116, + "Name": "faster_dequeues_cm_action_jobs", + "UpQuery": "CREATE INDEX CONCURRENTLY IF NOT EXISTS cm_action_jobs_state_idx ON cm_action_jobs (state);", + "DownQuery": "DROP INDEX IF EXISTS cm_action_jobs_state_idx;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1656447205, + 1657107627 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "cm_action_jobs", + "IndexName": "cm_action_jobs_state_idx" + } + }, + { + "ID": 1657279170, + "Name": "faster_dequeues_cm_trigger_jobs", + "UpQuery": "CREATE INDEX CONCURRENTLY IF NOT EXISTS cm_trigger_jobs_state_idx ON cm_trigger_jobs (state);", + "DownQuery": "DROP INDEX IF EXISTS cm_trigger_jobs_state_idx;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1657279116 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "cm_trigger_jobs", + "IndexName": "cm_trigger_jobs_state_idx" + } + }, + { + "ID": 1657635365, + "Name": "add_fidelity_to_lockfiles", + "UpQuery": "ALTER TABLE codeintel_lockfiles\n ADD COLUMN IF NOT EXISTS fidelity text NOT NULL DEFAULT 'flat';\n\nCOMMENT ON COLUMN codeintel_lockfiles.fidelity IS 'Fidelity of the dependency graph thats persisted, whether it is a flat list, a whole graph, circular graph, ...';", + "DownQuery": "ALTER TABLE codeintel_lockfiles DROP COLUMN IF EXISTS fidelity;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1657279170 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1658122170, + "Name": "add_batch_change_id_to_batch_spec", + "UpQuery": "ALTER TABLE batch_specs\n ADD COLUMN IF NOT EXISTS batch_change_id bigint,\n ADD FOREIGN KEY (batch_change_id) REFERENCES batch_changes(id) ON DELETE SET NULL DEFERRABLE;\n\nUPDATE batch_specs SET batch_change_id = (\n -- In the event, the database is in a not-so-optimal state (usually in dev environment)\n -- we want the subquery to never return more than one row.\n -- This will never happen in production.\n SELECT\n bc.id\n FROM batch_changes bc\n WHERE bc.batch_spec_id = batch_specs.id\n LIMIT 1\n);", + "DownQuery": "ALTER TABLE batch_specs\n DROP COLUMN IF EXISTS batch_change_id;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1657635365 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1658174103, + "Name": "workspace_execution_user_queues", + "UpQuery": "CREATE TABLE IF NOT EXISTS batch_spec_workspace_execution_last_dequeues (\n user_id integer PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED,\n latest_dequeue timestamp with time zone\n);\n\nCREATE OR REPLACE FUNCTION batch_spec_workspace_execution_last_dequeues_upsert() RETURNS trigger\n LANGUAGE plpgsql\n AS $$ BEGIN\n INSERT INTO\n batch_spec_workspace_execution_last_dequeues\n SELECT\n user_id,\n MAX(started_at) as latest_dequeue\n FROM\n newtab\n GROUP BY\n user_id\n ON CONFLICT (user_id) DO UPDATE SET\n latest_dequeue = GREATEST(batch_spec_workspace_execution_last_dequeues.latest_dequeue, EXCLUDED.latest_dequeue);\n\n RETURN NULL;\nEND $$;\n\nDROP TRIGGER IF EXISTS batch_spec_workspace_execution_last_dequeues_insert ON batch_spec_workspace_execution_jobs;\nCREATE TRIGGER batch_spec_workspace_execution_last_dequeues_insert AFTER INSERT ON batch_spec_workspace_execution_jobs REFERENCING NEW TABLE AS newtab FOR EACH STATEMENT EXECUTE FUNCTION batch_spec_workspace_execution_last_dequeues_upsert();\n\nDROP TRIGGER IF EXISTS batch_spec_workspace_execution_last_dequeues_update ON batch_spec_workspace_execution_jobs;\nCREATE TRIGGER batch_spec_workspace_execution_last_dequeues_update AFTER UPDATE ON batch_spec_workspace_execution_jobs REFERENCING NEW TABLE AS newtab FOR EACH STATEMENT EXECUTE FUNCTION batch_spec_workspace_execution_last_dequeues_upsert();\n\nDROP VIEW IF EXISTS batch_spec_workspace_execution_jobs_with_rank;\nDROP VIEW IF EXISTS batch_spec_workspace_execution_queue;\n\nCREATE VIEW batch_spec_workspace_execution_queue AS\nWITH queue_candidates AS (\n SELECT\n exec.id,\n RANK() OVER (\n PARTITION BY queue.user_id\n -- Make sure the jobs are still fulfilled in timely order, and that the ordering is stable.\n ORDER BY exec.created_at ASC, exec.id ASC\n ) AS place_in_user_queue\n FROM batch_spec_workspace_execution_jobs exec\n JOIN batch_spec_workspace_execution_last_dequeues queue ON queue.user_id = exec.user_id\n WHERE\n \t-- Only queued records should get a rank.\n exec.state = 'queued'\n ORDER BY\n -- Round-robin let users dequeue jobs.\n place_in_user_queue,\n -- And ensure the user who dequeued the longest ago is next.\n queue.latest_dequeue ASC NULLS FIRST\n)\nSELECT\n queue_candidates.id, ROW_NUMBER() OVER () AS place_in_global_queue, queue_candidates.place_in_user_queue\nFROM queue_candidates;\n\nCREATE VIEW batch_spec_workspace_execution_jobs_with_rank AS (\n SELECT\n j.*,\n q.place_in_global_queue,\n q.place_in_user_queue\n FROM\n batch_spec_workspace_execution_jobs j\n LEFT JOIN batch_spec_workspace_execution_queue q ON j.id = q.id\n);\n\nINSERT INTO batch_spec_workspace_execution_last_dequeues\nSELECT\n exec.user_id as user_id,\n MAX(exec.started_at) AS latest_dequeue\nFROM batch_spec_workspace_execution_jobs exec\nGROUP BY exec.user_id\nON CONFLICT (user_id) DO UPDATE\n SET latest_dequeue = GREATEST(batch_spec_workspace_execution_last_dequeues.latest_dequeue, EXCLUDED.latest_dequeue);", + "DownQuery": "DROP TRIGGER IF EXISTS batch_spec_workspace_execution_last_dequeues_insert ON batch_spec_workspace_execution_jobs;\nDROP TRIGGER IF EXISTS batch_spec_workspace_execution_last_dequeues_update ON batch_spec_workspace_execution_jobs;\nDROP FUNCTION IF EXISTS batch_spec_workspace_execution_last_dequeues_upsert();\n\nDROP VIEW IF EXISTS batch_spec_workspace_execution_jobs_with_rank;\nDROP VIEW IF EXISTS batch_spec_workspace_execution_queue;\n\nCREATE VIEW batch_spec_workspace_execution_queue AS\nWITH user_queues AS (\n SELECT\n exec.user_id,\n MAX(exec.started_at) AS latest_dequeue\n FROM batch_spec_workspace_execution_jobs AS exec\n GROUP BY exec.user_id\n),\nqueue_candidates AS (\n SELECT\n exec.id,\n RANK() OVER (\n PARTITION BY queue.user_id\n -- Make sure the jobs are still fulfilled in timely order, and that the ordering is stable.\n ORDER BY exec.created_at ASC, exec.id ASC\n ) AS place_in_user_queue\n FROM batch_spec_workspace_execution_jobs exec\n JOIN user_queues queue ON queue.user_id = exec.user_id\n WHERE\n \t-- Only queued records should get a rank.\n exec.state = 'queued'\n ORDER BY\n -- Round-robin let users dequeue jobs.\n place_in_user_queue,\n -- And ensure the user who dequeued the longest ago is next.\n queue.latest_dequeue ASC NULLS FIRST\n)\nSELECT\n queue_candidates.id, ROW_NUMBER() OVER () AS place_in_global_queue, queue_candidates.place_in_user_queue\nFROM queue_candidates;\n\nCREATE VIEW batch_spec_workspace_execution_jobs_with_rank AS (\n SELECT\n j.*,\n q.place_in_global_queue,\n q.place_in_user_queue\n FROM\n batch_spec_workspace_execution_jobs j\n LEFT JOIN batch_spec_workspace_execution_queue q ON j.id = q.id\n);\n\nDROP TABLE IF EXISTS batch_spec_workspace_execution_last_dequeues;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1657635365 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1658225452, + "Name": "fast_cm_trigger_jobs_delete", + "UpQuery": "CREATE INDEX CONCURRENTLY IF NOT EXISTS cm_trigger_jobs_finished_at ON cm_trigger_jobs (finished_at ASC);", + "DownQuery": "DROP INDEX IF EXISTS cm_trigger_jobs_finished_at;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1657635365 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "cm_trigger_jobs", + "IndexName": "cm_trigger_jobs_finished_at" + } + }, + { + "ID": 1657663493, + "Name": "cancel_worker_feature", + "UpQuery": "ALTER TABLE explicit_permissions_bitbucket_projects_jobs ADD COLUMN IF NOT EXISTS cancel BOOLEAN NOT NULL DEFAULT FALSE;\nALTER TABLE external_service_sync_jobs ADD COLUMN IF NOT EXISTS cancel BOOLEAN NOT NULL DEFAULT FALSE;\nALTER TABLE gitserver_relocator_jobs ADD COLUMN IF NOT EXISTS cancel BOOLEAN NOT NULL DEFAULT FALSE;\nALTER TABLE insights_query_runner_jobs ADD COLUMN IF NOT EXISTS cancel BOOLEAN NOT NULL DEFAULT FALSE;\nALTER TABLE lsif_dependency_indexing_jobs ADD COLUMN IF NOT EXISTS cancel BOOLEAN NOT NULL DEFAULT FALSE;\nALTER TABLE lsif_dependency_syncing_jobs ADD COLUMN IF NOT EXISTS cancel BOOLEAN NOT NULL DEFAULT FALSE;\nALTER TABLE lsif_indexes ADD COLUMN IF NOT EXISTS cancel BOOLEAN NOT NULL DEFAULT FALSE;\nALTER TABLE lsif_uploads ADD COLUMN IF NOT EXISTS cancel BOOLEAN NOT NULL DEFAULT FALSE;\nALTER TABLE batch_spec_resolution_jobs ADD COLUMN IF NOT EXISTS cancel BOOLEAN NOT NULL DEFAULT FALSE;\nALTER TABLE changeset_jobs ADD COLUMN IF NOT EXISTS cancel BOOLEAN NOT NULL DEFAULT FALSE;\nALTER TABLE changesets ADD COLUMN IF NOT EXISTS cancel BOOLEAN NOT NULL DEFAULT FALSE;\nALTER TABLE cm_action_jobs ADD COLUMN IF NOT EXISTS cancel BOOLEAN NOT NULL DEFAULT FALSE;\nALTER TABLE cm_trigger_jobs ADD COLUMN IF NOT EXISTS cancel BOOLEAN NOT NULL DEFAULT FALSE;", + "DownQuery": "ALTER TABLE explicit_permissions_bitbucket_projects_jobs DROP COLUMN IF EXISTS cancel;\nALTER TABLE external_service_sync_jobs DROP COLUMN IF EXISTS cancel;\nALTER TABLE gitserver_relocator_jobs DROP COLUMN IF EXISTS cancel;\nALTER TABLE insights_query_runner_jobs DROP COLUMN IF EXISTS cancel;\nALTER TABLE lsif_dependency_indexing_jobs DROP COLUMN IF EXISTS cancel;\nALTER TABLE lsif_dependency_syncing_jobs DROP COLUMN IF EXISTS cancel;\nALTER TABLE lsif_indexes DROP COLUMN IF EXISTS cancel;\nALTER TABLE lsif_uploads DROP COLUMN IF EXISTS cancel;\nALTER TABLE batch_spec_resolution_jobs DROP COLUMN IF EXISTS cancel;\nALTER TABLE changeset_jobs DROP COLUMN IF EXISTS cancel;\nALTER TABLE changesets DROP COLUMN IF EXISTS cancel;\nALTER TABLE cm_action_jobs DROP COLUMN IF EXISTS cancel;\nALTER TABLE cm_trigger_jobs DROP COLUMN IF EXISTS cancel;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1657279170 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1658255432, + "Name": "add_missing_constraints", + "UpQuery": "DELETE FROM batch_spec_resolution_jobs WHERE batch_spec_id IS NULL OR state IS NULL;\n\nALTER TABLE batch_spec_resolution_jobs\n ALTER COLUMN batch_spec_id SET NOT NULL,\n ALTER COLUMN state SET NOT NULL;\n\nDELETE FROM batch_spec_workspace_execution_jobs WHERE batch_spec_workspace_id IS NULL OR state IS NULL;\n\nALTER TABLE batch_spec_workspace_execution_jobs\n ALTER COLUMN batch_spec_workspace_id SET NOT NULL,\n ALTER COLUMN state SET NOT NULL;\n\nDELETE FROM batch_spec_workspaces WHERE batch_spec_id IS NULL OR changeset_spec_ids IS NULL OR repo_id IS NULL;\n\nALTER TABLE batch_spec_workspaces\n ALTER COLUMN batch_spec_id SET NOT NULL,\n ALTER COLUMN changeset_spec_ids SET NOT NULL,\n ALTER COLUMN repo_id SET NOT NULL;\n\nDELETE FROM changeset_jobs WHERE state IS NULL;\nALTER TABLE changeset_jobs\n ALTER COLUMN state SET NOT NULL;", + "DownQuery": "ALTER TABLE batch_spec_resolution_jobs\n ALTER COLUMN batch_spec_id DROP NOT NULL,\n ALTER COLUMN state DROP NOT NULL;\n\nALTER TABLE batch_spec_workspace_execution_jobs\n ALTER COLUMN batch_spec_workspace_id DROP NOT NULL,\n ALTER COLUMN state DROP NOT NULL;\n\nALTER TABLE batch_spec_workspaces\n ALTER COLUMN batch_spec_id DROP NOT NULL,\n ALTER COLUMN changeset_spec_ids DROP NOT NULL,\n ALTER COLUMN repo_id DROP NOT NULL;\n\nALTER TABLE changeset_jobs\n ALTER COLUMN state DROP NOT NULL;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1654770608, + 1657663493, + 1658174103, + 1658225452 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1658384388, + "Name": "normalize product_licenses.license_key fields", + "UpQuery": "ALTER TABLE product_licenses ADD COLUMN IF NOT EXISTS license_version INT;\nALTER TABLE product_licenses ADD COLUMN IF NOT EXISTS license_tags TEXT[];\nALTER TABLE product_licenses ADD COLUMN IF NOT EXISTS license_user_count INT;\nALTER TABLE product_licenses ADD COLUMN IF NOT EXISTS license_expires_at TIMESTAMP WITH TIME ZONE;\nALTER TABLE product_subscriptions ADD COLUMN IF NOT EXISTS account_number TEXT;", + "DownQuery": "ALTER TABLE product_licenses DROP COLUMN IF EXISTS license_version;\nALTER TABLE product_licenses DROP COLUMN IF EXISTS license_tags;\nALTER TABLE product_licenses DROP COLUMN IF EXISTS license_user_count;\nALTER TABLE product_licenses DROP COLUMN IF EXISTS license_expires_at;\nALTER TABLE product_subscriptions DROP COLUMN IF EXISTS account_number;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1658255432 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1653596521, + "Name": "Add column detached_at to changesets table", + "UpQuery": "ALTER TABLE changesets\n ADD COLUMN IF NOT EXISTS detached_at timestamp with time zone;\n\nCREATE INDEX IF NOT EXISTS\n changesets_detached_at\n ON\n changesets (detached_at);\n\nDROP VIEW IF EXISTS reconciler_changesets;\n\nCREATE VIEW reconciler_changesets AS\nSELECT c.id,\n c.batch_change_ids,\n c.repo_id,\n c.queued_at,\n c.created_at,\n c.updated_at,\n c.metadata,\n c.external_id,\n c.external_service_type,\n c.external_deleted_at,\n c.external_branch,\n c.external_updated_at,\n c.external_state,\n c.external_review_state,\n c.external_check_state,\n c.diff_stat_added,\n c.diff_stat_changed,\n c.diff_stat_deleted,\n c.sync_state,\n c.current_spec_id,\n c.previous_spec_id,\n c.publication_state,\n c.owned_by_batch_change_id,\n c.reconciler_state,\n c.failure_message,\n c.started_at,\n c.finished_at,\n c.process_after,\n c.num_resets,\n c.closing,\n c.num_failures,\n c.log_contents,\n c.execution_logs,\n c.syncer_error,\n c.external_title,\n c.worker_hostname,\n c.ui_publication_state,\n c.last_heartbeat_at,\n c.external_fork_namespace,\n c.detached_at\nFROM changesets c\n JOIN repo r ON r.id = c.repo_id\nWHERE r.deleted_at IS NULL AND EXISTS (\n SELECT 1\n FROM batch_changes\n LEFT JOIN users namespace_user ON batch_changes.namespace_user_id = namespace_user.id\n LEFT JOIN orgs namespace_org ON batch_changes.namespace_org_id = namespace_org.id\n WHERE c.batch_change_ids ? batch_changes.id::text AND namespace_user.deleted_at IS NULL AND namespace_org.deleted_at IS NULL\n );", + "DownQuery": "DROP VIEW IF EXISTS reconciler_changesets;\n\nCREATE VIEW reconciler_changesets AS\nSELECT c.id,\n c.batch_change_ids,\n c.repo_id,\n c.queued_at,\n c.created_at,\n c.updated_at,\n c.metadata,\n c.external_id,\n c.external_service_type,\n c.external_deleted_at,\n c.external_branch,\n c.external_updated_at,\n c.external_state,\n c.external_review_state,\n c.external_check_state,\n c.diff_stat_added,\n c.diff_stat_changed,\n c.diff_stat_deleted,\n c.sync_state,\n c.current_spec_id,\n c.previous_spec_id,\n c.publication_state,\n c.owned_by_batch_change_id,\n c.reconciler_state,\n c.failure_message,\n c.started_at,\n c.finished_at,\n c.process_after,\n c.num_resets,\n c.closing,\n c.num_failures,\n c.log_contents,\n c.execution_logs,\n c.syncer_error,\n c.external_title,\n c.worker_hostname,\n c.ui_publication_state,\n c.last_heartbeat_at,\n c.external_fork_namespace\nFROM changesets c\n JOIN repo r ON r.id = c.repo_id\nWHERE r.deleted_at IS NULL AND EXISTS (\n SELECT 1\n FROM batch_changes\n LEFT JOIN users namespace_user ON batch_changes.namespace_user_id = namespace_user.id\n LEFT JOIN orgs namespace_org ON batch_changes.namespace_org_id = namespace_org.id\n WHERE c.batch_change_ids ? batch_changes.id::text AND namespace_user.deleted_at IS NULL AND namespace_org.deleted_at IS NULL\n );\n\nDROP INDEX IF EXISTS changesets_detached_at;\n\nALTER TABLE changesets DROP COLUMN IF EXISTS detached_at;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1652946496, + 1653334014 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1658484997, + "Name": "add webhook_build_jobs table", + "UpQuery": "CREATE SEQUENCE IF NOT EXISTS webhook_build_jobs_id_seq\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1;\n\n CREATE TABLE IF NOT EXISTS webhook_build_jobs (\n repo_id integer,\n repo_name text,\n extsvc_kind text,\n queued_at timestamp with time zone DEFAULT now(),\n id integer DEFAULT nextval('webhook_build_jobs_id_seq'::regclass) NOT NULL,\n state text DEFAULT 'queued'::text NOT NULL,\n failure_message text,\n started_at timestamp with time zone,\n finished_at timestamp with time zone,\n process_after timestamp with time zone,\n num_resets integer DEFAULT 0 NOT NULL,\n num_failures integer DEFAULT 0 NOT NULL,\n execution_logs json[],\n last_heartbeat_at timestamp with time zone,\n worker_hostname text DEFAULT ''::text NOT NULL\n );\n\n CREATE INDEX IF NOT EXISTS webhook_build_jobs_queued_at_idx ON webhook_build_jobs USING btree (queued_at);", + "DownQuery": "DROP TABLE IF EXISTS webhook_build_jobs;\nDROP INDEX IF EXISTS webhook_build_jobs_queued_at_idx;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1653596521, + 1658384388 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1658503913, + "Name": "batches_changeset_state_computed", + "UpQuery": "ALTER TABLE changesets ADD COLUMN IF NOT EXISTS computed_state TEXT;\n\nDROP TRIGGER IF EXISTS changesets_update_computed_state ON changesets;\n\nUPDATE\n changesets\nSET\n computed_state = CASE\n WHEN reconciler_state = 'errored' THEN 'RETRYING'\n WHEN reconciler_state = 'failed' THEN 'FAILED'\n WHEN reconciler_state = 'scheduled' THEN 'SCHEDULED'\n WHEN reconciler_state != 'completed' THEN 'PROCESSING'\n WHEN publication_state = 'UNPUBLISHED' THEN 'UNPUBLISHED'\n ELSE external_state\n END;\n\nALTER TABLE changesets ALTER COLUMN computed_state SET NOT NULL;\n\nCREATE OR REPLACE FUNCTION changesets_computed_state_ensure() RETURNS trigger\n LANGUAGE plpgsql\n AS $$ BEGIN\n\n NEW.computed_state = CASE\n WHEN NEW.reconciler_state = 'errored' THEN 'RETRYING'\n WHEN NEW.reconciler_state = 'failed' THEN 'FAILED'\n WHEN NEW.reconciler_state = 'scheduled' THEN 'SCHEDULED'\n WHEN NEW.reconciler_state != 'completed' THEN 'PROCESSING'\n WHEN NEW.publication_state = 'UNPUBLISHED' THEN 'UNPUBLISHED'\n ELSE NEW.external_state\n END AS computed_state;\n\n RETURN NEW;\nEND $$;\n\nCREATE TRIGGER changesets_update_computed_state BEFORE INSERT OR UPDATE ON changesets FOR EACH ROW EXECUTE FUNCTION changesets_computed_state_ensure();\n\nDROP VIEW IF EXISTS branch_changeset_specs_and_changesets;\nCREATE VIEW branch_changeset_specs_and_changesets AS\n SELECT changeset_specs.id AS changeset_spec_id,\n COALESCE(changesets.id, (0)::bigint) AS changeset_id,\n changeset_specs.repo_id,\n changeset_specs.batch_spec_id,\n changesets.owned_by_batch_change_id AS owner_batch_change_id,\n repo.name AS repo_name,\n changeset_specs.title AS changeset_name,\n changesets.external_state,\n changesets.publication_state,\n changesets.reconciler_state,\n changesets.computed_state\n FROM ((changeset_specs\n LEFT JOIN changesets ON (((changesets.repo_id = changeset_specs.repo_id) AND (changesets.current_spec_id IS NOT NULL) AND (EXISTS ( SELECT 1\n FROM changeset_specs changeset_specs_1\n WHERE ((changeset_specs_1.id = changesets.current_spec_id) AND (changeset_specs_1.head_ref = changeset_specs.head_ref)))))))\n JOIN repo ON ((changeset_specs.repo_id = repo.id)))\n WHERE ((changeset_specs.external_id IS NULL) AND (repo.deleted_at IS NULL));\n\nDROP VIEW IF EXISTS tracking_changeset_specs_and_changesets;\nCREATE VIEW tracking_changeset_specs_and_changesets AS\n SELECT changeset_specs.id AS changeset_spec_id,\n COALESCE(changesets.id, (0)::bigint) AS changeset_id,\n changeset_specs.repo_id,\n changeset_specs.batch_spec_id,\n repo.name AS repo_name,\n COALESCE((changesets.metadata -\u003e\u003e 'Title'::text), (changesets.metadata -\u003e\u003e 'title'::text)) AS changeset_name,\n changesets.external_state,\n changesets.publication_state,\n changesets.reconciler_state,\n changesets.computed_state\n FROM ((changeset_specs\n LEFT JOIN changesets ON (((changesets.repo_id = changeset_specs.repo_id) AND (changesets.external_id = changeset_specs.external_id))))\n JOIN repo ON ((changeset_specs.repo_id = repo.id)))\n WHERE ((changeset_specs.external_id IS NOT NULL) AND (repo.deleted_at IS NULL));\n\nDROP VIEW IF EXISTS reconciler_changesets;\nCREATE VIEW reconciler_changesets AS\nSELECT c.id,\n c.batch_change_ids,\n c.repo_id,\n c.queued_at,\n c.created_at,\n c.updated_at,\n c.metadata,\n c.external_id,\n c.external_service_type,\n c.external_deleted_at,\n c.external_branch,\n c.external_updated_at,\n c.external_state,\n c.external_review_state,\n c.external_check_state,\n c.diff_stat_added,\n c.diff_stat_changed,\n c.diff_stat_deleted,\n c.sync_state,\n c.current_spec_id,\n c.previous_spec_id,\n c.publication_state,\n c.owned_by_batch_change_id,\n c.reconciler_state,\n c.computed_state,\n c.failure_message,\n c.started_at,\n c.finished_at,\n c.process_after,\n c.num_resets,\n c.closing,\n c.num_failures,\n c.log_contents,\n c.execution_logs,\n c.syncer_error,\n c.external_title,\n c.worker_hostname,\n c.ui_publication_state,\n c.last_heartbeat_at,\n c.external_fork_namespace,\n c.detached_at\nFROM changesets c\n JOIN repo r ON r.id = c.repo_id\nWHERE r.deleted_at IS NULL AND EXISTS (\n SELECT 1\n FROM batch_changes\n LEFT JOIN users namespace_user ON batch_changes.namespace_user_id = namespace_user.id\n LEFT JOIN orgs namespace_org ON batch_changes.namespace_org_id = namespace_org.id\n WHERE c.batch_change_ids ? batch_changes.id::text AND namespace_user.deleted_at IS NULL AND namespace_org.deleted_at IS NULL\n );", + "DownQuery": "DROP TRIGGER IF EXISTS changesets_update_computed_state ON changesets;\nDROP FUNCTION IF EXISTS changesets_computed_state_ensure();\n\nDROP VIEW IF EXISTS branch_changeset_specs_and_changesets;\nCREATE VIEW branch_changeset_specs_and_changesets AS\n SELECT changeset_specs.id AS changeset_spec_id,\n COALESCE(changesets.id, (0)::bigint) AS changeset_id,\n changeset_specs.repo_id,\n changeset_specs.batch_spec_id,\n changesets.owned_by_batch_change_id AS owner_batch_change_id,\n repo.name AS repo_name,\n changeset_specs.title AS changeset_name,\n changesets.external_state,\n changesets.publication_state,\n changesets.reconciler_state\n FROM ((changeset_specs\n LEFT JOIN changesets ON (((changesets.repo_id = changeset_specs.repo_id) AND (changesets.current_spec_id IS NOT NULL) AND (EXISTS ( SELECT 1\n FROM changeset_specs changeset_specs_1\n WHERE ((changeset_specs_1.id = changesets.current_spec_id) AND (changeset_specs_1.head_ref = changeset_specs.head_ref)))))))\n JOIN repo ON ((changeset_specs.repo_id = repo.id)))\n WHERE ((changeset_specs.external_id IS NULL) AND (repo.deleted_at IS NULL));\n\nDROP VIEW IF EXISTS tracking_changeset_specs_and_changesets;\nCREATE VIEW tracking_changeset_specs_and_changesets AS\n SELECT changeset_specs.id AS changeset_spec_id,\n COALESCE(changesets.id, (0)::bigint) AS changeset_id,\n changeset_specs.repo_id,\n changeset_specs.batch_spec_id,\n repo.name AS repo_name,\n COALESCE((changesets.metadata -\u003e\u003e 'Title'::text), (changesets.metadata -\u003e\u003e 'title'::text)) AS changeset_name,\n changesets.external_state,\n changesets.publication_state,\n changesets.reconciler_state\n FROM ((changeset_specs\n LEFT JOIN changesets ON (((changesets.repo_id = changeset_specs.repo_id) AND (changesets.external_id = changeset_specs.external_id))))\n JOIN repo ON ((changeset_specs.repo_id = repo.id)))\n WHERE ((changeset_specs.external_id IS NOT NULL) AND (repo.deleted_at IS NULL));\n\nDROP VIEW IF EXISTS reconciler_changesets;\nCREATE VIEW reconciler_changesets AS\nSELECT c.id,\n c.batch_change_ids,\n c.repo_id,\n c.queued_at,\n c.created_at,\n c.updated_at,\n c.metadata,\n c.external_id,\n c.external_service_type,\n c.external_deleted_at,\n c.external_branch,\n c.external_updated_at,\n c.external_state,\n c.external_review_state,\n c.external_check_state,\n c.diff_stat_added,\n c.diff_stat_changed,\n c.diff_stat_deleted,\n c.sync_state,\n c.current_spec_id,\n c.previous_spec_id,\n c.publication_state,\n c.owned_by_batch_change_id,\n c.reconciler_state,\n c.failure_message,\n c.started_at,\n c.finished_at,\n c.process_after,\n c.num_resets,\n c.closing,\n c.num_failures,\n c.log_contents,\n c.execution_logs,\n c.syncer_error,\n c.external_title,\n c.worker_hostname,\n c.ui_publication_state,\n c.last_heartbeat_at,\n c.external_fork_namespace,\n c.detached_at\nFROM changesets c\n JOIN repo r ON r.id = c.repo_id\nWHERE r.deleted_at IS NULL AND EXISTS (\n SELECT 1\n FROM batch_changes\n LEFT JOIN users namespace_user ON batch_changes.namespace_user_id = namespace_user.id\n LEFT JOIN orgs namespace_org ON batch_changes.namespace_org_id = namespace_org.id\n WHERE c.batch_change_ids ? batch_changes.id::text AND namespace_user.deleted_at IS NULL AND namespace_org.deleted_at IS NULL\n );\n\n\nALTER TABLE changesets DROP COLUMN IF EXISTS computed_state;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1653596521, + 1658384388 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1658512336, + "Name": "batches_changeset_state_index", + "UpQuery": "CREATE INDEX CONCURRENTLY IF NOT EXISTS changesets_computed_state ON changesets (computed_state);", + "DownQuery": "DROP INDEX IF EXISTS changesets_computed_state;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1658503913 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "changesets", + "IndexName": "changesets_computed_state" + } + }, + { + "ID": 1658748822, + "Name": "add_timestamps_to_lockfiles", + "UpQuery": "ALTER TABLE codeintel_lockfiles\n ADD COLUMN IF NOT EXISTS created_at timestamptz NOT NULL DEFAULT NOW(),\n ADD COLUMN IF NOT EXISTS updated_at timestamptz NOT NULL DEFAULT NOW()\n ;\n\nCOMMENT ON COLUMN codeintel_lockfiles.created_at IS 'Time when lockfile was indexed';\nCOMMENT ON COLUMN codeintel_lockfiles.updated_at IS 'Time when lockfile index was updated';", + "DownQuery": "ALTER TABLE codeintel_lockfiles\n DROP COLUMN IF EXISTS created_at,\n DROP COLUMN IF EXISTS updated_at\n ;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1658512336 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1658837440, + "Name": "sync_jobs_missing_index", + "UpQuery": "DELETE FROM external_service_sync_jobs WHERE external_service_id IS NULL;\nALTER TABLE external_service_sync_jobs ALTER COLUMN external_service_id SET NOT NULL;", + "DownQuery": "ALTER TABLE external_service_sync_jobs ALTER COLUMN external_service_id DROP NOT NULL;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1658748822 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1658856572, + "Name": "event_log_scrape_state", + "UpQuery": "CREATE TABLE IF NOT EXISTS event_logs_scrape_state\n(\n id SERIAL\n CONSTRAINT event_logs_scrape_state_pk\n PRIMARY KEY,\n bookmark_id INT NOT NULL\n);\n\nCOMMENT ON TABLE event_logs_scrape_state IS 'Contains state for the periodic telemetry job that scrapes events if enabled.';\nCOMMENT ON COLUMN event_logs_scrape_state.bookmark_id IS 'Bookmarks the maximum most recent successful event_logs.id that was scraped';", + "DownQuery": "DROP TABLE IF EXISTS event_logs_scrape_state;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1658748822 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1658950366, + "Name": "event_log_scrape_allow_list", + "UpQuery": "CREATE TABLE IF NOT EXISTS event_logs_export_allowlist\n(\n id SERIAL PRIMARY KEY,\n event_name TEXT NOT NULL\n);\n\nCREATE UNIQUE INDEX IF NOT EXISTS event_logs_export_allowlist_event_name_idx ON event_logs_export_allowlist (event_name);\n\nCOMMENT ON TABLE event_logs_export_allowlist IS 'An allowlist of events that are approved for export if the scraping job is enabled';\nCOMMENT ON COLUMN event_logs_export_allowlist.event_name IS 'Name of the event that corresponds to event_logs.name';", + "DownQuery": "DROP TABLE IF EXISTS event_logs_export_allowlist;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1658122170, + 1658484997, + 1658856572 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1659085788, + "Name": "add_repo_stats_table", + "UpQuery": "--------------------------------------------------------------------------------\n-- repos table --\n--------------------------------------------------------------------------------\n\n-- repo_statistics holds statistics for the repo table (hence the singular\n-- \"repo\" in the name)\nCREATE TABLE IF NOT EXISTS repo_statistics (\n total BIGINT NOT NULL DEFAULT 0,\n soft_deleted BIGINT NOT NULL DEFAULT 0,\n not_cloned BIGINT NOT NULL DEFAULT 0,\n cloning BIGINT NOT NULL DEFAULT 0,\n cloned BIGINT NOT NULL DEFAULT 0,\n failed_fetch BIGINT NOT NULL DEFAULT 0\n);\n\nCOMMENT ON COLUMN repo_statistics.total IS 'Number of repositories that are not soft-deleted and not blocked';\nCOMMENT ON COLUMN repo_statistics.soft_deleted IS 'Number of repositories that are soft-deleted and not blocked';\nCOMMENT ON COLUMN repo_statistics.not_cloned IS 'Number of repositories that are NOT soft-deleted and not blocked and not cloned by gitserver';\nCOMMENT ON COLUMN repo_statistics.cloning IS 'Number of repositories that are NOT soft-deleted and not blocked and currently being cloned by gitserver';\nCOMMENT ON COLUMN repo_statistics.cloned IS 'Number of repositories that are NOT soft-deleted and not blocked and cloned by gitserver';\nCOMMENT ON COLUMN repo_statistics.failed_fetch IS 'Number of repositories that are NOT soft-deleted and not blocked and have last_error set in gitserver_repos table';\n\n-- Insert initial values into repo_statistics table\nINSERT INTO repo_statistics (total, soft_deleted, not_cloned, cloning, cloned, failed_fetch)\nVALUES (\n (SELECT COUNT(*) FROM repo WHERE deleted_at is NULL AND blocked IS NULL),\n (SELECT COUNT(*) FROM repo WHERE deleted_at is NOT NULL AND blocked IS NULL),\n (\n SELECT COUNT(*)\n FROM repo\n JOIN gitserver_repos gr ON gr.repo_id = repo.id\n WHERE\n repo.deleted_at is NULL\n AND\n repo.blocked IS NULL\n AND\n gr.clone_status = 'not_cloned'\n ),\n (\n SELECT COUNT(*)\n FROM repo\n JOIN gitserver_repos gr ON gr.repo_id = repo.id\n WHERE\n repo.deleted_at is NULL\n AND\n repo.blocked IS NULL\n AND\n gr.clone_status = 'cloning'\n ),\n (\n SELECT COUNT(*)\n FROM repo\n JOIN gitserver_repos gr ON gr.repo_id = repo.id\n WHERE\n repo.deleted_at is NULL\n AND\n repo.blocked IS NULL\n AND\n gr.clone_status = 'cloned'\n ),\n (\n SELECT COUNT(*)\n FROM repo\n JOIN gitserver_repos gr ON gr.repo_id = repo.id\n WHERE\n repo.deleted_at is NULL\n AND\n repo.blocked IS NULL\n AND\n gr.last_error IS NOT NULL\n )\n);\n\n-- UPDATE\nCREATE OR REPLACE FUNCTION recalc_repo_statistics_on_repo_update() RETURNS trigger\n LANGUAGE plpgsql\n AS $$ BEGIN\n -- Insert diff of changes\n INSERT INTO\n repo_statistics (total, soft_deleted, not_cloned, cloning, cloned, failed_fetch)\n VALUES (\n (SELECT COUNT(*) FROM newtab WHERE deleted_at IS NULL AND blocked IS NULL) - (SELECT COUNT(*) FROM oldtab WHERE deleted_at IS NULL AND blocked IS NULL),\n (SELECT COUNT(*) FROM newtab WHERE deleted_at IS NOT NULL AND blocked IS NULL) - (SELECT COUNT(*) FROM oldtab WHERE deleted_at IS NOT NULL AND blocked IS NULL),\n (\n (SELECT COUNT(*) FROM newtab JOIN gitserver_repos gr ON gr.repo_id = newtab.id WHERE newtab.deleted_at is NULL AND newtab.blocked IS NULL AND gr.clone_status = 'not_cloned')\n -\n (SELECT COUNT(*) FROM oldtab JOIN gitserver_repos gr ON gr.repo_id = oldtab.id WHERE oldtab.deleted_at is NULL AND oldtab.blocked IS NULL AND gr.clone_status = 'not_cloned')\n ),\n (\n (SELECT COUNT(*) FROM newtab JOIN gitserver_repos gr ON gr.repo_id = newtab.id WHERE newtab.deleted_at is NULL AND newtab.blocked IS NULL AND gr.clone_status = 'cloning')\n -\n (SELECT COUNT(*) FROM oldtab JOIN gitserver_repos gr ON gr.repo_id = oldtab.id WHERE oldtab.deleted_at is NULL AND oldtab.blocked IS NULL AND gr.clone_status = 'cloning')\n ),\n (\n (SELECT COUNT(*) FROM newtab JOIN gitserver_repos gr ON gr.repo_id = newtab.id WHERE newtab.deleted_at is NULL AND newtab.blocked IS NULL AND gr.clone_status = 'cloned')\n -\n (SELECT COUNT(*) FROM oldtab JOIN gitserver_repos gr ON gr.repo_id = oldtab.id WHERE oldtab.deleted_at is NULL AND oldtab.blocked IS NULL AND gr.clone_status = 'cloned')\n ),\n (\n (SELECT COUNT(*) FROM newtab JOIN gitserver_repos gr ON gr.repo_id = newtab.id WHERE newtab.deleted_at is NULL AND newtab.blocked IS NULL AND gr.last_error IS NOT NULL)\n -\n (SELECT COUNT(*) FROM oldtab JOIN gitserver_repos gr ON gr.repo_id = oldtab.id WHERE oldtab.deleted_at is NULL AND oldtab.blocked IS NULL AND gr.last_error IS NOT NULL)\n )\n )\n ;\n RETURN NULL;\n END\n$$;\nDROP TRIGGER IF EXISTS trig_recalc_repo_statistics_on_repo_update ON repo;\nCREATE TRIGGER trig_recalc_repo_statistics_on_repo_update\nAFTER UPDATE ON repo\nREFERENCING OLD TABLE AS oldtab NEW TABLE AS newtab\nFOR EACH STATEMENT EXECUTE FUNCTION recalc_repo_statistics_on_repo_update();\n\n-- INSERT\nCREATE OR REPLACE FUNCTION recalc_repo_statistics_on_repo_insert() RETURNS trigger\n LANGUAGE plpgsql\n AS $$ BEGIN\n INSERT INTO\n repo_statistics (total, soft_deleted, not_cloned)\n VALUES (\n (SELECT COUNT(*) FROM newtab WHERE deleted_at IS NULL AND blocked IS NULL),\n (SELECT COUNT(*) FROM newtab WHERE deleted_at IS NOT NULL AND blocked IS NULL),\n -- New repositories are always not_cloned by default, so we can count them as not cloned here\n (SELECT COUNT(*) FROM newtab WHERE deleted_at IS NULL AND blocked IS NULL)\n -- New repositories never have last_error set, so we can also ignore those here\n );\n RETURN NULL;\n END\n$$;\nDROP TRIGGER IF EXISTS trig_recalc_repo_statistics_on_repo_insert ON repo;\nCREATE TRIGGER trig_recalc_repo_statistics_on_repo_insert\nAFTER INSERT ON repo\nREFERENCING NEW TABLE AS newtab\nFOR EACH STATEMENT EXECUTE FUNCTION recalc_repo_statistics_on_repo_insert();\n\n-- DELETE\nCREATE OR REPLACE FUNCTION recalc_repo_statistics_on_repo_delete() RETURNS trigger\n LANGUAGE plpgsql\n AS $$ BEGIN\n INSERT INTO\n repo_statistics (total, soft_deleted, not_cloned, cloning, cloned, failed_fetch)\n VALUES (\n -- Insert negative counts\n (SELECT -COUNT(*) FROM oldtab WHERE deleted_at IS NULL AND blocked IS NULL),\n (SELECT -COUNT(*) FROM oldtab WHERE deleted_at IS NOT NULL AND blocked IS NULL),\n (SELECT -COUNT(*) FROM oldtab JOIN gitserver_repos gr ON gr.repo_id = oldtab.id WHERE oldtab.deleted_at is NULL AND oldtab.blocked IS NULL AND gr.clone_status = 'not_cloned'),\n (SELECT -COUNT(*) FROM oldtab JOIN gitserver_repos gr ON gr.repo_id = oldtab.id WHERE oldtab.deleted_at is NULL AND oldtab.blocked IS NULL AND gr.clone_status = 'cloning'),\n (SELECT -COUNT(*) FROM oldtab JOIN gitserver_repos gr ON gr.repo_id = oldtab.id WHERE oldtab.deleted_at is NULL AND oldtab.blocked IS NULL AND gr.clone_status = 'cloned'),\n (SELECT -COUNT(*) FROM oldtab JOIN gitserver_repos gr ON gr.repo_id = oldtab.id WHERE oldtab.deleted_at is NULL AND oldtab.blocked IS NULL AND gr.last_error IS NOT NULL)\n );\n RETURN NULL;\n END\n$$;\nDROP TRIGGER IF EXISTS trig_recalc_repo_statistics_on_repo_delete ON repo;\nCREATE TRIGGER trig_recalc_repo_statistics_on_repo_delete\nAFTER DELETE ON repo\nREFERENCING OLD TABLE AS oldtab\nFOR EACH STATEMENT EXECUTE FUNCTION recalc_repo_statistics_on_repo_delete();\n\n--------------------------------------------------------------------------------\n-- gitserver_repos table --\n--------------------------------------------------------------------------------\n\n-- gitserver_repos_statistics holds statistics for the gitserver_repos table\nCREATE TABLE IF NOT EXISTS gitserver_repos_statistics (\n -- In this table we have one row per shard_id\n shard_id text PRIMARY KEY,\n\n total BIGINT NOT NULL DEFAULT 0,\n not_cloned BIGINT NOT NULL DEFAULT 0,\n cloning BIGINT NOT NULL DEFAULT 0,\n cloned BIGINT NOT NULL DEFAULT 0,\n failed_fetch BIGINT NOT NULL DEFAULT 0\n);\n\nCOMMENT ON COLUMN gitserver_repos_statistics.shard_id IS 'ID of this gitserver shard. If an empty string then the repositories havent been assigned a shard.';\nCOMMENT ON COLUMN gitserver_repos_statistics.total IS 'Number of repositories in gitserver_repos table on this shard';\nCOMMENT ON COLUMN gitserver_repos_statistics.not_cloned IS 'Number of repositories in gitserver_repos table on this shard that are not cloned yet';\nCOMMENT ON COLUMN gitserver_repos_statistics.cloning IS 'Number of repositories in gitserver_repos table on this shard that cloning';\nCOMMENT ON COLUMN gitserver_repos_statistics.cloned IS 'Number of repositories in gitserver_repos table on this shard that are cloned';\nCOMMENT ON COLUMN gitserver_repos_statistics.failed_fetch IS 'Number of repositories in gitserver_repos table on this shard where last_error is set';\n\n-- Insert initial values into gitserver_repos_statistics\nINSERT INTO\n gitserver_repos_statistics (shard_id, total, not_cloned, cloning, cloned, failed_fetch)\nSELECT\n shard_id,\n COUNT(*) AS total,\n COUNT(*) FILTER(WHERE clone_status = 'not_cloned') AS not_cloned,\n COUNT(*) FILTER(WHERE clone_status = 'cloning') AS cloning,\n COUNT(*) FILTER(WHERE clone_status = 'cloned') AS cloned,\n COUNT(*) FILTER(WHERE last_error IS NOT NULL) AS failed_fetch\nFROM\n gitserver_repos\nGROUP BY shard_id\nON CONFLICT(shard_id)\nDO UPDATE\nSET\n total = gitserver_repos_statistics.total + excluded.total,\n not_cloned = gitserver_repos_statistics.not_cloned + excluded.not_cloned,\n cloning = gitserver_repos_statistics.cloning + excluded.cloning,\n cloned = gitserver_repos_statistics.cloned + excluded.cloned,\n failed_fetch = gitserver_repos_statistics.failed_fetch + excluded.failed_fetch\n;\n\n-- UPDATE\nCREATE OR REPLACE FUNCTION recalc_gitserver_repos_statistics_on_update() RETURNS trigger\n LANGUAGE plpgsql\n AS $$ BEGIN\n INSERT INTO gitserver_repos_statistics AS grs (shard_id, total, not_cloned, cloning, cloned, failed_fetch)\n SELECT\n newtab.shard_id AS shard_id,\n COUNT(*) AS total,\n COUNT(*) FILTER(WHERE clone_status = 'not_cloned') AS not_cloned,\n COUNT(*) FILTER(WHERE clone_status = 'cloning') AS cloning,\n COUNT(*) FILTER(WHERE clone_status = 'cloned') AS cloned,\n COUNT(*) FILTER(WHERE last_error IS NOT NULL) AS failed_fetch\n FROM\n newtab\n GROUP BY newtab.shard_id\n ON CONFLICT(shard_id) DO\n UPDATE\n SET\n total = grs.total + (excluded.total - (SELECT COUNT(*) FROM oldtab ot WHERE ot.shard_id = excluded.shard_id)),\n not_cloned = grs.not_cloned + (excluded.not_cloned - (SELECT COUNT(*) FILTER(WHERE ot.clone_status = 'not_cloned') FROM oldtab ot WHERE ot.shard_id = excluded.shard_id)),\n cloning = grs.cloning + (excluded.cloning - (SELECT COUNT(*) FILTER(WHERE ot.clone_status = 'cloning') FROM oldtab ot WHERE ot.shard_id = excluded.shard_id)),\n cloned = grs.cloned + (excluded.cloned - (SELECT COUNT(*) FILTER(WHERE ot.clone_status = 'cloned') FROM oldtab ot WHERE ot.shard_id = excluded.shard_id)),\n failed_fetch = grs.failed_fetch + (excluded.failed_fetch - (SELECT COUNT(*) FILTER(WHERE ot.last_error IS NOT NULL) FROM oldtab ot WHERE ot.shard_id = excluded.shard_id))\n ;\n\n WITH moved AS (\n SELECT\n oldtab.shard_id AS shard_id,\n COUNT(*) AS total,\n COUNT(*) FILTER(WHERE oldtab.clone_status = 'not_cloned') AS not_cloned,\n COUNT(*) FILTER(WHERE oldtab.clone_status = 'cloning') AS cloning,\n COUNT(*) FILTER(WHERE oldtab.clone_status = 'cloned') AS cloned,\n COUNT(*) FILTER(WHERE oldtab.last_error IS NOT NULL) AS failed_fetch\n FROM\n oldtab\n JOIN newtab ON newtab.repo_id = oldtab.repo_id\n WHERE\n oldtab.shard_id != newtab.shard_id\n GROUP BY oldtab.shard_id\n )\n UPDATE gitserver_repos_statistics grs\n SET\n total = grs.total - moved.total,\n not_cloned = grs.not_cloned - moved.not_cloned,\n cloning = grs.cloning - moved.cloning,\n cloned = grs.cloned - moved.cloned,\n failed_fetch = grs.failed_fetch - moved.failed_fetch\n FROM moved\n WHERE moved.shard_id = grs.shard_id;\n\n INSERT INTO repo_statistics (not_cloned, cloning, cloned, failed_fetch)\n VALUES (\n (\n (SELECT COUNT(*) FROM newtab JOIN repo r ON newtab.repo_id = r.id WHERE r.deleted_at is NULL AND r.blocked IS NULL AND newtab.clone_status = 'not_cloned')\n -\n (SELECT COUNT(*) FROM oldtab JOIN repo r ON oldtab.repo_id = r.id WHERE r.deleted_at is NULL AND r.blocked IS NULL AND oldtab.clone_status = 'not_cloned')\n ),\n (\n (SELECT COUNT(*) FROM newtab JOIN repo r ON newtab.repo_id = r.id WHERE r.deleted_at is NULL AND r.blocked IS NULL AND newtab.clone_status = 'cloning')\n -\n (SELECT COUNT(*) FROM oldtab JOIN repo r ON oldtab.repo_id = r.id WHERE r.deleted_at is NULL AND r.blocked IS NULL AND oldtab.clone_status = 'cloning')\n ),\n (\n (SELECT COUNT(*) FROM newtab JOIN repo r ON newtab.repo_id = r.id WHERE r.deleted_at is NULL AND r.blocked IS NULL AND newtab.clone_status = 'cloned')\n -\n (SELECT COUNT(*) FROM oldtab JOIN repo r ON oldtab.repo_id = r.id WHERE r.deleted_at is NULL AND r.blocked IS NULL AND oldtab.clone_status = 'cloned')\n ),\n (\n (SELECT COUNT(*) FROM newtab JOIN repo r ON newtab.repo_id = r.id WHERE r.deleted_at is NULL AND r.blocked IS NULL AND newtab.last_error IS NOT NULL)\n -\n (SELECT COUNT(*) FROM oldtab JOIN repo r ON oldtab.repo_id = r.id WHERE r.deleted_at is NULL AND r.blocked IS NULL AND oldtab.last_error IS NOT NULL)\n )\n );\n\n RETURN NULL;\n END\n$$;\nDROP TRIGGER IF EXISTS trig_recalc_gitserver_repos_statistics_on_update ON gitserver_repos;\nCREATE TRIGGER trig_recalc_gitserver_repos_statistics_on_update\nAFTER UPDATE ON gitserver_repos\nREFERENCING OLD TABLE AS oldtab NEW TABLE AS newtab\nFOR EACH STATEMENT EXECUTE FUNCTION recalc_gitserver_repos_statistics_on_update();\n\n-- INSERT\nCREATE OR REPLACE FUNCTION recalc_gitserver_repos_statistics_on_insert() RETURNS trigger\n LANGUAGE plpgsql\n AS $$ BEGIN\n INSERT INTO gitserver_repos_statistics AS grs (shard_id, total, not_cloned, cloning, cloned, failed_fetch)\n SELECT\n shard_id,\n COUNT(*) AS total,\n COUNT(*) FILTER(WHERE clone_status = 'not_cloned') AS not_cloned,\n COUNT(*) FILTER(WHERE clone_status = 'cloning') AS cloning,\n COUNT(*) FILTER(WHERE clone_status = 'cloned') AS cloned,\n COUNT(*) FILTER(WHERE last_error IS NOT NULL) AS failed_fetch\n FROM\n newtab\n GROUP BY shard_id\n ON CONFLICT(shard_id)\n DO UPDATE\n SET\n total = grs.total + excluded.total,\n not_cloned = grs.not_cloned + excluded.not_cloned,\n cloning = grs.cloning + excluded.cloning,\n cloned = grs.cloned + excluded.cloned,\n failed_fetch = grs.failed_fetch + excluded.failed_fetch\n ;\n\n RETURN NULL;\n END\n$$;\nDROP TRIGGER IF EXISTS trig_recalc_gitserver_repos_statistics_on_insert ON gitserver_repos;\nCREATE TRIGGER trig_recalc_gitserver_repos_statistics_on_insert\nAFTER INSERT ON gitserver_repos\nREFERENCING NEW TABLE AS newtab\nFOR EACH STATEMENT EXECUTE FUNCTION recalc_gitserver_repos_statistics_on_insert();\n\n-- DELETE\nCREATE OR REPLACE FUNCTION recalc_gitserver_repos_statistics_on_delete() RETURNS trigger\n LANGUAGE plpgsql\n AS $$ BEGIN\n UPDATE gitserver_repos_statistics grs\n SET\n total = grs.total - (SELECT COUNT(*) FROM oldtab WHERE oldtab.shard_id = grs.shard_id),\n not_cloned = grs.not_cloned - (SELECT COUNT(*) FILTER(WHERE clone_status = 'not_cloned') FROM oldtab WHERE oldtab.shard_id = grs.shard_id),\n cloning = grs.cloning - (SELECT COUNT(*) FILTER(WHERE clone_status = 'cloning') FROM oldtab WHERE oldtab.shard_id = grs.shard_id),\n cloned = grs.cloned - (SELECT COUNT(*) FILTER(WHERE clone_status = 'cloned') FROM oldtab WHERE oldtab.shard_id = grs.shard_id),\n failed_fetch = grs.cloned - (SELECT COUNT(*) FILTER(WHERE last_error IS NOT NULL) FROM oldtab WHERE oldtab.shard_id = grs.shard_id)\n ;\n\n RETURN NULL;\n END\n$$;\nDROP TRIGGER IF EXISTS trig_recalc_gitserver_repos_statistics_on_delete ON gitserver_repos;\nCREATE TRIGGER trig_recalc_gitserver_repos_statistics_on_delete\nAFTER DELETE ON gitserver_repos REFERENCING\nOLD TABLE AS oldtab\nFOR EACH STATEMENT EXECUTE FUNCTION recalc_gitserver_repos_statistics_on_delete();", + "DownQuery": "DROP TRIGGER IF EXISTS trig_recalc_repo_statistics_on_repo_update ON repo;\nDROP TRIGGER IF EXISTS trig_recalc_repo_statistics_on_repo_insert ON repo;\nDROP TRIGGER IF EXISTS trig_recalc_repo_statistics_on_repo_delete ON repo;\n\nDROP FUNCTION IF EXISTS recalc_repo_statistics_on_repo_update();\nDROP FUNCTION IF EXISTS recalc_repo_statistics_on_repo_insert();\nDROP FUNCTION IF EXISTS recalc_repo_statistics_on_repo_delete();\n\nDROP TRIGGER IF EXISTS trig_recalc_gitserver_repos_statistics_on_update ON gitserver_repos;\nDROP TRIGGER IF EXISTS trig_recalc_gitserver_repos_statistics_on_insert ON gitserver_repos;\nDROP TRIGGER IF EXISTS trig_recalc_gitserver_repos_statistics_on_delete ON gitserver_repos;\n\nDROP FUNCTION IF EXISTS recalc_gitserver_repos_statistics_on_update();\nDROP FUNCTION IF EXISTS recalc_gitserver_repos_statistics_on_insert();\nDROP FUNCTION IF EXISTS recalc_gitserver_repos_statistics_on_delete();\n\nDROP TABLE IF EXISTS gitserver_repos_statistics;\nDROP TABLE IF EXISTS repo_statistics;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1658950366 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1659368926, + "Name": "cleanup_lsif_indexes_errored", + "UpQuery": "UPDATE lsif_indexes SET state = 'failed' WHERE state = 'errored' AND num_failures \u003e 0;", + "DownQuery": "-- Nothing to do here, to older instances both versions of this data are valid state.", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1658950366 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1659380538, + "Name": "event_log_dot_com_fields", + "UpQuery": "ALTER TABLE IF EXISTS event_logs\n ADD COLUMN IF NOT EXISTS first_source_url TEXT,\n ADD COLUMN IF NOT EXISTS last_source_url TEXT,\n ADD COLUMN IF NOT EXISTS referrer TEXT,\n ADD COLUMN IF NOT EXISTS device_id TEXT,\n ADD COLUMN IF NOT EXISTS insert_id TEXT;", + "DownQuery": "ALTER TABLE IF EXISTS event_logs\n DROP COLUMN IF EXISTS first_source_url,\n DROP COLUMN IF EXISTS last_source_url,\n DROP COLUMN IF EXISTS referrer,\n DROP COLUMN IF EXISTS device_id,\n DROP COLUMN IF EXISTS insert_id;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1659368926 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1659434035, + "Name": "alter webhook_build_jobs table", + "UpQuery": "ALTER TABLE IF EXISTS webhook_build_jobs\n ADD COLUMN IF NOT EXISTS org text,\n ADD COLUMN IF NOT EXISTS extsvc_id integer;", + "DownQuery": "ALTER TABLE IF EXISTS webhook_build_jobs\n DROP COLUMN IF EXISTS org,\n DROP COLUMN IF EXISTS extsvc_id;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1659368926 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1659459805, + "Name": "repo key value pairs", + "UpQuery": "-- Perform migration here.\n\nCREATE TABLE IF NOT EXISTS repo_kvps (\n repo_id INTEGER NOT NULL REFERENCES repo(id) ON DELETE CASCADE,\n key TEXT NOT NULL,\n value TEXT NULL,\n PRIMARY KEY (repo_id, key) INCLUDE (value)\n);", + "DownQuery": "-- Undo the changes made in the up migration\n\nDROP TABLE IF EXISTS repo_kvps;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1659434035 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1659721548, + "Name": "data_usage_seed_allowlist", + "UpQuery": "INSERT INTO event_logs_export_allowlist (event_name)\nVALUES ('codeintel.searchDocumentHighlight'),\n ('SearchNotebookBlocksUpdated'),\n ('search.latencies.symbol'),\n ('hover'),\n ('codeintel.lsifDocumentHighlight'),\n ('search.latencies.literal'),\n ('codeintel.lsifHover'),\n ('codeintel.lsifDefinitions'),\n ('SearchResultsFetched'),\n ('search.latencies.regexp'),\n ('codeintel.searchDefinitions'),\n ('codeintel.searchHover'),\n ('ViewHome'),\n ('ViewSearchResults'),\n ('search.latencies.repo'),\n ('HomepageInvitationsViewEmpty'),\n ('RecentSearchesPanelLoaded'),\n ('SavedSearchesPanelLoaded'),\n ('SearchResultClicked'),\n ('INSIGHT_TOTAL_ORGS_WITH_DASHBOARD'),\n ('INSIGHT_TOTAL_COUNT_CRITICAL'),\n ('INSIGHT_TIME_INTERVALS'),\n ('INSIGHT_ORG_VISIBLE_INSIGHTS'),\n ('INSIGHT_TOTAL_COUNTS'),\n ('INSIGHT_DASHBOARD_TOTAL_COUNT'),\n ('INSIGHTS_PER_DASHBORD_STATS'),\n ('RepositoriesPanelLoaded'),\n ('RecentFilesPanelLoaded'),\n ('SearchResultsCacheRetrieved'),\n ('BrowserExtensionConnectedToServer'),\n ('ViewTree'),\n ('FileTreeClick'),\n ('codeintel.searchDefinitions.xrepo'),\n ('search.latencies.file'),\n ('ViewNoResultsPage'),\n ('ViewRepository'),\n ('search.latencies.structural'),\n ('InsightHover'),\n ('ExternalAuthSignupFailed'),\n ('CodeIntelRefs'),\n ('search.latencies.diff'),\n ('SurveyReminderViewed'),\n ('ExtensionActivation'),\n ('InstallBrowserExtensionCTAShown'),\n ('ViewSiteAdminOverview'),\n ('ViewSettingsUser'),\n ('SearchContextDropdownToggled'),\n ('definitionHoverOverlay.click'),\n ('InstallIDEExtensionCTAShown'),\n ('search.latencies.commit'),\n ('ViewRepositoryCommit'),\n ('ViewOnboardingTour'),\n ('ViewCodeIntelIndexes'),\n ('ViewInsights'),\n ('codeintel.lsifReferences'),\n ('NotebookVisibilitySettingsDropdownToggled'),\n ('referenceHoverOverlay.click'),\n ('ViewSearchNotebooksListMyNotebooks'),\n ('ViewBatchChangesListPage'),\n ('SearchContextsDropdownViewed'),\n ('ViewExecutorsList'),\n ('findReferences'),\n ('ReferencePanelResultsClicked'),\n ('SearchNotebooksListPageViewed'),\n ('SearchNotebookPageViewed'),\n ('ViewCodeIntelUploads'),\n ('ViewCodeIntelConfiguration'),\n ('ExternalAuthSignupSucceeded'),\n ('ViewSiteAdminConfiguration'),\n ('goToDefinition.preloaded'),\n ('ViewSiteAdminExternalServices'),\n ('CodeCopied'),\n ('SearchNotebookRunBlock'),\n ('ViewSiteAdminRepos'),\n ('git.blame.toggle'),\n ('codeintel.searchReferences'),\n ('SearchContextSelected'),\n ('ViewSiteAdminUsageStatistics'),\n ('ViewUserProfile'),\n ('SettingsFileSaved'),\n ('CodeMonitoringGettingStartedPageViewed'),\n ('SignInAttempted'),\n ('SearchNotebookAddBlock'),\n ('ViewUserSettingsTokens'),\n ('ViewCodeIntelIndex'),\n ('GoToCodeHostClicked'),\n ('RecentSearchesPanelSearchClicked'),\n ('RepositoriesPanelRepoFilterClicked'),\n ('codeintel.lsifDefinitions.xrepo'),\n ('ViewSiteAdminAllUsers'),\n ('SignInSucceeded'),\n ('CodeMonitoringPageViewed'),\n ('ViewCodeIntelRepositoryIndexConfiguration'),\n ('ViewCodeIntelConfigurationPolicy'),\n ('NotebooksGettingStartedTabViewed'),\n ('ViewAddExternalService'),\n ('InsightUICustomization'),\n ('ViewRepositoryError'),\n ('ViewCodeInsightsCreationPage'),\n ('SearchNotebookShareModalOpened'),\n ('ViewSiteAdminExternalService'),\n ('ViewExtensionsOverview'),\n ('ManageCodeMonitorPageViewed'),\n ('ViewInsightsGetStartedPage'),\n ('StandaloneInsightPageViewed'),\n ('ViewBatchChangeDetailsPage'),\n ('ViewRevisionsPopover'),\n ('ViewUserSettingsEmails'),\n ('codeintel.searchReferences.xrepo'),\n ('SymbolTreeViewClicked'),\n ('ViewApiConsole'),\n ('UTMCodeHostIntegration'),\n ('ViewSettingsSite'),\n ('ViewRepoSettingsIndex'),\n ('codeintel.lsifImplementations'),\n ('IDESearchSubmitted'),\n ('ViewUserSettingsProductResearch'),\n ('ViewUserSettingsPassword'),\n ('ViewSettingsOrg'),\n ('ViewSearchNotebooksListExploreNotebooks'),\n ('ViewRepoSettings'),\n ('SearchDidYouMeanDisplayed'),\n ('SiteConfigurationSaved'),\n ('ShowHistoryPanel'),\n ('ViewSavedSearchListPage'),\n ('ViewCodeInsightsSearchBasedCreationPage'),\n ('findImplementations'),\n ('ViewRepoSettingsMirror'),\n ('AdminAnalyticsCodeIntelViewed'),\n ('AdminAnalyticsSearchViewed'),\n ('InsightAddMoreClick'),\n ('ViewSignIn'),\n ('ViewOrgSettingsProfile'),\n ('InsightDataPointClick'),\n ('SignInFailed'),\n ('ViewSearchNotebooksListStarredNotebooks'),\n ('ViewSiteAdminOrgs'),\n ('ViewRepoSettingsPermissions'),\n ('BrowserExtensionPopupOpened'),\n ('CreateCodeMonitorPageViewed'),\n ('FuzzyFinderViewed'),\n ('ViewNewAccessToken'),\n ('AccessTokenCreated'),\n ('RepositoriesPopover'),\n ('ViewRepositoriesPopover'),\n ('SearchNotebookDeleteBlock'),\n ('RootBreadcrumbClicked'),\n ('ViewUserEventLogPage'),\n ('CodeInsightsCreateSearchBasedInsightClick'),\n ('ViewRepositoryCompareOverview'),\n ('InsightAddition'),\n ('AdminAnalyticsCodeIntelAggUniquesClicked'),\n ('StandaloneInsightPageEditClick'),\n ('SearchNotebookTitleUpdated'),\n ('SearchNotebooksNotebooksTabClick'),\n ('CopyFilePath'),\n ('ViewOrgMembers'),\n ('InsightEdit'),\n ('RepositoryComparisonFetched'),\n ('SearchNotebookCreated'),\n ('AdminAnalyticsNotebooksViewed'),\n ('NoResultsPanel'),\n ('ViewSiteAdminProductSubscription'),\n ('AdminAnalyticsUsersViewed'),\n ('ReferencePanelClickedReferences'),\n ('CreateCodeMonitorFormSubmitted'),\n ('ViewBatchChangeApplyPage'),\n ('CloseOnboardingTourClicked'),\n ('IDEInstalled'),\n ('FileTreeViewClicked'),\n ('AdminAnalyticsBatchChangesViewed'),\n ('ViewRepositoryBranchesOverview'),\n ('WAUsChartSelected'),\n ('ViewCodeIntelUpload'),\n ('codeintel.lsifReferences.xrepo'),\n ('mixPreciseAndSearchBasedReferences.toggle'),\n ('ViewSiteAdminSurveyResponses'),\n ('ViewRepositoryCommits'),\n ('ViewNewOrg'),\n ('SearchResultsFetchFailed'),\n ('SiteConfigurationActionExecuted'),\n ('CodeInsightsSearchBasedCreationPageSubmitClick'),\n ('ReferencePanelClickedImplementations'),\n ('SearchNotebookMoveBlock'),\n ('UserNotificationsLinkClicked'),\n ('AdminAnalyticsCodeIntelAggTotalsClicked'),\n ('ReferencePanelClickedDefinition'),\n ('ViewCodeInsightsCaptureGroupCreationPage'),\n ('SearchNotebooksGettingStartedTabClick'),\n ('ViewUserSettingsPermissions'),\n ('CodeInsightsCreateCaptureGroupInsightClick'),\n ('BrowserExtensionPopupRejected'),\n ('AdminAnalyticsSearchAggUniquesClicked'),\n ('CommitSHACopiedToClipboard'),\n ('ExtensionToggled'),\n ('vscode.open.file'),\n ('SearchNotebookRunAllBlocks'),\n ('CodeInsightsDashboardCreationPageSubmitClick'),\n ('BatchSpecCreated'),\n ('AddExternalServiceSucceeded'),\n ('ManageCodeMonitorFormSubmitted'),\n ('BatchChangeCreatedOrUpdated'),\n ('SearchNotepadEnabled'),\n ('ReferencePanelClickedHistory'),\n ('SearchSnippetClicked'),\n ('ViewSiteAdminUpdates'),\n ('CodeInsightsCaptureGroupCreationPageSubmitClick'),\n ('SearchSkippedResultsAgainClicked'),\n ('ViewRepositoryReleasesTags'),\n ('OrgMemberAdded'),\n ('RepositoryComparisonSubmitted'),\n ('AdminAnalyticsSearchDateRangeLAST_WEEKSelected'),\n ('ViewCodeInsightsCodeStatsCreationPage'),\n ('DAUsChartSelected'),\n ('goToDefinition'),\n ('MAUsChartSelected'),\n ('SettingsFileDiscard'),\n ('ViewRepositoryStatsContributors'),\n ('InstallBrowserExtensionCTAClicked'),\n ('NewUserEmailAddressAdded'),\n ('HomepageFooterCTASelected'),\n ('ViewedOnboardingTourFilterRepoStep'),\n ('SurveyButtonClicked'),\n ('ViewNewSavedSearchPage'),\n ('allResultsCollapsed'),\n ('SearchHelpDropdownQueryDocsLinkClicked'),\n ('CodeMonitoringLogsPageViewed'),\n ('AdminAnalyticsSearchAggTotalsClicked'),\n ('ViewBatchChangeDetailsPageAfterCreate'),\n ('OnboardingTourRepositoryOptionClicked'),\n ('CodeInsightsCreateCodeStatsInsightClick'),\n ('referenceCodeHost.click'),\n ('InsightsGetStartedTabClick'),\n ('NewOrgCreated'),\n ('BatchChangeClosed'),\n ('CreateNewOrgClicked'),\n ('AddExternalServiceFailed'),\n ('CommitBodyToggled'),\n ('ViewSurvey'),\n ('HideHistoryPanel'),\n ('IDEUninstalled'),\n ('ViewSiteAdminPings'),\n ('InsightRemoval'),\n ('ViewRepositoryBranchesAll'),\n ('SavedSearchCreated'),\n ('UserEmailAddressSetAsPrimary'),\n ('WrappedCode'),\n ('batch_change_list_page:create_batch_change_details:clicked'),\n ('ViewRegistryExtensionManifest'),\n ('SearchReferenceClosed'),\n ('AdminAnalyticsUsersAggTotalsClicked'),\n ('SearchNotebookCopyNotebookButtonClick'),\n ('codecov.decorations.toggleCoverage'),\n ('AdminAnalyticsUsersAggUniquesClicked'),\n ('AlertNeedsRepoConfigCTAClicked'),\n ('BatchChangeDeleted'),\n ('ManageCodeMonitorDeleteSubmitted'),\n ('AdminAnalyticsNotebooksAggTotalsClicked'),\n ('CodeInsightsCodeStatsCreationPageSubmitClick'),\n ('SearchNotebookImportMarkdownNotebookButtonClick'),\n ('NoResultsVideoPlayed'),\n ('AdminAnalyticsNotebooksAggUniquesClicked'),\n ('NoResultsMore'),\n ('SearchNotebookDeleteButtonClicked'),\n ('SurveySubmitted'),\n ('UpdateUserClicked'),\n ('SavedSearchesPanelCreateButtonClicked'),\n ('UserEmailAddressMarkedVerified'),\n ('SearchNotebookImportedFromMarkdown'),\n ('AddOrgMemberFailed'),\n ('SearchResultsAutoPureOther'),\n ('allResultsExpanded'),\n ('SettingsFileDiscardCanceled'),\n ('SearchResultsAutoPureAnd'),\n ('SignUpSucceeded'),\n ('SearchNotebookDeleteModalOpened'),\n ('AdminAnalyticsNotebooksDateRangeLAST_MONTHSelected'),\n ('AdminAnalyticsNotebooksDateRangeLAST_WEEKSelected'),\n ('ViewSiteAdminRegistryExtensions'),\n ('InsightsGetStartedBigTemplateClick'),\n ('ViewSiteAdminCreateUser'),\n ('SearchResultContextsCTAShown'),\n ('AdminAnalyticsNotebooksDateRangeLAST_THREE_MONTHSSelected'),\n ('SearchDidYouMeanClicked'),\n ('SearchNotebookExportNotebook'),\n ('InsightGetStartedTemplateClick'),\n ('UserProfileUpdated'),\n ('AdminAnalyticsSearchMinutesInputEdited'),\n ('UserEmailAddressMarkedUnverified'),\n ('searchExport.export'),\n ('CodeMonitoringExampleMonitorClicked'),\n ('BrowserExtensionPopupClosed'),\n ('ViewSearchNotebooksListOrgNotebooks')\nON CONFLICT DO NOTHING;", + "DownQuery": "DELETE\nFROM event_logs_export_allowlist\nWHERE event_name IN ('codeintel.searchDocumentHighlight',\n 'SearchNotebookBlocksUpdated',\n 'search.latencies.symbol',\n 'hover',\n 'codeintel.lsifDocumentHighlight',\n 'search.latencies.literal',\n 'codeintel.lsifHover',\n 'codeintel.lsifDefinitions',\n 'SearchResultsFetched',\n 'search.latencies.regexp',\n 'codeintel.searchDefinitions',\n 'codeintel.searchHover',\n 'ViewHome',\n 'ViewSearchResults',\n 'search.latencies.repo',\n 'HomepageInvitationsViewEmpty',\n 'RecentSearchesPanelLoaded',\n 'SavedSearchesPanelLoaded',\n 'SearchResultClicked',\n 'INSIGHT_TOTAL_ORGS_WITH_DASHBOARD',\n 'INSIGHT_TOTAL_COUNT_CRITICAL',\n 'INSIGHT_TIME_INTERVALS',\n 'INSIGHT_ORG_VISIBLE_INSIGHTS',\n 'INSIGHT_TOTAL_COUNTS',\n 'INSIGHT_DASHBOARD_TOTAL_COUNT',\n 'INSIGHTS_PER_DASHBORD_STATS',\n 'RepositoriesPanelLoaded',\n 'RecentFilesPanelLoaded',\n 'SearchResultsCacheRetrieved',\n 'BrowserExtensionConnectedToServer',\n 'ViewTree',\n 'FileTreeClick',\n 'codeintel.searchDefinitions.xrepo',\n 'search.latencies.file',\n 'ViewNoResultsPage',\n 'ViewRepository',\n 'search.latencies.structural',\n 'InsightHover',\n 'ExternalAuthSignupFailed',\n 'CodeIntelRefs',\n 'search.latencies.diff',\n 'SurveyReminderViewed',\n 'ExtensionActivation',\n 'InstallBrowserExtensionCTAShown',\n 'ViewSiteAdminOverview',\n 'ViewSettingsUser',\n 'SearchContextDropdownToggled',\n 'definitionHoverOverlay.click',\n 'InstallIDEExtensionCTAShown',\n 'search.latencies.commit',\n 'ViewRepositoryCommit',\n 'ViewOnboardingTour',\n 'ViewCodeIntelIndexes',\n 'ViewInsights',\n 'codeintel.lsifReferences',\n 'NotebookVisibilitySettingsDropdownToggled',\n 'referenceHoverOverlay.click',\n 'ViewSearchNotebooksListMyNotebooks',\n 'ViewBatchChangesListPage',\n 'SearchContextsDropdownViewed',\n 'ViewExecutorsList',\n 'findReferences',\n 'ReferencePanelResultsClicked',\n 'SearchNotebooksListPageViewed',\n 'SearchNotebookPageViewed',\n 'ViewCodeIntelUploads',\n 'ViewCodeIntelConfiguration',\n 'ExternalAuthSignupSucceeded',\n 'ViewSiteAdminConfiguration',\n 'goToDefinition.preloaded',\n 'ViewSiteAdminExternalServices',\n 'CodeCopied',\n 'SearchNotebookRunBlock',\n 'ViewSiteAdminRepos',\n 'git.blame.toggle',\n 'codeintel.searchReferences',\n 'SearchContextSelected',\n 'ViewSiteAdminUsageStatistics',\n 'ViewUserProfile',\n 'SettingsFileSaved',\n 'CodeMonitoringGettingStartedPageViewed',\n 'SignInAttempted',\n 'SearchNotebookAddBlock',\n 'ViewUserSettingsTokens',\n 'ViewCodeIntelIndex',\n 'GoToCodeHostClicked',\n 'RecentSearchesPanelSearchClicked',\n 'RepositoriesPanelRepoFilterClicked',\n 'codeintel.lsifDefinitions.xrepo',\n 'ViewSiteAdminAllUsers',\n 'SignInSucceeded',\n 'CodeMonitoringPageViewed',\n 'ViewCodeIntelRepositoryIndexConfiguration',\n 'ViewCodeIntelConfigurationPolicy',\n 'NotebooksGettingStartedTabViewed',\n 'ViewAddExternalService',\n 'InsightUICustomization',\n 'ViewRepositoryError',\n 'ViewCodeInsightsCreationPage',\n 'SearchNotebookShareModalOpened',\n 'ViewSiteAdminExternalService',\n 'ViewExtensionsOverview',\n 'ManageCodeMonitorPageViewed',\n 'ViewInsightsGetStartedPage',\n 'StandaloneInsightPageViewed',\n 'ViewBatchChangeDetailsPage',\n 'ViewRevisionsPopover',\n 'ViewUserSettingsEmails',\n 'codeintel.searchReferences.xrepo',\n 'SymbolTreeViewClicked',\n 'ViewApiConsole',\n 'UTMCodeHostIntegration',\n 'ViewSettingsSite',\n 'ViewRepoSettingsIndex',\n 'codeintel.lsifImplementations',\n 'IDESearchSubmitted',\n 'ViewUserSettingsProductResearch',\n 'ViewUserSettingsPassword',\n 'ViewSettingsOrg',\n 'ViewSearchNotebooksListExploreNotebooks',\n 'ViewRepoSettings',\n 'SearchDidYouMeanDisplayed',\n 'SiteConfigurationSaved',\n 'ShowHistoryPanel',\n 'ViewSavedSearchListPage',\n 'ViewCodeInsightsSearchBasedCreationPage',\n 'findImplementations',\n 'ViewRepoSettingsMirror',\n 'AdminAnalyticsCodeIntelViewed',\n 'AdminAnalyticsSearchViewed',\n 'InsightAddMoreClick',\n 'ViewSignIn',\n 'ViewOrgSettingsProfile',\n 'InsightDataPointClick',\n 'SignInFailed',\n 'ViewSearchNotebooksListStarredNotebooks',\n 'ViewSiteAdminOrgs',\n 'ViewRepoSettingsPermissions',\n 'BrowserExtensionPopupOpened',\n 'CreateCodeMonitorPageViewed',\n 'FuzzyFinderViewed',\n 'ViewNewAccessToken',\n 'AccessTokenCreated',\n 'RepositoriesPopover',\n 'ViewRepositoriesPopover',\n 'SearchNotebookDeleteBlock',\n 'RootBreadcrumbClicked',\n 'ViewUserEventLogPage',\n 'CodeInsightsCreateSearchBasedInsightClick',\n 'ViewRepositoryCompareOverview',\n 'InsightAddition',\n 'AdminAnalyticsCodeIntelAggUniquesClicked',\n 'StandaloneInsightPageEditClick',\n 'SearchNotebookTitleUpdated',\n 'SearchNotebooksNotebooksTabClick',\n 'CopyFilePath',\n 'ViewOrgMembers',\n 'InsightEdit',\n 'RepositoryComparisonFetched',\n 'SearchNotebookCreated',\n 'AdminAnalyticsNotebooksViewed',\n 'NoResultsPanel',\n 'ViewSiteAdminProductSubscription',\n 'AdminAnalyticsUsersViewed',\n 'ReferencePanelClickedReferences',\n 'CreateCodeMonitorFormSubmitted',\n 'ViewBatchChangeApplyPage',\n 'CloseOnboardingTourClicked',\n 'IDEInstalled',\n 'FileTreeViewClicked',\n 'AdminAnalyticsBatchChangesViewed',\n 'ViewRepositoryBranchesOverview',\n 'WAUsChartSelected',\n 'ViewCodeIntelUpload',\n 'codeintel.lsifReferences.xrepo',\n 'mixPreciseAndSearchBasedReferences.toggle',\n 'ViewSiteAdminSurveyResponses',\n 'ViewRepositoryCommits',\n 'ViewNewOrg',\n 'SearchResultsFetchFailed',\n 'SiteConfigurationActionExecuted',\n 'CodeInsightsSearchBasedCreationPageSubmitClick',\n 'ReferencePanelClickedImplementations',\n 'SearchNotebookMoveBlock',\n 'UserNotificationsLinkClicked',\n 'AdminAnalyticsCodeIntelAggTotalsClicked',\n 'ReferencePanelClickedDefinition',\n 'ViewCodeInsightsCaptureGroupCreationPage',\n 'SearchNotebooksGettingStartedTabClick',\n 'ViewUserSettingsPermissions',\n 'CodeInsightsCreateCaptureGroupInsightClick',\n 'BrowserExtensionPopupRejected',\n 'AdminAnalyticsSearchAggUniquesClicked',\n 'CommitSHACopiedToClipboard',\n 'ExtensionToggled',\n 'vscode.open.file',\n 'SearchNotebookRunAllBlocks',\n 'CodeInsightsDashboardCreationPageSubmitClick',\n 'BatchSpecCreated',\n 'AddExternalServiceSucceeded',\n 'ManageCodeMonitorFormSubmitted',\n 'BatchChangeCreatedOrUpdated',\n 'SearchNotepadEnabled',\n 'ReferencePanelClickedHistory',\n 'SearchSnippetClicked',\n 'ViewSiteAdminUpdates',\n 'CodeInsightsCaptureGroupCreationPageSubmitClick',\n 'SearchSkippedResultsAgainClicked',\n 'ViewRepositoryReleasesTags',\n 'OrgMemberAdded',\n 'RepositoryComparisonSubmitted',\n 'AdminAnalyticsSearchDateRangeLAST_WEEKSelected',\n 'ViewCodeInsightsCodeStatsCreationPage',\n 'DAUsChartSelected',\n 'goToDefinition',\n 'MAUsChartSelected',\n 'SettingsFileDiscard',\n 'ViewRepositoryStatsContributors',\n 'InstallBrowserExtensionCTAClicked',\n 'NewUserEmailAddressAdded',\n 'HomepageFooterCTASelected',\n 'ViewedOnboardingTourFilterRepoStep',\n 'SurveyButtonClicked',\n 'ViewNewSavedSearchPage',\n 'allResultsCollapsed',\n 'SearchHelpDropdownQueryDocsLinkClicked',\n 'CodeMonitoringLogsPageViewed',\n 'AdminAnalyticsSearchAggTotalsClicked',\n 'ViewBatchChangeDetailsPageAfterCreate',\n 'OnboardingTourRepositoryOptionClicked',\n 'CodeInsightsCreateCodeStatsInsightClick',\n 'referenceCodeHost.click',\n 'InsightsGetStartedTabClick',\n 'NewOrgCreated',\n 'BatchChangeClosed',\n 'CreateNewOrgClicked',\n 'AddExternalServiceFailed',\n 'CommitBodyToggled',\n 'ViewSurvey',\n 'HideHistoryPanel',\n 'IDEUninstalled',\n 'ViewSiteAdminPings',\n 'InsightRemoval',\n 'ViewRepositoryBranchesAll',\n 'SavedSearchCreated',\n 'UserEmailAddressSetAsPrimary',\n 'WrappedCode',\n 'batch_change_list_page:create_batch_change_details:clicked',\n 'ViewRegistryExtensionManifest',\n 'SearchReferenceClosed',\n 'AdminAnalyticsUsersAggTotalsClicked',\n 'SearchNotebookCopyNotebookButtonClick',\n 'codecov.decorations.toggleCoverage',\n 'AdminAnalyticsUsersAggUniquesClicked',\n 'AlertNeedsRepoConfigCTAClicked',\n 'BatchChangeDeleted',\n 'ManageCodeMonitorDeleteSubmitted',\n 'AdminAnalyticsNotebooksAggTotalsClicked',\n 'CodeInsightsCodeStatsCreationPageSubmitClick',\n 'SearchNotebookImportMarkdownNotebookButtonClick',\n 'NoResultsVideoPlayed',\n 'AdminAnalyticsNotebooksAggUniquesClicked',\n 'NoResultsMore',\n 'SearchNotebookDeleteButtonClicked',\n 'SurveySubmitted',\n 'UpdateUserClicked',\n 'SavedSearchesPanelCreateButtonClicked',\n 'UserEmailAddressMarkedVerified',\n 'SearchNotebookImportedFromMarkdown',\n 'AddOrgMemberFailed',\n 'SearchResultsAutoPureOther',\n 'allResultsExpanded',\n 'SettingsFileDiscardCanceled',\n 'SearchResultsAutoPureAnd',\n 'SignUpSucceeded',\n 'SearchNotebookDeleteModalOpened',\n 'AdminAnalyticsNotebooksDateRangeLAST_MONTHSelected',\n 'AdminAnalyticsNotebooksDateRangeLAST_WEEKSelected',\n 'ViewSiteAdminRegistryExtensions',\n 'InsightsGetStartedBigTemplateClick',\n 'ViewSiteAdminCreateUser',\n 'SearchResultContextsCTAShown',\n 'AdminAnalyticsNotebooksDateRangeLAST_THREE_MONTHSSelected',\n 'SearchDidYouMeanClicked',\n 'SearchNotebookExportNotebook',\n 'InsightGetStartedTemplateClick',\n 'UserProfileUpdated',\n 'AdminAnalyticsSearchMinutesInputEdited',\n 'UserEmailAddressMarkedUnverified',\n 'searchExport.export',\n 'CodeMonitoringExampleMonitorClicked',\n 'BrowserExtensionPopupClosed',\n 'ViewSearchNotebooksListOrgNotebooks');", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1658837440, + 1659380538, + 1659434035 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1660132915, + "Name": "lsif_uploads_uncompressed_size", + "UpQuery": "ALTER TABLE lsif_uploads\nADD COLUMN IF NOT EXISTS uncompressed_size bigint;\n\nDROP VIEW IF EXISTS lsif_uploads_with_repository_name;\n\nCREATE VIEW lsif_uploads_with_repository_name AS\nSELECT u.id,\n u.commit,\n u.root,\n u.queued_at,\n u.uploaded_at,\n u.state,\n u.failure_message,\n u.started_at,\n u.finished_at,\n u.repository_id,\n u.indexer,\n u.indexer_version,\n u.num_parts,\n u.uploaded_parts,\n u.process_after,\n u.num_resets,\n u.upload_size,\n u.num_failures,\n u.associated_index_id,\n u.expired,\n u.last_retention_scan_at,\n r.name AS repository_name,\n u.uncompressed_size\nFROM lsif_uploads u\nJOIN repo r ON r.id = u.repository_id\nWHERE r.deleted_at IS NULL;", + "DownQuery": "DROP VIEW IF EXISTS lsif_uploads_with_repository_name;\n\nCREATE VIEW lsif_uploads_with_repository_name AS\nSELECT u.id,\n u.commit,\n u.root,\n u.queued_at,\n u.uploaded_at,\n u.state,\n u.failure_message,\n u.started_at,\n u.finished_at,\n u.repository_id,\n u.indexer,\n u.indexer_version,\n u.num_parts,\n u.uploaded_parts,\n u.process_after,\n u.num_resets,\n u.upload_size,\n u.num_failures,\n u.associated_index_id,\n u.expired,\n u.last_retention_scan_at,\n r.name AS repository_name\nFROM lsif_uploads u\nJOIN repo r ON r.id = u.repository_id\nWHERE r.deleted_at IS NULL;\n\nALTER TABLE lsif_uploads\nDROP COLUMN IF EXISTS uncompressed_size;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1659721548 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1660312877, + "Name": "add aggregated user statistics table", + "UpQuery": "-- Perform migration here.\n\nCREATE TABLE IF NOT EXISTS aggregated_user_statistics (\n user_id BIGINT NOT NULL PRIMARY KEY,\n created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,\n updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,\n user_last_active_at TIMESTAMP WITH TIME ZONE DEFAULT NULL,\n user_events_count BIGINT DEFAULT NULL,\n CONSTRAINT aggregated_user_statistics_user_id_fkey FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE\n);", + "DownQuery": "-- Undo the changes made in the up migration\n\nDROP TABLE IF EXISTS aggregated_user_statistics;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1659459805, + 1660132915 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1658874734, + "Name": "normalized_changeset_specs", + "UpQuery": "ALTER TABLE changeset_specs\n ADD COLUMN IF NOT EXISTS diff bytea,\n ADD COLUMN IF NOT EXISTS base_rev TEXT,\n ADD COLUMN IF NOT EXISTS base_ref TEXT,\n ADD COLUMN IF NOT EXISTS body TEXT,\n ADD COLUMN IF NOT EXISTS published TEXT,\n ADD COLUMN IF NOT EXISTS commit_message TEXT,\n ADD COLUMN IF NOT EXISTS commit_author_name TEXT,\n ADD COLUMN IF NOT EXISTS commit_author_email TEXT,\n ADD COLUMN IF NOT EXISTS type TEXT;\n\nUPDATE\n changeset_specs\nSET\n diff = convert_to(spec-\u003e'commits'-\u003e0-\u003e\u003e'diff', 'UTF8'),\n base_rev = spec-\u003e\u003e'baseRev',\n base_ref = spec-\u003e\u003e'baseRef',\n body = spec-\u003e\u003e'body',\n published = spec-\u003e\u003e'published',\n commit_message = spec-\u003e'commits'-\u003e0-\u003e\u003e'message',\n commit_author_name = spec-\u003e'commits'-\u003e0-\u003e\u003e'authorName',\n commit_author_email = spec-\u003e'commits'-\u003e0-\u003e\u003e'authorEmail',\n type = CASE WHEN spec-\u003e\u003e'externalID' IS NOT NULL THEN 'existing' ELSE 'branch' END;", + "DownQuery": "ALTER TABLE changeset_specs\n DROP COLUMN IF EXISTS diff,\n DROP COLUMN IF EXISTS base_rev,\n DROP COLUMN IF EXISTS base_ref,\n DROP COLUMN IF EXISTS body,\n DROP COLUMN IF EXISTS published,\n DROP COLUMN IF EXISTS commit_message,\n DROP COLUMN IF EXISTS commit_author_name,\n DROP COLUMN IF EXISTS commit_author_email,\n DROP COLUMN IF EXISTS type;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1658748822 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1660710812, + "Name": "update_reconciler_changeset_view", + "UpQuery": "DROP VIEW IF EXISTS reconciler_changesets;\n\nCREATE VIEW reconciler_changesets AS\n SELECT c.id,\n c.batch_change_ids,\n c.repo_id,\n c.queued_at,\n c.created_at,\n c.updated_at,\n c.metadata,\n c.external_id,\n c.external_service_type,\n c.external_deleted_at,\n c.external_branch,\n c.external_updated_at,\n c.external_state,\n c.external_review_state,\n c.external_check_state,\n c.diff_stat_added,\n c.diff_stat_deleted,\n c.sync_state,\n c.current_spec_id,\n c.previous_spec_id,\n c.publication_state,\n c.owned_by_batch_change_id,\n c.reconciler_state,\n c.computed_state,\n c.failure_message,\n c.started_at,\n c.finished_at,\n c.process_after,\n c.num_resets,\n c.closing,\n c.num_failures,\n c.log_contents,\n c.execution_logs,\n c.syncer_error,\n c.external_title,\n c.worker_hostname,\n c.ui_publication_state,\n c.last_heartbeat_at,\n c.external_fork_namespace,\n c.detached_at\n FROM (changesets c\n JOIN repo r ON ((r.id = c.repo_id)))\n WHERE ((r.deleted_at IS NULL) AND (EXISTS ( SELECT 1\n FROM ((batch_changes\n LEFT JOIN users namespace_user ON ((batch_changes.namespace_user_id = namespace_user.id)))\n LEFT JOIN orgs namespace_org ON ((batch_changes.namespace_org_id = namespace_org.id)))\n WHERE ((c.batch_change_ids ? (batch_changes.id)::text) AND (namespace_user.deleted_at IS NULL) AND (namespace_org.deleted_at IS NULL)))));", + "DownQuery": "DROP VIEW IF EXISTS reconciler_changesets;\n\nCREATE VIEW reconciler_changesets AS\n SELECT c.id,\n c.batch_change_ids,\n c.repo_id,\n c.queued_at,\n c.created_at,\n c.updated_at,\n c.metadata,\n c.external_id,\n c.external_service_type,\n c.external_deleted_at,\n c.external_branch,\n c.external_updated_at,\n c.external_state,\n c.external_review_state,\n c.external_check_state,\n c.diff_stat_added,\n c.diff_stat_changed,\n c.diff_stat_deleted,\n c.sync_state,\n c.current_spec_id,\n c.previous_spec_id,\n c.publication_state,\n c.owned_by_batch_change_id,\n c.reconciler_state,\n c.computed_state,\n c.failure_message,\n c.started_at,\n c.finished_at,\n c.process_after,\n c.num_resets,\n c.closing,\n c.num_failures,\n c.log_contents,\n c.execution_logs,\n c.syncer_error,\n c.external_title,\n c.worker_hostname,\n c.ui_publication_state,\n c.last_heartbeat_at,\n c.external_fork_namespace,\n c.detached_at\n FROM (changesets c\n JOIN repo r ON ((r.id = c.repo_id)))\n WHERE ((r.deleted_at IS NULL) AND (EXISTS ( SELECT 1\n FROM ((batch_changes\n LEFT JOIN users namespace_user ON ((batch_changes.namespace_user_id = namespace_user.id)))\n LEFT JOIN orgs namespace_org ON ((batch_changes.namespace_org_id = namespace_org.id)))\n WHERE ((c.batch_change_ids ? (batch_changes.id)::text) AND (namespace_user.deleted_at IS NULL) AND (namespace_org.deleted_at IS NULL)))));", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1658874734, + 1660312877 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1660710916, + "Name": "remove_diff_stat_changed_changeset_specs", + "UpQuery": "-- We update the `diff_stat_added` and `diff_stat_deleted` to reflect the way git calculate diffs.\n-- When calculating diffs, we only care about the added \u0026 deleted lines\ndo $$\nbegin\n /* if column `diff_stat_changed` exists on `changeset_specs` table */\n IF EXISTS(\n SELECT 1\n FROM information_schema.columns\n WHERE table_schema = 'public'\n AND table_name = 'changeset_specs'\n AND column_name = 'diff_stat_changed'\n ) THEN\n /* update the `diff_stat_added` and `diff_stat_deleted` */\n UPDATE changeset_specs\n SET\n diff_stat_added = diff_stat_added + diff_stat_changed,\n diff_stat_deleted = diff_stat_deleted + diff_stat_changed\n WHERE\n diff_stat_changed != 0;\n END IF;\nend$$;\n\nALTER TABLE IF EXISTS changeset_specs DROP COLUMN IF EXISTS diff_stat_changed;", + "DownQuery": "ALTER TABLE IF EXISTS changeset_specs ADD COLUMN IF NOT EXISTS diff_stat_changed integer;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1660710812 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1660711451, + "Name": "remove_diff_stat_changed_changesets", + "UpQuery": "-- We update the `diff_stat_added` and `diff_stat_deleted` to reflect the way git calculate diffs.\n-- When calculating diffs, we only care about the added \u0026 deleted lines\ndo $$\nbegin\n /* if column `diff_stat_changed` exists on `changesets` table */\n IF EXISTS(\n SELECT 1\n FROM information_schema.columns\n WHERE table_schema = 'public'\n AND table_name = 'changesets'\n AND column_name = 'diff_stat_changed'\n ) THEN\n /* update the `diff_stat_added` and `diff_stat_deleted` */\n UPDATE changesets\n SET\n diff_stat_added = diff_stat_added + diff_stat_changed,\n diff_stat_deleted = diff_stat_deleted + diff_stat_changed\n WHERE\n diff_stat_changed != 0;\n END IF;\nend$$;\n\nALTER TABLE IF EXISTS changesets DROP COLUMN IF EXISTS diff_stat_changed;", + "DownQuery": "ALTER TABLE IF EXISTS changesets ADD COLUMN IF NOT EXISTS diff_stat_changed integer;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1660710916 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1660742069, + "Name": "non_null_changeset_spec_type", + "UpQuery": "-- Ensure no unmigrated records exist.\nUPDATE\n changeset_specs\nSET\n diff = convert_to(spec-\u003e'commits'-\u003e0-\u003e\u003e'diff', 'UTF8'),\n base_rev = spec-\u003e\u003e'baseRev',\n base_ref = spec-\u003e\u003e'baseRef',\n body = spec-\u003e\u003e'body',\n published = spec-\u003e\u003e'published',\n commit_message = spec-\u003e'commits'-\u003e0-\u003e\u003e'message',\n commit_author_name = spec-\u003e'commits'-\u003e0-\u003e\u003e'authorName',\n commit_author_email = spec-\u003e'commits'-\u003e0-\u003e\u003e'authorEmail',\n type = CASE WHEN spec-\u003e\u003e'externalID' IS NOT NULL THEN 'existing' ELSE 'branch' END;\n\nALTER TABLE changeset_specs ALTER COLUMN type SET NOT NULL;\nALTER TABLE changeset_specs ALTER COLUMN spec DROP NOT NULL;\nUPDATE changeset_specs SET spec = NULL;", + "DownQuery": "ALTER TABLE changeset_specs ALTER COLUMN type DROP NOT NULL;\nALTER TABLE changeset_specs ADD COLUMN IF NOT EXISTS spec jsonb;\n\nUPDATE\n changeset_specs\nSET\n spec = jsonb_build_object(\n 'baseRev', base_rev,\n 'baseRef', base_ref,\n 'externalID', external_id,\n 'headRef', head_ref,\n 'title', title,\n 'body', body,\n 'published', published,\n 'commits', json_build_array(\n jsonb_build_object(\n 'diff', encode(diff, 'escape'),\n 'message', commit_message,\n 'authorName', commit_author_name,\n 'authorEmail', commit_author_email\n )\n )\n );\n\nALTER TABLE changeset_specs ALTER COLUMN spec SET NOT NULL;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1658874734, + 1660312877 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1661441160, + "Name": "batch spec remote mounts", + "UpQuery": "CREATE TABLE IF NOT EXISTS batch_spec_workspace_files\n(\n id serial PRIMARY KEY,\n rand_id text NOT NULL,\n batch_spec_id bigint NOT NULL,\n filename text NOT NULL,\n path text NOT NULL,\n size bigint NOT NULL,\n content bytea NOT NULL,\n modified_at timestamp with time zone NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL\n);\n\nALTER TABLE batch_spec_workspace_files\n DROP CONSTRAINT IF EXISTS batch_spec_workspace_files_batch_spec_id_fkey;\n\nALTER TABLE ONLY batch_spec_workspace_files\n ADD CONSTRAINT batch_spec_workspace_files_batch_spec_id_fkey FOREIGN KEY (batch_spec_id) REFERENCES batch_specs (id) ON DELETE CASCADE;\n\nCREATE INDEX IF NOT EXISTS batch_spec_workspace_files_rand_id ON batch_spec_workspace_files USING btree (rand_id);\n\nCREATE UNIQUE INDEX IF NOT EXISTS batch_spec_workspace_files_batch_spec_id_filename_path ON batch_spec_workspace_files (batch_spec_id, filename, path);", + "DownQuery": "DROP TABLE IF EXISTS batch_spec_workspace_files;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1659085788, + 1660742069 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1661502186, + "Name": "fix_repo_stats_initial_state", + "UpQuery": "-- In the previous migration (1659085788_add_repo_stats_table) the triggers\n-- adding data to the stats table and the initial state of the stats table were\n-- setup in the wrong order:\n--\n-- 1. Create repo_statistics/gitserver_repos_statistics tables\n-- 2. Insert initial state into tables\n-- 3. Setup database triggers that insert/update these tables\n--\n-- That's wrong. Instead we should've :\n--\n-- 1. Create repo_statistics/gitserver_repos_statistics tables\n-- 2. Setup database triggers that insert/update these tables\n-- 3. Update tables to have correct initial state\n--\n--\n-- What this migration does is correct the initial wrong states by\n\n-- 1. Lock repo and gitserver_repos tables, so that no inserts/updates/deletes happen while we compute new total state.\n-- EXCLUSIVE is the mode that says \"no one else can write, only read\".\n\nLOCK repo IN EXCLUSIVE MODE; -- first lock repo, since we have triggers that write `repo` and cause updates on `gitserver_repos` but not the other way around\nLOCK gitserver_repos IN EXCLUSIVE MODE; -- then lock `gitserver_repos`\n\n--- 2. Delete old state in `repo_statistics` (we can't update the state, since this is an append-only table).\nDELETE FROM repo_statistics;\n\n--- 3. Insert new total counts in `repo_statistics`\nINSERT INTO repo_statistics (total, soft_deleted, not_cloned, cloning, cloned, failed_fetch)\nSELECT\n COUNT(*) AS total,\n (SELECT COUNT(*) FROM repo WHERE deleted_at is NOT NULL AND blocked IS NULL) AS soft_deleted,\n COUNT(*) FILTER(WHERE gitserver_repos.clone_status = 'not_cloned') AS not_cloned,\n COUNT(*) FILTER(WHERE gitserver_repos.clone_status = 'cloning') AS cloning,\n COUNT(*) FILTER(WHERE gitserver_repos.clone_status = 'cloned') AS cloned,\n COUNT(*) FILTER(WHERE gitserver_repos.last_error IS NOT NULL) AS failed_fetch\nFROM repo\nJOIN gitserver_repos ON gitserver_repos.repo_id = repo.id\nWHERE\n repo.deleted_at is NULL AND repo.blocked IS NULL;\n\n--- 4. Insert/update `gitserver_repos_statistics` by updating/insert the recalculated counts per shard.\nINSERT INTO\n gitserver_repos_statistics (shard_id, total, not_cloned, cloning, cloned, failed_fetch)\nSELECT\n shard_id,\n COUNT(*) AS total,\n COUNT(*) FILTER(WHERE clone_status = 'not_cloned') AS not_cloned,\n COUNT(*) FILTER(WHERE clone_status = 'cloning') AS cloning,\n COUNT(*) FILTER(WHERE clone_status = 'cloned') AS cloned,\n COUNT(*) FILTER(WHERE last_error IS NOT NULL) AS failed_fetch\nFROM\n gitserver_repos\nGROUP BY shard_id\nON CONFLICT(shard_id)\nDO UPDATE\nSET\n total = excluded.total,\n not_cloned = excluded.not_cloned,\n cloning = excluded.cloning,\n cloned = excluded.cloned,\n failed_fetch = excluded.failed_fetch\n;", + "DownQuery": "-- No schema changes made in up migrations, only data migrations that can't be\n-- undone.", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1659085788, + 1660742069 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1661507724, + "Name": "update_repo_stats_trigger_to_avoid_all_zeros", + "UpQuery": "-- repo UPDATE trigger\nCREATE OR REPLACE FUNCTION recalc_repo_statistics_on_repo_update() RETURNS trigger\n LANGUAGE plpgsql\n AS $$ BEGIN\n -- Insert diff of changes\n WITH diff(total, soft_deleted, not_cloned, cloning, cloned, failed_fetch) AS (\n VALUES (\n (SELECT COUNT(*) FROM newtab WHERE deleted_at IS NULL AND blocked IS NULL) - (SELECT COUNT(*) FROM oldtab WHERE deleted_at IS NULL AND blocked IS NULL),\n (SELECT COUNT(*) FROM newtab WHERE deleted_at IS NOT NULL AND blocked IS NULL) - (SELECT COUNT(*) FROM oldtab WHERE deleted_at IS NOT NULL AND blocked IS NULL),\n (\n (SELECT COUNT(*) FROM newtab JOIN gitserver_repos gr ON gr.repo_id = newtab.id WHERE newtab.deleted_at is NULL AND newtab.blocked IS NULL AND gr.clone_status = 'not_cloned')\n -\n (SELECT COUNT(*) FROM oldtab JOIN gitserver_repos gr ON gr.repo_id = oldtab.id WHERE oldtab.deleted_at is NULL AND oldtab.blocked IS NULL AND gr.clone_status = 'not_cloned')\n ),\n (\n (SELECT COUNT(*) FROM newtab JOIN gitserver_repos gr ON gr.repo_id = newtab.id WHERE newtab.deleted_at is NULL AND newtab.blocked IS NULL AND gr.clone_status = 'cloning')\n -\n (SELECT COUNT(*) FROM oldtab JOIN gitserver_repos gr ON gr.repo_id = oldtab.id WHERE oldtab.deleted_at is NULL AND oldtab.blocked IS NULL AND gr.clone_status = 'cloning')\n ),\n (\n (SELECT COUNT(*) FROM newtab JOIN gitserver_repos gr ON gr.repo_id = newtab.id WHERE newtab.deleted_at is NULL AND newtab.blocked IS NULL AND gr.clone_status = 'cloned')\n -\n (SELECT COUNT(*) FROM oldtab JOIN gitserver_repos gr ON gr.repo_id = oldtab.id WHERE oldtab.deleted_at is NULL AND oldtab.blocked IS NULL AND gr.clone_status = 'cloned')\n ),\n (\n (SELECT COUNT(*) FROM newtab JOIN gitserver_repos gr ON gr.repo_id = newtab.id WHERE newtab.deleted_at is NULL AND newtab.blocked IS NULL AND gr.last_error IS NOT NULL)\n -\n (SELECT COUNT(*) FROM oldtab JOIN gitserver_repos gr ON gr.repo_id = oldtab.id WHERE oldtab.deleted_at is NULL AND oldtab.blocked IS NULL AND gr.last_error IS NOT NULL)\n )\n )\n )\n INSERT INTO\n repo_statistics (total, soft_deleted, not_cloned, cloning, cloned, failed_fetch)\n SELECT total, soft_deleted, not_cloned, cloning, cloned, failed_fetch\n FROM diff\n WHERE\n total != 0\n OR soft_deleted != 0\n OR not_cloned != 0\n OR cloning != 0\n OR cloned != 0\n OR failed_fetch != 0\n ;\n RETURN NULL;\n END\n$$;\n\nCREATE OR REPLACE FUNCTION recalc_gitserver_repos_statistics_on_update() RETURNS trigger\n LANGUAGE plpgsql\n AS $$ BEGIN\n --------------------\n -- THIS IS UNCHANGED\n --------------------\n INSERT INTO gitserver_repos_statistics AS grs (shard_id, total, not_cloned, cloning, cloned, failed_fetch)\n SELECT\n newtab.shard_id AS shard_id,\n COUNT(*) AS total,\n COUNT(*) FILTER(WHERE clone_status = 'not_cloned') AS not_cloned,\n COUNT(*) FILTER(WHERE clone_status = 'cloning') AS cloning,\n COUNT(*) FILTER(WHERE clone_status = 'cloned') AS cloned,\n COUNT(*) FILTER(WHERE last_error IS NOT NULL) AS failed_fetch\n FROM\n newtab\n GROUP BY newtab.shard_id\n ON CONFLICT(shard_id) DO\n UPDATE\n SET\n total = grs.total + (excluded.total - (SELECT COUNT(*) FROM oldtab ot WHERE ot.shard_id = excluded.shard_id)),\n not_cloned = grs.not_cloned + (excluded.not_cloned - (SELECT COUNT(*) FILTER(WHERE ot.clone_status = 'not_cloned') FROM oldtab ot WHERE ot.shard_id = excluded.shard_id)),\n cloning = grs.cloning + (excluded.cloning - (SELECT COUNT(*) FILTER(WHERE ot.clone_status = 'cloning') FROM oldtab ot WHERE ot.shard_id = excluded.shard_id)),\n cloned = grs.cloned + (excluded.cloned - (SELECT COUNT(*) FILTER(WHERE ot.clone_status = 'cloned') FROM oldtab ot WHERE ot.shard_id = excluded.shard_id)),\n failed_fetch = grs.failed_fetch + (excluded.failed_fetch - (SELECT COUNT(*) FILTER(WHERE ot.last_error IS NOT NULL) FROM oldtab ot WHERE ot.shard_id = excluded.shard_id))\n ;\n\n --------------------\n -- THIS IS UNCHANGED\n --------------------\n WITH moved AS (\n SELECT\n oldtab.shard_id AS shard_id,\n COUNT(*) AS total,\n COUNT(*) FILTER(WHERE oldtab.clone_status = 'not_cloned') AS not_cloned,\n COUNT(*) FILTER(WHERE oldtab.clone_status = 'cloning') AS cloning,\n COUNT(*) FILTER(WHERE oldtab.clone_status = 'cloned') AS cloned,\n COUNT(*) FILTER(WHERE oldtab.last_error IS NOT NULL) AS failed_fetch\n FROM\n oldtab\n JOIN newtab ON newtab.repo_id = oldtab.repo_id\n WHERE\n oldtab.shard_id != newtab.shard_id\n GROUP BY oldtab.shard_id\n )\n UPDATE gitserver_repos_statistics grs\n SET\n total = grs.total - moved.total,\n not_cloned = grs.not_cloned - moved.not_cloned,\n cloning = grs.cloning - moved.cloning,\n cloned = grs.cloned - moved.cloned,\n failed_fetch = grs.failed_fetch - moved.failed_fetch\n FROM moved\n WHERE moved.shard_id = grs.shard_id;\n\n -------------------------------------------------\n -- IMPORTANT: THIS IS CHANGED\n -------------------------------------------------\n WITH diff(not_cloned, cloning, cloned, failed_fetch) AS (\n VALUES (\n (\n (SELECT COUNT(*) FROM newtab JOIN repo r ON newtab.repo_id = r.id WHERE r.deleted_at is NULL AND r.blocked IS NULL AND newtab.clone_status = 'not_cloned')\n -\n (SELECT COUNT(*) FROM oldtab JOIN repo r ON oldtab.repo_id = r.id WHERE r.deleted_at is NULL AND r.blocked IS NULL AND oldtab.clone_status = 'not_cloned')\n ),\n (\n (SELECT COUNT(*) FROM newtab JOIN repo r ON newtab.repo_id = r.id WHERE r.deleted_at is NULL AND r.blocked IS NULL AND newtab.clone_status = 'cloning')\n -\n (SELECT COUNT(*) FROM oldtab JOIN repo r ON oldtab.repo_id = r.id WHERE r.deleted_at is NULL AND r.blocked IS NULL AND oldtab.clone_status = 'cloning')\n ),\n (\n (SELECT COUNT(*) FROM newtab JOIN repo r ON newtab.repo_id = r.id WHERE r.deleted_at is NULL AND r.blocked IS NULL AND newtab.clone_status = 'cloned')\n -\n (SELECT COUNT(*) FROM oldtab JOIN repo r ON oldtab.repo_id = r.id WHERE r.deleted_at is NULL AND r.blocked IS NULL AND oldtab.clone_status = 'cloned')\n ),\n (\n (SELECT COUNT(*) FROM newtab JOIN repo r ON newtab.repo_id = r.id WHERE r.deleted_at is NULL AND r.blocked IS NULL AND newtab.last_error IS NOT NULL)\n -\n (SELECT COUNT(*) FROM oldtab JOIN repo r ON oldtab.repo_id = r.id WHERE r.deleted_at is NULL AND r.blocked IS NULL AND oldtab.last_error IS NOT NULL)\n )\n )\n )\n INSERT INTO repo_statistics (not_cloned, cloning, cloned, failed_fetch)\n SELECT not_cloned, cloning, cloned, failed_fetch\n FROM diff\n WHERE\n not_cloned != 0\n OR cloning != 0\n OR cloned != 0\n OR failed_fetch != 0\n ;\n\n RETURN NULL;\n END\n$$;", + "DownQuery": "-- Recreate old version of function\nCREATE OR REPLACE FUNCTION recalc_repo_statistics_on_repo_update() RETURNS trigger\n LANGUAGE plpgsql\n AS $$ BEGIN\n -- Insert diff of changes\n INSERT INTO\n repo_statistics (total, soft_deleted, not_cloned, cloning, cloned, failed_fetch)\n VALUES (\n (SELECT COUNT(*) FROM newtab WHERE deleted_at IS NULL AND blocked IS NULL) - (SELECT COUNT(*) FROM oldtab WHERE deleted_at IS NULL AND blocked IS NULL),\n (SELECT COUNT(*) FROM newtab WHERE deleted_at IS NOT NULL AND blocked IS NULL) - (SELECT COUNT(*) FROM oldtab WHERE deleted_at IS NOT NULL AND blocked IS NULL),\n (\n (SELECT COUNT(*) FROM newtab JOIN gitserver_repos gr ON gr.repo_id = newtab.id WHERE newtab.deleted_at is NULL AND newtab.blocked IS NULL AND gr.clone_status = 'not_cloned')\n -\n (SELECT COUNT(*) FROM oldtab JOIN gitserver_repos gr ON gr.repo_id = oldtab.id WHERE oldtab.deleted_at is NULL AND oldtab.blocked IS NULL AND gr.clone_status = 'not_cloned')\n ),\n (\n (SELECT COUNT(*) FROM newtab JOIN gitserver_repos gr ON gr.repo_id = newtab.id WHERE newtab.deleted_at is NULL AND newtab.blocked IS NULL AND gr.clone_status = 'cloning')\n -\n (SELECT COUNT(*) FROM oldtab JOIN gitserver_repos gr ON gr.repo_id = oldtab.id WHERE oldtab.deleted_at is NULL AND oldtab.blocked IS NULL AND gr.clone_status = 'cloning')\n ),\n (\n (SELECT COUNT(*) FROM newtab JOIN gitserver_repos gr ON gr.repo_id = newtab.id WHERE newtab.deleted_at is NULL AND newtab.blocked IS NULL AND gr.clone_status = 'cloned')\n -\n (SELECT COUNT(*) FROM oldtab JOIN gitserver_repos gr ON gr.repo_id = oldtab.id WHERE oldtab.deleted_at is NULL AND oldtab.blocked IS NULL AND gr.clone_status = 'cloned')\n ),\n (\n (SELECT COUNT(*) FROM newtab JOIN gitserver_repos gr ON gr.repo_id = newtab.id WHERE newtab.deleted_at is NULL AND newtab.blocked IS NULL AND gr.last_error IS NOT NULL)\n -\n (SELECT COUNT(*) FROM oldtab JOIN gitserver_repos gr ON gr.repo_id = oldtab.id WHERE oldtab.deleted_at is NULL AND oldtab.blocked IS NULL AND gr.last_error IS NOT NULL)\n )\n )\n ;\n RETURN NULL;\n END\n$$;\n\n-- Recreate old version of function\nCREATE OR REPLACE FUNCTION recalc_gitserver_repos_statistics_on_update() RETURNS trigger\n LANGUAGE plpgsql\n AS $$ BEGIN\n INSERT INTO gitserver_repos_statistics AS grs (shard_id, total, not_cloned, cloning, cloned, failed_fetch)\n SELECT\n newtab.shard_id AS shard_id,\n COUNT(*) AS total,\n COUNT(*) FILTER(WHERE clone_status = 'not_cloned') AS not_cloned,\n COUNT(*) FILTER(WHERE clone_status = 'cloning') AS cloning,\n COUNT(*) FILTER(WHERE clone_status = 'cloned') AS cloned,\n COUNT(*) FILTER(WHERE last_error IS NOT NULL) AS failed_fetch\n FROM\n newtab\n GROUP BY newtab.shard_id\n ON CONFLICT(shard_id) DO\n UPDATE\n SET\n total = grs.total + (excluded.total - (SELECT COUNT(*) FROM oldtab ot WHERE ot.shard_id = excluded.shard_id)),\n not_cloned = grs.not_cloned + (excluded.not_cloned - (SELECT COUNT(*) FILTER(WHERE ot.clone_status = 'not_cloned') FROM oldtab ot WHERE ot.shard_id = excluded.shard_id)),\n cloning = grs.cloning + (excluded.cloning - (SELECT COUNT(*) FILTER(WHERE ot.clone_status = 'cloning') FROM oldtab ot WHERE ot.shard_id = excluded.shard_id)),\n cloned = grs.cloned + (excluded.cloned - (SELECT COUNT(*) FILTER(WHERE ot.clone_status = 'cloned') FROM oldtab ot WHERE ot.shard_id = excluded.shard_id)),\n failed_fetch = grs.failed_fetch + (excluded.failed_fetch - (SELECT COUNT(*) FILTER(WHERE ot.last_error IS NOT NULL) FROM oldtab ot WHERE ot.shard_id = excluded.shard_id))\n ;\n\n WITH moved AS (\n SELECT\n oldtab.shard_id AS shard_id,\n COUNT(*) AS total,\n COUNT(*) FILTER(WHERE oldtab.clone_status = 'not_cloned') AS not_cloned,\n COUNT(*) FILTER(WHERE oldtab.clone_status = 'cloning') AS cloning,\n COUNT(*) FILTER(WHERE oldtab.clone_status = 'cloned') AS cloned,\n COUNT(*) FILTER(WHERE oldtab.last_error IS NOT NULL) AS failed_fetch\n FROM\n oldtab\n JOIN newtab ON newtab.repo_id = oldtab.repo_id\n WHERE\n oldtab.shard_id != newtab.shard_id\n GROUP BY oldtab.shard_id\n )\n UPDATE gitserver_repos_statistics grs\n SET\n total = grs.total - moved.total,\n not_cloned = grs.not_cloned - moved.not_cloned,\n cloning = grs.cloning - moved.cloning,\n cloned = grs.cloned - moved.cloned,\n failed_fetch = grs.failed_fetch - moved.failed_fetch\n FROM moved\n WHERE moved.shard_id = grs.shard_id;\n\n INSERT INTO repo_statistics (not_cloned, cloning, cloned, failed_fetch)\n VALUES (\n (\n (SELECT COUNT(*) FROM newtab JOIN repo r ON newtab.repo_id = r.id WHERE r.deleted_at is NULL AND r.blocked IS NULL AND newtab.clone_status = 'not_cloned')\n -\n (SELECT COUNT(*) FROM oldtab JOIN repo r ON oldtab.repo_id = r.id WHERE r.deleted_at is NULL AND r.blocked IS NULL AND oldtab.clone_status = 'not_cloned')\n ),\n (\n (SELECT COUNT(*) FROM newtab JOIN repo r ON newtab.repo_id = r.id WHERE r.deleted_at is NULL AND r.blocked IS NULL AND newtab.clone_status = 'cloning')\n -\n (SELECT COUNT(*) FROM oldtab JOIN repo r ON oldtab.repo_id = r.id WHERE r.deleted_at is NULL AND r.blocked IS NULL AND oldtab.clone_status = 'cloning')\n ),\n (\n (SELECT COUNT(*) FROM newtab JOIN repo r ON newtab.repo_id = r.id WHERE r.deleted_at is NULL AND r.blocked IS NULL AND newtab.clone_status = 'cloned')\n -\n (SELECT COUNT(*) FROM oldtab JOIN repo r ON oldtab.repo_id = r.id WHERE r.deleted_at is NULL AND r.blocked IS NULL AND oldtab.clone_status = 'cloned')\n ),\n (\n (SELECT COUNT(*) FROM newtab JOIN repo r ON newtab.repo_id = r.id WHERE r.deleted_at is NULL AND r.blocked IS NULL AND newtab.last_error IS NOT NULL)\n -\n (SELECT COUNT(*) FROM oldtab JOIN repo r ON oldtab.repo_id = r.id WHERE r.deleted_at is NULL AND r.blocked IS NULL AND oldtab.last_error IS NOT NULL)\n )\n );\n\n RETURN NULL;\n END\n$$;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1659085788, + 1660742069 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1662467128, + "Name": "Add on-demand autoindexing queue", + "UpQuery": "CREATE TABLE IF NOT EXISTS codeintel_autoindex_queue (\n id SERIAL PRIMARY KEY,\n repository_id int NOT NULL,\n rev text NOT NULL,\n queued_at timestamptz NOT NULL DEFAULT NOW(),\n processed_at timestamptz\n);\n\nCREATE UNIQUE INDEX IF NOT EXISTS codeintel_autoindex_queue_repository_id_commit ON codeintel_autoindex_queue(repository_id, rev);", + "DownQuery": "DROP TABLE IF EXISTS codeintel_autoindex_queue;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1661502186, + 1661507724 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1663569995, + "Name": "update_username_valid_chars_contraint", + "UpQuery": "-- Allow underscores in usernames.\n\nALTER TABLE users\n DROP CONSTRAINT users_username_valid_chars,\n ADD CONSTRAINT users_username_valid_chars CHECK (username ~ '^\\w(?:\\w|[-.](?=\\w))*-?$'::citext);", + "DownQuery": "-- Undo allow underscores in usernames.\n\nALTER TABLE users\n DROP CONSTRAINT users_username_valid_chars,\n ADD CONSTRAINT users_username_valid_chars CHECK (username ~ '^[a-zA-Z0-9](?:[a-zA-Z0-9]|[-.](?=[a-zA-Z0-9]))*-?$'::citext);", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1662467128 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1664300936, + "Name": "Move lsif_upload reference count to different table", + "UpQuery": "CREATE TABLE IF NOT EXISTS lsif_uploads_reference_counts (\n upload_id INTEGER UNIQUE NOT NULL,\n reference_count INTEGER NOT NULL\n);\n\nCOMMENT ON TABLE lsif_uploads_reference_counts IS 'A less hot-path reference count for upload records.';\n\nCOMMENT ON COLUMN lsif_uploads_reference_counts.upload_id IS 'The identifier of the referenced upload.';\n\nCOMMENT ON COLUMN lsif_uploads_reference_counts.reference_count IS 'The number of references to the associated upload from other records (via lsif_references).';\n\nALTER TABLE\n lsif_uploads_reference_counts DROP CONSTRAINT IF EXISTS lsif_data_docs_search_private_repo_name_id_fk;\n\nALTER TABLE\n lsif_uploads_reference_counts\nADD\n CONSTRAINT lsif_data_docs_search_private_repo_name_id_fk FOREIGN KEY (upload_id) REFERENCES lsif_uploads(id) ON DELETE CASCADE;", + "DownQuery": "-- Force recalculation of reference counts\nUPDATE\n lsif_uploads\nSET\n reference_count = NULL;\n\n-- Remove new table\nDROP TABLE IF EXISTS lsif_uploads_reference_counts;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1660711451, + 1661441160, + 1663569995 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1663665519, + "Name": "perforce_merge_includes_excludes_columns", + "UpQuery": "ALTER TABLE ONLY sub_repo_permissions\n ADD COLUMN IF NOT EXISTS paths text[];\n\nCOMMENT ON COLUMN sub_repo_permissions.paths IS 'Paths that begin with a minus sign (-) are exclusion paths.';\n\nUPDATE sub_repo_permissions\n SET paths = (ARRAY(SELECT CONCAT('/', path_include) FROM unnest(path_includes) as path_include) || ARRAY(SELECT CONCAT('-/', path_exclude) FROM unnest(path_excludes) as path_exclude));", + "DownQuery": "ALTER TABLE sub_repo_permissions\n DROP COLUMN IF EXISTS paths;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1660711451, + 1662467128 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1663871069, + "Name": "changeset specs null published", + "UpQuery": "UPDATE changeset_specs\nSET published = NULL\nWHERE published = 'null';\n\nUPDATE changeset_specs\nSET published = '\"draft\"'\nWHERE published = 'draft';\n\nALTER TABLE changeset_specs\n DROP CONSTRAINT IF EXISTS changeset_specs_published_valid_values,\n ADD CONSTRAINT changeset_specs_published_valid_values CHECK (published = 'true' OR published = 'false' OR\n published = '\"draft\"' OR published IS NULL);", + "DownQuery": "ALTER TABLE changeset_specs\n DROP CONSTRAINT IF EXISTS changeset_specs_published_valid_values;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1660711451, + 1662467128 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1664897165, + "Name": "executor_secrets", + "UpQuery": "CREATE TABLE IF NOT EXISTS executor_secrets (\n id SERIAL PRIMARY KEY,\n key text NOT NULL,\n value bytea NOT NULL,\n scope text NOT NULL,\n encryption_key_id text,\n namespace_user_id integer REFERENCES users(id) ON DELETE CASCADE,\n namespace_org_id integer REFERENCES orgs(id) ON DELETE CASCADE,\n created_at timestamp with time zone NOT NULL DEFAULT NOW(),\n updated_at timestamp with time zone NOT NULL DEFAULT NOW(),\n creator_id integer REFERENCES users(id) ON DELETE SET NULL\n);\n\nCOMMENT ON COLUMN executor_secrets.creator_id IS 'NULL, if the user has been deleted.';\n\n-- Enforce uniqueness of the key in a given namespace.\nCREATE UNIQUE INDEX IF NOT EXISTS executor_secrets_unique_key_namespace_user ON executor_secrets (key, namespace_user_id, scope) WHERE namespace_user_id IS NOT NULL;\nCREATE UNIQUE INDEX IF NOT EXISTS executor_secrets_unique_key_namespace_org ON executor_secrets (key, namespace_org_id, scope) WHERE namespace_org_id IS NOT NULL;\n-- Enforce uniqueness of the key in the global namespace. NULL is a fun type :)\nCREATE UNIQUE INDEX IF NOT EXISTS executor_secrets_unique_key_global ON executor_secrets(key, scope) WHERE namespace_user_id IS NULL AND namespace_org_id IS NULL;\n\nCREATE TABLE IF NOT EXISTS executor_secret_access_logs (\n id SERIAL PRIMARY KEY,\n executor_secret_id integer NOT NULL REFERENCES executor_secrets(id) ON DELETE CASCADE,\n user_id integer NOT NULL REFERENCES users(id) ON DELETE CASCADE,\n created_at timestamp with time zone NOT NULL DEFAULT NOW()\n);", + "DownQuery": "DROP TABLE IF EXISTS executor_secret_access_logs;\nDROP TABLE IF EXISTS executor_secrets;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1663665519, + 1663871069, + 1664300936 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1664988036, + "Name": "create_webhooks_table", + "UpQuery": "CREATE TABLE IF NOT EXISTS webhooks(\n id UUID NOT NULL,\n code_host_kind TEXT NOT NULL,\n code_host_urn TEXT NOT NULL,\n secret TEXT,\n created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,\n updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,\n encryption_key_id TEXT NOT NULL DEFAULT ''\n);\n\nCOMMENT ON TABLE webhooks IS 'Webhooks registered in Sourcegraph instance.';\nCOMMENT ON COLUMN webhooks.code_host_kind IS 'Kind of an external service for which webhooks are registered.';\nCOMMENT ON COLUMN webhooks.code_host_urn IS 'URN of a code host. This column maps to external_service_id column of repo table.';\nCOMMENT ON COLUMN webhooks.secret IS 'Secret used to decrypt webhook payload (if supported by the code host).';", + "DownQuery": "DROP TABLE IF EXISTS webhooks;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1663665519, + 1663871069, + 1664300936 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1665056530, + "Name": "auto-generate-webhook-id", + "UpQuery": "ALTER TABLE webhooks\n DROP CONSTRAINT IF EXISTS webhooks_pkey,\n ADD CONSTRAINT webhooks_pkey PRIMARY KEY (id),\n ALTER COLUMN id SET DEFAULT gen_random_uuid();", + "DownQuery": "ALTER TABLE IF EXISTS webhooks\n ALTER COLUMN id DROP DEFAULT,\n DROP CONSTRAINT IF EXISTS webhooks_pkey;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1664988036 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1665138849, + "Name": "add-rand-id-to-webhooks", + "UpQuery": "-- We are changing the schema and we don't expect any rows yet so we can just drop\n-- the old table\nDROP TABLE IF EXISTS webhooks;\n\nCREATE TABLE webhooks (\n id SERIAL PRIMARY KEY,\n rand_id uuid DEFAULT gen_random_uuid() NOT NULL,\n code_host_kind text NOT NULL,\n code_host_urn text NOT NULL,\n secret text,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n encryption_key_id text\n);\n\nCOMMENT ON TABLE webhooks IS 'Webhooks registered in Sourcegraph instance.';\n\nCOMMENT ON COLUMN webhooks.code_host_kind IS 'Kind of an external service for which webhooks are registered.';\n\nCOMMENT ON COLUMN webhooks.code_host_urn IS 'URN of a code host. This column maps to external_service_id column of repo table.';\n\nCOMMENT ON COLUMN webhooks.secret IS 'Secret used to decrypt webhook payload (if supported by the code host).';\n\nCOMMENT ON COLUMN webhooks.rand_id IS 'rand_id will be the user facing ID';", + "DownQuery": "-- We can just drop the new table and create the old one again\n\nDROP TABLE IF EXISTS webhooks;\n\nCREATE TABLE webhooks (\n id uuid DEFAULT gen_random_uuid() NOT NULL,\n code_host_kind text NOT NULL,\n code_host_urn text NOT NULL,\n secret text,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n encryption_key_id text DEFAULT ''::text NOT NULL\n);\n\nCOMMENT ON TABLE webhooks IS 'Webhooks registered in Sourcegraph instance.';\n\nCOMMENT ON COLUMN webhooks.code_host_kind IS 'Kind of an external service for which webhooks are registered.';\n\nCOMMENT ON COLUMN webhooks.code_host_urn IS 'URN of a code host. This column maps to external_service_id column of repo table.';\n\nCOMMENT ON COLUMN webhooks.secret IS 'Secret used to decrypt webhook payload (if supported by the code host).';\n\nALTER TABLE webhooks\n ADD CONSTRAINT webhooks_pkey PRIMARY KEY (id);", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1665056530 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1665399117, + "Name": "rename a column and add an index to webhooks table", + "UpQuery": "ALTER TABLE webhooks\n DROP COLUMN IF EXISTS rand_id,\n ADD COLUMN IF NOT EXISTS uuid UUID UNIQUE NOT NULL DEFAULT gen_random_uuid();", + "DownQuery": "ALTER TABLE webhooks\n DROP COLUMN IF EXISTS uuid,\n ADD COLUMN IF NOT EXISTS rand_id UUID DEFAULT gen_random_uuid() NOT NULL;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1665138849 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1662636054, + "Name": "autoindexing_persisted_inference_script", + "UpQuery": "CREATE TABLE IF NOT EXISTS codeintel_inference_scripts (\n insert_timestamp timestamptz NOT NULL default NOW(),\n script text NOT NULL\n);\n\nCOMMENT ON table codeintel_inference_scripts IS 'Contains auto-index job inference Lua scripts as an alternative to setting via environment variables.';", + "DownQuery": "-- Undo the changes made in the up migration\nDROP TABLE IF EXISTS codeintel_inference_scripts;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1661502186, + 1661507724 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1665420690, + "Name": "persisted repo document ranks", + "UpQuery": "CREATE TABLE IF NOT EXISTS codeintel_path_ranks (\n repository_id integer NOT NULL UNIQUE,\n payload text NOT NULL\n);", + "DownQuery": "DROP TABLE IF EXISTS codeintel_path_ranks;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1662636054, + 1665399117 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1665477911, + "Name": "add_zoekt_repos_table", + "UpQuery": "CREATE TABLE IF NOT EXISTS zoekt_repos (\n repo_id integer NOT NULL PRIMARY KEY REFERENCES repo(id) ON DELETE CASCADE,\n branches jsonb DEFAULT '[]'::jsonb NOT NULL,\n\n index_status text DEFAULT 'not_indexed'::text NOT NULL,\n\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL\n);\n\nCREATE INDEX IF NOT EXISTS zoekt_repos_index_status ON zoekt_repos USING btree (index_status);\n\nCREATE OR REPLACE FUNCTION func_insert_zoekt_repo() RETURNS TRIGGER AS $$\nBEGIN\n INSERT INTO zoekt_repos (repo_id) VALUES (NEW.id);\n\n RETURN NULL;\nEND;\n$$ LANGUAGE plpgsql;\n\nDROP TRIGGER IF EXISTS trig_create_zoekt_repo_on_repo_insert on repo;\n\nCREATE TRIGGER trig_create_zoekt_repo_on_repo_insert\nAFTER INSERT\nON repo\nFOR EACH ROW\nEXECUTE FUNCTION func_insert_zoekt_repo();", + "DownQuery": "DROP TRIGGER IF EXISTS trig_create_zoekt_repo_on_repo_insert ON repo;\nDROP FUNCTION IF EXISTS func_insert_zoekt_repo();\n\nDROP TABLE IF EXISTS zoekt_repos;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1662636054, + 1665399117 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1665488828, + "Name": "add columns to webhooks table", + "UpQuery": "ALTER TABLE webhooks\n DROP COLUMN IF EXISTS created_by_user_id,\n DROP COLUMN IF EXISTS updated_by_user_id,\n ADD COLUMN created_by_user_id INTEGER REFERENCES users(id) ON DELETE SET NULL,\n ADD COLUMN updated_by_user_id INTEGER DEFAULT NULL REFERENCES users(id) ON DELETE SET NULL;\n\nCOMMENT ON COLUMN webhooks.created_by_user_id IS 'ID of a user, who created the webhook. If NULL, then the user does not exist (never existed or was deleted).';\nCOMMENT ON COLUMN webhooks.updated_by_user_id IS 'ID of a user, who updated the webhook. If NULL, then the user does not exist (never existed or was deleted).';", + "DownQuery": "ALTER TABLE webhooks\n DROP COLUMN IF EXISTS created_by_user_id,\n DROP COLUMN IF EXISTS updated_by_user_id;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1662636054, + 1665399117 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1665524865, + "Name": "add column repo_status to gitserver_repos table", + "UpQuery": "ALTER TABLE gitserver_repos\n -- repo_status indicates the \"live\" status of a cloned repo and\n -- is to be used in addition to clone_status. For example, it\n -- may indicate if a repo is currently being \"fetched\" or if it\n -- is currently being garbage collcted by one of the cleanup\n -- jobs.\n ADD COLUMN IF NOT EXISTS repo_status text;", + "DownQuery": "-- Undo the changes made in the up migration\n\nALTER TABLE gitserver_repos\n DROP COLUMN IF EXISTS repo_status;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1662636054, + 1665399117 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1665646849, + "Name": "add-counters-to-external-service-sync-job", + "UpQuery": "ALTER TABLE IF EXISTS external_service_sync_jobs\nADD COLUMN IF NOT EXISTS repos_synced integer DEFAULT 0 NOT NULL,\nADD COLUMN IF NOT EXISTS repo_sync_errors integer DEFAULT 0 NOT NULL,\nADD COLUMN IF NOT EXISTS repos_added integer DEFAULT 0 NOT NULL,\nADD COLUMN IF NOT EXISTS repos_deleted integer DEFAULT 0 NOT NULL,\nADD COLUMN IF NOT EXISTS repos_modified integer DEFAULT 0 NOT NULL,\nADD COLUMN IF NOT EXISTS repos_unmodified integer DEFAULT 0 NOT NULL;\n\nCOMMENT ON COLUMN external_service_sync_jobs.repos_synced IS 'The number of repos synced during this sync job.';\nCOMMENT ON COLUMN external_service_sync_jobs.repo_sync_errors IS 'The number of times an error occurred syncing a repo during this sync job.';\nCOMMENT ON COLUMN external_service_sync_jobs.repos_added IS 'The number of new repos discovered during this sync job.';\nCOMMENT ON COLUMN external_service_sync_jobs.repos_deleted IS 'The number of repos deleted as a result of this sync job.';\nCOMMENT ON COLUMN external_service_sync_jobs.repos_modified IS 'The number of existing repos whose metadata has changed during this sync job.';\nCOMMENT ON COLUMN external_service_sync_jobs.repos_unmodified IS 'The number of existing repos whose metadata did not change during this sync job.';", + "DownQuery": "ALTER TABLE IF EXISTS external_service_sync_jobs\nDROP COLUMN IF EXISTS repos_synced,\nDROP COLUMN IF EXISTS repo_sync_errors,\nDROP COLUMN IF EXISTS repos_added,\nDROP COLUMN IF EXISTS repos_deleted,\nDROP COLUMN IF EXISTS repos_modified,\nDROP COLUMN IF EXISTS repos_unmodified;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1665524865 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1665588249, + "Name": "Rename bad fk constraint", + "UpQuery": "-- Migration 1664300936 had a really weird copy and paste error we can fix here.\nALTER TABLE\n lsif_uploads_reference_counts DROP CONSTRAINT IF EXISTS lsif_uploads_reference_counts_upload_id_fk;\n\nALTER TABLE\n lsif_uploads_reference_counts DROP CONSTRAINT IF EXISTS lsif_data_docs_search_private_repo_name_id_fk;\n\nALTER TABLE\n lsif_uploads_reference_counts\nADD\n CONSTRAINT lsif_uploads_reference_counts_upload_id_fk FOREIGN KEY (upload_id) REFERENCES lsif_uploads(id) ON DELETE CASCADE;", + "DownQuery": "-- Put the weird name back\nALTER TABLE\n lsif_uploads_reference_counts DROP CONSTRAINT IF EXISTS lsif_uploads_reference_counts_upload_id_fk;\n\nALTER TABLE\n lsif_uploads_reference_counts DROP CONSTRAINT IF EXISTS lsif_data_docs_search_private_repo_name_id_fk;\n\nALTER TABLE\n lsif_uploads_reference_counts\nADD\n CONSTRAINT lsif_data_docs_search_private_repo_name_id_fk FOREIGN KEY (upload_id) REFERENCES lsif_uploads(id) ON DELETE CASCADE;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1662636054, + 1665399117 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1665770699, + "Name": "Add codeintel_commit_dates", + "UpQuery": "CREATE TABLE IF NOT EXISTS codeintel_commit_dates(\n repository_id integer NOT NULL,\n commit_bytea bytea NOT NULL,\n committed_at timestamp with time zone,\n PRIMARY KEY(repository_id, commit_bytea)\n);\n\nCOMMENT ON TABLE codeintel_commit_dates IS 'Maps commits within a repository to the commit date as reported by gitserver.';\n\nCOMMENT ON COLUMN codeintel_commit_dates.repository_id IS 'Identifies a row in the `repo` table.';\n\nCOMMENT ON COLUMN codeintel_commit_dates.commit_bytea IS 'Identifies the 40-character commit hash.';\n\nCOMMENT ON COLUMN codeintel_commit_dates.committed_at IS 'The commit date (may be -infinity if unresolvable).';\n\nINSERT INTO\n codeintel_commit_dates (repository_id, commit_bytea, committed_at)\nSELECT\n u.repository_id,\n decode(u.commit, 'hex'),\n MIN(u.committed_at)\nFROM\n lsif_uploads u\nWHERE\n u.committed_at IS NOT NULL\nGROUP BY\n u.repository_id,\n u.commit\nON CONFLICT DO NOTHING;", + "DownQuery": "DROP TABLE IF EXISTS codeintel_commit_dates;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1665420690, + 1665488828, + 1665524865, + 1665588249 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1666034720, + "Name": "Add lsif_upload references (gc) scan timestamp", + "UpQuery": "ALTER TABLE\n lsif_uploads\nADD\n COLUMN IF NOT EXISTS last_referenced_scan_at timestamp with time zone;\n\nCOMMENT ON COLUMN lsif_uploads.last_referenced_scan_at IS 'The last time this upload was known to be referenced by another (possibly expired) index.';", + "DownQuery": "ALTER TABLE\n lsif_uploads DROP COLUMN IF EXISTS last_referenced_scan_at;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1665420690, + 1665488828, + 1665524865, + 1665588249 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1666131819, + "Name": "Add lsif_upload traversal scan timestamp", + "UpQuery": "ALTER TABLE\n lsif_uploads\nADD\n COLUMN IF NOT EXISTS last_traversal_scan_at timestamp with time zone;\n\nCOMMENT ON COLUMN lsif_uploads.last_traversal_scan_at IS 'The last time this upload was known to be reachable by a non-expired index.';", + "DownQuery": "ALTER TABLE\n lsif_uploads DROP COLUMN IF EXISTS last_traversal_scan_at;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1665646849, + 1665770699, + 1666034720 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1666145729, + "Name": "Add lsif_indexes.should__reindex", + "UpQuery": "ALTER TABLE lsif_indexes ADD COLUMN IF NOT EXISTS should_reindex boolean NOT NULL DEFAULT false;\n\nDROP VIEW IF EXISTS lsif_indexes_with_repository_name;\n\nCREATE VIEW lsif_indexes_with_repository_name AS\n SELECT u.id,\n u.commit,\n u.queued_at,\n u.state,\n u.failure_message,\n u.started_at,\n u.finished_at,\n u.repository_id,\n u.process_after,\n u.num_resets,\n u.num_failures,\n u.docker_steps,\n u.root,\n u.indexer,\n u.indexer_args,\n u.outfile,\n u.log_contents,\n u.execution_logs,\n u.local_steps,\n u.should_reindex,\n r.name AS repository_name\n FROM (lsif_indexes u\n JOIN repo r ON ((r.id = u.repository_id)))\n WHERE (r.deleted_at IS NULL);", + "DownQuery": "DROP VIEW IF EXISTS lsif_indexes_with_repository_name;\n\nCREATE VIEW lsif_indexes_with_repository_name AS\n SELECT u.id,\n u.commit,\n u.queued_at,\n u.state,\n u.failure_message,\n u.started_at,\n u.finished_at,\n u.repository_id,\n u.process_after,\n u.num_resets,\n u.num_failures,\n u.docker_steps,\n u.root,\n u.indexer,\n u.indexer_args,\n u.outfile,\n u.log_contents,\n u.execution_logs,\n u.local_steps,\n r.name AS repository_name\n FROM (lsif_indexes u\n JOIN repo r ON ((r.id = u.repository_id)))\n WHERE (r.deleted_at IS NULL);\n\nALTER TABLE lsif_indexes DROP COLUMN IF EXISTS should_reindex;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1665420690, + 1665488828, + 1665524865, + 1665588249 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1666344635, + "Name": "fill_zoekt_repos_table", + "UpQuery": "INSERT INTO zoekt_repos (repo_id)\nSELECT id\nFROM repo\nLEFT JOIN zoekt_repos zr ON repo.id = zr.repo_id\nWHERE zr.repo_id IS NULL\nON CONFLICT (repo_id) DO NOTHING;", + "DownQuery": "-- No undo", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1665477911, + 1666131819, + 1666145729 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1666398757, + "Name": "ensure_cancel_column", + "UpQuery": "ALTER TABLE webhook_build_jobs ADD COLUMN IF NOT EXISTS cancel BOOLEAN NOT NULL DEFAULT FALSE;", + "DownQuery": "ALTER TABLE webhook_build_jobs DROP COLUMN IF EXISTS cancel;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1666131819, + 1666145729 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1666524436, + "Name": "Add missing state index on lsif_dependency_indexing_jobs table", + "UpQuery": "CREATE INDEX CONCURRENTLY IF NOT EXISTS lsif_dependency_indexing_jobs_state ON lsif_dependency_indexing_jobs (state);", + "DownQuery": "DROP INDEX IF EXISTS lsif_dependency_indexing_jobs_state;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1666131819, + 1666145729 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "lsif_dependency_indexing_jobs", + "IndexName": "lsif_dependency_indexing_jobs_state" + } + }, + { + "ID": 1666598814, + "Name": "Add missing state index on lsif_dependency_syncing_jobs table", + "UpQuery": "CREATE INDEX CONCURRENTLY IF NOT EXISTS lsif_dependency_syncing_jobs_state ON lsif_dependency_syncing_jobs (state);", + "DownQuery": "DROP INDEX IF EXISTS lsif_dependency_syncing_jobs_state;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1666524436 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "lsif_dependency_syncing_jobs", + "IndexName": "lsif_dependency_syncing_jobs_state" + } + }, + { + "ID": 1666598828, + "Name": "Add missing state index on batch_spec_resolution_jobs table", + "UpQuery": "CREATE INDEX CONCURRENTLY IF NOT EXISTS batch_spec_resolution_jobs_state ON batch_spec_resolution_jobs (state);", + "DownQuery": "DROP INDEX IF EXISTS batch_spec_resolution_jobs_state;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1666598814 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "batch_spec_resolution_jobs", + "IndexName": "batch_spec_resolution_jobs_state" + } + }, + { + "ID": 1666598983, + "Name": "Add missing state index on gitserver_relocator_jobs table", + "UpQuery": "CREATE INDEX CONCURRENTLY IF NOT EXISTS gitserver_relocator_jobs_state ON gitserver_relocator_jobs (state);", + "DownQuery": "DROP INDEX IF EXISTS gitserver_relocator_jobs_state;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1666598828 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "gitserver_relocator_jobs", + "IndexName": "gitserver_relocator_jobs_state" + } + }, + { + "ID": 1666598987, + "Name": "Add missing state index on webhook_build_jobs table", + "UpQuery": "CREATE INDEX CONCURRENTLY IF NOT EXISTS webhook_build_jobs_state ON webhook_build_jobs (state);", + "DownQuery": "DROP INDEX IF EXISTS webhook_build_jobs_state;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1666598983 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "webhook_build_jobs", + "IndexName": "webhook_build_jobs_state" + } + }, + { + "ID": 1666598990, + "Name": "add columns to webhooks table", + "UpQuery": "ALTER TABLE webhook_logs\n ADD COLUMN IF NOT EXISTS webhook_id INTEGER REFERENCES webhooks(id) ON DELETE CASCADE;", + "DownQuery": "ALTER TABLE webhook_logs\n DROP COLUMN IF EXISTS webhook_id;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1666598987 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1666717223, + "Name": "Add codeintel_ranking_exports table", + "UpQuery": "CREATE TABLE IF NOT EXISTS codeintel_ranking_exports (\n upload_id integer NOT NULL,\n graph_key text NOT NULL,\n locked_at timestamp with time zone NOT NULL DEFAULT NOW(),\n PRIMARY KEY (upload_id, graph_key),\n FOREIGN KEY (upload_id) REFERENCES lsif_uploads(id) ON DELETE CASCADE\n);", + "DownQuery": "DROP TABLE IF EXISTS codeintel_ranking_exports;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1666598987 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1666886757, + "Name": "add_event_logs_user_id_timestamp_index", + "UpQuery": "CREATE INDEX CONCURRENTLY IF NOT EXISTS event_logs_user_id_timestamp ON event_logs(user_id, timestamp);", + "DownQuery": "DROP INDEX IF EXISTS event_logs_user_id_timestamp;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1664897165, + 1666598990, + 1666717223 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "event_logs", + "IndexName": "event_logs_user_id_timestamp" + } + }, + { + "ID": 1666904087, + "Name": "Add codeintel_path_rank_inputs table", + "UpQuery": "CREATE\nOR REPLACE AGGREGATE sg_jsonb_concat_agg(jsonb) (\n SFUNC = 'jsonb_concat',\n STYPE = jsonb,\n INITCOND = '{}'\n);\n\nALTER TABLE\n codeintel_path_ranks\nALTER COLUMN\n payload TYPE jsonb USING payload :: jsonb;\n\nCREATE TABLE IF NOT EXISTS codeintel_path_rank_inputs(\n id BIGSERIAL PRIMARY KEY,\n graph_key text NOT NULL,\n input_filename text NOT NULL,\n repository_name text NOT NULL,\n payload jsonb NOT NULL,\n processed boolean NOT NULL DEFAULT false,\n UNIQUE (graph_key, input_filename, repository_name)\n);\n\nCREATE INDEX IF NOT EXISTS codeintel_path_rank_graph_key_id_repository_name_processed ON codeintel_path_rank_inputs(graph_key, id, repository_name)\nWHERE\n NOT processed;\n\nCOMMENT ON TABLE codeintel_path_rank_inputs IS 'Sharded inputs from Spark jobs that will subsequently be written into `codeintel_path_ranks`.';", + "DownQuery": "DROP TABLE IF EXISTS codeintel_path_rank_inputs;\n\nALTER TABLE\n codeintel_path_ranks\nALTER COLUMN\n payload TYPE text USING payload :: text;\n\nDROP AGGREGATE IF EXISTS sg_jsonb_concat_agg(jsonb);", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1664897165, + 1666344635, + 1666598990, + 1666717223 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1666939263, + "Name": "add_index_on_event_logs_user_id_name", + "UpQuery": "CREATE INDEX CONCURRENTLY IF NOT EXISTS event_logs_user_id_name ON event_logs (user_id, name);", + "DownQuery": "DROP INDEX IF EXISTS event_logs_user_id_name;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1664897165, + 1666344635, + 1666598990, + 1666717223 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "event_logs", + "IndexName": "event_logs_user_id_name" + } + }, + { + "ID": 1667220502, + "Name": "Add precision to codeintel_path_ranks", + "UpQuery": "DELETE FROM\n codeintel_path_ranks;\n\nALTER TABLE\n codeintel_path_ranks\nADD\n COLUMN IF NOT EXISTS precision float NOT NULL;", + "DownQuery": "ALTER TABLE\n codeintel_path_ranks DROP COLUMN IF EXISTS precision;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1666886757, + 1666904087, + 1666939263 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1667220626, + "Name": "Rename codeintel_path_ranks key", + "UpQuery": "-- Rename default constraint name to something we can control\nALTER TABLE codeintel_path_ranks DROP CONSTRAINT IF EXISTS codeintel_path_ranks_repository_id_key;\nCREATE UNIQUE INDEX IF NOT EXISTS codeintel_path_ranks_repository_id ON codeintel_path_ranks (repository_id);", + "DownQuery": "-- Note: same as up.sql\nALTER TABLE codeintel_path_ranks DROP CONSTRAINT IF EXISTS codeintel_path_ranks_repository_id_key;\nCREATE UNIQUE INDEX IF NOT EXISTS codeintel_path_ranks_repository_id ON codeintel_path_ranks (repository_id);", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1667220502 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1667220628, + "Name": "Update codeintel_path_ranks unique constraint to include precision", + "UpQuery": "DROP INDEX IF EXISTS codeintel_path_ranks_repository_id;\n\nCREATE UNIQUE INDEX IF NOT EXISTS codeintel_path_ranks_repository_id_precision ON codeintel_path_ranks (repository_id, precision);", + "DownQuery": "DROP INDEX IF EXISTS codeintel_path_ranks_repository_id_precision;\n\nCREATE UNIQUE INDEX IF NOT EXISTS codeintel_path_ranks_repository_id ON codeintel_path_ranks (repository_id);", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1667220626 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1667220768, + "Name": "Add precision to codeintel_path_rank_inputs", + "UpQuery": "ALTER TABLE\n codeintel_path_rank_inputs\nADD\n COLUMN IF NOT EXISTS precision float NOT NULL;", + "DownQuery": "ALTER TABLE\n codeintel_path_rank_inputs DROP COLUMN IF EXISTS precision;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1667220628 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1667222952, + "Name": "Add codeintel ranking timestamps", + "UpQuery": "ALTER TABLE\n codeintel_path_ranks\nADD\n COLUMN IF NOT EXISTS updated_at timestamp with time zone NOT NULL DEFAULT NOW();\n\nCREATE INDEX IF NOT EXISTS codeintel_path_ranks_updated_at ON codeintel_path_ranks(updated_at) INCLUDE (repository_id);\n\nCREATE OR REPLACE FUNCTION update_codeintel_path_ranks_updated_at_column() RETURNS TRIGGER AS\n$$ BEGIN\n NEW.updated_at = NOW();\n RETURN NEW;\nEND;\n$$ language 'plpgsql';\n\nDROP TRIGGER IF EXISTS update_codeintel_path_ranks_updated_at ON codeintel_path_ranks;\nCREATE TRIGGER update_codeintel_path_ranks_updated_at BEFORE UPDATE ON codeintel_path_ranks FOR EACH ROW EXECUTE PROCEDURE update_codeintel_path_ranks_updated_at_column();", + "DownQuery": "DROP TRIGGER IF EXISTS update_codeintel_path_ranks_updated_at ON codeintel_path_ranks;\nDROP FUNCTION IF EXISTS update_codeintel_path_ranks_updated_at_column;\nDROP INDEX IF EXISTS codeintel_path_ranks_updated_at;\nALTER TABLE codeintel_path_ranks DROP COLUMN IF EXISTS updated_at;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1666886757, + 1666904087, + 1666939263 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1667259203, + "Name": "Add graph_key to codeintel_path_ranks", + "UpQuery": "ALTER TABLE\n codeintel_path_ranks\nADD\n COLUMN IF NOT EXISTS graph_key text;", + "DownQuery": "ALTER TABLE\n codeintel_path_ranks DROP COLUMN IF EXISTS graph_key;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1667220768, + 1667222952 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1667313173, + "Name": "Add index to lsif_uploads_visible_at_tip", + "UpQuery": "CREATE INDEX IF NOT EXISTS lsif_uploads_visible_at_tip_is_default_branch ON lsif_uploads_visible_at_tip(upload_id)\nWHERE\n is_default_branch;", + "DownQuery": "DROP INDEX IF EXISTS lsif_uploads_visible_at_tip_is_default_branch;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1667259203 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1667395984, + "Name": "Remove filter from lsif_references", + "UpQuery": "ALTER TABLE\n lsif_references DROP COLUMN IF EXISTS filter;", + "DownQuery": "ALTER TABLE\n lsif_references\nADD\n COLUMN IF NOT EXISTS filter bytea;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1667313173 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1667433265, + "Name": "Add last_reconcile to lsif_uploads table", + "UpQuery": "ALTER TABLE\n lsif_uploads\nADD\n COLUMN IF NOT EXISTS last_reconcile_at timestamp with time zone;\n\nCREATE INDEX IF NOT EXISTS lsif_uploads_last_reconcile_at ON lsif_uploads(last_reconcile_at, id)\nWHERE\n state = 'completed';", + "DownQuery": "DROP INDEX IF EXISTS lsif_uploads_last_reconcile_at;\n\nALTER TABLE\n lsif_uploads DROP COLUMN IF EXISTS last_reconcile_at;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1667395984 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1667497565, + "Name": "Fix cascade behavior for codeintel_ranking_exports", + "UpQuery": "-- Change primary key\nALTER TABLE codeintel_ranking_exports DROP CONSTRAINT IF EXISTS codeintel_ranking_exports_pkey;\nALTER TABLE codeintel_ranking_exports ADD COLUMN IF NOT EXISTS id SERIAL NOT NULL;\nALTER TABLE codeintel_ranking_exports ADD PRIMARY KEY (id);\n\n-- Make column + foreign key nullable\nALTER TABLE codeintel_ranking_exports DROP CONSTRAINT IF EXISTS codeintel_ranking_exports_upload_id_fkey;\nALTER TABLE codeintel_ranking_exports ALTER COLUMN upload_id DROP NOT NULL;\nALTER TABLE codeintel_ranking_exports ADD CONSTRAINT codeintel_ranking_exports_upload_id_fkey FOREIGN KEY (upload_id) REFERENCES lsif_uploads(id) ON DELETE SET NULL;\n\n-- Emulate old primary key index\nCREATE UNIQUE INDEX IF NOT EXISTS codeintel_ranking_exports_upload_id_graph_key ON codeintel_ranking_exports(upload_id, graph_key);\n\n-- Add prefix to control authoritative GCS paths as we might set upload_id to NULL now\nALTER TABLE codeintel_ranking_exports ADD COLUMN IF NOT EXISTS object_prefix TEXT;", + "DownQuery": "-- Drop dependent constraints\nALTER TABLE codeintel_ranking_exports DROP CONSTRAINT IF EXISTS codeintel_ranking_exports_pkey;\n\n-- Make column + foreign key non-nullable\nALTER TABLE codeintel_ranking_exports DROP CONSTRAINT IF EXISTS codeintel_ranking_exports_upload_id_fkey;\nDELETE FROM codeintel_ranking_exports WHERE upload_id IS NULL;\nALTER TABLE codeintel_ranking_exports ALTER COLUMN upload_id SET NOT NULL;\nALTER TABLE codeintel_ranking_exports ADD CONSTRAINT codeintel_ranking_exports_upload_id_fkey FOREIGN KEY (upload_id) REFERENCES lsif_uploads(id) ON DELETE CASCADE;\n\n-- Restore the old primary key\nALTER TABLE codeintel_ranking_exports DROP COLUMN IF EXISTS id;\nALTER TABLE codeintel_ranking_exports ADD PRIMARY KEY (upload_id, graph_key);\n\n-- Drop now duplicate index\nDROP INDEX IF EXISTS codeintel_ranking_exports_upload_id_graph_key;\n\n-- Drop new column\nALTER TABLE codeintel_ranking_exports DROP COLUMN IF EXISTS object_prefix;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1667395984 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1667500111, + "Name": "Fix codeintel_path_ranks trigger condition", + "UpQuery": "DROP TRIGGER IF EXISTS update_codeintel_path_ranks_updated_at ON codeintel_path_ranks;\nCREATE TRIGGER update_codeintel_path_ranks_updated_at BEFORE UPDATE ON codeintel_path_ranks FOR EACH ROW WHEN (NEW IS DISTINCT FROM OLD) EXECUTE PROCEDURE update_codeintel_path_ranks_updated_at_column();", + "DownQuery": "DROP TRIGGER IF EXISTS update_codeintel_path_ranks_updated_at ON codeintel_path_ranks;\nCREATE TRIGGER update_codeintel_path_ranks_updated_at BEFORE UPDATE ON codeintel_path_ranks FOR EACH ROW EXECUTE PROCEDURE update_codeintel_path_ranks_updated_at_column();", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1667395984 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1667825028, + "Name": "Add SSBC execution V2 flag", + "UpQuery": "ALTER TABLE batch_spec_workspace_execution_jobs ADD COLUMN IF NOT EXISTS version integer NOT NULL DEFAULT 1;\n\nDROP VIEW batch_spec_workspace_execution_jobs_with_rank;\nCREATE VIEW batch_spec_workspace_execution_jobs_with_rank AS (\n SELECT\n j.*,\n q.place_in_global_queue,\n q.place_in_user_queue\n FROM\n batch_spec_workspace_execution_jobs j\n LEFT JOIN batch_spec_workspace_execution_queue q ON j.id = q.id\n);", + "DownQuery": "DROP VIEW batch_spec_workspace_execution_jobs_with_rank;\nCREATE VIEW batch_spec_workspace_execution_jobs_with_rank AS (\n SELECT\n j.id,\n j.batch_spec_workspace_id,\n j.state,\n j.failure_message,\n j.started_at,\n j.finished_at,\n j.process_after,\n j.num_resets,\n j.num_failures,\n j.execution_logs,\n j.worker_hostname,\n j.last_heartbeat_at,\n j.created_at,\n j.updated_at,\n j.cancel,\n j.queued_at,\n j.user_id,\n q.place_in_global_queue,\n q.place_in_user_queue\n FROM\n batch_spec_workspace_execution_jobs j\n LEFT JOIN batch_spec_workspace_execution_queue q ON j.id = q.id\n);\n\nALTER TABLE batch_spec_workspace_execution_jobs DROP COLUMN IF EXISTS version;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1667433265, + 1667497565, + 1667500111 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1667848448, + "Name": "Flip index field order", + "UpQuery": "-- Effectively replaces codeintel_path_rank_graph_key_id_repository_name_processed\nCREATE INDEX IF NOT EXISTS codeintel_path_rank_inputs_graph_key_repository_name_id_processed ON codeintel_path_rank_inputs(graph_key, repository_name, id)\nWHERE\n NOT processed;", + "DownQuery": "DROP INDEX IF EXISTS codeintel_path_rank_inputs_graph_key_repository_name_id_processed;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1667433265, + 1667497565, + 1667500111 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1667863757, + "Name": "Drop old index", + "UpQuery": "DROP INDEX IF EXISTS codeintel_path_rank_graph_key_id_repository_name_processed;", + "DownQuery": "CREATE INDEX IF NOT EXISTS codeintel_path_rank_graph_key_id_repository_name_processed ON codeintel_path_rank_inputs(graph_key, id, repository_name)\nWHERE\n NOT processed;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1667848448 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1667917030, + "Name": "Fix codeintel_ranking_exports index order", + "UpQuery": "CREATE UNIQUE INDEX IF NOT EXISTS codeintel_ranking_exports_graph_key_upload_id ON codeintel_ranking_exports(graph_key, upload_id);\n\nDROP INDEX IF EXISTS codeintel_ranking_exports_upload_id_graph_key;", + "DownQuery": "CREATE UNIQUE INDEX IF NOT EXISTS codeintel_ranking_exports_upload_id_graph_key ON codeintel_ranking_exports(upload_id, graph_key);\n\nDROP INDEX IF EXISTS codeintel_ranking_exports_graph_key_upload_id;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1667863757 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1667950421, + "Name": "Speed up ListSourcegraphDotComIndexableRepos", + "UpQuery": "CREATE INDEX CONCURRENTLY IF NOT EXISTS repo_dotcom_indexable_repos_idx ON repo (stars DESC NULLS LAST) INCLUDE (id, name)\nWHERE\n deleted_at IS NULL AND blocked IS NULL AND (\n (repo.stars \u003e= 5 AND NOT COALESCE(fork, false) AND NOT archived)\n OR\n (lower(repo.name) ~ '^(src\\.fedoraproject\\.org|maven|npm|jdk)')\n );", + "DownQuery": "DROP INDEX IF EXISTS repo_dotcom_indexable_repos_idx;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1667917030 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "repo", + "IndexName": "repo_dotcom_indexable_repos_idx" + } + }, + { + "ID": 1667952974, + "Name": "Speed up ListSourcegraphDotComIndexableRepos (part 2)", + "UpQuery": "CREATE INDEX CONCURRENTLY IF NOT EXISTS gitserver_repos_not_explicitly_cloned_idx ON gitserver_repos (repo_id) WHERE clone_status \u003c\u003e 'cloned';", + "DownQuery": "DROP INDEX IF EXISTS gitserver_repos_not_explicitly_cloned_idx;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1667950421 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "gitserver_repos", + "IndexName": "gitserver_repos_not_explicitly_cloned_idx" + } + }, + { + "ID": 1668174127, + "Name": "Add gitserver_repos_last_changed_idx", + "UpQuery": "CREATE INDEX CONCURRENTLY IF NOT EXISTS gitserver_repos_last_changed_idx ON gitserver_repos(last_changed, repo_id);", + "DownQuery": "DROP INDEX IF EXISTS gitserver_repos_last_changed_idx;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1667825028, + 1667952974 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "gitserver_repos", + "IndexName": "gitserver_repos_last_changed_idx" + } + }, + { + "ID": 1668184279, + "Name": "remove git_status column from gitserver_repos table", + "UpQuery": "-- Perform migration here.\n--\n-- See /migrations/README.md. Highlights:\n-- * Make migrations idempotent (use IF EXISTS)\n-- * Make migrations backwards-compatible (old readers/writers must continue to work)\n-- * If you are using CREATE INDEX CONCURRENTLY, then make sure that only one statement\n-- is defined per file, and that each such statement is NOT wrapped in a transaction.\n-- Each such migration must also declare \"createIndexConcurrently: true\" in their\n-- associated metadata.yaml file.\n-- * If you are modifying Postgres extensions, you must also declare \"privileged: true\"\n-- in the associated metadata.yaml file.\n\nALTER TABLE gitserver_repos DROP COLUMN IF EXISTS repo_status;", + "DownQuery": "-- Undo the changes made in the up migration\nALTER TABLE gitserver_repos\nADD COLUMN IF NOT EXISTS repo_status text;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1668174127 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1668179496, + "Name": "Add event_logs_name_timestamp", + "UpQuery": "CREATE INDEX CONCURRENTLY IF NOT EXISTS event_logs_name_timestamp ON event_logs(name, timestamp desc);", + "DownQuery": "DROP INDEX IF EXISTS event_logs_name_timestamp;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1667825028, + 1667952974 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "event_logs", + "IndexName": "event_logs_name_timestamp" + } + }, + { + "ID": 1668179619, + "Name": "Drop redundant index", + "UpQuery": "DROP INDEX IF EXISTS event_logs_name;", + "DownQuery": "CREATE INDEX IF NOT EXISTS event_logs_name ON event_logs(name);", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1668179496 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1668603582, + "Name": "add gitserver.repo_size_bytes index", + "UpQuery": "CREATE INDEX CONCURRENTLY IF NOT EXISTS gitserver_repo_size_bytes\n ON gitserver_repos USING btree (repo_size_bytes);", + "DownQuery": "DROP INDEX IF EXISTS gitserver_repo_size_bytes;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1668179619, + 1668184279 + ], + "IsCreateIndexConcurrently": true, + "IndexMetadata": { + "TableName": "gitserver_repos", + "IndexName": "gitserver_repo_size_bytes" + } + }, + { + "ID": 1668707631, + "Name": "add_unique_constraint_batch_specs_rand_id", + "UpQuery": "CREATE UNIQUE INDEX\n IF NOT EXISTS batch_specs_unique_rand_id ON batch_specs (rand_id);", + "DownQuery": "DROP INDEX IF EXISTS batch_specs_unique_rand_id;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1668603582 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1668767882, + "Name": "add_unique_constraint_changeset_specs_rand_id", + "UpQuery": "CREATE UNIQUE INDEX\n IF NOT EXISTS changeset_specs_unique_rand_id ON changeset_specs (rand_id);", + "DownQuery": "DROP INDEX IF EXISTS changeset_specs_unique_rand_id;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1668707631 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1668808118, + "Name": "temp_codeinsights_trace_with_query", + "UpQuery": "ALTER TABLE IF EXISTS insights_query_runner_jobs\n ADD COLUMN IF NOT EXISTS trace_id TEXT;", + "DownQuery": "ALTER TABLE IF EXISTS insights_query_runner_jobs\n DROP COLUMN IF EXISTS trace_id;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1668603582 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1669184869, + "Name": "add name to webhooks table", + "UpQuery": "ALTER TABLE webhooks\n ADD COLUMN IF NOT EXISTS name TEXT;\n\nCOMMENT ON COLUMN webhooks.name IS 'Descriptive name of a webhook.';\n\nUPDATE webhooks SET name = code_host_urn WHERE name IS NULL;\n\nALTER TABLE webhooks\n ALTER COLUMN name SET NOT NULL;", + "DownQuery": "ALTER TABLE webhooks\n DROP COLUMN IF EXISTS name;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1666398757, + 1668808118 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1669836151, + "Name": "Add manager to lsif_package/references", + "UpQuery": "ALTER TABLE lsif_packages ADD COLUMN IF NOT EXISTS manager TEXT NOT NULL DEFAULT '';\nALTER TABLE lsif_references ADD COLUMN IF NOT EXISTS manager TEXT NOT NULL DEFAULT '';\n\nCOMMENT ON COLUMN lsif_packages.manager IS 'The package manager name.';\nCOMMENT ON COLUMN lsif_references.manager IS 'The package manager name.';", + "DownQuery": "ALTER TABLE lsif_packages DROP COLUMN IF EXISTS manager;\nALTER TABLE lsif_references DROP COLUMN IF EXISTS manager;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1668767882, + 1669184869 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1670256530, + "Name": "Add content type to lsif uploads", + "UpQuery": "DROP VIEW IF EXISTS lsif_uploads_with_repository_name;\nALTER TABLE lsif_uploads ADD COLUMN IF NOT EXISTS content_type TEXT NOT NULL DEFAULT 'application/x-ndjson+lsif';\nALTER TABLE lsif_uploads_audit_logs ADD COLUMN IF NOT EXISTS content_type TEXT NOT NULL DEFAULT 'application/x-ndjson+lsif';\n\nCOMMENT ON COLUMN lsif_uploads.content_type IS 'The content type of the upload record. For now, the default value is `application/x-ndjson+lsif` to backfill existing records. This will change as we remove LSIF support.';\n\nCREATE VIEW lsif_uploads_with_repository_name AS\nSELECT u.id,\n u.commit,\n u.root,\n u.queued_at,\n u.uploaded_at,\n u.state,\n u.failure_message,\n u.started_at,\n u.finished_at,\n u.repository_id,\n u.indexer,\n u.indexer_version,\n u.num_parts,\n u.uploaded_parts,\n u.process_after,\n u.num_resets,\n u.upload_size,\n u.num_failures,\n u.associated_index_id,\n u.content_type,\n u.expired,\n u.last_retention_scan_at,\n r.name AS repository_name,\n u.uncompressed_size\nFROM lsif_uploads u\nJOIN repo r ON r.id = u.repository_id\nWHERE r.deleted_at IS NULL;\n\nCREATE OR REPLACE FUNCTION func_lsif_uploads_update() RETURNS TRIGGER AS $$\n DECLARE\n diff hstore[];\n BEGIN\n diff = func_lsif_uploads_transition_columns_diff(\n func_row_to_lsif_uploads_transition_columns(OLD),\n func_row_to_lsif_uploads_transition_columns(NEW)\n );\n\n IF (array_length(diff, 1) \u003e 0) THEN\n INSERT INTO lsif_uploads_audit_logs\n (reason, upload_id, commit, root, repository_id, uploaded_at,\n indexer, indexer_version, upload_size, associated_index_id,\n content_type,\n operation, transition_columns)\n VALUES (\n COALESCE(current_setting('codeintel.lsif_uploads_audit.reason', true), ''),\n NEW.id, NEW.commit, NEW.root, NEW.repository_id, NEW.uploaded_at,\n NEW.indexer, NEW.indexer_version, NEW.upload_size, NEW.associated_index_id,\n NEW.content_type,\n 'modify', diff\n );\n END IF;\n\n RETURN NEW;\n END;\n$$ LANGUAGE plpgsql;\n\nCREATE OR REPLACE FUNCTION func_lsif_uploads_insert() RETURNS TRIGGER AS $$\n BEGIN\n INSERT INTO lsif_uploads_audit_logs\n (upload_id, commit, root, repository_id, uploaded_at,\n indexer, indexer_version, upload_size, associated_index_id,\n content_type,\n operation, transition_columns)\n VALUES (\n NEW.id, NEW.commit, NEW.root, NEW.repository_id, NEW.uploaded_at,\n NEW.indexer, NEW.indexer_version, NEW.upload_size, NEW.associated_index_id,\n NEW.content_type,\n 'create', func_lsif_uploads_transition_columns_diff(\n (NULL, NULL, NULL, NULL, NULL, NULL),\n func_row_to_lsif_uploads_transition_columns(NEW)\n )\n );\n RETURN NULL;\n END;\n$$ LANGUAGE plpgsql;", + "DownQuery": "CREATE OR REPLACE FUNCTION func_lsif_uploads_update() RETURNS TRIGGER AS $$\n DECLARE\n diff hstore[];\n BEGIN\n diff = func_lsif_uploads_transition_columns_diff(\n func_row_to_lsif_uploads_transition_columns(OLD),\n func_row_to_lsif_uploads_transition_columns(NEW)\n );\n\n IF (array_length(diff, 1) \u003e 0) THEN\n INSERT INTO lsif_uploads_audit_logs\n (reason, upload_id, commit, root, repository_id, uploaded_at,\n indexer, indexer_version, upload_size, associated_index_id,\n operation, transition_columns)\n VALUES (\n COALESCE(current_setting('codeintel.lsif_uploads_audit.reason', true), ''),\n NEW.id, NEW.commit, NEW.root, NEW.repository_id, NEW.uploaded_at,\n NEW.indexer, NEW.indexer_version, NEW.upload_size, NEW.associated_index_id,\n 'modify', diff\n );\n END IF;\n\n RETURN NEW;\n END;\n$$ LANGUAGE plpgsql;\n\nCREATE OR REPLACE FUNCTION func_lsif_uploads_insert() RETURNS TRIGGER AS $$\n BEGIN\n INSERT INTO lsif_uploads_audit_logs\n (upload_id, commit, root, repository_id, uploaded_at,\n indexer, indexer_version, upload_size, associated_index_id,\n operation, transition_columns)\n VALUES (\n NEW.id, NEW.commit, NEW.root, NEW.repository_id, NEW.uploaded_at,\n NEW.indexer, NEW.indexer_version, NEW.upload_size, NEW.associated_index_id,\n 'create', func_lsif_uploads_transition_columns_diff(\n (NULL, NULL, NULL, NULL, NULL, NULL),\n func_row_to_lsif_uploads_transition_columns(NEW)\n )\n );\n RETURN NULL;\n END;\n$$ LANGUAGE plpgsql;\n\nDROP VIEW IF EXISTS lsif_uploads_with_repository_name;\nALTER TABLE lsif_uploads DROP COLUMN IF EXISTS content_type;\nALTER TABLE lsif_uploads_audit_logs DROP COLUMN IF EXISTS content_type;\n\nCREATE VIEW lsif_uploads_with_repository_name AS \nSELECT u.id,\n u.commit,\n u.root,\n u.queued_at,\n u.uploaded_at,\n u.state,\n u.failure_message,\n u.started_at,\n u.finished_at,\n u.repository_id,\n u.indexer,\n u.indexer_version,\n u.num_parts,\n u.uploaded_parts,\n u.process_after,\n u.num_resets,\n u.upload_size,\n u.num_failures,\n u.associated_index_id,\n u.expired,\n u.last_retention_scan_at,\n r.name AS repository_name,\n u.uncompressed_size\nFROM lsif_uploads u\nJOIN repo r ON r.id = u.repository_id\nWHERE r.deleted_at IS NULL;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1669836151 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1668813365, + "Name": "create_search_contexts_stars_defaults", + "UpQuery": "CREATE TABLE IF NOT EXISTS search_context_stars (\n search_context_id bigint REFERENCES search_contexts(id) ON DELETE CASCADE DEFERRABLE,\n user_id integer REFERENCES users(id) ON DELETE CASCADE DEFERRABLE,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n PRIMARY KEY (search_context_id, user_id)\n);\n\nCOMMENT ON TABLE search_context_stars IS 'When a user stars a search context, a row is inserted into this table. If the user unstars the search context, the row is deleted. The global context is not in the database, and therefore cannot be starred.';\n\nCREATE TABLE IF NOT EXISTS search_context_default (\n user_id integer PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE DEFERRABLE,\n search_context_id bigint NOT NULL REFERENCES search_contexts(id) ON DELETE CASCADE DEFERRABLE\n);\n\nCOMMENT ON TABLE search_context_default IS 'When a user sets a search context as default, a row is inserted into this table. A user can only have one default search context. If the user has not set their default search context, it will fall back to `global`.';", + "DownQuery": "DROP TABLE IF EXISTS search_context_stars;\n\nDROP TABLE IF EXISTS search_context_default;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1668603582 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1670350006, + "Name": "add_should_reindex_to_lsif_uploads", + "UpQuery": "ALTER TABLE lsif_uploads ADD COLUMN IF NOT EXISTS should_reindex boolean NOT NULL DEFAULT false;", + "DownQuery": "ALTER TABLE lsif_uploads DROP COLUMN IF EXISTS should_reindex;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1668813365, + 1670256530 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1670539388, + "Name": "create_roles_table", + "UpQuery": "CREATE TABLE IF NOT EXISTS roles (\n id SERIAL PRIMARY KEY,\n name TEXT NOT NULL,\n\n created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,\n deleted_at TIMESTAMP WITH TIME ZONE,\n\n CONSTRAINT name_not_blank CHECK ((name \u003c\u003e ''::text)),\n CONSTRAINT roles_name UNIQUE (name)\n);\n\nCOMMENT ON COLUMN roles.name IS 'The uniquely identifying name of the role.';", + "DownQuery": "DROP TABLE IF EXISTS roles;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1668813365, + 1670256530 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1670539913, + "Name": "create_permissions_table", + "UpQuery": "CREATE TABLE IF NOT EXISTS permissions (\n id SERIAL PRIMARY KEY,\n namespace text NOT NULL,\n action TEXT NOT NULL,\n\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n\n CONSTRAINT namespace_not_blank CHECK (namespace \u003c\u003e ''::text),\n CONSTRAINT action_not_blank CHECK (action \u003c\u003e ''::text)\n);\n\n-- Enforce uniqueness of actions in a given namespace\nCREATE UNIQUE INDEX IF NOT EXISTS permissions_unique_namespace_action ON permissions (namespace, action);", + "DownQuery": "DROP TABLE IF EXISTS permissions;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1670539388 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1670542168, + "Name": "create_user_roles_table", + "UpQuery": "CREATE TABLE IF NOT EXISTS user_roles (\n user_id integer REFERENCES users(id) ON DELETE CASCADE DEFERRABLE,\n role_id integer REFERENCES roles(id) ON DELETE CASCADE DEFERRABLE,\n\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n\n PRIMARY KEY (user_id, role_id)\n);", + "DownQuery": "DROP TABLE IF EXISTS user_roles;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1670539913 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + }, + { + "ID": 1670543231, + "Name": "create_role_permissions_table", + "UpQuery": "CREATE TABLE IF NOT EXISTS role_permissions (\n role_id integer REFERENCES roles(id) ON DELETE CASCADE DEFERRABLE,\n permission_id integer REFERENCES permissions(id) ON DELETE CASCADE DEFERRABLE,\n\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n\n PRIMARY KEY (permission_id, role_id)\n);", + "DownQuery": "DROP TABLE IF EXISTS role_permissions;", + "Privileged": false, + "NonIdempotent": false, + "Parents": [ + 1670542168 + ], + "IsCreateIndexConcurrently": false, + "IndexMetadata": null + } + ], + "BoundsByRev": { + "4.3.0": { + "RootID": 1648051770, + "LeafIDs": [ + 1670350006, + 1670543231 + ], + "PreCreation": false + } + } + } +} diff --git a/internal/database/migration/shared/upgradedata/stitched-migration-graph.json b/internal/database/migration/shared/data/stitched-migration-graph.json similarity index 100% rename from internal/database/migration/shared/upgradedata/stitched-migration-graph.json rename to internal/database/migration/shared/data/stitched-migration-graph.json diff --git a/internal/database/migration/shared/embed.go b/internal/database/migration/shared/embed.go index ba37e264cf0..52e24d73aa9 100644 --- a/internal/database/migration/shared/embed.go +++ b/internal/database/migration/shared/embed.go @@ -1,23 +1,66 @@ package shared import ( - _ "embed" + "embed" "encoding/json" "fmt" + "io" + "os" + "path/filepath" + + "github.com/sourcegraph/sourcegraph/internal/database/migration/definition" + "github.com/sourcegraph/sourcegraph/lib/errors" ) -//go:generate go run ./upgradedata/cmd/generator -// Ensure upgradedata/stitched-migration-graph.json is generated +//go:generate go run ./data/cmd/generator +// Ensure data/* files are generated -//go:embed upgradedata/stitched-migration-graph.json -var upgradeDataPayloadContents string +var ( + root = "internal/database/migration/shared/data" + stitchfile = filepath.Join(root, "stitched-migration-graph.json") + constfile = filepath.Join(root, "cmd/generator/consts.go") +) + +//go:embed data/stitched-migration-graph.json +var stitchedPayloadContents string // StitchedMigationsBySchemaName is a map from schema name to migration upgrade metadata. // The data backing the map is updated by `go generating` this package. var StitchedMigationsBySchemaName = map[string]StitchedMigration{} func init() { - if err := json.Unmarshal([]byte(upgradeDataPayloadContents), &StitchedMigationsBySchemaName); err != nil { - panic(fmt.Sprintf("failed to load upgrade data (check the contents of internal/database/migration/shared/upgradedata/stitched-migration-graph.json): %s", err)) + if err := json.Unmarshal([]byte(stitchedPayloadContents), &StitchedMigationsBySchemaName); err != nil { + panic(fmt.Sprintf("failed to load upgrade data (check the contents of %s): %s", stitchfile, err)) } } + +//go:embed data/frozen/* +var frozenDataDir embed.FS + +// GetFrozenDefinitions returns the schema definitions frozen at a given revision. This +// function returns an error if the given schema has not been generated into data/frozen. +func GetFrozenDefinitions(schemaName, rev string) (*definition.Definitions, error) { + f, err := frozenDataDir.Open(fmt.Sprintf("data/frozen/%s.json", rev)) + if err != nil { + if os.IsNotExist(err) { + return nil, errors.Newf("failed to load schema at revision %q (check the versions listed in %s)", rev, constfile) + } + + return nil, err + } + defer f.Close() + + content, err := io.ReadAll(f) + if err != nil { + return nil, err + } + + var definitionBySchema map[string]struct { + Definitions *definition.Definitions + } + if err := json.Unmarshal(content, &definitionBySchema); err != nil { + return nil, err + } + + return definitionBySchema[schemaName].Definitions, nil +}