Skip to content

Commit 5a4f7dc

Browse files
committed
Multiple Tables incorporated
1 parent 00e0035 commit 5a4f7dc

File tree

2 files changed

+167
-28
lines changed

2 files changed

+167
-28
lines changed

src/interpreter/SelectProc.java

Lines changed: 166 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,7 @@
33
import parser.SelectStatement;
44
import storageManager.*;
55

6-
import java.util.ArrayList;
7-
import java.util.Iterator;
8-
import java.util.LinkedHashSet;
9-
import java.util.Set;
6+
import java.util.*;
107

118
public class SelectProc extends Procedures {
129
public SelectProc(MainMemory mem, Disk disk, SchemaManager schema_manager) {
@@ -185,22 +182,178 @@ public ArrayList<Tuple> selectTuples(SelectStatement stmt) {
185182
schema_manager.deleteRelation("tempSelect");
186183
}
187184

188-
// Checking DISTINCT clause
189-
if (stmt.isHasDistinct()) {
190-
// System.out.println("In DISTINCT clause ");
191-
Set<Tuple> hs = new LinkedHashSet<>();
192-
hs.addAll(result);
193-
// System.out.println(hs);
194-
result.clear();
195-
result.addAll(hs);
196-
}
197185
} else { // Multiple Table queries
198186

187+
// Create temporary schema and relation to store the combined tuple with fields from all relations
188+
ArrayList<String> temp_Fnames = new ArrayList<String>();
189+
ArrayList<FieldType> temp_Ftypes = new ArrayList<FieldType>();
190+
Schema join_schema = null;
191+
192+
stmt.getTables().forEach(rel -> {
193+
Schema schema = schema_manager.getRelation(rel).getSchema();
194+
schema.getFieldNames().forEach(fname -> {
195+
temp_Fnames.add(rel +"." + fname);
196+
temp_Ftypes.add(schema.getFieldType(fname));
197+
});
198+
});
199+
200+
if (!temp_Fnames.isEmpty()) {
201+
join_schema = new Schema(temp_Fnames, temp_Ftypes);
202+
}
203+
Relation join_relation = schema_manager.createRelation("joinSelect", join_schema);
204+
205+
206+
// Check for Order By clause. If present, sort the given relation and then apply cross product with other
207+
// relations. Always use this relation or its result in Outer loop so as to maintain the sorted order.
208+
if (!(orderCol == null || orderCol.isEmpty())) {
209+
int idx = orderCol.lastIndexOf('.');
210+
if (idx != -1) {
211+
String orderRelName = orderCol.substring(0, idx);
212+
List<String> names = stmt.getTables();
213+
// put the order relation name at first
214+
names.remove(orderRelName);
215+
names.add(0, orderRelName);
216+
stmt.setTables(names);
217+
// get the sorted tuples
218+
result = OrderClause.sortRelation(schema_manager.getRelation(orderRelName),
219+
orderCol.substring(idx + 1), mem, disk, schema_manager);
220+
// eliminate duplicates if required so as to reduce time taken by cross join
221+
if (stmt.isHasDistinct()) {
222+
Set<Tuple> hs = new LinkedHashSet<>();
223+
hs.addAll(result);
224+
result.clear();
225+
result.addAll(hs);
226+
}
227+
result = crossProduct(join_relation, orderRelName, result, stmt.getTables().get(1),
228+
loadTuples(stmt.getTables().get(1), stmt.isHasDistinct()));
229+
} else {
230+
throw new RuntimeException("Relation name not specified in OrderBy clause");
231+
}
232+
} else {
233+
result = crossProduct(join_relation,
234+
stmt.getTables().get(0), loadTuples(stmt.getTables().get(0), stmt.isHasDistinct()),
235+
stmt.getTables().get(1), loadTuples(stmt.getTables().get(1), stmt.isHasDistinct()));
236+
}
237+
for(int i=2; i<stmt.getTables().size(); i++) {
238+
ArrayList<Tuple> loadedTuples = loadTuples(stmt.getTables().get(i), stmt.isHasDistinct());
239+
result = crossProduct(join_relation, null, result, stmt.getTables().get(i), loadedTuples);
240+
}
241+
242+
// Check for where clause. Eliminate tuple not confirming Where clause, if any
243+
if (clause != null) {
244+
Iterator<Tuple> iter = result.iterator();
245+
while (iter.hasNext()) {
246+
Tuple tup = iter.next();
247+
if (!WhereClause.evaluatePostfix(clause, tup))
248+
iter.remove();
249+
}
250+
}
251+
252+
// Projection
253+
if (!"*".equals(stmt.getColumns().get(0))) {
254+
ArrayList<String> tmp_Fnames = new ArrayList<String>();
255+
ArrayList<FieldType> tmp_Ftypes = new ArrayList<FieldType>();
256+
Schema tmp_schema = null;
257+
258+
Schema finalJoin_schema = join_schema;
259+
stmt.getColumns().forEach(s -> {
260+
if (s.lastIndexOf('.') == -1){
261+
throw new RuntimeException("Relation name NOT specified for column " + s);
262+
} else if (!finalJoin_schema.fieldNameExists(s)) {
263+
throw new RuntimeException("No such field " + s + " exists ");
264+
}
265+
tmp_Fnames.add(s);
266+
tmp_Ftypes.add(finalJoin_schema.getFieldType(s));
267+
});
268+
269+
if (!tmp_Fnames.isEmpty()) {
270+
tmp_schema = new Schema(tmp_Fnames, tmp_Ftypes);
271+
}
272+
Relation tmp_relation = schema_manager.createRelation("tmpSelect", tmp_schema);
273+
274+
ArrayList<Tuple> tmpResult = result;
275+
result = new ArrayList<>();
276+
ArrayList<Tuple> finalResult2 = result;
277+
tmpResult.forEach(tuple -> {
278+
Tuple tmp_Tuple = tmp_relation.createTuple();
279+
stmt.getColumns().forEach(s -> {
280+
if (finalJoin_schema.getFieldType(s) == FieldType.INT) {
281+
tmp_Tuple.setField(s, tuple.getField(s).integer);
282+
} else {
283+
tmp_Tuple.setField(s, tuple.getField(s).str);
284+
}
285+
});
286+
finalResult2.add(tmp_Tuple);
287+
});
288+
289+
// Delete temporary relation
290+
schema_manager.deleteRelation("tmpSelect");
291+
}
292+
293+
// Delete Temporary Table
294+
schema_manager.deleteRelation("joinSelect");
199295
}
200296

297+
// Check for eliminating duplicates
298+
if (stmt.isHasDistinct()) {
299+
Set<Tuple> hs = new LinkedHashSet<>();
300+
hs.addAll(result);
301+
result.clear();
302+
result.addAll(hs);
303+
}
201304

202305
System.out.println("Select Procedure Result size \n" + result.size());
203306
System.out.println("Select Procedure Result \n" + result.toString());
204307
return result;
205308
}
309+
310+
public ArrayList<Tuple> crossProduct(Relation relation, String relationName1, ArrayList<Tuple> r1,
311+
String relationName2, ArrayList<Tuple> r2) {
312+
ArrayList<Tuple> result = new ArrayList<>();
313+
Schema schema1 = r1.get(0).getSchema();
314+
Schema schema2 = r2.get(0).getSchema();
315+
316+
r1.forEach(tup1 -> r2.forEach(tup2 -> {
317+
Tuple tuple = relation.createTuple();
318+
schema1.getFieldNames().forEach(s -> {
319+
if (schema1.getFieldType(s) == FieldType.INT) {
320+
tuple.setField((relationName1 == null)? s: relationName1 + "." + s, tup1.getField(s).integer);
321+
} else {
322+
tuple.setField((relationName1 == null)? s: relationName1 + "." + s, tup1.getField(s).str);
323+
}
324+
});
325+
schema2.getFieldNames().forEach(s -> {
326+
if (schema2.getFieldType(s) == FieldType.INT) {
327+
tuple.setField((relationName2 == null)? s: relationName2 + "." + s, tup2.getField(s).integer);
328+
} else {
329+
tuple.setField((relationName2 == null)? s: relationName2 + "." + s, tup2.getField(s).str);
330+
}
331+
});
332+
result.add(tuple);
333+
}));
334+
return result;
335+
}
336+
337+
public ArrayList<Tuple> loadTuples(String relationName, boolean distinct) {
338+
ArrayList<Tuple> result = new ArrayList<>();
339+
Set<Tuple> hashSet = new LinkedHashSet<>();
340+
Relation relation = schema_manager.getRelation(relationName);
341+
int blocksInRel = relation.getNumOfBlocks();
342+
for (int i = 0; i < blocksInRel; i += mem.getMemorySize()) {
343+
// reading blocks from disk in accordance to memory capacity
344+
relation.getBlocks(i, 0, (blocksInRel - i >= mem.getMemorySize()) ?
345+
mem.getMemorySize() : blocksInRel - i);
346+
if (distinct) {
347+
hashSet.addAll(mem.getTuples(0, (blocksInRel - i >= mem.getMemorySize()) ?
348+
mem.getMemorySize() : blocksInRel - i));
349+
} else {
350+
result.addAll(mem.getTuples(0, (blocksInRel - i >= mem.getMemorySize()) ?
351+
mem.getMemorySize() : blocksInRel - i));
352+
}
353+
}
354+
if (distinct) {
355+
result.addAll(hashSet);
356+
}
357+
return result;
358+
}
206359
}

