SQL 語句解析過程詳解

SQL 語句解析過程詳解:

1.輸入SQL語句

2.詞法分析------flex

????????使用詞法分析器(由Flex生成)將 SQL 語句分解為一個個單詞,這些單詞被稱為“標記“。標記包括關鍵字、標識符、運算符、分隔符等。

2.1 flex 原理

1、使用 flex 工具定義正則表達式規則來匹配不同類型的詞法單元;例如,可以定義以下規則:

  • 匹配關鍵字:SELECT、FROM、WHERE、HAVING等。
  • 匹配標識符:由字母或下劃線開頭,后跟字母、數字或下劃線組成。
  • 匹配運算符:比如=、<、>、+、等。
  • 匹配常量:包括整數、浮點數、字符串等。

2、生成詞法分析器代碼:根據定義的詞法規則,使用Flex工具生成對應的詞法分析器代碼;

3、輸入查詢字符串:將要解析的查詢字符串作為輸入提供給同法分析器;

4、掃描和匹配:詞法分析器從輸入字符串中逐個讀取字符,并嘗試將其與定義的詞法規則進行匹配;

5、生成詞法單元:當詞法分析器匹配到一個詞法規則時,它會生成相應的詞法單元并返回給語法分析器。每個詞法單元通常包含兩部分信息:

  • 詞法單元類型(token type):表示該詞法單元的種類,比如關鍵字、標識符、運算符等;
  • 詞法單元值(tokenvalue):表示該詞法單元具體的取值;

6、繼續掃描:詞法分析器會持續從輸入字符串中讀取字符,并重復步驟4和步驟5,直到整個查詢字符串被完全解析為一系列詞法單元;

7、返回詞法單元序列:當整個查詢字符串都被解析后,詞法分析器將返回一個包含所有詞法單元的序列給語法分析器,供后續的語法分析處理;

2.2 flex 文件代碼結構

2.2.1 flex 文件介紹

1、flex文件代碼

%option noyywrap
%{
definition
%}%%
rules
%%
Code

(1)%option 指定 flex 掃描時的一些特性。yywrap 通常在多文件掃描時定義使用。常用的一些選項有:

  • Noyywrap:告訴flex不使用yywrap函數;
  • yylineno:會告訴flex生成一個名為yylineno的整型變量來保存當前的行號;
  • case-insensitive 正則表達式規則大小寫無關;

(2)definitio部分為定義部分,包括引入頭文件,變量聲明,函數聲明,注釋等,這部分會被原樣拷貝到輸出的.c文件中。

(3)rules部分定義詞法規則,使用正則表達式定義詞法,后面{}內則是掃描到對應詞法時的動作代碼;“|”是一個特殊符號,表示下一個模式應用相同的動作;正則表達式后面不指定動作,則相應的模式會被忽略。

(4)code部分為C語言的代碼。yylex為flex的函數,使用yylex開始掃描。

2.2.2 flex 文件常用變量

(1)yytext:詞法分析程序當前識別到的一些詞素,與轉換規則部分中的某個模式相匹配;

(2)yylength:詞法分析程序當前識別到的詞素的長度;

(3)yylval:yylval是在bison中定義的聯合類型變量(union),因為Flex生成的詞法分析程序yylex()需要向bison生成的語法分析器返回識別到的詞法單元,所以需要使用yylval來保存詞法單元的屬性值;

2.2.3 正則表達式

.????????匹配除換行符”\n”以外的任何單個字符;*????????匹配前面表達式的零個或多個拷貝;[]???????匹配括號中任意字符的字符類,如果第一個字符是 “^”,則匹配除括號中的字符以外的任意字符;“-” 指示一個字符范圍,例如“[0-9]”和“[0123456789]”含義相同;除了以 “\” 開始的轉義序列,元字符在括號內沒有任何含義;^?????? 作為正則表達式的行首匹配行的開頭,也用于方括號中的否定;$? ? ? ?作為正則表達式的行尾匹配行的結尾;\? ? ? ? 用于轉義元字符,也作為常用的C轉義序列的一部分,例如”\n”表示換行,“\*” 表示非元字符的星號;+? ? ? ?匹配前面的正則表達式一次或多次出現;?? ? ? 匹配前面的正則表達式零次或一次出現;|??????? ?匹配前面的正則表達式或隨后的正則表達式;“…”??引號中的每個字符解釋為字面意義,除C轉義序列外元字符會失去其特殊含義;()??????將一系列正則表達式組成一個新的正則表達式,例如(01),表示字符序列 01;{}? ? ? 當括號中包含一個或兩個數字時,指示前面的模式允許被匹配多少次,例如{1,3}表示匹配字母一次到三次;

