Skip to content
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 CTE Materialized clause and Sql body in Function #2165

Open
wants to merge 13 commits into
base: main
Choose a base branch
from

Conversation

priyanshi-yb
Copy link
Contributor

@priyanshi-yb priyanshi-yb commented Jan 8, 2025

Describe the changes in this pull request

Reports the CTE statements with Materialized clause as not supported. https://yugabyte.atlassian.net/browse/DB-14227
Reports the presence of SQL body in Functions - PG15 docs
https://yugabyte.atlassian.net/browse/DB-14234

Describe if there are any user-facing changes

Added new feature SQL body in Function to report functions and Modifying the Materialized option with CTE in assessment.

How was this pull request tested?

unit tests and end-to-end-tests

Does your PR have changes that can cause upgrade issues?

Component Breaking changes?
MetaDB No
Name registry json No
Data File Descriptor Json No
Export Snapshot Status Json o
Import Data State No
Export Status Json No
Data .sql files of tables No
Export and import data queue No
Schema Dump No
AssessmentDB No
Sizing DB No
Migration Assessment Report Json No
Callhome Json No
YugabyteD Tables No
TargetDB Metadata Tables No

@priyanshi-yb priyanshi-yb force-pushed the priyanshi/cte-sql-body-fn branch from 047fb53 to fc1b227 Compare January 16, 2025 13:30
@priyanshi-yb priyanshi-yb marked this pull request as ready for review January 16, 2025 14:15
@@ -566,6 +566,19 @@ func NewForeignKeyReferencesPartitionedTableIssue(objectType string, objectName
return newQueryIssue(foreignKeyReferencesPartitionedTableIssue, objectType, objectName, SqlStatement, details)
}

var sqlBodyInFunctionIssue = issue.Issue{
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please define a Description for each issue moving forward.

Type: CTE_WITH_MATERIALIZED_CLAUSE,
Name: CTE_WITH_MATERIALIZED_CLAUSE_NAME,
Impact: constants.IMPACT_LEVEL_2,
Description: "",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

similarly here.

if err != nil {
return err
}
if cteNode.Ctematerialized != queryparser.CTE_MATERIALIZED_DEFAULT {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a comment here explaining that both MATERIALIZED, NOT MATERIALIZED flags were not supported..

}
var issues []QueryIssue

if function.HasSqlBody {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you use just BEGIN to start a function block?

yes BEGIN can also start a function block

If so, are both BEGIN and BEGIN ATOMIC unsupported?

No only BEGIN ATOMIC is unsupported as its PG 15 feature

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, but will function.HasSqlBody be true even if the function has just BEGIN ? That would be a problem, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, this HasSqlBody is true only if the parser has populated the sql_body field for function stmt, which is a new PG 15 feature for the BEGIN ATOMIC/RETURN expr type of function block. So, in normal BEGIN cases, this can't be true.

)
SELECT * FROM w AS w1 JOIN w AS w2 ON w1.key = w2.ref
WHERE w2.key = 123;`: `syntax error at or near "NOT"`,
`WITH moved_rows AS MATERIALIZED (
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add a sql for NOT MATERIALIZED as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes its there as first stmt

@@ -420,28 +412,44 @@ func ProtoAsSelectStmt(msg protoreflect.Message) (*pg_query.SelectStmt, error) {
return selectStmtNode, nil
}

func ProtoAsCTENode(msg protoreflect.Message) (*pg_query.CommonTableExpr, error) {
protoMsg, ok := msg.Interface().(proto.Message)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found out recently you don't need to do two steps.
You can convert it in one step directly.

msg.Interface().(*pg_query.xxx)

@@ -1070,7 +1070,7 @@ func fetchUnsupportedPGFeaturesFromSchemaReport(schemaAnalysisReport utils.Schem
unsupportedFeatures = append(unsupportedFeatures, getUnsupportedFeaturesFromSchemaAnalysisReport(queryissue.JSONB_SUBSCRIPTING_NAME, "", queryissue.JSONB_SUBSCRIPTING, schemaAnalysisReport, false, ""))
unsupportedFeatures = append(unsupportedFeatures, getUnsupportedFeaturesFromSchemaAnalysisReport(queryissue.FOREIGN_KEY_REFERENCES_PARTITIONED_TABLE_NAME, "", queryissue.FOREIGN_KEY_REFERENCES_PARTITIONED_TABLE, schemaAnalysisReport, false, ""))
unsupportedFeatures = append(unsupportedFeatures, getUnsupportedFeaturesFromSchemaAnalysisReport(queryissue.JSON_TYPE_PREDICATE_NAME, "", queryissue.JSON_TYPE_PREDICATE, schemaAnalysisReport, false, ""))

unsupportedFeatures = append(unsupportedFeatures, getUnsupportedFeaturesFromSchemaAnalysisReport(queryissue.SQL_BODY_IN_FUNCTION_NAME, "", queryissue.SQL_BODY_IN_FUNCTION, schemaAnalysisReport, false, ""))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about MATERIALIZED CTE issue? Can they not show up in DDLs?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah CTE can be in CREATE VIEW, adding it here as well

@@ -918,6 +918,9 @@ sqlParsingLoop:
} else if matches := dollarQuoteRegex.FindStringSubmatch(currLine); matches != nil {
dollarQuoteFlag = 1 //denotes start of the code/body part
codeBlockDelimiter = matches[0]
} else if strings.Contains(currLine, "BEGIN ATOMIC") {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also fixed in https://github.com/yugabyte/yb-voyager/pull/2201/files ?
Is that a prerequisite for this PR?

Copy link
Contributor Author

@priyanshi-yb priyanshi-yb Jan 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes otherwise analyze-schema/assessment won't be able to report the case as our parser will not work

@@ -1021,6 +1021,7 @@ func (mv *FunctionProcessor) Process(parseTree *pg_query.ParseResult) (DDLObject
SchemaName: funcSchemaName,
FuncName: funcName,
ReturnType: GetReturnTypeOfFunc(parseTree),
HasSqlBody: funcNode.CreateFunctionStmt.GetSqlBody() != nil,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what if funcNode.CreateFunctionStmt is nil? Is that possible here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, that is not possible if its function node, create function stmt can't be nil.

Comment on lines +30 to +31
node, isPlPgSQLObject := getCreateFuncStmtNode(parseTree)
return isPlPgSQLObject && (node.CreateFunctionStmt.SqlBody == nil) //TODO fix proper https://github.com/pganalyze/pg_query_go/issues/129
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how/where are we handling the case when node.CreateFunctionStmt.SqlBody != nil in a plpgsql object.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no need to handle this case because sqlBody is only possible in language sql, so language plpgsql can't have sql_body in parser.
docs- https://www.postgresql.org/docs/15/sql-createfunction.html#:~:text=The%20body%20of%20a%20LANGUAGE%20SQL%20function.%20This%20can%20either%20be%20a%20single%20statement

func IsPLPGSQLObject(parseTree *pg_query.ParseResult) bool {
// CREATE FUNCTION is same parser NODE for FUNCTION/PROCEDURE
_, isPlPgSQLObject := getCreateFuncStmtNode(parseTree)
return isPlPgSQLObject
node, isPlPgSQLObject := getCreateFuncStmtNode(parseTree)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

call it node, ok now because isPlPgSqlObject has logic depending on the node.

Copy link
Collaborator

@makalaaneesh makalaaneesh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with a nit. Let's wait for Sanyam's approval as well before merging.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants