課程設(shè)計---小型數(shù)據(jù)庫命令解析器、數(shù)據(jù)存儲的設(shè)計與實現(xiàn)設(shè)計與實現(xiàn)_第1頁
已閱讀1頁,還剩22頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)

文檔簡介

1、<p><b>  小型數(shù)據(jù)庫</b></p><p>  ——命令解析器、數(shù)據(jù)存儲的設(shè)計與實現(xiàn)</p><p><b>  摘 要</b></p><p>  當(dāng)今時代,“數(shù)據(jù)”已經(jīng)成為一種資源。隨著各種數(shù)據(jù)獲取技術(shù)和數(shù)據(jù)庫技術(shù)的迅速發(fā)展,人們積累的數(shù)據(jù)越來越多,如何更加合理的管理數(shù)據(jù)顯得更加重要。小型數(shù)據(jù)

2、庫就是模擬目前比較流行的一些大型數(shù)據(jù)庫,實現(xiàn)通過在命令行輸入相應(yīng)命令來對數(shù)據(jù)進行存儲,管理和查詢。</p><p>  該小型數(shù)據(jù)庫MyDB包括兩大模塊:SQL命令解析器及數(shù)據(jù)存儲模塊。SQL命令解析器負(fù)責(zé)解析用戶命令并完成用戶對表的創(chuàng)建、刪除、插入、更新等操作;數(shù)據(jù)存儲模塊的主要功能是保存和管理用戶的數(shù)據(jù)。整個系統(tǒng)是用C語言、采用模塊化的程序設(shè)計思想實現(xiàn)的。</p><p>  關(guān)鍵詞:

3、MyDB;命令解析;數(shù)據(jù)存儲;C語言</p><p>  Minidatabase</p><p>  ---- Design and Implementation of Command Interpreter and Data Storage</p><p><b>  Abstract</b></p><p>  I

4、n this information era, data has been a kind of resource. With the fast development of data getting technology and database technology, people accumulate more and more data. How to manage these data more rational become

5、more and more important. Minidatabase is to simulate popular database at present and implement data storage, management and querying by inputting commands from command line. </p><p>  This Minidatabase ——My

6、DB includes two modules: SQL command parser and data storage. SQL command parser takes in change of parsing user commands and operating tables, such as creating a table, deleting a table, inserting elements into table an

7、d updating table. The primary function of data storage module is to save and manage user data. The whole system is designed with the idea of modularized programmer and developed with C program language.</p><p&

8、gt;  Key words: MyDB ; command parse ; data storage ; C program language</p><p><b>  目 錄</b></p><p><b>  論文總頁數(shù):24頁</b></p><p><b>  1引言1</b><

9、;/p><p>  1.1數(shù)據(jù)庫課程教學(xué)的現(xiàn)狀1</p><p>  1.2研制DBMS的重要性1</p><p>  1.3MyDB的設(shè)計目標(biāo)2</p><p><b>  2數(shù)據(jù)庫理論2</b></p><p>  2.1數(shù)據(jù)元素的表示2</p><p>

10、;<b>  2.1.1字段2</b></p><p><b>  2.1.2記錄3</b></p><p><b>  2.1.3塊3</b></p><p>  2.2查詢編譯器3</p><p>  3MyDB的實現(xiàn)5</p><p>

11、;  3.1記錄的定義5</p><p>  3.2命令解析模塊6</p><p>  3.2.1 詞法分析器7</p><p>  3.2.2 語法分析器11</p><p>  3.2.3 SQL語句的實現(xiàn)13</p><p>  3.3基本表模塊18</p><p>  

12、3.3.1數(shù)據(jù)組織18</p><p>  3.3.2基本表的實現(xiàn)19</p><p>  3.4數(shù)據(jù)存儲模塊20</p><p><b>  結(jié) 論21</b></p><p><b>  參考文獻21</b></p><p><b>  致 謝

13、23</b></p><p><b>  聲 明24</b></p><p><b>  引言</b></p><p>  數(shù)據(jù)庫課程教學(xué)的現(xiàn)狀</p><p>  現(xiàn)在數(shù)據(jù)庫教學(xué)的不足突出地表現(xiàn)在以下幾點:</p><p>  1.普遍只強調(diào)理論,不重視實踐

14、,在學(xué)習(xí)過程中難以對概念深刻領(lǐng)悟,課程結(jié)束后就很快把其中許多內(nèi)容給淡忘掉了。</p><p>  2.現(xiàn)有對數(shù)據(jù)庫的實踐也是流于形式,內(nèi)容膚淺與真實的數(shù)據(jù)庫管理系統(tǒng)相去甚遠。比如用SQL語言對數(shù)據(jù)庫進行一定的創(chuàng)建查詢操作。這些實踐都不過是對數(shù)據(jù)庫管理系統(tǒng)的使用,根本談不上了解數(shù)據(jù)庫本身的運行機理。而且這些實踐都太過理想化,完全把底層原理透明化了,這些實踐充其量只不過是對SQL語言熟悉而已。</p>

15、<p>  3.用真實的數(shù)據(jù)庫管理系統(tǒng)來實踐顯然要好得多。但現(xiàn)實中的數(shù)據(jù)庫管理系統(tǒng)都太過龐大,比如開源的數(shù)據(jù)庫管理系統(tǒng)MYSQL,僅源代碼就達數(shù)十萬行之多。專業(yè)人員閱讀起來都不會很容易,更不要說剛讀本科的學(xué)生對其進行修改了,所以收效甚微。</p><p>  以上三點明顯地說明了:“實踐”在數(shù)據(jù)庫原理教學(xué)中的重要性。需要一個能夠真正對數(shù)據(jù)庫所學(xué)理論進行有效的實踐的數(shù)據(jù)庫管理系統(tǒng)。但缺少一個好的教學(xué)用數(shù)據(jù)

