From e1fa4a088dd95caef22045f905a9d5d22b71bef0 Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Tue, 24 Jan 2017 21:50:39 -0500 Subject: Whitespace changes --- generator/database.cpp | 14 +-- generator/database.h | 2 +- generator/field.h | 12 +- generator/frame.h | 38 +++---- generator/generator.h | 108 +++++++++--------- generator/group.cpp | 46 ++++---- generator/group.h | 52 ++++----- generator/main.cpp | 2 +- generator/notion.cpp | 14 +-- generator/notion.h | 8 +- generator/part.cpp | 134 +++++++++++------------ generator/part.h | 74 ++++++------- generator/progress.h | 16 +-- generator/word.cpp | 8 +- generator/word.h | 10 +- lib/binding.h | 14 +-- lib/database.cpp | 14 +-- lib/database.h | 18 +-- lib/enums.h | 10 +- lib/field.cpp | 34 +++--- lib/lemma.cpp | 34 +++--- lib/lemma.h | 78 ++++++------- lib/pronunciation.cpp | 34 +++--- lib/query.h | 48 ++++---- lib/role.h | 24 ++-- lib/selrestr.cpp | 102 ++++++++--------- lib/selrestr.h | 56 +++++----- lib/statement.cpp | 290 ++++++++++++++++++++++++------------------------- lib/statement.h | 130 +++++++++++----------- lib/util.h | 22 ++-- lib/word.cpp | 56 +++++----- lib/word.h | 100 ++++++++--------- 32 files changed, 801 insertions(+), 801 deletions(-) diff --git a/generator/database.cpp b/generator/database.cpp index c7e4cfa..188fa2a 100644 --- a/generator/database.cpp +++ b/generator/database.cpp @@ -73,19 +73,19 @@ namespace verbly { { sqlite3_close_v2(ppdb_); } - + void database::runQuery(std::string query) { // This can only happen when doing bad things with move semantics. assert(ppdb_ != nullptr); - + sqlite3_stmt* ppstmt; if (sqlite3_prepare_v2(ppdb_, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) { throw sqlite3_error("Error writing to database", sqlite3_errmsg(ppdb_)); } - + int result = sqlite3_step(ppstmt); sqlite3_finalize(ppstmt); @@ -99,10 +99,10 @@ namespace verbly { { // This can only happen when doing bad things with move semantics. assert(ppdb_ != nullptr); - + // This shouldn't happen. assert(!fields.empty()); - + std::list fieldNames; std::list qs; for (field& f : fields) @@ -110,7 +110,7 @@ namespace verbly { fieldNames.push_back(f.getName()); qs.push_back("?"); } - + std::ostringstream query; query << "INSERT INTO "; query << table; @@ -119,7 +119,7 @@ namespace verbly { query << ") VALUES ("; query << implode(std::begin(qs), std::end(qs), ", "); query << ")"; - + std::string query_str = query.str(); sqlite3_stmt* ppstmt; diff --git a/generator/database.h b/generator/database.h index 15cdff5..7906304 100644 --- a/generator/database.h +++ b/generator/database.h @@ -52,7 +52,7 @@ namespace verbly { ~database(); // Actions - + void runQuery(std::string query); void insertIntoTable(std::string table, std::list fields); diff --git a/generator/field.h b/generator/field.h index 1fbabfc..aaca3fa 100644 --- a/generator/field.h +++ b/generator/field.h @@ -32,27 +32,27 @@ namespace verbly { ~field(); // Generic accessors - + type getType() const { return type_; } - + std::string getName() const { return name_; } // Integer - + field(std::string name, int arg); - + int getInteger() const; // String - + field(std::string name, std::string arg); - + std::string getString() const; private: diff --git a/generator/frame.h b/generator/frame.h index 411ce6c..764564d 100644 --- a/generator/frame.h +++ b/generator/frame.h @@ -6,53 +6,53 @@ namespace verbly { namespace generator { - + class database; - + class frame { public: - + // Aliases - + using const_iterator = std::list::const_iterator; - + // Constructor - + frame(); - + // Mutators - + void push_back(part fp); - + // Accessors - + int getId() const { return id_; } - + const_iterator begin() const { return std::begin(parts_); } - + const_iterator end() const { return std::end(parts_); } - + private: - + static int nextId_; - + const int id_; - + std::list parts_; - + }; - + database& operator<<(database& db, const frame& arg); - + }; }; diff --git a/generator/generator.h b/generator/generator.h index c829c21..8352693 100644 --- a/generator/generator.h +++ b/generator/generator.h @@ -16,17 +16,17 @@ #include "frame.h" namespace verbly { - + enum class part_of_speech; class selrestr; - + namespace generator { - + class generator { public: - + // Constructor - + generator( std::string verbNetPath, std::string agidPath, @@ -34,95 +34,95 @@ namespace verbly { std::string cmudictPath, std::string imageNetPath, std::string outputPath); - + // Action - + void run(); - + private: - + // Subroutines - + void readWordNetSynsets(); - + void readAdjectivePositioning(); - + void readImageNetUrls(); - + void readWordNetSenseKeys(); - + void readVerbNet(); - + void readAgidInflections(); - + void readPrepositions(); - + void readCmudictPronunciations(); - + void writeSchema(); - + void dumpObjects(); - + void readWordNetAntonymy(); - + void readWordNetVariation(); - + void readWordNetClasses(); - + void readWordNetCausality(); - + void readWordNetEntailment(); - + void readWordNetHypernymy(); - + void readWordNetInstantiation(); - + void readWordNetMemberMeronymy(); - + void readWordNetPartMeronymy(); - + void readWordNetSubstanceMeronymy(); - + void readWordNetPertainymy(); - + void readWordNetSpecification(); - + void readWordNetSimilarity(); - + // Helpers - + std::list readFile(std::string path); - + inline part_of_speech partOfSpeechByWnid(int wnid); - + notion& createNotion(part_of_speech partOfSpeech); - + notion& lookupOrCreateNotion(int wnid); - + lemma& lookupOrCreateLemma(std::string base_form); - + form& lookupOrCreateForm(std::string text); - + template word& createWord(Args&&... args); - + group& createGroup(xmlNodePtr top); - + selrestr parseSelrestr(xmlNodePtr top); - + // Input - + std::string verbNetPath_; std::string agidPath_; std::string wordNetPath_; std::string cmudictPath_; std::string imageNetPath_; - + // Output - + database db_; - + // Data - + std::list notions_; std::list words_; std::list lemmas_; @@ -130,22 +130,22 @@ namespace verbly { std::list pronunciations_; std::list frames_; std::list groups_; - + // Indexes - + std::map notionByWnid_; std::map> wordsByWnid_; std::map, word*> wordByWnidAndWnum_; std::map> wordsByBaseForm_; std::map lemmaByBaseForm_; std::map formByText_; - + // Caches - + std::map wnSenseKeys_; - + }; - + }; }; diff --git a/generator/group.cpp b/generator/group.cpp index 334c2aa..cebe2b9 100644 --- a/generator/group.cpp +++ b/generator/group.cpp @@ -8,37 +8,37 @@ namespace verbly { namespace generator { - + int group::nextId_ = 0; - + group::group() : id_(nextId_++) { } - + void group::setParent(const group& parent) { // Adding a group to itself is nonsensical. assert(&parent != this); - + parent_ = &parent; } - + void group::addRole(role r) { std::string name = r.getName(); roles_[name] = std::move(r); roleNames_.insert(std::move(name)); } - + void group::addFrame(const frame& f) { frames_.insert(&f); } - + std::set group::getRoles() const { std::set fullRoles = roleNames_; - + if (hasParent()) { for (std::string name : getParent().getRoles()) @@ -46,10 +46,10 @@ namespace verbly { fullRoles.insert(name); } } - + return fullRoles; } - + const role& group::getRole(std::string name) const { if (roles_.count(name)) @@ -62,11 +62,11 @@ namespace verbly { throw std::invalid_argument("Specified role not found in verb group"); } } - + std::set group::getFrames() const { std::set fullFrames = frames_; - + if (hasParent()) { for (const frame* f : getParent().getFrames()) @@ -74,47 +74,47 @@ namespace verbly { fullFrames.insert(f); } } - + return fullFrames; } - + database& operator<<(database& db, const group& arg) { // Serialize the group first { std::list fields; fields.emplace_back("group_id", arg.getId()); - + nlohmann::json jsonRoles; for (std::string name : arg.getRoles()) { const role& r = arg.getRole(name); - + nlohmann::json jsonRole; jsonRole["type"] = name; jsonRole["selrestrs"] = r.getSelrestrs().toJson(); - + jsonRoles.emplace_back(std::move(jsonRole)); } fields.emplace_back("data", jsonRoles.dump()); - + db.insertIntoTable("groups", std::move(fields)); } - + // Then, serialize the group/frame relationship for (const frame* f : arg.getFrames()) { std::list fields; - + fields.emplace_back("group_id", arg.getId()); fields.emplace_back("frame_id", f->getId()); - + db.insertIntoTable("groups_frames", std::move(fields)); } - + return db; } - + }; }; diff --git a/generator/group.h b/generator/group.h index 5084ea4..83f40c2 100644 --- a/generator/group.h +++ b/generator/group.h @@ -9,71 +9,71 @@ namespace verbly { namespace generator { - + class frame; class database; - + class group { public: - + // Constructor - + group(); - + // Mutators - + void setParent(const group& parent); - + void addRole(role r); - + void addFrame(const frame& f); - + // Accessors - + int getId() const { return id_; } - + bool hasParent() const { return (parent_ != nullptr); } - + const group& getParent() const { // Calling code should always call hasParent first assert(parent_ != nullptr); - + return *parent_; } - + std::set getRoles() const; - + const role& getRole(std::string name) const; - + std::set getFrames() const; - + private: - + static int nextId_; - + const int id_; - + const group* parent_ = nullptr; std::map roles_; std::set frames_; - + // Caches - + std::set roleNames_; - + }; - + // Serializer - + database& operator<<(database& db, const group& arg); - + }; }; diff --git a/generator/main.cpp b/generator/main.cpp index 827c963..1b07706 100644 --- a/generator/main.cpp +++ b/generator/main.cpp @@ -20,7 +20,7 @@ int main(int argc, char** argv) try { verbly::generator::generator app(argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]); - + try { app.run(); diff --git a/generator/notion.cpp b/generator/notion.cpp index 290d982..1878ba9 100644 --- a/generator/notion.cpp +++ b/generator/notion.cpp @@ -30,15 +30,15 @@ namespace verbly { { // Calling code should always call hasWnid and check that the notion is a noun first. assert(hasWnid_ && (partOfSpeech_ == part_of_speech::noun)); - + numOfImages_++; } - + void notion::setPrepositionGroups(std::list groups) { // Calling code should always check that the notion is a preposition first. assert(partOfSpeech_ == part_of_speech::preposition); - + prepositionGroups_ = groups; } @@ -54,7 +54,7 @@ namespace verbly { if (arg.hasWnid()) { fields.emplace_back("wnid", arg.getWnid()); - + if (arg.getPartOfSpeech() == part_of_speech::noun) { fields.emplace_back("images", arg.getNumOfImages()); @@ -63,17 +63,17 @@ namespace verbly { db.insertIntoTable("notions", std::move(fields)); } - + // Next, serialize the is_a relationship if this is a preposition if (arg.getPartOfSpeech() == part_of_speech::preposition) { for (std::string group : arg.getPrepositionGroups()) { std::list fields; - + fields.emplace_back("notion_id", arg.getId()); fields.emplace_back("groupname", group); - + db.insertIntoTable("is_a", std::move(fields)); } } diff --git a/generator/notion.h b/generator/notion.h index cc64c48..6e38497 100644 --- a/generator/notion.h +++ b/generator/notion.h @@ -23,7 +23,7 @@ namespace verbly { // Mutators void incrementNumOfImages(); - + void setPrepositionGroups(std::list groups); // Accessors @@ -37,7 +37,7 @@ namespace verbly { { return partOfSpeech_; } - + bool hasWnid() const { return hasWnid_; @@ -58,12 +58,12 @@ namespace verbly { return numOfImages_; } - + std::list getPrepositionGroups() const { // Calling code should always check that the notion is a preposition first. assert(partOfSpeech_ == part_of_speech::preposition); - + return prepositionGroups_; } diff --git a/generator/part.cpp b/generator/part.cpp index b69ec65..8a75ed4 100644 --- a/generator/part.cpp +++ b/generator/part.cpp @@ -3,56 +3,56 @@ namespace verbly { namespace generator { - + part part::createNounPhrase(std::string role, selrestr selrestrs, std::set synrestrs) { part p(type::noun_phrase); - + new(&p.noun_phrase_.role) std::string(std::move(role)); new(&p.noun_phrase_.selrestrs) selrestr(std::move(selrestrs)); new(&p.noun_phrase_.synrestrs) std::set(std::move(synrestrs)); - + return p; } - + part part::createVerb() { return part(type::verb); } - + part part::createPreposition(std::set choices, bool literal) { part p(type::preposition); - + new(&p.preposition_.choices) std::set(std::move(choices)); p.preposition_.literal = literal; - + return p; } - + part part::createAdjective() { return part(type::adjective); } - + part part::createAdverb() { return part(type::adverb); } - + part part::createLiteral(std::string value) { part p(type::literal); - + new(&p.literal_) std::string(std::move(value)); - + return p; } - + part::part(const part& other) { type_ = other.type_; - + switch (type_) { case type::noun_phrase: @@ -60,25 +60,25 @@ namespace verbly { new(&noun_phrase_.role) std::string(other.noun_phrase_.role); new(&noun_phrase_.selrestrs) selrestr(other.noun_phrase_.selrestrs); new(&noun_phrase_.synrestrs) std::set(other.noun_phrase_.synrestrs); - + break; } - + case type::preposition: { new(&preposition_.choices) std::set(other.preposition_.choices); preposition_.literal = other.preposition_.literal; - + break; } - + case type::literal: { new(&literal_) std::string(other.literal_); - + break; } - + case type::verb: case type::adjective: case type::adverb: @@ -88,23 +88,23 @@ namespace verbly { } } } - + part::part(part&& other) : part() { swap(*this, other); } - + part& part::operator=(part other) { swap(*this, other); - + return *this; } - + void swap(part& first, part& second) { using type = part::type; - + type tempType = first.type_; std::string tempRole; selrestr tempSelrestrs; @@ -112,7 +112,7 @@ namespace verbly { std::set tempChoices; bool tempPrepLiteral; std::string tempLiteralValue; - + switch (tempType) { case type::noun_phrase: @@ -120,25 +120,25 @@ namespace verbly { tempRole = std::move(first.noun_phrase_.role); tempSelrestrs = std::move(first.noun_phrase_.selrestrs); tempSynrestrs = std::move(first.noun_phrase_.synrestrs); - + break; } - + case type::preposition: { tempChoices = std::move(first.preposition_.choices); tempPrepLiteral = first.preposition_.literal; - + break; } - + case type::literal: { tempLiteralValue = std::move(first.literal_); - + break; } - + case type::verb: case type::adjective: case type::adverb: @@ -147,11 +147,11 @@ namespace verbly { break; } } - + first.~part(); - + first.type_ = second.type_; - + switch (first.type_) { case type::noun_phrase: @@ -159,25 +159,25 @@ namespace verbly { new(&first.noun_phrase_.role) std::string(std::move(second.noun_phrase_.role)); new(&first.noun_phrase_.selrestrs) selrestr(std::move(second.noun_phrase_.selrestrs)); new(&first.noun_phrase_.synrestrs) std::set(std::move(second.noun_phrase_.synrestrs)); - + break; } - + case type::preposition: { new(&first.preposition_.choices) std::set(std::move(second.preposition_.choices)); first.preposition_.literal = second.preposition_.literal; - + break; } - + case type::literal: { new(&first.literal_) std::string(std::move(second.literal_)); - + break; } - + case type::verb: case type::adjective: case type::adverb: @@ -186,11 +186,11 @@ namespace verbly { break; } } - + second.~part(); - + second.type_ = tempType; - + switch (second.type_) { case type::noun_phrase: @@ -198,25 +198,25 @@ namespace verbly { new(&second.noun_phrase_.role) std::string(std::move(tempRole)); new(&second.noun_phrase_.selrestrs) selrestr(std::move(tempSelrestrs)); new(&second.noun_phrase_.synrestrs) std::set(std::move(tempSynrestrs)); - + break; } - + case type::preposition: { new(&second.preposition_.choices) std::set(std::move(tempChoices)); second.preposition_.literal = tempPrepLiteral; - + break; } - + case type::literal: { new(&second.literal_) std::string(std::move(tempLiteralValue)); - + break; } - + case type::verb: case type::adjective: case type::adverb: @@ -226,7 +226,7 @@ namespace verbly { } } } - + part::~part() { switch (type_) @@ -235,32 +235,32 @@ namespace verbly { { using string_type = std::string; using set_type = std::set; - + noun_phrase_.role.~string_type(); noun_phrase_.selrestrs.~selrestr(); noun_phrase_.synrestrs.~set_type(); - + break; } - + case type::preposition: { using set_type = std::set; - + preposition_.choices.~set_type(); - + break; } - + case type::literal: { using string_type = std::string; - + literal_.~string_type(); - + break; } - + case type::verb: case type::adjective: case type::adverb: @@ -270,7 +270,7 @@ namespace verbly { } } } - + std::string part::getNounRole() const { if (type_ == type::noun_phrase) @@ -280,7 +280,7 @@ namespace verbly { throw std::domain_error("part::getNounRole is only valid for noun phrase parts"); } } - + selrestr part::getNounSelrestrs() const { if (type_ == type::noun_phrase) @@ -290,7 +290,7 @@ namespace verbly { throw std::domain_error("part::getNounSelrestrs is only valid for noun phrase parts"); } } - + std::set part::getNounSynrestrs() const { if (type_ == type::noun_phrase) @@ -300,7 +300,7 @@ namespace verbly { throw std::domain_error("part::getNounSynrestrs is only valid for noun phrase parts"); } } - + std::set part::getPrepositionChoices() const { if (type_ == type::preposition) @@ -310,7 +310,7 @@ namespace verbly { throw std::domain_error("part::getPrepositionChoices is only valid for preposition parts"); } } - + bool part::isPrepositionLiteral() const { if (type_ == type::preposition) @@ -320,7 +320,7 @@ namespace verbly { throw std::domain_error("part::isPrepositionLiteral is only valid for preposition parts"); } } - + std::string part::getLiteralValue() const { if (type_ == type::literal) @@ -330,6 +330,6 @@ namespace verbly { throw std::domain_error("part::getLiteralValue is only valid for literal parts"); } } - + }; }; diff --git a/generator/part.h b/generator/part.h index 86d5d57..b010f62 100644 --- a/generator/part.h +++ b/generator/part.h @@ -7,7 +7,7 @@ namespace verbly { namespace generator { - + class part { public: enum class type { @@ -19,78 +19,78 @@ namespace verbly { adverb = 4, literal = 5 }; - + // Static factories - + static part createNounPhrase(std::string role, selrestr selrestrs, std::set synrestrs); - + static part createVerb(); - + static part createPreposition(std::set choices, bool literal); - + static part createAdjective(); - + static part createAdverb(); - + static part createLiteral(std::string value); - + // Copy and move constructors - + part(const part& other); - + part(part&& other); - + // Assignment - + part& operator=(part other); - + // Swap - + friend void swap(part& first, part& second); - + // Destructor - + ~part(); - + // General accessors - + type getType() const { return type_; } - + // Noun phrase accessors - + std::string getNounRole() const; - + selrestr getNounSelrestrs() const; - + std::set getNounSynrestrs() const; - + // Preposition accessors - + std::set getPrepositionChoices() const; - + bool isPrepositionLiteral() const; - + // Literal accessors - + std::string getLiteralValue() const; - + private: - + // Private constructors - + part() { } - + part(type t) : type_(t) { } - + // Data - + union { struct { std::string role; @@ -103,11 +103,11 @@ namespace verbly { } preposition_; std::string literal_; }; - + type type_ = type::invalid; - + }; - + }; }; diff --git a/generator/progress.h b/generator/progress.h index fcb680d..76cde48 100644 --- a/generator/progress.h +++ b/generator/progress.h @@ -5,20 +5,20 @@ namespace verbly { namespace generator { - + class progress { private: std::string message; int total; int cur = 0; int lprint = 0; - + public: progress(std::string message, int total) : message(message), total(total) { std::cout << message << " 0%" << std::flush; } - + void update(int val) { if (val <= total) @@ -27,29 +27,29 @@ namespace verbly { } else { cur = total; } - + int pp = cur * 100 / total; if (pp != lprint) { lprint = pp; - + std::cout << "\b\b\b\b" << std::right; std::cout.width(3); std::cout << pp << "%" << std::flush; } } - + void update() { update(cur+1); } - + ~progress() { std::cout << "\b\b\b\b100%" << std::endl; } }; - + }; }; diff --git a/generator/word.cpp b/generator/word.cpp index 8ba3ce2..b3fc490 100644 --- a/generator/word.cpp +++ b/generator/word.cpp @@ -37,7 +37,7 @@ namespace verbly { { adjectivePosition_ = adjectivePosition; } - + void word::setVerbGroup(const group& verbGroup) { verbGroup_ = &verbGroup; @@ -46,7 +46,7 @@ namespace verbly { database& operator<<(database& db, const word& arg) { std::list fields; - + fields.emplace_back("word_id", arg.getId()); fields.emplace_back("notion_id", arg.getNotion().getId()); fields.emplace_back("lemma_id", arg.getLemma().getId()); @@ -55,13 +55,13 @@ namespace verbly { { fields.emplace_back("tag_count", arg.getTagCount()); } - + if ((arg.getNotion().getPartOfSpeech() == part_of_speech::adjective) && (arg.getAdjectivePosition() != positioning::undefined)) { fields.emplace_back("position", static_cast(arg.getAdjectivePosition())); } - + if ((arg.getNotion().getPartOfSpeech() == part_of_speech::verb) && (arg.hasVerbGroup())) { diff --git a/generator/word.h b/generator/word.h index 1d77ed3..a994ec3 100644 --- a/generator/word.h +++ b/generator/word.h @@ -24,7 +24,7 @@ namespace verbly { // Mutators void setAdjectivePosition(positioning adjectivePosition); - + void setVerbGroup(const group& verbGroup); // Accessors @@ -58,7 +58,7 @@ namespace verbly { { return hasTagCount_; } - + int getTagCount() const { // Calling code should always call hasTagCount first. @@ -71,17 +71,17 @@ namespace verbly { { return adjectivePosition_; } - + bool hasVerbGroup() const { return (verbGroup_ != nullptr); } - + const group& getVerbGroup() const { // Calling code should always call hasVerbGroup first. assert(verbGroup_ != nullptr); - + return *verbGroup_; } diff --git a/lib/binding.h b/lib/binding.h index 7fbe20e..5578a09 100644 --- a/lib/binding.h +++ b/lib/binding.h @@ -12,9 +12,9 @@ namespace verbly { integer, string }; - + // Default constructor - + binding() { } @@ -37,22 +37,22 @@ namespace verbly { ~binding(); // Generic accessors - + type getType() const { return type_; } // Integer - + binding(int arg); - + int getInteger() const; // String - + binding(std::string arg); - + std::string getString() const; private: diff --git a/lib/database.cpp b/lib/database.cpp index 351b93d..fb00ef3 100644 --- a/lib/database.cpp +++ b/lib/database.cpp @@ -40,37 +40,37 @@ namespace verbly { { sqlite3_close_v2(ppdb_); } - + query database::notions(filter where, bool random, int limit) const { return query(*this, ppdb_, std::move(where), random, limit); } - + query database::words(filter where, bool random, int limit) const { return query(*this, ppdb_, std::move(where), random, limit); } - + query database::groups(filter where, bool random, int limit) const { return query(*this, ppdb_, std::move(where), random, limit); } - + query database::frames(filter where, bool random, int limit) const { return query(*this, ppdb_, std::move(where), random, limit); } - + query database::lemmas(filter where, bool random, int limit) const { return query(*this, ppdb_, std::move(where), random, limit); } - + query
database::forms(filter where, bool random, int limit) const { return query(*this, ppdb_, std::move(where), random, limit); } - + query database::pronunciations(filter where, bool random, int limit) const { return query(*this, ppdb_, std::move(where), random, limit); diff --git a/lib/database.h b/lib/database.h index d68c40b..ef50739 100644 --- a/lib/database.h +++ b/lib/database.h @@ -15,7 +15,7 @@ struct sqlite3; namespace verbly { - + template class query; @@ -43,21 +43,21 @@ namespace verbly { // Destructor ~database(); - + // Queries - + query notions(filter where, bool random = true, int limit = 1) const; - + query words(filter where, bool random = true, int limit = 1) const; - + query groups(filter where, bool random = true, int limit = 1) const; - + query frames(filter where, bool random = true, int limit = 1) const; - + query lemmas(filter where, bool random = true, int limit = 1) const; - + query forms(filter where, bool random = true, int limit = 1) const; - + query pronunciations(filter where, bool random = true, int limit = 1) const; private: diff --git a/lib/enums.h b/lib/enums.h index b37be7b..e634959 100644 --- a/lib/enums.h +++ b/lib/enums.h @@ -2,7 +2,7 @@ #define ENUMS_H_260BA847 namespace verbly { - + enum class part_of_speech { noun = 0, adjective = 1, @@ -10,14 +10,14 @@ namespace verbly { verb = 3, preposition = 4 }; - + enum class positioning { undefined = -1, predicate = 0, attributive = 1, postnominal = 2 }; - + enum class inflection { base = 0, plural = 1, @@ -28,7 +28,7 @@ namespace verbly { ing_form = 6, s_form = 7 }; - + enum class object { undefined = -1, notion = 0, @@ -39,7 +39,7 @@ namespace verbly { form = 5, pronunciation = 6 }; - + }; #endif /* end of include guard: ENUMS_H_260BA847 */ diff --git a/lib/field.cpp b/lib/field.cpp index 168935c..deecb06 100644 --- a/lib/field.cpp +++ b/lib/field.cpp @@ -2,72 +2,72 @@ #include "filter.h" namespace verbly { - + filter field::operator==(int value) const { return filter(*this, filter::comparison::int_equals, value); } - + filter field::operator!=(int value) const { return filter(*this, filter::comparison::int_does_not_equal, value); } - + filter field::operator<(int value) const { return filter(*this, filter::comparison::int_is_less_than, value); } - + filter field::operator<=(int value) const { return filter(*this, filter::comparison::int_is_at_most, value); } - + filter field::operator>(int value) const { return filter(*this, filter::comparison::int_is_greater_than, value); } - + filter field::operator>=(int value) const { return filter(*this, filter::comparison::int_is_at_least, value); } - + filter field::operator==(part_of_speech value) const { return filter(*this, filter::comparison::int_equals, static_cast(value)); } - + filter field::operator==(positioning value) const { return filter(*this, filter::comparison::int_equals, static_cast(value)); } - + filter field::operator==(inflection value) const { return filter(*this, filter::comparison::int_equals, static_cast(value)); } - + filter field::operator==(bool value) const { return filter(*this, filter::comparison::boolean_equals, value); } - + filter field::operator==(std::string value) const { return filter(*this, filter::comparison::string_equals, std::move(value)); } - + filter field::operator!=(std::string value) const { return filter(*this, filter::comparison::string_does_not_equal, std::move(value)); } - + filter field::operator%=(std::string value) const { return filter(*this, filter::comparison::string_is_like, std::move(value)); } - + field::operator filter() const { if (isJoin()) @@ -77,7 +77,7 @@ namespace verbly { return filter(*this, filter::comparison::is_not_null); } } - + filter field::operator!() const { if (isJoin()) @@ -87,7 +87,7 @@ namespace verbly { return filter(*this, filter::comparison::is_null); } } - + filter field::operator%=(filter joinCondition) const { if (type_ == type::hierarchal_join) @@ -97,5 +97,5 @@ namespace verbly { return filter(*this, filter::comparison::matches, std::move(joinCondition)); } } - + }; diff --git a/lib/lemma.cpp b/lib/lemma.cpp index 7fdc360..1601460 100644 --- a/lib/lemma.cpp +++ b/lib/lemma.cpp @@ -4,71 +4,71 @@ #include "query.h" namespace verbly { - + const object lemma::objectType = object::lemma; - + const std::list lemma::select = {"lemma_id"}; - + const field lemma::id = field::integerField(object::lemma, "lemma_id"); - + const field lemma::word = field::joinField(object::lemma, "lemma_id", object::word); - + const field lemma::formJoin = field::joinField(object::lemma, "form_id", object::form); const field lemma::inflectionCategory = field::integerField(object::lemma, "category"); - + filter operator%=(lemma::inflection_field check, filter joinCondition) { return (lemma::formJoin %= joinCondition) && (lemma::inflectionCategory == check.getCategory()); } - + lemma::inflection_field::operator filter() const { return (lemma::inflectionCategory == category_); } - + lemma::lemma(const database& db, sqlite3_stmt* row) : db_(&db), valid_(true) { id_ = sqlite3_column_int(row, 0); } - + const form& lemma::getBaseForm() const { if (!valid_) { throw std::domain_error("Bad access to uninitialized lemma"); } - + if (!forms_.count(inflection::base)) { initializeForm(inflection::base); } - + return forms_.at(inflection::base).front(); } - + bool lemma::hasInflection(inflection category) const { return !getInflections(category).empty(); } - + const std::vector& lemma::getInflections(inflection category) const { if (!valid_) { throw std::domain_error("Bad access to uninitialized lemma"); } - + if (!forms_.count(category)) { initializeForm(category); } - + return forms_.at(category); } - + void lemma::initializeForm(inflection infl) const { forms_[infl] = db_->forms(form::lemma(infl) %= *this, false, -1).all(); } - + }; diff --git a/lib/lemma.h b/lib/lemma.h index 8c8d1c1..407fa3c 100644 --- a/lib/lemma.h +++ b/lib/lemma.h @@ -13,110 +13,110 @@ struct sqlite3_stmt; namespace verbly { - + class database; - + class lemma { public: - + // Default constructor - + lemma() = default; - + // Construct from database - + lemma(const database& db, sqlite3_stmt* row); - + // Accessors - + operator bool() const { return valid_; } - + int getId() const { if (!valid_) { throw std::domain_error("Bad access to uninitialized lemma"); } - + return id_; } - + const form& getBaseForm() const; - + bool hasInflection(inflection category) const; - + const std::vector& getInflections(inflection category) const; - + // Type info - + static const object objectType; - + static const std::list select; - + // Query fields - + static const field id; - + operator filter() const { if (!valid_) { throw std::domain_error("Bad access to uninitialized lemma"); } - + return (id == id_); } - + // Relationships to other objects - + static const field word; - + class inflection_field { public: - + inflection_field(inflection category) : category_(category) { } - + const inflection getCategory() const { return category_; } - + operator filter() const; - + private: - + const inflection category_; }; - + static const inflection_field form(inflection category) { return inflection_field(category); } - + friend filter operator%=(lemma::inflection_field check, filter joinCondition); - + private: - + void initializeForm(inflection category) const; - + bool valid_ = false; - + int id_; - + mutable std::map> forms_; - + const database* db_; - + static const field formJoin; static const field inflectionCategory; - + }; - + }; #endif /* end of include guard: LEMMA_H_0A180D30 */ diff --git a/lib/pronunciation.cpp b/lib/pronunciation.cpp index f5b742f..e937ba6 100644 --- a/lib/pronunciation.cpp +++ b/lib/pronunciation.cpp @@ -6,64 +6,64 @@ #include "util.h" namespace verbly { - + const object pronunciation::objectType = object::pronunciation; - + const std::list pronunciation::select = {"pronunciation_id", "phonemes", "syllables", "stress", "prerhyme", "rhyme"}; - + const field pronunciation::id = field::integerField(object::pronunciation, "pronunciation_id"); const field pronunciation::numOfSyllables = field::integerField(object::pronunciation, "syllables"); const field pronunciation::stress = field::stringField(object::pronunciation, "stress"); - + const field pronunciation::form = field::joinThrough(object::pronunciation, "pronunciation_id", object::form, "forms_pronunciations", "form_id"); - + const field pronunciation::prerhyme = field::stringField(object::pronunciation, "prerhyme", true); const field pronunciation::rhyme = field::stringField(object::pronunciation, "rhyme", true); - + pronunciation::pronunciation(const database& db, sqlite3_stmt* row) : db_(&db), valid_(true) { id_ = sqlite3_column_int(row, 0); - + std::string phonemesStr(reinterpret_cast(sqlite3_column_text(row, 1))); phonemes_ = split>(phonemesStr, " "); - + syllables_ = sqlite3_column_int(row, 2); stress_ = std::string(reinterpret_cast(sqlite3_column_text(row, 3))); - + if (sqlite3_column_type(row, 5) != SQLITE_NULL) { hasRhyme_ = true; - + prerhyme_ = std::string(reinterpret_cast(sqlite3_column_text(row, 4))); rhyme_ = std::string(reinterpret_cast(sqlite3_column_text(row, 5))); } } - + filter pronunciation::rhymesWith(const pronunciation& arg) { return (prerhyme != arg.getPrerhyme()) && (rhyme == arg.getRhyme()); } - + /*filter pronunciation::rhymesWith(const class form& arg) { filter result; - + for (const pronunciation& p : arg.getPronunciations()) { result |= rhymesWith(p); } - + return result; } - + filter pronunciation::rhymesWith(const lemma& arg) { return rhymesWith(arg.getBaseForm()); } - + filter pronunciation::rhymesWith(const word& arg) { return rhymesWith(arg.getLemma()); }*/ - + }; diff --git a/lib/query.h b/lib/query.h index e31be3d..352748f 100644 --- a/lib/query.h +++ b/lib/query.h @@ -11,36 +11,36 @@ #include "binding.h" namespace verbly { - + class database_error : public std::logic_error { public: - + database_error(std::string msg, std::string sqlMsg) : std::logic_error(msg + " (" + sqlMsg + ")") { } }; - + template class query { public: - + query(const database& db, sqlite3* ppdb, filter queryFilter, bool random, int limit) : db_(&db) { statement stmt(Object::objectType, std::move(queryFilter)); - + std::string queryString = stmt.getQueryString(Object::select, random, limit); std::list bindings = stmt.getBindings(); - + std::cout << queryString << std::endl; - + if (sqlite3_prepare_v2(ppdb, queryString.c_str(), queryString.length(), &ppstmt_, NULL) != SQLITE_OK) { std::string errorMsg = sqlite3_errmsg(ppdb); sqlite3_finalize(ppstmt_); - + throw database_error("Error preparing query", errorMsg); } - + int i = 1; for (const binding& value : bindings) { @@ -52,52 +52,52 @@ namespace verbly { { std::string errorMsg = sqlite3_errmsg(ppdb); sqlite3_finalize(ppstmt_); - + throw database_error("Error binding value to query", errorMsg); } - + break; } - + case binding::type::string: { if (sqlite3_bind_text(ppstmt_, i, value.getString().c_str(), value.getString().length(), SQLITE_TRANSIENT) != SQLITE_OK) { std::string errorMsg = sqlite3_errmsg(ppdb); sqlite3_finalize(ppstmt_); - + throw database_error("Error binding value to query", errorMsg); } - + break; } - + case binding::type::invalid: { throw std::logic_error("Cannot use invalid bindings"); } } - + i++; } } - + ~query() { sqlite3_finalize(ppstmt_); } - + std::vector all() const { std::vector result; - + while (sqlite3_step(ppstmt_) == SQLITE_ROW) { result.emplace_back(*db_, ppstmt_); } - + sqlite3_reset(ppstmt_); - + return result; } @@ -111,13 +111,13 @@ namespace verbly { throw std::logic_error("query returned empty dataset"); } } - + private: const database* db_; sqlite3_stmt* ppstmt_; - + }; - + }; #endif /* end of include guard: QUERY_H_7CC5284C */ diff --git a/lib/role.h b/lib/role.h index 8653710..4884ef3 100644 --- a/lib/role.h +++ b/lib/role.h @@ -9,13 +9,13 @@ namespace verbly { class role { public: - + // Default constructor - + role() = default; - + // Constructor - + role( std::string name, selrestr selrestrs = {}) : @@ -24,35 +24,35 @@ namespace verbly { selrestrs_(selrestrs) { } - + // Accessors - + const std::string& getName() const { if (!valid_) { throw std::domain_error("Bad access to invalid role"); } - + return name_; } - + const selrestr& getSelrestrs() const { if (!valid_) { throw std::domain_error("Bad access to invalid role"); } - + return selrestrs_; } - + private: - + bool valid_ = false; std::string name_; selrestr selrestrs_; - + }; }; diff --git a/lib/selrestr.cpp b/lib/selrestr.cpp index 74ea726..8646871 100644 --- a/lib/selrestr.cpp +++ b/lib/selrestr.cpp @@ -1,7 +1,7 @@ #include "selrestr.h" namespace verbly { - + selrestr::selrestr(nlohmann::json data) { if (data.find("children") != data.end()) @@ -13,7 +13,7 @@ namespace verbly { { group_.children.emplace_back(child); } - + group_.orlogic = (data["logic"] == "or"); } else if (data.find("type") != data.end()) { @@ -24,139 +24,139 @@ namespace verbly { type_ = type::empty; } } - + selrestr::selrestr(const selrestr& other) { type_ = other.type_; - + switch (type_) { case type::singleton: { singleton_.pos = other.singleton_.pos; new(&singleton_.restriction) std::string(other.singleton_.restriction); - + break; } - + case type::group: { new(&group_.children) std::list(other.group_.children); group_.orlogic = other.group_.orlogic; - + break; } - + case type::empty: { break; } } } - + selrestr::selrestr(selrestr&& other) : selrestr() { swap(*this, other); } - + selrestr& selrestr::operator=(selrestr other) { swap(*this, other); - + return *this; } - + void swap(selrestr& first, selrestr& second) { using type = selrestr::type; - + type tempType = first.type_; int tempPos; std::string tempRestriction; std::list tempChildren; bool tempOrlogic; - + switch (tempType) { case type::singleton: { tempPos = first.singleton_.pos; tempRestriction = std::move(first.singleton_.restriction); - + break; } - + case type::group: { tempChildren = std::move(first.group_.children); tempOrlogic = first.group_.orlogic; - + break; } - + case type::empty: { break; } } - + first.~selrestr(); - + first.type_ = second.type_; - + switch (first.type_) { case type::singleton: { first.singleton_.pos = second.singleton_.pos; new(&first.singleton_.restriction) std::string(std::move(second.singleton_.restriction)); - + break; } - + case type::group: { new(&first.group_.children) std::list(std::move(second.group_.children)); first.group_.orlogic = second.group_.orlogic; - + break; } - + case type::empty: { break; } } - + second.~selrestr(); - + second.type_ = tempType; - + switch (second.type_) { case type::singleton: { second.singleton_.pos = tempPos; new(&second.singleton_.restriction) std::string(std::move(tempRestriction)); - + break; } - + case type::group: { new(&second.group_.children) std::list(std::move(tempChildren)); second.group_.orlogic = tempOrlogic; - + break; } - + case type::empty: { break; } } } - + selrestr::~selrestr() { switch (type_) @@ -165,29 +165,29 @@ namespace verbly { { using string_type = std::string; singleton_.restriction.~string_type(); - + break; } - + case type::group: { using list_type = std::list; group_.children.~list_type(); - + break; } - + case type::empty: { break; } } } - + selrestr::selrestr() : type_(type::empty) { } - + selrestr::selrestr( std::string restriction, bool pos) : @@ -196,7 +196,7 @@ namespace verbly { new(&singleton_.restriction) std::string(std::move(restriction)); singleton_.pos = pos; } - + std::string selrestr::getRestriction() const { if (type_ == type::singleton) @@ -206,7 +206,7 @@ namespace verbly { throw std::domain_error("Only singleton selrestrs have restrictions"); } } - + bool selrestr::getPos() const { if (type_ == type::singleton) @@ -216,7 +216,7 @@ namespace verbly { throw std::domain_error("Only singleton selrestrs have positivity flags"); } } - + selrestr::selrestr( std::list children, bool orlogic) : @@ -225,7 +225,7 @@ namespace verbly { new(&group_.children) std::list(std::move(children)); group_.orlogic = orlogic; } - + std::list selrestr::getChildren() const { if (type_ == type::group) @@ -235,7 +235,7 @@ namespace verbly { throw std::domain_error("Only group selrestrs have children"); } } - + std::list::const_iterator selrestr::begin() const { if (type_ == type::group) @@ -245,7 +245,7 @@ namespace verbly { throw std::domain_error("Only group selrestrs have children"); } } - + std::list::const_iterator selrestr::end() const { if (type_ == type::group) @@ -255,7 +255,7 @@ namespace verbly { throw std::domain_error("Only group selrestrs have children"); } } - + bool selrestr::getOrlogic() const { if (type_ == type::group) @@ -265,7 +265,7 @@ namespace verbly { throw std::domain_error("Only group selrestrs have logic"); } } - + nlohmann::json selrestr::toJson() const { switch (type_) @@ -274,7 +274,7 @@ namespace verbly { { return {}; } - + case type::singleton: { return { @@ -282,7 +282,7 @@ namespace verbly { {"pos", singleton_.pos} }; } - + case type::group: { std::string logic; @@ -292,12 +292,12 @@ namespace verbly { } else { logic = "and"; } - + std::list children; std::transform(std::begin(group_.children), std::end(group_.children), std::back_inserter(children), [] (const selrestr& child) { return child.toJson(); }); - + return { {"logic", logic}, {"children", children} diff --git a/lib/selrestr.h b/lib/selrestr.h index 9f82e3e..a7cde0a 100644 --- a/lib/selrestr.h +++ b/lib/selrestr.h @@ -6,7 +6,7 @@ #include "../vendor/json/json.hpp" namespace verbly { - + class selrestr { public: enum class type { @@ -14,63 +14,63 @@ namespace verbly { singleton, group }; - + // Construct from json - + explicit selrestr(nlohmann::json json); - + // Copy and move constructors - + selrestr(const selrestr& other); selrestr(selrestr&& other); - + // Assignment - + selrestr& operator=(selrestr other); - + // Swap - + friend void swap(selrestr& first, selrestr& second); - + // Destructor - + ~selrestr(); - + // Generic accessors - + type getType() const { return type_; } - + // Empty - + selrestr(); - + // Singleton - + selrestr(std::string restriction, bool pos); - + std::string getRestriction() const; - + bool getPos() const; - + // Group - + selrestr(std::list children, bool orlogic); - + std::list getChildren() const; - + std::list::const_iterator begin() const; - + std::list::const_iterator end() const; - + bool getOrlogic() const; - + // Helpers - + nlohmann::json toJson() const; - + private: union { struct { diff --git a/lib/statement.cpp b/lib/statement.cpp index 222a8eb..846b9de 100644 --- a/lib/statement.cpp +++ b/lib/statement.cpp @@ -12,22 +12,22 @@ #include "pronunciation.h" namespace verbly { - + statement::statement( object context, filter queryFilter) : statement(getTableForContext(context), queryFilter.compact().normalize(context)) { } - + std::string statement::getQueryString(std::list select, bool random, int limit) const { std::stringstream queryStream; - + if (!withs_.empty()) { queryStream << "WITH RECURSIVE "; - + std::list ctes; for (const with& cte : withs_) { @@ -39,19 +39,19 @@ namespace verbly { cteStream << cte.getTableForId(cte.getTopTable()); cteStream << " AS "; cteStream << cte.getTopTable(); - + for (const join& j : cte.getJoins()) { cteStream << " "; cteStream << j; } - + if (cte.getCondition().getType() != condition::type::empty) { cteStream << " WHERE "; cteStream << cte.getCondition().toSql(); } - + if (cte.isRecursive()) { cteStream << " UNION SELECT l.* FROM "; @@ -69,59 +69,59 @@ namespace verbly { cteStream << " = l."; cteStream << cte.getField().getColumn(); } - + cteStream << ")"; ctes.push_back(cteStream.str()); } - + queryStream << implode(std::begin(ctes), std::end(ctes), ", "); queryStream << " "; } - + std::list realSelect; for (std::string& s : select) { realSelect.push_back(topTable_ + "." + s); } - + queryStream << "SELECT "; queryStream << implode(std::begin(realSelect), std::end(realSelect), ", "); queryStream << " FROM "; queryStream << tables_.at(topTable_); queryStream << " AS "; queryStream << topTable_; - + for (const join& j : joins_) { queryStream << " "; queryStream << j; } - + if (topCondition_.getType() != condition::type::empty) { queryStream << " WHERE "; queryStream << topCondition_.toSql(); } - + if (random) { queryStream << " ORDER BY RANDOM()"; } - + if (limit > 0) { queryStream << " LIMIT "; queryStream << limit; } - + return queryStream.str(); } - + std::list statement::getBindings() const { std::list result; - + for (const with& w : withs_) { for (binding value : w.getCondition().flattenBindings()) @@ -129,15 +129,15 @@ namespace verbly { result.push_back(std::move(value)); } } - + for (binding value : topCondition_.flattenBindings()) { result.push_back(std::move(value)); } - + return result; } - + statement::statement( std::string tableName, filter clause, @@ -149,7 +149,7 @@ namespace verbly { topCondition_(parseFilter(std::move(clause))) { } - + /** * This function recursively parses the query's filter condition. It is not * idempotent. It returns a condition object representing the passed filter, @@ -165,7 +165,7 @@ namespace verbly { { return {}; } - + case filter::type::singleton: { switch (clause.getField().getType()) @@ -174,7 +174,7 @@ namespace verbly { { return {}; } - + // For primitive type filters, all we need to do is translate the // filter object directly into a condition object. No joins are // necessary. @@ -188,67 +188,67 @@ namespace verbly { { return condition(topTable_, clause.getField().getColumn(), true); } - + case filter::comparison::is_not_null: { return condition(topTable_, clause.getField().getColumn(), false); } - + case filter::comparison::int_equals: { return condition(topTable_, clause.getField().getColumn(), condition::comparison::equals, clause.getIntegerArgument()); } - + case filter::comparison::int_does_not_equal: { return condition(topTable_, clause.getField().getColumn(), condition::comparison::does_not_equal, clause.getIntegerArgument()); } - + case filter::comparison::int_is_at_least: { return condition(topTable_, clause.getField().getColumn(), condition::comparison::is_at_least, clause.getIntegerArgument()); } - + case filter::comparison::int_is_greater_than: { return condition(topTable_, clause.getField().getColumn(), condition::comparison::is_greater_than, clause.getIntegerArgument()); } - + case filter::comparison::int_is_at_most: { return condition(topTable_, clause.getField().getColumn(), condition::comparison::is_at_most, clause.getIntegerArgument()); } - + case filter::comparison::int_is_less_than: { return condition(topTable_, clause.getField().getColumn(), condition::comparison::is_less_than, clause.getIntegerArgument()); } - + case filter::comparison::boolean_equals: { return condition(topTable_, clause.getField().getColumn(), condition::comparison::equals, clause.getBooleanArgument() ? 1 : 0); } - + case filter::comparison::string_equals: { return condition(topTable_, clause.getField().getColumn(), condition::comparison::equals, clause.getStringArgument()); } - + case filter::comparison::string_does_not_equal: { return condition(topTable_, clause.getField().getColumn(), condition::comparison::does_not_equal, clause.getStringArgument()); } - + case filter::comparison::string_is_like: { return condition(topTable_, clause.getField().getColumn(), condition::comparison::is_like, clause.getStringArgument()); } - + case filter::comparison::string_is_not_like: { return condition(topTable_, clause.getField().getColumn(), condition::comparison::is_not_like, clause.getStringArgument()); } - + case filter::comparison::matches: case filter::comparison::does_not_match: case filter::comparison::hierarchally_matches: @@ -258,7 +258,7 @@ namespace verbly { } } } - + case field::type::join: { // First, figure out what table we need to join against. @@ -278,9 +278,9 @@ namespace verbly { clause.getJoinCondition().normalize(clause.getField().getJoinObject()), nextTableId_, nextWithId_); - + std::string joinTable = joinStmt.topTable_; - + if (clause.getComparison() == filter::comparison::does_not_match) { // If the comparison is actually a negative filter, we can't just @@ -293,7 +293,7 @@ namespace verbly { // condition on the join column being NULL as before. std::string withName = instantiateWith(clause.getField().getTable()); std::string withInstName = instantiateTable(withName); - + // LEFT JOIN against the CTE. joins_.emplace_back( true, @@ -310,7 +310,7 @@ namespace verbly { std::map cteTables = std::move(joinStmt.tables_); std::list cteJoins = std::move(joinStmt.joins_); condition cteCondition = integrate(std::move(joinStmt), true); - + withs_.emplace_back( std::move(withName), clause.getField(), @@ -319,7 +319,7 @@ namespace verbly { std::move(cteCondition), std::move(cteJoins), false); - + // Condition on the join column being NULL, which causes the query // to only return results that do not match the subquery. return condition(std::move(withInstName), clause.getField().getColumn(), true); @@ -332,14 +332,14 @@ namespace verbly { clause.getField().getColumn(), std::move(joinTable), clause.getField().getColumn()); - + // Integrate the subquery's table mappings, joins, and CTEs into // this statement, and return the subquery condition as our // condition. return integrate(std::move(joinStmt)); } } - + case field::type::join_through: { // Recursively parse the subquery, and therefore obtain an @@ -350,9 +350,9 @@ namespace verbly { clause.getJoinCondition().normalize(clause.getField().getJoinObject()), nextTableId_, nextWithId_); - + std::string joinTable = joinStmt.topTable_; - + if (clause.getComparison() == filter::comparison::does_not_match) { // If the comparison is actually a negative filter, we can't just @@ -366,7 +366,7 @@ namespace verbly { // condition on the join column being NULL as before. std::string withName = instantiateWith(clause.getField().getTable()); std::string withInstName = instantiateTable(withName); - + // LEFT JOIN against the CTE. joins_.emplace_back( true, @@ -375,7 +375,7 @@ namespace verbly { clause.getField().getColumn(), withInstName, clause.getField().getJoinColumn()); - + // Modify the substatement such that the through table is the top // table, and such that it joins against the previous top table. std::string throughTable = joinStmt.instantiateTable(clause.getField().getTable()); @@ -386,7 +386,7 @@ namespace verbly { clause.getField().getForeignJoinColumn(), std::move(joinTable), clause.getField().getForeignColumn()); - + joinStmt.topTable_ = throughTable; // All CTEs have to be in the main statement, so integrate any @@ -396,7 +396,7 @@ namespace verbly { std::map cteTables = std::move(joinStmt.tables_); std::list cteJoins = std::move(joinStmt.joins_); condition cteCondition = integrate(std::move(joinStmt), true); - + withs_.emplace_back( std::move(withName), clause.getField(), @@ -405,14 +405,14 @@ namespace verbly { std::move(cteCondition), std::move(cteJoins), false); - + // Condition on the join column being NULL, which causes the query // to only return results that do not match the subquery. return condition(std::move(withInstName), clause.getField().getJoinColumn(), true); } else { // Instantiate the through table. std::string throughTable = instantiateTable(clause.getField().getTable()); - + // INNER JOIN against the through table. joins_.emplace_back( false, @@ -421,7 +421,7 @@ namespace verbly { clause.getField().getColumn(), throughTable, clause.getField().getJoinColumn()); - + // INNER JOIN from the through table to the top table of the subquery. joins_.emplace_back( false, @@ -430,20 +430,20 @@ namespace verbly { clause.getField().getForeignJoinColumn(), std::move(joinTable), clause.getField().getForeignColumn()); - + // Integrate the subquery's table mappings, joins, and CTEs into // this statement, and return the subquery condition as our // condition. return integrate(std::move(joinStmt)); } } - + case field::type::hierarchal_join: { // Create a recursive CTE that represents the results of the subquery. std::string withName = instantiateWith(clause.getField().getTable()); std::string withInstName = instantiateTable(withName); - + // If we are matching against the subquery, we INNER JOIN with the // CTE. If we are negatively matching the subquery, we LEFT JOIN // with the CTE. @@ -452,7 +452,7 @@ namespace verbly { { outer = true; } - + // Join against the CTE. joins_.emplace_back( outer, @@ -461,14 +461,14 @@ namespace verbly { clause.getField().getColumn(), withInstName, clause.getField().getColumn()); - + // Recursively parse the subquery in order to create the CTE. statement withStmt( getTableForContext(clause.getField().getObject()), clause.getJoinCondition().normalize(clause.getField().getObject()), nextTableId_, nextWithId_); - + // All CTEs have to be in the main statement, so integrate any CTEs // that our subquery uses. Also, retrieve the table mapping, joins // list, and subquery condition, and use them to create the CTE. @@ -476,7 +476,7 @@ namespace verbly { std::map cteTables = std::move(withStmt.tables_); std::list cteJoins = std::move(withStmt.joins_); condition cteCondition = integrate(std::move(withStmt), true); - + withs_.emplace_back( std::move(withName), clause.getField(), @@ -498,11 +498,11 @@ namespace verbly { } } } - + case filter::type::group: { condition grp(clause.getOrlogic()); - + for (const filter& child : clause) { condition newChild = parseFilter(child); @@ -511,30 +511,30 @@ namespace verbly { grp += std::move(newChild); } } - + if (grp.getChildren().empty()) { grp = {}; } - + return grp; } } } - + std::string statement::instantiateTable(std::string name) { std::string identifier = name + "_" + std::to_string(nextTableId_++); tables_[identifier] = name; - + return identifier; } - + std::string statement::instantiateWith(std::string name) { return name + "_tree_" + std::to_string(nextWithId_++); } - + /** * This method integrates the parts of a recursively generated statement into * this statement. This is used because filters are recursive objects, but @@ -551,13 +551,13 @@ namespace verbly { { tables_[mapping.first] = mapping.second; } - + for (auto& j : subStmt.joins_) { joins_.push_back(j); } } - + for (auto& w : subStmt.withs_) { withs_.push_back(w); @@ -565,10 +565,10 @@ namespace verbly { nextTableId_ = subStmt.nextTableId_; nextWithId_ = subStmt.nextWithId_; - + return subStmt.topCondition_; } - + std::ostream& operator<<(std::ostream& oss, const statement::join& j) { if (j.isOuterJoin()) @@ -577,7 +577,7 @@ namespace verbly { } else { oss << "INNER"; } - + return oss << " JOIN " << j.getForeignTableName() @@ -592,55 +592,55 @@ namespace verbly { << "." << j.getJoinColumn(); } - + statement::condition::condition(const condition& other) { type_ = other.type_; - + switch (type_) { case type::empty: { break; } - + case type::singleton: { new(&singleton_.table_) std::string(other.singleton_.table_); new(&singleton_.column_) std::string(other.singleton_.column_); singleton_.comparison_ = other.singleton_.comparison_; new(&singleton_.value_) binding(other.singleton_.value_); - + break; } - + case type::group: { new(&group_.children_) std::list(other.group_.children_); group_.orlogic_ = other.group_.orlogic_; - + break; } } } - + statement::condition::condition(condition&& other) : condition() { swap(*this, other); } - + statement::condition& statement::condition::operator=(condition other) { swap(*this, other); - + return *this; } - + void swap(statement::condition& first, statement::condition& second) { using type = statement::condition::type; using condition = statement::condition; - + type tempType = first.type_; std::string tempTable; std::string tempColumn; @@ -648,94 +648,94 @@ namespace verbly { binding tempBinding; std::list tempChildren; bool tempOrlogic; - + switch (tempType) { case type::empty: { break; } - + case type::singleton: { tempTable = std::move(first.singleton_.table_); tempColumn = std::move(first.singleton_.column_); tempComparison = first.singleton_.comparison_; tempBinding = std::move(first.singleton_.value_); - + break; } - + case type::group: { tempChildren = std::move(first.group_.children_); tempOrlogic = first.group_.orlogic_; - + break; } } - + first.~condition(); - + first.type_ = second.type_; - + switch (first.type_) { case type::empty: { break; } - + case type::singleton: { new(&first.singleton_.table_) std::string(std::move(second.singleton_.table_)); new(&first.singleton_.column_) std::string(std::move(second.singleton_.column_)); first.singleton_.comparison_ = second.singleton_.comparison_; new(&first.singleton_.value_) binding(std::move(second.singleton_.value_)); - + break; } - + case type::group: { new(&first.group_.children_) std::list(std::move(second.group_.children_)); first.group_.orlogic_ = second.group_.orlogic_; - + break; } } - + second.~condition(); - + second.type_ = tempType; - + switch (second.type_) { case type::empty: { break; } - + case type::singleton: { new(&second.singleton_.table_) std::string(std::move(tempTable)); new(&second.singleton_.column_) std::string(std::move(tempColumn)); second.singleton_.comparison_ = tempComparison; new(&second.singleton_.value_) binding(std::move(tempBinding)); - + break; } - + case type::group: { new(&second.group_.children_) std::list(std::move(tempChildren)); second.group_.orlogic_ = tempOrlogic; - + break; } } } - + statement::condition::~condition() { switch (type_) @@ -744,33 +744,33 @@ namespace verbly { { break; } - + case type::singleton: { using string_type = std::string; - + singleton_.table_.~string_type(); singleton_.column_.~string_type(); singleton_.value_.~binding(); break; } - + case type::group: { using list_type = std::list; - + group_.children_.~list_type(); - + break; } } } - + statement::condition::condition() : type_(type::empty) { } - + statement::condition::condition( std::string table, std::string column, @@ -779,7 +779,7 @@ namespace verbly { { new(&singleton_.table_) std::string(std::move(table)); new(&singleton_.column_) std::string(std::move(column)); - + if (isNull) { singleton_.comparison_ = comparison::is_null; @@ -787,7 +787,7 @@ namespace verbly { singleton_.comparison_ = comparison::is_not_null; } } - + statement::condition::condition( std::string table, std::string column, @@ -800,7 +800,7 @@ namespace verbly { singleton_.comparison_ = comp; new(&singleton_.value_) binding(std::move(value)); } - + std::string statement::condition::toSql() const { switch (type_) @@ -809,7 +809,7 @@ namespace verbly { { return ""; } - + case type::singleton: { switch (singleton_.comparison_) @@ -818,54 +818,54 @@ namespace verbly { { return singleton_.table_ + "." + singleton_.column_ + " = ?"; } - + case comparison::does_not_equal: { return singleton_.table_ + "." + singleton_.column_ + " != ?"; } - + case comparison::is_greater_than: { return singleton_.table_ + "." + singleton_.column_ + " > ?"; } - + case comparison::is_at_most: { return singleton_.table_ + "." + singleton_.column_ + " <= ?"; } - + case comparison::is_less_than: { return singleton_.table_ + "." + singleton_.column_ + " < ?"; } - + case comparison::is_at_least: { return singleton_.table_ + "." + singleton_.column_ + " >= ?"; } - + case comparison::is_like: { return singleton_.table_ + "." + singleton_.column_ + " LIKE ?"; } - + case comparison::is_not_like: { return singleton_.table_ + "." + singleton_.column_ + " NOT LIKE ?"; } - + case comparison::is_not_null: { return singleton_.table_ + "." + singleton_.column_ + " IS NOT NULL"; } - + case comparison::is_null: { return singleton_.table_ + "." + singleton_.column_ + " IS NULL"; } } } - + case type::group: { std::list clauses; @@ -873,12 +873,12 @@ namespace verbly { { clauses.push_back(cond.toSql()); } - + return implode(std::begin(clauses), std::end(clauses), group_.orlogic_ ? " OR " : " AND "); } } } - + std::list statement::condition::flattenBindings() const { switch (type_) @@ -887,7 +887,7 @@ namespace verbly { { return {}; } - + case type::singleton: { switch (singleton_.comparison_) @@ -903,7 +903,7 @@ namespace verbly { { return {singleton_.value_}; } - + case comparison::is_not_null: case comparison::is_null: { @@ -911,7 +911,7 @@ namespace verbly { } } } - + case type::group: { std::list bindings; @@ -922,30 +922,30 @@ namespace verbly { bindings.push_back(std::move(value)); } } - + return bindings; } } } - + statement::condition::condition(bool orlogic) : type_(type::group) { new(&group_.children_) std::list(); group_.orlogic_ = orlogic; } - + statement::condition& statement::condition::operator+=(condition n) { if (type_ == type::group) { group_.children_.push_back(std::move(n)); - + return *this; } else { throw std::domain_error("Cannot add condition to non-group condition"); } } - + statement::condition& statement::condition::operator&=(condition n) { switch (type_) @@ -953,32 +953,32 @@ namespace verbly { case type::empty: { *this = std::move(n); - + break; } - + case type::singleton: { condition grp(false); grp += *this; grp += std::move(n); - + *this = grp; - + break; } - + case type::group: { *this += std::move(n); - + break; } } - + return *this; } - + const std::list& statement::condition::getChildren() const { if (type_ == type::group) @@ -988,5 +988,5 @@ namespace verbly { throw std::domain_error("Cannot get children of non-group condition"); } } - + }; diff --git a/lib/statement.h b/lib/statement.h index 8188ec0..aa56568 100644 --- a/lib/statement.h +++ b/lib/statement.h @@ -11,23 +11,23 @@ #include "filter.h" namespace verbly { - + class filter; - + class statement { public: - + statement(object context, filter queryFilter); - + std::string getQueryString(std::list select, bool random, int limit) const; - + std::list getBindings() const; - + private: - + class join { public: - + join( bool outer, std::string foreignTableName, @@ -43,37 +43,37 @@ namespace verbly { foreignColumn_(std::move(foreignColumn)) { } - + bool isOuterJoin() const { return outer_; } - + const std::string& getForeignTableName() const { return foreignTableName_; } - + const std::string& getJoinTable() const { return joinTable_; } - + const std::string& getJoinColumn() const { return joinColumn_; } - + const std::string& getForeignTable() const { return foreignTable_; } - + const std::string& getForeignColumn() const { return foreignColumn_; } - + private: bool outer_ = false; std::string foreignTableName_; @@ -81,11 +81,11 @@ namespace verbly { std::string joinColumn_; std::string foreignTable_; std::string foreignColumn_; - + }; - + friend std::ostream& operator<<(std::ostream& oss, const join& j); - + class condition { public: enum class type { @@ -93,7 +93,7 @@ namespace verbly { singleton, group }; - + enum class comparison { equals, does_not_equal, @@ -106,57 +106,57 @@ namespace verbly { is_not_null, is_null }; - + // Copy and move constructors - + condition(const condition& other); condition(condition&& other); - + // Assignment - + condition& operator=(condition other); - + // Swap - + friend void swap(condition& first, condition& second); - + // Destructor - + ~condition(); - + // Accessors - + type getType() const { return type_; } - + // Empty - + condition(); - + // Singleton - + condition(std::string table, std::string column, bool isNull); - + condition(std::string table, std::string column, comparison comp, binding value); - + // Group - + explicit condition(bool orlogic); - + condition& operator+=(condition n); - + condition& operator&=(condition n); - + const std::list& getChildren() const; - + // Utility - + std::string toSql() const; - + std::list flattenBindings() const; - + private: union { struct { @@ -172,12 +172,12 @@ namespace verbly { }; type type_; }; - + friend void swap(condition& first, condition& second); - + class with { public: - + with( std::string identifier, field f, @@ -195,42 +195,42 @@ namespace verbly { recursive_(recursive) { } - + const std::string& getIdentifier() const { return identifier_; } - + field getField() const { return field_; } - + std::string getTableForId(std::string identifier) const { return tables_.at(identifier); } - + const std::string& getTopTable() const { return topTable_; } - + const condition& getCondition() const { return topCondition_; } - + const std::list& getJoins() const { return joins_; } - + bool isRecursive() const { return recursive_; } - + private: std::string identifier_; field field_; @@ -239,9 +239,9 @@ namespace verbly { condition topCondition_; std::list joins_; bool recursive_; - + }; - + static constexpr const char* getTableForContext(object context) { return (context == object::notion) ? "notions" @@ -253,22 +253,22 @@ namespace verbly { : (context == object::pronunciation) ? "pronunciations" : throw std::domain_error("Provided context has no associated table"); } - + static const std::list getSelectForContext(object context); - + statement(std::string tableName, filter clause, int nextTableId = 0, int nextWithId = 0); - + condition parseFilter(filter queryFilter); - + std::string instantiateTable(std::string name); - + std::string instantiateWith(std::string name); - + condition integrate(statement subStmt, bool cte = false); - + int nextTableId_; int nextWithId_; - + std::map tables_; std::string topTable_; std::list joins_; @@ -276,7 +276,7 @@ namespace verbly { condition topCondition_; }; - + }; #endif /* end of include guard: STATEMENT_H_29F51659 */ diff --git a/lib/util.h b/lib/util.h index b74b050..9db8678 100644 --- a/lib/util.h +++ b/lib/util.h @@ -6,25 +6,25 @@ #include namespace verbly { - + template std::string implode(InputIterator first, InputIterator last, std::string delimiter) { std::stringstream result; - + for (InputIterator it = first; it != last; it++) { if (it != first) { result << delimiter; } - + result << *it; } - + return result.str(); } - + template void split(std::string input, std::string delimiter, OutputIterator out) { @@ -35,27 +35,27 @@ namespace verbly { { *out = input; out++; - + input = ""; } else { *out = input.substr(0, divider); out++; - + input = input.substr(divider+delimiter.length()); } } } - + template Container split(std::string input, std::string delimiter) { Container result; - + split(input, delimiter, std::back_inserter(result)); - + return result; } - + }; #endif /* end of include guard: UTIL_H_15DDCA2D */ diff --git a/lib/word.cpp b/lib/word.cpp index d13d0bc..a928659 100644 --- a/lib/word.cpp +++ b/lib/word.cpp @@ -6,118 +6,118 @@ #include "query.h" namespace verbly { - + const object word::objectType = object::word; - + const std::list word::select = {"word_id", "notion_id", "lemma_id", "tag_count", "position", "group_id"}; - + const field word::id = field::integerField(object::word, "word_id"); const field word::tagCount = field::integerField(object::word, "tag_count", true); const field word::adjectivePosition = field::integerField(object::word, "position", true); - + const field word::notion = field::joinField(object::word, "notion_id", object::notion); const field word::lemma = field::joinField(object::word, "lemma_id", object::lemma); const field word::group = field::joinField(object::word, "group_id", object::group, true); - + const field word::antonyms = field::selfJoin(object::word, "word_id", "antonymy", "antonym_2_id", "antonym_1_id"); - + const field word::specifications = field::selfJoin(object::word, "word_id", "specification", "general_id", "specific_id"); const field word::generalizations = field::selfJoin(object::word, "word_id", "specification", "specific_id", "general_id"); - + const field word::pertainyms = field::selfJoin(object::word, "word_id", "pertainymy", "noun_id", "pertainym_id"); const field word::antiPertainyms = field::selfJoin(object::word, "word_id", "pertainymy", "pertainym_id", "noun_id"); - + const field word::mannernyms = field::selfJoin(object::word, "word_id", "mannernymy", "adjective_id", "mannernym_id"); const field word::antiMannernyms = field::selfJoin(object::word, "word_id", "mannernymy", "mannernym_id", "adjective_id"); - + const field word::usageTerms = field::selfJoin(object::word, "word_id", "usage", "domain_id", "term_id"); const field word::usageDomains = field::selfJoin(object::word, "word_id", "usage", "term_id", "domain_id"); - + const field word::topicalTerms = field::selfJoin(object::word, "word_id", "topicality", "domain_id", "term_id"); const field word::topicalDomains = field::selfJoin(object::word, "word_id", "topicality", "term_id", "domain_id"); - + const field word::regionalTerms = field::selfJoin(object::word, "word_id", "regionality", "domain_id", "term_id"); const field word::regionalDomains = field::selfJoin(object::word, "word_id", "regionality", "term_id", "domain_id"); - + word::word(const database& db, sqlite3_stmt* row) : db_(&db), valid_(true) { id_ = sqlite3_column_int(row, 0); notionId_ = sqlite3_column_int(row, 1); lemmaId_ = sqlite3_column_int(row, 2); - + if (sqlite3_column_type(row, 3) != SQLITE_NULL) { hasTagCount_ = true; tagCount_ = sqlite3_column_int(row, 3); } - + if (sqlite3_column_type(row, 4) != SQLITE_NULL) { adjectivePosition_ = static_cast(sqlite3_column_int(row, 4)); } - + if (sqlite3_column_type(row, 5) != SQLITE_NULL) { hasGroup_ = true; groupId_ = sqlite3_column_int(row, 5); } } - + const notion& word::getNotion() const { if (!valid_) { throw std::domain_error("Bad access to uninitialized word"); } - + if (!notion_) { notion_ = db_->notions(notion::id == notionId_).first(); } - + return notion_; } - + const lemma& word::getLemma() const { if (!valid_) { throw std::domain_error("Bad access to uninitialized word"); } - + if (!lemma_) { lemma_ = db_->lemmas(lemma::id == lemmaId_).first(); } - + return lemma_; } - + const group& word::getGroup() const { if (!valid_) { throw std::domain_error("Bad access to uninitialized word"); } - + if (!hasGroup_) { throw std::domain_error("Word does not have a group"); } - + if (!group_) { group_ = db_->groups(group::id == groupId_).first(); } - + return group_; } - + std::string word::getBaseForm() const { return getLemma().getBaseForm().getText(); } - + std::vector word::getInflections(inflection category) const { std::vector result; @@ -128,5 +128,5 @@ namespace verbly { return result; } - + }; diff --git a/lib/word.h b/lib/word.h index 7b3c0f7..ddcabe4 100644 --- a/lib/word.h +++ b/lib/word.h @@ -12,157 +12,157 @@ struct sqlite3_stmt; namespace verbly { - + class database; - + class word { public: - + // Default constructor - + word() = default; - + // Construct from database - + word(const database& db, sqlite3_stmt* row); - + // Accessors - + operator bool() const { return valid_; } - + int getId() const { if (!valid_) { throw std::domain_error("Bad access to uninitialized word"); } - + return id_; } - + bool hasTagCount() const { if (!valid_) { throw std::domain_error("Bad access to uninitialized word"); } - + return hasTagCount_; } - + int getTagCount() const { if (!valid_) { throw std::domain_error("Bad access to uninitialized word"); } - + if (!hasTagCount_) { throw std::domain_error("Word has no tag count"); } - + return tagCount_; } - + bool hasAdjectivePositioning() const { if (!valid_) { throw std::domain_error("Bad access to uninitialized word"); } - + return (adjectivePosition_ != positioning::undefined); } - + positioning getAdjectivePosition() const { if (!valid_) { throw std::domain_error("Bad access to uninitialized word"); } - + if (adjectivePosition_ == positioning::undefined) { throw std::domain_error("Word has no adjective position"); } - + return adjectivePosition_; } - + const notion& getNotion() const; - + const lemma& getLemma() const; - + bool hasGroup() const { if (!valid_) { throw std::domain_error("Bad access to uninitialized word"); } - + return hasGroup_; } - + const group& getGroup() const; - + // Convenience accessors - + std::string getBaseForm() const; - + std::vector getInflections(inflection infl) const; - + // Type info - + static const object objectType; - + static const std::list select; - + // Query fields - + static const field id; static const field tagCount; static const field adjectivePosition; - + operator filter() const { return (id == id_); } - + // Relationships with other objects - + static const field notion; static const field lemma; static const field group; - + // Relationships with self - + static const field antonyms; - + static const field specifications; static const field generalizations; - + static const field pertainyms; static const field antiPertainyms; - + static const field mannernyms; static const field antiMannernyms; - + static const field usageTerms; static const field usageDomains; - + static const field topicalTerms; static const field topicalDomains; - + static const field regionalTerms; static const field regionalDomains; - + private: bool valid_ = false; - + int id_; bool hasTagCount_ = false; int tagCount_; @@ -171,15 +171,15 @@ namespace verbly { int lemmaId_; bool hasGroup_ = false; int groupId_; - + const database* db_; - + mutable class notion notion_; mutable class lemma lemma_; mutable class group group_; - + }; - + }; #endif /* end of include guard: WORD_H_DF91B1B4 */ -- cgit 1.4.1