1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-08-07 03:22:57 +03:00

Reformat all code to coding standard

This commit is contained in:
Andrew Hutchings
2017-10-26 17:18:17 +01:00
parent 4985f3456e
commit 01446d1e22
1296 changed files with 403852 additions and 353747 deletions

View File

@@ -21,139 +21,159 @@
bool parseAutoincrementTableComment ( std::string comment, uint64_t& startValue, std::string& columnName )
{
algorithm::to_upper(comment);
regex compat("[[:space:]]*AUTOINCREMENT[[:space:]]*=[[:space:]]*", regex_constants::extended);
bool autoincrement = false;
columnName = "";
boost::match_results<std::string::const_iterator> what;
std::string::const_iterator start, end;
start = comment.begin();
end = comment.end();
boost::match_flag_type flags = boost::match_default;
if (boost::regex_search(start, end, what, compat, flags))
{
if (what[0].matched)
{
//string params (what[0].first, what[0].second);
string params (&(*(what[0].second)));
unsigned i = params.find_first_of(",");
if ( i <= params.length() )
{
//check whether there is more autoincrement column
string restComment = params.substr(i+1, params.length());
start = restComment.begin();
end = restComment.end();
if (boost::regex_search(start, end, what, compat, flags))
{
if (what[0].matched)
throw runtime_error(IDBErrorInfo::instance()->errorMsg(ERR_INVALID_NUMBER_AUTOINCREMENT));
}
columnName = params.substr(0, i);
string startVal = params.substr(i+1, params.length());
//get rid of possible empty space
i = startVal.find_first_not_of(" ");
if ( i <= startVal.length() )
{
startVal = startVal.substr( i, startVal.length());
//; is the seperator between compression and autoincrement comments.
i = startVal.find_first_of(";");
if ( i <= startVal.length() )
{
startVal = startVal.substr( 0,i);
}
i = startVal.find_last_not_of(" ");
if ( i <= startVal.length() )
{
startVal = startVal.substr( 0,i+1);
}
errno = 0;
char *ep = NULL;
const char *str = startVal.c_str();
startValue = strtoull(str, &ep, 10);
// (no digits) || (more chars) || (other errors & value = 0)
if ((ep == str) || (*ep != '\0') || (errno != 0))
{
throw runtime_error(IDBErrorInfo::instance()->errorMsg(ERR_INVALID_START_VALUE));
}
}
}
else
{
columnName = params;
}
autoincrement = true;
}
}
if (columnName.compare("") != 0)
{
//get rid of possible empty space
unsigned i = columnName.find_last_not_of(" ");
if ( i <= columnName.length() )
{
columnName = columnName.substr( 0,i+1);
}
}
return autoincrement;
algorithm::to_upper(comment);
regex compat("[[:space:]]*AUTOINCREMENT[[:space:]]*=[[:space:]]*", regex_constants::extended);
bool autoincrement = false;
columnName = "";
boost::match_results<std::string::const_iterator> what;
std::string::const_iterator start, end;
start = comment.begin();
end = comment.end();
boost::match_flag_type flags = boost::match_default;
if (boost::regex_search(start, end, what, compat, flags))
{
if (what[0].matched)
{
//string params (what[0].first, what[0].second);
string params (&(*(what[0].second)));
unsigned i = params.find_first_of(",");
if ( i <= params.length() )
{
//check whether there is more autoincrement column
string restComment = params.substr(i + 1, params.length());
start = restComment.begin();
end = restComment.end();
if (boost::regex_search(start, end, what, compat, flags))
{
if (what[0].matched)
throw runtime_error(IDBErrorInfo::instance()->errorMsg(ERR_INVALID_NUMBER_AUTOINCREMENT));
}
columnName = params.substr(0, i);
string startVal = params.substr(i + 1, params.length());
//get rid of possible empty space
i = startVal.find_first_not_of(" ");
if ( i <= startVal.length() )
{
startVal = startVal.substr( i, startVal.length());
//; is the seperator between compression and autoincrement comments.
i = startVal.find_first_of(";");
if ( i <= startVal.length() )
{
startVal = startVal.substr( 0, i);
}
i = startVal.find_last_not_of(" ");
if ( i <= startVal.length() )
{
startVal = startVal.substr( 0, i + 1);
}
errno = 0;
char* ep = NULL;
const char* str = startVal.c_str();
startValue = strtoull(str, &ep, 10);
// (no digits) || (more chars) || (other errors & value = 0)
if ((ep == str) || (*ep != '\0') || (errno != 0))
{
throw runtime_error(IDBErrorInfo::instance()->errorMsg(ERR_INVALID_START_VALUE));
}
}
}
else
{
columnName = params;
}
autoincrement = true;
}
}
if (columnName.compare("") != 0)
{
//get rid of possible empty space
unsigned i = columnName.find_last_not_of(" ");
if ( i <= columnName.length() )
{
columnName = columnName.substr( 0, i + 1);
}
}
return autoincrement;
}
bool parseAutoincrementColumnComment ( std::string comment, uint64_t& startValue )
{
algorithm::to_upper(comment);
regex compat("[[:space:]]*AUTOINCREMENT[[:space:]]*", regex_constants::extended);
bool autoincrement = false;
boost::match_results<std::string::const_iterator> what;
std::string::const_iterator start, end;
start = comment.begin();
end = comment.end();
boost::match_flag_type flags = boost::match_default;
if (boost::regex_search(start, end, what, compat, flags))
{
if (what[0].matched)
{
string params (&(*(what[0].second)));
unsigned i = params.find_first_of(",");
if ( i <= params.length() )
{
string startVal = params.substr(i+1, params.length());
//get rid of possible empty space
i = startVal.find_first_not_of(" ");
if ( i <= startVal.length() )
{
startVal = startVal.substr( i, startVal.length());
//; is the seperator between compression and autoincrement comments.
i = startVal.find_first_of(";");
if ( i <= startVal.length() )
{
startVal = startVal.substr( 0,i);
}
i = startVal.find_last_not_of(" ");
if ( i <= startVal.length() )
{
startVal = startVal.substr( 0,i+1);
}
errno = 0;
char *ep = NULL;
const char *str = startVal.c_str();
startValue = strtoll(str, &ep, 10);
// (no digits) || (more chars) || (other errors & value = 0)
if ((ep == str) || (*ep != '\0') || (errno != 0))
{
throw runtime_error (IDBErrorInfo::instance()->errorMsg(ERR_INVALID_START_VALUE));
}
}
}
else
{
startValue = 1;
}
autoincrement = true;
}
}
return autoincrement;
algorithm::to_upper(comment);
regex compat("[[:space:]]*AUTOINCREMENT[[:space:]]*", regex_constants::extended);
bool autoincrement = false;
boost::match_results<std::string::const_iterator> what;
std::string::const_iterator start, end;
start = comment.begin();
end = comment.end();
boost::match_flag_type flags = boost::match_default;
if (boost::regex_search(start, end, what, compat, flags))
{
if (what[0].matched)
{
string params (&(*(what[0].second)));
unsigned i = params.find_first_of(",");
if ( i <= params.length() )
{
string startVal = params.substr(i + 1, params.length());
//get rid of possible empty space
i = startVal.find_first_not_of(" ");
if ( i <= startVal.length() )
{
startVal = startVal.substr( i, startVal.length());
//; is the seperator between compression and autoincrement comments.
i = startVal.find_first_of(";");
if ( i <= startVal.length() )
{
startVal = startVal.substr( 0, i);
}
i = startVal.find_last_not_of(" ");
if ( i <= startVal.length() )
{
startVal = startVal.substr( 0, i + 1);
}
errno = 0;
char* ep = NULL;
const char* str = startVal.c_str();
startValue = strtoll(str, &ep, 10);
// (no digits) || (more chars) || (other errors & value = 0)
if ((ep == str) || (*ep != '\0') || (errno != 0))
{
throw runtime_error (IDBErrorInfo::instance()->errorMsg(ERR_INVALID_START_VALUE));
}
}
}
else
{
startValue = 1;
}
autoincrement = true;
}
}
return autoincrement;
}
// vim:ts=4 sw=4:

670
dbcon/mysql/ha_calpont.cpp Executable file → Normal file

File diff suppressed because it is too large Load Diff

308
dbcon/mysql/ha_calpont.h Executable file → Normal file
View File

@@ -44,11 +44,12 @@
EXAMPLE_SHARE is a structure that will be shared among all open handlers.
This example implements the minimum of what you will probably need.
*/
typedef struct st_calpont_share {
char *table_name;
uint32_t table_name_length,use_count;
pthread_mutex_t mutex;
THR_LOCK lock;
typedef struct st_calpont_share
{
char* table_name;
uint32_t table_name_length, use_count;
pthread_mutex_t mutex;
THR_LOCK lock;
} INFINIDB_SHARE;
/** @brief
@@ -56,173 +57,188 @@ typedef struct st_calpont_share {
*/
class ha_calpont: public handler
{
THR_LOCK_DATA lock; ///< MySQL lock
INFINIDB_SHARE *share; ///< Shared lock info
ulonglong int_table_flags;
THR_LOCK_DATA lock; ///< MySQL lock
INFINIDB_SHARE* share; ///< Shared lock info
ulonglong int_table_flags;
public:
ha_calpont(handlerton *hton, TABLE_SHARE *table_arg);
~ha_calpont()
{
}
ha_calpont(handlerton* hton, TABLE_SHARE* table_arg);
~ha_calpont()
{
}
/** @brief
The name that will be used for display purposes.
*/
const char *table_type() const { return "ColumnStore"; }
/** @brief
The name that will be used for display purposes.
*/
const char* table_type() const
{
return "ColumnStore";
}
/** @brief
The name of the index type that will be used for display.
Don't implement this method unless you really have indexes.
*/
//const char *index_type(uint32_t inx) { return "HASH"; }
/** @brief
The name of the index type that will be used for display.
Don't implement this method unless you really have indexes.
*/
//const char *index_type(uint32_t inx) { return "HASH"; }
/** @brief
The file extensions.
*/
const char **bas_ext() const;
/** @brief
The file extensions.
*/
const char** bas_ext() const;
/** @brief
This is a list of flags that indicate what functionality the storage engine
implements. The current table flags are documented in handler.h
*/
ulonglong table_flags() const {return int_table_flags;}
/** @brief
This is a list of flags that indicate what functionality the storage engine
implements. The current table flags are documented in handler.h
*/
ulonglong table_flags() const
{
return int_table_flags;
}
/** @brief
This is a bitmap of flags that indicates how the storage engine
implements indexes. The current index flags are documented in
handler.h. If you do not implement indexes, just return zero here.
/** @brief
This is a bitmap of flags that indicates how the storage engine
implements indexes. The current index flags are documented in
handler.h. If you do not implement indexes, just return zero here.
@details
part is the key part to check. First key part is 0.
If all_parts is set, MySQL wants to know the flags for the combined
index, up to and including 'part'.
*/
ulong index_flags(uint32_t inx, uint32_t part, bool all_parts) const {return 0;}
@details
part is the key part to check. First key part is 0.
If all_parts is set, MySQL wants to know the flags for the combined
index, up to and including 'part'.
*/
ulong index_flags(uint32_t inx, uint32_t part, bool all_parts) const
{
return 0;
}
/** @brief
unireg.cc will call max_supported_record_length(), max_supported_keys(),
max_supported_key_parts(), uint32_t max_supported_key_length()
to make sure that the storage engine can handle the data it is about to
send. Return *real* limits of your storage engine here; MySQL will do
min(your_limits, MySQL_limits) automatically.
*/
uint32_t max_supported_record_length() const { return HA_MAX_REC_LENGTH; }
/** @brief
unireg.cc will call max_supported_record_length(), max_supported_keys(),
max_supported_key_parts(), uint32_t max_supported_key_length()
to make sure that the storage engine can handle the data it is about to
send. Return *real* limits of your storage engine here; MySQL will do
min(your_limits, MySQL_limits) automatically.
*/
uint32_t max_supported_record_length() const
{
return HA_MAX_REC_LENGTH;
}
/** @brief
Called in test_quick_select to determine if indexes should be used.
*/
virtual double scan_time() { return (double) (stats.records+stats.deleted) / 20.0+10; }
/** @brief
Called in test_quick_select to determine if indexes should be used.
*/
virtual double scan_time()
{
return (double) (stats.records + stats.deleted) / 20.0 + 10;
}
/*
Everything below are methods that we implement in ha_example.cc.
/*
Everything below are methods that we implement in ha_example.cc.
Most of these methods are not obligatory, skip them and
MySQL will treat them as not implemented
*/
Most of these methods are not obligatory, skip them and
MySQL will treat them as not implemented
*/
/** @brief
We implement this in ha_example.cc; it's a required method.
*/
int open(const char *name, int mode, uint32_t test_if_locked); // required
/** @brief
We implement this in ha_example.cc; it's a required method.
*/
int open(const char* name, int mode, uint32_t test_if_locked); // required
/** @brief
We implement this in ha_example.cc; it's a required method.
*/
int close(void); // required
/** @brief
We implement this in ha_example.cc; it's a required method.
*/
int close(void); // required
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int write_row(uchar *buf);
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
void start_bulk_insert(ha_rows rows, uint flags= 0) ;
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int end_bulk_insert(bool abort) ;
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int write_row(uchar* buf);
/**@bug 2461 - Overloaded end_bulk_insert. MariaDB uses the abort bool, mysql does not. */
int end_bulk_insert() ;
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
void start_bulk_insert(ha_rows rows, uint flags = 0) ;
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int update_row(const uchar *old_data, uchar *new_data);
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int end_bulk_insert(bool abort) ;
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int delete_row(const uchar *buf);
/**@bug 2461 - Overloaded end_bulk_insert. MariaDB uses the abort bool, mysql does not. */
int end_bulk_insert() ;
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int index_read_map(uchar *buf, const uchar *key,
key_part_map keypart_map, enum ha_rkey_function find_flag);
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int update_row(const uchar* old_data, uchar* new_data);
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int index_next(uchar *buf);
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int delete_row(const uchar* buf);
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int index_prev(uchar *buf);
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int index_read_map(uchar* buf, const uchar* key,
key_part_map keypart_map, enum ha_rkey_function find_flag);
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int index_first(uchar *buf);
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int index_next(uchar* buf);
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int index_last(uchar *buf);
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int index_prev(uchar* buf);
/** @brief
Unlike index_init(), rnd_init() can be called two consecutive times
without rnd_end() in between (it only makes sense if scan=1). In this
case, the second call should prepare for the new table scan (e.g if
rnd_init() allocates the cursor, the second call should position the
cursor to the start of the table; no need to deallocate and allocate
it again. This is a required method.
*/
int rnd_init(bool scan); //required
int rnd_end();
int rnd_next(uchar *buf); ///< required
int rnd_pos(uchar *buf, uchar *pos); ///< required
void position(const uchar *record); ///< required
int info(uint32_t); ///< required
int extra(enum ha_extra_function operation);
int external_lock(THD *thd, int lock_type); ///< required
int delete_all_rows(void);
ha_rows records_in_range(uint32_t inx, key_range *min_key,
key_range *max_key);
int delete_table(const char *from);
int rename_table(const char * from, const char * to);
int create(const char *name, TABLE *form,
HA_CREATE_INFO *create_info); ///< required
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int index_first(uchar* buf);
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
enum thr_lock_type lock_type); ///< required
const COND *cond_push(const COND *cond);
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int index_last(uchar* buf);
/** @brief
Unlike index_init(), rnd_init() can be called two consecutive times
without rnd_end() in between (it only makes sense if scan=1). In this
case, the second call should prepare for the new table scan (e.g if
rnd_init() allocates the cursor, the second call should position the
cursor to the start of the table; no need to deallocate and allocate
it again. This is a required method.
*/
int rnd_init(bool scan); //required
int rnd_end();
int rnd_next(uchar* buf); ///< required
int rnd_pos(uchar* buf, uchar* pos); ///< required
void position(const uchar* record); ///< required
int info(uint32_t); ///< required
int extra(enum ha_extra_function operation);
int external_lock(THD* thd, int lock_type); ///< required
int delete_all_rows(void);
ha_rows records_in_range(uint32_t inx, key_range* min_key,
key_range* max_key);
int delete_table(const char* from);
int rename_table(const char* from, const char* to);
int create(const char* name, TABLE* form,
HA_CREATE_INFO* create_info); ///< required
THR_LOCK_DATA** store_lock(THD* thd, THR_LOCK_DATA** to,
enum thr_lock_type lock_type); ///< required
const COND* cond_push(const COND* cond);
};
#endif //HA_CALPONT_H__

3756
dbcon/mysql/ha_calpont_ddl.cpp Executable file → Normal file

File diff suppressed because it is too large Load Diff

3249
dbcon/mysql/ha_calpont_dml.cpp Executable file → Normal file

File diff suppressed because it is too large Load Diff

13268
dbcon/mysql/ha_calpont_execplan.cpp Executable file → Normal file

File diff suppressed because it is too large Load Diff

7281
dbcon/mysql/ha_calpont_impl.cpp Executable file → Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -28,46 +28,46 @@
#include "idb_mysql.h"
#ifdef NEED_CALPONT_EXTERNS
extern int ha_calpont_impl_discover_existence(const char *schema, const char *name);
extern int ha_calpont_impl_create(const char *name, TABLE *table_arg, HA_CREATE_INFO *create_info);
extern int ha_calpont_impl_delete_table(const char *name);
extern int ha_calpont_impl_open(const char *name, int mode, uint32_t test_if_locked);
extern int ha_calpont_impl_discover_existence(const char* schema, const char* name);
extern int ha_calpont_impl_create(const char* name, TABLE* table_arg, HA_CREATE_INFO* create_info);
extern int ha_calpont_impl_delete_table(const char* name);
extern int ha_calpont_impl_open(const char* name, int mode, uint32_t test_if_locked);
extern int ha_calpont_impl_close(void);
extern int ha_calpont_impl_rnd_init(TABLE* table);
extern int ha_calpont_impl_rnd_next(uchar *buf, TABLE* table);
extern int ha_calpont_impl_rnd_next(uchar* buf, TABLE* table);
extern int ha_calpont_impl_rnd_end(TABLE* table);
extern int ha_calpont_impl_write_row(uchar *buf, TABLE* table);
extern int ha_calpont_impl_write_row(uchar* buf, TABLE* table);
extern void ha_calpont_impl_start_bulk_insert(ha_rows rows, TABLE* table);
extern int ha_calpont_impl_end_bulk_insert(bool abort, TABLE* table);
extern int ha_calpont_impl_rename_table(const char* from, const char* to);
extern int ha_calpont_impl_commit (handlerton *hton, THD *thd, bool all);
extern int ha_calpont_impl_rollback (handlerton *hton, THD *thd, bool all);
extern int ha_calpont_impl_close_connection (handlerton *hton, THD *thd);
extern COND* ha_calpont_impl_cond_push(COND *cond, TABLE* table);
extern int ha_calpont_impl_external_lock(THD *thd, TABLE* table, int lock_type);
extern int ha_calpont_impl_commit (handlerton* hton, THD* thd, bool all);
extern int ha_calpont_impl_rollback (handlerton* hton, THD* thd, bool all);
extern int ha_calpont_impl_close_connection (handlerton* hton, THD* thd);
extern COND* ha_calpont_impl_cond_push(COND* cond, TABLE* table);
extern int ha_calpont_impl_external_lock(THD* thd, TABLE* table, int lock_type);
extern int ha_calpont_impl_update_row();
extern int ha_calpont_impl_delete_row();
extern int ha_calpont_impl_rnd_pos(uchar *buf, uchar *pos);
extern int ha_calpont_impl_rnd_pos(uchar* buf, uchar* pos);
#endif
#ifdef NEED_CALPONT_INTERFACE
#include "ha_calpont_impl_if.h"
#include "calpontsystemcatalog.h"
extern int ha_calpont_impl_rename_table_(const char* from, const char* to, cal_impl_if::cal_connection_info& ci);
extern int ha_calpont_impl_write_row_(uchar *buf, TABLE* table, cal_impl_if::cal_connection_info& ci, ha_rows& rowsInserted);
extern int ha_calpont_impl_write_batch_row_(uchar *buf,TABLE* table, cal_impl_if::cal_connection_info& ci);
extern int ha_calpont_impl_write_row_(uchar* buf, TABLE* table, cal_impl_if::cal_connection_info& ci, ha_rows& rowsInserted);
extern int ha_calpont_impl_write_batch_row_(uchar* buf, TABLE* table, cal_impl_if::cal_connection_info& ci);
extern int ha_calpont_impl_write_last_batch(TABLE* table, cal_impl_if::cal_connection_info& ci, bool abort);
extern int ha_calpont_impl_commit_ (handlerton *hton, THD *thd, bool all, cal_impl_if::cal_connection_info& ci);
extern int ha_calpont_impl_rollback_ (handlerton *hton, THD *thd, bool all, cal_impl_if::cal_connection_info& ci);
extern int ha_calpont_impl_close_connection_ (handlerton *hton, THD *thd, cal_impl_if::cal_connection_info& ci);
extern int ha_calpont_impl_delete_table_(const char *db, const char *name, cal_impl_if::cal_connection_info& ci);
extern int ha_calpont_impl_create_(const char *name, TABLE *table_arg, HA_CREATE_INFO *create_info,
cal_impl_if::cal_connection_info& ci);
extern int ha_calpont_impl_commit_ (handlerton* hton, THD* thd, bool all, cal_impl_if::cal_connection_info& ci);
extern int ha_calpont_impl_rollback_ (handlerton* hton, THD* thd, bool all, cal_impl_if::cal_connection_info& ci);
extern int ha_calpont_impl_close_connection_ (handlerton* hton, THD* thd, cal_impl_if::cal_connection_info& ci);
extern int ha_calpont_impl_delete_table_(const char* db, const char* name, cal_impl_if::cal_connection_info& ci);
extern int ha_calpont_impl_create_(const char* name, TABLE* table_arg, HA_CREATE_INFO* create_info,
cal_impl_if::cal_connection_info& ci);
extern std::string ha_calpont_impl_markpartition_ (execplan::CalpontSystemCatalog::TableName tableName, uint32_t partition);
extern std::string ha_calpont_impl_restorepartition_ (execplan::CalpontSystemCatalog::TableName tableName, uint32_t partition);
extern std::string ha_calpont_impl_droppartition_ (execplan::CalpontSystemCatalog::TableName tableName, uint32_t partition);
extern std::string ha_calpont_impl_viewtablelock( cal_impl_if::cal_connection_info& ci, execplan::CalpontSystemCatalog::TableName& tablename);
extern std::string ha_calpont_impl_viewtablelock( cal_impl_if::cal_connection_info& ci, execplan::CalpontSystemCatalog::TableName& tablename);
extern std::string ha_calpont_impl_cleartablelock( cal_impl_if::cal_connection_info& ci, uint64_t tableLockID);
#endif

View File

