github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/db/migration/build_events_bigint_test.go (about)

     1  package migration_test
     2  
     3  import (
     4  	"database/sql"
     5  	"fmt"
     6  	"strings"
     7  
     8  	. "github.com/onsi/ginkgo"
     9  	. "github.com/onsi/gomega"
    10  )
    11  
    12  var _ = Describe("build_events bigint indexes", func() {
    13  	const preMigrationVersion = 1602860421
    14  	const postMigrationVersion = 1606068653
    15  	const downMigrationVersion = 1603405319
    16  
    17  	var db *sql.DB
    18  	var teamID int
    19  	var pipelineID int
    20  
    21  	explain := func(query string, params ...interface{}) string {
    22  		rows, err := db.Query("SET enable_seqscan = OFF; EXPLAIN "+query, params...)
    23  		Expect(err).ToNot(HaveOccurred())
    24  
    25  		lines := []string{}
    26  		for rows.Next() {
    27  			var line string
    28  			Expect(rows.Scan(&line)).To(Succeed())
    29  			lines = append(lines, line)
    30  		}
    31  
    32  		return strings.Join(lines, "\n")
    33  	}
    34  
    35  	BeforeEach(func() {
    36  		db = postgresRunner.OpenDBAtVersion(preMigrationVersion)
    37  
    38  		err := db.QueryRow(`
    39  			INSERT INTO teams (name, auth)
    40  			VALUES ('some-team', '{}')
    41  			RETURNING id
    42  		`).Scan(&teamID)
    43  		Expect(err).ToNot(HaveOccurred())
    44  
    45  		err = db.QueryRow(`
    46  			INSERT INTO pipelines (name, team_id)
    47  			VALUES ('some-pipeline', $1)
    48  			RETURNING id
    49  		`, teamID).Scan(&pipelineID)
    50  		Expect(err).ToNot(HaveOccurred())
    51  
    52  		postgresRunner.MigrateToVersion(postMigrationVersion)
    53  	})
    54  
    55  	AfterEach(func() {
    56  		Expect(db.Close()).To(Succeed())
    57  	})
    58  
    59  	Describe("Up", func() {
    60  		It("has indexes for both build_id_old and build_id in parent table", func() {
    61  			plan := explain(`SELECT * FROM build_events WHERE build_id = 1`)
    62  			Expect(plan).To(ContainSubstring("Index Scan"))
    63  
    64  			plan = explain(`SELECT * FROM build_events WHERE build_id_old = 1`)
    65  			Expect(plan).To(ContainSubstring("Index Scan"))
    66  		})
    67  
    68  		It("has indexes for both build_id_old and build_id in pipeline partitions", func() {
    69  			plan := explain(fmt.Sprintf(
    70  				`SELECT * FROM pipeline_build_events_%d WHERE build_id = 1`,
    71  				pipelineID,
    72  			))
    73  			Expect(plan).To(ContainSubstring("Index Scan"))
    74  
    75  			plan = explain(fmt.Sprintf(
    76  				`SELECT * FROM pipeline_build_events_%d WHERE build_id_old = 1`,
    77  				pipelineID,
    78  			))
    79  			Expect(plan).To(ContainSubstring("Index Scan"))
    80  		})
    81  
    82  		It("has indexes for only build_id in team partitions", func() {
    83  			plan := explain(fmt.Sprintf(
    84  				`SELECT * FROM team_build_events_%d WHERE build_id = 1`,
    85  				teamID,
    86  			))
    87  			Expect(plan).To(ContainSubstring("Index Scan"))
    88  
    89  			plan = explain(fmt.Sprintf(
    90  				`SELECT * FROM team_build_events_%d WHERE build_id_old = 1`,
    91  				pipelineID,
    92  			))
    93  			Expect(plan).To(ContainSubstring("Seq Scan"))
    94  		})
    95  
    96  		It("has indexes for newly created team partitions", func() {
    97  			var newTeamID int
    98  			err := db.QueryRow(`
    99  				INSERT INTO teams (name, auth)
   100  				VALUES ('some-other-team', '{}')
   101  				RETURNING id
   102  			`).Scan(&newTeamID)
   103  			Expect(err).ToNot(HaveOccurred())
   104  
   105  			plan := explain(fmt.Sprintf(
   106  				`SELECT * FROM team_build_events_%d WHERE build_id = 1`,
   107  				newTeamID,
   108  			))
   109  			Expect(plan).To(ContainSubstring("Index Scan"))
   110  		})
   111  
   112  		It("has indexes for both build_id and build_id_old in newly created pipeline partitions", func() {
   113  			var newPipelineID int
   114  			err := db.QueryRow(`
   115  				INSERT INTO pipelines (name, team_id)
   116  				VALUES ('some-other-pipeline', $1)
   117  				RETURNING id
   118  			`, teamID).Scan(&newPipelineID)
   119  			Expect(err).ToNot(HaveOccurred())
   120  
   121  			plan := explain(fmt.Sprintf(
   122  				`SELECT * FROM pipeline_build_events_%d WHERE build_id = 1`,
   123  				newPipelineID,
   124  			))
   125  			Expect(plan).To(ContainSubstring("Index Scan"))
   126  
   127  			plan = explain(fmt.Sprintf(
   128  				`SELECT * FROM pipeline_build_events_%d WHERE build_id_old = 1`,
   129  				newPipelineID,
   130  			))
   131  			Expect(plan).To(ContainSubstring("Index Scan"))
   132  		})
   133  	})
   134  
   135  	Describe("Down", func() {
   136  		BeforeEach(func() {
   137  			postgresRunner.MigrateToVersion(downMigrationVersion)
   138  		})
   139  
   140  		It("has index for build_id", func() {
   141  			plan := explain(`SELECT * FROM build_events WHERE build_id = 1`)
   142  			Expect(plan).To(ContainSubstring("Index Scan"))
   143  			Expect(plan).ToNot(ContainSubstring("build_id_old"))
   144  		})
   145  
   146  		It("has index for build_id_old in pipeline partitions", func() {
   147  			plan := explain(fmt.Sprintf(
   148  				`SELECT * FROM pipeline_build_events_%d WHERE build_id_old = 1`,
   149  				pipelineID,
   150  			))
   151  			Expect(plan).To(ContainSubstring("Index Scan"))
   152  		})
   153  
   154  		It("does not have index for build_id in pipeline partitions", func() {
   155  			plan := explain(fmt.Sprintf(
   156  				`SELECT * FROM pipeline_build_events_%d WHERE build_id = 1`,
   157  				pipelineID,
   158  			))
   159  			Expect(plan).To(ContainSubstring("Seq Scan"))
   160  		})
   161  
   162  		It("does not have index for build_id in team partitions", func() {
   163  			plan := explain(fmt.Sprintf(
   164  				`SELECT * FROM team_build_events_%d WHERE build_id = 1`,
   165  				teamID,
   166  			))
   167  			Expect(plan).To(ContainSubstring("Seq Scan"))
   168  		})
   169  
   170  		It("does not have index for build_id in newly created team partitions", func() {
   171  			var newTeamID int
   172  			err := db.QueryRow(`
   173  				INSERT INTO teams (name, auth)
   174  				VALUES ('some-other-team', '{}')
   175  				RETURNING id
   176  			`).Scan(&newTeamID)
   177  			Expect(err).ToNot(HaveOccurred())
   178  
   179  			plan := explain(fmt.Sprintf(
   180  				`SELECT * FROM team_build_events_%d WHERE build_id = 1`,
   181  				newTeamID,
   182  			))
   183  			Expect(plan).To(ContainSubstring("Seq Scan"))
   184  		})
   185  
   186  		It("has index for build_id in newly created pipeline partitions", func() {
   187  			var newPipelineID int
   188  			err := db.QueryRow(`
   189  				INSERT INTO pipelines (name, team_id)
   190  				VALUES ('some-other-pipeline', $1)
   191  				RETURNING id
   192  			`, teamID).Scan(&newPipelineID)
   193  			Expect(err).ToNot(HaveOccurred())
   194  
   195  			plan := explain(fmt.Sprintf(
   196  				`SELECT * FROM pipeline_build_events_%d WHERE build_id = 1`,
   197  				newPipelineID,
   198  			))
   199  			Expect(plan).To(ContainSubstring("Index Scan"))
   200  		})
   201  	})
   202  })