Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations derfloh on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Select # and Use statments 2

Status
Not open for further replies.

jmeckley

Programmer
Jul 15, 2002
5,269
US
I have a FP 2.5a system. for the most part it runs without any major problems. The system runs on virtual Windows 98 machines. the files and tables are on the network (WS2K3) and foxpro is local on the 98 machine.

Lately the system will hang if we try to print invoices (a report). I haven't found out why this happens, but I can reproduce the problem on my local development copy.

One thing I noticed about the procedure to process invoices is the code looks like this
Code:
procedure processinvoice
select 1
use customer.dbf
select 2
use orderheader.dbf
select 3
use orderdetail.dbf
set relations from orderheader to orderdetail
select 4
...
select 5

ordernumber = 0
get "enter order number: " ordernumber

select 2
locate orderheader.id = ordernumber
while .T.
   process order and line items
endwhile

do printinvoice.qpr

select 1
update customer table

select 2
update orderheader table

return
If I understand FP queries correctly. each Select is like a different container which a tale is opened in. If I want to read/write values to a table I need to select that container and then update the fields/columns.

however the containers are never closed. no code like this exists
Code:
select 1
use
select 2
use
...
select n
use
should the containers be closed before exiting the procedure? would this be a source of a memory leak?

I know enough about FP to be dangerous. I spend the majority of time in C#, so FP 2.5a is very foreign to me.

one thing that has changed is the volume of data. each day the invoices older than 90 days are archived to another table to help keep the volume of data manageable. The volume of orders has increased so the overall table size has grown, despite the archiving process. Could this have an impact on the queries/reports/prints hanging?
.........

additional information
the system is a procedural code file the basic structure looks like this
Code:
say "main menu"
say "1. do this"
say "2. do that"
say "3. exit system"
get "enter option" option
do case
   case option = 1
      dothis
   case option = 2
      dothat
   case option = 3
      exit
endcase

procedure tothis
   select 1
   use a table.dbf

   get "enter id" id
   while locate table.column = id
     do some work
   endwhile
   do report.frx
return

procedure tothat
   say "1. do it like this"
   say "2. do it like that"
   say "3. return to main menu"

   get "enter option" option

   do case
      case option = 1
         a procedure similar to dothis
      case option = 2
        a procedure similar to dothat
      case option = 3
        return 
   endcase
the menus can be nest several procedures deep. The point of all this is to ask. would opening a Select container and not closing it cause a memory leak?

Jason Meckley
Programmer
Specialty Bakers, Inc.

faq855-7190
faq732-7259
 
To answer the memory leak question, no. It wouldn't be a 'leak', but you could be running low on usable memory by having a lot of tables open. Closing them again with a USE or a CLOSE ALL would free up that memory.
What usually causes memory leaks is running SQL statements from those tables.
And just so you no, the 'container' you refer to is called a 'work are' in fox.

There is a file size limit of 2 gig for any fox table though, so if you reach that limit, the application can hang. Larger tables will definitely slow the app down though.

There is also a nesting limit I believe of 25 levels. The application will hang if your procedures nest that deep.

Beyond that, it's hard to say what is hanging without knowing a little more detail about precisely where it hangs. Can you step through the code and determine at what point it hangs?

One more thing, were I you, I would get in the habit of referencing the tables/work areas by name rather than number.
Issuing a SELECT 0 gets the next available work area. You can then open the table such as 'customers' by saying USE customers. From that point, you can make sure you're updating the proper table by saying SELECT customers and making your updates.

SELECT 0
USE customers
SET ORDER TO ....

SELECT 0
USE invoices
SET ORDER TO ...
.
.
.

SELECT customer
REPLACE something WITH something
SELECT invoices
APPEND BLANK
REPLACE something WITH something

And so on.



-Dave Summers-
[cheers]
Even more Fox stuff at:
 
thank you dave, this provides some insight into how FP is behaving. some follow up questions:

1. what is the impact of not closing/use/close all at the end of a procedure?

