package dynamodb import ( "encoding/json" "errors" "fmt" simplejson "github.com/bitly/go-simplejson" ) type Table struct { Server *Server Name string Key PrimaryKey } type AttributeDefinitionT struct { Name string `json:"AttributeName"` Type string `json:"AttributeType"` } type KeySchemaT struct { AttributeName string KeyType string } type ProjectionT struct { ProjectionType string } type GlobalSecondaryIndexT struct { IndexName string IndexSizeBytes int64 ItemCount int64 KeySchema []KeySchemaT Projection ProjectionT ProvisionedThroughput ProvisionedThroughputT } type LocalSecondaryIndexT struct { IndexName string IndexSizeBytes int64 ItemCount int64 KeySchema []KeySchemaT Projection ProjectionT } type ProvisionedThroughputT struct { NumberOfDecreasesToday int64 ReadCapacityUnits int64 WriteCapacityUnits int64 } type StreamSpecificationT struct { StreamEnabled bool StreamViewType string } type TableDescriptionT struct { AttributeDefinitions []AttributeDefinitionT CreationDateTime float64 ItemCount int64 KeySchema []KeySchemaT GlobalSecondaryIndexes []GlobalSecondaryIndexT LocalSecondaryIndexes []LocalSecondaryIndexT ProvisionedThroughput ProvisionedThroughputT StreamSpecification StreamSpecificationT TableName string TableSizeBytes int64 TableStatus string LatestStreamArn string LatestStreamLabel string } type describeTableResponse struct { Table TableDescriptionT } func findAttributeDefinitionByName(ads []AttributeDefinitionT, name string) *AttributeDefinitionT { for _, a := range ads { if a.Name == name { return &a } } return nil } func (a *AttributeDefinitionT) GetEmptyAttribute() *Attribute { switch a.Type { case "S": return NewStringAttribute(a.Name, "") case "N": return NewNumericAttribute(a.Name, "") case "B": return NewBinaryAttribute(a.Name, "") default: return nil } } func (t *TableDescriptionT) BuildPrimaryKey() (pk PrimaryKey, err error) { for _, k := range t.KeySchema { var attr *Attribute ad := findAttributeDefinitionByName(t.AttributeDefinitions, k.AttributeName) if ad == nil { return pk, errors.New("An inconsistency found in TableDescriptionT") } attr = ad.GetEmptyAttribute() if attr == nil { return pk, errors.New("An inconsistency found in TableDescriptionT") } switch k.KeyType { case "HASH": pk.KeyAttribute = attr case "RANGE": pk.RangeAttribute = attr } } return } func (s *Server) NewTable(name string, key PrimaryKey) *Table { return &Table{s, name, key} } func (s *Server) ListTables() ([]string, error) { var tables []string query := NewEmptyQuery() jsonResponse, err := s.queryServer(target("ListTables"), query) if err != nil { return nil, err } json, err := simplejson.NewJson(jsonResponse) if err != nil { return nil, err } response, err := json.Get("TableNames").Array() if err != nil { message := fmt.Sprintf("Unexpected response %s", jsonResponse) return nil, errors.New(message) } for _, value := range response { if t, ok := (value).(string); ok { tables = append(tables, t) } } return tables, nil } func (s *Server) CreateTable(tableDescription TableDescriptionT) (string, error) { query := NewEmptyQuery() query.AddCreateRequestTable(tableDescription) jsonResponse, err := s.queryServer(target("CreateTable"), query) if err != nil { return "unknown", err } json, err := simplejson.NewJson(jsonResponse) if err != nil { return "unknown", err } return json.Get("TableDescription").Get("TableStatus").MustString(), nil } func (s *Server) DeleteTable(tableDescription TableDescriptionT) (string, error) { query := NewEmptyQuery() query.AddDeleteRequestTable(tableDescription) jsonResponse, err := s.queryServer(target("DeleteTable"), query) if err != nil { return "unknown", err } json, err := simplejson.NewJson(jsonResponse) if err != nil { return "unknown", err } return json.Get("TableDescription").Get("TableStatus").MustString(), nil } func (t *Table) DescribeTable() (*TableDescriptionT, error) { return t.Server.DescribeTable(t.Name) } func (s *Server) DescribeTable(name string) (*TableDescriptionT, error) { q := NewEmptyQuery() q.addTableByName(name) jsonResponse, err := s.queryServer(target("DescribeTable"), q) if err != nil { return nil, err } var r describeTableResponse err = json.Unmarshal(jsonResponse, &r) if err != nil { return nil, err } return &r.Table, nil } func (s *Server) UpdateTable(tableDescription TableDescriptionT) (string, error) { query := NewEmptyQuery() query.AddUpdateRequestTable(tableDescription) jsonResponse, err := s.queryServer(target("UpdateTable"), query) if err != nil { return "unknown", err } json, err := simplejson.NewJson(jsonResponse) if err != nil { return "unknown", err } return json.Get("TableDescription").Get("TableStatus").MustString(), nil } func (t *Table) ListStreams(startArn string) ([]StreamListItemT, error) { return t.Server.ListTableStreams(t.Name, startArn) } func (t *Table) LimitedListStreams(startArn string, limit int64) ([]StreamListItemT, error) { return t.Server.LimitedListTableStreams(t.Name, startArn, limit) } func keyParam(k *PrimaryKey, hashKey string, rangeKey string) string { value := fmt.Sprintf("{\"HashKeyElement\":{%s}", keyValue(k.KeyAttribute.Type, hashKey)) if k.RangeAttribute != nil { value = fmt.Sprintf("%s,\"RangeKeyElement\":{%s}", value, keyValue(k.RangeAttribute.Type, rangeKey)) } return fmt.Sprintf("\"Key\":%s}", value) } func keyValue(key string, value string) string { return fmt.Sprintf("\"%s\":\"%s\"", key, value) }