Add further unit tests.
[cfb.git] / test / net / jaekl / cfb / db / driver / DbDriverMock.java
1 package net.jaekl.cfb.db.driver;
2
3 import static org.junit.Assert.assertEquals;
4 import static org.junit.Assert.assertFalse;
5 import static org.junit.Assert.assertNotNull;
6 import static org.junit.Assert.assertTrue;
7
8 import java.sql.Connection;
9 import java.sql.SQLException;
10 import java.util.ArrayList;
11 import java.util.Date;
12 import java.util.HashMap;
13 import java.util.List;
14
15 import net.jaekl.cfb.db.Column;
16 import net.jaekl.cfb.db.Condition;
17 import net.jaekl.cfb.db.Row;
18 import net.jaekl.cfb.db.Sequence;
19 import net.jaekl.cfb.db.SequenceMock;
20 import net.jaekl.cfb.db.Sort;
21 import net.jaekl.cfb.db.Table;
22 import net.jaekl.cfb.db.TableMock;
23 import net.jaekl.cfb.db.TypeMismatchException;
24 import net.jaekl.cfb.util.Util;
25
26 public class DbDriverMock extends DbDriver {
27
28         private HashMap<String, TableMock> m_tables;
29         private HashMap<String, SequenceMock> m_sequences;
30         
31         public DbDriverMock() {
32                 super();
33                 m_tables = new HashMap<String, TableMock>();
34                 m_sequences = new HashMap<String, SequenceMock>();
35         }
36
37         @Override
38         public void load() throws ClassNotFoundException {
39                 // no-op
40         }
41
42         @Override
43         public Connection connect(String host, int port, String dbName, String user, String pass) 
44                 throws SQLException 
45         {
46                 return null;
47         }
48         
49         @Override
50         public boolean createTable(Connection con, Table table) throws SQLException
51         {
52                 assertNotNull(con);
53                 assertNotNull(table);
54                 assertFalse(m_tables.containsKey(table.getName()));
55                 
56                 TableMock tm = new TableMock(table);
57                 m_tables.put(table.getName(), tm);
58                 return true;
59         }
60         
61         @Override
62         public void dropTable(Connection con, Table table) throws SQLException 
63         {
64                 assertNotNull(con);
65                 assertNotNull(table);
66                 assertTrue(table instanceof TableMock);
67                 
68                 if (m_tables.containsKey(table.getName())) {
69                         m_tables.remove(table.getName());
70                 }
71                 else {
72                         throw new SQLException("Table " + table.getName() + " does not exist.");
73                 }
74         }
75         
76         @Override
77         public boolean createSequence(Connection con, Sequence seq) throws SQLException 
78         {
79                 assertNotNull(con);
80                 assertNotNull(seq);
81                 assertFalse(m_sequences.containsKey(seq.getName()));
82                 
83                 SequenceMock sm = (seq instanceof SequenceMock) ? (SequenceMock)seq : new SequenceMock(seq);
84                 
85                 m_sequences.put(seq.getName(), sm);
86                 return true;
87         }
88         
89         public void dropSequence(Connection con, Sequence seq) throws SQLException
90         {
91                 assertNotNull(con);
92                 assertNotNull(seq);
93                 assertTrue(seq instanceof SequenceMock);
94
95                 if (m_sequences.containsKey(seq.getName())) {
96                         m_sequences.remove(seq.getName());
97                 }
98                 else {
99                         throw new SQLException("Sequence " + seq.getName() + " does not exist.");
100                 }
101         }
102         
103         public List<Row> select(Connection con, Column[] columns, Table[] tables, Condition[] conditions, Sort[] sorts, int limit)
104                 throws SQLException
105         {
106                 assertNotNull(con);
107                 assertNotNull(columns);
108                 assertNotNull(tables);
109                 
110                 if (1 != tables.length) {
111                         throw new UnsupportedOperationException("DbDriverMock does not (yet) implement table joins");
112                 }
113                 
114                 Table schemaTable = tables[0];
115                 TableMock table = m_tables.get(schemaTable.getName());
116                 if (null == table) {
117                         throw new SQLException("Could not find table \"" + schemaTable.getName() + "\" in schema.");
118                 }
119                 
120                 ArrayList<Row> rows = table.mock_getRows();
121                 if (null != conditions) {
122                         ArrayList<Row> filteredRows = new ArrayList<Row>();
123                         for (Row row : rows) {
124                                 boolean match = true;
125                                 for (Condition condition : conditions) {
126                                         try {
127                                                 if (!conditionSatisfied(condition, row)) {
128                                                         match = false;
129                                                 }
130                                         }
131                                         catch (TypeMismatchException exc) {
132                                                 throw new SQLException(exc);
133                                         }
134                                 }
135                                 if (match) {
136                                         filteredRows.add(row);
137                                 }
138                         }
139                         rows = filteredRows;
140                 }
141                 
142                 ArrayList<Row> result = new ArrayList<Row>();
143                 
144                 // Now, convert the rows from select(*) to select(specified columns)
145                 for (Row row : rows) {
146                         Object[] values = new Object[columns.length];
147                         
148                         for (int outIdx = 0; outIdx < columns.length; ++outIdx) {
149                                 for (int inIdx = 0; inIdx < row.getNumColumns(); ++inIdx) {
150                                         if (row.getColumn(inIdx).getName().equals(columns[outIdx].getName())) {
151                                                 values[outIdx] = row.getValue(inIdx);
152                                         }
153                                 }
154                         }
155                         result.add(new Row(columns, values));
156                 }
157                 
158                 return result;
159         }
160         
161         private boolean aLessThanB(Object a, Object b) 
162         {
163                 if ((null == a) || (null == b)) {
164                         return false;
165                 }
166                 
167                 if (a instanceof Number) {
168                         if (! (b instanceof Number)) {
169                                 throw new UnsupportedOperationException("Incompatible types");
170                         }
171                         Number first = (Number)a;
172                         Number second = (Number)b;
173                         return first.doubleValue() < second.doubleValue();
174                 }
175                 
176                 if (a instanceof Date) {
177                         if (! (b instanceof Date)) {
178                                 throw new UnsupportedOperationException("Incompatible types");
179                         }
180                         Date first = (Date)a;
181                         Date second = (Date)b;
182                         int comp = first.compareTo(second);
183                         boolean result = (comp < 0);
184                         
185                         return (result);
186                 }
187                 
188                 throw new UnsupportedOperationException("Incompatible types");
189         }
190         
191         private boolean conditionSatisfied(Condition condition, Row row) throws TypeMismatchException, SQLException
192         {
193                 for (int idx = 0; idx < row.getNumColumns(); ++idx) {
194                         Column col = row.getColumn(idx);
195                         if (condition.getColumn().equals(col)) {
196                                 switch(condition.getOperation()) {
197                                 case EQUAL:
198                                         return Util.objsAreEqual(condition.getValue(), row.getValue(idx));
199                                 case GREATER_THAN:
200                                         return (aLessThanB(condition.getValue(), row.getValue(idx)));
201                                 case LESS_THAN:
202                                         return (aLessThanB(row.getValue(idx), condition.getValue()));
203                                 case NOT_NULL:
204                                         return (null != row.getValue(idx));
205                                 case NULL:
206                                         return (null == row.getValue(idx));
207                                 default:
208                                         throw new UnsupportedOperationException("This condition operation is not supported by DbDriverMock");
209                                 }
210                         }
211                 }
212                 throw new SQLException("Could not locate column \"" + condition.getColumn().getName() + "\" in TableMock.");
213         }
214         
215         // Returns the number of rows inserted
216         @Override
217         public int insert(Connection con, Table table, Object[][] values) throws SQLException 
218         {
219                 assertNotNull(con);
220                 assertNotNull(table);
221                 assertNotNull(values);
222                 
223                 TableMock tm = m_tables.get(table.getName());
224                 if (null == tm) {
225                         throw new SQLException("Table " + table.getName() + " does not exist.");
226                 }
227                 Column[] columns = tm.mock_getColumns();
228
229                 for (Object[] rowVals : values) {
230                         assertNotNull(rowVals);
231                         assertEquals(table.getNumColumns(), rowVals.length);
232                         
233                         tm.mock_insert(new Row(columns, rowVals));
234                 }
235                 
236                 return values.length;
237         }
238
239
240         public long nextVal(Connection con, Sequence seq) throws SQLException
241         {
242                 assertNotNull(con);
243                 assertNotNull(seq);
244                 
245                 SequenceMock sm = m_sequences.get(seq.getName());
246                 return sm.mock_nextVal();
247         }
248 }