Plateforme Level Extreme
Abonnement
Profil corporatif
Produits & Services
Support
Légal
English
Upgrading a product
Message
Information générale
Forum:
Visual FoxPro
Catégorie:
InstallShield
Divers
Thread ID:
00912401
Message ID:
00913130
Vues:
19
>>Make all structural changes in an empty copy of the database. At the client site, copy this empty structure to a temporary location, and do an APPEND FROM for each table.
>
>That's exactly what I'm doing now, I create a project with a .prg that include the database, table, etc. struture using GENDBC.PRG. Then One programa apply a APPEND from and copy files. But I'm looking for a more practical way. "Cosas que la puedan hacer los usuarios con solo enviarle un CD"

I use a similar approach, but I don't use GENDBC. I have an empty copy of the database (i.e., zero records in each table, and do all the changes there in the first place. Then, for testing, I use my database update project first to update on my development machine - combining old data with the new structure. Later, I upgrade the shared database on the network (with a procedure that runs late at night).

I don't see any problem for an end-user to do this update, if you provide the update program.

The program would be the same in every case; only the contents of the database will change.

Two considerations:

1) It is convenient to make a backup first, in case there are problems during the update.

2) And don't forget my previous comments, about copying a parent before you copy a child. For instance, if you have a client table and an invoices (facturas) table, and if you have defined RI, you should copy the client table first.

The standard upgrade program should check for these relations automatically, so that you can always use the same upgrade program.

I send you my update program, in case it helps you. There is one problem: it depends on a function in the Visual Extend library. If you don't use Visual Extend, you will have to write your own version.

Greetings,

Hilmar.
* Update the structure of a local database,
* based on the official, empty, database

lParameters tlRealData && (Not required right now.) .T. for update on shared server, .F. for local test-data.

#DEFINE DIR_BACKUP		"c:\DataBackup\"
#DEFINE TEMPDIR			"c:\TempData\"
#DEFINE FORCEUPDATE		.F.

* Avoid backlink error
close all
for i = 1 to adir(laTables, "data\*.dbf")
	use (laTables(i,1))
next
use

local lcEmptyStructure, lcTargetDatabase
lcEmptyStructure = fullpath("") + "EmptyStructure\"  && or something like: "c:\projects\ra\EmptyStructure\"
* lcTargetDatabase = iif(tlRealData, "\\MyServer\MyApp\data\", "c:\projects\ra\data\")
lcTargetDatabase = fullpath("") + "data\"

UpdateDatabase(lcEmptyStructure, lcTargetDatabase, .T.)	&& call main program

* cd c:\...	&& My working folder



FUNCTION UpdateDatabase(tcEmptyStructure, tcTargetDatabase, tlDoBackup)
	if parameters() < 3
		tlDoBackup = .T.	&& assign default (the default is: yes, make backup)
	endif

	* Initialization
	set deleted on
	set safety off
	close databases all
	set talk off
	set procedure to c:\proyectos\produccion\program\vfxfunc additive	&& for vfx_needupdate()
	clear	&& For showing messages on main screen
	if FORCEUPDATE
		? "FORCED UPDATE. ALL TABLES WILL BE UPDATED."
	endif
	* clear all

	* Don't register auditing information (audit trail), when appending records
	private pldoaudit
	pldoaudit = .F.

	* Copy data to backup dir
	if tlDoBackup
		? time(), "Copying files to backup folder"
		if not directory(DIR_BACKUP)
			md (DIR_BACKUP)
		endif
		erase (DIR_BACKUP + "*.*")
		copy file (tcTargetDatabase + "*.*") to (DIR_BACKUP + "*.*")
	endif

	* Copy empty structure to temp data
	? time(), "Copying empty structure to " + TEMPDIR
	if not directory(TEMPDIR)
		md TEMPDIR
	endif
	erase (TEMPDIR + "*.*")
	copy file (tcEmptyStructure + "*.*") to (TEMPDIR + "*.*")

	* Create list of tables to be copied
	? time(), "Creating list of tables"
	local array laTables(1,1)
	adir(laTables, tcEmptyStructure + "*.dbf")
	create table TempTableList (table C(30))
	append from array laTables
	replace all table with juststem(table)	&& get rid of extension

	* Create list of relations, for checking order of table copy
	? time(), "Creating list of relations"
	open database tcEmptyStructure + "database"
	local array laRelations(1,1)
	adbobjects(laRelations, "relation")
	create table TempRelations free (child C(30), parent C(30), childtag C(10), parenttag C(10), ri C(10))
	append from array laRelations
	* If a relation doesn't "Restrict" child inserts, it causes no problem.
	delete for substr(ri,3,1) # "R"
	index on child tag child
	index on parent tag parent
	close database

	* Append modified tables; erase others (no need to overwrite non-modified files
	*   back to target data)
	set talk on
	? time(), "Combining data with updated structure"
	local lnNeedUpdate
	local llTablesProcessed
	llTablesProcessed = .T.
	do while llTablesProcessed
		select TempTableList
		llTablesProcessed = .F.
		scan && in TempTableList
			wait window nowait "Searching for next table to copy"
			llTablesProcessed = .T.	&& there still is at least one table in TempTableList
			lcTable = alltrim(TempTableList.table)
			select TempRelations
			set order to "child"
			if seek(padr(lcTable, len(child)))
				* Table depends on un-copied parents. Try to copy next table.
				select TempTableList
				loop
			endif
			lnNeedUpdate = vfx_needupdate(lcTable + ".dbf", TEMPDIR, tcTargetDatabase)
			if lnNeedUpdate > 0
				? time(), "Table:", padr(lcTable,30, " ."), " "
			endif
			do case
			case lnNeedUpdate = 0 and not FORCEUPDATE	&& no update needed (OS-level copy)
				* ?? "Structure didn't change."
				wait window nowait "Erasing temporary table " + lcTable
				erase (TEMPDIR + lcTable + ".*")
			case lnNeedUpdate = 1 or (lnNeedUpdate = 0 and FORCEUPDATE)	&& need update
				if lnNeedUpdate = 1
					?? "There are changes. Transferring data."
				else
					?? "No changes. Forced update."
				endif
				wait window nowait "Updating table " + lcTable
				select 0
				use (TEMPDIR + lcTable)
				append from (tcTargetDatabase + lcTable)
				use
			case lnNeedUpdate = 2	&& new table
				?? "New table."
				* No additional action is required.
			endcase
			select TempRelations
			set order to "parent"
			delete for parent = padr(lcTable, len(parent))
			select TempTableList
			delete	&& table has been processed.
		endscan
	enddo

	set talk off
	? time(), "Moving to final destination."

	close database all

	erase TempTableList.*
	erase TempRelations.*

	* Move temp to target data
	* Moving is much faster than copying, if moving occurs on the same disk
	local lnFileCount
	local array laFiles(1,1)
	for lnFileCount = 1 to adir(laFiles, TEMPDIR + "*.*")
		erase (tcTargetDatabase + laFiles(lnFileCount, 1))
		rename (TEMPDIR + laFiles(lnFileCount, 1)) to (tcTargetDatabase + laFiles(lnFileCount, 1))
	next
	? time(), "Done."


	* Cleanup
	rd TEMPDIR
	set safety on
	wait clear
	?? chr(7)
ENDFUNC
Difference in opinions hath cost many millions of lives: for instance, whether flesh be bread, or bread be flesh; whether whistling be a vice or a virtue; whether it be better to kiss a post, or throw it into the fire... (from Gulliver's Travels)
Précédent
Répondre
Fil
Voir

Click here to load this message in the networking platform