mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-03-09 14:34:43 +00:00
sql subdir compiles
Original commit: elastic/x-pack-elasticsearch@1ffb55c7f8
This commit is contained in:
parent
593e6572c1
commit
642048e639
@ -1,15 +1,13 @@
|
|||||||
apply plugin: 'elasticsearch.build'
|
apply plugin: 'elasticsearch.build'
|
||||||
apply plugin: 'application'
|
apply plugin: 'application'
|
||||||
|
|
||||||
project.compactProfile = 'full'
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile "org.jline:jline:3.3.0"
|
compile "org.jline:jline:3.3.0"
|
||||||
|
|
||||||
compile project(':x-pack-elasticsearch:sql-clients:net-client')
|
compile project(':x-pack-elasticsearch:sql-clients:net-client')
|
||||||
compile project(':x-pack-elasticsearch:sql-clients:cli-proto')
|
compile project(':x-pack-elasticsearch:sql-clients:cli-proto')
|
||||||
|
|
||||||
testCompile project(":x-pack-elasticsearch:transport-client")
|
testCompile project(":x-pack-elasticsearch:transport-client")
|
||||||
|
testCompile project(path: ':x-pack-elasticsearch:plugin', configuration: 'testArtifacts')
|
||||||
testCompile project(':x-pack-elasticsearch:sql-clients:test-utils')
|
testCompile project(':x-pack-elasticsearch:sql-clients:test-utils')
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,3 +22,6 @@ mainClassName = "org.elasticsearch.sql.console.SqlConsole"
|
|||||||
run {
|
run {
|
||||||
classpath = sourceSets.test.runtimeClasspath
|
classpath = sourceSets.test.runtimeClasspath
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Needed so we can launch graphviz if it is installed
|
||||||
|
project.compactProfile = 'full'
|
||||||
|
@ -6,9 +6,10 @@
|
|||||||
package org.elasticsearch.xpack.sql.cli.integration.server;
|
package org.elasticsearch.xpack.sql.cli.integration.server;
|
||||||
|
|
||||||
import org.elasticsearch.client.Client;
|
import org.elasticsearch.client.Client;
|
||||||
|
import org.elasticsearch.xpack.sql.cli.net.protocol.Response;
|
||||||
import org.elasticsearch.xpack.sql.test.server.ProtoHttpServer;
|
import org.elasticsearch.xpack.sql.test.server.ProtoHttpServer;
|
||||||
|
|
||||||
public class CliHttpServer extends ProtoHttpServer {
|
public class CliHttpServer extends ProtoHttpServer<Response> {
|
||||||
|
|
||||||
public CliHttpServer(Client client) {
|
public CliHttpServer(Client client) {
|
||||||
super(client, new CliProtoHandler(client), "/cli/", "sql/");
|
super(client, new CliProtoHandler(client), "/cli/", "sql/");
|
||||||
|
@ -37,6 +37,7 @@ dependencies {
|
|||||||
compile project(':x-pack-elasticsearch:sql-clients:jdbc-proto')
|
compile project(':x-pack-elasticsearch:sql-clients:jdbc-proto')
|
||||||
|
|
||||||
testCompile project(":x-pack-elasticsearch:transport-client")
|
testCompile project(":x-pack-elasticsearch:transport-client")
|
||||||
|
testCompile project(path: ':x-pack-elasticsearch:plugin', configuration: 'testArtifacts')
|
||||||
testCompile project(':x-pack-elasticsearch:sql-clients:test-utils')
|
testCompile project(':x-pack-elasticsearch:sql-clients:test-utils')
|
||||||
|
|
||||||
testRuntime "com.h2database:h2:1.4.194"
|
testRuntime "com.h2database:h2:1.4.194"
|
||||||
|
@ -135,7 +135,7 @@ public class ProtoTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBasicJdbc() throws Exception {
|
public void testBasicJdbc() throws Exception {
|
||||||
j.con(c -> {
|
j.consume(c -> {
|
||||||
assertThat(c.isClosed(), is(false));
|
assertThat(c.isClosed(), is(false));
|
||||||
assertThat(c.isReadOnly(), is(true));
|
assertThat(c.isReadOnly(), is(true));
|
||||||
});
|
});
|
||||||
@ -145,7 +145,7 @@ public class ProtoTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBasicSelect() throws Exception {
|
public void testBasicSelect() throws Exception {
|
||||||
j.con(c -> {
|
j.consume(c -> {
|
||||||
assertThat(c.isClosed(), is(false));
|
assertThat(c.isClosed(), is(false));
|
||||||
assertThat(c.isReadOnly(), is(true));
|
assertThat(c.isReadOnly(), is(true));
|
||||||
});
|
});
|
||||||
@ -155,7 +155,7 @@ public class ProtoTest {
|
|||||||
|
|
||||||
@Test(expected = RuntimeException.class)
|
@Test(expected = RuntimeException.class)
|
||||||
public void testBasicDemo() throws Exception {
|
public void testBasicDemo() throws Exception {
|
||||||
j.con(c -> {
|
j.consume(c -> {
|
||||||
assertThat(c.isClosed(), is(false));
|
assertThat(c.isClosed(), is(false));
|
||||||
assertThat(c.isReadOnly(), is(true));
|
assertThat(c.isReadOnly(), is(true));
|
||||||
});
|
});
|
||||||
@ -166,7 +166,7 @@ public class ProtoTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMetadataGetProcedures() throws Exception {
|
public void testMetadataGetProcedures() throws Exception {
|
||||||
j.con(c -> {
|
j.consume(c -> {
|
||||||
DatabaseMetaData metaData = c.getMetaData();
|
DatabaseMetaData metaData = c.getMetaData();
|
||||||
ResultSet results = metaData.getProcedures(null, null, null);
|
ResultSet results = metaData.getProcedures(null, null, null);
|
||||||
assertThat(results, is(notNullValue()));
|
assertThat(results, is(notNullValue()));
|
||||||
@ -177,7 +177,7 @@ public class ProtoTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMetadataGetProcedureColumns() throws Exception {
|
public void testMetadataGetProcedureColumns() throws Exception {
|
||||||
j.con(c -> {
|
j.consume(c -> {
|
||||||
DatabaseMetaData metaData = c.getMetaData();
|
DatabaseMetaData metaData = c.getMetaData();
|
||||||
ResultSet results = metaData.getProcedureColumns(null, null, null, null);
|
ResultSet results = metaData.getProcedureColumns(null, null, null, null);
|
||||||
assertThat(results, is(notNullValue()));
|
assertThat(results, is(notNullValue()));
|
||||||
@ -188,7 +188,7 @@ public class ProtoTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMetadataGetTables() throws Exception {
|
public void testMetadataGetTables() throws Exception {
|
||||||
j.con(c -> {
|
j.consume(c -> {
|
||||||
DatabaseMetaData metaData = c.getMetaData();
|
DatabaseMetaData metaData = c.getMetaData();
|
||||||
ResultSet results = metaData.getTables("elasticsearch", "", "%", null);
|
ResultSet results = metaData.getTables("elasticsearch", "", "%", null);
|
||||||
assertThat(results, is(notNullValue()));
|
assertThat(results, is(notNullValue()));
|
||||||
@ -199,7 +199,7 @@ public class ProtoTest {
|
|||||||
|
|
||||||
@Test(expected = RuntimeException.class)
|
@Test(expected = RuntimeException.class)
|
||||||
public void testMetadataColumns() throws Exception {
|
public void testMetadataColumns() throws Exception {
|
||||||
j.con(c -> {
|
j.consume(c -> {
|
||||||
DatabaseMetaData metaData = c.getMetaData();
|
DatabaseMetaData metaData = c.getMetaData();
|
||||||
ResultSet results = metaData.getColumns("elasticsearch", "", "dep.dep", "%");
|
ResultSet results = metaData.getColumns("elasticsearch", "", "dep.dep", "%");
|
||||||
assertThat(results, is(notNullValue()));
|
assertThat(results, is(notNullValue()));
|
||||||
|
@ -6,9 +6,10 @@
|
|||||||
package org.elasticsearch.xpack.sql.jdbc.integration.server;
|
package org.elasticsearch.xpack.sql.jdbc.integration.server;
|
||||||
|
|
||||||
import org.elasticsearch.client.Client;
|
import org.elasticsearch.client.Client;
|
||||||
|
import org.elasticsearch.xpack.sql.jdbc.net.protocol.Response;
|
||||||
import org.elasticsearch.xpack.sql.test.server.ProtoHttpServer;
|
import org.elasticsearch.xpack.sql.test.server.ProtoHttpServer;
|
||||||
|
|
||||||
public class JdbcHttpServer extends ProtoHttpServer {
|
public class JdbcHttpServer extends ProtoHttpServer<Response> {
|
||||||
|
|
||||||
public JdbcHttpServer(Client client) {
|
public JdbcHttpServer(Client client) {
|
||||||
super(client, new SqlProtoHandler(client), "/jdbc/", "sql/");
|
super(client, new SqlProtoHandler(client), "/jdbc/", "sql/");
|
||||||
|
@ -5,19 +5,25 @@
|
|||||||
*/
|
*/
|
||||||
package org.elasticsearch.xpack.sql.jdbc.integration.util;
|
package org.elasticsearch.xpack.sql.jdbc.integration.util;
|
||||||
|
|
||||||
|
import org.elasticsearch.xpack.sql.jdbc.integration.util.JdbcTemplate.JdbcSupplier;
|
||||||
|
import org.junit.rules.ExternalResource;
|
||||||
|
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
|
import java.sql.DriverManager;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.elasticsearch.xpack.sql.jdbc.integration.util.JdbcTemplate.JdbcSupplier;
|
|
||||||
import org.h2.Driver;
|
|
||||||
import org.junit.rules.ExternalResource;
|
|
||||||
|
|
||||||
public class H2 extends ExternalResource implements JdbcSupplier<Connection> {
|
public class H2 extends ExternalResource implements JdbcSupplier<Connection> {
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
Class.forName("org.h2.Driver");
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private final String url;
|
private final String url;
|
||||||
private final Properties DEFAULT_PROPS = new Properties();
|
private final Properties DEFAULT_PROPS = new Properties();
|
||||||
private final Driver driver = Driver.load();
|
|
||||||
private Connection keepAlive;
|
private Connection keepAlive;
|
||||||
|
|
||||||
public H2() {
|
public H2() {
|
||||||
@ -48,6 +54,6 @@ public class H2 extends ExternalResource implements JdbcSupplier<Connection> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Connection jdbc() throws SQLException {
|
public Connection jdbc() throws SQLException {
|
||||||
return driver.connect(url, DEFAULT_PROPS);
|
return DriverManager.getConnection(url, DEFAULT_PROPS);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,6 +5,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.elasticsearch.xpack.sql.jdbc.integration.util;
|
package org.elasticsearch.xpack.sql.jdbc.integration.util;
|
||||||
|
|
||||||
|
import org.elasticsearch.common.CheckedConsumer;
|
||||||
|
import org.elasticsearch.common.CheckedFunction;
|
||||||
|
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
@ -15,13 +18,8 @@ import java.util.ArrayList;
|
|||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.BiFunction;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import static java.lang.String.format;
|
|
||||||
|
|
||||||
// poor's man JdbcTemplate
|
// poor's man JdbcTemplate
|
||||||
public class JdbcTemplate {
|
public class JdbcTemplate {
|
||||||
|
|
||||||
@ -45,52 +43,9 @@ public class JdbcTemplate {
|
|||||||
T jdbc() throws SQLException;
|
T jdbc() throws SQLException;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static interface JdbcConsumer<T> extends Consumer<T> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
default void accept(T t) {
|
|
||||||
try {
|
|
||||||
jdbc(t);
|
|
||||||
} catch (SQLException ex) {
|
|
||||||
throw new RuntimeException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void jdbc(T t) throws SQLException;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static interface JdbcFunction<T, R> extends Function<T, R> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
default R apply(T t) {
|
|
||||||
try {
|
|
||||||
return jdbc(t);
|
|
||||||
} catch (SQLException ex) {
|
|
||||||
throw new RuntimeException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
R jdbc(T t) throws SQLException;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static interface JdbcBiFunction<T, U, R> extends BiFunction<T, U, R> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
default R apply(T t, U u) {
|
|
||||||
try {
|
|
||||||
return jdbc(t, u);
|
|
||||||
} catch (SQLException ex) {
|
|
||||||
throw new RuntimeException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
R jdbc(T t, U u) throws SQLException;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static final int MAX_WIDTH = 20;
|
private static final int MAX_WIDTH = 20;
|
||||||
|
|
||||||
public static JdbcFunction<ResultSet, Void> resultSetToConsole() {
|
public static CheckedFunction<ResultSet, Void, SQLException> resultSetToConsole() {
|
||||||
return rs -> {
|
return rs -> {
|
||||||
ResultSetMetaData metaData = rs.getMetaData();
|
ResultSetMetaData metaData = rs.getMetaData();
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
@ -145,20 +100,20 @@ public class JdbcTemplate {
|
|||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void con(JdbcConsumer<Connection> c) throws Exception {
|
public void consume(CheckedConsumer<Connection, SQLException> c) throws Exception {
|
||||||
try (Connection con = conn.get()) {
|
try (Connection con = conn.get()) {
|
||||||
c.accept(con);
|
c.accept(con);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> T con(JdbcFunction<Connection, T> c) throws Exception {
|
public <T> T map(CheckedFunction<Connection, T, SQLException> c) throws Exception {
|
||||||
try (Connection con = conn.get()) {
|
try (Connection con = conn.get()) {
|
||||||
return c.apply(con);
|
return c.apply(con);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> T query(String q, JdbcFunction<ResultSet, T> f) throws Exception {
|
public <T> T query(String q, CheckedFunction<ResultSet, T, SQLException> f) throws Exception {
|
||||||
return con(c -> {
|
return map(c -> {
|
||||||
try (Statement st = c.createStatement();
|
try (Statement st = c.createStatement();
|
||||||
ResultSet rset = st.executeQuery(q)) {
|
ResultSet rset = st.executeQuery(q)) {
|
||||||
return f.apply(rset);
|
return f.apply(rset);
|
||||||
@ -175,7 +130,7 @@ public class JdbcTemplate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void execute(String query) throws Exception {
|
public void execute(String query) throws Exception {
|
||||||
con(c -> {
|
map(c -> {
|
||||||
try (Statement st = c.createStatement()) {
|
try (Statement st = c.createStatement()) {
|
||||||
st.execute(query);
|
st.execute(query);
|
||||||
return null;
|
return null;
|
||||||
@ -183,15 +138,16 @@ public class JdbcTemplate {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> T execute(String query, JdbcFunction<PreparedStatement, T> callback) throws Exception {
|
public <T> T execute(String query, CheckedFunction<PreparedStatement, T, SQLException> callback) throws Exception {
|
||||||
return con(c -> {
|
return map(c -> {
|
||||||
try (PreparedStatement ps = c.prepareStatement(query)) {
|
try (PreparedStatement ps = c.prepareStatement(query)) {
|
||||||
return callback.apply(ps);
|
return callback.apply(ps);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> T execute(String query, JdbcConsumer<PreparedStatement> prepare, JdbcFunction<ResultSet, T> mapper) throws Exception {
|
public <T> T execute(String query, CheckedConsumer<PreparedStatement, SQLException> prepare,
|
||||||
|
CheckedFunction<ResultSet, T, SQLException> mapper) throws Exception {
|
||||||
return execute(query, ps -> {
|
return execute(query, ps -> {
|
||||||
prepare.accept(ps);
|
prepare.accept(ps);
|
||||||
try (ResultSet rs = ps.executeQuery()) {
|
try (ResultSet rs = ps.executeQuery()) {
|
||||||
@ -200,8 +156,8 @@ public class JdbcTemplate {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> T query(String q, JdbcFunction<ResultSet, T> mapper, Object... args) throws Exception {
|
public <T> T query(String q, CheckedFunction<ResultSet, T, SQLException> mapper, Object... args) throws Exception {
|
||||||
JdbcConsumer<PreparedStatement> p = ps -> {
|
CheckedConsumer<PreparedStatement, SQLException> p = ps -> {
|
||||||
if (args != null) {
|
if (args != null) {
|
||||||
for (int i = 0; i < args.length; i++) {
|
for (int i = 0; i < args.length; i++) {
|
||||||
ps.setObject(i + 1, args[i]);
|
ps.setObject(i + 1, args[i]);
|
||||||
@ -216,8 +172,9 @@ public class JdbcTemplate {
|
|||||||
return query(q, singleResult(type), args);
|
return query(q, singleResult(type), args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> List<T> queryForList(String q, JdbcBiFunction<ResultSet, Integer, T> mapper, Object... args) throws Exception {
|
public <T> List<T> queryForList(String q, CheckedBiFunction<ResultSet, Integer, T, SQLException> mapper, Object... args)
|
||||||
JdbcFunction<ResultSet, List<T>> f = rs -> {
|
throws Exception {
|
||||||
|
CheckedFunction<ResultSet, List<T>, SQLException> f = rs -> {
|
||||||
List<T> list = new ArrayList<>();
|
List<T> list = new ArrayList<>();
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
list.add(mapper.apply(rs, rs.getRow()));
|
list.add(mapper.apply(rs, rs.getRow()));
|
||||||
@ -229,7 +186,7 @@ public class JdbcTemplate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public <T> List<T> queryForList(String q, Class<T> type, Object... args) throws Exception {
|
public <T> List<T> queryForList(String q, Class<T> type, Object... args) throws Exception {
|
||||||
JdbcBiFunction<ResultSet, Integer, T> mapper = (rs, i) -> {
|
CheckedBiFunction<ResultSet, Integer, T, SQLException> mapper = (rs, i) -> {
|
||||||
if (i != 1) {
|
if (i != 1) {
|
||||||
throw new IllegalArgumentException("Expected exactly one column...");
|
throw new IllegalArgumentException("Expected exactly one column...");
|
||||||
}
|
}
|
||||||
@ -238,7 +195,7 @@ public class JdbcTemplate {
|
|||||||
return queryForList(q, mapper, args);
|
return queryForList(q, mapper, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> JdbcFunction<ResultSet, T> singleResult(Class<T> type) {
|
public static <T> CheckedFunction<ResultSet, T, SQLException> singleResult(Class<T> type) {
|
||||||
return rs -> {
|
return rs -> {
|
||||||
if (rs.next()) {
|
if (rs.next()) {
|
||||||
T result = convertObject(rs.getObject(1), type);
|
T result = convertObject(rs.getObject(1), type);
|
||||||
@ -246,7 +203,7 @@ public class JdbcTemplate {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new IllegalArgumentException(format("Expected exactly one column; discovered %s",rs.getMetaData().getColumnCount()));
|
throw new IllegalArgumentException("Expected exactly one column; discovered [" + rs.getMetaData().getColumnCount() + "]");
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,4 +247,9 @@ public class JdbcTemplate {
|
|||||||
return map;
|
return map;
|
||||||
}, args);
|
}, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface CheckedBiFunction<T, U, R, E extends Exception> {
|
||||||
|
R apply(T t, U u) throws E;
|
||||||
|
}
|
||||||
}
|
}
|
@ -83,7 +83,7 @@ public abstract class ProtoHandler<R> implements HttpHandler, AutoCloseable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws Exception {
|
public void close() {
|
||||||
// no-op
|
// no-op
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -15,14 +15,14 @@ import com.sun.net.httpserver.HttpServer;
|
|||||||
|
|
||||||
import static java.lang.String.format;
|
import static java.lang.String.format;
|
||||||
|
|
||||||
public abstract class ProtoHttpServer {
|
public abstract class ProtoHttpServer<R> {
|
||||||
|
|
||||||
private final ProtoHandler handler;
|
private final ProtoHandler<R> handler;
|
||||||
private final String defaultPrefix, protoPrefix;
|
private final String defaultPrefix, protoPrefix;
|
||||||
private final Client client;
|
private final Client client;
|
||||||
private HttpServer server;
|
private HttpServer server;
|
||||||
|
|
||||||
public ProtoHttpServer(Client client, ProtoHandler handler, String defaultPrefix, String protoPrefix) {
|
public ProtoHttpServer(Client client, ProtoHandler<R> handler, String defaultPrefix, String protoPrefix) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.handler = handler;
|
this.handler = handler;
|
||||||
this.defaultPrefix = defaultPrefix;
|
this.defaultPrefix = defaultPrefix;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user