Added type mappings between Skript and SQL
This commit is contained in:
		
							parent
							
								
									e99465ab13
								
							
						
					
					
						commit
						82bd53d107
					
				
							
								
								
									
										202
									
								
								src/main/java/com/btk5h/skriptdb/SkriptValueWrapper.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										202
									
								
								src/main/java/com/btk5h/skriptdb/SkriptValueWrapper.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,202 @@
 | 
			
		||||
package com.btk5h.skriptdb;
 | 
			
		||||
 | 
			
		||||
import static java.sql.Types.*;
 | 
			
		||||
 | 
			
		||||
import java.sql.ResultSet;
 | 
			
		||||
import java.sql.SQLException;
 | 
			
		||||
import java.sql.Timestamp;
 | 
			
		||||
import java.time.Instant;
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.function.Function;
 | 
			
		||||
import java.util.stream.IntStream;
 | 
			
		||||
 | 
			
		||||
import ch.njol.skript.util.Date;
 | 
			
		||||
import ch.njol.skript.util.Time;
 | 
			
		||||
 | 
			
		||||
public class SkriptValueWrapper {
 | 
			
		||||
	
 | 
			
		||||
	private static final Map<Class<?>, SkriptValueWrapper> wrappersBySkript = new HashMap<>();
 | 
			
		||||
	private static final Map<Integer, SkriptValueWrapper> wrappersBySql = new HashMap<>();
 | 
			
		||||
	
 | 
			
		||||
	
 | 
			
		||||
	public static final SkriptValueWrapper FALLBACK = register(Object.class, Function.identity(), ResultSet::getObject);
 | 
			
		||||
	public static final SkriptValueWrapper TEXT_VALUE = register(String.class, SkriptValueWrapper::asString, SkriptValueWrapper::getString, CHAR, VARCHAR, LONGVARCHAR, CLOB);
 | 
			
		||||
	public static final SkriptValueWrapper BOOLEAN_VALUE = register(Boolean.class, SkriptValueWrapper::asBoolean, ResultSet::getBoolean, BOOLEAN);
 | 
			
		||||
	public static final SkriptValueWrapper LONG_VALUE = register(Long.class, x -> x, SkriptValueWrapper::getLong, BIT, TINYINT, SMALLINT, INTEGER, BIGINT);
 | 
			
		||||
	public static final SkriptValueWrapper DOUBLE_VALUE = register(Double.class, x -> x, SkriptValueWrapper::getDouble, FLOAT, REAL, DOUBLE, NUMERIC, DECIMAL);
 | 
			
		||||
	public static final SkriptValueWrapper DATE_VALUE = register(String.class, SkriptValueWrapper::noParser, SkriptValueWrapper::getString, DATE);
 | 
			
		||||
	public static final SkriptValueWrapper TIME_VALUE = register(Time.class, SkriptValueWrapper::asTime, SkriptValueWrapper::getTime, TIME);
 | 
			
		||||
	public static final SkriptValueWrapper TIMESTAMP_VALUE = register(Date.class, SkriptValueWrapper::asTimestamp, SkriptValueWrapper::getTimestamp, TIMESTAMP);
 | 
			
		||||
	public static final SkriptValueWrapper BINARY_VALUE = register(String.class, SkriptValueWrapper::noParser, SkriptValueWrapper::getBinary, TIMESTAMP);
 | 
			
		||||
	
 | 
			
		||||
	
 | 
			
		||||
	
 | 
			
		||||
	private final Class<?> skriptType;
 | 
			
		||||
	private final Function<Object, Object> skToSqlMapper;
 | 
			
		||||
	private final ResultFetcher<Object> sqlToSkMapper;
 | 
			
		||||
	private final int[] validSqlTypes;
 | 
			
		||||
	
 | 
			
		||||
	
 | 
			
		||||
	@SuppressWarnings("unchecked")
 | 
			