16、庫管理系統(tǒng),現(xiàn)有的教學(xué)用數(shù)據(jù)庫管理系統(tǒng)并不那么適合中國的實際情況。</p><p>  因此,無論是從應(yīng)用的角度還是學(xué)習(xí)數(shù)據(jù)庫的理論教學(xué)的角度來看,設(shè)計與實現(xiàn)一個小型的數(shù)據(jù)庫管理系統(tǒng)都是很有必要的。</p><p>  研制DBMS的重要性</p><p>  數(shù)據(jù)庫技術(shù)產(chǎn)生于1970年前后。它的出現(xiàn)使得計算機的應(yīng)用進入了新的時期,社會的每個領(lǐng)域都與計算機發(fā)生了聯(lián)系

17、。數(shù)據(jù)庫技術(shù)聚集了數(shù)據(jù)處理最精華的思想,是管理信息最先進的工具。信息社會的緊迫需求使數(shù)據(jù)庫技術(shù)成為計算機園地中一支最有生命力的新秀。而與人工智能的結(jié)合又使它獲得了新的血液。20世紀(jì)80年代中期數(shù)據(jù)庫技術(shù)進入一個新的層次,智能數(shù)據(jù)庫、演繹數(shù)據(jù)庫、專家數(shù)據(jù)庫、面向?qū)ο髷?shù)據(jù)庫、工程數(shù)據(jù)庫、多介質(zhì)數(shù)據(jù)庫、并行數(shù)據(jù)庫、實時數(shù)據(jù)庫等就是當(dāng)代數(shù)據(jù)庫研究的前沿。</p><p>  數(shù)據(jù)庫管理系統(tǒng)(DBMS)的研制是一件非常復(fù)雜

18、的軟件工程。它涉及的面非常廣泛,需要軟件、硬件及設(shè)備方面的知識;需要一定的物質(zhì)條件;需要研制人員的豐富的編程經(jīng)驗和精深的軟件技術(shù);需要科學(xué)的管理方法和科學(xué)先進的測試技術(shù)。當(dāng)然由于系統(tǒng)的功能和規(guī)模不一樣,其復(fù)雜程度也相差很大。大一點的數(shù)據(jù)庫如IMS花費幾千人年,系統(tǒng)R的研制花費了120個專家人年以及幾千程序員人年,SYSTEM2000花費400人年。數(shù)據(jù)庫的設(shè)計與數(shù)據(jù)庫的設(shè)計不同,前者屬于系統(tǒng)軟件設(shè)計,與機器世界比較接近,它的基礎(chǔ)是OS;

19、后者屬于應(yīng)用軟件設(shè)計,與現(xiàn)實世界更為接近,它的基礎(chǔ)是數(shù)據(jù)庫。所以數(shù)據(jù)庫是介于用戶程序和OS之間的一個中間媒介,是使得物理數(shù)據(jù)庫與用戶程序相互獨立的軟件系統(tǒng)。</p><p>  研制數(shù)據(jù)庫對于從事數(shù)據(jù)庫開發(fā)的科研人員和教學(xué)人員是一件十分有價值的工作。通過參加研制數(shù)據(jù)庫的工作,可以加深對數(shù)據(jù)庫技術(shù)的理解,弄清其來龍去脈,提高技術(shù)水平,從而改進數(shù)據(jù)庫教學(xué)質(zhì)量。更重要的是滿足社會需求。同時數(shù)據(jù)庫的研制是一件很基礎(chǔ)的工作

20、,是研究面向?qū)ο髷?shù)據(jù)庫、分布式數(shù)據(jù)庫、知識庫以及智能數(shù)據(jù)庫的基礎(chǔ)。因此,數(shù)據(jù)庫原理一般都作為計算機專業(yè)的基礎(chǔ)課程學(xué)習(xí)。</p><p><b>  MyDB的設(shè)計目標(biāo)</b></p><p>  先看看國際上有關(guān)數(shù)據(jù)庫發(fā)展的情況。隨著計算機廣泛而深入地應(yīng)用與社會各行各業(yè),作為其中重要支柱的系統(tǒng)軟件——數(shù)據(jù)庫變的越來越龐大,功能越來越強,而且這種發(fā)展勢頭絲毫不見有放慢的

21、跡象。特別是隨著網(wǎng)絡(luò)通信技術(shù)的發(fā)展,現(xiàn)代主流的數(shù)據(jù)庫廠商紛紛把網(wǎng)絡(luò)特性集成系統(tǒng)之中,甚至還出現(xiàn)了專門應(yīng)用于網(wǎng)絡(luò)環(huán)境的分布式數(shù)據(jù)庫管理系統(tǒng)。所有這些數(shù)據(jù)庫的復(fù)雜性給數(shù)據(jù)庫的設(shè)計帶來很大的挑戰(zhàn)。</p><p>  如果個人想設(shè)計并實現(xiàn)一個商用的數(shù)據(jù)庫基本上是不可能的,復(fù)雜的技術(shù)細(xì)節(jié)會把數(shù)據(jù)庫的最基本的理論完全掩蓋。因此,學(xué)生很難通過商用的數(shù)據(jù)庫學(xué)習(xí)數(shù)據(jù)庫的原理。MyDB是一個面向教學(xué)用的DBMS,這是必須首先堅持的

22、,同時亦對DBMS的存儲管理、SQL語言感興趣。</p><p>  總之,MyDB是一個基于關(guān)系代數(shù)的、用C實現(xiàn)的、面向教學(xué)的關(guān)系型數(shù)據(jù)庫管理系統(tǒng)。</p><p><b>  數(shù)據(jù)庫理論</b></p><p><b>  數(shù)據(jù)元素的表示</b></p><p>  首先,研究一下最基本的數(shù)據(jù)元

