Skip to main content
Glama
FreePeak

Multi Database MCP Server

continuous_aggregate_test.go7.04 kB
package timescale import ( "context" "fmt" "strings" "testing" ) func TestCreateContinuousAggregate(t *testing.T) { t.Run("should create a continuous aggregate view", func(t *testing.T) { // Setup test with a custom mock DB mockDB := NewMockDB() mockDB.SetTimescaleAvailable(true) tsdb := &DB{ Database: mockDB, isTimescaleDB: true, config: DBConfig{ UseTimescaleDB: true, }, } ctx := context.Background() // Create a continuous aggregate err := tsdb.CreateContinuousAggregate(ctx, ContinuousAggregateOptions{ ViewName: "daily_metrics", SourceTable: "raw_metrics", TimeColumn: "time", BucketInterval: "1 day", Aggregations: []ColumnAggregation{ {Function: AggrAvg, Column: "temperature", Alias: "avg_temp"}, {Function: AggrMax, Column: "temperature", Alias: "max_temp"}, {Function: AggrMin, Column: "temperature", Alias: "min_temp"}, {Function: AggrCount, Column: "*", Alias: "count"}, }, WithData: true, RefreshPolicy: false, // Set to false to avoid additional queries }) // Assert if err != nil { t.Fatalf("Expected no error, got: %v", err) } // Verify query contains required elements - since we're checking the last query directly lastQuery := mockDB.LastQuery() requiredElements := []string{ "CREATE MATERIALIZED VIEW", "daily_metrics", "time_bucket", "1 day", "AVG", "MAX", "MIN", "COUNT", "raw_metrics", "WITH DATA", } for _, element := range requiredElements { if !strings.Contains(lastQuery, element) { t.Errorf("Expected query to contain '%s', but got: %s", element, lastQuery) } } }) t.Run("should error when TimescaleDB not available", func(t *testing.T) { // Setup test with TimescaleDB unavailable tsdb, mockDB := MockTimescaleDB(t) mockDB.SetTimescaleAvailable(false) tsdb.isTimescaleDB = false // Explicitly set this to false ctx := context.Background() // Create a continuous aggregate err := tsdb.CreateContinuousAggregate(ctx, ContinuousAggregateOptions{ ViewName: "daily_metrics", SourceTable: "raw_metrics", TimeColumn: "time", BucketInterval: "1 day", Aggregations: []ColumnAggregation{ {Function: AggrAvg, Column: "temperature", Alias: "avg_temp"}, }, }) // Assert if err == nil { t.Fatal("Expected an error when TimescaleDB not available, got none") } }) t.Run("should handle database errors", func(t *testing.T) { // Setup test with a custom mock DB mockDB := NewMockDB() mockDB.SetTimescaleAvailable(true) tsdb := &DB{ Database: mockDB, isTimescaleDB: true, config: DBConfig{ UseTimescaleDB: true, }, } ctx := context.Background() // Register a query result with an error mockDB.RegisterQueryResult("CREATE MATERIALIZED VIEW", nil, fmt.Errorf("query error")) // Create a continuous aggregate err := tsdb.CreateContinuousAggregate(ctx, ContinuousAggregateOptions{ ViewName: "daily_metrics", SourceTable: "raw_metrics", TimeColumn: "time", BucketInterval: "1 day", RefreshPolicy: false, // Disable to avoid additional queries }) // Assert if err == nil { t.Fatal("Expected an error, got none") } }) } func TestRefreshContinuousAggregate(t *testing.T) { t.Run("should refresh a continuous aggregate view", func(t *testing.T) { // Setup test tsdb, mockDB := MockTimescaleDB(t) ctx := context.Background() // Set mock behavior mockDB.SetQueryResult([]map[string]interface{}{ {"refreshed": true}, }) // Refresh a continuous aggregate with time range err := tsdb.RefreshContinuousAggregate(ctx, "daily_metrics", "2023-01-01", "2023-01-31") // Assert if err != nil { t.Fatalf("Expected no error, got: %v", err) } // Verify SQL contains proper calls if !mockDB.QueryContains("CALL") || !mockDB.QueryContains("refresh_continuous_aggregate") { t.Error("Expected query to call refresh_continuous_aggregate") } }) t.Run("should refresh without time range", func(t *testing.T) { // Setup test tsdb, mockDB := MockTimescaleDB(t) ctx := context.Background() // Refresh a continuous aggregate without time range err := tsdb.RefreshContinuousAggregate(ctx, "daily_metrics", "", "") // Assert if err != nil { t.Fatalf("Expected no error, got: %v", err) } // Verify SQL contains proper calls but no time range if !mockDB.QueryContains("CALL") || !mockDB.QueryContains("refresh_continuous_aggregate") { t.Error("Expected query to call refresh_continuous_aggregate") } if !mockDB.QueryContains("NULL, NULL") { t.Error("Expected query to use NULL for undefined time ranges") } }) } func TestManageContinuousAggregatePolicy(t *testing.T) { t.Run("should add a refresh policy", func(t *testing.T) { // Setup test tsdb, mockDB := MockTimescaleDB(t) ctx := context.Background() // Add a refresh policy err := tsdb.AddContinuousAggregatePolicy(ctx, ContinuousAggregatePolicyOptions{ ViewName: "daily_metrics", Start: "-2 days", End: "now()", ScheduleInterval: "1 hour", }) // Assert if err != nil { t.Fatalf("Expected no error, got: %v", err) } // Verify SQL contains proper calls if !mockDB.QueryContains("add_continuous_aggregate_policy") { t.Error("Expected query to contain add_continuous_aggregate_policy") } }) t.Run("should remove a refresh policy", func(t *testing.T) { // Setup test tsdb, mockDB := MockTimescaleDB(t) ctx := context.Background() // Remove a refresh policy err := tsdb.RemoveContinuousAggregatePolicy(ctx, "daily_metrics") // Assert if err != nil { t.Fatalf("Expected no error, got: %v", err) } // Verify SQL contains proper calls if !mockDB.QueryContains("remove_continuous_aggregate_policy") { t.Error("Expected query to contain remove_continuous_aggregate_policy") } }) } func TestDropContinuousAggregate(t *testing.T) { t.Run("should drop a continuous aggregate", func(t *testing.T) { // Setup test tsdb, mockDB := MockTimescaleDB(t) ctx := context.Background() // Drop a continuous aggregate err := tsdb.DropContinuousAggregate(ctx, "daily_metrics", false) // Assert if err != nil { t.Fatalf("Expected no error, got: %v", err) } // Verify SQL contains proper calls if !mockDB.QueryContains("DROP MATERIALIZED VIEW") { t.Error("Expected query to contain DROP MATERIALIZED VIEW") } }) t.Run("should drop a continuous aggregate with cascade", func(t *testing.T) { // Setup test tsdb, mockDB := MockTimescaleDB(t) ctx := context.Background() // Drop a continuous aggregate with cascade err := tsdb.DropContinuousAggregate(ctx, "daily_metrics", true) // Assert if err != nil { t.Fatalf("Expected no error, got: %v", err) } // Verify SQL contains proper calls if !mockDB.QueryContains("DROP MATERIALIZED VIEW") || !mockDB.QueryContains("CASCADE") { t.Error("Expected query to contain DROP MATERIALIZED VIEW with CASCADE") } }) }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/FreePeak/db-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server