1## @file
2# This file is used to create a database used by ECC tool
3#
4# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
5# SPDX-License-Identifier: BSD-2-Clause-Patent
6#
7
8##
9# Import Modules
10#
11from __future__ import absolute_import
12import sqlite3
13import Common.LongFilePathOs as os, time
14
15import Common.EdkLogger as EdkLogger
16import CommonDataClass.DataClass as DataClass
17
18from Table.TableDataModel import TableDataModel
19from Table.TableFile import TableFile
20from Table.TableFunction import TableFunction
21from Table.TablePcd import TablePcd
22from Table.TableIdentifier import TableIdentifier
23from Table.TableReport import TableReport
24from Ecc.MetaFileWorkspace.MetaFileTable import ModuleTable
25from Ecc.MetaFileWorkspace.MetaFileTable import PackageTable
26from Ecc.MetaFileWorkspace.MetaFileTable import PlatformTable
27from Table.TableFdf import TableFdf
28
29##
30# Static definitions
31#
32DATABASE_PATH = "Ecc.db"
33
34## Database
35#
36# This class defined the ECC database
37# During the phase of initialization, the database will create all tables and
38# insert all records of table DataModel
39#
40# @param object:    Inherited from object class
41# @param DbPath:    A string for the path of the ECC database
42#
43# @var Conn:        Connection of the ECC database
44# @var Cur:         Cursor of the connection
45# @var TblDataModel:  Local instance for TableDataModel
46#
47class Database(object):
48    def __init__(self, DbPath):
49        self.DbPath = DbPath
50        self.Conn = None
51        self.Cur = None
52        self.TblDataModel = None
53        self.TblFile = None
54        self.TblFunction = None
55        self.TblIdentifier = None
56        self.TblPcd = None
57        self.TblReport = None
58        self.TblInf = None
59        self.TblDec = None
60        self.TblDsc = None
61        self.TblFdf = None
62
63    ## Initialize ECC database
64    #
65    # 1. Delete all old existing tables
66    # 2. Create new tables
67    # 3. Initialize table DataModel
68    #
69    def InitDatabase(self, NewDatabase = True):
70        EdkLogger.verbose("\nInitialize ECC database started ...")
71        #
72        # Drop all old existing tables
73        #
74        if NewDatabase:
75            if os.path.exists(self.DbPath):
76                os.remove(self.DbPath)
77        self.Conn = sqlite3.connect(self.DbPath, isolation_level = 'DEFERRED')
78        self.Conn.execute("PRAGMA page_size=4096")
79        self.Conn.execute("PRAGMA synchronous=OFF")
80        # to avoid non-ascii character conversion error
81        self.Conn.text_factory = str
82        self.Cur = self.Conn.cursor()
83
84        self.TblDataModel = TableDataModel(self.Cur)
85        self.TblFile = TableFile(self.Cur)
86        self.TblFunction = TableFunction(self.Cur)
87        self.TblIdentifier = TableIdentifier(self.Cur)
88        self.TblPcd = TablePcd(self.Cur)
89        self.TblReport = TableReport(self.Cur)
90        self.TblInf = ModuleTable(self.Cur)
91        self.TblDec = PackageTable(self.Cur)
92        self.TblDsc = PlatformTable(self.Cur)
93        self.TblFdf = TableFdf(self.Cur)
94
95        #
96        # Create new tables
97        #
98        if NewDatabase:
99            self.TblDataModel.Create()
100            self.TblFile.Create()
101            self.TblFunction.Create()
102            self.TblPcd.Create()
103            self.TblReport.Create()
104            self.TblInf.Create()
105            self.TblDec.Create()
106            self.TblDsc.Create()
107            self.TblFdf.Create()
108
109        #
110        # Init each table's ID
111        #
112        self.TblDataModel.InitID()
113        self.TblFile.InitID()
114        self.TblFunction.InitID()
115        self.TblPcd.InitID()
116        self.TblReport.InitID()
117        self.TblInf.InitID()
118        self.TblDec.InitID()
119        self.TblDsc.InitID()
120        self.TblFdf.InitID()
121
122        #
123        # Initialize table DataModel
124        #
125        if NewDatabase:
126            self.TblDataModel.InitTable()
127
128        EdkLogger.verbose("Initialize ECC database ... DONE!")
129
130    ## Query a table
131    #
132    # @param Table:  The instance of the table to be queried
133    #
134    def QueryTable(self, Table):
135        Table.Query()
136
137    ## Close entire database
138    #
139    # Commit all first
140    # Close the connection and cursor
141    #
142    def Close(self):
143        #
144        # Commit to file
145        #
146        self.Conn.commit()
147
148        #
149        # Close connection and cursor
150        #
151        self.Cur.close()
152        self.Conn.close()
153
154    ## Insert one file information
155    #
156    # Insert one file's information to the database
157    # 1. Create a record in TableFile
158    # 2. Create functions one by one
159    #    2.1 Create variables of function one by one
160    #    2.2 Create pcds of function one by one
161    # 3. Create variables one by one
162    # 4. Create pcds one by one
163    #
164    def InsertOneFile(self, File):
165        #
166        # Insert a record for file
167        #
168        FileID = self.TblFile.Insert(File.Name, File.ExtName, File.Path, File.FullPath, Model = File.Model, TimeStamp = File.TimeStamp)
169
170        if File.Model == DataClass.MODEL_FILE_C or File.Model == DataClass.MODEL_FILE_H:
171            IdTable = TableIdentifier(self.Cur)
172            IdTable.Table = "Identifier%s" % FileID
173            IdTable.Create()
174            #
175            # Insert function of file
176            #
177            for Function in File.FunctionList:
178                FunctionID = self.TblFunction.Insert(Function.Header, Function.Modifier, Function.Name, Function.ReturnStatement, \
179                                        Function.StartLine, Function.StartColumn, Function.EndLine, Function.EndColumn, \
180                                        Function.BodyStartLine, Function.BodyStartColumn, FileID, \
181                                        Function.FunNameStartLine, Function.FunNameStartColumn)
182                #
183                # Insert Identifier of function
184                #
185                for Identifier in Function.IdentifierList:
186                    IdentifierID = IdTable.Insert(Identifier.Modifier, Identifier.Type, Identifier.Name, Identifier.Value, Identifier.Model, \
187                                            FileID, FunctionID, Identifier.StartLine, Identifier.StartColumn, Identifier.EndLine, Identifier.EndColumn)
188                #
189                # Insert Pcd of function
190                #
191                for Pcd in Function.PcdList:
192                    PcdID = self.TblPcd.Insert(Pcd.CName, Pcd.TokenSpaceGuidCName, Pcd.Token, Pcd.DatumType, Pcd.Model, \
193                                       FileID, FunctionID, Pcd.StartLine, Pcd.StartColumn, Pcd.EndLine, Pcd.EndColumn)
194            #
195            # Insert Identifier of file
196            #
197            for Identifier in File.IdentifierList:
198                IdentifierID = IdTable.Insert(Identifier.Modifier, Identifier.Type, Identifier.Name, Identifier.Value, Identifier.Model, \
199                                        FileID, -1, Identifier.StartLine, Identifier.StartColumn, Identifier.EndLine, Identifier.EndColumn)
200            #
201            # Insert Pcd of file
202            #
203            for Pcd in File.PcdList:
204                PcdID = self.TblPcd.Insert(Pcd.CName, Pcd.TokenSpaceGuidCName, Pcd.Token, Pcd.DatumType, Pcd.Model, \
205                                   FileID, -1, Pcd.StartLine, Pcd.StartColumn, Pcd.EndLine, Pcd.EndColumn)
206
207        EdkLogger.verbose("Insert information from file %s ... DONE!" % File.FullPath)
208
209    ## UpdateIdentifierBelongsToFunction
210    #
211    # Update the field "BelongsToFunction" for each Identifier
212    #
213    #
214    def UpdateIdentifierBelongsToFunction_disabled(self):
215        EdkLogger.verbose("Update 'BelongsToFunction' for Identifiers started ...")
216
217        SqlCommand = """select ID, BelongsToFile, StartLine, EndLine, Model from Identifier"""
218        EdkLogger.debug(4, "SqlCommand: %s" %SqlCommand)
219        self.Cur.execute(SqlCommand)
220        Records = self.Cur.fetchall()
221        for Record in Records:
222            IdentifierID = Record[0]
223            BelongsToFile = Record[1]
224            StartLine = Record[2]
225            EndLine = Record[3]
226            Model = Record[4]
227
228            #
229            # Check whether an identifier belongs to a function
230            #
231            EdkLogger.debug(4, "For common identifiers ... ")
232            SqlCommand = """select ID from Function
233                        where StartLine < %s and EndLine > %s
234                        and BelongsToFile = %s""" % (StartLine, EndLine, BelongsToFile)
235            EdkLogger.debug(4, "SqlCommand: %s" %SqlCommand)
236            self.Cur.execute(SqlCommand)
237            IDs = self.Cur.fetchall()
238            for ID in IDs:
239                SqlCommand = """Update Identifier set BelongsToFunction = %s where ID = %s""" % (ID[0], IdentifierID)
240                EdkLogger.debug(4, "SqlCommand: %s" %SqlCommand)
241                self.Cur.execute(SqlCommand)
242
243            #
244            # Check whether the identifier is a function header
245            #
246            EdkLogger.debug(4, "For function headers ... ")
247            if Model == DataClass.MODEL_IDENTIFIER_COMMENT:
248                SqlCommand = """select ID from Function
249                        where StartLine = %s + 1
250                        and BelongsToFile = %s""" % (EndLine, BelongsToFile)
251                EdkLogger.debug(4, "SqlCommand: %s" %SqlCommand)
252                self.Cur.execute(SqlCommand)
253                IDs = self.Cur.fetchall()
254                for ID in IDs:
255                    SqlCommand = """Update Identifier set BelongsToFunction = %s, Model = %s where ID = %s""" % (ID[0], DataClass.MODEL_IDENTIFIER_FUNCTION_HEADER, IdentifierID)
256                    EdkLogger.debug(4, "SqlCommand: %s" %SqlCommand)
257                    self.Cur.execute(SqlCommand)
258
259        EdkLogger.verbose("Update 'BelongsToFunction' for Identifiers ... DONE")
260
261
262    ## UpdateIdentifierBelongsToFunction
263    #
264    # Update the field "BelongsToFunction" for each Identifier
265    #
266    #
267    def UpdateIdentifierBelongsToFunction(self):
268        EdkLogger.verbose("Update 'BelongsToFunction' for Identifiers started ...")
269
270        SqlCommand = """select ID, BelongsToFile, StartLine, EndLine from Function"""
271        Records = self.TblFunction.Exec(SqlCommand)
272        Data1 = []
273        Data2 = []
274        for Record in Records:
275            FunctionID = Record[0]
276            BelongsToFile = Record[1]
277            StartLine = Record[2]
278            EndLine = Record[3]
279            #Data1.append(("'file%s'" % BelongsToFile, FunctionID, BelongsToFile, StartLine, EndLine))
280            #Data2.append(("'file%s'" % BelongsToFile, FunctionID, DataClass.MODEL_IDENTIFIER_FUNCTION_HEADER, BelongsToFile, DataClass.MODEL_IDENTIFIER_COMMENT, StartLine - 1))
281
282            SqlCommand = """Update Identifier%s set BelongsToFunction = %s where BelongsToFile = %s and StartLine > %s and EndLine < %s""" % \
283                        (BelongsToFile, FunctionID, BelongsToFile, StartLine, EndLine)
284            self.TblIdentifier.Exec(SqlCommand)
285
286            SqlCommand = """Update Identifier%s set BelongsToFunction = %s, Model = %s where BelongsToFile = %s and Model = %s and EndLine = %s""" % \
287                         (BelongsToFile, FunctionID, DataClass.MODEL_IDENTIFIER_FUNCTION_HEADER, BelongsToFile, DataClass.MODEL_IDENTIFIER_COMMENT, StartLine - 1)
288            self.TblIdentifier.Exec(SqlCommand)
289#       #
290#       # Check whether an identifier belongs to a function
291#       #
292#       print Data1
293#       SqlCommand = """Update ? set BelongsToFunction = ? where BelongsToFile = ? and StartLine > ? and EndLine < ?"""
294#       print SqlCommand
295#       EdkLogger.debug(4, "SqlCommand: %s" %SqlCommand)
296#       self.Cur.executemany(SqlCommand, Data1)
297#
298#       #
299#       # Check whether the identifier is a function header
300#       #
301#       EdkLogger.debug(4, "For function headers ... ")
302#       SqlCommand = """Update ? set BelongsToFunction = ?, Model = ? where BelongsToFile = ? and Model = ? and EndLine = ?"""
303#       EdkLogger.debug(4, "SqlCommand: %s" %SqlCommand)
304#       self.Cur.executemany(SqlCommand, Data2)
305#
306#       EdkLogger.verbose("Update 'BelongsToFunction' for Identifiers ... DONE")
307
308
309##
310#
311# This acts like the main() function for the script, unless it is 'import'ed into another
312# script.
313#
314if __name__ == '__main__':
315    EdkLogger.Initialize()
316    #EdkLogger.SetLevel(EdkLogger.VERBOSE)
317    EdkLogger.SetLevel(EdkLogger.DEBUG_0)
318    EdkLogger.verbose("Start at " + time.strftime('%H:%M:%S', time.localtime()))
319
320    Db = Database(DATABASE_PATH)
321    Db.InitDatabase()
322    Db.QueryTable(Db.TblDataModel)
323
324    identifier1 = DataClass.IdentifierClass(-1, '', '', "i''1", 'aaa', DataClass.MODEL_IDENTIFIER_COMMENT, 1, -1, 32,  43,  54,  43)
325    identifier2 = DataClass.IdentifierClass(-1, '', '', 'i1', 'aaa', DataClass.MODEL_IDENTIFIER_COMMENT, 1, -1, 15,  43,  20,  43)
326    identifier3 = DataClass.IdentifierClass(-1, '', '', 'i1', 'aaa', DataClass.MODEL_IDENTIFIER_COMMENT, 1, -1, 55,  43,  58,  43)
327    identifier4 = DataClass.IdentifierClass(-1, '', '', "i1'", 'aaa', DataClass.MODEL_IDENTIFIER_COMMENT, 1, -1, 77,  43,  88,  43)
328    fun1 = DataClass.FunctionClass(-1, '', '', 'fun1', '', 21, 2, 60,  45, 1, 23, 0, [], [])
329    file = DataClass.FileClass(-1, 'F1', 'c', 'C:\\', 'C:\\F1.exe', DataClass.MODEL_FILE_C, '2007-12-28', [fun1], [identifier1, identifier2, identifier3, identifier4], [])
330    Db.InsertOneFile(file)
331    Db.UpdateIdentifierBelongsToFunction()
332
333    Db.QueryTable(Db.TblFile)
334    Db.QueryTable(Db.TblFunction)
335    Db.QueryTable(Db.TblPcd)
336    Db.QueryTable(Db.TblIdentifier)
337
338    Db.Close()
339    EdkLogger.verbose("End at " + time.strftime('%H:%M:%S', time.localtime()))
340
341