Home > Archive > dBASE Code Sharing > August 2005 > Problems with CreateReindex.prg/RebuildIndexes.prg in dUFLP









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Problems with CreateReindex.prg/RebuildIndexes.prg in dUFLP
Ivar B. Jessen

2005-07-18, 8:24 pm

Using Win2000/Plus 2.21

1) First problem

In the command pane type do :duflp:CreateReindex
with "dbasesamples"
and the program RebuildIndexex.prg is created. Open said file and
notice that it has code to create _two_ primary indexes, namely

on Name tag 'PRIMARYNAME and on Name tag 'NAME' as indicated below,

try
use :dbasesamples:FISH.DBF exclusive
index on Name tag 'PRIMARYNAME' primary
catch ( exception e )
....

try
use :dbasesamples:FISH.DBF exclusive
index on Name tag 'NAME' primary
catch ( exception e )

As a dbf table can one primary index only ( and the Fish table has one
primary index only ) there must be something wrong in CreateIndex.prg.


2) Second problem.

RebuildIndexes contains code to drop each individual index in a table.
It is difficult to see the rationale for this construction. What
purpose does it serve to attempt to drop 37 individual indexes which
all may be corrupt and give rise to 37 different error messages which
you have to handle? A nasty case is when the mdx file has been
deleted, RebuildIndexes.prg will then result in a dialog box with the
message,

Production Index file missing, corrupt or cannot interpret index key,

and the whole process which is supposed to run unattended stops.

Would it not be more logic to first detach the production index flag
at byte 28 in the file header, then delete the mdx file and finally
recreate the indexes.

When this is done byte 37 in the Field Descriptor Array will still be
set for the fields which had an index. This doesn't really matter
because it will be reset when the index is recreated. If it is felt
that byte 37 should be set to '00' first it could be done by packing
the table or by resetting the values directly in the file header in
the same way that byte 28 was reset.

To me the proposed process looks much more straight-forward than the
presently used process. Are there anything which speaks against it? It
should also be be much less error prone as it doesn't deal with a
possibly corrupt mdx file at all.


Ivar B. Jessen
Howard Mintzer

2005-07-18, 8:24 pm

I use the routine in dbf7file.cc (i think its in that cc)
OpenWithoutMdx(). then I comment out all the detatch lines and just
recreate the indexes. Seems to work better that way for me.

Howie

Ivar B. Jessen wrote:
> Using Win2000/Plus 2.21
>
> 1) First problem
>
> In the command pane type do :duflp:CreateReindex
with "dbasesamples"
> and the program RebuildIndexex.prg is created. Open said file and
> notice that it has code to create _two_ primary indexes, namely
>
> on Name tag 'PRIMARYNAME and on Name tag 'NAME' as indicated below,
>
> try
> use :dbasesamples:FISH.DBF exclusive
> index on Name tag 'PRIMARYNAME' primary
> catch ( exception e )
> ...
>
> try
> use :dbasesamples:FISH.DBF exclusive
> index on Name tag 'NAME' primary
> catch ( exception e )
>
> As a dbf table can one primary index only ( and the Fish table has one
> primary index only ) there must be something wrong in CreateIndex.prg.
>
>
> 2) Second problem.
>
> RebuildIndexes contains code to drop each individual index in a table.
> It is difficult to see the rationale for this construction. What
> purpose does it serve to attempt to drop 37 individual indexes which
> all may be corrupt and give rise to 37 different error messages which
> you have to handle? A nasty case is when the mdx file has been
> deleted, RebuildIndexes.prg will then result in a dialog box with the
> message,
>
> Production Index file missing, corrupt or cannot interpret index key,
>
> and the whole process which is supposed to run unattended stops.
>
> Would it not be more logic to first detach the production index flag
> at byte 28 in the file header, then delete the mdx file and finally
> recreate the indexes.
>
> When this is done byte 37 in the Field Descriptor Array will still be
> set for the fields which had an index. This doesn't really matter
> because it will be reset when the index is recreated. If it is felt
> that byte 37 should be set to '00' first it could be done by packing
> the table or by resetting the values directly in the file header in
> the same way that byte 28 was reset.
>
> To me the proposed process looks much more straight-forward than the
> presently used process. Are there anything which speaks against it? It
> should also be be much less error prone as it doesn't deal with a
> possibly corrupt mdx file at all.
>
>
> Ivar B. Jessen

Ken Mayer [dBVIPS]

2005-07-19, 7:24 am

Ivar B. Jessen wrote:
> Using Win2000/Plus 2.21
>
> 1) First problem
>
> In the command pane type do :duflp:CreateReindex
with "dbasesamples"
> and the program RebuildIndexex.prg is created. Open said file and
> notice that it has code to create _two_ primary indexes, namely
>
> on Name tag 'PRIMARYNAME and on Name tag 'NAME' as indicated below,
>
> try
> use :dbasesamples:FISH.DBF exclusive
> index on Name tag 'PRIMARYNAME' primary
> catch ( exception e )
> ...
>
> try
> use :dbasesamples:FISH.DBF exclusive
> index on Name tag 'NAME' primary
> catch ( exception e )
>
> As a dbf table can one primary index only ( and the Fish table has one
> primary index only ) there must be something wrong in CreateIndex.prg.
>
>
> 2) Second problem.
>
> RebuildIndexes contains code to drop each individual index in a table.
> It is difficult to see the rationale for this construction. What
> purpose does it serve to attempt to drop 37 individual indexes which
> all may be corrupt and give rise to 37 different error messages which
> you have to handle? A nasty case is when the mdx file has been
> deleted, RebuildIndexes.prg will then result in a dialog box with the
> message,
>
> Production Index file missing, corrupt or cannot interpret index key,
>
> and the whole process which is supposed to run unattended stops.
>
> Would it not be more logic to first detach the production index flag
> at byte 28 in the file header, then delete the mdx file and finally
> recreate the indexes.
>
> When this is done byte 37 in the Field Descriptor Array will still be
> set for the fields which had an index. This doesn't really matter
> because it will be reset when the index is recreated. If it is felt
> that byte 37 should be set to '00' first it could be done by packing
> the table or by resetting the values directly in the file header in
> the same way that byte 28 was reset.
>
> To me the proposed process looks much more straight-forward than the
> presently used process. Are there anything which speaks against it? It
> should also be be much less error prone as it doesn't deal with a
> possibly corrupt mdx file at all.


