Skip to content

Commit 7554062

Browse files
committed
Added first implementation from fhq-server
1 parent a8d7bc9 commit 7554062

File tree

7 files changed

+416
-11
lines changed

7 files changed

+416
-11
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ set(EXECUTABLE_OUTPUT_PATH ${wsjcpp-sql-builder_SOURCE_DIR})
1111
list (APPEND WSJCPP_INCLUDE_DIRS "src")
1212

1313
list (APPEND WSJCPP_SOURCES "src/main.cpp")
14+
list (APPEND WSJCPP_SOURCES "src/wsjcpp_sql_builder.cpp")
1415

1516
#### BEGIN_WSJCPP_APPEND
1617
#### END_WSJCPP_APPEND

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2025 wsjcpp
3+
Copyright (c) 2025 Evgenii Sopov <mrseakg@gmail.com>
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

README.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,41 @@
11
# wsjcpp-sql-builder
2+
23
C++ Class-helper for build SQL queries
4+
5+
## How to integrate to your project
6+
7+
via wsjcpp:
8+
```
9+
$ wsjcpp install https://github.com/wsjcpp/wsjcpp-sql-builder:master
10+
```
11+
12+
or include this files:
13+
14+
- src/wsjcpp_sql_builder.h
15+
- src/wsjcpp_sql_builder.cpp
16+
17+
18+
## How use this
19+
20+
Example main func:
21+
```
22+
#include <wsjcpp_sql_builder.h>
23+
24+
int main(int argc, const char* argv[]) {
25+
// init employees
26+
bool bSilent = false;
27+
WsjcppEmployeesInit empls({}, bSilent);
28+
if (!empls.inited) {
29+
WsjcppLog::err(TAG, "Could not init employees");
30+
return -1;
31+
}
32+
return 0;
33+
}
34+
```
35+
36+
Example output:
37+
```
38+
% ./wsjcpp-employees
39+
2020-03-22 11:32:31.750, 0x0x110c21dc0 [INFO] WJSCppEmployRuntimeGlobalCache: init
40+
2020-03-22 11:32:31.750, 0x0x110c21dc0 [OK] Employees_init: Init WJSCppEmployRuntimeGlobalCache ... OK
41+
```

src/main.cpp

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
#include <string.h>
22
#include <iostream>
3-
#include <algorithm>
4-
#include <wsjcpp_core.h>
3+
#include <wsjcpp_sql_builder.h>
54