test/flow_test.txt

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -47,22 +47,8 @@ INSERT INTO course2 (sid, exam, grade) VALUES (18, 0, "C")
4747
INSERT INTO course2 (sid, exam, grade) VALUES (2, 99, "B")
4848
INSERT INTO course2 (sid, exam, grade) VALUES (2, 99, "B")
4949
INSERT INTO course2 (sid, exam, grade) VALUES (3, 98, "C")
50-
INSERT INTO course2 (sid, exam, grade) VALUES (6, 65, "B")
51-
INSERT INTO course2 (sid, exam, grade) VALUES (18, 0, "A")
52-
INSERT INTO course2 (sid, exam, grade) VALUES (6, 65, "D")
53-
INSERT INTO course2 (sid, exam, grade) VALUES (18, 0, "C")
54-
INSERT INTO course2 (sid, exam, grade) VALUES (2, 99, "B")
55-
INSERT INTO course2 (sid, exam, grade) VALUES (2, 99, "B")
56-
INSERT INTO course2 (sid, exam, grade) VALUES (3, 98, "C")
57-
INSERT INTO course2 (sid, exam, grade) VALUES (6, 65, "B")
58-
INSERT INTO course2 (sid, exam, grade) VALUES (18, 0, "A")
59-
INSERT INTO course2 (sid, exam, grade) VALUES (6, 65, "D")
60-
INSERT INTO course2 (sid, exam, grade) VALUES (18, 0, "C")
61-
INSERT INTO course2 (sid, exam, grade) VALUES (2, 99, "B")
62-
INSERT INTO course2 (sid, exam, grade) VALUES (2, 99, "B")
63-
INSERT INTO course2 (sid, exam, grade) VALUES (3, 98, "C")
6450

65-
SELECT DISTINCT sid, grade FROM course2 ORDER BY course2.exam
51+
SELECT DISTINCT course.grade, course2.grade FROM course, course2 ORDER BY course2.exam
6652

6753

6854
DROP TABLE course

0 commit comments

Comments
 (0)