Conversation
7117b79 to
82b5a66
Compare
gkodinov
left a comment
There was a problem hiding this comment.
Thank you for your contribution! This is a preliminary review.
This fix needs more work IMHO. I've tried outlining some of it below.
But, this is a stuff for the final review anyway. For the preliminary review, please squash the two commits together.
| case JSON_VALUE_TRUE: | ||
| case JSON_VALUE_FALSE: | ||
| { | ||
| if (f->type_handler() == &type_handler_bit) |
There was a problem hiding this comment.
The expectation here is that JSON boolean values will store as integer 1/0 into "numeric" data types and as a string literal ("true"/"false") into "string" data types. However bit type is a special case: it can store integers but is not an integer.
This fix proposed is a workaround at best: what happens when the next data type that has different base result type is to receive a value of some other kind?
E.g. store a date? or some such. or if the bit data type is implemented as a pluggable type? Or even consider other operations that call Field->store() with a hybrid data type.
I believe a proper fix should involve one of:
- Come up with a "value store type" for data types and use that instead of the result type. Have bit report an int "value store type".
- Consider converting BIT to int result/cmp type altogether, since the longest boolean literal is 64 bits anyway
There was a problem hiding this comment.
Implemented your first suggestion in 17eaf8d6, and squashed the PR into one commit.
Type_handler::value_store_type() now expresses the preferred representation for values with numeric and string forms; BIT explicitly returns INT_RESULT, and JSON boolean conversion uses that policy. Numeric JSON text goes through a separate virtual Field::store_numeric() interface. Its default preserves existing field conversion, while BIT overrides it with charset-aware unsigned integer parsing and the existing range checks. JSON_TABLE no longer checks for a particular type handler, and data type implementations can override these interfaces.
On this 11.4 base, BIT already inherits integer result/comparison types, so its previous boolean special case was redundant. The actual regression is numeric JSON input. Regression coverage now includes BIT widths, uint64 boundaries, fractions/exponents, and boolean/string/null inputs, with other destination types as controls.
| } | ||
| break; | ||
| } | ||
| case JSON_VALUE_NUMBER: |
There was a problem hiding this comment.
This is unrelated to the topic of the bug. Make it abundantly clear in the commit message what is it that you're fixing here please.
There was a problem hiding this comment.
Rewrote the commit message and PR description to make the numeric conversion bug explicit. The MDEV-39969 report uses JSON numbers: [0,1] stored into BIT(1) produces [1,1]. The old path passes the decimal text to BIT's binary-string store; the byte for '0' is 48 and gets clipped to 1.
The numeric branch addresses that reported failure. Boolean-to-integer conversion already worked on this 11.4 base, and the revised message no longer presents it as the bug being fixed. The new regression fails on a separately built clean baseline and passes with the revision.
JSON_TABLE('[0,1]', '$[*]' COLUMNS (b BIT(1) PATH '$')) returns 1
for both JSON numbers because Field_bit::store(const char *, ...) treats
their decimal text as binary bytes. The byte for '0' is 48, which is
clipped to 1. The reported bug concerns numeric JSON values, not a
missing boolean-to-integer conversion.
Add a value_store_type policy, separate from the result, comparison and
protocol types. BIT explicitly selects integer storage for values with
both numeric and string forms. Use this policy for JSON booleans.
Add virtual Field::store_numeric for numeric values serialized as text.
Its default preserves the existing field conversion; BIT overrides it
using the charset-aware rounded unsigned integer parser and normal BIT
range checks. JSON_TABLE can now dispatch numbers without identifying
specific destination types. Keep JSON strings on their existing path.
Preserve the distinction between datatype conversion warnings and JSON
errors. Numeric overflow must not trigger NULL, DEFAULT or ERROR ON
ERROR; actual JSON structural errors continue to use those responses.
Extend json.json_table with bit widths and uint64 boundaries, fractions,
exponents, negative values and overflow, boolean/string/null inputs,
other destination types, and error responses in strict SQL mode.
Bug report: https://jira.mariadb.org/browse/MDEV-39969
b805654 to
17eaf8d
Compare
gkodinov
left a comment
There was a problem hiding this comment.
Thank you! LGTM. Please stand by for the final review.
BTW, are you testing some sort of a tool? I'd be very interested to find out more about it. Reach out to me on https://mariadb.zulipchat.com please in case you can share details.
JSON_TABLE('[0,1]', '$[*]' COLUMNS (b BIT(1) PATH '$'))returns 1 for both JSON numbers. The scalar helper passes their decimal text to BIT's binary-string store; the byte for'0'is 48, which is clipped to 1.Bug report: https://jira.mariadb.org/browse/MDEV-39969
Changes
Type_handler::value_store_type()for values with both numeric and string forms. It defaults to the existing result type; BIT explicitly selects integer storage. JSON boolean conversion uses this policy.Field::store_numeric()for numeric values serialized as text. The default delegates to the existing field conversion. BIT overrides it using the charset-aware rounded unsigned integer parser and the existing BIT range checks, including the full unsigned 64-bit range.NULL,DEFAULT, orERROR ON ERROR; JSON structural errors continue to use those responses. The scalar helper has no BIT-specific error output parameter.Regression coverage
The regression is in the existing
json.json_tabletest. It covers numeric 0/1, multiple bit widths, the unsigned 64-bit boundary, fractions and exponents, negative values and overflow, boolean/string/null inputs, and numeric/string/date destination controls. It also checks allON ERRORresponses, strict SQL mode, and genuine array/object errors.Validation
Built the revised code and a separate clean
11.4baseline atd10e5d726799b1cd57cc866f40aad68c720803dawith GCC 13 in Release mode.ON ERRORhandling.json.json_table,json.json_table_mysql,json.json_table_notembedded,main.func_json,main.type_bit,main.type_bit_innodb,main.type_int,main.type_uint,main.type_newdecimal,main.type_float, andmain.select.json.json_tableandjson.json_table_mysqlalso passed with--ps-protocol.--view-protocol.git diff --checkpassed.The complete existing JSON_TABLE tests have two pre-existing
--view-protocolfailures, reproduced on both the clean baseline and the revision: alatin1_bin/utf8mb4_bincollation expectation injson.json_table, and aDEFAULT NULL ON EMPTYserialization syntax error injson.json_table_mysql. The full regression suite and Windows builds were not run locally.