188 lines
6.9 KiB
C++
188 lines
6.9 KiB
C++
/*
|
|
Copyright (c) 2019, 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, version 2.0,
|
|
as published by the Free Software Foundation.
|
|
|
|
This program is also distributed with certain software (including
|
|
but not limited to OpenSSL) that is licensed under separate terms,
|
|
as designated in a particular file or component or in included license
|
|
documentation. The authors of MySQL hereby grant you an additional
|
|
permission to link the program and your derivative works with the
|
|
separately licensed software that they have included with MySQL.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License, version 2.0, for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#include "storage/ndb/plugin/ndb_sql_metadata_table.h"
|
|
|
|
#include <sstream>
|
|
|
|
#include "storage/ndb/plugin/ndb_thd_ndb.h"
|
|
|
|
Ndb_sql_metadata_table::Ndb_sql_metadata_table(Thd_ndb *thd_ndb)
|
|
: Ndb_util_table(thd_ndb, "mysql", "ndb_sql_metadata", true, false) {}
|
|
|
|
bool Ndb_sql_metadata_table::define_table_ndb(NdbDictionary::Table &new_table,
|
|
unsigned) const {
|
|
static const char *COL_TYPE = "type";
|
|
static const char *COL_NAME = "name";
|
|
static const char *COL_SEQUENCE = "seq";
|
|
static const char *COL_NOTE = "note";
|
|
static const char *COL_TEXT = "sql_ddl_text";
|
|
|
|
// Allow later online add column
|
|
new_table.setForceVarPart(true);
|
|
|
|
// Allow table to be read+write also in single user mode
|
|
new_table.setSingleUserMode(NdbDictionary::Table::SingleUserModeReadWrite);
|
|
|
|
{
|
|
// `type` smallint(6) NOT NULL
|
|
NdbDictionary::Column col_type(COL_TYPE);
|
|
col_type.setType(NdbDictionary::Column::Smallint);
|
|
col_type.setNullable(false);
|
|
col_type.setPrimaryKey(true);
|
|
if (!define_table_add_column(new_table, col_type)) return false;
|
|
}
|
|
|
|
{
|
|
// `name` varbinary(400) NOT NULL
|
|
NdbDictionary::Column col_name(COL_NAME);
|
|
col_name.setType(NdbDictionary::Column::Longvarbinary);
|
|
col_name.setLength(400);
|
|
col_name.setNullable(false);
|
|
col_name.setPrimaryKey(true);
|
|
if (!define_table_add_column(new_table, col_name)) return false;
|
|
}
|
|
|
|
{
|
|
// `seq` smallint(6) unsigned NOT NULL
|
|
NdbDictionary::Column col_seq(COL_SEQUENCE);
|
|
col_seq.setType(NdbDictionary::Column::Smallunsigned);
|
|
col_seq.setNullable(false);
|
|
col_seq.setPrimaryKey(true);
|
|
if (!define_table_add_column(new_table, col_seq)) return false;
|
|
}
|
|
|
|
{
|
|
// `note` int unsigned
|
|
NdbDictionary::Column col_note(COL_NOTE);
|
|
col_note.setType(NdbDictionary::Column::Unsigned);
|
|
col_note.setNullable(true);
|
|
if (!define_table_add_column(new_table, col_note)) return false;
|
|
}
|
|
|
|
{
|
|
// `sql_ddl_text` varbinary(12000) DEFAULT NULL
|
|
NdbDictionary::Column col_text(COL_TEXT);
|
|
col_text.setType(NdbDictionary::Column::Longvarbinary);
|
|
col_text.setLength(12000);
|
|
if (!define_table_add_column(new_table, col_text)) return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Ndb_sql_metadata_table::define_indexes(const NdbDictionary::Table &table,
|
|
unsigned) const {
|
|
return create_primary_ordered_index(table);
|
|
}
|
|
|
|
bool Ndb_sql_metadata_table::check_schema() const { return true; }
|
|
|
|
bool Ndb_sql_metadata_table::need_upgrade() const { return false; }
|
|
|
|
std::string Ndb_sql_metadata_table::define_table_dd() const {
|
|
std::stringstream ss;
|
|
ss << "CREATE TABLE " << db_name() << "." << table_name() << "(\n";
|
|
ss << "type smallint not null,"
|
|
"name varbinary(400) NOT NULL,"
|
|
"seq smallint unsigned not null,"
|
|
"note int unsigned,"
|
|
"sql_ddl_text varbinary(12000),"
|
|
"PRIMARY KEY (type,name,seq)"
|
|
<< ") ENGINE=ndbcluster";
|
|
return ss.str();
|
|
}
|
|
|
|
Ndb_sql_metadata_table::~Ndb_sql_metadata_table() {}
|
|
|
|
// Ndb_sql_metadata_api
|
|
|
|
/* Map the table.
|
|
Determine record sizes for a key record, a partial row record,
|
|
and a full row record. Create NdbRecords for the hash primary key,
|
|
ordered index, partial row, and full row.
|
|
After setup_records() is called, the API's getters and setters become
|
|
usable.
|
|
Returns true on success.
|
|
*/
|
|
void Ndb_sql_metadata_api::setup(NdbDictionary::Dictionary *dict,
|
|
const NdbDictionary::Table *table) {
|
|
m_record_layout.addColumn(table->getColumn("type"));
|
|
m_record_layout.addColumn(table->getColumn("name"));
|
|
m_record_layout.addColumn(table->getColumn("seq"));
|
|
m_key_record_size = m_record_layout.record_size;
|
|
|
|
m_record_layout.addColumn(table->getColumn("note"));
|
|
m_note_record_size = m_record_layout.record_size;
|
|
|
|
m_record_layout.addColumn(table->getColumn("sql_ddl_text"));
|
|
m_full_record_size = m_record_layout.record_size;
|
|
|
|
m_row_rec = dict->createRecord(table, m_record_layout.record_specs,
|
|
5, // ALL FIVE COLUMNS
|
|
sizeof(m_record_layout.record_specs[0]));
|
|
m_note_rec = dict->createRecord(table, m_record_layout.record_specs,
|
|
4, // FIRST FOUR COLUMNS
|
|
sizeof(m_record_layout.record_specs[0]));
|
|
m_hash_key_rec = dict->createRecord(table, m_record_layout.record_specs,
|
|
3, // FIRST THREE COLUMNS
|
|
sizeof(m_record_layout.record_specs[0]));
|
|
|
|
const NdbDictionary::Index *primary = dict->getIndexGlobal("PRIMARY", *table);
|
|
/* There is a test case where primary == nullptr because NDB has been
|
|
configured with __at_restart_skip_indexes, and presumably there are also
|
|
real-world data corruption situations where the table is available but
|
|
the index is not. Do not handle those conditions here. They are detected
|
|
later, when isInitialized() returns false.
|
|
*/
|
|
if (primary) {
|
|
m_ordered_index_rec =
|
|
dict->createRecord(primary, table, m_record_layout.record_specs,
|
|
3, // FIRST THREE COLUMNS
|
|
sizeof(m_record_layout.record_specs[0]));
|
|
dict->removeIndexGlobal(*primary, false);
|
|
}
|
|
}
|
|
|
|
void Ndb_sql_metadata_api::clear(NdbDictionary::Dictionary *dict) {
|
|
if (m_full_record_size) {
|
|
dict->releaseRecord(m_row_rec);
|
|
m_row_rec = nullptr;
|
|
dict->releaseRecord(m_note_rec);
|
|
m_note_rec = nullptr;
|
|
dict->releaseRecord(m_hash_key_rec);
|
|
m_hash_key_rec = nullptr;
|
|
m_key_record_size = 0;
|
|
m_note_record_size = 0;
|
|
m_full_record_size = 0;
|
|
}
|
|
|
|
if (m_ordered_index_rec) {
|
|
dict->releaseRecord(m_ordered_index_rec);
|
|
m_ordered_index_rec = nullptr;
|
|
}
|
|
|
|
m_record_layout.clear();
|
|
}
|