package com.cube.sql;
import com.cube.cql.CQLParser;
import com.cube.cql.QueryExecutor;
import com.cube.storage.StorageEngine;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
/**
* SQL Executor - Executes SQL statements by translating to internal operations
*/
public class SQLExecutor {
private static final Logger logger = LoggerFactory.getLogger(SQLExecutor.class);
private final QueryExecutor queryExecutor;
private final StorageEngine storageEngine;
public static class SQLResult {
private final boolean success;
private final String message;
private final List<Map<String, String>> rows;
private final int rowsAffected;
public SQLResult(boolean success, String message, List<Map<String, String>> rows, int rowsAffected) {
this.success = success;
this.message = message;
this.rows = rows != null ? rows : new ArrayList<>();
this.rowsAffected = rowsAffected;
}
public boolean isSuccess() { return success; }
public String getMessage() { return message; }
public List<Map<String, String>> getRows() { return rows; }
public int getRowsAffected() { return rowsAffected; }
public static SQLResult success(String message) {
return new SQLResult(true, message, null, 0);
}
public static SQLResult success(String message, int rowsAffected) {
return new SQLResult(true, message, null, rowsAffected);
}
public static SQLResult success(List<Map<String, String>> rows) {
return new SQLResult(true, "Query executed successfully", rows, rows.size());
}
public static SQLResult error(String message) {
return new SQLResult(false, message, null, 0);
}
}
public SQLExecutor(QueryExecutor queryExecutor, StorageEngine storageEngine) {
this.queryExecutor = queryExecutor;
this.storageEngine = storageEngine;
}
/**
* Execute SQL statement
*/
public SQLResult execute(String sql) {
try {
SQLParser.ParsedSQL parsedSQL = SQLParser.parse(sql);
logger.info("Executing SQL: {} (Type: {})", sql, parsedSQL.getType());
switch (parsedSQL.getType()) {
case SELECT:
return executeSelect(parsedSQL);
case INSERT:
return executeInsert(parsedSQL);
case UPDATE:
return executeUpdate(parsedSQL);
case DELETE:
return executeDelete(parsedSQL);
case CREATE_TABLE:
return executeCreateTable(parsedSQL);
case DROP_TABLE:
return executeDropTable(parsedSQL);
case DESCRIBE:
return executeDescribe(parsedSQL);
case SHOW_TABLES:
return executeShowTables();
default:
return SQLResult.error("Unsupported SQL type: " + parsedSQL.getType());
}
} catch (Exception e) {
logger.error("SQL execution error", e);
return SQLResult.error("Error: " + e.getMessage());
}
}
/**
* Execute SELECT statement
*/
private SQLResult executeSelect(SQLParser.ParsedSQL sql) {
try {
// Build CQL query
StringBuilder cql = new StringBuilder("SELECT ");
if (sql.getSelectColumns().contains("*")) {
cql.append("*");
} else {
cql.append(String.join(", ", sql.getSelectColumns()));
}
cql.append(" FROM ").append(sql.getKeyspace()).append(".").append(sql.getTable());
if (!sql.getWhereClause().isEmpty()) {
cql.append(" WHERE ");
List<String> conditions = new ArrayList<>();
for (Map.Entry<String, String> entry : sql.getWhereClause().entrySet()) {
conditions.add(entry.getKey() + " = '" + entry.getValue() + "'");
}
cql.append(String.join(" AND ", conditions));
}
// Execute via CQL
CQLParser.ParsedQuery parsedQuery = CQLParser.parse(cql.toString());
QueryExecutor.Result result = queryExecutor.execute(parsedQuery);
if (result.isSuccess()) {
return SQLResult.success(convertRows(result.getRows()));
} else {
return SQLResult.error(result.getMessage());
}
} catch (Exception e) {
return SQLResult.error("SELECT error: " + e.getMessage());
}
}
/**
* Execute INSERT statement
*/
private SQLResult executeInsert(SQLParser.ParsedSQL sql) {
try {
// Build CQL query
StringBuilder cql = new StringBuilder("INSERT INTO ");
cql.append(sql.getKeyspace()).append(".").append(sql.getTable());
cql.append(" (");
List<String> columns = new ArrayList<>(sql.getColumns().keySet());
cql.append(String.join(", ", columns));
cql.append(") VALUES (");
List<String> values = new ArrayList<>();
for (String col : columns) {
values.add("'" + sql.getColumns().get(col) + "'");
}
cql.append(String.join(", ", values));
cql.append(")");
// Execute via CQL
CQLParser.ParsedQuery parsedQuery = CQLParser.parse(cql.toString());
QueryExecutor.Result result = queryExecutor.execute(parsedQuery);
if (result.isSuccess()) {
return SQLResult.success(result.getMessage(), result.getRowsAffected());
} else {
return SQLResult.error(result.getMessage());
}
} catch (Exception e) {
return SQLResult.error("INSERT error: " + e.getMessage());
}
}
/**
* Execute UPDATE statement
*/
private SQLResult executeUpdate(SQLParser.ParsedSQL sql) {
try {
// Build CQL query
StringBuilder cql = new StringBuilder("UPDATE ");
cql.append(sql.getKeyspace()).append(".").append(sql.getTable());
cql.append(" SET ");
List<String> sets = new ArrayList<>();
for (Map.Entry<String, String> entry : sql.getColumns().entrySet()) {
sets.add(entry.getKey() + "='" + entry.getValue() + "'");
}
cql.append(String.join(", ", sets));
cql.append(" WHERE ");
List<String> conditions = new ArrayList<>();
for (Map.Entry<String, String> entry : sql.getWhereClause().entrySet()) {
conditions.add(entry.getKey() + "='" + entry.getValue() + "'");
}
cql.append(String.join(" AND ", conditions));
// Execute via CQL
CQLParser.ParsedQuery parsedQuery = CQLParser.parse(cql.toString());
QueryExecutor.Result result = queryExecutor.execute(parsedQuery);
if (result.isSuccess()) {
return SQLResult.success(result.getMessage(), result.getRowsAffected());
} else {
return SQLResult.error(result.getMessage());
}
} catch (Exception e) {
return SQLResult.error("UPDATE error: " + e.getMessage());
}
}
/**
* Execute DELETE statement
*/
private SQLResult executeDelete(SQLParser.ParsedSQL sql) {
try {
// Build CQL query
StringBuilder cql = new StringBuilder("DELETE FROM ");
cql.append(sql.getKeyspace()).append(".").append(sql.getTable());
cql.append(" WHERE ");
List<String> conditions = new ArrayList<>();
for (Map.Entry<String, String> entry : sql.getWhereClause().entrySet()) {
conditions.add(entry.getKey() + "='" + entry.getValue() + "'");
}
cql.append(String.join(" AND ", conditions));
// Execute via CQL
CQLParser.ParsedQuery parsedQuery = CQLParser.parse(cql.toString());
QueryExecutor.Result result = queryExecutor.execute(parsedQuery);
if (result.isSuccess()) {
return SQLResult.success(result.getMessage(), result.getRowsAffected());
} else {
return SQLResult.error(result.getMessage());
}
} catch (Exception e) {
return SQLResult.error("DELETE error: " + e.getMessage());
}
}
/**
* Execute CREATE TABLE statement
*/
private SQLResult executeCreateTable(SQLParser.ParsedSQL sql) {
try {
// Build CQL query
StringBuilder cql = new StringBuilder("CREATE TABLE ");
cql.append(sql.getKeyspace()).append(".").append(sql.getTable());
cql.append(" (");
List<String> colDefs = new ArrayList<>();
for (Map.Entry<String, String> entry : sql.getColumnDefinitions().entrySet()) {
colDefs.add(entry.getKey() + " " + entry.getValue());
}
cql.append(String.join(", ", colDefs));
cql.append(")");
// Execute via CQL
CQLParser.ParsedQuery parsedQuery = CQLParser.parse(cql.toString());
QueryExecutor.Result result = queryExecutor.execute(parsedQuery);
if (result.isSuccess()) {
return SQLResult.success("Table created: " + sql.getKeyspace() + "." + sql.getTable());
} else {
return SQLResult.error(result.getMessage());
}
} catch (Exception e) {
return SQLResult.error("CREATE TABLE error: " + e.getMessage());
}
}
/**
* Execute DROP TABLE statement
*/
private SQLResult executeDropTable(SQLParser.ParsedSQL sql) {
return SQLResult.error("DROP TABLE not yet implemented");
}
/**
* Execute DESCRIBE statement
*/
private SQLResult executeDescribe(SQLParser.ParsedSQL sql) {
return SQLResult.error("DESCRIBE not yet implemented");
}
/**
* Execute SHOW TABLES statement
*/
private SQLResult executeShowTables() {
return SQLResult.error("SHOW TABLES not yet implemented");
}
/**
* Convert CQL rows to SQL result format
*/
private List<Map<String, String>> convertRows(List<Map<String, byte[]>> cqlRows) {
List<Map<String, String>> sqlRows = new ArrayList<>();
for (Map<String, byte[]> cqlRow : cqlRows) {
Map<String, String> sqlRow = new LinkedHashMap<>();
for (Map.Entry<String, byte[]> entry : cqlRow.entrySet()) {
if (entry.getValue() != null) {
sqlRow.put(entry.getKey(), new String(entry.getValue()));
} else {
sqlRow.put(entry.getKey(), null);
}
}
sqlRows.add(sqlRow);
}
return sqlRows;
}
}