I am looking at this now. At the time the program was written (a loooong
time ago), some things were not available.

The issue you found with the attempt to create multiple primary keys on
the same table is due to wierd design in the FISH table (two indexes
with the exact same expression? Not a great design ...), but also
because there is no way with the TableDef object (actually the indexes
array used by both TableDef and Rowset) to know if an index tag is the
primary key. With code created by Michael Nuwer (BDEIndex.cc) I can
actually determine this better, so I will be working with that.

I hope to be able to post an update in awhile, so you can try testing it
out ...

Ken

--
/(Opinions expressed are purely my own, not those of dataBased
Intelligence, Inc.)/

*Ken Mayer* [dBVIPS]
/Golden Stag Productions/
dBASE at goldenstag dot net
http://www.goldenstag.net/GSP
http://www.goldenstag.net/dbase
Ken Mayer [dBVIPS]

2005-07-19, 9:23 am

Ivar B. Jessen wrote:
> Using Win2000/Plus 2.21
>
> 1) First problem


Please try the attached version. It should resolve both of the issues
you brought up. I tried it with :dBASESamples: and with a local folder,
and appears to work fine in both cases.

Ken

--
/(Opinions expressed are purely my own, not those of dataBased
Intelligence, Inc.)/

*Ken Mayer* [dBVIPS]
/Golden Stag Productions/
dBASE at goldenstag dot net
http://www.goldenstag.net/GSP
http://www.goldenstag.net/dbase


Ivar B. Jessen

2005-07-19, 1:23 pm

<UdpklsGjFHA.1188@news-server> datefromnewsgroupssu
bject

>Ivar B. Jessen wrote:
>
>Please try the attached version. It should resolve both of the issues
>you brought up. I tried it with :dBASESamples: and with a local folder,
>and appears to work fine in both cases.
>


Ken,

Thanks for stepping in here with a new version as I did not know how
to modify the existing code without breaking something else.

I am surprised that you adapted my proposal just like that, not even
the smallest objection against somebody proposing to change that old
venerable code you threw together in about an hour of tinkering in
1988 :-)


The new version appears to work fine except that in some cases I get
an error like this when running RebuildIndexes.prg,

Error: Class does not exist: MESSAGEFORM::REPAINT

File: RebuildIndexe
s.prg
Routine: REBUILDINDE
XES
Line: 70

// -- TESTREINDEX4.DBF
fMessage.message.text = 'TESTREINDEX4.DBF'
fMessage.repaint() // <----- Line 70
// No Indexes to Process


In this case there are six similar simple tables where only
TESTREINDEX3.DBF has an index, i.e. the error pops up for the table
TESTREINDEX4.DBF which is following the first table with an index to
be processed. Cliking 'Ignore' results in same error for the next
table. Could it indicate that the link to fMessage gets broken by the
processing for TESTREINDEX3.DBF?


The following lines in CreateReindex.prg should be reworded,

line 288 to 290
cOutString = " This will delete index tags and rebuild from"
fProgram.puts( cOutString )
cOutString = " scratch ..."

reworded
cOutString = " This will delete the .mdx file and rebuild"
fProgram.puts( cOutString )
cOutString = " the index tags from scratch ..."

Line 411
cOutString = [ msgbox( "An error occurred
disconnecting MDX tag(s) for table ']+;

reworded
cOutString = [ msgbox( "An error occurred
disconnecting MDX flag for table ']+;


I have not checked how the messages work as they all flash quickly by
when the small tables I have are processed.


Ivar B. Jessen
Ken Mayer [dBVIPS]

2005-07-19, 8:24 pm

Ivar B. Jessen wrote:
> <UdpklsGjFHA.1188@news-server> datefromnewsgroupssu
bject
>
>
>
> Ken,
>
> Thanks for stepping in here with a new version as I did not know how
> to modify the existing code without breaking something else.
>
> I am surprised that you adapted my proposal just like that, not even
> the smallest objection against somebody proposing to change that old
> venerable code you threw together in about an hour of tinkering in
> 1988 :-)


Well, it was a chance to clean up some really old code that obviously
could have been more efficient (well, obviously now ...). And I'm
waiting for the principal on my current project to find some time to
answer some questions before I can move on ... so ...

> The new version appears to work fine except that in some cases I get
> an error like this when running RebuildIndexes.prg,
>
> Error: Class does not exist: MESSAGEFORM::REPAINT

> File: RebuildIndexe
s.prg
> Routine: REBUILDINDE
XES
> Line: 70
>
> // -- TESTREINDEX4.DBF
> fMessage.message.text = 'TESTREINDEX4.DBF'
> fMessage.repaint() // <----- Line 70
> // No Indexes to Process


Hmm. Odd. The message form in the dUFLP should have the repaint method.
I assume you have the most recent version of the dUFLP (and I haven't
changed that form in a LONG time).

The "Class does not exist" error is truly odd, since it's not hitting
that earlier. I suppose I need to check and make sure I didn't do a SET
PROCEDURE without the ADDITIVE keyword (current versions of dBASE don't
require it, but ...).

> I have not checked how the messages work as they all flash quickly by
> when the small tables I have are processed.


Yeah. Me, too ... it was rather startling the first time I had it all
working ...

Ken

--
/(Opinions expressed are purely my own, not those of dataBased
Intelligence, Inc.)/

*Ken Mayer* [dBVIPS]
/Golden Stag Productions/
dBASE at goldenstag dot net
http://www.goldenstag.net/GSP
http://www.goldenstag.net/dbase
Ken Mayer [dBVIPS]

2005-07-19, 8:24 pm

Ken Mayer [dBVIPS] wrote:
>
>
> The "Class does not exist" error is truly odd, since it's not hitting
> that earlier. I suppose I need to check and make sure I didn't do a SET
> PROCEDURE without the ADDITIVE keyword (current versions of dBASE don't
> require it, but ...).


That was it. I have found that and fixed it. And dealt with the strings
suggested. See attached ...

Ken

--
/(Opinions expressed are purely my own, not those of dataBased
Intelligence, Inc.)/

*Ken Mayer* [dBVIPS]
/Golden Stag Productions/
dBASE at goldenstag dot net
http://www.goldenstag.net/GSP
http://www.goldenstag.net/dbase


Ivar B. Jessen

2005-07-20, 7:23 am

<H1vy#LLjFHA.1760@news-server> datefromnewsgroupssu
bject

>Ken Mayer [dBVIPS] wrote:
>
>That was it. I have found that and fixed it. And dealt with the strings
>suggested. See attached ...


The new version now runs without the error "Class does not exist".


A few more suggestions.


1)
The comment in lines 465 and 465 should be reworded,

// at this point there should be no index tags and hence
// no .MDX file. Next, we need to rebuild ...

reworded comment,

// at this point there should be no .MDX file and hence
// no index tags. Next, we need to rebuild ...


2)
The readability of RebuildIndexes.prg could be improved by moving the
block of code for turning the mdx flag off and deleting the .MDX file
into a function, say removeMDX(), at the bottom of the program.
The generated code would then look like this:

// -- FISH.DBF
fMessage.message.text = 'FISH.DBF'
fMessage.repaint()
// Disconnecting index flag for table and
// Erasing the .mdx file:
removeMDX( ":dbasesamples:fish.dbf" )
<blank line>


3)
The present generated code for the primary key looks like this:

