Skip to content

Commit a0fe7c1

Browse files
Patryk Jatczakpiotrczarnas
Patryk Jatczak
authored andcommitted
Merged PR 2604: duckdb directories has a special string for directory mapping
duckdb directories has a special string for directory mapping Related work items: #11648
2 parents e026477 + ac63ae5 commit a0fe7c1

File tree

4 files changed

+128
-21
lines changed

4 files changed

+128
-21
lines changed

dqops/src/main/java/com/dqops/connectors/duckdb/DuckdbConnectionProvider.java

+25-20
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,7 @@
3232
import tech.tablesaw.api.ColumnType;
3333
import tech.tablesaw.columns.Column;
3434

35-
import java.util.Arrays;
36-
import java.util.List;
37-
import java.util.NoSuchElementException;
35+
import java.util.*;
3836
import java.util.stream.Collectors;
3937

4038
/**
@@ -139,30 +137,37 @@ public void promptForConnectionParameters(ConnectionSpec connectionSpec, boolean
139137
duckdbSpec.setFilesFormatType(terminalReader.promptEnum("Type of source files for DuckDB", DuckdbFilesFormatType.class, null, false));
140138
}
141139

142-
if (duckdbSpec.getDirectories().isEmpty()) {
140+
if (duckdbSpec.getDirectoriesString().isEmpty()) {
143141
if (isHeadless) {
144142
throw new CliRequiredParameterMissingException("--duckdb-directories");
145143
}
144+
duckdbSpec.setDirectoriesString(terminalReader.prompt("Virtual schema name and path in a pattern: schema=path. For multiple use pattern: schema=path1,schema=path2", null, false));
145+
}
146146

147-
String directoriesRaw = terminalReader.prompt("Virtual schema names and paths (in a pattern schema=path)", null, false);
148-
if(!directoriesRaw.contains("/") && !directoriesRaw.contains("\\")){
149-
throw new RuntimeException("The provided path is invalid. The path should be an absolute path to the directory with folders or files. On Windows use double backslash (\\\\).");
150-
}
151-
List<String> directories = Arrays.stream(directoriesRaw.split(",")).collect(Collectors.toList());
152-
153-
for (String directory : directories) {
154-
List<String> schemaDirectory = Arrays.stream(directory.split("="))
155-
.map(String::trim)
156-
.collect(Collectors.toList());
157-
if(schemaDirectory.size() != 2){
158-
throw new RuntimeException("Unbalanced values for " + directory + "." +
159-
"Ensure you provide directories in a schema=path pattern.");
160-
}
161-
duckdbSpec.getDirectories().put(schemaDirectory.get(0), schemaDirectory.get(1));
162-
}
147+
Map<String, String> directories = parseDirectoriesString(duckdbSpec.getDirectoriesString());
148+
duckdbSpec.setDirectories(directories);
149+
}
163150

151+
Map<String, String> parseDirectoriesString(String directoriesRaw){
152+
Map<String, String> directories = new HashMap<>();
153+
154+
if(!directoriesRaw.contains("/") && !directoriesRaw.contains("\\")){
155+
throw new RuntimeException("The provided path is invalid. The path should be an absolute path to the directory with folders or files. On Windows use double backslash (\\\\).");
156+
}
157+
List<String> singleMapping = Arrays.stream(directoriesRaw.split(",")).collect(Collectors.toList());
158+
159+
for (String mapping : singleMapping) {
160+
List<String> schemaDirectory = Arrays.stream(mapping.split("="))
161+
.map(String::trim)
162+
.collect(Collectors.toList());
163+
if(schemaDirectory.size() != 2){
164+
throw new RuntimeException("Unbalanced values for " + mapping + "." +
165+
"Ensure you provide directories in a schema=path pattern.");
166+
}
167+
directories.put(schemaDirectory.get(0), schemaDirectory.get(1));
164168
}
165169

170+
return directories;
166171
}
167172

168173
/**

dqops/src/main/java/com/dqops/connectors/duckdb/DuckdbParametersSpec.java

+21-1
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,14 @@ public class DuckdbParametersSpec extends BaseProviderParametersSpec
9090
@JsonSerialize(using = IgnoreEmptyYamlSerializer.class)
9191
private ParquetFileFormatSpec parquet;
9292

93-
@CommandLine.Option(names = "--duckdb-directories", split = ",")
9493
@JsonPropertyDescription("Virtual schema name to directory mappings. The path must be an absolute path.")
9594
@JsonInclude(JsonInclude.Include.NON_EMPTY)
9695
private Map<String, String> directories = new HashMap<>();
9796

97+
@CommandLine.Option(names = {"--duckdb-directories"}, description = "Virtual schema name to directory mappings. The path must be an absolute path.")
98+
@JsonIgnore
99+
private String directoriesString;
100+
98101
@CommandLine.Option(names = {"--duckdb-storage-type"}, description = "The storage type.")
99102
@JsonPropertyDescription("The storage type.")
100103
private DuckdbStorageType storageType;
@@ -254,6 +257,23 @@ public void setDirectories(Map<String, String> directories) {
254257
this.directories = directories != null ? Collections.unmodifiableMap(directories) : null;
255258
}
256259

260+
/**
261+
* Returns a raw directories string containing mapping between schemas and directories
262+
* @return Raw directories string containing mapping between schemas and directories
263+
*/
264+
public String getDirectoriesString() {
265+
return directoriesString;
266+
}
267+
268+
/**
269+
* Sets a raw directories string containing mapping between schemas and directories
270+
* @param directoriesString Raw directories string containing mapping between schemas and directories
271+
*/
272+
public void setDirectoriesString(String directoriesString) {
273+
setDirtyIf(!Objects.equals(this.directoriesString, directoriesString));
274+
this.directoriesString = directoriesString;
275+
}
276+
257277
/**
258278
* Returns the storage type.
259279
* @return the storage type.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright © 2021 DQOps (support@dqops.com)
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.dqops.connectors.duckdb;
17+
18+
import com.dqops.utils.BeanFactoryObjectMother;
19+
import org.springframework.beans.factory.BeanFactory;
20+
21+
/**
22+
* DuckdbConnectionProvider object mother.
23+
*/
24+
public class DuckdbConnectionProviderObjectMother {
25+
/**
26+
* Returns the DuckdbConnectionProvider.
27+
* @return DuckdbConnectionProvider.
28+
*/
29+
public static DuckdbConnectionProvider getProvider() {
30+
BeanFactory beanFactory = BeanFactoryObjectMother.getBeanFactory();
31+
return beanFactory.getBean(DuckdbConnectionProvider.class);
32+
}
33+
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package com.dqops.connectors.duckdb;
2+
3+
import com.dqops.BaseTest;
4+
import org.junit.jupiter.api.Assertions;
5+
import org.junit.jupiter.api.BeforeEach;
6+
import org.junit.jupiter.api.Test;
7+
import org.springframework.boot.test.context.SpringBootTest;
8+
9+
import java.util.Map;
10+
11+
@SpringBootTest
12+
class DuckdbConnectionProviderTest extends BaseTest {
13+
14+
private DuckdbConnectionProvider sut;
15+
16+
17+
@BeforeEach
18+
void setUp() {
19+
sut = DuckdbConnectionProviderObjectMother.getProvider();
20+
}
21+
22+
@Test
23+
void parseDirectoriesString_whenOneValidMapping_parsesIt() {
24+
String inputString = "schema=/directory";
25+
26+
Map<String, String> mapping = sut.parseDirectoriesString(inputString);
27+
28+
Assertions.assertEquals(1, mapping.size());
29+
Assertions.assertTrue(mapping.containsKey("schema"));
30+
Assertions.assertEquals("/directory", mapping.get("schema"));
31+
}
32+
33+
@Test
34+
void parseDirectoriesString_whenMultiMapping_parsesIt() {
35+
String inputString = "schema1=/directory1,schema2=/directory2";
36+
37+
Map<String, String> mapping = sut.parseDirectoriesString(inputString);
38+
39+
Assertions.assertEquals(2, mapping.size());
40+
41+
Assertions.assertTrue(mapping.containsKey("schema1"));
42+
Assertions.assertEquals("/directory1", mapping.get("schema1"));
43+
44+
Assertions.assertTrue(mapping.containsKey("schema2"));
45+
Assertions.assertEquals("/directory2", mapping.get("schema2"));
46+
}
47+
48+
}

0 commit comments

Comments
 (0)