1 package net.jaekl.cfb.db.driver;
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;
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;
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;
26 public class DbDriverMock extends DbDriver {
28 private HashMap<String, TableMock> m_tables;
29 private HashMap<String, SequenceMock> m_sequences;
31 public DbDriverMock() {
33 m_tables = new HashMap<String, TableMock>();
34 m_sequences = new HashMap<String, SequenceMock>();
38 public void load() throws ClassNotFoundException {
43 public Connection connect(String host, int port, String dbName, String user, String pass)
50 public boolean createTable(Connection con, Table table) throws SQLException
54 assertFalse(m_tables.containsKey(table.getName()));
56 TableMock tm = new TableMock(table);
57 m_tables.put(table.getName(), tm);
62 public void dropTable(Connection con, Table table) throws SQLException
66 assertTrue(table instanceof TableMock);
68 if (m_tables.containsKey(table.getName())) {
69 m_tables.remove(table.getName());
72 throw new SQLException("Table " + table.getName() + " does not exist.");
77 public boolean createSequence(Connection con, Sequence seq) throws SQLException
81 assertFalse(m_sequences.containsKey(seq.getName()));
83 SequenceMock sm = (seq instanceof SequenceMock) ? (SequenceMock)seq : new SequenceMock(seq);
85 m_sequences.put(seq.getName(), sm);
89 public void dropSequence(Connection con, Sequence seq) throws SQLException
93 assertTrue(seq instanceof SequenceMock);
95 if (m_sequences.containsKey(seq.getName())) {
96 m_sequences.remove(seq.getName());
99 throw new SQLException("Sequence " + seq.getName() + " does not exist.");
103 public List<Row> select(Connection con, Column[] columns, Table[] tables, Condition[] conditions, Sort[] sorts, int limit)
107 assertNotNull(columns);
108 assertNotNull(tables);
110 if (1 != tables.length) {
111 throw new UnsupportedOperationException("DbDriverMock does not (yet) implement table joins");
114 Table schemaTable = tables[0];
115 TableMock table = m_tables.get(schemaTable.getName());
117 throw new SQLException("Could not find table \"" + schemaTable.getName() + "\" in schema.");
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) {
127 if (!conditionSatisfied(condition, row)) {
131 catch (TypeMismatchException exc) {
132 throw new SQLException(exc);
136 filteredRows.add(row);
142 ArrayList<Row> result = new ArrayList<Row>();
144 // Now, convert the rows from select(*) to select(specified columns)
145 for (Row row : rows) {
146 Object[] values = new Object[columns.length];
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);
155 result.add(new Row(columns, values));
161 private boolean aLessThanB(Object a, Object b)
163 if ((null == a) || (null == b)) {
167 if (a instanceof Number) {
168 if (! (b instanceof Number)) {
169 throw new UnsupportedOperationException("Incompatible types");
171 Number first = (Number)a;
172 Number second = (Number)b;
173 return first.doubleValue() < second.doubleValue();
176 if (a instanceof Date) {
177 if (! (b instanceof Date)) {
178 throw new UnsupportedOperationException("Incompatible types");
180 Date first = (Date)a;
181 Date second = (Date)b;
182 int comp = first.compareTo(second);
183 boolean result = (comp < 0);
188 throw new UnsupportedOperationException("Incompatible types");
191 private boolean conditionSatisfied(Condition condition, Row row) throws TypeMismatchException, SQLException
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()) {
198 return Util.objsAreEqual(condition.getValue(), row.getValue(idx));
200 return (aLessThanB(condition.getValue(), row.getValue(idx)));
202 return (aLessThanB(row.getValue(idx), condition.getValue()));
204 return (null != row.getValue(idx));
206 return (null == row.getValue(idx));
208 throw new UnsupportedOperationException("This condition operation is not supported by DbDriverMock");
212 throw new SQLException("Could not locate column \"" + condition.getColumn().getName() + "\" in TableMock.");
215 // Returns the number of rows inserted
217 public int insert(Connection con, Table table, Object[][] values) throws SQLException
220 assertNotNull(table);
221 assertNotNull(values);
223 TableMock tm = m_tables.get(table.getName());
225 throw new SQLException("Table " + table.getName() + " does not exist.");
227 Column[] columns = tm.mock_getColumns();
229 for (Object[] rowVals : values) {
230 assertNotNull(rowVals);
231 assertEquals(table.getNumColumns(), rowVals.length);
233 tm.mock_insert(new Row(columns, rowVals));
236 return values.length;
240 public long nextVal(Connection con, Sequence seq) throws SQLException
245 SequenceMock sm = m_sequences.get(seq.getName());
246 return sm.mock_nextVal();