23、素的表示,即關(guān)系數(shù)據(jù)庫系統(tǒng)中的屬性值的表示。這是用“字段”來表示的。然后,考察字段如何組裝成存儲系統(tǒng)中更大的元素:記錄、塊和文件</p><p><b>  字段</b></p><p>  屬性需要用定長或變長的字節(jié)序列表示,稱作“字段”;</p><p>  可以用下式所示的CREATE TABLE 語句在SQL系統(tǒng)中聲明一個關(guān)系。數(shù)據(jù)庫負(fù)

24、責(zé)表示和存儲由這個定義描述的關(guān)系。既然關(guān)系是元組的集合,元組與記錄或“結(jié)構(gòu)”(C或C++術(shù)語)相似,可以設(shè)想每一個元組在磁盤中作為一條記錄來存儲。記錄會占據(jù)某個磁盤塊(或一部分),在記錄內(nèi)部,對應(yīng)于關(guān)系的每一個屬性有一個字段。</p><p>  CREATE TABLE StudentInfor</p><p><b> ?。?lt;/b></p><

25、p>  number int ,</p><p>  name CHAR(6) ,</p><p><b>  age int ,</b></p><p>  address CHAR(20) ,</p><p><b>  ……</b></p><p><b&g

26、t; ?。?lt;/b></p><p><b>  記錄</b></p><p>  字段被組裝成定長或變長的集合,成為“記錄”;</p><p><b>  定長記錄的構(gòu)造</b></p><p>  元組由記錄表示,而記錄由上述所討論的各種字段組成。最簡單的情況是記錄的所有字段均為定長,

27、則可以將字段連接成記錄。</p><p><b>  記錄首部</b></p><p>  當(dāng)設(shè)計記錄的格式的時候,必然會引出另一個問題:通常在記錄中需要保存一些信息,而這些信息不是任何字段的值。因此有必要在記錄的首部添加相關(guān)信息,如:記錄長度、字段數(shù)等。</p><p><b>  塊</b></p>&l

28、t;p>  構(gòu)成一個關(guān)系或類的外延的記錄集存儲為塊的集合,成為文件。</p><p><b>  查詢編譯器</b></p><p>  查詢處理器需采取三個主要步驟:</p><p>  1)對使用諸如SQL的某種語言書寫的查詢進行語法分析,亦即將查詢語句轉(zhuǎn)換成按某種有用方式表示查詢語句結(jié)構(gòu)的語法樹;</p><p&

29、gt;  2)把語法分析樹轉(zhuǎn)換成代數(shù)關(guān)系表達式樹(或某種類似標(biāo)記),稱之為邏輯查詢計劃;</p><p>  3)邏輯查詢計劃需轉(zhuǎn)換成物理查詢計劃,物理查詢計劃不僅指名了要執(zhí)行的操作,而且也找出了這些操作執(zhí)行的順序、執(zhí)行每步所用的算法、獲得所存儲數(shù)據(jù)的方式以及數(shù)據(jù)從一個操作傳遞給另一個操作的方式。</p><p>  查詢編譯的開始幾個階段如圖所示:</p><p>

30、;  圖1 查詢編譯的階段圖</p><p>  語法分析與語法分析樹</p><p>  語法分析器的工作是接收用類似SQL這樣的語言編寫的文本并將之轉(zhuǎn)換成語法分析樹,結(jié)點對應(yīng)于以下兩者之一:</p><p>  1)原子:它們是詞法成分,如關(guān)鍵字(如SELECT等)、關(guān)系或?qū)傩缘拿?、常?shù)、括號、操作符(如+等),以及其它成分;</p><p

31、>  2)語法類:即在一個查詢中起相似作用的查詢子成分所形成族的名字??梢杂眉饫ㄌ枌⒚枋鲂缘拿Q括起來表示語法類。例如,<SFW>用于表示以常用的select-from-where形式的查詢,而<Condition>將用于表示屬性條件的任何表達式,如跟在SQL語句where之后的表達式。</p><p>  如果結(jié)點是一個原子,則該結(jié)點沒有子女。然而,若該結(jié)點是一個語法類,則其子女通

32、過該語言的語法規(guī)則之一進行描述。</p><p>  SQL的一個簡單子集的語法</p><p>  通過給出可用于SQL子集的語言的某些規(guī)則,我們借此說明語法分析樹的過程。</p><p><b>  1)查詢</b></p><p>  語法<Query>用于表示所有正則SQL查詢語句。它的一些語法規(guī)則是

33、:</p><p>  <Query> ::= <SFW></p><p>  <Query> ::= (<Query>)</p><p>  ::=符號表示“可以表述為”。</p><p>  2)Select列表</p><p>  <SelList> :

34、:= <Attribute> , <SelList></p><p>  <SelList> ::= <Attribute></p><p>  這兩條規(guī)則說明一個選擇列表可以為任何由逗號分隔的屬性列表:要么是單個屬性,要么是一個屬性、一個逗號以及一個或多個屬性的任意列表。</p><p><b>  3)F

35、rom列表</b></p><p>  <FromList> ::= <Relation> , <FromList></p><p>  <FromList> ::= <Relation></p><p>  這里的from列表可由任意用逗號分隔的關(guān)系列表組成。</p><p

36、>  這里只列出了部分規(guī)則,其他的規(guī)則請參考其他的書籍。</p><p>  我們來看這樣一個查詢語句:</p><p>  SELECT title </p><p>  FROM StarsIn</p><p>  WHERE starName IN</p><p><b>  (</b>

37、;</p><p>  SELECT name</p><p>  FROM MovieStar</p><p>  WHERE birthdate LIKE ‘%1960’</p><p><b>  );</b></p><p>  按照我們所描繪的語法,此查詢語句的語法分析樹如下所示<

