You've already forked mariadb-columnstore-engine
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:
@@ -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
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
308
dbcon/mysql/ha_calpont.h
Executable file → Normal 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
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
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
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
7281
dbcon/mysql/ha_calpont_impl.cpp
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
|
@@ -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
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
297
dbcon/mysql/ha_calpont_udf.cpp
Executable file → Normal 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
170
dbcon/mysql/ha_exists_sub.cpp
Executable file → Normal 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
518
dbcon/mysql/ha_from_sub.cpp
Executable file → Normal 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
397
dbcon/mysql/ha_in_sub.cpp
Executable file → Normal 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
766
dbcon/mysql/ha_pseudocolumn.cpp
Executable file → Normal 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
442
dbcon/mysql/ha_scalar_sub.cpp
Executable file → Normal 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
88
dbcon/mysql/ha_select_sub.cpp
Executable file → Normal 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
371
dbcon/mysql/ha_subquery.h
Executable file → Normal 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
204
dbcon/mysql/ha_view.cpp
Executable file → Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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
1393
dbcon/mysql/ha_window_function.cpp
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
||||
|
311
dbcon/mysql/sm.h
311
dbcon/mysql/sm.h
@@ -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);
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user