2.2.4 flex 文件具體案例

1、創建一個名為 lexer.l 的文件,其中包含詞法規則;

%{
#include <stdio.h>
%}%%
SELECT                  { printf("Keyword: SELECT\n"); }
FROM                    { printf("Keyword: FROM\n"); }
WHERE                   { printf("Keyword: WHERE\n"); }
AND                     { printf("Keyword: AND\n"); }
OR                      { printf("Keyword: OR\n"); }[0-9]+                  { printf("Number: %s\n", yytext); }[A-Za-z_][A-Za-z0-9_]*  { printf("Identifier: %s\n", yytext); }
[=><]+                  { printf("Operator: %s\n", yytext); }
[ \t\n]                 ; // Skip whitespace.                       { printf("Unknown: %s\n",yytext); }%%int main() {    yylex();   return 0;
}

2、使用 flex 命令編譯 lexer.l 文件,生成詞法分析器代碼?

(1)執行下列語句生成詞法分析器代碼

flex lexer.l

(2)詞法分析器生成結果

lex.yy.c

(3)編譯生成的詞法分析器代碼,生成可執行文件

gcc -o lexer lex.yy.c -lfl

(4)運行可執行文件并輸入一些算術表達式進行測試

./lexer輸入:SELECT * FROM table;

(5)執行結果如下

說明:

  • -ll: 這是舊版本的Flex生成器(例如Flex 2.5.4)的鏈接選項。它指示鏈接器將使用名為 libl.a 或 libl.so 的庫文件。在以前的版本中,Flex生成的詞法分析器的默認名稱是 lex.yy.c,而庫文件的名稱以 "l" 開頭,因此使用 -ll 是一種傳統的方式。
  • -lg: 這是新版本的Flex生成器(例如Flex 2.5.35)的鏈接選項。類似于舊版本的 -ll,它指示鏈接器使用名為 libg.a 或 libg.so 的庫文件。這種新方式是為了避免與其他工具和庫發生命名沖突。
  • -lfl: 這是一個與Flex生成的詞法分析器庫相關的選項。-lfl 表示鏈接器將使用名為 libfl.a 或 libfl.so 的庫文件。這個庫包含了Flex所需的運行時支持函數。

注意:

????????如果 flex 詞法分析器對 .l 進行編譯時報錯:

????????/opt/h/devtoolset-11/root/usr/ibexec/gcex86.64-redhat-linux/11/ld: cannot find -lfn

解決方案:

????????該錯誤表明鏈接器無法找到名為 -if 的庫文件。這通常是因為在您的系統上缺少libfl庫,或者庫文件的路徑未正確配置。要解決這個問題,您可以嘗試以下步驟:

1、確認庫是否已安裝:首先,請確保您的系統上已安裝了libfl庫。您可以嘗試使用包管理器來安裝它。在基于Red Hat的系統中,您可能需要執行類似于以下的命令:

yum install flex-devel

2、檢查庫文件路徑:如果庫已安裝,但鏈接器仍然找不到它,可能是因為庫文件的路徑未正確配置。您可以嘗試手動指定庫文件的路徑。例如,假設libfl庫文件位于/usr/lib64目錄下,您可以使用以下方式鏈接:

gcc -o my program lex.yy.c -L/usr/lib64 -1f1

3、更新庫文件緩存:如果您最近安裝了libfl庫,但鏈接器仍然找不到它,您可能需要更新庫文件緩存。運行以下命令以更新庫文件緩存:

sudo ldconfig

3.語法分析------bison

????????使用語法分析器(由 Bison 生成)根據語法規則進行語法分析,生成抽象語法樹。語法樹是一種樹形結構,它表示 SQL 語句的語法結構。語法分析器會檢查語法樹是否符合 SQL 語法規則,如果不符合,則會拋出語法錯誤。