38、/p><p><b>  圖2 語法分析樹</b></p><p>  根是語法類<Query>,任何一個查詢語句的語法樹都必然是這種情況。順著數(shù)往下走,我們可知該查詢語句是select-from-where的形式;選擇列表僅由屬性title構(gòu)成,from列表只有一個關(guān)系StarsIn。</p><p><b>  MyDB的

39、實現(xiàn)</b></p><p><b>  記錄的定義</b></p><p>  在這里,段是解析用戶命令的最小單位,若干段的集合就構(gòu)成了一條記錄。因此段和記錄的定義是進行命令解析器及數(shù)據(jù)存儲的基礎(chǔ)。</p><p>  在MyDB中,段與記錄的關(guān)系可表示如下:</p><p>  圖3 段與記錄的關(guān)系<

40、;/p><p>  段和記錄的定義在hrecord.h中實現(xiàn):</p><p><b>  段的定義:</b></p><p>  typedef struct FldInforStruct</p><p><b>  {</b></p><p><b>  /* 字段

41、名 */</b></p><p>  char fldname[10] ;</p><p>  /* 字段類型 */</p><p>  char fldclass[6] ;</p><p>  /* 字段長度 */</p><p>  int fldlen ;</p><p&

42、gt;  /* 小數(shù)長度 */</p><p>  int dicimllen ;</p><p>  } FieldInfor_T ;</p><p><b>  記錄的定義:</b></p><p>  typedef struct WorkAreaStruct </p><p><

43、;b>  {</b></p><p>  /* 記錄長度 */</p><p>  int reclen ;</p><p>  /* 字段數(shù) */</p><p>  int fldnum ;</p><p>  /* 記錄總數(shù) */</p><p>  

44、int rectotal ;</p><p>  /* 字段結(jié)構(gòu)信息指針數(shù)組,0號單元未用 */</p><p>  FieldInfor_T fldinforptr[MAX_FIELD_NUM + 1];</p><p>  /* 文件指針 */</p><p>  FILE *DBFile_ptr ;</p>

45、<p>  } RecordWorkArea ;</p><p><b>  命令解析模塊</b></p><p>  SQL語言是一種面向集合的結(jié)構(gòu)化查詢語言。用SQL語言編寫的命令一般都是解釋執(zhí)行的。所謂解釋執(zhí)行,就是解釋和執(zhí)行同步,不是像編譯那樣先把程序全部掃描一遍翻譯成機器指令再直接運行機器指令。一般SQL語言可以嵌套在C等其他的高級語言中。因此

46、,現(xiàn)在的商業(yè)用數(shù)據(jù)庫都有自己的一套編譯器系統(tǒng),實現(xiàn)SQL解釋(或編譯)和高級語言編譯器的無縫集成。由于MyDB的各個模塊接口是采用C語言函數(shù)調(diào)用,因此SQL語言也不可避免地要和底層模塊的接口函數(shù)打交道。MyDB命令解析器具體的原理圖如下:</p><p>  圖4 命令解析器具體工作流程原理圖</p><p><b>  詞法分析器</b></p>&l

47、t;p>  詞法分析器將SQL源程序解釋成一個個獨立的記號,然后將記號的類型以及記號所對應(yīng)的值返回給語法分析器。</p><p>  MyDB的詞法分析過程如圖所示:</p><p><b>  圖5 詞法分析</b></p><p>  首先刪除用戶命令中的空格、制表符、逗號等,提取相關(guān)的字符,這個功能由函數(shù)CutBlankTab_He

48、ad_Tail完成;</p><p>  然后掃描提取的字符串,分步將關(guān)鍵字提取出。第一步,連分隔符(如括號等)一起提取,這個由函數(shù)GetSubstr_Delimitor完成;第二步,提取分隔符內(nèi)的字符串,這步由函數(shù)GetSubstr_BetweenDelim完成;第三步,提取合法字符集,這一步由函數(shù)GetSubstr_ValidChar完成;</p><p>  將字段信息存入數(shù)組,包括

49、所提取出的字段名,字段類型,字段長度等,這個主要由函數(shù)*Change完成;</p><p>  將記錄值存入結(jié)構(gòu)中,將所提取出來的記錄值插入相應(yīng)的結(jié)構(gòu)之中。</p><p>  實現(xiàn)各流程的函數(shù)會在下面分別敘述。</p><p>  MyDB的詞法分析器的關(guān)鍵字表為:</p><p>  enum SysKeyWordSet</p>

50、;<p><b>  {</b></p><p>  CREATE,DROP,INSERT,DELETE,</p><p>  SELECT,UPDATE,EXIT,HELP</p><p><b>  } ;</b></p><p>  由于MyDB只是一個面向教學(xué)的微型數(shù)據(jù)庫,所以

51、它所包含的關(guān)鍵字僅僅是標(biāo)準(zhǔn)SQL的一個很小的子集。</p><p>  詞法分析器的接口參數(shù):</p><p>  用戶給出的命令結(jié)構(gòu)是SQL編譯器進行詞法分析的基礎(chǔ)。詞法分析的任務(wù)在于提取關(guān)鍵字、省略多余空格等等。所以用戶命令結(jié)構(gòu)信息的定義也是必要的。</p><p>  /* 用戶命令結(jié)構(gòu)信息 */</p><p>  typedef s

52、truct </p><p><b>  {</b></p><p>  /* 命令內(nèi)部代碼,如"INSERT" , "CREATE"等 */</p><p>  SysKeyWord_Type Cmd ;</p><p>  /* 表名 */</p><

53、;p>  char userstr[10] ;</p><p>  /* 字段信息指針 */</p><p>  FieldInfor_T *fld ;</p><p>  /* 記錄值指針數(shù)組 */</p><p>  char *recvalptr[MAX_FIELD_NUM + 1] ;</p><p

54、>  /* 查找范圍 */</p><p>  char range[10] ;</p><p>  /* 介詞 */</p><p>  char parse[20] ;</p><p><b>  /* 表達式 */</b></p><p>  char expressio

55、n[30] ;</p><p>  char token[100] ;</p><p>  int count ;</p><p>  }CmdRec_Type ;</p><p>  此接口參數(shù)定義了用戶命令的結(jié)構(gòu)信息,以便后來詞法分析中關(guān)鍵字及有效值的提取。</p><p>

