-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Reporting the Advisory locks, XML Functions and System columns on the DDLs in the unsupported features in assess/analyze #2061
Changes from 3 commits
20e5089
c127704
8afaaea
0baf78c
c528346
0a11460
cc9018f
9e0c265
1d73003
43f1853
ae5ba19
cea6410
1cd099d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,6 +19,8 @@ import ( | |
"slices" | ||
"testing" | ||
|
||
"github.com/google/go-cmp/cmp" | ||
"github.com/samber/lo" | ||
"github.com/stretchr/testify/assert" | ||
|
||
"github.com/yugabyte/yb-voyager/yb-voyager/src/ybversion" | ||
|
@@ -154,6 +156,13 @@ CHECK (xpath_exists('/invoice/customer', data));` | |
stmt18 = `CREATE INDEX idx_invoices on invoices (xpath('/invoice/customer/text()', data));` | ||
) | ||
|
||
func modifyiedIssuesforPLPGSQL(issues []QueryIssue, objType string, objName string) []QueryIssue { | ||
return lo.Map(issues, func(i QueryIssue, _ int) QueryIssue { | ||
i.ObjectType = objType | ||
i.ObjectName = objName | ||
return i | ||
}) | ||
} | ||
func TestAllIssues(t *testing.T) { | ||
requiredDDLs := []string{stmt12} | ||
parserIssueDetector := NewParserIssueDetector() | ||
|
@@ -162,19 +171,19 @@ func TestAllIssues(t *testing.T) { | |
NewPercentTypeSyntaxIssue("FUNCTION", "list_high_earners", "public.emp1.salary%TYPE"), | ||
NewPercentTypeSyntaxIssue("FUNCTION", "list_high_earners", "employees.name%TYPE"), | ||
NewPercentTypeSyntaxIssue("FUNCTION", "list_high_earners", "employees.salary%TYPE"), | ||
NewClusterONIssue("FUNCTION", "list_high_earners", "ALTER TABLE employees CLUSTER ON idx;"), | ||
NewAdvisoryLocksIssue("FUNCTION", "list_high_earners", "SELECT pg_advisory_unlock(sender_id);"), | ||
NewAdvisoryLocksIssue("FUNCTION", "list_high_earners", "SELECT pg_advisory_unlock(receiver_id);"), | ||
NewXmlFunctionsIssue("FUNCTION", "list_high_earners", "SELECT id, xpath('/person/name/text()', data) AS name FROM test_xml_type;"), | ||
NewSystemColumnsIssue("FUNCTION", "list_high_earners", "SELECT * FROM employees e WHERE e.xmax = (SELECT MAX(xmax) FROM employees WHERE department = e.department);"), | ||
NewClusterONIssue("TABLE", "employees", "ALTER TABLE employees CLUSTER ON idx;"), | ||
NewAdvisoryLocksIssue("DML_QUERY", "", "SELECT pg_advisory_unlock(sender_id);"), | ||
NewAdvisoryLocksIssue("DML_QUERY", "", "SELECT pg_advisory_unlock(receiver_id);"), | ||
NewXmlFunctionsIssue("DML_QUERY", "", "SELECT id, xpath('/person/name/text()', data) AS name FROM test_xml_type;"), | ||
NewSystemColumnsIssue("DML_QUERY", "", "SELECT * FROM employees e WHERE e.xmax = (SELECT MAX(xmax) FROM employees WHERE department = e.department);"), | ||
}, | ||
stmt2: []QueryIssue{ | ||
NewPercentTypeSyntaxIssue("FUNCTION", "process_order", "orders.id%TYPE"), | ||
NewStorageParameterIssue("FUNCTION", "process_order", "ALTER TABLE ONLY public.example ADD CONSTRAINT example_email_key UNIQUE (email) WITH (fillfactor=70);"), | ||
NewUnloggedTableIssue("FUNCTION", "process_order", "CREATE UNLOGGED TABLE tbl_unlog (id int, val text);"), | ||
NewMultiColumnGinIndexIssue("FUNCTION", "process_order", "CREATE INDEX idx_example ON example_table USING gin(name, name1);"), | ||
NewUnsupportedIndexMethodIssue("FUNCTION", "process_order", "CREATE INDEX idx_example ON schema1.example_table USING gist(name);", "gist"), | ||
NewAdvisoryLocksIssue("FUNCTION", "process_order", "SELECT pg_advisory_unlock(orderid);"), | ||
NewStorageParameterIssue("TABLE", "public.example", "ALTER TABLE ONLY public.example ADD CONSTRAINT example_email_key UNIQUE (email) WITH (fillfactor=70);"), | ||
NewUnloggedTableIssue("TABLE", "tbl_unlog", "CREATE UNLOGGED TABLE tbl_unlog (id int, val text);"), | ||
NewMultiColumnGinIndexIssue("INDEX", "idx_example ON example_table", "CREATE INDEX idx_example ON example_table USING gin(name, name1);"), | ||
NewUnsupportedIndexMethodIssue("INDEX", "idx_example ON schema1.example_table", "CREATE INDEX idx_example ON schema1.example_table USING gist(name);", "gist"), | ||
NewAdvisoryLocksIssue("DML_QUERY", "", "SELECT pg_advisory_unlock(orderid);"), | ||
}, | ||
stmt3: []QueryIssue{ | ||
NewStorageParameterIssue("INDEX", "abc ON public.example", stmt3), | ||
|
@@ -210,6 +219,11 @@ func TestAllIssues(t *testing.T) { | |
}, | ||
} | ||
|
||
//Should modify it in similar way we do it actual code as the particular DDL issue in plpgsql can have different Details map on the basis of objectType | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm confused. What was wrong with the previous approach where you define issues directly with "FUNCTION", "list_high_earners" ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. example for this cluster on -
earlier I was using the New function for getting queryissue -
giving this QueryIssue, with details as empty as -
But the actual query issue will look like this where details will be populated based on TABLE object type-
In the code to detect these issues in PLPGSQL, we modify the issues later (in getAllPLPGSQLIssues()) to change the objectType and objectName to the actual object name and type of the PLPGSQL object. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Orthogonal point: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I agree. This was just a hack while refactoring. I already removed it in this PR with handling all cases for invalid count #2073 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oh nice, will check! |
||
stmtsWithExpectedIssues[stmt1] = modifyiedIssuesforPLPGSQL(stmtsWithExpectedIssues[stmt1], "FUNCTION", "list_high_earners") | ||
|
||
stmtsWithExpectedIssues[stmt2] = modifyiedIssuesforPLPGSQL(stmtsWithExpectedIssues[stmt2], "FUNCTION", "process_order") | ||
|
||
for _, stmt := range requiredDDLs { | ||
err := parserIssueDetector.ParseRequiredDDLs(stmt) | ||
assert.NoError(t, err, "Error parsing required ddl: %s", stmt) | ||
|
@@ -220,12 +234,8 @@ func TestAllIssues(t *testing.T) { | |
|
||
assert.Equal(t, len(expectedIssues), len(issues), "Mismatch in issue count for statement: %s", stmt) | ||
for _, expectedIssue := range expectedIssues { | ||
found := slices.ContainsFunc(issues, func(QueryIssue QueryIssue) bool { | ||
typeNameMatches := QueryIssue.TypeName == expectedIssue.TypeName | ||
queryMatches := QueryIssue.SqlStatement == expectedIssue.SqlStatement | ||
objectNameMatches := QueryIssue.ObjectName == expectedIssue.ObjectName | ||
objectTypeMatches := QueryIssue.ObjectType == expectedIssue.ObjectType | ||
return typeNameMatches && queryMatches && objectNameMatches && objectTypeMatches | ||
found := slices.ContainsFunc(issues, func(queryIssue QueryIssue) bool { | ||
return cmp.Equal(expectedIssue, queryIssue) | ||
}) | ||
assert.True(t, found, "Expected issue not found: %v in statement: %s", expectedIssue, stmt) | ||
} | ||
|
@@ -272,12 +282,8 @@ func TestDDLIssues(t *testing.T) { | |
|
||
assert.Equal(t, len(expectedIssues), len(issues), "Mismatch in issue count for statement: %s", stmt) | ||
for _, expectedIssue := range expectedIssues { | ||
found := slices.ContainsFunc(issues, func(QueryIssue QueryIssue) bool { | ||
typeNameMatches := QueryIssue.TypeName == expectedIssue.TypeName | ||
queryMatches := QueryIssue.SqlStatement == expectedIssue.SqlStatement | ||
objectNameMatches := QueryIssue.ObjectName == expectedIssue.ObjectName | ||
objectTypeMatches := QueryIssue.ObjectType == expectedIssue.ObjectType | ||
return typeNameMatches && queryMatches && objectNameMatches && objectTypeMatches | ||
found := slices.ContainsFunc(issues, func(queryIssue QueryIssue) bool { | ||
return cmp.Equal(expectedIssue, queryIssue) | ||
}) | ||
assert.True(t, found, "Expected issue not found: %v in statement: %s", expectedIssue, stmt) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment here explaining why we're making this call for DDLs. Give an example.