2. are there issues with opening the same table in multiple workareas? for example
Code:
procedure foo
   select 0
   use cusotmer.dbf
   ....
   do bar
   alter customer
return

procedure bar
   select 1
   use customer.dbf
   alter customer
return

is there a memory leak (or just a problem) with code like this? the original code would look like the first 3 lines in display order. I added the code to precalculate the total based on my understanding of sql.
Code:
procedure displayorder
  select 0
  use Order.dbf

  Do OrderScreen.spr

  replace Order.ComputedValue = Compute(Order.OrderNumber)
return

function Compute parameter orderNumber
  Dim result[0]
  select sum(quantity * price) from orderdetail d, product p where d.productid = p.id and d.ordernumber = OrderNumber into array result

  return cint(result[1])

Jason Meckley
Programmer

faq855-7190
faq732-7259
 
The main issue with not closing tables after you open them is that you might be trying to open them elsewhere.

Which leads to the problem is your second question. The code you show won't work. You can open a table more than once at the same time. However, to do so, each instance must have a different _alias_ and you need the AGAIN keyword.

For example, here I'm opening the Customer table twice:

SELECT 0
USE Customer

SELECT 0
USE Customer AGAIN ALIAS Cust2

Now I can talk to both instances, by referring to the first as Customer and the second as Cust2.

As Dave said, you should get out of the habit of referring to work areas by their numbers. Always use the alias of the table open in the work area. That way, you never care which work area a table is in.

Tamar
 
The first versions of foxpro only had 10 work areas (not work are, work area), which you could also adress as a to j. Therefor early fox programming might have rather worked with work area numbers than alias names.

As Tamar says this is bad habit, I think way back then there were perhaps no alias names to also adress work areas, only the single letter or a number 1 to 10.

That's perhaps explaing why the code was written that way. You may even get used to a work area number always "hosting" a certain table. This also may be a reason to keep tables open. Code would perhaps reuse open tables and not close and open them all the time, this also takes time, remember fox goes far back, foxbase released 1984 as dbase II "clone".

An open table does not occupy much memory, it's rather it's buffer containing changes, if it's buffered at all. Itself is only occupying a file handle and caching memory, which of course could grow up to the table size.

Yes, you could flush that memory by closing tables and reopening them.

It's hard to say, what your problem is, without debugging. I think either set step on or suspend in the code would open the debugger so you should try one of these before the report runs and then could single step through code. That's when running within VFP, both commands won't work in the compiled version.

You may get a more stable system virtualizing XP rather than Win98, which may simply better work in the network than win98.

Bye, Olaf.
 
thanks Olaf. problem is it's FP 2.5 and it doesn't run on Windows XP. We don't have VFP either. if we were to upgrade it would be a re-write to .net.

Jason Meckley
Programmer

faq855-7190
faq732-7259
 
and FPD should also have a debugger, as I said VFP I merely meant running within the IDE vs the compiled code. As you say reports hang, you should debug them.

Bye, Olaf.
 
now to figure out how to debug FP 2.5a. I didn't even know this was an option. makes sense, but I never saw a "deubg" option in the menu strip.

Jason Meckley
Programmer

faq855-7190
faq732-7259
 
The best way to use the debugger is to click on the 'Window' -> 'Trace' menu selections, or type in SET STEP ON in the command window. This opens the 'trace' window which lets you step through program code. Within the Trace window, click on 'Program' -> 'Open', then find the .prg file you want to debug. By clicking on a line of code, you toggle it as being a breakpoint.
The 'Window' -> 'Debug' menu selection opens a window where you can input variables of which you want to monitor values.

You can also use SET STEP ON in your .PRG to have execution stop and open the 'trace' window at run time, if you're running your application through the Fox IDE. You will get a 'Feature not available' if you try using that statement in an executable though, so you need to remember to remove those statements.


-Dave Summers-
[cheers]
Even more Fox stuff at:
 
thanks Dave, I'll give it a shot.

Jason Meckley
Programmer

faq855-7190
faq732-7259
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top