00001 package net.threebit.utils.sosc;
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 import java.io.*;
00023 import java.sql.*;
00024 import java.util.*;
00025
00029 public class BatchTool extends DbTool {
00030
00031 public String CONTENTARGUMENTS = "_PREFIX__B_atchContentArguments";
00032 public String CONTENTS = "_PREFIX__B_atchContents";
00033 public String BATCHES = "_PREFIX__B_atches";
00034 public String PROFILES = "_PREFIX__B_atchProfiles";
00035
00039 final static String MSSQL =
00040 " create table _PROFILES_ ( \n" +
00041 " id int primary key identity, \n" +
00042 " name varchar(100) \n" +
00043 " ); \n" +
00044 " create table _BATCHES_ ( \n" +
00045 " id int primary key identity, \n" +
00046 " profile int foreign key references _PROFILES_(id), \n" +
00047 " created datetime default getdate(), \n" +
00048 " status varchar(20) not null default 'review' \n" +
00049 " ); \n" +
00050 " create table _CONTENTS_ ( \n" +
00051 " id int primary key identity, \n" +
00052 " batch int foreign key references _BATCHES_(id), \n" +
00053 " i int, \n" +
00054 " v varchar(1000), \n" +
00055 " killed bit default 0 \n" +
00056 " ); \n" +
00057 " create table _CONTENTARGUMENTS_ ( \n" +
00058 " id int primary key identity, \n" +
00059 " content int foreign key references _CONTENTS_(id), \n" +
00060 " k varchar(100), \n" +
00061 " v varchar(1000) \n" +
00062 " ); \n"
00063 ;
00064
00068 private String prefix = null;
00069
00073 public BatchTool (String prefix, String className, String url, String userName, String password) throws Exception {
00074 super(className, url, userName, password);
00075 setPrefix(prefix);
00076 }
00077
00081 public BatchTool (String prefix, Connection connection) throws Exception {
00082 super(connection);
00083 setPrefix(prefix);
00084 }
00085
00089 private void setPrefix (String prefix) throws Exception {
00090 if (prefix == null) { throw new Exception("Cannot specify a null prefix value; use an empty string instead"); }
00091 this.prefix = prefix;
00092
00093 String b = "B";
00094 if (prefix.equals("")) { b = "b"; }
00095 CONTENTARGUMENTS = CONTENTARGUMENTS.replaceAll("_PREFIX_",prefix).replaceAll("_B_",b);
00096 CONTENTS = CONTENTS.replaceAll("_PREFIX_",prefix).replaceAll("_B_",b);
00097 BATCHES = BATCHES.replaceAll("_PREFIX_",prefix).replaceAll("_B_",b);
00098 PROFILES = PROFILES.replaceAll("_PREFIX_",prefix).replaceAll("_B_",b);
00099 }
00100
00104 public String getSchemaSQL (String dbType) throws Exception {
00105 String sql = null;
00106 if (dbType.equals("pgsql")) { throw new Exception("Sorry, pgsql is not supported yet;"); }
00107 else if (dbType.equals("mssql")) { sql = MSSQL; }
00108 else { throw new Exception("Unsupported dbType: '" + dbType + "'"); }
00109 sql = sql.replaceAll("_PROFILES_",PROFILES);
00110 sql = sql.replaceAll("_CONTENTARGUMENTS_",CONTENTARGUMENTS);
00111 sql = sql.replaceAll("_CONTENTS_",CONTENTS);
00112 sql = sql.replaceAll("_BATCHES_",BATCHES);
00113 return sql;
00114 }
00115
00119 public void dropSchema (String dbType) throws Exception {
00120 try {
00121 update(
00122 " drop table " + CONTENTARGUMENTS + ";\n" +
00123 " drop table " + CONTENTS + ";\n" +
00124 " drop table " + BATCHES + ";\n" +
00125 " drop table " + PROFILES + ";\n"
00126 );
00127 }
00128 catch (Exception e) {
00129
00130 e.printStackTrace(System.out);
00131 }
00132 }
00133
00137 public void createSchema (String dbType) throws Exception {
00138 update( getSchemaSQL(dbType));
00139 }
00140
00144 public int createProfile (String name) throws Exception {
00145
00146 boolean exists = false;
00147 int id = 0;
00148 try {
00149 id = getProfileId(name);
00150 exists = true;
00151 }
00152 catch (Exception e) {
00153
00154 }
00155
00156 if (exists) { throw new Exception("A profile with id " + id + " already exists named '" + name + "'"); }
00157
00158
00159 update("insert into " + PROFILES + " (name) values (" + quote(name) + ")");
00160 return getProfileId(name);
00161 };
00162
00166 public int getProfileId (String name) throws Exception {
00167 ResultSet r = query("select id from " + PROFILES + " where name = " + quote(name));
00168 int rowCount = rowCount(r);
00169 if (rowCount != 1) { throw new Exception("Too many or too few rows returned (" + rowCount + ")"); }
00170 r.first();
00171 return r.getInt("id");
00172 }
00173
00177 public int createBatch (String profile) throws Exception {
00178 int profileId = getProfileId(profile);
00179 update("insert into " + BATCHES + " (profile) values ("+profileId+")");
00180 return getInt("select max(id) from " + BATCHES + " where profile = " + profileId);
00181 }
00182
00186 public void addIntContents (int batch, ResultSet r) throws Exception {
00187
00188 StringBuffer sql = new StringBuffer();
00189 Map args = new HashMap();
00190
00191 Map m = null;
00192 int content = -1;
00193 while (r.next()) {
00194 content = r.getInt("content");
00195 sql.append(" insert into " + CONTENTS + " (batch,i) values ("+batch+","+content+");\n");
00196 m = toMap(r,false);
00197 m.remove("content");
00198 args.put(new Integer(content),m);
00199 }
00200
00201 update(sql.toString());
00202 r.close();
00203
00204
00205 sql = new StringBuffer();
00206 r = getBatchContents(batch);
00207 int id = -1;
00208 content = -1;
00209 while (r.next()) {
00210 id = r.getInt("id");
00211 content = r.getInt("i");
00212 m = (Map) args.get(new Integer(content));
00213 for (Iterator i = m.keySet().iterator(); i.hasNext(); ) {
00214 String key = (String) i.next();
00215 String value = (String) m.get(key);
00216 sql.append(" insert into "+CONTENTARGUMENTS+" (content,k,v) values ("+id+","+quote(key)+","+quote(value)+"); \n");
00217 }
00218 }
00219 update(sql.toString());
00220 }
00221
00227 public void addIntContents (String query) throws Exception {
00228 update( " insert into " + CONTENTS + " (batch,i) \n" + query);
00229 }
00230
00236 public void addVarcharContents (String query) throws Exception {
00237 update( " insert into " + CONTENTS + " (batch,v) \n" + query);
00238 }
00239
00243 public void addContentArguments () throws Exception {
00244 }
00245
00252 public ResultSet getContentArguments(int batchId) throws Exception {
00253
00254 StringBuffer sb = new StringBuffer();
00255
00256
00257 ResultSet r = query(
00258 "select distinct k from "+CONTENTARGUMENTS+" bca \n" +
00259 " join "+CONTENTS+" bc on bc.id = bca.content and bc.killed = 0 \n" +
00260 " where bc.batch = " + batchId
00261 );
00262
00263 int rows = rowCount(r);
00264 r.beforeFirst();
00265
00266
00267 String[] keys = new String[rows];
00268 for (int x = 0; x < rows; x++) { r.next(); keys[x] = r.getString("k"); }
00269
00270
00271 sb.append("select content,\n");
00272 sb.append(" max(contentI) as contentI,\n");
00273 sb.append(" max(contentV) as contentV,\n");
00274 for (int x = 0; x < keys.length; x++) {
00275 sb.append(" max("+keys[x]+") as "+keys[x]+",\n");
00276 }
00277 sb.deleteCharAt( sb.length()-2 );
00278 sb.append("from (\n");
00279
00280
00281
00282 for (int x = 0; x < keys.length; x++) {
00283 sb.append(" select bca.id, content, bc.i as contentI, bc.v as contentv, ");
00284 for (int y = 0; y < keys.length; y++) {
00285 sb.append((x==y) ? " bca.v" : " null");
00286 sb.append(" as " + keys[y]);
00287 sb.append(((y+1)==keys.length) ? "" : ",");
00288 }
00289 sb.append(" from "+CONTENTARGUMENTS+" bca \n");
00290 sb.append(" join "+CONTENTS+" bc on bc.id = bca.content \n");
00291 sb.append(" where \n");
00292 sb.append(" bc.batch = " + batchId + "\n");
00293 sb.append(" and k = '" + keys[x] + "'\n");
00294 sb.append(" and bc.killed = 0 \n");
00295 sb.append(((x+1)==keys.length) ? "" : " union\n");
00296 }
00297
00298
00299 sb.append(") as s group by content\n");
00300
00301 return query(sb.toString());
00302 }
00303
00307 public ResultSet getBatchContents (int batch) throws Exception {
00308 return query("select * from " + CONTENTS + " where batch = " + batch + " and killed = 0 ");
00309 };
00310
00314 public ResultSet batchSummary (int profileId) throws Exception {
00315 return query(
00316 " select b.id, b.created, sum(case when bc.id is not null then 1 else 0 end) as size from " + BATCHES + " b " +
00317 " left join " + CONTENTS + " bc on bc.batch = b.id " +
00318 " where b.profile = " + profileId + " and bc.killed = 0 " +
00319 " group by b.id, b.created "
00320 );
00321 }
00322
00323 }