// rebuild index tags ...
// primary key, we must use XDML to create it:
try
use :dbasesamples:fish exclusive
index on Name tag 'PRIMARYNAME' primary
catch ( exception e )
// dBASE may throw an exception about invalid file name here
// (presumably for the key violation table)
// of course it will also fail if we didn't
// get exclusive use of the table.
endtry
use

The code would be nicer if it looks more like the sections for normal
indexes:

// rebuild index tags ...
// index tag: PRIMARYNAME (primary )
// we must use XDML to create it:
try
use :dbasesamples:fish exclusive
index on Name tag 'PRIMARYNAME' primary
catch ( exception e )
// dBASE may throw an exception about invalid file name here
// (presumably for the key violation table)
// of course it will also fail if we didn't
// get exclusive use of the table.
endtry
use


Ivar B. Jessen
Ken Mayer [dBVIPS]

2005-07-20, 7:23 am

Ivar B. Jessen wrote:
> <H1vy#LLjFHA.1760@news-server> datefromnewsgroupssu
bject
>
>
>
> The new version now runs without the error "Class does not exist".
>
>
> A few more suggestions.
>
>
> 1)
> The comment in lines 465 and 465 should be reworded,
>
> // at this point there should be no index tags and hence
> // no .MDX file. Next, we need to rebuild ...
>
> reworded comment,
>
> // at this point there should be no .MDX file and hence
> // no index tags. Next, we need to rebuild ...
>
>
> 2)
> The readability of RebuildIndexes.prg could be improved by moving the
> block of code for turning the mdx flag off and deleting the .MDX file
> into a function, say removeMDX(), at the bottom of the program.
> The generated code would then look like this:
>
> // -- FISH.DBF
> fMessage.message.text = 'FISH.DBF'
> fMessage.repaint()
> // Disconnecting index flag for table and
> // Erasing the .mdx file:
> removeMDX( ":dbasesamples:fish.dbf" )
> <blank line>


There does come a point where rewriting the code gets to be too much. <g>

Ken

--
/(Opinions expressed are purely my own, not those of dataBased
Intelligence, Inc.)/

*Ken Mayer* [dBVIPS]
/Golden Stag Productions/
dBASE at goldenstag dot net
http://www.goldenstag.net/GSP
http://www.goldenstag.net/dbase
Howard Mintzer

2005-08-05, 3:24 am

I've found a bug in the createreindex program. In line 402 you have
cDatabasePath += "\"
Unfortunately it seems to run this line over and over again (once for
each talbe) so your path becomes
c:\myfiles\mytable
c:\myfiles\\mytable2

c:\myfiles\\\mytable
3
etc.
I've nulled out that line and have changed line 199 to
cDataBasePath = oBDE.databaseDir( dMyData.databaseName ) +''

That seems to fix the problem for me...but since you know alot more
about how the program works I figured I'd send it back to you to make
sure I didn't futz things up

Howie

Ken Mayer [dBVIPS] wrote:
> Ivar B. Jessen wrote:
>
>
>
> There does come a point where rewriting the code gets to be too much. <g>
>
> Ken
>

Ken Mayer [dBVIPS]

2005-08-05, 11:24 am

Howard Mintzer wrote:
> I've found a bug in the createreindex program. In line 402 you have
> cDatabasePath += "\"
> Unfortunately it seems to run this line over and over again (once for
> each talbe) so your path becomes
> c:\myfiles\mytable
> c:\myfiles\\mytable2

> c:\myfiles\\\mytable
3
> etc.
> I've nulled out that line and have changed line 199 to
> cDataBasePath = oBDE.databaseDir( dMyData.databaseName ) +''
>
> That seems to fix the problem for me...but since you know alot more
> about how the program works I figured I'd send it back to you to make
> sure I didn't futz things up


Good catch. Actually, hardcoding the path when generating the code was a
poor decision on my part in the first place. I have fixed this, and
modified the code to select the path for the tables when it runs, based
on the BDE Alias passed (if any) ... tested on one of my own apps and
works a lot better ...

Ken

--
/(Opinions expressed are purely my own, not those of dataBased
Intelligence, Inc.)/

*Ken Mayer* [dBVIPS]
/Golden Stag Productions/
dBASE at goldenstag dot net
http://www.goldenstag.net/GSP
http://www.goldenstag.net/dbase


Howard Mintzer

2005-08-05, 8:24 pm

