home *** CD-ROM | disk | FTP | other *** search
- *****************************************************************
- FUNCTION MAKEDBF (App_def)
- *****************************************************************
-
- * Creates or recreates an application's database files
-
- * Copyright(c) 1991 -- James Occhiogrosso
-
- * Note: Since successful operation of MAKEDBF is usually critical
- * to application integrity, it returns to DOS with an message if
- * any error occurs that prevents proper updating.
-
- # include "box.ch"
- # define f_names 1
- # define f_types 2
- # define f_lens 3
- # define f_decs 4
- # define f_ok 5
-
- LOCAL counter := num_fields := pointer := 0
- LOCAL create_dbf := dbf_exist := memoflds := old_cursor := ;
- old_exact := .F.
- LOCAL temp_stru := ''
- LOCAL dbf_stru := {}, dbf_names := {}, memo_files[1]
-
- PRIVATE dbf_name := dbf_text := textline := '', handle := 0, ;
- text_row := 7, new_stru := {}
-
- IF PCOUNT() != 1
- * Return to DOS if no argument passed
- * Critical error - return to DOS
- ?? CHR(7)
- ? 'Must specify application definition file'
- SET CURSOR ON
- QUIT
- ELSE
- * Return to DOS if data dictionary file cannot be opened
- handle = FOPEN(app_def)
- IF handle <= 0
- * Critical error - return to DOS
- ?? CHR(7)
- ? 'Application definition file missing.'
- SET CURSOR ON
- QUIT
- ENDIF
- ENDIF
-
- * Save cursor status and turn cursor off
- old_cursor = SETCURSOR(.F.)
-
- * Display MAKEDBF installation screen
-
- CLEAR SCREEN
- @ 1, 7, 23, 70 BOX B_DOUBLE + SPACE(1)
- @ 1, 0 SAY ''
- TEXT
- ║ S Y S T E M I N S T A L L A T I O N ║
- ╟──────────────────────────────────────────────────────────────╢
- ║ This is a new or updated system configuation. System files ║
- ║ will be checked and updated as required. Data will not be ║
- ║ lost. The process takes a few minutes. Please be patient. ║
- ╟──────────────────────────────────────────────────────────────╢
- ENDTEXT
-
-
- * Get first database definition from data dictionary
- GETDBFDEF()
-
- * Loop until no more database definition (DBFDEF) lines
-
- DO WHILE .NOT. EMPTY(dbf_name)
-
- * Reset loop control variables
- create_dbf = .F.
- dbf_exist = .F.
-
- * Check for existence of database
- IF FILE(dbf_name + '.dbf')
- * Database exists, set flag and open it for exclusive use
- dbf_exist = .T.
- USE &dbf_name EXCLUSIVE NEW
- IF NETERR()
- ?? CHR(7)
- ? 'File ' + UPPER(dbf_name) + ' cannot be opened ' + ;
- 'exclusively. '
- SET CURSOR ON
- QUIT
- ENDIF
-
- * Load field structures to dbf_stru array
- dbf_stru = DBSTRUCT()
- num_fields = LEN(dbf_stru)
-
-
- * Add and initalize a logical dimension for field status
- FOR counter = 1 TO num_fields
- ASIZE(dbf_stru[counter], 5)
- dbf_stru[counter][5] = .F.
- NEXT
-
- * Open and load temporary file with field definitions
- LOADSTRU()
-
-
- * Set EXACT on and verify fields to data dictionary
- old_exact = SET(_SET_EXACT, .T.)
-
- IF LEN(new_stru) != num_fields
- * Database and dictionary have different number
- * of fields. Set create flag
- create_dbf = .T.
- ELSE
- * Test all fields to dictionary definitions
- FOR counter = 1 TO num_fields
-
- IF dbf_stru[counter][f_names] == ;
- TRIM(new_stru[counter][f_names])
- * Field names match. Check type and length
-
- IF new_stru[counter][f_types] != ;
- dbf_stru[counter][f_types]
- ?? CHR(7)
- ? 'Field type ' + ;
- TRIM(new_stru[counter][f_names]) + ;
- ' in database ' + dbf_name + ;
- ' changed. Cannot continue. '
- SET CURSOR ON
- QUIT
-
- ELSEIF new_stru[counter][f_lens] != ;
- dbf_stru[counter][f_lens] .OR. ;
- new_stru[counter][f_decs] != ;
- dbf_stru[counter][f_decs]
-
- * Dictionary definition is not same
- * as database. Set create flag
- create_dbf = .T.
-
- ELSE
- * Flag verified field in f_ok array
- dbf_stru[counter][f_ok] = .T.
- ENDIF
-
- ELSE
- * Field name changed. Set create flag
- create_dbf = .T.
-
- ENDIF
- NEXT
- ENDIF
-
- * Reset EXACT to entry condition
- SET(_SET_EXACT, old_exact)
-
- * Check flags array. False indicates field exists in
- * database but not in dictionary. (Field was deleted)
-
- IF ! create_dbf
- * Test for deletions unless create flag allready set
- FOR counter = 1 TO num_fields
- IF ! dbf_stru[counter][f_ok]
- * A field was deleted. Set create flag
- create_dbf = .T.
- ENDIF
- NEXT
- ENDIF
-
- ELSE
- * Database does not exist, set flag to re-create it
- LOADSTRU()
- create_dbf = .T.
- ENDIF
-
- * Close the file
- USE
-
- * Test flags and recreate database if necessary
- IF dbf_exist .AND. create_dbf
-
- * Old database exists. Create backup files
- * Delete any old backups if they exist
-
- IF FILE(dbf_name + '.BAK')
- ERASE &dbf_name..BAK
- ENDIF
- IF FILE(dbf_name + '.TBK')
- ERASE &dbf_name..TBK
- ENDIF
-
- * Test database for defined memo fields
- memoflds = IF(ISMEMO(dbf_name) = 1, .T., .F.)
-
- * Rename old database file(s) to backups
- IF memoflds .AND. .NOT. FILE(dbf_name + '.DBT')
- ?? CHR(7)
- ? 'Memo file ' + dbf_name + '.DBT missing.'
- SET CURSOR ON
- QUIT
- ELSEIF memoflds .AND. FILE(dbf_name + '.DBT')
- RENAME &dbf_name..DBT TO &dbf_name..TBK
- ENDIF
- RENAME &dbf_name..DBF TO &dbf_name..BAK
-
- * Make sure both backup files exist before creating
- * new ones. CREATE will destroy existing DBT files!
-
- IF .NOT. FILE(dbf_name + '.BAK') .OR. ;
- (memoflds .AND. !FILE(dbf_name + '.TBK'))
- ?? CHR(7)
- ? 'Backup files cannot be created for ' + dbf_name
- SET CURSOR ON
- QUIT
- ENDIF
-
- ENDIF
-
- IF create_dbf
-
- * Scroll screen up if at bottom of window
- IF text_row = 22
- SCROLL(8, 9, 22, 68, 1)
- ELSE
- text_row = text_row + 1
- ENDIF
-
- * Display associated text (balance of textline)
- @ text_row, 7 SAY '║' + ' ' + SUBSTR(dbf_text, 1, 60)
- @ text_row, 70 SAY '║'
-
- * Recreate database file from structure file
- DBCREATE(dbf_name, new_stru)
-
- USE
-
- * Rename DBT file if memo fields exist
- IF memoflds .AND. dbf_exist
- ERASE &dbf_name..DBT
- RENAME &dbf_name..TBK TO &dbf_name..DBT
- ENDIF
-
- * If database exists, copy all records from backup
- IF dbf_exist
- USE &dbf_name EXCLUSIVE NEW
- IF NETERR()
- ?? CHR(7)
- ? 'File ' + UPPER(dbf_name) + ' cannot be opened ' + ;
- 'exclusively. '
- SET CURSOR ON
- QUIT
- ENDIF
-
- APPEND FROM &dbf_name..BAK
- IF memoflds
- * Pack DBT file if memo fields exist
- memo_files[1] := dbf_name
- MEMOPACK(memo_files)
- ENDIF
- USE
- ENDIF
-
- * Add current database filename to the array
- AADD(dbf_names, dbf_name)
-
-
- ENDIF
-
- * Get next database definition line from data dictionary
- GETDBFDEF()
-
- ENDDO WHILE .NOT. EMPTY(dbf_name)
-
- * Call MAKENDX to recreate indexes of updated databases
- SETCURSOR(old_cursor)
- RETURN MAKENDX(DBf_names, textline, text_row)
-
-
- *****************************************************************
- STATIC FUNCTION GETDBFDEF
- *****************************************************************
-
- * Locate and read the next database definition (DBFDEF) line
-
- * Get next defined line from data dictionary
- NEXTLINE()
-
- * Check line for database definition code
-
- IF UPPER(SUBSTR(textline, 1, 6)) = 'DBFDEF'
- * Line is a valid database definition, strip
- * DBFDEF code identifier and return.
-
- textline = LTRIM(SUBSTR(textline, 7))
- dbf_name = PARSE(@textline)
- dbf_text = textline
-
- ELSE
- * Otherwise, set dbf_name to an empty string
- * and return without altering textline
- dbf_name = ''
- ENDIF
-
- RETURN ''
-
-
-
- *****************************************************************
- STATIC FUNCTION NEXTLINE
- *****************************************************************
-
- * Get next non-comment line in definitions file
-
- * Test first character of line
- textline = '*'
- DO WHILE (SUBSTR(textline, 1, 1) $ '*#' .OR. EMPTY(textline)) ;
- .AND. UPPER(SUBSTR(textline, 1, 7)) != 'ENDFILE'
-
- * If it is a comment or blank line, skip it.
- textline = LTRIM(FREADLINE(handle))
-
- ENDDO
- RETURN NIL
-
-
- *****************************************************************
- STATIC FUNCTION LOADSTRU
- *****************************************************************
-
- * Load database definitions into structure array
-
- LOCAL fld_dec := fld_len := fld_name := fld_type := message := ''
-
- * Clear the new structure array
- new_stru := {}
-
- * Get next non-comment line of definitions file
- NEXTLINE()
-
- * Stay in loop until we read end of definitions code
- DO WHILE UPPER(SUBSTR(textline, 1, 6)) != 'ENDDEF'
-
- * Get and verify field definitions from data dictionary
-
- fld_name = UPPER(PARSE(@textline)) && Get field name
- fld_type = UPPER(PARSE(@textline)) && Get field type
- fld_len = PARSE(@textline) && Get field length
- fld_dec = PARSE(@textline) && Get field decimals
-
- IF EMPTY(fld_name) .OR. LEN(fld_name) > 10
- message = 'Field name'
-
- ELSEIF EMPTY(fld_type) .OR. LEN(fld_type) > 1 ;
- .OR. .NOT. (fld_type) $ 'CDNLM'
- message = 'Field type'
-
- ELSEIF EMPTY(fld_len) .OR. .NOT. VAL(fld_len) >= 0 ;
- .OR. VAL(fld_len) > 999
- message = 'Field length'
-
- ELSEIF EMPTY(fld_dec) .OR. .NOT. VAL(fld_dec) >= 0 ;
- .OR. VAL(fld_dec) > 999
- message = 'Field decimals'
-
- ENDIF
-
- IF .NOT. EMPTY(message)
- * If message is loaded, display it and return to DOS
- ?? CHR(7)
- ? message + ' error in data dictionary ..... ' + fld_name
- ? 'Text line = ' + SUBSTR(textline,1,60)
- SET CURSOR ON
- QUIT
- ELSE
- * Load each field definition to structure array
- AADD(new_stru, { fld_name, fld_type, ;
- VAL(fld_len), VAL(fld_dec) } )
- ENDIF
-
- * Get next non-comment line of definitions file
- NEXTLINE()
-
- ENDDO
-
- * Reset pointer to top of file and return
- GO TOP
- RETURN NIL
-
-
-