Automatic Recovery of Indexes

Description

The following two scripts allow a user to take a snapshot of all of the indexes in all of the tables in their application, and then check the actual indexes against the index definitions stored in the snapshot. Script 1 loops through all of the table in a database and stores the index definitions in a text file on disk. The text file is the same as the Database name but it has a ".TableInformation" extension. You would run Script 1 only once. Script 2 retrieves the index definitions and checks the indexes in the tables against the saved index definitions.

 Script 1 - Save Index Definitions

Start by getting a list of all tables.

dim tables as C 
tables = a5.Table_Enum()

Create an array to hold the index information for each table.

dim td as P
dim count as N 
count = line_count(tables) 
dim td.TableInfo[count] as P

Initialize the array.

td.TableInfo.initialize_properties("TableName",tables)

Create and display a progress dialog box with the WaitDialog .Create() method.

dim pDlg1 as {waitdialog} 
pDlg1.Create(3,"Percent") 
pDlg1.Set_Title("Please Wait") 
pDlg1.Set_Message("Storing index information. Please wait...")

Iterate through the tables, retrieving the index information for each.

dim i as N 
dim table_i as C 
dim indexInfo_i as C 
dim sourceType_i as C
  
for i = 1 to count 
    table_i = td.TableInfo[i].tablename

Check the table type. The only type of table to examine is a "Native" table. Use the .Set_Bottom_Message() method to update the progress dialog.

sourceType_i = table.get_source_type(table.filename_get(table_i)) 
    td.TableInfo[i].sourceType = sourceType_i 
    pDlg1.Set_Bottom_Message(table_i) 
    if (sourceType_i = "Native") then

The get_index_definitions() function retrieves a text definition of a table's indexes.

td.TableInfo[i].indexDefinitions = get_index_definitions(table_i) 
    else 
        td.TableInfo[i].indexDefinitions = "" 
    end if 
next i

Close the progress dialog. The a5.get_name() method returns the name of the current database. The file.filename_parse() method constructs the path and filename for the file that will store the index definitions.

pDlg1.close() 

dim fn as C 
fn = file.filename_parse(a5.Get_Name(),"dpn") + ".TableInformation"

Use save_to_file() to save the variable that contains the index information to the file on disk. Before you can save the variable, you have to convert it to a character value using property_to_string().

save_to_file(property_to_string(td),fn)

 Retrieve Index Definitions

Script 2 is used to check the indexes in the tables against the saved index definitions. The first step is to compute the name of the index definition file and open it. If the file doesn't exist, the script exits by going to the skip label.

dim fn as C
  
fn = file.filename_parse(a5.Get_Name(),"dpn") + ".TableInformation" 
if file.exists(fn) = .f. then 
ui_msg_box("Error", "Saved index information file not found.") 
goto skip 
end if

Retrieve the index definition using the get_from_file() function, then import the ASCII data into the td dot variable using property_from_string().

dim txt as C 
dim td as P
txt = get_from_file(fn) 
property_from_string(td, txt)

Count the number of entries in the td dot variable by finding the first empty entry with the array .first_empty() method and subtracting 1.

dim i as N 
dim count as N 
count = td.TableInfo.first_empty()- 1

Create and display a progress dialog box. Use the WaitDialog .Set_Title() method to set the title of the progress dialog.

dim pDlg1 as {waitdialog} 
pDlg1.Create(3,"Percent") 
pDlg1.Set_Title("Please Wait") 
pDlg1.Set_Message("Checking indexes. Please wait...")

Compare the saved index definitions with each table's indexes.

dim tablesWithErrors as C = "" 
dim index_info_i as C 
dim table_i as C 
dim ptr as P
  
for i = 1 to count 
    index_info_i = td.TableInfo[i].indexDefinitions 
    table_i = td.TableInfo[i].tablename 
    pDlg1.Set_Bottom_Message(table_i)

Only restore indexes if the table type is a native table. Use the <a>indexes_match_defstring() function to do the comparison. Check the .missingIndexTags property to see which tables have missing or damaged indexes. If necessary, use the create_indexes() function to restore an index.

if td.TableInfo[i].sourceType = "Native" then 
        ptr = indexes_match_defstring(table_i , index_info_i) 
        if ptr.missingIndexTags <> "" then 
            tablesWithErrors = tablesWithErrors + table_i + crlf() 
            Create_Indexes(table_i, index_info_i) 
        end if 
    end if 
next i

Close the progress dialog using the .close() method. Use ui_msg_box() to report what was done.

pDlg1.close() 


if tablesWithErrors <> "" then 
    ui_msg_box("Notice","Missing indexes were re-created in the following tables: " + crlf()+ tablesWithErrors) 
else 
    ui_msg_box("Notice","No missing indexes were found") 
end if
  
skip:

See Also