glad to be of help....anxiously (well maybe not anxiously <g> ) waiting
for the book to come out

Howie

Ken Mayer [dBVIPS] wrote:
> Howard Mintzer wrote:
>
>
>
> Good catch. Actually, hardcoding the path when generating the code was a
> poor decision on my part in the first place. I have fixed this, and
> modified the code to select the path for the tables when it runs, based
> on the BDE Alias passed (if any) ... tested on one of my own apps and
> works a lot better ...
>
> Ken
>
>
> ------------------------------------------------------------------------
>
> /*
> CREATEREINDEX.PRG
> This program is designed to do what the version that
> Romain once did does -- it creates a program for you
> that will re-build your index tags on your tables --
> but this one uses some special features of Visual dBASE 7
> to do it ...
>
> This will create a single program file that should regenerate
> your index tags for all tables (after deleting them) --
> if you add a table, or add a new index tag, or change an
> index tag definition, you should re-run this routine!
>
> // NOTE: If anyone has suggestions for improvements,
> // feel free to contact me. This is something I threw
> // together in about an hour of tinkering ...
>
> Programmer: Ken Mayer
> Updates:
> 08/23/1998 -- added addition of a try/catch around
> the DROP INDEX command, to catch
> an error if the index tag doesn't
> exist ... this adds heavily to the
> length of the code, because the try/catch
> is created for *each* index tag that
> we attempt to drop, but it should
> avoid the user being interrupted
> by an error that won't stop the
> program from doing it's job ...
>
> 9/29/1998 -- Gary White added code to handle primary key
> index tags.
>
> 10/6/1998 -- GW added a minor fix ...
>
> January 26, 1999 -- Added optional database parameter,
> which can be used to pass the name of
> a database to this routine. If used,
> you MUST be sure to have access to
> PATHDATA.CC (also in the dUFLP library),
> otherwise it won't function.
>
> The advantage to this is that you can
> use this routine to generate the
> correct database object and references
> so that it will use that information,
> rather than the default database
> (_app.databases[1]), and will therefore
> find tables stored in a database
> folder other than the current directory.
>
> February 1, 1999 -- minor modification -- this will
> make sure that the new program created
> by this one will close any open databases
> before it tries to do anything -- otherwise
> the user will get "file in use" errors.
>
> March/April 1999 -- Gary White added more code, and
> program renamed to "CreateReindex"
> No longer requires the use of "PathData.cc"
> as well ...
>
> 5/24/1999 -- GW added small fix to primary keys where
> the primary key was a single field with
> a space in the field name.
>
> June 23, 1999 -- Lawrence Bain modified to accept an array
> of database names as a parameter.
>
> April 2, 2003 -- Geoff Wass and Ivar Jessen ran into some
> difficulties with string delimiters in expressions
> and forExpressions for index tags, which we have
> attempted to deal with here. If an index tag
> has an expression or forExpression using all three
> string delimiters: ', ", or [], this code will
> not generate code to generate that index tag.
>
> In addition, it will attempt to generate a string
> with an appropriate set of delimiters to avoid
> problems where in the past the code here assumed
> you were not using ' as a delimiter in your index
> expression and/or forExpression ...
>
> July, 2005 -- Ivar B. Jessen noted two things:
> * A table can have two index tags that
> have the exact same expression. The
> problem then becomes if one of them
> is the Primary key. The old code would
> attempt to create two primary keys in
> this instance. Changing this program
> to use BDEIndex.cc appears to resolve
> the problem, as this class uses the
> BDE API to determine if the tag is
> the primary key (the tableDef object
> does not allow this).
>
> * The second problem is that if a corrupt
> index tag exists, the old code would
> have heartburn when deleting indexes.
> This code now uses dBF7File, and the
> SetMDXFlag method to turn off the byte
> in the table header that determines if
> the table has indexes, then we delete
> the .mdx file. Much more efficient ...
>
> August, 2005 -- Fixed a bug found by Howard Mintzer, and
> dealt with hard-coded path when deleting
> the .MDX file ... can't have that in the
> final program of course, because the
> path may change ...
>
> Usage:
> set procedure to :dUFLP:CreateReindex
.prg additive
> CreateReindex()
> or
> do :dUFLP:CreateReindex

>
> ** OR:
>
> set procedure to :dUFLP:CreateReindex
.prg additive
> CreateReindex( "databaseName")
> or
> do :dUFLP:CreateReindex
with "databaseName"
> // where "databaseName" is the BDE Alias
> // where the tables are stored
>
> ** OR:
>
> set procedure to :dUFLP:CreateReindex
.prg additive
> CreateReindex( arrayOfDatabaseNames
)
> or
> do :dUFLP:CreateReindex
"with arrayOfDatabaseName
>
> DEPENDENCIES:
> :dUFLP:MESSAGE.WFM -- when you deploy an application using
> the code created below, it will assume that message.wfm
> is included in the application, and if not, you will
> get an error.
>
> :dUFLP:BDEIndex.cc -- used to obtain detailed information
> about the indexes in the table, this is vital for the
> determination of the primary key, which is not really possible
> through the TableDef object as we were doing before. The problem
> with the TableDef is that the primaryKey expression can be
> obtained, but it is possible to have two index tags with the
> same expression, but one of them be a primary key. The code
> that was being used before would attempt to create BOTH
> tags as primary keys, which is not possible ...
>
> ** Note that this program uses Source Aliasing, specifically the
> ** dUFLP source Alias. If you do not know how to set up
> ** a Source Alias, see the instructions in WHATS.NEW at
> ** the top of the file, or in README.TXT.
> ** Any files referenced by :dUFLP:filename must be
> ** included in an executable if you are building
> ** one ... make sure that your project includes these
> ** files.
> **
> ** This particular program uses:
> ** :dUFLP:message.wfm
> ** :dUFLP:BDEIndex.cc
> ** :dUFLP:dBF7File.cc
> ** :dUFLP:BFile.cc
> ** :dUFLP:BDEAlias.cc
>
> */
>
> parameter aDatabase // changed to array of databases 6/22/99
>
> //new section to handle character rather than array parameter 6/22/99
> if type("aDatabase")=="C"
> local cTmp
> cTmp=aDatabase
> aDatabase=new array()
> aDatabase.add(cTmp)
> endif
>
> close database // just to be sure no tables or
> // databases are open ...
>
> // Need this array:
> aTables = new Array()
> // we'll be checking this throughout ...:
> lDatabase = false
>
> if argCount() > 0
> for x=1 to aDatabase.size // added loop for number of databases 6/22/99
> // if we're using a database, we need to get the
> // table names into an array ...:
> lDatabase := true
> try
> dMyData = new database()
> dMyData.databaseName := aDatabase[x]//changed to array 6/22/99
> dMyData.active := true
> catch (exception e)
> msgbox( "BDE Alias error: "+e.code+", "+e.message, ;
> "Problem!", 16 )
> dMyData.active := false
> return
> endtry
> aTables = dMyData.getSchema("tables")
>
> set procedure to :dUFLP:BDEAlias.cc additive
> oBDE = new BDEAlias()
> cDataBasePath = oBDE.databaseDir( dMyData.databaseName )
> // add trailing backslash
> cDatabasePath += "\"
>
> //new section - 6/22/99
> if anyFiles() //check for files
> fProgram=iif(type("fProgram")="O" ,fProgram,openfile()
) // opens 'rebuild indes.prg'
> makeFile(lDatabase,a
Tables,fProgram,aDat
abase& #91;x],cDatabasePath
) // writes to 'rebuild index.prg'
> endif
> endfor
> cleanup(fProgram) // created cleanup function 6/23/99
> else
> // we're NOT using a database, so check the current directory:
> aTables = _app.databases[1].getSchema("tables")
> cDataBasePath = set("dire")
>
> //new section - 6/22/99
> if anyFiles() //check for files
> fProgram=openfile() // opens 'rebuild indes.prg'
> makeFile(lDatabase,a
Tables,fProgram,"",cDatabasePath) // writes to 'rebuild index.prg'
> cleanup(fProgram)
> endif
> endif
> return
>
> function cleanup(fProgram) // new function - old code 6/23/99
> // cleanup ... //pulled parts of following from end of old program 6/22/99
> cOutString = ""
> fProgram.puts( cOutString )
> cOutString = "/* -- End of Program: RebuildIndexes.prg */"
> fProgram.puts( cOutString )
> fProgram.close()
> msgbox( "The program is RebuildIndexes.prg -- note if you used"+chr(13)+;
> "earlier versions of this program, the space is gone from the filename.",;
> "Finished!",64)
> return
>
> function Anyfiles // new function - old code 6/22/99
> // check to see if we're wasting our time:
> if aLen( aTables ) == 0
> msgbox( "There are no .DBF tables in this directory!",;
> "Nothing to do", 16)
> return false
> endif
> return true
>
> function openFile // new function - old code 6/22/99
> // create file object:
> fProgram = new File()
> // should just overwrite one if it exists
> fProgram.create( "RebuildIndexes.prg", "W" )
> return (fProgram)
>
> // new function - old code 6/22/99
> // function called as many times as there are database names in the aDatabase array paramater
> function makeFile(lDatabase,a
Tables,fProgram,cDat
abase,cDatabasePath)