@@ -54,15 +54,15 @@ struct st_ha_create_information;
namespace execplan
{
class ReturnedColumn;
class SimpleColumn;
class SimpleFilter;
class AggregateColumn;
class FunctionColumn;
class ArithmeticColumn;
class ParseTree;
class ConstantColumn;
class RowColumn;
class ReturnedColumn;
class SimpleColumn;
class SimpleFilter;
class AggregateColumn;
class FunctionColumn;
class ArithmeticColumn;
class ParseTree;
class ConstantColumn;
class RowColumn;
}
namespace cal_impl_if
@@ -72,20 +72,20 @@ class View;
struct JoinInfo
{
execplan::CalpontSystemCatalog::TableAliasName tn;
uint32_t joinTimes;
std::vector<uint32_t> IDs;
execplan::CalpontSystemCatalog::TableAliasName tn;
uint32_t joinTimes;
std::vector<uint32_t> IDs;
};
enum ClauseType
{
INIT = 0,
SELECT,
FROM,
WHERE,
HAVING,
GROUP_BY,
ORDER_BY
INIT = 0,
SELECT,
FROM,
WHERE,
HAVING,
GROUP_BY,
ORDER_BY
};
typedef std::vector<JoinInfo> JoinInfoVec;
@@ -94,101 +94,101 @@ typedef std::map<execplan::CalpontSystemCatalog::TableAliasName, std::pair<int,
struct gp_walk_info
{
std::vector <std::string> selectCols;
execplan::CalpontSelectExecutionPlan::ReturnedColumnList returnedCols;
execplan::CalpontSelectExecutionPlan::ReturnedColumnList groupByCols;
execplan::CalpontSelectExecutionPlan::ReturnedColumnList subGroupByCols;
execplan::CalpontSelectExecutionPlan::ReturnedColumnList orderByCols;
execplan::CalpontSelectExecutionPlan::ColumnMap columnMap;
// This vector temporarily hold the projection columns to be added
// to the returnedCols vector for subquery processing. It will be appended
// to the end of returnedCols when the processing is finished.
execplan::CalpontSelectExecutionPlan::ReturnedColumnList additionalRetCols;
// the sequence # of the subselect local columns need to be set after
// the additionRetCols are merged to the returnedCols.
std::vector<execplan::ReturnedColumn*> localCols;
std::stack<execplan::ReturnedColumn*> rcWorkStack;
std::stack<execplan::ParseTree*> ptWorkStack;
boost::shared_ptr<execplan::SimpleColumn> scsp;
uint32_t sessionid;
bool fatalParseError;
std::string parseErrorText;
// for outer join walk. the column that is not of the outerTable has the returnAll flag set.
std::set<execplan::CalpontSystemCatalog::TableAliasName> innerTables;
// the followinig members are used for table mode
bool condPush;
bool dropCond;
std::string funcName;
std::vector<execplan::AggregateColumn*> count_asterisk_list;
std::vector<execplan::FunctionColumn*> no_parm_func_list;
std::vector<execplan::ReturnedColumn*> windowFuncList;
TableMap tableMap;
boost::shared_ptr<execplan::CalpontSystemCatalog> csc;
int8_t internalDecimalScale;
THD* thd;
uint64_t subSelectType; // the type of sub select filter that owns the gwi
SubQuery* subQuery;
execplan::CalpontSelectExecutionPlan::SelectList derivedTbList;
execplan::CalpontSelectExecutionPlan::TableList tbList;
std::vector<execplan::CalpontSystemCatalog::TableAliasName> correlatedTbNameVec;
ClauseType clauseType;
execplan::CalpontSystemCatalog::TableAliasName viewName;
bool aggOnSelect;
bool hasWindowFunc;
bool hasSubSelect;
SubQuery* lastSub;
std::vector<View*> viewList;
std::map<std::string, execplan::ParseTree*> derivedTbFilterMap;
uint32_t derivedTbCnt;
std::vector<execplan::SCSEP> subselectList;
std::vector <std::string> selectCols;
execplan::CalpontSelectExecutionPlan::ReturnedColumnList returnedCols;
execplan::CalpontSelectExecutionPlan::ReturnedColumnList groupByCols;
execplan::CalpontSelectExecutionPlan::ReturnedColumnList subGroupByCols;
execplan::CalpontSelectExecutionPlan::ReturnedColumnList orderByCols;
execplan::CalpontSelectExecutionPlan::ColumnMap columnMap;
// This vector temporarily hold the projection columns to be added
// to the returnedCols vector for subquery processing. It will be appended
// to the end of returnedCols when the processing is finished.
execplan::CalpontSelectExecutionPlan::ReturnedColumnList additionalRetCols;
// the sequence # of the subselect local columns need to be set after
// the additionRetCols are merged to the returnedCols.
std::vector<execplan::ReturnedColumn*> localCols;
std::stack<execplan::ReturnedColumn*> rcWorkStack;
std::stack<execplan::ParseTree*> ptWorkStack;
boost::shared_ptr<execplan::SimpleColumn> scsp;
uint32_t sessionid;
bool fatalParseError;
std::string parseErrorText;
// for outer join walk. the column that is not of the outerTable has the returnAll flag set.
std::set<execplan::CalpontSystemCatalog::TableAliasName> innerTables;
// the followinig members are used for table mode
bool condPush;
bool dropCond;
std::string funcName;
std::vector<execplan::AggregateColumn*> count_asterisk_list;
std::vector<execplan::FunctionColumn*> no_parm_func_list;
std::vector<execplan::ReturnedColumn*> windowFuncList;
TableMap tableMap;
boost::shared_ptr<execplan::CalpontSystemCatalog> csc;
int8_t internalDecimalScale;
THD* thd;
uint64_t subSelectType; // the type of sub select filter that owns the gwi
SubQuery* subQuery;
execplan::CalpontSelectExecutionPlan::SelectList derivedTbList;
execplan::CalpontSelectExecutionPlan::TableList tbList;
std::vector<execplan::CalpontSystemCatalog::TableAliasName> correlatedTbNameVec;
ClauseType clauseType;
execplan::CalpontSystemCatalog::TableAliasName viewName;
bool aggOnSelect;
bool hasWindowFunc;
bool hasSubSelect;
SubQuery* lastSub;
std::vector<View*> viewList;
std::map<std::string, execplan::ParseTree*> derivedTbFilterMap;
uint32_t derivedTbCnt;
std::vector<execplan::SCSEP> subselectList;
// Kludge for Bug 750
int32_t recursionLevel;
int32_t recursionHWM;
std::stack<int32_t> rcBookMarkStack;
// Kludge for Bug 750
int32_t recursionLevel;
int32_t recursionHWM;
std::stack<int32_t> rcBookMarkStack;
gp_walk_info() : sessionid(0),
fatalParseError(false),
condPush(false),
dropCond(false),
internalDecimalScale(4),
thd(0),
subSelectType(uint64_t(-1)),
subQuery(0),
clauseType(INIT),
aggOnSelect(false),
hasWindowFunc(false),
hasSubSelect(false),
lastSub(0),
derivedTbCnt(0),
recursionLevel(-1),
recursionHWM(0)
{}
gp_walk_info() : sessionid(0),
fatalParseError(false),
condPush(false),
dropCond(false),
internalDecimalScale(4),
thd(0),
subSelectType(uint64_t(-1)),
subQuery(0),
clauseType(INIT),
aggOnSelect(false),
hasWindowFunc(false),
hasSubSelect(false),
lastSub(0),
derivedTbCnt(0),
recursionLevel(-1),
recursionHWM(0)
{}
~gp_walk_info() {}
~gp_walk_info() {}
};
struct cal_table_info
{
enum RowSources { FROM_ENGINE, FROM_FILE };
enum RowSources { FROM_ENGINE, FROM_FILE };
cal_table_info() : tpl_ctx(0),
//tpl_scan_ctx(0),
c(0),
msTablePtr(0),
conn_hndl(0),
condInfo(0),
moreRows(false)
{ }
~cal_table_info() {}
sm::cpsm_tplh_t* tpl_ctx;
sm::sp_cpsm_tplsch_t tpl_scan_ctx;
unsigned c; // for debug purpose
TABLE* msTablePtr; // no ownership
sm::cpsm_conhdl_t* conn_hndl;
gp_walk_info* condInfo;
execplan::SCSEP csep;
bool moreRows; //are there more rows to consume (b/c of limit)
cal_table_info() : tpl_ctx(0),
//tpl_scan_ctx(0),
c(0),
msTablePtr(0),
conn_hndl(0),
condInfo(0),
moreRows(false)
{ }
~cal_table_info() {}
sm::cpsm_tplh_t* tpl_ctx;
sm::sp_cpsm_tplsch_t tpl_scan_ctx;
unsigned c; // for debug purpose
TABLE* msTablePtr; // no ownership
sm::cpsm_conhdl_t* conn_hndl;
gp_walk_info* condInfo;
execplan::SCSEP csep;
bool moreRows; //are there more rows to consume (b/c of limit)
};
typedef std::tr1::unordered_map<TABLE*, cal_table_info> CalTableMap;
@@ -198,93 +198,97 @@ typedef std::map<uint32_t, ColValuesList> TableValuesMap;
typedef std::bitset<4096> NullValuesBitset;
struct cal_connection_info
{
enum AlterTableState { NOT_ALTER, ALTER_SECOND_RENAME, ALTER_FIRST_RENAME };
cal_connection_info() : cal_conn_hndl(0),
queryState(0),
currentTable(0),
traceFlags(0),
alterTableState(NOT_ALTER),
isAlter(false),
bulkInsertRows(0),
singleInsert(true),
isLoaddataInfile( false ),
dmlProc(0),
rowsHaveInserted(0),
rc(0),
tableOid(0),
localPm(-1),
isSlaveNode(false),
expressionId(0),
mysqld_pid(getpid()),
cpimport_pid(0),
filePtr(0),
headerLength(0),
useXbit(false),
utf8(false),
useCpimport(1),
delimiter('\7')
{
// check if this is a slave mysql daemon
isSlaveNode = checkSlave();
}
enum AlterTableState { NOT_ALTER, ALTER_SECOND_RENAME, ALTER_FIRST_RENAME };
cal_connection_info() : cal_conn_hndl(0),
queryState(0),
currentTable(0),
traceFlags(0),
alterTableState(NOT_ALTER),
isAlter(false),
bulkInsertRows(0),
singleInsert(true),
isLoaddataInfile( false ),
dmlProc(0),
rowsHaveInserted(0),
rc(0),
tableOid(0),
localPm(-1),
isSlaveNode(false),
expressionId(0),
mysqld_pid(getpid()),
cpimport_pid(0),
filePtr(0),
headerLength(0),
useXbit(false),
utf8(false),
useCpimport(1),
delimiter('\7')
{
// check if this is a slave mysql daemon
isSlaveNode = checkSlave();
}
static bool checkSlave()
{
config::Config* cf = config::Config::makeConfig();
std::string configVal = cf->getConfig("Installation", "MySQLRep");
bool isMysqlRep = (configVal == "y" || configVal == "Y");
if (!isMysqlRep) return false;
configVal = cf->getConfig("SystemConfig", "PrimaryUMModuleName");
std::string module = execplan::ClientRotator::getModule();
if (boost::iequals(configVal, module))
return false;
return true;
}
static bool checkSlave()
{
config::Config* cf = config::Config::makeConfig();
std::string configVal = cf->getConfig("Installation", "MySQLRep");
bool isMysqlRep = (configVal == "y" || configVal == "Y");
sm::cpsm_conhdl_t* cal_conn_hndl;
int queryState;
CalTableMap tableMap;
sm::tableid_t currentTable;
uint32_t traceFlags;
std::string queryStats;
AlterTableState alterTableState;
bool isAlter;
ha_rows bulkInsertRows;
bool singleInsert;
bool isLoaddataInfile;
std::string extendedStats;
std::string miniStats;
messageqcpp::MessageQueueClient* dmlProc;
ha_rows rowsHaveInserted;
ColNameList colNameList;
TableValuesMap tableValuesMap;
NullValuesBitset nullValuesBitset;
int rc;
uint32_t tableOid;
querystats::QueryStats stats;
std::string warningMsg;
int64_t localPm;
bool isSlaveNode;
uint32_t expressionId; // for F&E
pid_t mysqld_pid;
pid_t cpimport_pid;
int fdt[2];
if (!isMysqlRep) return false;
configVal = cf->getConfig("SystemConfig", "PrimaryUMModuleName");
std::string module = execplan::ClientRotator::getModule();
if (boost::iequals(configVal, module))
return false;
return true;
}
sm::cpsm_conhdl_t* cal_conn_hndl;
int queryState;
CalTableMap tableMap;
sm::tableid_t currentTable;
uint32_t traceFlags;
std::string queryStats;
AlterTableState alterTableState;
bool isAlter;
ha_rows bulkInsertRows;
bool singleInsert;
bool isLoaddataInfile;
std::string extendedStats;
std::string miniStats;
messageqcpp::MessageQueueClient* dmlProc;
ha_rows rowsHaveInserted;
ColNameList colNameList;
TableValuesMap tableValuesMap;
NullValuesBitset nullValuesBitset;
int rc;
uint32_t tableOid;
querystats::QueryStats stats;
std::string warningMsg;
int64_t localPm;
bool isSlaveNode;
uint32_t expressionId; // for F&E
pid_t mysqld_pid;
pid_t cpimport_pid;
int fdt[2];
#ifdef _MSC_VER
// Used for launching cpimport for Load Data Infile
HANDLE cpimport_stdin_Rd;
HANDLE cpimport_stdin_Wr;
HANDLE cpimport_stdout_Rd;
HANDLE cpimport_stdout_Wr;
PROCESS_INFORMATION cpimportProcInfo;
HANDLE cpimport_stdin_Rd;
HANDLE cpimport_stdin_Wr;
HANDLE cpimport_stdout_Rd;
HANDLE cpimport_stdout_Wr;
PROCESS_INFORMATION cpimportProcInfo;
#endif
FILE * filePtr;
uint8_t headerLength;
bool useXbit;
bool utf8;
uint8_t useCpimport;
char delimiter;
char enclosed_by;
std::vector <execplan::CalpontSystemCatalog::ColType> columnTypes;
FILE* filePtr;
uint8_t headerLength;
bool useXbit;
bool utf8;
uint8_t useCpimport;
char delimiter;
char enclosed_by;
std::vector <execplan::CalpontSystemCatalog::ColType> columnTypes;
};
typedef std::tr1::unordered_map<int, cal_connection_info> CalConnMap;
@@ -293,11 +297,11 @@ const std::string infinidb_err_msg = "\nThe query includes syntax that is not su
int cp_get_plan(THD* thd, execplan::SCSEP& csep);
int cp_get_table_plan(THD* thd, execplan::SCSEP& csep, cal_impl_if::cal_table_info& ti);
int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, execplan::SCSEP& csep, bool isUnion=false);
int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, execplan::SCSEP& csep, bool isUnion = false);
void setError(THD* thd, uint32_t errcode, const std::string errmsg, gp_walk_info* gwi);
void setError(THD* thd, uint32_t errcode, const std::string errmsg);
void gp_walk(const Item *item, void *arg);
void parse_item (Item *item, std::vector<Item_field*>& field_vec, bool& hasNonSupportItem, uint16& parseInfo);
void gp_walk(const Item* item, void* arg);
void parse_item (Item* item, std::vector<Item_field*>& field_vec, bool& hasNonSupportItem, uint16& parseInfo);
execplan::ReturnedColumn* buildReturnedColumn(Item* item, gp_walk_info& gwi, bool& nonSupport);
const std::string bestTableName(const Item_field* ifp);
bool isInfiniDB(TABLE* table_ptr);
@@ -305,8 +309,8 @@ bool isInfiniDB(TABLE* table_ptr);
// execution plan util functions prototypes
execplan::ReturnedColumn* buildReturnedColumn(Item* item, gp_walk_info& gwi, bool& nonSupport);
execplan::ReturnedColumn* buildFunctionColumn(Item_func* item, gp_walk_info& gwi, bool& nonSupport);
execplan::ArithmeticColumn* buildArithmeticColumn(Item_func* item, gp_walk_info &gwi, bool& nonSupport);
execplan::ConstantColumn* buildDecimalColumn(Item *item, gp_walk_info &gwi);
execplan::ArithmeticColumn* buildArithmeticColumn(Item_func* item, gp_walk_info& gwi, bool& nonSupport);
execplan::ConstantColumn* buildDecimalColumn(Item* item, gp_walk_info& gwi);
execplan::SimpleColumn* buildSimpleColumn(Item_field* item, gp_walk_info& gwi);
execplan::FunctionColumn* buildCaseFunction(Item_func* item, gp_walk_info& gwi, bool& nonSupport);
execplan::ParseTree* buildParseTree(Item_func* item, gp_walk_info& gwi, bool& nonSupport);
@@ -317,7 +321,7 @@ void addIntervalArgs(Item_func* ifp, funcexp::FunctionParm& functionParms);
void castCharArgs(Item_func* ifp, funcexp::FunctionParm& functionParms);
void castDecimalArgs(Item_func* ifp, funcexp::FunctionParm& functionParms);
void castTypeArgs(Item_func* ifp, funcexp::FunctionParm& functionParms);
void parse_item (Item *item, std::vector<Item_field*>& field_vec, bool& hasNonSupportItem, uint16& parseInfo);
void parse_item (Item* item, std::vector<Item_field*>& field_vec, bool& hasNonSupportItem, uint16& parseInfo);
bool isPredicateFunction(Item* item, gp_walk_info* gwip);
execplan::ParseTree* buildRowPredicate(execplan::RowColumn* lhs, execplan::RowColumn* rhs, std::string predicateOp);
bool buildRowColumnFilter(gp_walk_info* gwip, execplan::RowColumn* rhs, execplan::RowColumn* lhs, Item_func* ifp);
@@ -332,13 +336,13 @@ execplan::CalpontSystemCatalog::ColType colType_MysqlToIDB (const Item* item);
execplan::SPTP getIntervalType(int interval_type);
uint32_t isPseudoColumn(std::string funcName);
void setDerivedTable(execplan::ParseTree* n);
execplan::ParseTree* setDerivedFilter(execplan::ParseTree*& n,
std::map<std::string, execplan::ParseTree*>& obj,
execplan::CalpontSelectExecutionPlan::SelectList& derivedTbList);
execplan::ParseTree* setDerivedFilter(execplan::ParseTree*& n,
std::map<std::string, execplan::ParseTree*>& obj,
execplan::CalpontSelectExecutionPlan::SelectList& derivedTbList);
void derivedTableOptimization(execplan::SCSEP& csep);
#ifdef DEBUG_WALK_COND
void debug_walk(const Item *item, void *arg);
void debug_walk(const Item* item, void* arg);
#endif
}

3181
dbcon/mysql/ha_calpont_partition.cpp Executable file → Normal file

File diff suppressed because it is too large Load Diff

297
dbcon/mysql/ha_calpont_udf.cpp Executable file → Normal file
View File

@@ -36,184 +36,193 @@ extern "C"
{
// Connector function stub -- CPFUNC1
long long cpfunc1(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
return 0;
}
long long cpfunc1(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
return 0;
}
my_bool cpfunc1_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message,"CALFUNC1() requires one COLUMN argument");
return 1;
}
return 0;
}
my_bool cpfunc1_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "CALFUNC1() requires one COLUMN argument");
return 1;
}
void cpfunc1_deinit(UDF_INIT* initid)
{
}
return 0;
}
void cpfunc1_deinit(UDF_INIT* initid)
{
}
// Connector function stub -- CPFUNC2
long long cpfunc2(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
return 0;
}
long long cpfunc2(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
return 0;
}
my_bool cpfunc2_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message,"CALFUNC2() requires one COLUMN argument");
return 1;
}
return 0;
}
my_bool cpfunc2_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "CALFUNC2() requires one COLUMN argument");
return 1;
}
void cpfunc2_deinit(UDF_INIT* initid)
{
}
return 0;
}
void cpfunc2_deinit(UDF_INIT* initid)
{
}
// Connector function stub -- CPFUNC3
long long cpfunc3(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
return 0;
}
long long cpfunc3(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
return 0;
}
my_bool cpfunc3_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message,"CALFUNC3() requires one COLUMN argument");
return 1;
}
return 0;
}
my_bool cpfunc3_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "CALFUNC3() requires one COLUMN argument");
return 1;
}
void cpfunc3_deinit(UDF_INIT* initid)
{
}
return 0;
}
void cpfunc3_deinit(UDF_INIT* initid)
{
}
// Connector function stub -- CPFUNC4
long long cpfunc4(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
return 0;
}
long long cpfunc4(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
return 0;
}
my_bool cpfunc4_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message,"CALFUNC4() requires one COLUMN argument");
return 1;
}
return 0;
}
my_bool cpfunc4_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "CALFUNC4() requires one COLUMN argument");
return 1;
}
void cpfunc4_deinit(UDF_INIT* initid)
{
}
return 0;
}
void cpfunc4_deinit(UDF_INIT* initid)
{
}
// Connector function stub -- CPFUNC5
long long cpfunc5(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
return 0;
}
long long cpfunc5(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
return 0;
}
my_bool cpfunc5_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message,"CALFUNC5() requires one COLUMN argument");
return 1;
}
return 0;
}
my_bool cpfunc5_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "CALFUNC5() requires one COLUMN argument");
return 1;
}
void cpfunc5_deinit(UDF_INIT* initid)
{
}
return 0;
}
void cpfunc5_deinit(UDF_INIT* initid)
{
}
// Connector function stub -- CPFUNC6
long long cpfunc6(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
return 0;
}
long long cpfunc6(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
return 0;
}
my_bool cpfunc6_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message,"CALFUNC6() requires one COLUMN argument");
return 1;
}
return 0;
}
my_bool cpfunc6_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "CALFUNC6() requires one COLUMN argument");
return 1;
}
void cpfunc6_deinit(UDF_INIT* initid)
{
}
return 0;
}
void cpfunc6_deinit(UDF_INIT* initid)
{
}
// Connector function stub -- CPFUNC7
long long cpfunc7(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
return 0;
}
long long cpfunc7(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
return 0;
}
my_bool cpfunc7_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message,"CALFUNC7() requires one COLUMN argument");
return 1;
}
return 0;
}
my_bool cpfunc7_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "CALFUNC7() requires one COLUMN argument");
return 1;
}
void cpfunc7_deinit(UDF_INIT* initid)
{
}
return 0;
}
void cpfunc7_deinit(UDF_INIT* initid)
{
}
// Connector function stub -- CPFUNC8
long long cpfunc8(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
return 0;
}
long long cpfunc8(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
return 0;
}
my_bool cpfunc8_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message,"CALFUNC8() requires one COLUMN argument");
return 1;
}
return 0;
}
my_bool cpfunc8_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "CALFUNC8() requires one COLUMN argument");
return 1;
}
void cpfunc8_deinit(UDF_INIT* initid)
{
}
return 0;
}
void cpfunc8_deinit(UDF_INIT* initid)
{
}
// Connector function stub -- CPFUNC9
long long cpfunc9(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
return 0;
}
long long cpfunc9(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
return 0;
}
my_bool cpfunc9_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message,"CALFUNC9() requires one COLUMN argument");
return 1;
}
return 0;
}
my_bool cpfunc9_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "CALFUNC9() requires one COLUMN argument");
return 1;
}
void cpfunc9_deinit(UDF_INIT* initid)
{
}
return 0;
}
void cpfunc9_deinit(UDF_INIT* initid)
{
}
}

170
dbcon/mysql/ha_exists_sub.cpp Executable file → Normal file
View File

@@ -46,33 +46,38 @@ extern void makeAntiJoin(const ParseTree* n);
void checkCorrelation(const ParseTree* n, void* obj)
{
ExistsFilter *ef = reinterpret_cast<ExistsFilter*>(obj);
TreeNode *tn = n->data();
SimpleFilter *sf = dynamic_cast<SimpleFilter*>(tn);
if (!sf)
return;
uint64_t lJoinInfo = sf->lhs()->joinInfo();
uint64_t rJoinInfo = sf->rhs()->joinInfo();
ExistsFilter* ef = reinterpret_cast<ExistsFilter*>(obj);
TreeNode* tn = n->data();
SimpleFilter* sf = dynamic_cast<SimpleFilter*>(tn);
if (lJoinInfo & JOIN_CORRELATED)
{
ConstantColumn *cc = dynamic_cast<ConstantColumn*>(sf->rhs());
if ((!cc || (cc && sf->op()->op() == OP_EQ)) && !(rJoinInfo & JOIN_CORRELATED))
ef->correlated(true);
}
if (rJoinInfo & JOIN_CORRELATED)
{
ConstantColumn *cc = dynamic_cast<ConstantColumn*>(sf->lhs());
if ((!cc || (cc && sf->op()->op() == OP_EQ)) && !(lJoinInfo & JOIN_CORRELATED))
ef->correlated(true);
}
if (!sf)
return;
uint64_t lJoinInfo = sf->lhs()->joinInfo();
uint64_t rJoinInfo = sf->rhs()->joinInfo();
if (lJoinInfo & JOIN_CORRELATED)
{
ConstantColumn* cc = dynamic_cast<ConstantColumn*>(sf->rhs());
if ((!cc || (cc && sf->op()->op() == OP_EQ)) && !(rJoinInfo & JOIN_CORRELATED))
ef->correlated(true);
}
if (rJoinInfo & JOIN_CORRELATED)
{
ConstantColumn* cc = dynamic_cast<ConstantColumn*>(sf->lhs());
if ((!cc || (cc && sf->op()->op() == OP_EQ)) && !(lJoinInfo & JOIN_CORRELATED))
ef->correlated(true);
}
}
ExistsSub::ExistsSub(gp_walk_info& gwip) : WhereSubQuery(gwip)
{}
ExistsSub::ExistsSub(gp_walk_info& gwip, Item_subselect* sub) :
WhereSubQuery(gwip, sub)
WhereSubQuery(gwip, sub)
{}
ExistsSub::~ExistsSub()
@@ -80,63 +85,69 @@ ExistsSub::~ExistsSub()
execplan::ParseTree* ExistsSub::transform()
{
idbassert(fSub);
idbassert(fSub);
SCSEP csep(new CalpontSelectExecutionPlan());
csep->sessionID(fGwip.sessionid);
csep->location(CalpontSelectExecutionPlan::WHERE);
csep->subType (CalpontSelectExecutionPlan::EXISTS_SUBS);
SCSEP csep(new CalpontSelectExecutionPlan());
csep->sessionID(fGwip.sessionid);
csep->location(CalpontSelectExecutionPlan::WHERE);
csep->subType (CalpontSelectExecutionPlan::EXISTS_SUBS);
// gwi for the sub query
gp_walk_info gwi;
gwi.thd = fGwip.thd;
gwi.subQuery = this;
// gwi for the sub query
gp_walk_info gwi;
gwi.thd = fGwip.thd;
gwi.subQuery = this;
// @4827 merge table list to gwi in case there is FROM sub to be referenced
// in the FROM sub
gwi.derivedTbCnt = fGwip.derivedTbList.size();
uint32_t tbCnt = fGwip.tbList.size();
// @4827 merge table list to gwi in case there is FROM sub to be referenced
// in the FROM sub
gwi.derivedTbCnt = fGwip.derivedTbList.size();
uint32_t tbCnt = fGwip.tbList.size();
gwi.tbList.insert(gwi.tbList.begin(), fGwip.tbList.begin(), fGwip.tbList.end());
gwi.derivedTbList.insert(gwi.derivedTbList.begin(), fGwip.derivedTbList.begin(), fGwip.derivedTbList.end());
gwi.tbList.insert(gwi.tbList.begin(), fGwip.tbList.begin(), fGwip.tbList.end());
gwi.derivedTbList.insert(gwi.derivedTbList.begin(), fGwip.derivedTbList.begin(), fGwip.derivedTbList.end());
if (fSub->get_select_lex()->with_sum_func)
{
fGwip.fatalParseError = true;
fGwip.parseErrorText = logging::IDBErrorInfo::instance()->errorMsg(logging::ERR_AGG_EXISTS);
return NULL;
}
if (fSub->get_select_lex()->with_sum_func)
{
fGwip.fatalParseError = true;
fGwip.parseErrorText = logging::IDBErrorInfo::instance()->errorMsg(logging::ERR_AGG_EXISTS);
return NULL;
}
if (getSelectPlan(gwi, *(fSub->get_select_lex()), csep) != 0)
{
fGwip.fatalParseError = true;
if (gwi.fatalParseError && !gwi.parseErrorText.empty())
fGwip.parseErrorText = gwi.parseErrorText;
else
fGwip.parseErrorText = "Error occured in ExistsSub::transform()";
return NULL;
}
if (getSelectPlan(gwi, *(fSub->get_select_lex()), csep) != 0)
{
fGwip.fatalParseError = true;
// remove outer query tables
CalpontSelectExecutionPlan::TableList tblist;
if (csep->tableList().size() >= tbCnt)
tblist.insert(tblist.begin(),csep->tableList().begin()+tbCnt, csep->tableList().end());
CalpontSelectExecutionPlan::SelectList derivedTbList;
if (csep->derivedTableList().size() >= gwi.derivedTbCnt)
derivedTbList.insert(derivedTbList.begin(), csep->derivedTableList().begin()+gwi.derivedTbCnt, csep->derivedTableList().end());
if (gwi.fatalParseError && !gwi.parseErrorText.empty())
fGwip.parseErrorText = gwi.parseErrorText;
else
fGwip.parseErrorText = "Error occured in ExistsSub::transform()";
csep->tableList(tblist);
csep->derivedTableList(derivedTbList);
return NULL;
}
ExistsFilter *subFilter = new ExistsFilter();
subFilter->correlated(false);
subFilter->sub(csep);
const ParseTree* pt = csep->filters();
if (pt)
pt->walk(checkCorrelation, subFilter);
// remove outer query tables
CalpontSelectExecutionPlan::TableList tblist;
fGwip.subselectList.push_back(csep);
return new ParseTree(subFilter);
if (csep->tableList().size() >= tbCnt)
tblist.insert(tblist.begin(), csep->tableList().begin() + tbCnt, csep->tableList().end());
CalpontSelectExecutionPlan::SelectList derivedTbList;
if (csep->derivedTableList().size() >= gwi.derivedTbCnt)
derivedTbList.insert(derivedTbList.begin(), csep->derivedTableList().begin() + gwi.derivedTbCnt, csep->derivedTableList().end());
csep->tableList(tblist);
csep->derivedTableList(derivedTbList);
ExistsFilter* subFilter = new ExistsFilter();
subFilter->correlated(false);
subFilter->sub(csep);
const ParseTree* pt = csep->filters();
if (pt)
pt->walk(checkCorrelation, subFilter);
fGwip.subselectList.push_back(csep);
return new ParseTree(subFilter);
}
/**
@@ -146,17 +157,20 @@ execplan::ParseTree* ExistsSub::transform()
*/
void ExistsSub::handleNot()
{
ParseTree *pt = fGwip.ptWorkStack.top();
ExistsFilter *subFilter = dynamic_cast<ExistsFilter*>(pt->data());
idbassert(subFilter);
subFilter->notExists(true);
SCSEP csep = subFilter->sub();
const ParseTree* ptsub = csep->filters();
if (ptsub)
ptsub->walk(makeAntiJoin);
ptsub = csep->having();
if (ptsub)
ptsub->walk(makeAntiJoin);
ParseTree* pt = fGwip.ptWorkStack.top();
ExistsFilter* subFilter = dynamic_cast<ExistsFilter*>(pt->data());
idbassert(subFilter);
subFilter->notExists(true);
SCSEP csep = subFilter->sub();
const ParseTree* ptsub = csep->filters();
if (ptsub)
ptsub->walk(makeAntiJoin);
ptsub = csep->having();
if (ptsub)
ptsub->walk(makeAntiJoin);
}
}

