MXS-2263: Retain integer sign information
The unsignedness of a column is now retained in the Column type as well as the JSON schema. This allows correct conversion of unsigned integer types which will be done in a later commit.
This commit is contained in:
@ -231,7 +231,7 @@ char* json_new_schema_from_table(const STableMapEvent& map, const STableCreateEv
|
||||
json_array_append_new(array,
|
||||
json_pack_ex(&err,
|
||||
0,
|
||||
"{s:s, s:[s, s], s:s, s:i}",
|
||||
"{s:s, s:[s, s], s:s, s:i, s:b}",
|
||||
"name",
|
||||
create->columns[i].name.c_str(),
|
||||
"type",
|
||||
@ -240,7 +240,9 @@ char* json_new_schema_from_table(const STableMapEvent& map, const STableCreateEv
|
||||
"real_type",
|
||||
create->columns[i].type.c_str(),
|
||||
"length",
|
||||
create->columns[i].length));
|
||||
create->columns[i].length,
|
||||
"unsigned",
|
||||
create->columns[i].is_unsigned));
|
||||
}
|
||||
json_object_set_new(schema, "fields", array);
|
||||
char* rval = json_dumps(schema, JSON_PRESERVE_ORDER);
|
||||
|
@ -102,6 +102,11 @@ bool json_extract_field_names(const char* filename, std::vector<Column>& columns
|
||||
{
|
||||
MXS_WARNING("No \"length\" value defined. Treating as default length field.");
|
||||
}
|
||||
|
||||
if ((value = json_object_get(val, "unsigned")) && json_is_boolean(value))
|
||||
{
|
||||
columns.back().is_unsigned = json_boolean_value(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -77,6 +77,7 @@ json_t* Column::to_json() const
|
||||
json_object_set_new(obj, "name", json_string(name.c_str()));
|
||||
json_object_set_new(obj, "type", json_string(type.c_str()));
|
||||
json_object_set_new(obj, "length", json_integer(length));
|
||||
json_object_set_new(obj, "is_unsigned", json_boolean(is_unsigned));
|
||||
return obj;
|
||||
}
|
||||
|
||||
@ -85,14 +86,24 @@ Column Column::from_json(json_t* json)
|
||||
json_t* name = json_object_get(json, "name");
|
||||
json_t* type = json_object_get(json, "type");
|
||||
json_t* length = json_object_get(json, "length");
|
||||
json_t* is_unsigned = json_object_get(json, "is_unsigned");
|
||||
|
||||
if (name && json_is_string(name)
|
||||
&& type && json_is_string(type)
|
||||
&& length && json_is_integer(length))
|
||||
{
|
||||
// is_unsigned was added in 2.4.3
|
||||
bool sign = false;
|
||||
|
||||
if (is_unsigned && json_is_boolean(is_unsigned))
|
||||
{
|
||||
sign = json_boolean_value(is_unsigned);
|
||||
}
|
||||
|
||||
return Column(json_string_value(name),
|
||||
json_string_value(type),
|
||||
json_integer_value(length));
|
||||
json_integer_value(length),
|
||||
sign);
|
||||
}
|
||||
|
||||
// Invalid JSON, return empty Column
|
||||
@ -411,7 +422,7 @@ static const char* extract_field_name(const char* ptr, char* dest, size_t size)
|
||||
return ptr;
|
||||
}
|
||||
|
||||
int extract_type_length(const char* ptr, char* dest)
|
||||
int extract_type_length_sign(const char* ptr, char* dest, bool* is_unsigned)
|
||||
{
|
||||
/** Skip any leading whitespace */
|
||||
while (*ptr && (isspace(*ptr) || *ptr == '`'))
|
||||
@ -455,9 +466,26 @@ int extract_type_length(const char* ptr, char* dest)
|
||||
if (*end == ')')
|
||||
{
|
||||
rval = val;
|
||||
ptr = end + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/** Skip whitespace */
|
||||
while (*ptr && isspace(*ptr))
|
||||
{
|
||||
ptr++;
|
||||
}
|
||||
|
||||
const char UNSIGNED[] = "unsigned";
|
||||
const char ZEROFILL[] = "zerofill";
|
||||
|
||||
// Start of integer sign definition: https://mariadb.com/kb/en/library/int/
|
||||
if (strncasecmp(ptr, UNSIGNED, sizeof(UNSIGNED) - 1) == 0
|
||||
|| strncasecmp(ptr, ZEROFILL, sizeof(ZEROFILL) - 1) == 0)
|
||||
{
|
||||
*is_unsigned = true;
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
@ -486,10 +514,11 @@ static void process_column_definition(const char* nameptr, std::vector<Column>&
|
||||
while ((nameptr = extract_field_name(nameptr, colname, sizeof(colname))))
|
||||
{
|
||||
char type[100] = "";
|
||||
int len = extract_type_length(nameptr, type);
|
||||
bool is_unsigned = false;
|
||||
int len = extract_type_length_sign(nameptr, type, &is_unsigned);
|
||||
nameptr = next_field_definition(nameptr);
|
||||
fix_reserved_word(colname);
|
||||
columns.emplace_back(colname, type, len);
|
||||
columns.emplace_back(colname, type, len, is_unsigned);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1302,10 +1331,11 @@ bool Rpl::table_create_alter(STableCreateEvent create, const char* sql, const ch
|
||||
if (is_new)
|
||||
{
|
||||
char field_type[200] = ""; // Enough to hold all types
|
||||
int field_length = extract_type_length(tok + len, field_type);
|
||||
bool is_unsigned = false;
|
||||
int field_length = extract_type_length_sign(tok + len, field_type, &is_unsigned);
|
||||
create->columns.emplace_back(std::string(avro_token),
|
||||
std::string(field_type),
|
||||
field_length);
|
||||
field_length, is_unsigned);
|
||||
updates++;
|
||||
}
|
||||
tok = get_next_def(tok, end);
|
||||
@ -1338,10 +1368,14 @@ bool Rpl::table_create_alter(STableCreateEvent create, const char* sql, const ch
|
||||
char avro_token[len + 1];
|
||||
make_avro_token(avro_token, tok, len);
|
||||
char field_type[200] = ""; // Enough to hold all types
|
||||
int field_length = extract_type_length(tok + len, field_type);
|
||||
bool is_unsigned = false;
|
||||
int field_length = extract_type_length_sign(tok + len,
|
||||
field_type,
|
||||
&is_unsigned);
|
||||
it->name = avro_token;
|
||||
it->type = field_type;
|
||||
it->length = field_length;
|
||||
it->is_unsigned = is_unsigned;
|
||||
updates++;
|
||||
}
|
||||
}
|
||||
|
@ -56,16 +56,18 @@ struct gtid_pos_t
|
||||
/** A single column in a CREATE TABLE statement */
|
||||
struct Column
|
||||
{
|
||||
Column(std::string name, std::string type = "unknown", int length = -1)
|
||||
Column(std::string name, std::string type = "unknown", int length = -1, bool is_unsigned = false)
|
||||
: name(name)
|
||||
, type(type)
|
||||
, length(length)
|
||||
, is_unsigned(is_unsigned)
|
||||
{
|
||||
}
|
||||
|
||||
std::string name;
|
||||
std::string type;
|
||||
int length;
|
||||
bool is_unsigned;
|
||||
|
||||
json_t* to_json() const;
|
||||
static Column from_json(json_t* json);
|
||||
|
Reference in New Issue
Block a user