Skip to content

Commit

Permalink
Improve statistics backup queries
Browse files Browse the repository at this point in the history
  • Loading branch information
whitehawk committed Aug 7, 2024
1 parent 42043d0 commit 2ddf265
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 24 deletions.
8 changes: 4 additions & 4 deletions backup/statistics.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,16 +69,16 @@ func GenerateAttributeStatisticsQueries(table Table, attStat AttributeStatistic)
attributeSlotsQueryStr = generateAttributeSlotsQuery4(attStat)
}

attributeQueries = append(attributeQueries, fmt.Sprintf(`DELETE FROM pg_statistic
WHERE starelid = %s AND staattnum = (SELECT attnum FROM pg_attribute WHERE attrelid = %s AND attname = '%s');`, starelidStr, starelidStr, utils.EscapeSingleQuotes(attStat.AttName)))
attributeQueries = append(attributeQueries, fmt.Sprintf(`WITH attr_info AS (SELECT attrelid, attnum FROM pg_attribute WHERE attrelid = %s AND attname = '%s')
DELETE FROM pg_statistic WHERE starelid = (SELECT attrelid from attr_info) AND staattnum = (SELECT attnum from attr_info);`, starelidStr, utils.EscapeSingleQuotes(attStat.AttName)))
attributeQueries = append(attributeQueries, fmt.Sprintf(`INSERT INTO pg_statistic SELECT
%s,
attrelid,
attnum,%s
%f::real,
%d::integer,
%f::real,
%s
FROM pg_attribute WHERE attrelid = %s AND attname = '%s';`, starelidStr, inheritStr, attStat.NullFraction, attStat.Width, attStat.Distinct, attributeSlotsQueryStr, starelidStr, utils.EscapeSingleQuotes(attStat.AttName)))
FROM pg_attribute WHERE attrelid = %s AND attname = '%s';`, inheritStr, attStat.NullFraction, attStat.Width, attStat.Distinct, attributeSlotsQueryStr, starelidStr, utils.EscapeSingleQuotes(attStat.AttName)))

/*
* If a type name starts with exactly one underscore, it describes an array
Expand Down
26 changes: 12 additions & 14 deletions backup/statistics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,10 @@ SET
reltuples = 0.000000::real
WHERE oid = 'testschema.testtable2'::regclass::oid;`,

`DELETE FROM pg_statistic
WHERE starelid = 'testschema.testtable2'::regclass::oid AND staattnum = (SELECT attnum FROM pg_attribute WHERE attrelid = 'testschema.testtable2'::regclass::oid AND attname = 'testattWithArray');`,

`WITH attr_info AS (SELECT attrelid, attnum FROM pg_attribute WHERE attrelid = 'testschema.testtable2'::regclass::oid AND attname = 'testattWithArray')
DELETE FROM pg_statistic WHERE starelid = (SELECT attrelid from attr_info) AND staattnum = (SELECT attnum from attr_info);`,
fmt.Sprintf(`INSERT INTO pg_statistic SELECT
'testschema.testtable2'::regclass::oid,
attrelid,
attnum,%[1]s
0.000000::real,
0::integer,
Expand All @@ -127,11 +126,10 @@ WHERE starelid = 'testschema.testtable2'::regclass::oid AND staattnum = (SELECT
NULL
FROM pg_attribute WHERE attrelid = 'testschema.testtable2'::regclass::oid AND attname = 'testattWithArray';`, insertReplace1, insertReplace2, insertReplace3, insertReplace4, insertReplace5),

`DELETE FROM pg_statistic
WHERE starelid = 'testschema.testtable2'::regclass::oid AND staattnum = (SELECT attnum FROM pg_attribute WHERE attrelid = 'testschema.testtable2'::regclass::oid AND attname = 'testatt');`,

`WITH attr_info AS (SELECT attrelid, attnum FROM pg_attribute WHERE attrelid = 'testschema.testtable2'::regclass::oid AND attname = 'testatt')
DELETE FROM pg_statistic WHERE starelid = (SELECT attrelid from attr_info) AND staattnum = (SELECT attnum from attr_info);`,
fmt.Sprintf(`INSERT INTO pg_statistic SELECT
'testschema.testtable2'::regclass::oid,
attrelid,
attnum,%[1]s
0.400000::real,
10::integer,
Expand Down Expand Up @@ -183,12 +181,12 @@ WHERE oid = '"""test''schema"""."""test''table"""'::regclass::oid;`))
}

attStatsQueries := backup.GenerateAttributeStatisticsQueries(tableTestTable, attStats)
Expect(attStatsQueries[0]).To(Equal(fmt.Sprintf(`DELETE FROM pg_statistic
WHERE starelid = 'testschema."test''table"'::regclass::oid AND staattnum = (SELECT attnum FROM pg_attribute WHERE attrelid = 'testschema."test''table"'::regclass::oid AND attname = 'testatt');`)))
Expect(attStatsQueries[0]).To(Equal(fmt.Sprintf(`WITH attr_info AS (SELECT attrelid, attnum FROM pg_attribute WHERE attrelid = 'testschema."test''table"'::regclass::oid AND attname = 'testatt')
DELETE FROM pg_statistic WHERE starelid = (SELECT attrelid from attr_info) AND staattnum = (SELECT attnum from attr_info);`)))

