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