Skip to content

Commit 540ecc9

Browse files
authored
#2116 fix backup database functionality and add more tests (#2198)
1 parent efdfa0d commit 540ecc9

File tree

21 files changed

+254
-60
lines changed

21 files changed

+254
-60
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,3 +545,4 @@ dist
545545

546546
# Python egg metadata
547547
*.egg-info/
548+
/backups/

e2e/src/test/java/com/arcadedb/e2e/ArcadeContainerTemplate.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,17 @@
2020

2121
import org.testcontainers.containers.GenericContainer;
2222
import org.testcontainers.containers.wait.strategy.Wait;
23-
import org.testcontainers.containers.wait.strategy.WaitAllStrategy;
24-
import org.testcontainers.containers.wait.strategy.WaitStrategyTarget;
2523

26-
import java.time.*;
24+
import java.time.Duration;
2725

2826
public abstract class ArcadeContainerTemplate {
29-
static final GenericContainer ARCADE;
27+
static final GenericContainer<?> ARCADE;
3028

3129
static {
32-
ARCADE = new GenericContainer("arcadedata/arcadedb:latest").withExposedPorts(2480, 6379, 5432, 8182)
33-
.withStartupTimeout(Duration.ofSeconds(90)).withEnv("JAVA_OPTS", """
30+
ARCADE = new GenericContainer<>("arcadedata/arcadedb:latest")
31+
.withExposedPorts(2480, 6379, 5432, 8182)
32+
.withStartupTimeout(Duration.ofSeconds(90))
33+
.withEnv("JAVA_OPTS", """
3434
-Darcadedb.server.rootPassword=playwithdata
3535
-Darcadedb.server.defaultDatabases=beer[root]{import:https://github.com/ArcadeData/arcadedb-datasets/raw/main/orientdb/OpenBeer.gz}
3636
-Darcadedb.server.plugins=Postgres:com.arcadedb.postgres.PostgresProtocolPlugin,GremlinServer:com.arcadedb.server.gremlin.GremlinServerPlugin

e2e/src/test/java/com/arcadedb/e2e/JdbcQueriesTest.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,6 @@ void preparedStatement() throws Exception {
9191
}
9292
}
9393

94-
95-
9694
@Test
9795
void bigResultSetSQLQuery() throws Exception {
9896

@@ -269,7 +267,19 @@ void testSelectSchemaTypes() throws SQLException, ClassNotFoundException {
269267
}
270268

271269
@Test
272-
// @Disabled
270+
void testBackupDatabase() throws SQLException {
271+
try (final Statement stmt = conn.createStatement()) {
272+
assertThat(stmt.execute("{sql}BACKUP DATABASE;")).isTrue();
273+
}
274+
275+
try (final Statement stmt = conn.createStatement()) {
276+
assertThat(stmt.execute("{sqlscript}BACKUP DATABASE;")).isTrue();
277+
}
278+
279+
}
280+
281+
@Test
282+
@Disabled
273283
void testMultipleInsert() throws SQLException, ClassNotFoundException {
274284
try (Statement stmt = conn.createStatement()) {
275285

e2e/src/test/java/com/arcadedb/e2e/RemoteDatabaseJavaApiTest.java

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,15 @@
2121
import com.arcadedb.graph.MutableEdge;
2222
import com.arcadedb.graph.MutableVertex;
2323
import com.arcadedb.graph.Vertex;
24+
import com.arcadedb.query.sql.executor.Result;
2425
import com.arcadedb.query.sql.executor.ResultSet;
2526
import com.arcadedb.remote.RemoteDatabase;
2627
import org.junit.jupiter.api.AfterEach;
2728
import org.junit.jupiter.api.BeforeEach;
29+
import org.junit.jupiter.api.Disabled;
2830
import org.junit.jupiter.api.Test;
2931

32+
import java.io.IOException;
3033
import java.sql.SQLException;
3134
import java.time.Duration;
3235
import java.time.LocalDateTime;
@@ -50,6 +53,34 @@ void tearDown() {
5053
database.close();
5154
}
5255

56+
@Test
57+
void backupDatabase() throws IOException, InterruptedException {
58+
59+
ResultSet resultSet = database.command("sql", "BACKUP DATABASE");
60+
61+
Result result = resultSet.next();
62+
assertThat(result.<String>getProperty("result")).isEqualTo("OK");
63+
assertThat(result.<String>getProperty("backupFile")).startsWith("beer-backup-");
64+
65+
resultSet = database.command("sqlscript", "BACKUP DATABASE");
66+
67+
result = resultSet.next();
68+
assertThat(result.<String>getProperty("result")).isEqualTo("OK");
69+
assertThat(result.<String>getProperty("backupFile")).startsWith("beer-backup-");
70+
71+
resultSet = database.command("sqlscript", """
72+
BEGIN;
73+
INSERT INTO Beer SET name = 'beer1';
74+
COMMIT;
75+
BACKUP DATABASE;
76+
""");
77+
78+
result = resultSet.next();
79+
assertThat(result.<String>getProperty("result")).isEqualTo("OK");
80+
assertThat(result.<String>getProperty("backupFile")).startsWith("beer-backup-");
81+
82+
}
83+
5384
@Test
5485
void createUnidirectionalEdge() {
5586

@@ -119,7 +150,7 @@ SELECT expand( out('HasUploaded') ) FROM Users WHERE id = "u1111"
119150
}
120151

121152
@Test
122-
// @Disabled
153+
@Disabled
123154
void testMultipleInsert() throws SQLException, ClassNotFoundException {
124155
database.command("sqlscript", """
125156
create vertex type `TEXT_EMBEDDING` if not exists;
@@ -129,15 +160,13 @@ void testMultipleInsert() throws SQLException, ClassNotFoundException {
129160

130161
LocalDateTime start = LocalDateTime.now();
131162

132-
// database.transaction(() -> {
133-
IntStream.range(1, 100001).forEach(i -> {
163+
IntStream.range(1, 100001).forEach(i -> {
134164

135-
database.command("sqlscript",
136-
"INSERT INTO `TEXT_EMBEDDING` SET str = meow_%d, embedding = [0.1,0.2,0.3] RETURN embedding;".formatted(i));
165+
database.command("sqlscript",
166+
"INSERT INTO `TEXT_EMBEDDING` SET str = meow_%d, embedding = [0.1,0.2,0.3] RETURN embedding;".formatted(i));
137167

138-
});
168+
});
139169

140-
// });
141170
LocalDateTime end = LocalDateTime.now();
142171
System.out.println("Execution time: " + Duration.between(start, end).toSeconds() + " seconds");
143172

@@ -147,7 +176,7 @@ void testMultipleInsert() throws SQLException, ClassNotFoundException {
147176
}
148177

149178
@Test
150-
// @Disabled
179+
@Disabled
151180
void testMultipleInsertBAtched() throws SQLException, ClassNotFoundException {
152181
database.command("sqlscript", """
153182
create vertex type `TEXT_EMBEDDING` if not exists;

engine/src/main/java/com/arcadedb/query/sql/SQLQueryEngine.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@
4040
import com.arcadedb.utility.Callable;
4141
import com.arcadedb.utility.MultiIterator;
4242

43-
import java.util.*;
43+
import java.util.Iterator;
44+
import java.util.Map;
45+
import java.util.Set;
4446

4547
import static com.arcadedb.query.sql.parser.SqlParserTreeConstants.JJTLIMIT;
4648

@@ -212,7 +214,7 @@ public SQLMethod getMethod(final String name) {
212214
return methods.createMethod(name);
213215
}
214216

215-
public static Statement parse(final String query, final DatabaseInternal database) {
217+
public Statement parse(final String query, final DatabaseInternal database) {
216218
return database.getStatementCache().get(query);
217219
}
218220

engine/src/main/java/com/arcadedb/query/sql/executor/BasicCommandContext.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
import java.util.*;
2727

2828
/**
29-
* Basic implementation of OCommandContext interface that stores variables in a map. Supports parent/child context to build a tree
29+
* Basic implementation of CommandContext interface that stores variables in a map. Supports parent/child context to build a tree
3030
* of contexts. If a variable is not found on current object the search is applied recursively on child contexts.
3131
*
3232
* @author Luca Garulli (l.garulli--(at)--gmail.com)

engine/src/main/java/com/arcadedb/query/sql/parser/BackupDatabaseStatement.java

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@
2929
import com.arcadedb.query.sql.executor.ResultInternal;
3030
import com.arcadedb.query.sql.executor.ResultSet;
3131

32-
import java.io.*;
33-
import java.lang.reflect.*;
34-
import java.util.*;
35-
import java.util.logging.*;
32+
import java.io.File;
33+
import java.lang.reflect.InvocationTargetException;
34+
import java.util.Map;
35+
import java.util.logging.Level;
3636

3737
public class BackupDatabaseStatement extends SimpleExecStatement {
3838
protected Url url;
@@ -62,16 +62,28 @@ public ResultSet executeSimple(final CommandContext context) {
6262
String backupDirectory = context.getConfiguration().getValueAsString(GlobalConfiguration.SERVER_BACKUP_DIRECTORY);
6363
if (!backupDirectory.endsWith(File.separator))
6464
backupDirectory += File.separator;
65+
6566
clazz.getMethod("setDirectory", String.class).invoke(backup, backupDirectory + context.getDatabase().getName());
66-
clazz.getMethod("setVerboseLevel", Integer.TYPE).invoke(backup, 1);
67-
final String backupFile = (String) clazz.getMethod("backupDatabase").invoke(backup);
67+
clazz.getMethod("setVerboseLevel", Integer.TYPE).invoke(backup, 0);
68+
try {
6869

69-
result.setProperty("result", "OK");
70-
result.setProperty("backupFile", backupFile);
70+
final String backupFile = (String) clazz.getMethod("backupDatabase").invoke(backup);
71+
result.setProperty("result", "OK");
72+
result.setProperty("backupFile", backupFile);
7173

72-
final InternalResultSet rs = new InternalResultSet();
73-
rs.add(result);
74-
return rs;
74+
final InternalResultSet rs = new InternalResultSet();
75+
rs.add(result);
76+
return rs;
77+
} catch (Exception e) {
78+
LogManager.instance().log(this, Level.SEVERE,
79+
String.format("Error on backup database '%s' to directory '%s'",
80+
context.getDatabase().getName(), backupDirectory), e);
81+
result.setProperty("result", "ERROR");
82+
result.setProperty("error", e.getMessage());
83+
final InternalResultSet rs = new InternalResultSet();
84+
rs.add(result);
85+
return rs;
86+
}
7587

7688
} catch (final ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InstantiationException e) {
7789
throw new CommandExecutionException("Error on backing up database, backup libs not found in classpath", e);

engine/src/test/java/com/arcadedb/TestHelper.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ protected void endTest() {
148148

149149
@BeforeEach
150150
public void beforeTest() {
151+
GlobalConfiguration.SERVER_ROOT_PATH.setValue("./target");
151152
if (autoStartTx && !database.isTransactionActive())
152153
database.begin();
153154
beginTest();
@@ -173,6 +174,7 @@ public void afterTest() {
173174

174175
checkActiveDatabases();
175176
FileUtils.deleteRecursively(new File(getDatabasePath()));
177+
GlobalConfiguration.resetAll();
176178
}
177179

178180
@AfterAll

integration/pom.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@
4242
<artifactId>arcadedb-engine</artifactId>
4343
<version>${project.parent.version}</version>
4444
</dependency>
45+
<dependency>
46+
<groupId>com.arcadedb</groupId>
47+
<artifactId>arcadedb-engine</artifactId>
48+
<version>${project.parent.version}</version>
49+
<scope>test</scope>
50+
<type>test-jar</type>
51+
</dependency>
4552
<dependency>
4653
<groupId>com.sonofab1rd</groupId>
4754
<artifactId>univocity-parsers</artifactId>

integration/src/main/java/com/arcadedb/integration/backup/BackupSettings.java

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,12 @@
1818
*/
1919
package com.arcadedb.integration.backup;
2020

21-
import java.io.*;
22-
import java.text.*;
23-
import java.util.*;
21+
import java.io.File;
22+
import java.text.DateFormat;
23+
import java.text.SimpleDateFormat;
24+
import java.util.HashMap;
25+
import java.util.Locale;
26+
import java.util.Map;
2427

2528
public class BackupSettings {
2629
public String format = "full";
@@ -52,33 +55,38 @@ public void validateSettings() {
5255

5356
if (file == null)
5457
// ASSIGN DEFAULT FILENAME
55-
switch (format) {
56-
case "full":
58+
if (format.equals("full")) {
5759
final DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd-HHmmssSSS");
5860
file = "%s-backup-%s.zip".formatted(databaseName, dateFormat.format(System.currentTimeMillis()));
59-
break;
6061
}
6162
}
6263

6364
public int parseParameter(final String name, final String value) {
64-
if ("format".equals(name)) {
65+
switch (name) {
66+
case "format" -> {
6567
if (value != null)
6668
format = value.toLowerCase(Locale.ENGLISH);
67-
} else if ("dir".equals(name)) {
69+
}
70+
case "dir" -> {
6871
if (value != null)
6972
directory = value.endsWith(File.separator) ? value : value + File.separator;
70-
} else if ("f".equals(name)) {
73+
}
74+
case "f" -> {
7175
if (value != null)
7276
file = value;
73-
} else if ("d".equals(name)) {
77+
}
78+
case "d" -> {
7479
if (value != null)
7580
databaseURL = value;
76-
} else if ("o".equals(name)) {
81+
}
82+
case "o" -> {
7783
overwriteFile = true;
7884
return 1;
79-
} else
85+
}
86+
case null, default ->
8087
// ADDITIONAL OPTIONS
81-
options.put(name, value);
88+
options.put(name, value);
89+
}
8290
return 2;
8391
}
8492
}

0 commit comments

Comments
 (0)