518
dbcon/mysql/ha_from_sub.cpp Executable file → Normal file
View File

@@ -46,258 +46,279 @@ namespace cal_impl_if
void derivedTableOptimization(SCSEP& csep)
{
// @bug5634. replace the unused column with ConstantColumn from derived table column list,
// ExeMgr will not project ConstantColumn. Only count for local derived column.
// subquery may carry main query derived table list for column reference, those
// derived tables are not checked for optimization in this scope.
CalpontSelectExecutionPlan::SelectList derivedTbList = csep->derivedTableList();
// @bug5634. replace the unused column with ConstantColumn from derived table column list,
// ExeMgr will not project ConstantColumn. Only count for local derived column.
// subquery may carry main query derived table list for column reference, those
// derived tables are not checked for optimization in this scope.
CalpontSelectExecutionPlan::SelectList derivedTbList = csep->derivedTableList();
// @bug6156. Skip horizontal optimization for no table union.
bool horizontalOptimization = true;
for (uint i = 0; i < derivedTbList.size(); i++)
{
CalpontSelectExecutionPlan *plan = dynamic_cast<CalpontSelectExecutionPlan*>(derivedTbList[i].get());
CalpontSelectExecutionPlan::ReturnedColumnList cols = plan->returnedCols();
vector<CalpontSelectExecutionPlan::ReturnedColumnList> unionColVec;
// @bug6156. Skip horizontal optimization for no table union.
bool horizontalOptimization = true;
// only do vertical optimization for union all
// @bug6134. Also skip the vertical optimization for select distinct
// because all columns need to be projected to check the distinctness.
bool verticalOptimization = false;
if (plan->distinctUnionNum() == 0 && !plan->distinct())
{
verticalOptimization = true;
for (uint j = 0; j < plan->unionVec().size(); j++)
{
unionColVec.push_back(
dynamic_cast<CalpontSelectExecutionPlan*>(plan->unionVec()[j].get())->returnedCols());
}
}
for (uint i = 0; i < derivedTbList.size(); i++)
{
CalpontSelectExecutionPlan* plan = dynamic_cast<CalpontSelectExecutionPlan*>(derivedTbList[i].get());
CalpontSelectExecutionPlan::ReturnedColumnList cols = plan->returnedCols();
vector<CalpontSelectExecutionPlan::ReturnedColumnList> unionColVec;
if (plan->tableList().empty())
horizontalOptimization = false;
for (uint j = 0; j < plan->unionVec().size(); j++)
{
if (dynamic_cast<CalpontSelectExecutionPlan*>(plan->unionVec()[j].get())->tableList().empty())
{
horizontalOptimization = false;
break;
}
}
// only do vertical optimization for union all
// @bug6134. Also skip the vertical optimization for select distinct
// because all columns need to be projected to check the distinctness.
bool verticalOptimization = false;
if (verticalOptimization)
{
int64_t val = 1;
for (uint i = 0; i < cols.size(); i++)
{
//if (cols[i]->derivedTable().empty())
if (cols[i]->refCount() == 0)
{
if (cols[i]->derivedRefCol())
cols[i]->derivedRefCol()->decRefCount();
cols[i].reset(new ConstantColumn(val));
for (uint j = 0; j < unionColVec.size(); j++)
unionColVec[j][i].reset(new ConstantColumn(val));
}
}
if (plan->distinctUnionNum() == 0 && !plan->distinct())
{
verticalOptimization = true;
// set back
plan->returnedCols(cols);
for (uint j = 0; j < unionColVec.size(); j++)
dynamic_cast<CalpontSelectExecutionPlan*>(plan->unionVec()[j].get())->returnedCols(unionColVec[j]);
}
}
for (uint j = 0; j < plan->unionVec().size(); j++)
{
unionColVec.push_back(
dynamic_cast<CalpontSelectExecutionPlan*>(plan->unionVec()[j].get())->returnedCols());
}
}
/*
* @bug5635. Move filters that only belongs to a derived table to inside the derived table.
* 1. parse tree walk to populate derivedTableFilterMap and set null candidate on the tree.
* 2. remove the null filters
* 3. and the filters of derivedTableFilterMap and append to the WHERE filter of the derived table
*
* Note:
* 1. Subquery filters is ignored because derived table can not be in subquery
* 2. While walking tree, whenever a single derive simplefilter is encountered,
* this filter is pushed to the corresponding stack
* 2. Whenever an OR operator is encountered, all the filter stack of
* that OR involving derived table are emptied and null candidate of each
* stacked filter needs to be reset (not null)
*/
ParseTree* pt = csep->filters();
map<string, ParseTree*> derivedTbFilterMap;
if (horizontalOptimization && pt)
{
pt->walk(setDerivedTable);
setDerivedFilter(pt, derivedTbFilterMap, derivedTbList);
csep->filters(pt);
}
if (plan->tableList().empty())
horizontalOptimization = false;
// AND the filters of individual stack to the derived table filter tree
// @todo union filters.
// @todo outer join complication
map<string, ParseTree*>::iterator mapIt;
for (uint i = 0; i < derivedTbList.size(); i++)
{
CalpontSelectExecutionPlan *plan = dynamic_cast<CalpontSelectExecutionPlan*>(derivedTbList[i].get());
CalpontSelectExecutionPlan::ReturnedColumnList derivedColList = plan->returnedCols();
mapIt = derivedTbFilterMap.find(plan->derivedTbAlias());
for (uint j = 0; j < plan->unionVec().size(); j++)
{
if (dynamic_cast<CalpontSelectExecutionPlan*>(plan->unionVec()[j].get())->tableList().empty())
{
horizontalOptimization = false;
break;
}
}
if (mapIt != derivedTbFilterMap.end())
{
// replace all derived column of this filter with real column from
// derived table projection list.
ParseTree *mainFilter = new ParseTree();
mainFilter->copyTree(*(mapIt->second));
replaceRefCol(mainFilter, derivedColList);
ParseTree* derivedFilter = plan->filters();
if (derivedFilter)
{
LogicOperator *op = new LogicOperator("and");
ParseTree *filter = new ParseTree(op);
filter->left(derivedFilter);
filter->right(mainFilter);
plan->filters(filter);
}
else
{
plan->filters(mainFilter);
}
if (verticalOptimization)
{
int64_t val = 1;
// union filter handling
for (uint j = 0; j < plan->unionVec().size(); j++)
{
CalpontSelectExecutionPlan *unionPlan =
dynamic_cast<CalpontSelectExecutionPlan*>(plan->unionVec()[j].get());
CalpontSelectExecutionPlan::ReturnedColumnList unionColList = unionPlan->returnedCols();
ParseTree* mainFilterForUnion = new ParseTree();
mainFilterForUnion->copyTree(*(mapIt->second));
replaceRefCol(mainFilterForUnion, unionColList);
ParseTree *unionFilter = unionPlan->filters();
if (unionFilter)
{
LogicOperator *op = new LogicOperator("and");
ParseTree *filter = new ParseTree(op);
filter->left(unionFilter);
filter->right(mainFilterForUnion);
unionPlan->filters(filter);
}
else
{
unionPlan->filters(mainFilterForUnion);
}
}
}
}
for (uint i = 0; i < cols.size(); i++)
{
//if (cols[i]->derivedTable().empty())
if (cols[i]->refCount() == 0)
{
if (cols[i]->derivedRefCol())
cols[i]->derivedRefCol()->decRefCount();
// clean derivedTbFilterMap because all the filters are copied
for( mapIt = derivedTbFilterMap.begin(); mapIt != derivedTbFilterMap.end(); ++mapIt )
delete (*mapIt).second;
cols[i].reset(new ConstantColumn(val));
// recursively process the nested derived table
for (uint i = 0; i < csep->subSelectList().size(); i++)
{
SCSEP subselect(boost::dynamic_pointer_cast<CalpontSelectExecutionPlan>(csep->subSelectList()[i]));
derivedTableOptimization(subselect);
}
for (uint j = 0; j < unionColVec.size(); j++)
unionColVec[j][i].reset(new ConstantColumn(val));
}
}
// set back
plan->returnedCols(cols);
for (uint j = 0; j < unionColVec.size(); j++)
dynamic_cast<CalpontSelectExecutionPlan*>(plan->unionVec()[j].get())->returnedCols(unionColVec[j]);
}
}
/*
* @bug5635. Move filters that only belongs to a derived table to inside the derived table.
* 1. parse tree walk to populate derivedTableFilterMap and set null candidate on the tree.
* 2. remove the null filters
* 3. and the filters of derivedTableFilterMap and append to the WHERE filter of the derived table
*
* Note:
* 1. Subquery filters is ignored because derived table can not be in subquery
* 2. While walking tree, whenever a single derive simplefilter is encountered,
* this filter is pushed to the corresponding stack
* 2. Whenever an OR operator is encountered, all the filter stack of
* that OR involving derived table are emptied and null candidate of each
* stacked filter needs to be reset (not null)
*/
ParseTree* pt = csep->filters();
map<string, ParseTree*> derivedTbFilterMap;
if (horizontalOptimization && pt)
{
pt->walk(setDerivedTable);
setDerivedFilter(pt, derivedTbFilterMap, derivedTbList);
csep->filters(pt);
}
// AND the filters of individual stack to the derived table filter tree
// @todo union filters.
// @todo outer join complication
map<string, ParseTree*>::iterator mapIt;
for (uint i = 0; i < derivedTbList.size(); i++)
{
CalpontSelectExecutionPlan* plan = dynamic_cast<CalpontSelectExecutionPlan*>(derivedTbList[i].get());
CalpontSelectExecutionPlan::ReturnedColumnList derivedColList = plan->returnedCols();
mapIt = derivedTbFilterMap.find(plan->derivedTbAlias());
if (mapIt != derivedTbFilterMap.end())
{
// replace all derived column of this filter with real column from
// derived table projection list.
ParseTree* mainFilter = new ParseTree();
mainFilter->copyTree(*(mapIt->second));
replaceRefCol(mainFilter, derivedColList);
ParseTree* derivedFilter = plan->filters();
if (derivedFilter)
{
LogicOperator* op = new LogicOperator("and");
ParseTree* filter = new ParseTree(op);
filter->left(derivedFilter);
filter->right(mainFilter);
plan->filters(filter);
}
else
{
plan->filters(mainFilter);
}
// union filter handling
for (uint j = 0; j < plan->unionVec().size(); j++)
{
CalpontSelectExecutionPlan* unionPlan =
dynamic_cast<CalpontSelectExecutionPlan*>(plan->unionVec()[j].get());
CalpontSelectExecutionPlan::ReturnedColumnList unionColList = unionPlan->returnedCols();
ParseTree* mainFilterForUnion = new ParseTree();
mainFilterForUnion->copyTree(*(mapIt->second));
replaceRefCol(mainFilterForUnion, unionColList);
ParseTree* unionFilter = unionPlan->filters();
if (unionFilter)
{
LogicOperator* op = new LogicOperator("and");
ParseTree* filter = new ParseTree(op);
filter->left(unionFilter);
filter->right(mainFilterForUnion);
unionPlan->filters(filter);
}
else
{
unionPlan->filters(mainFilterForUnion);
}
}
}
}
// clean derivedTbFilterMap because all the filters are copied
for ( mapIt = derivedTbFilterMap.begin(); mapIt != derivedTbFilterMap.end(); ++mapIt )
delete (*mapIt).second;
// recursively process the nested derived table
for (uint i = 0; i < csep->subSelectList().size(); i++)
{
SCSEP subselect(boost::dynamic_pointer_cast<CalpontSelectExecutionPlan>(csep->subSelectList()[i]));
derivedTableOptimization(subselect);
}
}
void setDerivedTable(execplan::ParseTree* n)
{
ParseTree *lhs = n->left();
ParseTree *rhs = n->right();
ParseTree* lhs = n->left();
ParseTree* rhs = n->right();
Operator *op = dynamic_cast<Operator*>(n->data());
Operator* op = dynamic_cast<Operator*>(n->data());
// if logic operator then lhs and rhs can't be both null
if (op)
{
if (!lhs || lhs->derivedTable() == "*")
{
n->derivedTable(rhs ? rhs->derivedTable() : "*");
}
else if (!rhs || rhs->derivedTable() == "*")
{
n->derivedTable(lhs->derivedTable());
}
else if (lhs->derivedTable() == rhs->derivedTable())
{
n->derivedTable(lhs->derivedTable());
}
else
{
n->derivedTable("");
}
}
else
{
n->data()->setDerivedTable();
n->derivedTable(n->data()->derivedTable());
}
// if logic operator then lhs and rhs can't be both null
if (op)
{
if (!lhs || lhs->derivedTable() == "*")
{
n->derivedTable(rhs ? rhs->derivedTable() : "*");
}
else if (!rhs || rhs->derivedTable() == "*")
{
n->derivedTable(lhs->derivedTable());
}
else if (lhs->derivedTable() == rhs->derivedTable())
{
n->derivedTable(lhs->derivedTable());
}
else
{
n->derivedTable("");
}
}
else
{
n->data()->setDerivedTable();
n->derivedTable(n->data()->derivedTable());
}
}
ParseTree* setDerivedFilter(ParseTree*& n, map<string, ParseTree*>& filterMap,
ParseTree* setDerivedFilter(ParseTree*& n, map<string, ParseTree*>& filterMap,
CalpontSelectExecutionPlan::SelectList& derivedTbList)
{
if (!(n->derivedTable().empty()))
{
// @todo replace virtual column of n to real column
// all simple columns should belong to the same derived table
CalpontSelectExecutionPlan *csep = NULL;
for (uint i = 0; i < derivedTbList.size(); i++)
{
CalpontSelectExecutionPlan *plan = dynamic_cast<CalpontSelectExecutionPlan*>(derivedTbList[i].get());
if (plan->derivedTbAlias() == n->derivedTable())
{
csep = plan;
break;
}
}
// should never be null; if null then give up optimization.
if (!csep)
return n;
if (!(n->derivedTable().empty()))
{
// @todo replace virtual column of n to real column
// all simple columns should belong to the same derived table
CalpontSelectExecutionPlan* csep = NULL;
// 2. push the filter to the derived table filter stack, or 'and' with
// the filters in the stack
map<string, ParseTree*>::iterator mapIter = filterMap.find(n->derivedTable());
if ( mapIter == filterMap.end())
{
filterMap.insert(pair<string, ParseTree*>(n->derivedTable(), n));
}
else
{
ParseTree* pt = new ParseTree(new LogicOperator("and"));
pt->left(mapIter->second);
pt->right(n);
mapIter->second = pt;
}
int64_t val = 1;
n = new ParseTree(new ConstantColumn(val));
}
else
{
Operator *op = dynamic_cast<Operator*>(n->data());
if (op && (op->op() == OP_OR || op->op() == OP_XOR))
{
return n;
}
else
{
ParseTree *lhs = n->left();
ParseTree *rhs = n->right();
if (lhs)
n->left(setDerivedFilter(lhs, filterMap, derivedTbList));
if (rhs)
n->right(setDerivedFilter(rhs, filterMap, derivedTbList));
}
}
return n;
for (uint i = 0; i < derivedTbList.size(); i++)
{
CalpontSelectExecutionPlan* plan = dynamic_cast<CalpontSelectExecutionPlan*>(derivedTbList[i].get());
if (plan->derivedTbAlias() == n->derivedTable())
{
csep = plan;
break;
}
}
// should never be null; if null then give up optimization.
if (!csep)
return n;
// 2. push the filter to the derived table filter stack, or 'and' with
// the filters in the stack
map<string, ParseTree*>::iterator mapIter = filterMap.find(n->derivedTable());
if ( mapIter == filterMap.end())
{
filterMap.insert(pair<string, ParseTree*>(n->derivedTable(), n));
}
else
{
ParseTree* pt = new ParseTree(new LogicOperator("and"));
pt->left(mapIter->second);
pt->right(n);
mapIter->second = pt;
}
int64_t val = 1;
n = new ParseTree(new ConstantColumn(val));
}
else
{
Operator* op = dynamic_cast<Operator*>(n->data());
if (op && (op->op() == OP_OR || op->op() == OP_XOR))
{
return n;
}
else
{
ParseTree* lhs = n->left();
ParseTree* rhs = n->right();
if (lhs)
n->left(setDerivedFilter(lhs, filterMap, derivedTbList));
if (rhs)
n->right(setDerivedFilter(rhs, filterMap, derivedTbList));
}
}
return n;
}
FromSubQuery::FromSubQuery(gp_walk_info& gwip) : SubQuery(gwip)
{}
FromSubQuery::FromSubQuery(gp_walk_info& gwip, SELECT_LEX* sub) :
SubQuery(gwip),
fFromSub(sub)
SubQuery(gwip),
fFromSub(sub)
{}
FromSubQuery::~FromSubQuery()
@@ -305,31 +326,34 @@ FromSubQuery::~FromSubQuery()
SCSEP FromSubQuery::transform()
{
assert (fFromSub);
SCSEP csep(new CalpontSelectExecutionPlan());
csep->sessionID(fGwip.sessionid);
csep->location(CalpontSelectExecutionPlan::FROM);
csep->subType (CalpontSelectExecutionPlan::FROM_SUBS);
assert (fFromSub);
SCSEP csep(new CalpontSelectExecutionPlan());
csep->sessionID(fGwip.sessionid);
csep->location(CalpontSelectExecutionPlan::FROM);
csep->subType (CalpontSelectExecutionPlan::FROM_SUBS);
// gwi for the sub query
gp_walk_info gwi;
gwi.thd = fGwip.thd;
gwi.subQuery = this;
gwi.viewName = fGwip.viewName;
csep->derivedTbAlias(fAlias); // always lower case
// gwi for the sub query
gp_walk_info gwi;
gwi.thd = fGwip.thd;
gwi.subQuery = this;
gwi.viewName = fGwip.viewName;
csep->derivedTbAlias(fAlias); // always lower case
if (getSelectPlan(gwi, *fFromSub, csep) != 0)
{
fGwip.fatalParseError = true;
if (!gwi.parseErrorText.empty())
fGwip.parseErrorText = gwi.parseErrorText;
else
fGwip.parseErrorText = "Error occured in FromSubQuery::transform()";
csep.reset();
return csep;
}
fGwip.subselectList.push_back(csep);
return csep;
if (getSelectPlan(gwi, *fFromSub, csep) != 0)
{
fGwip.fatalParseError = true;
if (!gwi.parseErrorText.empty())
fGwip.parseErrorText = gwi.parseErrorText;
else
fGwip.parseErrorText = "Error occured in FromSubQuery::transform()";
csep.reset();
return csep;
}
fGwip.subselectList.push_back(csep);
return csep;
}
}

397
dbcon/mysql/ha_in_sub.cpp Executable file → Normal file
View File