56、  詞法分析器的接口函數(shù)</p><p>  詞法分析器的接口函數(shù)定義在頭文件lexical_tool.h中。主要是與詞法分析相關(guān)的函數(shù)體,包括:</p><p>  void CutBlankTab_Head_Tail (char *S);</p><p>  此函數(shù)用于刪除詞頭和詞尾的空格以及控制符;</p><p>  void Cut

57、Comma (char *S) ;</p><p>  此函數(shù)用于刪除詞頭逗號;</p><p>  int CountSymbol (char *S , char c) ;</p><p>  此函數(shù)用于計算字符個數(shù);</p><p>  int GetSubstr_Delimitor (char *S , int *ScanPos , c

58、har * Delimitor , char *Substr) ;</p><p>  此函數(shù)根據(jù)分隔符集合Delimitor,在串S中掃描起點ScanPos,取出子串Substr,并且移動掃描起點到新的位置,用于詞法分析。偽碼如下:</p><p>  int GetSubstr_Delimitor(char *S , int *ScanPos , char * Delimitor ,

59、char *Substr)</p><p><b>  {</b></p><p>  InStr = FALSE;</p><p>  /*跳過分隔符(雙引號的分隔符除外)*/</p><p>  while((*ScanPos < len) && (strchr(Delimitor , *(S

60、+ (*ScanPos))) != NULL))</p><p><b>  {</b></p><p>  if(*(S + (*ScanPos)) == '\"')</p><p>  InStr = !InStr ;</p><p>  (*ScanPos) ++ ;</p>

61、<p><b>  }</b></p><p>  SubstrBegin = *ScanPos ;</p><p>  /*掃描子串,包括雙引號內(nèi)的分隔符*/</p><p>  while((*ScanPos <= len) && (InStr || (strchr (Delimitor , *(S + *

62、ScanPos)) == NULL)))</p><p><b>  {</b></p><p>  if(*(S + (*ScanPos)) == '\"')</p><p>  InStr = !InStr ;</p><p>  (*ScanPos) ++ ;</p><

63、;p><b>  }</b></p><p><b>  /*復(fù)制子串*/</b></p><p>  strncpy(Substr , S + SubstrBegin , *ScanPos - SubstrBegin) ;</p><p><b>  /*串尾加0*/</b></p>

64、;<p>  (Substr + *ScanPos - SubstrBegin) = '\0' ;</p><p>  ok = ((strcmp(Substr , "") != 0) && (*ScanPos) <= len) ;</p><p><b>  }</b></p>&

65、lt;p>  int GetSubstr_BetweenDelim(char *S , int *ScanPos , char Delim1 , char Delim2 , char *Substr);</p><p>  此函數(shù)在串S中掃描起點,取出在分隔符Delim1和Delim2之間的子串Substr,并且移動掃描起點到新的位置,用于詞法分析。偽碼如下:</p><p>  i

66、nt GetSubstr_BetweenDelim(char *S , int *ScanPos , char Delim1 , char Delim2 , char *Substr)</p><p><b>  {</b></p><p>  left = *ScanPos ;</p><p>  len = strlen(S) ;</

67、p><p>  if(len == 0)</p><p><b>  {</b></p><p>  *Substr = '\0' ;</p><p>  return (TURE) ;</p><p><b>  }</b></p><p&g

68、t;  /*驗明左邊的分隔符*/</p><p>  while((left < len) && (Delim1 != S[left]))</p><p><b>  ++left ;</b></p><p>  if(S[left] != Delim1)</p><p>  return 0 ;&

69、lt;/p><p>  right = left + 1 ;</p><p>  /*驗明右邊的分隔符*/</p><p>  while((right < len) && S[right] != Delim2)</p><p><b>  ++right ;</b></p><p&

70、gt;  if(S[right] != Delim2)</p><p>  return 0 ;</p><p><b>  /*復(fù)制子串*/</b></p><p>  strncpy(Sunstr , &S[left + 1] , right - left + 1) ;</p><p>  Substr[ri

71、ght - left + 1] = '\0' ;</p><p><b>  /*移動掃描點*/</b></p><p>  *ScanPos = right + 1 ;</p><p><b>  }</b></p><p>  int GetSunstr_ValidChar(ch

72、ar *S , int *ScanPos , char *ValidCh , char *Substr);</p><p>  此函數(shù)在串S中掃描起點后,取出由合法字符集合ValidCh組成的子串Substr,并且移動掃描點到新的位置,用于詞法分析。偽碼如下:</p><p>  int GetSunstr_ValidChar(char *S , int *ScanPos , char *

73、ValidCh , char *Substr)</p><p><b>  {</b></p><p>  len = strlen(S) ;</p><p>  *Substr = '\0' ;</p><p>  while((*ScanPos < len) && (strchr

74、(ValidCh , S[ScanPos])) == NULL) </p><p>  ++ (*ScanPos) ;</p><p>  left = *ScanPos ;</p><p>  while((*ScanPos < len) && (strchr(ValidCh , S[ScanPos])) != NULL)</p>

75、<p>  ++ (*ScanPos) ;</p><p><b>  /*復(fù)制子串*/</b></p><p>  strncpy(Substr , &S[left] , *ScanPos - left) ;</p><p>  Substr[*ScanPos - left] = '\0' ;</p

76、><p>  return (*ScanPos - left) ;</p><p><b>  }</b></p><p>  void CloseWA();</p><p>  此函數(shù)用于關(guān)閉工作區(qū)間;</p><p>  void ClearCmdRec (CmdRec_Type CmdRec);

