View Javadoc
1   package com.randomnoun.common.db;
2   
3   /* (c) 2013 randomnoun. All Rights Reserved. This work is licensed under a
4    * BSD Simplified License. (http://www.randomnoun.com/bsd-simplified.html)
5    */
6   
7   import java.util.HashMap;
8   
9   import javax.sql.DataSource;
10  
11  import org.springframework.jdbc.core.JdbcTemplate;
12  
13  import com.randomnoun.common.db.to.SchemaTO;
14  import com.randomnoun.common.db.to.TableColumnTO;
15  import com.randomnoun.common.db.to.TableTO;
16  
17  /** Container class for database metadata.
18   * 
19   * <p>Rewrite of DatabaseTO to be marginally more structured
20   * 
21   * <p>Contains methods for populating metadata from the data dictionaries of
22   * Oracle and MySQL, for the purposes of whatever it is that I'm doing at the time.
23   *
24   *  
25   *  NB: does not set default values for oracle
26   *  
27   */
28  public abstract class DatabaseReader {
29  
30  	protected com.randomnoun.common.db.to.DatabaseTO db;
31      
32  	// only required for online DB metadata
33  	public DataSource ds;
34  	public JdbcTemplate jt;
35  	
36  	/* these aren't used yet
37  	public static class SourceTypeTO {
38  		public SchemaTO schema;
39  		public List packages;
40  		public List packageBodies;
41  		public List procedures;
42  		public List functions;
43  		public List triggers;
44  	}
45  	
46  	public static class UserTypeTO {
47  		public SchemaTO schema;
48  		public List arrayTypes;
49  		public List objectTypes;
50  		public List tableTypes;
51  		public List xmlSchema;
52  	}
53  	
54  	public static class SecurityTO {
55  		public SchemaTO schema;
56  		public List users;
57  		public List roles;
58  		public List profiles;
59  	}
60  	
61  	public static class StorageTO {
62  		public SchemaTO schema;
63  		public Map<String, TableTO> tablespaces;
64  		public List datafiles;
65  		public List rollbackSegments;
66  		public List redoLogGroups;
67  		public List archiveLogs;
68  	}
69  	
70  	public static class DistributedTO {
71  		public SchemaTO schema;
72  		public List inDoubtTransactions;
73  		public List databaseLinks;
74  		public List streams;
75  		public List advancedQueues;
76  		public List advancedReplication;
77  	}
78  	*/
79  	
80  	/** Database metadata container. Will load reference data on demand */
81  	// @TODO look up correct Reader instance and use that 
82  	public DatabaseReader(DataSource dataSource /*, DatabaseType dbType*/) {
83  		this.ds = dataSource;
84  		this.jt = new JdbcTemplate(dataSource);
85  		this.db = new com.randomnoun.common.db.to.DatabaseTO();
86  		db.setDatabaseType(null);
87  		db.setSchemaMap(new HashMap<String, SchemaTO>());
88  	}
89  	
90  	
91  	// this only works for MYSQL. so that's odd.
92  	public SchemaTO getSchema(String schemaName) {
93  		
94  		// default schema name
95  		if (schemaName==null) {
96  			switch (db.getDatabaseType()) {
97  				case ORACLE:
98  					throw new UnsupportedOperationException("Not supported for this database type");
99  				
100 				case MYSQL:
101 					schemaName = (String) jt.queryForObject("SELECT DATABASE();", java.lang.String.class);
102 					break;
103 			
104 				case SQLSERVER:
105 					throw new UnsupportedOperationException("Not supported for this database type");
106 					
107 				default:
108 					throw new IllegalStateException("Unknown database type " + db.getDatabaseType());
109 			}
110 		}
111 		
112 		SchemaTO schema = db.getSchemaMap().get(db.upper(schemaName));
113 		if (schema == null) {
114 			schema = readSchema(db.upper(schemaName));
115 			db.getSchemaMap().put(db.upper(schemaName), schema); 
116 		}
117 		return schema;
118 	}
119 	
120 	abstract public SchemaTO readSchema(String schemaName);  // SchemaTO schema
121 	
122 	
123 	// @TODO pass in current schema/table for context resolution
124 	public TableColumnTO getColumn(com.randomnoun.common.db.to.DatabaseTO db, String identifier) {
125 		String schemaName = null;
126 		String tableName = null;
127 		String columnName = null;
128 		String[] bits = identifier.split("\\.");
129 		if (bits.length > 3) { throw new IllegalArgumentException("Too many components in column identifier '" + identifier + "'"); }
130 		if (bits.length < 1) { throw new IllegalArgumentException("Too few components in column identifier '" + identifier + "'"); }
131 		if (bits.length > 2) { schemaName = bits[bits.length - 3]; }
132 		if (bits.length > 1) { tableName = bits[bits.length - 2]; }
133 		columnName = bits[bits.length - 1];
134 		SchemaTO schema = db.getSchemaMap().get(schemaName); 
135 		TableTO table = schema.getTable(tableName);
136 		return table.getTableColumn(columnName);
137 	}
138 	
139 }