@@ -50,44 +50,52 @@ using namespace logging;
namespace cal_impl_if
{
extern void parse_item (Item *item, vector<Item_field*>& field_vec, bool& hasNonSupportItem, uint16& parseInfo);
extern void parse_item (Item* item, vector<Item_field*>& field_vec, bool& hasNonSupportItem, uint16& parseInfo);
void makeAntiJoin(const ParseTree* n)
{
TreeNode *tn = n->data();
SimpleFilter *sf = dynamic_cast<SimpleFilter*>(tn);
if (!sf)
return;
uint64_t lJoinInfo = sf->lhs()->joinInfo();
TreeNode* tn = n->data();
SimpleFilter* sf = dynamic_cast<SimpleFilter*>(tn);
if (lJoinInfo & JOIN_SEMI)
{
lJoinInfo &= ~JOIN_SEMI;
lJoinInfo |= JOIN_ANTI;
if (lJoinInfo & JOIN_NULLMATCH_CANDIDATE)
lJoinInfo |= JOIN_NULL_MATCH;
sf->lhs()->joinInfo(lJoinInfo);
}
uint64_t rJoinInfo = sf->rhs()->joinInfo();
if (rJoinInfo & JOIN_SEMI)
{
rJoinInfo &= ~JOIN_SEMI;
rJoinInfo |= JOIN_ANTI;
if (rJoinInfo & JOIN_NULLMATCH_CANDIDATE)
rJoinInfo |= JOIN_NULL_MATCH;
sf->rhs()->joinInfo(rJoinInfo);
}
if (!sf)
return;
uint64_t lJoinInfo = sf->lhs()->joinInfo();
if (lJoinInfo & JOIN_SEMI)
{
lJoinInfo &= ~JOIN_SEMI;
lJoinInfo |= JOIN_ANTI;
if (lJoinInfo & JOIN_NULLMATCH_CANDIDATE)
lJoinInfo |= JOIN_NULL_MATCH;
sf->lhs()->joinInfo(lJoinInfo);
}
uint64_t rJoinInfo = sf->rhs()->joinInfo();
if (rJoinInfo & JOIN_SEMI)
{
rJoinInfo &= ~JOIN_SEMI;
rJoinInfo |= JOIN_ANTI;
if (rJoinInfo & JOIN_NULLMATCH_CANDIDATE)
rJoinInfo |= JOIN_NULL_MATCH;
sf->rhs()->joinInfo(rJoinInfo);
}
}
InSub::InSub(gp_walk_info& gwip) : WhereSubQuery(gwip)
{}
InSub::InSub(gp_walk_info& gwip, Item_func* func) :
WhereSubQuery(gwip, func)
WhereSubQuery(gwip, func)
{}
InSub::InSub(const InSub& rhs) :
WhereSubQuery(rhs.gwip(), rhs.fColumn, rhs.fSub, rhs.fFunc)
WhereSubQuery(rhs.gwip(), rhs.fColumn, rhs.fSub, rhs.fFunc)
{}
InSub::~InSub()
@@ -98,86 +106,92 @@ InSub::~InSub()
*/
execplan::ParseTree* InSub::transform()
{
if (!fFunc)
return NULL;
if (!fFunc)
return NULL;
// @todo need to handle scalar IN and BETWEEN specially
// this blocks handles only one subselect scalar
// arg[0]: column | arg[1]: subselect
//assert (fFunc->argument_count() == 2 && fGwip.rcWorkStack.size() >= 2);
if (fFunc->argument_count() != 2 || fGwip.rcWorkStack.size() < 2)
{
fGwip.fatalParseError = true;
fGwip.parseErrorText = "Unsupported item in IN subquery";
return NULL;
}
// @todo need to handle scalar IN and BETWEEN specially
// this blocks handles only one subselect scalar
// arg[0]: column | arg[1]: subselect
//assert (fFunc->argument_count() == 2 && fGwip.rcWorkStack.size() >= 2);
if (fFunc->argument_count() != 2 || fGwip.rcWorkStack.size() < 2)
{
fGwip.fatalParseError = true;
fGwip.parseErrorText = "Unsupported item in IN subquery";
return NULL;
}
ReturnedColumn* rhs = fGwip.rcWorkStack.top();
fGwip.rcWorkStack.pop();
delete rhs;
ReturnedColumn* lhs = fGwip.rcWorkStack.top();
fGwip.rcWorkStack.pop();
delete lhs;
ReturnedColumn* rhs = fGwip.rcWorkStack.top();
fGwip.rcWorkStack.pop();
delete rhs;
ReturnedColumn* lhs = fGwip.rcWorkStack.top();
fGwip.rcWorkStack.pop();
delete lhs;
fSub = (Item_subselect*)(fFunc->arguments()[1]);
idbassert(fSub && fFunc);
fSub = (Item_subselect*)(fFunc->arguments()[1]);
idbassert(fSub && fFunc);
SCSEP csep (new CalpontSelectExecutionPlan());
csep->sessionID(fGwip.sessionid);
csep->location(CalpontSelectExecutionPlan::WHERE);
csep->subType (CalpontSelectExecutionPlan::IN_SUBS);
SCSEP csep (new CalpontSelectExecutionPlan());
csep->sessionID(fGwip.sessionid);
csep->location(CalpontSelectExecutionPlan::WHERE);
csep->subType (CalpontSelectExecutionPlan::IN_SUBS);
// gwi for the sub query
gp_walk_info gwi;
gwi.thd = fGwip.thd;
gwi.subQuery = this;
// gwi for the sub query
gp_walk_info gwi;
gwi.thd = fGwip.thd;
gwi.subQuery = this;
// @4827 merge table list to gwi in case there is FROM sub to be referenced
// in the FROM sub
gwi.derivedTbCnt = fGwip.derivedTbList.size();
uint32_t tbCnt = fGwip.tbList.size();
// @4827 merge table list to gwi in case there is FROM sub to be referenced
// in the FROM sub
gwi.derivedTbCnt = fGwip.derivedTbList.size();
uint32_t tbCnt = fGwip.tbList.size();
gwi.tbList.insert(gwi.tbList.begin(), fGwip.tbList.begin(), fGwip.tbList.end());
gwi.derivedTbList.insert(gwi.derivedTbList.begin(), fGwip.derivedTbList.begin(), fGwip.derivedTbList.end());
gwi.tbList.insert(gwi.tbList.begin(), fGwip.tbList.begin(), fGwip.tbList.end());
gwi.derivedTbList.insert(gwi.derivedTbList.begin(), fGwip.derivedTbList.begin(), fGwip.derivedTbList.end());
if (getSelectPlan(gwi, *(fSub->get_select_lex()), csep) != 0)
{
fGwip.fatalParseError = true;
if (gwi.fatalParseError && !gwi.parseErrorText.empty())
fGwip.parseErrorText = gwi.parseErrorText;
else
fGwip.parseErrorText = "Error occured in InSub::transform()";
return NULL;
}
if (getSelectPlan(gwi, *(fSub->get_select_lex()), csep) != 0)
{
fGwip.fatalParseError = true;
// remove outer query tables
CalpontSelectExecutionPlan::TableList tblist;
if (csep->tableList().size() >= tbCnt)
tblist.insert(tblist.begin(),csep->tableList().begin()+tbCnt, csep->tableList().end());
CalpontSelectExecutionPlan::SelectList derivedTbList;
if (csep->derivedTableList().size() >= gwi.derivedTbCnt)
derivedTbList.insert(derivedTbList.begin(),
csep->derivedTableList().begin()+gwi.derivedTbCnt,
csep->derivedTableList().end());
if (gwi.fatalParseError && !gwi.parseErrorText.empty())
fGwip.parseErrorText = gwi.parseErrorText;
else
fGwip.parseErrorText = "Error occured in InSub::transform()";
csep->tableList(tblist);
csep->derivedTableList(derivedTbList);
return NULL;
}
ExistsFilter *subFilter = new ExistsFilter();
subFilter->sub(csep);
// remove outer query tables
CalpontSelectExecutionPlan::TableList tblist;
if (gwi.subQuery->correlated())
subFilter->correlated(true);
else
subFilter->correlated(false);
if (fGwip.clauseType == HAVING && subFilter->correlated())
{
fGwip.fatalParseError = true;
fGwip.parseErrorText = logging::IDBErrorInfo::instance()->errorMsg(logging::ERR_NON_SUPPORT_HAVING);
}
if (csep->tableList().size() >= tbCnt)
tblist.insert(tblist.begin(), csep->tableList().begin() + tbCnt, csep->tableList().end());
fGwip.subselectList.push_back(csep);
return new ParseTree(subFilter);
CalpontSelectExecutionPlan::SelectList derivedTbList;
if (csep->derivedTableList().size() >= gwi.derivedTbCnt)
derivedTbList.insert(derivedTbList.begin(),
csep->derivedTableList().begin() + gwi.derivedTbCnt,
csep->derivedTableList().end());
csep->tableList(tblist);
csep->derivedTableList(derivedTbList);
ExistsFilter* subFilter = new ExistsFilter();
subFilter->sub(csep);
if (gwi.subQuery->correlated())
subFilter->correlated(true);
else
subFilter->correlated(false);
if (fGwip.clauseType == HAVING && subFilter->correlated())
{
fGwip.fatalParseError = true;
fGwip.parseErrorText = logging::IDBErrorInfo::instance()->errorMsg(logging::ERR_NON_SUPPORT_HAVING);
}
fGwip.subselectList.push_back(csep);
return new ParseTree(subFilter);
}
/**
@@ -186,88 +200,104 @@ execplan::ParseTree* InSub::transform()
*/
void InSub::handleFunc(gp_walk_info* gwip, Item_func* func)
{
if (func->functype() == Item_func::TRIG_COND_FUNC || func->functype() == Item_func::COND_OR_FUNC)
{
// purpose: remove the isnull() function from the parsetree in ptWorkStack.
// IDB handles the null semantics in the join operation
// trigcond(or_cond) is the only form we recognize for now
if (func->argument_count() > 2)
{
fGwip.fatalParseError = true;
fGwip.parseErrorText = "Unsupported item in IN subquery";
return;
}
Item_cond* cond;
if (func->functype() == Item_func::TRIG_COND_FUNC || func->functype() == Item_func::COND_OR_FUNC)
{
// purpose: remove the isnull() function from the parsetree in ptWorkStack.
// IDB handles the null semantics in the join operation
// trigcond(or_cond) is the only form we recognize for now
if (func->argument_count() > 2)
{
fGwip.fatalParseError = true;
fGwip.parseErrorText = "Unsupported item in IN subquery";
return;
}
if (func->functype() == Item_func::TRIG_COND_FUNC)
{
Item* item;
if (func->arguments()[0]->type() == Item::REF_ITEM)
item = (Item_ref*)(func->arguments()[0])->real_item();
else
item = func->arguments()[0];
cond = (Item_cond*)(item);
}
else
{
cond = (Item_cond*)(func);
}
if (cond->functype() == Item_func::COND_OR_FUNC)
{
// (cache=item) case. do nothing. ignore trigcond()?
if (cond->argument_list()->elements == 1)
return;
// (cache=item or isnull(item)) case. remove "or isnull()"
if (cond->argument_list()->elements == 2)
{
// don't know how to deal with this. don't think it's a fatal error either.
if (gwip->ptWorkStack.empty())
return;
ParseTree *pt = gwip->ptWorkStack.top();
if (!pt->left() || !pt->right())
return;
SimpleFilter *sf = dynamic_cast<SimpleFilter*>(pt->left()->data());
//assert (sf && sf->op()->op() == execplan::OP_ISNULL);
if (!sf || sf->op()->op() != execplan::OP_ISNULL)
return;
delete sf;
sf = dynamic_cast<SimpleFilter*>(pt->right()->data());
//idbassert(sf && sf->op()->op() == execplan::OP_EQ);
if (!sf || sf->op()->op() != execplan::OP_EQ)
return;
Item_cond* cond;
// set NULLMATCH for both operand. It's really a setting for the join.
// should only set NULLMATCH when the subtype is NOT_IN. for some IN subquery
// with aggregation column, MySQL inefficiently convert to:
// (cache=item or item is null) and item is not null, which is equivalent to
// cache = item. Do not set NULLMATCH for this case.
// Because we don't know IN or NOTIN yet, set candidate bit and switch to NULLMATCH
// later in handleNot function.
if (sf->lhs()->joinInfo() & JOIN_CORRELATED)
sf->lhs()->joinInfo(sf->lhs()->joinInfo() | JOIN_NULLMATCH_CANDIDATE);
if (sf->rhs()->joinInfo() & JOIN_CORRELATED)
sf->rhs()->joinInfo(sf->rhs()->joinInfo() | JOIN_NULLMATCH_CANDIDATE);
pt = pt->right();
gwip->ptWorkStack.pop();
gwip->ptWorkStack.push(pt);
}
}
else if (cond->functype() == Item_func::EQ_FUNC)
{
// not in (select const ...)
if (gwip->ptWorkStack.empty())
return;
ParseTree *pt = gwip->ptWorkStack.top();
SimpleFilter *sf = dynamic_cast<SimpleFilter*>(pt->data());
if (!sf || sf->op()->op() != execplan::OP_EQ)
return;
if (func->functype() == Item_func::TRIG_COND_FUNC)
{
Item* item;
if (sf->lhs()->joinInfo() & JOIN_CORRELATED)
sf->lhs()->joinInfo(sf->lhs()->joinInfo() | JOIN_NULLMATCH_CANDIDATE);
if (sf->rhs()->joinInfo() & JOIN_CORRELATED)
sf->rhs()->joinInfo(sf->rhs()->joinInfo() | JOIN_NULLMATCH_CANDIDATE);
}
}
if (func->arguments()[0]->type() == Item::REF_ITEM)
item = (Item_ref*)(func->arguments()[0])->real_item();
else
item = func->arguments()[0];
cond = (Item_cond*)(item);
}
else
{
cond = (Item_cond*)(func);
}
if (cond->functype() == Item_func::COND_OR_FUNC)
{
// (cache=item) case. do nothing. ignore trigcond()?
if (cond->argument_list()->elements == 1)
return;
// (cache=item or isnull(item)) case. remove "or isnull()"
if (cond->argument_list()->elements == 2)
{
// don't know how to deal with this. don't think it's a fatal error either.
if (gwip->ptWorkStack.empty())
return;
ParseTree* pt = gwip->ptWorkStack.top();
if (!pt->left() || !pt->right())
return;
SimpleFilter* sf = dynamic_cast<SimpleFilter*>(pt->left()->data());
//assert (sf && sf->op()->op() == execplan::OP_ISNULL);
if (!sf || sf->op()->op() != execplan::OP_ISNULL)
return;
delete sf;
sf = dynamic_cast<SimpleFilter*>(pt->right()->data());
//idbassert(sf && sf->op()->op() == execplan::OP_EQ);
if (!sf || sf->op()->op() != execplan::OP_EQ)
return;
// set NULLMATCH for both operand. It's really a setting for the join.
// should only set NULLMATCH when the subtype is NOT_IN. for some IN subquery
// with aggregation column, MySQL inefficiently convert to:
// (cache=item or item is null) and item is not null, which is equivalent to
// cache = item. Do not set NULLMATCH for this case.
// Because we don't know IN or NOTIN yet, set candidate bit and switch to NULLMATCH
// later in handleNot function.
if (sf->lhs()->joinInfo() & JOIN_CORRELATED)
sf->lhs()->joinInfo(sf->lhs()->joinInfo() | JOIN_NULLMATCH_CANDIDATE);
if (sf->rhs()->joinInfo() & JOIN_CORRELATED)
sf->rhs()->joinInfo(sf->rhs()->joinInfo() | JOIN_NULLMATCH_CANDIDATE);
pt = pt->right();
gwip->ptWorkStack.pop();
gwip->ptWorkStack.push(pt);
}
}
else if (cond->functype() == Item_func::EQ_FUNC)
{
// not in (select const ...)
if (gwip->ptWorkStack.empty())
return;
ParseTree* pt = gwip->ptWorkStack.top();
SimpleFilter* sf = dynamic_cast<SimpleFilter*>(pt->data());
if (!sf || sf->op()->op() != execplan::OP_EQ)
return;
if (sf->lhs()->joinInfo() & JOIN_CORRELATED)
sf->lhs()->joinInfo(sf->lhs()->joinInfo() | JOIN_NULLMATCH_CANDIDATE);
if (sf->rhs()->joinInfo() & JOIN_CORRELATED)
sf->rhs()->joinInfo(sf->rhs()->joinInfo() | JOIN_NULLMATCH_CANDIDATE);
}
}
}
/**
@@ -277,17 +307,20 @@ void InSub::handleFunc(gp_walk_info* gwip, Item_func* func)
*/
void InSub::handleNot()
{
ParseTree *pt = fGwip.ptWorkStack.top();
ExistsFilter *subFilter = dynamic_cast<ExistsFilter*>(pt->data());
idbassert(subFilter);
subFilter->notExists(true);
SCSEP csep = subFilter->sub();
const ParseTree* ptsub = csep->filters();
if (ptsub)
ptsub->walk(makeAntiJoin);
ptsub = csep->having();
if (ptsub)
ptsub->walk(makeAntiJoin);
ParseTree* pt = fGwip.ptWorkStack.top();
ExistsFilter* subFilter = dynamic_cast<ExistsFilter*>(pt->data());
idbassert(subFilter);
subFilter->notExists(true);
SCSEP csep = subFilter->sub();
const ParseTree* ptsub = csep->filters();
if (ptsub)
ptsub->walk(makeAntiJoin);
ptsub = csep->having();
if (ptsub)
ptsub->walk(makeAntiJoin);
}
}

766
dbcon/mysql/ha_pseudocolumn.cpp Executable file → Normal file
View File

@@ -22,7 +22,8 @@ using namespace execplan;
#include "ha_calpont_impl_if.h"
using namespace cal_impl_if;
namespace {
namespace
{
/*******************************************************************************
* Pseudo column connector interface
@@ -43,531 +44,546 @@ namespace {
void bailout(char* error, const string& funcName)
{
string errMsg = IDBErrorInfo::instance()->errorMsg(ERR_PSEUDOCOL_IDB_ONLY, funcName);
current_thd->get_stmt_da()->set_overwrite_status(true);
string errMsg = IDBErrorInfo::instance()->errorMsg(ERR_PSEUDOCOL_IDB_ONLY, funcName);
current_thd->get_stmt_da()->set_overwrite_status(true);
current_thd->raise_error_printf(ER_INTERNAL_ERROR, errMsg.c_str());
*error = 1;
*error = 1;
}
int64_t idblocalpm()
{
THD* thd = current_thd;
if (!thd->infinidb_vtable.cal_conn_info)
thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info());
cal_connection_info* ci = reinterpret_cast<cal_connection_info*>(thd->infinidb_vtable.cal_conn_info);
THD* thd = current_thd;
if (ci->localPm == -1)
{
string module = ClientRotator::getModule();
if (module.size() >= 3 && (module[0] == 'p' || module[0] == 'P'))
ci->localPm = atol(module.c_str()+2);
else
ci->localPm = 0;
}
return ci->localPm;
if (!thd->infinidb_vtable.cal_conn_info)
thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info());
cal_connection_info* ci = reinterpret_cast<cal_connection_info*>(thd->infinidb_vtable.cal_conn_info);
if (ci->localPm == -1)
{
string module = ClientRotator::getModule();
if (module.size() >= 3 && (module[0] == 'p' || module[0] == 'P'))
ci->localPm = atol(module.c_str() + 2);
else
ci->localPm = 0;
}
return ci->localPm;
}
extern "C"
{
/**
* IDBDBROOT
*/
/**
* IDBDBROOT
*/
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
my_bool idbdbroot_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message,"idbdbroot() requires one argument");
return 1;
}
my_bool idbdbroot_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "idbdbroot() requires one argument");
return 1;
}
return 0;
}
return 0;
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
void idbdbroot_deinit(UDF_INIT* initid)
{
}
void idbdbroot_deinit(UDF_INIT* initid)
{
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
long long idbdbroot(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error)
{
bailout(error, "idbdbroot");
return 0;
}
long long idbdbroot(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
bailout(error, "idbdbroot");
return 0;
}
/**
* IDBPM
*/
/**
* IDBPM
*/
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
my_bool idbpm_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message,"idbpm() requires one argument");
return 1;
}
my_bool idbpm_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "idbpm() requires one argument");
return 1;
}
return 0;
}
return 0;
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
void idbpm_deinit(UDF_INIT* initid)
{
}
void idbpm_deinit(UDF_INIT* initid)
{
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
long long idbpm(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error)
{
bailout(error, "idbpm");
return 0;
}
long long idbpm(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
bailout(error, "idbpm");
return 0;
}
/**
* IDBEXTENTRELATIVERID
*/
/**
* IDBEXTENTRELATIVERID
*/
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
my_bool idbextentrelativerid_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message,"idbextentrelativerid() requires one argument");
return 1;
}
my_bool idbextentrelativerid_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "idbextentrelativerid() requires one argument");
return 1;
}
return 0;
}
return 0;
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
void idbextentrelativerid_deinit(UDF_INIT* initid)
{
}
void idbextentrelativerid_deinit(UDF_INIT* initid)
{
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
long long idbextentrelativerid(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error)
{
bailout(error, "idbextentrelativerid");
return 0;
}
long long idbextentrelativerid(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
bailout(error, "idbextentrelativerid");
return 0;
}
/**
* IDBBLOCKID
*/
/**
* IDBBLOCKID
*/
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
my_bool idbblockid_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message,"idbblockid() requires one argument");
return 1;
}
my_bool idbblockid_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "idbblockid() requires one argument");
return 1;
}
return 0;
}
return 0;
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
void idbblockid_deinit(UDF_INIT* initid)
{
}
void idbblockid_deinit(UDF_INIT* initid)
{
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
long long idbblockid(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error)
{
bailout(error, "idbblockid");
return 0;
}
long long idbblockid(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
bailout(error, "idbblockid");
return 0;
}
/**
* IDBEXTENTID
*/
/**
* IDBEXTENTID
*/
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
my_bool idbextentid_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message,"idbextentid() requires one argument");
return 1;
}
my_bool idbextentid_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "idbextentid() requires one argument");
return 1;
}
return 0;
}
return 0;
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
void idbextentid_deinit(UDF_INIT* initid)
{
}
void idbextentid_deinit(UDF_INIT* initid)
{
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
long long idbextentid(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error)
{
bailout(error, "idbextentid");
return 0;
}
long long idbextentid(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
bailout(error, "idbextentid");
return 0;
}
/**
* IDBSEGMENT
*/
/**
* IDBSEGMENT
*/
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
my_bool idbsegment_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message,"idbsegment() requires one argument");
return 1;
}
my_bool idbsegment_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "idbsegment() requires one argument");
return 1;
}
return 0;
}
return 0;
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
void idbsegment_deinit(UDF_INIT* initid)
{
}
void idbsegment_deinit(UDF_INIT* initid)
{
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
long long idbsegment(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error)
{
bailout(error, "idbsegment");
return 0;
}
long long idbsegment(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
bailout(error, "idbsegment");
return 0;
}
/**
* IDBSEGMENTDIR
*/
/**
* IDBSEGMENTDIR
*/
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
my_bool idbsegmentdir_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message,"idbsegmentdir() requires one argument");
return 1;
}
my_bool idbsegmentdir_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "idbsegmentdir() requires one argument");
return 1;
}
return 0;
}
return 0;
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
void idbsegmentdir_deinit(UDF_INIT* initid)
{
}
void idbsegmentdir_deinit(UDF_INIT* initid)
{
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
long long idbsegmentdir(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error)
{
bailout(error, "idbsegmentdir");
return 0;
}
long long idbsegmentdir(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
bailout(error, "idbsegmentdir");
return 0;
}
/**
* IDBPARTITION
*/
/**
* IDBPARTITION
*/
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
my_bool idbpartition_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message,"idbpartition() requires one argument");
return 1;
}
my_bool idbpartition_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "idbpartition() requires one argument");
return 1;
}
return 0;
}
return 0;
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
void idbpartition_deinit(UDF_INIT* initid)
{
}
void idbpartition_deinit(UDF_INIT* initid)
{
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
const char* idbpartition(UDF_INIT* initid, UDF_ARGS* args,
char* result, unsigned long* length,
char* is_null, char* error)
{
bailout(error, "idbpartition");
return result;
}
const char* idbpartition(UDF_INIT* initid, UDF_ARGS* args,
char* result, unsigned long* length,
char* is_null, char* error)
{
bailout(error, "idbpartition");
return result;
}
/**
* IDBEXTENTMIN
*/
/**
* IDBEXTENTMIN
*/
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
my_bool idbextentmin_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message,"idbpm() requires one argument");
return 1;
}
initid->maybe_null = 1;
return 0;
}
my_bool idbextentmin_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "idbpm() requires one argument");
return 1;
}
initid->maybe_null = 1;
return 0;
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
void idbextentmin_deinit(UDF_INIT* initid)
{
}
void idbextentmin_deinit(UDF_INIT* initid)
{
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
const char* idbextentmin(UDF_INIT* initid, UDF_ARGS* args,
char* result, unsigned long* length,
char* is_null, char* error)
{
bailout(error, "idbextentmin");
return result;
}
const char* idbextentmin(UDF_INIT* initid, UDF_ARGS* args,
char* result, unsigned long* length,
char* is_null, char* error)
{
bailout(error, "idbextentmin");
return result;
}
/**
* IDBEXTENTMAX
*/
/**
* IDBEXTENTMAX
*/
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
my_bool idbextentmax_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message,"idbextentmax() requires one argument");
return 1;
}
initid->maybe_null = 1;
return 0;
}
my_bool idbextentmax_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "idbextentmax() requires one argument");
return 1;
}
initid->maybe_null = 1;
return 0;
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
void idbextentmax_deinit(UDF_INIT* initid)
{
}
void idbextentmax_deinit(UDF_INIT* initid)
{
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
const char* idbextentmax(UDF_INIT* initid, UDF_ARGS* args,
char* result, unsigned long* length,
char* is_null, char* error)
{
bailout(error, "idbextentmax");
return result;
}
const char* idbextentmax(UDF_INIT* initid, UDF_ARGS* args,
char* result, unsigned long* length,
char* is_null, char* error)
{
bailout(error, "idbextentmax");
return result;
}
/**
* IDBLOCALPM
*/
/**
* IDBLOCALPM
*/
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
my_bool idblocalpm_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 0)
{
strcpy(message,"idblocalpm() should take no argument");
return 1;
}
initid->maybe_null = 1;
return 0;
}
my_bool idblocalpm_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 0)
{
strcpy(message, "idblocalpm() should take no argument");
return 1;
}
initid->maybe_null = 1;
return 0;
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
void idblocalpm_deinit(UDF_INIT* initid)
{
}
void idblocalpm_deinit(UDF_INIT* initid)
{
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
long long idblocalpm(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error)
long long idblocalpm(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
longlong localpm = idblocalpm();
if (localpm == 0)
*is_null = 1;
return localpm;
}
}
}
namespace cal_impl_if
{
longlong localpm = idblocalpm();
if (localpm == 0)
*is_null = 1;
return localpm;
}
}
}
namespace cal_impl_if {
ReturnedColumn* nullOnError(gp_walk_info& gwi, string& funcName)
{
gwi.fatalParseError = true;
gwi.parseErrorText =
logging::IDBErrorInfo::instance()->errorMsg(logging::ERR_PSEUDOCOL_WRONG_ARG, funcName);
return NULL;
gwi.fatalParseError = true;
gwi.parseErrorText =
logging::IDBErrorInfo::instance()->errorMsg(logging::ERR_PSEUDOCOL_WRONG_ARG, funcName);
return NULL;
}
uint32_t isPseudoColumn(string funcName)
{
return execplan::PseudoColumn::pseudoNameToType(funcName);
return execplan::PseudoColumn::pseudoNameToType(funcName);
}
execplan::ReturnedColumn* buildPseudoColumn(Item* item,
gp_walk_info& gwi,
bool& nonSupport,
uint32_t pseudoType)
gp_walk_info& gwi,
bool& nonSupport,
uint32_t pseudoType)
{
if (!(gwi.thd->infinidb_vtable.cal_conn_info))
gwi.thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info());
cal_connection_info* ci = reinterpret_cast<cal_connection_info*>(gwi.thd->infinidb_vtable.cal_conn_info);
if (!(gwi.thd->infinidb_vtable.cal_conn_info))
gwi.thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info());
Item_func* ifp = (Item_func*)item;
cal_connection_info* ci = reinterpret_cast<cal_connection_info*>(gwi.thd->infinidb_vtable.cal_conn_info);
// idblocalpm is replaced by constant
if (pseudoType == PSEUDO_LOCALPM)
{
int64_t localPm = idblocalpm();
ConstantColumn* cc;
if (localPm)
cc = new ConstantColumn(localPm);
else
cc = new ConstantColumn("", ConstantColumn::NULLDATA);
cc->alias(ifp->full_name() ? ifp->full_name() : "");
return cc;
}
Item_func* ifp = (Item_func*)item;
// convert udf item to pseudocolumn item.
// adjust result type
// put arg col to column map
string funcName = ifp->func_name();
if (ifp->argument_count() != 1 ||
!(ifp->arguments()) ||
!(ifp->arguments()[0]) ||
ifp->arguments()[0]->type() != Item::FIELD_ITEM)
return nullOnError(gwi, funcName);
// idblocalpm is replaced by constant
if (pseudoType == PSEUDO_LOCALPM)
{
int64_t localPm = idblocalpm();
ConstantColumn* cc;
Item_field* field = (Item_field*)(ifp->arguments()[0]);
if (localPm)
cc = new ConstantColumn(localPm);
else
cc = new ConstantColumn("", ConstantColumn::NULLDATA);
// @todo rule out derive table
if (!field->field || !field->db_name || strlen(field->db_name) == 0)
return nullOnError(gwi, funcName);
cc->alias(ifp->full_name() ? ifp->full_name() : "");
return cc;
}
SimpleColumn *sc = buildSimpleColumn(field, gwi);
if (!sc)
return nullOnError(gwi, funcName);
// convert udf item to pseudocolumn item.
// adjust result type
// put arg col to column map
string funcName = ifp->func_name();
if ((pseudoType == PSEUDO_EXTENTMIN || pseudoType == PSEUDO_EXTENTMAX) &&
(sc->colType().colDataType == CalpontSystemCatalog::VARBINARY ||
(sc->colType().colDataType == CalpontSystemCatalog::VARCHAR && sc->colType().colWidth > 7) ||
(sc->colType().colDataType == CalpontSystemCatalog::CHAR && sc->colType().colWidth > 8)))
return nullOnError(gwi, funcName);
if (ifp->argument_count() != 1 ||
!(ifp->arguments()) ||
!(ifp->arguments()[0]) ||
ifp->arguments()[0]->type() != Item::FIELD_ITEM)
return nullOnError(gwi, funcName);
// put arg col to column map
if (gwi.clauseType == SELECT || gwi.clauseType == GROUP_BY) // select clause
{
SRCP srcp(sc);
gwi.columnMap.insert(CalpontSelectExecutionPlan::ColumnMap::value_type(sc->columnName(), srcp));
gwi.tableMap[make_aliastable(sc->schemaName(), sc->tableName(), sc->tableAlias(), sc->isInfiniDB())] =
make_pair(1, field->cached_table);
}
else if (!gwi.rcWorkStack.empty())
{
gwi.rcWorkStack.pop();
}
Item_field* field = (Item_field*)(ifp->arguments()[0]);
if (pseudoType == PSEUDO_PARTITION)
{
// parms: psueducolumn dbroot, segmentdir, segment
SPTP sptp;
FunctionColumn *fc = new FunctionColumn(funcName);
funcexp::FunctionParm parms;
PseudoColumn *dbroot = new PseudoColumn(*sc, PSEUDO_DBROOT);
sptp.reset(new ParseTree(dbroot));
parms.push_back(sptp);
PseudoColumn *pp = new PseudoColumn(*sc, PSEUDO_SEGMENTDIR);
sptp.reset(new ParseTree(pp));
parms.push_back(sptp);
PseudoColumn* seg = new PseudoColumn(*sc, PSEUDO_SEGMENT);
sptp.reset(new ParseTree(seg));
parms.push_back(sptp);
fc->functionParms(parms);
fc->expressionId(ci->expressionId++);
// @todo rule out derive table
if (!field->field || !field->db_name || strlen(field->db_name) == 0)
return nullOnError(gwi, funcName);
// string result type
CalpontSystemCatalog::ColType ct;
ct.colDataType = CalpontSystemCatalog::VARCHAR;
ct.colWidth = 256;
fc->resultType(ct);
SimpleColumn* sc = buildSimpleColumn(field, gwi);
// operation type integer
funcexp::Func_idbpartition* idbpartition = new funcexp::Func_idbpartition();
fc->operationType(idbpartition->operationType(parms, fc->resultType()));
fc->alias(ifp->full_name() ? ifp->full_name() : "");
return fc;
}
if (!sc)
return nullOnError(gwi, funcName);
PseudoColumn *pc = new PseudoColumn(*sc, pseudoType);
if ((pseudoType == PSEUDO_EXTENTMIN || pseudoType == PSEUDO_EXTENTMAX) &&
(sc->colType().colDataType == CalpontSystemCatalog::VARBINARY ||
(sc->colType().colDataType == CalpontSystemCatalog::VARCHAR && sc->colType().colWidth > 7) ||
(sc->colType().colDataType == CalpontSystemCatalog::CHAR && sc->colType().colWidth > 8)))
return nullOnError(gwi, funcName);
// @bug5892. set alias for derived table column matching.
pc->alias(ifp->name? ifp->name : "");
return pc;
// put arg col to column map
if (gwi.clauseType == SELECT || gwi.clauseType == GROUP_BY) // select clause
{
SRCP srcp(sc);
gwi.columnMap.insert(CalpontSelectExecutionPlan::ColumnMap::value_type(sc->columnName(), srcp));
gwi.tableMap[make_aliastable(sc->schemaName(), sc->tableName(), sc->tableAlias(), sc->isInfiniDB())] =
make_pair(1, field->cached_table);
}
else if (!gwi.rcWorkStack.empty())
{
gwi.rcWorkStack.pop();
}
if (pseudoType == PSEUDO_PARTITION)
{
// parms: psueducolumn dbroot, segmentdir, segment
SPTP sptp;
FunctionColumn* fc = new FunctionColumn(funcName);
funcexp::FunctionParm parms;
PseudoColumn* dbroot = new PseudoColumn(*sc, PSEUDO_DBROOT);
sptp.reset(new ParseTree(dbroot));
parms.push_back(sptp);
PseudoColumn* pp = new PseudoColumn(*sc, PSEUDO_SEGMENTDIR);
sptp.reset(new ParseTree(pp));
parms.push_back(sptp);
PseudoColumn* seg = new PseudoColumn(*sc, PSEUDO_SEGMENT);
sptp.reset(new ParseTree(seg));
parms.push_back(sptp);
fc->functionParms(parms);
fc->expressionId(ci->expressionId++);
// string result type
CalpontSystemCatalog::ColType ct;
ct.colDataType = CalpontSystemCatalog::VARCHAR;
ct.colWidth = 256;
fc->resultType(ct);
// operation type integer
funcexp::Func_idbpartition* idbpartition = new funcexp::Func_idbpartition();
fc->operationType(idbpartition->operationType(parms, fc->resultType()));
fc->alias(ifp->full_name() ? ifp->full_name() : "");
return fc;
}
PseudoColumn* pc = new PseudoColumn(*sc, pseudoType);
// @bug5892. set alias for derived table column matching.
pc->alias(ifp->name ? ifp->name : "");
return pc;
}
}

