00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <config.h>
00022
00023 #include <assert.h>
00024 #include <boost/lexical_cast.hpp>
00025 #include <drizzled/identifier.h>
00026 #include <drizzled/internal/my_sys.h>
00027
00028 #include <drizzled/error.h>
00029 #include <drizzled/errmsg_print.h>
00030 #include <drizzled/gettext.h>
00031
00032 #include <drizzled/table.h>
00033
00034 #include <drizzled/util/string.h>
00035 #include <drizzled/util/tablename_to_filename.h>
00036
00037 #include <algorithm>
00038 #include <sstream>
00039 #include <cstdio>
00040
00041 #include <boost/thread.hpp>
00042
00043 using namespace std;
00044
00045 namespace drizzled {
00046
00047 extern std::string drizzle_tmpdir;
00048 extern pid_t current_pid;
00049
00050 namespace identifier {
00051
00052 static const char hexchars[]= "0123456789abcdef";
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 uint32_t Table::filename_to_tablename(const char *from, char *to, uint32_t to_length)
00067 {
00068 uint32_t length= 0;
00069
00070 if (!memcmp(from, TMP_FILE_PREFIX, TMP_FILE_PREFIX_LENGTH))
00071 {
00072
00073 length= strlen(strncpy(to, from, to_length));
00074 }
00075 else
00076 {
00077 for (; *from && length < to_length; length++, from++)
00078 {
00079 if (*from != '@')
00080 {
00081 to[length]= *from;
00082 continue;
00083 }
00084
00085 from++;
00086 to[length]= 0;
00087
00088 for (int x=1; x >= 0; x--)
00089 {
00090 if (*from >= '0' && *from <= '9')
00091 to[length] += ((*from++ - '0') << (4 * x));
00092 else if (*from >= 'a' && *from <= 'f')
00093 to[length] += ((*from++ - 'a' + 10) << (4 * x));
00094 }
00095
00096 from--;
00097 }
00098 }
00099
00100 return length;
00101 }
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121 #ifdef _GLIBCXX_HAVE_TLS
00122 __thread uint32_t counter= 0;
00123
00124 static uint32_t get_counter()
00125 {
00126 return ++counter;
00127 }
00128
00129 #else
00130 boost::mutex counter_mutex;
00131 static uint32_t counter= 1;
00132
00133 static uint32_t get_counter()
00134 {
00135 boost::mutex::scoped_lock lock(counter_mutex);
00136 return ++counter;
00137 }
00138
00139 #endif
00140
00141 std::string Table::build_tmptable_filename()
00142 {
00143 ostringstream os;
00144 os << "/" << TMP_FILE_PREFIX << current_pid << pthread_self() << "-" << get_counter();
00145 return drizzle_tmpdir + boost::to_lower_copy(os.str());
00146 }
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180 std::string Table::build_table_filename(const std::string &in_db, const std::string &in_table_name, bool is_tmp)
00181 {
00182 string in_path= util::tablename_to_filename(in_db) + FN_LIBCHAR;
00183 return in_path + (is_tmp ? in_table_name : util::tablename_to_filename(in_table_name));
00184 }
00185
00186 Table::Table(const drizzled::Table &table) :
00187 identifier::Schema(str_ref(table.getShare()->getSchemaName())),
00188 type(table.getShare()->getTableType()),
00189 table_name(table.getShare()->getTableName())
00190 {
00191 if (type == message::Table::TEMPORARY)
00192 path= table.getShare()->getPath();
00193
00194 init();
00195 }
00196
00197 void Table::init()
00198 {
00199 switch (type)
00200 {
00201 case message::Table::FUNCTION:
00202 case message::Table::STANDARD:
00203 assert(path.empty());
00204 path= build_table_filename(getSchemaName(), table_name, false);
00205 break;
00206 case message::Table::INTERNAL:
00207 assert(path.empty());
00208 path= build_table_filename(getSchemaName(), table_name, true);
00209 break;
00210 case message::Table::TEMPORARY:
00211 if (path.empty())
00212 path= build_tmptable_filename();
00213 break;
00214 }
00215
00216 if (type == message::Table::TEMPORARY)
00217 {
00218 size_t pos= path.find("tmp/#sql");
00219 if (pos != std::string::npos)
00220 key_path= path.substr(pos);
00221 }
00222
00223 hash_value= util::insensitive_hash()(path);
00224 key.set(getKeySize(), getCatalogName(), getSchemaName(), boost::to_lower_copy(std::string(getTableName())));
00225 }
00226
00227
00228 const std::string &Table::getPath() const
00229 {
00230 return path;
00231 }
00232
00233 const std::string &Table::getKeyPath() const
00234 {
00235 return key_path.empty() ? path : key_path;
00236 }
00237
00238 std::string Table::getSQLPath() const
00239 {
00240 switch (type)
00241 {
00242 case message::Table::FUNCTION:
00243 case message::Table::STANDARD:
00244 return getSchemaName() + "." + table_name;
00245 case message::Table::INTERNAL:
00246 return "temporary." + table_name;
00247 case message::Table::TEMPORARY:
00248 return getSchemaName() + ".#" + table_name;
00249 }
00250 assert(false);
00251 return "<no table>";
00252 }
00253
00254 bool Table::isValid() const
00255 {
00256 if (not identifier::Schema::isValid())
00257 return false;
00258
00259 bool error= false;
00260 if (table_name.empty()
00261 || table_name.size() > NAME_LEN
00262 || table_name[table_name.length() - 1] == ' '
00263 || table_name[0] == '.')
00264 {
00265 error= true;
00266 }
00267 else
00268 {
00269 const charset_info_st& cs= my_charset_utf8mb4_general_ci;
00270 int well_formed_error;
00271 uint32_t res= cs.cset->well_formed_len(cs, table_name, NAME_CHAR_LEN, &well_formed_error);
00272 if (well_formed_error or table_name.length() != res)
00273 error= true;
00274 }
00275 if (not error)
00276 return true;
00277 my_error(ER_WRONG_TABLE_NAME, MYF(0), getSQLPath().c_str());
00278 return false;
00279 }
00280
00281 void Table::copyToTableMessage(message::Table &message) const
00282 {
00283 message.set_name(table_name);
00284 message.set_schema(getSchemaName());
00285 }
00286
00287 void Table::Key::set(size_t resize_arg, const std::string &a, const std::string &b, const std::string &c)
00288 {
00289 key_buffer.resize(resize_arg);
00290
00291 std::copy(a.begin(), a.end(), key_buffer.begin());
00292 std::copy(b.begin(), b.end(), key_buffer.begin() + a.length() + 1);
00293 std::copy(c.begin(), c.end(),
00294 key_buffer.begin() + a.length() + 1 + b.length() + 1);
00295
00296 util::sensitive_hash hasher;
00297 hash_value= hasher(key_buffer);
00298 }
00299
00300 std::size_t hash_value(Table const& b)
00301 {
00302 return b.getHashValue();
00303 }
00304
00305 std::size_t hash_value(Table::Key const& b)
00306 {
00307 return b.getHashValue();
00308 }
00309
00310 std::ostream& operator<<(std::ostream& output, const Table& identifier)
00311 {
00312 return output << "Table:(" << identifier.getSchemaName() << ", " << identifier.getTableName() << ", " << message::type(identifier.getType()) << ", " << identifier.getPath() << ", " << identifier.getHashValue() << ")";
00313 }
00314
00315 }
00316 }