[factions-banking] VERY start of SQL stuff for the banking system. Tables are figured out locally; implementing logic for JBDC driver here
Some checks failed
build / build (21) (push) Has been cancelled

This commit is contained in:
Jkibbels 2025-01-14 22:56:38 -05:00
parent f6af706a60
commit f22da92cab
7 changed files with 178 additions and 49 deletions

View File

@ -4,11 +4,13 @@ package jesse.keeblarcraft.BankMgr;
public class TransactionMetadata {
enum TRANSACTION_TYPE {
DEBIT,
CREDIT
CREDIT,
WITHDRAWAL,
DEPOSIT
}
public String fromParty; // Account ID
public String toParty; // Account ID
public String toParty; // Account ID or party (like ATM/self,etc)
public Integer amount;
public String transactionId;
public TRANSACTION_TYPE transactionType;

View File

@ -394,29 +394,6 @@ public class BankCommands {
});
}
/////////////////////////////////////////////////////////////////////////////
/// @fn RemoveFillerWords
///
/// @brief Takes in a list of arguments with the intention to remove
/// all words found in the filler list. This helps with dynamic
/// typing
///
/// @return List of arguments without filler words
/////////////////////////////////////////////////////////////////////////////
public List<String> RemoveFillerWords(List<String> argList) {
int index = 0;
for (String str : argList) {
if (FILLER_WORDS.contains(str)) {
argList.remove(index);
}
// Also make every word lower case
str = str.toLowerCase();
index++;
}
return argList;
}
public int SelectBank(ServerPlayerEntity player, String bank) {
System.out.println("Select bank called");
BankManager.GetInstance().ChangeDefaultSelectedBank(player, bank);
@ -552,6 +529,7 @@ public class BankCommands {
return 0;
}
// TODO: make prettier
public int ListAllBanks(ServerPlayerEntity sourcePlayer) {
sourcePlayer.sendMessage(Text.of("Here is a list of available banks on the server: " + BankManager.GetInstance().GetAllBankNames()));
return 0;
@ -668,9 +646,6 @@ public class BankCommands {
return 0;
}
// Possible code paths:
// REQUIRED = {AMOUNT} {ACCOUNT_ID} [optional]
// OPTIONAL = [reason]
/////////////////////////////////////////////////////////////////////////////
/// @fn WireCommand
///

View File

@ -6,6 +6,7 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import jesse.keeblarcraft.ConfigMgr.SQLTypeSupport.VALID_SQL_TYPE;
import jesse.keeblarcraft.Utils.CommonStructures.Pair;
public class SQLConfig {
@ -17,6 +18,20 @@ public class SQLConfig {
private Boolean connected = false;
private Connection conn = null; // Actual connection object
private enum SQL_RUN_TYPE {
GENERAL,
QUERY,
UPDATE
}
// Direct return object in relation to the SQL_RUN_TYPE of the SQL command that was used. Only one will
// be filled out properly for what you run - the other values will be null and not cleared!
private class SQLRunReturn {
Boolean generalRet;
ResultSet queryReturn;
Integer updateReturn;
}
public static SQLConfig GetInstance() {
if (static_inst == null) {
static_inst = new SQLConfig();
@ -44,28 +59,38 @@ public class SQLConfig {
dbPass = GeneralConfig.GetInstance().GetSQLPassword();
dbAddr = "jdbc:mysql://" + GeneralConfig.GetInstance().GetSQLAddress() + "/" + dbName;
conn = DriverManager.getConnection(dbAddr, dbUser, dbPass);
Statement stmnt = conn.createStatement();
String testSql = "SELECT * FROM test_table";
ResultSet rs = stmnt.executeQuery(testSql);
System.out.println("Printing out result set from test query");
while (rs.next()) {
System.out.println("[RS]: " + rs.getString("test_name"));
}
} catch (SQLException e) {}
}
}
private ResultSet RunCommand(String sqlCommand) {
ResultSet cmdResult = null;
private SQLRunReturn RunCommand(String sqlCommand, SQL_RUN_TYPE type) {
SQLRunReturn sqlData = new SQLRunReturn();
// If conn is null; we may need to reconnect before running the command
if (conn == null) {
Connect();
}
if (conn != null) {
try {
Statement statement = conn.createStatement();
cmdResult = statement.executeQuery(sqlCommand);
} catch (Exception e) {}
switch(type) {
case GENERAL:
sqlData.generalRet = statement.execute(sqlCommand);
break;
case QUERY:
sqlData.queryReturn = statement.executeQuery(sqlCommand);
break;
case UPDATE:
sqlData.updateReturn = statement.executeUpdate(sqlCommand);
break;
}
} catch (SQLException e) {
System.out.println(e.getSQLState());
}
}
return cmdResult;
return sqlData;
}
// Re-attempt the connection
@ -88,7 +113,8 @@ public class SQLConfig {
return conn != null && this.connected;
}
private Boolean TableExists(String name) {
// The case is converted to upper case automatically to be case insensitive
public Boolean DoesTableExist(String name) {
boolean tableExists = false;
try (ResultSet rs = conn.getMetaData().getTables(null, null, name, null)) {
while (rs.next()) {
@ -102,18 +128,54 @@ public class SQLConfig {
return tableExists;
}
// Might fix heap pollution decay in future with enum types or something. For now we assume the user isn't horrifically stupid and will give a SQL-able type
public Boolean CreateTable(String tableName, Pair<String, Object>... columnPairs) {
Boolean success = false;
if (!TableExists(tableName.toUpperCase())) {
String sqlCommand = "CREATE TABLE " + tableName.toUpperCase() + "(";
for (Pair<String, Object> colPair : columnPairs) {
sqlCommand = sqlCommand + " " + colPair.GetKey() + " " + String.valueOf(colPair.GetValue()) + ",";
public Boolean MakeNonNullable(String table, String columnName) {
return false;
}
System.out.println("DEBUG STATEMENT, SQL STATEMENT: " + sqlCommand);
ResultSet rs = RunCommand(sqlCommand);
public Integer AddPrimaryKey(String tableName, String primaryKeyColumn) {
SQLRunReturn success = new SQLRunReturn();
if (DoesTableExist(tableName)) {
String sqlCmd = "ALTER TABLE " + tableName + " ADD PRIMARY KEY (" + primaryKeyColumn + ");";
success = RunCommand(sqlCmd, SQL_RUN_TYPE.UPDATE);
}
return success.updateReturn;
}
public Integer AddForeignKey(String primaryTableName, String primaryColumnName, String foreignTableName, String foreignKeyColumn) {
SQLRunReturn success = new SQLRunReturn();
Boolean primaryTableExists = DoesTableExist(primaryTableName);
Boolean foreignTableExists = DoesTableExist(foreignTableName);
if (primaryTableExists && foreignTableExists) {
String sqlCmd = "ALTER TABLE " + primaryTableName + " ADD FOREIGN KEY (" + primaryColumnName + ") REFERENCES " + foreignTableName + " (" + foreignKeyColumn + ")";
success = RunCommand(sqlCmd, SQL_RUN_TYPE.UPDATE);
}
return success.updateReturn;
}
// Might fix heap pollution decay in future with enum types or something. For now we assume the user isn't horrifically stupid and will give a SQL-able type
public Boolean CreateTable(String tableName, Pair<String, VALID_SQL_TYPE>... columnPairs) {
Boolean success = false;
if (!DoesTableExist(tableName.toUpperCase())) {
String sqlCommand = "CREATE TABLE " + tableName.toUpperCase() + "(";
for (Pair<String, VALID_SQL_TYPE> colPair : columnPairs) {
sqlCommand = sqlCommand + " " + colPair.GetKey() + " " + SQLTypeSupport.GetSqlStrForType(colPair.GetValue()) + ",";
}
// Strip the leading comma and append the ending ');' on the SQL statement
sqlCommand = sqlCommand.substring(0, sqlCommand.length() - 1) + ");";
SQLRunReturn rs = RunCommand(sqlCommand, SQL_RUN_TYPE.GENERAL);
try {
while (rs.queryReturn.next()) {
}
} catch (Exception e) {}
}
return success;
}

View File

@ -0,0 +1,23 @@
package jesse.keeblarcraft.ConfigMgr;
import jesse.keeblarcraft.ConfigMgr.SQLTypeSupport.VALID_SQL_TYPE;
import jesse.keeblarcraft.Utils.CommonStructures.Pair;
public class SQLInitServer {
// Initial run-time checks to make sure tables are all setup in advanced
public void Initialize() {
SetupTables();
}
private void SetupTables() {
// These are all hard coded and non-changeable in this version of the mod
String accountsTable = "ACCOUNTS";
String banksTable = "BANKS";
String customerTable = "CUSTOMER";
String transactionTable = "TRANSACTION";
Pair<String, VALID_SQL_TYPE> pairOne = new Pair<>("name", VALID_SQL_TYPE.VARCHAR);
Pair<String, VALID_SQL_TYPE> pairTwo = new Pair<>("address", VALID_SQL_TYPE.BIGINT);
Pair<String, VALID_SQL_TYPE> pairThree = new Pair<>("email", VALID_SQL_TYPE.TEXT);
}
}

View File

@ -0,0 +1,27 @@
package jesse.keeblarcraft.ConfigMgr;
public class SQLTypeSupport {
public enum VALID_SQL_TYPE {
VARCHAR,
BIGINT,
INT,
TEXT
}
// Produces the word that SQL would expect for the given datatype. In general it's usually just the word itself but in cases
// like 'varchar' you usually specify a size too. For now it defaults 255 but this can be expanded in the future
public static String GetSqlStrForType(VALID_SQL_TYPE type) {
switch(type) {
case VARCHAR:
return "VARCHAR(255)";
case BIGINT:
return "BIGINT";
case INT:
return "INT";
case TEXT:
return "TEXT";
}
return null; // This should never get hit
}
}

View File

@ -0,0 +1,38 @@
package jesse.keeblarcraft.ConfigMgr;
import jesse.keeblarcraft.ConfigMgr.SQLTypeSupport.VALID_SQL_TYPE;
import jesse.keeblarcraft.Utils.CommonStructures.Pair;
// Random commands to run to test the SQL class
public class SQLUnitTest {
public void RunTests() {
CreateTableTest();
ForeignKeyTest();
}
public void CreateTableTest() {
String tableName = "test_table";
Pair<String, VALID_SQL_TYPE> pairOne = new Pair<>("name", VALID_SQL_TYPE.VARCHAR);
Pair<String, VALID_SQL_TYPE> pairTwo = new Pair<>("address", VALID_SQL_TYPE.BIGINT);
Pair<String, VALID_SQL_TYPE> pairThree = new Pair<>("email", VALID_SQL_TYPE.TEXT);
SQLConfig.GetInstance().CreateTable(tableName, pairOne, pairTwo, pairThree);
}
public void DoesTableExistTest() {
String tableName = "test_table";
Boolean temp = SQLConfig.GetInstance().DoesTableExist(tableName.toUpperCase());
System.out.println("[SQL-UnitTest]: Does the table " + tableName + " exist? " + (temp ? "YES":"NO"));
}
public void ForeignKeyTest() {
String primTableName = "test_table";
String primColName = "name";
String foreTableName = "accounts";
String foreColName = "global_account_id";
Integer ret = SQLConfig.GetInstance().AddForeignKey(primTableName, primColName, foreTableName, foreColName);
System.out.println("[SQL-UnitTest]: Update foreign key test. Got return result number: " + ret);
}
}

View File

@ -41,6 +41,7 @@ import jesse.keeblarcraft.AttributeMgr.AttributeTree;
import jesse.keeblarcraft.BankMgr.BankManager;
import jesse.keeblarcraft.Commands.CustomCommandManager;
import jesse.keeblarcraft.ConfigMgr.SQLConfig;
import jesse.keeblarcraft.ConfigMgr.SQLUnitTest;
import jesse.keeblarcraft.CustomBlocks.BlockList;
import jesse.keeblarcraft.CustomBlocks.BlockEntities.BlockEntityRegistration;
import jesse.keeblarcraft.CustomItems.ItemManager;
@ -120,8 +121,9 @@ public class Keeblarcraft implements ModInitializer {
BankManager.GetInstance().InitializeBanks();
System.out.println("Attempting SQL Registration call");
SQLConfig.GetInstance();
SQLUnitTest sqlTests = new SQLUnitTest();
sqlTests.RunTests();
/// THE BELOW ITEMS MUST BE DONE LAST IN THE STEPS
// Register items