Skip to content

Commit 49c8505

Browse files
committed
Support adding position
1 parent 4ed5c90 commit 49c8505

File tree

8 files changed

+191
-17
lines changed

8 files changed

+191
-17
lines changed

README.md

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Support following features.
1313
* Formatting sql to one line format and separate column list using `','`
1414
* Supports column position based operations for sql without column list such as `"insert into xxxx values('123',NULL,'0');"`
1515
* Supports position based column value reference (variable name format: `column{position}`) such as `--column-values=#column1`
16+
* Supports adding column at any position
1617

1718
> **NOTE:**
1819
>
@@ -41,10 +42,10 @@ Search files that matches conditions specified by `--dir` and `--files`.
4142
[INFO] Scanning for projects...
4243
[INFO]
4344
[INFO] -------------------< com.example:sql-bulk-commands >--------------------
44-
[INFO] Building sql-bulk-commands 0.0.1-SNAPSHOT
45+
[INFO] Building sql-bulk-commands 0.0.3-SNASPHOT
4546
[INFO] --------------------------------[ jar ]---------------------------------
4647
[INFO]
47-
[INFO] >>> spring-boot-maven-plugin:2.5.6:run (default-cli) > test-compile @ sql-bulk-commands >>>
48+
[INFO] >>> spring-boot-maven-plugin:2.6.4:run (default-cli) > test-compile @ sql-bulk-commands >>>
4849
[INFO]
4950
[INFO] --- maven-resources-plugin:3.2.0:resources (default-resources) @ sql-bulk-commands ---
5051
[INFO] Using 'UTF-8' encoding to copy filtered resources.
@@ -58,15 +59,15 @@ Search files that matches conditions specified by `--dir` and `--files`.
5859
[INFO] --- maven-resources-plugin:3.2.0:testResources (default-testResources) @ sql-bulk-commands ---
5960
[INFO] Using 'UTF-8' encoding to copy filtered resources.
6061
[INFO] Using 'UTF-8' encoding to copy filtered properties files.
61-
[INFO] Copying 3 resources
62+
[INFO] Copying 18 resources
6263
[INFO]
6364
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ sql-bulk-commands ---
6465
[INFO] Nothing to compile - all classes are up to date
6566
[INFO]
66-
[INFO] <<< spring-boot-maven-plugin:2.5.6:run (default-cli) < test-compile @ sql-bulk-commands <<<
67+
[INFO] <<< spring-boot-maven-plugin:2.6.4:run (default-cli) < test-compile @ sql-bulk-commands <<<
6768
[INFO]
6869
[INFO]
69-
[INFO] --- spring-boot-maven-plugin:2.5.6:run (default-cli) @ sql-bulk-commands ---
70+
[INFO] --- spring-boot-maven-plugin:2.6.4:run (default-cli) @ sql-bulk-commands ---
7071
[INFO] Attaching agents: []
7172
7273
[Command arguments]
@@ -103,6 +104,12 @@ Search files that matches conditions specified by `--dir` and `--files`.
103104
- id
104105
- vendor_id
105106
- amount
107+
--first
108+
indicate that adding column at first position
109+
--after-by-name
110+
indicate that adding column at after specified column name
111+
--after-by-position
112+
indicate that adding column at after specified column position
106113
--h (--help)
107114
print help
108115
@@ -122,6 +129,25 @@ Search files that matches conditions specified by `--dir` and `--files`.
122129
insert into xxxx (a,b,c) values ('123',1,'123');
123130
------------------------
124131
132+
e.g.) --command=adding-columns --dir=src/test/resources/data --files=xxx.sql,yyy.sql --column-names=d,e --column-values=1,#a --first
133+
------------------------
134+
insert into xxxx (a,b,c) values('123','1','2');
135+
------------------------
136+
137+
------------------------
138+
insert into xxxx (d,e,a,b,c) values (1,'123','123','1','2');
139+
------------------------
140+
141+
e.g.) --command=adding-columns --dir=src/test/resources/data --files=xxx.sql,yyy.sql --column-names=d,e --column-values=1,#a --after-by-name=a
142+
--command=adding-columns --dir=src/test/resources/data --files=xxx.sql,yyy.sql --column-names=d,e --column-values=1,#a --after-by-position=1
143+
------------------------
144+
insert into xxxx (a,b,c) values('123','1','2');
145+
------------------------
146+
147+
------------------------
148+
insert into xxxx (a,d,e,b,c) values ('123',1,'123','1','2');
149+
------------------------
150+
125151
[Usage: deleting-columns]
126152
Deleting specified existing column using column-names(or column-positions).
127153
e.g.) --command=deleting-columns --dir=src/test/resources/data --files=xxx.sql,yyy.sql --column-names=b
@@ -170,12 +196,11 @@ Search files that matches conditions specified by `--dir` and `--files`.
170196
insert into xxxx (a,b,c) values ('123',1,'0');
171197
------------------------
172198
173-
174199
[INFO] ------------------------------------------------------------------------
175200
[INFO] BUILD SUCCESS
176201
[INFO] ------------------------------------------------------------------------
177-
[INFO] Total time: 2.828 s
178-
[INFO] Finished at: 2021-11-01T02:28:57+09:00
202+
[INFO] Total time: 1.938 s
203+
[INFO] Finished at: 2022-02-27T11:38:12+09:00
179204
[INFO] ------------------------------------------------------------------------
180205
```
181206

src/main/java/com/example/tools/AddingColumnProcessor.java

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,39 @@
11
package com.example.tools;
22

33
import org.springframework.expression.EvaluationContext;
4-
import org.springframework.expression.ExpressionParser;
54
import org.springframework.util.StringUtils;
65

6+
import java.nio.charset.Charset;
7+
import java.nio.file.Path;
78
import java.util.ArrayList;
89
import java.util.Arrays;
910
import java.util.LinkedHashMap;
1011
import java.util.List;
1112
import java.util.Map;
1213
import java.util.stream.Collectors;
14+
import java.util.stream.Stream;
1315

1416
public class AddingColumnProcessor extends SqlBulkCommandsProcessorSupport {
1517

1618
static final AddingColumnProcessor INSTANCE = new AddingColumnProcessor();
19+
private final ThreadLocal<String> currentMethod = new ThreadLocal<>();
20+
private final ThreadLocal<String> currentTarget = new ThreadLocal<>();
1721

1822
private AddingColumnProcessor() {
1923
// NOP
2024
}
25+
26+
void execute(String method, String target,List<String> columnNames, List<Integer> columnPositions, List<String> columnValues, Path file,
27+
Charset encoding, Map<String, Object> valueMappings, Map<String, Object> tableDefinitions) {
28+
currentMethod.set(method);
29+
currentTarget.set(target);
30+
try {
31+
super.execute(columnNames, columnPositions, columnValues, file, encoding, valueMappings, tableDefinitions);
32+
} finally {
33+
currentMethod.remove();
34+
currentTarget.remove();
35+
}
36+
}
2137

2238
@Override
2339
protected String generateSql(String tableName, String sqlTemplate, String columns, String values,
@@ -27,6 +43,17 @@ protected String generateSql(String tableName, String sqlTemplate, String column
2743
List<String> valueColumns = Arrays.stream(StringUtils.commaDelimitedListToStringArray(values)).map(String::trim)
2844
.collect(
2945
Collectors.toList());
46+
47+
String method = currentMethod.get();
48+
String target = currentTarget.get();
49+
50+
if ("after-by-name".equalsIgnoreCase(method) && (headerColumns.isEmpty() || Stream.of(target, target.toLowerCase(),
51+
target.toUpperCase()).map(x -> headerColumns.indexOf(target))
52+
.noneMatch(x -> x != -1))) {
53+
throw new IllegalArgumentException(
54+
"Cannot use the 'after-by-name' option because no header names in sql or no provide table definition.");
55+
}
56+
3057
Map<String, Integer> headerIndexMap = new LinkedHashMap<>();
3158
if (headerColumns.isEmpty()) {
3259
for (int i = 0; i < valueColumns.size(); i++) {
@@ -38,12 +65,27 @@ protected String generateSql(String tableName, String sqlTemplate, String column
3865
headerIndexMap.put("column" + (i + 1), i);
3966
}
4067
}
68+
69+
int addingStartIndex;
70+
if ("first".equalsIgnoreCase(method)) {
71+
addingStartIndex = 0;
72+
} else if ("after-by-name".equalsIgnoreCase(method)) {
73+
addingStartIndex =
74+
Stream.of(target, target.toLowerCase(), target.toUpperCase()).map(x -> headerColumns.indexOf(target))
75+
.filter(x -> x != -1).findAny().orElse(0) + 1;
76+
} else if ("after-by-position".equalsIgnoreCase(method)) {
77+
addingStartIndex = headerColumns.isEmpty() ? 0 : Integer.parseInt(target);
78+
} else {
79+
addingStartIndex = headerColumns.size();
80+
}
81+
4182
Map<Integer, Boolean> containsColumnMap = new LinkedHashMap<>();
83+
int baseHeaderColumnSize = headerColumns.size();
4284
for (String columnName : columnNames) {
4385
boolean contains = headerColumns.contains(columnName);
4486
containsColumnMap.put(containsColumnMap.size(), contains);
4587
if (!contains) {
46-
headerColumns.add(columnName);
88+
headerColumns.add(addingStartIndex + (headerColumns.size() - baseHeaderColumnSize), columnName);
4789
}
4890
}
4991
List<String> validColumnValues = new ArrayList<>();
@@ -53,8 +95,14 @@ protected String generateSql(String tableName, String sqlTemplate, String column
5395
}
5496
}
5597
EvaluationContext context = createEvaluationContext(headerIndexMap, valueColumns, valueMappings);
98+
if ("last".equalsIgnoreCase(method)) {
99+
addingStartIndex = valueColumns.size();
100+
} else if ("after-by-position".equalsIgnoreCase(method)) {
101+
addingStartIndex = Integer.parseInt(target);
102+
}
103+
int baseValueColumnSize = valueColumns.size();
56104
for (String value : validColumnValues) {
57-
valueColumns.add(eval(value, context));
105+
valueColumns.add(addingStartIndex + (valueColumns.size() - baseValueColumnSize), eval(value, context));
58106
}
59107
return formatSql(sqlTemplate, columns, headerColumns, valueColumns);
60108
}

src/main/java/com/example/tools/SqlBulkCommandsApplicationRunner.java

Lines changed: 64 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,12 @@ public void run(ApplicationArguments args) throws IOException {
7171
System.out.println(" - id");
7272
System.out.println(" - vendor_id");
7373
System.out.println(" - amount");
74+
System.out.println(" --first");
75+
System.out.println(" indicate that adding column at first position");
76+
System.out.println(" --after-by-name");
77+
System.out.println(" indicate that adding column at after specified column name");
78+
System.out.println(" --after-by-position");
79+
System.out.println(" indicate that adding column at after specified column position");
7480
System.out.println(" --h (--help)");
7581
System.out.println(" print help");
7682
System.out.println();
@@ -91,6 +97,28 @@ public void run(ApplicationArguments args) throws IOException {
9197
System.out.println(" insert into xxxx (a,b,c) values ('123',1,'123');");
9298
System.out.println(" ------------------------");
9399
System.out.println();
100+
System.out.println(
101+
" e.g.) --command=adding-columns --dir=src/test/resources/data --files=xxx.sql,yyy.sql --column-names=d,e --column-values=1,#a --first");
102+
System.out.println(" ------------------------");
103+
System.out.println(" insert into xxxx (a,b,c) values('123','1','2');");
104+
System.out.println(" ------------------------");
105+
System.out.println(" ↓");
106+
System.out.println(" ------------------------");
107+
System.out.println(" insert into xxxx (d,e,a,b,c) values (1,'123','123','1','2');");
108+
System.out.println(" ------------------------");
109+
System.out.println();
110+
System.out.println(
111+
" e.g.) --command=adding-columns --dir=src/test/resources/data --files=xxx.sql,yyy.sql --column-names=d,e --column-values=1,#a --after-by-name=a");
112+
System.out.println(
113+
" --command=adding-columns --dir=src/test/resources/data --files=xxx.sql,yyy.sql --column-names=d,e --column-values=1,#a --after-by-position=1");
114+
System.out.println(" ------------------------");
115+
System.out.println(" insert into xxxx (a,b,c) values('123','1','2');");
116+
System.out.println(" ------------------------");
117+
System.out.println(" ↓");
118+
System.out.println(" ------------------------");
119+
System.out.println(" insert into xxxx (a,d,e,b,c) values ('123',1,'123','1','2');");
120+
System.out.println(" ------------------------");
121+
System.out.println();
94122
System.out.println("[Usage: deleting-columns]");
95123
System.out.println(" Deleting specified existing column using column-names(or column-positions).");
96124
System.out.println(
@@ -106,7 +134,8 @@ public void run(ApplicationArguments args) throws IOException {
106134
System.out.println(" ------------------------");
107135
System.out.println();
108136
System.out.println("[Usage: updating-columns]");
109-
System.out.println(" Updating value specified existing column using column-names(or column-positions) and column-values.");
137+
System.out.println(
138+
" Updating value specified existing column using column-names(or column-positions) and column-values.");
110139
System.out.println(
111140
" e.g.) --command=updating-columns --dir=src/test/resources/data --files=xxx.sql,yyy.sql --column-names=b --column-values=NULL");
112141
System.out.println(
@@ -221,17 +250,44 @@ public void run(ApplicationArguments args) throws IOException {
221250
tableDefinitions = Collections.emptyMap();
222251
}
223252

253+
final String addingMethod;
254+
final String addingTarget;
255+
if (args.containsOption("first")) {
256+
addingMethod = "first";
257+
addingTarget = null;
258+
} else if (args.containsOption("after-by-name")) {
259+
addingMethod = "after-by-name";
260+
addingTarget = args.getOptionValues("after-by-name").stream().findFirst().orElse(null);
261+
if (addingTarget == null) {
262+
this.exitCode = 2;
263+
LOGGER.warn("'after-by-name' is required.");
264+
return;
265+
}
266+
} else if (args.containsOption("after-by-position")) {
267+
addingMethod = "after-by-position";
268+
addingTarget = args.getOptionValues("after-by-position").stream().findFirst().orElse(null);
269+
if (addingTarget == null) {
270+
this.exitCode = 2;
271+
LOGGER.warn("'after-by-position' is required.");
272+
return;
273+
}
274+
} else {
275+
addingMethod = "last";
276+
addingTarget = null;
277+
}
278+
224279
LOGGER.info(
225-
"Start. command:{} dir:{} files:{} encoding:{} column-names:{} column-positions:{} column-values:{} value-mappings:{} table-definitions:{}",
226-
command, dir, files, encoding, columnNames, columnPositions, columnValues, valueMappings, tableDefinitions);
280+
"Start. command:{} dir:{} files:{} encoding:{} column-names:{} column-positions:{} column-values:{} value-mappings:{} table-definitions:{} adding-type:{} adding-target:{}",
281+
command, dir, files, encoding, columnNames, columnPositions, columnValues, valueMappings, tableDefinitions,
282+
addingMethod, addingTarget);
227283

228284
try {
229285
Files.walk(Paths.get(dir))
230286
.filter(Files::isRegularFile)
231287
.filter(file -> files.stream().anyMatch(x -> file.toString().replace('\\', '/').endsWith(x)))
232288
.sorted().forEach(
233289
file -> execute(command, columnNames, columnPositions, columnValues, file, encoding, valueMappings,
234-
tableDefinitions));
290+
tableDefinitions, addingMethod, addingTarget));
235291
}
236292
catch (IllegalArgumentException e) {
237293
this.exitCode = 2;
@@ -245,7 +301,8 @@ public void run(ApplicationArguments args) throws IOException {
245301
private void execute(String command, List<String> columnNames, List<Integer> columnPositions,
246302
List<String> columnValues,
247303
Path file, Charset encoding,
248-
Map<String, Object> valueMappings, Map<String, Object> tableDefinitions) {
304+
Map<String, Object> valueMappings, Map<String, Object> tableDefinitions, String addingMethod,
305+
String addingTarget) {
249306
LOGGER.info("processing file:{}", file);
250307
switch (command) {
251308
case "adding-columns":
@@ -255,7 +312,8 @@ private void execute(String command, List<String> columnNames, List<Integer> col
255312
if (columnNames.size() != columnValues.size()) {
256313
throw new IllegalArgumentException("'column-names' and 'column-values' should be same size.");
257314
}
258-
AddingColumnProcessor.INSTANCE.execute(columnNames, columnPositions, columnValues, file, encoding, valueMappings,
315+
AddingColumnProcessor.INSTANCE.execute(addingMethod, addingTarget, columnNames, columnPositions, columnValues,
316+
file, encoding, valueMappings,
259317
tableDefinitions);
260318
break;
261319
case "deleting-columns":

src/test/java/com/example/tools/SqlBulkCommandsApplicationRunnerTests.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,42 @@ void addingColumns2() throws IOException {
2626
runner.run(new DefaultApplicationArguments(args));
2727
}
2828

29+
@Test
30+
void addingColumns3() throws IOException {
31+
String[] args = { "--command=adding-columns", "--files=m.sql", "--column-names=d",
32+
"--column-values='0'",
33+
"--first",
34+
"--dir=target/test-classes/data" };
35+
runner.run(new DefaultApplicationArguments(args));
36+
}
37+
38+
@Test
39+
void addingColumns4() throws IOException {
40+
String[] args = { "--command=adding-columns", "--files=n.sql", "--column-names=d",
41+
"--column-values='0'",
42+
"--after-by-name=b",
43+
"--dir=target/test-classes/data" };
44+
runner.run(new DefaultApplicationArguments(args));
45+
}
46+
47+
@Test
48+
void addingColumns5() throws IOException {
49+
String[] args = { "--command=adding-columns", "--files=o.sql", "--column-names=d",
50+
"--column-values='0'",
51+
"--after-by-position=2",
52+
"--dir=target/test-classes/data" };
53+
runner.run(new DefaultApplicationArguments(args));
54+
}
55+
56+
@Test
57+
void addingColumns6() throws IOException {
58+
String[] args = { "--command=adding-columns", "--files=p.sql", "--column-names=d",
59+
"--column-values='0'",
60+
"--after-by-position=3",
61+
"--dir=target/test-classes/data" };
62+
runner.run(new DefaultApplicationArguments(args));
63+
}
64+
2965
@Test
3066
void addingColumnsWithIndexedRef() throws IOException {
3167
String[] args = { "--command=adding-columns", "--files=c.sql", "--column-names=d",

src/test/resources/data/m.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
INSERT INTO xxxx VALUES ('10',1,null);
2+
INSERT INTO xxxx (a,b,c) VALUES ('20',2,NULL);

src/test/resources/data/n.sql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
INSERT INTO xxxx (a,b,c) VALUES ('20',2,NULL);

src/test/resources/data/o.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
INSERT INTO xxxx VALUES ('10',1,null);
2+
INSERT INTO xxxx (a,b,c) VALUES ('20',2,NULL);

src/test/resources/data/p.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
INSERT INTO xxxx VALUES ('10',1,null);
2+
INSERT INTO xxxx (a,b,c) VALUES ('20',2,NULL);

0 commit comments

Comments
 (0)