Skip to content

Commit 56b738b

Browse files
committed
First implement where for select
1 parent 2637d63 commit 56b738b

File tree

3 files changed

+273
-17
lines changed

3 files changed

+273
-17
lines changed

src/tests/test_select.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,18 @@ int main() {
3434
.colum("col1")
3535
.colum("col2", "c3")
3636
.colum("col3")
37+
.where()
38+
.equal("col1", "1")
39+
.or_()
40+
.notEqual("col2", "2")
41+
.endWhere()
42+
// .groupBy()
3743
;
3844
if (builder.hasErrors()) {
3945
return -1;
4046
}
4147
std::string sqlQuery = builder.sql();
42-
std::string sqlQueryExpected = "SELECT col1, col2 AS c3, col3 FROM table1";
48+
std::string sqlQueryExpected = "SELECT col1, col2 AS c3, col3 FROM table1 WHERE col1 = \"1\" OR col2 <> \"2\"";
4349
if (sqlQuery != sqlQueryExpected) {
4450
std::cerr
4551
<< "Expected:" << std::endl
@@ -51,8 +57,14 @@ int main() {
5157
}
5258

5359
builder.clear();
54-
55-
60+
sqlQuery = builder.sql();
61+
if (sqlQuery != "") {
62+
std::cerr
63+
<< "Expected empty, but got: " << std::endl
64+
<< " " << sqlQuery << std::endl
65+
;
66+
return -1;
67+
}
5668

5769
return 0;
5870
}

src/wsjcpp_sql_builder.cpp

Lines changed: 189 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -288,11 +288,168 @@ WsjcppSqlBuilderUpdate::WsjcppSqlBuilderUpdate(const std::string &sSqlTable)
288288
: WsjcppSqlQuery(WsjcppSqlBuilderType::UPDATE, sSqlTable) {}
289289

290290

291+
// ---------------------------------------------------------------------
292+
// WsjcppSqlWhereBase
293+
294+
WsjcppSqlWhereBase::WsjcppSqlWhereBase(WsjcppSqlWhereType type) : m_type(type) {
295+
296+
};
297+
298+
WsjcppSqlWhereType WsjcppSqlWhereBase::type() {
299+
return m_type;
300+
}
301+
302+
// ---------------------------------------------------------------------
303+
// WsjcppSqlWhereOr
304+
305+
WsjcppSqlWhereOr::WsjcppSqlWhereOr() : WsjcppSqlWhereBase(WsjcppSqlWhereType::OR) { }
306+
std::string WsjcppSqlWhereOr::sql() { return " OR "; };
307+
308+
// ---------------------------------------------------------------------
309+
// WsjcppSqlWhereAnd
310+
311+
WsjcppSqlWhereAnd::WsjcppSqlWhereAnd() : WsjcppSqlWhereBase(WsjcppSqlWhereType::AND) { }
312+
std::string WsjcppSqlWhereAnd::sql() { return " AND "; };
313+
314+
// ---------------------------------------------------------------------
315+
// WsjcppSqlWhereCondition
316+
317+
WsjcppSqlWhereCondition::WsjcppSqlWhereCondition(
318+
const std::string &name,
319+
WsjcppSqlWhereConditionType comparator,
320+
const std::string &value
321+
)
322+
: WsjcppSqlWhereBase(WsjcppSqlWhereType::CONDITION), m_name(name), m_comparator(comparator), m_value(value) {
323+
324+
}
325+
326+
const std::string &WsjcppSqlWhereCondition::name() {
327+
return m_name;
328+
}
329+
330+
WsjcppSqlWhereConditionType WsjcppSqlWhereCondition::comparator() {
331+
return m_comparator;
332+
}
333+
334+
const std::string &WsjcppSqlWhereCondition::value() {
335+
return m_value;
336+
}
337+
338+
std::string WsjcppSqlWhereCondition::sql() {
339+
std::string ret;
340+
ret += m_name; // TODO validate and escaping
341+
switch (m_comparator) {
342+
case WsjcppSqlWhereConditionType::NOT_EQUAL:
343+
ret += " <> ";
344+
break;
345+
case WsjcppSqlWhereConditionType::EQUAL:
346+
ret += " = ";
347+
break;
348+
case WsjcppSqlWhereConditionType::MORE_THEN:
349+
ret += " > ";
350+
break;
351+
case WsjcppSqlWhereConditionType::LESS_THEN:
352+
ret += " < ";
353+
break;
354+
case WsjcppSqlWhereConditionType::LIKE:
355+
ret += " LIKE ";
356+
break;
357+
default:
358+
ret += " unknwon_operator ";
359+
break;
360+
}
361+
ret += "\"" + m_value + "\""; // TODO validate and escaping
362+
return ret;
363+
}
364+
365+
// ---------------------------------------------------------------------
366+
// WsjcppSqlWhere
367+
368+
WsjcppSqlWhere &WsjcppSqlWhere::cond(const std::string &name, WsjcppSqlWhereConditionType comparator, const std::string &value) {
369+
if (
370+
m_conditions.size() > 0
371+
&& m_conditions[m_conditions.size()-1]->type() == WsjcppSqlWhereType::CONDITION
372+
) {
373+
and_(); // default add and_
374+
}
375+
376+
m_conditions.push_back(std::make_shared<WsjcppSqlWhereCondition>(name, comparator, value));
377+
return *this;
378+
}
379+
380+
WsjcppSqlWhere &WsjcppSqlWhere::notEqual(const std::string &name, const std::string &value) {
381+
cond(name, WsjcppSqlWhereConditionType::NOT_EQUAL, value);
382+
return *this;
383+
}
384+
385+
WsjcppSqlWhere &WsjcppSqlWhere::equal(const std::string &name, const std::string &value) {
386+
cond(name, WsjcppSqlWhereConditionType::EQUAL, value);
387+
return *this;
388+
}
389+
390+
WsjcppSqlWhere &WsjcppSqlWhere::moreThen(const std::string &name, const std::string &value) {
391+
cond(name, WsjcppSqlWhereConditionType::MORE_THEN, value);
392+
return *this;
393+
}
394+
395+
WsjcppSqlWhere &WsjcppSqlWhere::lessThen(const std::string &name, const std::string &value) {
396+
cond(name, WsjcppSqlWhereConditionType::LESS_THEN, value);
397+
return *this;
398+
}
399+
400+
WsjcppSqlWhere &WsjcppSqlWhere::like(const std::string &name, const std::string &value) {
401+
cond(name, WsjcppSqlWhereConditionType::LIKE, value);
402+
return *this;
403+
}
404+
405+
406+
WsjcppSqlWhere &WsjcppSqlWhere::or_() {
407+
if (
408+
m_conditions.size() > 0
409+
&& (
410+
m_conditions[m_conditions.size()-1]->type() == WsjcppSqlWhereType::OR
411+
|| m_conditions[m_conditions.size()-1]->type() == WsjcppSqlWhereType::AND
412+
)
413+
) {
414+
// TODO add to builder errors;
415+
// std::cerr << "[WARNING] WsjcppSqlWhere. Last item alredy defined 'or' or 'and'. current will be skipped." << std::endl;
416+
return *this;
417+
}
418+
419+
m_conditions.push_back(std::make_shared<WsjcppSqlWhereOr>());
420+
return *this;
421+
}
422+
423+
WsjcppSqlWhere &WsjcppSqlWhere::and_() {
424+
if (
425+
m_conditions.size() > 0
426+
&& (
427+
m_conditions[m_conditions.size()-1]->type() == WsjcppSqlWhereType::OR
428+
|| m_conditions[m_conditions.size()-1]->type() == WsjcppSqlWhereType::AND
429+
)
430+
) {
431+
// TODO add to builder errors;
432+
// std::cerr << "[WARNING] WsjcppSqlWhere. Last item alredy defined 'or' or 'and'. current will be skipped." << std::endl;
433+
return *this;
434+
}
435+
m_conditions.push_back(std::make_shared<WsjcppSqlWhereAnd>());
436+
return *this;
437+
}
438+
439+
std::string WsjcppSqlWhere::sql() {
440+
std::string ret = "";
441+
for (auto item : m_conditions) {
442+
ret += item->sql();
443+
}
444+
return ret;
445+
};
446+
291447
// ---------------------------------------------------------------------
292448
// WsjcppSqlBuilderUpdate
293449

294450
WsjcppSqlSelect::WsjcppSqlSelect(const std::string &tableName, WsjcppSqlBuilder2 *builder)
295451
: WsjcppSqlQuery(WsjcppSqlBuilderType::SELECT, tableName) {
452+
// TODO multitype table names with AS
296453
m_tableName = tableName;
297454
m_builder = builder;
298455
}
@@ -308,26 +465,46 @@ WsjcppSqlSelect &WsjcppSqlSelect::colum(const std::string &col, const std::strin
308465
return *this;
309466
}
310467

468+
// WsjcppSqlWhere<WsjcppSqlSelect> &WsjcppSqlSelect::where() {
469+
WsjcppSqlWhere &WsjcppSqlSelect::where() {
470+
if (!m_where) {
471+
// m_where = std::make_shared<WsjcppSqlWhere<WsjcppSqlSelect>>();
472+
m_where = std::make_shared<WsjcppSqlWhere>(m_builder, this);
473+
}
474+
475+
return *(m_where.get());
476+
}
477+
311478
WsjcppSqlBuilder2 &WsjcppSqlSelect::compile() {
312479
return *m_builder;
313480
}
314481

315482
std::string WsjcppSqlSelect::sql() {
316483
std::string ret = "SELECT ";
317484
// TODO TOP OR LIMIT for different databases
318-
bool first = true;
319-
for (auto col : m_columns) {
320-
if (!first) {
321-
ret += ", ";
322-
}
323-
ret += col;
324-
if (m_columns_as[col] != "") {
325-
ret += " AS " + m_columns_as[col];
485+
486+
if (m_columns.size() == 0) {
487+
ret += "*";
488+
} else {
489+
bool first = true;
490+
for (auto col : m_columns) {
491+
if (!first) {
492+
ret += ", ";
493+
}
494+
ret += col;
495+
if (m_columns_as[col] != "") {
496+
ret += " AS " + m_columns_as[col];
497+
}
498+
first = false;
326499
}
327-
first = false;
500+
ret += " FROM ";
501+
ret += m_tableName;
502+
}
503+
504+
if (m_where) {
505+
ret += " WHERE " + m_where->sql();
328506
}
329-
ret += " FROM ";
330-
ret += m_tableName;
507+
331508
// TODO where
332509
// TODO group by
333510
// TODO order by
@@ -341,6 +518,7 @@ WsjcppSqlSelect &WsjcppSqlBuilder2::selectFrom(const std::string &tableName) {
341518
m_tableName = tableName;
342519
m_nSqlType = WsjcppSqlBuilderType::SELECT;
343520
m_queries.push_back(std::make_shared<WsjcppSqlSelect>(m_tableName, this));
521+
// TODO check must be select last one;
344522
return *(WsjcppSqlSelect *)(m_queries[m_queries.size() -1].get());
345523
}
346524

src/wsjcpp_sql_builder.h

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,20 +85,83 @@ class WsjcppSqlBuilderUpdate : public WsjcppSqlQuery {
8585

8686
class WsjcppSqlBuilder2;
8787

88-
class WsjcppSqlWhere {
88+
89+
enum class WsjcppSqlWhereType { OR, AND, CONDITION, SUB };
90+
91+
class WsjcppSqlWhereBase {
8992
public:
90-
WsjcppSqlWhere();
93+
WsjcppSqlWhereBase(WsjcppSqlWhereType type);
94+
WsjcppSqlWhereType type();
95+
virtual std::string sql() = 0;
96+
9197
private:
98+
WsjcppSqlWhereType m_type;
99+
};
100+
101+
class WsjcppSqlWhereOr : public WsjcppSqlWhereBase {
102+
public:
103+
WsjcppSqlWhereOr();
104+
virtual std::string sql() override;
105+
};
106+
107+
class WsjcppSqlWhereAnd : public WsjcppSqlWhereBase {
108+
public:
109+
WsjcppSqlWhereAnd();
110+
virtual std::string sql() override;
111+
};
112+
113+
enum class WsjcppSqlWhereConditionType { NOT_EQUAL, EQUAL, MORE_THEN, LESS_THEN, LIKE };
92114

115+
class WsjcppSqlWhereCondition : public WsjcppSqlWhereBase {
116+
public:
117+
WsjcppSqlWhereCondition(const std::string &name, WsjcppSqlWhereConditionType comparator, const std::string &value);
118+
const std::string &name();
119+
WsjcppSqlWhereConditionType comparator();
120+
const std::string &value();
121+
virtual std::string sql() override;
122+
private:
123+
std::string m_name;
124+
std::string m_value;
125+
WsjcppSqlWhereConditionType m_comparator;
93126
};
94127

128+
class WsjcppSqlSelect;
129+
130+
// template<class T>
131+
class WsjcppSqlWhere : public WsjcppSqlWhereBase {
132+
public:
133+
// WsjcppSqlWhere(WsjcppSqlBuilder2 *builder, T *query) : WsjcppSqlWhereBase(WsjcppSqlWhereType::SUB), m_builder(builder), m_query(query) { }
134+
WsjcppSqlWhere(WsjcppSqlBuilder2 *builder, WsjcppSqlSelect *query) : WsjcppSqlWhereBase(WsjcppSqlWhereType::SUB), m_builder(builder), m_query(query) { }
135+
WsjcppSqlWhere &notEqual(const std::string &name, const std::string &value);
136+
WsjcppSqlWhere &equal(const std::string &name, const std::string &value);
137+
WsjcppSqlWhere &moreThen(const std::string &name, const std::string &value);
138+
WsjcppSqlWhere &lessThen(const std::string &name, const std::string &value);
139+
WsjcppSqlWhere &like(const std::string &name, const std::string &value);
140+
141+
WsjcppSqlWhere &or_();
142+
WsjcppSqlWhere &and_();
143+
// T &endWhere() {
144+
WsjcppSqlSelect &endWhere() {
145+
return *m_query;
146+
}
147+
148+
virtual std::string sql() override;
149+
150+
private:
151+
WsjcppSqlWhere &cond(const std::string &name, WsjcppSqlWhereConditionType comparator, const std::string &value);
152+
153+
WsjcppSqlBuilder2 *m_builder;
154+
// T *m_query;
155+
WsjcppSqlSelect *m_query;
156+
std::vector<std::shared_ptr<WsjcppSqlWhereBase>> m_conditions;
157+
};
95158

96159
class WsjcppSqlSelect : public WsjcppSqlQuery {
97160
public:
98161
WsjcppSqlSelect(const std::string &tableName, WsjcppSqlBuilder2 *builder);
99162
WsjcppSqlSelect &colum(const std::string &col, const std::string &col_as = "");
100163

101-
// TODO where
164+
WsjcppSqlWhere &where();
102165
// TODO group by
103166
// TODO order by
104167
WsjcppSqlBuilder2 &compile();
@@ -107,12 +170,15 @@ class WsjcppSqlSelect : public WsjcppSqlQuery {
107170
private:
108171
std::string m_tableName;
109172
WsjcppSqlBuilder2 *m_builder;
173+
std::shared_ptr<WsjcppSqlWhere> m_where;
110174
std::vector<std::string> m_columns;
111175
std::map<std::string, std::string> m_columns_as;
112176
};
113177

114178
class WsjcppSqlBuilder2 {
115179
public:
180+
// TODO begin / end transaction can be added here
181+
116182
WsjcppSqlSelect &selectFrom(const std::string &sSqlTable);
117183
WsjcppSqlBuilder2 &makeInsert(const std::string &sSqlTable);
118184
WsjcppSqlBuilder2 &makeUpdate(const std::string &sSqlTable);

0 commit comments

Comments
 (0)