package cassandra import ( "fmt" "github.com/scylladb/gocqlx/v3/table" "reflect" ) // GenerateTableMetadata 根據傳入的 struct 產生 table.Metadata func GenerateTableMetadata(document any, keyspace string) (table.Metadata, error) { // 取得型別資訊,若是指標則取 Elem t := reflect.TypeOf(document) if t.Kind() == reflect.Ptr { t = t.Elem() } // 取得表名稱:若 model 有實作 TableName() 則使用該方法,否則轉換型別名稱為 snake_case var tableName string if tm, ok := document.(interface{ TableName() string }); ok { tableName = fmt.Sprintf("%s.%s", keyspace, tm.TableName()) } else { return table.Metadata{}, fmt.Errorf("failed to get table func") } columns := make([]string, 0, t.NumField()) partKeys := make([]string, 0, t.NumField()) sortKeys := make([]string, 0, t.NumField()) // 遍歷所有 exported 欄位 for i := 0; i < t.NumField(); i++ { field := t.Field(i) // 跳過 unexported 欄位 if field.PkgPath != "" { continue } // 如果欄位有標記 db:"-" 則跳過 if tag := field.Tag.Get("db"); tag == "-" { continue } // 取得欄位名稱 colName := field.Tag.Get("db") if colName == "" { colName = toSnakeCase(field.Name) } columns = append(columns, colName) // 若有 partition:"true" 標記,加入 PartKey if field.Tag.Get("partition_key") == "true" { partKeys = append(partKeys, colName) } // 若有 sort:"true" 標記,加入 SortKey if field.Tag.Get("clustering_key") == "true" { sortKeys = append(sortKeys, colName) } } if len(partKeys) == 0 { return table.Metadata{}, fmt.Errorf("no partition key defined in struct") } // 組合 Metadata meta := table.Metadata{ Name: tableName, Columns: columns, PartKey: partKeys, SortKey: sortKeys, } return meta, nil }