-
Notifications
You must be signed in to change notification settings - Fork 13
Use an INSERT rather than an UPSERT when only touching partition/clustering columns #60
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,8 @@ | ||
language: go | ||
|
||
go: | ||
- 1.11.x | ||
- 1.12.x | ||
- 1.13.x | ||
- 1.14.x | ||
- tip | ||
|
||
addons: | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ package gocassa | |
import ( | ||
"bytes" | ||
"fmt" | ||
"reflect" | ||
"strconv" | ||
"strings" | ||
|
||
|
@@ -124,6 +125,25 @@ func transformFields(m map[string]interface{}) { | |
} | ||
} | ||
|
||
// allFieldValuesAreNullable checks if all the fields passed in contain | ||
// items that will eventually be marked in Cassandra as null (so we can | ||
// better predict if we should do an INSERT or an UPSERT). This is to | ||
// protect against https://issues.apache.org/jira/browse/CASSANDRA-11805 | ||
func allFieldValuesAreNullable(fields map[string]interface{}) bool { | ||
for _, value := range fields { | ||
rv := reflect.ValueOf(value) | ||
switch rv.Kind() { | ||
case reflect.Array, reflect.Slice, reflect.Map: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just to check — are these the only types which could be nullable? I'm trying to see where passing an incorrect type would be filtered out, but I can't see anything that does this? Is it possible for value to be a nil pointer for example? In https://play.golang.org/p/lOA15Bdk5v3 Would this be filtered out later by GoCQL as a field of type There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Pointers are filtered out a layer above through Also yes, those are the fields that I found to be susceptible to the nullable behaviour. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have added an explicit test for this behaviour just to make sure it's codified |
||
if rv.Len() > 0 { | ||
return false | ||
} | ||
default: | ||
return false | ||
} | ||
} | ||
return true | ||
} | ||
|
||
// INSERT INTO Hollywood.NerdMovies (user_uuid, fan) | ||
// VALUES ('cfd66ccc-d857-4e90-b1e5-df98a3d40cd6', 'johndoe') | ||
// | ||
|
@@ -161,10 +181,8 @@ func (t t) Set(i interface{}) Op { | |
} | ||
ks := append(t.info.keys.PartitionKeys, t.info.keys.ClusteringColumns...) | ||
updFields := removeFields(m, ks) | ||
if len(updFields) == 0 { | ||
return newWriteOp(t.keySpace.qe, filter{ | ||
t: t, | ||
}, insertOpType, m) | ||
if len(updFields) == 0 || allFieldValuesAreNullable(updFields) { | ||
return newWriteOp(t.keySpace.qe, filter{t: t}, insertOpType, m) | ||
} | ||
transformFields(updFields) | ||
rels := relations(t.info.keys, m) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this say
UPDATE
? [CQL Reference]There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I specifically wanted upsert to describe this behaviour. The intention is not to map to a cql command but rather a behaviour of the library (which is to do an upsert)