mirror of
https://github.com/temporalio/temporal.git
synced 2026-08-30 18:41:49 -07:00
Accept WorkflowType in S3 visibility queries (#11383)
## What changed - Allow the S3 visibility archiver query parser to accept `WorkflowType`. - Keep `WorkflowTypeName` as a deprecated compatibility alias. - Rename the parsed query field to `workflowType` and update S3 visibility archiver tests. - Fix the S3 parser StartTime test assertion and StartTime operator error message. ## Why - S3 visibility archiver queries only accepted `WorkflowTypeName`, while filestore, gcloud, and non-archived visibility records use `WorkflowType`. This keeps old queries working while accepting the standard field name. - Fix https://github.com/temporalio/temporal/issues/7821
This commit is contained in:
@@ -37,12 +37,13 @@ The syntax for the query is based on SQL
|
||||
|
||||
Supported column names are
|
||||
- WorkflowId *String*
|
||||
- WorkflowTypeName *String*
|
||||
- WorkflowType *String*
|
||||
- WorkflowTypeName *String (legacy alias)*
|
||||
- StartTime *Date*
|
||||
- CloseTime *Date*
|
||||
- SearchPrecision *String - Day, Hour, Minute, Second*
|
||||
|
||||
WorkflowId or WorkflowTypeName is required. If filtering on date use StartTime or CloseTime in combination with SearchPrecision.
|
||||
WorkflowId or WorkflowType is required. WorkflowTypeName is still accepted as a legacy alias. If filtering on date use StartTime or CloseTime in combination with SearchPrecision.
|
||||
|
||||
Searching for a record will be done in times in the UTC timezone
|
||||
|
||||
|
||||
@@ -20,17 +20,19 @@ type (
|
||||
queryParser struct{}
|
||||
|
||||
parsedQuery struct {
|
||||
workflowTypeName *string
|
||||
workflowID *string
|
||||
startTime *time.Time
|
||||
closeTime *time.Time
|
||||
searchPrecision *string
|
||||
workflowType *string
|
||||
workflowID *string
|
||||
startTime *time.Time
|
||||
closeTime *time.Time
|
||||
searchPrecision *string
|
||||
}
|
||||
)
|
||||
|
||||
// All allowed fields for filtering
|
||||
const (
|
||||
// Deprecated: use WorkflowType instead. This filter name is kept for backward compatibility.
|
||||
WorkflowTypeName = "WorkflowTypeName"
|
||||
WorkflowType = "WorkflowType"
|
||||
WorkflowID = "WorkflowId"
|
||||
StartTime = "StartTime"
|
||||
CloseTime = "CloseTime"
|
||||
@@ -60,11 +62,11 @@ func (p *queryParser) Parse(query string) (*parsedQuery, error) {
|
||||
if err := p.convertWhereExpr(whereExpr, parsedQuery); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if parsedQuery.workflowID == nil && parsedQuery.workflowTypeName == nil {
|
||||
return nil, errors.New("WorkflowId or WorkflowTypeName is required in query")
|
||||
if parsedQuery.workflowID == nil && parsedQuery.workflowType == nil {
|
||||
return nil, errors.New("WorkflowId or WorkflowType is required in query")
|
||||
}
|
||||
if parsedQuery.workflowID != nil && parsedQuery.workflowTypeName != nil {
|
||||
return nil, errors.New("only one of WorkflowId or WorkflowTypeName can be specified in a query")
|
||||
if parsedQuery.workflowID != nil && parsedQuery.workflowType != nil {
|
||||
return nil, errors.New("only one of WorkflowId or WorkflowType can be specified in a query")
|
||||
}
|
||||
if parsedQuery.closeTime != nil && parsedQuery.startTime != nil {
|
||||
return nil, errors.New("only one of StartTime or CloseTime can be specified in a query")
|
||||
@@ -121,18 +123,18 @@ func (p *queryParser) convertComparisonExpr(compExpr *sqlparser.ComparisonExpr,
|
||||
valStr := sqlparser.String(valExpr)
|
||||
|
||||
switch colNameStr {
|
||||
case WorkflowTypeName:
|
||||
case WorkflowTypeName, WorkflowType:
|
||||
val, err := sqlquery.ExtractStringValue(valStr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if op != "=" {
|
||||
return fmt.Errorf("only operation = is support for %s", WorkflowTypeName)
|
||||
return fmt.Errorf("only operation = is support for %s", colNameStr)
|
||||
}
|
||||
if parsedQuery.workflowTypeName != nil {
|
||||
return fmt.Errorf("can not query %s multiple times", WorkflowTypeName)
|
||||
if parsedQuery.workflowType != nil {
|
||||
return fmt.Errorf("can not query %s multiple times", colNameStr)
|
||||
}
|
||||
parsedQuery.workflowTypeName = new(val)
|
||||
parsedQuery.workflowType = new(val)
|
||||
case WorkflowID:
|
||||
val, err := sqlquery.ExtractStringValue(valStr)
|
||||
if err != nil {
|
||||
@@ -160,7 +162,7 @@ func (p *queryParser) convertComparisonExpr(compExpr *sqlparser.ComparisonExpr,
|
||||
return err
|
||||
}
|
||||
if op != "=" {
|
||||
return fmt.Errorf("only operation = is support for %s", CloseTime)
|
||||
return fmt.Errorf("only operation = is support for %s", StartTime)
|
||||
}
|
||||
parsedQuery.startTime = ×tamp
|
||||
case SearchPrecision:
|
||||
|
||||
@@ -41,13 +41,28 @@ func (s *queryParserSuite) TestParseWorkflowIDAndWorkflowTypeName() {
|
||||
query: "WorkflowTypeName = \"random workflowTypeName\"",
|
||||
expectErr: false,
|
||||
parsedQuery: &parsedQuery{
|
||||
workflowTypeName: new("random workflowTypeName"),
|
||||
workflowType: new("random workflowTypeName"),
|
||||
},
|
||||
},
|
||||
{
|
||||
query: "WorkflowType = \"random workflowType\"",
|
||||
expectErr: false,
|
||||
parsedQuery: &parsedQuery{
|
||||
workflowType: new("random workflowType"),
|
||||
},
|
||||
},
|
||||
{
|
||||
query: "WorkflowId = \"random workflowID\" and WorkflowTypeName = \"random workflowTypeName\"",
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
query: "WorkflowId = \"random workflowID\" and WorkflowType = \"random workflowTypeName\"",
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
query: "WorkflowTypeName = \"random workflowTypeName\" and WorkflowType = \"random workflowTypeName\"",
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
query: "WorkflowId = \"random workflowID\" and WorkflowId = \"random workflowID\"",
|
||||
expectErr: true,
|
||||
@@ -100,7 +115,7 @@ func (s *queryParserSuite) TestParseWorkflowIDAndWorkflowTypeName() {
|
||||
}
|
||||
s.NoError(err)
|
||||
s.Equal(tc.parsedQuery.workflowID, parsedQuery.workflowID)
|
||||
s.Equal(tc.parsedQuery.workflowTypeName, parsedQuery.workflowTypeName)
|
||||
s.Equal(tc.parsedQuery.workflowType, parsedQuery.workflowType)
|
||||
|
||||
}
|
||||
}
|
||||
@@ -217,7 +232,7 @@ func (s *queryParserSuite) TestParseStartTime() {
|
||||
query: commonQueryPart + "StartTime = 1000",
|
||||
expectErr: false,
|
||||
parsedQuery: &parsedQuery{
|
||||
startTime: new(time.Unix(0, 1000)),
|
||||
startTime: new(time.Unix(0, 1000).UTC()),
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -244,6 +259,6 @@ func (s *queryParserSuite) TestParseStartTime() {
|
||||
continue
|
||||
}
|
||||
s.NoError(err)
|
||||
s.Equal(tc.parsedQuery.closeTime, parsedQuery.closeTime)
|
||||
s.Equal(tc.parsedQuery.startTime, parsedQuery.startTime)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,7 +259,7 @@ func (v *visibilityArchiver) query(
|
||||
saTypeMap searchattribute.NameTypeMap,
|
||||
) (*archiver.QueryVisibilityResponse, error) {
|
||||
primaryIndex := primaryIndexKeyWorkflowTypeName
|
||||
primaryIndexValue := request.parsedQuery.workflowTypeName
|
||||
primaryIndexValue := request.parsedQuery.workflowType
|
||||
if request.parsedQuery.workflowID != nil {
|
||||
primaryIndex = primaryIndexKeyWorkflowID
|
||||
primaryIndexValue = request.parsedQuery.workflowID
|
||||
|
||||
@@ -533,9 +533,9 @@ func (s *visibilityArchiverSuite) TestArchiveAndQueryPrecisions() {
|
||||
|
||||
mockParser = NewMockQueryParser(s.controller)
|
||||
mockParser.EXPECT().Parse(gomock.Any()).Return(&parsedQuery{
|
||||
closeTime: new(time.Date(2000, 1, testData.day, testData.hour, testData.minute, testData.second, 0, time.UTC)),
|
||||
searchPrecision: new(testData.precision),
|
||||
workflowTypeName: new(testWorkflowTypeName),
|
||||
closeTime: new(time.Date(2000, 1, testData.day, testData.hour, testData.minute, testData.second, 0, time.UTC)),
|
||||
searchPrecision: new(testData.precision),
|
||||
workflowType: new(testWorkflowTypeName),
|
||||
}, nil).AnyTimes()
|
||||
visibilityArchiver.queryParser = mockParser
|
||||
|
||||
@@ -546,9 +546,9 @@ func (s *visibilityArchiverSuite) TestArchiveAndQueryPrecisions() {
|
||||
|
||||
mockParser = NewMockQueryParser(s.controller)
|
||||
mockParser.EXPECT().Parse(gomock.Any()).Return(&parsedQuery{
|
||||
startTime: new(time.Date(2000, 1, testData.day, testData.hour, testData.minute, testData.second, 0, time.UTC)),
|
||||
searchPrecision: new(testData.precision),
|
||||
workflowTypeName: new(testWorkflowTypeName),
|
||||
startTime: new(time.Date(2000, 1, testData.day, testData.hour, testData.minute, testData.second, 0, time.UTC)),
|
||||
searchPrecision: new(testData.precision),
|
||||
workflowType: new(testWorkflowTypeName),
|
||||
}, nil).AnyTimes()
|
||||
visibilityArchiver.queryParser = mockParser
|
||||
|
||||
@@ -601,7 +601,7 @@ func (s *visibilityArchiverSuite) TestArchiveAndQuery() {
|
||||
|
||||
mockParser = NewMockQueryParser(s.controller)
|
||||
mockParser.EXPECT().Parse(gomock.Any()).Return(&parsedQuery{
|
||||
workflowTypeName: new(testWorkflowTypeName),
|
||||
workflowType: new(testWorkflowTypeName),
|
||||
}, nil).AnyTimes()
|
||||
visibilityArchiver.queryParser = mockParser
|
||||
request = &archiver.QueryVisibilityRequest{
|
||||
|
||||
Reference in New Issue
Block a user