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