package main import ( "fmt" "log" "net/url" "your_module_path/utils" // Ganti dengan path modul Anda ) func main() { // --- 1. Setup QueryBuilder --- // Kita akan menggunakan PostgreSQL untuk contoh ini. // Untuk database lain, cukup ganti DBTypePostgreSQL menjadi DBTypeMySQL, dll. qb := utils.NewQueryBuilder("users", utils.DBTypePostgreSQL). SetColumnMapping(map[string]string{ // API Field -> DB Column "userId": "id", "username": "user_name", "email": "email_address", "isActive": "is_active", "createdAt": "created_at", }). SetAllowedColumns([]string{ "id", "user_name", "email_address", "is_active", "created_at", "updated_at", }) fmt.Println("=== QUERY BUILDER EXAMPLES ===\n") // --- 2. CREATE (INSERT) --- fmt.Println("--- CREATE (INSERT) ---") // Contoh data user baru newUser := utils.InsertData{ Columns: []string{"username", "email", "is_active"}, Values: []interface{}{"john_doe", "john.doe@example.com", true}, } // Build INSERT query sql, args, err := qb.BuildInsertQuery(newUser, "id", "created_at") if err != nil { log.Fatalf("Failed to build INSERT query: %v", err) } fmt.Printf("SQL: %s\n", sql) fmt.Printf("Args: %v\n\n", args) // Output (PostgreSQL): // SQL: INSERT INTO users (user_name, email_address, is_active) VALUES ($1, $2, $3) RETURNING id, created_at // Args: [john_doe john.doe@example.com true] // --- 3. UPDATE --- fmt.Println("--- UPDATE ---") // Data yang akan diupdate untuk user dengan ID 1 updateData := utils.UpdateData{ Columns: []string{"username", "is_active"}, Values: []interface{}{"john_doe_updated", false}, } // Filter untuk menentukan user mana yang akan diupdate filters := []utils.FilterGroup{{ Filters: []utils.DynamicFilter{{ Column: "userId", Operator: utils.OpEqual, Value: 1, }}, }} // Build UPDATE query sql, args, err = qb.BuildUpdateQuery(updateData, filters, "updated_at") if err != nil { log.Fatalf("Failed to build UPDATE query: %v", err) } fmt.Printf("SQL: %s\n", sql) fmt.Printf("Args: %v\n\n", args) // Output (PostgreSQL): // SQL: UPDATE "users" SET "user_name" = $1, "is_active" = $2 WHERE ("id" = $3) RETURNING updated_at // Args: [john_doe_updated false 1] // --- 4. DELETE --- fmt.Println("--- DELETE ---") // Filter untuk menghapus user yang tidak aktif deleteFilters := []utils.FilterGroup{{ Filters: []utils.DynamicFilter{{ Column: "isActive", Operator: utils.OpEqual, Value: false, }}, }} // Build DELETE query sql, args, err = qb.BuildDeleteQuery(deleteFilters, "id") if err != nil { log.Fatalf("Failed to build DELETE query: %v", err) } fmt.Printf("SQL: %s\n", sql) fmt.Printf("Args: %v\n\n", args) // Output (PostgreSQL): // SQL: DELETE FROM "users" WHERE ("is_active" = $1) RETURNING id // Args: [false] // --- 5. UPSERT (INSERT ... ON CONFLICT) --- fmt.Println("--- UPSERT ---") // Data untuk upsert (insert atau update jika sudah ada) upsertData := utils.InsertData{ Columns: []string{"id", "username", "email"}, Values: []interface{}{1, "unique_user", "unique@example.com"}, // ID 1 mungkin sudah ada } // Kolom yang menjadi penentu konflik (misalnya, primary key atau unique key) conflictColumns := []string{"id"} // Data yang akan diupdate jika terjadi konflik upsertUpdateData := utils.UpdateData{ Columns: []string{"username", "email"}, Values: []interface{}{"unique_user_updated", "updated@example.com"}, } // Build UPSERT query sql, args, err = qb.BuildUpsertQuery(upsertData, conflictColumns, upsertUpdateData, "updated_at") if err != nil { log.Fatalf("Failed to build UPSERT query: %v", err) } fmt.Printf("SQL: %s\n", sql) fmt.Printf("Args: %v\n\n", args) // Output (PostgreSQL): // SQL: INSERT INTO users (id, user_name, email_address) VALUES ($1, $2, $3) ON CONFLICT (id) DO UPDATE SET "user_name" = EXCLUDED.user_name, "email_address" = EXCLUDED.email_address RETURNING updated_at // Args: [1 unique_user unique@example.com unique_user_updated updated@example.com] // --- 6. SELECT dengan JOIN --- fmt.Println("--- SELECT with JOIN ---") // Reset builder untuk query baru qbJoin := utils.NewQueryBuilder("users", utils.DBTypePostgreSQL). SetColumnMapping(map[string]string{"userId": "id", "username": "user_name"}). SetAllowedColumns([]string{"id", "user_name", "profile_id"}). Join("INNER", "profiles", "users.id = profiles.user_id") // Tambahkan JOIN // Query untuk mendapatkan user dan profilnya joinQuery := utils.DynamicQuery{ Fields: []string{"users.id", "user_name", "profiles.bio"}, Filters: []utils.FilterGroup{{ Filters: []utils.DynamicFilter{{ Column: "isActive", Operator: utils.OpEqual, Value: true, }}, }}, Limit: 10, } sql, args, err = qbJoin.BuildQuery(joinQuery) if err != nil { log.Fatalf("Failed to build JOIN query: %v", err) } fmt.Printf("SQL: %s\n", sql) fmt.Printf("Args: %v\n\n", args) // Output (PostgreSQL): // SQL: SELECT "users"."id", "user_name", "profiles"."bio" FROM "users" INNER JOIN "profiles" ON users.id = profiles.user_id WHERE ("is_active" = $1) LIMIT 10 // Args: [true] // --- 7. SELECT dengan UNION --- fmt.Println("--- SELECT with UNION ---") // Buat dua query builder untuk dua tabel berbeda qbActive := utils.NewQueryBuilder("users", utils.DBTypePostgreSQL) qbArchived := utils.NewQueryBuilder("archived_users", utils.DBTypePostgreSQL) // Query pertama: user aktif dari tabel 'users' query1 := qbActive.sqlBuilder.Select("id", "user_name", "'active' as status").Where("is_active = ?", true) // Query kedua: user aktif dari tabel 'archived_users' query2 := qbArchived.sqlBuilder.Select("id", "user_name", "'archived' as status").Where("is_active = ?", true) // Gabungkan dengan UNION unionQuery := query1.Union(query2) sql, args, err = unionQuery.ToSql() if err != nil { log.Fatalf("Failed to build UNION query: %v", err) } fmt.Printf("SQL: %s\n", sql) fmt.Printf("Args: %v\n\n", args) // Output (PostgreSQL): // SQL: SELECT id, user_name, 'active' as status FROM users WHERE is_active = $1 UNION SELECT id, user_name, 'archived' as status FROM archived_users WHERE is_active = $2 // Args: [true true] // --- 8. Integrasi dengan QueryParser (Web Context) --- fmt.Println("--- Integration with QueryParser ---") // Simulasi query parameter dari URL: /users?fields=id,username&filter[username][_contains]=john&sort=-createdAt&limit=5 mockURLValues := url.Values{ "fields": []string{"id", "username"}, "filter[username][_contains]": []string{"john"}, "sort": []string{"-createdAt"}, "limit": []string{"5"}, } parser := utils.NewQueryParser() dynamicQuery, err := parser.ParseQuery(mockURLValues) if err != nil { log.Fatalf("Failed to parse query: %v", err) } // Build query dari hasil parsing qbParser := utils.NewQueryBuilder("users", utils.DBTypePostgreSQL). SetColumnMapping(map[string]string{"username": "user_name", "createdAt": "created_at"}). SetAllowedColumns([]string{"id", "user_name", "created_at"}) sql, args, err = qbParser.BuildQuery(dynamicQuery) if err != nil { log.Fatalf("Failed to build query from parser: %v", err) } fmt.Printf("SQL: %s\n", sql) fmt.Printf("Args: %v\n\n", args) // Output (PostgreSQL): // SQL: SELECT "id", "user_name" FROM "users" WHERE ("user_name" ILIKE $1) ORDER BY "created_at" DESC LIMIT 5 // Args: [%john%] }