1package entities
2
3import (
4	"context"
5	"net/http"
6
7	"github.com/Azure/go-autorest/autorest"
8	"github.com/Azure/go-autorest/autorest/azure"
9	"github.com/Azure/go-autorest/autorest/validation"
10	"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
11)
12
13type InsertOrReplaceEntityInput struct {
14	// The Entity which should be inserted, by default all values are strings
15	// To explicitly type a property, specify the appropriate OData data type by setting
16	// the m:type attribute within the property definition
17	Entity map[string]interface{}
18
19	// When inserting an entity into a table, you must specify values for the PartitionKey and RowKey system properties.
20	// Together, these properties form the primary key and must be unique within the table.
21	// Both the PartitionKey and RowKey values must be string values; each key value may be up to 64 KB in size.
22	// If you are using an integer value for the key value, you should convert the integer to a fixed-width string,
23	// because they are canonically sorted. For example, you should convert the value 1 to 0000001 to ensure proper sorting.
24	RowKey       string
25	PartitionKey string
26}
27
28// InsertOrReplace replaces an existing entity or inserts a new entity if it does not exist in the table.
29// Because this operation can insert or update an entity, it is also known as an upsert operation.
30func (client Client) InsertOrReplace(ctx context.Context, accountName, tableName string, input InsertOrReplaceEntityInput) (result autorest.Response, err error) {
31	if accountName == "" {
32		return result, validation.NewError("entities.Client", "InsertOrReplace", "`accountName` cannot be an empty string.")
33	}
34	if tableName == "" {
35		return result, validation.NewError("entities.Client", "InsertOrReplace", "`tableName` cannot be an empty string.")
36	}
37	if input.PartitionKey == "" {
38		return result, validation.NewError("entities.Client", "InsertOrReplace", "`input.PartitionKey` cannot be an empty string.")
39	}
40	if input.RowKey == "" {
41		return result, validation.NewError("entities.Client", "InsertOrReplace", "`input.RowKey` cannot be an empty string.")
42	}
43
44	req, err := client.InsertOrReplacePreparer(ctx, accountName, tableName, input)
45	if err != nil {
46		err = autorest.NewErrorWithError(err, "entities.Client", "InsertOrReplace", nil, "Failure preparing request")
47		return
48	}
49
50	resp, err := client.InsertOrReplaceSender(req)
51	if err != nil {
52		result = autorest.Response{Response: resp}
53		err = autorest.NewErrorWithError(err, "entities.Client", "InsertOrReplace", resp, "Failure sending request")
54		return
55	}
56
57	result, err = client.InsertOrReplaceResponder(resp)
58	if err != nil {
59		err = autorest.NewErrorWithError(err, "entities.Client", "InsertOrReplace", resp, "Failure responding to request")
60		return
61	}
62
63	return
64}
65
66// InsertOrReplacePreparer prepares the InsertOrReplace request.
67func (client Client) InsertOrReplacePreparer(ctx context.Context, accountName, tableName string, input InsertOrReplaceEntityInput) (*http.Request, error) {
68	pathParameters := map[string]interface{}{
69		"tableName":    autorest.Encode("path", tableName),
70		"partitionKey": autorest.Encode("path", input.PartitionKey),
71		"rowKey":       autorest.Encode("path", input.RowKey),
72	}
73
74	headers := map[string]interface{}{
75		"x-ms-version": APIVersion,
76		"Accept":       "application/json",
77		"Prefer":       "return-no-content",
78	}
79
80	preparer := autorest.CreatePreparer(
81		autorest.AsContentType("application/json"),
82		autorest.AsMerge(),
83		autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
84		autorest.WithPathParameters("/{tableName}(PartitionKey='{partitionKey}', RowKey='{rowKey}')", pathParameters),
85		autorest.WithJSON(input.Entity),
86		autorest.WithHeaders(headers))
87	return preparer.Prepare((&http.Request{}).WithContext(ctx))
88}
89
90// InsertOrReplaceSender sends the InsertOrReplace request. The method will close the
91// http.Response Body if it receives an error.
92func (client Client) InsertOrReplaceSender(req *http.Request) (*http.Response, error) {
93	return autorest.SendWithSender(client, req,
94		azure.DoRetryWithRegistration(client.Client))
95}
96
97// InsertOrReplaceResponder handles the response to the InsertOrReplace request. The method always
98// closes the http.Response Body.
99func (client Client) InsertOrReplaceResponder(resp *http.Response) (result autorest.Response, err error) {
100	err = autorest.Respond(
101		resp,
102		client.ByInspecting(),
103		azure.WithErrorUnlessStatusCode(http.StatusNoContent),
104		autorest.ByClosing())
105	result = autorest.Response{Response: resp}
106
107	return
108}
109