3.1 bison原理

3.2 bison文件代碼結構

1、bison文件代碼

%{
// C 代碼和頭文件的聲明
#include <stdio.h>
// 在這里可以定義全局變量和函數等
%}
// Bison 的選項部分
%option verbose   		// 控制 Bison 解析器的詳細輸出// Bison 的聲明部分    
%token NAME       	    // 定義終結符或標記的名稱
%token NUMBER%left ‘+’ ‘-‘           // 定義運算符的優先級和結合性
%left ‘*’ ‘/’%{
// 在這里可以編寫更多的 C 代碼
%}// Bison 的規則部分%%
// 語法規則的定義
expression : expression '+' expression           | expression '-' expression           | expression '*' expression           | expression '/' expression           | '(' expression ')'           | NUMBER           ;
// 更多的語法規則...
%%// C 代碼部分(選項中的 %{ ... %} 和規則部分中的 %% 之間的部分)
// 在這里可以編寫與語法規則相關的 C 代碼
int main() {    yyparse();  // 調用 Bison 生成的解析函數    return 0;
}

? bison文件的書寫格式與flex文件的書寫格式基本一致,只是規則的定義語法不同。

3.3 規則語法介紹

(1)終結符(Terminals)

????????終結符是語法規則中的基本符號,通常是語言中的關鍵字、運算符、標識符等。可以使用%token來定義終結符。以下是一個示例:

%token NUMBER 
%token PLUS MINUS TIMES DIVIDE 
%token IDENTIFIER 
%token SEMICOLON

????????在這個示例中,我們定義了幾個終結符,包括數字(NUMBER)、加號(PLUS)、減號(MINUS)、乘號(TIMES)、除號(DIVIDE)、標識符(IDENTIFIER)和分號(SEMICOLON)等。終結符是語法規則中的基本符號,代表語言中的最小單元或詞匯元素。終結符在語法分析的過程中與輸入字符串的實際內容進行匹配,幫助構建解析樹或語法分析樹。在 Bison 文件中,終結符通常以大寫字母或使用引號括起來的字符串表示。

(2)非終結符(Non-terminals)

????????非終結符表示語法規則中的抽象結構,可以由其他非終結符和/或終結符組成。您可以使用?%type?來定義非終結符的類型。以下是一個示例:

%type <expr> expression%type <term> term%type <factor> factor

????????在這個示例中,我們定義了三個非終結符 expression、term 和 factor,并指定了它們的類型。這些類型標記可以在產生式的操作部分使用,以便對解析樹節點進行更復雜的操作。非終結符在語法分析樹中代表了一些更高級的結構,可以用來執行語義操作、構建解析樹,并幫助描述語言的抽象語法結構。在 Bison 文件中,非終結符通常以小寫字母開頭。

????????終結符和非終結符在 Bison 文件中共同定義了語法規則,幫助我們描述和分析特定編程語言或語言的一部分。終結符代表了實際的詞法單元,而非終結符則代表了更高層次的語法結構。通過將終結符和非終結符組合起來,我們可以創建復雜的語法規則,用于生成和解析語言的有效字符串。

(3)“文法”

????????“文法”是一組規則,用于描述編程語言或語言的語法結構。這些規則定義了語言的句法(syntax),即哪些組合是有效的、合法的語句和表達式,以及它們如何組合在一起。文法規則使用產生式(productions)的形式來表示,其中包含終結符(terminals)和非終結符(non-terminals)的組合。

????????文法規則在 Bison 文件中是使用 BNF(巴科斯-諾爾范式)或 EBNF(擴展巴科斯-諾爾范式)的形式表示的。BNF 是一種形式化的表示方法,用于定義上下文無關文法(Context-Free Grammar),這些文法用于指定編程語言的語法規則。

expression : expression '+' term| expression '-' term| term;

(4) %start

????????%start 指令用于指定文法的起始非終結符。起始非終結符是語法分析的入口點,也就是從哪個語法規則開始構建解析樹或語法分析樹。

%start program%%statements : statement| statements statement;statement : assignment| if_statement| while_statement| /* ... other statement types ... */ ;

