diff --git a/src/main/java/com/cube/shell/CubeShell.java b/src/main/java/com/cube/shell/CubeShell.java index 31ac4a5..4694ea7 100644 --- a/src/main/java/com/cube/shell/CubeShell.java +++ b/src/main/java/com/cube/shell/CubeShell.java @@ -25,10 +25,37 @@ * - View replication statistics */ public class CubeShell { + // 0x1000-table start. --16 + // 0x1100-table end. --16+4 + // + // 0x0001-right alignment -- 1 + // 0x0010-left alignment. == 2 + // 0x0011- center. ==3 + private static final String VERSION = "2.0.0"; private static final String PROMPT = "cube> "; - + private static final int FMT_TABLE = 16; + private static final int FMT_TABLE_END = 4; + private static final int FMT_RIGHT_ALIGN= 1; + private static final int FMT_LEFT_ALIGN= 2; + private static final int FMT_CENTER_ALIGN=FMT_LEFT_ALIGN|FMT_RIGHT_ALIGN; + private static final int FMT_TABLE_SEPRATOR = 8; + + + private static final String TABLE_BORDER_VERTICAL = "║"; + private static final String TABLE_START_LEFT="╔"; + private static final String TABLE_START_RIGHT="╗"; + + + private static final String TABLE_END_LEFT="╚"; + private static final String TABLE_END_RIGHT="╝"; + + private static final int TABLE_MAX_LENGTH =100 ; + private static final String TABLE_BORDER_HORIZANTAL = "═"; + private static final String TABLE_SEPRATOR_LEFT = "╠"; + private static final String TABLE_SEPRATOR_RIGHT = "╣"; + private final List clusterNodes; private ClusterNode currentNode; private ConsistencyLevel defaultConsistencyLevel; @@ -76,16 +103,147 @@ } private void printBanner() { - System.out.println("╔══════════════════════════════════════════════════════════╗"); - System.out.println("║ 🌵 CubeShell v" + VERSION + " ║"); - System.out.println("║ CubeCactus Interactive Shell ║"); - System.out.println("║ SQL/CQL + Cluster Management ║"); - System.out.println("╚══════════════════════════════════════════════════════════╝"); + System.out.println( fillChar(TABLE_MAX_LENGTH, "═")); + System.out.println( fillFormat(TABLE_MAX_LENGTH, "CubeShell v" + VERSION + " ", " ", FMT_CENTER_ALIGN |FMT_TABLE, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, "CubeCactus Interactive Shell", " ", FMT_CENTER_ALIGN , true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, "SQL/CQL + Cluster Management", " ", FMT_CENTER_ALIGN |FMT_TABLE| FMT_TABLE_END, true)); System.out.println(); System.out.println("Type 'HELP' for available commands, 'EXIT' to quit."); System.out.println(); + } - + + private String fillFormat(int len, String text, String filler, int align, boolean table) { + StringBuilder sb = new StringBuilder(); + + //System.out.printf("align="+ align + "(align & FMT_TABLE_START)" + (align & FMT_TABLE_START) + "==" + FMT_TABLE_START ); + if (((align & FMT_TABLE) == FMT_TABLE) && (align & FMT_TABLE_END) != FMT_TABLE_END &&((align & FMT_TABLE_SEPRATOR) != FMT_TABLE_SEPRATOR)) { + int startLen=len; + if (table) { + startLen= startLen -2; + } + + if (table) { + sb.append(TABLE_START_LEFT); + } + + sb.append(TABLE_BORDER_HORIZANTAL.repeat(startLen)); + if (table) { + sb.append(TABLE_START_RIGHT); + } + sb.append("\n"); + } + + + if ((((align & FMT_TABLE) == FMT_TABLE) && (align & FMT_TABLE_END) != FMT_TABLE_END) &&((align & FMT_TABLE_SEPRATOR) == FMT_TABLE_SEPRATOR)) { + int startLen=len; + if (table) { + startLen= startLen -2; + } + + if (table) { + sb.append(TABLE_SEPRATOR_LEFT); + } + + sb.append(TABLE_BORDER_HORIZANTAL.repeat(startLen)); + if (table) { + sb.append(TABLE_SEPRATOR_RIGHT); + } + sb.append("\n"); + } + + if ((align & FMT_CENTER_ALIGN) == FMT_CENTER_ALIGN) { + int textLen= text.length(); + int centerLen= len; + if (table) { + centerLen = centerLen -2; + } + if (textLen < centerLen) { + int padLen= centerLen-textLen; + int leftPadLen= padLen/2; + int rightPadLen=centerLen- (leftPadLen +textLen); + if (table) { + sb.append(TABLE_BORDER_VERTICAL); + } + + sb.append(filler.repeat(leftPadLen)); + sb.append(text); + sb.append(filler.repeat(rightPadLen)); + if (table) { + sb.append(TABLE_BORDER_VERTICAL); + } + } else { + sb.append(text); + } + } else if ((align & FMT_LEFT_ALIGN) == FMT_LEFT_ALIGN) { + int textLen= text.length(); + int leftLen= len; + if (table) { + leftLen = leftLen -2; + } + if (textLen < leftLen) { + + int rightPadLen=leftLen-textLen; + if (table) { + sb.append(TABLE_BORDER_VERTICAL); + } + + sb.append(text); + sb.append(filler.repeat(rightPadLen)); + if (table) { + sb.append(TABLE_BORDER_VERTICAL); + } + } else { + sb.append(text); + } + } else if ((align & FMT_RIGHT_ALIGN) == FMT_RIGHT_ALIGN) { + int textLen= text.length(); + int rightLen= len; + if (table) { + rightLen = rightLen -2; + } + if (textLen < rightLen) { + + int leftPadLen=rightLen-textLen; + if (table) { + sb.append(TABLE_BORDER_VERTICAL); + } + sb.append(filler.repeat(leftPadLen)); + sb.append(text); + + if (table) { + sb.append(TABLE_BORDER_VERTICAL); + } + } else { + sb.append(text); + } + } + + if (((align & FMT_TABLE) == FMT_TABLE) && (align & FMT_TABLE_END) == FMT_TABLE_END) { + sb.append("\n"); + int startLen=len; + if (table) { + startLen= startLen -2; + } + + if (table) { + sb.append(TABLE_END_LEFT); + } + + sb.append(TABLE_BORDER_HORIZANTAL.repeat(startLen)); + if (table) { + sb.append(TABLE_END_RIGHT); + } + sb.append("\n"); + } + return sb.toString(); + // return len/2 + text.length(), + } + + private String fillChar(int len, String s) { + return s.repeat(len); + } + private void run() { try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) { while (running) { @@ -213,81 +371,52 @@ } private void showHelp() { - System.out.println("\n╔════════════════════════════════════════════════════════════╗"); - System.out.println("║ CubeShell Commands ║"); - System.out.println("╠════════════════════════════════════════════════════════════╣"); - System.out.println("║ SQL/CQL Queries: ║"); - System.out.println("║ CREATE TABLE keyspace.table (col TYPE, ...) ║"); - System.out.println("║ INSERT INTO table (cols) VALUES (vals) ║"); - System.out.println("║ SELECT * FROM table WHERE id = 'value' ║"); - System.out.println("║ UPDATE table SET col='val' WHERE id='value' ║"); - System.out.println("║ DELETE FROM table WHERE id='value' ║"); - System.out.println("║ DESCRIBE table ║"); - System.out.println("║ SHOW TABLES ║"); - System.out.println("║ ║"); - System.out.println("║ Examples: ║"); - System.out.println("║ CREATE TABLE users (id TEXT PRIMARY KEY, name TEXT) ║"); - System.out.println("║ INSERT INTO users (id, name) VALUES ('1', 'Alice') ║"); - System.out.println("║ SELECT * FROM users WHERE id = '1' ║"); - System.out.println("║ UPDATE users SET name = 'Bob' WHERE id = '1' ║"); - System.out.println("║ ║"); - System.out.println("║ Key-Value Operations: ║"); - System.out.println("║ PUT - Store key-value pair ║"); - System.out.println("║ GET - Retrieve value ║"); - System.out.println("║ DEL - Delete key ║"); - System.out.println("║ SCAN - Scan keys by prefix ║"); - System.out.println("║ ║"); - System.out.println("║ Cluster Management: ║"); - System.out.println("║ CONNECT - Connect to node ║"); - System.out.println("║ DISCONNECT - Disconnect from node ║"); - System.out.println("║ NODES / CLUSTER - Show cluster topology ║"); - System.out.println("║ USE - Switch active node ║"); - System.out.println("║ STATUS - Show current node status ║"); - System.out.println("║ STATS - Show replication stats ║"); - System.out.println("║ ║"); - System.out.println("║ Consistency: ║"); - System.out.println("║ CONSISTENCY - Set consistency (ONE/QUORUM/ALL)║"); - System.out.println("║ CL - Short form ║"); - System.out.println("║ ║"); - System.out.println("║ Utility: ║"); - System.out.println("║ HISTORY - Show command history ║"); - System.out.println("║ CLEAR / CLS - Clear screen ║"); - System.out.println("║ HELP / ? - Show this help ║"); - System.out.println("║ EXIT / QUIT - Exit shell ║"); - System.out.println("╚════════════════════════════════════════════════════════════╝\n"); + System.out.println( fillFormat(TABLE_MAX_LENGTH, "CubeShell Commands v" + VERSION + " ", " ", FMT_CENTER_ALIGN |FMT_TABLE, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, "SQL/CQL Queries:" + VERSION + " ", " ", FMT_LEFT_ALIGN |FMT_TABLE|FMT_TABLE_SEPRATOR, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " CREATE TABLE keyspace.table (col TYPE, ...) " + VERSION + " ", " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " INSERT INTO table (cols) VALUES (vals) " + VERSION + " ", " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " INSERT INTO table (cols) VALUES (vals) " , " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " SELECT * FROM table WHERE id = 'value' " , " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " UPDATE table SET col='val' WHERE id='value' " , " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " DELETE FROM table WHERE id='value' " , " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " DESCRIBE table " , " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " SHOW TABLES " , " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " " , " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " Examples: " , " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " CREATE TABLE users (id TEXT PRIMARY KEY, name TEXT) " , " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " INSERT INTO users (id, name) VALUES ('1', 'Alice') " , " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " SELECT * FROM users WHERE id = '1' " , " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " UPDATE users SET name = 'Bob' WHERE id = '1' " , " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " " , " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " Key-Value Operations: " , " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " PUT - Store key-value pair " , " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " GET - Retrieve value " , " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " DEL - Delete key " , " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " SCAN - Scan keys by prefix " , " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " " , " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " Cluster Management: " , " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " CONNECT - Connect to node " , " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " DISCONNECT - Disconnect from node " , " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " NODES / CLUSTER - Show cluster topology " , " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " USE - Switch active node " , " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " STATUS - Show current node status " , " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " STATS - Show replication stats " , " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " " , " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " Consistency: " , " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " CONSISTENCY - Set consistency (ONE/QUORUM/ALL)" , " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " CL - Short form ", " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " ", " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " Utility: ", " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " HISTORY - Show command history ", " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " CLEAR / CLS - Clear screen ", " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " HELP / ? - Show this help ", " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " EXIT / QUIT - Exit shell ", " ", FMT_LEFT_ALIGN|FMT_TABLE|FMT_TABLE_SEPRATOR, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " ", " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " SELECT * FROM table WHERE id = 'value' ", " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " UPDATE table SET col='val' WHERE id='value' ", " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " DELETE FROM table WHERE id='value' ", " ", FMT_LEFT_ALIGN, true)); + System.out.println( fillFormat(TABLE_MAX_LENGTH, " DESCRIBE table ", " ", FMT_LEFT_ALIGN, true)); - System.out.println("║ SELECT * FROM table WHERE id = 'value' ║"); - System.out.println("║ UPDATE table SET col='val' WHERE id='value' ║"); - System.out.println("║ DELETE FROM table WHERE id='value' ║"); - System.out.println("║ DESCRIBE table ║"); - System.out.println("║ SHOW TABLES ║"); - System.out.println("║ ║"); - System.out.println("║ Cluster Management: ║"); - System.out.println("║ CONNECT - Add node to cluster ║"); - System.out.println("║ DISCONNECT - Remove node from cluster ║"); - System.out.println("║ NODES / CLUSTER - Show all cluster nodes ║"); - System.out.println("║ USE - Switch to specific node ║"); - System.out.println("║ STATUS - Show current node status ║"); - System.out.println("║ STATS - Show replication statistics ║"); - System.out.println("║ ║"); - System.out.println("║ Consistency: ║"); - System.out.println("║ CONSISTENCY - Set consistency level ║"); - System.out.println("║ CL - Short form ║"); - System.out.println("║ Levels: ONE, TWO, THREE, QUORUM, ALL, ANY ║"); - System.out.println("║ ║"); - System.out.println("║ Key-Value Operations (Legacy): ║"); - System.out.println("║ PUT - Write key-value ║"); - System.out.println("║ GET - Read value ║"); - System.out.println("║ DELETE - Delete key ║"); - System.out.println("║ SCAN - Scan with prefix ║"); - System.out.println("║ ║"); - System.out.println("║ Shell Commands: ║"); - System.out.println("║ HISTORY - Show command history ║"); - System.out.println("║ CLEAR - Clear screen ║"); - System.out.println("║ HELP / ? - Show this help ║"); - System.out.println("║ EXIT / QUIT - Exit shell ║"); - System.out.println("╚════════════════════════════════════════════════════════════╝\n"); - System.out.println("Examples:"); System.out.println(" CREATE TABLE users.profiles (id TEXT PRIMARY KEY, name TEXT, email TEXT)"); System.out.println(" INSERT INTO users.profiles (id, name, email) VALUES ('1', 'Alice', 'alice@example.com')"); diff --git a/src/main/java/com/cube/sql/CubicSQLExecutor.java b/src/main/java/com/cube/sql/CubicSQLExecutor.java index cf3b846..ea11931 100644 --- a/src/main/java/com/cube/sql/CubicSQLExecutor.java +++ b/src/main/java/com/cube/sql/CubicSQLExecutor.java @@ -1,118 +1,110 @@ package com.cube.sql; import com.cube.index.CubicIndexTree; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.nio.charset.StandardCharsets; import java.util.*; +import java.nio.charset.StandardCharsets; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.core.type.TypeReference; /** * Enhanced SQL Executor with Cubic Index support - * - * Features: - * - Automatic index creation for frequently queried columns - * - Range query optimization using Cubic Index - * - Prefix search acceleration - * - Secondary index support - * - Index statistics and monitoring + * Works with existing SQLParser and SQLExecutor */ public class CubicSQLExecutor { private static final Logger logger = LoggerFactory.getLogger(CubicSQLExecutor.class); - private final SQLParser sqlParser; private final SQLExecutor sqlExecutor; private final ObjectMapper objectMapper; // Primary indexes: keyspace.table -> CubicIndexTree - // Maps primary key -> serialized row data private final Map primaryIndexes; // Secondary indexes: keyspace.table.column -> CubicIndexTree - // Maps column value -> primary key(s) private final Map secondaryIndexes; - // Index metadata: index name -> index key + // Index metadata: index name -> index key (keyspace.table.column) private final Map indexMetadata; - // Index statistics + // Statistics private long indexHits = 0; private long indexMisses = 0; private long queriesOptimized = 0; private long indexCreations = 0; - public CubicSQLExecutor(SQLParser sqlParser, SQLExecutor sqlExecutor) { - this.sqlParser = sqlParser; + public CubicSQLExecutor(SQLExecutor sqlExecutor) { this.sqlExecutor = sqlExecutor; this.objectMapper = new ObjectMapper(); this.primaryIndexes = new HashMap<>(); this.secondaryIndexes = new HashMap<>(); this.indexMetadata = new HashMap<>(); - logger.info("Cubic SQL Executor initialized with index support"); + logger.info("Cubic SQL Executor initialized"); } /** * Execute SQL with automatic index optimization */ - public Map executeWithIndex(String sql) { + public SQLExecutor.SQLResult executeWithIndex(String sql) { try { - IndexedParsedSQL parsed = CubicIndexSQLParser.parseWithIndex(sql); + // Check for index-specific commands + String upperSQL = sql.toUpperCase().trim(); + if (upperSQL.startsWith("CREATE INDEX")) { + return handleCreateIndex(sql); + } else if (upperSQL.startsWith("DROP INDEX")) { + return handleDropIndex(sql); + } else if (upperSQL.startsWith("SHOW INDEXES")) { + return handleShowIndexes(sql); + } + + // Parse regular SQL + SQLParser.ParsedSQL parsed = SQLParser.parse(sql); + + // Handle based on type switch (parsed.getType()) { case CREATE_TABLE: - return handleCreateTable(parsed); - - case CREATE_INDEX: - return handleCreateIndex(parsed); - - case DROP_INDEX: - return handleDropIndex(parsed); - - case SHOW_INDEXES: - return handleShowIndexes(parsed); + return handleCreateTable(sql, parsed); case SELECT: - return handleSelectWithIndex(parsed); + return handleSelectWithIndex(sql, parsed); case INSERT: - return handleInsertWithIndex(parsed); + return handleInsertWithIndex(sql, parsed); case UPDATE: - return handleUpdateWithIndex(parsed); + return handleUpdateWithIndex(sql, parsed); case DELETE: - return handleDeleteWithIndex(parsed); + return handleDeleteWithIndex(sql, parsed); default: - // Fall back to regular SQL executor return sqlExecutor.execute(sql); } } catch (Exception e) { logger.error("Error executing SQL with index: {}", e.getMessage(), e); - return createErrorResult(e.getMessage()); + return SQLExecutor.SQLResult.error(e.getMessage()); } } - /** * Handle CREATE TABLE - automatically create primary index */ - private Map handleCreateTable(IndexedParsedSQL parsed) { + private SQLExecutor.SQLResult handleCreateTable(String sql, SQLParser.ParsedSQL parsed) { // Execute the CREATE TABLE - Map result = sqlExecutor.execute(parsed.getOriginalSQL()); + SQLExecutor.SQLResult result = sqlExecutor.execute(sql); - if (isSuccess(result)) { - // Create primary index for the table - String indexKey = parsed.getFullTableName(); + if (result.isSuccess()) { + // Create primary index + String tableKey = parsed.getKeyspace() + "." + parsed.getTable(); CubicIndexTree primaryIndex = new CubicIndexTree(3, 15, true); - primaryIndexes.put(indexKey, primaryIndex); + primaryIndexes.put(tableKey, primaryIndex); - logger.info("Created primary cubic index for table: {}", indexKey); + logger.info("Created primary cubic index for table: {}", tableKey); indexCreations++; } @@ -120,129 +112,165 @@ } /** - * Handle CREATE INDEX - create secondary index on column - * + * Handle CREATE INDEX * Syntax: CREATE INDEX idx_name ON table(column) */ - private Map handleCreateIndex(IndexedParsedSQL parsed) { - String indexName = parsed.getIndexName(); - String table = parsed.getTable(); - String column = parsed.getIndexColumn(); - String keyspace = parsed.getKeyspace(); - - // Create index key - String indexKey = CubicIndexSQLParser.generateIndexKey(keyspace, table, column); - - // Check if index already exists - if (secondaryIndexes.containsKey(indexKey)) { - return createErrorResult("Index already exists on " + table + "." + column); + private SQLExecutor.SQLResult handleCreateIndex(String sql) { + try { + // Simple regex parsing + String pattern = "CREATE\\s+INDEX\\s+(\\w+)\\s+ON\\s+([\\w.]+)\\s*\\(\\s*(\\w+)\\s*\\)"; + java.util.regex.Pattern p = java.util.regex.Pattern.compile(pattern, java.util.regex.Pattern.CASE_INSENSITIVE); + java.util.regex.Matcher m = p.matcher(sql); + + if (!m.find()) { + return SQLExecutor.SQLResult.error("Invalid CREATE INDEX syntax"); + } + + String indexName = m.group(1); + String tableName = m.group(2); + String columnName = m.group(3); + + // Parse table name + String keyspace = "default"; + String table = tableName; + if (tableName.contains(".")) { + String[] parts = tableName.split("\\."); + keyspace = parts[0]; + table = parts[1]; + } + + // Create index key + String indexKey = keyspace + "." + table + "." + columnName; + + // Check if exists + if (secondaryIndexes.containsKey(indexKey)) { + return SQLExecutor.SQLResult.error("Index already exists on " + table + "." + columnName); + } + + // Create secondary index + CubicIndexTree secondaryIndex = new CubicIndexTree(3, 15, true); + secondaryIndexes.put(indexKey, secondaryIndex); + indexMetadata.put(indexName, indexKey); + + // Populate with existing data + int keysIndexed = populateSecondaryIndex(keyspace, table, columnName, secondaryIndex); + + logger.info("Created secondary index '{}' on {}.{} ({} keys)", + indexName, table, columnName, keysIndexed); + indexCreations++; + + return SQLExecutor.SQLResult.success("Index created: " + indexName + + " on " + table + "(" + columnName + ") - " + keysIndexed + " keys indexed"); + + } catch (Exception e) { + logger.error("Error creating index: {}", e.getMessage()); + return SQLExecutor.SQLResult.error(e.getMessage()); } - - // Create secondary index - CubicIndexTree secondaryIndex = new CubicIndexTree(3, 15, true); - secondaryIndexes.put(indexKey, secondaryIndex); - indexMetadata.put(indexName, indexKey); - - // Populate index with existing data - int keysIndexed = populateSecondaryIndex(keyspace, table, column, secondaryIndex); - - logger.info("Created secondary cubic index '{}' on {}.{} ({} keys indexed)", - indexName, table, column, keysIndexed); - indexCreations++; - - Map result = new LinkedHashMap<>(); - result.put("success", true); - result.put("message", "Index created: " + indexName + " on " + table + "(" + column + ")"); - result.put("keysIndexed", keysIndexed); - result.put("indexType", "CUBIC"); - return result; } /** * Handle DROP INDEX */ - private Map handleDropIndex(IndexedParsedSQL parsed) { - String indexName = parsed.getIndexName(); - - // Find and remove index - String indexKey = indexMetadata.remove(indexName); - - if (indexKey != null) { - CubicIndexTree removed = secondaryIndexes.remove(indexKey); - if (removed != null) { - removed.clear(); + private SQLExecutor.SQLResult handleDropIndex(String sql) { + try { + String pattern = "DROP\\s+INDEX\\s+(\\w+)"; + java.util.regex.Pattern p = java.util.regex.Pattern.compile(pattern, java.util.regex.Pattern.CASE_INSENSITIVE); + java.util.regex.Matcher m = p.matcher(sql); + + if (!m.find()) { + return SQLExecutor.SQLResult.error("Invalid DROP INDEX syntax"); } - logger.info("Dropped index: {}", indexName); + String indexName = m.group(1); + String indexKey = indexMetadata.remove(indexName); - Map result = new LinkedHashMap<>(); - result.put("success", true); - result.put("message", "Index dropped: " + indexName); - return result; - } else { - return createErrorResult("Index not found: " + indexName); + if (indexKey != null) { + CubicIndexTree removed = secondaryIndexes.remove(indexKey); + if (removed != null) { + removed.clear(); + } + logger.info("Dropped index: {}", indexName); + return SQLExecutor.SQLResult.success("Index dropped: " + indexName); + } else { + return SQLExecutor.SQLResult.error("Index not found: " + indexName); + } + + } catch (Exception e) { + return SQLExecutor.SQLResult.error(e.getMessage()); } } /** * Handle SHOW INDEXES */ - private Map handleShowIndexes(IndexedParsedSQL parsed) { - String tableKey = parsed.getFullTableName(); - - List> indexes = new ArrayList<>(); - - // Add primary index - if (primaryIndexes.containsKey(tableKey)) { - Map indexInfo = new LinkedHashMap<>(); - indexInfo.put("name", "PRIMARY"); - indexInfo.put("column", parsed.getPrimaryKey() != null ? parsed.getPrimaryKey() : "id"); - indexInfo.put("type", "PRIMARY"); - indexInfo.put("keys", primaryIndexes.get(tableKey).getTotalSize()); - indexes.add(indexInfo); - } - - // Add secondary indexes - for (Map.Entry entry : indexMetadata.entrySet()) { - String indexName = entry.getKey(); - String indexKey = entry.getValue(); + private SQLExecutor.SQLResult handleShowIndexes(String sql) { + try { + String pattern = "SHOW\\s+INDEXES\\s+ON\\s+([\\w.]+)"; + java.util.regex.Pattern p = java.util.regex.Pattern.compile(pattern, java.util.regex.Pattern.CASE_INSENSITIVE); + java.util.regex.Matcher m = p.matcher(sql); - if (indexKey.startsWith(tableKey + ".")) { - String[] parts = CubicIndexSQLParser.parseIndexKey(indexKey); - if (parts != null) { - Map indexInfo = new LinkedHashMap<>(); - indexInfo.put("name", indexName); - indexInfo.put("column", parts[2]); - indexInfo.put("type", "SECONDARY"); - indexInfo.put("keys", secondaryIndexes.get(indexKey).getTotalSize()); - indexes.add(indexInfo); + if (!m.find()) { + return SQLExecutor.SQLResult.error("Invalid SHOW INDEXES syntax"); + } + + String tableName = m.group(1); + String keyspace = "default"; + String table = tableName; + + if (tableName.contains(".")) { + String[] parts = tableName.split("\\."); + keyspace = parts[0]; + table = parts[1]; + } + + String tableKey = keyspace + "." + table; + + StringBuilder result = new StringBuilder(); + result.append("Indexes on ").append(tableKey).append(":\n"); + + // Primary index + if (primaryIndexes.containsKey(tableKey)) { + CubicIndexTree idx = primaryIndexes.get(tableKey); + result.append(" PRIMARY: ").append(idx.getTotalSize()).append(" keys\n"); + } + + // Secondary indexes + for (Map.Entry entry : indexMetadata.entrySet()) { + String idxName = entry.getKey(); + String idxKey = entry.getValue(); + + if (idxKey.startsWith(tableKey + ".")) { + String column = idxKey.substring(tableKey.length() + 1); + CubicIndexTree idx = secondaryIndexes.get(idxKey); + if (idx != null) { + result.append(" ").append(idxName).append(" (").append(column) + .append("): ").append(idx.getTotalSize()).append(" keys\n"); + } } } + + return SQLExecutor.SQLResult.success(result.toString()); + + } catch (Exception e) { + return SQLExecutor.SQLResult.error(e.getMessage()); } - - Map result = new LinkedHashMap<>(); - result.put("success", true); - result.put("table", tableKey); - result.put("indexes", indexes); - result.put("indexCount", indexes.size()); - return result; } /** * Handle SELECT with index optimization */ - private Map handleSelectWithIndex(IndexedParsedSQL parsed) { - String tableKey = parsed.getFullTableName(); + private SQLExecutor.SQLResult handleSelectWithIndex(String sql, SQLParser.ParsedSQL parsed) { + String tableKey = parsed.getKeyspace() + "." + parsed.getTable(); CubicIndexTree primaryIndex = primaryIndexes.get(tableKey); // Check if we can use index - if (primaryIndex != null && parsed.hasWhereClause()) { - String whereColumn = parsed.getWhereColumn(); - String whereValue = parsed.getWhereValue(); + if (primaryIndex != null && parsed.getWhereClause() != null && !parsed.getWhereClause().isEmpty()) { + String whereColumn = parsed.getWhereClause().keySet().iterator().next(); + String whereValue = parsed.getWhereClause().values().iterator().next(); // Check if querying by primary key - if (isPrimaryKeyColumn(whereColumn, parsed.getPrimaryKey())) { - return executeIndexedSelect(parsed, primaryIndex, whereValue); + if (isPrimaryKey(whereColumn)) { + return executeIndexedSelect(primaryIndex, whereValue, tableKey); } // Check for secondary index @@ -250,75 +278,56 @@ CubicIndexTree secondaryIndex = secondaryIndexes.get(secondaryIndexKey); if (secondaryIndex != null) { - return executeSecondaryIndexSelect(parsed, primaryIndex, secondaryIndex, whereValue); + return executeSecondaryIndexSelect(primaryIndex, secondaryIndex, whereValue, tableKey); } } // Fall back to regular query indexMisses++; - return sqlExecutor.execute(parsed.getOriginalSQL()); + return sqlExecutor.execute(sql); } /** * Execute SELECT using primary index */ - private Map executeIndexedSelect(IndexedParsedSQL parsed, - CubicIndexTree index, - String key) { + private SQLExecutor.SQLResult executeIndexedSelect(CubicIndexTree index, String key, String table) { try { - // Use cubic index for fast lookup byte[] data = index.get(key); if (data != null) { indexHits++; queriesOptimized++; - // Deserialize row Map row = deserializeRow(data); List> rows = Collections.singletonList(row); - logger.debug("Index hit for key: {} (cubic level: {})", - key, index.calculateLevel(key)); + logger.debug("Index hit for key: {} (level: {})", key, index.calculateLevel(key)); - Map result = new LinkedHashMap<>(); - result.put("success", true); - result.put("message", "Query executed (cubic-index-optimized)"); - result.put("rows", rows); - result.put("rowCount", 1); - result.put("indexUsed", "PRIMARY"); - result.put("cubicLevel", index.calculateLevel(key)); - return result; + return SQLExecutor.SQLResult.success("Query executed (cubic-index-optimized)") + .withRows(rows); } else { - indexMisses++; - Map result = new LinkedHashMap<>(); - result.put("success", true); - result.put("rows", Collections.emptyList()); - result.put("rowCount", 0); - return result; + return SQLExecutor.SQLResult.success("Query executed").withRows(Collections.emptyList()); } } catch (Exception e) { logger.error("Error in indexed select: {}", e.getMessage()); - // Fall back to regular query - return sqlExecutor.execute(parsed.getOriginalSQL()); + indexMisses++; + return SQLExecutor.SQLResult.error(e.getMessage()); } } /** * Execute SELECT using secondary index */ - private Map executeSecondaryIndexSelect(IndexedParsedSQL parsed, - CubicIndexTree primaryIndex, - CubicIndexTree secondaryIndex, - String columnValue) { + private SQLExecutor.SQLResult executeSecondaryIndexSelect(CubicIndexTree primaryIndex, + CubicIndexTree secondaryIndex, + String columnValue, + String table) { try { - // Secondary index maps column value -> primary key byte[] primaryKeyData = secondaryIndex.get(columnValue); if (primaryKeyData != null) { String primaryKey = new String(primaryKeyData, StandardCharsets.UTF_8); - - // Now lookup by primary key byte[] rowData = primaryIndex.get(primaryKey); if (rowData != null) { @@ -328,40 +337,28 @@ Map row = deserializeRow(rowData); List> rows = Collections.singletonList(row); - logger.debug("Secondary index hit for value: {} -> key: {}", - columnValue, primaryKey); + logger.debug("Secondary index hit: {} -> {}", columnValue, primaryKey); - Map result = new LinkedHashMap<>(); - result.put("success", true); - result.put("message", "Query executed (secondary-index-optimized)"); - result.put("rows", rows); - result.put("rowCount", 1); - result.put("indexUsed", "SECONDARY"); - return result; + return SQLExecutor.SQLResult.success("Query executed (secondary-index-optimized)") + .withRows(rows); } } - Map result = new LinkedHashMap<>(); - result.put("success", true); - result.put("rows", Collections.emptyList()); - result.put("rowCount", 0); - return result; + return SQLExecutor.SQLResult.success("Query executed").withRows(Collections.emptyList()); } catch (Exception e) { logger.error("Error in secondary index select: {}", e.getMessage()); - return sqlExecutor.execute(parsed.getOriginalSQL()); + return SQLExecutor.SQLResult.error(e.getMessage()); } } /** * Handle INSERT with index update */ - private Map handleInsertWithIndex(IndexedParsedSQL parsed) { - // Execute the INSERT - Map result = sqlExecutor.execute(parsed.getOriginalSQL()); + private SQLExecutor.SQLResult handleInsertWithIndex(String sql, SQLParser.ParsedSQL parsed) { + SQLExecutor.SQLResult result = sqlExecutor.execute(sql); - if (isSuccess(result)) { - // Update indexes + if (result.isSuccess()) { updateIndexesOnInsert(parsed); } @@ -371,12 +368,10 @@ /** * Handle UPDATE with index update */ - private Map handleUpdateWithIndex(IndexedParsedSQL parsed) { - // Execute the UPDATE - Map result = sqlExecutor.execute(parsed.getOriginalSQL()); + private SQLExecutor.SQLResult handleUpdateWithIndex(String sql, SQLParser.ParsedSQL parsed) { + SQLExecutor.SQLResult result = sqlExecutor.execute(sql); - if (isSuccess(result)) { - // Update indexes + if (result.isSuccess()) { updateIndexesOnUpdate(parsed); } @@ -386,301 +381,67 @@ /** * Handle DELETE with index update */ - private Map handleDeleteWithIndex(IndexedParsedSQL parsed) { - String whereValue = parsed.getWhereValue(); - - if (whereValue != null) { - // Remove from indexes first - String tableKey = parsed.getFullTableName(); - CubicIndexTree primaryIndex = primaryIndexes.get(tableKey); + private SQLExecutor.SQLResult handleDeleteWithIndex(String sql, SQLParser.ParsedSQL parsed) { + // Remove from indexes first + if (parsed.getWhereClause() != null && !parsed.getWhereClause().isEmpty()) { + String whereValue = parsed.getWhereClause().values().iterator().next(); + String tableKey = parsed.getKeyspace() + "." + parsed.getTable(); + CubicIndexTree primaryIndex = primaryIndexes.get(tableKey); if (primaryIndex != null) { primaryIndex.remove(whereValue); logger.debug("Removed from primary index: {}", whereValue); } - // Remove from secondary indexes removeFromSecondaryIndexes(tableKey, whereValue); } - // Execute the DELETE - return sqlExecutor.execute(parsed.getOriginalSQL()); - } - - /** - * Update indexes after INSERT - */ - private void updateIndexesOnInsert(IndexedParsedSQL parsed) { - String tableKey = parsed.getFullTableName(); - CubicIndexTree primaryIndex = primaryIndexes.get(tableKey); - - if (primaryIndex != null) { - Map columns = parsed.getColumns(); - - if (!columns.isEmpty()) { - // Get primary key (first column or specified primary key) - String primaryKey = parsed.getPrimaryKey(); - if (primaryKey == null) { - primaryKey = columns.values().iterator().next(); - } else { - primaryKey = columns.get(parsed.getPrimaryKey()); - } - - if (primaryKey != null) { - // Serialize row data - byte[] rowData = serializeRow(columns); - primaryIndex.put(primaryKey, rowData); - - logger.debug("Updated primary index for key: {} at cubic level: {}", - primaryKey, primaryIndex.calculateLevel(primaryKey)); - - // Update secondary indexes - updateSecondaryIndexes(tableKey, primaryKey, columns); - } - } - } - } - - /** - * Handle CREATE INDEX - create secondary index on column - */ - private SQLResult handleCreateIndex(SQLParser.ParsedSQL parsed) { - String indexName = parsed.getIndexName(); - String table = parsed.getTable(); - String column = parsed.getColumn(); - String keyspace = parsed.getKeyspace(); - - // Create secondary index - String indexKey = keyspace + "." + table + "." + column; - CubicIndexTree secondaryIndex = new CubicIndexTree(3, 15, true); - secondaryIndexes.put(indexKey, secondaryIndex); - - // Populate index with existing data - int keysIndexed = populateSecondaryIndex(keyspace, table, column, secondaryIndex); - - logger.info("Created secondary cubic index '{}' on {}.{} ({} keys indexed)", - indexName, table, column, keysIndexed); - - return SQLResult.success("Index created: " + indexName + " on " + table + "(" + column + ")") - .withRowsAffected(keysIndexed); - } - - /** - * Handle SELECT with index optimization - */ - private SQLResult handleSelectWithIndex(SQLParser.ParsedSQL parsed) { - String indexKey = parsed.getKeyspace() + "." + parsed.getTable(); - CubicIndexTree primaryIndex = tableIndexes.get(indexKey); - - // Check if we can use index - if (primaryIndex != null && parsed.hasWhereClause()) { - String whereColumn = parsed.getWhereColumn(); - String whereValue = parsed.getWhereValue(); - - // Check if querying by primary key or indexed column - if (isPrimaryKeyColumn(whereColumn, parsed.getTable())) { - return executeIndexedSelect(parsed, primaryIndex); - } - - // Check for secondary index - String secondaryIndexKey = indexKey + "." + whereColumn; - CubicIndexTree secondaryIndex = secondaryIndexes.get(secondaryIndexKey); - - if (secondaryIndex != null) { - return executeSecondaryIndexSelect(parsed, secondaryIndex); - } - } - - // Fall back to regular query - indexMisses++; - return executeSQLParser(parsed.getOriginalSQL(), parsed); - } - - /** - * Execute SELECT using primary index - */ - private SQLResult executeIndexedSelect(SQLParser.ParsedSQL parsed, CubicIndexTree index) { - try { - String whereValue = parsed.getWhereValue(); - - // Use cubic index for fast lookup - byte[] data = index.get(whereValue); - - if (data != null) { - indexHits++; - queriesOptimized++; - - // Deserialize and format result - Map row = deserializeRow(data); - List> rows = Collections.singletonList(row); - - logger.debug("Index hit for key: {}", whereValue); - return SQLResult.success("Query executed (index-optimized)") - .withRows(rows) - .withRowCount(1); - } else { - indexMisses++; - return SQLResult.success("Query executed").withRowCount(0); - } - - } catch (Exception e) { - logger.error("Error in indexed select: {}", e.getMessage()); - // Fall back to regular query - return executeSQLParser(parsed.getOriginalSQL(), parsed); - } - } - - /** - * Execute SELECT using secondary index - */ - private SQLResult executeSecondaryIndexSelect(SQLParser.ParsedSQL parsed, CubicIndexTree secondaryIndex) { - try { - String whereValue = parsed.getWhereValue(); - - // Secondary index maps column value -> primary key - byte[] primaryKeyData = secondaryIndex.get(whereValue); - - if (primaryKeyData != null) { - String primaryKey = new String(primaryKeyData); - - // Now lookup by primary key - String indexKey = parsed.getKeyspace() + "." + parsed.getTable(); - CubicIndexTree primaryIndex = tableIndexes.get(indexKey); - - if (primaryIndex != null) { - return executeIndexedSelectByPrimaryKey(parsed, primaryIndex, primaryKey); - } - } - - return SQLResult.success("Query executed").withRowCount(0); - - } catch (Exception e) { - logger.error("Error in secondary index select: {}", e.getMessage()); - return executeSQLParser(parsed.getOriginalSQL(), parsed); - } - } - - /** - * Execute SELECT by primary key - */ - private SQLResult executeIndexedSelectByPrimaryKey(SQLParser.ParsedSQL parsed, - CubicIndexTree primaryIndex, - String primaryKey) { - byte[] data = primaryIndex.get(primaryKey); - - if (data != null) { - indexHits++; - queriesOptimized++; - - Map row = deserializeRow(data); - List> rows = Collections.singletonList(row); - - return SQLResult.success("Query executed (secondary-index-optimized)") - .withRows(rows) - .withRowCount(1); - } - - return SQLResult.success("Query executed").withRowCount(0); - } - - /** - * Handle INSERT with index update - */ - private SQLResult handleInsertWithIndex(SQLParser.ParsedSQL parsed) { - // Execute the INSERT - SQLResult result = executeSQLParser(parsed.getOriginalSQL(), parsed); - - if (result.isSuccess()) { - // Update indexes - updateIndexesOnInsert(parsed); - } - - return result; - } - - /** - * Handle UPDATE with index update - */ - private SQLResult handleUpdateWithIndex(SQLParser.ParsedSQL parsed) { - // Execute the UPDATE - SQLResult result = executeSQLParser(parsed.getOriginalSQL(), parsed); - - if (result.isSuccess()) { - // Update indexes - updateIndexesOnUpdate(parsed); - } - - return result; - } - - /** - * Handle DELETE with index update - */ - private SQLResult handleDeleteWithIndex(SQLParser.ParsedSQL parsed) { - String whereValue = parsed.getWhereValue(); - - // Remove from indexes first - String indexKey = parsed.getKeyspace() + "." + parsed.getTable(); - CubicIndexTree primaryIndex = tableIndexes.get(indexKey); - - if (primaryIndex != null) { - primaryIndex.remove(whereValue); - } - - // Remove from secondary indexes - removeFromSecondaryIndexes(indexKey, whereValue); - - // Execute the DELETE - return executeSQLParser(parsed.getOriginalSQL(), parsed); - } - - /** - * Handle DROP INDEX - */ - private SQLResult handleDropIndex(SQLParser.ParsedSQL parsed) { - String indexName = parsed.getIndexName(); - - // Remove from secondary indexes map - // (simplified - in production, maintain index name mapping) - logger.info("Dropped index: {}", indexName); - - return SQLResult.success("Index dropped: " + indexName); + return sqlExecutor.execute(sql); } /** * Update indexes after INSERT */ private void updateIndexesOnInsert(SQLParser.ParsedSQL parsed) { - String indexKey = parsed.getKeyspace() + "." + parsed.getTable(); - CubicIndexTree primaryIndex = tableIndexes.get(indexKey); + String tableKey = parsed.getKeyspace() + "." + parsed.getTable(); + CubicIndexTree primaryIndex = primaryIndexes.get(tableKey); - if (primaryIndex != null && parsed.getValues() != null && !parsed.getValues().isEmpty()) { - // First value is typically the primary key - String primaryKey = parsed.getValues().get(0); - byte[] rowData = serializeRow(parsed); + if (primaryIndex != null && parsed.getColumns() != null && !parsed.getColumns().isEmpty()) { + Map columns = parsed.getColumns(); - primaryIndex.put(primaryKey, rowData); - logger.debug("Updated primary index for key: {}", primaryKey); + // Get primary key (first value) + String primaryKey = columns.values().iterator().next(); + + if (primaryKey != null) { + byte[] rowData = serializeRow(columns); + primaryIndex.put(primaryKey, rowData); + + logger.debug("Updated primary index for key: {} at level: {}", + primaryKey, primaryIndex.calculateLevel(primaryKey)); + + // Update secondary indexes + updateSecondaryIndexes(tableKey, primaryKey, columns); + } } } - /** * Update indexes after UPDATE */ - private void updateIndexesOnUpdate(IndexedParsedSQL parsed) { - String whereValue = parsed.getWhereValue(); - String tableKey = parsed.getFullTableName(); + private void updateIndexesOnUpdate(SQLParser.ParsedSQL parsed) { + if (parsed.getWhereClause() == null || parsed.getWhereClause().isEmpty()) { + return; + } + + String whereValue = parsed.getWhereClause().values().iterator().next(); + String tableKey = parsed.getKeyspace() + "." + parsed.getTable(); CubicIndexTree primaryIndex = primaryIndexes.get(tableKey); - if (primaryIndex != null && whereValue != null) { - // Re-serialize and update + if (primaryIndex != null && parsed.getColumns() != null) { byte[] rowData = serializeRow(parsed.getColumns()); primaryIndex.put(whereValue, rowData); logger.debug("Updated primary index for key: {}", whereValue); - - // Update secondary indexes updateSecondaryIndexes(tableKey, whereValue, parsed.getColumns()); } } @@ -697,7 +458,6 @@ CubicIndexTree secondaryIndex = secondaryIndexes.get(indexKey); if (secondaryIndex != null) { - // Map column value -> primary key secondaryIndex.put(value, primaryKey.getBytes(StandardCharsets.UTF_8)); logger.debug("Updated secondary index {}: {} -> {}", column, value, primaryKey); } @@ -708,7 +468,6 @@ * Populate secondary index with existing data */ private int populateSecondaryIndex(String keyspace, String table, String column, CubicIndexTree index) { - // Get primary index to scan existing data String tableKey = keyspace + "." + table; CubicIndexTree primaryIndex = primaryIndexes.get(tableKey); @@ -726,7 +485,6 @@ String columnValue = row.get(column); if (columnValue != null) { - // Map column value -> primary key index.put(columnValue, primaryKey.getBytes(StandardCharsets.UTF_8)); count++; } @@ -744,8 +502,6 @@ String indexKey = entry.getKey(); if (indexKey.startsWith(tableKey + ".")) { - // We need to find which value maps to this primary key - // For simplicity, remove by scanning (could be optimized with reverse index) CubicIndexTree index = entry.getValue(); Set keysToRemove = new HashSet<>(); @@ -766,12 +522,8 @@ /** * Check if column is primary key */ - private boolean isPrimaryKeyColumn(String column, String primaryKey) { - if (primaryKey != null && primaryKey.equals(column)) { - return true; - } - // Common primary key column names - return "id".equals(column) || column.endsWith("_id") || column.equals("pk"); + private boolean isPrimaryKey(String column) { + return "id".equals(column) || column.endsWith("_id") || "pk".equals(column) || column.endsWith("_pk"); } /** @@ -801,23 +553,6 @@ } /** - * Check if result is successful - */ - private boolean isSuccess(Map result) { - return result != null && Boolean.TRUE.equals(result.get("success")); - } - - /** - * Create error result - */ - private Map createErrorResult(String message) { - Map result = new LinkedHashMap<>(); - result.put("success", false); - result.put("error", message); - return result; - } - - /** * Get index statistics */ public Map getIndexStats() { @@ -833,7 +568,7 @@ stats.put("totalIndexes", primaryIndexes.size() + secondaryIndexes.size()); stats.put("indexCreations", indexCreations); - // Per-table primary index stats + // Per-table stats Map tableStats = new LinkedHashMap<>(); for (Map.Entry entry : primaryIndexes.entrySet()) { Map indexStats = entry.getValue().getStats(); @@ -888,7 +623,6 @@ logger.info("Rebalancing all cubic indexes..."); int rebalanced = 0; - for (CubicIndexTree index : primaryIndexes.values()) { index.rebalance(); rebalanced++; @@ -901,28 +635,4 @@ logger.info("Rebalanced {} cubic indexes", rebalanced); } - - /** - * Get all indexed tables - */ - public Set getIndexedTables() { - return new HashSet<>(primaryIndexes.keySet()); - } - - /** - * Get secondary indexes for a table - */ - public List getSecondaryIndexes(String keyspace, String table) { - String tableKey = keyspace + "." + table; - List indexes = new ArrayList<>(); - - for (Map.Entry entry : indexMetadata.entrySet()) { - String indexKey = entry.getValue(); - if (indexKey.startsWith(tableKey + ".")) { - indexes.add(entry.getKey()); - } - } - - return indexes; - } } diff --git a/src/main/java/com/cube/sql/SQLExecutor.java b/src/main/java/com/cube/sql/SQLExecutor.java index ec10982..ecfc1b2 100644 --- a/src/main/java/com/cube/sql/SQLExecutor.java +++ b/src/main/java/com/cube/sql/SQLExecutor.java @@ -51,6 +51,12 @@ public static SQLResult error(String message) { return new SQLResult(false, message, null, 0); } + + public SQLResult withRows(List> rows) { + + return new SQLResult(false, message, rows, rows.size()); + + } } public SQLExecutor(QueryExecutor queryExecutor, StorageEngine storageEngine) { diff --git a/src/main/java/com/cube/sql/SQLParser.java b/src/main/java/com/cube/sql/SQLParser.java index 7a86d71..58f4308 100644 --- a/src/main/java/com/cube/sql/SQLParser.java +++ b/src/main/java/com/cube/sql/SQLParser.java @@ -26,7 +26,7 @@ DROP_TABLE, DESCRIBE, SHOW_TABLES, - UNKNOWN + CREATE_INDEX, SHOW_INDEXES, DROP_INDEX, UNKNOWN } public static class ParsedSQL { diff --git a/target/classes/com/cube/shell/CubeShell.class b/target/classes/com/cube/shell/CubeShell.class index 5f65614..3c35eba 100644 --- a/target/classes/com/cube/shell/CubeShell.class +++ b/target/classes/com/cube/shell/CubeShell.class Binary files differ diff --git a/target/classes/com/cube/sql/SQLExecutor$1.class b/target/classes/com/cube/sql/SQLExecutor$1.class index ed7d753..23ed676 100644 --- a/target/classes/com/cube/sql/SQLExecutor$1.class +++ b/target/classes/com/cube/sql/SQLExecutor$1.class Binary files differ diff --git a/target/classes/com/cube/sql/SQLExecutor$SQLResult.class b/target/classes/com/cube/sql/SQLExecutor$SQLResult.class index 0177932..5c974f5 100644 --- a/target/classes/com/cube/sql/SQLExecutor$SQLResult.class +++ b/target/classes/com/cube/sql/SQLExecutor$SQLResult.class Binary files differ diff --git a/target/classes/com/cube/sql/SQLExecutor.class b/target/classes/com/cube/sql/SQLExecutor.class index f1d75ae..480f157 100644 --- a/target/classes/com/cube/sql/SQLExecutor.class +++ b/target/classes/com/cube/sql/SQLExecutor.class Binary files differ diff --git a/target/classes/com/cube/sql/SQLParser$SQLType.class b/target/classes/com/cube/sql/SQLParser$SQLType.class index 60161b7..bc4d1d6 100644 --- a/target/classes/com/cube/sql/SQLParser$SQLType.class +++ b/target/classes/com/cube/sql/SQLParser$SQLType.class Binary files differ