Skip to content
Draft
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions server/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ dependencies {
implementation 'com.google.guava:guava:31.0.1-jre'
implementation 'org.reflections:reflections:0.10.1'

implementation 'com.github.jsqlparser:jsqlparser:3.2'

// Experimental
implementation files('libs/keva-ioc-0.1.0-SNAPSHOT.jar')

Expand Down
91 changes: 91 additions & 0 deletions server/src/main/java/dev/keva/server/command/impl/kql/Kql.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package dev.keva.server.command.impl.kql;

import dev.keva.ioc.annotation.Autowired;
import dev.keva.ioc.annotation.Component;
import dev.keva.protocol.resp.reply.*;
import dev.keva.server.command.annotation.CommandImpl;
import dev.keva.server.command.annotation.Execute;
import dev.keva.server.command.annotation.ParamLength;
import dev.keva.server.command.impl.kql.manager.KqlManager;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.create.table.CreateTable;
import net.sf.jsqlparser.statement.delete.Delete;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.update.Update;

import java.util.List;

@Component
@CommandImpl("kql")
@ParamLength(1)
public class Kql {
private final KqlManager kqlManager;

@Autowired
public Kql(KqlManager kqlManager) {
this.kqlManager = kqlManager;
}

@Execute
public Reply<?> execute(byte[] sqlBytes) {
String sql = new String(sqlBytes);
Statement stmt = null;
try {
stmt = kqlManager.parse(sql);
} catch (JSQLParserException e) {
return new ErrorReply("ERR " + e.getMessage());
}
if (stmt instanceof CreateTable) {
kqlManager.create(stmt);
Reply<?>[] replies = new Reply[2];
replies[0] = new StatusReply("DONE");
replies[1] = new IntegerReply(0);
return new MultiBulkReply(replies);
} else if (stmt instanceof Insert) {
kqlManager.insert(stmt);
Reply<?>[] replies = new Reply[2];
replies[0] = new StatusReply("DONE");
replies[1] = new IntegerReply(1);
return new MultiBulkReply(replies);
} else if (stmt instanceof Update) {
int numOfUpdated = kqlManager.update(stmt);
Reply<?>[] replies = new Reply[2];
replies[0] = new StatusReply("DONE");
replies[1] = new IntegerReply(numOfUpdated);
return new MultiBulkReply(replies);
} else if (stmt instanceof Delete) {
int numOfDeleted = kqlManager.delete(stmt);
Reply<?>[] replies = new Reply[2];
replies[0] = new StatusReply("DONE");
replies[1] = new IntegerReply(numOfDeleted);
return new MultiBulkReply(replies);
} else if (stmt instanceof Select) {
List<List<Object>> result = kqlManager.select(stmt);
Reply<?>[] rowReplies = new Reply[result.size()];
for (int i = 0; i < result.size(); i++) {
Reply<?>[] columnReplies = new Reply[result.get(i).size()];
for (int j = 0; j < result.get(i).size(); j++) {
if (result.get(i).get(j) instanceof String) {
columnReplies[j] = new BulkReply((String) result.get(i).get(j));
} else if (result.get(i).get(j) instanceof Integer) {
columnReplies[j] = new IntegerReply((Integer) result.get(i).get(j));
} else if (result.get(i).get(j) instanceof Long) {
columnReplies[j] = new IntegerReply((Long) result.get(i).get(j));
} else if (result.get(i).get(j) instanceof Double) {
columnReplies[j] = new BulkReply(result.get(i).get(j).toString());
} else if (result.get(i).get(j) instanceof Boolean) {
columnReplies[j] = new IntegerReply((Boolean) result.get(i).get(j) ? 1 : 0);
} else if (result.get(i).get(j) == null) {
columnReplies[j] = BulkReply.NIL_REPLY;
}
}
rowReplies[i] = new MultiBulkReply(columnReplies);
}
return new MultiBulkReply(rowReplies);
} else {
return new ErrorReply("ERR unsupported statement");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package dev.keva.server.command.impl.kql.manager;

import lombok.AllArgsConstructor;

@AllArgsConstructor
public class KevaColumnDefinition {
public String name;
public String type;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package dev.keva.server.command.impl.kql.manager;

import java.util.List;

public class KevaColumnFinder {
public static int findColumn(String columnName, List<KevaColumnDefinition> kevaColumns) {
for (int i = 0; i < kevaColumns.size(); i++) {
KevaColumnDefinition kevaColumn = kevaColumns.get(i);
if (kevaColumn.name.equals(columnName)) {
return i;
}
}
return -1;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package dev.keva.server.command.impl.kql.manager;

public class KevaSQLException extends RuntimeException {
public KevaSQLException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package dev.keva.server.command.impl.kql.manager;

import java.util.Collections;
import java.util.List;

public class KevaSQLResponseUtil {
public static List<List<Object>> singleSelectResponse(Object object) {
return Collections.singletonList(Collections.singletonList(object));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package dev.keva.server.command.impl.kql.manager;

public class KevaSQLStringUtil {
public static String escape(String str) {
if (str.startsWith("'") && str.endsWith("'")) {
return str.replaceAll("^.|.$", "");
}
return str;
}
}
Loading