Detect the Type of a Column with SQLite.swift - sqlite.swift

I am reading two different SQLite files and reading the 4th column. In one of the files, the type is REAL and in the other, it's INTEGER.
When I try to extract the value, I am unable to ever determine the type:
for row in try! db.prepare("SELECT * FROM things") {
let value = row[4]
print(value) //This logs "Optional(7)" or "Optional(1.2)" etc.
switch value{
case let double as Double:
print("Double: \(double)") //This never gets called...
case let int as Int:
print("Int: \(int)") //This never gets called
default:
return 0 //This always gets called
}
}
How can I accurately detect the type of the column?

switch sqlite3_column_type(sqliteStatement, index) {
case SQLITE_TEXT:
// handle text
case SQLITE_BLOB:
// handle image
case SQLITE_NULL:
// handle null
case SQLITE_FLOAT:
// handle float
case SQLITE_INTEGER:
// handle integer
default:
break
}

I figured this out. I needed to check against Int64 instead of Int.

Related

How to use `omitempty` with protobuf Timestamp in Golang

I have an optional field on my struct called ExpireTime. It has a time.Time type and a json:"expire_time,omitempty" tag to not send it, when it is empty. This part works perfectly fine.
When I want to use the same field via GRPC, I run into an issue when converting it to the protobuf timestamp format.
type Timestamp struct {
// Represents seconds of UTC time since Unix epoch
// 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
// 9999-12-31T23:59:59Z inclusive.
Seconds int64 `protobuf:"varint,1,opt,name=seconds,proto3" json:"seconds,omitempty"`
// Non-negative fractions of a second at nanosecond resolution. Negative
// second values with fractions must still have non-negative nanos values
// that count forward in time. Must be from 0 to 999,999,999
// inclusive.
Nanos int32 `protobuf:"varint,2,opt,name=nanos,proto3" json:"nanos,omitempty"`
// contains filtered or unexported fields
}
ExpireTime *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=expire_time,json=expireTime,proto3" json:"expire_time,omitempty"`
The issue is that an empty time.Time{} object will be converted to a negative seconds value corresponding to 0001-01-01T00:00:00Z. Having the omitEmpty flag will not be applied in this case as the value is not zeroed out. What could I do to omit this field, when it is actually empty? Thanks!
As you say time.Time{} converts to 0001-01-01T00:00:00Z; this is working as intended. Note that you also need to be careful converting in the opposite direction (a zero TimeStamp will become 1970-01-01T00:00:00Z).
However generally the Timestamp will be part of a message, for example:
message MyMessage{
google.protobuf.Timestamp comm_time = 1;
}
Running this through protoc will result in something like:
type MyMessage struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
CommTime *timestamppb.Timestamp `protobuf:"bytes, 1,opt,name=comm_time,json=commTime,proto3" json:"comm_time,omitempty"`
}
This means you should be able to achieve the result you are looking for with CommTime=nil; e.g.
sourceTime := time.Time{} // Whatever time you want to encode
var commTime *timestamp.Timestamp
if !sourceTime.IsZero() {
commTime = timestamppb.New(sourceTime)
}
msg := MyMessage{
CommTime: commTime,
}

Is there a way to extract a protobuf oneof int value?