		||||
	private <T> SkriptValueWrapper(Class<T> skriptType, Function<T, Object> skToSql, ResultFetcher<? super T> sqlToSk, int... validSqlTypes) {
 | 
			
		||||
		this.skriptType = skriptType;
 | 
			
		||||
		this.skToSqlMapper = (Function<Object, Object>) skToSql;
 | 
			
		||||
		this.sqlToSkMapper = (ResultFetcher<Object>) sqlToSk;
 | 
			
		||||
		this.validSqlTypes = IntStream.of(validSqlTypes)
 | 
			
		||||
				.sorted()
 | 
			
		||||
				.toArray();
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	
 | 
			
		||||
	public Object asSql(Object obj) {
 | 
			
		||||
		return this.skToSqlMapper.apply(obj);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	
 | 
			
		||||
	public boolean isSkApplicable(Class<?> type) {
 | 
			
		||||
		return this.skriptType.isAssignableFrom(type);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	
 | 
			
		||||
	public boolean isSqlApplicable(int sqlType) {
 | 
			
		||||
		return Arrays.binarySearch(this.validSqlTypes, sqlType) >= 0;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	
 | 
			
		||||
	public Object asSkript(ResultSet rs, int column) throws SQLException {
 | 
			
		||||
		return this.sqlToSkMapper.fetch(rs, column);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	
 | 
			
		||||
	public static SkriptValueWrapper getBySQLType(int type) {
 | 
			
		||||
		return wrappersBySql.getOrDefault(type, FALLBACK);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	
 | 
			
		||||
	public static SkriptValueWrapper getBySkriptType(Class<?> type) {
 | 
			
		||||
		return wrappersBySkript.getOrDefault(type, FALLBACK);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	
 | 
			
		||||
	public static SkriptValueWrapper getBySQLLType(int type) {
 | 
			
		||||
		return switch (type) {
 | 
			
		||||
			//case CHAR, VARCHAR, LONGVARCHAR, CLOB -> null; // string
 | 
			
		||||
			//case BOOLEAN -> null; // boolean
 | 
			
		||||
			//case BIT, TINYINT, SMALLINT, INTEGER, BIGINT -> null; // long
 | 
			
		||||
			//case FLOAT, REAL, DOUBLE, NUMERIC, DECIMAL -> null; // double
 | 
			
		||||
			//case DATE -> null; // string
 | 
			
		||||
			//case TIME -> null; // time
 | 
			
		||||
			//case TIMESTAMP -> null; // Date
 | 
			
		||||
			//case BINARY, VARBINARY, LONGVARBINARY, BLOB -> null; // hex String
 | 
			
		||||
			//case NULL, OTHER, JAVA_OBJECT, DISTINCT, STRUCT, ARRAY -> null; // just whatever it gives to me
 | 
			
		||||
			default -> null;
 | 
			
		||||
		};
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	
 | 
			
		||||
	private static <T> SkriptValueWrapper register(Class<T> skriptType, Function<T, Object> skToSql, ResultFetcher<? super T> sqlToSk, int... validSqlTypes) {
 | 
			
		||||
		SkriptValueWrapper wrapper = new SkriptValueWrapper(skriptType, skToSql, sqlToSk, validSqlTypes);
 | 
			
		||||
		wrappersBySkript.putIfAbsent(skriptType, wrapper);
 | 
			
		||||
		for (int i : validSqlTypes) {
 | 
			
		||||
			wrappersBySql.putIfAbsent(i, wrapper);
 | 
			
		||||
		}
 | 
			
		||||
		return wrapper;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	
 | 
			
		||||
	private static String getString(ResultSet rs, int column) throws SQLException {
 | 
			
		||||
		return rs.getString(column);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	private static String asString(Object obj) {
 | 
			
		||||
		return obj != null ? String.valueOf(obj) : null;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	
 | 
			
		||||
	private static Long getLong(ResultSet rs, int column) throws SQLException {
 | 
			
		||||
		var val = rs.getLong(column);
 | 
			
		||||
		if (!rs.wasNull()) {
 | 
			
		||||
			return val;
 | 
			
		||||
		}
 | 
			
		||||
		return null;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	
 | 
			
		||||
	private static Double getDouble(ResultSet rs, int column) throws SQLException {
 | 
			
		||||
		var val = rs.getDouble(column);
 | 
			
		||||
		if (!rs.wasNull()) {
 | 
			
		||||
			return val;
 | 
			
		||||
		}
 | 
			
		||||
		return null;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	
 | 
			
		||||
	private static final int TICKS_PER_HOUR = 1000;
 | 
			
		||||
	private static final double TICKS_PER_MINUTE = 1000. / 60;
 | 
			
		||||
	private static final int HOUR_ZERO = 6 * TICKS_PER_HOUR;
 | 
			
		||||
	
 | 
			
		||||
	private static Time getTime(ResultSet rs, int column) throws SQLException {
 | 
			
		||||
		var time = rs.getTime(column);
 | 
			
		||||
		if (time != null) {
 | 
			
		||||
			var local = time.toLocalTime();
 | 
			
		||||
			var minutes = local.getMinute();
 | 
			
		||||
			var hours = local.getHour();
 | 
			
		||||
			return new Time((int) Math.round(
 | 
			
		||||
					hours * TICKS_PER_HOUR
 | 
			
		||||
					- HOUR_ZERO
 | 
			
		||||
					+ minutes * TICKS_PER_MINUTE));
 | 
			
		||||
		}
 | 
			
		||||
		return null;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	private static Object asTime(Time time) {
 | 
			
		||||
		if (time != null) {
 | 
			
		||||
			return new java.sql.Time(time.getTime());
 | 
			
		||||
		}
 | 
			
		||||
		return null;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	
 | 
			
		||||
	private static Date getTimestamp(ResultSet rs, int column) throws SQLException {
 | 
			
		||||
		return new Date(rs.getTimestamp(column).getTime());
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	private static Object asTimestamp(Date date) {
 | 
			
		||||
		return Timestamp.from(Instant.ofEpochMilli(date.getTimestamp()));
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	private static Object asBoolean(Object obj) {
 | 
			
		||||
		if (obj instanceof Number n) {
 | 
			
		||||
			return n.doubleValue() > 0;
 | 
			
		||||
		} else if (obj instanceof Boolean b) {
 | 
			
		||||
			return b;
 | 
			
		||||
		}
 | 
			
		||||
		return null;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	
 | 
			
		||||
	private static String getBinary(ResultSet rs, int column) throws SQLException {
 | 
			
		||||
		byte[] bytes = rs.getBytes(column);
 | 
			
		||||
		if (!rs.wasNull()) {
 | 
			
		||||
			StringBuilder sb = new StringBuilder(bytes.length);
 | 
			
		||||
			for (int i = 0; i < bytes.length; i++) {
 | 
			
		||||
				sb.append(String.format("%02X", bytes[i]));
 | 
			
		||||
			}
 | 
			
		||||
			return sb.toString();
 | 
			
		||||
		}
 | 
			
		||||
		return null;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	
 | 
			
		||||
	private static <T, U> U noParser(T t) {
 | 
			
		||||
		throw new IllegalStateException("This value shouldn't have a parser");
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	
 | 
			
		||||
	private interface ResultFetcher<T> {
 | 
			
		||||
		public T fetch(ResultSet rs, int index) throws SQLException;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -1,33 +1,51 @@
 | 
			
		||||
package com.btk5h.skriptdb.skript;
 | 
			
		||||
 | 
			
		||||
import ch.njol.skript.Skript;
 | 
			
		||||
import ch.njol.skript.effects.Delay;
 | 
			
		||||
import ch.njol.skript.lang.*;
 | 
			
		||||
import ch.njol.skript.variables.Variables;
 | 
			
		||||
import ch.njol.util.Kleenean;
 | 
			
		||||
import ch.njol.util.Pair;
 | 
			
		||||
import com.btk5h.skriptdb.SkriptDB;
 | 
			
		||||
import com.btk5h.skriptdb.SkriptUtil;
 | 
			
		||||
import com.zaxxer.hikari.HikariDataSource;
 | 
			
		||||
import org.bukkit.Bukkit;
 | 
			
		||||
import org.bukkit.event.Event;
 | 
			
		||||
 | 
			
		||||
import javax.sql.DataSource;
 | 
			
		||||
import javax.sql.rowset.CachedRowSet;
 | 
			
		||||
import javax.sql.rowset.serial.SerialBlob;
 | 
			
		||||
import javax.sql.rowset.serial.SerialException;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.sql.Connection;
 | 
			
		||||
import java.sql.PreparedStatement;
 | 
			
		||||
import java.sql.ResultSet;
 | 
			
		||||
import java.sql.ResultSetMetaData;
 | 
			
		||||
import java.sql.SQLException;
 | 
			
		||||
import java.sql.Statement;
 | 
			
		||||
import java.util.*;
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Iterator;
 | 
			
		||||
import java.util.LinkedList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Locale;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.Optional;
 | 
			
		||||
import java.util.concurrent.CompletableFuture;
 | 
			
		||||
import java.util.concurrent.CompletionException;
 | 
			
		||||
import java.util.concurrent.ExecutorService;
 | 
			
		||||
import java.util.concurrent.Executors;
 | 
			
		||||
import java.util.regex.Pattern;
 | 
			
		||||
import java.util.stream.Stream;
 | 
			
		||||
 | 
			
		||||
import javax.sql.DataSource;
 | 
			
		||||
import javax.sql.rowset.serial.SerialBlob;
 | 
			
		||||
import javax.sql.rowset.serial.SerialException;
 | 
			
		||||
 | 
			
		||||
import org.bukkit.Bukkit;
 | 
			
		||||
import org.bukkit.event.Event;
 | 
			
		||||
 | 
			
		||||
import com.btk5h.skriptdb.SkriptDB;
 | 
			
		||||
import com.btk5h.skriptdb.SkriptUtil;
 | 
			
		||||
import com.btk5h.skriptdb.SkriptValueWrapper;
 | 
			
		||||
import com.zaxxer.hikari.HikariDataSource;
 | 
			
		||||
 | 
			
		||||
import ch.njol.skript.Skript;
 | 
			
		||||
import ch.njol.skript.effects.Delay;
 | 
			
		||||
import ch.njol.skript.lang.Effect;
 | 
			
		||||
import ch.njol.skript.lang.Expression;
 | 
			
		||||
import ch.njol.skript.lang.SkriptParser;
 | 
			
		||||
import ch.njol.skript.lang.Trigger;
 | 
			
		||||
import ch.njol.skript.lang.TriggerItem;
 | 
			
		||||
import ch.njol.skript.lang.Variable;
 | 
			
		||||
import ch.njol.skript.lang.VariableString;
 | 
			
		||||
import ch.njol.skript.variables.Variables;
 | 
			
		||||
import ch.njol.util.Kleenean;
 | 
			
		||||
import ch.njol.util.Pair;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Executes a statement on a database and optionally stores the result in a variable. Expressions
 | 
			
		||||
@ -72,7 +90,7 @@ public class EffExecuteStatement extends Effect {
 | 
			
		||||
        DataSource ds = dataSource.getSingle(e);
 | 
			
		||||
        //if data source isn't set
 | 
			
		||||
        if (ds == null) {
 | 
			
		||||
        	return;
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        Pair<String, List<Object>> parsedQuery = parseQuery(e);
 | 
			
		||||
        String baseVariable = resultVariableName != null ? resultVariableName.toString(e).toLowerCase(Locale.ENGLISH) : null;
 | 
			
		||||
@ -82,22 +100,22 @@ public class EffExecuteStatement extends Effect {
 | 
			
		||||
        //execute SQL statement
 | 
			
		||||
        if (Bukkit.isPrimaryThread()) {
 | 
			
		||||
            CompletableFuture.supplyAsync(() -> executeStatement(ds, baseVariable, parsedQuery), threadPool)
 | 
			
		||||
		            .whenComplete((resources, err) -> {
 | 
			
		||||
		            	//handle last error syntax data
 | 
			
		||||
		            	resetLastSQLError();
 | 
			
		||||
		            	if (err instanceof CompletionException && err.getCause() instanceof SkriptDBQueryException) {
 | 
			
		||||
	            			setLastSQLError(err.getCause().getMessage());
 | 
			
		||||
	            		}
 | 
			
		||||
		                //if local variables are present
 | 
			
		||||
		                //bring back local variables
 | 
			
		||||
		                //populate SQL data into variables
 | 
			
		||||
		                if (!quickly) {
 | 
			
		||||
		                    Bukkit.getScheduler().runTask(SkriptDB.getInstance(),
 | 
			
		||||
		                    		() -> postExecution(e, locals, resources));
 | 
			
		||||
		                } else {
 | 
			
		||||
		                	postExecution(e, locals, resources);
 | 
			
		||||
		                }
 | 
			
		||||
		            });
 | 
			
		||||
                    .whenComplete((resources, err) -> {
 | 
			
		||||
                        //handle last error syntax data
 | 
			
		||||
                        resetLastSQLError();
 | 
			
		||||
                        if (err instanceof CompletionException && err.getCause() instanceof SkriptDBQueryException) {
 | 
			
		||||
                            setLastSQLError(err.getCause().getMessage());
 | 
			
		||||
                        }
 | 
			
		||||
                        //if local variables are present
 | 
			
		||||
                        //bring back local variables
 | 
			
		||||
                        //populate SQL data into variables
 | 
			
		||||
                        if (!quickly) {
 | 
			
		||||
                            Bukkit.getScheduler().runTask(SkriptDB.getInstance(),
 | 
			
		||||
                                    () -> postExecution(e, locals, resources));
 | 
			
		||||
                        } else {
 | 
			
		||||
                            postExecution(e, locals, resources);
 | 
			
		||||
                        }
 | 
			
		||||
                    });
 | 
			
		||||
            // sync executed SQL query, same as above, just sync
 | 
			
		||||
        } else {
 | 
			
		||||
            isSync = true;
 | 
			
		||||
@ -105,23 +123,23 @@ public class EffExecuteStatement extends Effect {
 | 
			
		||||
            resetLastSQLError();
 | 
			
		||||
            try {
 | 
			
		||||
                resources = executeStatement(ds, baseVariable, parsedQuery);
 | 
			
		||||
			} catch (SkriptDBQueryException err) {
 | 
			
		||||
	            //handle last error syntax data
 | 
			
		||||
				setLastSQLError(err.getMessage());
 | 
			
		||||
			}
 | 
			
		||||
            } catch (SkriptDBQueryException err) {
 | 
			
		||||
                //handle last error syntax data
 | 
			
		||||
                setLastSQLError(err.getMessage());
 | 
			
		||||
            }
 | 
			
		||||
            //if local variables are present
 | 
			
		||||
            //bring back local variables
 | 
			
		||||
            //populate SQL data into variables
 | 
			
		||||
			postExecution(e, locals, resources);
 | 
			
		||||
            postExecution(e, locals, resources);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    private void postExecution(Event e, Object locals, Map<String, Object> resources) {
 | 
			
		||||
    	if (locals != null && getNext() != null) {
 | 
			
		||||
        if (locals != null && getNext() != null) {
 | 
			
		||||
            Variables.setLocalVariables(e, locals);
 | 
			
		||||
        }
 | 
			
		||||
        if (resources != null) {
 | 
			
		||||
        	resources.forEach((name, value) -> setVariable(e, name, value));
 | 
			
		||||
            resources.forEach((name, value) -> setVariable(e, name, value));
 | 
			
		||||
        }
 | 
			
		||||
        TriggerItem.walk(getNext(), e);
 | 
			
		||||
        //the line below is required to prevent memory leaks
 | 
			
		||||
@ -145,15 +163,18 @@ public class EffExecuteStatement extends Effect {
 | 
			
		||||
            int queryArgCount = (int) ARGUMENT_PLACEHOLDER.matcher(queryString).results().count();
 | 
			
		||||
            if (queryArgCount != args.length) {
 | 
			
		||||
                Skript.warning(String.format("Your query has %d question marks, but you provided %d arguments. (%s) [%s]",
 | 
			
		||||
                		queryArgCount,
 | 
			
		||||
                		args.length,
 | 
			
		||||
                		queryArguments.toString(e, true),
 | 
			
		||||
                		Optional.ofNullable(getTrigger())
 | 
			
		||||
                				.map(Trigger::getDebugLabel)
 | 
			
		||||
                				.orElse("unknown")));
 | 
			
		||||
                        queryArgCount,
 | 
			
		||||
                        args.length,
 | 
			
		||||
                        queryArguments.toString(e, true),
 | 
			
		||||
                        Optional.ofNullable(getTrigger())
 | 
			
		||||
                                .map(Trigger::getDebugLabel)
 | 
			
		||||
                                .orElse("unknown")));
 | 
			
		||||
                args = Arrays.copyOf(args, queryArgCount);
 | 
			
		||||
            }
 | 
			
		||||
            return new Pair<>(query.getSingle(e), Arrays.asList(args));
 | 
			
		||||
            List<Object> argsList = Stream.of(args)
 | 
			
		||||
            		.map(arg -> SkriptValueWrapper.getBySkriptType(arg.getClass()).asSql(arg))
 | 
			
		||||
            		.toList();
 | 
			
		||||
            return new Pair<>(query.getSingle(e), argsList);
 | 
			
		||||
        } else if (query instanceof VariableString && !((VariableString) query).isSimple()) {
 | 
			
		||||
            return parseVariableQuery(e, (VariableString) query);
 | 
			
		||||
        }
 | 
			
		||||
@ -201,7 +222,7 @@ public class EffExecuteStatement extends Effect {
 | 
			
		||||
 | 
			
		||||
    private Map<String, Object> executeStatement(DataSource ds, String baseVariable, Pair<String, List<Object>> query) throws SkriptDBQueryException {
 | 
			
		||||
        if (ds == null) {
 | 
			
		||||
        	throw new SkriptDBQueryException("Data source is not set");
 | 
			
		||||
            throw new SkriptDBQueryException("Data source is not set");
 | 
			
		||||
        }
 | 
			
		||||
        try (Connection conn = ds.getConnection()) {
 | 
			
		||||
            try (PreparedStatement stmt = createStatement(conn, query)) {
 | 
			
		||||
@ -223,14 +244,16 @@ public class EffExecuteStatement extends Effect {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (hasResultSet) {
 | 
			
		||||
            CachedRowSet crs = SkriptDB.getRowSetFactory().createCachedRowSet();
 | 
			
		||||
            crs.populate(generatedKeys ? stmt.getGeneratedKeys() : stmt.getResultSet());
 | 
			
		||||
        	// TODO: Check if caching is even needed
 | 
			
		||||
            //CachedRowSet crs = SkriptDB.getRowSetFactory().createCachedRowSet();
 | 
			
		||||
            ResultSet rs = generatedKeys ? stmt.getGeneratedKeys() : stmt.getResultSet();
 | 
			
		||||
            //crs.populate(rs);
 | 
			
		||||
 | 
			
		||||
            if (isList) {
 | 
			
		||||
                return fetchQueryResultSet(crs, baseVariable);
 | 
			
		||||
                return fetchQueryResultSet(rs, baseVariable);
 | 
			
		||||
            } else {
 | 
			
		||||
                crs.last();
 | 
			
		||||
                return Map.of(baseVariable, crs.getRow());
 | 
			
		||||
            	rs.last();
 | 
			
		||||
                return Map.of(baseVariable, rs.getRow());
 | 
			
		||||
            }
 | 
			
		||||
        } else if (!isList) {
 | 
			
		||||
            //if no results are returned and the specified variable isn't a list variable, put the affected rows count in the variable
 | 
			
		||||
@ -239,21 +262,25 @@ public class EffExecuteStatement extends Effect {
 | 
			
		||||
        return Map.of();
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    private Map<String, Object> fetchQueryResultSet(CachedRowSet crs, String baseVariable) throws SQLException {
 | 
			
		||||
        Map<String, Object> variableList = new HashMap<>();
 | 
			
		||||
    private Map<String, Object> fetchQueryResultSet(/*CachedRowSet*/ResultSet crs, String baseVariable) throws SQLException {
 | 
			
		||||
    	Map<String, Object> variableList = new HashMap<>();
 | 
			
		||||
        ResultSetMetaData meta = crs.getMetaData();
 | 
			
		||||
        int columnCount = meta.getColumnCount();
 | 
			
		||||
 | 
			
		||||
        SkriptValueWrapper[] wrappers = new SkriptValueWrapper[columnCount];
 | 
			
		||||
        String[] columnNames = new String[columnCount];
 | 
			
		||||
        for (int i = 1; i <= columnCount; i++) {
 | 
			
		||||
            String label = meta.getColumnLabel(i);
 | 
			
		||||
            variableList.put(baseVariable + label, label);
 | 
			
		||||
            columnNames[i - 1] = label;
 | 
			
		||||
            wrappers[i - 1] = SkriptValueWrapper.getBySQLType(meta.getColumnType(i));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
        int rowNumber = 1;
 | 
			
		||||
        while (crs.next()) {
 | 
			
		||||
            for (int i = 1; i <= columnCount; i++) {
 | 
			
		||||
                variableList.put(baseVariable + meta.getColumnLabel(i).toLowerCase(Locale.ENGLISH)
 | 
			
		||||
                        + Variable.SEPARATOR + rowNumber, crs.getObject(i));
 | 
			
		||||
            	Object obj = wrappers[i - 1].asSkript(crs, i);
 | 
			
		||||
                variableList.put(baseVariable + columnNames[i - 1].toLowerCase(Locale.ENGLISH)
 | 
			
		||||
                        + Variable.SEPARATOR + rowNumber, obj);
 | 
			
		||||
            }
 | 
			
		||||
            rowNumber++;
 | 
			
		||||
        }
 | 
			
		||||
@ -262,8 +289,8 @@ public class EffExecuteStatement extends Effect {
 | 
			
		||||
 | 
			
		||||
    private PreparedStatement createStatement(Connection conn, Pair<String, List<Object>> query) throws SQLException {
 | 
			
		||||
        PreparedStatement stmt = generatedKeys ? 
 | 
			
		||||
        		conn.prepareStatement(query.getFirst(), Statement.RETURN_GENERATED_KEYS)
 | 
			
		||||
        		: conn.prepareStatement(query.getFirst(), Statement.NO_GENERATED_KEYS);
 | 
			
		||||
                conn.prepareStatement(query.getFirst(), Statement.RETURN_GENERATED_KEYS)
 | 
			
		||||
                : conn.prepareStatement(query.getFirst(), Statement.NO_GENERATED_KEYS);
 | 
			
		||||
        if (query.getSecond() != null) {
 | 
			
		||||
            Iterator<Object> iter = query.getSecond().iterator();
 | 
			
		||||
            for (int i = 1; iter.hasNext(); i++) {
 | 
			
		||||
@ -307,11 +334,11 @@ public class EffExecuteStatement extends Effect {
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    private static void resetLastSQLError() {
 | 
			
		||||
    	lastError = null;
 | 
			
		||||
        lastError = null;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    private static void setLastSQLError(String error) {
 | 
			
		||||
    	lastError = error;
 | 
			
		||||
        lastError = error;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
@ -338,7 +365,6 @@ public class EffExecuteStatement extends Effect {
 | 
			
		||||
            }
 | 
			
		||||
            queryArguments = (Expression<Object>) exprs[2];
 | 
			
		||||
        }
 | 
			
		||||
        ;
 | 
			
		||||
        Expression<?> resultHolder = exprs[3];
 | 
			
		||||
        quickly = parseResult.hasTag("quickly");
 | 
			
		||||
        if (resultHolder instanceof Variable) {
 | 
			
		||||
@ -356,12 +382,12 @@ public class EffExecuteStatement extends Effect {
 | 
			
		||||
    
 | 
			
		||||
    public static class SkriptDBQueryException extends RuntimeException {
 | 
			
		||||
 | 
			
		||||
		private static final long serialVersionUID = -1869895286406538884L;
 | 
			
		||||
		
 | 
			
		||||
		public SkriptDBQueryException(String message) {
 | 
			
		||||
			super(message);
 | 
			
		||||
		}
 | 
			
		||||
    	
 | 
			
		||||
        private static final long serialVersionUID = -1869895286406538884L;
 | 
			
		||||
        
 | 
			
		||||
        public SkriptDBQueryException(String message) {
 | 
			
		||||
            super(message);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user