Support Spanner's UNION syntax, which needs to be UNION DISTINCT or UNION ALL. (#101768)
* Support Spanner's UNION syntax, which needs to be UNION DISTINCT or UNION ALL.
This commit is contained in:
@@ -32,6 +32,8 @@ type Dialect interface {
|
||||
BooleanStr(bool) string
|
||||
DateTimeFunc(string) string
|
||||
BatchSize() int
|
||||
UnionDistinct() string // this is the default UNION type
|
||||
UnionAll() string
|
||||
|
||||
OrderBy(order string) string
|
||||
|
||||
@@ -467,3 +469,11 @@ func (b *BaseDialect) Update(ctx context.Context, tx *session.SessionTx, tableNa
|
||||
func (b *BaseDialect) Concat(strs ...string) string {
|
||||
return fmt.Sprintf("CONCAT(%s)", strings.Join(strs, ", "))
|
||||
}
|
||||
|
||||
func (b *BaseDialect) UnionDistinct() string {
|
||||
return "UNION"
|
||||
}
|
||||
|
||||
func (b *BaseDialect) UnionAll() string {
|
||||
return "UNION ALL"
|
||||
}
|
||||
|
||||
@@ -325,3 +325,7 @@ func confToClientOptions(connectorConfig spannerdriver.ConnectorConfig) []option
|
||||
}
|
||||
return opts
|
||||
}
|
||||
|
||||
func (s *SpannerDialect) UnionDistinct() string {
|
||||
return "UNION DISTINCT"
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
"github.com/grafana/grafana/pkg/services/login"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/searchstore"
|
||||
)
|
||||
|
||||
@@ -44,14 +45,14 @@ type PermissionsFilter interface {
|
||||
With() (string, []any)
|
||||
Where() (string, []any)
|
||||
|
||||
buildClauses()
|
||||
buildClauses(dialect migrator.Dialect)
|
||||
nestedFoldersSelectors(permSelector string, permSelectorArgs []any, leftTable string, Col string, rightTableCol string, orgID int64) (string, []any)
|
||||
}
|
||||
|
||||
// NewAccessControlDashboardPermissionFilter creates a new AccessControlDashboardPermissionFilter that is configured with specific actions calculated based on the dashboardaccess.PermissionType and query type
|
||||
// The filter is configured to use the new permissions filter (without subqueries) if the feature flag is enabled
|
||||
// The filter is configured to use the old permissions filter (with subqueries) if the feature flag is disabled
|
||||
func NewAccessControlDashboardPermissionFilter(user identity.Requester, permissionLevel dashboardaccess.PermissionType, queryType string, features featuremgmt.FeatureToggles, recursiveQueriesAreSupported bool) PermissionsFilter {
|
||||
func NewAccessControlDashboardPermissionFilter(user identity.Requester, permissionLevel dashboardaccess.PermissionType, queryType string, features featuremgmt.FeatureToggles, recursiveQueriesAreSupported bool, dialect migrator.Dialect) PermissionsFilter {
|
||||
needEdit := permissionLevel > dashboardaccess.PERMISSION_VIEW
|
||||
|
||||
var folderAction string
|
||||
@@ -129,7 +130,7 @@ func NewAccessControlDashboardPermissionFilter(user identity.Requester, permissi
|
||||
features: features, recursiveQueriesAreSupported: recursiveQueriesAreSupported,
|
||||
}
|
||||
}
|
||||
f.buildClauses()
|
||||
f.buildClauses(dialect)
|
||||
return f
|
||||
}
|
||||
|
||||
@@ -157,7 +158,7 @@ func (f *accessControlDashboardPermissionFilter) hasRequiredActions() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (f *accessControlDashboardPermissionFilter) buildClauses() {
|
||||
func (f *accessControlDashboardPermissionFilter) buildClauses(dialect migrator.Dialect) {
|
||||
if f.user == nil || f.user.IsNil() || !f.hasRequiredActions() {
|
||||
f.where = clause{string: "(1 = 0)"}
|
||||
return
|
||||
@@ -171,7 +172,7 @@ func (f *accessControlDashboardPermissionFilter) buildClauses() {
|
||||
}
|
||||
|
||||
orgID := f.user.GetOrgID()
|
||||
filter, params := accesscontrol.UserRolesFilter(orgID, userID, f.user.GetTeams(), accesscontrol.GetOrgRoles(f.user))
|
||||
filter, params := accesscontrol.UserRolesFilter(orgID, userID, f.user.GetTeams(), accesscontrol.GetOrgRoles(f.user), dialect)
|
||||
rolesFilter := " AND role_id IN(SELECT id FROM role " + filter + ") "
|
||||
var args []any
|
||||
builder := strings.Builder{}
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
"github.com/grafana/grafana/pkg/services/login"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
|
||||
)
|
||||
|
||||
type accessControlDashboardPermissionFilterNoFolderSubquery struct {
|
||||
@@ -25,7 +26,7 @@ func (f *accessControlDashboardPermissionFilterNoFolderSubquery) LeftJoin() stri
|
||||
return " dashboard AS folder ON dashboard.org_id = folder.org_id AND dashboard.folder_id = folder.id"
|
||||
}
|
||||
|
||||
func (f *accessControlDashboardPermissionFilterNoFolderSubquery) buildClauses() {
|
||||
func (f *accessControlDashboardPermissionFilterNoFolderSubquery) buildClauses(dialect migrator.Dialect) {
|
||||
if f.user == nil || f.user.IsNil() || len(f.user.GetPermissions()) == 0 {
|
||||
f.where = clause{string: "(1 = 0)"}
|
||||
return
|
||||
@@ -39,7 +40,7 @@ func (f *accessControlDashboardPermissionFilterNoFolderSubquery) buildClauses()
|
||||
}
|
||||
|
||||
orgID := f.user.GetOrgID()
|
||||
filter, params := accesscontrol.UserRolesFilter(orgID, userID, f.user.GetTeams(), accesscontrol.GetOrgRoles(f.user))
|
||||
filter, params := accesscontrol.UserRolesFilter(orgID, userID, f.user.GetTeams(), accesscontrol.GetOrgRoles(f.user), dialect)
|
||||
rolesFilter := " AND role_id IN(SELECT id FROM role " + filter + ") "
|
||||
var args []any
|
||||
builder := strings.Builder{}
|
||||
|
||||
@@ -183,7 +183,7 @@ func TestIntegration_DashboardPermissionFilter(t *testing.T) {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
t.Run(tt.desc+" with features "+strings.Join(keys, ","), func(t *testing.T) {
|
||||
filter := permissions.NewAccessControlDashboardPermissionFilter(usr, tt.permission, tt.queryType, features, recursiveQueriesAreSupported)
|
||||
filter := permissions.NewAccessControlDashboardPermissionFilter(usr, tt.permission, tt.queryType, features, recursiveQueriesAreSupported, store.GetDialect())
|
||||
|
||||
var result int
|
||||
err = store.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
|
||||
@@ -355,7 +355,7 @@ func TestIntegration_DashboardPermissionFilter_WithSelfContainedPermissions(t *t
|
||||
keys = append(keys, k)
|
||||
}
|
||||
t.Run(tt.desc+" with features "+strings.Join(keys, ","), func(t *testing.T) {
|
||||
filter := permissions.NewAccessControlDashboardPermissionFilter(usr, tt.permission, tt.queryType, features, recursiveQueriesAreSupported)
|
||||
filter := permissions.NewAccessControlDashboardPermissionFilter(usr, tt.permission, tt.queryType, features, recursiveQueriesAreSupported, store.GetDialect())
|
||||
|
||||
var result int
|
||||
err = store.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
|
||||
@@ -470,7 +470,7 @@ func TestIntegration_DashboardNestedPermissionFilter(t *testing.T) {
|
||||
db := setupNestedTest(t, usr, tc.permissions, orgID, features)
|
||||
recursiveQueriesAreSupported, err := db.RecursiveQueriesAreSupported()
|
||||
require.NoError(t, err)
|
||||
filter := permissions.NewAccessControlDashboardPermissionFilter(usr, tc.permission, tc.queryType, features, recursiveQueriesAreSupported)
|
||||
filter := permissions.NewAccessControlDashboardPermissionFilter(usr, tc.permission, tc.queryType, features, recursiveQueriesAreSupported, db.GetDialect())
|
||||
var result []string
|
||||
err = db.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
|
||||
q, params := filter.Where()
|
||||
@@ -588,7 +588,7 @@ func TestIntegration_DashboardNestedPermissionFilter_WithSelfContainedPermission
|
||||
db := setupNestedTest(t, helperUser, []accesscontrol.Permission{}, orgID, features)
|
||||
recursiveQueriesAreSupported, err := db.RecursiveQueriesAreSupported()
|
||||
require.NoError(t, err)
|
||||
filter := permissions.NewAccessControlDashboardPermissionFilter(usr, tc.permission, tc.queryType, features, recursiveQueriesAreSupported)
|
||||
filter := permissions.NewAccessControlDashboardPermissionFilter(usr, tc.permission, tc.queryType, features, recursiveQueriesAreSupported, db.GetDialect())
|
||||
var result []string
|
||||
err = db.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
|
||||
q, params := filter.Where()
|
||||
@@ -707,7 +707,7 @@ func TestIntegration_DashboardNestedPermissionFilter_WithActionSets(t *testing.T
|
||||
db := setupNestedTest(t, usr, tc.signedInUserPermissions, orgID, features)
|
||||
recursiveQueriesAreSupported, err := db.RecursiveQueriesAreSupported()
|
||||
require.NoError(t, err)
|
||||
filter := permissions.NewAccessControlDashboardPermissionFilter(usr, tc.permission, tc.queryType, features, recursiveQueriesAreSupported)
|
||||
filter := permissions.NewAccessControlDashboardPermissionFilter(usr, tc.permission, tc.queryType, features, recursiveQueriesAreSupported, db.GetDialect())
|
||||
var result []string
|
||||
err = db.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
|
||||
q, params := filter.Where()
|
||||
|
||||
@@ -56,7 +56,7 @@ func benchmarkDashboardPermissionFilter(b *testing.B, numUsers, numDashboards, n
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
filter := permissions.NewAccessControlDashboardPermissionFilter(&usr, dashboardaccess.PERMISSION_VIEW, "", features, recursiveQueriesAreSupported)
|
||||
filter := permissions.NewAccessControlDashboardPermissionFilter(&usr, dashboardaccess.PERMISSION_VIEW, "", features, recursiveQueriesAreSupported, store.GetDialect())
|
||||
var result int
|
||||
err := store.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
|
||||
q, params := filter.Where()
|
||||
|
||||
@@ -334,6 +334,7 @@ func TestBuilder_RBAC(t *testing.T) {
|
||||
"",
|
||||
tc.features,
|
||||
recursiveQueriesAreSupported,
|
||||
store.GetDialect(),
|
||||
),
|
||||
},
|
||||
Dialect: store.GetDialect(),
|
||||
|
||||
Reference in New Issue
Block a user