1 5 package org.h2.command.dml; 6 7 import java.io.FileInputStream ; 8 import java.io.FileOutputStream ; 9 import java.io.FileReader ; 10 import java.io.FileWriter ; 11 import java.io.IOException ; 12 import java.io.InputStream ; 13 import java.io.Reader ; 14 import java.sql.Connection ; 15 import java.sql.ResultSet ; 16 import java.sql.SQLException ; 17 import java.sql.Statement ; 18 import java.util.Comparator ; 19 20 import org.h2.command.Parser; 21 import org.h2.constraint.Constraint; 22 import org.h2.engine.Comment; 23 import org.h2.engine.Constants; 24 import org.h2.engine.Database; 25 import org.h2.engine.DbObject; 26 import org.h2.engine.FunctionAlias; 27 import org.h2.engine.Right; 28 import org.h2.engine.Role; 29 import org.h2.engine.Session; 30 import org.h2.engine.Setting; 31 import org.h2.engine.User; 32 import org.h2.engine.UserDataType; 33 import org.h2.expression.ExpressionColumn; 34 import org.h2.index.Cursor; 35 import org.h2.index.Index; 36 import org.h2.message.Message; 37 import org.h2.result.LocalResult; 38 import org.h2.result.Row; 39 import org.h2.schema.Constant; 40 import org.h2.schema.Schema; 41 import org.h2.schema.Sequence; 42 import org.h2.schema.TriggerObject; 43 import org.h2.table.Column; 44 import org.h2.table.PlanItem; 45 import org.h2.table.Table; 46 import org.h2.util.ByteUtils; 47 import org.h2.util.FileUtils; 48 import org.h2.util.IOUtils; 49 import org.h2.util.MathUtils; 50 import org.h2.util.ObjectArray; 51 import org.h2.util.StringUtils; 52 import org.h2.value.Value; 53 import org.h2.value.ValueLob; 54 import org.h2.value.ValueString; 55 56 public class Script extends ScriptBase { 57 58 private boolean passwords; 59 private boolean data; 60 private boolean settings; 61 private boolean drop; 62 private LocalResult result; 63 private byte[] lineSeparator; 64 private byte[] buffer; 65 private boolean tempLobTableCreated; 66 private int nextLobId; 67 private int lobBlockSize = Integer.MAX_VALUE; 68 private static final String TEMP_LOB_FILENAME = "system_temp_lob.db"; 69 70 public Script(Session session) { 71 super(session); 72 } 73 74 public boolean isQuery() { 75 return true; 76 } 77 78 80 public void setData(boolean data) { 81 this.data = data; 82 } 83 84 public void setPasswords(boolean passwords) { 85 this.passwords = passwords; 86 } 87 88 public void setSettings(boolean settings) { 89 this.settings = settings; 90 } 91 92 public void setLobBlockSize(long blockSize) { 93 this.lobBlockSize = MathUtils.convertLongToInt(blockSize); 94 } 95 96 public void setDrop(boolean drop) { 97 this.drop = drop; 98 } 99 100 public LocalResult query(int maxrows) throws SQLException { 101 session.getUser().checkAdmin(); 102 reset(); 103 try { 104 ObjectArray cols = new ObjectArray(); 105 cols.add(new ExpressionColumn(session.getDatabase(), null, new Column("SCRIPT", Value.STRING, 0, 0))); 106 result = new LocalResult(session, cols, 1); 107 deleteStore(); 108 openOutput(); 109 if(out != null) { 110 buffer = new byte[Constants.IO_BUFFER_SIZE]; 111 } 112 Database db = session.getDatabase(); 113 if(settings) { 114 ObjectArray settings = db.getAllSettings(); 115 for(int i=0; i<settings.size(); i++) { 116 Setting setting = (Setting) settings.get(i); 117 add(setting.getCreateSQL(), false); 118 } 119 } 120 if(out != null) { 121 add("", true); 122 } 123 ObjectArray users = db.getAllUsers(); 124 for(int i=0; i<users.size(); i++) { 125 User user = (User) users.get(i); 126 add(user.getCreateSQL(passwords, true), false); 127 } 128 ObjectArray roles = db.getAllRoles(); 129 for(int i=0; i<roles.size(); i++) { 130 Role role = (Role) roles.get(i); 131 add(role.getCreateSQL(), false); 132 } 133 ObjectArray schemas = db.getAllSchemas(); 134 for(int i=0; i<schemas.size(); i++) { 135 Schema schema = (Schema) schemas.get(i); 136 add(schema.getCreateSQL(), false); 137 } 138 ObjectArray datatypes = db.getAllUserDataTypes(); 139 for(int i=0; i<datatypes.size(); i++) { 140 UserDataType datatype = (UserDataType) datatypes.get(i); 141 add(datatype.getCreateSQL(), false); 142 } 143 ObjectArray constants = db.getAllSchemaObjects(DbObject.CONSTANT); 144 for(int i=0; i<constants.size(); i++) { 145 Constant constant = (Constant) constants.get(i); 146 add(constant.getCreateSQL(), false); 147 } 148 ObjectArray functionAliases = db.getAllFunctionAliases(); 149 for(int i=0; i<functionAliases.size(); i++) { 150 FunctionAlias alias = (FunctionAlias) functionAliases.get(i); 151 add(alias.getCreateSQL(), false); 152 } 153 ObjectArray tables = db.getAllSchemaObjects(DbObject.TABLE_OR_VIEW); 154 tables.sort(new Comparator () { 156 public int compare(Object o1, Object o2) { 157 Table t1 = (Table)o1; 158 Table t2 = (Table)o2; 159 return t1.getId() - t2.getId(); 160 } 161 }); 162 for(int i=0; i<tables.size(); i++) { 163 Table table = (Table) tables.get(i); 164 table.lock(session, false); 165 String sql = table.getCreateSQL(); 166 if(sql == null) { 167 continue; 169 } 170 String tableType = table.getTableType(); 171 if(drop) { 172 if(Table.VIEW.equals(tableType)) { 173 add("DROP VIEW IF EXISTS " + table.getSQL(), false); 174 } else { 175 add("DROP TABLE IF EXISTS " + table.getSQL(), false); 176 } 177 } 178 } 179 ObjectArray sequences = db.getAllSchemaObjects(DbObject.SEQUENCE); 180 for(int i=0; i<sequences.size(); i++) { 181 Sequence sequence = (Sequence) sequences.get(i); 182 if(drop && !sequence.getBelongsToTable()) { 183 add("DROP SEQUENCE IF EXISTS " + sequence.getSQL(), false); 184 } 185 add(sequence.getCreateSQL(), false); 186 } 187 for(int i=0; i<tables.size(); i++) { 188 Table table = (Table) tables.get(i); 189 table.lock(session, false); 190 String sql = table.getCreateSQL(); 191 if(sql == null) { 192 continue; 194 } 195 String tableType = table.getTableType(); 196 add(sql, false); 197 if(Table.TABLE.equals(tableType)) { 198 if(table.canGetRowCount()) { 199 String rowcount = "-- " + table.getRowCount() + " = SELECT COUNT(*) FROM " + table.getSQL(); 200 add(rowcount, false); 201 } 202 if(data) { 203 PlanItem plan = table.getBestPlanItem(session, null); 204 Index index = plan.getIndex(); 205 Cursor cursor = index.find(session, null, null); 206 Column[] columns = table.getColumns(); 207 String ins = "INSERT INTO " + table.getSQL() + "("; 208 for(int j=0; j<columns.length; j++) { 209 if(j>0) { 210 ins += ", "; 211 } 212 ins += Parser.quoteIdentifier(columns[j].getName()); 213 } 214 ins += ") VALUES("; 215 while(cursor.next()) { 216 Row row = cursor.get(); 217 String s = ins; 218 for(int j=0; j<row.getColumnCount(); j++) { 219 if(j>0) { 220 s += ", "; 221 } 222 Value v = row.getValue(j); 223 if(v.getPrecision() > lobBlockSize) { 224 int id; 225 if(v.getType() == Value.CLOB) { 226 id = writeLobStream((ValueLob)v); 227 s += "SYSTEM_COMBINE_CLOB("+id+")"; 228 } else if(v.getType() == Value.BLOB) { 229 id = writeLobStream((ValueLob)v); 230 s += "SYSTEM_COMBINE_BLOB("+id+")"; 231 } else { 232 s += v.getSQL(); 233 } 234 } else { 235 s += v.getSQL(); 236 } 237 } 238 s += ")"; 239 add(s, true); 240 } 241 } 242 } 243 ObjectArray indexes = table.getIndexes(); 244 for(int j=0; indexes != null && j<indexes.size(); j++) { 245 Index index = (Index) indexes.get(j); 246 if(!index.getIndexType().belongsToConstraint()) { 247 add(index.getCreateSQL(), false); 248 } 249 } 250 } 251 if(tempLobTableCreated) { 252 add("DROP TABLE IF EXISTS SYSTEM_LOB_STREAM", true); 253 add("CALL SYSTEM_COMBINE_BLOB(-1)", true); 254 add("DROP ALIAS IF EXISTS SYSTEM_COMBINE_CLOB", true); 255 add("DROP ALIAS IF EXISTS SYSTEM_COMBINE_BLOB", true); 256 tempLobTableCreated = false; 257 } 258 ObjectArray constraints = db.getAllSchemaObjects(DbObject.CONSTRAINT); 259 for(int i=0; i<constraints.size(); i++) { 260 Constraint constraint = (Constraint) constraints.get(i); 261 add(constraint.getCreateSQLWithoutIndexes(), false); 262 } 263 ObjectArray triggers = db.getAllSchemaObjects(DbObject.TRIGGER); 264 for(int i=0; i<triggers.size(); i++) { 265 TriggerObject trigger = (TriggerObject) triggers.get(i); 266 add(trigger.getCreateSQL(), false); 267 } 268 ObjectArray rights = db.getAllRights(); 269 for(int i=0; i<rights.size(); i++) { 270 Right right = (Right) rights.get(i); 271 add(right.getCreateSQL(), false); 272 } 273 ObjectArray comments = db.getAllComments(); 274 for(int i=0; i<comments.size(); i++) { 275 Comment comment = (Comment) comments.get(i); 276 add(comment.getCreateSQL(), false); 277 } 278 closeIO(); 279 } catch(IOException e) { 280 throw Message.convert(e); 281 } finally { 282 closeIO(); 283 } 284 result.done(); 285 LocalResult r = result; 286 reset(); 287 return r; 288 } 289 290 private int writeLobStream(ValueLob v) throws IOException , SQLException { 291 if(!tempLobTableCreated) { 292 add("CREATE TABLE IF NOT EXISTS SYSTEM_LOB_STREAM(ID INT, PART INT, CDATA VARCHAR, BDATA BINARY, PRIMARY KEY(ID, PART))", true); 293 add("CREATE ALIAS IF NOT EXISTS SYSTEM_COMBINE_CLOB FOR \"" + this.getClass().getName() + ".combineClob\"", true); 294 add("CREATE ALIAS IF NOT EXISTS SYSTEM_COMBINE_BLOB FOR \"" + this.getClass().getName() + ".combineBlob\"", true); 295 tempLobTableCreated = true; 296 } 297 int id = nextLobId++; 298 switch(v.getType()) { 299 case Value.BLOB: { 300 byte[] bytes = new byte[lobBlockSize]; 301 InputStream in = v.getInputStream(); 302 try { 303 for(int i=0; ; i++) { 304 StringBuffer buff = new StringBuffer (lobBlockSize * 2); 305 buff.append("INSERT INTO SYSTEM_LOB_STREAM VALUES(" + id + ", " + i + ", NULL, '"); 306 int len = IOUtils.readFully(in, bytes, lobBlockSize); 307 if(len < 0) { 308 break; 309 } 310 buff.append(ByteUtils.convertBytesToString(bytes, len)); 311 buff.append("');"); 312 String sql = buff.toString(); 313 add(sql, true); 314 } 315 } finally { 316 IOUtils.closeSilently(in); 317 } 318 break; 319 } 320 case Value.CLOB: { 321 char[] chars = new char[lobBlockSize]; 322 Reader in = v.getReader(); 323 try { 324 for(int i=0; ; i++) { 325 StringBuffer buff = new StringBuffer (lobBlockSize * 2); 326 buff.append("INSERT INTO SYSTEM_LOB_STREAM VALUES(" + id + ", " + i + ", "); 327 int len = IOUtils.readFully(in, chars, lobBlockSize); 328 if(len < 0) { 329 break; 330 } 331 buff.append(StringUtils.quoteStringSQL(new String (chars))); 332 buff.append(", NULL);"); 333 String sql = buff.toString(); 334 add(sql, true); 335 } 336 } finally { 337 IOUtils.closeSilently(in); 338 } 339 break; 340 } 341 default: 342 throw Message.getInternalError("type:"+v.getType()); 343 } 344 return id; 345 } 346 347 public static InputStream combineBlob(Connection conn, int id) throws SQLException , IOException { 349 if(id < 0) { 350 FileUtils.delete(TEMP_LOB_FILENAME); 351 return null; 352 } 353 Statement stat = conn.createStatement(); 354 ResultSet rs = stat.executeQuery("SELECT BDATA FROM SYSTEM_LOB_STREAM WHERE ID=" + id + " ORDER BY PART"); 355 FileOutputStream out = new FileOutputStream (TEMP_LOB_FILENAME); 356 while(rs.next()) { 357 InputStream in = rs.getBinaryStream(1); 358 IOUtils.copyAndCloseInput(in, out); 359 } 360 out.close(); 361 stat.execute("DELETE FROM SYSTEM_LOB_STREAM WHERE ID=" + id); 362 return new FileInputStream (TEMP_LOB_FILENAME); 363 } 364 365 public static Reader combineClob(Connection conn, int id) throws SQLException , IOException { 367 Statement stat = conn.createStatement(); 368 ResultSet rs = stat.executeQuery("SELECT CDATA FROM SYSTEM_LOB_STREAM WHERE ID=" + id + " ORDER BY PART"); 369 FileWriter out = new FileWriter (TEMP_LOB_FILENAME); 370 while(rs.next()) { 371 Reader in = rs.getCharacterStream(1); 372 IOUtils.copyAndCloseInput(in, out); 373 } 374 out.close(); 375 stat.execute("DELETE FROM SYSTEM_LOB_STREAM WHERE ID=" + id); 376 return new FileReader (TEMP_LOB_FILENAME); 377 } 378 379 private void reset() throws SQLException { 380 result = null; 381 buffer = null; 382 lineSeparator = StringUtils.utf8Encode(System.getProperty("line.separator")); 383 } 384 385 private void add(String s, boolean insert) throws SQLException , IOException { 386 if(s==null) { 387 return; 388 } 389 if (out != null) { 390 byte[] buff = StringUtils.utf8Encode(s + ";"); 391 int len = MathUtils.roundUp(buff.length + lineSeparator.length, Constants.FILE_BLOCK_SIZE); 392 buffer = ByteUtils.copy(buff, buffer); 393 394 if(len > buffer.length) { 395 buffer = new byte[len]; 396 } 397 System.arraycopy(buff, 0, buffer, 0, buff.length); 398 for(int i=buff.length; i<len - lineSeparator.length; i++) { 399 buffer[i] = ' '; 400 } 401 for(int j=0, i=len - lineSeparator.length; i<len; i++, j++) { 402 buffer[i] = lineSeparator[j]; 403 } 404 out.write(buffer, 0, len); 405 if(!insert) { 406 Value[] row = new Value[1]; 407 row[0] = ValueString.get(s); 408 result.addRow(row); 409 } 410 } else { 411 Value[] row = new Value[1]; 412 row[0] = ValueString.get(s); 413 result.addRow(row); 414 } 415 } 416 417 } 418 | Popular Tags |