> // sort it ...
> aTables.sort()
>
> // Store some basic stuff into beginning of program:
> cOutString = "/*"
> fProgram.puts( cOutString )
> cOutString = " RebuildIndexes.prg"
> fProgram.puts( cOutString )
> cOutString = " Program Generated by 'CreateReindex.prg' in the dUFLP library."
> fProgram.puts( cOutString )
> cOutString = " Date generated: "+date()
> fProgram.puts( cOutString )
> cOutString = " This will delete the .mdx file and rebuild the index tags from scratch."
> fProgram.puts( cOutString )
> cOutString = ""
> fProgram.puts( cOutString )
> cOutString = " ** Make sure you deploy: "
> fProgram.puts( cOutString )
> cOutString = " :dUFLP:Message.wfm"
> fProgram.puts( cOutString )
> cOutString = " :dUFLP:dBF7File.cc"
> fProgram.puts( cOutString )
> cOutString = " :dUFLP:BFile.cc"
> fProgram.puts( cOutString )
> cOutString = " :dUFLP:BDEAlias.cc"
> fProgram.puts( cOutString )
> cOutString = "*/"
> fProgram.puts( cOutString )
> cOutString = ""
> fProgram.puts( cOutString )
> cOutString = "close database // Will close tables/databases just to be safe"
> fProgram.puts( cOutString )
> cOutString = ""
> fProgram.puts( cOutString )
> if lDatabase
> cOutString = "// set up the database if needed"
> fProgram.puts( cOutString )
> cOutString = "d = new Database()"
> fProgram.puts( cOutString )
> cOutString = "d.databaseName := '"+cDatabase+"'"
> fProgram.puts( cOutString )
> cOutString = "d.active := true"
> fProgram.puts( cOutString )
> cOutString = ""
> fProgram.puts( cOutString )
> else
> cOutString = "// need a database reference"
> fProgram.puts( cOutString )
> cOutString = "d = _app.databases[1]"
> fProgram.puts( cOutString )
> cOutString = ""
> fProgram.puts( cOutString )
> endif
> cOutString = "set procedure to :dUFLP:message.wfm additive"
> fProgram.puts( cOutString )
> cOutString = "fMessage = new MessageForm()"
> fProgram.puts( cOutString )
> cOutString = "fMessage.text = 'Processing Tables'"
> fProgram.puts( cOutString )
> cOutString = "fMessage.title.text = 'Recreating index tags'"
> fProgram.puts( cOutString )
> cOutString = "fMessage.open()"
> fProgram.puts( cOutString )
>
> // add a blank line
> cOutString = ""
> fProgram.puts( cOutString )
>
> // open a message dialog to show user something's
> // happening:
> set procedure to :dUFLP:message.wfm additive
> fMessage = new MessageForm()
> fMessage.text := "Processing tables"
> fMessage.title.text := "Getting index tags"
> fMessage.message.text := upper( aTables[ 1 ] )
> fMessage.Open()
>
> // need to get path to tables, so we can delete .mdx files
> // as needed. Currently we're outputting a hard-coded path ...
> cOutString = "// Need the path to the tables"
> fProgram.puts( cOutString )
> if lDatabase
> cOutString = "set procedure to :dUFLP:BDEAlias.cc additive"
> fProgram.puts( cOutString )
> cOutString = "oBDE = new BDEAlias()"
> fProgram.puts( cOutString )
> cOutString = [cDataBasePath = oBDE.databaseDir( d.databaseName )]
> fProgram.puts( cOutString )
> cOutString = "// add trailing backslash"
> fProgram.puts( cOutString )
> cOutString = [cDatabasePath += "\"]
> fProgram.puts( cOutString )
> else
> cOutString = [cDatabasePath = set("dire")+"\"]
> fProgram.puts( cOutString )
> endif
> fProgram.puts( " " )
>
>
> // now, do it!
> fProgram.puts( "// --------------------------------------" )
> fProgram.puts( "// Start processing individual tables ..." )
> fProgram.puts( "// --------------------------------------" )
>
> for tableNumber = 1 to aLen( aTables, 1 )
> // Display information in message form:
> fMessage.message.text := upper( aTables[ tableNumber ] )
>
> // Instance of TableDef object
> tTable = new TableDef()
> if lDatabase
> tTable.database := dMyData
> endif
> // Give it the table name to use
> tTable.tableName := aTables[tableNumber]
> // Load the table
> tTable.load()
> // new for the update -- July 2005:
> // and we need a query:
> qTable = new query()
> if lDatabase
> qTable.database := dMyData
> endif
> qTable.sql := [select * from ']+aTables[TableNumber]+[']
> qTable.active := true
>
> // shorten coding a bit:
> cTableName = aTables[ tableNumber ].toUpperCase()
> // output name of table and message instructions ...
> cOutString = " // -- "+cTableName
> fProgram.puts( cOutString )
> cOutString = " fMessage.message.text = '"+cTableName+"'"
> fProgram.puts( cOutString )
> cOutString = " fMessage.repaint()"
> fProgram.puts( cOutString )
>
> // Deal with index tags, if any.
> if tTable.indexes.size > 0
>
> // Open the index ...
> set procedure to :dUFLP:BDEIndex.cc additive
> oInd = new BDEIndex()
>
> // code to unhook the indexes using :dUFLP:dBF7File.cc
> cOutString = " /"+"/ Disconnecting index flag for table"
> fProgram.puts( cOutString )
> cOutString = " try"
> fProgram.puts( cOutString )
> cOutString = " set procedure to :dUFLP:dBF7File.cc additive"
> fProgram.puts( cOutString )
> if lDatabase // database?
> cOutString = [ oDBF7File = new DBF7File( ":]+dMyData.databaseName+[:]+aTables[TableNumber]+[" )]
> else // no database
> cOutString = [ oDBF7File = new DBF7File( "]+aTables[TableNumber]+[" )]
> endif
> fProgram.puts( cOutString )
> // Disconnect MDX tags:
> cOutString = " nRet = oDBF7File.SetMDXFlag(false) // turn off internal flag in table"
> fProgram.puts( cOutString )
> cOutString = " if nRet > 0 // Error!"
> fProgram.puts( cOutString )
> cOutString = [ msgbox( "An error occurred disconnecting MDX flag for table ']+;
> aTables[TableNumber]+['", "RebuildIndex.prg Error", 16 )]
> fProgram.puts( cOutString )
> cOutString = " return"
> fProgram.puts( cOutString )
> cOutString = " endif"
> fProgram.puts( cOutString )
> cOutString = " release object oDBF7File"
> fProgram.puts( cOutString )
> cOutString = " close procedure :dUFLP:dBF7File.cc"
> fProgram.puts( cOutString )
> // add code to delete the .MDX file -- this should hopefully get rid of any issues
> // with the primary index existing ...?
> cTableName = left( aTables[TableNumber], at( ".", aTables[TableNumber] )-1 )
> cIndexFile = cTableName+".mdx"
> cOutString = " // Erase the .mdx file:"
> fProgram.puts( cOutString )
> cOutString = [ cFullIndex = cDatabasePath+"]+cIndexFile+["]
> fProgram.puts( cOutString )
> cOutString = [ if file( cFullIndex )]
> fProgram.puts( cOutString )
> cOutString = [ erase ( cFullIndex )]
> fProgram.puts( cOutString )
> cOutString = " endif"
> fProgram.puts( cOutString )
> cOutString = " catch( Exception E )"
> fProgram.puts( cOutString )
> cOutString = " msgbox( 'Error: '+e.code+chr(13)+e.message )"
> fProgram.puts( cOutString )
> cOutString = " return"
> fProgram.puts( cOutString )
> cOutString = " endtry"
> fProgram.puts( cOutString )
> cOutString = "" // blank line
> fProgram.puts( cOutString )
> else
> cOutString = " // No Indexes to Process"
> fProgram.puts( cOutString )
> endif
>
> // at this point there should be no .MDX file and hence
> // no index tags. Next, we need to rebuild ...
>
> // are there any index tags in the first place?
> if tTable.indexes.size > 0
> cOutString = " // rebuild index tags ..."
> fProgram.puts( cOutString )
>
> for indexNumber = 1 to tTable.indexes.size
> // use BDEIndex.cc, we can get *ALL* the properties of the index tag:
> aTag = oInd.TagProperties( qTable, indexNumber )
> // see if this is a primary key
> if aTag["Primary"]
> cOutString = " // index tag: "+aTag["IndexName"]+" (primary key)"
> fProgram.puts( cOutString )
> cOutString = " // primary key, we must use XDML to create it:"
> fProgram.puts( cOutString )
> cOutString = " try"
> fProgram.puts( cOutString )
>
> if lDatabase
> cOutString = " use :"+cDatabase+":"+cTableName+;
> " exclusive"
> else
> cOutString = " use " + cTableName + " exclusive"
> endif
> fProgram.puts( cOutString )
>
> // fix for single field primary key with space in field name
> // added 5/24/99 by gw
> cTemp = aTag["Expression"]
> for i = 1 to tTable.fields.size
> if trim(upper(tTable.fields[i].fieldName)) == ;
> trim(upper(cTemp)) and ;
> ' ' $ cTemp
> cTemp := ':' + cTemp + ':'
> endif
> endfor
> // end of fix
>
> cOutString = " index on " + ;
> cTemp + ;
> " tag '" + ;
> aTag["IndexName"]+"'"
>
> if aTag["Descending"]
> cOutString += " descending"
> endif
>
> cOutString += " primary"
> fProgram.puts( cOutString )
>
> cOutString = " catch ( exception e )"
> fProgram.puts( cOutString )
>
> cOutString = ;
> " // dBASE may throw an exception about " + ;
> "invalid file name here " + chr(13) + ;
> " // (presumably for the key violation table)" + chr(13) + ;
> " // of course it will also fail if we didn't" + chr(13) + ;
> " // get exclusive use of the table."
> fProgram.puts( cOutString )
>
> cOutString = " endtry"
> fProgram.puts( cOutString )
>
> cOutString = " use"
> fProgram.puts( cOutString )
>
> cOutString = ""
> fProgram.puts( cOutString )
>
> else
> /*
> Modified, April 2, 2003 -- changed function call for
> expression, forExpression and indexName, in case of problems
> with the use of various string delimiters the problem
> is that the table designer allows you to use any
> combination of the three possible delimiters, and this
> caused a problem in some testing Geoff Wass and Ivar Jessen
> were doing. We also need to check to see if the expression
> and forExpression contain, by chance, all three delimiters,
> in which case we cannot create this index tag ...
> */
> cExp = aTag["Expression"]
> cForExp = aTag["ForExpression"]
>
> // check to see if the expression contains all three
> // OR the forExpression contains all three ...
> if ( cExp.indexOf( ["] ) > -1 AND ;
> cExp.indexOf( ['] ) > -1 AND ;
> cExp.indexOf( "[" ) > -1 ) OR ;
> ( cForExp.indexOf( ["] ) > -1 AND ;
> cForExp.indexOf( ['] ) > -1 AND ;
> cForExp.indexOf( "[" ) > -1 )
>
> msgbox( "Index: "+aTag["IndexName"] +;
> "has an expression or forExpression containing "+chr(13)+;
> "all three string delimiters, which this program cannot "+;
> "work with."+chr(13)+;
> "Please use a maximum of two string delimiters ... "+chr(13)+;
> "This index tag will not be created.",;
> "CreateReindex Error", 16 )
>
> else // it's okay
> cOutString = " // index tag: "+aTag["IndexName"]
> fProgram.puts( cOutString )
> cOutString = " i = new DBFIndex()"
> fProgram.puts( cOutString )
> cOutString = " i.expression := "+CheckDelim( aTag["Expression"] )
> fProgram.puts( cOutString )
> cOutString = " i.descending := "+aTag["Descending"]
> fProgram.puts( cOutString )
> cOutString = " i.unique := "+aTag["Unique"]
> fProgram.puts( cOutString )
> cOutString = " i.forExpression := "+CheckDelim( aTag["ForExpression"] )
> fProgram.puts( cOutString )
> cOutString = " i.indexName := "+CheckDelim( aTag["IndexName"] )
> fProgram.puts( cOutString )
> // another undocumented feature:
> cOutString = " d.createIndex( '"+cTableName+"', i ) // create it"
> fProgram.puts( cOutString )
>
> endif // check for all three string delimiters
>
> endif // skip primary key
>
> next // indexNumber
> endif
>
> cOutString = ""
> fProgram.puts( cOutString )
> release object tTable
> tTable = null
> next
>
> if lDatabase
> // deactivate the database we used in this program:
> dMyData.active := false
> // output code to deactivate it in the new program:
> cOutString = "// deactivate database:"
> fProgram.puts( cOutString )
> cOutString = "d.active := false"
> fProgram.puts( cOutString )
> endif
>
> // the rest ... (cleanup ...)
> cOutString = ""
> fProgram.puts( cOutString )
> cOutString = "// remove the message dialog"
> fProgram.puts( cOutString )
> cOutString = "fMessage.release()"
> fProgram.puts( cOutString )
>
> // cleanup
> fMessage.release() //left this here.
>
> return
>
> function CheckDelim( cString )
> /*
> Code provided by Geoff Wass to check for
> delimiters of specific types, and try to
> deal with setting beginning/ending delimiters
> for a string that are not contained IN the
> string ...
> */
> local cStart, cEnd
>
> cStart = ""
> cEnd = ""
>
> if cString.indexOf( ["] ) == -1 // " not found
> cStart := ["]
> cEnd := ["]
> elseif cString.indexOf( ['] ) == -1 // ' not found
> cStart := [']
> cEnd := [']
> elseif cString.indexOf( "[" ) == -1 // [ not found
> cStart := "["
> cEnd := "]"
> endif
>
> return( cStart+cString+cEnd )
>
> /*
> -- End of Program: CREATEREINDEX.PRG --
> */
>

Ken Mayer [dBVIPS]

2005-08-05, 8:24 pm

Howard Mintzer wrote:
> glad to be of help....anxiously (well maybe not anxiously <g> ) waiting
> for the book to come out


Well, if you're too anxious you could probably hurt yourself. <g> I sure
wish I didn't have to wait for the printed galleys as long as I have to,
but that's the way it goes (a couple-three weeks ... sheesh!).

Ken

--
/(Opinions expressed are purely my own, not those of dataBased
Intelligence, Inc.)/

*Ken Mayer* [dBVIPS]
/Golden Stag Productions/
dBASE at goldenstag dot net
http://www.goldenstag.net/GSP
http://www.goldenstag.net/dbase
Howard Mintzer

2005-08-07, 3:23 am

Ken,
I uses the rebuildindexes.prg as a daily file maintenance. I also use
it to pack files in order to get rid of dbase soft deletes. I modified
the createreindex.prg to accept another parameter after aDatabases
called bPack, true adds the lines d.packfile(mytable) and false doesn't.
Here are the lines I've changed the code in and attached it my version
of the file...if you think it's useful, add it to the duflp code....

Howie

parameter aDatabase,bPack //original line 168
if argcount()=1
bPack=false
endif


makeFile(lDatabase,a
Tables,fProgram,aDat
abase& #91;x],cDatabasePath
,bPack)
//original line 212

function makeFile(lDatabase,a
Tables,fProgram,cDat
abase,cDatabasePath,
bPack)
//original line 274

if bPack
cOutString = " d.packtable( '"+cTableName+"') // pack it"
fProgram.puts( cOutString )
endif
//original line 476


<BTW>
when i run the program like this
set proc to createreindex.prg addi
createreindex('mydat
abase',false) or
createreindex('mydat
abase',true)
it runs fine.

when i run it like this
do createreindex('mydat
abase',false)

It runs to completion and then gives me the following error message:
Error: datatype mismatch, expecting character. Can't seem to find the
source of it. This happens with either your version or mine

Howie

Ivar B. Jessen

2005-08-07, 7:23 am

On Sat, 06 Aug 2005 23:52:24 -0400, Howard Mintzer <hmintzer@optonline.net>
wrote:


><BTW>
>when i run the program like this
>set proc to createreindex.prg addi
> createreindex('mydat
abase',false) or
> createreindex('mydat
abase',true)
>it runs fine.
>
>when i run it like this
>do createreindex('mydat
abase',false)
>
>It runs to completion and then gives me the following error message:
>Error: datatype mismatch, expecting character. Can't seem to find the
>source of it. This happens with either your version or mine



See the OLH on DO:

"Although you may use DO to execute functions, common style dictates the
use of the call operator (the parentheses) when calling functions, and the
DO command when running a program file. The DO command supports the use of
a file path and extension, and the ? and <filename skeleton> options. The
call operator supports calling a function by name only. In the
not-recommended situation where you have a program file that has the same
name as a function loaded into memory, the DO command will execute the
program file, and the call operator will executed the loaded function.
Other than these differences, the two calling methods behave the same, and
follow the same search rules described later in this section".

It is probably not good practice to use
do createreindex('mydat
abase',false)

Also the program is a little weak in checking the validity of the
parameters, see the errors you get when doing this:

CreateReindex( , false)
CreateReindex("", false) // error is trapped but not in friendly way ;-)
CreateReindex(0, false)
CreateReindex(true, false)


BTW typing 'display memory' after running CreateReindex.prg I see this:

VSTRUCTREGI... Pub O
1 variables defined, 0 bytes used

It looks like CreateReindex is forgetting to release something connected
with Vstruct.prg in the duflp.


Ivar B. Jessen
Howard Mintzer

2005-08-07, 11:23 am

Thnaks Ivar for straightening me out on that. Not that I use it much :-)
Just wanted to add that packtable line to the rebuildindexes that I do
each morning, so I could have my users fully clean out and make sure
that i get any built up little problems out of the data files.

All the other problems might be a big deal if this program was actually
run over and over again in someone's app. but being a once in a long
while utility program, the little probs you've mentioned don't really
mean much

Howie


Ivar B. Jessen wrote:
> On Sat, 06 Aug 2005 23:52:24 -0400, Howard Mintzer <hmintzer@optonline.net>
> wrote:
>
>
>
>
>
>
> See the OLH on DO:
>
> "Although you may use DO to execute functions, common style dictates the
> use of the call operator (the parentheses) when calling functions, and the
> DO command when running a program file. The DO command supports the use of
> a file path and extension, and the ? and <filename skeleton> options. The
> call operator supports calling a function by name only. In the
> not-recommended situation where you have a program file that has the same
> name as a function loaded into memory, the DO command will execute the
> program file, and the call operator will executed the loaded function.
> Other than these differences, the two calling methods behave the same, and
> follow the same search rules described later in this section".
>
> It is probably not good practice to use
> do createreindex('mydat
abase',false)
>
> Also the program is a little weak in checking the validity of the
> parameters, see the errors you get when doing this:
>
> CreateReindex( , false)
> CreateReindex("", false) // error is trapped but not in friendly way ;-)
> CreateReindex(0, false)
> CreateReindex(true, false)
>
>
> BTW typing 'display memory' after running CreateReindex.prg I see this:
>
> VSTRUCTREGI... Pub O
> 1 variables defined, 0 bytes used
>
> It looks like CreateReindex is forgetting to release something connected
> with Vstruct.prg in the duflp.
>
>
> Ivar B. Jessen

Ken Mayer [dBVIPS]

2005-08-07, 1:23 pm

Howard Mintzer wrote:
> Ken,
> I uses the rebuildindexes.prg as a daily file maintenance. I also use
> it to pack files in order to get rid of dbase soft deletes. I modified
> the createreindex.prg to accept another parameter after aDatabases
> called bPack, true adds the lines d.packfile(mytable) and false doesn't.
> Here are the lines I've changed the code in and attached it my version
> of the file...if you think it's useful, add it to the duflp code....


Seems to me that packing should be independent of rebuilding indexes ...
at least for a utility ...

Ken

--
/(Opinions expressed are purely my own, not those of dataBased
Intelligence, Inc.)/

*Ken Mayer* [dBVIPS]
/Golden Stag Productions/
dBASE at goldenstag dot net
http://www.goldenstag.net/GSP
http://www.goldenstag.net/dbase
Howard Mintzer

2005-08-08, 3:25 am

Thanks Ken, I respect your opinion....but I'm happy this solution works
for me.

Howie

Ken Mayer [dBVIPS] wrote:
> Howard Mintzer wrote:
>
>
>
> Seems to me that packing should be independent of rebuilding indexes ...
> at least for a utility ...
>
> Ken
>

Sponsored Links





Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive | Programming forum archive

Copyright 2008 droptable.com