|
| 1 | +#include "llvm/ADT/StringExtras.h" |
| 2 | +#include "llvm/ADT/StringMap.h" |
| 3 | +#include "Error.h" |
| 4 | +#include "SQLQueryEmitter.h" |
| 5 | + |
| 6 | +using namespace llvm; |
| 7 | + |
| 8 | +namespace { |
| 9 | +class SQLWhereClauseEmitter { |
| 10 | + raw_ostream &OS; |
| 11 | + |
| 12 | +public: |
| 13 | + SQLWhereClauseEmitter(raw_ostream &OS) : OS(OS) {} |
| 14 | + |
| 15 | + Error run(const DagInit *WhereClause); |
| 16 | +}; |
| 17 | +} // end anonymous namespace |
| 18 | + |
| 19 | +Error SQLWhereClauseEmitter::run(const DagInit *WhereClause) { |
| 20 | + // TODO: Build an operator tree and visit it in an infix fashion. |
| 21 | + return Error::success(); |
| 22 | +} |
| 23 | + |
| 24 | +Error SQLQueryEmitter::run(ArrayRef<const Record *> Queries, |
| 25 | + ArrayRef<const Record *> Operators) { |
| 26 | + // Map from the tag name to its corresponding SQL table field name. |
| 27 | + StringMap<StringRef> FieldTagMap; |
| 28 | + |
| 29 | + for (const auto *QueryRecord : Queries) { |
| 30 | + auto MaybeTableName = QueryRecord->getValueAsOptionalString("TableName"); |
| 31 | + if (!MaybeTableName || MaybeTableName->empty()) |
| 32 | + return createTGStringError(QueryRecord->getLoc()[0], "SQL table name " |
| 33 | + "is missing"); |
| 34 | + auto TableName = *MaybeTableName; |
| 35 | + |
| 36 | + OS << "SELECT "; |
| 37 | + |
| 38 | + const DagInit *FieldsInit = QueryRecord->getValueAsDag("Fields"); |
| 39 | + auto FieldOpName = FieldsInit->getOperator()->getAsString(); |
| 40 | + if (FieldOpName == "all") |
| 41 | + OS << "*"; |
| 42 | + else if (FieldOpName != "fields") |
| 43 | + // FIXME: This is a terrible SMLoc to use here. |
| 44 | + return createTGStringError(QueryRecord->getLoc()[0], "Invalid dag operator" |
| 45 | + " \"" + FieldOpName + "\""); |
| 46 | + |
| 47 | + FieldTagMap.clear(); |
| 48 | + { |
| 49 | + ListSeparator LS; |
| 50 | + for (unsigned i = 0U; i != FieldsInit->arg_size(); ++i) |
| 51 | + if (const auto *Field = dyn_cast<StringInit>(FieldsInit->getArg(i))) { |
| 52 | + OS << LS << Field->getValue(); |
| 53 | + if (const auto *Tag = FieldsInit->getArgName(i)) |
| 54 | + FieldTagMap.insert({Tag->getValue(), Field->getValue()}); |
| 55 | + } |
| 56 | + } |
| 57 | + |
| 58 | + OS << " FROM " << TableName; |
| 59 | + |
| 60 | + const DagInit *WhereClause = QueryRecord->getValueAsDag("WhereClause"); |
| 61 | + if (WhereClause->getOperator()->getAsString() != "none") { |
| 62 | + OS << "\n"; |
| 63 | + if (auto E = SQLWhereClauseEmitter(OS).run(WhereClause)) |
| 64 | + return std::move(E); |
| 65 | + } |
| 66 | + |
| 67 | + auto OrderedBy = QueryRecord->getValueAsListOfStrings("OrderedBy"); |
| 68 | + if (OrderedBy.size()) { |
| 69 | + OS << "\n"; |
| 70 | + OS << "ORDER BY "; |
| 71 | + ListSeparator LS; |
| 72 | + for (auto FieldOrTag : OrderedBy) { |
| 73 | + auto FieldName = FieldOrTag; |
| 74 | + if (FieldOrTag.startswith("$")) { |
| 75 | + // It's a tag |
| 76 | + auto TagName = FieldOrTag.drop_front(1); |
| 77 | + auto I = FieldTagMap.find(TagName); |
| 78 | + if (I == FieldTagMap.end()) |
| 79 | + return createTGStringError(QueryRecord->getLoc()[0], "Unrecognized " |
| 80 | + "tag \"" + TagName + "\""); |
| 81 | + FieldName = I->second; |
| 82 | + } |
| 83 | + OS << LS << FieldName; |
| 84 | + } |
| 85 | + } |
| 86 | + |
| 87 | + OS << ";\n\n"; |
| 88 | + } |
| 89 | + |
| 90 | + return Error::success(); |
| 91 | +} |
0 commit comments