442
dbcon/mysql/ha_scalar_sub.cpp Executable file → Normal file
View File

@@ -54,16 +54,16 @@ ScalarSub::ScalarSub(gp_walk_info& gwip) : WhereSubQuery(gwip), fReturnedColPos(
{}
ScalarSub::ScalarSub(gp_walk_info& gwip, Item_func* func) :
WhereSubQuery(gwip, func), fReturnedColPos(0)
WhereSubQuery(gwip, func), fReturnedColPos(0)
{}
ScalarSub::ScalarSub(gp_walk_info& gwip, const execplan::SRCP& column, Item_subselect* sub, Item_func* func):
WhereSubQuery(gwip, column, sub, func), fReturnedColPos(0)
WhereSubQuery(gwip, column, sub, func), fReturnedColPos(0)
{}
ScalarSub::ScalarSub(const ScalarSub& rhs) :
WhereSubQuery(rhs.gwip(), rhs.fColumn, rhs.fSub, rhs.fFunc),
fReturnedColPos(rhs.fReturnedColPos)
WhereSubQuery(rhs.gwip(), rhs.fColumn, rhs.fSub, rhs.fFunc),
fReturnedColPos(rhs.fReturnedColPos)
{}
ScalarSub::~ScalarSub()
@@ -71,244 +71,266 @@ ScalarSub::~ScalarSub()
execplan::ParseTree* ScalarSub::transform()
{
if (!fFunc)
return NULL;
if (!fFunc)
return NULL;
// @todo need to handle scalar IN and BETWEEN specially
// this blocks handles only one subselect scalar
// arg[0]: column | arg[1]: subselect
//idbassert(fGwip.rcWorkStack.size() >= 2);
if (fFunc->functype() == Item_func::BETWEEN)
return transform_between();
if (fFunc->functype() == Item_func::IN_FUNC)
return transform_in();
// @todo need to handle scalar IN and BETWEEN specially
// this blocks handles only one subselect scalar
// arg[0]: column | arg[1]: subselect
//idbassert(fGwip.rcWorkStack.size() >= 2);
if (fFunc->functype() == Item_func::BETWEEN)
return transform_between();
ReturnedColumn* rhs = NULL;
ReturnedColumn* lhs = NULL;
if (!fGwip.rcWorkStack.empty())
{
rhs = fGwip.rcWorkStack.top();
fGwip.rcWorkStack.pop();
}
if (!fGwip.rcWorkStack.empty())
{
lhs = fGwip.rcWorkStack.top();
fGwip.rcWorkStack.pop();
}
if (fFunc->functype() == Item_func::IN_FUNC)
return transform_in();
PredicateOperator *op = new PredicateOperator(fFunc->func_name());
if (!lhs && (fFunc->functype() == Item_func::ISNULL_FUNC ||
fFunc->functype() == Item_func::ISNOTNULL_FUNC))
{
fSub = (Item_subselect*)(fFunc->arguments()[0]);
fColumn.reset(new ConstantColumn("", ConstantColumn::NULLDATA));
delete rhs;
return buildParseTree(op);
}
ReturnedColumn* rhs = NULL;
ReturnedColumn* lhs = NULL;
bool reverseOp = false;
SubSelect* sub = dynamic_cast<SubSelect*>(rhs);
if (!sub)
{
reverseOp = true;
delete lhs;
lhs = rhs;
fSub = (Item_subselect*)(fFunc->arguments()[0]);
}
else
{
delete rhs;
fSub = (Item_subselect*)(fFunc->arguments()[1]);
}
fColumn.reset(lhs); // column should be in the stack already. in, between may be different
//PredicateOperator *op = new PredicateOperator(fFunc->func_name());
if (reverseOp)
op->reverseOp();
if (!fGwip.rcWorkStack.empty())
{
rhs = fGwip.rcWorkStack.top();
fGwip.rcWorkStack.pop();
}
return buildParseTree(op);
if (!fGwip.rcWorkStack.empty())
{
lhs = fGwip.rcWorkStack.top();
fGwip.rcWorkStack.pop();
}
PredicateOperator* op = new PredicateOperator(fFunc->func_name());
if (!lhs && (fFunc->functype() == Item_func::ISNULL_FUNC ||
fFunc->functype() == Item_func::ISNOTNULL_FUNC))
{
fSub = (Item_subselect*)(fFunc->arguments()[0]);
fColumn.reset(new ConstantColumn("", ConstantColumn::NULLDATA));
delete rhs;
return buildParseTree(op);
}
bool reverseOp = false;
SubSelect* sub = dynamic_cast<SubSelect*>(rhs);
if (!sub)
{
reverseOp = true;
delete lhs;
lhs = rhs;
fSub = (Item_subselect*)(fFunc->arguments()[0]);
}
else
{
delete rhs;
fSub = (Item_subselect*)(fFunc->arguments()[1]);
}
fColumn.reset(lhs); // column should be in the stack already. in, between may be different
//PredicateOperator *op = new PredicateOperator(fFunc->func_name());
if (reverseOp)
op->reverseOp();
return buildParseTree(op);
}
execplan::ParseTree* ScalarSub::transform_between()
{
//idbassert(fGwip.rcWorkStack.size() >= 3);
if (fGwip.rcWorkStack.size() < 3)
{
fGwip.fatalParseError = true;
fGwip.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_NON_SUPPORT_SCALAR);
return NULL;
}
ReturnedColumn* op3 = fGwip.rcWorkStack.top();
fGwip.rcWorkStack.pop();
ReturnedColumn* op2 = fGwip.rcWorkStack.top();
fGwip.rcWorkStack.pop();
ReturnedColumn* op1 = fGwip.rcWorkStack.top();
fGwip.rcWorkStack.pop();
fColumn.reset(op1);
//idbassert(fGwip.rcWorkStack.size() >= 3);
if (fGwip.rcWorkStack.size() < 3)
{
fGwip.fatalParseError = true;
fGwip.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_NON_SUPPORT_SCALAR);
return NULL;
}
ParseTree* lhs = NULL;
ParseTree* rhs = NULL;
PredicateOperator* op_LE = new PredicateOperator("<=");
PredicateOperator* op_GE = new PredicateOperator(">=");
ReturnedColumn* op3 = fGwip.rcWorkStack.top();
fGwip.rcWorkStack.pop();
ReturnedColumn* op2 = fGwip.rcWorkStack.top();
fGwip.rcWorkStack.pop();
ReturnedColumn* op1 = fGwip.rcWorkStack.top();
fGwip.rcWorkStack.pop();
fColumn.reset(op1);
SubSelect* sub2 = dynamic_cast<SubSelect*>(op3);
fSub = (Item_subselect*)(fFunc->arguments()[2]);
if (sub2)
{
rhs = buildParseTree(op_LE);
delete sub2;
}
else
{
SOP sop;
sop.reset(op_LE);
rhs = new ParseTree(new SimpleFilter(sop, fColumn.get(), op3));
}
ParseTree* lhs = NULL;
ParseTree* rhs = NULL;
PredicateOperator* op_LE = new PredicateOperator("<=");
PredicateOperator* op_GE = new PredicateOperator(">=");
SubSelect* sub1 = dynamic_cast<SubSelect*>(op2);
fSub = (Item_subselect*)(fFunc->arguments()[1]);
if (sub1)
{
lhs = buildParseTree(op_GE);
delete sub1;
}
else
{
SOP sop;
sop.reset(op_GE);
lhs = new ParseTree(new SimpleFilter(sop, fColumn.get(), op2));
}
SubSelect* sub2 = dynamic_cast<SubSelect*>(op3);
fSub = (Item_subselect*)(fFunc->arguments()[2]);
if (!rhs || !lhs)
{
fGwip.fatalParseError = true;
fGwip.parseErrorText = "non-supported scalar subquery";
fGwip.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_NON_SUPPORT_SCALAR);
return NULL;
}
ParseTree* pt = new ParseTree (new LogicOperator("and"));
pt->left(lhs);
pt->right(rhs);
return pt;
if (sub2)
{
rhs = buildParseTree(op_LE);
delete sub2;
}
else
{
SOP sop;
sop.reset(op_LE);
rhs = new ParseTree(new SimpleFilter(sop, fColumn.get(), op3));
}
SubSelect* sub1 = dynamic_cast<SubSelect*>(op2);
fSub = (Item_subselect*)(fFunc->arguments()[1]);
if (sub1)
{
lhs = buildParseTree(op_GE);
delete sub1;
}
else
{
SOP sop;
sop.reset(op_GE);
lhs = new ParseTree(new SimpleFilter(sop, fColumn.get(), op2));
}
if (!rhs || !lhs)
{
fGwip.fatalParseError = true;
fGwip.parseErrorText = "non-supported scalar subquery";
fGwip.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_NON_SUPPORT_SCALAR);
return NULL;
}
ParseTree* pt = new ParseTree (new LogicOperator("and"));
pt->left(lhs);
pt->right(rhs);
return pt;
}
execplan::ParseTree* ScalarSub::transform_in()
{
fGwip.fatalParseError = true;
fGwip.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_NON_SUPPORT_SCALAR);
return NULL;
fGwip.fatalParseError = true;
fGwip.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_NON_SUPPORT_SCALAR);
return NULL;
}
execplan::ParseTree* ScalarSub::buildParseTree(PredicateOperator* op)
{
idbassert(fColumn.get() && fSub && fFunc);
idbassert(fColumn.get() && fSub && fFunc);
vector<SRCP> cols;
Filter *filter;
RowColumn* rcol = dynamic_cast<RowColumn*>(fColumn.get());
if (rcol)
{
// IDB only supports (c1,c2..) =/!= (subquery)
if (fFunc->functype() != Item_func::EQ_FUNC && fFunc->functype() != Item_func::NE_FUNC)
{
fGwip.fatalParseError = true;
fGwip.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_INVALID_OPERATOR_WITH_LIST);
return NULL;
}
cols = rcol->columnVec();
}
else
cols.push_back(fColumn);
vector<SRCP> cols;
Filter* filter;
RowColumn* rcol = dynamic_cast<RowColumn*>(fColumn.get());
SCSEP csep(new CalpontSelectExecutionPlan());
csep->sessionID(fGwip.sessionid);
csep->location(CalpontSelectExecutionPlan::WHERE);
csep->subType (CalpontSelectExecutionPlan::SINGLEROW_SUBS);
if (rcol)
{
// IDB only supports (c1,c2..) =/!= (subquery)
if (fFunc->functype() != Item_func::EQ_FUNC && fFunc->functype() != Item_func::NE_FUNC)
{
fGwip.fatalParseError = true;
fGwip.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_INVALID_OPERATOR_WITH_LIST);
return NULL;
}
// gwi for the sub query
gp_walk_info gwi;
gwi.thd = fGwip.thd;
gwi.subQuery = this;
cols = rcol->columnVec();
}
else
cols.push_back(fColumn);
// @4827 merge table list to gwi in case there is FROM sub to be referenced
// in the FROM sub
gwi.derivedTbCnt = fGwip.derivedTbList.size();
uint32_t tbCnt = fGwip.tbList.size();
SCSEP csep(new CalpontSelectExecutionPlan());
csep->sessionID(fGwip.sessionid);
csep->location(CalpontSelectExecutionPlan::WHERE);
csep->subType (CalpontSelectExecutionPlan::SINGLEROW_SUBS);
gwi.tbList.insert(gwi.tbList.begin(), fGwip.tbList.begin(), fGwip.tbList.end());
gwi.derivedTbList.insert(gwi.derivedTbList.begin(), fGwip.derivedTbList.begin(), fGwip.derivedTbList.end());
// gwi for the sub query
gp_walk_info gwi;
gwi.thd = fGwip.thd;
gwi.subQuery = this;
if (getSelectPlan(gwi, *(fSub->get_select_lex()), csep) != 0)
{
//@todo more in error handling
if (!gwi.fatalParseError)
{
fGwip.fatalParseError = true;
fGwip.parseErrorText = "Error occured in ScalarSub::transform()";
}
else
{
fGwip.fatalParseError = gwi.fatalParseError;
fGwip.parseErrorText = gwi.parseErrorText;
}
return NULL;
}
fGwip.subselectList.push_back(csep);
// @4827 merge table list to gwi in case there is FROM sub to be referenced
// in the FROM sub
gwi.derivedTbCnt = fGwip.derivedTbList.size();
uint32_t tbCnt = fGwip.tbList.size();
// error out non-support case for now: comparison out of semi join tables.
// only check for simplecolumn
if (!gwi.correlatedTbNameVec.empty())
{
for (uint32_t i = 0; i < cols.size(); i++)
{
SimpleColumn* sc = dynamic_cast<SimpleColumn*>(cols[i].get());
if (sc)
{
CalpontSystemCatalog::TableAliasName tan = make_aliastable(sc->schemaName(), sc->tableName(), sc->tableAlias());
uint32_t j = 0;
for (; j < gwi.correlatedTbNameVec.size(); j++)
if (tan == gwi.correlatedTbNameVec[j])
break;
if (j == gwi.correlatedTbNameVec.size())
{
fGwip.fatalParseError = true;
fGwip.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_NON_SUPPORT_SCALAR);
return NULL;
}
}
}
}
gwi.tbList.insert(gwi.tbList.begin(), fGwip.tbList.begin(), fGwip.tbList.end());
gwi.derivedTbList.insert(gwi.derivedTbList.begin(), fGwip.derivedTbList.begin(), fGwip.derivedTbList.end());
// remove outer query tables
CalpontSelectExecutionPlan::TableList tblist;
if (csep->tableList().size() >= tbCnt)
tblist.insert(tblist.begin(),csep->tableList().begin()+tbCnt, csep->tableList().end());
CalpontSelectExecutionPlan::SelectList derivedTbList;
if (csep->derivedTableList().size() >= gwi.derivedTbCnt)
derivedTbList.insert(derivedTbList.begin(), csep->derivedTableList().begin()+gwi.derivedTbCnt, csep->derivedTableList().end());
if (getSelectPlan(gwi, *(fSub->get_select_lex()), csep) != 0)
{
//@todo more in error handling
if (!gwi.fatalParseError)
{
fGwip.fatalParseError = true;
fGwip.parseErrorText = "Error occured in ScalarSub::transform()";
}
else
{
fGwip.fatalParseError = gwi.fatalParseError;
fGwip.parseErrorText = gwi.parseErrorText;
}
csep->tableList(tblist);
csep->derivedTableList(derivedTbList);
return NULL;
}
fGwip.subselectList.push_back(csep);
// error out non-support case for now: comparison out of semi join tables.
// only check for simplecolumn
if (!gwi.correlatedTbNameVec.empty())
{
for (uint32_t i = 0; i < cols.size(); i++)
{
SimpleColumn* sc = dynamic_cast<SimpleColumn*>(cols[i].get());
if (sc)
{
CalpontSystemCatalog::TableAliasName tan = make_aliastable(sc->schemaName(), sc->tableName(), sc->tableAlias());
uint32_t j = 0;
for (; j < gwi.correlatedTbNameVec.size(); j++)
if (tan == gwi.correlatedTbNameVec[j])
break;
if (j == gwi.correlatedTbNameVec.size())
{
fGwip.fatalParseError = true;
fGwip.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_NON_SUPPORT_SCALAR);
return NULL;
}
}
}
}
// remove outer query tables
CalpontSelectExecutionPlan::TableList tblist;
if (csep->tableList().size() >= tbCnt)
tblist.insert(tblist.begin(), csep->tableList().begin() + tbCnt, csep->tableList().end());
CalpontSelectExecutionPlan::SelectList derivedTbList;
if (csep->derivedTableList().size() >= gwi.derivedTbCnt)
derivedTbList.insert(derivedTbList.begin(), csep->derivedTableList().begin() + gwi.derivedTbCnt, csep->derivedTableList().end());
csep->tableList(tblist);
csep->derivedTableList(derivedTbList);
// if (fSub->is_correlated)
if (fSub->unit->first_select()->master_unit()->uncacheable)
{
SelectFilter *subFilter = new SelectFilter();
subFilter->correlated(true);
subFilter->cols(cols);
subFilter->sub(csep);
subFilter->op(SOP(op));
subFilter->returnedColPos(fReturnedColPos);
filter = subFilter;
}
else
{
SimpleScalarFilter *subFilter = new SimpleScalarFilter();
subFilter->cols(cols);
subFilter->sub(csep);
subFilter->op(SOP(op));
filter = subFilter;
}
return new ParseTree(filter);
if (fSub->unit->first_select()->master_unit()->uncacheable)
{
SelectFilter* subFilter = new SelectFilter();
subFilter->correlated(true);
subFilter->cols(cols);
subFilter->sub(csep);
subFilter->op(SOP(op));
subFilter->returnedColPos(fReturnedColPos);
filter = subFilter;
}
else
{
SimpleScalarFilter* subFilter = new SimpleScalarFilter();
subFilter->cols(cols);
subFilter->sub(csep);
subFilter->op(SOP(op));
filter = subFilter;
}
return new ParseTree(filter);
}

88
dbcon/mysql/ha_select_sub.cpp Executable file → Normal file
View File

@@ -50,8 +50,8 @@ SelectSubQuery::SelectSubQuery(gp_walk_info& gwip) : SubQuery(gwip), fSelSub (NU
{}
SelectSubQuery::SelectSubQuery(gp_walk_info& gwip, Item_subselect* selSub) :
SubQuery(gwip),
fSelSub(selSub)
SubQuery(gwip),
fSelSub(selSub)
{}
SelectSubQuery::~SelectSubQuery()
@@ -59,53 +59,57 @@ SelectSubQuery::~SelectSubQuery()
SCSEP SelectSubQuery::transform()
{
idbassert(fSelSub);
SCSEP csep(new CalpontSelectExecutionPlan());
csep->sessionID(fGwip.sessionid);
csep->subType (CalpontSelectExecutionPlan::SELECT_SUBS);
idbassert(fSelSub);
SCSEP csep(new CalpontSelectExecutionPlan());
csep->sessionID(fGwip.sessionid);
csep->subType (CalpontSelectExecutionPlan::SELECT_SUBS);
// gwi for the sub query
gp_walk_info gwi;
gwi.thd = fGwip.thd;
gwi.subQuery = this;
// gwi for the sub query
gp_walk_info gwi;
gwi.thd = fGwip.thd;
gwi.subQuery = this;
// @4632 merge table list to gwi in case there is FROM sub to be referenced
// in the SELECT sub
gwi.derivedTbCnt = fGwip.derivedTbList.size();
uint32_t tbCnt = fGwip.tbList.size();
// @4632 merge table list to gwi in case there is FROM sub to be referenced
// in the SELECT sub
gwi.derivedTbCnt = fGwip.derivedTbList.size();
uint32_t tbCnt = fGwip.tbList.size();
gwi.tbList.insert(gwi.tbList.begin(), fGwip.tbList.begin(), fGwip.tbList.end());
gwi.derivedTbList.insert(gwi.derivedTbList.begin(), fGwip.derivedTbList.begin(), fGwip.derivedTbList.end());
gwi.tbList.insert(gwi.tbList.begin(), fGwip.tbList.begin(), fGwip.tbList.end());
gwi.derivedTbList.insert(gwi.derivedTbList.begin(), fGwip.derivedTbList.begin(), fGwip.derivedTbList.end());
if (getSelectPlan(gwi, *(fSelSub->get_select_lex()), csep) != 0)
{
if (!gwi.fatalParseError)
{
fGwip.fatalParseError = true;
fGwip.parseErrorText = "Error occured in SelectSubQuery::transform()";
}
else
{
fGwip.fatalParseError = gwi.fatalParseError;
fGwip.parseErrorText = gwi.parseErrorText;
}
csep.reset();
return csep;
}
if (getSelectPlan(gwi, *(fSelSub->get_select_lex()), csep) != 0)
{
if (!gwi.fatalParseError)
{
fGwip.fatalParseError = true;
fGwip.parseErrorText = "Error occured in SelectSubQuery::transform()";
}
else
{
fGwip.fatalParseError = gwi.fatalParseError;
fGwip.parseErrorText = gwi.parseErrorText;
}
fGwip.subselectList.push_back(csep);
csep.reset();
return csep;
}
// remove outer query tables
CalpontSelectExecutionPlan::TableList tblist;
if (csep->tableList().size() >= tbCnt)
tblist.insert(tblist.begin(),csep->tableList().begin()+tbCnt, csep->tableList().end());
CalpontSelectExecutionPlan::SelectList derivedTbList;
fGwip.subselectList.push_back(csep);
if (csep->derivedTableList().size() >= gwi.derivedTbCnt)
derivedTbList.insert(derivedTbList.begin(), csep->derivedTableList().begin()+gwi.derivedTbCnt, csep->derivedTableList().end());
csep->tableList(tblist);
csep->derivedTableList(derivedTbList);
return csep;
// remove outer query tables
CalpontSelectExecutionPlan::TableList tblist;
if (csep->tableList().size() >= tbCnt)
tblist.insert(tblist.begin(), csep->tableList().begin() + tbCnt, csep->tableList().end());
CalpontSelectExecutionPlan::SelectList derivedTbList;
if (csep->derivedTableList().size() >= gwi.derivedTbCnt)
derivedTbList.insert(derivedTbList.begin(), csep->derivedTableList().begin() + gwi.derivedTbCnt, csep->derivedTableList().end());
csep->tableList(tblist);
csep->derivedTableList(derivedTbList);
return csep;
}
}

371
dbcon/mysql/ha_subquery.h Executable file → Normal file
View File

