nebius/SWE-bench-extra huggingface dataset:
Repository: reata/sqllineage

Issue:
Incorrect Result for UPDATE statement
hello reata.when i using sqllineage to analyze the follow SQL .I got a bug.
`UPDATE tablea a
	INNER JOIN (
		SELECT col2
		FROM tableb
		GROUP BY col
	) b
	ON b.col = a.col
SET a.col1 = a.col2 * b.col2
`
that SQL update tablea`s col1  using tableb`s col2 . when i running the SQLLINGAGE it returns tableb as source table but null as target table .in my view the source table should be tableb and the target table should be tablea but not null

Comments:

Patch:
diff --git a/sqllineage/core.py b/sqllineage/core.py
index f46ba1d..5d34b6b 100644
--- a/sqllineage/core.py
+++ b/sqllineage/core.py
@@ -20,7 +20,7 @@ SOURCE_TABLE_TOKENS = (
     # inspired by https://github.com/andialbrecht/sqlparse/blob/master/sqlparse/keywords.py
     r"((LEFT\s+|RIGHT\s+|FULL\s+)?(INNER\s+|OUTER\s+|STRAIGHT\s+)?|(CROSS\s+|NATURAL\s+)?)?JOIN",
 )
-TARGET_TABLE_TOKENS = ("INTO", "OVERWRITE", "TABLE", "VIEW")
+TARGET_TABLE_TOKENS = ("INTO", "OVERWRITE", "TABLE", "VIEW", "UPDATE")
 TEMP_TABLE_TOKENS = ("WITH",)
 
 


Test patch:
diff --git a/tests/test_others.py b/tests/test_others.py
index afe8852..93233dc 100644
--- a/tests/test_others.py
+++ b/tests/test_others.py
@@ -45,6 +45,18 @@ def test_create_after_drop():
     )
 
 
+def test_update():
+    helper("UPDATE tab1 SET col1='val1' WHERE col2='val2'", None, {"tab1"})
+
+
+def test_update_with_join():
+    helper(
+        "UPDATE tab1 a INNER JOIN tab2 b ON a.col1=b.col1 SET a.col2=b.col2",
+        {"tab2"},
+        {"tab1"},
+    )
+
+
 def test_drop():
     helper("DROP TABLE IF EXISTS tab1", None, None)
Repository: reata/sqllineage

Issue:
subquery mistake alias as table name
```
$ python -m sqllineage.core -e "SELECT col1 FROM (SELECT col2 from tab1) dt"
Statements(#): 1
Source Tables:
    dt
Target Tables:

```

expect source table as tab1

Comments:

Patch:
diff --git a/sqllineage/core.py b/sqllineage/core.py
index 301c818..2f5e0b6 100644
--- a/sqllineage/core.py
+++ b/sqllineage/core.py
@@ -3,7 +3,7 @@ import sys
 from typing import List, Set
 
 import sqlparse
