diff --git a/BUILD/mdbci/create_repo.sh b/BUILD/mdbci/create_repo.sh index f3a565ebf..127476b30 100755 --- a/BUILD/mdbci/create_repo.sh +++ b/BUILD/mdbci/create_repo.sh @@ -55,7 +55,7 @@ if [ $z_res -eq 127 ] && [ $y_res -eq 127 ] ; then exit 1 fi - gpg -abs -o dists/$dist_name/Release.gpg dists/$dist_name/Release + gpg -abs --digest-algo sha256 -o dists/$dist_name/Release.gpg dists/$dist_name/Release if [ $? != 0 ] ; then echo "Package signing failed!" exit 1 @@ -70,8 +70,7 @@ else sudo zypper -n install createrepo fi echo "%_signature gpg" >> ~/.rpmmacros - echo "%_gpg_name MariaDB Maxscale" >> ~/.rpmmacros -# echo "%_gpg_name MariaDBManager" >> ~/.rpmmacros + echo "%_gpg_name MariaDB Maxscale " >> ~/.rpmmacros echo "\r" | setsid rpm --resign $sourcedir/*.rpm if [ $? != 0 ] ; then diff --git a/BUILD/mdbci/remote_build.sh b/BUILD/mdbci/remote_build.sh index be02521f2..298068ea7 100755 --- a/BUILD/mdbci/remote_build.sh +++ b/BUILD/mdbci/remote_build.sh @@ -17,7 +17,7 @@ ssh $sshopt "sudo rm -rf $work_dir" echo "copying stuff to $image machine" ssh $sshopt "mkdir -p $work_dir" -rsync -avz --progress --delete -e "ssh $scpopt" ${script_dir}/../../* $sshuser@$IP:./$work_dir/ +rsync -avz --delete -e "ssh $scpopt" ${script_dir}/../../ $sshuser@$IP:./$work_dir/ if [ $? -ne 0 ] ; then echo "Error copying stuff to $box machine" exit 2 diff --git a/Documentation/About/Limitations.md b/Documentation/About/Limitations.md index a5e10e1c4..b84615e50 100644 --- a/Documentation/About/Limitations.md +++ b/Documentation/About/Limitations.md @@ -130,10 +130,11 @@ can be influenced with the server priority mechanic described in the ### Avrorouter limitations (avrorouter) -The avrorouter does not support the following data types and conversions: +The avrorouter does not support the following data types, conversions or SQL statements: * BIT * Fields CAST from integer types to string types +* [CREATE TABLE ... AS SELECT statements](https://mariadb.com/kb/en/library/create-table/#create-select) The avrorouter does not do any crash recovery. This means that the avro files need to be truncated to valid block lengths before starting the avrorouter. diff --git a/server/core/mysql_binlog.cc b/server/core/mysql_binlog.cc index c51fbbce6..899fa9225 100644 --- a/server/core/mysql_binlog.cc +++ b/server/core/mysql_binlog.cc @@ -402,6 +402,32 @@ static void unpack_time(uint8_t *ptr, struct tm *dest) dest->tm_sec = second; } +/** + * @brief Unpack a TIME2 + * + * The TIME2 is stored as a 3 byte value containing the integer parts plus + * the additional fractional parts as a trailing value. The + * integer parts of the time are extracted with the following algorithm: + * + * hours = (value >> 12) % (1 << 10) + * minutes = (value >> 6) % (1 << 6) + * seconds = value % (1 << 6) + * + * As the `struct tm` doesn't support fractional seconds, the fractional part + * is ignored. + * + * @param val Value read from the binary log + * @param dest Pointer where the unpacked value is stored + */ +static void unpack_time2(uint8_t *ptr, uint8_t decimals, struct tm *dest) +{ + uint64_t val = unpack3(ptr) - DATETIME2_OFFSET; + memset(dest, 0, sizeof(struct tm)); + dest->tm_hour = (val >> 12) % (1 << 10); + dest->tm_min = (val >> 6) % (1 << 6); + dest->tm_sec = val % (1 << 6); +} + /** * @brief Unpack a DATE value * @param ptr Pointer to packed value @@ -524,6 +550,10 @@ size_t unpack_temporal_value(uint8_t type, uint8_t *ptr, uint8_t *metadata, int unpack_time(ptr, tm); break; + case TABLE_COL_TYPE_TIME2: + unpack_time2(ptr, *metadata, tm); + break; + case TABLE_COL_TYPE_DATE: unpack_date(ptr, tm); break; diff --git a/server/modules/routing/avrorouter/avro_file.c b/server/modules/routing/avrorouter/avro_file.c index f497b0ac1..f1cc0f53d 100644 --- a/server/modules/routing/avrorouter/avro_file.c +++ b/server/modules/routing/avrorouter/avro_file.c @@ -909,6 +909,27 @@ bool is_create_like_statement(const char* ptr, size_t len) return strcasestr(sql, " like ") || strcasestr(sql, "(like "); } +bool is_create_as_statement(const char* ptr, size_t len) +{ + int err = 0; + char sql[len + 1]; + memcpy(sql, ptr, len); + sql[len] = '\0'; + const char* pattern = + // Case-insensitive mode + "(?i)" + // Main CREATE TABLE part (the \s is for any whitespace) + "create\\stable\\s" + // Optional IF NOT EXISTS + "(if\\snot\\sexists\\s)?" + // The table name with optional database name, both enclosed in optional backticks + "(`?\\S+`?.)`?\\S+`?\\s" + // And finally the AS keyword + "as"; + + return mxs_pcre2_simple_match(pattern, sql, 0, &err) == MXS_PCRE2_MATCH; +} + /** * @brief Detection of table alteration statements * @param router Avro router instance @@ -1025,6 +1046,15 @@ void handle_query_event(AVRO_INSTANCE *router, REP_HEADER *hdr, int *pending_tra { created = table_create_copy(router, sql, len, db); } + else if (is_create_as_statement(sql, len)) + { + static bool warn_create_as = true; + if (warn_create_as) + { + MXS_WARNING("`CREATE TABLE AS` is not yet supported, ignoring events to this table: %.*s", len, sql); + warn_create_as = false; + } + } else { created = table_create_alloc(sql, len, db); diff --git a/server/modules/routing/avrorouter/avro_rbr.c b/server/modules/routing/avrorouter/avro_rbr.c index 89f0e4182..01f52050d 100644 --- a/server/modules/routing/avrorouter/avro_rbr.c +++ b/server/modules/routing/avrorouter/avro_rbr.c @@ -544,16 +544,8 @@ uint8_t* process_row_event_data(TABLE_MAP *map, TABLE_CREATE *create, avro_value { uint8_t val[metadata[metadata_offset + 1]]; uint64_t bytes = unpack_enum(ptr, &metadata[metadata_offset], val); - char strval[32]; - - /** Right now only ENUMs/SETs with less than 256 values - * are printed correctly */ - snprintf(strval, sizeof(strval), "%hhu", val[0]); - if (bytes > 1 && warn_large_enumset) - { - warn_large_enumset = true; - MXS_WARNING("ENUM/SET values larger than 255 values aren't supported."); - } + char strval[bytes * 2 + 1]; + gw_bin2hex(strval, val, bytes); avro_value_set_string(&field, strval); MXS_INFO("[%ld] ENUM: %lu bytes", i, bytes); ptr += bytes; @@ -599,11 +591,9 @@ uint8_t* process_row_event_data(TABLE_MAP *map, TABLE_CREATE *create, avro_value else if (column_is_bit(map->column_types[i])) { uint64_t value = 0; - int width = metadata[metadata_offset] + metadata[metadata_offset + 1] * 8; - int bits_in_nullmap = MXS_MIN(width, extra_bits); - extra_bits -= bits_in_nullmap; - width -= bits_in_nullmap; - size_t bytes = width / 8; + uint8_t len = metadata[metadata_offset + 1]; + uint8_t bit_len = metadata[metadata_offset] > 0 ? 1 : 0; + size_t bytes = len + bit_len; // TODO: extract the bytes if (!warn_bit) @@ -675,7 +665,7 @@ uint8_t* process_row_event_data(TABLE_MAP *map, TABLE_CREATE *create, avro_value create->column_lengths[i], &tm); format_temporal_value(buf, sizeof(buf), map->column_types[i], &tm); avro_value_set_string(&field, buf); - MXS_INFO("[%ld] TEMPORAL: %s", i, buf); + MXS_INFO("[%ld] %s: %s", i, column_type_to_string(map->column_types[i]), buf); ss_dassert(ptr < end); } /** All numeric types (INT, LONG, FLOAT etc.) */