diff --git a/.github/workflows/generate-component-metadata-for-tag.yml b/.github/workflows/generate-component-metadata-for-tag.yml index 226d305bbb..333d6507af 100644 --- a/.github/workflows/generate-component-metadata-for-tag.yml +++ b/.github/workflows/generate-component-metadata-for-tag.yml @@ -9,6 +9,11 @@ jobs: upload-bundle: runs-on: ubuntu-latest steps: + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version-file: 'go.mod' + cache: 'false' - name: Checkout code uses: actions/checkout@v4 - name: Build component-metadata-bundle.json diff --git a/state/sqlite/sqlite.go b/state/sqlite/sqlite.go index 1e2c76e6aa..a9ff2ee41a 100644 --- a/state/sqlite/sqlite.go +++ b/state/sqlite/sqlite.go @@ -49,7 +49,6 @@ func newSQLiteStateStore(logger logger.Logger, dba DBAccess) *SQLiteStore { state.FeatureETag, state.FeatureTransactional, state.FeatureTTL, - state.FeatureDeleteWithPrefix, }, dbaccess: dba, } @@ -101,11 +100,6 @@ func (s *SQLiteStore) Multi(ctx context.Context, request *state.TransactionalSta return s.dbaccess.ExecuteMulti(ctx, request.Operations) } -// DeleteWithPrefix deletes objects with a prefix. -func (s *SQLiteStore) DeleteWithPrefix(ctx context.Context, req state.DeleteWithPrefixRequest) (state.DeleteWithPrefixResponse, error) { - return s.dbaccess.DeleteWithPrefix(ctx, req) -} - // Close implements io.Closer. func (s *SQLiteStore) Close() error { if s.dbaccess != nil { diff --git a/state/sqlite/sqlite_dbaccess.go b/state/sqlite/sqlite_dbaccess.go index d333038958..cb40627ac3 100644 --- a/state/sqlite/sqlite_dbaccess.go +++ b/state/sqlite/sqlite_dbaccess.go @@ -46,7 +46,6 @@ type DBAccess interface { Delete(ctx context.Context, req *state.DeleteRequest) error BulkGet(ctx context.Context, req []state.GetRequest) ([]state.BulkGetResponse, error) ExecuteMulti(ctx context.Context, reqs []state.TransactionalStateOperation) error - DeleteWithPrefix(ctx context.Context, req state.DeleteWithPrefixRequest) (state.DeleteWithPrefixResponse, error) Close() error } @@ -80,7 +79,6 @@ func (a *sqliteDBAccess) Init(ctx context.Context, md state.Metadata) error { return err } - registerFuntions() connString, err := a.metadata.GetConnectionString(a.logger, sqlite.GetConnectionStringOpts{}) if err != nil { // Already logged @@ -421,30 +419,6 @@ func (a *sqliteDBAccess) Delete(ctx context.Context, req *state.DeleteRequest) e return a.doDelete(ctx, a.db, req) } -func (a *sqliteDBAccess) DeleteWithPrefix(ctx context.Context, req state.DeleteWithPrefixRequest) (state.DeleteWithPrefixResponse, error) { - err := req.Validate() - if err != nil { - return state.DeleteWithPrefixResponse{}, err - } - - ctx, cancel := context.WithTimeout(ctx, a.metadata.Timeout) - defer cancel() - - // Concatenation is required for table name because sql.DB does not substitute parameters for table names. - //nolint:gosec - result, err := a.db.ExecContext(ctx, "DELETE FROM "+a.metadata.TableName+" WHERE prefix = ?", req.Prefix) - if err != nil { - return state.DeleteWithPrefixResponse{}, err - } - - rows, err := result.RowsAffected() - if err != nil { - return state.DeleteWithPrefixResponse{}, err - } - - return state.DeleteWithPrefixResponse{Count: rows}, nil -} - func (a *sqliteDBAccess) ExecuteMulti(parentCtx context.Context, reqs []state.TransactionalStateOperation) error { // If there's only 1 operation, skip starting a transaction switch len(reqs) { diff --git a/state/sqlite/sqlite_integration_test.go b/state/sqlite/sqlite_integration_test.go index 53852be74a..bb376e9796 100644 --- a/state/sqlite/sqlite_integration_test.go +++ b/state/sqlite/sqlite_integration_test.go @@ -140,10 +140,6 @@ func TestSqliteIntegration(t *testing.T) { multiWithSetOnly(t, s) }) - t.Run("Delete with Prefix (actor state)", func(t *testing.T) { - testDeleteWithPrefix(t, s) - }) - t.Run("ttlExpireTime", func(t *testing.T) { getExpireTime(t, s) getBulkExpireTime(t, s) @@ -614,55 +610,6 @@ func setItemWithNoKey(t *testing.T, s state.Store) { require.Error(t, err) } -func testDeleteWithPrefix(t *testing.T, s state.Store) { - setReq1 := &state.SetRequest{ - Key: "mock-app-id||mock-actor-type||mock-actor-id||key0", - } - - setReq2 := &state.SetRequest{ - Key: "mock-app-id||mock-actor-type||mock-actor-id||key1", - } - - setReq3 := &state.SetRequest{ - Key: "mock-app-id||mock-actor-type||mock-actor-id||key2", - } - - setReq4 := &state.SetRequest{ - Key: "different-app-id||different-actor-type||different-actor-id||key0", - } - - delReq := state.DeleteWithPrefixRequest{ - Prefix: "mock-app-id||mock-actor-type||mock-actor-id", - } - - err := s.Set(context.Background(), setReq1) - require.NoError(t, err) - - err = s.Set(context.Background(), setReq2) - require.NoError(t, err) - - err = s.Set(context.Background(), setReq3) - require.NoError(t, err) - - err = s.Set(context.Background(), setReq4) - require.NoError(t, err) - - res, err := s.(state.DeleteWithPrefix).DeleteWithPrefix(context.Background(), delReq) - require.NoError(t, err) - assert.Equal(t, int64(3), res.Count) - - delReq = state.DeleteWithPrefixRequest{ - Prefix: "different-app-id||different-actor-type||different-actor-id||", - } - res, err = s.(state.DeleteWithPrefix).DeleteWithPrefix(context.Background(), delReq) - require.NoError(t, err) - assert.Equal(t, int64(1), res.Count) - - res, err = s.(state.DeleteWithPrefix).DeleteWithPrefix(context.Background(), delReq) - require.NoError(t, err) - assert.Equal(t, int64(0), res.Count) -} - func testSetItemWithInvalidTTL(t *testing.T, s state.Store) { setReq := &state.SetRequest{ Key: randomKey(), diff --git a/state/sqlite/sqlite_migrations.go b/state/sqlite/sqlite_migrations.go index 5bbdbcd7c6..78de6c69a3 100644 --- a/state/sqlite/sqlite_migrations.go +++ b/state/sqlite/sqlite_migrations.go @@ -16,15 +16,11 @@ package sqlite import ( "context" "database/sql" - "database/sql/driver" "fmt" - "strings" commonsql "github.com/dapr/components-contrib/common/component/sql" sqlitemigrations "github.com/dapr/components-contrib/common/component/sql/migrations/sqlite" "github.com/dapr/kit/logger" - - sqlite3 "modernc.org/sqlite" ) type migrationOptions struct { @@ -32,31 +28,6 @@ type migrationOptions struct { MetadataTableName string } -func registerFuntions() { - sqlite3.RegisterDeterministicScalarFunction( - "parse_key_prefix", - 1, - func(ctx *sqlite3.FunctionContext, args []driver.Value) (driver.Value, error) { - var s1 string - switch arg0 := args[0].(type) { - case string: - s1 = arg0 - default: - return "", fmt.Errorf("expected argv[0] to be text") - } - if len(s1) == 0 { - return "", fmt.Errorf("cannot create prefix for empty string") - } - - lastIndex := strings.LastIndex(s1, "||") - if lastIndex != -1 { - return s1[:lastIndex+2], nil - } - return "", nil - }, - ) -} - // Perform the required migrations func performMigrations(ctx context.Context, db *sql.DB, logger logger.Logger, opts migrationOptions) error { m := sqlitemigrations.Migrations{ @@ -90,23 +61,5 @@ func performMigrations(ctx context.Context, db *sql.DB, logger logger.Logger, op } return nil }, - // Migration 1: add the "prefix" column - func(ctx context.Context) error { - // Add the "prefix" column that can be used by DeleteWithPrefix - logger.Infof("Adding 'prefix' column to table '%s'", opts.StateTableName) - _, err := m.GetConn().ExecContext( - ctx, - fmt.Sprintf( - `ALTER TABLE %[1]s ADD COLUMN prefix TEXT GENERATED ALWAYS AS (parse_key_prefix(key)) VIRTUAL; - CREATE INDEX %[1]s_prefix_index ON %[1]s(prefix) WHERE prefix != ""`, - opts.StateTableName, - ), - ) - if err != nil { - return fmt.Errorf("failed to create virtual column: %w", err) - } - return nil - }, - }, - ) + }) } diff --git a/state/sqlite/sqlite_test.go b/state/sqlite/sqlite_test.go index 177fb6c4cc..3ffcdc3f61 100644 --- a/state/sqlite/sqlite_test.go +++ b/state/sqlite/sqlite_test.go @@ -294,15 +294,6 @@ func TestValidMultiDeleteRequest(t *testing.T) { require.NoError(t, err) } -func TestValidEmptyDeleteWithPrefixRequest(t *testing.T) { - t.Parallel() - - ods := createSqlite(t) - res, err := ods.DeleteWithPrefix(context.Background(), createDeleteWithPrefixRequest()) - require.NoError(t, err) - assert.Equal(t, int64(0), res.Count) -} - // Proves that the Ping method runs the ping method. func TestPingRunsDBAccessPing(t *testing.T) { t.Parallel() @@ -347,10 +338,6 @@ func (m *fakeDBaccess) BulkGet(parentCtx context.Context, req []state.GetRequest return nil, nil } -func (m *fakeDBaccess) DeleteWithPrefix(ctx context.Context, req state.DeleteWithPrefixRequest) (state.DeleteWithPrefixResponse, error) { - return state.DeleteWithPrefixResponse{}, nil -} - func (m *fakeDBaccess) Delete(ctx context.Context, req *state.DeleteRequest) error { return nil } @@ -402,12 +389,6 @@ func createDeleteRequest() state.DeleteRequest { } } -func createDeleteWithPrefixRequest() state.DeleteWithPrefixRequest { - return state.DeleteWithPrefixRequest{ - Prefix: randomKey(), - } -} - func createSqliteWithFake(t *testing.T) (*SQLiteStore, *fakeDBaccess) { ods := createSqlite(t) fake := ods.dbaccess.(*fakeDBaccess) diff --git a/tests/certification/state/sqlite/artifacts/readonly.db b/tests/certification/state/sqlite/artifacts/readonly.db index 7d6f81b517..d2772f5217 100644 Binary files a/tests/certification/state/sqlite/artifacts/readonly.db and b/tests/certification/state/sqlite/artifacts/readonly.db differ diff --git a/tests/certification/state/sqlite/sqlite_test.go b/tests/certification/state/sqlite/sqlite_test.go index 4eaefa5712..f02de2c79d 100644 --- a/tests/certification/state/sqlite/sqlite_test.go +++ b/tests/certification/state/sqlite/sqlite_test.go @@ -64,7 +64,7 @@ const ( // Update this constant if you add more migrations // Don't forget to also run the utility `artifacts/update_readonlydb.go` to update the read-only DB - migrationLevel = "2" + migrationLevel = "1" ) func TestSQLite(t *testing.T) { diff --git a/tests/config/state/tests.yml b/tests/config/state/tests.yml index 77a3234619..5e5328e098 100644 --- a/tests/config/state/tests.yml +++ b/tests/config/state/tests.yml @@ -55,7 +55,7 @@ components: # This component requires etags to be UUIDs badEtag: "e9b9e142-74b1-4a2e-8e90-3f4ffeea2e70" - component: sqlite - operations: [ "transaction", "etag", "first-write", "ttl", "delete-with-prefix" ] + operations: [ "transaction", "etag", "first-write", "ttl" ] - component: mysql.mysql operations: [ "transaction", "etag", "first-write", "ttl" ] - component: mysql.mariadb