TL;DR: In Go, is there any way to get the integer value of a protobuf oneof case?
Detail:
In C# I can easily query the integer value of a Oneof case using something like the following:
opcode = (int)ChannelMessage.ChannelActionOneofCase.Register; // opcode will equal 1
However in Golang, there does not appear to be anything that I can use to easily extract that integer value.
I know that I can switch on the type itself:
switch m.ChannelAction.(type) {
case *proto.ChannelMessage_Register:
...
however in my case this will require me to unmarshal every message, which for certain types isn't strictly necessary since I'm required to send the opcode along every time.
If it's helpful, my ChannelMessage type looks like the following:
message ChannelMessage
{
oneof ChannelAction
{
ChannelRegister register = 1;
ChannelUnregister unregister = 2;
...
}
}
It's probably not what you want to actually do, but the google.golang.org/protobuf/reflect/protoreflect package does have the necessary functions, if you need to refer to the field numbers of the fields that are part of your oneof.
For example, assuming you've imported your protos as pb, to get the number 1 by name (as in your C# example) you can do:
desc := (&pb.ChannelMessage{}).ProtoReflect().Descriptor()
opcode := desc.Fields().ByName("register").Number()
(This isn't strictly specific to the oneof, since oneof fields are really just regular message fields with an additional constraint that only one of them may be set.)
Or to figure out which field number a oneof field is set to in message m without writing out a type switch, assuming you know one of them has definitely been set, you can do:
ref := m.ProtoReflect()
desc := ref.Descriptor()
num := ref.WhichOneof(desc.Oneofs().ByName("ChannelAction")).Number()
In both cases the result (opcode, num) will be a numeric type (protoreflect.FieldNumber = protowire.Number) that has an underlying type of int32 you can convert it to.
You are right, you can do that with type switch:
// my example used simple strings instead of custom messages.
example := proto.ChannelMessage{
ChannelAction: &pbExample.ChannelMessage_Register{"foobar"},
}
t := example.GetChannelAction()
switch v := t.(type) {
case *pbExample.ChannelMessage_Register:
fmt.Printf("register\n")
case *pbExample.ChannelMessage_Unregister:
fmt.Printf("unregister\n")
default:
fmt.Printf("I don't know about type %T!\n", v)
}
// what you also can do is to ask directly your oneOf case and try to typecast it.
val, ok := example.GetRegister().(int) // GetUnregister is other option.
if ok {
// black magic happens here
}

Check if every item in a struct is unchanged

I have the following package:
// Contains state read in from the command line
type State struct {
Domain string // Domain to check for
DomainList string // File location for a list of domains
OutputNormal string // File to output in normal format
OutputDomains string // File to output domains only to
Verbose bool // Verbose prints, incl. Debug information
Threads int // Number of threads to use
NoColour bool // Strip colour from output
Silent bool // Output domains only
Usage bool // Print usage information
}
func InitState() (state State) {
return State { "", "", "", "", false, 20, false, false, false }
}
func ValidateState(s *State) (result bool, error string ) {
if s.Domain == "" && s.DomainList == "" {
return false, "You must specify either a domain or list of domains to test"
}
return true, ""
}
Within ValidateState() I would like to return true if every item in State is the same as what is defined in InitState(). I can see a few ways to do this, but nothing that seems concise. I would greatly value some direction!
Struct values are comparable if all their fields are comparable (see Spec: Comparison operators). And since in your case this holds, we can take advantage of this.
In your case the simplest and most efficient way to achieve this is to save a struct value holding the initial value, and whenever you want to tell if a struct value (if any of its fields) has changed, simply compare it to the saved, initial value. This is all it takes:
var defaultState = InitState()
func isUnchanged(s State) bool {
return s == defaultState
}
Testing it:
s := InitState()
fmt.Println(isUnchanged(s))
s.Threads = 1
fmt.Println(isUnchanged(s))
Output (try it on the Go Playground):
true
false
Note that this solution will still work without any modification if you change the State type by adding / removing / renaming / rearranging fields as long as they all will still be comparable. As a counter example, if you add a field of slice type, it won't work anymore as slices are not comparable. It will result in a compile-time error. To handle such cases, reflect.DeepEqual() might be used instead of the simple == comparison operator.
Also note that you should create default values of State like this:
func NewState() State {
return State{Threads: 20}
}
You don't have to list fields whose values are the zero values of their types.

In Go, is there any way to compare two mixed-type interfaces without nested switch statements?

Go's interface{} type is both the best and most annoying feature of the language, I find. I'm trying to create a simple user-customisable validation rule solution where the user can define:
The comparison operator.
The comparison operand.
The map key that leads to the value to test.
As well as a simple Boolean expression parser that allows the user to combine multiple rules using AND and OR. So far it all works well, the expressions can be parsed, tokenised, and evaluated successfully, but it's running the rules on the given data that causes problems.
This is the current version of the function that actually evaluates the data:
/*
validate returns a boolean value denoting whether a test was successful. This
function will panic if the type assertions fail.
*/
func (sfvre standardFieldValidationRuleEntry) validate(fieldValue interface{}) bool {
switch sfvre.Operator() {
case VROP_EQUAL:
return fieldValue == sfvre.ComparisonOperand()
case VROP_NEQUAL:
return fieldValue != sfvre.ComparisonOperand()
case VROP_GT:
return fieldValue.(int) > sfvre.ComparisonOperand().(int)
case VROP_LT:
return fieldValue.(int) < sfvre.ComparisonOperand().(int)
case VROP_GTET:
return fieldValue.(int) >= sfvre.ComparisonOperand().(int)
case VROP_LTET:
return fieldValue.(int) <= sfvre.ComparisonOperand().(int)
case VROP_CONTAINS:
return strings.Contains(fieldValue.(string), sfvre.ComparisonOperand().(string))
case VROP_NCONTAINS:
return !strings.Contains(fieldValue.(string), sfvre.ComparisonOperand().(string))
default:
return false
}
}
At the moment the operator implies whether the data is numeric (greater than, less than, etc.). The type assertion to int did the job while building the other parts of the package, but the finished system should also be able to take float64 and be able to handle mixed type comparisons.
The only way I can see of doing this at the moment is by having multiple nested type switches, a level for each of:
The operator.
The type of the field value given.
The type of the comparison operand.
But this has the potential to become very large and not easily manageable. Is there a 'cleaner' way to do this that I can't see, or am I stuck using nested switches?
The solution I've got as of now (thanks to #Volker for the suggestion) does a quick type switch on the values that need comparing and then instead of using the originals in the Operator() switch, it uses the concrete float values:
/*
validate returns a boolean value denoting whether a test was successful. This
function will panic if the type assertions fail.
*/
func (sfvre standardFieldValidationRuleEntry) validate(fieldValue interface{}) bool {
var floatFieldVal, floatCompVal float64
//If the interface is int or float, convert it to a statically typed float64.
switch fieldValue.(type) {
case int:
floatFieldVal = float64(fieldValue.(int))
case float64:
floatFieldVal = fieldValue.(float64)
}
//Do the same with the comparison value.
switch sfvre.ComparisonOperand().(type) {
case int:
floatCompVal = float64(sfvre.ComparisonOperand().(int))
case float64:
floatCompVal = sfvre.ComparisonOperand().(float64)
}
switch sfvre.Operator() {
case VROP_EQUAL:
return fieldValue == sfvre.ComparisonOperand()
case VROP_NEQUAL:
return fieldValue != sfvre.ComparisonOperand()
case VROP_GT:
return floatFieldVal > floatCompVal
case VROP_LT:
return floatFieldVal < floatCompVal
case VROP_GTET:
return floatFieldVal >= floatCompVal
case VROP_LTET:
return floatFieldVal <= floatCompVal
case VROP_CONTAINS:
return strings.Contains(fieldValue.(string), sfvre.ComparisonOperand().(string))
case VROP_NCONTAINS:
return !strings.Contains(fieldValue.(string), sfvre.ComparisonOperand().(string))
default:
return false
}
}
It doesn't catch everything, but restricting what operators the user can choose based on what field they're comparing can mitigate this, but that's part of the larger solution so irrelevant here.

Get index of element from array / slice or key of value from map in Go?

I have an enumerated list of strings (which are constant, e.g. a list of countries), that I'd like to be able to get the string when providing the enumerated int value, and vice-versa be able to get the enumerated int value when providing the string. This is in order to translate between the two for database transactions.
var MyData = [...]string {
"string1", // index 0
"string2", // index 1
"string3", // index 2
}
That's easy for a language like python, where one can just do something like MyData[1] to get "string2" and MyData.index("string2") to get 1.
A few possible solutions would be to
write my own function to get the index by iterating over the array / slice
sort the array / slice and use a search function to return index (though this doesn't allow for an unsorted sequence, which is what I'd prefer)
maintain a map and an array that mirror each other, which is prone to errors.
Speaking of maps, can one access the key of a particular value? Then I could simply have a map like the following, and be able to get the string key when providing the int value.
var MyData = map[string]int {
"string1": 0,
"string2": 1,
"string3": 2,
}
UPDATE: Before I accept my answer, I want to explain the problem more thoroughly, which I know must be fairly common. I basically have a set of strings that are constant (such as a list of countries) each with an associated integer value. In my database I simply store the integer to conserve space, since there are millions of entries. But when I display an entry from the database I need to display the string value for it to be readable to a user. A simple array will do for that. However, I also need to add entries to the database (such as a new person and their country of residence) and in this scenario need to translate from the country string which is entered in a form to that integer value. Again, this is just an example use case, but the goal remains the same. I need a table that can translate in both directions between a string value and an enumerated int value. The most obvious thing to do is to maintain an array (for the int to string translation) and a map (for the string to int translation). I'd prefer not to manually maintain both variables, since this is prone to errors. So my solution below is to maintain just a single array, and have the constructor method automatically build the map at runtime when the program is first run. This has the advantage of not needing to iterate over the entire array when I fetch the integer value based on the string (which was the other proposed solution).
In both cases you should just use the built in range function.
for k, v := range MyData {
}
for i, v := range ThisArray {
}
for i, _ := range ThisArrayIndexOnly {
value := ThisArrayIndexOnly[i]
}
You can build helper functions or whatever you like on top of this but range is fundamentally the mechanism available for accessing that data. If you want an "indexof" function it would be
for i, v := range ArrayPassedIntoFunction {
if v == ValuePassedIntoFunction {
return i
}
}
return -1
To get the value, you of course would just do MyArray[i] including a bounds check or whatever. Note the pseudo code above is written in a style that indicates it's an array but virtually the same code will work for a map, I would just typically use the var name k instead of i.
Assume you want getting index of word in the data of array
data := [...] {"one","two","three"}
or fixed length array
data := [3] {"one","two","three"}
create function
func indexOf(word string, data []string) (int) {
for k, v := range data {
if word == v {
return k
}
}
return -1
}
to get value from function above, to match the type, pass the array with array[:] like below
fmt.Println(indexOf("two", data[:]))
Here's a solution that I mentioned earlier, which works well for static slices (which is my use case). Iterating over the slice every time I want the index of a value adds unnecessary delay, especially since my data is static during runtime. This just creates a struct which initializes the slice and creates the corresponding inverse map. And then I would use the GetKey and GetVal methods to get either the string 'key' by providing the int 'value', or get the int 'value' by providing the string 'key'. Perhaps there's already a way to get the key of a particular value of a map in Go.
type MyData struct {
dataslice []string
datamap map[string]int
}
func NewMyData() *MyData {
m := new(MyData)
m.dataslice= []string {
"string1",
"string2",
"string3",
}
m.datamap = make(map[string]int)
for x := range m.dataslice {
m.datamap[m.dataslice[x]] = x
}
return m
}
func (m *MyData) GetKey(x int) string {
return m.dataslice[x]
}
func (m *MyData) GetVal(x string) int {
return m.datamap[x]
}

Resources