@@ -15,167 +15,212 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
/***********************************************************************
* $Id: ha_subquery.h 6418 2010-03-29 21:55:08Z zzhu $
*
*
***********************************************************************/
/** @file */
/** class subquery series interface */
#ifndef HA_SUBQUERY
#define HA_SUBQUERY
//#undef LOG_INFO
/***********************************************************************
* $Id: ha_subquery.h 6418 2010-03-29 21:55:08Z zzhu $
*
*
***********************************************************************/
/** @file */
/** class subquery series interface */
#ifndef HA_SUBQUERY
#define HA_SUBQUERY
//#undef LOG_INFO
#include <my_config.h>
#include "idb_mysql.h"
#include "ha_calpont_impl_if.h"
namespace execplan
{
class PredicateOperator;
}
namespace cal_impl_if
{
/** @file */
class SubQuery
{
public:
SubQuery(gp_walk_info& gwip) : fGwip(gwip), fCorrelated(false) {}
virtual ~SubQuery() {}
virtual gp_walk_info& gwip() const { return fGwip; }
const bool correlated() const { return fCorrelated; }
void correlated (const bool correlated) { fCorrelated = correlated; }
virtual void handleFunc (gp_walk_info* gwip, Item_func* func) {}
virtual void handleNot () {}
protected:
gp_walk_info& fGwip;
bool fCorrelated;
};
/**
* @brief A class to represent a generic WHERE clause subquery
*/
class WhereSubQuery : public SubQuery
{
public:
WhereSubQuery(gp_walk_info& gwip) : SubQuery(gwip),
fSub(NULL),
fFunc(NULL) {}
WhereSubQuery(gp_walk_info& gwip, const execplan::SRCP& column, Item_subselect* sub, Item_func* func) :
SubQuery(gwip),
fColumn(column),
fSub(sub),
fFunc(func) {}
WhereSubQuery(gp_walk_info& gwip, Item_func* func) : SubQuery(gwip), fFunc(func) {}
WhereSubQuery(gp_walk_info& gwip, Item_subselect* sub) : SubQuery(gwip), fSub(sub) {} // for exists
virtual ~WhereSubQuery() {}
/** Accessors and mutators */
virtual Item_subselect* sub() const { return fSub; }
virtual void sub(Item_subselect* sub) { fSub = sub; }
virtual Item_func* func() const { return fFunc; }
virtual void func(Item_func* func) { fFunc = func; }
virtual execplan::ParseTree* transform() = 0;
protected:
execplan::SRCP fColumn;
Item_subselect* fSub;
Item_func* fFunc;
};
/**
* @brief A class to represent a scalar subquery
*/
class ScalarSub : public WhereSubQuery
{
public:
ScalarSub(gp_walk_info& gwip);
ScalarSub(gp_walk_info& gwip, Item_func* func);
ScalarSub(gp_walk_info& gwip, const execplan::SRCP& column, Item_subselect* sub, Item_func* func);
ScalarSub(const ScalarSub& rhs);
~ScalarSub();
execplan::ParseTree* transform();
execplan::ParseTree* transform_between();
execplan::ParseTree* transform_in();
execplan::ParseTree* buildParseTree(execplan::PredicateOperator* op);
const uint64_t returnedColPos() const { return fReturnedColPos; }
void returnedColPos(const uint64_t returnedColPos) {fReturnedColPos = returnedColPos;}
private:
uint64_t fReturnedColPos;
};
/**
* @brief A class to represent a IN subquery
*/
class InSub : public WhereSubQuery
{
public:
InSub(gp_walk_info& gwip);
InSub(gp_walk_info& gwip, Item_func* func);
InSub(const InSub& rhs);
~InSub();
execplan::ParseTree* transform();
void handleFunc(gp_walk_info* gwip, Item_func* func);
void handleNot();
};
/**
* @brief A class to represent an EXISTS subquery
*/
class ExistsSub : public WhereSubQuery
{
public:
ExistsSub(gp_walk_info&); // not complete. just for compile
ExistsSub(gp_walk_info&, Item_subselect* sub);
~ExistsSub();
execplan::ParseTree* transform();
void handleNot();
};
/**
* @brief A class to represent a subquery which contains GROUP BY
*/
class AggregateSub : public WhereSubQuery
{
};
/**
* @brief A class to represent a generic FROM subquery
*/
class FromSubQuery : public SubQuery
{
public:
FromSubQuery(gp_walk_info&);
FromSubQuery(gp_walk_info&, SELECT_LEX* fromSub);
~FromSubQuery();
const SELECT_LEX* fromSub() const { return fFromSub; }
void fromSub(SELECT_LEX* fromSub) {fFromSub = fromSub; }
const std::string alias () const { return fAlias; }
void alias (const std::string alias) { fAlias = alias; }
execplan::SCSEP transform();
private:
SELECT_LEX* fFromSub;
std::string fAlias;
};
class SelectSubQuery : public SubQuery
{
public:
SelectSubQuery(gp_walk_info&);
SelectSubQuery(gp_walk_info&, Item_subselect* sel);
~SelectSubQuery();
execplan::SCSEP transform();
Item_subselect* selSub() { return fSelSub; }
void selSub( Item_subselect* selSub ) { fSelSub = selSub; }
private:
Item_subselect* fSelSub;
};
}
#endif
#include "idb_mysql.h"
#include "ha_calpont_impl_if.h"
namespace execplan
{
class PredicateOperator;
}
namespace cal_impl_if
{
/** @file */
class SubQuery
{
public:
SubQuery(gp_walk_info& gwip) : fGwip(gwip), fCorrelated(false) {}
virtual ~SubQuery() {}
virtual gp_walk_info& gwip() const
{
return fGwip;
}
const bool correlated() const
{
return fCorrelated;
}
void correlated (const bool correlated)
{
fCorrelated = correlated;
}
virtual void handleFunc (gp_walk_info* gwip, Item_func* func) {}
virtual void handleNot () {}
protected:
gp_walk_info& fGwip;
bool fCorrelated;
};
/**
* @brief A class to represent a generic WHERE clause subquery
*/
class WhereSubQuery : public SubQuery
{
public:
WhereSubQuery(gp_walk_info& gwip) : SubQuery(gwip),
fSub(NULL),
fFunc(NULL) {}
WhereSubQuery(gp_walk_info& gwip, const execplan::SRCP& column, Item_subselect* sub, Item_func* func) :
SubQuery(gwip),
fColumn(column),
fSub(sub),
fFunc(func) {}
WhereSubQuery(gp_walk_info& gwip, Item_func* func) : SubQuery(gwip), fFunc(func) {}
WhereSubQuery(gp_walk_info& gwip, Item_subselect* sub) : SubQuery(gwip), fSub(sub) {} // for exists
virtual ~WhereSubQuery() {}
/** Accessors and mutators */
virtual Item_subselect* sub() const
{
return fSub;
}
virtual void sub(Item_subselect* sub)
{
fSub = sub;
}
virtual Item_func* func() const
{
return fFunc;
}
virtual void func(Item_func* func)
{
fFunc = func;
}
virtual execplan::ParseTree* transform() = 0;
protected:
execplan::SRCP fColumn;
Item_subselect* fSub;
Item_func* fFunc;
};
/**
* @brief A class to represent a scalar subquery
*/
class ScalarSub : public WhereSubQuery
{
public:
ScalarSub(gp_walk_info& gwip);
ScalarSub(gp_walk_info& gwip, Item_func* func);
ScalarSub(gp_walk_info& gwip, const execplan::SRCP& column, Item_subselect* sub, Item_func* func);
ScalarSub(const ScalarSub& rhs);
~ScalarSub();
execplan::ParseTree* transform();
execplan::ParseTree* transform_between();
execplan::ParseTree* transform_in();
execplan::ParseTree* buildParseTree(execplan::PredicateOperator* op);
const uint64_t returnedColPos() const
{
return fReturnedColPos;
}
void returnedColPos(const uint64_t returnedColPos)
{
fReturnedColPos = returnedColPos;
}
private:
uint64_t fReturnedColPos;
};
/**
* @brief A class to represent a IN subquery
*/
class InSub : public WhereSubQuery
{
public:
InSub(gp_walk_info& gwip);
InSub(gp_walk_info& gwip, Item_func* func);
InSub(const InSub& rhs);
~InSub();
execplan::ParseTree* transform();
void handleFunc(gp_walk_info* gwip, Item_func* func);
void handleNot();
};
/**
* @brief A class to represent an EXISTS subquery
*/
class ExistsSub : public WhereSubQuery
{
public:
ExistsSub(gp_walk_info&); // not complete. just for compile
ExistsSub(gp_walk_info&, Item_subselect* sub);
~ExistsSub();
execplan::ParseTree* transform();
void handleNot();
};
/**
* @brief A class to represent a subquery which contains GROUP BY
*/
class AggregateSub : public WhereSubQuery
{
};
/**
* @brief A class to represent a generic FROM subquery
*/
class FromSubQuery : public SubQuery
{
public:
FromSubQuery(gp_walk_info&);
FromSubQuery(gp_walk_info&, SELECT_LEX* fromSub);
~FromSubQuery();
const SELECT_LEX* fromSub() const
{
return fFromSub;
}
void fromSub(SELECT_LEX* fromSub)
{
fFromSub = fromSub;
}
const std::string alias () const
{
return fAlias;
}
void alias (const std::string alias)
{
fAlias = alias;
}
execplan::SCSEP transform();
private:
SELECT_LEX* fFromSub;
std::string fAlias;
};
class SelectSubQuery : public SubQuery
{
public:
SelectSubQuery(gp_walk_info&);
SelectSubQuery(gp_walk_info&, Item_subselect* sel);
~SelectSubQuery();
execplan::SCSEP transform();
Item_subselect* selSub()
{
return fSelSub;
}
void selSub( Item_subselect* selSub )
{
fSelSub = selSub;
}
private:
Item_subselect* fSelSub;
};
}
#endif

204
dbcon/mysql/ha_view.cpp Executable file → Normal file
View File

@@ -49,130 +49,134 @@ extern string getViewName(TABLE_LIST* table_ptr);
CalpontSystemCatalog::TableAliasName& View::viewName()
{
return fViewName;
return fViewName;
}
void View::viewName(execplan::CalpontSystemCatalog::TableAliasName& viewName)
{
fViewName = viewName;
fViewName = viewName;
}
void View::transform()
{
CalpontSelectExecutionPlan* csep = new CalpontSelectExecutionPlan();
csep->sessionID(fParentGwip->sessionid);
CalpontSelectExecutionPlan* csep = new CalpontSelectExecutionPlan();
csep->sessionID(fParentGwip->sessionid);
// gwi for the sub query
gp_walk_info gwi;
gwi.thd = fParentGwip->thd;
// gwi for the sub query
gp_walk_info gwi;
gwi.thd = fParentGwip->thd;
uint32_t sessionID = csep->sessionID();
gwi.sessionid = sessionID;
boost::shared_ptr<CalpontSystemCatalog> csc = CalpontSystemCatalog::makeCalpontSystemCatalog(sessionID);
csc->identity(CalpontSystemCatalog::FE);
gwi.csc = csc;
uint32_t sessionID = csep->sessionID();
gwi.sessionid = sessionID;
boost::shared_ptr<CalpontSystemCatalog> csc = CalpontSystemCatalog::makeCalpontSystemCatalog(sessionID);
csc->identity(CalpontSystemCatalog::FE);
gwi.csc = csc;
// traverse the table list of the view
TABLE_LIST* table_ptr = fSelect.get_table_list();
CalpontSelectExecutionPlan::SelectList derivedTbList;
// traverse the table list of the view
TABLE_LIST* table_ptr = fSelect.get_table_list();
CalpontSelectExecutionPlan::SelectList derivedTbList;
// @bug 1796. Remember table order on the FROM list.
gwi.clauseType = FROM;
try {
for (; table_ptr; table_ptr= table_ptr->next_local)
{
// mysql put vtable here for from sub. we ignore it
if (string(table_ptr->table_name).find("$vtable") != string::npos)
continue;
// @bug 1796. Remember table order on the FROM list.
gwi.clauseType = FROM;
string viewName = getViewName(table_ptr);
try
{
for (; table_ptr; table_ptr = table_ptr->next_local)
{
// mysql put vtable here for from sub. we ignore it
if (string(table_ptr->table_name).find("$vtable") != string::npos)
continue;
if (table_ptr->derived)
{
SELECT_LEX *select_cursor = table_ptr->derived->first_select();
FromSubQuery *fromSub = new FromSubQuery(gwi, select_cursor);
string alias(table_ptr->alias);
gwi.viewName = make_aliasview("", alias, table_ptr->belong_to_view->alias, "");
algorithm::to_lower(alias);
fromSub->alias(alias);
gwi.derivedTbList.push_back(SCSEP(fromSub->transform()));
// set alias to both table name and alias name of the derived table
CalpontSystemCatalog::TableAliasName tn = make_aliasview("", "", alias, viewName);
gwi.tbList.push_back(tn);
gwi.tableMap[tn] = make_pair(0, table_ptr);
gwi.thd->infinidb_vtable.isUnion = true; //by-pass the 2nd pass of rnd_init
}
else if (table_ptr->view)
{
// for nested view, the view name is vout.vin... format
CalpontSystemCatalog::TableAliasName tn = make_aliasview(table_ptr->db, table_ptr->table_name, table_ptr->alias, viewName);
gwi.viewName = make_aliastable(table_ptr->db, table_ptr->table_name, viewName);
View *view = new View(table_ptr->view->select_lex, &gwi);
view->viewName(gwi.viewName);
gwi.viewList.push_back(view);
view->transform();
}
else
{
// check foreign engine tables
bool infiniDB = (table_ptr->table ? isInfiniDB(table_ptr->table) : true);
string viewName = getViewName(table_ptr);
// trigger system catalog cache
if (infiniDB)
csc->columnRIDs(make_table(table_ptr->db, table_ptr->table_name), true);
if (table_ptr->derived)
{
SELECT_LEX* select_cursor = table_ptr->derived->first_select();
FromSubQuery* fromSub = new FromSubQuery(gwi, select_cursor);
string alias(table_ptr->alias);
gwi.viewName = make_aliasview("", alias, table_ptr->belong_to_view->alias, "");
algorithm::to_lower(alias);
fromSub->alias(alias);
gwi.derivedTbList.push_back(SCSEP(fromSub->transform()));
// set alias to both table name and alias name of the derived table
CalpontSystemCatalog::TableAliasName tn = make_aliasview("", "", alias, viewName);
gwi.tbList.push_back(tn);
gwi.tableMap[tn] = make_pair(0, table_ptr);
gwi.thd->infinidb_vtable.isUnion = true; //by-pass the 2nd pass of rnd_init
}
else if (table_ptr->view)
{
// for nested view, the view name is vout.vin... format
CalpontSystemCatalog::TableAliasName tn = make_aliasview(table_ptr->db, table_ptr->table_name, table_ptr->alias, viewName);
gwi.viewName = make_aliastable(table_ptr->db, table_ptr->table_name, viewName);
View* view = new View(table_ptr->view->select_lex, &gwi);
view->viewName(gwi.viewName);
gwi.viewList.push_back(view);
view->transform();
}
else
{
// check foreign engine tables
bool infiniDB = (table_ptr->table ? isInfiniDB(table_ptr->table) : true);
CalpontSystemCatalog::TableAliasName tn = make_aliasview(table_ptr->db, table_ptr->table_name, table_ptr->alias, viewName, infiniDB);
gwi.tbList.push_back(tn);
gwi.tableMap[tn] = make_pair(0, table_ptr);
fParentGwip->tableMap[tn] = make_pair(0, table_ptr);
}
}
if (gwi.fatalParseError)
{
setError(gwi.thd, ER_INTERNAL_ERROR, gwi.parseErrorText);
return;
}
}
catch (IDBExcept& ie)
{
setError(gwi.thd, ER_INTERNAL_ERROR, ie.what());
CalpontSystemCatalog::removeCalpontSystemCatalog(sessionID);
return;
}
catch (...)
{
string emsg = IDBErrorInfo::instance()->errorMsg(ERR_LOST_CONN_EXEMGR);
setError(gwi.thd, ER_INTERNAL_ERROR, emsg);
CalpontSystemCatalog::removeCalpontSystemCatalog(sessionID);
return;
}
// trigger system catalog cache
if (infiniDB)
csc->columnRIDs(make_table(table_ptr->db, table_ptr->table_name), true);
// merge table list to parent select
fParentGwip->tbList.insert(fParentGwip->tbList.end(), gwi.tbList.begin(), gwi.tbList.end());
fParentGwip->derivedTbList.insert(fParentGwip->derivedTbList.end(), gwi.derivedTbList.begin(), gwi.derivedTbList.end());
fParentGwip->correlatedTbNameVec.insert(fParentGwip->correlatedTbNameVec.end(), gwi.correlatedTbNameVec.begin(), gwi.correlatedTbNameVec.end());
CalpontSystemCatalog::TableAliasName tn = make_aliasview(table_ptr->db, table_ptr->table_name, table_ptr->alias, viewName, infiniDB);
gwi.tbList.push_back(tn);
gwi.tableMap[tn] = make_pair(0, table_ptr);
fParentGwip->tableMap[tn] = make_pair(0, table_ptr);
}
}
// merge view list to parent
fParentGwip->viewList.insert(fParentGwip->viewList.end(), gwi.viewList.begin(), gwi.viewList.end());
if (gwi.fatalParseError)
{
setError(gwi.thd, ER_INTERNAL_ERROR, gwi.parseErrorText);
return;
}
}
catch (IDBExcept& ie)
{
setError(gwi.thd, ER_INTERNAL_ERROR, ie.what());
CalpontSystemCatalog::removeCalpontSystemCatalog(sessionID);
return;
}
catch (...)
{
string emsg = IDBErrorInfo::instance()->errorMsg(ERR_LOST_CONN_EXEMGR);
setError(gwi.thd, ER_INTERNAL_ERROR, emsg);
CalpontSystemCatalog::removeCalpontSystemCatalog(sessionID);
return;
}
// merge non-collapsed outer join to parent select
stack<ParseTree*> tmpstack;
while (!gwi.ptWorkStack.empty())
{
tmpstack.push(gwi.ptWorkStack.top());
gwi.ptWorkStack.pop();
}
// merge table list to parent select
fParentGwip->tbList.insert(fParentGwip->tbList.end(), gwi.tbList.begin(), gwi.tbList.end());
fParentGwip->derivedTbList.insert(fParentGwip->derivedTbList.end(), gwi.derivedTbList.begin(), gwi.derivedTbList.end());
fParentGwip->correlatedTbNameVec.insert(fParentGwip->correlatedTbNameVec.end(), gwi.correlatedTbNameVec.begin(), gwi.correlatedTbNameVec.end());
while (!tmpstack.empty())
{
fParentGwip->ptWorkStack.push(tmpstack.top());
tmpstack.pop();
}
// merge view list to parent
fParentGwip->viewList.insert(fParentGwip->viewList.end(), gwi.viewList.begin(), gwi.viewList.end());
// merge non-collapsed outer join to parent select
stack<ParseTree*> tmpstack;
while (!gwi.ptWorkStack.empty())
{
tmpstack.push(gwi.ptWorkStack.top());
gwi.ptWorkStack.pop();
}
while (!tmpstack.empty())
{
fParentGwip->ptWorkStack.push(tmpstack.top());
tmpstack.pop();
}
}
uint32_t View::processOuterJoin(gp_walk_info& gwi)
{
return buildOuterJoin(gwi, fSelect);
return buildOuterJoin(gwi, fSelect);
}
}

View File

@@ -32,7 +32,7 @@
namespace execplan
{
class CalpontSystemCatalog;
class CalpontSystemCatalog;
}
namespace cal_impl_if
@@ -41,24 +41,24 @@ namespace cal_impl_if
class View
{
public:
View(SELECT_LEX& select, gp_walk_info* parentGwip) :
fSelect(select),
fParentGwip(parentGwip) {}
~View() {}
View(SELECT_LEX& select, gp_walk_info* parentGwip) :
fSelect(select),
fParentGwip(parentGwip) {}
~View() {}
execplan::CalpontSystemCatalog::TableAliasName& viewName();
void viewName(execplan::CalpontSystemCatalog::TableAliasName& viewName);
execplan::CalpontSystemCatalog::TableAliasName& viewName();
void viewName(execplan::CalpontSystemCatalog::TableAliasName& viewName);
/** get execution plan for this view. merge the table list and join list to the
parent select.
*/
void transform();
uint32_t processOuterJoin(gp_walk_info& gwi);
/** get execution plan for this view. merge the table list and join list to the
parent select.
*/
void transform();
uint32_t processOuterJoin(gp_walk_info& gwi);
private:
SELECT_LEX fSelect;
gp_walk_info* fParentGwip;
execplan::CalpontSystemCatalog::TableAliasName fViewName;
SELECT_LEX fSelect;
gp_walk_info* fParentGwip;
execplan::CalpontSystemCatalog::TableAliasName fViewName;
};
}

