Bring things to a state where the basic DB schema gets auto-created if it doesn't...
[cfb.git] / prod / net / jaekl / cfb / db / Schema.java
1 package net.jaekl.cfb.db;
2
3 import java.sql.Connection;
4 import java.sql.DatabaseMetaData;
5 import java.sql.ResultSet;
6 import java.sql.SQLException;
7 import java.util.ArrayList;
8 import java.util.HashSet;
9 import java.util.Locale;
10
11 import net.jaekl.cfb.db.driver.DbDriver;
12
13 public class Schema {
14         String m_name;
15         DbDriver m_driver;
16         ArrayList<Table> m_tables;
17         
18         public Schema(String name, DbDriver driver) {
19                 m_name = name;
20                 m_driver = driver;
21                 m_tables = new ArrayList<Table>();
22         }
23         
24         public boolean ensureDbInitialized(Connection con) throws SQLException {
25                 assert(null != con);
26                 boolean result = true;
27                 
28                 if (allTablesPresent(con)) {
29                         return true;
30                 }
31                 
32                 result = createAllTables(con);
33                 
34                 return result;
35         }
36         
37         boolean allTablesPresent(Connection con) throws SQLException 
38         {
39                 assert(null != con);
40                 
41                 DatabaseMetaData dbmd = con.getMetaData();
42                 HashSet<String> extantTables = new HashSet<String>();
43                 
44                 try (ResultSet rs = dbmd.getTables(null, null, null, new String[]{"TABLE"})) {
45                         while (rs.next()) {
46                                 extantTables.add(rs.getString(3).toUpperCase(Locale.CANADA));
47                         }
48                 }
49                 
50                 for (Table table : m_tables) {
51                         String name = table.getName().toUpperCase(Locale.CANADA);
52                         if ( ! extantTables.contains(name) ) {
53                                 // One or more tables missing
54                                 return false;
55                         }
56                 }
57                 
58                 // We could be more thorough here, and check that the expected columns are in place.
59                 
60                 return true;            
61         }
62         
63         boolean createAllTables(Connection con) throws SQLException {
64                 for (Table table : m_tables) {
65                         if (!m_driver.createTable(con, table)) {
66                                 return false;
67                         }
68                 }
69                 return true;
70         }
71         
72         void addTable(Table table) {
73                 m_tables.add(table);
74         }
75         
76         // Add a list of tables.
77         // Define each table in the list as follows:
78         // {
79         //   { table_name },
80         //   { column_name, type, width (-1 for default), null/not_null }
81         // }
82         void addTables(Object[][][] tables) 
83         {
84                 for (Object[][] table : tables) {
85                         addTable(Table.construct(table));
86                 }
87         }       
88 }