77、</p><p>  此函數(shù)用于把命令行記錄,即分析結(jié)果清0;</p><p>  void CallbackCmdRec (CmdRec_Type CmdRec);</p><p>  此函數(shù)用于回收分配的指針空間并清0;</p><p>  FieldInfor_T ToFldStr(char *Token , int i);</p

78、><p>  此函數(shù)通過字符串string,分別對各個參數(shù)進行賦值;</p><p>  FieldInfor_T StoreToStr(char *Token , int i);</p><p>  此函數(shù)將第i個字段信息數(shù)組Token的字段名、字段類型,整數(shù)和小數(shù)長度存入結(jié)構(gòu)中,供建表時使用;</p><p>  FieldInfor_T *

79、Change(char *Token1);</p><p>  此函數(shù)用于將字段信息放入CmdRec的字段結(jié)構(gòu)數(shù)組中;</p><p>  char (*Value(char *Token))[15][30];</p><p>  將用戶插入的記錄值分別存入CmdRec結(jié)構(gòu)的recvalptr中,供插入時使用;</p><p>  以上函數(shù)均

80、在lexical_too.c中進行了實現(xiàn)。SQL命令編譯器對用戶命令進行掃描,調(diào)用以上函數(shù)實現(xiàn)基本的詞法分析。先根據(jù)第一個字符判斷該記號可能是什么類型,然后根據(jù)好的規(guī)則繼續(xù)分析,直到遇到一個新的記號類型。</p><p><b>  語法分析器</b></p><p>  語法分析器依據(jù)SQL語言的相關(guān)規(guī)則,對由詞法分析器返回的記號序列進行分析。語法分析器和詞法分析類

81、似,不過語法分析器是在詞法分析的基礎(chǔ)上,對一系列記號進行分析。</p><p>  MyDB的語法分析過程圖如下:</p><p><b>  圖6 語法分析</b></p><p><b>  語法分析過程如下:</b></p><p>  刪除用戶命令中的詞頭尾的空格、制表符等無關(guān)元素;<

82、/p><p>  掃描用戶命令,判斷其詞性并做相應(yīng)的處理,直到掃描到用戶命令的結(jié)尾;</p><p>  實現(xiàn)語法分析器相應(yīng)的函數(shù)體CmdRec_Type CmdLine_To_CmdRec (char *CmdLine)的偽碼表示為:</p><p>  CmdRec_Type CmdLine_To_CmdRec (char *CmdLine)</p>