65
int main(int argc, const char* argv[]) {
7-
std::string TAG = "MAIN";
8-
std::string appName = std::string(WSJCPP_APP_NAME);
9-
std::string appVersion = std::string(WSJCPP_APP_VERSION);
10-
if (!WsjcppCore::dirExists(".logs")) {
11-
WsjcppCore::makeDir(".logs");
6+
WsjcppSqlBuilderInsert sql("TABLE_NAME");
7+
sql.add("COL1", "val1"); // will be escaped
8+
sql.add("COL2", 1);
9+
// sql.add("COL3", 1.1);
10+
if (!sql.isValid()) {
11+
std::cerr << "Something wrong with query: " << sql.getErrorMessage() << std::endl;
12+
return -1;
1213
}
13-
WsjcppLog::setPrefixLogFile("wsjcpp");
14-
WsjcppLog::setLogDirectory(".logs");
1514

16-
// TODO your code here
15+
std::cout << sql.getTextQuery() << std::endl;
1716

1817
return 0;
1918
}

src/wsjcpp_sql_builder.cpp

Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
/**********************************************************************************
2+
* MIT License
3+
*
4+
* Copyright (c) 2025 Evgenii Sopov <mrseakg@gmail.com>
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*
24+
***********************************************************************************/
25+
26+
#include "wsjcpp_sql_builder.h"
27+
28+
// ---------------------------------------------------------------------
29+
// WsjcppSqlBuilder
30+
31+
WsjcppSqlBuilder::WsjcppSqlBuilder(
32+
WsjcppSqlBuilderType nSqlType, const std::string &sSqlTable
33+
) {
34+
m_nSqlType = nSqlType;
35+
m_sSqlTable = sSqlTable;
36+
m_bValid = true;
37+
if (m_nSqlType == WsjcppSqlBuilderType::SELECT) {
38+
m_sSqlQuery0 = "SELECT ";
39+
m_sSqlQuery1 = " FROM " + sSqlTable;
40+
m_sSqlQuery2 = "";
41+
} else if (m_nSqlType == WsjcppSqlBuilderType::INSERT) {
42+
m_sSqlQuery0 = "INSERT INTO " + sSqlTable + "(";
43+
m_sSqlQuery1 = ") VALUES (";
44+
m_sSqlQuery2 = ");";
45+
} else if (m_nSqlType == WsjcppSqlBuilderType::UPDATE) {
46+
m_sSqlQuery0 = "UPDATE " + sSqlTable + " SET ";
47+
m_sSqlQuery1 = " WHERE ";
48+
} else {
49+
m_sErrorMessage = "Unknown sql type";
50+
m_bValid = false;
51+
}
52+
}
53+
54+
bool WsjcppSqlBuilder::sel(const std::string &sColumnName) {
55+
if (!checkName(sColumnName)) {
56+
return false;
57+
}
58+
m_sSqlQuery0 += sColumnName + ", ";
59+
return true;
60+
}
61+
62+
bool WsjcppSqlBuilder::add(const std::string &sColumnName, const std::string &sValue) {
63+
if (!checkName(sColumnName)) {
64+
return false;
65+
}
66+
if (m_nSqlType == WsjcppSqlBuilderType::SELECT) {
67+
m_sErrorMessage = "For select you could not use 'add'";
68+
m_bValid = false;
69+
} else if (m_nSqlType == WsjcppSqlBuilderType::INSERT) {
70+
m_sSqlQuery0 += sColumnName + ", ";
71+
m_sSqlQuery1 += prepareStringValue(sValue) + ", ";
72+
} else if (m_nSqlType == WsjcppSqlBuilderType::UPDATE) {
73+
m_sSqlQuery0 += sColumnName + " = " + prepareStringValue(sValue);
74+
} else {
75+
m_sErrorMessage = "Unknown sql type";
76+
m_bValid = false;
77+
}
78+
79+
// m_sSqlQuery = sBefore + sEscapedValue + sAfter;
80+
81+
// while (true) {
82+
// /* Locate the substring to replace. */
83+
// index = str.find(sName, index);
84+
// if (index == std::string::npos)
85+
// return false;
86+
87+
// /* Make the replacement. */
88+
// str.replace(index, 3, "def");
89+
90+
// /* Advance index forward so the next iteration doesn't pick it up as well. */
91+
// index += 3;
92+
// }
93+
return true;
94+
}
95+
96+
bool WsjcppSqlBuilder::add(const std::string &sColumnName, int nValue) {
97+
if (!checkName(sColumnName)) {
98+
return false;
99+
}
100+
101+
if (m_nSqlType == WsjcppSqlBuilderType::SELECT) {
102+
m_sErrorMessage = "For select you could not use 'add'";
103+
m_bValid = false;
104+
} else if (m_nSqlType == WsjcppSqlBuilderType::INSERT) {
105+
m_sSqlQuery0 += sColumnName + ", ";
106+
m_sSqlQuery1 += std::to_string(nValue) + ", ";
107+
} else if (m_nSqlType == WsjcppSqlBuilderType::UPDATE) {
108+
m_sSqlQuery0 += sColumnName + " = " + std::to_string(nValue);
109+
}
110+
111+
return true;
112+
}
113+
114+
bool WsjcppSqlBuilder::add(const std::string &sColumnName, long nValue) {
115+
if (!checkName(sColumnName)) {
116+
return false;
117+
}
118+
119+
if (m_nSqlType == WsjcppSqlBuilderType::SELECT) {
120+
m_sErrorMessage = "For select you could not use 'add'";
121+
m_bValid = false;
122+
} else if (m_nSqlType == WsjcppSqlBuilderType::INSERT) {
123+
m_sSqlQuery0 += sColumnName + ", ";
124+
m_sSqlQuery1 += std::to_string(nValue) + ", ";
125+
} else if (m_nSqlType == WsjcppSqlBuilderType::UPDATE) {
126+
m_sSqlQuery0 += sColumnName + " = " + std::to_string(nValue);
127+
}
128+
129+
return true;
130+
}
131+
132+
bool WsjcppSqlBuilder::where(const std::string &sColumnName, const std::string &sValue) {
133+
if (!checkName(sColumnName)) {
134+
return false;
135+
}
136+
if (m_nSqlType == WsjcppSqlBuilderType::SELECT) {
137+
m_sSqlQuery2 += sColumnName + " = " + prepareStringValue(sValue);
138+
} else if (m_nSqlType == WsjcppSqlBuilderType::INSERT) {
139+
m_sErrorMessage = "where can be in insert";
140+
return false;
141+
} else if (m_nSqlType == WsjcppSqlBuilderType::UPDATE) {
142+
m_sSqlQuery1 += sColumnName + " = " + prepareStringValue(sValue);
143+
}
144+
145+
return true;
146+
}
147+
148+
bool WsjcppSqlBuilder::where(const std::string &sColumnName, int nValue) {
149+
if (!checkName(sColumnName)) {
150+
return false;
151+
}
152+
if (m_nSqlType == WsjcppSqlBuilderType::SELECT) {
153+
m_sSqlQuery2 += sColumnName + " = " + std::to_string(nValue);
154+
} else if (m_nSqlType == WsjcppSqlBuilderType::INSERT) {
155+
m_sErrorMessage = "where can be in insert";
156+
return false;
157+
} else if (m_nSqlType == WsjcppSqlBuilderType::UPDATE) {
158+
m_sSqlQuery1 += sColumnName + " = " + std::to_string(nValue);
159+
}
160+
return true;
161+
}
162+
163+
bool WsjcppSqlBuilder::where(const std::string &sColumnName, long nValue) {
164+
if (!checkName(sColumnName)) {
165+
return false;
166+
}
167+
if (m_nSqlType == WsjcppSqlBuilderType::SELECT) {
168+
m_sSqlQuery2 += sColumnName + " = " + std::to_string(nValue);
169+
} else if (m_nSqlType == WsjcppSqlBuilderType::INSERT) {
170+
m_sErrorMessage = "where can be in insert";
171+
return false;
172+
} else if (m_nSqlType == WsjcppSqlBuilderType::UPDATE) {
173+
m_sSqlQuery1 += sColumnName + " = " + std::to_string(nValue);
174+
}
175+
return true;
176+
}
177+
178+
std::string WsjcppSqlBuilder::getTextQuery() {
179+
std::string sSqlQuery = "";
180+
size_t size0 = m_sSqlQuery0.size();
181+
size_t size1 = m_sSqlQuery1.size();
182+
size_t size2 = m_sSqlQuery2.size();
183+
if (m_nSqlType == WsjcppSqlBuilderType::SELECT) {
184+
// TODO refactor this to vector and join
185+
sSqlQuery = m_sSqlQuery0;
186+
if (size0 > 2 && m_sSqlQuery0[size0 - 1] == ' ' && m_sSqlQuery0[size0 - 2] == ',') {
187+
sSqlQuery += m_sSqlQuery0.substr(0, size0 - 2);
188+
}
189+
sSqlQuery += m_sSqlQuery1;
190+
if (size2 > 2 && m_sSqlQuery2[size2 - 1] == ' ' && m_sSqlQuery2[size2 - 2] == ',') {
191+
sSqlQuery += m_sSqlQuery2.substr(0, size2 - 2);
192+
}
193+
} else if (m_nSqlType == WsjcppSqlBuilderType::INSERT) {
194+
if (size0 > 2 && m_sSqlQuery0[size0 - 1] == ' ' && m_sSqlQuery0[size0 - 2] == ',') {
195+
sSqlQuery += m_sSqlQuery0.substr(0, size0 - 2);
196+
}
197+
if (size1 > 2 && m_sSqlQuery1[size1 - 1] == ' ' && m_sSqlQuery1[size1 - 2] == ',') {
198+
sSqlQuery += m_sSqlQuery1.substr(0, size1 - 2);
199+
}
200+
sSqlQuery += m_sSqlQuery2;
201+
} else if (m_nSqlType == WsjcppSqlBuilderType::UPDATE) {
202+
sSqlQuery = m_sSqlQuery0 + m_sSqlQuery1 + m_sSqlQuery2;
203+
}
204+
return sSqlQuery;
205+
}
206+
207+
bool WsjcppSqlBuilder::isValid() { return m_bValid; }
208+
209+
std::string WsjcppSqlBuilder::getErrorMessage() { return m_sErrorMessage; }
210+
211+
bool WsjcppSqlBuilder::checkName(const std::string &sColumnName) {
212+
if (sColumnName.size() < 2) {
213+
m_sErrorMessage = "Parameter '" + sColumnName + "' must more than 2 characters";
214+
m_bValid = false;
215+
return false;
216+
}
217+
// TODO check alphabet
218+
219+
// if (sName[0] != ':') {
220+
// m_sErrorMessage = "Parameter '" + sName + "' must starts with ':'";
221+
// m_bValid = false;
222+
// return false;
223+
// }
224+
// nIndex = m_sSqlQuery.find(sName, 0);
225+
// if (nIndex == std::string::npos) {
226+
// m_sErrorMessage = "Not found '" + sName + "' in " + m_sSqlQuery;
227+
// m_bValid = false;
228+
// return false;
229+
// }
230+
return true;
231+
}
232+
233+
std::string WsjcppSqlBuilder::prepareStringValue(const std::string &sValue) {
234+
// escaping simbols NUL (ASCII 0), \n, \r, \, ', ", и Control-Z.
235+
std::string sResult;
236+
sResult.reserve(sValue.size() * 2);
237+
sResult.push_back('\'');
238+
for (int i = 0; i < sValue.size(); i++) {
239+
char c = sValue[i];
240+
if (c == '\n') {
241+
sResult.push_back('\\');
242+
sResult.push_back('n');
243+
} else if (c == '\r') {
244+
sResult.push_back('\\');
245+
sResult.push_back('r');
246+
} else if (c == '\\' || c == '"') {
247+
sResult.push_back('\\');
248+
sResult.push_back(c);
249+
} else if (c == '\'') {
250+
sResult.push_back('\'');
251+
sResult.push_back(c);
252+
} else if (c == 0) {
253+
sResult.push_back('\\');
254+
sResult.push_back('0');
255+
} else {
256+
sResult.push_back(c);
257+
}
258+
}
259+
sResult.push_back('\'');
260+
return sResult;
261+
}
262+
263+
// ---------------------------------------------------------------------
264+
// WsjcppSqlBuilderSelect
265+
266+
WsjcppSqlBuilderSelect::WsjcppSqlBuilderSelect(const std::string &sSqlTable)
267+
: WsjcppSqlBuilder(WsjcppSqlBuilderType::SELECT, sSqlTable) {}
268+
269+
// ---------------------------------------------------------------------
270+
// WsjcppSqlBuilderInsert
271+
272+
WsjcppSqlBuilderInsert::WsjcppSqlBuilderInsert(const std::string &sSqlTable)
273+
: WsjcppSqlBuilder(WsjcppSqlBuilderType::INSERT, sSqlTable) {}
274+
275+
// ---------------------------------------------------------------------
276+
// WsjcppSqlBuilderUpdate
277+
278+
WsjcppSqlBuilderUpdate::WsjcppSqlBuilderUpdate(const std::string &sSqlTable)
279+
: WsjcppSqlBuilder(WsjcppSqlBuilderType::UPDATE, sSqlTable) {}

0 commit comments

Comments
 (0)