You've already forked mariadb-connector-c
mirror of
https://github.com/mariadb-corporation/mariadb-connector-c.git
synced 2025-08-07 02:42:49 +03:00
Merge branch '3.3-rpl' into 3.3
This commit is contained in:
0
.gitmodules
vendored
Normal file
0
.gitmodules
vendored
Normal file
@@ -107,10 +107,16 @@ extern const char *mariadb_client_errors[]; /* Error messages */
|
|||||||
#define CR_ERR_NET_WRITE 5014
|
#define CR_ERR_NET_WRITE 5014
|
||||||
#define CR_ERR_NET_UNCOMPRESS 5015
|
#define CR_ERR_NET_UNCOMPRESS 5015
|
||||||
#define CR_ERR_STMT_PARAM_CALLBACK 5016
|
#define CR_ERR_STMT_PARAM_CALLBACK 5016
|
||||||
|
#define CR_ERR_BINLOG_UNCOMPRESS 5017
|
||||||
|
#define CR_ERR_CHECKSUM_VERIFICATION_ERROR 5018
|
||||||
|
#define CR_ERR_UNSUPPORTED_BINLOG_FORMAT 5019
|
||||||
|
#define CR_UNKNOWN_BINLOG_EVENT 5020
|
||||||
|
#define CR_BINLOG_ERROR 5021
|
||||||
|
#define CR_BINLOG_INVALID_FILE 5022
|
||||||
|
|
||||||
/* Always last, if you add new error codes please update the
|
/* Always last, if you add new error codes please update the
|
||||||
value for CR_MARIADB_LAST_ERROR */
|
value for CR_MARIADB_LAST_ERROR */
|
||||||
#define CR_MARIADB_LAST_ERROR CR_ERR_STMT_PARAM_CALLBACK
|
#define CR_MARIADB_LAST_ERROR CR_BINLOG_INVALID_FILE
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
64
include/ma_decimal.h
Normal file
64
include/ma_decimal.h
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
/* Copyright (C) 2000 Sergei Golubchik
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _decimal_h
|
||||||
|
#define _decimal_h
|
||||||
|
|
||||||
|
typedef enum {TRUNCATE=0, HALF_EVEN, HALF_UP, CEILING, FLOOR} decimal_round_mode;
|
||||||
|
typedef int32 decimal_digit;
|
||||||
|
|
||||||
|
typedef struct st_decimal {
|
||||||
|
int intg, frac, len;
|
||||||
|
my_bool sign;
|
||||||
|
decimal_digit *buf;
|
||||||
|
} decimal;
|
||||||
|
|
||||||
|
int decimal2string(decimal *from, char *to, int *to_len);
|
||||||
|
int bin2decimal(const char *from, decimal *to, int precision, int scale);
|
||||||
|
|
||||||
|
int decimal_size(int precision, int scale);
|
||||||
|
int decimal_bin_size(int precision, int scale);
|
||||||
|
int decimal_result_size(decimal *from1, decimal *from2, char op, int param);
|
||||||
|
|
||||||
|
|
||||||
|
/* set a decimal to zero */
|
||||||
|
|
||||||
|
#define decimal_make_zero(dec) do { \
|
||||||
|
(dec)->buf[0]=0; \
|
||||||
|
(dec)->intg=1; \
|
||||||
|
(dec)->frac=0; \
|
||||||
|
(dec)->sign=0; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
returns the length of the buffer to hold string representation
|
||||||
|
of the decimal (including decimal dot, possible sign and \0)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define decimal_string_size(dec) ((dec)->intg + (dec)->frac + ((dec)->frac > 0) + 2)
|
||||||
|
|
||||||
|
/* negate a decimal */
|
||||||
|
#define decimal_neg(dec) do { (dec)->sign^=1; } while(0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
conventions:
|
||||||
|
|
||||||
|
decimal_smth() == 0 -- everything's ok
|
||||||
|
decimal_smth() <= 1 -- result is usable, but precision loss is possible
|
||||||
|
decimal_smth() <= 2 -- result can be unusable, most significant digits
|
||||||
|
could've been lost
|
||||||
|
decimal_smth() > 2 -- no result was generated
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define E_DEC_OK 0
|
||||||
|
#define E_DEC_TRUNCATED 1
|
||||||
|
#define E_DEC_OVERFLOW 2
|
||||||
|
#define E_DEC_DIV_ZERO 4
|
||||||
|
#define E_DEC_BAD_NUM 8
|
||||||
|
#define E_DEC_OOM 16
|
||||||
|
|
||||||
|
#define E_DEC_ERROR 31
|
||||||
|
#define E_DEC_FATAL_ERROR 30
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@@ -749,6 +749,7 @@ typedef char bool; /* Ordinary boolean values 0 1 */
|
|||||||
/* Optimized store functions for Intel x86 */
|
/* Optimized store functions for Intel x86 */
|
||||||
#define int1store(T,A) *((int8*) (T)) = (A)
|
#define int1store(T,A) *((int8*) (T)) = (A)
|
||||||
#define uint1korr(A) (*(((uint8*)(A))))
|
#define uint1korr(A) (*(((uint8*)(A))))
|
||||||
|
#define sint1korr(A) (*(((int8*)(A))))
|
||||||
#if defined(__i386__) || defined(_WIN32)
|
#if defined(__i386__) || defined(_WIN32)
|
||||||
#define sint2korr(A) (*((int16 *) (A)))
|
#define sint2korr(A) (*((int16 *) (A)))
|
||||||
#define sint3korr(A) ((int32) ((((uchar) (A)[2]) & 128) ? \
|
#define sint3korr(A) ((int32) ((((uchar) (A)[2]) & 128) ? \
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2018-2021 MariaDB Corporation AB
|
/* Copyright (C) 2018-2022 MariaDB Corporation AB
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
This library is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU Library General Public
|
modify it under the terms of the GNU Library General Public
|
||||||
@@ -22,9 +22,14 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <ma_global.h>
|
||||||
|
#include <mariadb/ma_io.h>
|
||||||
|
|
||||||
#define MARIADB_RPL_VERSION 0x0001
|
#define MARIADB_RPL_VERSION 0x0002
|
||||||
#define MARIADB_RPL_REQUIRED_VERSION 0x0001
|
#define MARIADB_RPL_REQUIRED_VERSION 0x0002
|
||||||
|
|
||||||
|
#define RPL_BINLOG_MAGIC (const uchar*) "\xFE\x62\x69\x6E"
|
||||||
|
#define RPL_BINLOG_MAGIC_SIZE 4
|
||||||
|
|
||||||
/* Protocol flags */
|
/* Protocol flags */
|
||||||
#define MARIADB_RPL_BINLOG_DUMP_NON_BLOCK 1
|
#define MARIADB_RPL_BINLOG_DUMP_NON_BLOCK 1
|
||||||
@@ -33,10 +38,37 @@ extern "C" {
|
|||||||
|
|
||||||
#define EVENT_HEADER_OFS 20
|
#define EVENT_HEADER_OFS 20
|
||||||
|
|
||||||
#define FL_GROUP_COMMIT_ID 2
|
|
||||||
#define FL_STMT_END 1
|
#define FL_STMT_END 1
|
||||||
|
|
||||||
#define LOG_EVENT_ARTIFICIAL_F 0x20
|
/* GTID flags */
|
||||||
|
|
||||||
|
/* FL_STANDALONE is set in case there is no terminating COMMIT event. */
|
||||||
|
#define FL_STANDALONE 0x01
|
||||||
|
|
||||||
|
/* FL_GROUP_COMMIT_ID is set when event group is part of a group commit */
|
||||||
|
#define FL_GROUP_COMMIT_ID 0x02
|
||||||
|
|
||||||
|
/* FL_TRANSACTIONAL is set for an event group that can be safely rolled back
|
||||||
|
(no MyISAM, eg.).
|
||||||
|
*/
|
||||||
|
#define FL_TRANSACTIONAL 0x04
|
||||||
|
/*
|
||||||
|
FL_ALLOW_PARALLEL reflects the (negation of the) value of
|
||||||
|
@@SESSION.skip_parallel_replication at the time of commit.
|
||||||
|
*/
|
||||||
|
#define FL_ALLOW_PARALLEL 0x08;
|
||||||
|
/*
|
||||||
|
FL_WAITED is set if a row lock wait (or other wait) is detected during the
|
||||||
|
execution of the transaction.
|
||||||
|
*/
|
||||||
|
#define FL_WAITED 0x10
|
||||||
|
/* FL_DDL is set for event group containing DDL. */
|
||||||
|
#define FL_DDL 0x20
|
||||||
|
/* FL_PREPARED_XA is set for XA transaction. */
|
||||||
|
#define FL_PREPARED_XA 0x40
|
||||||
|
/* FL_"COMMITTED or ROLLED-BACK"_XA is set for XA transaction. */
|
||||||
|
#define FL_COMPLETED_XA 0x80
|
||||||
|
|
||||||
|
|
||||||
/* SEMI SYNCHRONOUS REPLICATION */
|
/* SEMI SYNCHRONOUS REPLICATION */
|
||||||
#define SEMI_SYNC_INDICATOR 0xEF
|
#define SEMI_SYNC_INDICATOR 0xEF
|
||||||
@@ -50,7 +82,12 @@ enum mariadb_rpl_option {
|
|||||||
MARIADB_RPL_FLAGS, /* Protocol flags */
|
MARIADB_RPL_FLAGS, /* Protocol flags */
|
||||||
MARIADB_RPL_GTID_CALLBACK, /* GTID callback function */
|
MARIADB_RPL_GTID_CALLBACK, /* GTID callback function */
|
||||||
MARIADB_RPL_GTID_DATA, /* GTID data */
|
MARIADB_RPL_GTID_DATA, /* GTID data */
|
||||||
MARIADB_RPL_BUFFER
|
MARIADB_RPL_BUFFER,
|
||||||
|
MARIADB_RPL_VERIFY_CHECKSUM,
|
||||||
|
MARIADB_RPL_UNCOMPRESS,
|
||||||
|
MARIADB_RPL_HOST,
|
||||||
|
MARIADB_RPL_PORT,
|
||||||
|
MARIADB_RPL_EXTRACT_VALUES
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Event types: From MariaDB Server sql/log_event.h */
|
/* Event types: From MariaDB Server sql/log_event.h */
|
||||||
@@ -125,6 +162,139 @@ enum mariadb_rpl_event {
|
|||||||
ENUM_END_EVENT /* end marker */
|
ENUM_END_EVENT /* end marker */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* ROWS_EVENT flags */
|
||||||
|
|
||||||
|
#define STMT_END_F 0x01
|
||||||
|
#define NO_FOREIGN_KEY_CHECKS_F 0x02
|
||||||
|
#define RELAXED_UNIQUE_KEY_CHECKS_F 0x04
|
||||||
|
#define COMPLETE_ROWS_F 0x08
|
||||||
|
#define NO_CHECK_CONSTRAINT_CHECKS_F 0x80
|
||||||
|
|
||||||
|
|
||||||
|
enum mariadb_rpl_status_code {
|
||||||
|
Q_FLAGS2_CODE= 0x00,
|
||||||
|
Q_SQL_MODE_CODE= 0x01,
|
||||||
|
Q_CATALOG_CODE= 0x02,
|
||||||
|
Q_AUTO_INCREMENT_CODE= 0x03,
|
||||||
|
Q_CHARSET_CODE= 0x04,
|
||||||
|
Q_TIMEZONE_CODE= 0x05,
|
||||||
|
Q_CATALOG_NZ_CODE= 0x06,
|
||||||
|
Q_LC_TIME_NAMES_CODE= 0x07,
|
||||||
|
Q_CHARSET_DATABASE_CODE= 0x08,
|
||||||
|
Q_TABLE_MAP_FOR_UPDATE_CODE= 0x09,
|
||||||
|
Q_MASTER_DATA_WRITTEN_CODE= 0x0A,
|
||||||
|
Q_INVOKERS_CODE= 0x0B,
|
||||||
|
Q_UPDATED_DB_NAMES_CODE= 0x0C,
|
||||||
|
Q_MICROSECONDS_CODE= 0x0D,
|
||||||
|
Q_COMMIT_TS_CODE= 0x0E, /* unused */
|
||||||
|
Q_COMMIT_TS2_CODE= 0x0F, /* unused */
|
||||||
|
Q_EXPLICIT_DEFAULTS_FOR_TIMESTAMP_CODE= 0x10,
|
||||||
|
Q_DDL_LOGGED_WITH_XID_CODE= 0x11,
|
||||||
|
Q_DEFAULT_COLLATION_FOR_UTF8_CODE= 0x12,
|
||||||
|
Q_SQL_REQUIRE_PRIMARY_KEY_CODE= 0x13,
|
||||||
|
Q_DEFAULT_TABLE_ENCRYPTION_CODE= 0x14,
|
||||||
|
Q_HRNOW= 128, /* second part: 3 bytes */
|
||||||
|
Q_XID= 129 /* xid: 8 bytes */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum opt_metadata_field_type
|
||||||
|
{
|
||||||
|
SIGNEDNESS = 1,
|
||||||
|
DEFAULT_CHARSET,
|
||||||
|
COLUMN_CHARSET,
|
||||||
|
COLUMN_NAME,
|
||||||
|
SET_STR_VALUE,
|
||||||
|
ENUM_STR_VALUE,
|
||||||
|
GEOMETRY_TYPE,
|
||||||
|
SIMPLE_PRIMARY_KEY,
|
||||||
|
PRIMARY_KEY_WITH_PREFIX,
|
||||||
|
ENUM_AND_SET_DEFAULT_CHARSET,
|
||||||
|
ENUM_AND_SET_COLUMN_CHARSET
|
||||||
|
};
|
||||||
|
|
||||||
|
/* QFLAGS2 codes */
|
||||||
|
#define OPTION_AUTO_IS_NULL 0x00040000
|
||||||
|
#define OPTION_NOT_AUTOCOMMIT 0x00080000
|
||||||
|
#define OPTION_NO_FOREIGN_KEY_CHECKS 0x04000000
|
||||||
|
#define OPTION_RELAXED_UNIQUE_CHECKS 0x08000000
|
||||||
|
|
||||||
|
/* SQL modes */
|
||||||
|
#define MODE_REAL_AS_FLOAT 0x00000001
|
||||||
|
#define MODE_PIPES_AS_CONCAT 0x00000002
|
||||||
|
#define MODE_ANSI_QUOTES 0x00000004
|
||||||
|
#define MODE_IGNORE_SPACE 0x00000008
|
||||||
|
#define MODE_NOT_USED 0x00000010
|
||||||
|
#define MODE_ONLY_FULL_GROUP_BY 0x00000020
|
||||||
|
#define MODE_NO_UNSIGNED_SUBTRACTION 0x00000040
|
||||||
|
#define MODE_NO_DIR_IN_CREATE 0x00000080
|
||||||
|
#define MODE_POSTGRESQL 0x00000100
|
||||||
|
#define MODE_ORACLE 0x00000200
|
||||||
|
#define MODE_MSSQL 0x00000400
|
||||||
|
#define MODE_DB2 0x00000800
|
||||||
|
#define MODE_MAXDB 0x00001000
|
||||||
|
#define MODE_NO_KEY_OPTIONS 0x00002000
|
||||||
|
#define MODE_NO_TABLE_OPTIONS 0x00004000
|
||||||
|
#define MODE_NO_FIELD_OPTIONS 0x00008000
|
||||||
|
#define MODE_MYSQL323 0x00010000
|
||||||
|
#define MODE_MYSQL40 0x00020000
|
||||||
|
#define MODE_ANSI 0x00040000
|
||||||
|
#define MODE_NO_AUTO_VALUE_ON_ZERO 0x00080000
|
||||||
|
#define MODE_NO_BACKSLASH_ESCAPES 0x00100000
|
||||||
|
#define MODE_STRICT_TRANS_TABLES 0x00200000
|
||||||
|
#define MODE_STRICT_ALL_TABLES 0x00400000
|
||||||
|
#define MODE_NO_ZERO_IN_DATE 0x00800000
|
||||||
|
#define MODE_NO_ZERO_DATE 0x01000000
|
||||||
|
#define MODE_INVALID_DATES 0x02000000
|
||||||
|
#define MODE_ERROR_FOR_DIVISION_BY_ZERO 0x04000000
|
||||||
|
#define MODE_TRADITIONAL 0x08000000
|
||||||
|
#define MODE_NO_AUTO_CREATE_USER 0x10000000
|
||||||
|
#define MODE_HIGH_NOT_PRECEDENCE 0x20000000
|
||||||
|
#define MODE_NO_ENGINE_SUBSTITUTION 0x40000000
|
||||||
|
#define MODE_PAD_CHAR_TO_FULL_LENGTH 0x80000000
|
||||||
|
|
||||||
|
/* Log Event flags */
|
||||||
|
|
||||||
|
/* used in FOMRAT_DESCRIPTION_EVENT. Indicates if it
|
||||||
|
is the active binary log.
|
||||||
|
Note: When reading data via COM_BINLOG_DUMP this
|
||||||
|
flag is never set.
|
||||||
|
*/
|
||||||
|
#define LOG_EVENT_BINLOG_IN_USE_F 0x0001
|
||||||
|
|
||||||
|
/* Looks like this flag is no longer in use */
|
||||||
|
#define LOG_EVENT_FORCED_ROTATE_F 0x0002
|
||||||
|
|
||||||
|
/* Log entry depends on thread, e.g. when using user variables
|
||||||
|
or temporary tables */
|
||||||
|
#define LOG_EVENT_THREAD_SPECIFIC_F 0x0004
|
||||||
|
|
||||||
|
/* Indicates that the USE command can be suppressed before
|
||||||
|
executing a statement: e.g. DRIP SCHEMA */
|
||||||
|
#define LOG_EVENT_SUPPRESS_USE_F 0x0008
|
||||||
|
|
||||||
|
/* ??? */
|
||||||
|
#define LOG_EVENT_UPDATE_TABLE_MAP_F 0x0010
|
||||||
|
|
||||||
|
/* Artifical event */
|
||||||
|
#define LOG_EVENT_ARTIFICIAL_F 0x0020
|
||||||
|
|
||||||
|
/* ??? */
|
||||||
|
#define LOG_EVENT_RELAY_LOG_F 0x0040
|
||||||
|
|
||||||
|
/* If an event is not supported, and LOG_EVENT_IGNORABLE_F was not
|
||||||
|
set, an error will be reported. */
|
||||||
|
#define LOG_EVENT_IGNORABLE_F 0x0080
|
||||||
|
|
||||||
|
/* ??? */
|
||||||
|
#define LOG_EVENT_NO_FILTER_F 0x0100
|
||||||
|
|
||||||
|
/* ?? */
|
||||||
|
#define LOG_EVENT_MTS_ISOLATE_F 0x0200
|
||||||
|
|
||||||
|
/* if session variable @@skip_repliation was set, this flag will be
|
||||||
|
reported for events which should be skipped. */
|
||||||
|
#define LOG_EVENT_SKIP_REPLICATION_F 0x8000
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char *str;
|
char *str;
|
||||||
size_t length;
|
size_t length;
|
||||||
@@ -143,22 +313,52 @@ typedef struct st_mariadb_gtid {
|
|||||||
unsigned long long sequence_nr;
|
unsigned long long sequence_nr;
|
||||||
} MARIADB_GTID;
|
} MARIADB_GTID;
|
||||||
|
|
||||||
|
|
||||||
/* Generic replication handle */
|
/* Generic replication handle */
|
||||||
typedef struct st_mariadb_rpl {
|
typedef struct st_mariadb_rpl {
|
||||||
unsigned int version;
|
unsigned int version;
|
||||||
MYSQL *mysql;
|
MYSQL *mysql;
|
||||||
char *filename;
|
char *filename;
|
||||||
uint32_t filename_length;
|
uint32_t filename_length;
|
||||||
unsigned char *buffer;
|
|
||||||
unsigned long buffer_size;
|
|
||||||
uint32_t server_id;
|
uint32_t server_id;
|
||||||
unsigned long start_position;
|
unsigned long start_position;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
uint8_t fd_header_len; /* header len from last format description event */
|
uint8_t fd_header_len; /* header len from last format description event */
|
||||||
uint8_t use_checksum;
|
uint8_t use_checksum;
|
||||||
uint8_t artificial_checksun;
|
uint8_t artificial_checksun;
|
||||||
|
uint8_t verify_checksum;
|
||||||
|
uint8_t post_header_len[ENUM_END_EVENT];
|
||||||
|
MA_FILE *fp;
|
||||||
|
uint32_t error_no;
|
||||||
|
char error_msg[MYSQL_ERRMSG_SIZE];
|
||||||
|
uint8_t uncompress;
|
||||||
|
char *host;
|
||||||
|
uint32_t port;
|
||||||
|
uint8_t extract_values;
|
||||||
|
char nonce[12];
|
||||||
|
uint8_t encrypted;
|
||||||
} MARIADB_RPL;
|
} MARIADB_RPL;
|
||||||
|
|
||||||
|
typedef struct st_mariadb_rpl_value {
|
||||||
|
enum enum_field_types field_type;
|
||||||
|
uint8_t is_null;
|
||||||
|
uint8_t is_signed;
|
||||||
|
union {
|
||||||
|
int64_t ll;
|
||||||
|
uint64_t ull;
|
||||||
|
float f;
|
||||||
|
double d;
|
||||||
|
MYSQL_TIME tm;
|
||||||
|
MARIADB_STRING str;
|
||||||
|
} val;
|
||||||
|
} MARIADB_RPL_VALUE;
|
||||||
|
|
||||||
|
typedef struct st_rpl_mariadb_row {
|
||||||
|
uint32_t column_count;
|
||||||
|
MARIADB_RPL_VALUE *columns;
|
||||||
|
struct st_rpl_mariadb_row *next;
|
||||||
|
} MARIADB_RPL_ROW;
|
||||||
|
|
||||||
/* Event header */
|
/* Event header */
|
||||||
struct st_mariadb_rpl_rotate_event {
|
struct st_mariadb_rpl_rotate_event {
|
||||||
unsigned long long position;
|
unsigned long long position;
|
||||||
@@ -174,6 +374,10 @@ struct st_mariadb_rpl_query_event {
|
|||||||
MARIADB_STRING statement;
|
MARIADB_STRING statement;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct st_mariadb_rpl_previous_gtid_event {
|
||||||
|
MARIADB_CONST_DATA content;
|
||||||
|
};
|
||||||
|
|
||||||
struct st_mariadb_rpl_gtid_list_event {
|
struct st_mariadb_rpl_gtid_list_event {
|
||||||
uint32_t gtid_cnt;
|
uint32_t gtid_cnt;
|
||||||
MARIADB_GTID *gtid;
|
MARIADB_GTID *gtid;
|
||||||
@@ -185,6 +389,7 @@ struct st_mariadb_rpl_format_description_event
|
|||||||
char *server_version;
|
char *server_version;
|
||||||
uint32_t timestamp;
|
uint32_t timestamp;
|
||||||
uint8_t header_len;
|
uint8_t header_len;
|
||||||
|
MARIADB_STRING post_header_lengths;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct st_mariadb_rpl_checkpoint_event {
|
struct st_mariadb_rpl_checkpoint_event {
|
||||||
@@ -210,10 +415,21 @@ struct st_mariadb_rpl_table_map_event {
|
|||||||
unsigned long long table_id;
|
unsigned long long table_id;
|
||||||
MARIADB_STRING database;
|
MARIADB_STRING database;
|
||||||
MARIADB_STRING table;
|
MARIADB_STRING table;
|
||||||
unsigned int column_count;
|
uint32_t column_count;
|
||||||
MARIADB_STRING column_types;
|
MARIADB_STRING column_types;
|
||||||
MARIADB_STRING metadata;
|
MARIADB_STRING metadata;
|
||||||
char *null_indicator;
|
unsigned char *null_indicator;
|
||||||
|
unsigned char *signed_indicator;
|
||||||
|
MARIADB_CONST_DATA column_names;
|
||||||
|
MARIADB_CONST_DATA geometry_types;
|
||||||
|
uint32_t default_charset;
|
||||||
|
MARIADB_CONST_DATA column_charsets;
|
||||||
|
MARIADB_CONST_DATA simple_primary_keys;
|
||||||
|
MARIADB_CONST_DATA prefixed_primary_keys;
|
||||||
|
MARIADB_CONST_DATA set_values;
|
||||||
|
MARIADB_CONST_DATA enum_values;
|
||||||
|
uint8_t enum_set_default_charset;
|
||||||
|
MARIADB_CONST_DATA enum_set_column_charsets;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct st_mariadb_rpl_rand_event {
|
struct st_mariadb_rpl_rand_event {
|
||||||
@@ -221,15 +437,33 @@ struct st_mariadb_rpl_rand_event {
|
|||||||
unsigned long long second_seed;
|
unsigned long long second_seed;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct st_mariadb_rpl_encryption_event {
|
struct st_mariadb_rpl_intvar_event {
|
||||||
char scheme;
|
unsigned long long value;
|
||||||
unsigned int key_version;
|
uint8_t type;
|
||||||
char *nonce;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct st_mariadb_rpl_intvar_event {
|
struct st_mariadb_begin_load_query_event {
|
||||||
char type;
|
uint32_t file_id;
|
||||||
unsigned long long value;
|
unsigned char *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct st_mariadb_start_encryption_event {
|
||||||
|
uint8_t scheme;
|
||||||
|
uint32_t key_version;
|
||||||
|
char nonce[12];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct st_mariadb_execute_load_query_event {
|
||||||
|
uint32_t thread_id;
|
||||||
|
uint32_t execution_time;
|
||||||
|
MARIADB_STRING schema;
|
||||||
|
uint16_t error_code;
|
||||||
|
uint32_t file_id;
|
||||||
|
uint32_t ofs1;
|
||||||
|
uint32_t ofs2;
|
||||||
|
uint8_t duplicate_flag;
|
||||||
|
MARIADB_STRING status_vars;
|
||||||
|
MARIADB_STRING statement;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct st_mariadb_rpl_uservar_event {
|
struct st_mariadb_rpl_uservar_event {
|
||||||
@@ -246,12 +480,15 @@ struct st_mariadb_rpl_rows_event {
|
|||||||
uint64_t table_id;
|
uint64_t table_id;
|
||||||
uint16_t flags;
|
uint16_t flags;
|
||||||
uint32_t column_count;
|
uint32_t column_count;
|
||||||
char *column_bitmap;
|
unsigned char *column_bitmap;
|
||||||
char *column_update_bitmap;
|
unsigned char *column_update_bitmap;
|
||||||
|
unsigned char *null_bitmap;
|
||||||
size_t row_data_size;
|
size_t row_data_size;
|
||||||
void *row_data;
|
void *row_data;
|
||||||
size_t extra_data_size;
|
size_t extra_data_size;
|
||||||
void *extra_data;
|
void *extra_data;
|
||||||
|
uint8_t compressed;
|
||||||
|
uint32_t row_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct st_mariadb_rpl_heartbeat_event {
|
struct st_mariadb_rpl_heartbeat_event {
|
||||||
@@ -261,10 +498,27 @@ struct st_mariadb_rpl_heartbeat_event {
|
|||||||
uint16_t flags;
|
uint16_t flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct st_mariadb_rpl_xa_prepare_log_event {
|
||||||
|
uint8_t one_phase;
|
||||||
|
uint32_t format_id;
|
||||||
|
uint32_t gtrid_len;
|
||||||
|
uint32_t bqual_len;
|
||||||
|
MARIADB_STRING xid;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct st_mariadb_gtid_log_event {
|
||||||
|
uint8_t commit_flag;
|
||||||
|
char source_id[16];
|
||||||
|
uint64_t sequence_nr;
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct st_mariadb_rpl_event
|
typedef struct st_mariadb_rpl_event
|
||||||
{
|
{
|
||||||
/* common header */
|
/* common header */
|
||||||
MA_MEM_ROOT memroot;
|
MA_MEM_ROOT memroot;
|
||||||
|
unsigned char *raw_data;
|
||||||
|
size_t raw_data_size;
|
||||||
|
size_t raw_data_ofs;
|
||||||
unsigned int checksum;
|
unsigned int checksum;
|
||||||
char ok;
|
char ok;
|
||||||
enum mariadb_rpl_event event_type;
|
enum mariadb_rpl_event event_type;
|
||||||
@@ -285,30 +539,124 @@ typedef struct st_mariadb_rpl_event
|
|||||||
struct st_mariadb_rpl_annotate_rows_event annotate_rows;
|
struct st_mariadb_rpl_annotate_rows_event annotate_rows;
|
||||||
struct st_mariadb_rpl_table_map_event table_map;
|
struct st_mariadb_rpl_table_map_event table_map;
|
||||||
struct st_mariadb_rpl_rand_event rand;
|
struct st_mariadb_rpl_rand_event rand;
|
||||||
struct st_mariadb_rpl_encryption_event encryption;
|
|
||||||
struct st_mariadb_rpl_intvar_event intvar;
|
struct st_mariadb_rpl_intvar_event intvar;
|
||||||
struct st_mariadb_rpl_uservar_event uservar;
|
struct st_mariadb_rpl_uservar_event uservar;
|
||||||
struct st_mariadb_rpl_rows_event rows;
|
struct st_mariadb_rpl_rows_event rows;
|
||||||
struct st_mariadb_rpl_heartbeat_event heartbeat;
|
struct st_mariadb_rpl_heartbeat_event heartbeat;
|
||||||
|
struct st_mariadb_rpl_xa_prepare_log_event xa_prepare_log;
|
||||||
|
struct st_mariadb_begin_load_query_event begin_load_query;
|
||||||
|
struct st_mariadb_execute_load_query_event execute_load_query;
|
||||||
|
struct st_mariadb_gtid_log_event gtid_log;
|
||||||
|
struct st_mariadb_start_encryption_event start_encryption;
|
||||||
|
struct st_mariadb_rpl_previous_gtid_event previous_gtid;
|
||||||
} event;
|
} event;
|
||||||
/* Added in C/C 3.3.0 */
|
/* Added in C/C 3.3.0 */
|
||||||
uint8_t is_semi_sync;
|
uint8_t is_semi_sync;
|
||||||
uint8_t semi_sync_flags;
|
uint8_t semi_sync_flags;
|
||||||
|
/* Added in C/C 3.3.5 */
|
||||||
|
MARIADB_RPL *rpl;
|
||||||
} MARIADB_RPL_EVENT;
|
} MARIADB_RPL_EVENT;
|
||||||
|
|
||||||
|
/* compression uses myisampack format */
|
||||||
|
#define myisam_uint1korr(B) ((uint8_t)(*B))
|
||||||
|
#define myisam_sint1korr(B) ((int8_t)(*B))
|
||||||
|
#define myisam_uint2korr(B)\
|
||||||
|
((uint16_t)(((uint16_t)(((const uchar*)(B))[1])) | ((uint16_t) (((const uchar*) (B))[0]) << 8)))
|
||||||
|
#define myisam_sint2korr(B)\
|
||||||
|
((int16_t)(((int16_t)(((const uchar*)(B))[1])) | ((int16_t) (((const uchar*) (B))[0]) << 8)))
|
||||||
|
#define myisam_uint3korr(B)\
|
||||||
|
((uint32_t)(((uint32_t)(((const uchar*)(B))[2])) |\
|
||||||
|
(((uint32_t)(((const uchar*)(B))[1])) << 8) |\
|
||||||
|
(((uint32_t)(((const uchar*)(B))[0])) << 16)))
|
||||||
|
#define myisam_sint3korr(B)\
|
||||||
|
((int32_t)(((int32_t)(((const uchar*)(B))[2])) |\
|
||||||
|
(((int32_t)(((const uchar*)(B))[1])) << 8) |\
|
||||||
|
(((int32_t)(((const uchar*)(B))[0])) << 16)))
|
||||||
|
#define myisam_uint4korr(B)\
|
||||||
|
((uint32_t)(((uint32_t)(((const uchar*)(B))[3])) |\
|
||||||
|
(((uint32_t)(((const uchar*)(B))[2])) << 8) |\
|
||||||
|
(((uint32_t)(((const uchar*) (B))[1])) << 16) |\
|
||||||
|
(((uint32_t)(((const uchar*) (B))[0])) << 24)))
|
||||||
|
#define myisam_sint4korr(B)\
|
||||||
|
((int32_t)(((int32_t)(((const uchar*)(B))[3])) |\
|
||||||
|
(((int32_t)(((const uchar*)(B))[2])) << 8) |\
|
||||||
|
(((int32_t)(((const uchar*) (B))[1])) << 16) |\
|
||||||
|
(((int32_t)(((const uchar*) (B))[0])) << 24)))
|
||||||
|
#define mi_uint5korr(B)\
|
||||||
|
((uint64_t)(((uint32_t) (((const uchar*) (B))[4])) |\
|
||||||
|
(((uint32_t) (((const uchar*) (B))[3])) << 8) |\
|
||||||
|
(((uint32_t) (((const uchar*) (B))[2])) << 16) |\
|
||||||
|
(((uint32_t) (((const uchar*) (B))[1])) << 24)) |\
|
||||||
|
(((uint64_t) (((const uchar*) (B))[0])) << 32))
|
||||||
|
|
||||||
|
#define RPL_SAFEGUARD(rpl, event, condition) \
|
||||||
|
if (!(condition))\
|
||||||
|
{\
|
||||||
|
my_set_error((rpl)->mysql, CR_BINLOG_ERROR, SQLSTATE_UNKNOWN, 0,\
|
||||||
|
(rpl)->filename_length, (rpl)->filename,\
|
||||||
|
(rpl)->start_position,\
|
||||||
|
"Packet corrupted");\
|
||||||
|
mariadb_free_rpl_event((event));\
|
||||||
|
return 0;\
|
||||||
|
}
|
||||||
|
|
||||||
#define mariadb_rpl_init(a) mariadb_rpl_init_ex((a), MARIADB_RPL_VERSION)
|
#define mariadb_rpl_init(a) mariadb_rpl_init_ex((a), MARIADB_RPL_VERSION)
|
||||||
|
#define rpl_clear_error(rpl)\
|
||||||
|
(rpl)->error_no= (rpl)->error_msg[0]= 0
|
||||||
|
|
||||||
|
#define IS_ROW_VERSION2(a)\
|
||||||
|
((a) == WRITE_ROWS_EVENT || (a) == UPDATE_ROWS_EVENT || \
|
||||||
|
(a) == DELETE_ROWS_EVENT || (a) == WRITE_ROWS_COMPRESSED_EVENT ||\
|
||||||
|
(a) == UPDATE_ROWS_COMPRESSED_EVENT || (a) == DELETE_ROWS_COMPRESSED_EVENT)
|
||||||
|
|
||||||
|
#define IS_ROW_EVENT(a)\
|
||||||
|
((a)->event_type == WRITE_ROWS_COMPRESSED_EVENT_V1 ||\
|
||||||
|
(a)->event_type == UPDATE_ROWS_COMPRESSED_EVENT_V1 ||\
|
||||||
|
(a)->event_type == DELETE_ROWS_COMPRESSED_EVENT_V1 ||\
|
||||||
|
(a)->event_type == WRITE_ROWS_EVENT_V1 ||\
|
||||||
|
(a)->event_type == UPDATE_ROWS_EVENT_V1 ||\
|
||||||
|
(a)->event_type == DELETE_ROWS_EVENT_V1 ||\
|
||||||
|
(a)->event_type == WRITE_ROWS_EVENT ||\
|
||||||
|
(a)->event_type == UPDATE_ROWS_EVENT ||\
|
||||||
|
(a)->event_type == DELETE_ROWS_EVENT)
|
||||||
|
|
||||||
|
static inline uint64_t uintNkorr(uint8_t len, u_char *p)
|
||||||
|
{
|
||||||
|
switch (len) {
|
||||||
|
case 1:
|
||||||
|
return *p;
|
||||||
|
case 2:
|
||||||
|
return uint2korr(p);
|
||||||
|
case 3:
|
||||||
|
return uint3korr(p);
|
||||||
|
case 4:
|
||||||
|
return uint4korr(p);
|
||||||
|
case 8:
|
||||||
|
return uint8korr(p);
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Function prototypes */
|
/* Function prototypes */
|
||||||
MARIADB_RPL * STDCALL mariadb_rpl_init_ex(MYSQL *mysql, unsigned int version);
|
MARIADB_RPL * STDCALL mariadb_rpl_init_ex(MYSQL *mysql, unsigned int version);
|
||||||
|
const char * STDCALL mariadb_rpl_error(MARIADB_RPL *rpl);
|
||||||
|
uint32_t STDCALL mariadb_rpl_errno(MARIADB_RPL *rpl);
|
||||||
|
|
||||||
int mariadb_rpl_optionsv(MARIADB_RPL *rpl, enum mariadb_rpl_option, ...);
|
int STDCALL mariadb_rpl_optionsv(MARIADB_RPL *rpl, enum mariadb_rpl_option, ...);
|
||||||
int mariadb_rpl_get_optionsv(MARIADB_RPL *rpl, enum mariadb_rpl_option, ...);
|
int STDCALL mariadb_rpl_get_optionsv(MARIADB_RPL *rpl, enum mariadb_rpl_option, ...);
|
||||||
|
|
||||||
int STDCALL mariadb_rpl_open(MARIADB_RPL *rpl);
|
int STDCALL mariadb_rpl_open(MARIADB_RPL *rpl);
|
||||||
void STDCALL mariadb_rpl_close(MARIADB_RPL *rpl);
|
void STDCALL mariadb_rpl_close(MARIADB_RPL *rpl);
|
||||||
MARIADB_RPL_EVENT * STDCALL mariadb_rpl_fetch(MARIADB_RPL *rpl, MARIADB_RPL_EVENT *event);
|
MARIADB_RPL_EVENT * STDCALL mariadb_rpl_fetch(MARIADB_RPL *rpl, MARIADB_RPL_EVENT *event);
|
||||||
void STDCALL mariadb_free_rpl_event(MARIADB_RPL_EVENT *event);
|
void STDCALL mariadb_free_rpl_event(MARIADB_RPL_EVENT *event);
|
||||||
|
|
||||||
|
MARIADB_RPL_ROW * STDCALL
|
||||||
|
mariadb_rpl_extract_rows(MARIADB_RPL *rpl,
|
||||||
|
MARIADB_RPL_EVENT *tm_event,
|
||||||
|
MARIADB_RPL_EVENT *row_event);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -68,6 +68,12 @@ typedef struct st_ma_const_string
|
|||||||
size_t length;
|
size_t length;
|
||||||
} MARIADB_CONST_STRING;
|
} MARIADB_CONST_STRING;
|
||||||
|
|
||||||
|
typedef struct st_ma_const_data
|
||||||
|
{
|
||||||
|
const unsigned char *data;
|
||||||
|
size_t length;
|
||||||
|
} MARIADB_CONST_DATA;
|
||||||
|
|
||||||
|
|
||||||
#ifndef ST_MA_USED_MEM_DEFINED
|
#ifndef ST_MA_USED_MEM_DEFINED
|
||||||
#define ST_MA_USED_MEM_DEFINED
|
#define ST_MA_USED_MEM_DEFINED
|
||||||
@@ -250,7 +256,8 @@ extern const char *SQLSTATE_UNKNOWN;
|
|||||||
MARIADB_OPT_SKIP_READ_RESPONSE,
|
MARIADB_OPT_SKIP_READ_RESPONSE,
|
||||||
MARIADB_OPT_RESTRICTED_AUTH,
|
MARIADB_OPT_RESTRICTED_AUTH,
|
||||||
MARIADB_OPT_RPL_REGISTER_REPLICA,
|
MARIADB_OPT_RPL_REGISTER_REPLICA,
|
||||||
MARIADB_OPT_STATUS_CALLBACK
|
MARIADB_OPT_STATUS_CALLBACK,
|
||||||
|
MARIADB_OPT_SERVER_PLUGINS
|
||||||
};
|
};
|
||||||
|
|
||||||
enum mariadb_value {
|
enum mariadb_value {
|
||||||
|
@@ -37,6 +37,11 @@ SET(MARIADB_LIB_SYMBOLS
|
|||||||
mariadb_free_rpl_event
|
mariadb_free_rpl_event
|
||||||
mariadb_field_attr
|
mariadb_field_attr
|
||||||
)
|
)
|
||||||
|
|
||||||
|
SET(MARIADB_LIB_3_3_5_SYMBOLS
|
||||||
|
mariadb_rpl_extract_rows
|
||||||
|
mariadb_rpl_error
|
||||||
|
mariadb_rpl_errno)
|
||||||
IF(WITH_SSL)
|
IF(WITH_SSL)
|
||||||
SET(MARIADB_LIB_SYMBOLS ${MARIADB_LIB_SYMBOLS} mariadb_deinitialize_ssl)
|
SET(MARIADB_LIB_SYMBOLS ${MARIADB_LIB_SYMBOLS} mariadb_deinitialize_ssl)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
@@ -303,6 +308,7 @@ SET(LIBMARIADB_SOURCES ${LIBMARIADB_SOURCES}
|
|||||||
${CC_SOURCE_DIR}/plugins/auth/my_auth.c
|
${CC_SOURCE_DIR}/plugins/auth/my_auth.c
|
||||||
ma_array.c
|
ma_array.c
|
||||||
ma_charset.c
|
ma_charset.c
|
||||||
|
ma_decimal.c
|
||||||
ma_hashtbl.c
|
ma_hashtbl.c
|
||||||
ma_net.c
|
ma_net.c
|
||||||
mariadb_charset.c
|
mariadb_charset.c
|
||||||
@@ -396,10 +402,14 @@ IF(NOT WIN32)
|
|||||||
"libmariadb_3"
|
"libmariadb_3"
|
||||||
"${MARIADB_LIB_SYMBOLS}"
|
"${MARIADB_LIB_SYMBOLS}"
|
||||||
"")
|
"")
|
||||||
|
CREATE_EXPORT_FILE(APPEND mariadbclient.def
|
||||||
|
"libmariadb_3_3_5"
|
||||||
|
"${MARIADB_LIB_3_3_5_SYMBOLS}"
|
||||||
|
"")
|
||||||
ELSE()
|
ELSE()
|
||||||
CREATE_EXPORT_FILE(WRITE mariadbclient.def
|
CREATE_EXPORT_FILE(WRITE mariadbclient.def
|
||||||
"libmariadb_3"
|
"libmariadb_3"
|
||||||
"${MARIADB_LIB_SYMBOLS};${MYSQL_LIB_SYMBOLS}"
|
"${MARIADB_LIB_SYMBOLS};${MYSQL_LIB_SYMBOLS};${MARIADB_LIB_3_3_5_SYMBOLS}"
|
||||||
"")
|
"")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
@@ -433,9 +443,8 @@ IF(WIN32)
|
|||||||
"FILE_DESCRIPTION:Dynamic lib for client/server communication")
|
"FILE_DESCRIPTION:Dynamic lib for client/server communication")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
|
|
||||||
ADD_LIBRARY(mariadbclient STATIC ${MARIADB_OBJECTS} ${EMPTY_FILE})
|
ADD_LIBRARY(mariadbclient STATIC ${MARIADB_OBJECTS} ${EMPTY_FILE})
|
||||||
TARGET_LINK_LIBRARIES(mariadbclient ${SYSTEM_LIBS})
|
TARGET_LINK_LIBRARIES(mariadbclient ${SYSTEM_LIBS} ${CRYPTO_LIBS})
|
||||||
|
|
||||||
IF(UNIX)
|
IF(UNIX)
|
||||||
ADD_LIBRARY(libmariadb SHARED ${libmariadb_RC} ${MARIADB_OBJECTS} ${EMPTY_FILE})
|
ADD_LIBRARY(libmariadb SHARED ${libmariadb_RC} ${MARIADB_OBJECTS} ${EMPTY_FILE})
|
||||||
@@ -445,7 +454,7 @@ ELSE()
|
|||||||
SET_TARGET_PROPERTIES(libmariadb PROPERTIES LINKER_LANGUAGE C)
|
SET_TARGET_PROPERTIES(libmariadb PROPERTIES LINKER_LANGUAGE C)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
TARGET_LINK_LIBRARIES(libmariadb LINK_PRIVATE ${SYSTEM_LIBS})
|
TARGET_LINK_LIBRARIES(libmariadb LINK_PRIVATE ${SYSTEM_LIBS} ${CRYPTO_LIBS})
|
||||||
|
|
||||||
SIGN_TARGET(libmariadb)
|
SIGN_TARGET(libmariadb)
|
||||||
|
|
||||||
|
479
libmariadb/ma_decimal.c
Normal file
479
libmariadb/ma_decimal.c
Normal file
@@ -0,0 +1,479 @@
|
|||||||
|
/* Copyright (C) 2004 Sergei Golubchik
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this library; if not see <http://www.gnu.org/licenses>
|
||||||
|
or write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
=======================================================================
|
||||||
|
NOTE: this library implements SQL standard "exact numeric" type
|
||||||
|
and is not at all generic, but rather intentinally crippled to
|
||||||
|
follow the standard :)
|
||||||
|
=======================================================================
|
||||||
|
Quoting the standard
|
||||||
|
(SQL:2003, Part 2 Foundations, aka ISO/IEC 9075-2:2003)
|
||||||
|
|
||||||
|
4.4.2 Characteristics of numbers, page 27:
|
||||||
|
|
||||||
|
An exact numeric type has a precision P and a scale S. P is a positive
|
||||||
|
integer that determines the number of significant digits in a
|
||||||
|
particular radix R, where R is either 2 or 10. S is a non-negative
|
||||||
|
integer. Every value of an exact numeric type of scale S is of the
|
||||||
|
form n*10^{-S}, where n is an integer such that ?-R^P <= n <= R^P.
|
||||||
|
|
||||||
|
[...]
|
||||||
|
|
||||||
|
If an assignment of some number would result in a loss of its most
|
||||||
|
significant digit, an exception condition is raised. If least
|
||||||
|
significant digits are lost, implementation-defined rounding or
|
||||||
|
truncating occurs, with no exception condition being raised.
|
||||||
|
|
||||||
|
[...]
|
||||||
|
|
||||||
|
Whenever an exact or approximate numeric value is assigned to an exact
|
||||||
|
numeric value site, an approximation of its value that preserves
|
||||||
|
leading significant digits after rounding or truncating is represented
|
||||||
|
in the declared type of the target. The value is converted to have the
|
||||||
|
precision and scale of the target. The choice of whether to truncate
|
||||||
|
or round is implementation-defined.
|
||||||
|
|
||||||
|
[...]
|
||||||
|
|
||||||
|
All numeric values between the smallest and the largest value,
|
||||||
|
inclusive, in a given exact numeric type have an approximation
|
||||||
|
obtained by rounding or truncation for that type; it is
|
||||||
|
implementation-defined which other numeric values have such
|
||||||
|
approximations.
|
||||||
|
|
||||||
|
5.3 <literal>, page 143
|
||||||
|
|
||||||
|
<exact numeric literal> ::=
|
||||||
|
<unsigned integer> [ <period> [ <unsigned integer> ] ]
|
||||||
|
| <period> <unsigned integer>
|
||||||
|
|
||||||
|
6.1 <data type>, page 165:
|
||||||
|
|
||||||
|
19) The <scale> of an <exact numeric type> shall not be greater than
|
||||||
|
the <precision> of the <exact numeric type>.
|
||||||
|
|
||||||
|
20) For the <exact numeric type>s DECIMAL and NUMERIC:
|
||||||
|
|
||||||
|
a) The maximum value of <precision> is implementation-defined.
|
||||||
|
<precision> shall not be greater than this value.
|
||||||
|
b) The maximum value of <scale> is implementation-defined. <scale>
|
||||||
|
shall not be greater than this maximum value.
|
||||||
|
|
||||||
|
21) NUMERIC specifies the data type exact numeric, with the decimal
|
||||||
|
precision and scale specified by the <precision> and <scale>.
|
||||||
|
|
||||||
|
22) DECIMAL specifies the data type exact numeric, with the decimal
|
||||||
|
scale specified by the <scale> and the implementation-defined
|
||||||
|
decimal precision equal to or greater than the value of the
|
||||||
|
specified <precision>.
|
||||||
|
|
||||||
|
6.26 <numeric value expression>, page 241:
|
||||||
|
|
||||||
|
1) If the declared type of both operands of a dyadic arithmetic
|
||||||
|
operator is exact numeric, then the declared type of the result is
|
||||||
|
an implementation-defined exact numeric type, with precision and
|
||||||
|
scale determined as follows:
|
||||||
|
|
||||||
|
a) Let S1 and S2 be the scale of the first and second operands
|
||||||
|
respectively.
|
||||||
|
b) The precision of the result of addition and subtraction is
|
||||||
|
implementation-defined, and the scale is the maximum of S1 and S2.
|
||||||
|
c) The precision of the result of multiplication is
|
||||||
|
implementation-defined, and the scale is S1 + S2.
|
||||||
|
d) The precision and scale of the result of division are
|
||||||
|
implementation-defined.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ma_global.h>
|
||||||
|
#include <ma_sys.h> /* for my_alloca */
|
||||||
|
#include <ma_decimal.h>
|
||||||
|
#include <mysql.h>
|
||||||
|
#include <mariadb_rpl.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#define alloca _malloca
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef decimal_digit dec1;
|
||||||
|
typedef longlong dec2;
|
||||||
|
|
||||||
|
#define unlikely(A) (A)
|
||||||
|
#define DIG_PER_DEC1 9
|
||||||
|
#define DIG_MASK 100000000
|
||||||
|
#define DIG_BASE 1000000000
|
||||||
|
#define DIG_BASE2 LL(1000000000000000000)
|
||||||
|
#define ROUND_UP(X) (((X)+DIG_PER_DEC1-1)/DIG_PER_DEC1)
|
||||||
|
static const dec1 powers10[DIG_PER_DEC1+1]={
|
||||||
|
1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
|
||||||
|
static const int dig2bytes[DIG_PER_DEC1+1]={0, 1, 1, 2, 2, 3, 3, 4, 4, 4};
|
||||||
|
|
||||||
|
#define sanity(d) DBUG_ASSERT((d)->len >0 && ((d)->buf[0] | \
|
||||||
|
(d)->buf[(d)->len-1] | 1))
|
||||||
|
|
||||||
|
#define FIX_INTG_FRAC_ERROR(len, intg1, frac1, error) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
if (unlikely(intg1+frac1 > (len))) \
|
||||||
|
{ \
|
||||||
|
if (unlikely(intg1 > (len))) \
|
||||||
|
{ \
|
||||||
|
intg1=(len); \
|
||||||
|
frac1=0; \
|
||||||
|
error=E_DEC_OVERFLOW; \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
frac1=(len)-intg1; \
|
||||||
|
error=E_DEC_TRUNCATED; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
error=E_DEC_OK; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define ADD(to, from1, from2, carry) /* assume carry <= 1 */ \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
dec1 a=(from1)+(from2)+(carry); \
|
||||||
|
if (((carry)= a >= DIG_BASE)) /* no division here! */ \
|
||||||
|
a-=DIG_BASE; \
|
||||||
|
(to)=a; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define ADD2(to, from1, from2, carry) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
dec1 a=(from1)+(from2)+(carry); \
|
||||||
|
if (((carry)= a >= DIG_BASE)) \
|
||||||
|
a-=DIG_BASE; \
|
||||||
|
if (unlikely(a >= DIG_BASE)) \
|
||||||
|
{ \
|
||||||
|
a-=DIG_BASE; \
|
||||||
|
carry++; \
|
||||||
|
} \
|
||||||
|
(to)=a; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define SUB(to, from1, from2, carry) /* to=from1-from2 */ \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
dec1 a=(from1)-(from2)-(carry); \
|
||||||
|
if (((carry)= a < 0)) \
|
||||||
|
a+=DIG_BASE; \
|
||||||
|
(to)=a; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define SUB2(to, from1, from2, carry) /* to=from1-from2 */ \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
dec1 a=(from1)-(from2)-(carry); \
|
||||||
|
if (((carry)= a < 0)) \
|
||||||
|
a+=DIG_BASE; \
|
||||||
|
if (unlikely(a < 0)) \
|
||||||
|
{ \
|
||||||
|
a+=DIG_BASE; \
|
||||||
|
carry++; \
|
||||||
|
} \
|
||||||
|
(to)=a; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
Convert decimal to its printable string representation
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
decimal2string()
|
||||||
|
from - value to convert
|
||||||
|
to - points to buffer where string representation should be stored
|
||||||
|
*to_len - in: size of to buffer
|
||||||
|
out: length of the actually written string
|
||||||
|
|
||||||
|
RETURN VALUE
|
||||||
|
E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
|
||||||
|
*/
|
||||||
|
|
||||||
|
int decimal2string(decimal *from, char *to, int *to_len)
|
||||||
|
{
|
||||||
|
int len, intg=from->intg, frac=from->frac, i;
|
||||||
|
int error=E_DEC_OK;
|
||||||
|
char *s=to;
|
||||||
|
dec1 *buf, *buf0=from->buf, tmp;
|
||||||
|
|
||||||
|
DBUG_ASSERT(*to_len >= 2+from->sign);
|
||||||
|
|
||||||
|
/* removing leading zeroes */
|
||||||
|
i=((intg-1) % DIG_PER_DEC1)+1;
|
||||||
|
while (intg > 0 && *buf0 == 0)
|
||||||
|
{
|
||||||
|
intg-=i;
|
||||||
|
i=DIG_PER_DEC1;
|
||||||
|
buf0++;
|
||||||
|
}
|
||||||
|
if (intg > 0)
|
||||||
|
{
|
||||||
|
for (i=(intg-1) % DIG_PER_DEC1; *buf0 < powers10[i--]; intg--) ;
|
||||||
|
DBUG_ASSERT(intg > 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
intg=0;
|
||||||
|
if (unlikely(intg+frac==0))
|
||||||
|
{
|
||||||
|
intg=1;
|
||||||
|
tmp=0;
|
||||||
|
buf0=&tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
len= from->sign + intg + test(frac) + frac;
|
||||||
|
if (unlikely(len > --*to_len)) /* reserve one byte for \0 */
|
||||||
|
{
|
||||||
|
int i=len-*to_len;
|
||||||
|
error= (frac && i <= frac + 1) ? E_DEC_TRUNCATED : E_DEC_OVERFLOW;
|
||||||
|
if (frac && i >= frac + 1) i--;
|
||||||
|
if (i > frac)
|
||||||
|
{
|
||||||
|
intg-= i-frac;
|
||||||
|
frac= 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
frac-=i;
|
||||||
|
len= from->sign + intg + test(frac) + frac;
|
||||||
|
}
|
||||||
|
*to_len=len;
|
||||||
|
s[len]=0;
|
||||||
|
|
||||||
|
if (from->sign)
|
||||||
|
*s++='-';
|
||||||
|
|
||||||
|
if (frac)
|
||||||
|
{
|
||||||
|
char *s1=s+intg;
|
||||||
|
buf=buf0+ROUND_UP(intg);
|
||||||
|
*s1++='.';
|
||||||
|
for (; frac>0; frac-=DIG_PER_DEC1)
|
||||||
|
{
|
||||||
|
dec1 x=*buf++;
|
||||||
|
for (i=min(frac, DIG_PER_DEC1); i; i--)
|
||||||
|
{
|
||||||
|
dec1 y=x/DIG_MASK;
|
||||||
|
*s1++='0'+(uchar)y;
|
||||||
|
x-=y*DIG_MASK;
|
||||||
|
x*=10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s+=intg;
|
||||||
|
for (buf=buf0+ROUND_UP(intg); intg>0; intg-=DIG_PER_DEC1)
|
||||||
|
{
|
||||||
|
dec1 x=*--buf;
|
||||||
|
for (i=min(intg, DIG_PER_DEC1); i; i--)
|
||||||
|
{
|
||||||
|
dec1 y=x/10;
|
||||||
|
*--s='0'+(uchar)(x-y*10);
|
||||||
|
x=y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Convert string to decimal
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
str2decl()
|
||||||
|
from - value to convert
|
||||||
|
to - decimal where where the result will be stored
|
||||||
|
to->buf and to->len must be set.
|
||||||
|
end - if not NULL, *end will be set to the char where
|
||||||
|
conversion ended
|
||||||
|
fixed - use to->intg, to->frac as limits for input number
|
||||||
|
|
||||||
|
NOTE
|
||||||
|
to->intg and to->frac can be modified even when fixed=1
|
||||||
|
(but only decreased, in this case)
|
||||||
|
|
||||||
|
RETURN VALUE
|
||||||
|
E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_BAD_NUM/E_DEC_OOM
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Convert decimal to its binary fixed-length representation
|
||||||
|
two representations of the same length can be compared with memcmp
|
||||||
|
with the correct -1/0/+1 result
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
decimal2bin()
|
||||||
|
from - value to convert
|
||||||
|
to - points to buffer where string representation should be stored
|
||||||
|
precision/scale - see decimal_bin_size() below
|
||||||
|
|
||||||
|
NOTE
|
||||||
|
the buffer is assumed to be of the size decimal_bin_size(precision, scale)
|
||||||
|
|
||||||
|
RETURN VALUE
|
||||||
|
E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Restores decimal from its binary fixed-length representation
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
bin2decimal()
|
||||||
|
from - value to convert
|
||||||
|
to - result
|
||||||
|
precision/scale - see decimal_bin_size() below
|
||||||
|
|
||||||
|
NOTE
|
||||||
|
see decimal2bin()
|
||||||
|
the buffer is assumed to be of the size decimal_bin_size(precision, scale)
|
||||||
|
|
||||||
|
RETURN VALUE
|
||||||
|
E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
|
||||||
|
*/
|
||||||
|
|
||||||
|
int bin2decimal(const char *from, decimal *to, int precision, int scale)
|
||||||
|
{
|
||||||
|
int error=E_DEC_OK,
|
||||||
|
intg= precision - scale,
|
||||||
|
intg0= intg / DIG_PER_DEC1,
|
||||||
|
frac0= scale / DIG_PER_DEC1,
|
||||||
|
intg0x= intg - intg0 * DIG_PER_DEC1,
|
||||||
|
frac0x= scale - frac0*DIG_PER_DEC1,
|
||||||
|
intg1= intg0 + (intg0x > 0),
|
||||||
|
frac1= frac0 + (frac0x > 0),
|
||||||
|
tmp_size= decimal_bin_size(precision, scale);
|
||||||
|
char *tmp;
|
||||||
|
dec1 *buf= to->buf,
|
||||||
|
mask=(*from & 0x80) ? 0 : -1;
|
||||||
|
char *stop;
|
||||||
|
|
||||||
|
/* Initial implementation from Sergei modified "from" buffer, (which errored
|
||||||
|
in binlog api when verifying checksum), so we declare from as read only and use
|
||||||
|
a stack buffer instead */
|
||||||
|
tmp= (char *)alloca(tmp_size);
|
||||||
|
memcpy(tmp, from, tmp_size);
|
||||||
|
*tmp^= 0x80; /* remove sign bit */
|
||||||
|
from= tmp;
|
||||||
|
|
||||||
|
sanity(to);
|
||||||
|
|
||||||
|
FIX_INTG_FRAC_ERROR(to->len, intg1, frac1, error);
|
||||||
|
if (unlikely(error))
|
||||||
|
{
|
||||||
|
if (intg1 < intg0+(intg0x>0))
|
||||||
|
{
|
||||||
|
from+= dig2bytes[intg0x] + sizeof(dec1)*(intg0 - intg1);
|
||||||
|
frac0= frac0x= intg0x= 0;
|
||||||
|
intg0= intg1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
frac0x= 0;
|
||||||
|
frac0= frac1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
to->sign= (mask != 0);
|
||||||
|
to->intg= intg0 * DIG_PER_DEC1 + intg0x;
|
||||||
|
to->frac= frac0 * DIG_PER_DEC1 + frac0x;
|
||||||
|
|
||||||
|
if (intg0x)
|
||||||
|
{
|
||||||
|
int i= dig2bytes[intg0x];
|
||||||
|
dec1 x= 0;
|
||||||
|
switch (i)
|
||||||
|
{
|
||||||
|
case 1: x=myisam_sint1korr(from); break;
|
||||||
|
case 2: x=myisam_sint2korr(from); break;
|
||||||
|
case 3: x=myisam_sint3korr(from); break;
|
||||||
|
case 4: x=myisam_sint4korr(from); break;
|
||||||
|
default: DBUG_ASSERT(0); x= 0;
|
||||||
|
}
|
||||||
|
from+=i;
|
||||||
|
*buf=x ^ mask;
|
||||||
|
if (buf > to->buf || *buf != 0)
|
||||||
|
buf++;
|
||||||
|
else
|
||||||
|
to->intg-=intg0x;
|
||||||
|
}
|
||||||
|
for (stop=(char *)from+intg0*sizeof(dec1); from < stop; from+=sizeof(dec1))
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(sizeof(dec1) == 4);
|
||||||
|
*buf=myisam_sint4korr(from) ^ mask;
|
||||||
|
if (buf > to->buf || *buf != 0)
|
||||||
|
buf++;
|
||||||
|
else
|
||||||
|
to->intg-=DIG_PER_DEC1;
|
||||||
|
}
|
||||||
|
DBUG_ASSERT(to->intg >=0);
|
||||||
|
for (stop=(char *)from+frac0*sizeof(dec1); from < stop; from+=sizeof(dec1))
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(sizeof(dec1) == 4);
|
||||||
|
*buf=myisam_sint4korr(from) ^ mask;
|
||||||
|
buf++;
|
||||||
|
}
|
||||||
|
if (frac0x)
|
||||||
|
{
|
||||||
|
int i=dig2bytes[frac0x];
|
||||||
|
dec1 x= 0;
|
||||||
|
switch (i)
|
||||||
|
{
|
||||||
|
case 1: x=myisam_sint1korr(from); break;
|
||||||
|
case 2: x=myisam_sint2korr(from); break;
|
||||||
|
case 3: x=myisam_sint3korr(from); break;
|
||||||
|
case 4: x=myisam_sint4korr(from); break;
|
||||||
|
default: DBUG_ASSERT(0); x= 0;
|
||||||
|
}
|
||||||
|
*buf= (x ^ mask) * powers10[DIG_PER_DEC1 - frac0x];
|
||||||
|
buf++;
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Returns the size of array to hold a decimal with given precision and scale
|
||||||
|
|
||||||
|
RETURN VALUE
|
||||||
|
size in dec1
|
||||||
|
(multiply by sizeof(dec1) to get the size if bytes)
|
||||||
|
*/
|
||||||
|
|
||||||
|
int decimal_size(int precision, int scale)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(scale >= 0 && precision > 0 && scale <= precision);
|
||||||
|
return ROUND_UP(precision-scale)+ROUND_UP(scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Returns the size of array to hold a binary representation of a decimal
|
||||||
|
|
||||||
|
RETURN VALUE
|
||||||
|
size in bytes
|
||||||
|
*/
|
||||||
|
|
||||||
|
int decimal_bin_size(int precision, int scale)
|
||||||
|
{
|
||||||
|
int intg=precision-scale,
|
||||||
|
intg0=intg/DIG_PER_DEC1, frac0=scale/DIG_PER_DEC1,
|
||||||
|
intg0x=intg-intg0*DIG_PER_DEC1, frac0x=scale-frac0*DIG_PER_DEC1;
|
||||||
|
|
||||||
|
DBUG_ASSERT(scale >= 0 && precision > 0 && scale <= precision);
|
||||||
|
return intg0*sizeof(dec1)+dig2bytes[intg0x]+
|
||||||
|
frac0*sizeof(dec1)+dig2bytes[frac0x];
|
||||||
|
}
|
@@ -111,6 +111,12 @@ const char *mariadb_client_errors[] =
|
|||||||
/* 5014 */ "Write error: %s (%d)",
|
/* 5014 */ "Write error: %s (%d)",
|
||||||
/* 5015 */ "Error while uncompressing packet",
|
/* 5015 */ "Error while uncompressing packet",
|
||||||
/* 5016 */ "Error while retrieving parameter from callback function",
|
/* 5016 */ "Error while retrieving parameter from callback function",
|
||||||
|
/* 5017 */ "Error while uncompressing packet (File: %.*s start_pos=%ld).",
|
||||||
|
/* 5018 */ "Checksum verification failed (File: %.*s start_pos=%ld). Reported checksum is %x, while calculated checksum is %x.",
|
||||||
|
/* 5019 */ "Binary log protocol error (File: %.*s start_pos=%ld): Log format %d not supported.",
|
||||||
|
/* 5020 */ "Binary log error (File: %.*s start_pos=%ld): Unknown event type (%d) with flag 'not_ignorable'.",
|
||||||
|
/* 5021 */ "Binary log error (File: %.*s start_pos=%ld): %s.",
|
||||||
|
/* 5022 */ "File '%s' is not a binary log file",
|
||||||
""
|
""
|
||||||
};
|
};
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -49,6 +49,7 @@ static int test_conc66(MYSQL *my)
|
|||||||
fprintf(fp, "user=conc66\n");
|
fprintf(fp, "user=conc66\n");
|
||||||
fprintf(fp, "port=3306\n");
|
fprintf(fp, "port=3306\n");
|
||||||
fprintf(fp, "enable-local-infile\n");
|
fprintf(fp, "enable-local-infile\n");
|
||||||
|
fprintf(fp, "server_plugin=file_key_management:file_key_management_algorithm=AES_CTR;file_key_management_key=secret\n");
|
||||||
fprintf(fp, "password='test@A1\\\";#test'\n");
|
fprintf(fp, "password='test@A1\\\";#test'\n");
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
Reference in New Issue
Block a user