├── .gitignore
├── README.md
├── nb-configuration.xml
├── pom.xml
└── src
├── main
└── java
│ └── kis
│ └── sqlparser
│ ├── App.java
│ ├── Column.java
│ ├── Context.java
│ ├── Index.java
│ ├── ModifiedTuple.java
│ ├── ObjectPatternMatch.java
│ ├── Pair.java
│ ├── Schema.java
│ ├── SqlAnalizer.java
│ ├── SqlParser.java
│ ├── StreamUtils.java
│ ├── Table.java
│ └── Transaction.java
└── test
└── java
└── kis
└── sqlparser
├── AppTest.java
├── IndexTest.java
├── SqlAnalizerTest.java
├── SqlParserTest.java
└── StreamUtilsTest.java
/.gitignore:
--------------------------------------------------------------------------------
1 | /target/
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | sqlparser
2 | =========
3 |
4 | tiny sql parser
5 |
6 | execute kis.sqlparser.SqlAnalizer
7 |
8 | Table tshohin = new Table("shohin", Stream.of("id", "name", "bunrui_id", "price")
9 | .map(s -> new Column(s)).collect(Collectors.toList()));
10 | Table tbunrui = new Table("bunrui", Stream.of("id", "name", "seisen")
11 | .map(s -> new Column(s)).collect(Collectors.toList()));
12 | tbunrui
13 | .insert(1, "野菜", 1)
14 | .insert(2, "くだもの", 1)
15 | .insert(3, "菓子", 2);
16 | tshohin
17 | .insert(1, "りんご", 2, 250)
18 | .insert(2, "キャベツ", 1, 200)
19 | .insert(3, "たけのこの", 3, 150)
20 | .insert(4, "きのこ", 3, 120)
21 | .insert(5, "パソコン", 0, 34800);
22 |
23 | result
24 |
25 | select id, name from shohin where price between 130 and 200 or id=1
26 | 初期プラン:select
27 | <- filter[between shohin.price:130:200 or shohin.id = 1]
28 | <- table[shohin]
29 | 論理最適化:select
30 | <- filter[between shohin.price:130:200 or shohin.id = 1]
31 | <- table[shohin]
32 | [1,りんご]
33 | [2,キャベツ]
34 | [3,たけのこの]
35 |
36 | select id, name from shohin where price between 130 and 200
37 | 初期プラン:select
38 | <- filter[between shohin.price:130:200]
39 | <- table[shohin]
40 | 論理最適化:select
41 | <- filter[between shohin.price:130:200]
42 | <- table[shohin]
43 | [2,キャベツ]
44 | [3,たけのこの]
45 |
46 | 普通のJOIN
47 | select shohin.id, shohin.name,bunrui.name
48 | from shohin left join bunrui on shohin.bunrui_id=bunrui.id
49 | 初期プラン:select
50 | <- join(nested loop)
51 | <- table[shohin]
52 | /
53 | <- table[bunrui]
54 | 論理最適化:select
55 | <- join(nested loop)
56 | <- table[shohin]
57 | /
58 | <- table[bunrui]
59 | [1,りんご,くだもの]
60 | [2,キャベツ,野菜]
61 | [3,たけのこの,菓子]
62 | [4,きのこ,菓子]
63 | [5,パソコン,null]
64 |
65 | optimize
66 |
67 | 常に真なので条件省略
68 | select id, name from shohin where 2 < 3
69 | 初期プラン:select
70 | <- filter[2 < 3]
71 | <- table[shohin]
72 | 論理最適化:select
73 | <- table[shohin]
74 | [1,りんご]
75 | [2,キャベツ]
76 | [3,たけのこの]
77 | [4,きのこ]
78 | [5,パソコン]
79 |
80 | 常に偽なので空になる
81 | select id, name from shohin where price < 130 and 2 > 3
82 | 初期プラン:select
83 | <- filter[shohin.price < 130 and 2 > 3]
84 | <- table[shohin]
85 | 論理最適化:select
86 | <- empty
87 | <- table[shohin]
88 |
89 | メインテーブルのみに関係のある条件はJOINの前に適用
90 | select shohin.id, shohin.name,bunrui.name
91 | from shohin left join bunrui on shohin.bunrui_id=bunrui.id
92 | where shohin.price <= 300 and bunrui.seisen=1
93 | 初期プラン:select
94 | <- filter[shohin.price <= 300 and bunrui.seisen = 1]
95 | <- join(nested loop)
96 | <- table[shohin]
97 | /
98 | <- table[bunrui]
99 | 論理最適化:select
100 | <- filter[bunrui.seisen = 1]
101 | <- join(nested loop)
102 | <- filter[shohin.price <= 300]
103 | <- table[shohin]
104 | /
105 | <- table[bunrui]
106 | [1,りんご,くだもの]
107 | [2,キャベツ,野菜]
108 |
109 |
110 |
--------------------------------------------------------------------------------
/nb-configuration.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
16 | JDK_1.8
17 |
18 |
19 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | kis
6 | sqlparser
7 | 1.0-SNAPSHOT
8 | jar
9 |
10 | sqlparser
11 | http://maven.apache.org
12 |
13 |
14 |
15 | org.apache.maven.plugins
16 | maven-compiler-plugin
17 | 2.3.2
18 |
19 | 1.8
20 | 1.8
21 |
22 |
23 |
24 |
25 |
26 | UTF-8
27 |
28 |
29 |
30 |
31 | junit
32 | junit
33 | 4.13.1
34 | test
35 |
36 |
37 | jparsec
38 | jparsec
39 | 2.0.1
40 |
41 |
42 | org.projectlombok
43 | lombok
44 | 1.12.2
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/src/main/java/kis/sqlparser/App.java:
--------------------------------------------------------------------------------
1 | package kis.sqlparser;
2 |
3 | /**
4 | * Hello world!
5 | *
6 | */
7 | public class App
8 | {
9 | public static void main( String[] args )
10 | {
11 | System.out.println( "Hello World!" );
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/kis/sqlparser/Column.java:
--------------------------------------------------------------------------------
1 | /*
2 | * To change this license header, choose License Headers in Project Properties.
3 | * To change this template file, choose Tools | Templates
4 | * and open the template in the editor.
5 | */
6 |
7 | package kis.sqlparser;
8 |
9 | import java.util.Optional;
10 | import lombok.AllArgsConstructor;
11 | import lombok.EqualsAndHashCode;
12 | import lombok.ToString;
13 |
14 | /**
15 | *
16 | * @author naoki
17 | */
18 | @AllArgsConstructor
19 | @EqualsAndHashCode
20 | @ToString
21 | public class Column {
22 | Optional
parent;
23 | String name;
24 |
25 | public Column(Table parent, String name){
26 | this(Optional.ofNullable(parent), name);
27 | }
28 |
29 | public Column(String name){
30 | this(Optional.empty(), name);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/java/kis/sqlparser/Context.java:
--------------------------------------------------------------------------------
1 | /*
2 | * To change this license header, choose License Headers in Project Properties.
3 | * To change this template file, choose Tools | Templates
4 | * and open the template in the editor.
5 | */
6 |
7 | package kis.sqlparser;
8 |
9 | import java.util.Optional;
10 | import java.util.function.Consumer;
11 | import kis.sqlparser.SqlAnalizer.Records;
12 | import kis.sqlparser.Table.Tuple;
13 |
14 | /**
15 | *
16 | * @author naoki
17 | */
18 | public class Context {
19 | Schema schema;
20 | Optional currentTx;
21 |
22 | public Context(Schema schema) {
23 | this.schema = schema;
24 | currentTx = Optional.empty();
25 | }
26 |
27 | public Records exec(String sql){
28 | return SqlAnalizer.exec(this, sql);
29 | }
30 |
31 | public void begin(){
32 | if(currentTx.isPresent()){
33 | throw new RuntimeException("transaction already exist.");
34 | }
35 | currentTx = Optional.of(schema.createTransaction());
36 | }
37 | public void commit(){
38 | currentTx.orElseThrow(() -> new RuntimeException("transaciton does not begin"))
39 | .commit();
40 | end();
41 | }
42 | public void abort(){
43 | currentTx.orElseThrow(() -> new RuntimeException("transaciton does not begin"))
44 | .abort();
45 | end();
46 | }
47 | void end(){
48 | currentTx = Optional.empty();
49 | }
50 |
51 | public void withTx(Consumer cons){
52 | Transaction tx = currentTx.orElseGet(() -> schema.createTransaction());
53 | if(!tx.enable){
54 | throw new RuntimeException("transaction is not enabled.");
55 | }
56 | cons.accept(tx);
57 |
58 | if(!currentTx.isPresent()){
59 | tx.commit();
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/kis/sqlparser/Index.java:
--------------------------------------------------------------------------------
1 | /*
2 | * To change this license header, choose License Headers in Project Properties.
3 | * To change this template file, choose Tools | Templates
4 | * and open the template in the editor.
5 | */
6 |
7 | package kis.sqlparser;
8 |
9 | import java.util.ArrayList;
10 | import java.util.Collections;
11 | import java.util.Iterator;
12 | import java.util.LinkedHashMap;
13 | import java.util.List;
14 | import java.util.Map;
15 | import java.util.Optional;
16 | import java.util.SortedMap;
17 | import java.util.TreeMap;
18 | import kis.sqlparser.Table.Tuple;
19 | import lombok.AllArgsConstructor;
20 |
21 | /**
22 | *
23 | * @author naoki
24 | */
25 | @AllArgsConstructor
26 | public abstract class Index {
27 |
28 | public Map