2 #include "tmdatabase.h"
10 #include <QDataStream>
14 // DatabaseBase ---------------------------------------------------------------
16 bool TM::DatabaseBase::open(char const *message)
18 assert(!m_database_name.isEmpty());
19 m_database = QSqlDatabase::addDatabase("QSQLITE", m_database_name);
20 m_database.setDatabaseName(m_database_name);
21 bool ret = m_database.open();
30 QSqlQuery TM::DatabaseBase::prepare(char const *sql, char const *message)
32 QSqlQuery result(m_database);
33 bool ret = result.prepare(sql);
36 error(message, &result);
42 bool TM::DatabaseBase::exec(QSqlQuery &query, char const *message)
44 bool ret = query.exec();
47 error(message, &query);
53 QSqlQuery TM::DatabaseBase::exec(char const *sql, char const *message)
55 QSqlQuery result = m_database.exec(sql);
56 if(result.lastError().isValid())
58 error(message, &result);
64 void TM::DatabaseBase::error(QString message, QSqlQuery *query)
67 if(query) s = query->lastError().text();
68 else s = m_database.lastError().text();
70 qCritical() << message << s;
73 // SiteDatabase ---------------------------------------------------------------
75 TM::SiteDatabase::SiteDatabase(Settings *settings)
78 m_cache_limit = settings->value(
79 "SiteDatabase/cache-limit", QVariant::fromValue(1024)).toInt();
82 m_database_name = settings->value(TMDATABASE_ROOT_PATH_KEY).toString() + "/site.db";
86 exec("CREATE TABLE IF NOT EXISTS sites("
87 "site_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,"
88 "host_name TEXT UNIQUE);", Q_FUNC_INFO);
90 exec("CREATE INDEX IF NOT EXISTS host_name_index ON sites(host_name);", Q_FUNC_INFO);
93 m_find_site_id = prepare("SELECT site_id FROM sites WHERE host_name=?;", Q_FUNC_INFO);
94 m_insert_site = prepare("INSERT INTO sites(host_name) VALUES(?);", Q_FUNC_INFO);
97 TM::SiteDatabase::~SiteDatabase()
99 if(m_database.isOpen()) m_database.close();
103 * \brief 引数として与えられたドメイン名に対して一意な番号を返します。
105 quint32 TM::SiteDatabase::site_id(QString domain)
107 // キャッシュが大きくなりすぎた場合、消去する。
108 if(m_cache_limit < m_cache.size()) m_cache.clear();
110 QMap<QString, quint32>::const_iterator it = m_cache.find(domain);
111 if(it != m_cache.end()) return *it; // キャッシュに存在する場合、ここで終わり。
113 // キャッシュにない場合、データベースを検索。
114 quint32 result = find_site_id(domain);
115 // データベースにない場合、データベースに登録。
119 result = find_site_id(domain);
123 m_cache.insert(domain, result);
129 * \brief 引数として与えられたドメイン名に対して一意な番号を返します。
133 quint32 TM::SiteDatabase::find_site_id(QString host_name)
135 m_find_site_id.bindValue(0, host_name);
136 exec(m_find_site_id, Q_FUNC_INFO);
137 if(m_find_site_id.next()) return m_find_site_id.value(0).toUInt();
142 void TM::SiteDatabase::insert_site(QString host_name)
144 m_insert_site.bindValue(0, host_name);
145 exec(m_insert_site, Q_FUNC_INFO);
148 TM::SiteDatabase::pointer TM::SiteDatabase::create(Settings *settings)
150 return pointer(new SiteDatabase(settings));
153 // WordDatabase ---------------------------------------------------------------
155 TM::WordDatabase::WordDatabase(Settings *settings, QString name)
158 m_cache_limit = settings->value(
159 "WordDatabase/cache-limit", QVariant::fromValue(100 * 1024)).toInt();
162 m_database_name = settings->value(
163 TMDATABASE_ROOT_PATH_KEY).toString() + "/word-" + name.toLower() + ".db";
167 exec("CREATE TABLE IF NOT EXISTS words("
168 "word_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,"
169 "word TEXT UNIQUE);", Q_FUNC_INFO);
171 exec("CREATE INDEX IF NOT EXISTS word_index ON words(word);", Q_FUNC_INFO);
174 m_find_word_id = prepare(
175 "SELECT word_id FROM words WHERE word=?;", Q_FUNC_INFO);
177 m_insert_word = prepare("INSERT INTO words(word) VALUES(?);", Q_FUNC_INFO);
180 TM::WordDatabase::~WordDatabase()
182 if(m_database.isOpen()) m_database.close();
185 int TM::WordDatabase::word_id(QString word)
187 // キャッシュが大きくなりすぎた場合、消去する。
188 if(m_cache_limit < m_cache.size()) m_cache.clear();
190 QMap<QString, int>::const_iterator it = m_cache.find(word);
191 if(it != m_cache.end()) return *it; // キャッシュに存在する場合、ここで終わり。
193 // キャッシュにない場合、データベースを検索。
194 int result = find_word_id(word);
195 // データベースにない場合、データベースに登録。
199 result = find_word_id(word);
203 m_cache.insert(word, result);
208 int TM::WordDatabase::find_word_id(QString word)
210 m_find_word_id.bindValue(0, word);
211 exec(m_find_word_id, Q_FUNC_INFO);
212 if(m_find_word_id.next()) return m_find_word_id.value(0).toInt();
217 void TM::WordDatabase::insert_word(QString word)
219 m_insert_word.bindValue(0, word);
220 exec(m_insert_word, Q_FUNC_INFO);
223 TM::WordDatabase::pointer TM::WordDatabase::create(Settings *settings, QString name)
225 return pointer(new WordDatabase(settings, name));
228 // SentenceDatabase -----------------------------------------------------------
230 TM::SentenceDatabase::SentenceDatabase(Settings *settings, int site_id, QString name)
234 settings->value(TMDATABASE_ROOT_PATH_KEY).toString()
235 + "/sentence-" + QString::number(site_id) + "-" + name.toLower() + ".db";
239 exec("CREATE TABLE IF NOT EXISTS sentences("
240 "sentence_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,"
245 "previous_crc INTEGER,"
251 exec("CREATE INDEX IF NOT EXISTS source_id_index ON sentences(source_id);", Q_FUNC_INFO);
252 exec("CREATE INDEX IF NOT EXISTS sentence_index ON sentences(sentence);", Q_FUNC_INFO);
255 m_find_sentence_id = prepare(
256 "SELECT sentence_id FROM sentences WHERE sentence=?;", Q_FUNC_INFO);
258 m_find_sentence_id_with_context = prepare(
259 "SELECT sentence_id FROM sentences "
261 "AND previous_crc=? "
262 "AND next_crc=?;", Q_FUNC_INFO);
264 m_find_sentence_by_crc = prepare("SELECT * FROM sentences WHERE crc=?;", Q_FUNC_INFO);
265 m_find_sentence_by_source_id = prepare("SELECT * FROM sentences WHERE source_id=?;", Q_FUNC_INFO);
266 m_insert_sentence = prepare(
267 "INSERT OR REPLACE INTO sentences("
268 "source_id, sentence, json, crc, previous_crc, next_crc, user_id, time) "
269 "VALUES(?, ?, ?, ?, ?, ?, ?, ?);", Q_FUNC_INFO);
270 m_update_sentence = prepare(
271 "UPDATE sentences SET "
280 "WHERE sentence_id=?;", Q_FUNC_INFO);
282 m_delete_sentence = prepare("DELETE FROM sentences WHERE source_id=?;");
285 TM::SentenceDatabase::~SentenceDatabase()
287 if(m_database.isOpen()) m_database.close();
290 quint32 TM::SentenceDatabase::find_sentence_id(QString sentence)
292 m_find_sentence_id.bindValue(0, sentence);
293 exec(m_find_sentence_id, Q_FUNC_INFO);
295 if(!m_find_sentence_id.next()) return 0;
296 return m_find_sentence_id.value(0).toUInt();
299 quint32 TM::SentenceDatabase::find_sentence_id_with_context(
300 QString sentence, quint32 previous_crc, quint32 next_crc)
302 m_find_sentence_id_with_context.bindValue(0, sentence);
303 m_find_sentence_id_with_context.bindValue(1, previous_crc);
304 m_find_sentence_id_with_context.bindValue(2, next_crc);
305 exec(m_find_sentence_id_with_context, Q_FUNC_INFO);
307 if(!m_find_sentence_id_with_context.next()) return 0;
308 return m_find_sentence_id_with_context.value(0).toUInt();
311 TM::sentence_data_type::pointer
312 TM::SentenceDatabase::find_sentence_by_source_id(int source_id)
316 sentence_data_type::pointer result;
318 m_find_sentence_by_source_id.bindValue(0, source_id);
319 exec(m_find_sentence_by_source_id, Q_FUNC_INFO);
321 if(!m_find_sentence_by_source_id.next()) return result;
323 return stuff_value(&m_find_sentence_by_source_id);
326 void TM::SentenceDatabase::insert(sentence_data_type::pointer sentence_data)
328 assert(m_database.isValid());
329 assert(m_database.isOpen());
331 m_insert_sentence.bindValue(0, sentence_data->source_id);
332 m_insert_sentence.bindValue(1, sentence_data->sentence);
333 m_insert_sentence.bindValue(2, sentence_data->json);
334 m_insert_sentence.bindValue(3, sentence_data->crc);
335 m_insert_sentence.bindValue(4, sentence_data->previous_crc);
336 m_insert_sentence.bindValue(5, sentence_data->next_crc);
337 m_insert_sentence.bindValue(6, sentence_data->user_id);
338 m_insert_sentence.bindValue(7, sentence_data->time);
340 exec(m_insert_sentence, Q_FUNC_INFO);
343 void TM::SentenceDatabase::update(sentence_data_type::pointer sentence_data)
345 assert(m_database.isValid());
346 assert(m_database.isOpen());
348 m_update_sentence.bindValue(0, sentence_data->source_id);
349 m_update_sentence.bindValue(1, sentence_data->sentence);
350 m_update_sentence.bindValue(2, sentence_data->json);
351 m_update_sentence.bindValue(3, sentence_data->crc);
352 m_update_sentence.bindValue(4, sentence_data->previous_crc);
353 m_update_sentence.bindValue(5, sentence_data->next_crc);
354 m_update_sentence.bindValue(6, sentence_data->user_id);
355 m_update_sentence.bindValue(7, sentence_data->time);
356 m_update_sentence.bindValue(8, sentence_data->sentence_id);
358 exec(m_update_sentence, Q_FUNC_INFO);
361 void TM::SentenceDatabase::remove(quint32 source_id)
364 assert(m_database.isValid());
365 assert(m_database.isOpen());
367 m_delete_sentence.bindValue(0, source_id);
369 exec(m_delete_sentence, Q_FUNC_INFO);
372 TM::sentence_data_type::pointer
373 TM::SentenceDatabase::stuff_value(QSqlQuery *query)
375 assert(query->isValid());
376 sentence_data_type::pointer result = sentence_data_type::create();
378 result->sentence_id = query->value(0).toUInt();
379 result->source_id = query->value(1).toUInt();
380 result->sentence = query->value(2).toString();
381 result->json = query->value(3).toByteArray();
382 result->crc = query->value(4).toUInt();
383 result->previous_crc = query->value(5).toUInt();
384 result->next_crc = query->value(6).toUInt();
385 result->user_id = query->value(7).toUInt();
386 result->time = query->value(8).toUInt();
391 TM::SentenceDatabase::pointer TM::SentenceDatabase::create(
392 Settings *settings, int site_id, QString name)
394 return pointer(new SentenceDatabase(settings, site_id, name));
398 // IndexDatabase --------------------------------------------------------------
400 TM::index_data_type::index_data_type()
403 , is_stop_word(false)
407 TM::index_data_type::pointer TM::index_data_type::create()
409 return pointer(new index_data_type());
412 TM::IndexDatabase::IndexDatabase(Settings *settings, QString dbname)
414 m_index_limit = 20 * 1024;
417 settings->value(TMDATABASE_ROOT_PATH_KEY).toString()
422 exec("CREATE TABLE IF NOT EXISTS indexes("
423 "index_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,"
424 "word_id INTEGER UNIQUE NOT NULL,"
426 "is_stop_word BOOLEAN);", Q_FUNC_INFO);
428 exec("CREATE INDEX IF NOT EXISTS word_id_index ON indexes(word_id);", Q_FUNC_INFO);
431 m_find_index = prepare(
432 "SELECT * FROM indexes WHERE word_id=?;", Q_FUNC_INFO);
433 m_insert_index = prepare(
434 "INSERT INTO indexes(word_id, sentence_ids, is_stop_word) "
435 "VALUES(?, ?, ?);", Q_FUNC_INFO);
436 m_update_index = prepare(
437 "UPDATE indexes SET "
441 "WHERE index_id=?;", Q_FUNC_INFO);
444 TM::index_data_type::pointer TM::IndexDatabase::find_index(quint32 word_id)
448 m_find_index.bindValue(0, word_id);
449 exec(m_find_index, Q_FUNC_INFO);
451 index_data_type::pointer result;
453 if(m_find_index.next())
455 result = index_data_type::create();
456 result->index_id = m_find_index.value(0).toUInt();
457 result->word_id = m_find_index.value(1).toUInt();
458 QByteArray sentence_ids = m_find_index.value(2).toByteArray();
459 QDataStream ds(sentence_ids);
464 result->sentence_ids.insert(sentence_id);
466 result->is_stop_word = m_find_index.value(3).toBool();
472 void TM::IndexDatabase::insert_index(WordDatabase::pointer word_database,
473 sentence_data_type::pointer source, quint32 target_id)
475 QString const &string = source->sentence;
476 for(QPair<int,int> const & range: source->words)
478 QString word = string.mid(
479 range.first, range.second - range.first + 1);
480 if(word.size() <= 2) continue;
483 word_id = word_database->word_id(word);
486 index_data_type::pointer index_data = find_index(word_id);
489 index_data->sentence_ids.insert(target_id);
490 // レコードが大きくなりすぎた場合、ストップワードとする。
491 if(m_index_limit < index_data->sentence_ids.size())
493 index_data->sentence_ids.clear();
494 index_data->is_stop_word = true;
496 update_index(index_data);
500 index_data = index_data_type::create();
501 index_data->word_id = word_id;
502 index_data->sentence_ids.insert(target_id);
503 index_data->is_stop_word = false;
504 insert_index(index_data);
509 void TM::IndexDatabase::insert_index(index_data_type::pointer index_data)
513 QByteArray sentence_ids;
514 QDataStream ds(&sentence_ids, QIODevice::WriteOnly);
515 for(quint32 sentence_id : index_data->sentence_ids) ds << sentence_id;
517 m_insert_index.bindValue(0, index_data->word_id);
518 m_insert_index.bindValue(1, sentence_ids);
519 m_insert_index.bindValue(2, index_data->is_stop_word);
521 exec(m_insert_index, Q_FUNC_INFO);
524 void TM::IndexDatabase::update_index(index_data_type::pointer index_data)
528 QByteArray sentence_ids;
529 QDataStream ds(&sentence_ids, QIODevice::WriteOnly);
530 for(quint32 sentence_id : index_data->sentence_ids) ds << sentence_id;
532 m_update_index.bindValue(0, index_data->word_id);
533 m_update_index.bindValue(1, sentence_ids);
534 m_update_index.bindValue(2, index_data->is_stop_word);
535 m_update_index.bindValue(3, index_data->index_id);
537 exec(m_update_index, Q_FUNC_INFO);
540 TM::IndexDatabase::pointer TM::IndexDatabase::create(Settings *settings, QString dbname)
542 return pointer(new IndexDatabase(settings, dbname));
545 // Database -------------------------------------------------------------------
547 TM::Database::Database(Settings *settings, Service *service)
549 , m_settings(settings)
552 qRegisterMetaType<sentence_data_type::pointer>();
555 TM::Database::~Database()
560 * \brief データベースのセットアップを行います。
562 * データベース接続を開いたスレッド内でしか使えない制限のため、スレッドの
565 void TM::Database::setup()
568 m_sentence_cache_limit = m_settings->value(
569 "Database/sentence-cache-limit", QVariant::fromValue(20)).toInt();
571 m_index_cache_limit = m_settings->value(
572 "Database/index-cache-limit", QVariant::fromValue(20)).toInt();
574 // データベース用のフォルダが無ければ作成する。
575 if(!m_settings->contains(TMDATABASE_ROOT_PATH_KEY)) qFatal("An error occured while find settings in Database().");
576 QString path = m_settings->value(TMDATABASE_ROOT_PATH_KEY).toString();
578 if(!dir.exists()) dir.mkpath(path);
581 m_site_database = SiteDatabase::create(m_settings);
585 * \brief 引数で指定された言語の単語データベースを開きます。
589 * 言語プラグインを読み込んだ時に呼び出すことを想定しています。
590 * 言語プラグインは、TM::Serviceで読み込まれます。
592 void TM::Database::open_word_database(int code, QString name)
594 m_language_map.insert(code, name);
595 m_word_databases.insert(code, WordDatabase::create(m_settings, name));
599 * \brief 引数として与えられたサイトに対応するIDを返します。
601 quint32 TM::Database::find_site_id(QString host_name)
603 quint32 result = m_site_database->site_id(host_name);
608 * \brief センテンスを検索して結果をサービスに返します。
615 void TM::Database::find_sentence(QString site_name, int scode, int tcode,
616 sentence_data_type::pointer source, int token)
618 sentence_data_type::pointer result;
620 quint32 site_id = find_site_id(site_name);
623 SentenceDatabase::pointer sdb = find_sentence_database(site_id, scode);
625 SentenceDatabase::pointer tdb = find_sentence_database(site_id, tcode);
629 quint32 source_id = sdb->find_sentence_id_with_context(
630 source->sentence, source->previous_crc, source->next_crc);
633 result = tdb->find_sentence_by_source_id(source_id);
634 if(result) result->quality = 101;
636 // 文脈込で発見できない場合、文脈無視で検索を試みる。
639 source_id = sdb->find_sentence_id(source->sentence);
640 if(source_id) result = tdb->find_sentence_by_source_id(source_id);
643 result->quality = 100;
644 result->source_id = source_id;
648 if(result) // 検索結果を返す。
650 QMetaObject::invokeMethod(
651 m_service, "sentence_found",
652 Qt::QueuedConnection,
653 Q_ARG(sentence_data_type::pointer, result),
654 Q_ARG(qint32, token));
656 else // 検索できなかったことを通知し、サービスはサーバに問い合わせる。
658 QMetaObject::invokeMethod(
659 m_service, "sentence_not_found",
660 Qt::QueuedConnection,
661 Q_ARG(QString, site_name),
662 Q_ARG(qint32, scode),
663 Q_ARG(qint32, tcode),
664 Q_ARG(QString, source->sentence),
665 Q_ARG(qint32, token));
669 void TM::Database::insert_sentence(
670 QString site_name, quint32 scode, quint32 tcode,
671 sentence_data_type::pointer source,
672 sentence_data_type::pointer target, qint32 token)
675 assert(!site_name.isEmpty());
678 assert(source->source_id == 0);
679 assert(source->json.isEmpty());
680 assert(target->previous_crc == 0);
681 assert(target->next_crc == 0);
683 quint32 site_id = find_site_id(site_name);
688 SentenceDatabase::pointer sdb = find_sentence_database(site_id, scode);
692 // 現在、前後の文脈が一致する場合のみ、IDを検索できたこととしている。
693 // 文脈が一致しない場合、新たにIDを付与する。
694 quint32 source_id = source->sentence_id;
695 if(!source_id) source_id = sdb->find_sentence_id_with_context(
696 source->sentence, source->previous_crc, source->next_crc);
699 source->time = QDateTime::currentDateTime().toMSecsSinceEpoch();
701 source_id = sdb->find_sentence_id_with_context(
702 source->sentence, source->previous_crc, source->next_crc);
707 SentenceDatabase::pointer tdb = find_sentence_database(site_id, tcode);
710 target->source_id = source_id;
711 target->time = QDateTime::currentDateTime().toMSecsSinceEpoch();
714 // 現在、原文IDに対して登録できる訳文は一つのみ。
715 sentence_data_type::pointer target_sentence =
716 tdb->find_sentence_by_source_id(source_id);
717 if(target_sentence) // 訳文があった場合、上書きして更新する。
719 target->sentence_id = target_sentence->sentence_id;
724 tdb->insert(target); // 訳文が無かった場合、新規挿入する。
725 // 挿入後、検索することで訳文IDを取得する。
726 target_sentence = tdb->find_sentence_by_source_id(source_id);
728 assert(target_sentence);
729 quint32 target_id = target_sentence->sentence_id;
730 assert(target_id); // 挿入あるいは更新しているので、IDがある。
733 IndexDatabase::pointer index_database =
734 find_index_database(site_id, scode, tcode);
735 assert(index_database);
736 WordDatabase::pointer word_database = find_word_database(scode);
737 assert(word_database);
738 index_database->insert_index(word_database, source, target_id);
741 QMetaObject::invokeMethod(
742 m_service, "sentence_inserted",
743 Qt::QueuedConnection,
744 Q_ARG(quint32, source_id),
745 Q_ARG(quint32, target_id),
746 Q_ARG(qint32, token));
750 * \brief データベースから引数として与えられた原文に対応する訳文を削除します。
756 void TM::Database::remove_sentence(QString site_name, quint32 scode, quint32 tcode,
757 sentence_data_type::pointer source)
759 qDebug() << "TM::Database::remove_sentence()";
762 assert(!site_name.isEmpty());
765 assert(source->source_id == 0);
766 assert(source->json.isEmpty());
768 quint32 site_id = find_site_id(site_name);
773 //SentenceDatabase::pointer sdb = find_sentence_database(site_id, scode);
776 // 原文IDの検索、無い場合、訳文を引き出せないので諦めるしかない。
777 quint32 source_id = source->sentence_id;
778 //if(!source_id) source_id = sdb->find_sentence_ids(source->sentence);
780 if(!source_id) qDebug() << "Database::remove_sentence(): Do not find source_id";
781 if(!source_id) return;
784 SentenceDatabase::pointer tdb = find_sentence_database(site_id, tcode);
787 tdb->remove(source_id);
790 QString TM::Database::find_language_name(int code) const
793 QMap<int, QString>::const_iterator it = m_language_map.find(code);
794 if(it != m_language_map.end()) result = it.value();
799 * \brief 引数として与えられた単語に対して一意な番号を返します。
803 int TM::Database::find_word_id(int code, QString word)
805 QMap<int, WordDatabase::pointer>::iterator it = m_word_databases.find(code);
806 assert(it != m_word_databases.end());
807 int result = (*it)->word_id(word);
812 TM::WordDatabase::pointer TM::Database::find_word_database(int code)
814 QMap<int, WordDatabase::pointer>::iterator it = m_word_databases.find(code);
815 assert(it != m_word_databases.end());
820 * \brief 原文の単語IDと訳文の文IDとの照応を保持するデータベースを返します。
821 * \param site_id サイトのID。
822 * \param scode 原文の言語コード。
823 * \param tcode 訳文の言語コード。
824 * \return データベースへのポインタ。
826 * このメンバは接続をキャッシュしています。
828 TM::IndexDatabase::pointer TM::Database::find_index_database(
829 quint32 site_id, int scode, int tcode)
835 // キャッシュが大きすぎる場合、消去する。
836 if(m_index_cache_limit < m_index_databases.size()) m_index_databases.clear();
839 QString dbname, sname, tname, site_name;
840 sname = find_language_name(scode).toLower();
841 assert(!sname.isEmpty());
844 tname = find_language_name(tcode).toLower();
845 assert(!tname.isEmpty());
849 site_name = QString::number(site_id);
850 assert(!site_name.isEmpty());
852 if(!site_name.isEmpty())
854 dbname = QString("index-");
855 dbname += site_name + "-" + sname + "-" + tname + ".db";
858 IndexDatabase::pointer result;
860 if(!dbname.isEmpty())
862 QMap<QString, IndexDatabase::pointer>::iterator it =
863 m_index_databases.find(dbname);
864 if(it == m_index_databases.end())
865 it = m_index_databases.insert(dbname, IndexDatabase::create(m_settings, dbname));
866 assert(it != m_index_databases.end());
868 if(it != m_index_databases.end()) result = it.value();
875 * \brief 引数として与えられたサイトと言語用のセンテンス・データベースを返します。
876 * \param site_id サイトを識別する番号。
879 * センテンス・データベースは、設定によって決められた数まで接続をキャッシュします。
880 * このメンバは、キャッシュ内にデータベース接続があればそれを返し、無ければ接続します。
882 TM::SentenceDatabase::pointer
883 TM::Database::find_sentence_database(quint32 site_id, int code)
885 typedef QMap<QPair<quint32, int>, SentenceDatabase::pointer>::iterator iterator;
889 // キャッシュが大きすぎる場合、消去する。
890 if(m_sentence_cache_limit < m_sentence_databases.size()) m_sentence_databases.clear();
892 // キャッシュにデータベースが無い場合、作成する。
893 QPair<quint32, int> key(site_id, code);
894 iterator it = m_sentence_databases.find(key);
895 if(it == m_sentence_databases.end())
897 QString name = find_language_name(code);
898 assert(!name.isEmpty());
899 it = m_sentence_databases.insert(
900 key, SentenceDatabase::create(m_settings, site_id, name));