Develop merge
Develop merge
This commit is contained in:
@ -159,7 +159,7 @@ public:
|
||||
*
|
||||
* @return True if data was written successfully
|
||||
*/
|
||||
bool write(GWBUF* buffer, response_type type = EXPECT_RESPONSE);
|
||||
virtual bool write(GWBUF* buffer, response_type type = EXPECT_RESPONSE);
|
||||
|
||||
/**
|
||||
* @brief Write an authentication switch request to the backend server
|
||||
|
@ -212,6 +212,21 @@ extern void gwbuf_free(GWBUF *buf);
|
||||
*/
|
||||
extern GWBUF *gwbuf_clone(GWBUF *buf);
|
||||
|
||||
/**
|
||||
* @brief Deep clone a GWBUF
|
||||
*
|
||||
* Clone the data inside a GWBUF into a new buffer. The created buffer has its
|
||||
* own internal buffer and any modifications to the deep cloned buffer will not
|
||||
* reflect on the original one. Any buffer objects attached to the original buffer
|
||||
* will not be copied. Only the buffer type of the original buffer will be copied
|
||||
* over to the cloned buffer.
|
||||
*
|
||||
* @param buf Buffer to clone
|
||||
*
|
||||
* @return Deep copy of @c buf or NULL on error
|
||||
*/
|
||||
extern GWBUF* gwbuf_deep_clone(const GWBUF* buf);
|
||||
|
||||
/**
|
||||
* Compare two GWBUFs. Two GWBUFs are considered identical if their
|
||||
* content is identical, irrespective of whether one is segmented and
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <maxscale/modinfo.h>
|
||||
#include <maxscale/jansson.h>
|
||||
#include <maxscale/pcre2.h>
|
||||
#include <maxscale/query_classifier.h>
|
||||
|
||||
MXS_BEGIN_DECLS
|
||||
|
||||
@ -204,6 +205,7 @@ typedef struct
|
||||
bool skip_permission_checks; /**< Skip service and monitor permission checks */
|
||||
char qc_name[PATH_MAX]; /**< The name of the query classifier to load */
|
||||
char* qc_args; /**< Arguments for the query classifier */
|
||||
qc_sql_mode_t qc_sql_mode; /**< The query classifier sql mode */
|
||||
char admin_host[MAX_ADMIN_HOST_LEN]; /**< Admin interface host */
|
||||
uint16_t admin_port; /**< Admin interface port */
|
||||
bool admin_auth; /**< Admin interface authentication */
|
||||
|
238
include/maxscale/customparser.hh
Normal file
238
include/maxscale/customparser.hh
Normal file
@ -0,0 +1,238 @@
|
||||
#pragma once
|
||||
/*
|
||||
* Copyright (c) 2016 MariaDB Corporation Ab
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file and at www.mariadb.com/bsl11.
|
||||
*
|
||||
* Change Date: 2019-07-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2 or later of the General
|
||||
* Public License.
|
||||
*/
|
||||
|
||||
#include <maxscale/cppdefs.hh>
|
||||
#include <maxscale/log_manager.h>
|
||||
#include <maxscale/modutil.h>
|
||||
#include <ctype.h>
|
||||
|
||||
namespace maxscale
|
||||
{
|
||||
|
||||
#define MXS_CP_EXPECT_TOKEN(string_literal) string_literal, (sizeof(string_literal) - 1)
|
||||
|
||||
// For debugging purposes.
|
||||
// #define MXS_CP_LOG_UNEXPECTED_AND_EXHAUSTED
|
||||
#undef MXS_CP_LOG_UNEXPECTED_AND_EXHAUSTED
|
||||
|
||||
class CustomParser
|
||||
{
|
||||
CustomParser(const CustomParser&);
|
||||
CustomParser& operator = (const CustomParser&);
|
||||
|
||||
public:
|
||||
typedef int32_t token_t;
|
||||
|
||||
enum token_required_t
|
||||
{
|
||||
TOKEN_REQUIRED,
|
||||
TOKEN_NOT_REQUIRED,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PARSER_UNKNOWN_TOKEN = -2,
|
||||
PARSER_EXHAUSTED = -1
|
||||
};
|
||||
|
||||
CustomParser()
|
||||
: m_pSql(NULL)
|
||||
, m_len(0)
|
||||
, m_pI(NULL)
|
||||
, m_pEnd(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* To be called when unexpected data is encountered. For debugging
|
||||
* purposes, logging will only be performed if the define
|
||||
* MXS_CP_LOG_UNEXPECTED_AND_EXHAUSTED is defined.
|
||||
*/
|
||||
void log_unexpected()
|
||||
{
|
||||
#ifdef MXS_CP_LOG_UNEXPECTED_AND_EXHAUSTED
|
||||
MXS_NOTICE("Custom parser: In statement '%.*s', unexpected token at '%.*s'.",
|
||||
(int)m_len, m_pSql, (int)(m_pEnd - m_pI), m_pI);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* To be called when there is no more data even though there is
|
||||
* expected to be. For debugging purposes, logging will only be
|
||||
* performed if the define MXS_CP_LOG_UNEXPECTED_AND_EXHAUSTED
|
||||
* is defined.
|
||||
*/
|
||||
void log_exhausted()
|
||||
{
|
||||
#ifdef MXS_CP_LOG_UNEXPECTED_AND_EXHAUSTED
|
||||
MXS_NOTICE("Custom parser: More tokens expected in statement '%.*s'.", (int)m_len, m_pSql);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the character an alphabetic character.
|
||||
*
|
||||
* @param c A char
|
||||
*
|
||||
* @return True if @c c is between 'a' and 'z' or 'A' and 'Z', inclusive.
|
||||
*/
|
||||
static bool is_alpha(char c)
|
||||
{
|
||||
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the character a number
|
||||
*
|
||||
* @param c A char
|
||||
*
|
||||
* @return True if @c c is between '0' and '9' inclusive.
|
||||
*/
|
||||
static bool is_number(char c)
|
||||
{
|
||||
return (c >= '0' && c <= '9');
|
||||
}
|
||||
|
||||
/**
|
||||
* Is a character some offset from the current position, a specific one.
|
||||
*
|
||||
* @param uc An UPPERCASE character.
|
||||
* @param offset How many characters from the current position.
|
||||
*
|
||||
* @return True if the character at the position is the one specified or
|
||||
* its lowercase equivalent.
|
||||
*/
|
||||
bool is_next_alpha(char uc, int offset = 1) const
|
||||
{
|
||||
ss_dassert(uc >= 'A' && uc <= 'Z');
|
||||
|
||||
char lc = uc + ('a' - 'A');
|
||||
|
||||
return
|
||||
((m_pI + offset) < m_pEnd) &&
|
||||
((*(m_pI + offset) == uc) || (*(m_pI + offset) == lc));
|
||||
}
|
||||
|
||||
/**
|
||||
* Peek current character.
|
||||
*
|
||||
* @param pC Upon successful return will be the current character.
|
||||
*
|
||||
* @return True, if the current character was returned, false otherwise.
|
||||
* False will only be returned if the current position is at
|
||||
* the end.
|
||||
*/
|
||||
bool peek_current_char(char* pC) const
|
||||
{
|
||||
if (m_pI != m_pEnd)
|
||||
{
|
||||
*pC = *m_pI;
|
||||
}
|
||||
|
||||
return m_pI != m_pEnd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Peek next character.
|
||||
*
|
||||
* @param pC Upon successful return will be the next character.
|
||||
*
|
||||
* @return True, if the next character was returned, false otherwise.
|
||||
* False will only be returned if the current position is at
|
||||
* the end.
|
||||
*/
|
||||
bool peek_next_char(char* pC) const
|
||||
{
|
||||
bool rc = (m_pI + 1 < m_pEnd);
|
||||
|
||||
if (rc)
|
||||
{
|
||||
*pC = *(m_pI + 1);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a character to upper case.
|
||||
*
|
||||
* @param c The character to convert.
|
||||
*
|
||||
* @return The uppercase equivalent. If @c c is already uppercase,
|
||||
* then it is returned.
|
||||
*/
|
||||
static char toupper(char c)
|
||||
{
|
||||
// Significantly faster than library version.
|
||||
return (c >= 'a' && c <='z') ? c - ('a' - 'A') : c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bypass all whitespace from current position.
|
||||
*/
|
||||
void bypass_whitespace()
|
||||
{
|
||||
m_pI = modutil_MySQL_bypass_whitespace(const_cast<char*>(m_pI), m_pEnd - m_pI);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether an expected token is available.
|
||||
*
|
||||
* @param zWord A token.
|
||||
* @param len The token length.
|
||||
* @param token The value to be returned if the next token is the
|
||||
* expected one.
|
||||
*
|
||||
* @return @c token if the current token is the expected one,
|
||||
* otherwise PARSER_UNKNOWN_TOKEN.
|
||||
*/
|
||||
token_t expect_token(const char* zWord, int len, token_t token)
|
||||
{
|
||||
const char* pI = m_pI;
|
||||
const char* pEnd = zWord + len;
|
||||
|
||||
while ((pI < m_pEnd) && (zWord < pEnd) && (toupper(*pI) == *zWord))
|
||||
{
|
||||
++pI;
|
||||
++zWord;
|
||||
}
|
||||
|
||||
if (zWord == pEnd)
|
||||
{
|
||||
if ((pI == m_pEnd) || (!isalpha(*pI))) // Handwritten isalpha not faster than library version.
|
||||
{
|
||||
m_pI = pI;
|
||||
}
|
||||
else
|
||||
{
|
||||
token = PARSER_UNKNOWN_TOKEN;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
token = PARSER_UNKNOWN_TOKEN;
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
protected:
|
||||
const char* m_pSql;
|
||||
int m_len;
|
||||
const char* m_pI;
|
||||
const char* m_pEnd;
|
||||
};
|
||||
|
||||
}
|
27
include/maxscale/encryption.h
Normal file
27
include/maxscale/encryption.h
Normal file
@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
/*
|
||||
* Copyright (c) 2016 MariaDB Corporation Ab
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file and at www.mariadb.com/bsl11.
|
||||
*
|
||||
* Change Date: 2020-01-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2 or later of the General
|
||||
* Public License.
|
||||
*/
|
||||
|
||||
#include <maxscale/cdefs.h>
|
||||
|
||||
#include <openssl/evp.h>
|
||||
|
||||
MXS_BEGIN_DECLS
|
||||
|
||||
|
||||
EVP_CIPHER_CTX* mxs_evp_cipher_ctx_alloc();
|
||||
void mxs_evp_cipher_ctx_free(EVP_CIPHER_CTX* ctx);
|
||||
uint8_t* mxs_evp_cipher_ctx_buf(EVP_CIPHER_CTX* ctx);
|
||||
uint8_t* mxs_evp_cipher_ctx_oiv(EVP_CIPHER_CTX* ctx);
|
||||
|
||||
MXS_END_DECLS
|
@ -84,9 +84,13 @@ MXS_BEGIN_DECLS
|
||||
* [10-11] warning_count (2) -- number of warnings
|
||||
*/
|
||||
#define MYSQL_PS_ID_OFFSET MYSQL_HEADER_LEN + 1
|
||||
#define MYSQL_PS_ID_SIZE 4
|
||||
#define MYSQL_PS_COLS_OFFSET MYSQL_HEADER_LEN + 5
|
||||
#define MYSQL_PS_COLS_SIZE 2
|
||||
#define MYSQL_PS_PARAMS_OFFSET MYSQL_HEADER_LEN + 7
|
||||
#define MYSQL_PS_PARAMS_SIZE 2
|
||||
#define MYSQL_PS_WARN_OFFSET MYSQL_HEADER_LEN + 10
|
||||
#define MYSQL_PS_WARN_SIZE 2
|
||||
|
||||
/** Name of the default server side authentication plugin */
|
||||
#define DEFAULT_MYSQL_AUTH_PLUGIN "mysql_native_password"
|
||||
@ -308,6 +312,14 @@ typedef struct
|
||||
#endif
|
||||
} MySQLProtocol;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t id;
|
||||
uint16_t columns;
|
||||
uint16_t parameters;
|
||||
uint16_t warnings;
|
||||
} MXS_PS_RESPONSE;
|
||||
|
||||
/** Defines for response codes */
|
||||
#define MYSQL_REPLY_ERR 0xff
|
||||
#define MYSQL_REPLY_OK 0x00
|
||||
@ -504,4 +516,44 @@ const char* mxs_mysql_get_current_db(MXS_SESSION* session);
|
||||
*/
|
||||
void mxs_mysql_set_current_db(MXS_SESSION* session, const char* db);
|
||||
|
||||
/**
|
||||
* @brief Get the command byte
|
||||
*
|
||||
* @param buffer Buffer containing a complete MySQL packet
|
||||
*
|
||||
* @return The command byte
|
||||
*/
|
||||
uint8_t mxs_mysql_get_command(GWBUF* buffer);
|
||||
|
||||
/**
|
||||
* @brief Extract PS response values
|
||||
*
|
||||
* @param buffer Buffer containing a complete response to a binary protocol
|
||||
* preparation of a prepared statement
|
||||
* @param out Destination where the values are extracted
|
||||
*
|
||||
* @return True if values were extracted successfully
|
||||
*/
|
||||
bool mxs_mysql_extract_ps_response(GWBUF* buffer, MXS_PS_RESPONSE* out);
|
||||
|
||||
/**
|
||||
* @brief Extract the ID from a COM_STMT command
|
||||
*
|
||||
* All the COM_STMT type commands store the statement ID in the same place.
|
||||
*
|
||||
* @param buffer Buffer containing one of the COM_STMT commands (not COM_STMT_PREPARE)
|
||||
*
|
||||
* @return The statement ID
|
||||
*/
|
||||
uint32_t mxs_mysql_extract_ps_id(GWBUF* buffer);
|
||||
|
||||
/**
|
||||
* @brief Determine if a packet contains a one way message
|
||||
*
|
||||
* @param cmd Command to inspect
|
||||
*
|
||||
* @return True if a response is expected from the server
|
||||
*/
|
||||
bool mxs_mysql_command_will_respond(uint8_t cmd);
|
||||
|
||||
MXS_END_DECLS
|
||||
|
@ -29,6 +29,16 @@ typedef enum qc_init_kind
|
||||
QC_INIT_BOTH = 0x03
|
||||
} qc_init_kind_t;
|
||||
|
||||
/**
|
||||
* qc_sql_mode_t specifies what should be assumed of the statements
|
||||
* that will be parsed.
|
||||
*/
|
||||
typedef enum qc_sql_mode
|
||||
{
|
||||
QC_SQL_MODE_DEFAULT, /*< Assume the statements are MariaDB SQL. */
|
||||
QC_SQL_MODE_ORACLE /*< Assume the statements are PL/SQL. */
|
||||
} qc_sql_mode_t;
|
||||
|
||||
/**
|
||||
* @c qc_collect_info_t specifies what information should be collected during parsing.
|
||||
*/
|
||||
@ -83,19 +93,22 @@ typedef enum qc_query_type
|
||||
typedef enum qc_query_op
|
||||
{
|
||||
QUERY_OP_UNDEFINED = 0,
|
||||
QUERY_OP_SELECT,
|
||||
QUERY_OP_UPDATE,
|
||||
QUERY_OP_INSERT,
|
||||
QUERY_OP_DELETE,
|
||||
QUERY_OP_TRUNCATE,
|
||||
|
||||
QUERY_OP_ALTER,
|
||||
QUERY_OP_CREATE,
|
||||
QUERY_OP_DROP,
|
||||
QUERY_OP_CHANGE_DB,
|
||||
QUERY_OP_LOAD,
|
||||
QUERY_OP_GRANT,
|
||||
QUERY_OP_REVOKE,
|
||||
QUERY_OP_CREATE,
|
||||
QUERY_OP_DELETE,
|
||||
QUERY_OP_DROP,
|
||||
QUERY_OP_EXECUTE,
|
||||
QUERY_OP_EXPLAIN,
|
||||
QUERY_OP_GRANT,
|
||||
QUERY_OP_INSERT,
|
||||
QUERY_OP_LOAD,
|
||||
QUERY_OP_REVOKE,
|
||||
QUERY_OP_SELECT,
|
||||
QUERY_OP_SHOW,
|
||||
QUERY_OP_TRUNCATE,
|
||||
QUERY_OP_UPDATE,
|
||||
} qc_query_op_t;
|
||||
|
||||
/**
|
||||
@ -173,12 +186,13 @@ typedef struct query_classifier
|
||||
/**
|
||||
* Called once to setup the query classifier
|
||||
*
|
||||
* @param args The value of `query_classifier_args` in the configuration file.
|
||||
* @param sql_mode The default sql mode.
|
||||
* @param args The value of `query_classifier_args` in the configuration file.
|
||||
*
|
||||
* @return QC_RESULT_OK, if the query classifier could be setup, otherwise
|
||||
* some specific error code.
|
||||
*/
|
||||
int32_t (*qc_setup)(const char* args);
|
||||
int32_t (*qc_setup)(qc_sql_mode_t sql_mode, const char* args);
|
||||
|
||||
/**
|
||||
* Called once at process startup, after @c qc_setup has successfully
|
||||
@ -393,6 +407,24 @@ typedef struct query_classifier
|
||||
* version = major * 10000 + minor * 100 + patch
|
||||
*/
|
||||
void (*qc_get_server_version)(uint64_t* version);
|
||||
|
||||
/**
|
||||
* Gets the sql mode of the *calling* thread.
|
||||
*
|
||||
* @param sql_mode The mode.
|
||||
*
|
||||
* @return QC_RESULT_OK
|
||||
*/
|
||||
int32_t (*qc_get_sql_mode)(qc_sql_mode_t* sql_mode);
|
||||
|
||||
/**
|
||||
* Sets the sql mode for the *calling* thread.
|
||||
*
|
||||
* @param sql_mode The mode.
|
||||
*
|
||||
* @return QC_RESULT_OK if @sql_mode is valid, otherwise QC_RESULT_ERROR.
|
||||
*/
|
||||
int32_t (*qc_set_sql_mode)(qc_sql_mode_t sql_mode);
|
||||
} QUERY_CLASSIFIER;
|
||||
|
||||
/**
|
||||
@ -406,6 +438,7 @@ typedef struct query_classifier
|
||||
*
|
||||
* @param plugin_name The name of the plugin from which the query classifier
|
||||
* should be loaded.
|
||||
* @param sql_mode The default sql mode.
|
||||
* @param plugin_args The arguments to be provided to the query classifier.
|
||||
*
|
||||
* @return True if the query classifier could be loaded and initialized,
|
||||
@ -413,7 +446,7 @@ typedef struct query_classifier
|
||||
*
|
||||
* @see qc_end qc_thread_init
|
||||
*/
|
||||
bool qc_setup(const char* plugin_name, const char* plugin_args);
|
||||
bool qc_setup(const char* plugin_name, qc_sql_mode_t sql_mode, const char* plugin_args);
|
||||
|
||||
/**
|
||||
* Intializes the query classifier.
|
||||
@ -658,6 +691,13 @@ char* qc_get_prepare_name(GWBUF* stmt);
|
||||
*/
|
||||
GWBUF* qc_get_preparable_stmt(GWBUF* stmt);
|
||||
|
||||
/**
|
||||
* Gets the sql mode of the *calling* thread.
|
||||
*
|
||||
* @return The mode.
|
||||
*/
|
||||
qc_sql_mode_t qc_get_sql_mode();
|
||||
|
||||
/**
|
||||
* Returns the tables accessed by the statement.
|
||||
*
|
||||
@ -756,6 +796,13 @@ static inline bool qc_query_is_type(uint32_t typemask, qc_query_type_t type)
|
||||
*/
|
||||
bool qc_query_has_clause(GWBUF* stmt);
|
||||
|
||||
/**
|
||||
* Sets the sql mode for the *calling* thread.
|
||||
*
|
||||
* @param sql_mode The mode.
|
||||
*/
|
||||
void qc_set_sql_mode(qc_sql_mode_t sql_mode);
|
||||
|
||||
/**
|
||||
* Returns the string representation of a query type.
|
||||
*
|
||||
|
@ -146,6 +146,7 @@ typedef struct session
|
||||
int refcount; /*< Reference count on the session */
|
||||
mxs_session_trx_state_t trx_state; /*< The current transaction state. */
|
||||
bool autocommit; /*< Whether autocommit is on. */
|
||||
intptr_t client_protocol_data; /*< Owned and managed by the client protocol. */
|
||||
struct
|
||||
{
|
||||
GWBUF *buffer; /**< Buffer containing the statement */
|
||||
|
@ -54,10 +54,11 @@ public:
|
||||
uint64_t get_position() const;
|
||||
|
||||
/**
|
||||
* @brief Creates a copy of the internal buffer
|
||||
* @return A copy of the internal buffer
|
||||
* @brief Creates a deep copy of the internal buffer
|
||||
*
|
||||
* @return A deep copy of the internal buffer or NULL on error
|
||||
*/
|
||||
mxs::Buffer copy_buffer() const;
|
||||
GWBUF* deep_copy_buffer();
|
||||
|
||||
/**
|
||||
* @brief Create a new session command
|
||||
|
Reference in New Issue
Block a user