-from sqlparse.sql import Function, Identifier, IdentifierList, Statement, TokenList
+from sqlparse.sql import Function, Identifier, Parenthesis, Statement, TokenList
 from sqlparse.tokens import Keyword, Token, Whitespace
 
 SOURCE_TABLE_TOKENS = ('FROM', 'JOIN', 'INNER JOIN', 'LEFT JOIN', 'RIGHT JOIN', 'LEFT OUTER JOIN', 'RIGHT OUTER JOIN',
@@ -51,11 +51,9 @@ Target Tables:
         return self._target_tables
 
     def _extract_from_token(self, token: Token):
-        if not isinstance(token, TokenList):
-            return
         source_table_token_flag = target_table_token_flag = temp_table_token_flag = False
         for sub_token in token.tokens:
-            if isinstance(token, TokenList) and not isinstance(sub_token, (Identifier, IdentifierList)):
+            if isinstance(sub_token, TokenList):
                 self._extract_from_token(sub_token)
             if sub_token.ttype in Keyword:
                 if sub_token.normalized in SOURCE_TABLE_TOKENS:
@@ -75,7 +73,13 @@ Target Tables:
                     continue
                 else:
                     assert isinstance(sub_token, Identifier)
-                    self._source_tables.add(sub_token.get_real_name())
+                    if isinstance(sub_token.token_first(), Parenthesis):
+                        # SELECT col1 FROM (SELECT col2 FROM tab1) dt, the subquery will be parsed as Identifier
+                        # and this Identifier's get_real_name method would return alias name dt
+                        # referring https://github.com/andialbrecht/sqlparse/issues/218 for further information
+                        pass
+                    else:
+                        self._source_tables.add(sub_token.get_real_name())
                     source_table_token_flag = False
             elif target_table_token_flag:
                 if sub_token.ttype == Whitespace:


Test patch:
diff --git a/tests/test_select.py b/tests/test_select.py
index cea96ef..49fe323 100644
--- a/tests/test_select.py
+++ b/tests/test_select.py
@@ -40,6 +40,10 @@ def test_select_count():
     helper("SELECT COUNT(*) FROM tab1", {"tab1"})
 
 
+def test_select_subquery():
+    helper("SELECT col1 FROM (SELECT col2 FROM tab1) dt", {"tab1"})
+
+
 def test_select_inner_join():
     helper("SELECT * FROM tab1 INNER JOIN tab2", {"tab1", "tab2"})
Repository: reata/sqllineage

Issue:
multi-line sql causes AssertionError
```sql
SELECT * FROM
tab1
```
causes following exception

Traceback (most recent call last):
  File "/home/admin/.pyenv/versions/3.6.8/lib/python3.6/runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "/home/admin/.pyenv/versions/3.6.8/lib/python3.6/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "/home/admin/repos/sqllineage/sqllineage/core.py", line 131, in <module>
    main()
  File "/home/admin/repos/sqllineage/sqllineage/core.py", line 119, in main
    print(LineageParser(sql))
  File "/home/admin/repos/sqllineage/sqllineage/core.py", line 23, in __init__
    self._extract_from_token(stmt)
  File "/home/admin/repos/sqllineage/sqllineage/core.py", line 75, in _extract_from_token
    assert isinstance(sub_token, Identifier)
AssertionError

Comments:

Patch:
diff --git a/sqllineage/core.py b/sqllineage/core.py
index 2f5e0b6..fbf17f2 100644
--- a/sqllineage/core.py
+++ b/sqllineage/core.py
@@ -4,7 +4,7 @@ from typing import List, Set
 
 import sqlparse
 from sqlparse.sql import Function, Identifier, Parenthesis, Statement, TokenList
-from sqlparse.tokens import Keyword, Token, Whitespace
+from sqlparse.tokens import Keyword, Token
 
 SOURCE_TABLE_TOKENS = ('FROM', 'JOIN', 'INNER JOIN', 'LEFT JOIN', 'RIGHT JOIN', 'LEFT OUTER JOIN', 'RIGHT OUTER JOIN',
                        'FULL OUTER JOIN', 'CROSS JOIN')
@@ -69,7 +69,7 @@ Target Tables:
                 self._target_tables.add(sub_token.get_alias())
                 continue
             if source_table_token_flag:
-                if sub_token.ttype == Whitespace:
+                if sub_token.is_whitespace:
                     continue
                 else:
                     assert isinstance(sub_token, Identifier)
@@ -82,7 +82,7 @@ Target Tables:
                         self._source_tables.add(sub_token.get_real_name())
                     source_table_token_flag = False
             elif target_table_token_flag:
-                if sub_token.ttype == Whitespace:
+                if sub_token.is_whitespace:
                     continue
                 elif isinstance(sub_token, Function):
                     # insert into tab (col1, col2), tab (col1, col2) will be parsed as Function
@@ -95,7 +95,7 @@ Target Tables:
                     self._target_tables.add(sub_token.get_real_name())
                     target_table_token_flag = False
             elif temp_table_token_flag:
-                if sub_token.ttype == Whitespace:
+                if sub_token.is_whitespace:
                     continue
                 else:
                     assert isinstance(sub_token, Identifier)


Test patch:
diff --git a/tests/test_select.py b/tests/test_select.py
index 49fe323..8837091 100644
--- a/tests/test_select.py
+++ b/tests/test_select.py
@@ -5,6 +5,11 @@ def test_select():
     helper("SELECT col1 FROM tab1", {"tab1"})
 
 
+def test_select_multi_line():
+    helper("""SELECT col1 FROM
+tab1""", {"tab1"})
+
+
 def test_select_asterisk():
     helper("SELECT * FROM tab1", {"tab1"})
Repository: reata/sqllineage

Issue:
drop table parsed as target table
```
$ sqllineage -e "DROP TABLE IF EXISTS tab1"
Statements(#): 1
Source Tables:
    
Target Tables:
    tab1
```

expect:
When a table is in target_tables, dropping table result in a removal from target_tables. Otherwise  the DROP DML doesn't affect the result.

Comments:

Patch:
diff --git a/sqllineage/core.py b/sqllineage/core.py
index fbf17f2..74c178d 100644
--- a/sqllineage/core.py
+++ b/sqllineage/core.py
@@ -4,7 +4,7 @@ from typing import List, Set
 
 import sqlparse
 from sqlparse.sql import Function, Identifier, Parenthesis, Statement, TokenList
-from sqlparse.tokens import Keyword, Token
+from sqlparse.tokens import DDL, Keyword, Token
 
 SOURCE_TABLE_TOKENS = ('FROM', 'JOIN', 'INNER JOIN', 'LEFT JOIN', 'RIGHT JOIN', 'LEFT OUTER JOIN', 'RIGHT OUTER JOIN',
                        'FULL OUTER JOIN', 'CROSS JOIN')
@@ -20,7 +20,10 @@ class LineageParser(object):
         self._target_tables = set()
         self._stmt = sqlparse.parse(sql, self._encoding)
         for stmt in self._stmt:
-            self._extract_from_token(stmt)
+            if stmt.token_first().ttype == DDL and stmt.token_first().normalized == "DROP":
+                self._target_tables -= {t.get_real_name() for t in stmt.tokens if isinstance(t, Identifier)}
+            else:
+                self._extract_from_token(stmt)
         self._tmp_tables = self._source_tables.intersection(self._target_tables)
         self._source_tables -= self._tmp_tables
         self._target_tables -= self._tmp_tables


Test patch:
diff --git a/tests/test_others.py b/tests/test_others.py
index a6f8472..6fc57c9 100644
--- a/tests/test_others.py
+++ b/tests/test_others.py
@@ -6,6 +6,26 @@ def test_use():
     helper("USE db1")
 
 
+def test_create():
+    helper("CREATE TABLE tab1 (col1 STRING)", None, {"tab1"})
+
+
+def test_create_if_not_exist():
+    helper("CREATE TABLE IF NOT EXISTS tab1 (col1 STRING)", None, {"tab1"})
+
+
+def test_create_after_drop():
+    helper("DROP TABLE IF EXISTS tab1; CREATE TABLE IF NOT EXISTS tab1 (col1 STRING)", None, {"tab1"})
+
+
+def test_drop():
+    helper("DROP TABLE IF EXISTS tab1", None, None)
+
+
+def test_drop_after_create():
+    helper("CREATE TABLE IF NOT EXISTS tab1 (col1 STRING);DROP TABLE IF EXISTS tab1", None, None)
+
+
 def test_create_select():
     helper("CREATE TABLE tab1 SELECT * FROM tab2", {"tab2"}, {"tab1"})
Repository: reata/sqllineage

Issue:
Empty Statement return
take the following sql as example

```sql
SELECT 1;

-- SELECT 2;
```

the parsing result says that it contains two statements, instead of one.

Comments:

Patch:
diff --git a/sqllineage/core.py b/sqllineage/core.py
index 2faa914..fbfff54 100644
--- a/sqllineage/core.py
+++ b/sqllineage/core.py
@@ -18,7 +18,7 @@ class LineageParser(object):
         self._encoding = encoding
         self._source_tables = set()
         self._target_tables = set()
-        self._stmt = sqlparse.parse(sql.strip(), self._encoding)
+        self._stmt = [s for s in sqlparse.parse(sql.strip(), self._encoding) if s.get_type() != "UNKNOWN"]
         for stmt in self._stmt:
             if stmt.get_type() == "DROP":
                 self._target_tables -= {t.get_real_name() for t in stmt.tokens if isinstance(t, Identifier)}


Test patch:
diff --git a/tests/test_others.py b/tests/test_others.py
index 7e0a287..9a0b89f 100644
--- a/tests/test_others.py
+++ b/tests/test_others.py
@@ -43,3 +43,10 @@ def test_split_statements():
 def test_split_statements_with_heading_and_ending_new_line():
     sql = "\nSELECT * FROM tab1;\nSELECT * FROM tab2;\n"
     assert len(LineageParser(sql).statements) == 2
+
+
+def test_split_statements_with_comment():
+    sql = """SELECT 1;
+
+-- SELECT 2;"""
+    assert len(LineageParser(sql).statements) == 1
Repository: reata/sqllineage

Issue:
Empty Statement return
take the following sql as example

```sql
SELECT 1;

-- SELECT 2;
```

the parsing result says that it contains two statements, instead of one.

Comments:

Patch:
diff --git a/sqllineage/core.py b/sqllineage/core.py
index fbfff54..231aa26 100644
--- a/sqllineage/core.py
+++ b/sqllineage/core.py
@@ -18,7 +18,7 @@ class LineageParser(object):
         self._encoding = encoding
         self._source_tables = set()
         self._target_tables = set()
-        self._stmt = [s for s in sqlparse.parse(sql.strip(), self._encoding) if s.get_type() != "UNKNOWN"]
+        self._stmt = [s for s in sqlparse.parse(sql.strip(), self._encoding) if s.token_first(skip_cm=True)]
         for stmt in self._stmt:
             if stmt.get_type() == "DROP":
                 self._target_tables -= {t.get_real_name() for t in stmt.tokens if isinstance(t, Identifier)}


Test patch:
diff --git a/tests/test_others.py b/tests/test_others.py
index 9a0b89f..ddc0c30 100644
--- a/tests/test_others.py
+++ b/tests/test_others.py
@@ -50,3 +50,17 @@ def test_split_statements_with_comment():
 
 -- SELECT 2;"""
     assert len(LineageParser(sql).statements) == 1
+
+
+def test_split_statements_with_show_create_table():
+    sql = """SELECT 1;
+
+SHOW CREATE TABLE tab1;"""
+    assert len(LineageParser(sql).statements) == 2
+
+
+def test_split_statements_with_desc():
+    sql = """SELECT 1;
+
+DESC tab1;"""
+    assert len(LineageParser(sql).statements) == 2
Repository: reata/sqllineage

Issue:
white space in left join
```sql
select * from tab_a
left  join tab_b
on tab_a.x = tab_b.x
```
an extra whitespace in "left  join" make tab_b undetectable.

Comments:

Patch:
diff --git a/sqllineage/core.py b/sqllineage/core.py
index 5b010e2..0d7c505 100644
--- a/sqllineage/core.py
+++ b/sqllineage/core.py
@@ -1,4 +1,5 @@
 import argparse
+import re
 import sys
 from typing import List, Set
 
@@ -6,8 +7,9 @@ import sqlparse
 from sqlparse.sql import Comment, Function, Identifier, Parenthesis, Statement, TokenList
 from sqlparse.tokens import Keyword, Token
 
-SOURCE_TABLE_TOKENS = ('FROM', 'JOIN', 'INNER JOIN', 'LEFT JOIN', 'RIGHT JOIN', 'LEFT OUTER JOIN', 'RIGHT OUTER JOIN',
-                       'FULL OUTER JOIN', 'CROSS JOIN')
+SOURCE_TABLE_TOKENS = (r'FROM',
+                       # inspired by https://github.com/andialbrecht/sqlparse/blob/master/sqlparse/keywords.py
+                       r'((LEFT\s+|RIGHT\s+|FULL\s+)?(INNER\s+|OUTER\s+|STRAIGHT\s+)?|(CROSS\s+|NATURAL\s+)?)?JOIN')
 TARGET_TABLE_TOKENS = ('INTO', 'OVERWRITE', 'TABLE')
 TEMP_TABLE_TOKENS = ('WITH',)
 
@@ -59,7 +61,7 @@ Target Tables:
             if isinstance(sub_token, TokenList):
                 self._extract_from_token(sub_token)
             if sub_token.ttype in Keyword:
-                if sub_token.normalized in SOURCE_TABLE_TOKENS:
+                if any(re.match(regex, sub_token.normalized) for regex in SOURCE_TABLE_TOKENS):
                     source_table_token_flag = True
                 elif sub_token.normalized in TARGET_TABLE_TOKENS:
                     target_table_token_flag = True


Test patch:
diff --git a/tests/test_select.py b/tests/test_select.py
index 69b6133..8f31412 100644
--- a/tests/test_select.py
+++ b/tests/test_select.py
@@ -69,6 +69,10 @@ def test_select_left_join():
     helper("SELECT * FROM tab1 LEFT JOIN tab2", {"tab1", "tab2"})
 
 
+def test_select_left_join_with_extra_space_in_middle():
+    helper("SELECT * FROM tab1 LEFT  JOIN tab2", {"tab1", "tab2"})
+
+
 def test_select_left_semi_join():
     helper("SELECT * FROM tab1 LEFT SEMI JOIN tab2", {"tab1", "tab2"})
Repository: reata/sqllineage

Issue:
Support Create Table Like Statement
```
drop table  if exists tab_a;
create table if not exists tab_a like tab_b;
```
drop before create, the result is tab_a exists after the above statements;


If we switch the order:
```
create table if not exists tab_a like tab_b;
drop table  if exists tab_a;
```
Although the above statements make no sense, still, we should output result as tab_a does not exist.

Under current circumstances, both cases will be that tab_a does not exists since tab_a is identified as temp table. This is related to #23 

Comments:

Patch:
diff --git a/sqllineage/core.py b/sqllineage/core.py
index a46e388..1d9a021 100644
--- a/sqllineage/core.py
+++ b/sqllineage/core.py
@@ -4,7 +4,7 @@ import sys
 from typing import List, Set
 
 import sqlparse
-from sqlparse.sql import Comment, Function, Identifier, Parenthesis, Statement, TokenList
+from sqlparse.sql import Comment, Comparison, Function, Identifier, Parenthesis, Statement, TokenList
 from sqlparse.tokens import Keyword, Token
 
 SOURCE_TABLE_TOKENS = (r'FROM',
@@ -95,11 +95,17 @@ Target Tables:
                     # referring https://github.com/andialbrecht/sqlparse/issues/483 for further information
                     assert isinstance(sub_token.token_first(skip_cm=True), Identifier)
                     self._target_tables.add(sub_token.token_first(skip_cm=True).get_real_name())
-                    target_table_token_flag = False
+                elif isinstance(sub_token, Comparison):
+                    # create table tab1 like tab2, tab1 like tab2 will be parsed as Comparison
+                    # referring https://github.com/andialbrecht/sqlparse/issues/543 for further information
+                    assert isinstance(sub_token.left, Identifier)
+                    assert isinstance(sub_token.right, Identifier)
+                    self._target_tables.add(sub_token.left.get_real_name())
+                    self._source_tables.add(sub_token.right.get_real_name())
                 else:
                     assert isinstance(sub_token, Identifier)
                     self._target_tables.add(sub_token.get_real_name())
-                    target_table_token_flag = False
+                target_table_token_flag = False
             elif temp_table_token_flag:
                 if self.__token_negligible_before_tablename(sub_token):
                     continue


Test patch:
diff --git a/tests/test_others.py b/tests/test_others.py
index eabb6d4..a9405c8 100644
--- a/tests/test_others.py
+++ b/tests/test_others.py
@@ -14,6 +14,14 @@ def test_create_if_not_exist():
     helper("CREATE TABLE IF NOT EXISTS tab1 (col1 STRING)", None, {"tab1"})
 
 
+def test_create_as():
+    helper("CREATE TABLE tab1 AS SELECT * FROM tab2", {"tab2"}, {"tab1"})
+
+
+def test_create_like():
+    helper("CREATE TABLE tab1 LIKE tab2", {"tab2"}, {"tab1"})
+
+
 def test_create_after_drop():
     helper("DROP TABLE IF EXISTS tab1; CREATE TABLE IF NOT EXISTS tab1 (col1 STRING)", None, {"tab1"})
Repository: reata/sqllineage

Issue:
case-sensitive parsing
```
insert overwrite table tab_a
select * from tab_b
union all
select * from TAB_B
```

here tab_b and TAB_B will be parsed as two different tables.

Comments:

Patch:
diff --git a/sqllineage/core.py b/sqllineage/core.py
index 059f40e..5ba4481 100644
--- a/sqllineage/core.py
+++ b/sqllineage/core.py
@@ -54,11 +54,11 @@ Target Tables:
 
     @property
     def source_tables(self) -> Set[str]:
-        return self._source_tables
+        return {t.lower() for t in self._source_tables}
 
     @property
     def target_tables(self) -> Set[str]:
-        return self._target_tables
+        return {t.lower() for t in self._target_tables}
 
     def _extract_from_DML(self, token: Token) -> None:
         source_table_token_flag = target_table_token_flag = temp_table_token_flag = False


Test patch:
diff --git a/tests/test_others.py b/tests/test_others.py
index 38956f1..f5f71f6 100644
--- a/tests/test_others.py
+++ b/tests/test_others.py
@@ -6,6 +6,13 @@ def test_use():
     helper("USE db1")
 
 
+def test_table_name_case():
+    helper("""insert overwrite table tab_a
+select * from tab_b
+union all
+select * from TAB_B""", {"tab_b"}, {"tab_a"})
+
+
 def test_create():
     helper("CREATE TABLE tab1 (col1 STRING)", None, {"tab1"})
Repository: reata/sqllineage

Issue:
Trim Leading Comment for Statement in Verbose Output
```
sqllineage -v -e "------------------------                    
dquote> select * from dual"
Statement #1: ------------------------select * from dual
table read: {Table: <unknown>.dual}
table write: {}
table rename: {}
table drop: {}
table with_: {}
==========
Summary:
Statements(#): 1
Source Tables:
    <unknown>.dual
Target Tables:
```

We should trim the leading comment line when showing statement.

Comments:

Patch:
diff --git a/sqllineage/runner.py b/sqllineage/runner.py
index 643bfc4..20705f7 100644
--- a/sqllineage/runner.py
+++ b/sqllineage/runner.py
@@ -29,7 +29,7 @@ class LineageRunner(object):
         self._verbose = verbose
 
     def __str__(self):
-        statements = self.statements
+        statements = self.statements(strip_comments=True)
         combined = """Statements(#): {stmt_cnt}
 Source Tables:
     {source_tables}
@@ -58,9 +58,8 @@ Target Tables:
     def statements_parsed(self) -> List[Statement]:
         return self._stmt
 
-    @property
-    def statements(self) -> List[str]:
-        return [sqlparse.format(s.value) for s in self.statements_parsed]
+    def statements(self, **kwargs) -> List[str]:
+        return [sqlparse.format(s.value, **kwargs) for s in self.statements_parsed]
 
     @property
     def source_tables(self) -> Set[Table]:


Test patch:
diff --git a/tests/test_others.py b/tests/test_others.py
index 863e1d0..2468ef5 100644
--- a/tests/test_others.py
+++ b/tests/test_others.py
@@ -101,30 +101,36 @@ def test_delete_from_table():
 
 def test_split_statements():
     sql = "SELECT * FROM tab1; SELECT * FROM tab2;"
-    assert len(LineageRunner(sql).statements) == 2
+    assert len(LineageRunner(sql).statements()) == 2
 
 
 def test_split_statements_with_heading_and_ending_new_line():
     sql = "\nSELECT * FROM tab1;\nSELECT * FROM tab2;\n"
-    assert len(LineageRunner(sql).statements) == 2
+    assert len(LineageRunner(sql).statements()) == 2
 
 
 def test_split_statements_with_comment():
     sql = """SELECT 1;
 
 -- SELECT 2;"""
-    assert len(LineageRunner(sql).statements) == 1
+    assert len(LineageRunner(sql).statements()) == 1
+
+
+def test_statements_trim_comment():
+    comment = "------------------\n"
+    sql = "select * from dual;"
+    assert LineageRunner(comment + sql).statements(strip_comments=True)[0] == sql
 
 
 def test_split_statements_with_show_create_table():
     sql = """SELECT 1;
 
 SHOW CREATE TABLE tab1;"""
-    assert len(LineageRunner(sql).statements) == 2
+    assert len(LineageRunner(sql).statements()) == 2
 
 
 def test_split_statements_with_desc():
     sql = """SELECT 1;
 
 DESC tab1;"""
-    assert len(LineageRunner(sql).statements) == 2
+    assert len(LineageRunner(sql).statements()) == 2
Repository: reata/sqllineage

Issue:
Refresh Table and Cache Table Should Not Count as Target Table
```
sqllineage -e "refresh table dual;" 
Statements(#): 1
Source Tables:
    
Target Tables:
    <unknown>.dual
```

Comments:

Patch:
diff --git a/sqllineage/core.py b/sqllineage/core.py
index 3657362..25f6751 100644
--- a/sqllineage/core.py
+++ b/sqllineage/core.py
@@ -70,6 +70,8 @@ class LineageAnalyzer:
         elif (
             stmt.get_type() == "DELETE"
             or stmt.token_first(skip_cm=True).normalized == "TRUNCATE"
+            or stmt.token_first(skip_cm=True).normalized.upper() == "REFRESH"
+            or stmt.token_first(skip_cm=True).normalized == "CACHE"
         ):
             pass
         else:


Test patch:
diff --git a/tests/test_others.py b/tests/test_others.py
index 2468ef5..afe8852 100644
--- a/tests/test_others.py
+++ b/tests/test_others.py
@@ -91,6 +91,14 @@ def test_alter_target_table_name():
     )
 
 
+def test_refresh_table():
+    helper("refresh table tab1", None, None)
+
+
+def test_cache_table():
+    helper("cache table tab1", None, None)
+
+
 def test_truncate_table():
     helper("truncate table tab1", None, None)