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