Repository navigation
Expand file tree
/
Copy pathForm1.cs
More file actions
273 lines (253 loc) · 10.7 KB
/
Copy pathForm1.cs
File metadata and controls
273 lines (253 loc) · 10.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;
/// <summary>
/// Name: Ido Bueno
/// Date: 08/06/2022
/// </summary>
namespace BackendDeveloperTest
{
/// <summary>
///
/// notes\assumptions:
/// * added another table to extarct data from (Orders) as showen in the question's description
/// and added as an extra table to extract from.
/// * the input (query sentence) and the output (query table data) is showen in the form under
/// the assigned locations for an additional convenience.
/// * added 'key-id' variables as background data like an actual table to the correctness and integrity of the data.
/// * support in bracket veriations and quantities in the 'where' section "()(())...etc"
///
/// manual:
/// 1) write a query extraction sentence in the multi-textbox area.
/// 2) click the "GO" button.
/// 3) the output will appear under the "Query Result" title if any relevant data was found.
/// </summary>
public partial class Form1 : Form
{
Data myData;
public Form1()
{
InitializeComponent();
//data insertion section! you may add additional data rows , format(User) : (email, fullname, age)
// format(User) : (userid, totalcost, userOrdername)
////user examples
this.myData = new Data();
this.myData.Users.Add(new User("jobs@hibernatingrhinos.com", "John Doe", 35));
this.myData.Users.Add(new User("selected.databases@ravendb.net", "ido bueno", 40));
this.myData.Users.Add(new User("selected.databases@ravendb.net", "ruth yehu", 23));
this.myData.Users.Add(new User("jobs@ravendb.net", "bar bar", 10));
this.myData.Users.Add(new User("mynewsql@ravendb.net", "foo man", 23));
this.myData.Users.Add(new User("getmyemail@ravendb.net", "foo1", 100));
this.myData.Users.Add(new User("getmail@ravendb.net", "foo2", 70));
////order examples
this.myData.Orders.Add(new Order(0, 100, "John Doe"));
this.myData.Orders.Add(new Order(2, 200, "ruth roy"));
this.myData.Orders.Add(new Order(1, 87, "ido bueno"));
this.myData.Orders.Add(new Order(3, 16, "bar bar"));
//end
}
/// <summary>
/// the start of the main action
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
this.queryresult.Text = "";
if (this.sqlAction.TextLength > 0)
{
//split the query by the 3 elements: 0- from , 1- where, 2- select
List<string> sqlSentence = this.sqlAction.Text.Split(new string[] { "from ", "FROM ", "select ", "SELECT ", "WHERE ", "where " }, StringSplitOptions.RemoveEmptyEntries).ToList();
List<string> sqltemp = new List<string>();
//remove \r\n
foreach (string s in sqlSentence)
{
string t = s.Replace("\r\n", string.Empty);
sqltemp.Add(t.Replace("\"",string.Empty).Trim());
}
sqlSentence.Clear();
sqlSentence = sqltemp;
//from list
List<string> fromSection = sqlSentence[0].Split(',').ToList();
List<string> whereSection1 = sqlSentence[1].Split(new string[] { " OR ", " or ", " and ", " AND " }, StringSplitOptions.None).ToList();//only numeric\equal commands
List<string> whereSection2 = new List<string>();// only logical commands
List<string> whereSection = new List<string>(); //final list
foreach (string s in this.sqlAction.Text.Split(' ').ToList())
{
if (s == "or" || s == "OR" || s == "and" || s == "AND")
{
whereSection2.Add(s);
}
}
//where list
while (whereSection1.Count > 0)
{
if (whereSection2.Count > 0)
{
whereSection.Add(whereSection1.ElementAt(0));
whereSection1.RemoveAt(0);
whereSection.Add(whereSection2.ElementAt(0));
whereSection2.RemoveAt(0);
}
else
{
whereSection.Add(whereSection1.ElementAt(0));
whereSection1.RemoveAt(0);
}
}
int maxbraket = 0, Bcount = 0;
List<command> myCommandsSet = new List<command>();
foreach (string s in whereSection)
{
//getting the number of braket sets
if (s.Contains("("))
{
Bcount += s.Split('(').Length - 1;
}
int cpriority = Bcount;
if (Bcount > maxbraket)
{
maxbraket = Bcount;
}
if (s.Contains(")"))
{
string[] temp = s.Split(')');
Bcount -= temp.Length - 1;
}
//set the string for extraction as a command
string a = s;
a = a.Replace('(', ' ');
a = a.Replace(')', ' ');
a = a.Replace('\'', ' ');
a = a.Trim();
string[] b = Regex.Replace(a, " {2,}", " ").Split(' ');
//if b is more then 3 strings, string [2..n] is multli-word name
if (b.Length > 3)
{
for(int i =3; i <b.Length;i++ )
{
b[2] = b[2] +" "+b[i];
}
}
command c;
if (b[0] == "or" || b[0] == "OR" || b[0] == "and" || b[0] == "AND")
{
c = new command(null, b[0], null, 1/*commtype*/);
}
else
{
c = new command(b[0], b[1], b[2], 0/*commtype*/);
}
c.priorityCount = cpriority;
myCommandsSet.Add(c);
}
//select list
List<string> selectSection1 = sqlSentence[2].Split(',').ToList();
List<string> selectSection = new List<string>();
selectSection1.ElementAt(selectSection1.Count - 1).Trim('\n', '\r');
for (int i = 0; i < selectSection1.Count; i++)
selectSection.Add(selectSection1.ElementAt(i).Trim());
if (whereSection.Count == 0 || fromSection.Count == 0 || selectSection.Count == 0)
{
Console.WriteLine("something went wrong with the query verification, please try again!");
}
//send the lists to the query engine
command retquery = Data.queryEngine(fromSection, myCommandsSet, selectSection, this.myData, maxbraket);
this.queryresult.Visible = true;
if (fromSection.ElementAt(0) == "Users")
{
this.queryresult.Text = PrintUsers(retquery.quaryResUser, selectSection);
}
else
{
this.queryresult.Text = PrintOrders(retquery.quaryResOrder, selectSection);
}
}
else
{
Console.WriteLine("Please enter a vaild query action!");
}
}
/// <summary>
/// returns string with the requested data columns of table Users
/// </summary>
/// <param name="lu"></param>
/// <param name="selectlist"></param>
/// <returns></returns>
private string PrintUsers(List<User> lu, List<string> selectlist)
{
string s = "";
foreach (User u in lu)
{
s += " | ";
if (selectlist.Contains("FullName"))
s += u.FullName + " | ";
if (selectlist.Contains("Email"))
s += u.Email + " | ";
if (selectlist.Contains("Age"))
s += u.Age + " | ";
s += "\n";
}
return s;
}
/// <summary>
/// returns string with the requested data columns of table Orders
/// </summary>
/// <param name="lo"></param>
/// <param name="selectlist"></param>
/// <returns></returns>
private string PrintOrders(List<Order> lo, List<string> selectlist)
{
string s = "";
foreach (Order u in lo)
{
s += " | ";
if (selectlist.Contains("orderUserName"))
s += u.orderUserName + " | ";
if (selectlist.Contains("totalcost"))
s += u.totalcost + " | ";
s += "\n";
}
return s;
}
}
/// <summary>
/// a class to help with the command-parsing operation
/// </summary>
class command
{
/// <summary>
/// 3 vars to preform a command
/// </summary>
public int commtype; // type =0 string\int operation
// type =1 or\and operation
// type =2 command has already executed and contains only table with answer (in order to make )
public string op1;
public string operand;
public object op2;
//is inside a brakets?
public int priorityCount;
//save resault from query
public List<User> quaryResUser;
public List<Order> quaryResOrder;
public command(string o1, string operand, string o2, int commtype)
{
this.commtype = commtype;
this.op1 = o1;
this.operand = operand;
this.op2 = o2;
priorityCount = 0;
quaryResUser = null; //depends on the query
quaryResOrder = null; //depends on the query
//null until determine the data type that going to be stored
}
}
}