|  | package exporter | 
|  |  | 
|  | import ( | 
|  | "strings" | 
|  | "testing" | 
|  | "time" | 
|  |  | 
|  | "github.com/stretchr/testify/assert" | 
|  | ) | 
|  |  | 
|  | type spannerTables struct { | 
|  | TableOne []spTableOneRow | 
|  | TableTwo []spTableTwoRow | 
|  | } | 
|  |  | 
|  | type spTableOneRow struct { | 
|  | ColumnOne   string `sql:"column_one STRING PRIMARY KEY"` | 
|  | ColumnTwo   int    `sql:"column_two INT8 NOT NULL"` | 
|  | ColumnThree int    `sql:"column_three INT unique_rowid()"` | 
|  | // CreatedAt indicates the time at which this row was created. | 
|  | CreatedAt time.Time `sql:"createdat TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP"` | 
|  | } | 
|  |  | 
|  | type spTableTwoRow struct { | 
|  | CompositeKeyOne []byte `sql:"comp_one BYTES"` | 
|  | CompositeKeyTwo []byte `sql:"comp_two BYTES"` | 
|  | // CreatedAt indicates the time at which this row was created. | 
|  | CreatedAt time.Time `sql:"createdat TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP"` | 
|  | // This is a test comment | 
|  | primaryKey struct{} `sql:"PRIMARY KEY (comp_one, comp_two)"` | 
|  | // We have this index for good reasons. Spaces are intentional to make sure they are trimmed | 
|  | indexForSearch struct{} `sql:"   INDEX comp_two_desc_idx (comp_two DESC)   "` | 
|  | // We have this index for even better reasons. | 
|  | otherIndex struct{} `sql:"INDEX comp_two_asc_idx (comp_two ASC)"` | 
|  | } | 
|  |  | 
|  | func TestSpanner_GenerateSQL_WellFormedInput_CorrectOutput(t *testing.T) { | 
|  |  | 
|  | gen := GenerateSQL(spannerTables{}, "test_package_one", SchemaOnly, Spanner, &SpannerConverter{SkipCreatedAt: true}) | 
|  | // We cannot have backticks in the multistring literal, so we substitute $$ for them. | 
|  | expectedOutput := strings.ReplaceAll(`package test_package_one | 
|  |  | 
|  | // Generated by //go/sql/exporter/ | 
|  | // DO NOT EDIT | 
|  |  | 
|  | const Schema = $$CREATE SEQUENCE IF NOT EXISTS TableOne_seq bit_reversed_positive; | 
|  | CREATE TABLE IF NOT EXISTS TableOne ( | 
|  | column_one TEXT PRIMARY KEY, | 
|  | column_two INT8 NOT NULL, | 
|  | column_three INT nextval('TableOne_seq'), | 
|  | createdat TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP | 
|  | ) TTL INTERVAL '1095 days' ON createdat; | 
|  | CREATE TABLE IF NOT EXISTS TableTwo ( | 
|  | comp_one BYTEA, | 
|  | comp_two BYTEA, | 
|  | createdat TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP, | 
|  | PRIMARY KEY (comp_one, comp_two) | 
|  | ) TTL INTERVAL '1095 days' ON createdat; | 
|  | CREATE INDEX IF NOT EXISTS comp_two_desc_idx on TableTwo (comp_two DESC); | 
|  | CREATE INDEX IF NOT EXISTS comp_two_asc_idx on TableTwo (comp_two ASC); | 
|  | $$ | 
|  | `, "$$", "`") | 
|  |  | 
|  | assert.Equal(t, expectedOutput, gen) | 
|  | } | 
|  |  | 
|  | func TestSpanner_GenerateSQL_WellFormedInput_CorrectOutputIncludingColumnNames(t *testing.T) { | 
|  | spannerConverter := DefaultSpannerConverter() | 
|  | spannerConverter.SkipCreatedAt = true | 
|  |  | 
|  | gen := GenerateSQL(spannerTables{}, "test_package_one", SchemaAndColumnNames, Spanner, spannerConverter) | 
|  | // We cannot have backticks in the multistring literal, so we substitute $$ for them. | 
|  | expectedOutput := strings.ReplaceAll(`package test_package_one | 
|  |  | 
|  | // Generated by //go/sql/exporter/ | 
|  | // DO NOT EDIT | 
|  |  | 
|  | const Schema = $$CREATE SEQUENCE IF NOT EXISTS TableOne_seq bit_reversed_positive; | 
|  | CREATE TABLE IF NOT EXISTS TableOne ( | 
|  | column_one TEXT PRIMARY KEY, | 
|  | column_two INT8 NOT NULL, | 
|  | column_three INT nextval('TableOne_seq'), | 
|  | createdat TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP | 
|  | ) TTL INTERVAL '1095 days' ON createdat; | 
|  | CREATE TABLE IF NOT EXISTS TableTwo ( | 
|  | comp_one BYTEA, | 
|  | comp_two BYTEA, | 
|  | createdat TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP, | 
|  | PRIMARY KEY (comp_one, comp_two) | 
|  | ) TTL INTERVAL '1095 days' ON createdat; | 
|  | CREATE INDEX IF NOT EXISTS comp_two_desc_idx on TableTwo (comp_two DESC); | 
|  | CREATE INDEX IF NOT EXISTS comp_two_asc_idx on TableTwo (comp_two ASC); | 
|  | $$ | 
|  |  | 
|  | var TableOne = []string{ | 
|  | "column_one", | 
|  | "column_two", | 
|  | "column_three", | 
|  | "createdat", | 
|  | } | 
|  |  | 
|  | var TableTwo = []string{ | 
|  | "comp_one", | 
|  | "comp_two", | 
|  | "createdat", | 
|  | } | 
|  | `, "$$", "`") | 
|  |  | 
|  | assert.Equal(t, expectedOutput, gen) | 
|  | } | 
|  |  | 
|  | func TestSpanner_GenerateSQL_WellFormedInput_TTLExclude(t *testing.T) { | 
|  | // This table should not have a "TTL INTERVAL" specified. | 
|  | excludeTTLTable := []string{"TableOne"} | 
|  | spannerConverter := DefaultSpannerConverter() | 
|  | spannerConverter.TtlExcludeTables = excludeTTLTable | 
|  | spannerConverter.SkipCreatedAt = true | 
|  | gen := GenerateSQL(spannerTables{}, "test_package_one", SchemaOnly, Spanner, spannerConverter) | 
|  | // We cannot have backticks in the multistring literal, so we substitute $$ for them. | 
|  | expectedOutput := strings.ReplaceAll(`package test_package_one | 
|  |  | 
|  | // Generated by //go/sql/exporter/ | 
|  | // DO NOT EDIT | 
|  |  | 
|  | const Schema = $$CREATE SEQUENCE IF NOT EXISTS TableOne_seq bit_reversed_positive; | 
|  | CREATE TABLE IF NOT EXISTS TableOne ( | 
|  | column_one TEXT PRIMARY KEY, | 
|  | column_two INT8 NOT NULL, | 
|  | column_three INT nextval('TableOne_seq'), | 
|  | createdat TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP | 
|  | ); | 
|  | CREATE TABLE IF NOT EXISTS TableTwo ( | 
|  | comp_one BYTEA, | 
|  | comp_two BYTEA, | 
|  | createdat TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP, | 
|  | PRIMARY KEY (comp_one, comp_two) | 
|  | ) TTL INTERVAL '1095 days' ON createdat; | 
|  | CREATE INDEX IF NOT EXISTS comp_two_desc_idx on TableTwo (comp_two DESC); | 
|  | CREATE INDEX IF NOT EXISTS comp_two_asc_idx on TableTwo (comp_two ASC); | 
|  | $$ | 
|  | `, "$$", "`") | 
|  |  | 
|  | assert.Equal(t, expectedOutput, gen) | 
|  | } | 
|  |  | 
|  | type spannerMalformedTable struct { | 
|  | TableOne []tableOneRow | 
|  | TableTwo tableTwoRow | 
|  | } | 
|  |  | 
|  | func TestSpanner_GenerateSQL_NonSliceField_Panics(t *testing.T) { | 
|  |  | 
|  | assert.Panics(t, func() { | 
|  | GenerateSQL(spannerMalformedTable{}, "test_package_one", SchemaOnly, Spanner, nil) | 
|  | }) | 
|  | } | 
|  |  | 
|  | type spannerMissingSQLStructs struct { | 
|  | TableOne []tableOneRow | 
|  | TableTwo []malformedTable | 
|  | } | 
|  |  | 
|  | func TestSpanner_GenerateSQL_MissingSQLStructTag_Panics(t *testing.T) { | 
|  |  | 
|  | assert.Panics(t, func() { | 
|  | GenerateSQL(spannerMissingSQLStructs{}, "test_package_one", SchemaOnly, Spanner, nil) | 
|  | }) | 
|  | } |