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