1## @file
2# This file is used to create a database used by EOT tool
3#
4# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
5# This program and the accompanying materials
6# are licensed and made available under the terms and conditions of the BSD License
7# which accompanies this distribution.  The full text of the license may be found at
8# http://opensource.org/licenses/bsd-license.php
9#
10# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12#
13
14##
15# Import Modules
16#
17import sqlite3
18import Common.LongFilePathOs as os, time
19
20import Common.EdkLogger as EdkLogger
21import CommonDataClass.DataClass as DataClass
22
23from Table.TableDataModel import TableDataModel
24from Table.TableFile import TableFile
25from Table.TableFunction import TableFunction
26from Table.TableIdentifier import TableIdentifier
27from Table.TableEotReport import TableEotReport
28from Table.TableInf import TableInf
29from Table.TableDec import TableDec
30from Table.TableDsc import TableDsc
31from Table.TableFdf import TableFdf
32from Table.TableQuery import TableQuery
33
34##
35# Static definitions
36#
37DATABASE_PATH = "Eot.db"
38
39## Database class
40#
41# This class defined the EOT databse
42# During the phase of initialization, the database will create all tables and
43# insert all records of table DataModel
44#
45class Database(object):
46    ## The constructor
47    #
48    #   @param  self:      The object pointer
49    #   @param  DbPath:    The file path of the database
50    #
51    def __init__(self, DbPath):
52        self.DbPath = DbPath
53        self.Conn = None
54        self.Cur = None
55        self.TblDataModel = None
56        self.TblFile = None
57        self.TblFunction = None
58        self.TblIdentifier = None
59        self.TblReport = None
60        self.TblInf = None
61        self.TblDec = None
62        self.TblDsc = None
63        self.TblFdf = None
64        self.TblQuery = None
65        self.TblQuery2 = None
66
67    ## InitDatabase() method
68    #  1. Delete all old existing tables
69    #  2. Create new tables
70    #  3. Initialize table DataModel
71    #
72    #  @param self: The object pointer
73    #  @param NewDatabase: Check if it needs to create a new database
74    #
75    def InitDatabase(self, NewDatabase = True):
76        EdkLogger.verbose("\nInitialize EOT database started ...")
77        #
78        # Drop all old existing tables
79        #
80        if NewDatabase:
81            if os.path.exists(self.DbPath):
82                os.remove(self.DbPath)
83        self.Conn = sqlite3.connect(self.DbPath, isolation_level = 'DEFERRED')
84        self.Conn.execute("PRAGMA page_size=8192")
85        self.Conn.execute("PRAGMA synchronous=OFF")
86        # to avoid non-ascii charater conversion error
87        self.Conn.text_factory = str
88        self.Cur = self.Conn.cursor()
89
90        self.TblDataModel = TableDataModel(self.Cur)
91        self.TblFile = TableFile(self.Cur)
92        self.TblFunction = TableFunction(self.Cur)
93        self.TblIdentifier = TableIdentifier(self.Cur)
94        self.TblReport = TableEotReport(self.Cur)
95        self.TblInf = TableInf(self.Cur)
96        self.TblDec = TableDec(self.Cur)
97        self.TblDsc = TableDsc(self.Cur)
98        self.TblFdf = TableFdf(self.Cur)
99        self.TblQuery = TableQuery(self.Cur)
100        self.TblQuery2 = TableQuery(self.Cur)
101        self.TblQuery2.Table = 'Query2'
102
103        # Create new tables
104        if NewDatabase:
105            self.TblDataModel.Create()
106            self.TblFile.Create()
107            self.TblFunction.Create()
108            self.TblReport.Create()
109            self.TblInf.Create()
110            self.TblDec.Create()
111            self.TblDsc.Create()
112            self.TblFdf.Create()
113            self.TblQuery.Create()
114            self.TblQuery2.Create()
115
116        # Init each table's ID
117        self.TblDataModel.InitID()
118        self.TblFile.InitID()
119        self.TblFunction.InitID()
120        self.TblReport.InitID()
121        self.TblInf.InitID()
122        self.TblDec.InitID()
123        self.TblDsc.InitID()
124        self.TblFdf.InitID()
125        self.TblQuery.Drop()
126        self.TblQuery.Create()
127        self.TblQuery.InitID()
128        self.TblQuery2.Drop()
129        self.TblQuery2.Create()
130        self.TblQuery2.InitID()
131
132        # Initialize table DataModel
133        if NewDatabase:
134            self.TblDataModel.InitTable()
135
136        EdkLogger.verbose("Initialize EOT database ... DONE!")
137
138    ## QueryTable() method
139    #
140    #  Query a table
141    #
142    #  @param self: The object pointer
143    #  @param Table: The instance of the table to be queried
144    #
145    def QueryTable(self, Table):
146        Table.Query()
147
148    ## Close() method
149    #
150    # Commit all first
151    # Close the connection and cursor
152    #
153    def Close(self):
154        # Commit to file
155        self.Conn.commit()
156
157        # Close connection and cursor
158        self.Cur.close()
159        self.Conn.close()
160
161    ## InsertOneFile() method
162    #
163    # Insert one file's information to the database
164    # 1. Create a record in TableFile
165    # 2. Create functions one by one
166    #    2.1 Create variables of function one by one
167    #    2.2 Create pcds of function one by one
168    # 3. Create variables one by one
169    # 4. Create pcds one by one
170    #
171    # @param self: The object pointer
172    # @param File: The object of the file to be inserted
173    #
174    def InsertOneFile(self, File):
175        # Insert a record for file
176        FileID = self.TblFile.Insert(File.Name, File.ExtName, File.Path, File.FullPath, Model = File.Model, TimeStamp = File.TimeStamp)
177        IdTable = TableIdentifier(self.Cur)
178        IdTable.Table = "Identifier%s" % FileID
179        IdTable.Create()
180
181        # Insert function of file
182        for Function in File.FunctionList:
183            FunctionID = self.TblFunction.Insert(Function.Header, Function.Modifier, Function.Name, Function.ReturnStatement, \
184                                    Function.StartLine, Function.StartColumn, Function.EndLine, Function.EndColumn, \
185                                    Function.BodyStartLine, Function.BodyStartColumn, FileID, \
186                                    Function.FunNameStartLine, Function.FunNameStartColumn)
187
188            # Insert Identifier of function
189            for Identifier in Function.IdentifierList:
190                IdentifierID = IdTable.Insert(Identifier.Modifier, Identifier.Type, Identifier.Name, Identifier.Value, Identifier.Model, \
191                                        FileID, FunctionID, Identifier.StartLine, Identifier.StartColumn, Identifier.EndLine, Identifier.EndColumn)
192        # Insert Identifier of file
193        for Identifier in File.IdentifierList:
194            IdentifierID = IdTable.Insert(Identifier.Modifier, Identifier.Type, Identifier.Name, Identifier.Value, Identifier.Model, \
195                                    FileID, -1, Identifier.StartLine, Identifier.StartColumn, Identifier.EndLine, Identifier.EndColumn)
196
197        EdkLogger.verbose("Insert information from file %s ... DONE!" % File.FullPath)
198
199    ## UpdateIdentifierBelongsToFunction() method
200    #
201    #  Update the field "BelongsToFunction" for each Indentifier
202    #
203    #  @param self: The object pointer
204    #
205    def UpdateIdentifierBelongsToFunction(self):
206        EdkLogger.verbose("Update 'BelongsToFunction' for Identifiers started ...")
207
208        SqlCommand = """select ID, BelongsToFile, StartLine, EndLine from Function"""
209        Records = self.TblFunction.Exec(SqlCommand)
210        Data1 = []
211        Data2 = []
212        for Record in Records:
213            FunctionID = Record[0]
214            BelongsToFile = Record[1]
215            StartLine = Record[2]
216            EndLine = Record[3]
217
218            SqlCommand = """Update Identifier%s set BelongsToFunction = %s where BelongsToFile = %s and StartLine > %s and EndLine < %s""" % \
219                        (BelongsToFile, FunctionID, BelongsToFile, StartLine, EndLine)
220            self.TblIdentifier.Exec(SqlCommand)
221
222            SqlCommand = """Update Identifier%s set BelongsToFunction = %s, Model = %s where BelongsToFile = %s and Model = %s and EndLine = %s""" % \
223                         (BelongsToFile, FunctionID, DataClass.MODEL_IDENTIFIER_FUNCTION_HEADER, BelongsToFile, DataClass.MODEL_IDENTIFIER_COMMENT, StartLine - 1)
224            self.TblIdentifier.Exec(SqlCommand)
225
226
227##
228#
229# This acts like the main() function for the script, unless it is 'import'ed into another
230# script.
231#
232if __name__ == '__main__':
233    EdkLogger.Initialize()
234    EdkLogger.SetLevel(EdkLogger.DEBUG_0)
235    EdkLogger.verbose("Start at " + time.strftime('%H:%M:%S', time.localtime()))
236
237    Db = Database(DATABASE_PATH)
238    Db.InitDatabase()
239    Db.QueryTable(Db.TblDataModel)
240
241    identifier1 = DataClass.IdentifierClass(-1, '', '', "i''1", 'aaa', DataClass.MODEL_IDENTIFIER_COMMENT, 1, -1, 32,  43,  54,  43)
242    identifier2 = DataClass.IdentifierClass(-1, '', '', 'i1', 'aaa', DataClass.MODEL_IDENTIFIER_COMMENT, 1, -1, 15,  43,  20,  43)
243    identifier3 = DataClass.IdentifierClass(-1, '', '', 'i1', 'aaa', DataClass.MODEL_IDENTIFIER_COMMENT, 1, -1, 55,  43,  58,  43)
244    identifier4 = DataClass.IdentifierClass(-1, '', '', "i1'", 'aaa', DataClass.MODEL_IDENTIFIER_COMMENT, 1, -1, 77,  43,  88,  43)
245    fun1 = DataClass.FunctionClass(-1, '', '', 'fun1', '', 21, 2, 60,  45, 1, 23, 0, [], [])
246    file = DataClass.FileClass(-1, 'F1', 'c', 'C:\\', 'C:\\F1.exe', DataClass.MODEL_FILE_C, '2007-12-28', [fun1], [identifier1, identifier2, identifier3, identifier4], [])
247    Db.InsertOneFile(file)
248
249    Db.QueryTable(Db.TblFile)
250    Db.QueryTable(Db.TblFunction)
251    Db.QueryTable(Db.TblIdentifier)
252
253    Db.Close()
254    EdkLogger.verbose("End at " + time.strftime('%H:%M:%S', time.localtime()))
255
256