????????%start program 指定了起始非終結符為 program。這意味著語法分析將從 program 規則開始,逐步展開其他非終結符,最終構建解析樹。在實際語法規則中,起始非終結符的選擇取決于您想要分析的語言的語法結構。

(5)$

????????在語法規則中,$ 用于引用當前產生式的右側的符號或值。例如,在產生式的右側,$1 表示該產生式右側的第一個元素(終結符或非終結符),$2表示第二個元素,依此類推。這些引用用于將產生式右側的值傳遞給產生式左側。注意:生產式的起始下標為1。

(6)$$

????????在語法規則中,$$ 用于引用當前產生式的結果。當 Bison 解析器完成一個產生式的分析并計算出其結果時,該結果會被賦值給 $$。這通常用于構建解析樹的節點或為更高層次的語法規則提供結果。

(7)|

????????| 用于表示多個產生式之間的選擇。它在上下文無關文法中用于定義非終結符的不同產生式形式。每個產生式通過豎線分隔,表示它們是該非終結符的可能形式之一。

3.4 bison文件具體案例

1、創建一個名為parser.l的文件,其中包含詞法規則;

%{
#include <stdio.h>
#include <stdlib.h>
%}//定義終結符
%token SELECT INSERT UPDATE DELETE FROM WHERE 
%token INTO VALUES SET
%token ID INT STRING%%//定義規則statement: SELECT columns FROM table WHERE condition ';'| INSERT INTO table '(' columns ')' VALUES '(' values ')' ';'| UPDATE table SET assignments WHERE condition ';'| DELETE FROM table WHERE condition ';';columns: ID| columns ',' ID;table: ID;assignments: ID '=' value| assignments ',' ID '=' value;values: value| values ',' value;value: INT| STRING;condition: ID '=' value;%%int main() {yyparse();return 0;
}int yyerror(const char *s) {printf("Error: %s\n", s);return 0;
}

2、使用 bison 命令編譯 lexer.l 文件

bison -d parser.y

????????這將生成 parser.tab.c 和 parser.tab.h 兩個文件。接下來,你可以將這些文件與你的編譯器項目一起編譯,并鏈接到你的代碼中。

3.5 抽象語法樹(AST)

AST構建步驟:

1、從前綴表達式構建函數關系表里獲取當前Token的構建函數,調用該函數構建出一個前綴表達式;

2、查看下一個Token的優先級,如果下一個Token的優先級比當前Token的優先級更高,則說明這可能是一個中綴表達式,或后綴表達式;

3、如果是中綴表達式,則從中綴表達式構建函數關系表里獲取下一個Token的構建函數,調用該函數構建出一個中綴表達式;

4、如果是后綴表達式,則從后綴表達式構建函數關系表里獲取下一個Token的構建函數,調用該函數構建出一個后綴表達式;

5、通過遞歸方式,將這些表達式建立起父子關系,最終形成一個抽象語法樹。

4.語義分析

????????在語法分析的基礎上,對生成的抽象語法樹進行語義分析。語義分析器會檢查SQL語句是否符合數據庫的語義規則,例如表是否存在、列是否存在、數據類型是否匹配等。如果不符合,則會拋出語義錯誤。

5.優化器

????????在語義分析的基礎上,進行優化。優化器會對SQL語句進行優化,以提高查詢效率。優化器會選擇最優的執行計劃,包括選擇最優的索引、選擇最優的連接方式等。

6.執行計劃生成器

????????在優化器的基礎上,生成執行計劃。執行計劃是一組計算機指令,用于執行SQL語句。執行計劃包括訪問表、過濾數據、排序數據等操作。

7.執行計劃執行器

????????執行計劃執行器會按照執行計劃執行SQL語句。執行計劃執行器會訪問表、過濾數據、排序數據等操作,最終返回查詢結果。

8.結果集返回

????????執行計劃執行器會將查詢結果返回給客戶端。查詢結果可以是一張表、一組記錄或一個標量值。

9.清理

????????在查詢結束后,數據庫管理系統會清理執行計劃、釋放資源等。

未完,writing……

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/36232.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/36232.shtml
英文地址,請注明出處:http://en.pswp.cn/news/36232.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【CSS 布局】水平垂直方向居中

