Closed
Description
CREATE TABLE t (key BLOB PRIMARY KEY);
INSERT INTO t VALUES ('abc');
In a nutshell, to execute last query following actions are performed:
1. OP_String8 r, 'abc' //Save constant string 'abc' to memory cell r
2. OP_ApplyType r, BLOB //Cast value in r to SCALAR type
3. OP_MakeRecord r, r1 //Encode value in r to msgpack and store to r1
4. OP_Insert r1, space(t) //Insert value of r1 to space(t)
At step 2 to convert value we are calling mem_apply_type() routine. If we want to convert string to scalar, next procedure is called:
366 case FIELD_TYPE_SCALAR:
367 if (record->flags & (MEM_Str | MEM_Blob))
368 record->flags |= MEM_Blob;
369 return 0;
So, in fact after type SCALAR is applied to STRING, value features both flags: MEM_Blob and MEM_Str.
And during msgpack encoding at stage 3, we set type of tuple format as MP_STR:
1714 void
1715 mpstream_encode_vdbe_mem(struct mpstream *stream, struct Mem *var)
1716 {
...
1740 } else if (var->flags & MEM_Str) {
1741 mpstream_encode_strn(stream, var->z, var->n);
Which is obviously wrong action, since after fetching value from tuple it will be treated as STRING (BLOB is detected as MP_BIN in tuple format). To resolve this problem, we should allow only one type-flag at once. Fix in this case is obvious, but it affects other type-related issues.