83、<p><b>  {</b></p><p>  /*刪除命令行頭尾空格及制表符,并取得括號之間的字符串;*/</p><p>  CutBlankTab_Head_Tail(CmdLine) ;</p><p>  GetSubstr_BetweenDelim (CmdLine , &TokenPos , '(&#

84、39; , ')' , CmdRec.token) ;</p><p>  while(strlen(CmdLine) >= 1)</p><p><b>  {</b></p><p>  for(i = 0 ; i < strlen(Cmdline) ; i ++)</p><p><

85、;b>  {</b></p><p>  if(判斷是否為行為動詞)</p><p>  /*存儲此關(guān)鍵字*/</p><p>  CmdRec.Cmd = SysKeyWordArray[i].SysW_N ;</p><p>  else if(判斷是否為介詞)</p><p><b>

86、  /*存儲此介詞*/</b></p><p>  strcpy(CmdRec.parse , Token) ;</p><p>  else if(判斷是否為表達式)</p><p>  ptr = strchr(Token , '=') ;</p><p><b>  if (ptr)</b&g

87、t;</p><p><b>  {</b></p><p>  strcpy(CmdRec.expression , Token) ;</p><p><b>  }</b></p><p><b>  else</b></p><p><b&g

88、t;  {</b></p><p>  /*判斷是否為全部范圍*/</p><p>  ptr = strchr(Token , '*') ;</p><p><b>  if(ptr)</b></p><p><b>  {</b></p><p&g

89、t;  strcpy(CmdRec.range , '*') ;</p><p><b>  }</b></p><p><b>  else</b></p><p><b>  {</b></p><p>  ptr = strchr(Token , '

90、;,') ;</p><p><b>  if(ptr)</b></p><p><b>  {</b></p><p>  strcpy(CmdRec.range , Token) ;</p><p><b>  }</b></p><p>&

91、lt;b>  else</b></p><p><b>  {</b></p><p>  strcpy(CmdRec.userstr , Token) ;</p><p><b>  }</b></p><p><b>  }</b></p>

92、<p><b>  }</b></p><p><b>  }</b></p><p><b>  }</b></p><p><b>  return ;</b></p><p><b>  }</b></p>

93、<p>  對具體SQL語句的語法的判斷在Mydb.c中進行處理。相應(yīng)的偽碼表示如下:</p><p>  int main(void)</p><p><b>  {</b></p><p>  swich(CmdRec.Cmd)</p><p><b>  {</b></p&

94、gt;<p>  case CREATE:Do_Create(CmdRec) ;break</p><p>  case DROP:Do_Remove(CmdRec.userstr) ;break;</p><p>  case INSERT:Do_Insert(CmdRec) ;break;</p><p>  case SELECT:Do

95、_Select(CmdRec,CmdRec.token) ;break;</p><p>  case UPDATE:Do_Update(CmdRec,CmdRec.token);break;</p><p>  case DELETE:Do_Delete(CmdRec,CmdRec.token);break;</p><p>  case EXIT:exi

96、t(0);break;</p><p>  case HELP:Do_Help;break;</p><p>  default:break;</p><p><b>  }</b></p><p><b>  return 0;</b></p><p><b&

97、gt;  }</b></p><p><b>  SQL語句的實現(xiàn)</b></p><p>  MyDB所支持的SQL語句大體遵從標(biāo)準(zhǔn)的SQL語句的規(guī)范。在其規(guī)范上有稍許變動。MyDB支持標(biāo)準(zhǔn)SQL語句的一個子集,具體所支持的SQL語句的行為動詞是:create、select、drop、delete、update、insert等。</p>&

98、lt;p>  SQL語句的接口函數(shù)均包含在mysql.h頭文件中,在mysql.c中進行具體的實現(xiàn)。接口函數(shù)如下:</p><p>  int Do_Remove(char *file) ;</p><p>  刪除文件,相當(dāng)于Drop語句;</p><p>  void Do_Insert(CmdRec_Type CmdRec) ;</p>&

99、lt;p>  插入語句,將要插入的值放入表內(nèi),插入語句的實現(xiàn)過程如下圖:</p><p>  圖7 Insert語句實現(xiàn)過程</p><p><b>  偽碼實現(xiàn)如下:</b></p><p>  void Do_Insert(CmdRec_Type CmdRec)</p><p><b>  {<

100、/b></p><p><b>  定位頭文件;</b></p><p><b>  讀取一級數(shù)據(jù)元;</b></p><p>  讀取二級數(shù)據(jù)元,即各字段信息;</p><p>  for(i = 0 ; i < 插入字段數(shù) ; i ++)</p><p>&l

101、t;b>  {</b></p><p>  /*根據(jù)不同情況將要出入的記錄值寫入文件;*/</p><p>  if(插入的屬性值為float)</p><p>  將此float類型字段值插入表中;</p><p>  else if(插入的屬性值為int)</p><p>  將此int類型字段值

102、插入表中;</p><p>  else (插入的屬性值為char)</p><p>  將此char類型字段值插入表中;</p><p><b>  }</b></p><p>  每插入一條記錄,記錄總數(shù)加1;</p><p><b>  關(guān)閉數(shù)據(jù)文件;</b></

103、p><p><b>  }</b></p><p>  void Do_Select (CmdRec_Type CmdRec , char *Token);</p><p>  查詢語句,根據(jù)不同的情況實現(xiàn)對數(shù)據(jù)的簡單查詢,SELECT函數(shù)的分析過程如下圖:</p><p>  圖8 Select語句實現(xiàn)過程</p&g

104、t;<p><b>  偽碼如下:</b></p><p>  void Do_Select(CmdRec_Type CmdRec , char *Token)</p><p><b>  {</b></p><p>  取得運算符在查詢條件數(shù)組中的位置;</p><p>  把數(shù)據(jù)文

105、件一二級原數(shù)據(jù)載入工作區(qū);</p><p>  取得查詢條件中字段相對應(yīng)的本記錄首位置的長度以便定位;</p><p>  for(m = 0 ; m < reordtotal ; m ++)</p><p><b>  {</b></p><p>  逐一從文件讀取每一條記錄;</p><p&

106、gt;  根據(jù)字段類型讀取記錄值;</p><p><b>  swich(ch)</b></p><p><b>  {</b></p><p>  /**根據(jù)記錄類型對取出的記錄值進行處理即滿足條件的記錄輸出到屏幕**/</p><p><b>  case 整形:</b>

107、</p><p>  該整型數(shù)據(jù)滿足條件,定位文件至該記錄頭位置;</p><p>  逐一輸出該記錄字段值;</p><p><b>  break;</b></p><p><b>  case 浮點形:</b></p><p>  該浮點型數(shù)據(jù)滿足條件,定位文件至該記錄

108、頭位置;</p><p>  逐一輸出該記錄字段值;</p><p><b>  break;</b></p><p><b>  case 字符型:</b></p><p>  該字符型數(shù)據(jù)滿足條件,定位文件至該記錄頭位置;</p><p>  逐一輸出該記錄字段值;<

109、;/p><p><b>  break;</b></p><p>  default:break;</p><p><b>  }</b></p><p><b>  }</b></p><p><b>  關(guān)閉數(shù)據(jù)文件;</b><

110、;/p><p><b>  }</b></p><p>  void Do_Delete(CmdRec_Type CmdRec , char *Token);</p><p>  對基本表的數(shù)據(jù)的刪除。MyDB的刪除函數(shù)的分析過程如下圖:</p><p>  圖9 Delete語句實現(xiàn)過程</p><p&

111、gt;<b>  偽碼如下:</b></p><p>  void Do_Delete(CmdRec_Type CmdRec , char *Token)</p><p><b>  {</b></p><p><b>  打開數(shù)據(jù)文件;</b></p><p>  for(m

112、 = 0 ; m < recordtotal ; m ++)</p><p><b>  {</b></p><p><b>  swich(ch)</b></p><p><b>  {</b></p><p>  /**根據(jù)刪除條件字段的類型的不同,分流處理**/&l

113、t;/p><p><b>  case 整形:</b></p><p>  滿足刪除條件顯示的屏幕;</p><p>  不滿足刪除條件的寫入臨時新文件;</p><p><b>  break;</b></p><p><b>  case 浮點形:</b>

114、;</p><p>  滿足刪除條件顯示的屏幕;</p><p>  不滿足刪除條件的寫入臨時新文件;</p><p><b>  break;</b></p><p><b>  case 字符型:</b></p><p>  滿足刪除條件顯示的屏幕;</p>

115、<p>  不滿足刪除條件的寫入臨時新文件;</p><p><b>  break;</b></p><p>  default:break;</p><p><b>  }</b></p><p><b>  }</b></p><p>

116、<b>  關(guān)閉數(shù)據(jù)文件;</b></p><p><b>  }</b></p><p>  void Do_Update(CmdRec_Type CmdRec,char *Token);</p><p>  更新數(shù)據(jù)庫中的數(shù)據(jù)。MyDB中的Update函數(shù)分析過程如下圖:</p><p>  圖

117、10 Update語句實現(xiàn)過程</p><p><b>  偽碼如下:</b></p><p>  void Do_Update(CmdRec_Type CmdRec , char *Token)</p><p><b>  {</b></p><p><b>  打開數(shù)據(jù)文件 ;<

118、/b></p><p>  for(m = 0 ; m < recordtotal ; m ++)</p><p><b>  {</b></p><p>  /**根據(jù)字段的不同進行分流處理**/</p><p><b>  swich(ch)</b></p><p

119、><b>  {</b></p><p><b>  case 整形:</b></p><p>  將滿足更新條件的進行更新并現(xiàn)實在屏幕;</p><p>  不滿足條件的寫入臨時文件;</p><p><b>  break;</b></p><p&

120、gt;<b>  case 浮點形:</b></p><p>  將滿足更新條件的進行更新并現(xiàn)實在屏幕;</p><p>  不滿足條件的寫入臨時文件;</p><p><b>  break;</b></p><p><b>  case 字符型:</b></p>

121、<p>  將滿足更新條件的進行更新并現(xiàn)實在屏幕;</p><p>  不滿足條件的寫入臨時文件;</p><p><b>  break;</b></p><p>  default:break;</p><p><b>  }</b></p><p><

122、;b>  }</b></p><p><b>  關(guān)閉數(shù)據(jù)文件;</b></p><p><b>  }</b></p><p>  void Do_Help();</p><p>  幫助文檔,在這里就不再贅述。</p><p>  void Do_Cre

123、ate(CmdRec_Type CmdRec) ;</p><p>  創(chuàng)建基本表。參見基本表模塊設(shè)計。</p><p><b>  基本表模塊</b></p><p>  基本表是關(guān)系數(shù)據(jù)庫的基礎(chǔ),沒有基本表提供的路徑無關(guān)的存儲支持,所有基于基本表的操作都將難以實現(xiàn)。基本表模塊本身就可以看做是一個表式的系統(tǒng)。</p><p

124、>  基本表模塊負(fù)責(zé)把整個數(shù)據(jù)以表的方式來管理,用戶可以通過關(guān)系名、主鍵的值以及屬性名的關(guān)聯(lián)地址唯一地操控表中的任何數(shù)據(jù)?;颈砟K在提供關(guān)聯(lián)地址支持的同時,也提供基本表的其他操作?;颈淼某S貌僮饔校簞?chuàng)建、刪除一個表,添加、刪除一個記錄,添加 、刪除一個列等。關(guān)于數(shù)據(jù)庫的操作本來不應(yīng)該是屬于基本表模塊的。但是數(shù)據(jù)庫由基本表組成,基本表和數(shù)據(jù)庫的關(guān)系太緊密了,如果要將數(shù)據(jù)庫的操作單獨分離成一個模塊,那它不可避免地要訪問基本表的內(nèi)部