【CSS 布局】水平垂直方向居中 單行元素 <div class"container"><div class"item"></div> </div>方式一&#xff1a;relative 和 absolute .container {position: relative;height: 400px;border: 1px solid #ccc;.item {posit…

20個互聯網用戶Python數據分析項目

這篇文章給大家整理了20個互聯網用戶數據分析的項目。所有收錄的項目&#xff0c;進行了嚴格的篩選&#xff0c;標準有二&#xff1a; 1.有解說性文字&#xff0c;大家能知道每一步在干嘛&#xff0c;新手友好 2.數據集公開&#xff0c;保證大家可以在原文的基礎上自行探索 更…

[保研/考研機試] KY96 Fibonacci 上海交通大學復試上機題 C++實現

題目鏈接&#xff1a; KY96 Fibonacci https://www.nowcoder.com/share/jump/437195121692000803047 描述 The Fibonacci Numbers{0,1,1,2,3,5,8,13,21,34,55...} are defined by the recurrence: F00 F11 FnFn-1Fn-2,n>2 Write a program to calculate the Fibon…

【STM32】FreeRTOS互斥量學習

互斥量&#xff08;Mutex&#xff09; 互斥量又稱互斥信號量&#xff08;本質也是一種信號量&#xff0c;不具備傳遞數據功能&#xff09;&#xff0c;是一種特殊的二值信號量&#xff0c;它和信號量不同的是&#xff0c;它支持互斥量所有權、遞歸訪問以及防止優先級翻轉的特性…

人文景區有必要做VR云游嗎?如何滿足游客出行需求?

VR云游在旅游行業中的應用正在快速增長&#xff0c;為游客帶來沉浸式體驗的同時&#xff0c;也為文旅景區提供了新的營銷方式。很多人說VR全景展示是虛假的&#xff0c;比不上真實的景區觸感&#xff0c;人文景區真的有必要做VR云游嗎&#xff1f;我的答案是很有必要。 如果你認…

【跟小嘉學 Rust 編程】十二、構建一個命令行程序

系列文章目錄 【跟小嘉學 Rust 編程】一、Rust 編程基礎 【跟小嘉學 Rust 編程】二、Rust 包管理工具使用 【跟小嘉學 Rust 編程】三、Rust 的基本程序概念 【跟小嘉學 Rust 編程】四、理解 Rust 的所有權概念 【跟小嘉學 Rust 編程】五、使用結構體關聯結構化數據 【跟小嘉學…

【Pytroch】基于K鄰近算法的數據分類預測(Excel可直接替換數據)

【Pytroch】基于K鄰近算法的數據分類預測&#xff08;Excel可直接替換數據&#xff09; 1.模型原理2.數學公式3.文件結構4.Excel數據5.下載地址6.完整代碼7.運行結果 1.模型原理 K最近鄰&#xff08;K-Nearest Neighbors&#xff0c;簡稱KNN&#xff09;是一種簡單但常用的機器…

Redis基礎學習

目錄 第一章、Redis數據庫的下載和安裝1.1&#xff09;nosql數據庫和 Redis 介紹1.2&#xff09;Windows中下載安裝Redis數據庫1.3&#xff09;Linux中安裝Redis數據庫1.4&#xff09;Linux中啟動redis1.5&#xff09;Linux中關閉redis 第二章、三種Redis客戶端連接Redis數據庫…

安全遠控如何設置?揭秘ToDesk、TeamViewer 、向日葵安全遠程防御大招

寫在前面一、遠程控制&#xff1a;安全性不可忽略二、遠控軟件安全設置實測? ToDesk? TeamViewer? 向日葵 三、遠控安全的亮點功能四、個人總結與建議 寫在前面 說到遠程辦公&#xff0c;相信大家都不陌生。遠程工作是員工在家中或者其他非辦公場所上班的一種工作模式&…

傳輸層協議

傳輸層協議 再談端口號端口號范圍劃分認識知名端口號兩個問題netstatpidof UDP協議UDP協議端格式UDP的特點面向數據報UDP的緩沖區UDP使用注意事項基于UDP的應用層協議 TCP協議TCP協議段格式確認應答(ACK)機制超時重傳機制連接管理機制理解 CLOSE_WAIT 狀態理解TIME_WAIT狀態解決…

