View Javadoc

1   /***
2    * @version $Revision: 1.6 $
3    */
4   package uba.db.sql.interpreter;
5   
6   import java.util.ArrayList;
7   import java.util.HashMap;
8   import java.util.Iterator;
9   import java.util.List;
10  
11  import uba.db.Database;
12  import uba.db.ar.Cartesiano;
13  import uba.db.ar.ConditionEvaluator;
14  import uba.db.ar.Proyector;
15  import uba.db.ar.ProyectorParameter;
16  import uba.db.ar.Seleccion;
17  import uba.db.ar.Tupla;
18  import uba.db.ar.TuplaDef;
19  import uba.db.ar.TupleProvider;
20  import uba.db.column.Column;
21  import uba.db.sql.language.Select;
22  import uba.db.sql.language.SelectionCriteria;
23  import uba.db.sql.language.TableName;
24  import uba.db.table.Table;
25  
26  public class SelectQueryPlan implements SentenceQueryPlan {
27  
28  	private List tables;
29  
30  	private List columnsToProject;
31  
32  	private List columnsToEvaluate;
33  
34  	private Select sentence;
35  
36  	private SelectionCriteria selectionCriteria;
37  
38  	private TupleProvider executionResult;
39  
40  	private String planDetail;
41  
42  	private Database database;
43  
44  	public SelectQueryPlan(Select sqlSentence, Database database) {
45  		tables = new ArrayList();
46  		columnsToProject = new ArrayList();
47  		columnsToEvaluate = new ArrayList();
48  		sentence = sqlSentence;
49  		selectionCriteria = sqlSentence.criteria();
50  		this.database = database;
51  		planDetail = "";
52  	}
53  
54  	/*
55  	 * @see uba.db.sql.interpreter.SentenceQueryPlan#startExecution(uba.db.sql.language.Sentence)
56  	 */
57  	public void startExecution() {
58  		sentence.source().accept(new TablesToJoinVisitor(this, database));
59  		sentence.displayColumns().accept(new ColumnsToProjectVisitor(this));
60  		sentence.criteria().accept(new ColumnsToEvaluateVisitor(this));
61  
62  		TupleProvider combinedTables = combine(tables);
63  		TupleProvider selectedTuples = filter(combinedTables);
64  		executionResult = project(selectedTuples);
65  	}
66  
67  	public void addTable(Table table) {
68  		tables.add(table);
69  	}
70  
71  	private TupleProvider combineSigleTable(List tableNames) {
72  		Table table = (Table) tables.get(0);
73  		TupleProvider tupleProvider = new TableToTupleProviderAdapter(table);
74  		planDetail += "Scan " + table.name() + "\t";
75  		return tupleProvider;
76  	}
77  
78  	private TupleProvider combineMultipleTables(List tableNames) {
79  		Iterator it = tableNames.iterator();
80  		Table firstTable = (Table) it.next();
81  		TupleProvider combinedTable = new TableToTupleProviderAdapter(
82  				firstTable);
83  		Table nextTable;
84  		TupleProvider nextTupleProvider;
85  		planDetail += "Scan " + firstTable.name() + "\t";
86  		while (it.hasNext()) {
87  			nextTable = (Table) it.next();
88  			planDetail += "Scan " + nextTable.name() + "\t";
89  			nextTupleProvider = new TableToTupleProviderAdapter(nextTable);
90  			combinedTable = new Cartesiano(combinedTable, nextTupleProvider);
91  			planDetail += "Producto cartesiano " + combinedTable.toString()
92  					+ "\t";
93  		}
94  		return combinedTable;
95  	}
96  
97  	/***
98  	 * Projecta. ES NECESARIO QUE EL ASTERISCO (*) SEA INTERPRETADO COMO "TODAS
99  	 * LAS COLUMNAS"
100 	 */
101 	private TupleProvider project(TupleProvider tp) {
102 		if (columnsToProject.isEmpty())
103 			return tp;
104 		else {
105 			List indices = averiguarIndices();
106 			planDetail += "Proyeccion " + columnsToProject.toString() + "\t";
107 			return new Proyector(new ProyectorParameter(indices), tp);
108 		}
109 	}
110 
111 	/***
112 	 * @todo mejorar esta manera de detectar el null
113 	 */
114 	private TupleProvider filter(TupleProvider tp) {
115 		if (selectionCriteria.not() == selectionCriteria)
116 			return tp;
117 		else {
118 			planDetail += "Filter " + selectionCriteria.toString() + "\t";
119 			return filtered(tp);
120 		}
121 	}
122 
123 	public List tables() {
124 		return tables;
125 	}
126 
127 	private TupleProvider combine(List tableNames) {
128 		if (tableNames.size() > 1)
129 			return combineMultipleTables(tableNames);
130 		else
131 			return combineSigleTable(tableNames);
132 	}
133 
134 	public Tupla nextTuple() {
135 		return executionResult.next();
136 	}
137 
138 	public String planDetail() {
139 		return planDetail;
140 	}
141 
142 	public boolean hasMoreResults() {
143 		return executionResult.hasNext();
144 	}
145 
146 	public void addColumnToProject(Column column) {
147 		columnsToProject.add(column);
148 	}
149 
150 	public Table tableNamed(TableName tableName) {
151 		Iterator iterator = tables.iterator();
152 		Table table = null;
153 
154 		while (iterator.hasNext() && table == null) {
155 			Table eachTable = (Table) iterator.next();
156 			if (eachTable.name().equalsIgnoreCase(tableName.toString())) {
157 				table = eachTable;
158 
159 			}
160 		}
161 		return table;
162 
163 	}
164 
165 	private List averiguarIndices() {
166 		Iterator iterator = columnsToProject.iterator();
167 		List indices = new ArrayList();
168 		while (iterator.hasNext()) {
169 			Column column = (Column) iterator.next();
170 			int index = column.table().indexOfColumnNamed(column.name());
171 			int fieldsBefore = fieldsBeforeTableAt(indexOfTableOf(column
172 					.table()));
173 			indices.add(new Integer(fieldsBefore + index));
174 		}
175 		return indices;
176 	}
177 
178 	private HashMap qualifiedColumnIndexes() {
179 		Iterator iterator = columnsToEvaluate.iterator();
180 		HashMap indexes = new HashMap();
181 		while (iterator.hasNext()) {
182 			Column column = (Column) iterator.next();
183 			int index = column.table().indexOfColumnNamed(column.name());
184 			int fieldsBefore = fieldsBeforeTableAt(indexOfTableOf(column
185 					.table()));
186 			indexes.put(column.table().name() + column.name(), new Integer(
187 					fieldsBefore + index));
188 		}
189 		return indexes;
190 	}
191 
192 	private int fieldsBeforeTableAt(int i) {
193 		Table table;
194 		int c;
195 		c = 0;
196 		for (int j = 0; j < i; j++) {
197 			table = (Table) tables.get(j);
198 			c += table.columns().size();
199 		}
200 		return c;
201 	}
202 
203 	private int indexOfTableOf(Table table) {
204 		return tables.indexOf(table);
205 	}
206 
207 	private TupleProvider filtered(TupleProvider tp) {
208 		HashMap indexes = qualifiedColumnIndexes();
209 		ConditionEvaluator evaluator = new ConditionEvaluator(
210 				selectionCriteria, indexes);
211 		return new Seleccion(tp, evaluator);
212 	} /*
213 	   * @see uba.db.sql.interpreter.SentenceQueryPlan#tuplaDefinition()
214 	   */
215 
216 	public TuplaDef tuplaDefinition() {
217 		return executionResult.tupleDefinition();
218 	}
219 
220 	public void addColumnToEvaluate(Column column) {
221 		columnsToEvaluate.add(column);
222 	}
223 
224 }