diff options
Diffstat (limited to 'storage')
101 files changed, 1371 insertions, 1503 deletions
diff --git a/storage/connect/CMakeLists.txt b/storage/connect/CMakeLists.txt index 2fabd12dcd0..a1594f8797c 100644 --- a/storage/connect/CMakeLists.txt +++ b/storage/connect/CMakeLists.txt @@ -245,7 +245,7 @@ int main() { ENDIF(CONNECT_WITH_ODBC) # -# JDBC and MongoDB Java Driver +# JDBC with MongoDB Java Driver included but disabled # OPTION(CONNECT_WITH_MONGO "Compile CONNECT storage engine with MONGO support" ON) OPTION(CONNECT_WITH_JDBC "Compile CONNECT storage engine with JDBC support" ON) @@ -265,13 +265,13 @@ IF(CONNECT_WITH_JDBC) MysqlInterface.java OracleInterface.java PostgresqlInterface.java JavaWrappers.jar) add_definitions(-DJDBC_SUPPORT) - IF(CONNECT_WITH_MONGO) + IF(CONNECT_WITH_MONGO) SET(CONNECT_SOURCES ${CONNECT_SOURCES} jmgfam.cpp jmgoconn.cpp mongo.cpp tabjmg.cpp jmgfam.h jmgoconn.h mongo.h tabjmg.h Mongo2Interface.java Mongo3Interface.java) - add_definitions(-DMONGO_SUPPORT) - ENDIF() + add_definitions(-DMONGO_SUPPORT -DMONGO_ENABLED=0) + ENDIF() ELSE() SET(JDBC_LIBRARY "") ENDIF() @@ -290,33 +290,36 @@ IF(CONNECT_WITH_ZIP) ENDIF(CONNECT_WITH_ZIP) # -# MONGO C Driver (CMAKE NOT YET WORKING) +# MONGO C Driver # -#IF(CONNECT_WITH_MONGO) -# IF(WIN32) -# # Adding some typical places to search in -# SET(PC_MONGO_INCLUDE_DIRS -# C:/mongo-c-driver/include -# D:/mongo-c-driver/include) -# SET(PC_MONGO_LIBRARY_DIRS -# C:/mongo-c-driver/lib -# D:/mongo-c-driver/lib) -# ENDIF(WIN32) -# FIND_PACKAGE(libmongoc 1.7) -# IF (MONGO_FOUND) -# INCLUDE_DIRECTORIES(${MONGO_INCLUDE_DIR}) -# SET(MONGO_LIBRARY ${MONGO_LIBRARIES}) -# SET(CONNECT_SOURCES ${CONNECT_SOURCES} -# cmgoconn.cpp cmgfam.cpp tabcmg.cpp -# cmgoconn.h cmgfam.h tabcmg.h) -# add_definitions(-DCMGO_SUPPORT) -# IF (NOT JAVA_FOUND AND JNI_FOUND) -# SET(CONNECT_SOURCES ${CONNECT_SOURCES} mongo.cpp mongo.h) -# add_definitions(-DMONGO_SUPPORT) -# ENDIF (NOT JAVA_FOUND AND JNI_FOUND) -# ENDIF(MONGO_FOUND) -#ENDIF(CONNECT_WITH_MONGO) +IF(CONNECT_WITH_MONGO) + IF(WIN32) + # Adding some typical places to search in + SET(PC_MONGO_INCLUDE_DIRS + C:/mongo-c-driver/include + D:/mongo-c-driver/include) + SET(PC_MONGO_LIBRARY_DIRS + C:/mongo-c-driver/lib + D:/mongo-c-driver/lib) + ENDIF(WIN32) + FIND_PACKAGE(libmongoc-1.0 1.7) + IF (libmongoc-1.0_FOUND) + INCLUDE_DIRECTORIES(${MONGOC_INCLUDE_DIRS}) + SET(MONGOC_LIBRARY ${MONGOC_LIBRARIES}) + SET(CONNECT_SOURCES ${CONNECT_SOURCES} + cmgoconn.cpp cmgfam.cpp tabcmg.cpp + cmgoconn.h cmgfam.h tabcmg.h) + add_definitions(-DCMGO_SUPPORT) + IF (NOT JAVA_FOUND AND JNI_FOUND) + SET(CONNECT_SOURCES ${CONNECT_SOURCES} mongo.cpp mongo.h) + add_definitions(-DMONGO_SUPPORT -DMONGO_ENABLED=1) + ELSE () + remove_definitions(-DMONGO_ENABLED=0) + add_definitions(-DMONGO_ENABLED=1) + ENDIF (NOT JAVA_FOUND AND JNI_FOUND) + ENDIF(libmongoc-1.0_FOUND) +ENDIF(CONNECT_WITH_MONGO) # @@ -337,9 +340,25 @@ MYSQL_ADD_PLUGIN(connect ${CONNECT_SOURCES} STORAGE_ENGINE COMPONENT connect-engine RECOMPILE_FOR_EMBEDDED -# LINK_LIBRARIES ${ZLIB_LIBRARY} ${XML_LIBRARY} ${ICONV_LIBRARY} $(MONGO_LIBRARY) LINK_LIBRARIES ${ZLIB_LIBRARY} ${XML_LIBRARY} ${ICONV_LIBRARY} - ${ODBC_LIBRARY} ${JDBC_LIBRARY} ${IPHLPAPI_LIBRARY}) + ${ODBC_LIBRARY} ${JDBC_LIBRARY} ${MONGOC_LIBRARY} ${IPHLPAPI_LIBRARY}) + +IF(NOT TARGET connect) + RETURN() +ENDIF() + +# Install some extra files that belong to connect engine +IF(WIN32) + # install ha_connect.lib + GET_TARGET_PROPERTY(CONNECT_LOCATION connect LOCATION) + STRING(REPLACE "dll" "lib" CONNECT_LIB ${CONNECT_LOCATION}) + IF(CMAKE_CONFIGURATION_TYPES) + STRING(REPLACE "${CMAKE_CFG_INTDIR}" "\${CMAKE_INSTALL_CONFIG_NAME}" + CONNECT_LIB ${CONNECT_LIB}) + ENDIF() + INSTALL(FILES ${CONNECT_LIB} + DESTINATION ${INSTALL_PLUGINDIR} COMPONENT connect-engine) +ENDIF(WIN32) IF(NOT TARGET connect) RETURN() @@ -368,4 +387,3 @@ IF(CONNECT_WITH_JDBC AND JAVA_FOUND AND JNI_FOUND) ${CMAKE_CURRENT_BINARY_DIR}/JdbcInterface.jar DESTINATION ${INSTALL_PLUGINDIR} COMPONENT connect-engine) ENDIF() - diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 1b09046a8ff..5d804b24b2b 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -171,9 +171,9 @@ #define JSONMAX 10 // JSON Default max grp size extern "C" { - char version[]= "Version 1.06.0001 April 17, 2017"; + char version[]= "Version 1.06.0004 September 03, 2017"; #if defined(__WIN__) - char compver[]= "Version 1.06.0001 " __DATE__ " " __TIME__; + char compver[]= "Version 1.06.0004 " __DATE__ " " __TIME__; char slash= '\\'; #else // !__WIN__ char slash= '/'; @@ -359,6 +359,13 @@ static MYSQL_THDVAR_STR(java_wrapper, NULL, NULL, "wrappers/JdbcInterface"); #endif // JDBC_SUPPORT +#if defined(MONGO_SUPPORT) +// Enabling MONGO table type +static MYSQL_THDVAR_BOOL(enable_mongo, PLUGIN_VAR_RQCMDARG, + "Enabling the MongoDB access", + NULL, NULL, MONGO_ENABLED); +#endif // MONGO_SUPPORT + #if defined(XMSG) || defined(NEWMSG) const char *language_names[]= { @@ -419,6 +426,10 @@ char *GetJavaWrapper(void) {return connect_hton ? THDVAR(current_thd, java_wrapper) : (char*)"wrappers/JdbcInterface";} #endif // JDBC_SUPPORT +#if defined(MONGO_SUPPORT) +bool MongoEnabled(void) { return THDVAR(current_thd, enable_mongo); } +#endif // MONGO_SUPPORT + extern "C" const char *msglang(void) { #if defined(FRENCH) @@ -1285,9 +1296,14 @@ PCSZ ha_connect::GetStringOption(PCSZ opname, PCSZ sdef) else opval= GetListOption(xp->g, opname, options->oplist); - } else if (!stricmp(opname, "Query_String")) - opval= thd_query_string(table->in_use)->str; - else if (!stricmp(opname, "Partname")) + } else if (!stricmp(opname, "Query_String")) { +// This escapes everything and returns a wrong query +// opval = thd_query_string(table->in_use)->str; + opval = (PCSZ)PlugSubAlloc(xp->g, NULL, + thd_query_string(table->in_use)->length + 1); + strcpy((char*)opval, thd_query_string(table->in_use)->str); +// sprintf((char*)opval, "%s", thd_query_string(table->in_use)->str); + } else if (!stricmp(opname, "Partname")) opval= partname; else if (!stricmp(opname, "Table_charset")) { const CHARSET_INFO *chif= (tshp) ? tshp->table_charset @@ -1433,7 +1449,7 @@ PFOS ha_connect::GetFieldOptionStruct(Field *fdp) void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf) { const char *cp; - char *chset, v; + char *chset, v = 0; ha_field_option_struct *fop; Field* fp; Field* *fldp; @@ -1486,7 +1502,6 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf) } // endif fop chset = (char *)fp->charset()->name; - v = (!strcmp(chset, "binary")) ? 'B' : 0; switch (fp->type()) { case MYSQL_TYPE_BLOB: @@ -1501,8 +1516,9 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf) switch (pcf->Type) { case TYPE_STRING: - // Do something for case - cp= fp->charset()->name; + case TYPE_BIN: + // Do something for case + cp= chset; // Find if collation name ends by _ci if (!strcmp(cp + strlen(cp) - 3, "_ci")) { @@ -2114,6 +2130,11 @@ int ha_connect::MakeRecord(char *buf) charset= tdbp->data_charset(); rc= fp->store(p, strlen(p), charset, CHECK_FIELD_WARN); break; + case TYPE_BIN: + p = value->GetCharValue(); + charset = &my_charset_bin; + rc = fp->store(p, strlen(p), charset, CHECK_FIELD_WARN); + break; case TYPE_DOUBLE: rc= fp->store(value->GetFloatValue()); break; @@ -5163,7 +5184,8 @@ static bool add_field(String *sql, const char *field_name, int typ, int len, error|= sql->append("` "); error|= sql->append(type); - if (len && typ != TYPE_DATE && (typ != TYPE_DOUBLE || dec >= 0)) { + if (typ == TYPE_STRING || + (len && typ != TYPE_DATE && (typ != TYPE_DOUBLE || dec >= 0))) { error|= sql->append('('); error|= sql->append_ulonglong(len); @@ -6389,6 +6411,7 @@ int ha_connect::create(const char *name, TABLE *table_arg, case MYSQL_TYPE_VARCHAR: case MYSQL_TYPE_VAR_STRING: case MYSQL_TYPE_STRING: +#if 0 if (!fp->field_length) { sprintf(g->Message, "Unsupported 0 length for column %s", fp->field_name.str); @@ -6398,7 +6421,7 @@ int ha_connect::create(const char *name, TABLE *table_arg, MYF(0), fp->field_name.str); DBUG_RETURN(rc); } // endif fp - +#endif // 0 break; // To be checked case MYSQL_TYPE_BIT: case MYSQL_TYPE_NULL: @@ -7166,7 +7189,10 @@ static struct st_mysql_sys_var* connect_system_variables[]= { MYSQL_SYSVAR(class_path), MYSQL_SYSVAR(java_wrapper), #endif // JDBC_SUPPORT - NULL +#if defined(MONGO_SUPPORT) + MYSQL_SYSVAR(enable_mongo), +#endif // MONGO_SUPPORT +NULL }; maria_declare_plugin(connect) @@ -7175,14 +7201,14 @@ maria_declare_plugin(connect) &connect_storage_engine, "CONNECT", "Olivier Bertrand", - "Management of External Data (SQL/MED), including many file formats", + "Management of External Data (SQL/NOSQL/MED), including many file formats", PLUGIN_LICENSE_GPL, connect_init_func, /* Plugin Init */ connect_done_func, /* Plugin Deinit */ 0x0106, /* version number (1.05) */ NULL, /* status variables */ connect_system_variables, /* system variables */ - "1.06.0001", /* string version */ - MariaDB_PLUGIN_MATURITY_BETA /* maturity */ + "1.06.0004", /* string version */ + MariaDB_PLUGIN_MATURITY_STABLE /* maturity */ } maria_declare_plugin_end; diff --git a/storage/connect/ha_connect.h b/storage/connect/ha_connect.h index 8a54f8f16d1..c3d458094a2 100644 --- a/storage/connect/ha_connect.h +++ b/storage/connect/ha_connect.h @@ -348,6 +348,13 @@ const char *GetValStr(OPVAL vop, bool neg); PFIL CondFilter(PGLOBAL g, Item *cond); //PFIL CheckFilter(PGLOBAL g); +/** admin commands - called from mysql_admin_table */ +virtual int check(THD* thd, HA_CHECK_OPT* check_opt) +{ + // TODO: implement it + return HA_ADMIN_OK; // Just to avoid error message with checktables +} // end of check + /** Number of rows in table. It will only be called if (table_flags() & (HA_HAS_RECORDS | HA_STATS_RECORDS_IS_EXACT)) != 0 diff --git a/storage/connect/jsonudf.cpp b/storage/connect/jsonudf.cpp index 34a43c72016..29bccc4afeb 100644 --- a/storage/connect/jsonudf.cpp +++ b/storage/connect/jsonudf.cpp @@ -539,7 +539,7 @@ PVAL JSNX::CalculateArray(PGLOBAL g, PJAR arp, int n) SetJsonValue(g, MulVal, jvp, n); if (!MulVal->IsNull()) { - switch (op) { + switch (op) { case OP_CNC: if (Nodes[n].CncVal) { val[0] = Nodes[n].CncVal; diff --git a/storage/connect/mycat.cc b/storage/connect/mycat.cc index 23005db5272..0f8d7b76b60 100644 --- a/storage/connect/mycat.cc +++ b/storage/connect/mycat.cc @@ -111,6 +111,9 @@ extern "C" HINSTANCE s_hModule; // Saved module handle #endif // !__WIN__ +#if defined(MONGO_SUPPORT) +bool MongoEnabled(void); +#endif // MONGO_SUPPORT PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info); /***********************************************************************/ @@ -558,7 +561,13 @@ PRELDEF MYCAT::MakeTableDesc(PGLOBAL g, PTABLE tablep, LPCSTR am) case TAB_VIR: tdp= new(g) VIRDEF; break; case TAB_JSON: tdp= new(g) JSONDEF; break; #if defined(MONGO_SUPPORT) - case TAB_MONGO: tdp = new(g) MGODEF; break; + case TAB_MONGO: + if (MongoEnabled()) + tdp = new(g) MGODEF; + else + strcpy(g->Message, "MONGO type not enabled"); + + break; #endif // MONGO_SUPPORT #if defined(ZIP_SUPPORT) case TAB_ZIP: tdp= new(g) ZIPDEF; break; diff --git a/storage/connect/myconn.cpp b/storage/connect/myconn.cpp index d2d55f33611..08bb24e14df 100644 --- a/storage/connect/myconn.cpp +++ b/storage/connect/myconn.cpp @@ -472,7 +472,7 @@ int MYSQLC::Open(PGLOBAL g, const char *host, const char *db, int pt, const char *csname) { const char *pipe = NULL; - uint cto = 6000, nrt = 12000; + uint cto = 10, nrt = 20; my_bool my_true= 1; m_DB = mysql_init(NULL); @@ -525,7 +525,8 @@ int MYSQLC::Open(PGLOBAL g, const char *host, const char *db, mysql_options(m_DB, MYSQL_OPT_USE_THREAD_SPECIFIC_MEMORY, (char*)&my_true); - if (!mysql_real_connect(m_DB, host, user, pwd, db, pt, pipe, CLIENT_MULTI_RESULTS)) { + if (!mysql_real_connect(m_DB, host, user, pwd, db, pt, pipe, + CLIENT_MULTI_RESULTS | CLIENT_REMEMBER_OPTIONS)) { #if defined(_DEBUG) sprintf(g->Message, "mysql_real_connect failed: (%d) %s", mysql_errno(m_DB), mysql_error(m_DB)); diff --git a/storage/connect/mysql-test/connect/r/json_java_2.result b/storage/connect/mysql-test/connect/r/json_java_2.result index 83272ec00ce..96c58221b24 100644 --- a/storage/connect/mysql-test/connect/r/json_java_2.result +++ b/storage/connect/mysql-test/connect/r/json_java_2.result @@ -1,4 +1,5 @@ SET GLOBAL connect_class_path='C:/MariaDB-10.2/MariaDB/storage/connect/mysql-test/connect/std_data/Mongo2.jar'; +set connect_enable_mongo=1; # # Test the MONGO table type # @@ -25,7 +26,6 @@ address_street 1 CHAR 38 38 0 0 address.street address_zipcode 1 CHAR 5 5 0 0 address.zipcode borough 1 CHAR 13 13 0 0 cuisine 1 CHAR 64 64 0 0 -grades 1 CHAR 0 0 0 1 grades_date 1 CHAR 256 256 0 1 grades.0.date grades_grade 1 CHAR 14 14 0 1 grades.0.grade grades_score 5 BIGINT 2 2 0 1 grades.0.score @@ -72,7 +72,6 @@ t1 CREATE TABLE `t1` ( `address_zipcode` char(5) NOT NULL `FIELD_FORMAT`='address.zipcode', `borough` char(13) NOT NULL, `cuisine` char(64) NOT NULL, - `grades` char(1) DEFAULT NULL, `grades_date` varchar(256) DEFAULT NULL `FIELD_FORMAT`='grades.0.date', `grades_grade` char(14) DEFAULT NULL `FIELD_FORMAT`='grades.0.grade', `grades_score` bigint(2) DEFAULT NULL `FIELD_FORMAT`='grades.0.score', @@ -80,12 +79,12 @@ t1 CREATE TABLE `t1` ( `restaurant_id` char(8) NOT NULL ) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='mongodb://localhost:27017' `TABLE_TYPE`='JSON' `TABNAME`='restaurants' `OPTION_LIST`='Level=1,Driver=Java,Version=2' `DATA_CHARSET`='utf8' `LRECL`=4096 SELECT * FROM t1 LIMIT 5; -_id address_building address_coord address_street address_zipcode borough cuisine grades grades_date grades_grade grades_score name restaurant_id -58ada47de5a51ddfcd5ed51c 1007 -73.856077 Morris Park Ave 10462 Bronx Bakery 2 2014-03-03T00:00:00.000Z A 2 Morris Park Bake Shop 30075445 -58ada47de5a51ddfcd5ed51d 469 -73.961704 Flatbush Avenue 11225 Brooklyn Hamburgers 2 2014-12-30T00:00:00.000Z A 8 Wendy'S 30112340 -58ada47de5a51ddfcd5ed51e 351 -73.98513559999999 West 57 Street 10019 Manhattan Irish 2 2014-09-06T00:00:00.000Z A 2 Dj Reynolds Pub And Restaurant 30191841 -58ada47de5a51ddfcd5ed51f 2780 -73.98241999999999 Stillwell Avenue 11224 Brooklyn American 2 2014-06-10T00:00:00.000Z A 5 Riviera Caterer 40356018 -58ada47de5a51ddfcd5ed520 97-22 -73.8601152 63 Road 11374 Queens Jewish/Kosher 2 2014-11-24T00:00:00.000Z Z 20 Tov Kosher Kitchen 40356068 +_id address_building address_coord address_street address_zipcode borough cuisine grades_date grades_grade grades_score name restaurant_id +58ada47de5a51ddfcd5ed51c 1007 -73.856077 Morris Park Ave 10462 Bronx Bakery 2014-03-03T00:00:00.000Z A 2 Morris Park Bake Shop 30075445 +58ada47de5a51ddfcd5ed51d 469 -73.961704 Flatbush Avenue 11225 Brooklyn Hamburgers 2014-12-30T00:00:00.000Z A 8 Wendy'S 30112340 +58ada47de5a51ddfcd5ed51e 351 -73.98513559999999 West 57 Street 10019 Manhattan Irish 2014-09-06T00:00:00.000Z A 2 Dj Reynolds Pub And Restaurant 30191841 +58ada47de5a51ddfcd5ed51f 2780 -73.98241999999999 Stillwell Avenue 11224 Brooklyn American 2014-06-10T00:00:00.000Z A 5 Riviera Caterer 40356018 +58ada47de5a51ddfcd5ed520 97-22 -73.8601152 63 Road 11374 Queens Jewish/Kosher 2014-11-24T00:00:00.000Z Z 20 Tov Kosher Kitchen 40356068 DROP TABLE t1; # # Dropping a column @@ -259,7 +258,6 @@ t1 CREATE TABLE `t1` ( `address_street` char(38) NOT NULL `FIELD_FORMAT`='address.street', `address_zipcode` char(5) NOT NULL `FIELD_FORMAT`='address.zipcode', `borough` char(13) NOT NULL, - `grades` char(1) DEFAULT NULL, `grades_date` char(24) DEFAULT NULL `FIELD_FORMAT`='grades.0.date', `grades_grade` char(14) DEFAULT NULL `FIELD_FORMAT`='grades.0.grade', `grades_score` bigint(2) DEFAULT NULL `FIELD_FORMAT`='grades.0.score', @@ -384,3 +382,4 @@ planner 167 41.75 postcard 23 5.75 DROP TABLE t1; true +set connect_enable_mongo=0; diff --git a/storage/connect/mysql-test/connect/r/json_java_3.result b/storage/connect/mysql-test/connect/r/json_java_3.result index 563bcef7321..09901452975 100644 --- a/storage/connect/mysql-test/connect/r/json_java_3.result +++ b/storage/connect/mysql-test/connect/r/json_java_3.result @@ -1,4 +1,5 @@ SET GLOBAL connect_class_path='C:/MariaDB-10.2/MariaDB/storage/connect/mysql-test/connect/std_data/Mongo3.jar'; +set connect_enable_mongo=1; # # Test the MONGO table type # @@ -25,7 +26,6 @@ address_street 1 CHAR 38 38 0 0 address.street address_zipcode 1 CHAR 5 5 0 0 address.zipcode borough 1 CHAR 13 13 0 0 cuisine 1 CHAR 64 64 0 0 -grades 1 CHAR 0 0 0 1 grades_date 1 CHAR 256 256 0 1 grades.0.date grades_grade 1 CHAR 14 14 0 1 grades.0.grade grades_score 5 BIGINT 2 2 0 1 grades.0.score @@ -72,7 +72,6 @@ t1 CREATE TABLE `t1` ( `address_zipcode` char(5) NOT NULL `FIELD_FORMAT`='address.zipcode', `borough` char(13) NOT NULL, `cuisine` char(64) NOT NULL, - `grades` char(1) DEFAULT NULL, `grades_date` varchar(256) DEFAULT NULL `FIELD_FORMAT`='grades.0.date', `grades_grade` char(14) DEFAULT NULL `FIELD_FORMAT`='grades.0.grade', `grades_score` bigint(2) DEFAULT NULL `FIELD_FORMAT`='grades.0.score', @@ -80,12 +79,12 @@ t1 CREATE TABLE `t1` ( `restaurant_id` char(8) NOT NULL ) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='mongodb://localhost:27017' `TABLE_TYPE`='JSON' `TABNAME`='restaurants' `OPTION_LIST`='Level=1,Driver=Java,Version=3' `DATA_CHARSET`='utf8' `LRECL`=4096 SELECT * FROM t1 LIMIT 5; -_id address_building address_coord address_street address_zipcode borough cuisine grades grades_date grades_grade grades_score name restaurant_id -58ada47de5a51ddfcd5ed51c 1007 -73.856077 Morris Park Ave 10462 Bronx Bakery 1 1393804800 A 2 Morris Park Bake Shop 30075445 -58ada47de5a51ddfcd5ed51d 469 -73.961704 Flatbush Avenue 11225 Brooklyn Hamburgers 1 1419897600 A 8 Wendy'S 30112340 -58ada47de5a51ddfcd5ed51e 351 -73.98513559999999 West 57 Street 10019 Manhattan Irish 1 1409961600 A 2 Dj Reynolds Pub And Restaurant 30191841 -58ada47de5a51ddfcd5ed51f 2780 -73.98241999999999 Stillwell Avenue 11224 Brooklyn American 1 1402358400 A 5 Riviera Caterer 40356018 -58ada47de5a51ddfcd5ed520 97-22 -73.8601152 63 Road 11374 Queens Jewish/Kosher 1 1416787200 Z 20 Tov Kosher Kitchen 40356068 +_id address_building address_coord address_street address_zipcode borough cuisine grades_date grades_grade grades_score name restaurant_id +58ada47de5a51ddfcd5ed51c 1007 -73.856077 Morris Park Ave 10462 Bronx Bakery 1393804800 A 2 Morris Park Bake Shop 30075445 +58ada47de5a51ddfcd5ed51d 469 -73.961704 Flatbush Avenue 11225 Brooklyn Hamburgers 1419897600 A 8 Wendy'S 30112340 +58ada47de5a51ddfcd5ed51e 351 -73.98513559999999 West 57 Street 10019 Manhattan Irish 1409961600 A 2 Dj Reynolds Pub And Restaurant 30191841 +58ada47de5a51ddfcd5ed51f 2780 -73.98241999999999 Stillwell Avenue 11224 Brooklyn American 1402358400 A 5 Riviera Caterer 40356018 +58ada47de5a51ddfcd5ed520 97-22 -73.8601152 63 Road 11374 Queens Jewish/Kosher 1416787200 Z 20 Tov Kosher Kitchen 40356068 DROP TABLE t1; # # Dropping a column @@ -259,7 +258,6 @@ t1 CREATE TABLE `t1` ( `address_street` char(38) NOT NULL `FIELD_FORMAT`='address.street', `address_zipcode` char(5) NOT NULL `FIELD_FORMAT`='address.zipcode', `borough` char(13) NOT NULL, - `grades` char(1) DEFAULT NULL, `grades_date` bigint(13) DEFAULT NULL `FIELD_FORMAT`='grades.0.date', `grades_grade` char(14) DEFAULT NULL `FIELD_FORMAT`='grades.0.grade', `grades_score` bigint(2) DEFAULT NULL `FIELD_FORMAT`='grades.0.score', @@ -384,3 +382,4 @@ planner 167 41.75 postcard 23 5.75 DROP TABLE t1; true +set connect_enable_mongo=0; diff --git a/storage/connect/mysql-test/connect/r/json_mongo_c.result b/storage/connect/mysql-test/connect/r/json_mongo_c.result index d3363f39eab..afcad8d2ea2 100644 --- a/storage/connect/mysql-test/connect/r/json_mongo_c.result +++ b/storage/connect/mysql-test/connect/r/json_mongo_c.result @@ -1,3 +1,4 @@ +set connect_enable_mongo=1; # # Test the MONGO table type # @@ -24,7 +25,6 @@ address_street 1 CHAR 38 38 0 0 address.street address_zipcode 1 CHAR 5 5 0 0 address.zipcode borough 1 CHAR 13 13 0 0 cuisine 1 CHAR 64 64 0 0 -grades 1 CHAR 0 0 0 1 grades_date 1 CHAR 256 256 0 1 grades.0.date grades_grade 1 CHAR 14 14 0 1 grades.0.grade grades_score 5 BIGINT 2 2 0 1 grades.0.score @@ -71,7 +71,6 @@ t1 CREATE TABLE `t1` ( `address_zipcode` char(5) NOT NULL `FIELD_FORMAT`='address.zipcode', `borough` char(13) NOT NULL, `cuisine` char(64) NOT NULL, - `grades` char(1) DEFAULT NULL, `grades_date` varchar(256) DEFAULT NULL `FIELD_FORMAT`='grades.0.date', `grades_grade` char(14) DEFAULT NULL `FIELD_FORMAT`='grades.0.grade', `grades_score` bigint(2) DEFAULT NULL `FIELD_FORMAT`='grades.0.score', @@ -79,12 +78,12 @@ t1 CREATE TABLE `t1` ( `restaurant_id` char(8) NOT NULL ) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='mongodb://localhost:27017' `TABLE_TYPE`='JSON' `TABNAME`='restaurants' `OPTION_LIST`='Level=1,Driver=C,Version=0' `DATA_CHARSET`='utf8' `LRECL`=1024 SELECT * FROM t1 LIMIT 5; -_id address_building address_coord address_street address_zipcode borough cuisine grades grades_date grades_grade grades_score name restaurant_id -58ada47de5a51ddfcd5ed51c 1007 -73.856076999999999089 Morris Park Ave 10462 Bronx Bakery 1 1393804800 A 2 Morris Park Bake Shop 30075445 -58ada47de5a51ddfcd5ed51d 469 -73.96170399999999745 Flatbush Avenue 11225 Brooklyn Hamburgers 1 1419897600 A 8 Wendy'S 30112340 -58ada47de5a51ddfcd5ed51e 351 -73.985135599999992451 West 57 Street 10019 Manhattan Irish 1 1409961600 A 2 Dj Reynolds Pub And Restaurant 30191841 -58ada47de5a51ddfcd5ed51f 2780 -73.982419999999990523 Stillwell Avenue 11224 Brooklyn American 1 1402358400 A 5 Riviera Caterer 40356018 -58ada47de5a51ddfcd5ed520 97-22 -73.860115199999995639 63 Road 11374 Queens Jewish/Kosher 1 1416787200 Z 20 Tov Kosher Kitchen 40356068 +_id address_building address_coord address_street address_zipcode borough cuisine grades_date grades_grade grades_score name restaurant_id +58ada47de5a51ddfcd5ed51c 1007 -73.856076999999999089 Morris Park Ave 10462 Bronx Bakery 1393804800 A 2 Morris Park Bake Shop 30075445 +58ada47de5a51ddfcd5ed51d 469 -73.96170399999999745 Flatbush Avenue 11225 Brooklyn Hamburgers 1419897600 A 8 Wendy'S 30112340 +58ada47de5a51ddfcd5ed51e 351 -73.985135599999992451 West 57 Street 10019 Manhattan Irish 1409961600 A 2 Dj Reynolds Pub And Restaurant 30191841 +58ada47de5a51ddfcd5ed51f 2780 -73.982419999999990523 Stillwell Avenue 11224 Brooklyn American 1402358400 A 5 Riviera Caterer 40356018 +58ada47de5a51ddfcd5ed520 97-22 -73.860115199999995639 63 Road 11374 Queens Jewish/Kosher 1416787200 Z 20 Tov Kosher Kitchen 40356068 DROP TABLE t1; # # Dropping a column @@ -258,7 +257,6 @@ t1 CREATE TABLE `t1` ( `address_street` char(38) NOT NULL `FIELD_FORMAT`='address.street', `address_zipcode` char(5) NOT NULL `FIELD_FORMAT`='address.zipcode', `borough` char(13) NOT NULL, - `grades` char(1) DEFAULT NULL, `grades_date` bigint(13) DEFAULT NULL `FIELD_FORMAT`='grades.0.date', `grades_grade` char(14) DEFAULT NULL `FIELD_FORMAT`='grades.0.grade', `grades_score` bigint(2) DEFAULT NULL `FIELD_FORMAT`='grades.0.score', @@ -383,3 +381,4 @@ planner 167 41.75 postcard 23 5.75 DROP TABLE t1; true +set connect_enable_mongo=0; diff --git a/storage/connect/mysql-test/connect/r/mongo_c.result b/storage/connect/mysql-test/connect/r/mongo_c.result index da0832994c2..f90f3a94b44 100644 --- a/storage/connect/mysql-test/connect/r/mongo_c.result +++ b/storage/connect/mysql-test/connect/r/mongo_c.result @@ -1,3 +1,4 @@ +set connect_enable_mongo=1; # # Test the MONGO table type # @@ -376,3 +377,4 @@ planner 167 41.750000 postcard 23 5.750000 DROP TABLE t1; true +set connect_enable_mongo=0; diff --git a/storage/connect/mysql-test/connect/r/mongo_java_2.result b/storage/connect/mysql-test/connect/r/mongo_java_2.result index b1e9ea74f72..02b8ae09d34 100644 --- a/storage/connect/mysql-test/connect/r/mongo_java_2.result +++ b/storage/connect/mysql-test/connect/r/mongo_java_2.result @@ -1,4 +1,5 @@ SET GLOBAL connect_class_path='C:/MariaDB-10.2/MariaDB/storage/connect/mysql-test/connect/std_data/Mongo2.jar'; +set connect_enable_mongo=1; # # Test the MONGO table type # @@ -377,3 +378,4 @@ planner 167 41.75 postcard 23 5.75 DROP TABLE t1; true +set connect_enable_mongo=0; diff --git a/storage/connect/mysql-test/connect/r/mongo_java_3.result b/storage/connect/mysql-test/connect/r/mongo_java_3.result index e2fe584620f..c4387bfa5b1 100644 --- a/storage/connect/mysql-test/connect/r/mongo_java_3.result +++ b/storage/connect/mysql-test/connect/r/mongo_java_3.result @@ -1,4 +1,5 @@ SET GLOBAL connect_class_path='C:/MariaDB-10.2/MariaDB/storage/connect/mysql-test/connect/std_data/Mongo3.jar'; +set connect_enable_mongo=1; # # Test the MONGO table type # @@ -377,3 +378,4 @@ planner 167 41.75 postcard 23 5.75 DROP TABLE t1; true +set connect_enable_mongo=0; diff --git a/storage/connect/mysql-test/connect/r/odbc_oracle.result b/storage/connect/mysql-test/connect/r/odbc_oracle.result index db7f78f67cd..8dc7dc07bb1 100644 --- a/storage/connect/mysql-test/connect/r/odbc_oracle.result +++ b/storage/connect/mysql-test/connect/r/odbc_oracle.result @@ -72,11 +72,11 @@ TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr' CATFUNC=Columns; SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name; Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks -NULL MTR T1 A 3 DECIMAL 38 40 0 10 1 NULL -NULL MTR T1 B 6 NUMBER 38 40 NULL NULL 1 NULL -NULL MTR T2 A 12 VARCHAR2 64 64 NULL NULL 1 NULL -NULL MTR V1 A 3 DECIMAL 38 40 0 10 1 NULL -NULL MTR V1 B 6 NUMBER 38 40 NULL NULL 1 NULL + MTR T1 A 3 DECIMAL 38 40 0 10 1 + MTR T1 B 6 NUMBER 38 40 NULL NULL 1 + MTR T2 A 12 VARCHAR2 64 64 NULL NULL 1 + MTR V1 A 3 DECIMAL 38 40 0 10 1 + MTR V1 B 6 NUMBER 38 40 NULL NULL 1 DROP TABLE t1; # All columns in all schemas (limited with WHERE) CREATE TABLE t1 ENGINE=CONNECT @@ -84,18 +84,18 @@ TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr' CATFUNC=Columns TABNAME='%.%'; SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name; Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks -NULL MTR T1 A 3 DECIMAL 38 40 0 10 1 NULL -NULL MTR T1 B 6 NUMBER 38 40 NULL NULL 1 NULL -NULL MTR T2 A 12 VARCHAR2 64 64 NULL NULL 1 NULL -NULL MTR V1 A 3 DECIMAL 38 40 0 10 1 NULL -NULL MTR V1 B 6 NUMBER 38 40 NULL NULL 1 NULL + MTR T1 A 3 DECIMAL 38 40 0 10 1 + MTR T1 B 6 NUMBER 38 40 NULL NULL 1 + MTR T2 A 12 VARCHAR2 64 64 NULL NULL 1 + MTR V1 A 3 DECIMAL 38 40 0 10 1 + MTR V1 B 6 NUMBER 38 40 NULL NULL 1 DROP TABLE t1; # All tables "T1" in all schemas (limited with WHERE) CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr' CATFUNC=Columns TABNAME='%.T1'; SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name; Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks -NULL MTR T1 A 3 DECIMAL 38 40 0 10 1 NULL -NULL MTR T1 B 6 NUMBER 38 40 NULL NULL 1 NULL + MTR T1 A 3 DECIMAL 38 40 0 10 1 + MTR T1 B 6 NUMBER 38 40 NULL NULL 1 DROP TABLE t1; # Table "T1" in the schema "MTR" CREATE TABLE t1 ENGINE=CONNECT @@ -103,8 +103,8 @@ TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr' CATFUNC=Columns TABNAME='MTR.T1'; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name; Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks -NULL MTR T1 A 3 DECIMAL 38 40 0 10 1 NULL -NULL MTR T1 B 6 NUMBER 38 40 NULL NULL 1 NULL + MTR T1 A 3 DECIMAL 38 40 0 10 1 + MTR T1 B 6 NUMBER 38 40 NULL NULL 1 DROP TABLE t1; # All tables "T1" in all schemas (filtered with WHERE) CREATE TABLE t1 ENGINE=CONNECT @@ -112,8 +112,8 @@ TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr' CATFUNC=Columns TABNAME='%.T1'; SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name; Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks -NULL MTR T1 A 3 DECIMAL 38 40 0 10 1 NULL -NULL MTR T1 B 6 NUMBER 38 40 NULL NULL 1 NULL + MTR T1 A 3 DECIMAL 38 40 0 10 1 + MTR T1 B 6 NUMBER 38 40 NULL NULL 1 DROP TABLE t1; # # Checking tables diff --git a/storage/connect/mysql-test/connect/r/tbl_thread.result b/storage/connect/mysql-test/connect/r/tbl_thread.result index ef6439462bb..f53ccd25b97 100644 --- a/storage/connect/mysql-test/connect/r/tbl_thread.result +++ b/storage/connect/mysql-test/connect/r/tbl_thread.result @@ -35,6 +35,22 @@ a b 9 test09 10 test10 11 test11 +CREATE TABLE rt4 (a int, b char(10)); +INSERT INTO rt4 VALUES (12,'test12'),(13,'test13'),(14,'test14'),(15,'test15'); +SELECT * FROM rt4; +a b +12 test12 +13 test13 +14 test14 +15 test15 +CREATE TABLE rt5 (a int, b char(10)); +INSERT INTO rt5 VALUES (16,'test16'),(17,'test17'),(18,'test18'),(19,'test19'); +SELECT * FROM rt5; +a b +16 test16 +17 test17 +18 test18 +19 test19 connection default; CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL CONNECTION='mysql://root@127.0.0.1:MASTER_PORT/test/rt2'; @@ -52,11 +68,36 @@ a b 9 test09 10 test10 11 test11 +CREATE TABLE t4 ENGINE=CONNECT TABLE_TYPE=MYSQL +CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/test/rt4'; +SELECT * FROM t4; +a b +12 test12 +13 test13 +14 test14 +15 test15 +CREATE TABLE t5 ENGINE=CONNECT TABLE_TYPE=MYSQL +CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/test/rt5'; +SELECT * FROM t5; +a b +16 test16 +17 test17 +18 test18 +19 test19 CREATE TABLE total (a int, b char(10)) -ENGINE=CONNECT TABLE_TYPE=TBL TABLE_LIST='t1,t2,t3' +ENGINE=CONNECT TABLE_TYPE=TBL TABLE_LIST='t1,t2,t3,t4,t5' OPTION_LIST='thread=yes,port=PORT'; +set connect_xtrace=1; SELECT * FROM total order by a desc; a b +19 test19 +18 test18 +17 test17 +16 test16 +15 test15 +14 test14 +13 test13 +12 test12 11 test11 10 test10 9 test09 @@ -69,12 +110,13 @@ a b 2 test02 1 test01 0 test00 +set connect_xtrace=0; connection master; DROP TABLE rt2; connection slave; -DROP TABLE rt3; +DROP TABLE rt3,rt4,rt5; connection default; -DROP TABLE t1,t2,t3,total; +DROP TABLE t1,t2,t3,t4,t5,total; # # Old thread TBL tables test modified # @@ -87,13 +129,15 @@ SELECT * FROM t2; v 22 CREATE TABLE total (v BIGINT(20) UNSIGNED NOT NULL) ENGINE=CONNECT TABLE_TYPE=TBL TABLE_LIST='t1,t2' OPTION_LIST='thread=yes,port=PORT';; +set connect_xtrace=1; SELECT * FROM total order by v desc; v 22 11 +set connect_xtrace=0; DROP TABLE t1,t2,total; # -# Old thread TBL tables test not modified +# Old thread TBL tables test not modified (suppressed until MDEV-10179 is fixed) # CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL SRCDEF='select 11 as v'; SELECT * FROM t1; @@ -104,10 +148,12 @@ SELECT * FROM t2; v 22 CREATE TABLE total (v BIGINT(20) UNSIGNED NOT NULL) ENGINE=CONNECT TABLE_TYPE=TBL TABLE_LIST='t1,t2' OPTION_LIST='thread=yes,port=PORT';; +set connect_xtrace=1; SELECT * FROM total order by v desc; v 22 11 +set connect_xtrace=0; DROP TABLE total; DROP TABLE t1; DROP TABLE t2; diff --git a/storage/connect/mysql-test/connect/std_data/Mongo2.jar b/storage/connect/mysql-test/connect/std_data/Mongo2.jar Binary files differindex d019bf6906b..9be654bd4c8 100644 --- a/storage/connect/mysql-test/connect/std_data/Mongo2.jar +++ b/storage/connect/mysql-test/connect/std_data/Mongo2.jar diff --git a/storage/connect/mysql-test/connect/std_data/Mongo3.jar b/storage/connect/mysql-test/connect/std_data/Mongo3.jar Binary files differindex 73eb3571290..2850177a668 100644 --- a/storage/connect/mysql-test/connect/std_data/Mongo3.jar +++ b/storage/connect/mysql-test/connect/std_data/Mongo3.jar diff --git a/storage/connect/mysql-test/connect/t/mongo_test.inc b/storage/connect/mysql-test/connect/t/mongo_test.inc index c223e70f719..c728b85fd2f 100644 --- a/storage/connect/mysql-test/connect/t/mongo_test.inc +++ b/storage/connect/mysql-test/connect/t/mongo_test.inc @@ -1,3 +1,5 @@ +set connect_enable_mongo=1; + --echo # --echo # Test the MONGO table type --echo # @@ -201,3 +203,5 @@ OPTION_LIST='Driver=$DRV,Version=$VERS,Pipeline=YES' $CONN; SELECT * FROM t1; DROP TABLE t1; --exec $MONGO --eval "db.testcoll.drop()" --quiet + +set connect_enable_mongo=0; diff --git a/storage/connect/mysql-test/connect/t/tbl_thread.test b/storage/connect/mysql-test/connect/t/tbl_thread.test index abc1ef34729..68a0ebcd44d 100644 --- a/storage/connect/mysql-test/connect/t/tbl_thread.test +++ b/storage/connect/mysql-test/connect/t/tbl_thread.test @@ -2,8 +2,6 @@ connection default; -let $PORT= `select @@port`; - --echo # --echo # Checking thread TBL tables --echo # @@ -24,6 +22,14 @@ CREATE TABLE rt3 (a int, b char(10)); INSERT INTO rt3 VALUES (8,'test08'),(9,'test09'),(10,'test10'),(11,'test11'); SELECT * FROM rt3; +CREATE TABLE rt4 (a int, b char(10)); +INSERT INTO rt4 VALUES (12,'test12'),(13,'test13'),(14,'test14'),(15,'test15'); +SELECT * FROM rt4; + +CREATE TABLE rt5 (a int, b char(10)); +INSERT INTO rt5 VALUES (16,'test16'),(17,'test17'),(18,'test18'),(19,'test19'); +SELECT * FROM rt5; + connection default; --replace_result $MASTER_MYPORT MASTER_PORT @@ -36,11 +42,23 @@ eval CREATE TABLE t3 ENGINE=CONNECT TABLE_TYPE=MYSQL CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/rt3'; SELECT * FROM t3; +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval CREATE TABLE t4 ENGINE=CONNECT TABLE_TYPE=MYSQL +CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/rt4'; +SELECT * FROM t4; + +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval CREATE TABLE t5 ENGINE=CONNECT TABLE_TYPE=MYSQL +CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/rt5'; +SELECT * FROM t5; + --replace_result $PORT PORT eval CREATE TABLE total (a int, b char(10)) -ENGINE=CONNECT TABLE_TYPE=TBL TABLE_LIST='t1,t2,t3' +ENGINE=CONNECT TABLE_TYPE=TBL TABLE_LIST='t1,t2,t3,t4,t5' OPTION_LIST='thread=yes,port=$PORT'; +set connect_xtrace=1; SELECT * FROM total order by a desc; +set connect_xtrace=0; connection master; @@ -48,11 +66,11 @@ DROP TABLE rt2; connection slave; -DROP TABLE rt3; +DROP TABLE rt3,rt4,rt5; connection default; -DROP TABLE t1,t2,t3,total; +DROP TABLE t1,t2,t3,t4,t5,total; --echo # --echo # Old thread TBL tables test modified @@ -67,11 +85,13 @@ SELECT * FROM t2; --replace_result $PORT PORT --eval CREATE TABLE total (v BIGINT(20) UNSIGNED NOT NULL) ENGINE=CONNECT TABLE_TYPE=TBL TABLE_LIST='t1,t2' OPTION_LIST='thread=yes,port=$PORT'; +set connect_xtrace=1; SELECT * FROM total order by v desc; +set connect_xtrace=0; DROP TABLE t1,t2,total; --echo # ---echo # Old thread TBL tables test not modified +--echo # Old thread TBL tables test not modified (suppressed until MDEV-10179 is fixed) --echo # CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL SRCDEF='select 11 as v'; SELECT * FROM t1; @@ -81,7 +101,9 @@ SELECT * FROM t2; --replace_result $PORT PORT --eval CREATE TABLE total (v BIGINT(20) UNSIGNED NOT NULL) ENGINE=CONNECT TABLE_TYPE=TBL TABLE_LIST='t1,t2' OPTION_LIST='thread=yes,port=$PORT'; +set connect_xtrace=1; SELECT * FROM total order by v desc; +set connect_xtrace=0; DROP TABLE total; DROP TABLE t1; diff --git a/storage/connect/myutil.cpp b/storage/connect/myutil.cpp index c2053f1c832..338a79d9455 100644 --- a/storage/connect/myutil.cpp +++ b/storage/connect/myutil.cpp @@ -218,7 +218,7 @@ int MYSQLtoPLG(int mytype, char *var) case MYSQL_TYPE_VARCHAR: #endif // !ALPHA) case MYSQL_TYPE_STRING: - type = TYPE_STRING; + type = (*var == 'B') ? TYPE_BIN : TYPE_STRING; break; case MYSQL_TYPE_BLOB: case MYSQL_TYPE_TINY_BLOB: @@ -232,7 +232,7 @@ int MYSQLtoPLG(int mytype, char *var) type = TYPE_STRING; *var = 'X'; } else - type = TYPE_ERROR; + type = TYPE_BIN; break; case TPC_SKIP: diff --git a/storage/connect/reldef.cpp b/storage/connect/reldef.cpp index 95069baf76e..031fdebe650 100644 --- a/storage/connect/reldef.cpp +++ b/storage/connect/reldef.cpp @@ -789,7 +789,7 @@ int COLDEF::Define(PGLOBAL g, void *, PCOLINFO cfp, int poff) Poff = poff; Buf_Type = cfp->Type; - if ((Clen = GetTypeSize(Buf_Type, cfp->Length)) <= 0) { + if ((Clen = GetTypeSize(Buf_Type, cfp->Length)) < 0) { sprintf(g->Message, MSG(BAD_COL_TYPE), GetTypeName(Buf_Type), Name); return -1; } // endswitch diff --git a/storage/connect/reldef.h b/storage/connect/reldef.h index 8b19a413ade..84ae2a491f0 100644 --- a/storage/connect/reldef.h +++ b/storage/connect/reldef.h @@ -94,6 +94,7 @@ public: virtual void SetIndx(PIXDEF) {} virtual bool IsHuge(void) {return false;} const CHARSET_INFO *data_charset() {return m_data_charset;} + const char *GetCsName(void) {return csname;} // Methods int GetColCatInfo(PGLOBAL g); diff --git a/storage/connect/tabext.cpp b/storage/connect/tabext.cpp index 1d76e0417fa..207c8401c7b 100644 --- a/storage/connect/tabext.cpp +++ b/storage/connect/tabext.cpp @@ -279,10 +279,57 @@ int TDBEXT::Decode(PCSZ txt, char *buf, size_t n) } // end of Decode /***********************************************************************/ -/* MakeSQL: make the SQL statement use with remote connection. */ -/* TODO: when implementing remote filtering, column only used in */ -/* local filter should be removed from column list. */ +/* MakeSrcdef: make the SQL statement from SRDEF option. */ /***********************************************************************/ +bool TDBEXT::MakeSrcdef(PGLOBAL g) +{ + char *catp = strstr(Srcdef, "%s"); + + if (catp) { + char *fil1= 0, *fil2; + PCSZ ph = ((EXTDEF*)To_Def)->Phpos; + + if (!ph) + ph = (strstr(catp + 2, "%s")) ? "WH" : "W"; + + if (stricmp(ph, "H")) { + fil1 = (To_CondFil && *To_CondFil->Body) + ? To_CondFil->Body : PlugDup(g, "1=1"); + } // endif ph + + if (stricmp(ph, "W")) { + fil2 = (To_CondFil && To_CondFil->Having && *To_CondFil->Having) + ? To_CondFil->Having : PlugDup(g, "1=1"); + } // endif ph + + if (!stricmp(ph, "W")) { + Query = new(g)STRING(g, strlen(Srcdef) + strlen(fil1)); + Query->SetLength(sprintf(Query->GetStr(), Srcdef, fil1)); + } else if (!stricmp(ph, "WH")) { + Query = new(g)STRING(g, strlen(Srcdef) + strlen(fil1) + strlen(fil2)); + Query->SetLength(sprintf(Query->GetStr(), Srcdef, fil1, fil2)); + } else if (!stricmp(ph, "H")) { + Query = new(g)STRING(g, strlen(Srcdef) + strlen(fil2)); + Query->SetLength(sprintf(Query->GetStr(), Srcdef, fil2)); + } else if (!stricmp(ph, "HW")) { + Query = new(g)STRING(g, strlen(Srcdef) + strlen(fil1) + strlen(fil2)); + Query->SetLength(sprintf(Query->GetStr(), Srcdef, fil2, fil1)); + } else { + strcpy(g->Message, "MakeSQL: Wrong place holders specification"); + return true; + } // endif's ph + + } else + Query = new(g)STRING(g, 0, Srcdef); + + return false; +} // end of MakeSrcdef + + /***********************************************************************/ + /* MakeSQL: make the SQL statement use with remote connection. */ + /* TODO: when implementing remote filtering, column only used in */ + /* local filter should be removed from column list. */ + /***********************************************************************/ bool TDBEXT::MakeSQL(PGLOBAL g, bool cnt) { PCSZ schmp = NULL; @@ -292,46 +339,8 @@ bool TDBEXT::MakeSQL(PGLOBAL g, bool cnt) PTABLE tablep = To_Table; PCOL colp; - if (Srcdef) { - if ((catp = strstr(Srcdef, "%s"))) { - char *fil1= 0, *fil2; - PCSZ ph = ((EXTDEF*)To_Def)->Phpos; - - if (!ph) - ph = (strstr(catp + 2, "%s")) ? "WH" : "W"; - - if (stricmp(ph, "H")) { - fil1 = (To_CondFil && *To_CondFil->Body) - ? To_CondFil->Body : PlugDup(g, "1=1"); - } // endif ph - - if (stricmp(ph, "W")) { - fil2 = (To_CondFil && To_CondFil->Having && *To_CondFil->Having) - ? To_CondFil->Having : PlugDup(g, "1=1"); - } // endif ph - - if (!stricmp(ph, "W")) { - Query = new(g)STRING(g, strlen(Srcdef) + strlen(fil1)); - Query->SetLength(sprintf(Query->GetStr(), Srcdef, fil1)); - } else if (!stricmp(ph, "WH")) { - Query = new(g)STRING(g, strlen(Srcdef) + strlen(fil1) + strlen(fil2)); - Query->SetLength(sprintf(Query->GetStr(), Srcdef, fil1, fil2)); - } else if (!stricmp(ph, "H")) { - Query = new(g)STRING(g, strlen(Srcdef) + strlen(fil2)); - Query->SetLength(sprintf(Query->GetStr(), Srcdef, fil2)); - } else if (!stricmp(ph, "HW")) { - Query = new(g)STRING(g, strlen(Srcdef) + strlen(fil1) + strlen(fil2)); - Query->SetLength(sprintf(Query->GetStr(), Srcdef, fil2, fil1)); - } else { - strcpy(g->Message, "MakeSQL: Wrong place holders specification"); - return true; - } // endif's ph - - } else - Query = new(g)STRING(g, 0, Srcdef); - - return false; - } // endif Srcdef + if (Srcdef) + return MakeSrcdef(g); // Allocate the string used to contain the Query Query = new(g)STRING(g, 1023, "SELECT "); diff --git a/storage/connect/tabext.h b/storage/connect/tabext.h index 7ddf2a68117..6b67c2ab5ed 100644 --- a/storage/connect/tabext.h +++ b/storage/connect/tabext.h @@ -126,6 +126,7 @@ public: protected: // Internal functions + virtual bool MakeSrcdef(PGLOBAL g); virtual bool MakeSQL(PGLOBAL g, bool cnt); //virtual bool MakeInsert(PGLOBAL g); virtual bool MakeCommand(PGLOBAL g); diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp index 76a3d5e9988..401441520da 100644 --- a/storage/connect/tabjson.cpp +++ b/storage/connect/tabjson.cpp @@ -136,6 +136,7 @@ PQRYRES JSONColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt, bool info) tdp->Base = GetIntegerTableOption(g, topt, "Base", 0) ? 1 : 0; tdp->Pretty = GetIntegerTableOption(g, topt, "Pretty", 2); tdp->Xcol = GetStringTableOption(g, topt, "Expand", NULL); + tdp->Accept = GetBooleanTableOption(g, topt, "Accept", false); tdp->Uri = (dsn && *dsn ? dsn : NULL); if (!tdp->Fn && !tdp->Uri) { @@ -365,7 +366,7 @@ PQRYRES JSONColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt, bool info) jcp->Scale = MY_MAX(jcp->Scale, jcol.Scale); jcp->Cbn |= jcol.Cbn; jcp->Found = true; - } else { + } else if (jcol.Type != TYPE_UNKNOWN || tdp->Accept) { // New column jcp = (PJCL)PlugSubAlloc(g, NULL, sizeof(JCOL)); *jcp = jcol; @@ -448,8 +449,8 @@ PQRYRES JSONColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt, bool info) /* Now get the results into blocks. */ /*********************************************************************/ for (i = 0, jcp = fjcp; jcp; i++, jcp = jcp->Next) { - if (jcp->Type == TYPE_UNKNOWN) // Void column - jcp->Type = TYPE_STRING; + if (jcp->Type == TYPE_UNKNOWN) + jcp->Type = TYPE_STRING; // Void column crp = qrp->Colresp; // Column Name crp->Kdata->SetValue(jcp->Name, i); diff --git a/storage/connect/tabmysql.cpp b/storage/connect/tabmysql.cpp index bdddcf64ca8..d1e2ae69608 100644 --- a/storage/connect/tabmysql.cpp +++ b/storage/connect/tabmysql.cpp @@ -513,18 +513,8 @@ bool TDBMYSQL::MakeSelect(PGLOBAL g, bool mx) if (Query) return false; // already done - if (Srcdef) { - if (strstr(Srcdef, "%s")) { - char *fil; - - fil = (To_CondFil) ? To_CondFil->Body : PlugDup(g, "1=1"); - Query = new(g)STRING(g, strlen(Srcdef) + strlen(fil)); - Query->SetLength(sprintf(Query->GetStr(), Srcdef, fil)); - } else - Query = new(g)STRING(g, 0, Srcdef); - - return false; - } // endif Srcdef + if (Srcdef) + return MakeSrcdef(g); // Allocate the string used to contain Query Query = new(g) STRING(g, 1023, "SELECT "); @@ -1270,7 +1260,8 @@ MYSQLCOL::MYSQLCOL(MYSQL_FIELD *fld, PTDB tdbp, int i, PCSZ am) : COLBLK(NULL, tdbp, i) { const char *chset = get_charset_name(fld->charsetnr); - char v = (!strcmp(chset, "binary")) ? 'B' : 0; +//char v = (!strcmp(chset, "binary")) ? 'B' : 0; + char v = 0; Name = fld->name; Opt = 0; diff --git a/storage/connect/tabmysql.h b/storage/connect/tabmysql.h index 3c37ae5bf3b..39fba87bcc9 100644 --- a/storage/connect/tabmysql.h +++ b/storage/connect/tabmysql.h @@ -69,6 +69,7 @@ class MYSQLDEF : public EXTDEF {/* Logical table description */ /***********************************************************************/ class TDBMYSQL : public TDBEXT { friend class MYSQLCOL; + friend class TDBTBM; public: // Constructor TDBMYSQL(PMYDEF tdp); diff --git a/storage/connect/tabtbl.cpp b/storage/connect/tabtbl.cpp index afd6b47c5a2..6e4a038ec92 100644 --- a/storage/connect/tabtbl.cpp +++ b/storage/connect/tabtbl.cpp @@ -578,10 +578,19 @@ pthread_handler_t ThreadOpen(void *p) // Try to open the connection if (!cmp->Tap->GetTo_Tdb()->OpenDB(cmp->G)) { pthread_mutex_lock(&tblmut); + if (trace) + htrc("Table %s ready\n", cmp->Tap->GetName()); + cmp->Ready = true; pthread_mutex_unlock(&tblmut); - } else - cmp->Rc = RC_FX; + } else { + pthread_mutex_lock(&tblmut); + if (trace) + htrc("Opening %s failed\n", cmp->Tap->GetName()); + + cmp->Rc = RC_FX; + pthread_mutex_unlock(&tblmut); + } // endif OpenDB my_thread_end(); } else @@ -633,6 +642,18 @@ int TDBTBM::RowNumber(PGLOBAL g, bool b) } // end of RowNumber /***********************************************************************/ +/* Returns true if this MYSQL table refers to a local table. */ +/***********************************************************************/ +bool TDBTBM::IsLocal(PTABLE tbp) +{ + TDBMYSQL *tdbp = (TDBMYSQL*)tbp->GetTo_Tdb(); + + return ((!stricmp(tdbp->Host, "localhost") || + !strcmp(tdbp->Host, "127.0.0.1")) && + tdbp->Port == GetDefaultPort()); +} // end of IsLocal + +/***********************************************************************/ /* Initialyze table parallel processing. */ /***********************************************************************/ bool TDBTBM::OpenTables(PGLOBAL g) @@ -644,10 +665,13 @@ bool TDBTBM::OpenTables(PGLOBAL g) // Allocates the TBMT blocks for the tables for (tabp = Tablist; tabp; tabp = tabp->Next) - if (tabp->GetTo_Tdb()->GetAmType() == TYPE_AM_MYSQL) { + if (tabp->GetTo_Tdb()->GetAmType() == TYPE_AM_MYSQL && !IsLocal(tabp)) { // Remove remote table from the local list *ptabp = tabp->Next; + if (trace) + htrc("=====> New remote table %s\n", tabp->GetName()); + // Make the remote table block tp = (PTBMT)PlugSubAlloc(g, NULL, sizeof(TBMT)); memset(tp, 0, sizeof(TBMT)); @@ -671,7 +695,10 @@ bool TDBTBM::OpenTables(PGLOBAL g) ptp = &tp->Next; Nrc++; // Number of remote connections } else { - ptabp = &tabp->Next; + if (trace) + htrc("=====> Local table %s\n", tabp->GetName()); + + ptabp = &tabp->Next; Nlc++; // Number of local connections } // endif Type @@ -788,7 +815,7 @@ int TDBTBM::ReadDB(PGLOBAL g) /***********************************************************************/ int TDBTBM::ReadNextRemote(PGLOBAL g) { - bool b = false; + bool b; if (Tdbp) Tdbp->CloseDB(g); @@ -796,17 +823,22 @@ int TDBTBM::ReadNextRemote(PGLOBAL g) Cmp = NULL; retry: - // Search for a remote table having its result set + b = false; + + // Search for a remote table having its result set pthread_mutex_lock(&tblmut); for (PTBMT tp = Tmp; tp; tp = tp->Next) - if (tp->Ready) { - if (!tp->Complete) { - Cmp = tp; - break; - } // endif Complete + if (tp->Rc != RC_FX) { + if (tp->Ready) { + if (!tp->Complete) { + Cmp = tp; + break; + } // endif Complete - } else - b = true; + } else + b = true; + + } // endif Rc pthread_mutex_unlock(&tblmut); diff --git a/storage/connect/tabtbl.h b/storage/connect/tabtbl.h index 3a5ec45d025..f02bf620aae 100644 --- a/storage/connect/tabtbl.h +++ b/storage/connect/tabtbl.h @@ -146,6 +146,7 @@ class DllExport TDBTBM : public TDBTBL { protected: // Internal functions + bool IsLocal(PTABLE tbp); bool OpenTables(PGLOBAL g); int ReadNextRemote(PGLOBAL g); diff --git a/storage/connect/tabutil.cpp b/storage/connect/tabutil.cpp index 158cf744a4a..9ab3d5e8806 100644 --- a/storage/connect/tabutil.cpp +++ b/storage/connect/tabutil.cpp @@ -186,7 +186,8 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db, crp->Kdata->SetValue(colname, i); chset = (char *)fp->charset()->name; - v = (!strcmp(chset, "binary")) ? 'B' : 0; +// v = (!strcmp(chset, "binary")) ? 'B' : 0; + v = 0; if ((type = MYSQLtoPLG(fp->type(), &v)) == TYPE_ERROR) { if (v == 'K') { diff --git a/storage/connect/valblk.cpp b/storage/connect/valblk.cpp index 5b98f3eb425..018c7ee3fe1 100644 --- a/storage/connect/valblk.cpp +++ b/storage/connect/valblk.cpp @@ -59,11 +59,12 @@ PVBLK AllocValBlock(PGLOBAL g, void *mp, int type, int nval, int len, switch (type) { case TYPE_STRING: + case TYPE_BIN: case TYPE_DECIM: if (len) - blkp = new(g) CHRBLK(mp, nval, len, prec, blank); + blkp = new(g) CHRBLK(mp, nval, type, len, prec, blank); else - blkp = new(g) STRBLK(g, mp, nval); + blkp = new(g) STRBLK(g, mp, nval, type); break; case TYPE_SHORT: @@ -615,8 +616,8 @@ int TYPBLK<TYPE>::GetMaxLength(void) /***********************************************************************/ /* Constructor. */ /***********************************************************************/ -CHRBLK::CHRBLK(void *mp, int nval, int len, int prec, bool blank) - : VALBLK(mp, TYPE_STRING, nval), Chrp((char*&)Blkp) +CHRBLK::CHRBLK(void *mp, int nval, int type, int len, int prec, bool blank) + : VALBLK(mp, type, nval), Chrp((char*&)Blkp) { Valp = NULL; Blanks = blank; @@ -1008,8 +1009,8 @@ int CHRBLK::GetMaxLength(void) /***********************************************************************/ /* Constructor. */ /***********************************************************************/ -STRBLK::STRBLK(PGLOBAL g, void *mp, int nval) - : VALBLK(mp, TYPE_STRING, nval), Strp((PSZ*&)Blkp) +STRBLK::STRBLK(PGLOBAL g, void *mp, int nval, int type) + : VALBLK(mp, type, nval), Strp((PSZ*&)Blkp) { Global = g; Nullable = true; diff --git a/storage/connect/valblk.h b/storage/connect/valblk.h index 38a73424985..a3d7bf30fcf 100644 --- a/storage/connect/valblk.h +++ b/storage/connect/valblk.h @@ -214,7 +214,7 @@ class TYPBLK : public VALBLK { class CHRBLK : public VALBLK { public: // Constructors - CHRBLK(void *mp, int size, int len, int prec, bool b); + CHRBLK(void *mp, int size, int type, int len, int prec, bool b); // Implementation virtual bool Init(PGLOBAL g, bool check); @@ -267,7 +267,7 @@ class CHRBLK : public VALBLK { class STRBLK : public VALBLK { public: // Constructors - STRBLK(PGLOBAL g, void *mp, int size); + STRBLK(PGLOBAL g, void *mp, int size, int type); // Implementation virtual void SetNull(int n, bool b) {if (b) {Strp[n] = NULL;}} @@ -345,7 +345,7 @@ class PTRBLK : public STRBLK { bool, bool, bool); protected: // Constructors - PTRBLK(PGLOBAL g, void *mp, int size) : STRBLK(g, mp, size) {} + PTRBLK(PGLOBAL g, void *mp, int size) : STRBLK(g, mp, size, TYPE_PCHAR) {} // Implementation diff --git a/storage/connect/value.cpp b/storage/connect/value.cpp index 60d1c2f459c..a80da808548 100644 --- a/storage/connect/value.cpp +++ b/storage/connect/value.cpp @@ -176,7 +176,7 @@ int GetTypeSize(int type, int len) case TYPE_DOUBLE: len = sizeof(double); break; case TYPE_TINY: len = sizeof(char); break; case TYPE_PCHAR: len = sizeof(char*); break; - default: len = 0; + default: len = -1; } // endswitch type return len; @@ -236,6 +236,7 @@ bool IsTypeChar(int type) switch (type) { case TYPE_STRING: case TYPE_DECIM: + case TYPE_BIN: return true; } // endswitch type @@ -1369,7 +1370,7 @@ bool TYPVAL<PSZ>::SetValue_char(const char *cp, int n) if (!cp || n == 0) { Reset(); - Null = Nullable; + Null = (cp) ? false : Nullable; } else if (cp != Strp) { const char *p = cp + n - 1; @@ -1858,8 +1859,9 @@ int DECVAL::CompareValue(PVAL vp) BINVAL::BINVAL(PGLOBAL g, void *p, int cl, int n) : VALUE(TYPE_BIN) { assert(g); - Len = n; - Clen = cl; +//Len = n; + Len = (g) ? n : (p) ? strlen((char*)p) : 0; + Clen = cl; Binp = PlugSubAlloc(g, NULL, Clen + 1); memset(Binp, 0, Clen + 1); @@ -1992,10 +1994,15 @@ bool BINVAL::SetValue_pval(PVAL valp, bool chktype) return true; if (!(Null = valp->IsNull() && Nullable)) { - if ((rc = (Len = valp->GetSize()) > Clen)) + int len = Len; + + if ((rc = (Len = valp->GetSize()) > Clen)) Len = Clen; + else if (len > Len) + memset(Binp, 0, len); memcpy(Binp, valp->GetTo_Val(), Len); + ((char*)Binp)[Len] = 0; } else Reset(); @@ -2012,10 +2019,15 @@ bool BINVAL::SetValue_char(const char *p, int n) bool rc; if (p && n > 0) { - rc = n > Clen; - Len = MY_MIN(n, Clen); - memcpy(Binp, p, Len); - Null = false; + int len = Len; + + if (len > (Len = MY_MIN(n, Clen))) + memset(Binp, 0, len); + + memcpy(Binp, p, Len); + ((char*)Binp)[Len] = 0; + rc = n > Clen; + Null = false; } else { rc = false; Reset(); @@ -2031,9 +2043,14 @@ bool BINVAL::SetValue_char(const char *p, int n) void BINVAL::SetValue_psz(PCSZ s) { if (s) { - Len = MY_MIN(Clen, (signed)strlen(s)); - memcpy(Binp, s, Len); - Null = false; + int len = Len; + + if (len > (Len = MY_MIN(Clen, (signed)strlen(s)))) + memset(Binp, 0, len); + + memcpy(Binp, s, Len); + ((char*)Binp)[Len] = 0; + Null = false; } else { Reset(); Null = Nullable; @@ -2053,14 +2070,19 @@ void BINVAL::SetValue_pvblk(PVBLK blk, int n) Reset(); Null = Nullable; } else if (vp != Binp) { + int len = Len; + if (blk->GetType() == TYPE_STRING) Len = strlen((char*)vp); else Len = blk->GetVlen(); - Len = MY_MIN(Clen, Len); + if (len > (Len = MY_MIN(Clen, Len))) + memset(Binp, 0, len); + memcpy(Binp, vp, Len); - Null = false; + ((char*)Binp)[Len] = 0; + Null = false; } // endif vp } // end of SetValue_pvblk @@ -2071,7 +2093,10 @@ void BINVAL::SetValue_pvblk(PVBLK blk, int n) void BINVAL::SetValue(int n) { if (Clen >= 4) { - *((int*)Binp) = n; + if (Len > 4) + memset(Binp, 0, Len); + + *((int*)Binp) = n; Len = 4; } else SetValue((short)n); @@ -2084,7 +2109,10 @@ void BINVAL::SetValue(int n) void BINVAL::SetValue(uint n) { if (Clen >= 4) { - *((uint*)Binp) = n; + if (Len > 4) + memset(Binp, 0, Len); + + *((uint*)Binp) = n; Len = 4; } else SetValue((ushort)n); @@ -2097,7 +2125,10 @@ void BINVAL::SetValue(uint n) void BINVAL::SetValue(short i) { if (Clen >= 2) { - *((int*)Binp) = i; + if (Len > 2) + memset(Binp, 0, Len); + + *((int*)Binp) = i; Len = 2; } else SetValue((char)i); @@ -2110,7 +2141,10 @@ void BINVAL::SetValue(short i) void BINVAL::SetValue(ushort i) { if (Clen >= 2) { - *((uint*)Binp) = i; + if (Len > 2) + memset(Binp, 0, Len); + + *((uint*)Binp) = i; Len = 2; } else SetValue((uchar)i); @@ -2123,7 +2157,10 @@ void BINVAL::SetValue(ushort i) void BINVAL::SetValue(longlong n) { if (Clen >= 8) { - *((longlong*)Binp) = n; + if (Len > 8) + memset(Binp, 0, Len); + + *((longlong*)Binp) = n; Len = 8; } else SetValue((int)n); @@ -2136,7 +2173,10 @@ void BINVAL::SetValue(longlong n) void BINVAL::SetValue(ulonglong n) { if (Clen >= 8) { - *((ulonglong*)Binp) = n; + if (Len > 8) + memset(Binp, 0, Len); + + *((ulonglong*)Binp) = n; Len = 8; } else SetValue((uint)n); @@ -2147,6 +2187,9 @@ void BINVAL::SetValue(ulonglong n) /***********************************************************************/ void BINVAL::SetValue(double n) { + if (Len > 8) + memset(Binp, 0, Len); + if (Clen >= 8) { *((double*)Binp) = n; Len = 8; @@ -2163,7 +2206,10 @@ void BINVAL::SetValue(double n) /***********************************************************************/ void BINVAL::SetValue(char c) { - *((char*)Binp) = c; + if (Len > 1) + memset(Binp, 0, Len); + + *((char*)Binp) = c; Len = 1; } // end of SetValue @@ -2172,7 +2218,10 @@ void BINVAL::SetValue(char c) /***********************************************************************/ void BINVAL::SetValue(uchar c) { - *((uchar*)Binp) = c; + if (Len > 1) + memset(Binp, 0, Len); + + *((uchar*)Binp) = c; Len = 1; } // end of SetValue @@ -2182,6 +2231,7 @@ void BINVAL::SetValue(uchar c) void BINVAL::SetBinValue(void *p) { memcpy(Binp, p, Clen); + Len = Clen; } // end of SetBinValue /***********************************************************************/ @@ -2207,10 +2257,11 @@ bool BINVAL::GetBinValue(void *buf, int buflen, bool go) /***********************************************************************/ char *BINVAL::ShowValue(char *buf, int len) { - int n = MY_MIN(Len, len / 2); + //int n = MY_MIN(Len, len / 2); - sprintf(buf, GetXfmt(), n, Binp); - return buf; + //sprintf(buf, GetXfmt(), n, Binp); + //return buf; + return (char*)Binp; } // end of ShowValue /***********************************************************************/ diff --git a/storage/federated/ha_federated.cc b/storage/federated/ha_federated.cc index e35da50ba96..059113e2fa5 100644 --- a/storage/federated/ha_federated.cc +++ b/storage/federated/ha_federated.cc @@ -2980,6 +2980,9 @@ int ha_federated::reset(void) } reset_dynamic(&results); + if (mysql) + mysql->net.thd= NULL; + return 0; } @@ -3200,12 +3203,14 @@ int ha_federated::real_query(const char *query, size_t length) int rc= 0; DBUG_ENTER("ha_federated::real_query"); - if (!mysql && (rc= real_connect())) + if (!query || !length) goto end; - if (!query || !length) + if (!mysql && (rc= real_connect())) goto end; + mysql->net.thd= table->in_use; + rc= mysql_real_query(mysql, query, (uint) length); end: @@ -3289,66 +3294,6 @@ int ha_federated::external_lock(THD *thd, int lock_type) int error= 0; DBUG_ENTER("ha_federated::external_lock"); - /* - Support for transactions disabled until WL#2952 fixes it. - */ -#ifdef XXX_SUPERCEDED_BY_WL2952 - if (lock_type != F_UNLCK) - { - ha_federated *trx= (ha_federated *)thd_get_ha_data(thd, ht); - - DBUG_PRINT("info",("federated not lock F_UNLCK")); - if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) - { - DBUG_PRINT("info",("federated autocommit")); - /* - This means we are doing an autocommit - */ - error= connection_autocommit(TRUE); - if (error) - { - DBUG_PRINT("info", ("error setting autocommit TRUE: %d", error)); - DBUG_RETURN(error); - } - trans_register_ha(thd, FALSE, ht); - } - else - { - DBUG_PRINT("info",("not autocommit")); - if (!trx) - { - /* - This is where a transaction gets its start - */ - error= connection_autocommit(FALSE); - if (error) - { - DBUG_PRINT("info", ("error setting autocommit FALSE: %d", error)); - DBUG_RETURN(error); - } - thd_set_ha_data(thd, ht, this); - trans_register_ha(thd, TRUE, ht); - /* - Send a lock table to the remote end. - We do not support this at the moment - */ - if (thd->options & (OPTION_TABLE_LOCK)) - { - DBUG_PRINT("info", ("We do not support lock table yet")); - } - } - else - { - ha_federated *ptr; - for (ptr= trx; ptr; ptr= ptr->trx_next) - if (ptr == this) - break; - else if (!ptr->trx_next) - ptr->trx_next= this; - } - } - } -#endif /* XXX_SUPERCEDED_BY_WL2952 */ table_will_be_deleted = FALSE; DBUG_RETURN(error); } diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc index 815324825bd..3e9f26ad125 100644 --- a/storage/innobase/btr/btr0btr.cc +++ b/storage/innobase/btr/btr0btr.cc @@ -720,8 +720,9 @@ btr_page_free_low( ulint* offsets = NULL; rec_t* rec = page_rec_get_next(page_get_infimum_rec(page)); while (!page_rec_is_supremum(rec)) { - offsets = rec_get_offsets(rec, index, - offsets, ULINT_UNDEFINED, + offsets = rec_get_offsets(rec, index, offsets, + page_is_leaf(page), + ULINT_UNDEFINED, &heap); ulint size = rec_offs_data_size(offsets); memset(rec, 0, size); @@ -832,7 +833,7 @@ btr_node_ptr_set_child_page_no( ulint len; ut_ad(rec_offs_validate(rec, NULL, offsets)); - ut_ad(!page_is_leaf(page_align(rec))); + ut_ad(!page_rec_is_leaf(rec)); ut_ad(!rec_offs_comp(offsets) || rec_get_node_ptr_flag(rec)); /* The child address is in the last field */ @@ -937,7 +938,7 @@ btr_page_get_father_node_ptr_func( node_ptr = btr_cur_get_rec(cursor); - offsets = rec_get_offsets(node_ptr, index, offsets, + offsets = rec_get_offsets(node_ptr, index, offsets, false, ULINT_UNDEFINED, &heap); if (btr_node_ptr_get_child_page_no(node_ptr, offsets) != page_no) { @@ -953,10 +954,11 @@ btr_page_get_father_node_ptr_func( print_rec = page_rec_get_next( page_get_infimum_rec(page_align(user_rec))); - offsets = rec_get_offsets(print_rec, index, - offsets, ULINT_UNDEFINED, &heap); + offsets = rec_get_offsets(print_rec, index, offsets, + page_rec_is_leaf(user_rec), + ULINT_UNDEFINED, &heap); page_rec_print(print_rec, offsets); - offsets = rec_get_offsets(node_ptr, index, offsets, + offsets = rec_get_offsets(node_ptr, index, offsets, false, ULINT_UNDEFINED, &heap); page_rec_print(node_ptr, offsets); @@ -2275,9 +2277,9 @@ btr_page_get_split_rec( /* Include tuple */ incl_data += insert_size; } else { - offsets = rec_get_offsets(rec, cursor->index, - offsets, ULINT_UNDEFINED, - &heap); + offsets = rec_get_offsets(rec, cursor->index, offsets, + page_is_leaf(page), + ULINT_UNDEFINED, &heap); incl_data += rec_offs_size(offsets); } @@ -2385,6 +2387,7 @@ btr_page_insert_fits( space after rec is removed from page. */ *offsets = rec_get_offsets(rec, cursor->index, *offsets, + page_is_leaf(page), ULINT_UNDEFINED, heap); total_data -= rec_offs_size(*offsets); @@ -2673,7 +2676,7 @@ btr_page_tuple_smaller( first_rec = page_cur_get_rec(&pcur); *offsets = rec_get_offsets( - first_rec, cursor->index, *offsets, + first_rec, cursor->index, *offsets, page_is_leaf(block->frame), n_uniq, heap); return(cmp_dtuple_rec(tuple, first_rec, *offsets) < 0); @@ -2980,7 +2983,7 @@ func_start: first_rec = move_limit = split_rec; *offsets = rec_get_offsets(split_rec, cursor->index, *offsets, - n_uniq, heap); + page_is_leaf(page), n_uniq, heap); if (tuple != NULL) { insert_left = cmp_dtuple_rec( @@ -3808,8 +3811,9 @@ retry: cursor2.tree_height = cursor->tree_height; offsets2 = rec_get_offsets( - btr_cur_get_rec(&cursor2), index, - NULL, ULINT_UNDEFINED, &heap); + btr_cur_get_rec(&cursor2), index, NULL, + page_is_leaf(cursor2.page_cur.block->frame), + ULINT_UNDEFINED, &heap); /* Check if parent entry needs to be updated */ mbr_changed = rtr_merge_mbr_changed( @@ -3989,8 +3993,9 @@ retry: ulint rec_info; offsets2 = rec_get_offsets( - btr_cur_get_rec(&cursor2), - index, NULL, ULINT_UNDEFINED, &heap); + btr_cur_get_rec(&cursor2), index, NULL, + page_is_leaf(cursor2.page_cur.block->frame), + ULINT_UNDEFINED, &heap); ut_ad(btr_node_ptr_get_child_page_no( btr_cur_get_rec(&cursor2), offsets2) @@ -4468,8 +4473,9 @@ btr_print_recursive( node_ptr = page_cur_get_rec(&cursor); - *offsets = rec_get_offsets(node_ptr, index, *offsets, - ULINT_UNDEFINED, heap); + *offsets = rec_get_offsets( + node_ptr, index, *offsets, false, + ULINT_UNDEFINED, heap); btr_print_recursive(index, btr_node_ptr_get_child(node_ptr, index, @@ -4662,7 +4668,8 @@ btr_index_rec_validate( return(FALSE); } - offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); + offsets = rec_get_offsets(rec, index, offsets, page_is_leaf(page), + ULINT_UNDEFINED, &heap); for (i = 0; i < n; i++) { dict_field_t* field = dict_index_get_nth_field(index, i); @@ -4916,7 +4923,7 @@ btr_validate_level( page_cur_move_to_next(&cursor); node_ptr = page_cur_get_rec(&cursor); - offsets = rec_get_offsets(node_ptr, index, offsets, + offsets = rec_get_offsets(node_ptr, index, offsets, false, ULINT_UNDEFINED, &heap); savepoint2 = mtr_set_savepoint(&mtr); @@ -5042,10 +5049,12 @@ loop: rec = page_rec_get_prev(page_get_supremum_rec(page)); right_rec = page_rec_get_next(page_get_infimum_rec( right_page)); - offsets = rec_get_offsets(rec, index, - offsets, ULINT_UNDEFINED, &heap); - offsets2 = rec_get_offsets(right_rec, index, - offsets2, ULINT_UNDEFINED, &heap); + offsets = rec_get_offsets(rec, index, offsets, + page_is_leaf(page), + ULINT_UNDEFINED, &heap); + offsets2 = rec_get_offsets(right_rec, index, offsets2, + page_is_leaf(right_page), + ULINT_UNDEFINED, &heap); /* For spatial index, we cannot guarantee the key ordering across pages, so skip the record compare verification for diff --git a/storage/innobase/btr/btr0bulk.cc b/storage/innobase/btr/btr0bulk.cc index 8a954f9d3c3..139e3116d06 100644 --- a/storage/innobase/btr/btr0bulk.cc +++ b/storage/innobase/btr/btr0bulk.cc @@ -176,7 +176,8 @@ PageBulk::insert( if (!page_rec_is_infimum(m_cur_rec)) { rec_t* old_rec = m_cur_rec; ulint* old_offsets = rec_get_offsets( - old_rec, m_index, NULL, ULINT_UNDEFINED, &m_heap); + old_rec, m_index, NULL, page_rec_is_leaf(old_rec), + ULINT_UNDEFINED, &m_heap); ut_ad(cmp_rec_rec(rec, old_rec, offsets, old_offsets, m_index) > 0); @@ -377,9 +378,9 @@ PageBulk::getSplitRec() rec = page_rec_get_next(rec); ut_ad(page_rec_is_user_rec(rec)); - offsets = rec_get_offsets(rec, m_index, - offsets, ULINT_UNDEFINED, - &(m_heap)); + offsets = rec_get_offsets(rec, m_index, offsets, + page_is_leaf(m_page), + ULINT_UNDEFINED, &m_heap); total_recs_size += rec_offs_size(offsets); n_recs++; } while (total_recs_size + page_dir_calc_reserved_space(n_recs) @@ -409,7 +410,8 @@ PageBulk::copyIn( do { offsets = rec_get_offsets(rec, m_index, offsets, - ULINT_UNDEFINED, &(m_heap)); + page_rec_is_leaf(split_rec), + ULINT_UNDEFINED, &m_heap); insert(rec, offsets); @@ -449,18 +451,18 @@ PageBulk::copyOut( /* Set last record's next in page */ ulint* offsets = NULL; rec = page_rec_get_prev(split_rec); - offsets = rec_get_offsets(rec, m_index, - offsets, ULINT_UNDEFINED, - &(m_heap)); + offsets = rec_get_offsets(rec, m_index, offsets, + page_rec_is_leaf(split_rec), + ULINT_UNDEFINED, &m_heap); page_rec_set_next(rec, page_get_supremum_rec(m_page)); /* Set related members */ m_cur_rec = rec; m_heap_top = rec_get_end(rec, offsets); - offsets = rec_get_offsets(last_rec, m_index, - offsets, ULINT_UNDEFINED, - &(m_heap)); + offsets = rec_get_offsets(last_rec, m_index, offsets, + page_rec_is_leaf(split_rec), + ULINT_UNDEFINED, &m_heap); m_free_space += rec_get_end(last_rec, offsets) - m_heap_top @@ -876,8 +878,8 @@ BtrBulk::insert( /* Convert tuple to rec. */ rec = rec_convert_dtuple_to_rec(static_cast<byte*>(mem_heap_alloc( page_bulk->m_heap, rec_size)), m_index, tuple, n_ext); - offsets = rec_get_offsets(rec, m_index, offsets, ULINT_UNDEFINED, - &(page_bulk->m_heap)); + offsets = rec_get_offsets(rec, m_index, offsets, !level, + ULINT_UNDEFINED, &page_bulk->m_heap); page_bulk->insert(rec, offsets); diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index e740370d2f0..25498a2530c 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -1545,8 +1545,8 @@ retry_page_get: node_ptr = page_cur_get_rec(page_cursor); - offsets = rec_get_offsets( - node_ptr, index, offsets, ULINT_UNDEFINED, &heap); + offsets = rec_get_offsets(node_ptr, index, offsets, false, + ULINT_UNDEFINED, &heap); /* If the rec is the first or last in the page for pessimistic delete intention, it might cause node_ptr insert @@ -1662,10 +1662,8 @@ need_opposite_intention: && latch_mode == BTR_MODIFY_TREE && (up_match >= rec_offs_n_fields(offsets) - 1 || low_match >= rec_offs_n_fields(offsets) - 1)) { - const rec_t* first_rec - = page_rec_get_next_const( - page_get_infimum_rec( - page)); + const rec_t* first_rec = page_rec_get_next_const( + page_get_infimum_rec(page)); ulint matched_fields; ut_ad(upper_rw_latch == RW_X_LATCH); @@ -1678,7 +1676,7 @@ need_opposite_intention: offsets2 = rec_get_offsets( first_rec, index, offsets2, - ULINT_UNDEFINED, &heap); + false, ULINT_UNDEFINED, &heap); cmp_rec_rec_with_match(node_ptr, first_rec, offsets, offsets2, index, FALSE, &matched_fields); @@ -1690,14 +1688,13 @@ need_opposite_intention: const rec_t* last_rec; last_rec = page_rec_get_prev_const( - page_get_supremum_rec( - page)); + page_get_supremum_rec(page)); matched_fields = 0; offsets2 = rec_get_offsets( last_rec, index, offsets2, - ULINT_UNDEFINED, &heap); + false, ULINT_UNDEFINED, &heap); cmp_rec_rec_with_match( node_ptr, last_rec, offsets, offsets2, index, @@ -1854,14 +1851,9 @@ need_opposite_intention: cursor->rtr_info->path; if (!path->empty() && found) { -#ifdef UNIV_DEBUG - node_visit_t last_visit = path->back(); - - ut_ad(last_visit.page_no == page_id.page_no()); -#endif /* UNIV_DEBUG */ - + ut_ad(path->back().page_no + == page_id.page_no()); path->pop_back(); - #ifdef UNIV_DEBUG if (page_mode == PAGE_CUR_RTREE_LOCATE && (latch_mode != BTR_MODIFY_LEAF)) { @@ -1873,14 +1865,13 @@ need_opposite_intention: offsets = rec_get_offsets( my_node_ptr, index, offsets, - ULINT_UNDEFINED, &heap); + false, ULINT_UNDEFINED, &heap); ulint my_page_no = btr_node_ptr_get_child_page_no( my_node_ptr, offsets); ut_ad(page_id.page_no() == my_page_no); - } #endif } @@ -2316,7 +2307,7 @@ btr_cur_open_at_index_side_func( node_ptr = page_cur_get_rec(page_cursor); offsets = rec_get_offsets(node_ptr, cursor->index, offsets, - ULINT_UNDEFINED, &heap); + false, ULINT_UNDEFINED, &heap); /* If the rec is the first or last in the page for pessimistic delete intention, it might cause node_ptr insert @@ -2612,7 +2603,7 @@ btr_cur_open_at_rnd_pos_func( node_ptr = page_cur_get_rec(page_cursor); offsets = rec_get_offsets(node_ptr, cursor->index, offsets, - ULINT_UNDEFINED, &heap); + false, ULINT_UNDEFINED, &heap); /* If the rec is the first or last in the page for pessimistic delete intention, it might cause node_ptr insert @@ -3086,10 +3077,11 @@ fail_err: } #ifdef BTR_CUR_HASH_ADAPT + if (!leaf) { # ifdef MYSQL_INDEX_DISABLE_AHI - if (index->disable_ahi); else + } else if (index->disable_ahi) { # endif - if (!reorg && leaf && (cursor->flag == BTR_CUR_HASH)) { + } else if (!reorg && cursor->flag == BTR_CUR_HASH) { btr_search_update_hash_node_on_insert(cursor); } else { btr_search_update_hash_on_insert(cursor); @@ -3285,15 +3277,19 @@ btr_cur_pessimistic_insert( } } + if (!page_is_leaf(btr_cur_get_page(cursor))) { + ut_ad(!big_rec_vec); + } else { #ifdef BTR_CUR_HASH_ADAPT # ifdef MYSQL_INDEX_DISABLE_AHI - if (index->disable_ahi); else + if (index->disable_ahi); else # endif - btr_search_update_hash_on_insert(cursor); + btr_search_update_hash_on_insert(cursor); #endif /* BTR_CUR_HASH_ADAPT */ - if (inherit && !(flags & BTR_NO_LOCKING_FLAG)) { + if (inherit && !(flags & BTR_NO_LOCKING_FLAG)) { - lock_update_insert(btr_cur_get_block(cursor), *rec); + lock_update_insert(btr_cur_get_block(cursor), *rec); + } } if (n_reserved > 0) { @@ -3489,7 +3485,8 @@ btr_cur_parse_update_in_place( /* We do not need to reserve search latch, as the page is only being recovered, and there cannot be a hash index to it. */ - offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, &heap); + offsets = rec_get_offsets(rec, index, NULL, true, + ULINT_UNDEFINED, &heap); if (!(flags & BTR_KEEP_SYS_FLAG)) { row_upd_rec_sys_fields_in_recovery(rec, page_zip, offsets, @@ -3813,7 +3810,7 @@ btr_cur_optimistic_update( ut_ad(fil_page_index_page_check(page)); ut_ad(btr_page_get_index_id(page) == index->id); - *offsets = rec_get_offsets(rec, index, *offsets, + *offsets = rec_get_offsets(rec, index, *offsets, true, ULINT_UNDEFINED, heap); #if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG ut_a(!rec_offs_any_null_extern(rec, *offsets) @@ -4180,7 +4177,8 @@ btr_cur_pessimistic_update( rec = btr_cur_get_rec(cursor); *offsets = rec_get_offsets( - rec, index, *offsets, ULINT_UNDEFINED, offsets_heap); + rec, index, *offsets, page_is_leaf(page), + ULINT_UNDEFINED, offsets_heap); dtuple_t* new_entry = row_rec_to_index_entry( rec, index, *offsets, &n_ext, entry_heap); @@ -4614,7 +4612,7 @@ btr_cur_parse_del_mark_set_clust_rec( if (!(flags & BTR_KEEP_SYS_FLAG)) { row_upd_rec_sys_fields_in_recovery( rec, page_zip, - rec_get_offsets(rec, index, offsets, + rec_get_offsets(rec, index, offsets, true, pos + 2, &heap), pos, trx_id, roll_ptr); } else { @@ -4623,8 +4621,8 @@ btr_cur_parse_del_mark_set_clust_rec( ut_ad(memcmp(rec_get_nth_field( rec, rec_get_offsets(rec, index, - offsets, pos, - &heap), + offsets, true, + pos, &heap), pos, &offset), field_ref_zero, DATA_TRX_ID_LEN)); ut_ad(offset == DATA_TRX_ID_LEN); @@ -4665,7 +4663,7 @@ btr_cur_del_mark_set_clust_rec( ut_ad(rec_offs_validate(rec, index, offsets)); ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table)); ut_ad(buf_block_get_frame(block) == page_align(rec)); - ut_ad(page_is_leaf(page_align(rec))); + ut_ad(page_rec_is_leaf(rec)); ut_ad(mtr->is_named_space(index->space)); if (rec_get_deleted_flag(rec, rec_offs_comp(offsets))) { @@ -4959,7 +4957,7 @@ btr_cur_optimistic_delete_func( || (flags & BTR_CREATE_FLAG)); rec = btr_cur_get_rec(cursor); - offsets = rec_get_offsets(rec, cursor->index, offsets, + offsets = rec_get_offsets(rec, cursor->index, offsets, true, ULINT_UNDEFINED, &heap); no_compress_needed = !rec_offs_any_extern(offsets) @@ -5103,7 +5101,8 @@ btr_cur_pessimistic_delete( ut_a(!page_zip || page_zip_validate(page_zip, page, index)); #endif /* UNIV_ZIP_DEBUG */ - offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, &heap); + offsets = rec_get_offsets(rec, index, NULL, page_is_leaf(page), + ULINT_UNDEFINED, &heap); if (rec_offs_any_extern(offsets)) { btr_rec_free_externally_stored_fields(index, @@ -5134,10 +5133,9 @@ btr_cur_pessimistic_delete( level = btr_page_get_level(page, mtr); - if (level > 0 - && UNIV_UNLIKELY(rec == page_rec_get_next( - page_get_infimum_rec(page)))) { - + if (level == 0) { + btr_search_update_hash_on_delete(cursor); + } else if (UNIV_UNLIKELY(page_rec_is_first(rec, page))) { rec_t* next_rec = page_rec_get_next(rec); if (btr_page_get_prev(page, mtr) == FIL_NULL) { @@ -5166,8 +5164,8 @@ btr_cur_pessimistic_delete( block, mtr, NULL, &father_cursor); offsets = rec_get_offsets( - btr_cur_get_rec(&father_cursor), index, - NULL, ULINT_UNDEFINED, &heap); + btr_cur_get_rec(&father_cursor), index, NULL, + false, ULINT_UNDEFINED, &heap); father_rec = btr_cur_get_rec(&father_cursor); rtr_read_mbr(rec_get_nth_field( @@ -5204,8 +5202,6 @@ btr_cur_pessimistic_delete( } } - btr_search_update_hash_on_delete(cursor); - page_cur_delete_rec(btr_cur_get_page_cur(cursor), index, offsets, mtr); #ifdef UNIV_ZIP_DEBUG ut_a(!page_zip || page_zip_validate(page_zip, page, index)); @@ -6061,10 +6057,12 @@ btr_estimate_number_of_different_key_vals( page = btr_cur_get_page(&cursor); rec = page_rec_get_next(page_get_infimum_rec(page)); + ut_d(const bool is_leaf = page_is_leaf(page)); if (!page_rec_is_supremum(rec)) { not_empty_flag = 1; offsets_rec = rec_get_offsets(rec, index, offsets_rec, + is_leaf, ULINT_UNDEFINED, &heap); if (n_not_null != NULL) { @@ -6085,6 +6083,7 @@ btr_estimate_number_of_different_key_vals( offsets_next_rec = rec_get_offsets(next_rec, index, offsets_next_rec, + is_leaf, ULINT_UNDEFINED, &heap); @@ -7353,6 +7352,8 @@ btr_rec_free_externally_stored_fields( ut_ad(rec_offs_validate(rec, index, offsets)); ut_ad(mtr_is_page_fix(mtr, rec, MTR_MEMO_PAGE_X_FIX, index->table)); + ut_ad(dict_index_is_clust(index)); + ut_ad(page_rec_is_leaf(rec)); /* Free possible externally stored fields in the record */ ut_ad(dict_table_is_comp(index->table) == !!rec_offs_comp(offsets)); diff --git a/storage/innobase/btr/btr0defragment.cc b/storage/innobase/btr/btr0defragment.cc index d4b83930191..335b4fc220d 100644 --- a/storage/innobase/btr/btr0defragment.cc +++ b/storage/innobase/btr/btr0defragment.cc @@ -402,6 +402,7 @@ btr_defragment_calc_n_recs_for_size( while (page_cur_get_rec(&cur) != page_get_supremum_rec(page)) { rec_t* cur_rec = page_cur_get_rec(&cur); offsets = rec_get_offsets(cur_rec, index, offsets, + page_is_leaf(page), ULINT_UNDEFINED, &heap); ulint rec_size = rec_offs_size(offsets); size += rec_size; diff --git a/storage/innobase/btr/btr0pcur.cc b/storage/innobase/btr/btr0pcur.cc index fdde6f5d3e7..ee33d9c296a 100644 --- a/storage/innobase/btr/btr0pcur.cc +++ b/storage/innobase/btr/btr0pcur.cc @@ -303,10 +303,10 @@ btr_pcur_restore_position_func( heap = mem_heap_create(256); offsets1 = rec_get_offsets( - cursor->old_rec, index, NULL, + cursor->old_rec, index, NULL, true, cursor->old_n_fields, &heap); offsets2 = rec_get_offsets( - rec, index, NULL, + rec, index, NULL, true, cursor->old_n_fields, &heap); ut_ad(!cmp_rec_rec(cursor->old_rec, @@ -365,7 +365,8 @@ btr_pcur_restore_position_func( && btr_pcur_is_on_user_rec(cursor) && !cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor), rec_get_offsets(btr_pcur_get_rec(cursor), - index, NULL, ULINT_UNDEFINED, &heap))) { + index, NULL, true, + ULINT_UNDEFINED, &heap))) { /* We have to store the NEW value for the modify clock, since the cursor can now be on a different page! diff --git a/storage/innobase/btr/btr0sea.cc b/storage/innobase/btr/btr0sea.cc index 3ae9e95819a..750c2506ff5 100644 --- a/storage/innobase/btr/btr0sea.cc +++ b/storage/innobase/btr/btr0sea.cc @@ -609,8 +609,8 @@ btr_search_update_hash_ref( ut_ad(rw_lock_own(btr_get_search_latch(cursor->index), RW_LOCK_X)); ut_ad(rw_lock_own(&(block->lock), RW_LOCK_S) || rw_lock_own(&(block->lock), RW_LOCK_X)); - ut_ad(page_align(btr_cur_get_rec(cursor)) - == buf_block_get_frame(block)); + ut_ad(page_align(btr_cur_get_rec(cursor)) == block->frame); + ut_ad(page_is_leaf(block->frame)); assert_block_ahi_valid(block); index = block->index; @@ -640,7 +640,7 @@ btr_search_update_hash_ref( } fold = rec_fold(rec, - rec_get_offsets(rec, index, offsets_, + rec_get_offsets(rec, index, offsets_, true, ULINT_UNDEFINED, &heap), block->curr_n_fields, block->curr_n_bytes, index->id); @@ -750,10 +750,11 @@ btr_search_check_guess( rec = btr_cur_get_rec(cursor); ut_ad(page_rec_is_user_rec(rec)); + ut_ad(page_rec_is_leaf(rec)); match = 0; - offsets = rec_get_offsets(rec, cursor->index, offsets, + offsets = rec_get_offsets(rec, cursor->index, offsets, true, n_unique, &heap); cmp = cmp_dtuple_rec_with_match(tuple, rec, offsets, &match); @@ -808,7 +809,7 @@ btr_search_check_guess( } offsets = rec_get_offsets(prev_rec, cursor->index, offsets, - n_unique, &heap); + true, n_unique, &heap); cmp = cmp_dtuple_rec_with_match( tuple, prev_rec, offsets, &match); if (mode == PAGE_CUR_GE) { @@ -837,7 +838,7 @@ btr_search_check_guess( } offsets = rec_get_offsets(next_rec, cursor->index, offsets, - n_unique, &heap); + true, n_unique, &heap); cmp = cmp_dtuple_rec_with_match( tuple, next_rec, offsets, &match); if (mode == PAGE_CUR_LE) { @@ -1139,6 +1140,7 @@ retry: || buf_block_get_state(block) == BUF_BLOCK_REMOVE_HASH || rw_lock_own(&block->lock, RW_LOCK_S) || rw_lock_own(&block->lock, RW_LOCK_X)); + ut_ad(page_is_leaf(block->frame)); /* We must not dereference index here, because it could be freed if (index->table->n_ref_count == 0 && !mutex_own(&dict_sys->mutex)). @@ -1229,7 +1231,7 @@ retry: while (!page_rec_is_supremum(rec)) { offsets = rec_get_offsets( - rec, index, offsets, + rec, index, offsets, true, btr_search_get_n_fields(n_fields, n_bytes), &heap); fold = rec_fold(rec, offsets, n_fields, n_bytes, index_id); @@ -1392,6 +1394,7 @@ btr_search_build_page_hash_index( ut_ad(index); ut_ad(block->page.id.space() == index->space); ut_a(!dict_index_is_ibuf(index)); + ut_ad(page_is_leaf(block->frame)); ut_ad(!rw_lock_own(btr_get_search_latch(index), RW_LOCK_X)); ut_ad(rw_lock_own(&(block->lock), RW_LOCK_S) @@ -1445,7 +1448,7 @@ btr_search_build_page_hash_index( rec = page_rec_get_next(page_get_infimum_rec(page)); offsets = rec_get_offsets( - rec, index, offsets, + rec, index, offsets, true, btr_search_get_n_fields(n_fields, n_bytes), &heap); ut_ad(page_rec_is_supremum(rec) @@ -1476,7 +1479,7 @@ btr_search_build_page_hash_index( } offsets = rec_get_offsets( - next_rec, index, offsets, + next_rec, index, offsets, true, btr_search_get_n_fields(n_fields, n_bytes), &heap); next_fold = rec_fold(next_rec, offsets, n_fields, n_bytes, index->id); @@ -1630,9 +1633,11 @@ btr_search_update_hash_on_delete(btr_cur_t* cursor) mem_heap_t* heap = NULL; rec_offs_init(offsets_); + ut_ad(page_is_leaf(btr_cur_get_page(cursor))); #ifdef MYSQL_INDEX_DISABLE_AHI if (cursor->index->disable_ahi) return; #endif + if (!btr_search_enabled) { return; } @@ -1658,7 +1663,7 @@ btr_search_update_hash_on_delete(btr_cur_t* cursor) rec = btr_cur_get_rec(cursor); - fold = rec_fold(rec, rec_get_offsets(rec, index, offsets_, + fold = rec_fold(rec, rec_get_offsets(rec, index, offsets_, true, ULINT_UNDEFINED, &heap), block->curr_n_fields, block->curr_n_bytes, index->id); if (UNIV_LIKELY_NULL(heap)) { @@ -1777,6 +1782,7 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor) ulint* offsets = offsets_; rec_offs_init(offsets_); + ut_ad(page_is_leaf(btr_cur_get_page(cursor))); #ifdef MYSQL_INDEX_DISABLE_AHI if (cursor->index->disable_ahi) return; #endif @@ -1816,13 +1822,13 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor) ins_rec = page_rec_get_next_const(rec); next_rec = page_rec_get_next_const(ins_rec); - offsets = rec_get_offsets(ins_rec, index, offsets, + offsets = rec_get_offsets(ins_rec, index, offsets, true, ULINT_UNDEFINED, &heap); ins_fold = rec_fold(ins_rec, offsets, n_fields, n_bytes, index->id); if (!page_rec_is_supremum(next_rec)) { offsets = rec_get_offsets( - next_rec, index, offsets, + next_rec, index, offsets, true, btr_search_get_n_fields(n_fields, n_bytes), &heap); next_fold = rec_fold(next_rec, offsets, n_fields, n_bytes, index->id); @@ -1830,7 +1836,7 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor) if (!page_rec_is_infimum(rec)) { offsets = rec_get_offsets( - rec, index, offsets, + rec, index, offsets, true, btr_search_get_n_fields(n_fields, n_bytes), &heap); fold = rec_fold(rec, offsets, n_fields, n_bytes, index->id); } else { @@ -2029,7 +2035,7 @@ btr_search_hash_table_validate(ulint hash_table_id) page_index_id = btr_page_get_index_id(block->frame); offsets = rec_get_offsets( - node->data, block->index, offsets, + node->data, block->index, offsets, true, btr_search_get_n_fields(block->curr_n_fields, block->curr_n_bytes), &heap); diff --git a/storage/innobase/data/data0data.cc b/storage/innobase/data/data0data.cc index d819ad50ed9..7fb0eae611c 100644 --- a/storage/innobase/data/data0data.cc +++ b/storage/innobase/data/data0data.cc @@ -803,14 +803,11 @@ big_rec_t::alloc( return(rec); } -/** Create a deep copy of this object -@param[in] heap the memory heap in which the clone will be - created. - -@return the cloned object. */ +/** Create a deep copy of this object. +@param[in,out] heap memory heap in which the clone will be created +@return the cloned object */ dfield_t* -dfield_t::clone( - mem_heap_t* heap) +dfield_t::clone(mem_heap_t* heap) const { const ulint size = len == UNIV_SQL_NULL ? 0 : len; dfield_t* obj = static_cast<dfield_t*>( diff --git a/storage/innobase/dict/dict0defrag_bg.cc b/storage/innobase/dict/dict0defrag_bg.cc index ccb73e02f43..3d1ee3f76e9 100644 --- a/storage/innobase/dict/dict0defrag_bg.cc +++ b/storage/innobase/dict/dict0defrag_bg.cc @@ -290,7 +290,7 @@ dict_stats_save_defrag_summary( dberr_t ret=DB_SUCCESS; lint now = (lint) ut_time(); - if (dict_index_is_univ(index)) { + if (dict_index_is_ibuf(index)) { return DB_SUCCESS; } @@ -320,7 +320,7 @@ dict_stats_save_defrag_stats( { dberr_t ret; - if (dict_index_is_univ(index)) { + if (dict_index_is_ibuf(index)) { return DB_SUCCESS; } diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 55429b2680f..f969acba35e 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -5654,7 +5654,7 @@ dict_index_build_node_ptr( dtype_set(dfield_get_type(field), DATA_SYS_CHILD, DATA_NOT_NULL, 4); - rec_copy_prefix_to_dtuple(tuple, rec, index, n_unique, heap); + rec_copy_prefix_to_dtuple(tuple, rec, index, !level, n_unique, heap); dtuple_set_info_bits(tuple, dtuple_get_info_bits(tuple) | REC_STATUS_NODE_PTR); @@ -5686,7 +5686,7 @@ dict_index_copy_rec_order_prefix( ut_a(!dict_table_is_comp(index->table)); n = rec_get_n_fields_old(rec); } else { - if (page_is_leaf(page_align(rec))) { + if (page_rec_is_leaf(rec)) { n = dict_index_get_n_unique_in_tree(index); } else { n = dict_index_get_n_unique_in_tree_nonleaf(index); @@ -5723,7 +5723,7 @@ dict_index_build_data_tuple( dict_index_copy_types(tuple, index, n_fields); - rec_copy_prefix_to_dtuple(tuple, rec, index, n_fields, heap); + rec_copy_prefix_to_dtuple(tuple, rec, index, true, n_fields, heap); ut_ad(dtuple_check_typed(tuple)); diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc index 177a16a2b37..17e66b3d99c 100644 --- a/storage/innobase/dict/dict0stats.cc +++ b/storage/innobase/dict/dict0stats.cc @@ -1172,6 +1172,7 @@ dict_stats_analyze_index_level( prev_rec_offsets = rec_get_offsets( prev_rec, index, prev_rec_offsets, + true, n_uniq, &heap); prev_rec = rec_copy_prefix_to_buf( @@ -1185,7 +1186,7 @@ dict_stats_analyze_index_level( continue; } rec_offsets = rec_get_offsets( - rec, index, rec_offsets, n_uniq, &heap); + rec, index, rec_offsets, !level, n_uniq, &heap); (*total_recs)++; @@ -1193,7 +1194,7 @@ dict_stats_analyze_index_level( ulint matched_fields; prev_rec_offsets = rec_get_offsets( - prev_rec, index, prev_rec_offsets, + prev_rec, index, prev_rec_offsets, !level, n_uniq, &heap); cmp_rec_rec_with_match(rec, @@ -1399,7 +1400,7 @@ dict_stats_scan_page( return(NULL); } - offsets_rec = rec_get_offsets(rec, index, offsets_rec, + offsets_rec = rec_get_offsets(rec, index, offsets_rec, is_leaf, ULINT_UNDEFINED, &heap); if (should_count_external_pages) { @@ -1416,7 +1417,7 @@ dict_stats_scan_page( ulint matched_fields; offsets_next_rec = rec_get_offsets(next_rec, index, - offsets_next_rec, + offsets_next_rec, is_leaf, ULINT_UNDEFINED, &heap); @@ -1522,8 +1523,9 @@ dict_stats_analyze_index_below_cur( rec_offs_set_n_alloc(offsets2, size); rec = btr_cur_get_rec(cur); + ut_ad(!page_rec_is_leaf(rec)); - offsets_rec = rec_get_offsets(rec, index, offsets1, + offsets_rec = rec_get_offsets(rec, index, offsets1, false, ULINT_UNDEFINED, &heap); page_id_t page_id(dict_index_get_space(index), diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index 60cc3c91fef..dd8de511b21 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -3460,10 +3460,10 @@ fts_add_doc_by_id( } - offsets = rec_get_offsets(clust_rec, clust_index, - NULL, ULINT_UNDEFINED, &heap); + offsets = rec_get_offsets(clust_rec, clust_index, NULL, true, + ULINT_UNDEFINED, &heap); - for (ulint i = 0; i < num_idx; ++i) { + for (ulint i = 0; i < num_idx; ++i) { fts_doc_t doc; dict_table_t* table; fts_get_doc_t* get_doc; @@ -3633,7 +3633,7 @@ fts_get_max_doc_id( } offsets = rec_get_offsets( - rec, index, offsets, ULINT_UNDEFINED, &heap); + rec, index, offsets, true, ULINT_UNDEFINED, &heap); data = rec_get_nth_field(rec, offsets, 0, &len); @@ -5120,7 +5120,7 @@ fts_get_doc_id_from_rec( rec_offs_init(offsets_); offsets = rec_get_offsets( - rec, index, offsets, ULINT_UNDEFINED, &my_heap); + rec, index, offsets, true, ULINT_UNDEFINED, &my_heap); col_no = dict_col_get_index_pos( &table->cols[table->fts->doc_col], index); diff --git a/storage/innobase/gis/gis0rtree.cc b/storage/innobase/gis/gis0rtree.cc index d14bafff72b..b8220d73ec0 100644 --- a/storage/innobase/gis/gis0rtree.cc +++ b/storage/innobase/gis/gis0rtree.cc @@ -85,7 +85,8 @@ rtr_page_split_initialize_nodes( stop = task + n_recs; rec = page_rec_get_next(page_get_infimum_rec(page)); - *offsets = rec_get_offsets(rec, cursor->index, *offsets, + ut_d(const bool is_leaf = page_is_leaf(page)); + *offsets = rec_get_offsets(rec, cursor->index, *offsets, is_leaf, n_uniq, &heap); source_cur = rec_get_nth_field(rec, *offsets, 0, &len); @@ -98,7 +99,7 @@ rtr_page_split_initialize_nodes( rec = page_rec_get_next(rec); *offsets = rec_get_offsets(rec, cursor->index, *offsets, - n_uniq, &heap); + is_leaf, n_uniq, &heap); source_cur = rec_get_nth_field(rec, *offsets, 0, &len); } @@ -324,7 +325,7 @@ rtr_update_mbr_field( if (cursor2) { rec_t* del_rec = btr_cur_get_rec(cursor2); offsets2 = rec_get_offsets(btr_cur_get_rec(cursor2), - index, NULL, + index, NULL, false, ULINT_UNDEFINED, &heap); del_page_no = btr_node_ptr_get_child_page_no(del_rec, offsets2); cur2_pos = page_rec_get_n_recs_before(btr_cur_get_rec(cursor2)); @@ -389,7 +390,7 @@ rtr_update_mbr_field( = page_rec_get_nth(page, cur2_pos); } offsets2 = rec_get_offsets(btr_cur_get_rec(cursor2), - index, NULL, + index, NULL, false, ULINT_UNDEFINED, &heap); ut_ad(del_page_no == btr_node_ptr_get_child_page_no( cursor2->page_cur.rec, @@ -427,8 +428,7 @@ rtr_update_mbr_field( ut_ad(old_rec != insert_rec); page_cur_position(old_rec, block, &page_cur); - offsets2 = rec_get_offsets(old_rec, - index, NULL, + offsets2 = rec_get_offsets(old_rec, index, NULL, !level, ULINT_UNDEFINED, &heap); page_cur_delete_rec(&page_cur, index, offsets2, mtr); @@ -458,6 +458,7 @@ update_mbr: cur2_rec = cursor2->page_cur.rec; offsets2 = rec_get_offsets(cur2_rec, index, NULL, + !level, ULINT_UNDEFINED, &heap); cur2_rec_info = rec_get_info_bits(cur2_rec, @@ -517,7 +518,7 @@ update_mbr: if (ins_suc) { btr_cur_position(index, insert_rec, block, cursor); offsets = rec_get_offsets(insert_rec, - index, offsets, + index, offsets, !level, ULINT_UNDEFINED, &heap); } @@ -532,6 +533,7 @@ update_mbr: cur2_rec = btr_cur_get_rec(cursor2); offsets2 = rec_get_offsets(cur2_rec, index, NULL, + !level, ULINT_UNDEFINED, &heap); /* If the cursor2 position is on a wrong rec, we @@ -545,6 +547,7 @@ update_mbr: while (!page_rec_is_supremum(cur2_rec)) { offsets2 = rec_get_offsets(cur2_rec, index, NULL, + !level, ULINT_UNDEFINED, &heap); cur2_pno = btr_node_ptr_get_child_page_no( @@ -862,6 +865,7 @@ rtr_split_page_move_rec_list( rec_move = static_cast<rtr_rec_move_t*>(mem_heap_alloc( heap, sizeof (*rec_move) * max_to_move)); + const bool is_leaf = page_is_leaf(page); /* Insert the recs in group 2 to new page. */ for (cur_split_node = node_array; @@ -871,11 +875,10 @@ rtr_split_page_move_rec_list( block, cur_split_node->key); offsets = rec_get_offsets(cur_split_node->key, - index, offsets, + index, offsets, is_leaf, ULINT_UNDEFINED, &heap); - ut_ad (cur_split_node->key != first_rec - || !page_is_leaf(page)); + ut_ad(!is_leaf || cur_split_node->key != first_rec); rec = page_cur_insert_rec_low( page_cur_get_rec(&new_page_cursor), @@ -910,8 +913,7 @@ rtr_split_page_move_rec_list( same temp-table in parallel. max_trx_id is ignored for temp tables because it not required for MVCC. */ - if (page_is_leaf(page) - && !dict_table_is_temporary(index->table)) { + if (is_leaf && !dict_table_is_temporary(index->table)) { page_update_max_trx_id(new_block, NULL, page_get_max_trx_id(page), mtr); @@ -964,7 +966,7 @@ rtr_split_page_move_rec_list( block, &page_cursor); offsets = rec_get_offsets( page_cur_get_rec(&page_cursor), index, - offsets, ULINT_UNDEFINED, + offsets, is_leaf, ULINT_UNDEFINED, &heap); page_cur_delete_rec(&page_cursor, index, offsets, mtr); @@ -1183,9 +1185,8 @@ func_start: *offsets = rec_get_offsets( page_cur_get_rec(page_cursor), - cursor->index, - *offsets, ULINT_UNDEFINED, - heap); + cursor->index, *offsets, !page_level, + ULINT_UNDEFINED, heap); page_cur_delete_rec(page_cursor, cursor->index, *offsets, mtr); @@ -1201,9 +1202,8 @@ func_start: block, page_cursor); *offsets = rec_get_offsets( page_cur_get_rec(page_cursor), - cursor->index, - *offsets, ULINT_UNDEFINED, - heap); + cursor->index, *offsets, !page_level, + ULINT_UNDEFINED, heap); page_cur_delete_rec(page_cursor, cursor->index, *offsets, mtr); } @@ -1461,13 +1461,14 @@ rtr_page_copy_rec_list_end_no_locks( cur_rec = page_rec_get_next(cur_rec); } - offsets1 = rec_get_offsets(cur1_rec, index, offsets1, + offsets1 = rec_get_offsets(cur1_rec, index, offsets1, is_leaf, ULINT_UNDEFINED, &heap); while (!page_rec_is_supremum(cur_rec)) { ulint cur_matched_fields = 0; int cmp; offsets2 = rec_get_offsets(cur_rec, index, offsets2, + is_leaf, ULINT_UNDEFINED, &heap); cmp = cmp_rec_rec_with_match(cur1_rec, cur_rec, offsets1, offsets2, @@ -1503,7 +1504,7 @@ rtr_page_copy_rec_list_end_no_locks( cur_rec = page_cur_get_rec(&page_cur); - offsets1 = rec_get_offsets(cur1_rec, index, offsets1, + offsets1 = rec_get_offsets(cur1_rec, index, offsets1, is_leaf, ULINT_UNDEFINED, &heap); ins_rec = page_cur_insert_rec_low(cur_rec, index, @@ -1579,7 +1580,7 @@ rtr_page_copy_rec_list_start_no_locks( cur_rec = page_rec_get_next(cur_rec); } - offsets1 = rec_get_offsets(cur1_rec, index, offsets1, + offsets1 = rec_get_offsets(cur1_rec, index, offsets1, is_leaf, ULINT_UNDEFINED, &heap); while (!page_rec_is_supremum(cur_rec)) { @@ -1587,6 +1588,7 @@ rtr_page_copy_rec_list_start_no_locks( int cmp; offsets2 = rec_get_offsets(cur_rec, index, offsets2, + is_leaf, ULINT_UNDEFINED, &heap); cmp = cmp_rec_rec_with_match(cur1_rec, cur_rec, offsets1, offsets2, @@ -1624,7 +1626,7 @@ rtr_page_copy_rec_list_start_no_locks( cur_rec = page_cur_get_rec(&page_cur); - offsets1 = rec_get_offsets(cur1_rec, index, offsets1, + offsets1 = rec_get_offsets(cur1_rec, index, offsets1, is_leaf, ULINT_UNDEFINED, &heap); ins_rec = page_cur_insert_rec_low(cur_rec, index, @@ -1787,7 +1789,7 @@ rtr_check_same_block( while (!page_rec_is_supremum(rec)) { offsets = rec_get_offsets( - rec, index, NULL, ULINT_UNDEFINED, &heap); + rec, index, NULL, false, ULINT_UNDEFINED, &heap); if (btr_node_ptr_get_child_page_no(rec, offsets) == page_no) { btr_cur_position(index, rec, parentb, cursor); @@ -1913,7 +1915,8 @@ rtr_estimate_n_rows_in_range( heap = mem_heap_create(512); rec = page_rec_get_next(page_get_infimum_rec(page)); - offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); + offsets = rec_get_offsets(rec, index, offsets, page_rec_is_leaf(rec), + ULINT_UNDEFINED, &heap); /* Scan records in root page and calculate area. */ double area = 0; diff --git a/storage/innobase/gis/gis0sea.cc b/storage/innobase/gis/gis0sea.cc index 97163cae410..5e5986594e9 100644 --- a/storage/innobase/gis/gis0sea.cc +++ b/storage/innobase/gis/gis0sea.cc @@ -533,7 +533,7 @@ rtr_compare_cursor_rec( rec = btr_cur_get_rec(cursor); offsets = rec_get_offsets( - rec, index, NULL, ULINT_UNDEFINED, heap); + rec, index, NULL, false, ULINT_UNDEFINED, heap); return(btr_node_ptr_get_child_page_no(rec, offsets) == page_no); } @@ -723,7 +723,7 @@ rtr_page_get_father_node_ptr( user_rec = btr_cur_get_rec(cursor); ut_a(page_rec_is_user_rec(user_rec)); - offsets = rec_get_offsets(user_rec, index, offsets, + offsets = rec_get_offsets(user_rec, index, offsets, !level, ULINT_UNDEFINED, &heap); rtr_get_mbr_from_rec(user_rec, offsets, &mbr); @@ -740,7 +740,7 @@ rtr_page_get_father_node_ptr( node_ptr = btr_cur_get_rec(cursor); ut_ad(!page_rec_is_comp(node_ptr) || rec_get_status(node_ptr) == REC_STATUS_NODE_PTR); - offsets = rec_get_offsets(node_ptr, index, offsets, + offsets = rec_get_offsets(node_ptr, index, offsets, false, ULINT_UNDEFINED, &heap); ulint child_page = btr_node_ptr_get_child_page_no(node_ptr, offsets); @@ -757,13 +757,14 @@ rtr_page_get_father_node_ptr( print_rec = page_rec_get_next( page_get_infimum_rec(page_align(user_rec))); - offsets = rec_get_offsets(print_rec, index, - offsets, ULINT_UNDEFINED, &heap); + offsets = rec_get_offsets(print_rec, index, offsets, + page_rec_is_leaf(user_rec), + ULINT_UNDEFINED, &heap); error << "; child "; rec_print(error.m_oss, print_rec, rec_get_info_bits(print_rec, rec_offs_comp(offsets)), offsets); - offsets = rec_get_offsets(node_ptr, index, offsets, + offsets = rec_get_offsets(node_ptr, index, offsets, false, ULINT_UNDEFINED, &heap); error << "; parent "; rec_print(error.m_oss, print_rec, @@ -1310,10 +1311,10 @@ rtr_cur_restore_position( heap = mem_heap_create(256); offsets1 = rec_get_offsets( - r_cursor->old_rec, index, NULL, + r_cursor->old_rec, index, NULL, !level, r_cursor->old_n_fields, &heap); offsets2 = rec_get_offsets( - rec, index, NULL, + rec, index, NULL, !level, r_cursor->old_n_fields, &heap); comp = rec_offs_comp(offsets1); @@ -1383,10 +1384,10 @@ search_again: rec = btr_pcur_get_rec(r_cursor); offsets1 = rec_get_offsets( - r_cursor->old_rec, index, NULL, + r_cursor->old_rec, index, NULL, !level, r_cursor->old_n_fields, &heap); offsets2 = rec_get_offsets( - rec, index, NULL, + rec, index, NULL, !level, r_cursor->old_n_fields, &heap); comp = rec_offs_comp(offsets1); @@ -1433,6 +1434,7 @@ rtr_leaf_push_match_rec( rtr_rec_t rtr_rec; buf = match_rec->block.frame + match_rec->used; + ut_ad(page_rec_is_leaf(rec)); copy = rec_copy(buf, rec, offsets); @@ -1661,11 +1663,9 @@ rtr_cur_search_with_match( ulint* offsets = offsets_; mem_heap_t* heap = NULL; int cmp = 1; - bool is_leaf; double least_inc = DBL_MAX; const rec_t* best_rec; const rec_t* last_match_rec = NULL; - ulint level; bool match_init = false; ulint space = block->page.id.space(); page_cur_mode_t orig_mode = mode; @@ -1679,8 +1679,8 @@ rtr_cur_search_with_match( page = buf_block_get_frame(block); - is_leaf = page_is_leaf(page); - level = btr_page_get_level(page, mtr); + const ulint level = btr_page_get_level(page, mtr); + const bool is_leaf = !level; if (mode == PAGE_CUR_RTREE_LOCATE) { ut_ad(level != 0); @@ -1702,7 +1702,7 @@ rtr_cur_search_with_match( ulint new_rec_size = rec_get_converted_size(index, tuple, 0); - offsets = rec_get_offsets(rec, index, offsets, + offsets = rec_get_offsets(rec, index, offsets, is_leaf, dtuple_get_n_fields_cmp(tuple), &heap); @@ -1723,7 +1723,7 @@ rtr_cur_search_with_match( } while (!page_rec_is_supremum(rec)) { - offsets = rec_get_offsets(rec, index, offsets, + offsets = rec_get_offsets(rec, index, offsets, is_leaf, dtuple_get_n_fields_cmp(tuple), &heap); if (!is_leaf) { @@ -1818,7 +1818,7 @@ rtr_cur_search_with_match( == PAGE_CUR_RTREE_GET_FATHER); offsets = rec_get_offsets( - rec, index, offsets, + rec, index, offsets, false, ULINT_UNDEFINED, &heap); page_no = btr_node_ptr_get_child_page_no( @@ -1867,7 +1867,7 @@ rtr_cur_search_with_match( /* Collect matched records on page */ offsets = rec_get_offsets( - rec, index, offsets, + rec, index, offsets, true, ULINT_UNDEFINED, &heap); rtr_leaf_push_match_rec( rec, rtr_info, offsets, @@ -1899,9 +1899,8 @@ rtr_cur_search_with_match( ulint child_no; ut_ad(least_inc < DBL_MAX); offsets = rec_get_offsets( - best_rec, index, - offsets, ULINT_UNDEFINED, - &heap); + best_rec, index, offsets, + false, ULINT_UNDEFINED, &heap); child_no = btr_node_ptr_get_child_page_no( best_rec, offsets); @@ -1953,12 +1952,12 @@ rtr_cur_search_with_match( /* Verify the record to be positioned is the same as the last record in matched_rec vector */ offsets2 = rec_get_offsets(test_rec.r_rec, index, - offsets2, ULINT_UNDEFINED, - &heap); + offsets2, true, + ULINT_UNDEFINED, &heap); offsets = rec_get_offsets(last_match_rec, index, - offsets, ULINT_UNDEFINED, - &heap); + offsets, true, + ULINT_UNDEFINED, &heap); ut_ad(cmp_rec_rec(test_rec.r_rec, last_match_rec, offsets2, offsets, index) == 0); @@ -1975,7 +1974,8 @@ rtr_cur_search_with_match( ut_ad(!last_match_rec && rec); offsets = rec_get_offsets( - rec, index, offsets, ULINT_UNDEFINED, &heap); + rec, index, offsets, false, + ULINT_UNDEFINED, &heap); child_no = btr_node_ptr_get_child_page_no(rec, offsets); @@ -1997,7 +1997,7 @@ rtr_cur_search_with_match( && mode != PAGE_CUR_RTREE_INSERT) { ulint page_no; - offsets = rec_get_offsets(rec, index, offsets, + offsets = rec_get_offsets(rec, index, offsets, false, ULINT_UNDEFINED, &heap); page_no = btr_node_ptr_get_child_page_no(rec, offsets); diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 6e1095d61ef..ce42d7ed3fe 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -71,8 +71,7 @@ static const char *MSG_UNSUPPORTED_ALTER_ONLINE_ON_VIRTUAL_COLUMN= /** Operations for creating secondary indexes (no rebuild needed) */ static const Alter_inplace_info::HA_ALTER_FLAGS INNOBASE_ONLINE_CREATE = Alter_inplace_info::ADD_INDEX - | Alter_inplace_info::ADD_UNIQUE_INDEX - | Alter_inplace_info::ADD_SPATIAL_INDEX; + | Alter_inplace_info::ADD_UNIQUE_INDEX; /** Operations for rebuilding a table in place */ static const Alter_inplace_info::HA_ALTER_FLAGS INNOBASE_ALTER_REBUILD @@ -702,11 +701,11 @@ ha_innobase::check_if_supported_inplace_alter( codes for certain types. In some cases the signed/unsigned bit was generated differently too. - Online ALTER would change the mtype/unsigned_flag (to what the + Inplace ALTER would change the mtype/unsigned_flag (to what the current code generates) without changing the underlying data represenation, and it might result in data corruption. - Don't do online ALTER if mtype/unsigned_flag are wrong. + Don't do inplace ALTER if mtype/unsigned_flag are wrong. */ for (ulint i = 0, icol= 0; i < table->s->fields; i++) { const Field* field = table->field[i]; @@ -897,29 +896,6 @@ ha_innobase::check_if_supported_inplace_alter( DBUG_ASSERT(!m_prebuilt->table->fts || m_prebuilt->table->fts->doc_col < dict_table_get_n_user_cols(m_prebuilt->table)); - /* Spatial indexes should use copy method for now. - TOO: remove this when below ADD_SPATIAL_INDEX supported. */ - for (uint i = 0; i < ha_alter_info->index_add_count; i++) { - const KEY* key = - &ha_alter_info->key_info_buffer[ - ha_alter_info->index_add_buffer[i]]; - if (key->flags & HA_SPATIAL) { - ha_alter_info->unsupported_reason = innobase_get_err_msg( - ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_GIS); - - DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); - } - } - -#ifdef MYSQL_SPATIAL_INDEX - if (ha_alter_info->handler_flags - & Alter_inplace_info::ADD_SPATIAL_INDEX) { - ha_alter_info->unsupported_reason = innobase_get_err_msg( - ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_GIS); - online = false; - } -#endif - if (m_prebuilt->table->fts && innobase_fulltext_exist(altered_table)) { /* FULLTEXT indexes are supposed to remain. */ @@ -964,7 +940,7 @@ ha_innobase::check_if_supported_inplace_alter( operation is possible. */ } else if (((ha_alter_info->handler_flags & Alter_inplace_info::ADD_PK_INDEX) - || innobase_need_rebuild(ha_alter_info, table)) + || innobase_need_rebuild(ha_alter_info, table)) && (innobase_fulltext_exist(altered_table) || innobase_spatial_exist(altered_table))) { /* Refuse to rebuild the table online, if @@ -982,8 +958,6 @@ ha_innobase::check_if_supported_inplace_alter( ha_alter_info->unsupported_reason = innobase_get_err_msg( ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_GIS); - - DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); } else { ha_alter_info->unsupported_reason = innobase_get_err_msg( @@ -991,10 +965,15 @@ ha_innobase::check_if_supported_inplace_alter( } } else if ((ha_alter_info->handler_flags & Alter_inplace_info::ADD_INDEX)) { - /* Building a full-text index requires a lock. - We could do without a lock if the table already contains - an FTS_DOC_ID column, but in that case we would have - to apply the modification log to the full-text indexes. */ + /* ADD FULLTEXT|SPATIAL INDEX requires a lock. + + We could do ADD FULLTEXT INDEX without a lock if the + table already contains an FTS_DOC_ID column, but in + that case we would have to apply the modification log + to the full-text indexes. + + We could also do ADD SPATIAL INDEX by implementing + row_log_apply() for it. */ for (uint i = 0; i < ha_alter_info->index_add_count; i++) { const KEY* key = @@ -1011,6 +990,12 @@ ha_innobase::check_if_supported_inplace_alter( online = false; break; } + if (key->flags & HA_SPATIAL) { + ha_alter_info->unsupported_reason = innobase_get_err_msg( + ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_GIS); + online = false; + break; + } } } @@ -5621,10 +5606,7 @@ ha_innobase::prepare_inplace_alter_table( /* The clustered index is corrupted. */ my_error(ER_CHECK_NO_SUCH_TABLE, MYF(0)); DBUG_RETURN(true); - } - - if (ha_alter_info->handler_flags - & Alter_inplace_info::CHANGE_CREATE_OPTION) { + } else { const char* invalid_opt = info.create_options_are_invalid(); /* Check engine specific table options */ diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc index eda6684e69f..b53ede41427 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.cc +++ b/storage/innobase/ibuf/ibuf0ibuf.cc @@ -559,7 +559,7 @@ ibuf_init_at_db_start(void) ibuf->index = dict_mem_index_create( "innodb_change_buffer", "CLUST_IND", - IBUF_SPACE_ID, DICT_CLUSTERED | DICT_UNIVERSAL | DICT_IBUF, 1); + IBUF_SPACE_ID, DICT_CLUSTERED | DICT_IBUF, 1); ibuf->index->id = DICT_IBUF_ID_MIN + IBUF_SPACE_ID; ibuf->index->table = dict_mem_table_create( "innodb_change_buffer", IBUF_SPACE_ID, 1, 0, 0, 0); @@ -1502,6 +1502,7 @@ ibuf_dummy_index_create( /* avoid ut_ad(index->cached) in dict_index_get_n_unique_in_tree */ index->cached = TRUE; + ut_d(index->is_dummy = true); return(index); } @@ -4000,8 +4001,8 @@ dump: row_ins_sec_index_entry_by_modify(BTR_MODIFY_LEAF). */ ut_ad(rec_get_deleted_flag(rec, page_is_comp(page))); - offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, - &heap); + offsets = rec_get_offsets(rec, index, NULL, true, + ULINT_UNDEFINED, &heap); update = row_upd_build_sec_rec_difference_binary( rec, index, offsets, entry, heap); @@ -4193,7 +4194,7 @@ ibuf_delete( rec_offs_init(offsets_); offsets = rec_get_offsets( - rec, index, offsets, ULINT_UNDEFINED, &heap); + rec, index, offsets, true, ULINT_UNDEFINED, &heap); if (page_get_n_recs(page) <= 1 || !(REC_INFO_DELETED_FLAG diff --git a/storage/innobase/include/data0data.h b/storage/innobase/include/data0data.h index 87a2228ff2d..b6187d46025 100644 --- a/storage/innobase/include/data0data.h +++ b/storage/innobase/include/data0data.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -586,11 +587,10 @@ struct dfield_t{ unsigned len; /*!< data length; UNIV_SQL_NULL if SQL null */ dtype_t type; /*!< type of data */ - /** Create a deep copy of this object - @param[in] heap the memory heap in which the clone will be - created. - @return the cloned object. */ - dfield_t* clone(mem_heap_t* heap); + /** Create a deep copy of this object. + @param[in,out] heap memory heap in which the clone will be created + @return the cloned object */ + dfield_t* clone(mem_heap_t* heap) const; }; /** Structure for an SQL data tuple of fields (logical record) */ diff --git a/storage/innobase/include/dict0dict.ic b/storage/innobase/include/dict0dict.ic index 1377acb1e64..505ecd95ffa 100644 --- a/storage/innobase/include/dict0dict.ic +++ b/storage/innobase/include/dict0dict.ic @@ -327,20 +327,6 @@ dict_index_is_unique( } /********************************************************************//** -Check whether the index is an universal index tree. -@return nonzero for universal tree, zero for other indexes */ -UNIV_INLINE -ulint -dict_index_is_univ( -/*===============*/ - const dict_index_t* index) /*!< in: index */ -{ - ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); - - return(index->type & DICT_UNIVERSAL); -} - -/********************************************************************//** Check whether the index is a Spatial Index. @return nonzero for Spatial Index, zero for other indexes */ UNIV_INLINE diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index f78267a1465..2ec63c9d3b7 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -66,8 +66,6 @@ combination of types */ auto-generated clustered indexes, also DICT_UNIQUE will be set */ #define DICT_UNIQUE 2 /*!< unique index */ -#define DICT_UNIVERSAL 4 /*!< index which can contain records from any - other index */ #define DICT_IBUF 8 /*!< insert buffer tree */ #define DICT_CORRUPT 16 /*!< bit to store the corrupted flag in SYS_INDEXES.TYPE */ @@ -862,6 +860,8 @@ struct dict_index_t{ data dictionary yet */ #ifdef UNIV_DEBUG + /** whether this is a dummy index object */ + bool is_dummy; uint32_t magic_n;/*!< magic number */ /** Value of dict_index_t::magic_n */ # define DICT_INDEX_MAGIC_N 76789786 diff --git a/storage/innobase/include/gis0rtree.ic b/storage/innobase/include/gis0rtree.ic index 7f64a9b13a1..e852ebd8028 100644 --- a/storage/innobase/include/gis0rtree.ic +++ b/storage/innobase/include/gis0rtree.ic @@ -57,7 +57,8 @@ rtr_page_cal_mbr( page = buf_block_get_frame(block); rec = page_rec_get_next(page_get_infimum_rec(page)); - offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); + offsets = rec_get_offsets(rec, index, offsets, page_is_leaf(page), + ULINT_UNDEFINED, &heap); do { /* The mbr address is in the first field. */ diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h index 7b3726b1fef..459304fc712 100644 --- a/storage/innobase/include/ha_prototypes.h +++ b/storage/innobase/include/ha_prototypes.h @@ -43,7 +43,6 @@ class THD; #undef MYSQL_PFS #undef MYSQL_RENAME_INDEX #undef MYSQL_REPLACE_TRX_IN_THD -#undef MYSQL_SPATIAL_INDEX #undef MYSQL_STORE_FTS_DOC_ID /*******************************************************************//** diff --git a/storage/innobase/include/page0cur.ic b/storage/innobase/include/page0cur.ic index 5eb1bc0cbc5..3e6d40cba4a 100644 --- a/storage/innobase/include/page0cur.ic +++ b/storage/innobase/include/page0cur.ic @@ -280,7 +280,9 @@ page_cur_tuple_insert( rec = rec_convert_dtuple_to_rec((byte*) mem_heap_alloc(*heap, size), index, tuple, n_ext); - *offsets = rec_get_offsets(rec, index, *offsets, ULINT_UNDEFINED, heap); + *offsets = rec_get_offsets(rec, index, *offsets, + page_is_leaf(cursor->block->frame), + ULINT_UNDEFINED, heap); if (buf_block_get_page_zip(cursor->block)) { rec = page_cur_insert_rec_zip( diff --git a/storage/innobase/include/page0page.h b/storage/innobase/include/page0page.h index 9243bcaa717..3b6a0215249 100644 --- a/storage/innobase/include/page0page.h +++ b/storage/innobase/include/page0page.h @@ -167,25 +167,196 @@ directory. */ #define PAGE_DIR_SLOT_MIN_N_OWNED 4 extern my_bool srv_immediate_scrub_data_uncompressed; +#endif /* UNIV_INNOCHECKSUM */ -/************************************************************//** -Gets the start of a page. -@return start of the page */ -UNIV_INLINE +/** Get the start of a page frame. +@param[in] ptr pointer within a page frame +@return start of the page frame */ +MY_ATTRIBUTE((const)) +inline page_t* -page_align( -/*=======*/ - const void* ptr) /*!< in: pointer to page frame */ - MY_ATTRIBUTE((const)); -/************************************************************//** -Gets the offset within a page. +page_align(const void* ptr) +{ + return(static_cast<page_t*>(ut_align_down(ptr, UNIV_PAGE_SIZE))); +} + +/** Gets the byte offset within a page frame. +@param[in] ptr pointer within a page frame @return offset from the start of the page */ -UNIV_INLINE +MY_ATTRIBUTE((const)) +inline ulint -page_offset( -/*========*/ - const void* ptr) /*!< in: pointer to page frame */ - MY_ATTRIBUTE((const)); +page_offset(const void* ptr) +{ + return(ut_align_offset(ptr, UNIV_PAGE_SIZE)); +} + +/** Determine whether an index page is not in ROW_FORMAT=REDUNDANT. +@param[in] page index page +@return nonzero if ROW_FORMAT is one of COMPACT,DYNAMIC,COMPRESSED +@retval 0 if ROW_FORMAT=REDUNDANT */ +inline +byte +page_is_comp(const page_t* page) +{ + ut_ad(!ut_align_offset(page, UNIV_ZIP_SIZE_MIN)); + return(page[PAGE_HEADER + PAGE_N_HEAP] & 0x80); +} + +/** Determine whether an index page is empty. +@param[in] page index page +@return whether the page is empty (PAGE_N_RECS = 0) */ +inline +bool +page_is_empty(const page_t* page) +{ + ut_ad(!ut_align_offset(page, UNIV_ZIP_SIZE_MIN)); + return !*reinterpret_cast<const uint16_t*>(PAGE_HEADER + PAGE_N_RECS + + page); +} + +/** Determine whether an index page contains garbage. +@param[in] page index page +@return whether the page contains garbage (PAGE_GARBAGE is not 0) */ +inline +bool +page_has_garbage(const page_t* page) +{ + ut_ad(!ut_align_offset(page, UNIV_ZIP_SIZE_MIN)); + return *reinterpret_cast<const uint16_t*>(PAGE_HEADER + PAGE_GARBAGE + + page); +} + +/** Determine whether an B-tree or R-tree index page is a leaf page. +@param[in] page index page +@return true if the page is a leaf (PAGE_LEVEL = 0) */ +inline +bool +page_is_leaf(const page_t* page) +{ + ut_ad(!ut_align_offset(page, UNIV_ZIP_SIZE_MIN)); + return !*reinterpret_cast<const uint16_t*>(PAGE_HEADER + PAGE_LEVEL + + page); +} + +#ifndef UNIV_INNOCHECKSUM +/** Determine whether an index page record is not in ROW_FORMAT=REDUNDANT. +@param[in] rec record in an index page frame (not a copy) +@return nonzero if ROW_FORMAT is one of COMPACT,DYNAMIC,COMPRESSED +@retval 0 if ROW_FORMAT=REDUNDANT */ +inline +byte +page_rec_is_comp(const byte* rec) +{ + return(page_is_comp(page_align(rec))); +} + +/** Determine the offset of the infimum record on the page. +@param[in] page index page +@return offset of the infimum record in record list, relative from page */ +inline +unsigned +page_get_infimum_offset(const page_t* page) +{ + ut_ad(!page_offset(page)); + return page_is_comp(page) ? PAGE_NEW_INFIMUM : PAGE_OLD_INFIMUM; +} + +/** Determine the offset of the supremum record on the page. +@param[in] page index page +@return offset of the supremum record in record list, relative from page */ +inline +unsigned +page_get_supremum_offset(const page_t* page) +{ + ut_ad(!page_offset(page)); + return page_is_comp(page) ? PAGE_NEW_SUPREMUM : PAGE_OLD_SUPREMUM; +} + +/** Determine whether an index page record is a user record. +@param[in] offset record offset in the page +@retval true if a user record +@retval false if the infimum or supremum pseudo-record */ +inline +bool +page_rec_is_user_rec_low(ulint offset) +{ + compile_time_assert(PAGE_OLD_INFIMUM >= PAGE_NEW_INFIMUM); + compile_time_assert(PAGE_OLD_SUPREMUM >= PAGE_NEW_SUPREMUM); + compile_time_assert(PAGE_NEW_INFIMUM < PAGE_OLD_SUPREMUM); + compile_time_assert(PAGE_OLD_INFIMUM < PAGE_NEW_SUPREMUM); + compile_time_assert(PAGE_NEW_SUPREMUM < PAGE_OLD_SUPREMUM_END); + compile_time_assert(PAGE_OLD_SUPREMUM < PAGE_NEW_SUPREMUM_END); + ut_ad(offset >= PAGE_NEW_INFIMUM); + ut_ad(offset <= UNIV_PAGE_SIZE - PAGE_EMPTY_DIR_START); + + return(offset != PAGE_NEW_SUPREMUM + && offset != PAGE_NEW_INFIMUM + && offset != PAGE_OLD_INFIMUM + && offset != PAGE_OLD_SUPREMUM); +} + +/** Determine if a record is the supremum record on an index page. +@param[in] offset record offset in an index page +@return true if the supremum record */ +inline +bool +page_rec_is_supremum_low(ulint offset) +{ + ut_ad(offset >= PAGE_NEW_INFIMUM); + ut_ad(offset <= UNIV_PAGE_SIZE - PAGE_EMPTY_DIR_START); + return(offset == PAGE_NEW_SUPREMUM || offset == PAGE_OLD_SUPREMUM); +} + +/** Determine if a record is the infimum record on an index page. +@param[in] offset record offset in an index page +@return true if the infimum record */ +inline +bool +page_rec_is_infimum_low(ulint offset) +{ + ut_ad(offset >= PAGE_NEW_INFIMUM); + ut_ad(offset <= UNIV_PAGE_SIZE - PAGE_EMPTY_DIR_START); + return(offset == PAGE_NEW_INFIMUM || offset == PAGE_OLD_INFIMUM); +} + +/** Determine whether an B-tree or R-tree index record is in a leaf page. +@param[in] rec index record in an index page +@return true if the record is in a leaf page */ +inline +bool +page_rec_is_leaf(const page_t* rec) +{ + const page_t* page = page_align(rec); + ut_ad(rec - page >= page_get_infimum_offset(page)); + bool leaf = page_is_leaf(page); + ut_ad(!page_rec_is_comp(rec) + || !page_rec_is_user_rec_low(rec - page) + || leaf == !rec_get_node_ptr_flag(rec)); + return leaf; +} + +/** Determine whether an index page record is a user record. +@param[in] rec record in an index page +@return true if a user record */ +inline +bool +page_rec_is_user_rec(const rec_t* rec); + +/** Determine whether an index page record is the supremum record. +@param[in] rec record in an index page +@return true if the supremum record */ +inline +bool +page_rec_is_supremum(const rec_t* rec); + +/** Determine whether an index page record is the infimum record. +@param[in] rec record in an index page +@return true if the infimum record */ +inline +bool +page_rec_is_infimum(const rec_t* rec); + /*************************************************************//** Returns the max trx id field value. */ UNIV_INLINE @@ -321,22 +492,6 @@ page_header_reset_last_insert( page_zip_des_t* page_zip,/*!< in/out: compressed page whose uncompressed part will be updated, or NULL */ mtr_t* mtr); /*!< in: mtr */ -/************************************************************//** -Gets the offset of the first record on the page. -@return offset of the first record in record list, relative from page */ -UNIV_INLINE -ulint -page_get_infimum_offset( -/*====================*/ - const page_t* page); /*!< in: page which must have record(s) */ -/************************************************************//** -Gets the offset of the last record on the page. -@return offset of the last record in record list, relative from page */ -UNIV_INLINE -ulint -page_get_supremum_offset( -/*=====================*/ - const page_t* page); /*!< in: page which must have record(s) */ #define page_get_infimum_rec(page) ((page) + page_get_infimum_offset(page)) #define page_get_supremum_rec(page) ((page) + page_get_supremum_offset(page)) @@ -522,23 +677,7 @@ ulint page_dir_find_owner_slot( /*=====================*/ const rec_t* rec); /*!< in: the physical record */ -/************************************************************//** -Determine whether the page is in new-style compact format. -@return nonzero if the page is in compact format, zero if it is in -old-style format */ -UNIV_INLINE -ulint -page_is_comp( -/*=========*/ - const page_t* page); /*!< in: index page */ -/************************************************************//** -TRUE if the record is on a page in compact format. -@return nonzero if in compact format */ -UNIV_INLINE -ulint -page_rec_is_comp( -/*=============*/ - const rec_t* rec); /*!< in: record */ + /***************************************************************//** Returns the heap number of a record. @return heap number */ @@ -547,24 +686,6 @@ ulint page_rec_get_heap_no( /*=================*/ const rec_t* rec); /*!< in: the physical record */ -/************************************************************//** -Determine whether the page is a B-tree leaf. -@return true if the page is a B-tree leaf (PAGE_LEVEL = 0) */ -UNIV_INLINE -bool -page_is_leaf( -/*=========*/ - const page_t* page) /*!< in: page */ - MY_ATTRIBUTE((warn_unused_result)); -/************************************************************//** -Determine whether the page is empty. -@return true if the page is empty (PAGE_N_RECS = 0) */ -UNIV_INLINE -bool -page_is_empty( -/*==========*/ - const page_t* page) /*!< in: page */ - MY_ATTRIBUTE((warn_unused_result)); /** Determine whether a page is an index root page. @param[in] page page frame @return true if the page is a root page of an index */ @@ -574,15 +695,6 @@ page_is_root( const page_t* page) MY_ATTRIBUTE((warn_unused_result)); /************************************************************//** -Determine whether the page contains garbage. -@return true if the page contains garbage (PAGE_GARBAGE is not 0) */ -UNIV_INLINE -bool -page_has_garbage( -/*=============*/ - const page_t* page) /*!< in: page */ - MY_ATTRIBUTE((warn_unused_result)); -/************************************************************//** Gets the pointer to the next record on the page. @return pointer to next record */ UNIV_INLINE @@ -645,62 +757,6 @@ page_rec_get_prev( /*==============*/ rec_t* rec); /*!< in: pointer to record, must not be page infimum */ -/************************************************************//** -TRUE if the record is a user record on the page. -@return TRUE if a user record */ -UNIV_INLINE -ibool -page_rec_is_user_rec_low( -/*=====================*/ - ulint offset) /*!< in: record offset on page */ - MY_ATTRIBUTE((const)); -/************************************************************//** -TRUE if the record is the supremum record on a page. -@return TRUE if the supremum record */ -UNIV_INLINE -ibool -page_rec_is_supremum_low( -/*=====================*/ - ulint offset) /*!< in: record offset on page */ - MY_ATTRIBUTE((const)); -/************************************************************//** -TRUE if the record is the infimum record on a page. -@return TRUE if the infimum record */ -UNIV_INLINE -ibool -page_rec_is_infimum_low( -/*====================*/ - ulint offset) /*!< in: record offset on page */ - MY_ATTRIBUTE((const)); - -/************************************************************//** -TRUE if the record is a user record on the page. -@return TRUE if a user record */ -UNIV_INLINE -ibool -page_rec_is_user_rec( -/*=================*/ - const rec_t* rec) /*!< in: record */ - MY_ATTRIBUTE((warn_unused_result)); -/************************************************************//** -TRUE if the record is the supremum record on a page. -@return TRUE if the supremum record */ -UNIV_INLINE -ibool -page_rec_is_supremum( -/*=================*/ - const rec_t* rec) /*!< in: record */ - MY_ATTRIBUTE((warn_unused_result)); - -/************************************************************//** -TRUE if the record is the infimum record on a page. -@return TRUE if the infimum record */ -UNIV_INLINE -ibool -page_rec_is_infimum( -/*================*/ - const rec_t* rec) /*!< in: record */ - MY_ATTRIBUTE((warn_unused_result)); /************************************************************//** true if the record is the first user record on a page. diff --git a/storage/innobase/include/page0page.ic b/storage/innobase/include/page0page.ic index db98f2e6558..0062db56bfa 100644 --- a/storage/innobase/include/page0page.ic +++ b/storage/innobase/include/page0page.ic @@ -40,32 +40,7 @@ Created 2/2/1994 Heikki Tuuri #undef UNIV_INLINE #define UNIV_INLINE #endif -#endif /* !UNIV_INNOCHECKSUM */ -/************************************************************//** -Gets the start of a page. -@return start of the page */ -UNIV_INLINE -page_t* -page_align( -/*=======*/ - const void* ptr) /*!< in: pointer to page frame */ -{ - return((page_t*) ut_align_down(ptr, UNIV_PAGE_SIZE)); -} - -#ifndef UNIV_INNOCHECKSUM -/************************************************************//** -Gets the offset within a page. -@return offset from the start of the page */ -UNIV_INLINE -ulint -page_offset( -/*========*/ - const void* ptr) /*!< in: pointer to page frame */ -{ - return(ut_align_offset(ptr, UNIV_PAGE_SIZE)); -} /*************************************************************//** Returns the max trx id field value. */ UNIV_INLINE @@ -286,34 +261,6 @@ page_header_reset_last_insert( } } -#endif /* !UNIV_INNOCHECKSUM */ - -/************************************************************//** -Determine whether the page is in new-style compact format. -@return nonzero if the page is in compact format, zero if it is in -old-style format */ -UNIV_INLINE -ulint -page_is_comp( -/*=========*/ - const page_t* page) /*!< in: index page */ -{ - return(page[PAGE_HEADER + PAGE_N_HEAP] & 0x80); -} - -#ifndef UNIV_INNOCHECKSUM -/************************************************************//** -TRUE if the record is on a page in compact format. -@return nonzero if in compact format */ -UNIV_INLINE -ulint -page_rec_is_comp( -/*=============*/ - const rec_t* rec) /*!< in: record */ -{ - return(page_is_comp(page_align(rec))); -} - /***************************************************************//** Returns the heap number of a record. @return heap number */ @@ -330,33 +277,6 @@ page_rec_get_heap_no( } } -#endif /* !UNIV_INNOCHECKSUM */ - -/************************************************************//** -Determine whether the page is a B-tree leaf. -@return true if the page is a B-tree leaf (PAGE_LEVEL = 0) */ -UNIV_INLINE -bool -page_is_leaf( -/*=========*/ - const page_t* page) /*!< in: page */ -{ - return(!*(const uint16*) (page + (PAGE_HEADER + PAGE_LEVEL))); -} - -#ifndef UNIV_INNOCHECKSUM -/************************************************************//** -Determine whether the page is empty. -@return true if the page is empty (PAGE_N_RECS = 0) */ -UNIV_INLINE -bool -page_is_empty( -/*==========*/ - const page_t* page) /*!< in: page */ -{ - return(!*(const uint16*) (page + (PAGE_HEADER + PAGE_N_RECS))); -} - /** Determine whether a page is an index root page. @param[in] page page frame @return true if the page is a root page of an index */ @@ -382,162 +302,36 @@ page_is_root( == IB_UINT64_MAX); } -/************************************************************//** -Determine whether the page contains garbage. -@return true if the page contains garbage (PAGE_GARBAGE is not 0) */ -UNIV_INLINE +/** Determine whether an index page record is a user record. +@param[in] rec record in an index page +@return true if a user record */ +inline bool -page_has_garbage( -/*=============*/ - const page_t* page) /*!< in: page */ -{ - return(!!*(const uint16*) (page + (PAGE_HEADER + PAGE_GARBAGE))); -} - -/************************************************************//** -Gets the offset of the first record on the page. -@return offset of the first record in record list, relative from page */ -UNIV_INLINE -ulint -page_get_infimum_offset( -/*====================*/ - const page_t* page) /*!< in: page which must have record(s) */ -{ - ut_ad(page); - ut_ad(!page_offset(page)); - - if (page_is_comp(page)) { - return(PAGE_NEW_INFIMUM); - } else { - return(PAGE_OLD_INFIMUM); - } -} - -/************************************************************//** -Gets the offset of the last record on the page. -@return offset of the last record in record list, relative from page */ -UNIV_INLINE -ulint -page_get_supremum_offset( -/*=====================*/ - const page_t* page) /*!< in: page which must have record(s) */ -{ - ut_ad(page); - ut_ad(!page_offset(page)); - - if (page_is_comp(page)) { - return(PAGE_NEW_SUPREMUM); - } else { - return(PAGE_OLD_SUPREMUM); - } -} - -/************************************************************//** -TRUE if the record is a user record on the page. -@return TRUE if a user record */ -UNIV_INLINE -ibool -page_rec_is_user_rec_low( -/*=====================*/ - ulint offset) /*!< in: record offset on page */ -{ - ut_ad(offset >= PAGE_NEW_INFIMUM); -#if PAGE_OLD_INFIMUM < PAGE_NEW_INFIMUM -# error "PAGE_OLD_INFIMUM < PAGE_NEW_INFIMUM" -#endif -#if PAGE_OLD_SUPREMUM < PAGE_NEW_SUPREMUM -# error "PAGE_OLD_SUPREMUM < PAGE_NEW_SUPREMUM" -#endif -#if PAGE_NEW_INFIMUM > PAGE_OLD_SUPREMUM -# error "PAGE_NEW_INFIMUM > PAGE_OLD_SUPREMUM" -#endif -#if PAGE_OLD_INFIMUM > PAGE_NEW_SUPREMUM -# error "PAGE_OLD_INFIMUM > PAGE_NEW_SUPREMUM" -#endif -#if PAGE_NEW_SUPREMUM > PAGE_OLD_SUPREMUM_END -# error "PAGE_NEW_SUPREMUM > PAGE_OLD_SUPREMUM_END" -#endif -#if PAGE_OLD_SUPREMUM > PAGE_NEW_SUPREMUM_END -# error "PAGE_OLD_SUPREMUM > PAGE_NEW_SUPREMUM_END" -#endif - ut_ad(offset <= UNIV_PAGE_SIZE - PAGE_EMPTY_DIR_START); - - return(offset != PAGE_NEW_SUPREMUM - && offset != PAGE_NEW_INFIMUM - && offset != PAGE_OLD_INFIMUM - && offset != PAGE_OLD_SUPREMUM); -} - -/************************************************************//** -TRUE if the record is the supremum record on a page. -@return TRUE if the supremum record */ -UNIV_INLINE -ibool -page_rec_is_supremum_low( -/*=====================*/ - ulint offset) /*!< in: record offset on page */ -{ - ut_ad(offset >= PAGE_NEW_INFIMUM); - ut_ad(offset <= UNIV_PAGE_SIZE - PAGE_EMPTY_DIR_START); - - return(offset == PAGE_NEW_SUPREMUM - || offset == PAGE_OLD_SUPREMUM); -} - -/************************************************************//** -TRUE if the record is the infimum record on a page. -@return TRUE if the infimum record */ -UNIV_INLINE -ibool -page_rec_is_infimum_low( -/*====================*/ - ulint offset) /*!< in: record offset on page */ -{ - ut_ad(offset >= PAGE_NEW_INFIMUM); - ut_ad(offset <= UNIV_PAGE_SIZE - PAGE_EMPTY_DIR_START); - - return(offset == PAGE_NEW_INFIMUM || offset == PAGE_OLD_INFIMUM); -} - -/************************************************************//** -TRUE if the record is a user record on the page. -@return TRUE if a user record */ -UNIV_INLINE -ibool -page_rec_is_user_rec( -/*=================*/ - const rec_t* rec) /*!< in: record */ +page_rec_is_user_rec(const rec_t* rec) { ut_ad(page_rec_check(rec)); - return(page_rec_is_user_rec_low(page_offset(rec))); } -/************************************************************//** -TRUE if the record is the supremum record on a page. -@return TRUE if the supremum record */ -UNIV_INLINE -ibool -page_rec_is_supremum( -/*=================*/ - const rec_t* rec) /*!< in: record */ +/** Determine whether an index page record is the supremum record. +@param[in] rec record in an index page +@return true if the supremum record */ +inline +bool +page_rec_is_supremum(const rec_t* rec) { ut_ad(page_rec_check(rec)); - return(page_rec_is_supremum_low(page_offset(rec))); } -/************************************************************//** -TRUE if the record is the infimum record on a page. -@return TRUE if the infimum record */ -UNIV_INLINE -ibool -page_rec_is_infimum( -/*================*/ - const rec_t* rec) /*!< in: record */ +/** Determine whether an index page record is the infimum record. +@param[in] rec record in an index page +@return true if the infimum record */ +inline +bool +page_rec_is_infimum(const rec_t* rec) { ut_ad(page_rec_check(rec)); - return(page_rec_is_infimum_low(page_offset(rec))); } diff --git a/storage/innobase/include/rem0rec.h b/storage/innobase/include/rem0rec.h index 61220d4f533..7076352d1c2 100644 --- a/storage/innobase/include/rem0rec.h +++ b/storage/innobase/include/rem0rec.h @@ -444,38 +444,41 @@ rec_get_n_extern_new( ulint n) /*!< in: number of columns to scan */ MY_ATTRIBUTE((nonnull, warn_unused_result)); -/******************************************************//** -The following function determines the offsets to each field -in the record. It can reuse a previously allocated array. +/** Determine the offsets to each field in an index record. +@param[in] rec physical record +@param[in] index the index that the record belongs to +@param[in,out] offsets array comprising offsets[0] allocated elements, + or an array from rec_get_offsets(), or NULL +@param[in] leaf whether this is a leaf-page record +@param[in] n_fields maximum number of offsets to compute + (ULINT_UNDEFINED to compute all offsets) +@param[in,out] heap memory heap @return the new offsets */ ulint* rec_get_offsets_func( -/*=================*/ - const rec_t* rec, /*!< in: physical record */ - const dict_index_t* index, /*!< in: record descriptor */ - ulint* offsets,/*!< in/out: array consisting of - offsets[0] allocated elements, - or an array from rec_get_offsets(), - or NULL */ - ulint n_fields,/*!< in: maximum number of - initialized fields - (ULINT_UNDEFINED if all fields) */ + const rec_t* rec, + const dict_index_t* index, + ulint* offsets, +#ifdef UNIV_DEBUG + bool leaf, +#endif /* UNIV_DEBUG */ + ulint n_fields, #ifdef UNIV_DEBUG const char* file, /*!< in: file name where called */ unsigned line, /*!< in: line number where called */ #endif /* UNIV_DEBUG */ mem_heap_t** heap) /*!< in/out: memory heap */ #ifdef UNIV_DEBUG - MY_ATTRIBUTE((nonnull(1,2,5,7),warn_unused_result)); + MY_ATTRIBUTE((nonnull(1,2,6,8),warn_unused_result)); #else /* UNIV_DEBUG */ MY_ATTRIBUTE((nonnull(1,2,5),warn_unused_result)); #endif /* UNIV_DEBUG */ #ifdef UNIV_DEBUG -# define rec_get_offsets(rec,index,offsets,n,heap) \ - rec_get_offsets_func(rec,index,offsets,n,__FILE__,__LINE__,heap) +# define rec_get_offsets(rec, index, offsets, leaf, n, heap) \ + rec_get_offsets_func(rec,index,offsets,leaf,n,__FILE__,__LINE__,heap) #else /* UNIV_DEBUG */ -# define rec_get_offsets(rec, index, offsets, n, heap) \ +# define rec_get_offsets(rec, index, offsets, leaf, n, heap) \ rec_get_offsets_func(rec, index, offsets, n, heap) #endif /* UNIV_DEBUG */ @@ -933,18 +936,21 @@ rec_get_converted_size( const dtuple_t* dtuple, /*!< in: data tuple */ ulint n_ext) /*!< in: number of externally stored columns */ MY_ATTRIBUTE((warn_unused_result, nonnull)); -/**************************************************************//** -Copies the first n fields of a physical record to a data tuple. -The fields are copied to the memory heap. */ +/** Copy the first n fields of a (copy of a) physical record to a data tuple. +The fields are copied into the memory heap. +@param[out] tuple data tuple +@param[in] rec index record, or a copy thereof +@param[in] is_leaf whether rec is a leaf page record +@param[in] n_fields number of fields to copy +@param[in,out] heap memory heap */ void rec_copy_prefix_to_dtuple( -/*======================*/ - dtuple_t* tuple, /*!< out: data tuple */ - const rec_t* rec, /*!< in: physical record */ - const dict_index_t* index, /*!< in: record descriptor */ - ulint n_fields, /*!< in: number of fields - to copy */ - mem_heap_t* heap) /*!< in: memory heap */ + dtuple_t* tuple, + const rec_t* rec, + const dict_index_t* index, + bool is_leaf, + ulint n_fields, + mem_heap_t* heap) MY_ATTRIBUTE((nonnull)); /***************************************************************//** Validates the consistency of a physical record. diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index d6e8be7fac0..b2f0d90583e 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -5590,13 +5590,14 @@ lock_rec_print(FILE* file, const lock_t* lock) fprintf(file, "Record lock, heap no %lu", (ulong) i); if (block) { + ut_ad(page_is_leaf(block->frame)); const rec_t* rec; rec = page_find_rec_with_heap_no( buf_block_get_frame(block), i); offsets = rec_get_offsets( - rec, lock->index, offsets, + rec, lock->index, offsets, true, ULINT_UNDEFINED, &heap); putc(' ', file); @@ -6428,8 +6429,10 @@ loop: rec = page_find_rec_with_heap_no(block->frame, i); ut_a(rec); + ut_ad(page_rec_is_leaf(rec)); offsets = rec_get_offsets(rec, lock->index, offsets, - ULINT_UNDEFINED, &heap); + true, ULINT_UNDEFINED, + &heap); /* If this thread is holding the file space latch (fil_space_t::latch), the following @@ -6772,7 +6775,7 @@ lock_rec_insert_check_and_lock( const ulint* offsets; rec_offs_init(offsets_); - offsets = rec_get_offsets(next_rec, index, offsets_, + offsets = rec_get_offsets(next_rec, index, offsets_, true, ULINT_UNDEFINED, &heap); ut_ad(lock_rec_queue_validate( @@ -6999,7 +7002,7 @@ lock_sec_rec_modify_check_and_lock( const ulint* offsets; rec_offs_init(offsets_); - offsets = rec_get_offsets(rec, index, offsets_, + offsets = rec_get_offsets(rec, index, offsets_, true, ULINT_UNDEFINED, &heap); ut_ad(lock_rec_queue_validate( @@ -7209,7 +7212,8 @@ lock_clust_rec_read_check_and_lock_alt( dberr_t err; rec_offs_init(offsets_); - offsets = rec_get_offsets(rec, index, offsets, + ut_ad(page_rec_is_leaf(rec)); + offsets = rec_get_offsets(rec, index, offsets, true, ULINT_UNDEFINED, &tmp_heap); err = lock_clust_rec_read_check_and_lock(flags, block, rec, index, offsets, mode, gap_mode, thr); diff --git a/storage/innobase/mtr/mtr0log.cc b/storage/innobase/mtr/mtr0log.cc index 7d97aaa3f42..8cfde15a3ba 100644 --- a/storage/innobase/mtr/mtr0log.cc +++ b/storage/innobase/mtr/mtr0log.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -443,10 +444,11 @@ mlog_open_and_write_index( alloc = mtr_buf_t::MAX_DATA_SIZE; } + const bool is_leaf = page_is_leaf(page_align(rec)); + /* For spatial index, on non-leaf page, we just keep 2 fields, MBR and page no. */ - if (dict_index_is_spatial(index) - && !page_is_leaf(page_align(rec))) { + if (!is_leaf && dict_index_is_spatial(index)) { n = DICT_INDEX_SPATIAL_NODEPTR_SIZE; } @@ -464,7 +466,7 @@ mlog_open_and_write_index( mach_write_to_2(log_ptr, n); log_ptr += 2; - if (page_is_leaf(page_align(rec))) { + if (is_leaf) { mach_write_to_2( log_ptr, dict_index_get_n_unique_in_tree(index)); } else { @@ -601,6 +603,7 @@ mlog_parse_index( } /* avoid ut_ad(index->cached) in dict_index_get_n_unique_in_tree */ ind->cached = TRUE; + ut_d(ind->is_dummy = true); *index = ind; return(ptr); } diff --git a/storage/innobase/page/page0cur.cc b/storage/innobase/page/page0cur.cc index e5c903935f1..23a11fcfaa3 100644 --- a/storage/innobase/page/page0cur.cc +++ b/storage/innobase/page/page0cur.cc @@ -107,9 +107,10 @@ page_cur_try_search_shortcut( rec_offs_init(offsets_); ut_ad(dtuple_check_typed(tuple)); + ut_ad(page_is_leaf(page)); rec = page_header_get_ptr(page, PAGE_LAST_INSERT); - offsets = rec_get_offsets(rec, index, offsets, + offsets = rec_get_offsets(rec, index, offsets, true, dtuple_get_n_fields(tuple), &heap); ut_ad(rec); @@ -124,7 +125,7 @@ page_cur_try_search_shortcut( next_rec = page_rec_get_next_const(rec); if (!page_rec_is_supremum(next_rec)) { - offsets = rec_get_offsets(next_rec, index, offsets, + offsets = rec_get_offsets(next_rec, index, offsets, true, dtuple_get_n_fields(tuple), &heap); if (cmp_dtuple_rec_with_match(tuple, next_rec, offsets, @@ -190,9 +191,10 @@ page_cur_try_search_shortcut_bytes( rec_offs_init(offsets_); ut_ad(dtuple_check_typed(tuple)); + ut_ad(page_is_leaf(page)); rec = page_header_get_ptr(page, PAGE_LAST_INSERT); - offsets = rec_get_offsets(rec, index, offsets, + offsets = rec_get_offsets(rec, index, offsets, true, dtuple_get_n_fields(tuple), &heap); ut_ad(rec); @@ -213,7 +215,7 @@ page_cur_try_search_shortcut_bytes( next_rec = page_rec_get_next_const(rec); if (!page_rec_is_supremum(next_rec)) { - offsets = rec_get_offsets(next_rec, index, offsets, + offsets = rec_get_offsets(next_rec, index, offsets, true, dtuple_get_n_fields(tuple), &heap); if (cmp_dtuple_rec_with_match_bytes( @@ -354,9 +356,10 @@ page_cur_search_with_match( #endif /* UNIV_ZIP_DEBUG */ ut_d(page_check_dir(page)); + const bool is_leaf = page_is_leaf(page); #ifdef BTR_CUR_HASH_ADAPT - if (page_is_leaf(page) + if (is_leaf && (mode == PAGE_CUR_LE) && !dict_index_is_spatial(index) && (page_header_get_field(page, PAGE_N_DIRECTION) > 3) @@ -383,7 +386,7 @@ page_cur_search_with_match( if (dict_index_is_spatial(index) && mode > PAGE_CUR_LE) { /* For leaf level insert, we still use the traditional compare function for now */ - if (mode == PAGE_CUR_RTREE_INSERT && page_is_leaf(page)){ + if (mode == PAGE_CUR_RTREE_INSERT && is_leaf) { mode = PAGE_CUR_LE; } else { rtr_cur_search_with_match( @@ -428,7 +431,7 @@ page_cur_search_with_match( offsets = offsets_; offsets = rec_get_offsets( - mid_rec, index, offsets, + mid_rec, index, offsets, is_leaf, dtuple_get_n_fields_cmp(tuple), &heap); cmp = cmp_dtuple_rec_with_match( @@ -482,7 +485,7 @@ up_slot_match: offsets = offsets_; offsets = rec_get_offsets( - mid_rec, index, offsets, + mid_rec, index, offsets, is_leaf, dtuple_get_n_fields_cmp(tuple), &heap); cmp = cmp_dtuple_rec_with_match( @@ -664,6 +667,7 @@ page_cur_search_with_match_bytes( /* Perform binary search until the lower and upper limit directory slots come to the distance 1 of each other */ + ut_d(bool is_leaf = page_is_leaf(page)); while (up - low > 1) { mid = (low + up) / 2; @@ -675,7 +679,7 @@ page_cur_search_with_match_bytes( up_matched_fields, up_matched_bytes); offsets = rec_get_offsets( - mid_rec, index, offsets_, + mid_rec, index, offsets_, is_leaf, dtuple_get_n_fields_cmp(tuple), &heap); cmp = cmp_dtuple_rec_with_match_bytes( @@ -732,7 +736,7 @@ up_slot_match: up_matched_fields, up_matched_bytes); offsets = rec_get_offsets( - mid_rec, index, offsets_, + mid_rec, index, offsets_, is_leaf, dtuple_get_n_fields_cmp(tuple), &heap); cmp = cmp_dtuple_rec_with_match_bytes( @@ -850,15 +854,9 @@ page_cur_insert_rec_write_log( const byte* log_end; ulint i; - /* Avoid REDO logging to save on costly IO because - temporary tables are not recovered during crash recovery. */ if (dict_table_is_temporary(index->table)) { - byte* log_ptr = mlog_open(mtr, 0); - if (log_ptr == NULL) { - return; - } - mlog_close(mtr, log_ptr); - log_ptr = NULL; + ut_ad(!mlog_open(mtr, 0)); + return; } ut_a(rec_size < UNIV_PAGE_SIZE); @@ -867,6 +865,8 @@ page_cur_insert_rec_write_log( ut_ad(!page_rec_is_comp(insert_rec) == !dict_table_is_comp(index->table)); + ut_d(const bool is_leaf = page_rec_is_leaf(cursor_rec)); + { mem_heap_t* heap = NULL; ulint cur_offs_[REC_OFFS_NORMAL_SIZE]; @@ -879,9 +879,9 @@ page_cur_insert_rec_write_log( rec_offs_init(ins_offs_); cur_offs = rec_get_offsets(cursor_rec, index, cur_offs_, - ULINT_UNDEFINED, &heap); + is_leaf, ULINT_UNDEFINED, &heap); ins_offs = rec_get_offsets(insert_rec, index, ins_offs_, - ULINT_UNDEFINED, &heap); + is_leaf, ULINT_UNDEFINED, &heap); extra_size = rec_offs_extra_size(ins_offs); cur_extra_size = rec_offs_extra_size(cur_offs); @@ -1139,7 +1139,9 @@ page_cur_parse_insert_rec( /* Read from the log the inserted index record end segment which differs from the cursor record */ - offsets = rec_get_offsets(cursor_rec, index, offsets, + ut_d(bool is_leaf = page_is_leaf(page)); + + offsets = rec_get_offsets(cursor_rec, index, offsets, is_leaf, ULINT_UNDEFINED, &heap); if (!(end_seg_len & 0x1UL)) { @@ -1184,7 +1186,7 @@ page_cur_parse_insert_rec( page_cur_position(cursor_rec, block, &cursor); offsets = rec_get_offsets(buf + origin_offset, index, offsets, - ULINT_UNDEFINED, &heap); + is_leaf, ULINT_UNDEFINED, &heap); if (UNIV_UNLIKELY(!page_cur_rec_insert(&cursor, buf + origin_offset, index, offsets, mtr))) { @@ -1275,7 +1277,8 @@ page_cur_insert_rec_low( rec_offs_init(foffsets_); foffsets = rec_get_offsets( - free_rec, index, foffsets, ULINT_UNDEFINED, &heap); + free_rec, index, foffsets, page_is_leaf(page), + ULINT_UNDEFINED, &heap); if (rec_offs_size(foffsets) < rec_size) { if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); @@ -1705,6 +1708,7 @@ page_cur_insert_rec_zip( rec_offs_init(foffsets_); foffsets = rec_get_offsets(free_rec, index, foffsets, + page_rec_is_leaf(free_rec), ULINT_UNDEFINED, &heap); if (rec_offs_size(foffsets) < rec_size) { too_small: @@ -2052,7 +2056,6 @@ page_copy_rec_list_end_to_created_page( page_header_set_ptr(new_page, NULL, PAGE_HEAP_TOP, new_page + UNIV_PAGE_SIZE - 1); #endif - log_ptr = page_copy_rec_list_to_created_page_write_log(new_page, index, mtr); @@ -2075,8 +2078,10 @@ page_copy_rec_list_end_to_created_page( slot_index = 0; n_recs = 0; + ut_d(const bool is_leaf = page_is_leaf(new_page)); + do { - offsets = rec_get_offsets(rec, index, offsets, + offsets = rec_get_offsets(rec, index, offsets, is_leaf, ULINT_UNDEFINED, &heap); insert_rec = rec_copy(heap_top, rec, offsets); @@ -2251,6 +2256,7 @@ page_cur_parse_delete_rec( page_cur_delete_rec(&cursor, index, rec_get_offsets(rec, index, offsets_, + page_rec_is_leaf(rec), ULINT_UNDEFINED, &heap), mtr); if (UNIV_LIKELY_NULL(heap)) { diff --git a/storage/innobase/page/page0page.cc b/storage/innobase/page/page0page.cc index b2c27acfbaa..fcc77aeb591 100644 --- a/storage/innobase/page/page0page.cc +++ b/storage/innobase/page/page0page.cc @@ -598,6 +598,7 @@ page_copy_rec_list_end_no_locks( ut_a(page_is_comp(new_page) == page_rec_is_comp(rec)); ut_a(mach_read_from_2(new_page + UNIV_PAGE_SIZE - 10) == (ulint) (page_is_comp(new_page) ? PAGE_NEW_INFIMUM : PAGE_OLD_INFIMUM)); + ut_d(const bool is_leaf = page_is_leaf(block->frame)); cur2 = page_get_infimum_rec(buf_block_get_frame(new_block)); @@ -606,7 +607,7 @@ page_copy_rec_list_end_no_locks( while (!page_cur_is_after_last(&cur1)) { rec_t* cur1_rec = page_cur_get_rec(&cur1); rec_t* ins_rec; - offsets = rec_get_offsets(cur1_rec, index, offsets, + offsets = rec_get_offsets(cur1_rec, index, offsets, is_leaf, ULINT_UNDEFINED, &heap); ins_rec = page_cur_insert_rec_low(cur2, index, cur1_rec, offsets, mtr); @@ -835,6 +836,8 @@ page_copy_rec_list_start( cur2 = ret; + const bool is_leaf = page_rec_is_leaf(rec); + /* Copy records from the original page to the new page */ if (dict_index_is_spatial(index)) { ulint max_to_move = page_get_n_recs( @@ -856,6 +859,7 @@ page_copy_rec_list_start( while (page_cur_get_rec(&cur1) != rec) { rec_t* cur1_rec = page_cur_get_rec(&cur1); offsets = rec_get_offsets(cur1_rec, index, offsets, + is_leaf, ULINT_UNDEFINED, &heap); cur2 = page_cur_insert_rec_low(cur2, index, cur1_rec, offsets, mtr); @@ -872,8 +876,7 @@ page_copy_rec_list_start( same temp-table in parallel. max_trx_id is ignored for temp tables because it not required for MVCC. */ - if (dict_index_is_sec_or_ibuf(index) - && page_is_leaf(page_align(rec)) + if (is_leaf && dict_index_is_sec_or_ibuf(index) && !dict_table_is_temporary(index->table)) { page_update_max_trx_id(new_block, NULL, page_get_max_trx_id(page_align(rec)), @@ -1103,6 +1106,8 @@ delete_all: ? MLOG_COMP_LIST_END_DELETE : MLOG_LIST_END_DELETE, mtr); + ut_d(const bool is_leaf = page_is_leaf(page)); + if (page_zip) { mtr_log_t log_mode; @@ -1115,7 +1120,7 @@ delete_all: page_cur_t cur; page_cur_position(rec, block, &cur); - offsets = rec_get_offsets(rec, index, offsets, + offsets = rec_get_offsets(rec, index, offsets, is_leaf, ULINT_UNDEFINED, &heap); rec = rec_get_next_ptr(rec, TRUE); #ifdef UNIV_ZIP_DEBUG @@ -1149,6 +1154,7 @@ delete_all: do { ulint s; offsets = rec_get_offsets(rec2, index, offsets, + is_leaf, ULINT_UNDEFINED, &heap); s = rec_offs_size(offsets); ut_ad(rec2 - page + s - rec_offs_extra_size(offsets) @@ -1291,10 +1297,12 @@ page_delete_rec_list_start( /* Individual deletes are not logged */ mtr_log_t log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE); + ut_d(const bool is_leaf = page_rec_is_leaf(rec)); while (page_cur_get_rec(&cur1) != rec) { offsets = rec_get_offsets(page_cur_get_rec(&cur1), index, - offsets, ULINT_UNDEFINED, &heap); + offsets, is_leaf, + ULINT_UNDEFINED, &heap); page_cur_delete_rec(&cur1, index, offsets, mtr); } @@ -2466,6 +2474,7 @@ page_validate( for (;;) { offsets = rec_get_offsets(rec, index, offsets, + page_is_leaf(page), ULINT_UNDEFINED, &heap); if (page_is_comp(page) && page_rec_is_user_rec(rec) @@ -2635,6 +2644,7 @@ n_owned_zero: while (rec != NULL) { offsets = rec_get_offsets(rec, index, offsets, + page_is_leaf(page), ULINT_UNDEFINED, &heap); if (UNIV_UNLIKELY(!page_rec_validate(rec, offsets))) { diff --git a/storage/innobase/page/page0zip.cc b/storage/innobase/page/page0zip.cc index b6e0409459b..f31ac653dc6 100644 --- a/storage/innobase/page/page0zip.cc +++ b/storage/innobase/page/page0zip.cc @@ -885,7 +885,7 @@ page_zip_compress_node_ptrs( do { const rec_t* rec = *recs++; - offsets = rec_get_offsets(rec, index, offsets, + offsets = rec_get_offsets(rec, index, offsets, false, ULINT_UNDEFINED, &heap); /* Only leaf nodes may contain externally stored columns. */ ut_ad(!rec_offs_any_extern(offsets)); @@ -1134,7 +1134,7 @@ page_zip_compress_clust( do { const rec_t* rec = *recs++; - offsets = rec_get_offsets(rec, index, offsets, + offsets = rec_get_offsets(rec, index, offsets, true, ULINT_UNDEFINED, &heap); ut_ad(rec_offs_n_fields(offsets) == dict_index_get_n_fields(index)); @@ -2078,6 +2078,7 @@ page_zip_apply_log( sorted by address (indexed by heap_no - PAGE_HEAP_NO_USER_LOW) */ ulint n_dense,/*!< in: size of recs[] */ + bool is_leaf,/*!< in: whether this is a leaf page */ ulint trx_id_col,/*!< in: column number of trx_id in the index, or ULINT_UNDEFINED if none */ ulint heap_status, @@ -2153,7 +2154,7 @@ page_zip_apply_log( /* Clear the data bytes of the record. */ mem_heap_t* heap = NULL; ulint* offs; - offs = rec_get_offsets(rec, index, offsets, + offs = rec_get_offsets(rec, index, offsets, is_leaf, ULINT_UNDEFINED, &heap); memset(rec, 0, rec_offs_data_size(offs)); @@ -2349,7 +2350,7 @@ page_zip_decompress_node_ptrs( } /* Read the offsets. The status bits are needed here. */ - offsets = rec_get_offsets(rec, index, offsets, + offsets = rec_get_offsets(rec, index, offsets, false, ULINT_UNDEFINED, &heap); /* Non-leaf nodes should not have any externally @@ -2435,7 +2436,7 @@ zlib_done: const byte* mod_log_ptr; mod_log_ptr = page_zip_apply_log(d_stream->next_in, d_stream->avail_in + 1, - recs, n_dense, + recs, n_dense, false, ULINT_UNDEFINED, heap_status, index, offsets); @@ -2466,7 +2467,7 @@ zlib_done: for (slot = 0; slot < n_dense; slot++) { rec_t* rec = recs[slot]; - offsets = rec_get_offsets(rec, index, offsets, + offsets = rec_get_offsets(rec, index, offsets, false, ULINT_UNDEFINED, &heap); /* Non-leaf nodes should not have any externally stored columns. */ @@ -2587,7 +2588,7 @@ zlib_done: const byte* mod_log_ptr; mod_log_ptr = page_zip_apply_log(d_stream->next_in, d_stream->avail_in + 1, - recs, n_dense, + recs, n_dense, true, ULINT_UNDEFINED, heap_status, index, offsets); @@ -2790,7 +2791,7 @@ page_zip_decompress_clust( } /* Read the offsets. The status bits are needed here. */ - offsets = rec_get_offsets(rec, index, offsets, + offsets = rec_get_offsets(rec, index, offsets, true, ULINT_UNDEFINED, &heap); /* This is a leaf page in a clustered index. */ @@ -2916,7 +2917,7 @@ zlib_done: const byte* mod_log_ptr; mod_log_ptr = page_zip_apply_log(d_stream->next_in, d_stream->avail_in + 1, - recs, n_dense, + recs, n_dense, true, trx_id_col, heap_status, index, offsets); @@ -2952,7 +2953,7 @@ zlib_done: rec_t* rec = recs[slot]; ibool exists = !page_zip_dir_find_free( page_zip, page_offset(rec)); - offsets = rec_get_offsets(rec, index, offsets, + offsets = rec_get_offsets(rec, index, offsets, true, ULINT_UNDEFINED, &heap); dst = rec_get_nth_field(rec, offsets, @@ -3463,6 +3464,7 @@ page_zip_validate_low( page + PAGE_NEW_INFIMUM, TRUE); trec = page_rec_get_next_low( temp_page + PAGE_NEW_INFIMUM, TRUE); + ut_d(const bool is_leaf = page_is_leaf(page)); do { if (page_offset(rec) != page_offset(trec)) { @@ -3477,7 +3479,7 @@ page_zip_validate_low( if (index) { /* Compare the data. */ offsets = rec_get_offsets( - rec, index, offsets, + rec, index, offsets, is_leaf, ULINT_UNDEFINED, &heap); if (memcmp(rec - rec_offs_extra_size(offsets), diff --git a/storage/innobase/rem/rem0cmp.cc b/storage/innobase/rem/rem0cmp.cc index 7c965f791be..0e2bc9b30de 100644 --- a/storage/innobase/rem/rem0cmp.cc +++ b/storage/innobase/rem/rem0cmp.cc @@ -797,7 +797,6 @@ cmp_dtuple_rec_with_match_bytes( ut_ad(dtuple_check_typed(dtuple)); ut_ad(rec_offs_validate(rec, index, offsets)); - //ut_ad(page_is_leaf(page_align(rec))); ut_ad(!(REC_INFO_MIN_REC_FLAG & dtuple_get_info_bits(dtuple))); ut_ad(!(REC_INFO_MIN_REC_FLAG diff --git a/storage/innobase/rem/rem0rec.cc b/storage/innobase/rem/rem0rec.cc index 66e8ccec178..0f9433aaf61 100644 --- a/storage/innobase/rem/rem0rec.cc +++ b/storage/innobase/rem/rem0rec.cc @@ -520,22 +520,25 @@ resolved: } } -/******************************************************//** -The following function determines the offsets to each field -in the record. It can reuse a previously returned array. +/** Determine the offsets to each field in an index record. +@param[in] rec physical record +@param[in] index the index that the record belongs to +@param[in,out] offsets array comprising offsets[0] allocated elements, + or an array from rec_get_offsets(), or NULL +@param[in] leaf whether this is a leaf-page record +@param[in] n_fields maximum number of offsets to compute + (ULINT_UNDEFINED to compute all offsets) +@param[in,out] heap memory heap @return the new offsets */ ulint* rec_get_offsets_func( -/*=================*/ - const rec_t* rec, /*!< in: physical record */ - const dict_index_t* index, /*!< in: record descriptor */ - ulint* offsets,/*!< in/out: array consisting of - offsets[0] allocated elements, - or an array from rec_get_offsets(), - or NULL */ - ulint n_fields,/*!< in: maximum number of - initialized fields - (ULINT_UNDEFINED if all fields) */ + const rec_t* rec, + const dict_index_t* index, + ulint* offsets, +#ifdef UNIV_DEBUG + bool leaf, +#endif /* UNIV_DEBUG */ + ulint n_fields, #ifdef UNIV_DEBUG const char* file, /*!< in: file name where called */ unsigned line, /*!< in: line number where called */ @@ -553,17 +556,23 @@ rec_get_offsets_func( switch (UNIV_EXPECT(rec_get_status(rec), REC_STATUS_ORDINARY)) { case REC_STATUS_ORDINARY: + ut_ad(leaf); n = dict_index_get_n_fields(index); break; case REC_STATUS_NODE_PTR: /* Node pointer records consist of the uniquely identifying fields of the record followed by a child page number field. */ + ut_ad(!leaf); n = dict_index_get_n_unique_in_tree_nonleaf(index) + 1; break; case REC_STATUS_INFIMUM: case REC_STATUS_SUPREMUM: /* infimum or supremum record */ + ut_ad(rec_get_heap_no_new(rec) + == (rec_get_status(rec) == REC_STATUS_INFIMUM + ? PAGE_HEAP_NO_INFIMUM + : PAGE_HEAP_NO_SUPREMUM)); n = 1; break; default: @@ -572,6 +581,28 @@ rec_get_offsets_func( } } else { n = rec_get_n_fields_old(rec); + /* Here, rec can be allocated from the heap (copied + from an index page record), or it can be located in an + index page. If rec is not in an index page, then + page_rec_is_user_rec(rec) and similar predicates + cannot be evaluated. We can still distinguish the + infimum and supremum record based on the heap number. */ + ut_d(const bool is_user_rec = rec_get_heap_no_old(rec) + >= PAGE_HEAP_NO_USER_LOW); + ut_ad(n <= index->n_fields + !leaf || index->is_dummy + || dict_index_is_ibuf(index)); + /* The infimum and supremum records carry 1 field. */ + ut_ad(is_user_rec || n == 1); + ut_ad(!is_user_rec || leaf || index->is_dummy + || dict_index_is_ibuf(index) + || n + == dict_index_get_n_unique_in_tree_nonleaf(index) + 1); + ut_ad(!is_user_rec || !leaf || index->is_dummy + || dict_index_is_ibuf(index) + || n == n_fields /* btr_pcur_restore_position() */ + || n == index->n_fields + || (index->id == DICT_INDEXES_ID + && (n == DICT_NUM_FIELDS__SYS_INDEXES - 1))); } if (UNIV_UNLIKELY(n_fields < n)) { @@ -1468,30 +1499,6 @@ rec_convert_dtuple_to_rec( rec = rec_convert_dtuple_to_rec_old(buf, dtuple, n_ext); } -#ifdef UNIV_DEBUG - { - mem_heap_t* heap = NULL; - ulint offsets_[REC_OFFS_NORMAL_SIZE]; - const ulint* offsets; - ulint i; - rec_offs_init(offsets_); - - offsets = rec_get_offsets(rec, index, - offsets_, ULINT_UNDEFINED, &heap); - ut_ad(rec_validate(rec, offsets)); - ut_ad(dtuple_get_n_fields(dtuple) - == rec_offs_n_fields(offsets)); - - for (i = 0; i < rec_offs_n_fields(offsets); i++) { - ut_ad(!dfield_is_ext(dtuple_get_nth_field(dtuple, i)) - == !rec_offs_nth_extern(offsets, i)); - } - - if (UNIV_LIKELY_NULL(heap)) { - mem_heap_free(heap); - } - } -#endif /* UNIV_DEBUG */ return(rec); } @@ -1541,25 +1548,30 @@ rec_convert_dtuple_to_temp( REC_STATUS_ORDINARY, true); } -/**************************************************************//** -Copies the first n fields of a physical record to a data tuple. The fields -are copied to the memory heap. */ +/** Copy the first n fields of a (copy of a) physical record to a data tuple. +The fields are copied into the memory heap. +@param[out] tuple data tuple +@param[in] rec index record, or a copy thereof +@param[in] is_leaf whether rec is a leaf page record +@param[in] n_fields number of fields to copy +@param[in,out] heap memory heap */ void rec_copy_prefix_to_dtuple( -/*======================*/ - dtuple_t* tuple, /*!< out: data tuple */ - const rec_t* rec, /*!< in: physical record */ - const dict_index_t* index, /*!< in: record descriptor */ - ulint n_fields, /*!< in: number of fields - to copy */ - mem_heap_t* heap) /*!< in: memory heap */ + dtuple_t* tuple, + const rec_t* rec, + const dict_index_t* index, + bool is_leaf, + ulint n_fields, + mem_heap_t* heap) { - ulint i; ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint* offsets = offsets_; rec_offs_init(offsets_); - offsets = rec_get_offsets(rec, index, offsets, n_fields, &heap); + ut_ad(is_leaf || n_fields <= index->n_uniq + 1); + + offsets = rec_get_offsets(rec, index, offsets, is_leaf, + n_fields, &heap); ut_ad(rec_validate(rec, offsets)); ut_ad(dtuple_check_typed(tuple)); @@ -1567,7 +1579,7 @@ rec_copy_prefix_to_dtuple( dtuple_set_info_bits(tuple, rec_get_info_bits( rec, dict_table_is_comp(index->table))); - for (i = 0; i < n_fields; i++) { + for (ulint i = 0; i < n_fields; i++) { dfield_t* field; const byte* data; ulint len; @@ -2155,6 +2167,7 @@ rec_print( rec_print_new(file, rec, rec_get_offsets(rec, index, offsets_, + page_rec_is_leaf(rec), ULINT_UNDEFINED, &heap)); if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); @@ -2225,7 +2238,8 @@ operator<<(std::ostream& o, const rec_index_print& r) { mem_heap_t* heap = NULL; ulint* offsets = rec_get_offsets( - r.m_rec, r.m_index, NULL, ULINT_UNDEFINED, &heap); + r.m_rec, r.m_index, NULL, page_rec_is_leaf(r.m_rec), + ULINT_UNDEFINED, &heap); rec_print(o, r.m_rec, rec_get_info_bits(r.m_rec, rec_offs_comp(offsets)), offsets); @@ -2272,10 +2286,12 @@ rec_get_trx_id( ut_ad(mach_read_from_8(page + PAGE_HEADER + PAGE_INDEX_ID) == index->id); ut_ad(dict_index_is_clust(index)); + ut_ad(page_rec_is_leaf(rec)); ut_ad(trx_id_col > 0); ut_ad(trx_id_col != ULINT_UNDEFINED); - offsets = rec_get_offsets(rec, index, offsets, trx_id_col + 1, &heap); + offsets = rec_get_offsets(rec, index, offsets, true, + trx_id_col + 1, &heap); trx_id = rec_get_nth_field(rec, offsets, trx_id_col, &len); @@ -2323,7 +2339,7 @@ wsrep_rec_get_foreign_key( ut_ad(index_ref); rec_offs_init(offsets_); - offsets = rec_get_offsets(rec, index_for, offsets_, + offsets = rec_get_offsets(rec, index_for, offsets_, true, ULINT_UNDEFINED, &heap); ut_ad(rec_offs_validate(rec, NULL, offsets)); diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index 45ca1582e49..59500b4919a 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -1735,7 +1735,7 @@ PageConverter::update_records( if (deleted || clust_index) { m_offsets = rec_get_offsets( - rec, m_index->m_srv_index, m_offsets, + rec, m_index->m_srv_index, m_offsets, true, ULINT_UNDEFINED, &m_heap); } @@ -2323,7 +2323,7 @@ row_import_set_sys_max_row_id( rec_offs_init(offsets_); offsets = rec_get_offsets( - rec, index, offsets_, ULINT_UNDEFINED, &heap); + rec, index, offsets_, true, ULINT_UNDEFINED, &heap); field = rec_get_nth_field( rec, offsets, diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index b7f28e633a3..a8258fa2c0f 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -952,7 +952,7 @@ row_ins_foreign_fill_virtual( ulint offsets_[REC_OFFS_NORMAL_SIZE]; rec_offs_init(offsets_); const ulint* offsets = - rec_get_offsets(rec, index, offsets_, + rec_get_offsets(rec, index, offsets_, true, ULINT_UNDEFINED, &cascade->heap); mem_heap_t* v_heap = NULL; upd_t* update = cascade->update; @@ -1732,8 +1732,8 @@ row_ins_check_foreign_constraint( continue; } - offsets = rec_get_offsets(rec, check_index, - offsets, ULINT_UNDEFINED, &heap); + offsets = rec_get_offsets(rec, check_index, offsets, true, + ULINT_UNDEFINED, &heap); if (page_rec_is_supremum(rec)) { @@ -2122,7 +2122,7 @@ row_ins_scan_sec_index_for_duplicate( continue; } - offsets = rec_get_offsets(rec, index, offsets, + offsets = rec_get_offsets(rec, index, offsets, true, ULINT_UNDEFINED, &offsets_heap); if (flags & BTR_NO_LOCKING_FLAG) { @@ -2251,7 +2251,7 @@ row_ins_duplicate_error_in_clust_online( const rec_t* rec = btr_cur_get_rec(cursor); if (cursor->low_match >= n_uniq && !page_rec_is_infimum(rec)) { - *offsets = rec_get_offsets(rec, cursor->index, *offsets, + *offsets = rec_get_offsets(rec, cursor->index, *offsets, true, ULINT_UNDEFINED, heap); err = row_ins_duplicate_online(n_uniq, entry, rec, *offsets); if (err != DB_SUCCESS) { @@ -2262,7 +2262,7 @@ row_ins_duplicate_error_in_clust_online( rec = page_rec_get_next_const(btr_cur_get_rec(cursor)); if (cursor->up_match >= n_uniq && !page_rec_is_supremum(rec)) { - *offsets = rec_get_offsets(rec, cursor->index, *offsets, + *offsets = rec_get_offsets(rec, cursor->index, *offsets, true, ULINT_UNDEFINED, heap); err = row_ins_duplicate_online(n_uniq, entry, rec, *offsets); } @@ -2318,6 +2318,7 @@ row_ins_duplicate_error_in_clust( if (!page_rec_is_infimum(rec)) { offsets = rec_get_offsets(rec, cursor->index, offsets, + true, ULINT_UNDEFINED, &heap); ulint lock_type; @@ -2377,6 +2378,7 @@ duplicate: if (!page_rec_is_supremum(rec)) { offsets = rec_get_offsets(rec, cursor->index, offsets, + true, ULINT_UNDEFINED, &heap); if (trx->duplicates) { @@ -2492,7 +2494,7 @@ row_ins_index_entry_big_rec( btr_pcur_open(index, entry, PAGE_CUR_LE, BTR_MODIFY_TREE, &pcur, &mtr); rec = btr_pcur_get_rec(&pcur); - offsets = rec_get_offsets(rec, index, offsets, + offsets = rec_get_offsets(rec, index, offsets, true, ULINT_UNDEFINED, heap); DEBUG_SYNC_C_IF_THD(thd, "before_row_ins_extern"); @@ -3052,7 +3054,7 @@ row_ins_sec_index_entry_low( ut_ad(!page_rec_is_infimum(rec)); - offsets = rec_get_offsets(rec, index, offsets, + offsets = rec_get_offsets(rec, index, offsets, true, ULINT_UNDEFINED, &offsets_heap); err = row_ins_set_exclusive_rec_lock( @@ -3083,7 +3085,7 @@ row_ins_sec_index_entry_low( prefix, we must convert the insert into a modify of an existing record */ offsets = rec_get_offsets( - btr_cur_get_rec(&cursor), index, offsets, + btr_cur_get_rec(&cursor), index, offsets, true, ULINT_UNDEFINED, &offsets_heap); err = row_ins_sec_index_entry_by_modify( diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc index 1b3521a557c..1385238f560 100644 --- a/storage/innobase/row/row0log.cc +++ b/storage/innobase/row/row0log.cc @@ -972,7 +972,7 @@ row_log_table_low( &index->lock, RW_LOCK_FLAG_S | RW_LOCK_FLAG_X | RW_LOCK_FLAG_SX)); ut_ad(fil_page_get_type(page_align(rec)) == FIL_PAGE_INDEX); - ut_ad(page_is_leaf(page_align(rec))); + ut_ad(page_rec_is_leaf(rec)); ut_ad(!page_is_comp(page_align(rec)) == !rec_offs_comp(offsets)); /* old_pk=row_log_table_get_pk() [not needed in INSERT] is a prefix of the clustered index record (PRIMARY KEY,DB_TRX_ID,DB_ROLL_PTR), @@ -1236,8 +1236,8 @@ row_log_table_get_pk( if (!offsets) { offsets = rec_get_offsets( - rec, index, NULL, pos + 1, - heap); + rec, index, NULL, true, + pos + 1, heap); } trx_id_offs = rec_get_nth_field_offs( @@ -1281,7 +1281,7 @@ row_log_table_get_pk( } if (!offsets) { - offsets = rec_get_offsets(rec, index, NULL, + offsets = rec_get_offsets(rec, index, NULL, true, ULINT_UNDEFINED, heap); } @@ -1962,7 +1962,7 @@ all_done: return(DB_SUCCESS); } - offsets = rec_get_offsets(btr_pcur_get_rec(&pcur), index, NULL, + offsets = rec_get_offsets(btr_pcur_get_rec(&pcur), index, NULL, true, ULINT_UNDEFINED, &offsets_heap); #if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG ut_a(!rec_offs_any_null_extern(btr_pcur_get_rec(&pcur), offsets)); @@ -2167,8 +2167,8 @@ func_exit_committed: /* Prepare to update (or delete) the record. */ ulint* cur_offsets = rec_get_offsets( - btr_pcur_get_rec(&pcur), - index, NULL, ULINT_UNDEFINED, &offsets_heap); + btr_pcur_get_rec(&pcur), index, NULL, true, + ULINT_UNDEFINED, &offsets_heap); if (!log->same_pk) { /* Only update the record if DB_TRX_ID,DB_ROLL_PTR match what diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index 8c02edcb3cc..cffc40af835 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -2043,7 +2043,7 @@ end_of_index: rec = page_cur_get_rec(cur); if (online) { - offsets = rec_get_offsets(rec, clust_index, NULL, + offsets = rec_get_offsets(rec, clust_index, NULL, true, ULINT_UNDEFINED, &row_heap); /* Perform a REPEATABLE READ. @@ -2115,7 +2115,7 @@ end_of_index: keys. */ continue; } else { - offsets = rec_get_offsets(rec, clust_index, NULL, + offsets = rec_get_offsets(rec, clust_index, NULL, true, ULINT_UNDEFINED, &row_heap); } diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 313a0d55a67..583acdc482b 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -2031,7 +2031,6 @@ run_again: node->cascade_upd_nodes = cascade_upd_nodes; cascade_upd_nodes->pop_front(); thr->fk_cascade_depth++; - prebuilt->m_mysql_table = NULL; goto run_again; } @@ -2245,7 +2244,7 @@ row_unlock_for_mysql( ulint* offsets = offsets_; rec_offs_init(offsets_); - offsets = rec_get_offsets(rec, index, offsets, + offsets = rec_get_offsets(rec, index, offsets, true, ULINT_UNDEFINED, &heap); rec_trx_id = row_get_rec_trx_id(rec, index, offsets); @@ -5069,7 +5068,7 @@ func_exit: rec = buf + mach_read_from_4(buf); - offsets = rec_get_offsets(rec, index, offsets_, + offsets = rec_get_offsets(rec, index, offsets_, true, ULINT_UNDEFINED, &heap); if (prev_entry != NULL) { diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc index cecd127e71e..ed07bcb03af 100644 --- a/storage/innobase/row/row0purge.cc +++ b/storage/innobase/row/row0purge.cc @@ -152,7 +152,7 @@ row_purge_remove_clust_if_poss_low( rec = btr_pcur_get_rec(&node->pcur); offsets = rec_get_offsets( - rec, index, offsets_, ULINT_UNDEFINED, &heap); + rec, index, offsets_, true, ULINT_UNDEFINED, &heap); if (node->roll_ptr != row_get_rec_roll_ptr(rec, index, offsets)) { /* Someone else has modified the record later: do not remove */ @@ -1140,7 +1140,8 @@ purge_node_t::validate_pcur() dict_index_t* clust_index = pcur.btr_cur.index; ulint* offsets = rec_get_offsets( - pcur.old_rec, clust_index, NULL, pcur.old_n_fields, &heap); + pcur.old_rec, clust_index, NULL, true, + pcur.old_n_fields, &heap); /* Here we are comparing the purge ref record and the stored initial part in persistent cursor. Both cases we store n_uniq fields of the diff --git a/storage/innobase/row/row0row.cc b/storage/innobase/row/row0row.cc index 9b5ef6a3f3c..748ac194110 100644 --- a/storage/innobase/row/row0row.cc +++ b/storage/innobase/row/row0row.cc @@ -400,7 +400,7 @@ row_build_low( ut_ad(!col_map || col_table); if (!offsets) { - offsets = rec_get_offsets(rec, index, offsets_, + offsets = rec_get_offsets(rec, index, offsets_, true, ULINT_UNDEFINED, &tmp_heap); } else { ut_ad(rec_offs_validate(rec, index, offsets)); @@ -792,7 +792,7 @@ row_build_row_ref( ut_ad(heap != NULL); ut_ad(!dict_index_is_clust(index)); - offsets = rec_get_offsets(rec, index, offsets, + offsets = rec_get_offsets(rec, index, offsets, true, ULINT_UNDEFINED, &tmp_heap); /* Secondary indexes must not contain externally stored columns. */ ut_ad(!rec_offs_any_extern(offsets)); @@ -904,7 +904,7 @@ row_build_row_ref_in_tuple( ut_ad(clust_index); if (!offsets) { - offsets = rec_get_offsets(rec, index, offsets_, + offsets = rec_get_offsets(rec, index, offsets_, true, ULINT_UNDEFINED, &heap); } else { ut_ad(rec_offs_validate(rec, index, offsets)); diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index d180ba6558f..2ab0adc2f1a 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -197,9 +197,9 @@ row_sel_sec_rec_is_for_clust_rec( heap = mem_heap_create(256); clust_offs = rec_get_offsets(clust_rec, clust_index, clust_offs, - ULINT_UNDEFINED, &heap); + true, ULINT_UNDEFINED, &heap); sec_offs = rec_get_offsets(sec_rec, sec_index, sec_offs, - ULINT_UNDEFINED, &heap); + true, ULINT_UNDEFINED, &heap); n = dict_index_get_n_ordering_defined_by_user(sec_index); @@ -904,7 +904,7 @@ row_sel_get_clust_rec( offsets = rec_get_offsets(rec, btr_pcur_get_btr_cur(&plan->pcur)->index, - offsets, ULINT_UNDEFINED, &heap); + offsets, true, ULINT_UNDEFINED, &heap); row_build_row_ref_fast(plan->clust_ref, plan->clust_map, rec, offsets); @@ -939,7 +939,7 @@ row_sel_get_clust_rec( goto func_exit; } - offsets = rec_get_offsets(clust_rec, index, offsets, + offsets = rec_get_offsets(clust_rec, index, offsets, true, ULINT_UNDEFINED, &heap); if (!node->read_view) { @@ -1158,7 +1158,7 @@ re_scan: rec = btr_pcur_get_rec(pcur); my_offsets = offsets_; - my_offsets = rec_get_offsets(rec, index, my_offsets, + my_offsets = rec_get_offsets(rec, index, my_offsets, true, ULINT_UNDEFINED, &heap); /* No match record */ @@ -1181,8 +1181,8 @@ re_scan: rtr_rec_t* rtr_rec = &(*it); my_offsets = rec_get_offsets( - rtr_rec->r_rec, index, my_offsets, - ULINT_UNDEFINED, &heap); + rtr_rec->r_rec, index, my_offsets, true, + ULINT_UNDEFINED, &heap); err = lock_sec_rec_read_check_and_lock( 0, &match->block, rtr_rec->r_rec, index, @@ -1196,12 +1196,10 @@ re_scan: } else { goto func_end; } - } match->locked = true; - func_end: rw_lock_x_unlock(&(match->block.lock)); if (heap != NULL) { @@ -1510,7 +1508,8 @@ row_sel_try_search_shortcut( /* This is a non-locking consistent read: if necessary, fetch a previous version of the record */ - offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); + offsets = rec_get_offsets(rec, index, offsets, true, + ULINT_UNDEFINED, &heap); if (dict_index_is_clust(index)) { if (!lock_clust_rec_cons_read_sees(rec, index, offsets, @@ -1768,6 +1767,7 @@ rec_loop: trx = thr_get_trx(thr); offsets = rec_get_offsets(next_rec, index, offsets, + true, ULINT_UNDEFINED, &heap); /* If innodb_locks_unsafe_for_binlog option is used @@ -1826,7 +1826,7 @@ skip_lock: ulint lock_type; trx_t* trx; - offsets = rec_get_offsets(rec, index, offsets, + offsets = rec_get_offsets(rec, index, offsets, true, ULINT_UNDEFINED, &heap); trx = thr_get_trx(thr); @@ -1913,7 +1913,8 @@ skip_lock: /* PHASE 3: Get previous version in a consistent read */ cons_read_requires_clust_rec = FALSE; - offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); + offsets = rec_get_offsets(rec, index, offsets, true, + ULINT_UNDEFINED, &heap); if (consistent_read) { /* This is a non-locking consistent read: if necessary, fetch @@ -1943,7 +1944,7 @@ skip_lock: exhausted. */ offsets = rec_get_offsets( - rec, index, offsets, + rec, index, offsets, true, ULINT_UNDEFINED, &heap); /* Fetch the columns needed in @@ -3457,7 +3458,7 @@ row_sel_get_clust_rec_for_mysql( goto func_exit; } - *offsets = rec_get_offsets(clust_rec, clust_index, *offsets, + *offsets = rec_get_offsets(clust_rec, clust_index, *offsets, true, ULINT_UNDEFINED, offset_heap); if (prebuilt->select_lock_type != LOCK_NONE) { @@ -3901,7 +3902,7 @@ row_sel_try_search_shortcut_for_mysql( /* This is a non-locking consistent read: if necessary, fetch a previous version of the record */ - *offsets = rec_get_offsets(rec, index, *offsets, + *offsets = rec_get_offsets(rec, index, *offsets, true, ULINT_UNDEFINED, heap); if (!lock_clust_rec_cons_read_sees( @@ -4031,8 +4032,9 @@ row_sel_fill_vrow( rec_offs_init(offsets_); ut_ad(!(*vrow)); + ut_ad(page_rec_is_leaf(rec)); - offsets = rec_get_offsets(rec, index, offsets, + offsets = rec_get_offsets(rec, index, offsets, true, ULINT_UNDEFINED, &heap); *vrow = dtuple_create_with_vcol( @@ -4585,6 +4587,7 @@ wait_table_again: pcur->trx_if_known = trx; rec = btr_pcur_get_rec(pcur); + ut_ad(page_rec_is_leaf(rec)); if (!moves_up && !page_rec_is_supremum(rec) @@ -4599,6 +4602,7 @@ wait_table_again: const rec_t* next_rec = page_rec_get_next_const(rec); offsets = rec_get_offsets(next_rec, index, offsets, + true, ULINT_UNDEFINED, &heap); err = sel_set_rec_lock(pcur, next_rec, index, offsets, @@ -4656,6 +4660,7 @@ rec_loop: } ut_ad(!!page_rec_is_comp(rec) == comp); + ut_ad(page_rec_is_leaf(rec)); if (page_rec_is_infimum(rec)) { @@ -4681,7 +4686,7 @@ rec_loop: level we do not lock gaps. Supremum record is really a gap and therefore we do not set locks there. */ - offsets = rec_get_offsets(rec, index, offsets, + offsets = rec_get_offsets(rec, index, offsets, true, ULINT_UNDEFINED, &heap); err = sel_set_rec_lock(pcur, rec, index, offsets, @@ -4771,7 +4776,8 @@ wrong_offs: ut_ad(fil_page_index_page_check(btr_pcur_get_page(pcur))); ut_ad(btr_page_get_index_id(btr_pcur_get_page(pcur)) == index->id); - offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); + offsets = rec_get_offsets(rec, index, offsets, true, + ULINT_UNDEFINED, &heap); if (UNIV_UNLIKELY(srv_force_recovery > 0)) { if (!rec_validate(rec, offsets) @@ -4992,8 +4998,8 @@ no_gap_lock: Do a normal locking read. */ offsets = rec_get_offsets( - rec, index, offsets, ULINT_UNDEFINED, - &heap); + rec, index, offsets, true, + ULINT_UNDEFINED, &heap); goto locks_ok; case DB_DEADLOCK: goto lock_wait_or_error; @@ -5432,6 +5438,7 @@ requires_clust_rec: /* We used 'offsets' for the clust rec, recalculate them for 'rec' */ offsets = rec_get_offsets(rec, index, offsets, + true, ULINT_UNDEFINED, &heap); result_rec = rec; @@ -5929,8 +5936,10 @@ row_search_autoinc_read_column( ulint* offsets = offsets_; rec_offs_init(offsets_); + ut_ad(page_rec_is_leaf(rec)); - offsets = rec_get_offsets(rec, index, offsets, col_no + 1, &heap); + offsets = rec_get_offsets(rec, index, offsets, true, + col_no + 1, &heap); if (rec_offs_nth_sql_null(offsets, col_no)) { /* There is no non-NULL value in the auto-increment column. */ diff --git a/storage/innobase/row/row0uins.cc b/storage/innobase/row/row0uins.cc index 0fce0731307..60a9f49b576 100644 --- a/storage/innobase/row/row0uins.cc +++ b/storage/innobase/row/row0uins.cc @@ -112,7 +112,7 @@ row_undo_ins_remove_clust_rec( const rec_t* rec = btr_cur_get_rec(btr_cur); mem_heap_t* heap = NULL; const ulint* offsets = rec_get_offsets( - rec, index, NULL, ULINT_UNDEFINED, &heap); + rec, index, NULL, true, ULINT_UNDEFINED, &heap); row_log_table_delete(rec, node->row, index, offsets, NULL); mem_heap_free(heap); } diff --git a/storage/innobase/row/row0umod.cc b/storage/innobase/row/row0umod.cc index 0a2a68d1fef..b45444ef064 100644 --- a/storage/innobase/row/row0umod.cc +++ b/storage/innobase/row/row0umod.cc @@ -196,7 +196,7 @@ row_undo_mod_remove_clust_low( offsets = rec_get_offsets( btr_cur_get_rec(btr_cur), btr_cur_get_index(btr_cur), - NULL, trx_id_col + 1, &heap); + NULL, true, trx_id_col + 1, &heap); trx_id_offset = rec_get_nth_field_offs( offsets, trx_id_col, &len); @@ -751,7 +751,7 @@ try_again: offsets_heap = NULL; offsets = rec_get_offsets( btr_cur_get_rec(btr_cur), - index, NULL, ULINT_UNDEFINED, &offsets_heap); + index, NULL, true, ULINT_UNDEFINED, &offsets_heap); update = row_upd_build_sec_rec_difference_binary( btr_cur_get_rec(btr_cur), index, offsets, entry, heap); if (upd_get_n_fields(update) == 0) { diff --git a/storage/innobase/row/row0undo.cc b/storage/innobase/row/row0undo.cc index b9e79e044de..f05324c6f2e 100644 --- a/storage/innobase/row/row0undo.cc +++ b/storage/innobase/row/row0undo.cc @@ -185,7 +185,7 @@ row_undo_search_clust_to_pcur( rec = btr_pcur_get_rec(&node->pcur); - offsets = rec_get_offsets(rec, clust_index, offsets, + offsets = rec_get_offsets(rec, clust_index, offsets, true, ULINT_UNDEFINED, &heap); found = row_get_rec_roll_ptr(rec, clust_index, offsets) diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index 6a76de39dca..a0314c9f67c 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -1069,7 +1069,7 @@ row_upd_build_difference_binary( == trx_id_pos + 1); if (!offsets) { - offsets = rec_get_offsets(rec, index, offsets_, + offsets = rec_get_offsets(rec, index, offsets_, true, ULINT_UNDEFINED, &heap); } else { ut_ad(rec_offs_validate(rec, index, offsets)); @@ -2196,7 +2196,7 @@ row_upd_store_row( rec = btr_pcur_get_rec(node->pcur); - offsets = rec_get_offsets(rec, clust_index, offsets_, + offsets = rec_get_offsets(rec, clust_index, offsets_, true, ULINT_UNDEFINED, &heap); if (dict_table_get_format(node->table) >= UNIV_FORMAT_B) { @@ -2444,8 +2444,8 @@ row_upd_sec_index_entry( && !wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { ulint* offsets = rec_get_offsets( - rec, index, NULL, ULINT_UNDEFINED, - &heap); + rec, index, NULL, true, + ULINT_UNDEFINED, &heap); err = wsrep_row_upd_check_foreign_constraints( node, &pcur, index->table, @@ -2481,7 +2481,7 @@ row_upd_sec_index_entry( ulint* offsets; offsets = rec_get_offsets( - rec, index, NULL, ULINT_UNDEFINED, + rec, index, NULL, true, ULINT_UNDEFINED, &heap); /* NOTE that the following call loses @@ -2691,7 +2691,7 @@ row_upd_clust_rec_by_insert( we update the primary key. Delete-mark the old record in the clustered index and prepare to insert a new entry. */ rec = btr_cur_get_rec(btr_cur); - offsets = rec_get_offsets(rec, index, NULL, + offsets = rec_get_offsets(rec, index, NULL, true, ULINT_UNDEFINED, &heap); ut_ad(page_rec_is_user_rec(rec)); @@ -2966,7 +2966,8 @@ row_upd_del_mark_clust_rec( entries */ row_upd_store_row(node, trx->mysql_thd, - thr->prebuilt ? thr->prebuilt->m_mysql_table : NULL); + thr->prebuilt && thr->prebuilt->table == node->table + ? thr->prebuilt->m_mysql_table : NULL); /* Mark the clustered index record deleted; we do not have to check locks, because we assume that we have an x-lock on the record */ @@ -3132,7 +3133,7 @@ row_upd_clust_step( } rec = btr_pcur_get_rec(pcur); - offsets = rec_get_offsets(rec, index, offsets_, + offsets = rec_get_offsets(rec, index, offsets_, true, ULINT_UNDEFINED, &heap); if (!flags && !node->has_clust_rec_x_lock) { diff --git a/storage/innobase/row/row0vers.cc b/storage/innobase/row/row0vers.cc index de33c7c4d1b..c5d08e1ece6 100644 --- a/storage/innobase/row/row0vers.cc +++ b/storage/innobase/row/row0vers.cc @@ -100,7 +100,7 @@ row_vers_impl_x_locked_low( heap = mem_heap_create(1024); clust_offsets = rec_get_offsets( - clust_rec, clust_index, NULL, ULINT_UNDEFINED, &heap); + clust_rec, clust_index, NULL, true, ULINT_UNDEFINED, &heap); trx_id = row_get_rec_trx_id(clust_rec, clust_index, clust_offsets); corrupt = FALSE; @@ -206,8 +206,8 @@ row_vers_impl_x_locked_low( } clust_offsets = rec_get_offsets( - prev_version, clust_index, NULL, ULINT_UNDEFINED, - &heap); + prev_version, clust_index, NULL, true, + ULINT_UNDEFINED, &heap); vers_del = rec_get_deleted_flag(prev_version, comp); @@ -568,7 +568,8 @@ row_vers_build_cur_vrow_low( } clust_offsets = rec_get_offsets(prev_version, clust_index, - NULL, ULINT_UNDEFINED, &heap); + NULL, + true, ULINT_UNDEFINED, &heap); ulint entry_len = dict_index_get_n_fields(index); @@ -706,7 +707,8 @@ row_vers_vc_matches_cluster( } clust_offsets = rec_get_offsets(prev_version, clust_index, - NULL, ULINT_UNDEFINED, &heap); + NULL, + true, ULINT_UNDEFINED, &heap); ulint entry_len = dict_index_get_n_fields(index); @@ -832,7 +834,7 @@ row_vers_build_cur_vrow( index, roll_ptr, trx_id, v_heap, &cur_vrow, mtr); } - *clust_offsets = rec_get_offsets(rec, clust_index, NULL, + *clust_offsets = rec_get_offsets(rec, clust_index, NULL, true, ULINT_UNDEFINED, &heap); return(cur_vrow); } @@ -881,7 +883,7 @@ row_vers_old_has_index_entry( comp = page_rec_is_comp(rec); ut_ad(!dict_table_is_comp(index->table) == !comp); heap = mem_heap_create(1024); - clust_offsets = rec_get_offsets(rec, clust_index, NULL, + clust_offsets = rec_get_offsets(rec, clust_index, NULL, true, ULINT_UNDEFINED, &heap); if (dict_index_has_virtual(index)) { @@ -955,6 +957,7 @@ row_vers_old_has_index_entry( } } clust_offsets = rec_get_offsets(rec, clust_index, NULL, + true, ULINT_UNDEFINED, &heap); } else { @@ -1029,7 +1032,8 @@ row_vers_old_has_index_entry( } clust_offsets = rec_get_offsets(prev_version, clust_index, - NULL, ULINT_UNDEFINED, &heap); + NULL, true, + ULINT_UNDEFINED, &heap); if (dict_index_has_virtual(index)) { if (vrow) { @@ -1174,8 +1178,8 @@ row_vers_build_for_consistent_read( } *offsets = rec_get_offsets( - prev_version, index, *offsets, ULINT_UNDEFINED, - offset_heap); + prev_version, index, *offsets, + true, ULINT_UNDEFINED, offset_heap); #if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG ut_a(!rec_offs_any_null_extern(prev_version, *offsets)); @@ -1306,6 +1310,7 @@ committed_version_trx: version = rec; *offsets = rec_get_offsets(version, index, *offsets, + true, ULINT_UNDEFINED, offset_heap); } @@ -1350,7 +1355,7 @@ committed_version_trx: } version = prev_version; - *offsets = rec_get_offsets(version, index, *offsets, + *offsets = rec_get_offsets(version, index, *offsets, true, ULINT_UNDEFINED, offset_heap); #if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG ut_a(!rec_offs_any_null_extern(version, *offsets)); diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 66866c98e62..bd3c5a3d8bc 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -2139,7 +2139,7 @@ files_checked: compile_time_assert(IBUF_SPACE_ID == 0); ulint ibuf_root = btr_create( - DICT_CLUSTERED | DICT_UNIVERSAL | DICT_IBUF, + DICT_CLUSTERED | DICT_IBUF, 0, univ_page_size, DICT_IBUF_ID_MIN, dict_ind_redundant, NULL, &mtr); diff --git a/storage/innobase/trx/trx0i_s.cc b/storage/innobase/trx/trx0i_s.cc index 7854ad2ab5a..327ebf79211 100644 --- a/storage/innobase/trx/trx0i_s.cc +++ b/storage/innobase/trx/trx0i_s.cc @@ -726,8 +726,7 @@ fill_lock_data( ut_a(n_fields > 0); heap = NULL; - offsets = rec_get_offsets(rec, index, offsets, n_fields, - &heap); + offsets = rec_get_offsets(rec, index, offsets, true, n_fields, &heap); /* format and store the data */ diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc index 02aee500e02..ca715371c44 100644 --- a/storage/innobase/trx/trx0rec.cc +++ b/storage/innobase/trx/trx0rec.cc @@ -2324,8 +2324,8 @@ trx_undo_prev_version_build( #if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG ut_a(!rec_offs_any_null_extern( - *old_vers, rec_get_offsets( - *old_vers, index, NULL, ULINT_UNDEFINED, &heap))); + *old_vers, rec_get_offsets(*old_vers, index, NULL, true, + ULINT_UNDEFINED, &heap))); #endif // defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG if (vrow && !(cmpl_info & UPD_NODE_NO_ORD_CHANGE)) { diff --git a/storage/innobase/trx/trx0sys.cc b/storage/innobase/trx/trx0sys.cc index dc59260c31d..1a7b9ef2905 100644 --- a/storage/innobase/trx/trx0sys.cc +++ b/storage/innobase/trx/trx0sys.cc @@ -982,6 +982,7 @@ trx_sys_close(void) /********************************************************************* Check if there are any active (non-prepared) transactions. +This is only used to check if it's safe to shutdown. @return total number of active transactions or 0 if none */ ulint trx_sys_any_active_transactions(void) @@ -991,8 +992,13 @@ trx_sys_any_active_transactions(void) trx_sys_mutex_enter(); - total_trx = UT_LIST_GET_LEN(trx_sys->rw_trx_list) - + UT_LIST_GET_LEN(trx_sys->mysql_trx_list); + total_trx = UT_LIST_GET_LEN(trx_sys->rw_trx_list); + + for (trx_t* trx = UT_LIST_GET_FIRST(trx_sys->mysql_trx_list); + trx != NULL; + trx = UT_LIST_GET_NEXT(mysql_trx_list, trx)) { + total_trx += trx->state != TRX_STATE_NOT_STARTED; + } ut_a(total_trx >= trx_sys->n_prepared_trx); total_trx -= trx_sys->n_prepared_trx; diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index 2941eb9e43f..55b16a286fc 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -2360,6 +2360,17 @@ ha_myisam::check_if_supported_inplace_alter(TABLE *new_table, } +static bool directories_differ(const char *d1, const char *d2) +{ + if (!d1 && !d2) + return false; + if (!d1 || !d2) + return true; + size_t l1= dirname_length(d1), l2= dirname_length(d2); + return l1 != l2 || strncmp(d1, d2, l1); +} + + bool ha_myisam::check_if_incompatible_data(HA_CREATE_INFO *create_info, uint table_changes) { @@ -2367,8 +2378,8 @@ bool ha_myisam::check_if_incompatible_data(HA_CREATE_INFO *create_info, if ((create_info->used_fields & HA_CREATE_USED_AUTO && create_info->auto_increment_value != stats.auto_increment_value) || - create_info->data_file_name != data_file_name || - create_info->index_file_name != index_file_name || + directories_differ(create_info->data_file_name, data_file_name) || + directories_differ(create_info->index_file_name, index_file_name) || table_changes == IS_EQUAL_NO || table_changes & IS_EQUAL_PACK_LENGTH) // Not implemented yet return COMPATIBLE_DATA_NO; diff --git a/storage/test_sql_discovery/mysql-test/sql_discovery/simple.result b/storage/test_sql_discovery/mysql-test/sql_discovery/simple.result index 7ca36e07438..23b7804638f 100644 --- a/storage/test_sql_discovery/mysql-test/sql_discovery/simple.result +++ b/storage/test_sql_discovery/mysql-test/sql_discovery/simple.result @@ -4,7 +4,7 @@ test_sql_discovery_statement test_sql_discovery_write_frm ON set sql_quote_show_create=0; create table t1 (a int) engine=test_sql_discovery; -ERROR HY000: Can't create table `test`.`t1` (errno: 131 "Command not supported by database") +ERROR HY000: Can't create table `test`.`t1` (errno: 131 "Command not supported by the engine") select * from t1; ERROR 42S02: Table 'test.t1' doesn't exist set @@test_sql_discovery_statement='t1:foobar bwa-ha-ha'; diff --git a/storage/tokudb/CMakeLists.txt b/storage/tokudb/CMakeLists.txt index ad96328b8db..73e4bf37a06 100644 --- a/storage/tokudb/CMakeLists.txt +++ b/storage/tokudb/CMakeLists.txt @@ -1,4 +1,4 @@ -SET(TOKUDB_VERSION 5.6.36-82.1) +SET(TOKUDB_VERSION 5.6.37-82.2) # PerconaFT only supports x86-64 and cmake-2.8.9+ IF(CMAKE_VERSION VERSION_LESS "2.8.9") MESSAGE(STATUS "CMake 2.8.9 or higher is required by TokuDB") @@ -24,7 +24,7 @@ SET(TOKUDB_SOURCES tokudb_thread.cc tokudb_dir_cmd.cc) MYSQL_ADD_PLUGIN(tokudb ${TOKUDB_SOURCES} STORAGE_ENGINE MODULE_ONLY - COMPONENT tokudb-engine) + COMPONENT tokudb-engine CONFIG tokudb.cnf) IF(NOT TARGET tokudb) RETURN() @@ -111,8 +111,3 @@ TARGET_LINK_LIBRARIES(tokudb tokufractaltree_static tokuportability_static SET(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} -flto -fuse-linker-plugin") SET(CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO} -flto -fuse-linker-plugin") - -IF (INSTALL_SYSCONF2DIR) - INSTALL(FILES tokudb.cnf DESTINATION ${INSTALL_SYSCONF2DIR} - COMPONENT tokudb-engine) -ENDIF(INSTALL_SYSCONF2DIR) diff --git a/storage/tokudb/PerconaFT/buildheader/make_tdb.cc b/storage/tokudb/PerconaFT/buildheader/make_tdb.cc index 6f0b7c5f419..0fa876f2bd8 100644 --- a/storage/tokudb/PerconaFT/buildheader/make_tdb.cc +++ b/storage/tokudb/PerconaFT/buildheader/make_tdb.cc @@ -231,6 +231,8 @@ static void print_defines (void) { printf("#define DB_SET_RANGE_REVERSE 252\n"); // private tokudb //printf("#define DB_GET_BOTH_RANGE_REVERSE 251\n"); // private tokudb. No longer supported #2862. dodefine(DB_RMW); + + printf("#define DB_LOCKING_READ 0x80000000\n"); printf("#define DB_IS_RESETTING_OP 0x01000000\n"); // private tokudb printf("#define DB_PRELOCKED 0x00800000\n"); // private tokudb printf("#define DB_PRELOCKED_WRITE 0x00400000\n"); // private tokudb diff --git a/storage/tokudb/PerconaFT/src/ydb-internal.h b/storage/tokudb/PerconaFT/src/ydb-internal.h index a1eb43a67c5..db2041095f7 100644 --- a/storage/tokudb/PerconaFT/src/ydb-internal.h +++ b/storage/tokudb/PerconaFT/src/ydb-internal.h @@ -239,13 +239,16 @@ struct __toku_dbc_internal { struct simple_dbt skey_s,sval_s; struct simple_dbt *skey,*sval; - // if the rmw flag is asserted, cursor operations (like set) grab write locks instead of read locks + // if the rmw flag is asserted, cursor operations (like set) grab write + // locks instead of read locks // the rmw flag is set when the cursor is created with the DB_RMW flag set bool rmw; + bool locking_read; }; -static_assert(sizeof(__toku_dbc_internal) <= sizeof(((DBC *) nullptr)->_internal), - "__toku_dbc_internal doesn't fit in the internal portion of a DBC"); +static_assert( + sizeof(__toku_dbc_internal) <= sizeof(((DBC *)nullptr)->_internal), + "__toku_dbc_internal doesn't fit in the internal portion of a DBC"); static inline __toku_dbc_internal *dbc_struct_i(DBC *c) { union dbc_union { diff --git a/storage/tokudb/PerconaFT/src/ydb_cursor.cc b/storage/tokudb/PerconaFT/src/ydb_cursor.cc index 015e302f1c6..1f4f00b7423 100644 --- a/storage/tokudb/PerconaFT/src/ydb_cursor.cc +++ b/storage/tokudb/PerconaFT/src/ydb_cursor.cc @@ -110,12 +110,14 @@ c_get_wrapper_callback(DBT const *key, DBT const *val, void *extra) { return r; } -static inline uint32_t -get_cursor_prelocked_flags(uint32_t flags, DBC* dbc) { +static inline uint32_t get_cursor_prelocked_flags(uint32_t flags, DBC *dbc) { uint32_t lock_flags = flags & (DB_PRELOCKED | DB_PRELOCKED_WRITE); - //DB_READ_UNCOMMITTED and DB_READ_COMMITTED transactions 'own' all read locks for user-data dictionaries. - if (dbc_struct_i(dbc)->iso != TOKU_ISO_SERIALIZABLE) { + // DB_READ_UNCOMMITTED and DB_READ_COMMITTED transactions 'own' all read + // locks for user-data dictionaries. + if (dbc_struct_i(dbc)->iso != TOKU_ISO_SERIALIZABLE && + !(dbc_struct_i(dbc)->iso == TOKU_ISO_SNAPSHOT && + dbc_struct_i(dbc)->locking_read)) { lock_flags |= DB_PRELOCKED; } return lock_flags; @@ -671,37 +673,44 @@ int toku_c_close(DBC *c) { return 0; } -static int -c_set_bounds(DBC *dbc, const DBT *left_key, const DBT *right_key, bool pre_acquire, int out_of_range_error) { +static int c_set_bounds(DBC *dbc, + const DBT *left_key, + const DBT *right_key, + bool pre_acquire, + int out_of_range_error) { if (out_of_range_error != DB_NOTFOUND && - out_of_range_error != TOKUDB_OUT_OF_RANGE && - out_of_range_error != 0) { - return toku_ydb_do_error( - dbc->dbp->dbenv, - EINVAL, - "Invalid out_of_range_error [%d] for %s\n", - out_of_range_error, - __FUNCTION__ - ); - } - if (left_key == toku_dbt_negative_infinity() && right_key == toku_dbt_positive_infinity()) { + out_of_range_error != TOKUDB_OUT_OF_RANGE && out_of_range_error != 0) { + return toku_ydb_do_error(dbc->dbp->dbenv, + EINVAL, + "Invalid out_of_range_error [%d] for %s\n", + out_of_range_error, + __FUNCTION__); + } + if (left_key == toku_dbt_negative_infinity() && + right_key == toku_dbt_positive_infinity()) { out_of_range_error = 0; } DB *db = dbc->dbp; DB_TXN *txn = dbc_struct_i(dbc)->txn; HANDLE_PANICKED_DB(db); - toku_ft_cursor_set_range_lock(dbc_ftcursor(dbc), left_key, right_key, - (left_key == toku_dbt_negative_infinity()), - (right_key == toku_dbt_positive_infinity()), - out_of_range_error); + toku_ft_cursor_set_range_lock(dbc_ftcursor(dbc), + left_key, + right_key, + (left_key == toku_dbt_negative_infinity()), + (right_key == toku_dbt_positive_infinity()), + out_of_range_error); if (!db->i->lt || !txn || !pre_acquire) return 0; - //READ_UNCOMMITTED and READ_COMMITTED transactions do not need read locks. - if (!dbc_struct_i(dbc)->rmw && dbc_struct_i(dbc)->iso != TOKU_ISO_SERIALIZABLE) + // READ_UNCOMMITTED and READ_COMMITTED transactions do not need read locks. + if (!dbc_struct_i(dbc)->rmw && + dbc_struct_i(dbc)->iso != TOKU_ISO_SERIALIZABLE && + !(dbc_struct_i(dbc)->iso == TOKU_ISO_SNAPSHOT && + dbc_struct_i(dbc)->locking_read)) return 0; - toku::lock_request::type lock_type = dbc_struct_i(dbc)->rmw ? - toku::lock_request::type::WRITE : toku::lock_request::type::READ; + toku::lock_request::type lock_type = dbc_struct_i(dbc)->rmw + ? toku::lock_request::type::WRITE + : toku::lock_request::type::READ; int r = toku_db_get_range_lock(db, txn, left_key, right_key, lock_type); return r; } @@ -783,18 +792,20 @@ toku_c_get(DBC* c, DBT* key, DBT* val, uint32_t flag) { return r; } -int -toku_db_cursor_internal(DB * db, DB_TXN * txn, DBC *c, uint32_t flags, int is_temporary_cursor) { +int toku_db_cursor_internal(DB *db, + DB_TXN *txn, + DBC *c, + uint32_t flags, + int is_temporary_cursor) { HANDLE_PANICKED_DB(db); HANDLE_DB_ILLEGAL_WORKING_PARENT_TXN(db, txn); - DB_ENV* env = db->dbenv; + DB_ENV *env = db->dbenv; - if (flags & ~(DB_SERIALIZABLE | DB_INHERIT_ISOLATION | DB_RMW | DBC_DISABLE_PREFETCHING)) { + if (flags & + ~(DB_SERIALIZABLE | DB_INHERIT_ISOLATION | DB_LOCKING_READ | DB_RMW | + DBC_DISABLE_PREFETCHING)) { return toku_ydb_do_error( - env, - EINVAL, - "Invalid flags set for toku_db_cursor\n" - ); + env, EINVAL, "Invalid flags set for toku_db_cursor\n"); } #define SCRS(name) c->name = name @@ -819,8 +830,8 @@ toku_db_cursor_internal(DB * db, DB_TXN * txn, DBC *c, uint32_t flags, int is_te c->dbp = db; dbc_struct_i(c)->txn = txn; - dbc_struct_i(c)->skey_s = (struct simple_dbt){0,0}; - dbc_struct_i(c)->sval_s = (struct simple_dbt){0,0}; + dbc_struct_i(c)->skey_s = (struct simple_dbt){0, 0}; + dbc_struct_i(c)->sval_s = (struct simple_dbt){0, 0}; if (is_temporary_cursor) { dbc_struct_i(c)->skey = &db->i->skey; dbc_struct_i(c)->sval = &db->i->sval; @@ -831,28 +842,27 @@ toku_db_cursor_internal(DB * db, DB_TXN * txn, DBC *c, uint32_t flags, int is_te if (flags & DB_SERIALIZABLE) { dbc_struct_i(c)->iso = TOKU_ISO_SERIALIZABLE; } else { - dbc_struct_i(c)->iso = txn ? db_txn_struct_i(txn)->iso : TOKU_ISO_SERIALIZABLE; + dbc_struct_i(c)->iso = + txn ? db_txn_struct_i(txn)->iso : TOKU_ISO_SERIALIZABLE; } dbc_struct_i(c)->rmw = (flags & DB_RMW) != 0; - enum cursor_read_type read_type = C_READ_ANY; // default, used in serializable and read uncommitted + dbc_struct_i(c)->locking_read = (flags & DB_LOCKING_READ) != 0; + enum cursor_read_type read_type = + C_READ_ANY; // default, used in serializable and read uncommitted if (txn) { if (dbc_struct_i(c)->iso == TOKU_ISO_READ_COMMITTED || - dbc_struct_i(c)->iso == TOKU_ISO_SNAPSHOT) - { + dbc_struct_i(c)->iso == TOKU_ISO_SNAPSHOT) { read_type = C_READ_SNAPSHOT; - } - else if (dbc_struct_i(c)->iso == TOKU_ISO_READ_COMMITTED_ALWAYS) { + } else if (dbc_struct_i(c)->iso == TOKU_ISO_READ_COMMITTED_ALWAYS) { read_type = C_READ_COMMITTED; } } - int r = toku_ft_cursor_create( - db->i->ft_handle, - dbc_ftcursor(c), - txn ? db_txn_struct_i(txn)->tokutxn : NULL, - read_type, - ((flags & DBC_DISABLE_PREFETCHING) != 0), - is_temporary_cursor != 0 - ); + int r = toku_ft_cursor_create(db->i->ft_handle, + dbc_ftcursor(c), + txn ? db_txn_struct_i(txn)->tokutxn : NULL, + read_type, + ((flags & DBC_DISABLE_PREFETCHING) != 0), + is_temporary_cursor != 0); if (r != 0) { invariant(r == TOKUDB_MVCC_DICTIONARY_TOO_NEW); } diff --git a/storage/tokudb/ha_tokudb.cc b/storage/tokudb/ha_tokudb.cc index 48c8da64a72..3c83049835a 100644 --- a/storage/tokudb/ha_tokudb.cc +++ b/storage/tokudb/ha_tokudb.cc @@ -7631,7 +7631,13 @@ static bool tokudb_check_db_dir_exist_from_table_name(const char *table_name) { memcpy(db_name, db_name_begin, db_name_size); db_name[db_name_size] = '\0'; - mysql_dir_exists = (check_db_dir_existence(db_name) == 0); + + // At this point, db_name contains the MySQL formatted database name. + // This is exactly the same format that would come into us through a + // CREATE TABLE. Some charaters (like ':' for example) might be expanded + // into hex (':' would papear as "@003a"). + // We need to check that the MySQL destination database directory exists. + mysql_dir_exists = (my_access(db_name, F_OK) == 0); return mysql_dir_exists; } diff --git a/storage/tokudb/mysql-test/rpl/r/rpl_row_log_tokudb.result b/storage/tokudb/mysql-test/rpl/r/rpl_row_log_tokudb.result deleted file mode 100644 index 73c010c6eb7..00000000000 --- a/storage/tokudb/mysql-test/rpl/r/rpl_row_log_tokudb.result +++ /dev/null @@ -1,315 +0,0 @@ -include/master-slave.inc -[connection master] -connection slave; -include/stop_slave.inc -include/wait_for_slave_to_stop.inc -reset master; -reset slave; -start slave; -include/wait_for_slave_to_start.inc -connection slave; -set @save_slave_ddl_exec_mode=@@global.slave_ddl_exec_mode; -set @@global.slave_ddl_exec_mode=STRICT; -connection master; -create table t1(n int not null auto_increment primary key)ENGINE=TokuDB; -insert into t1 values (NULL); -drop table t1; -create table t1 (word char(20) not null)ENGINE=TokuDB; -load data infile 'LOAD_FILE' into table t1 ignore 1 lines; -select count(*) from t1; -count(*) -69 -include/show_binlog_events.inc -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Gtid # # GTID #-#-# -master-bin.000001 # Query # # use `test`; create table t1(n int not null auto_increment primary key)ENGINE=TokuDB -master-bin.000001 # Gtid # # BEGIN GTID #-#-# -master-bin.000001 # Annotate_rows # # insert into t1 values (NULL) -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F -master-bin.000001 # Xid # # COMMIT /* XID */ -master-bin.000001 # Gtid # # GTID #-#-# -master-bin.000001 # Query # # use `test`; DROP TABLE `t1` /* generated by server */ -master-bin.000001 # Gtid # # GTID #-#-# -master-bin.000001 # Query # # use `test`; create table t1 (word char(20) not null)ENGINE=TokuDB -master-bin.000001 # Gtid # # BEGIN GTID #-#-# -master-bin.000001 # Annotate_rows # # load data infile '../../std_data/words.dat' into table t1 ignore 1 lines -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F -master-bin.000001 # Xid # # COMMIT /* XID */ -include/show_binlog_events.inc -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Gtid # # GTID #-#-# -master-bin.000001 # Query # # use `test`; create table t1(n int not null auto_increment primary key)ENGINE=TokuDB -include/show_binlog_events.inc -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Gtid # # GTID #-#-# -master-bin.000001 # Query # # use `test`; create table t1(n int not null auto_increment primary key)ENGINE=TokuDB -master-bin.000001 # Gtid # # BEGIN GTID #-#-# -include/show_binlog_events.inc -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Gtid # # BEGIN GTID #-#-# -master-bin.000001 # Annotate_rows # # insert into t1 values (NULL) -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F -master-bin.000001 # Xid # # COMMIT /* XID */ -flush logs; -create table t3 (a int)ENGINE=TokuDB; -connection master; -select * from t1 order by 1 asc; -word -Aarhus -Aaron -Aaron -Ababa -Ababa -aback -aback -abaft -abaft -abandon -abandon -abandoned -abandoned -abandoning -abandoning -abandonment -abandonment -abandons -abandons -abase -abased -abasement -abasements -abases -abash -abashed -abashes -abashing -abasing -abate -abated -abatement -abatements -abater -abates -abating -Abba -abbe -abbey -abbeys -abbot -abbots -Abbott -abbreviate -abbreviated -abbreviates -abbreviating -abbreviation -abbreviations -Abby -abdomen -abdomens -abdominal -abduct -abducted -abduction -abductions -abductor -abductors -abducts -Abe -abed -Abel -Abelian -Abelson -Aberdeen -Abernathy -aberrant -aberration -connection slave; -select * from t1 order by 1 asc; -word -Aarhus -Aaron -Aaron -Ababa -Ababa -aback -aback -abaft -abaft -abandon -abandon -abandoned -abandoned -abandoning -abandoning -abandonment -abandonment -abandons -abandons -abase -abased -abasement -abasements -abases -abash -abashed -abashes -abashing -abasing -abate -abated -abatement -abatements -abater -abates -abating -Abba -abbe -abbey -abbeys -abbot -abbots -Abbott -abbreviate -abbreviated -abbreviates -abbreviating -abbreviation -abbreviations -Abby -abdomen -abdomens -abdominal -abduct -abducted -abduction -abductions -abductor -abductors -abducts -Abe -abed -Abel -Abelian -Abelson -Aberdeen -Abernathy -aberrant -aberration -flush logs; -include/stop_slave.inc -include/start_slave.inc -connection master; -create table t2 (n int)ENGINE=TokuDB; -insert into t2 values (1); -include/show_binlog_events.inc -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Gtid # # GTID #-#-# -master-bin.000001 # Query # # use `test`; create table t1(n int not null auto_increment primary key)ENGINE=TokuDB -master-bin.000001 # Gtid # # BEGIN GTID #-#-# -master-bin.000001 # Annotate_rows # # insert into t1 values (NULL) -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F -master-bin.000001 # Xid # # COMMIT /* XID */ -master-bin.000001 # Gtid # # GTID #-#-# -master-bin.000001 # Query # # use `test`; DROP TABLE `t1` /* generated by server */ -master-bin.000001 # Gtid # # GTID #-#-# -master-bin.000001 # Query # # use `test`; create table t1 (word char(20) not null)ENGINE=TokuDB -master-bin.000001 # Gtid # # BEGIN GTID #-#-# -master-bin.000001 # Annotate_rows # # load data infile '../../std_data/words.dat' into table t1 ignore 1 lines -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F -master-bin.000001 # Xid # # COMMIT /* XID */ -master-bin.000001 # Rotate # # master-bin.000002;pos=POS -include/show_binlog_events.inc -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000002 # Binlog_checkpoint # # master-bin.000002 -master-bin.000002 # Gtid # # GTID #-#-# -master-bin.000002 # Query # # use `test`; create table t3 (a int)ENGINE=TokuDB -master-bin.000002 # Gtid # # GTID #-#-# -master-bin.000002 # Query # # use `test`; create table t2 (n int)ENGINE=TokuDB -master-bin.000002 # Gtid # # BEGIN GTID #-#-# -master-bin.000002 # Annotate_rows # # insert into t2 values (1) -master-bin.000002 # Table_map # # table_id: # (test.t2) -master-bin.000002 # Write_rows_v1 # # table_id: # flags: STMT_END_F -master-bin.000002 # Xid # # COMMIT /* XID */ -show binary logs; -Log_name File_size -master-bin.000001 # -master-bin.000002 # -connection slave; -show binary logs; -Log_name File_size -slave-bin.000001 # -slave-bin.000002 # -include/show_binlog_events.inc -Log_name Pos Event_type Server_id End_log_pos Info -slave-bin.000001 # Gtid # # GTID #-#-# -slave-bin.000001 # Query # # use `test`; create table t1(n int not null auto_increment primary key)ENGINE=TokuDB -slave-bin.000001 # Gtid # # BEGIN GTID #-#-# -slave-bin.000001 # Annotate_rows # # insert into t1 values (NULL) -slave-bin.000001 # Table_map # # table_id: # (test.t1) -slave-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F -slave-bin.000001 # Xid # # COMMIT /* XID */ -slave-bin.000001 # Gtid # # GTID #-#-# -slave-bin.000001 # Query # # use `test`; DROP TABLE `t1` /* generated by server */ -slave-bin.000001 # Gtid # # GTID #-#-# -slave-bin.000001 # Query # # use `test`; create table t1 (word char(20) not null)ENGINE=TokuDB -slave-bin.000001 # Gtid # # BEGIN GTID #-#-# -slave-bin.000001 # Annotate_rows # # load data infile '../../std_data/words.dat' into table t1 ignore 1 lines -slave-bin.000001 # Table_map # # table_id: # (test.t1) -slave-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F -slave-bin.000001 # Xid # # COMMIT /* XID */ -slave-bin.000001 # Gtid # # GTID #-#-# -slave-bin.000001 # Query # # use `test`; create table t3 (a int)ENGINE=TokuDB -slave-bin.000001 # Rotate # # slave-bin.000002;pos=POS -include/show_binlog_events.inc -Log_name Pos Event_type Server_id End_log_pos Info -slave-bin.000002 # Binlog_checkpoint # # slave-bin.000002 -slave-bin.000002 # Gtid # # GTID #-#-# -slave-bin.000002 # Query # # use `test`; create table t2 (n int)ENGINE=TokuDB -slave-bin.000002 # Gtid # # BEGIN GTID #-#-# -slave-bin.000002 # Annotate_rows # # insert into t2 values (1) -slave-bin.000002 # Table_map # # table_id: # (test.t2) -slave-bin.000002 # Write_rows_v1 # # table_id: # flags: STMT_END_F -slave-bin.000002 # Xid # # COMMIT /* XID */ -include/check_slave_is_running.inc -show binlog events in 'slave-bin.000005' from 4; -ERROR HY000: Error when executing command SHOW BINLOG EVENTS: Could not find target log -connection master; -DROP TABLE t1; -DROP TABLE t2; -DROP TABLE t3; -include/rpl_reset.inc -connection master; -create table t1(a int auto_increment primary key, b int); -insert into t1 values (NULL, 1); -set insert_id=5; -insert into t1 values (NULL, last_insert_id()), (NULL, last_insert_id()); -include/show_binlog_events.inc -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Gtid # # GTID #-#-# -master-bin.000001 # Query # # use `test`; create table t1(a int auto_increment primary key, b int) -master-bin.000001 # Gtid # # BEGIN GTID #-#-# -master-bin.000001 # Annotate_rows # # insert into t1 values (NULL, 1) -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F -master-bin.000001 # Query # # COMMIT -master-bin.000001 # Gtid # # BEGIN GTID #-#-# -master-bin.000001 # Annotate_rows # # insert into t1 values (NULL, last_insert_id()), (NULL, last_insert_id()) -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F -master-bin.000001 # Query # # COMMIT -select * from t1; -a b -1 1 -5 1 -6 1 -drop table t1; -connection slave; -set @@global.slave_ddl_exec_mode=@save_slave_ddl_exec_mode; -connection master; -include/rpl_end.inc diff --git a/storage/tokudb/mysql-test/rpl/t/rpl_row_log_tokudb-master.opt b/storage/tokudb/mysql-test/rpl/t/rpl_row_log_tokudb-master.opt deleted file mode 100644 index 773ec62bef2..00000000000 --- a/storage/tokudb/mysql-test/rpl/t/rpl_row_log_tokudb-master.opt +++ /dev/null @@ -1,2 +0,0 @@ ---skip-external-locking ---default-storage-engine=MyISAM diff --git a/storage/tokudb/mysql-test/rpl/t/rpl_row_log_tokudb.test b/storage/tokudb/mysql-test/rpl/t/rpl_row_log_tokudb.test deleted file mode 100644 index 826eb5eab86..00000000000 --- a/storage/tokudb/mysql-test/rpl/t/rpl_row_log_tokudb.test +++ /dev/null @@ -1,14 +0,0 @@ -################################### -# Wrapper for rpl_row_log.test # -# Added wrapper so that MyISAM & # -# Innodb and NDB could all use the# -# Same test. NDB produced a diff # -# bin-log # -################################### --- source include/have_binlog_format_row.inc --- source include/have_tokudb.inc --- source include/master-slave.inc -let $engine_type=TokuDB; --- source extra/rpl_tests/rpl_log.test - ---source include/rpl_end.inc diff --git a/storage/tokudb/mysql-test/tokudb/r/dir_per_db.result b/storage/tokudb/mysql-test/tokudb/r/dir_per_db.result index 371f97406c8..30d4e4244fd 100644 --- a/storage/tokudb/mysql-test/tokudb/r/dir_per_db.result +++ b/storage/tokudb/mysql-test/tokudb/r/dir_per_db.result @@ -1,3 +1,4 @@ +SET @orig_tokudb_dir_per_db=@@global.tokudb_dir_per_db; ######## # tokudb_dir_per_db = 1 ######## @@ -177,4 +178,11 @@ t1_status_id.tokudb DROP TABLE t2; ## Looking for *.tokudb files in data_dir ## Looking for *.tokudb files in data_dir/test -SET GLOBAL tokudb_dir_per_db=default; +CREATE DATABASE `a::a@@`; +CREATE TABLE `a::a@@`.`t1` (a INT) ENGINE=TOKUDB; +CREATE DATABASE `!@#$%^&*()`; +ALTER TABLE `a::a@@`.`t1` RENAME `!@#$%^&*()`.`t1`; +DROP TABLE `!@#$%^&*()`.`t1`; +DROP DATABASE `!@#$%^&*()`; +DROP DATABASE `a::a@@`; +SET GLOBAL tokudb_dir_per_db=@orig_tokudb_dir_per_db; diff --git a/storage/tokudb/mysql-test/tokudb/t/dir_per_db.test b/storage/tokudb/mysql-test/tokudb/t/dir_per_db.test index b638b706d87..64745cb049c 100644 --- a/storage/tokudb/mysql-test/tokudb/t/dir_per_db.test +++ b/storage/tokudb/mysql-test/tokudb/t/dir_per_db.test @@ -1,5 +1,7 @@ source include/have_tokudb.inc; +SET @orig_tokudb_dir_per_db=@@global.tokudb_dir_per_db; + --let $DB= test --let $DATADIR= `select @@datadir` --let $i= 2 @@ -73,4 +75,17 @@ while ($i) { --source dir_per_db_show_table_files.inc } -SET GLOBAL tokudb_dir_per_db=default; + +# test case for TDB-72 : Can not rename table in database with non alphanum +# characters in its name. +CREATE DATABASE `a::a@@`; +CREATE TABLE `a::a@@`.`t1` (a INT) ENGINE=TOKUDB; +CREATE DATABASE `!@#$%^&*()`; +ALTER TABLE `a::a@@`.`t1` RENAME `!@#$%^&*()`.`t1`; + +DROP TABLE `!@#$%^&*()`.`t1`; +DROP DATABASE `!@#$%^&*()`; +DROP DATABASE `a::a@@`; + +# cleanup +SET GLOBAL tokudb_dir_per_db=@orig_tokudb_dir_per_db; diff --git a/storage/xtradb/api/api0api.cc b/storage/xtradb/api/api0api.cc index 2a46dd4b4c1..0aae482b9f5 100644 --- a/storage/xtradb/api/api0api.cc +++ b/storage/xtradb/api/api0api.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2008, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2008, 2017, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1988,6 +1988,7 @@ ib_cursor_read_row( page_format = static_cast<ib_bool_t>( dict_table_is_comp(tuple->index->table)); + rec = btr_pcur_get_rec(pcur); if (prebuilt->innodb_api_rec && @@ -2029,6 +2030,7 @@ ib_cursor_position( buf = static_cast<unsigned char*>(mem_alloc(UNIV_PAGE_SIZE)); + /* We want to position at one of the ends, row_search_for_mysql() uses the search_tuple fields to work out what to do. */ dtuple_set_n_fields(prebuilt->search_tuple, 0); diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index ef523bea0d5..64b93a07bd7 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -10561,6 +10561,27 @@ ha_innobase::ft_init_ext( } /*****************************************************************//** +Copy a cached MySQL row. +If requested, also avoids overwriting non-read columns. +@param[out] buf Row in MySQL format. +@param[in] cached_row Which row to copy. +@param[in] rec_len Record length. */ +void +ha_innobase::copy_cached_row( + uchar* buf, + const uchar* cached_row, + uint rec_len) +{ + if (prebuilt->keep_other_fields_on_keyread) { + row_sel_copy_cached_fields_for_mysql(buf, cached_row, + prebuilt); + } else { + memcpy(buf, cached_row, rec_len); + } +} + + +/*****************************************************************//** Set up search tuple for a query through FTS_DOC_ID_INDEX on supplied Doc ID. This is used by MySQL to retrieve the documents once the search result (Doc IDs) is available */ diff --git a/storage/xtradb/handler/ha_innodb.h b/storage/xtradb/handler/ha_innodb.h index 3bb67532954..c2905d80642 100644 --- a/storage/xtradb/handler/ha_innodb.h +++ b/storage/xtradb/handler/ha_innodb.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2000, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2000, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2013, 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under @@ -167,6 +167,10 @@ class ha_innobase: public handler int index_first(uchar * buf); int index_last(uchar * buf); + /* Copy a cached MySQL row. If requested, also avoids + overwriting non-read columns. */ + void copy_cached_row(uchar *to_rec, const uchar *from_rec, + uint rec_length); bool has_gap_locks() const { return true; } int rnd_init(bool scan); diff --git a/storage/xtradb/include/row0mysql.h b/storage/xtradb/include/row0mysql.h index a8503a5cfda..4326f1208e5 100644 --- a/storage/xtradb/include/row0mysql.h +++ b/storage/xtradb/include/row0mysql.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2000, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2000, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under diff --git a/storage/xtradb/include/row0sel.h b/storage/xtradb/include/row0sel.h index fd5bc755a22..afeb216c2a2 100644 --- a/storage/xtradb/include/row0sel.h +++ b/storage/xtradb/include/row0sel.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1997, 2017, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -205,6 +205,18 @@ struct sel_buf_t{ when data != NULL */ }; +/** Copy used fields from cached row. +Copy cache record field by field, don't touch fields that +are not covered by current key. +@param[out] buf Where to copy the MySQL row. +@param[in] cached_rec What to copy (in MySQL row format). +@param[in] prebuilt prebuilt struct. */ +void +row_sel_copy_cached_fields_for_mysql( + byte* buf, + const byte* cached_rec, + row_prebuilt_t* prebuilt); + /** Query plan */ struct plan_t{ dict_table_t* table; /*!< table struct in the dictionary diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i index 739f6640eef..5886b078e4d 100644 --- a/storage/xtradb/include/univ.i +++ b/storage/xtradb/include/univ.i @@ -48,7 +48,7 @@ Created 1/20/1994 Heikki Tuuri #define INNODB_VERSION_BUGFIX 36 #ifndef PERCONA_INNODB_VERSION -#define PERCONA_INNODB_VERSION 82.1 +#define PERCONA_INNODB_VERSION 82.2 #endif /* Enable UNIV_LOG_ARCHIVE in XtraDB */ diff --git a/storage/xtradb/row/row0merge.cc b/storage/xtradb/row/row0merge.cc index d38f10ee7ba..9d299bf6288 100644 --- a/storage/xtradb/row/row0merge.cc +++ b/storage/xtradb/row/row0merge.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2005, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2014, 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under @@ -1538,6 +1538,8 @@ row_merge_read_clustered_index( goto func_exit; } + mem_heap_empty(row_heap); + page_cur_move_to_next(cur); if (page_cur_is_after_last(cur)) { @@ -1970,8 +1972,6 @@ write_buffers: goto func_exit; } - mem_heap_empty(row_heap); - /* Increment innodb_onlineddl_pct_progress status variable */ read_rows++; if(read_rows % 1000 == 0) { diff --git a/storage/xtradb/row/row0sel.cc b/storage/xtradb/row/row0sel.cc index 26fd7629a5d..d96d6d37844 100644 --- a/storage/xtradb/row/row0sel.cc +++ b/storage/xtradb/row/row0sel.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1997, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. Copyright (c) 2015, 2017, MariaDB Corporation. @@ -2571,31 +2571,30 @@ row_sel_store_row_id_to_prebuilt( (dest,templ,src,len) #endif /* UNIV_DEBUG */ -/**************************************************************//** -Stores a non-SQL-NULL field in the MySQL format. The counterpart of this -function is row_mysql_store_col_in_innobase_format() in row0mysql.cc. */ +/** Stores a non-SQL-NULL field in the MySQL format. The counterpart of this +function is row_mysql_store_col_in_innobase_format() in row0mysql.cc. +@param[in,out] dest buffer where to store; NOTE + that BLOBs are not in themselves stored + here: the caller must allocate and copy + the BLOB into buffer before, and pass + the pointer to the BLOB in 'data' +@param[in] templ MySQL column template. Its following fields + are referenced: type, is_unsigned, mysql_col_len, + mbminlen, mbmaxlen +@param[in] index InnoDB index +@param[in] field_no templ->rec_field_no or templ->clust_rec_field_no + or templ->icp_rec_field_no +@param[in] data data to store +@param[in] len length of the data +*/ static MY_ATTRIBUTE((nonnull)) void row_sel_field_store_in_mysql_format_func( -/*=====================================*/ - byte* dest, /*!< in/out: buffer where to store; NOTE - that BLOBs are not in themselves - stored here: the caller must allocate - and copy the BLOB into buffer before, - and pass the pointer to the BLOB in - 'data' */ + byte* dest, const mysql_row_templ_t* templ, - /*!< in: MySQL column template. - Its following fields are referenced: - type, is_unsigned, mysql_col_len, - mbminlen, mbmaxlen */ #ifdef UNIV_DEBUG const dict_index_t* index, - /*!< in: InnoDB index */ ulint field_no, - /*!< in: templ->rec_field_no or - templ->clust_rec_field_no or - templ->icp_rec_field_no */ #endif /* UNIV_DEBUG */ const byte* data, /*!< in: data to store */ ulint len) /*!< in: length of the data */ @@ -2748,7 +2747,7 @@ row_sel_field_store_in_mysql_format_func( #endif /* UNIV_DEBUG */ ut_ad(field->prefix_len ? field->prefix_len == len - : templ->mysql_col_len == len); + : (templ->mysql_col_len == len)); memcpy(dest, data, len); } } @@ -2772,8 +2771,6 @@ row_sel_field_store_in_mysql_format_func( @param[in] field_no templ->rec_field_no or templ->clust_rec_field_no or templ->icp_rec_field_no - or sec field no if clust_templ_for_sec - is TRUE @param[in] templ row template */ static MY_ATTRIBUTE((warn_unused_result)) @@ -2955,6 +2952,7 @@ row_sel_store_mysql_rec( = rec_clust ? templ->clust_rec_field_no : templ->rec_field_no; + /* We should never deliver column prefixes to MySQL, except for evaluating innobase_index_cond() and if the prefix index is longer than the actual row data. */ @@ -3353,6 +3351,36 @@ row_sel_copy_cached_field_for_mysql( ut_memcpy(buf, cache, len); } +/** Copy used fields from cached row. +Copy cache record field by field, don't touch fields that +are not covered by current key. +@param[out] buf Where to copy the MySQL row. +@param[in] cached_rec What to copy (in MySQL row format). +@param[in] prebuilt prebuilt struct. */ +void +row_sel_copy_cached_fields_for_mysql( + byte* buf, + const byte* cached_rec, + row_prebuilt_t* prebuilt) +{ + const mysql_row_templ_t*templ; + ulint i; + for (i = 0; i < prebuilt->n_template; i++) { + templ = prebuilt->mysql_template + i; + + row_sel_copy_cached_field_for_mysql( + buf, cached_rec, templ); + /* Copy NULL bit of the current field from cached_rec + to buf */ + if (templ->mysql_null_bit_mask) { + buf[templ->mysql_null_byte_offset] + ^= (buf[templ->mysql_null_byte_offset] + ^ cached_rec[templ->mysql_null_byte_offset]) + & (byte) templ->mysql_null_bit_mask; + } + } +} + /********************************************************************//** Pops a cached row for MySQL from the fetch cache. */ UNIV_INLINE |