修改el-select和el-input樣式;修改element-plus的下拉框el-select樣式

修改el-select樣式 .select_box{// 默認placeholder:deep .el-input__inner::placeholder {font-size: 14px;font-weight: 500;color: #3E534F;}// 默認框狀態樣式更改:deep .el-input__wrapper {height: 42px;background-color: rgba(0,0,0,0)!important;box-shadow: 0 0 0 …

OptaPlanner筆記6 N皇后

N 個皇后 問題描述 將n個皇后放在n大小的棋盤上&#xff0c;沒有兩個皇后可以互相攻擊。 最常見的 n 個皇后謎題是八個皇后謎題&#xff0c;n 8&#xff1a; 約束&#xff1a; 使用 n 列和 n 行的棋盤。在棋盤上放置n個皇后。沒有兩個女王可以互相攻擊。女王可以攻擊同一水…

如何做好一名網絡工程師?具體實踐?

預防問題 – 資格與認證 在安裝線纜或升級網絡時測試線纜是預防問題的有效方式。對已安裝布線進行測試的方法有兩種。 資格測試確定布線是否有資格執行某些操作 — 換言之&#xff0c;支持特定網絡速度或應用。盡管“通過”認證測試也表明按標準支持某一網絡速度或應用的能力…

Redux - Redux在React函數式組件中的基本使用

文章目錄 一&#xff0c;簡介二&#xff0c;安裝三&#xff0c;三大核心概念Store、Action、Reducer3.1 Store3.2 Reducer3.3 Action 四&#xff0c;開始函數式組件中使用4.1&#xff0c;引入store4.1&#xff0c;store.getState()方法4.3&#xff0c;store.dispatch()方法4.4&…

cookie和session的區別及原理

Cookie概念 在瀏覽某些 網站 時,這些網站會把 一些數據存在 客戶端 , 用于使用網站 等跟蹤用戶,實現用戶自定義 功能. 是否設置過期時間: 如果不設置 過期時間,則表示這個 Cookie生命周期為 瀏覽器會話期間 , 只要關閉瀏覽器,cookie就消失了. 這個生命期為瀏覽會話期的cookie,就…

其他行業跳槽轉入計算機領域簡單看法

其他行業跳槽轉入計算機領域簡單看法 本人選擇從以下幾個方向談談自己的想法和觀點。 如何規劃才能實現轉碼 自我評估和目標設定&#xff1a;首先&#xff0c;你需要評估自己的技能和興趣&#xff0c;確定你希望在計算機領域從事的具體職位或領域。這有助于你更好地規劃學習路…

深入了解 Rancher Desktop 設置

Rancher Desktop 設置的全面概述 Rancher Desktop 擁有方便、強大的功能&#xff0c;是最佳的開發者工具之一&#xff0c;也是在本地構建和部署 Kubernetes 的最快捷方式。 本文將介紹 Rancher Desktop 的功能和特性&#xff0c;以及 Rancher Desktop 作為容器管理平臺和本地…

人工智能原理(2)

目錄 一、知識與知識表示 1、知識 2、知識表示 3、知識表示方法 二、謂詞邏輯表示法 1、命題邏輯 2、謂詞邏輯 三、產生式表達法 1、知識的表示方法 2、產生式系統組成 3、推理方式 4、產生式表示法特點 四、語義網絡 1、概念及結構 2、語義網絡的基本語義聯系 …

zookeeper案例

目錄 案例一&#xff1a;服務器動態上下線 服務端&#xff1a; &#xff08;1&#xff09;先獲取zookeeper連接 &#xff08;2&#xff09;注冊服務器到zookeeper集群&#xff1a; &#xff08;3&#xff09;業務邏輯&#xff08;睡眠&#xff09;&#xff1a; 服務端代碼…

Java+Excel+POI+testNG基于數據驅動做一個簡單的接口測試【杭州多測師_王sir】

一、創建一個apicases.xlsx放入到eclipse的resource里面&#xff0c;然后refresh刷新一下 二、在pom.xml文件中加入poi和testng的mvn repository、然后在eclipse的對應目錄下放入features和plugins&#xff0c;重啟eclipse就可以看到testNG了 <!--poi excel解析 --><d…