ee1c7fffca3b36923f72ba37e5995170743a282e
[mirror_edk2.git] / BaseTools / Source / Python / Workspace / MetaFileTable.py
1 ## @file
2 # This file is used to create/update/query/erase a meta file table
3 #
4 # Copyright (c) 2008 - 2018, 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 #
17 import uuid
18
19 import Common.EdkLogger as EdkLogger
20 from Common.BuildToolError import FORMAT_INVALID
21
22 from MetaDataTable import Table, TableFile
23 from MetaDataTable import ConvertToSqlString
24 from CommonDataClass.DataClass import MODEL_FILE_DSC, MODEL_FILE_DEC, MODEL_FILE_INF, \
25 MODEL_FILE_OTHERS
26 from Common.DataType import *
27
28 class MetaFileTable(Table):
29 # TRICK: use file ID as the part before '.'
30 _ID_STEP_ = 0.00000001
31 _ID_MAX_ = 0.99999999
32
33 ## Constructor
34 def __init__(self, Cursor, MetaFile, FileType, Temporary, FromItem=None):
35 self.MetaFile = MetaFile
36
37 self._FileIndexTable = TableFile(Cursor)
38 self._FileIndexTable.Create(False)
39
40 FileId = self._FileIndexTable.GetFileId(MetaFile, FromItem)
41 if not FileId:
42 FileId = self._FileIndexTable.InsertFile(MetaFile, FileType, FromItem)
43
44 if Temporary:
45 TableName = "_%s_%s_%s" % (FileType, FileId, uuid.uuid4().hex)
46 else:
47 TableName = "_%s_%s" % (FileType, FileId)
48
49 #Table.__init__(self, Cursor, TableName, FileId, False)
50 Table.__init__(self, Cursor, TableName, FileId, Temporary)
51 self.Create(not self.IsIntegrity())
52
53 def IsIntegrity(self):
54 try:
55 TimeStamp = self.MetaFile.TimeStamp
56 Result = self.Cur.execute("select ID from %s where ID<0" % (self.Table)).fetchall()
57 if not Result:
58 # update the timestamp in database
59 self._FileIndexTable.SetFileTimeStamp(self.IdBase, TimeStamp)
60 return False
61
62 if TimeStamp != self._FileIndexTable.GetFileTimeStamp(self.IdBase):
63 # update the timestamp in database
64 self._FileIndexTable.SetFileTimeStamp(self.IdBase, TimeStamp)
65 return False
66 except Exception as Exc:
67 EdkLogger.debug(EdkLogger.DEBUG_5, str(Exc))
68 return False
69 return True
70
71 ## Python class representation of table storing module data
72 class ModuleTable(MetaFileTable):
73 _ID_STEP_ = 0.00000001
74 _ID_MAX_ = 0.99999999
75 _COLUMN_ = '''
76 ID REAL PRIMARY KEY,
77 Model INTEGER NOT NULL,
78 Value1 TEXT NOT NULL,
79 Value2 TEXT,
80 Value3 TEXT,
81 Scope1 TEXT,
82 Scope2 TEXT,
83 BelongsToItem REAL NOT NULL,
84 StartLine INTEGER NOT NULL,
85 StartColumn INTEGER NOT NULL,
86 EndLine INTEGER NOT NULL,
87 EndColumn INTEGER NOT NULL,
88 Enabled INTEGER DEFAULT 0
89 '''
90 # used as table end flag, in case the changes to database is not committed to db file
91 _DUMMY_ = "-1, -1, '====', '====', '====', '====', '====', -1, -1, -1, -1, -1, -1"
92
93 ## Constructor
94 def __init__(self, Cursor, MetaFile, Temporary):
95 MetaFileTable.__init__(self, Cursor, MetaFile, MODEL_FILE_INF, Temporary)
96
97 ## Insert a record into table Inf
98 #
99 # @param Model: Model of a Inf item
100 # @param Value1: Value1 of a Inf item
101 # @param Value2: Value2 of a Inf item
102 # @param Value3: Value3 of a Inf item
103 # @param Scope1: Arch of a Inf item
104 # @param Scope2 Platform os a Inf item
105 # @param BelongsToItem: The item belongs to which another item
106 # @param StartLine: StartLine of a Inf item
107 # @param StartColumn: StartColumn of a Inf item
108 # @param EndLine: EndLine of a Inf item
109 # @param EndColumn: EndColumn of a Inf item
110 # @param Enabled: If this item enabled
111 #
112 def Insert(self, Model, Value1, Value2, Value3, Scope1=TAB_ARCH_COMMON, Scope2=TAB_COMMON,
113 BelongsToItem=-1, StartLine=-1, StartColumn=-1, EndLine=-1, EndColumn=-1, Enabled=0):
114 (Value1, Value2, Value3, Scope1, Scope2) = ConvertToSqlString((Value1, Value2, Value3, Scope1, Scope2))
115 return Table.Insert(
116 self,
117 Model,
118 Value1,
119 Value2,
120 Value3,
121 Scope1,
122 Scope2,
123 BelongsToItem,
124 StartLine,
125 StartColumn,
126 EndLine,
127 EndColumn,
128 Enabled
129 )
130
131 ## Query table
132 #
133 # @param Model: The Model of Record
134 # @param Arch: The Arch attribute of Record
135 # @param Platform The Platform attribute of Record
136 #
137 # @retval: A recordSet of all found records
138 #
139 def Query(self, Model, Arch=None, Platform=None, BelongsToItem=None):
140 ConditionString = "Model=%s AND Enabled>=0" % Model
141 ValueString = "Value1,Value2,Value3,Scope1,Scope2,ID,StartLine"
142
143 if Arch is not None and Arch != TAB_ARCH_COMMON:
144 ConditionString += " AND (Scope1='%s' OR Scope1='COMMON')" % Arch
145 if Platform is not None and Platform != TAB_COMMON:
146 ConditionString += " AND (Scope2='%s' OR Scope2='COMMON' OR Scope2='DEFAULT')" % Platform
147 if BelongsToItem is not None:
148 ConditionString += " AND BelongsToItem=%s" % BelongsToItem
149
150 SqlCommand = "SELECT %s FROM %s WHERE %s" % (ValueString, self.Table, ConditionString)
151 return self.Exec(SqlCommand)
152
153 ## Python class representation of table storing package data
154 class PackageTable(MetaFileTable):
155 _COLUMN_ = '''
156 ID REAL PRIMARY KEY,
157 Model INTEGER NOT NULL,
158 Value1 TEXT NOT NULL,
159 Value2 TEXT,
160 Value3 TEXT,
161 Scope1 TEXT,
162 Scope2 TEXT,
163 BelongsToItem REAL NOT NULL,
164 StartLine INTEGER NOT NULL,
165 StartColumn INTEGER NOT NULL,
166 EndLine INTEGER NOT NULL,
167 EndColumn INTEGER NOT NULL,
168 Enabled INTEGER DEFAULT 0
169 '''
170 # used as table end flag, in case the changes to database is not committed to db file
171 _DUMMY_ = "-1, -1, '====', '====', '====', '====', '====', -1, -1, -1, -1, -1, -1"
172
173 ## Constructor
174 def __init__(self, Cursor, MetaFile, Temporary):
175 MetaFileTable.__init__(self, Cursor, MetaFile, MODEL_FILE_DEC, Temporary)
176
177 ## Insert table
178 #
179 # Insert a record into table Dec
180 #
181 # @param Model: Model of a Dec item
182 # @param Value1: Value1 of a Dec item
183 # @param Value2: Value2 of a Dec item
184 # @param Value3: Value3 of a Dec item
185 # @param Scope1: Arch of a Dec item
186 # @param Scope2: Module type of a Dec item
187 # @param BelongsToItem: The item belongs to which another item
188 # @param StartLine: StartLine of a Dec item
189 # @param StartColumn: StartColumn of a Dec item
190 # @param EndLine: EndLine of a Dec item
191 # @param EndColumn: EndColumn of a Dec item
192 # @param Enabled: If this item enabled
193 #
194 def Insert(self, Model, Value1, Value2, Value3, Scope1=TAB_ARCH_COMMON, Scope2=TAB_COMMON,
195 BelongsToItem=-1, StartLine=-1, StartColumn=-1, EndLine=-1, EndColumn=-1, Enabled=0):
196 (Value1, Value2, Value3, Scope1, Scope2) = ConvertToSqlString((Value1, Value2, Value3, Scope1, Scope2))
197 return Table.Insert(
198 self,
199 Model,
200 Value1,
201 Value2,
202 Value3,
203 Scope1,
204 Scope2,
205 BelongsToItem,
206 StartLine,
207 StartColumn,
208 EndLine,
209 EndColumn,
210 Enabled
211 )
212
213 ## Query table
214 #
215 # @param Model: The Model of Record
216 # @param Arch: The Arch attribute of Record
217 #
218 # @retval: A recordSet of all found records
219 #
220 def Query(self, Model, Arch=None):
221 ConditionString = "Model=%s AND Enabled>=0" % Model
222 ValueString = "Value1,Value2,Value3,Scope1,Scope2,ID,StartLine"
223
224 if Arch is not None and Arch != TAB_ARCH_COMMON:
225 ConditionString += " AND (Scope1='%s' OR Scope1='COMMON')" % Arch
226
227 SqlCommand = "SELECT %s FROM %s WHERE %s" % (ValueString, self.Table, ConditionString)
228 return self.Exec(SqlCommand)
229
230 def GetValidExpression(self, TokenSpaceGuid, PcdCName):
231 SqlCommand = "select Value1,StartLine from %s WHERE Value2='%s' and Value3='%s'" % (self.Table, TokenSpaceGuid, PcdCName)
232 self.Cur.execute(SqlCommand)
233 validateranges = []
234 validlists = []
235 expressions = []
236 try:
237 for row in self.Cur:
238 comment = row[0]
239
240 LineNum = row[1]
241 comment = comment.strip("#")
242 comment = comment.strip()
243 oricomment = comment
244 if comment.startswith("@ValidRange"):
245 comment = comment.replace("@ValidRange", "", 1)
246 validateranges.append(comment.split("|")[1].strip())
247 if comment.startswith("@ValidList"):
248 comment = comment.replace("@ValidList", "", 1)
249 validlists.append(comment.split("|")[1].strip())
250 if comment.startswith("@Expression"):
251 comment = comment.replace("@Expression", "", 1)
252 expressions.append(comment.split("|")[1].strip())
253 except Exception as Exc:
254 ValidType = ""
255 if oricomment.startswith("@ValidRange"):
256 ValidType = "@ValidRange"
257 if oricomment.startswith("@ValidList"):
258 ValidType = "@ValidList"
259 if oricomment.startswith("@Expression"):
260 ValidType = "@Expression"
261 EdkLogger.error('Parser', FORMAT_INVALID, "The syntax for %s of PCD %s.%s is incorrect" % (ValidType, TokenSpaceGuid, PcdCName),
262 ExtraData=oricomment, File=self.MetaFile, Line=LineNum)
263 return set(), set(), set()
264 return set(validateranges), set(validlists), set(expressions)
265 ## Python class representation of table storing platform data
266 class PlatformTable(MetaFileTable):
267 _COLUMN_ = '''
268 ID REAL PRIMARY KEY,
269 Model INTEGER NOT NULL,
270 Value1 TEXT NOT NULL,
271 Value2 TEXT,
272 Value3 TEXT,
273 Scope1 TEXT,
274 Scope2 TEXT,
275 Scope3 TEXT,
276 BelongsToItem REAL NOT NULL,
277 FromItem REAL NOT NULL,
278 StartLine INTEGER NOT NULL,
279 StartColumn INTEGER NOT NULL,
280 EndLine INTEGER NOT NULL,
281 EndColumn INTEGER NOT NULL,
282 Enabled INTEGER DEFAULT 0
283 '''
284 # used as table end flag, in case the changes to database is not committed to db file
285 _DUMMY_ = "-1, -1, '====', '====', '====', '====', '====','====', -1, -1, -1, -1, -1, -1, -1"
286
287 ## Constructor
288 def __init__(self, Cursor, MetaFile, Temporary, FromItem=0):
289 MetaFileTable.__init__(self, Cursor, MetaFile, MODEL_FILE_DSC, Temporary, FromItem)
290
291 ## Insert table
292 #
293 # Insert a record into table Dsc
294 #
295 # @param Model: Model of a Dsc item
296 # @param Value1: Value1 of a Dsc item
297 # @param Value2: Value2 of a Dsc item
298 # @param Value3: Value3 of a Dsc item
299 # @param Scope1: Arch of a Dsc item
300 # @param Scope2: Module type of a Dsc item
301 # @param BelongsToItem: The item belongs to which another item
302 # @param FromItem: The item belongs to which dsc file
303 # @param StartLine: StartLine of a Dsc item
304 # @param StartColumn: StartColumn of a Dsc item
305 # @param EndLine: EndLine of a Dsc item
306 # @param EndColumn: EndColumn of a Dsc item
307 # @param Enabled: If this item enabled
308 #
309 def Insert(self, Model, Value1, Value2, Value3, Scope1=TAB_ARCH_COMMON, Scope2=TAB_COMMON, Scope3=TAB_DEFAULT_STORES_DEFAULT,BelongsToItem=-1,
310 FromItem=-1, StartLine=-1, StartColumn=-1, EndLine=-1, EndColumn=-1, Enabled=1):
311 (Value1, Value2, Value3, Scope1, Scope2, Scope3) = ConvertToSqlString((Value1, Value2, Value3, Scope1, Scope2, Scope3))
312 return Table.Insert(
313 self,
314 Model,
315 Value1,
316 Value2,
317 Value3,
318 Scope1,
319 Scope2,
320 Scope3,
321 BelongsToItem,
322 FromItem,
323 StartLine,
324 StartColumn,
325 EndLine,
326 EndColumn,
327 Enabled
328 )
329
330 ## Query table
331 #
332 # @param Model: The Model of Record
333 # @param Scope1: Arch of a Dsc item
334 # @param Scope2: Module type of a Dsc item
335 # @param BelongsToItem: The item belongs to which another item
336 # @param FromItem: The item belongs to which dsc file
337 #
338 # @retval: A recordSet of all found records
339 #
340 def Query(self, Model, Scope1=None, Scope2=None, BelongsToItem=None, FromItem=None):
341 ConditionString = "Model=%s AND Enabled>0" % Model
342 ValueString = "Value1,Value2,Value3,Scope1,Scope2,Scope3,ID,StartLine"
343
344 if Scope1 is not None and Scope1 != TAB_ARCH_COMMON:
345 ConditionString += " AND (Scope1='%s' OR Scope1='COMMON')" % Scope1
346 if Scope2 is not None and Scope2 != TAB_COMMON:
347 # Cover the case that CodeBase is 'COMMON' for BuildOptions section
348 if '.' in Scope2:
349 Index = Scope2.index('.')
350 NewScope = TAB_COMMON + Scope2[Index:]
351 ConditionString += " AND (Scope2='%s' OR Scope2='COMMON' OR Scope2='DEFAULT' OR Scope2='%s')" % (Scope2, NewScope)
352 else:
353 ConditionString += " AND (Scope2='%s' OR Scope2='COMMON' OR Scope2='DEFAULT')" % Scope2
354
355 if BelongsToItem is not None:
356 ConditionString += " AND BelongsToItem=%s" % BelongsToItem
357 else:
358 ConditionString += " AND BelongsToItem<0"
359
360 if FromItem is not None:
361 ConditionString += " AND FromItem=%s" % FromItem
362
363 SqlCommand = "SELECT %s FROM %s WHERE %s" % (ValueString, self.Table, ConditionString)
364 return self.Exec(SqlCommand)
365
366 ## Factory class to produce different storage for different type of meta-file
367 class MetaFileStorage(object):
368 _FILE_TABLE_ = {
369 MODEL_FILE_INF : ModuleTable,
370 MODEL_FILE_DEC : PackageTable,
371 MODEL_FILE_DSC : PlatformTable,
372 MODEL_FILE_OTHERS : MetaFileTable,
373 }
374
375 _FILE_TYPE_ = {
376 ".inf" : MODEL_FILE_INF,
377 ".dec" : MODEL_FILE_DEC,
378 ".dsc" : MODEL_FILE_DSC,
379 }
380
381 ## Constructor
382 def __new__(Class, Cursor, MetaFile, FileType=None, Temporary=False, FromItem=None):
383 # no type given, try to find one
384 if not FileType:
385 if MetaFile.Type in self._FILE_TYPE_:
386 FileType = Class._FILE_TYPE_[MetaFile.Type]
387 else:
388 FileType = MODEL_FILE_OTHERS
389
390 # don't pass the type around if it's well known
391 if FileType == MODEL_FILE_OTHERS:
392 Args = (Cursor, MetaFile, FileType, Temporary)
393 else:
394 Args = (Cursor, MetaFile, Temporary)
395 if FromItem:
396 Args = Args + (FromItem,)
397
398 # create the storage object and return it to caller
399 return Class._FILE_TABLE_[FileType](*Args)
400