-
-
Notifications
You must be signed in to change notification settings - Fork 520
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixed MySQL database backend/Region_Storage.sql files for new installations, converts db automatically for old installations #197
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,13 +19,16 @@ | |
|
||
package com.sk89q.worldguard.protection.databases; | ||
|
||
|
||
import java.util.ArrayList; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.logging.Level; | ||
import java.util.logging.Logger; | ||
import java.io.ByteArrayInputStream; | ||
import java.io.ByteArrayOutputStream; | ||
import java.io.ObjectInputStream; | ||
import java.io.ObjectOutputStream; | ||
|
||
import java.sql.Connection; | ||
import java.sql.DriverManager; | ||
|
@@ -49,7 +52,7 @@ | |
|
||
public class MySQLDatabase extends AbstractProtectionDatabase { | ||
private final Logger logger; | ||
|
||
private boolean isNewMysqlFormat; | ||
private Map<String, ProtectedRegion> regions; | ||
|
||
private Map<String, ProtectedRegion> cuboidRegions; | ||
|
@@ -97,6 +100,11 @@ public MySQLDatabase(ConfigurationManager config, String world, Logger logger) t | |
this.worldDbId = generatedKeys.getInt(1); | ||
} | ||
} | ||
Statement testStmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); | ||
ResultSet testRS = testStmt.executeQuery("SELECT * FROM region_flag"); | ||
if(testRS.getMetaData().getColumnType(testRS.getMetaData().getColumnCount()) != -4) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This line simply tests if the current MySQL region_flag table format is the updated one, or the old one, when the MySQLDatabase is instantiated. This automatically updates the table format to the new format which allows all flag types to be stored, given that the flag data is of a class that extends Serializable. (Most all of them should, to be honest.) |
||
convertTables(); | ||
|
||
} catch (SQLException ex) { | ||
logger.log(Level.SEVERE, ex.getMessage(), ex); | ||
// We havn't connected to the databases, or there was an error | ||
|
@@ -112,6 +120,59 @@ public MySQLDatabase(ConfigurationManager config, String world, Logger logger) t | |
} | ||
} | ||
|
||
private void convertTables() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This method is an automatic converter for the MySQL tables. There is no reason whatsoever that previous MySQL installations should be allowed to remain on the old format. It doesn't store many flags on a server reload. This update code will automatically recover more flags than the current worldguard setup will even allow to be parsed on server reload, such as Double and Integer flags. |
||
if(!isNewMysqlFormat) { | ||
String regionID = ""; | ||
String tmpData = ""; | ||
Object data = null; | ||
String flagName = ""; | ||
try { | ||
Statement stmt = conn.createStatement(); | ||
stmt.executeUpdate("RENAME TABLE region_flag TO legacy_flag"); | ||
stmt.executeUpdate("CREATE TABLE `region_flag` (`id` INT UNSIGNED NOT NULL AUTO_INCREMENT , `region_id` VARCHAR(128) NOT NULL , `flag` VARCHAR(64) NOT NULL , `value` MEDIUMBLOB NOT NULL , INDEX `fk_flags_region` (`region_id` ASC) , PRIMARY KEY (`id`) ) ENGINE = InnoDB"); | ||
stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); | ||
ResultSet rs = stmt.executeQuery("SELECT * FROM legacy_flag"); | ||
while(rs.next()) { | ||
Map<String,String> regionFlags = new HashMap<String,String>(); | ||
tmpData = rs.getString("value"); | ||
flagName = rs.getString("flag"); | ||
regionID = rs.getString("region_id"); | ||
regionFlags.put(flagName,tmpData); | ||
for(Flag<?> flag : DefaultFlag.getFlags()) { | ||
Object o = regionFlags.get(flag.getName()); | ||
if(o != null) { | ||
System.out.println(o); | ||
String className = flag.getClass().getName(); | ||
if(className.contains("DoubleFlag")) | ||
data = Double.parseDouble(tmpData); | ||
else if(className.contains("IntegerFlag")) | ||
data = Integer.parseInt(tmpData); | ||
else | ||
data = tmpData; | ||
ByteArrayOutputStream buf = new ByteArrayOutputStream(); | ||
ObjectOutputStream out = new ObjectOutputStream(buf); | ||
out.writeUnshared(data); | ||
Object toDbData = buf.toByteArray(); | ||
PreparedStatement pstmt = conn.prepareStatement("INSERT INTO `region_flag` ( `id`, `region_id`, `flag`, `value`) VALUES (null, ?, ?, ?)"); | ||
pstmt.setString(1, regionID.toLowerCase()); | ||
pstmt.setString(2, flag.getName()); | ||
pstmt.setObject(3, toDbData); | ||
pstmt.execute(); | ||
} | ||
|
||
} | ||
} | ||
|
||
|
||
} catch (Exception e) { | ||
System.out.println("There was a problem converting your MySQL table."); | ||
System.out.println(e); | ||
} | ||
} | ||
} | ||
|
||
|
||
|
||
private void connect() throws SQLException { | ||
if (conn == null || conn.isClosed()) { | ||
conn = DriverManager.getConnection(config.sqlDsn, config.sqlUsername, config.sqlPassword); | ||
|
@@ -134,9 +195,25 @@ private void loadFlags(ProtectedRegion region) { | |
|
||
Map<String,Object> regionFlags = new HashMap<String,Object>(); | ||
while (flagsResultSet.next()) { | ||
String flagName = flagsResultSet.getString("flag"); | ||
Object flagValue = null; | ||
if(flagsResultSet.getMetaData().getColumnType(flagsResultSet.getMetaData().getColumnCount()) == -4) { | ||
isNewMysqlFormat = true;; | ||
java.sql.Blob blob = flagsResultSet.getBlob("value"); | ||
try{ | ||
java.io.ObjectInputStream obIn = new java.io.ObjectInputStream(blob.getBinaryStream()); | ||
flagValue = obIn.readUnshared(); | ||
} catch (Exception e) { | ||
System.out.println(e); | ||
continue; | ||
} | ||
} else { | ||
flagValue = flagsResultSet.getObject("value"); | ||
flagName = flagsResultSet.getString("flag"); | ||
} | ||
regionFlags.put( | ||
flagsResultSet.getString("flag"), | ||
flagsResultSet.getObject("value") | ||
flagName, | ||
flagValue | ||
); | ||
} | ||
|
||
|
@@ -590,10 +667,10 @@ private Map<String,Integer> getGroupIds(String... groupnames) { | |
* b) If the region is not in the database, we insert it | ||
* 3) We iterate over what remains of the in-database list and remove | ||
* them from the database | ||
* | ||
* | ||
* TODO: Look at adding/removing/updating the database when the in | ||
* memory region is created/remove/updated | ||
* | ||
* | ||
* @see com.sk89q.worldguard.protection.databases.ProtectionDatabase#save() | ||
*/ | ||
public void save() throws ProtectionDatabaseException { | ||
|
@@ -702,8 +779,22 @@ private void updateFlags(ProtectedRegion region) throws SQLException { | |
|
||
for (Map.Entry<Flag<?>, Object> entry : region.getFlags().entrySet()) { | ||
if (entry.getValue() == null) continue; | ||
|
||
Object flag = marshalFlag(entry.getKey(), entry.getValue()); | ||
Object flag; | ||
if (isNewMysqlFormat) { | ||
flag = new byte[0]; | ||
Object flag2 = marshalFlag(entry.getKey(), entry.getValue()); | ||
try{ | ||
ByteArrayOutputStream buf = new ByteArrayOutputStream(); | ||
ObjectOutputStream out = new ObjectOutputStream(buf); | ||
out.writeUnshared(flag2); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the latest update to the code and SUPER IMPORTANT |
||
flag = buf.toByteArray(); | ||
} catch(Exception e) { | ||
System.out.println(e); | ||
continue; | ||
} | ||
} else { | ||
flag = marshalFlag(entry.getKey(), entry.getValue()); | ||
} | ||
|
||
PreparedStatement insertFlagStatement = this.conn.prepareStatement( | ||
"INSERT INTO `region_flag` ( " + | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This just changes the MySQL table format from a VARCHAR to a BLOB which is basically a byte array as far as Java is concerned.