insertReplace1, insertReplace2, insertReplace3, insertReplace4, insertReplace5 := getStatInsertReplace(0, 0)
Expect(attStatsQueries[1]).To(Equal(fmt.Sprintf(`INSERT INTO pg_statistic SELECT
'testschema."test''table"'::regclass::oid,
attrelid,
attnum,%s
0.400000::real,
10::integer,
Expand Down Expand Up @@ -222,12 +220,12 @@ FROM pg_attribute WHERE attrelid = 'testschema."test''table"'::regclass::oid AND

attStatsQueries := backup.GenerateAttributeStatisticsQueries(tableTestTable, attStats)

Expect(attStatsQueries[0]).To(Equal(fmt.Sprintf(`DELETE FROM pg_statistic
WHERE starelid = 'testschema."test''table"'::regclass::oid AND staattnum = (SELECT attnum FROM pg_attribute WHERE attrelid = 'testschema."test''table"'::regclass::oid AND attname = 'testatt');`)))
Expect(attStatsQueries[0]).To(Equal(fmt.Sprintf(`WITH attr_info AS (SELECT attrelid, attnum FROM pg_attribute WHERE attrelid = 'testschema."test''table"'::regclass::oid AND attname = 'testatt')
DELETE FROM pg_statistic WHERE starelid = (SELECT attrelid from attr_info) AND staattnum = (SELECT attnum from attr_info);`)))

insertReplace1, insertReplace2, insertReplace3, insertReplace4, insertReplace5 := getStatInsertReplace(10, 12)
Expect(attStatsQueries[1]).To(Equal(fmt.Sprintf(`INSERT INTO pg_statistic SELECT
'testschema."test''table"'::regclass::oid,
attrelid,
attnum,%s
0.400000::real,
10::integer,
Expand Down
10 changes: 4 additions & 6 deletions restore/restore.go
Original file line number Diff line number Diff line change
Expand Up @@ -410,15 +410,14 @@ func editStatementsRedirectSchema(statements []toc.StatementWithType, redirectSc
return
}

schemaMatch := `(?:".+?"|[^."']+?)` // matches either an unquoted schema with no dots and no quotes or a quoted schema
schemaMatch := `(?:".+?"|[^.]+?)` // matches either an unquoted schema with no dots or a quoted schema containing dots
// This expression matches a GRANT or REVOKE statement on any object and captures the old schema name
permissionsRE := regexp.MustCompile(fmt.Sprintf(`(?m)(^(?:REVOKE|GRANT) .+ ON .+?) (%s)((\..+)? (?:FROM|TO) .+)`, schemaMatch))
// This expression matches an ATTACH PARTITION statement and captures both the parent and child schema names
attachRE := regexp.MustCompile(fmt.Sprintf(`(ALTER TABLE(?: ONLY)?) (%[1]s)(\..+ ATTACH PARTITION) (%[1]s)(\..+)`, schemaMatch))
// This expression matches a '<schema>.<table>'::regclass::oid expression
regclassOidRE := regexp.MustCompile(fmt.Sprintf(`'(%s)((\.[^']+)'\:\:regclass\:\:oid)`, schemaMatch))
// These expressions match the first and the last occurences of the '<schema>.<table>'::regclass::oid expression
firstRegclassOidRE := regexp.MustCompile(fmt.Sprintf(`(?s)^(.*?)(%s)(.*)$`, regclassOidRE))
// These expression matches the last occurence of the '<schema>.<table>'::regclass::oid expression
lastRegclassOidRE := regexp.MustCompile(fmt.Sprintf(`(?s)^(.*)(%s)(.*?)$`, regclassOidRE))
for i := range statements {
oldSchema := fmt.Sprintf("%s.", statements[i].Schema)
Expand All @@ -445,10 +444,9 @@ func editStatementsRedirectSchema(statements []toc.StatementWithType, redirectSc
replaced = true
}

// Statistic statements need two schema replacements. We replace the first and the last occurences,
// to avoid a very small chance that schema name was in the statistic data itself, that we do not want to alter.
// Statistic statements needs one schema replacements. We replace the last occurence to avoid a very small
// chance that schema name was in the statistic data itself, that we do not want to alter.
if strings.Contains(statement, "pg_statistic") {
statement = firstRegclassOidRE.ReplaceAllString(statement, fmt.Sprintf("${1}'%s${4}$6", redirectSchema))
statement = lastRegclassOidRE.ReplaceAllString(statement, fmt.Sprintf("${1}'%s${4}$6", redirectSchema))
replaced = true
}
Expand Down

0 comments on commit 2ddf265

Please sign in to comment.