1393
dbcon/mysql/ha_window_function.cpp Executable file → Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -95,13 +95,14 @@ template <class T> bool isnan(T);
#undef DEBUG
#undef set_bits
namespace {
namespace
{
inline char* idb_mysql_query_str(THD* thd)
{
#if MYSQL_VERSION_ID >= 50172
return thd->query();
return thd->query();
#else
return thd->query;
return thd->query;
#endif
}
}

View File

@@ -30,7 +30,7 @@
// Required declaration as it isn't in a MairaDB include
bool schema_table_store_record(THD *thd, TABLE *table);
bool schema_table_store_record(THD* thd, TABLE* table);
ST_FIELD_INFO is_columnstore_columns_fields[] =
{
@@ -54,10 +54,10 @@ ST_FIELD_INFO is_columnstore_columns_fields[] =
};
static int is_columnstore_columns_fill(THD *thd, TABLE_LIST *tables, COND *cond)
static int is_columnstore_columns_fill(THD* thd, TABLE_LIST* tables, COND* cond)
{
CHARSET_INFO *cs = system_charset_info;
TABLE *table = tables->table;
CHARSET_INFO* cs = system_charset_info;
TABLE* table = tables->table;
boost::shared_ptr<execplan::CalpontSystemCatalog> systemCatalogPtr =
execplan::CalpontSystemCatalog::makeCalpontSystemCatalog(execplan::CalpontSystemCatalog::idb_tid2sid(thd->thread_id));
@@ -68,84 +68,97 @@ static int is_columnstore_columns_fill(THD *thd, TABLE_LIST *tables, COND *cond)
systemCatalogPtr->identity(execplan::CalpontSystemCatalog::FE);
for (std::vector<std::pair<execplan::CalpontSystemCatalog::OID, execplan::CalpontSystemCatalog::TableName> >::const_iterator it = catalog_tables.begin();
it != catalog_tables.end(); ++it)
it != catalog_tables.end(); ++it)
{
execplan::CalpontSystemCatalog::RIDList column_rid_list = systemCatalogPtr->columnRIDs((*it).second, true);
for (size_t col_num = 0; col_num < column_rid_list.size(); col_num++)
{
execplan::CalpontSystemCatalog::TableColName tcn = systemCatalogPtr->colName(column_rid_list[col_num].objnum);
execplan::CalpontSystemCatalog::ColType ct = systemCatalogPtr->colType(column_rid_list[col_num].objnum);
table->field[0]->store(tcn.schema.c_str(), tcn.schema.length(), cs);
table->field[1]->store(tcn.table.c_str(), tcn.table.length(), cs);
table->field[2]->store(tcn.column.c_str(), tcn.column.length(), cs);
table->field[3]->store(column_rid_list[col_num].objnum);
if (ct.ddn.dictOID == std::numeric_limits<int32_t>::min())
{
table->field[4]->set_null();
}
else
{
table->field[4]->set_notnull();
table->field[4]->store(ct.ddn.dictOID);
}
if (ct.ddn.listOID == std::numeric_limits<int32_t>::min())
{
table->field[5]->set_null();
}
else
{
table->field[5]->set_notnull();
table->field[5]->store(ct.ddn.listOID);
}
if (ct.ddn.treeOID == std::numeric_limits<int32_t>::min())
{
table->field[6]->set_null();
}
else
{
table->field[6]->set_notnull();
table->field[6]->store(ct.ddn.treeOID);
}
std::string data_type = execplan::colDataTypeToString(ct.colDataType);
table->field[7]->store(data_type.c_str(), data_type.length(), cs);
table->field[8]->store(ct.colWidth);
table->field[9]->store(ct.colPosition);
if (ct.defaultValue.empty())
{
table->field[10]->set_null();
}
else
{
table->field[10]->set_notnull();
table->field[10]->store(ct.defaultValue.c_str(), ct.defaultValue.length(), cs);
}
table->field[11]->store(ct.autoincrement);
table->field[12]->store(ct.precision);
table->field[13]->store(ct.scale);
if (ct.constraintType != execplan::CalpontSystemCatalog::NOTNULL_CONSTRAINT)
{
table->field[14]->store(true);
}
else
{
table->field[14]->store(false);
}
table->field[0]->store(tcn.schema.c_str(), tcn.schema.length(), cs);
table->field[1]->store(tcn.table.c_str(), tcn.table.length(), cs);
table->field[2]->store(tcn.column.c_str(), tcn.column.length(), cs);
table->field[3]->store(column_rid_list[col_num].objnum);
if (ct.ddn.dictOID == std::numeric_limits<int32_t>::min())
{
table->field[4]->set_null();
}
else
{
table->field[4]->set_notnull();
table->field[4]->store(ct.ddn.dictOID);
}
if (ct.ddn.listOID == std::numeric_limits<int32_t>::min())
{
table->field[5]->set_null();
}
else
{
table->field[5]->set_notnull();
table->field[5]->store(ct.ddn.listOID);
}
if (ct.ddn.treeOID == std::numeric_limits<int32_t>::min())
{
table->field[6]->set_null();
}
else
{
table->field[6]->set_notnull();
table->field[6]->store(ct.ddn.treeOID);
}
std::string data_type = execplan::colDataTypeToString(ct.colDataType);
table->field[7]->store(data_type.c_str(), data_type.length(), cs);
table->field[8]->store(ct.colWidth);
table->field[9]->store(ct.colPosition);
if (ct.defaultValue.empty())
{
table->field[10]->set_null();
}
else
{
table->field[10]->set_notnull();
table->field[10]->store(ct.defaultValue.c_str(), ct.defaultValue.length(), cs);
}
table->field[11]->store(ct.autoincrement);
table->field[12]->store(ct.precision);
table->field[13]->store(ct.scale);
if (ct.constraintType != execplan::CalpontSystemCatalog::NOTNULL_CONSTRAINT)
{
table->field[14]->store(true);
}
else
{
table->field[14]->store(false);
}
std::string compression_type;
switch (ct.compressionType)
{
case 0:
compression_type = "None";
break;
case 2:
compression_type = "Snappy";
break;
default:
compression_type = "Unknown";
break;
}
table->field[15]->store(compression_type.c_str(), compression_type.length(), cs);
std::string compression_type;
switch (ct.compressionType)
{
case 0:
compression_type = "None";
break;
case 2:
compression_type = "Snappy";
break;
default:
compression_type = "Unknown";
break;
}
table->field[15]->store(compression_type.c_str(), compression_type.length(), cs);
if (schema_table_store_record(thd, table))
return 1;
}
@@ -156,9 +169,9 @@ static int is_columnstore_columns_fill(THD *thd, TABLE_LIST *tables, COND *cond)
return 0;
}
static int is_columnstore_columns_plugin_init(void *p)
static int is_columnstore_columns_plugin_init(void* p)
{
ST_SCHEMA_TABLE *schema = (ST_SCHEMA_TABLE*) p;
ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
schema->fields_info = is_columnstore_columns_fields;
schema->fill_table = is_columnstore_columns_fill;
return 0;

View File

@@ -29,7 +29,7 @@
// Required declaration as it isn't in a MairaDB include
bool schema_table_store_record(THD *thd, TABLE *table);
bool schema_table_store_record(THD* thd, TABLE* table);
ST_FIELD_INFO is_columnstore_extents_fields[] =
{
@@ -52,15 +52,16 @@ ST_FIELD_INFO is_columnstore_extents_fields[] =
{0, 0, MYSQL_TYPE_NULL, 0, 0, 0, 0}
};
static int is_columnstore_extents_fill(THD *thd, TABLE_LIST *tables, COND *cond)
static int is_columnstore_extents_fill(THD* thd, TABLE_LIST* tables, COND* cond)
{
CHARSET_INFO *cs = system_charset_info;
TABLE *table = tables->table;
CHARSET_INFO* cs = system_charset_info;
TABLE* table = tables->table;
std::vector<struct BRM::EMEntry> entries;
std::vector<struct BRM::EMEntry>::iterator iter;
std::vector<struct BRM::EMEntry>::iterator end;
std::vector<struct BRM::EMEntry>::iterator iter;
std::vector<struct BRM::EMEntry>::iterator end;
BRM::DBRM* emp = new BRM::DBRM();
BRM::DBRM *emp = new BRM::DBRM();
if (!emp || !emp->isDBRMReady())
{
return 1;
@@ -69,40 +70,46 @@ static int is_columnstore_extents_fill(THD *thd, TABLE_LIST *tables, COND *cond)
execplan::ObjectIDManager oidm;
BRM::OID_t MaxOID = oidm.size();
for(BRM::OID_t oid = 3000; oid <= MaxOID; oid++)
for (BRM::OID_t oid = 3000; oid <= MaxOID; oid++)
{
emp->getExtents(oid, entries, false, false, true);
if (entries.size() == 0)
continue;
iter = entries.begin();
end = entries.end();
while (iter != end)
{
table->field[0]->store(oid);
if (iter->colWid > 0)
{
table->field[1]->store("Column", strlen("Column"), cs);
if (iter->partition.cprange.lo_val == std::numeric_limits<int64_t>::max() ||
iter->partition.cprange.lo_val <= (std::numeric_limits<int64_t>::min() + 2))
{
table->field[4]->set_null();
}
else
{
table->field[4]->set_notnull();
iter->partition.cprange.lo_val <= (std::numeric_limits<int64_t>::min() + 2))
{
table->field[4]->set_null();
}
else
{
table->field[4]->set_notnull();
table->field[4]->store(iter->partition.cprange.lo_val);
}
if (iter->partition.cprange.hi_val == std::numeric_limits<int64_t>::max() ||
iter->partition.cprange.hi_val <= (std::numeric_limits<int64_t>::min() + 2))
{
table->field[5]->set_null();
}
else
{
iter->partition.cprange.hi_val <= (std::numeric_limits<int64_t>::min() + 2))
{
table->field[5]->set_null();
}
else
{
table->field[5]->set_notnull();
table->field[5]->store(iter->partition.cprange.hi_val);
}
table->field[6]->store(iter->colWid);
}
@@ -113,6 +120,7 @@ static int is_columnstore_extents_fill(THD *thd, TABLE_LIST *tables, COND *cond)
table->field[5]->set_null();
table->field[6]->store(8192);
}
table->field[2]->store(iter->range.start);
table->field[3]->store(iter->range.start + (iter->range.size * 1024) - 1);
@@ -128,30 +136,38 @@ static int is_columnstore_extents_fill(THD *thd, TABLE_LIST *tables, COND *cond)
case 0:
table->field[13]->store("Invalid", strlen("Invalid"), cs);
break;
case 1:
table->field[13]->store("Updating", strlen("Updating"), cs);
break;
case 2:
table->field[13]->store("Valid", strlen("Valid"), cs);
break;
default:
table->field[13]->store("Unknown", strlen("Unknown"), cs);
break;
}
switch (iter->status)
{
case BRM::EXTENTAVAILABLE:
table->field[14]->store("Available", strlen("Available"), cs);
break;
case BRM::EXTENTUNAVAILABLE:
table->field[14]->store("Unavailable", strlen("Unavailable"), cs);
break;
case BRM::EXTENTOUTOFSERVICE:
table->field[14]->store("Out of service", strlen("Out of service"), cs);
break;
default:
table->field[14]->store("Unknown", strlen("Unknown"), cs);
}
// MCOL-454: special case, sometimes blockOffset can be > 0 and HWM can be 0
if (iter->HWM == 0)
{
@@ -177,9 +193,9 @@ static int is_columnstore_extents_fill(THD *thd, TABLE_LIST *tables, COND *cond)
return 0;
}
static int is_columnstore_extents_plugin_init(void *p)
static int is_columnstore_extents_plugin_init(void* p)
{
ST_SCHEMA_TABLE *schema = (ST_SCHEMA_TABLE*) p;
ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
schema->fields_info = is_columnstore_extents_fields;
schema->fill_table = is_columnstore_extents_fill;
return 0;

View File

@@ -37,7 +37,7 @@
#include "we_messages.h"
// Required declaration as it isn't in a MairaDB include
bool schema_table_store_record(THD *thd, TABLE *table);
bool schema_table_store_record(THD* thd, TABLE* table);
ST_FIELD_INFO is_columnstore_files_fields[] =
{
@@ -50,7 +50,7 @@ ST_FIELD_INFO is_columnstore_files_fields[] =
{0, 0, MYSQL_TYPE_NULL, 0, 0, 0, 0}
};
static bool get_file_sizes(messageqcpp::MessageQueueClient *msgQueueClient, const char *fileName, off_t *fileSize, off_t *compressedFileSize)
static bool get_file_sizes(messageqcpp::MessageQueueClient* msgQueueClient, const char* fileName, off_t* fileSize, off_t* compressedFileSize)
{
messageqcpp::ByteStream bs;
messageqcpp::ByteStream::byte rc;
@@ -65,11 +65,13 @@ static bool get_file_sizes(messageqcpp::MessageQueueClient *msgQueueClient, cons
// namespace??
messageqcpp::SBS sbs;
sbs = msgQueueClient->read();
if (sbs->length() == 0)
{
delete msgQueueClient;
return false;
}
*sbs >> rc;
*sbs >> errMsg;
*sbs >> *fileSize;
@@ -82,22 +84,22 @@ static bool get_file_sizes(messageqcpp::MessageQueueClient *msgQueueClient, cons
}
}
static int is_columnstore_files_fill(THD *thd, TABLE_LIST *tables, COND *cond)
static int is_columnstore_files_fill(THD* thd, TABLE_LIST* tables, COND* cond)
{
BRM::DBRM *emp = new BRM::DBRM();
BRM::DBRM* emp = new BRM::DBRM();
std::vector<struct BRM::EMEntry> entries;
CHARSET_INFO *cs = system_charset_info;
TABLE *table = tables->table;
CHARSET_INFO* cs = system_charset_info;
TABLE* table = tables->table;
char oidDirName[WriteEngine::FILE_NAME_SIZE];
char fullFileName[WriteEngine::FILE_NAME_SIZE];
char fullFileName[WriteEngine::FILE_NAME_SIZE];
char dbDir[WriteEngine::MAX_DB_DIR_LEVEL][WriteEngine::MAX_DB_DIR_NAME_SIZE];
config::Config* config = config::Config::makeConfig();
WriteEngine::Config we_config;
off_t fileSize = 0;
off_t compressedFileSize = 0;
we_config.initConfigCache();
messageqcpp::MessageQueueClient *msgQueueClient;
messageqcpp::MessageQueueClient* msgQueueClient;
oam::Oam oam_instance;
int pmId = 0;
@@ -109,13 +111,15 @@ static int is_columnstore_files_fill(THD *thd, TABLE_LIST *tables, COND *cond)
execplan::ObjectIDManager oidm;
BRM::OID_t MaxOID = oidm.size();
for(BRM::OID_t oid = 3000; oid <= MaxOID; oid++)
for (BRM::OID_t oid = 3000; oid <= MaxOID; oid++)
{
emp->getExtents(oid, entries, false, false, true);
if (entries.size() == 0)
continue;
std::vector<struct BRM::EMEntry>::const_iterator iter = entries.begin();
while ( iter != entries.end() ) //organize extents into files
{
// Don't include files more than once at different block offsets
@@ -124,6 +128,7 @@ static int is_columnstore_files_fill(THD *thd, TABLE_LIST *tables, COND *cond)
iter++;
continue;
}
table->field[0]->store(oid);
table->field[1]->store(iter->segmentNum);
table->field[2]->store(iter->partitionNum);
@@ -139,19 +144,21 @@ static int is_columnstore_files_fill(THD *thd, TABLE_LIST *tables, COND *cond)
oss << "pm" << pmId << "_WriteEngineServer";
std::string client = oss.str();
msgQueueClient = messageqcpp::MessageQueueClientPool::getInstance(oss.str());
if (!get_file_sizes(msgQueueClient, fullFileName, &fileSize, &compressedFileSize))
{
messageqcpp::MessageQueueClientPool::releaseInstance(msgQueueClient);
delete emp;
return 1;
}
table->field[3]->store(fullFileName, strlen(fullFileName), cs);
if (fileSize > 0)
{
table->field[4]->set_notnull();
table->field[4]->store(fileSize);
if (compressedFileSize > 0)
{
table->field[5]->set_notnull();
@@ -174,18 +181,20 @@ static int is_columnstore_files_fill(THD *thd, TABLE_LIST *tables, COND *cond)
delete emp;
return 1;
}
iter++;
messageqcpp::MessageQueueClientPool::releaseInstance(msgQueueClient);
msgQueueClient = NULL;
}
}
delete emp;
return 0;
}
static int is_columnstore_files_plugin_init(void *p)
static int is_columnstore_files_plugin_init(void* p)
{
ST_SCHEMA_TABLE *schema = (ST_SCHEMA_TABLE*) p;
ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
schema->fields_info = is_columnstore_files_fields;
schema->fill_table = is_columnstore_files_fill;
return 0;

View File

@@ -29,7 +29,7 @@
// Required declaration as it isn't in a MairaDB include
bool schema_table_store_record(THD *thd, TABLE *table);
bool schema_table_store_record(THD* thd, TABLE* table);
ST_FIELD_INFO is_columnstore_tables_fields[] =
{
@@ -42,10 +42,10 @@ ST_FIELD_INFO is_columnstore_tables_fields[] =
{0, 0, MYSQL_TYPE_NULL, 0, 0, 0, 0}
};
static int is_columnstore_tables_fill(THD *thd, TABLE_LIST *tables, COND *cond)
static int is_columnstore_tables_fill(THD* thd, TABLE_LIST* tables, COND* cond)
{
CHARSET_INFO *cs = system_charset_info;
TABLE *table = tables->table;
CHARSET_INFO* cs = system_charset_info;
TABLE* table = tables->table;
boost::shared_ptr<execplan::CalpontSystemCatalog> systemCatalogPtr =
execplan::CalpontSystemCatalog::makeCalpontSystemCatalog(execplan::CalpontSystemCatalog::idb_tid2sid(thd->thread_id));
@@ -56,7 +56,7 @@ static int is_columnstore_tables_fill(THD *thd, TABLE_LIST *tables, COND *cond)
= systemCatalogPtr->getTables();
for (std::vector<std::pair<execplan::CalpontSystemCatalog::OID, execplan::CalpontSystemCatalog::TableName> >::const_iterator it = catalog_tables.begin();
it != catalog_tables.end(); ++it)
it != catalog_tables.end(); ++it)
{
execplan::CalpontSystemCatalog::TableInfo tb_info = systemCatalogPtr->tableInfo((*it).second);
std::string create_date = dataconvert::DataConvert::dateToString((*it).second.create_date);
@@ -65,6 +65,7 @@ static int is_columnstore_tables_fill(THD *thd, TABLE_LIST *tables, COND *cond)
table->field[2]->store((*it).first);
table->field[3]->store(create_date.c_str(), create_date.length(), cs);
table->field[4]->store(tb_info.numOfCols);
if (tb_info.tablewithautoincr)
{
table->field[5]->set_notnull();
@@ -74,7 +75,9 @@ static int is_columnstore_tables_fill(THD *thd, TABLE_LIST *tables, COND *cond)
{
table->field[5]->set_null();
}
table->field[5]->store(tb_info.tablewithautoincr);
if (schema_table_store_record(thd, table))
return 1;
}
@@ -82,9 +85,9 @@ static int is_columnstore_tables_fill(THD *thd, TABLE_LIST *tables, COND *cond)
return 0;
}
static int is_columnstore_tables_plugin_init(void *p)
static int is_columnstore_tables_plugin_init(void* p)
{
ST_SCHEMA_TABLE *schema = (ST_SCHEMA_TABLE*) p;
ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
schema->fields_info = is_columnstore_tables_fields;
schema->fill_table = is_columnstore_tables_fill;
return 0;

View File

@@ -1,14 +1,14 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by libcalmysql.rc
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by libcalmysql.rc
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@@ -53,195 +53,215 @@ using namespace querystats;
#include "sm.h"
namespace {
namespace
{
using namespace sm;
// @bug 159 fix. clean up routine when error happened
void cleanup(cpsm_conhdl_t* hndl)
{
// remove system catalog instance for this statement.
CalpontSystemCatalog::removeCalpontSystemCatalog(hndl->sessionID);
hndl->queryState = NO_QUERY;
hndl->resultSet.erase(hndl->resultSet.begin(), hndl->resultSet.end());
// remove system catalog instance for this statement.
CalpontSystemCatalog::removeCalpontSystemCatalog(hndl->sessionID);
hndl->queryState = NO_QUERY;
hndl->resultSet.erase(hndl->resultSet.begin(), hndl->resultSet.end());
}
status_t tpl_scan_fetch_getband(cpsm_conhdl_t* hndl, sp_cpsm_tplsch_t& ntplsch, int* killed)
{
// @bug 649 check keybandmap first
map<int, int>::iterator keyBandMapIter = hndl->keyBandMap.find(ntplsch->key);
// @bug 649 check keybandmap first
map<int, int>::iterator keyBandMapIter = hndl->keyBandMap.find(ntplsch->key);
try {
if (keyBandMapIter != hndl->keyBandMap.end())
{
ByteStream bs;
ostringstream oss;
oss << DEFAULT_SAVE_PATH << '/' << hndl->sessionID << '/' << ntplsch->key << '_' << ntplsch->bandID << ".band";
ifstream bandFile (oss.str().c_str(), ios::in);
bandFile >> bs;
unlink (oss.str().c_str());
try
{
if (keyBandMapIter != hndl->keyBandMap.end())
{
ByteStream bs;
ostringstream oss;
oss << DEFAULT_SAVE_PATH << '/' << hndl->sessionID << '/' << ntplsch->key << '_' << ntplsch->bandID << ".band";
ifstream bandFile (oss.str().c_str(), ios::in);
bandFile >> bs;
unlink (oss.str().c_str());
// not possible for vtable
ntplsch->deserializeTable(bs);
ntplsch->bandID++;
// not possible for vtable
ntplsch->deserializeTable(bs);
ntplsch->bandID++;
// end of result set
if (ntplsch->bandID == keyBandMapIter->second)
{
hndl->keyBandMap.erase(keyBandMapIter);
return SQL_NOT_FOUND;
}
}
else
{
ByteStream bs;
// @bug 626. check saveFlag. If SAVING, read band from socket and save to disk
if (ntplsch->saveFlag == SAVING)
{
ByteStream bs;
// @bug 2244. Bypass ClientRotator::read() because if I/O error occurs, it tries
// to reestablish a connection with ExeMgr which ends up causing mysql
// session to hang.
bs = hndl->exeMgr->read();
ostringstream oss;
oss << DEFAULT_SAVE_PATH << '/' << hndl->sessionID << '/' << ntplsch->tableid << '_' << ntplsch->bandsReturned << ".band";
ofstream saveFile (oss.str().c_str(), ios::out);
saveFile << bs;
saveFile.close();
ntplsch->bandsReturned++;
// not possible for vtable
ntplsch->deserializeTable(bs);
}
// if SAVED, read from saved file. not possible for vtable
else if (ntplsch->saveFlag == SAVED)
{
ostringstream oss;
oss << DEFAULT_SAVE_PATH << '/' << hndl->sessionID << '/' << ntplsch->tableid << '_' << ntplsch->bandsReturned << ".band";
ifstream saveFile (oss.str().c_str(), ios::in);
saveFile >> bs;
saveFile.close();
ntplsch->bandsReturned++;
ntplsch->deserializeTable(bs);
}
// most normal path. also the path for vtable
else
{
ntplsch->bs.restart();
// @bug 2244. Bypass ClientRotator::read() because if I/O error occurs, it tries
// to reestablish a connection with ExeMgr which ends up causing mysql
// session to hang.
// @bug 3386. need to abort the query when user does ctrl+c
timespec t;
t.tv_sec = 5L;
t.tv_nsec = 0L;
if (killed && *killed)
return SQL_KILLED;
ntplsch->bs = hndl->exeMgr->read();
// end of result set
if (ntplsch->bandID == keyBandMapIter->second)
{
hndl->keyBandMap.erase(keyBandMapIter);
return SQL_NOT_FOUND;
}
}
else
{
ByteStream bs;
if (ntplsch->bs.length() != 0)
{
ntplsch->deserializeTable(ntplsch->bs);
if (ntplsch->rowGroup && ntplsch->rowGroup->getRGData() == NULL)
{
ntplsch->bs.restart();
// @bug 2244. Bypass ClientRotator::read() because if I/O error occurs, it tries
// to reestablish a connection with ExeMgr which ends up causing mysql
// session to hang.
bool timeout = true;
while (timeout)
{
timeout = false;
ntplsch->bs = hndl->exeMgr->getClient()->read(&t, &timeout);
// @bug 626. check saveFlag. If SAVING, read band from socket and save to disk
if (ntplsch->saveFlag == SAVING)
{
ByteStream bs;
// @bug 2244. Bypass ClientRotator::read() because if I/O error occurs, it tries
// to reestablish a connection with ExeMgr which ends up causing mysql
// session to hang.
bs = hndl->exeMgr->read();
ostringstream oss;
oss << DEFAULT_SAVE_PATH << '/' << hndl->sessionID << '/' << ntplsch->tableid << '_' << ntplsch->bandsReturned << ".band";
ofstream saveFile (oss.str().c_str(), ios::out);
saveFile << bs;
saveFile.close();
ntplsch->bandsReturned++;
// not possible for vtable
ntplsch->deserializeTable(bs);
}
// if SAVED, read from saved file. not possible for vtable
else if (ntplsch->saveFlag == SAVED)
{
ostringstream oss;
oss << DEFAULT_SAVE_PATH << '/' << hndl->sessionID << '/' << ntplsch->tableid << '_' << ntplsch->bandsReturned << ".band";
ifstream saveFile (oss.str().c_str(), ios::in);
saveFile >> bs;
saveFile.close();
ntplsch->bandsReturned++;
ntplsch->deserializeTable(bs);
}
// most normal path. also the path for vtable
else
{
ntplsch->bs.restart();
// @bug 2244. Bypass ClientRotator::read() because if I/O error occurs, it tries
// to reestablish a connection with ExeMgr which ends up causing mysql
// session to hang.
// @bug 3386. need to abort the query when user does ctrl+c
timespec t;
t.tv_sec = 5L;
t.tv_nsec = 0L;
if (killed && *killed)
return SQL_KILLED;
}
if (killed && *killed)
return SQL_KILLED;
if (ntplsch->bs.length() == 0)
{
hndl->curFetchTb = 0;
return logging::ERR_LOST_CONN_EXEMGR;
}
ntplsch->deserializeTable(ntplsch->bs);
}
ntplsch->bs = hndl->exeMgr->read();
uint16_t error = ntplsch->getStatus();
if (0 != error)
{
ntplsch->setErrMsg();
return error;
}
}
else // @todo error handling
{
hndl->curFetchTb = 0;
if (ntplsch->saveFlag == NO_SAVE)
hndl->tidScanMap[ntplsch->tableid] = ntplsch;
ntplsch->errMsg = IDBErrorInfo::instance()->errorMsg(ERR_LOST_CONN_EXEMGR);
return logging::ERR_LOST_CONN_EXEMGR;
}
}
if (ntplsch->bs.length() != 0)
{
ntplsch->deserializeTable(ntplsch->bs);
// All done with this table. reset curFetchTb when finish SOCKET reading
if (ntplsch->getRowCount() == 0)
{
hndl->curFetchTb = 0;
if (ntplsch->saveFlag == NO_SAVE)
hndl->tidScanMap[ntplsch->tableid] = ntplsch;
return SQL_NOT_FOUND;
}
}
} catch (std::exception &e)
{
hndl->curFetchTb = 0;
if (ntplsch->saveFlag == NO_SAVE)
hndl->tidScanMap[ntplsch->tableid] = ntplsch;
ntplsch->errMsg = e.what();
return logging::ERR_LOST_CONN_EXEMGR;
}
ntplsch->rowsreturned = 0;
return STATUS_OK;
if (ntplsch->rowGroup && ntplsch->rowGroup->getRGData() == NULL)
{
ntplsch->bs.restart();
// @bug 2244. Bypass ClientRotator::read() because if I/O error occurs, it tries
// to reestablish a connection with ExeMgr which ends up causing mysql
// session to hang.
bool timeout = true;
while (timeout)
{
timeout = false;
ntplsch->bs = hndl->exeMgr->getClient()->read(&t, &timeout);
if (killed && *killed)
return SQL_KILLED;
}
if (ntplsch->bs.length() == 0)
{
hndl->curFetchTb = 0;
return logging::ERR_LOST_CONN_EXEMGR;
}
ntplsch->deserializeTable(ntplsch->bs);
}
uint16_t error = ntplsch->getStatus();
if (0 != error)
{
ntplsch->setErrMsg();
return error;
}
}
else // @todo error handling
{
hndl->curFetchTb = 0;
if (ntplsch->saveFlag == NO_SAVE)
hndl->tidScanMap[ntplsch->tableid] = ntplsch;
ntplsch->errMsg = IDBErrorInfo::instance()->errorMsg(ERR_LOST_CONN_EXEMGR);
return logging::ERR_LOST_CONN_EXEMGR;
}
}
// All done with this table. reset curFetchTb when finish SOCKET reading
if (ntplsch->getRowCount() == 0)
{
hndl->curFetchTb = 0;
if (ntplsch->saveFlag == NO_SAVE)
hndl->tidScanMap[ntplsch->tableid] = ntplsch;
return SQL_NOT_FOUND;
}
}
}
catch (std::exception& e)
{
hndl->curFetchTb = 0;
if (ntplsch->saveFlag == NO_SAVE)
hndl->tidScanMap[ntplsch->tableid] = ntplsch;
ntplsch->errMsg = e.what();
return logging::ERR_LOST_CONN_EXEMGR;
}
ntplsch->rowsreturned = 0;
return STATUS_OK;
}
void end_query(cpsm_conhdl_t* hndl)
{
// remove system catalog instance for this statement.
// @bug 695. turn on system catalog session cache for FE
// CalpontSystemCatalog::removeCalpontSystemCatalog(hndl->sessionID);
hndl->queryState = NO_QUERY;
// reset at the end of query
hndl->curFetchTb = 0;
// @bug 626 clear up
hndl->tidMap.clear();
hndl->tidScanMap.clear();
hndl->keyBandMap.clear();
// Tell ExeMgr we are done with this query
try {
ByteStream bs;
ByteStream::quadbyte qb = 0;
bs << qb;
hndl->write(bs);
}
catch(...)
{
throw;
}
// remove system catalog instance for this statement.
// @bug 695. turn on system catalog session cache for FE
// CalpontSystemCatalog::removeCalpontSystemCatalog(hndl->sessionID);
hndl->queryState = NO_QUERY;
// reset at the end of query
hndl->curFetchTb = 0;
// @bug 626 clear up
hndl->tidMap.clear();
hndl->tidScanMap.clear();
hndl->keyBandMap.clear();
// Tell ExeMgr we are done with this query
try
{
ByteStream bs;
ByteStream::quadbyte qb = 0;
bs << qb;
hndl->write(bs);
}
catch (...)
{
throw;
}
}
// @bug 1054, 863 - SIGPIPE handler
bool sigFlag = false;
void sighandler(int sig_num)
{
FILE* p;
char buf[1024];
FILE* p;
char buf[1024];
if ((p = fopen("/tmp/f1.dat", "a")) != NULL)
{
snprintf(buf, 1024, "sighandler() hit with %d\n", sig_num);
fwrite(buf, 1, strlen(buf), p);
fclose(p);
}
sigFlag = true;
throw runtime_error("zerror");
if ((p = fopen("/tmp/f1.dat", "a")) != NULL)
{
snprintf(buf, 1024, "sighandler() hit with %d\n", sig_num);
fwrite(buf, 1, strlen(buf), p);
fclose(p);
}
sigFlag = true;
throw runtime_error("zerror");
}
}
@@ -249,215 +269,231 @@ void sighandler(int sig_num)
namespace sm
{
#ifdef _MSC_VER
const std::string DEFAULT_SAVE_PATH = "C:\\Calpont\\tmp";
const std::string DEFAULT_SAVE_PATH = "C:\\Calpont\\tmp";
#else
const std::string DEFAULT_SAVE_PATH = "/var/tmp";
const std::string DEFAULT_SAVE_PATH = "/var/tmp";
#endif
status_t
tpl_open ( tableid_t tableid,
cpsm_tplh_t* ntplh,
cpsm_conhdl_t* conn_hdl)
cpsm_tplh_t* ntplh,
cpsm_conhdl_t* conn_hdl)
{
SMDEBUGLOG << "tpl_open: " << conn_hdl << " tableid: " << tableid << endl;
SMDEBUGLOG << "tpl_open: " << conn_hdl << " tableid: " << tableid << endl;
// if first time enter this function for a statement, set
// queryState to QUERY_IN_PRCOESS and get execution plan.
if (conn_hdl->queryState == NO_QUERY)
{
conn_hdl->queryState = QUERY_IN_PROCESS;
}
// if first time enter this function for a statement, set
// queryState to QUERY_IN_PRCOESS and get execution plan.
if (conn_hdl->queryState == NO_QUERY)
{
conn_hdl->queryState = QUERY_IN_PROCESS;
}
try {
// @bug 626. check saveFlag, if SAVED, do not project
if (ntplh->saveFlag != SAVED)
{
// Request ExeMgr to start projecting table tableid
CalpontSystemCatalog::OID tableOID = static_cast<CalpontSystemCatalog::OID>(tableid);
ByteStream::quadbyte qb = static_cast<ByteStream::quadbyte>(tableOID);
ByteStream bs;
bs << qb;
conn_hdl->write(bs);
}
}
catch (std::exception& ex)
{
SMDEBUGLOG << "Exception caught in tpl_open: " << ex.what() << endl;
cleanup(conn_hdl);
return CALPONT_INTERNAL_ERROR;
}
try
{
// @bug 626. check saveFlag, if SAVED, do not project
if (ntplh->saveFlag != SAVED)
{
// Request ExeMgr to start projecting table tableid
CalpontSystemCatalog::OID tableOID = static_cast<CalpontSystemCatalog::OID>(tableid);
ByteStream::quadbyte qb = static_cast<ByteStream::quadbyte>(tableOID);
ByteStream bs;
bs << qb;
conn_hdl->write(bs);
}
}
catch (std::exception& ex)
{
SMDEBUGLOG << "Exception caught in tpl_open: " << ex.what() << endl;
cleanup(conn_hdl);
return CALPONT_INTERNAL_ERROR;
}
ntplh->tableid = tableid;
ntplh->tableid = tableid;
return STATUS_OK;
return STATUS_OK;
}
status_t
tpl_scan_open ( tableid_t tableid,
sp_cpsm_tplsch_t& ntplsch,
cpsm_conhdl_t* conn_hdl )
sp_cpsm_tplsch_t& ntplsch,
cpsm_conhdl_t* conn_hdl )
{
SMDEBUGLOG << "tpl_scan_open: " << conn_hdl << " tableid: " << tableid << endl;
SMDEBUGLOG << "tpl_scan_open: " << conn_hdl << " tableid: " << tableid << endl;
// @bug 649. No initialization here. take passed in reference
ntplsch->tableid = tableid;
// @bug 649. No initialization here. take passed in reference
ntplsch->tableid = tableid;
ntplsch->rowsreturned = 0;
return STATUS_OK;
ntplsch->rowsreturned = 0;
return STATUS_OK;
}
status_t
tpl_scan_fetch ( sp_cpsm_tplsch_t& ntplsch,
cpsm_conhdl_t* conn_hdl,
int* killed )
cpsm_conhdl_t* conn_hdl,
int* killed )
{
// @770. force end of result set when this is not the first table to be fetched.
if (ntplsch->traceFlags & CalpontSelectExecutionPlan::TRACE_NO_ROWS2)
if (conn_hdl->tidScanMap.size() >= 1)
return SQL_NOT_FOUND;
// @770. force end of result set when this is not the first table to be fetched.
if (ntplsch->traceFlags & CalpontSelectExecutionPlan::TRACE_NO_ROWS2)
if (conn_hdl->tidScanMap.size() >= 1)
return SQL_NOT_FOUND;
// need another band
status_t status = STATUS_OK;
if (ntplsch->rowsreturned == ntplsch->getRowCount())
status = tpl_scan_fetch_getband(conn_hdl, ntplsch, killed);
// need another band
status_t status = STATUS_OK;
return status;
if (ntplsch->rowsreturned == ntplsch->getRowCount())
status = tpl_scan_fetch_getband(conn_hdl, ntplsch, killed);
return status;
}
status_t
tpl_scan_close ( sp_cpsm_tplsch_t& ntplsch )
{
#if IDB_SM_DEBUG
SMDEBUGLOG << "tpl_scan_close: ";
if (ntplsch)
SMDEBUGLOG << " tableid: " << ntplsch->tableid << endl;
#endif
ntplsch.reset();
SMDEBUGLOG << "tpl_scan_close: ";
return STATUS_OK;
if (ntplsch)
SMDEBUGLOG << " tableid: " << ntplsch->tableid << endl;
#endif
ntplsch.reset();
return STATUS_OK;
}
status_t
tpl_close ( cpsm_tplh_t* ntplh,
cpsm_conhdl_t** conn_hdl,
QueryStats& stats )
cpsm_conhdl_t** conn_hdl,
QueryStats& stats )
{
cpsm_conhdl_t* hndl = *conn_hdl;
cpsm_conhdl_t* hndl = *conn_hdl;
#if IDB_SM_DEBUG
SMDEBUGLOG << "tpl_close: " << hndl;
if (ntplh)
SMDEBUGLOG << " tableid: " << ntplh->tableid;
SMDEBUGLOG << endl;
#endif
delete ntplh;
SMDEBUGLOG << "tpl_close: " << hndl;
// determine end of result set and end of statement execution
if (hndl->queryState == QUERY_IN_PROCESS)
{
// Get the query stats
ByteStream bs;
ByteStream::quadbyte qb = 3;
bs << qb;
hndl->write(bs);
//keep reading until we get a string
//TODO: really need to fix this! Why is ExeMgr sending other stuff?
for (int tries = 0; tries < 10; tries++)
{
bs = hndl->exeMgr->read();
if (bs.length() == 0) break;
try {
bs >> hndl->queryStats;
bs >> hndl->extendedStats;
bs >> hndl->miniStats;
stats.unserialize(bs);
stats.setEndTime();
stats.insert();
break;
} catch (IDBExcept&)
{
// @bug4732
end_query(hndl);
throw;
}
catch (...) {
// querystats messed up. close connection.
// no need to throw for querystats protocol error, like for tablemode.
end_query(hndl);
sm_cleanup(hndl);
*conn_hdl = 0;
return STATUS_OK;
//throw runtime_error(string("tbl_close catch exception: ") + e.what());
}
}
end_query(hndl);
}
return STATUS_OK;
if (ntplh)
SMDEBUGLOG << " tableid: " << ntplh->tableid;
SMDEBUGLOG << endl;
#endif
delete ntplh;
// determine end of result set and end of statement execution
if (hndl->queryState == QUERY_IN_PROCESS)
{
// Get the query stats
ByteStream bs;
ByteStream::quadbyte qb = 3;
bs << qb;
hndl->write(bs);
//keep reading until we get a string
//TODO: really need to fix this! Why is ExeMgr sending other stuff?
for (int tries = 0; tries < 10; tries++)
{
bs = hndl->exeMgr->read();
if (bs.length() == 0) break;
try
{
bs >> hndl->queryStats;
bs >> hndl->extendedStats;
bs >> hndl->miniStats;
stats.unserialize(bs);
stats.setEndTime();
stats.insert();
break;
}
catch (IDBExcept&)
{
// @bug4732
end_query(hndl);
throw;
}
catch (...)
{
// querystats messed up. close connection.
// no need to throw for querystats protocol error, like for tablemode.
end_query(hndl);
sm_cleanup(hndl);
*conn_hdl = 0;
return STATUS_OK;
//throw runtime_error(string("tbl_close catch exception: ") + e.what());
}
}
end_query(hndl);
}
return STATUS_OK;
}
status_t
sm_init ( uint32_t sid,
cpsm_conhdl_t **conn_hdl,
uint32_t infinidb_local_query)
cpsm_conhdl_t** conn_hdl,
uint32_t infinidb_local_query)
{
// clear file content
// clear file content
#if IDB_SM_DEBUG
smlog.close();
smlog.open("/tmp/sm.log");
SMDEBUGLOG << "sm_init: " << dboptions << endl;
smlog.close();
smlog.open("/tmp/sm.log");
SMDEBUGLOG << "sm_init: " << dboptions << endl;
#endif
// @bug5660 Connection changes related to the local pm setting
/**
* when local PM is detected, or infinidb_local_query is set:
* 1. SELECT query connect to local ExeMgr 127.0.0.1:8601;
* 2. DML/DDL is disallowed.
* once local connection is determined, no need to check
* again because it will not switch back.
**/
if (*conn_hdl)
{
// existing connection is local, ok.
if ((*conn_hdl)->exeMgr->localQuery() || ! infinidb_local_query)
return STATUS_OK;
// if session variable changes to local, re-establish the connection to loopback.
else
sm_cleanup(*conn_hdl);
}
cpsm_conhdl_t* hndl = new cpsm_conhdl_t(time(0), sid, infinidb_local_query);
*conn_hdl = hndl;
hndl->sessionID = sid;
// @bug5660 Connection changes related to the local pm setting
/**
* when local PM is detected, or infinidb_local_query is set:
* 1. SELECT query connect to local ExeMgr 127.0.0.1:8601;
* 2. DML/DDL is disallowed.
* once local connection is determined, no need to check
* again because it will not switch back.
**/
if (*conn_hdl)
{
// existing connection is local, ok.
if ((*conn_hdl)->exeMgr->localQuery() || ! infinidb_local_query)
return STATUS_OK;
// if session variable changes to local, re-establish the connection to loopback.
else
sm_cleanup(*conn_hdl);
}
// profiling statistics
GET_PF_TIME(hndl->pf.login);
cpsm_conhdl_t* hndl = new cpsm_conhdl_t(time(0), sid, infinidb_local_query);
*conn_hdl = hndl;
hndl->sessionID = sid;
return STATUS_OK;
// profiling statistics
GET_PF_TIME(hndl->pf.login);
return STATUS_OK;
}
status_t
sm_cleanup ( cpsm_conhdl_t* conn_hdl )
{
#if IDB_SM_DEBUG
SMDEBUGLOG << "sm_cleanup: " << conn_hdl << endl;
SMDEBUGLOG.close();
SMDEBUGLOG << "sm_cleanup: " << conn_hdl << endl;
SMDEBUGLOG.close();
#endif
delete conn_hdl;
delete conn_hdl;
return STATUS_OK;
return STATUS_OK;
}
void cpsm_conhdl_t::write(ByteStream bs)
{
#ifdef _MSC_VER
exeMgr->write(bs);
exeMgr->write(bs);
#else
sighandler_t old_handler = signal(SIGPIPE, sighandler);
sigFlag = false;
exeMgr->write(bs);
signal(SIGPIPE, old_handler);
if (sigFlag)
throw runtime_error("Broken Pipe Error");
sighandler_t old_handler = signal(SIGPIPE, sighandler);
sigFlag = false;
exeMgr->write(bs);
signal(SIGPIPE, old_handler);
if (sigFlag)
throw runtime_error("Broken Pipe Error");
#endif
}
@@ -473,52 +509,58 @@ void cpsm_conhdl_t::write(ByteStream bs)
* these functions aren't needed.
*/
unsigned long mysql_real_escape_string(MYSQL *mysql,
char *to,const char *from,
unsigned long length)
unsigned long mysql_real_escape_string(MYSQL* mysql,
char* to, const char* from,
unsigned long length)
{
return escape_string_for_mysql(mysql->charset, to, length*2+1, from, length);
return escape_string_for_mysql(mysql->charset, to, length * 2 + 1, from, length);
}
// Clone of sql-common/client.c cli_use_result
MYSQL_RES* mysql_use_result(MYSQL *mysql)
MYSQL_RES* mysql_use_result(MYSQL* mysql)
{
MYSQL_RES *result;
DBUG_ENTER("mysql_use_result (clone)");
MYSQL_RES* result;
DBUG_ENTER("mysql_use_result (clone)");
if (!mysql->fields)
DBUG_RETURN(0);
if (mysql->status != MYSQL_STATUS_GET_RESULT)
{
set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
DBUG_RETURN(0);
}
if (!(result=(MYSQL_RES*) my_malloc(sizeof(*result)+
sizeof(ulong)*mysql->field_count,
MYF(MY_WME | MY_ZEROFILL))))
DBUG_RETURN(0);
result->lengths=(ulong*) (result+1);
result->methods= mysql->methods;
if (!(result->row=(MYSQL_ROW)
my_malloc(sizeof(result->row[0])*(mysql->field_count+1), MYF(MY_WME))))
{ /* Ptrs: to one row */
my_free(result);
DBUG_RETURN(0);
}
result->fields= mysql->fields;
result->field_alloc= mysql->field_alloc;
result->field_count= mysql->field_count;
result->current_field=0;
result->handle= mysql;
result->current_row= 0;
mysql->fields=0; /* fields is now in result */
clear_alloc_root(&mysql->field_alloc);
mysql->status=MYSQL_STATUS_USE_RESULT;
mysql->unbuffered_fetch_owner= &result->unbuffered_fetch_cancelled;
DBUG_RETURN(result); /* Data is read to be fetched */
if (!mysql->fields)
DBUG_RETURN(0);
if (mysql->status != MYSQL_STATUS_GET_RESULT)
{
set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
DBUG_RETURN(0);
}
if (!(result = (MYSQL_RES*) my_malloc(sizeof(*result) +
sizeof(ulong) * mysql->field_count,
MYF(MY_WME | MY_ZEROFILL))))
DBUG_RETURN(0);
result->lengths = (ulong*) (result + 1);
result->methods = mysql->methods;
if (!(result->row = (MYSQL_ROW)
my_malloc(sizeof(result->row[0]) * (mysql->field_count + 1), MYF(MY_WME))))
{
/* Ptrs: to one row */
my_free(result);
DBUG_RETURN(0);
}
result->fields = mysql->fields;
result->field_alloc = mysql->field_alloc;
result->field_count = mysql->field_count;
result->current_field = 0;
result->handle = mysql;
result->current_row = 0;
mysql->fields = 0; /* fields is now in result */
clear_alloc_root(&mysql->field_alloc);
mysql->status = MYSQL_STATUS_USE_RESULT;
mysql->unbuffered_fetch_owner = &result->unbuffered_fetch_cancelled;
DBUG_RETURN(result); /* Data is read to be fetched */
}
MYSQL_FIELD* mysql_fetch_fields(MYSQL_RES *res)
MYSQL_FIELD* mysql_fetch_fields(MYSQL_RES* res)
{
return res->fields;
}

View File

@@ -55,10 +55,10 @@
namespace sm
{
const int STATUS_OK=0;
const int SQL_NOT_FOUND=-1000;
const int SQL_KILLED=-1001;
const int CALPONT_INTERNAL_ERROR=-1007;
const int STATUS_OK = 0;
const int SQL_NOT_FOUND = -1000;
const int SQL_KILLED = -1001;
const int CALPONT_INTERNAL_ERROR = -1007;
#if IDB_SM_DEBUG
extern std::ofstream smlog;
@@ -73,113 +73,124 @@ typedef int32_t status_t;
enum QueryState
{
NO_QUERY = 0,
QUERY_IN_PROCESS
NO_QUERY = 0,
QUERY_IN_PROCESS
};
typedef struct Column {
Column():tableID(-1) {}
~Column() {}
int tableID;
int colPos;
int dataType;
std::vector <std::string> data;
typedef struct Column
{
Column(): tableID(-1) {}
~Column() {}
int tableID;
int colPos;
int dataType;
std::vector <std::string> data;
} Column;
typedef std::map <int, Column*> ResultMap;
struct Profiler
{
struct timeval login;
struct timeval beforePlan;
struct timeval afterPlan;
struct timeval resultArrival;
struct timeval resultReady;
struct timeval endProcess;
long prePlan(){
return (beforePlan.tv_sec-login.tv_sec) * 1000 +
(beforePlan.tv_usec - login.tv_usec)/1000; }
long buildPlan() {
return (afterPlan.tv_sec - beforePlan.tv_sec) * 1000 +
(afterPlan.tv_usec - beforePlan.tv_usec)/1000; }
long jobProcess() {
return (resultArrival.tv_sec - afterPlan.tv_sec) * 1000 +
(resultArrival.tv_usec - afterPlan.tv_usec)/1000; }
long buildResult() {
return (resultReady.tv_sec - resultArrival.tv_sec) * 1000 +
(resultReady.tv_usec - resultArrival.tv_usec)/1000; }
long tableFetch () {
return (endProcess.tv_sec - resultReady.tv_sec) * 1000 +
(endProcess.tv_usec - resultReady.tv_usec)/1000; }
struct timeval login;
struct timeval beforePlan;
struct timeval afterPlan;
struct timeval resultArrival;
struct timeval resultReady;
struct timeval endProcess;
long prePlan()
{
return (beforePlan.tv_sec - login.tv_sec) * 1000 +
(beforePlan.tv_usec - login.tv_usec) / 1000;
}
long buildPlan()
{
return (afterPlan.tv_sec - beforePlan.tv_sec) * 1000 +
(afterPlan.tv_usec - beforePlan.tv_usec) / 1000;
}
long jobProcess()
{
return (resultArrival.tv_sec - afterPlan.tv_sec) * 1000 +
(resultArrival.tv_usec - afterPlan.tv_usec) / 1000;
}
long buildResult()
{
return (resultReady.tv_sec - resultArrival.tv_sec) * 1000 +
(resultReady.tv_usec - resultArrival.tv_usec) / 1000;
}
long tableFetch ()
{
return (endProcess.tv_sec - resultReady.tv_sec) * 1000 +
(endProcess.tv_usec - resultReady.tv_usec) / 1000;
}
};
/** @brief Calpont table scan handle */
struct cpsm_tplsch_t
{
cpsm_tplsch_t() : tableid(0), rowsreturned(0), rowGroup(0), traceFlags(0), bandID(0), saveFlag(0), bandsReturned(0),
ctp(0) {}
~cpsm_tplsch_t()
{
delete rowGroup;
}
cpsm_tplsch_t() : tableid(0), rowsreturned(0), rowGroup(0), traceFlags(0), bandID(0), saveFlag(0), bandsReturned(0),
ctp(0) {}
~cpsm_tplsch_t()
{
delete rowGroup;
}
tableid_t tableid;
uint64_t rowsreturned;
rowgroup::RowGroup *rowGroup;
messageqcpp::ByteStream bs; // rowgroup bytestream. need to stay with the life span of rowgroup
uint32_t traceFlags;
// @bug 649
int bandID; // the band that being read from the disk
int key; // unique key for the table's scan context
// @bug 626
uint16_t saveFlag;
uint32_t bandsReturned;
std::vector<execplan::CalpontSystemCatalog::ColType> ctp;
std::string errMsg;
rowgroup::RGData rgData;
void deserializeTable(messageqcpp::ByteStream& bs)
{
if (!rowGroup)
{
rowGroup = new rowgroup::RowGroup();
rowGroup->deserialize(bs);
}
else
{
// XXXST: the 'true' is to ease the transition to RGDatas. Take it out when the
// transition is done.
rgData.deserialize(bs, true);
rowGroup->setData(&rgData);
//rowGroup->setData(const_cast<uint8_t*>(bs.buf()));
}
}
tableid_t tableid;
uint64_t rowsreturned;
rowgroup::RowGroup* rowGroup;
messageqcpp::ByteStream bs; // rowgroup bytestream. need to stay with the life span of rowgroup
uint32_t traceFlags;
// @bug 649
int bandID; // the band that being read from the disk
int key; // unique key for the table's scan context
// @bug 626
uint16_t saveFlag;
uint32_t bandsReturned;
std::vector<execplan::CalpontSystemCatalog::ColType> ctp;
std::string errMsg;
rowgroup::RGData rgData;
void deserializeTable(messageqcpp::ByteStream& bs)
{
if (!rowGroup)
{
rowGroup = new rowgroup::RowGroup();
rowGroup->deserialize(bs);
}
else
{
// XXXST: the 'true' is to ease the transition to RGDatas. Take it out when the
// transition is done.
rgData.deserialize(bs, true);
rowGroup->setData(&rgData);
//rowGroup->setData(const_cast<uint8_t*>(bs.buf()));
}
}
uint16_t getStatus()
{
idbassert(rowGroup != 0);
return rowGroup->getStatus();
}
uint16_t getStatus()
{
idbassert(rowGroup != 0);
return rowGroup->getStatus();
}
uint64_t getRowCount()
{
if (rowGroup)
return rowGroup->getRowCount();
else
return 0;
}
uint64_t getRowCount()
{
if (rowGroup)
return rowGroup->getRowCount();
else
return 0;
}
void setErrMsg()
{
if (rowGroup && getStatus())
{
//bs.advance(rowGroup->getDataSize());
bs >> errMsg;
}
else
{
errMsg = "NOERROR";
}
}
void setErrMsg()
{
if (rowGroup && getStatus())
{
//bs.advance(rowGroup->getDataSize());
bs >> errMsg;
}
else
{
errMsg = "NOERROR";
}
}
};
typedef boost::shared_ptr<cpsm_tplsch_t> sp_cpsm_tplsch_t;
@@ -187,48 +198,50 @@ typedef boost::shared_ptr<cpsm_tplsch_t> sp_cpsm_tplsch_t;
class cpsm_conhdl_t
{
public:
cpsm_conhdl_t(time_t v, const uint32_t sid, bool infinidb_local_query) :
value(v), sessionID(sid), queryState (NO_QUERY),
exeMgr( new execplan::ClientRotator(sid, "ExeMgr", infinidb_local_query)),
tblinfo_idx(0), idxinfo_idx(0), curFetchTb (0)
{ }
cpsm_conhdl_t(time_t v, const uint32_t sid, bool infinidb_local_query) :
value(v), sessionID(sid), queryState (NO_QUERY),
exeMgr( new execplan::ClientRotator(sid, "ExeMgr", infinidb_local_query)),
tblinfo_idx(0), idxinfo_idx(0), curFetchTb (0)
{ }
/** @brief connnect ExeMgr
*
* Try connecting to ExeMgr. If no connection, try ExeMgr1,
* ExeMgr2... until timeout lapses. Then throw exception.
*/
void connect(double timeout=0.005) {
exeMgr->connect(timeout);
}
EXPORT void write(messageqcpp::ByteStream bs);
/** @brief connnect ExeMgr
*
* Try connecting to ExeMgr. If no connection, try ExeMgr1,
* ExeMgr2... until timeout lapses. Then throw exception.
*/
void connect(double timeout = 0.005)
{
exeMgr->connect(timeout);
}
EXPORT void write(messageqcpp::ByteStream bs);
~cpsm_conhdl_t() {
delete exeMgr;
}
EXPORT const std::string toString() const;
time_t value;
uint32_t sessionID;
short queryState; // 0 -- NO_QUERY; 1 -- QUERY_IN_PROCESS
execplan::ClientRotator* exeMgr;
ResultMap resultSet;
Profiler pf;
int tblinfo_idx;
int idxinfo_idx;
std::string schemaname;
std::string tablename;
int tboid;
short requestType; // 0 -- ID2NAME; 1 -- NAME2ID
boost::shared_ptr<execplan::CalpontSystemCatalog> csc;
// @bug 649; @bug 626
std::map <int, int> tidMap; // tableid-tableStartCount map
std::map <int, sp_cpsm_tplsch_t> tidScanMap;
std::map <int, int> keyBandMap; // key-savedBandCount map
int curFetchTb; // current fetching table key
std::string queryStats;
std::string extendedStats;
std::string miniStats;
~cpsm_conhdl_t()
{
delete exeMgr;
}
EXPORT const std::string toString() const;
time_t value;
uint32_t sessionID;
short queryState; // 0 -- NO_QUERY; 1 -- QUERY_IN_PROCESS
execplan::ClientRotator* exeMgr;
ResultMap resultSet;
Profiler pf;
int tblinfo_idx;
int idxinfo_idx;
std::string schemaname;
std::string tablename;
int tboid;
short requestType; // 0 -- ID2NAME; 1 -- NAME2ID
boost::shared_ptr<execplan::CalpontSystemCatalog> csc;
// @bug 649; @bug 626
std::map <int, int> tidMap; // tableid-tableStartCount map
std::map <int, sp_cpsm_tplsch_t> tidScanMap;
std::map <int, int> keyBandMap; // key-savedBandCount map
int curFetchTb; // current fetching table key
std::string queryStats;
std::string extendedStats;
std::string miniStats;
private:
};
std::ostream& operator<<(std::ostream& output, const cpsm_conhdl_t& rhs);
@@ -236,30 +249,30 @@ std::ostream& operator<<(std::ostream& output, const cpsm_conhdl_t& rhs);
// @bug 626 save table bands to avoid sending plan too many times
enum SavingFlag
{
NO_SAVE = 0,
SAVING,
SAVED
NO_SAVE = 0,
SAVING,
SAVED
};
/** @brief Calpont table handle */
struct cpsm_tplh_t
{
cpsm_tplh_t() : tableid(0), rowsintable(0), bandID(0), saveFlag(NO_SAVE), bandsInTable(0) {}
tableid_t tableid;
int rowsintable;
// @bug 649
int bandID; // the band that being read from the disk
int key; // unique key for the table's scan context
// @bug 626
uint16_t saveFlag;
int bandsInTable;
cpsm_tplh_t() : tableid(0), rowsintable(0), bandID(0), saveFlag(NO_SAVE), bandsInTable(0) {}
tableid_t tableid;
int rowsintable;
// @bug 649
int bandID; // the band that being read from the disk
int key; // unique key for the table's scan context
// @bug 626
uint16_t saveFlag;
int bandsInTable;
};
struct cpsm_tid_t
{
cpsm_tid_t() : valid(false), value(0) {}
bool valid;
int value;
cpsm_tid_t() : valid(false), value(0) {}
bool valid;
int value;
};
extern status_t sm_init(uint32_t, cpsm_conhdl_t**, uint32_t infinidb_local_query = false);
@@ -267,7 +280,7 @@ extern status_t sm_cleanup(cpsm_conhdl_t*);
extern status_t tpl_open(tableid_t, cpsm_tplh_t*, cpsm_conhdl_t*);
extern status_t tpl_scan_open(tableid_t, sp_cpsm_tplsch_t&, cpsm_conhdl_t*);
extern status_t tpl_scan_fetch(sp_cpsm_tplsch_t&, cpsm_conhdl_t*, int* k=0);
extern status_t tpl_scan_fetch(sp_cpsm_tplsch_t&, cpsm_conhdl_t*, int* k = 0);
extern status_t tpl_scan_close(sp_cpsm_tplsch_t&);
extern status_t tpl_close(cpsm_tplh_t*, cpsm_conhdl_t**, querystats::QueryStats& stats);

View File

@@ -29,82 +29,85 @@ typedef int64_t longlong;
string toString(int64_t t1, unsigned scale)
{
longlong int_val = (longlong)t1;
// MySQL seems to round off values unless we use the string store method. Groan.
// Taken from tablefuncs.cpp
longlong int_val = (longlong)t1;
// MySQL seems to round off values unless we use the string store method. Groan.
// Taken from tablefuncs.cpp
//biggest Calpont supports is DECIMAL(18,x), or 18 total digits+dp+sign
const int ctmp_size = 18+1+1+1;
char ctmp[ctmp_size];
snprintf(ctmp, ctmp_size,
//biggest Calpont supports is DECIMAL(18,x), or 18 total digits+dp+sign
const int ctmp_size = 18 + 1 + 1 + 1;
char ctmp[ctmp_size];
snprintf(ctmp, ctmp_size,
#if __WORDSIZE <= 32
"%lld",
"%lld",
#else
"%ld",
"%ld",
#endif
int_val);
//we want to move the last dt_scale chars right by one spot to insert the dp
//we want to move the trailing null as well, so it's really dt_scale+1 chars
size_t l1 = strlen(ctmp);
//need to make sure we have enough leading zeros for this to work...
//at this point scale is always > 0
char* ptr = &ctmp[0];
if (int_val < 0)
{
ptr++;
idbassert(l1 >= 2);
l1--;
}
if (scale > l1)
{
const char* zeros = "000000000000000000"; //18 0's
size_t diff = scale - l1; //this will always be > 0
memmove((ptr + diff), ptr, l1 + 1); //also move null
memcpy(ptr, zeros, diff);
l1 = 0;
}
else
l1 -= scale;
memmove((ptr + l1 + 1), (ptr + l1), scale + 1); //also move null
*(ptr + l1) = '.';
int_val);
//we want to move the last dt_scale chars right by one spot to insert the dp
//we want to move the trailing null as well, so it's really dt_scale+1 chars
size_t l1 = strlen(ctmp);
//need to make sure we have enough leading zeros for this to work...
//at this point scale is always > 0
char* ptr = &ctmp[0];
return string(ctmp);
if (int_val < 0)
{
ptr++;
idbassert(l1 >= 2);
l1--;
}
if (scale > l1)
{
const char* zeros = "000000000000000000"; //18 0's
size_t diff = scale - l1; //this will always be > 0
memmove((ptr + diff), ptr, l1 + 1); //also move null
memcpy(ptr, zeros, diff);
l1 = 0;
}
else
l1 -= scale;
memmove((ptr + l1 + 1), (ptr + l1), scale + 1); //also move null
*(ptr + l1) = '.';
return string(ctmp);
}
}
int main(int argc, char** argv)
{
int64_t x;
string xstr;
int64_t x;
string xstr;
x = 10001LL;
xstr = toString(x, 2);
idbassert(xstr == "100.01");
x = 10001LL;
xstr = toString(x, 2);
idbassert(xstr == "100.01");
x = -10001LL;
xstr = toString(x, 2);
idbassert(xstr == "-100.01");
x = -10001LL;
xstr = toString(x, 2);
idbassert(xstr == "-100.01");
x = 999999999999999999LL;
xstr = toString(x, 2);
idbassert(xstr == "9999999999999999.99");
x = 999999999999999999LL;
xstr = toString(x, 2);
idbassert(xstr == "9999999999999999.99");
x = -999999999999999999LL;
xstr = toString(x, 2);
idbassert(xstr == "-9999999999999999.99");
x = -999999999999999999LL;
xstr = toString(x, 2);
idbassert(xstr == "-9999999999999999.99");
x = 1LL;
xstr = toString(x, 5);
idbassert(xstr == ".00001");
x = 1LL;
xstr = toString(x, 5);
idbassert(xstr == ".00001");
x = -1LL;
xstr = toString(x, 5);
idbassert(xstr == "-.00001");
x = -1LL;
xstr = toString(x, 5);
idbassert(xstr == "-.00001");
x = -1LL;
xstr = toString(x, 16);
idbassert(xstr == "-.0000000000000001");
x = -1LL;
xstr = toString(x, 16);
idbassert(xstr == "-.0000000000000001");
return 0;
return 0;
}