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 ArrayList<ConnectionMock> m_cons;
29 private HashMap<String, SequenceMock> m_sequences;
30 private HashMap<String, TableMock> m_tables;
32 public DbDriverMock() {
34 m_cons = new ArrayList<ConnectionMock>();
35 m_sequences = new HashMap<String, SequenceMock>();
36 m_tables = new HashMap<String, TableMock>();
40 public void load() throws ClassNotFoundException {
45 public Connection connect(String host, int port, String dbName, String user, String pass)
48 ConnectionMock con = new ConnectionMock();
54 public boolean createTable(Connection con, Table table) throws SQLException
58 assertFalse(m_tables.containsKey(table.getName()));
60 TableMock tm = new TableMock(table);
61 m_tables.put(table.getName(), tm);
66 public void dropTable(Connection con, Table table) throws SQLException
70 assertTrue(table instanceof TableMock);
72 if (m_tables.containsKey(table.getName())) {
73 m_tables.remove(table.getName());
76 throw new SQLException("Table " + table.getName() + " does not exist.");
81 public boolean createSequence(Connection con, Sequence seq) throws SQLException
85 assertFalse(m_sequences.containsKey(seq.getName()));
87 SequenceMock sm = (seq instanceof SequenceMock) ? (SequenceMock)seq : new SequenceMock(seq);
89 m_sequences.put(seq.getName(), sm);
93 public void dropSequence(Connection con, Sequence seq) throws SQLException
97 assertTrue(seq instanceof SequenceMock);
99 if (m_sequences.containsKey(seq.getName())) {
100 m_sequences.remove(seq.getName());
103 throw new SQLException("Sequence " + seq.getName() + " does not exist.");
107 public List<Row> select(Connection con, Column[] columns, Table[] tables, Condition[] conditions, Sort[] sorts, int limit)
111 assertNotNull(columns);
112 assertNotNull(tables);
114 if (1 != tables.length) {
115 throw new UnsupportedOperationException("DbDriverMock does not (yet) implement table joins");
118 Table schemaTable = tables[0];
119 TableMock table = m_tables.get(schemaTable.getName());
121 throw new SQLException("Could not find table \"" + schemaTable.getName() + "\" in schema.");
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) {
131 if (!conditionSatisfied(condition, row)) {
135 catch (TypeMismatchException exc) {
136 throw new SQLException(exc);
140 filteredRows.add(row);
146 ArrayList<Row> result = new ArrayList<Row>();
148 // Now, convert the rows from select(*) to select(specified columns)
149 for (Row row : rows) {
150 Object[] values = new Object[columns.length];
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);
159 result.add(new Row(columns, values));
165 private boolean aLessThanB(Object a, Object b)
167 if ((null == a) || (null == b)) {
171 if (a instanceof Number) {
172 if (! (b instanceof Number)) {
173 throw new UnsupportedOperationException("Incompatible types");
175 Number first = (Number)a;
176 Number second = (Number)b;
177 return first.doubleValue() < second.doubleValue();
180 if (a instanceof Date) {
181 if (! (b instanceof Date)) {
182 throw new UnsupportedOperationException("Incompatible types");
184 Date first = (Date)a;
185 Date second = (Date)b;
186 int comp = first.compareTo(second);
187 boolean result = (comp < 0);
192 throw new UnsupportedOperationException("Incompatible types");
195 private boolean conditionSatisfied(Condition condition, Row row) throws TypeMismatchException, SQLException
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()) {
202 return Util.objsAreEqual(condition.getValue(), row.getValue(idx));
204 return (aLessThanB(condition.getValue(), row.getValue(idx)));
206 return (aLessThanB(row.getValue(idx), condition.getValue()));
208 return (null != row.getValue(idx));
210 return (null == row.getValue(idx));
212 throw new UnsupportedOperationException("This condition operation is not supported by DbDriverMock");
216 throw new SQLException("Could not locate column \"" + condition.getColumn().getName() + "\" in TableMock.");
219 // Returns the number of rows inserted
221 public int insert(Connection con, Table table, Object[][] values) throws SQLException
224 assertNotNull(table);
225 assertNotNull(values);
227 TableMock tm = m_tables.get(table.getName());
229 throw new SQLException("Table " + table.getName() + " does not exist.");
231 Column[] columns = tm.mock_getColumns();
233 for (Object[] rowVals : values) {
234 assertNotNull(rowVals);
235 assertEquals(table.getNumColumns(), rowVals.length);
237 tm.mock_insert(new Row(columns, rowVals));
240 return values.length;
244 public long nextVal(Connection con, Sequence seq) throws SQLException
249 SequenceMock sm = m_sequences.get(seq.getName());
250 return sm.mock_nextVal();