125、數(shù)據(jù),那樣反而造成不安全。因此,在MyDB中將數(shù)據(jù)庫的操作和基本表的操作放在一個模塊實現(xiàn)。</p><p>  在MyDB中,每一個表即對應(yīng)一個文件,表中的數(shù)據(jù)按照順序表的數(shù)據(jù)結(jié)構(gòu)進行存儲、刪除、更新等等。</p><p><b>  數(shù)據(jù)組織</b></p><p>  在MyDB中,將多個表實現(xiàn)在一起,對應(yīng)一個數(shù)據(jù)庫。每個表的基本屬性信息,

126、包括表的名稱、列的名稱、列的數(shù)據(jù)類型等都統(tǒng)一存放在一個二進制文件中。將表屬性放在一個文件中的目的是為了方便查找表的信息。</p><p>  MyDB的表的數(shù)據(jù)組織方式如下:</p><p>  圖11 MyDB表的組織方式圖</p><p><b>  基本表的實現(xiàn)</b></p><p>  基本表的接口函數(shù)定義在t

127、able.h頭文件中,具體實現(xiàn)是在table.c文件中。至于刪除一個表、在表中對數(shù)據(jù)進行刪除、插入、更新等操作,在命令行解析模塊中進行了具體的講解,這里就不再贅述。</p><p>  MyDB的基本表的實現(xiàn)過程如下圖所示:</p><p>  圖12 基本表的實現(xiàn)過程</p><p><b>  打開文件;</b></p>&l

128、t;p>  若打開文件失敗則輸出文件不存在;若成功則計算記錄長度,直到掃描所有字段結(jié)束;</p><p><b>  將數(shù)據(jù)寫入文件;</b></p><p><b>  關(guān)閉文件指針。</b></p><p>  創(chuàng)建基本表的接口函數(shù)為:</p><p>  void Do_Create (

129、CmdRec_Type CmdRec);</p><p><b>  偽碼如下:</b></p><p>  void Do_Create(CmdRec_Type CmdRec)</p><p><b>  {</b></p><p><b>  FILE fp ;</b>&l

130、t;/p><p>  int string[3] = {0,0,0} ;</p><p><b>  /*打開文件*/</b></p><p>  fp = fopen(TemName , "w + b") ;</p><p>  if(fp == NULL)</p><p&g

131、t;<b>  {</b></p><p>  printf("文件不存在\n") ;</p><p><b>  }</b></p><p>  for(i = 0 ; i <= CmdRec.count ; i ++)</p><p><b>  {</

132、b></p><p><b>  計算記錄的長度;</b></p><p><b>  }</b></p><p><b>  /*記錄長度*/</b></p><p>  string[0] = reclen ;</p><p>  /*字段數(shù)

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論