VFP SQL verus DO WHILE

Filed Under (Visual FoxPro, work.BLOG) by WildFire on 30-09-2004

172 bugs-to-squash+features-to-code down… 1,161,017 to go. I’ll break from the task for a while and blog a little.

I visited a client yesterday confident that I had tweaked the ILS program to make things faster. I ended up realizing ‘on site’ that things got slower by 1560 folds.

Bad. Too bad really.

Because of some server folder/file-security-related issues, I have to separate the directories that are used for the ILS module (the main library system) and SASM (the book+author+subject+callnum+isbn searching) module that is being used by the students/faculty members in a given library.

Because the tables are normalized (UGH I still have an unfinished discussion blog about normalization), I have to use some VFP SQL queries to gather all the data needed from three separate tables. VFP SQL ((sans the JOIN…. yup using that makes the querying of data turtle-fast (no offense to the turtles)) is still slow.

(More than 30 seconds of query-ing is slow by Foxpro standards (we’re so used to Rushmore’s legendary lightning speed technology)).

For those who are not used to Visual Foxpro, VFP has it’s own ‘native’ SQL functions which can be used without relying on ADODB, OLEDB, ODBC and whatever ODODODODO-database-related-technologies proliferating around.

So to tighten up things a little bit I decided to make a separate ‘gatherer module’ which will be executed on the server/admin part and will be thrown to the student/users PC used for searching instead of slowing down things every time the user ‘SASMs’.

I tried using the VIEWS approach on this one (which apparently uses VFP SQL commands too) but have to withdraw at the last minute since there are some incompatibility issues with some table formats that I’m using and I don’t want to completely dive in without testing things further.

So I decided to just create a different ‘buffer table’ that will hold the fields gathered from these three databases… using the native VFP SQL command. Here’s the code:

cDATABASE = 'BOOKSASM'
set safety OFF
select BOOKS.ACCESSNO, BOOKS.CALLNUM, BOOKS.TITLE, BOOKS.ISBN, ;
BOOKS.BORROWED, min(AUTHORS.NAME) as [NAME], ;
LOCATION.LOCATION ;
from BOOKS, AUTHORS, LOCATION ;
into dbf &cDATABASE ;
group by BOOKS.ACCESSNO, BOOKS.CALLNUM, BOOKS.TITLE, ;
BOOKS.ISBN, BOOKS.BORROWED, LOCATION.LOCATION ;
where ((BOOKS.ACCESSNO == AUTHORS.ACCESSNO) or ;
BOOKS.NUM_AUTHOR == 0) ;
and BOOKS.LIBSECTION == LOCATION.ID
set safety ON

select BOOKSASM
if !file('BOOKSASM.cdx')
index on alltrim(ACCESSNO) tag CBOOIDNO
index on upper(alltrim(CALLNUM)) tag CBOOCALL
index on upper(alltrim(TITLE)) tag CBOOTITL
index on alltrim(LOCATION) tag CBOOLIBS
index on alltrim(ISBN) tag CBOOISBN
index on upper(alltrim(NAME)) tag CBOONAME
endif

close databases
close all

Guess how long it took for that piece of code to process 2224 records in BOOKS.dbf, 2856 records in AUTHORS.dbf and 15 records in LOCATION.dbf?

Well long enough for me to visit another office and install a newly updated AVRCOM module, discuss that module with the user, return and discuss (with the librarians this time) another set of topics from their lovelife to the difference between computer science and other courses with the ‘IT’ letters in it to topics which made me retrieve the baby pictures I have in my wallet.

52 minutes… for that code… for that number of records.

And I did not even include the instances where a conflict with the screensaver crashed the query process that I have to start things all over again, and that I copied the files outside the arms of a burdened Novell Netware 6 server and transferred it to the local drive for faster processing.

52 whoopin’ minutes!

So when I got home. I re-configured the code using a reliable old school approach… DO WHILE/FOR LOOPS + SET FILTER TO.

Here…

select BOOKS	
nCountTotal = reccount()
nCounter = 0
set filter to
set order to CBOOIDNO
go top
do while not eof()
nCounter = nCounter + 1

cAccessNo = BOOKS.ACCESSNO
cCallNum = BOOKS.CALLNUM
cBookTitle = BOOKS.TITLE
cISBN = BOOKS.ISBN
lBorrowed = BOOKS.BORROWED
cLibSection = BOOKS.LIBSECTION

select AUTHORS
set filter to (AUTHORS.ACCESSNO == cAccessNo)
go top
cAuthor = AUTHORS.NAME
set filter to
cLocation = ''

select LOCATION
set filter to
set order to CLOCIDNO
go top
seek cLibSection
if found()
cLocation = LOCATION.LOCATION
endif

select BOOKSASM
append blank
replace BOOKSASM.ACCESSNO with cAccessNo
replace BOOKSASM.CALLNUM with cCallNum
replace BOOKSASM.TITLE with cBookTitle
replace BOOKSASM.ISBN with cISBN
replace BOOKSASM.BORROWED with lBorrowed
replace BOOKSASM.NAME with cAuthor
replace BOOKSASM.LOCATION with cLocation

.cStatusCounter.value = str(nCounter) + '/' + str(nCountTotal)

select BOOKS
skip
enddo

Now guess how long this code processed those 2224*2856*15 (Yes * not + : figure that out).

Less than 15 seconds.

I was even tempted to write an exact time counter after an initial test run but things were so fast that writing that part was not needed anymore.

OK… let me write a code to grab the exact time… wait.

TimeStart: 20:48:46
TimeEnd: 20:48:54

It is even less than 10 seconds!

So tell me… what am I missing here?

(Well aside from the fact that VisualFoxpro is fast and it rocks… everyone knows that already… including VB-lovin’ humans [GRIN])

Walking on Cloud 9.0 of Visual FoxPro

Filed Under (Visual FoxPro, work.BLOG) by WildFire on 20-09-2004

Darn. I can’t work without my costume.

We visited a new client this afternoon. We’ll visit an old client tomorrow. On Wednesday we will visit another new client and another new one on Thursday or Friday depending on the schedule we will set after Wednesday’s visit.

Let’s not even talk about Saturday.

This is something I haven’t anticipated when I dived into the freelance world. That there are instances I would be spending more time visiting clients than coding stuff in front of the PC.

Not that I’m regretting things… it is just that it’s so time consuming. Plus… the travel alone renders the late night after a visit too tiring to code.

Anyway… here are some foxpro-warps: Walking on Cloud 9.0 of Visual FoxPro and The Kit Box: Knock, Knock! Who’s There? (via Alex Feldstein and Andrew MacNeill‘s blogs)

Database Normalization Part 001

Filed Under (Visual FoxPro, work.BLOG) by WildFire on 15-09-2004

This is a screenshot of the prototype of a new project of ours.

To a give you a short overview it is a database program that monitors the children records in a certain place where parents can ‘safely’ leave their children so they can shop with comfort and peace of mind.

These children will then unite with the other ‘temporarily abandoned’ children in that place to battle the forces of evil and squash the invading twelve-headed-iodine-squirting aliens while their parents comfortably shop for shoes and perfumes.

(How I wish someone would come up with the idea for something like this where instead of children, the husbands are the main clients while their lovely wives do the shopping thing… (I would even wholeheartedly create a database program for free if that business pops up))

Some of these children obviously do not win in this enormous battle so a database program is needed to monitor who came back ‘alive’ and who came back ‘replaced’. The TimeIn and TimeOut records of these brave kids are necessary to compute the wormhole coordinates use for their battle portals.

Let us leave those alien battle-invasion details for now and proceed.

If you can remember I posted this yesterday:

If you are to choose between the second level of data normalization or an easier usable interface, what would you prioritize?

Going back to the prototype screenshot above, you see a very simple interface. There are textboxes and combo boxes for the regular information this application needs: ChildIDNO, ChildName, Nickname, Birthdate, FatherName, MotherName, Guardian, ParentsAddress, ParentsPhoneNumber to name a few.

Easy flowing, right?

Probably yes… IF you’re creating something and don’t give an aliens arse after you get paid. If you’re one of those irresponsible ‘database dudes’ out there who deserve to be devoured by sex-cravin’-tentacle-infested aliens.

If you choose the easy path you’ll get a lame database that looks like this (let’s just select the important fields):

_KIDS DATABASE
ChildIDNO ChildName Father Mother Etc…
0000001 X FatherofX+Y MotherofX+Y  
0000002 Y (X’s bro) FatherofX+Y MotherofX+Y  
0000003 Z FatherofZ MotherofZ  

That is even the picture in the best case scenario. Re-entering the parent data again for another kid with the same parents would yield possible errors… extra spaces and more open for typo-related errors.

For example: Foo, John R.
Can be entered as: Foo, John
  Foo, John R
  Foo, John _R. (an extra space)
  Foo, Jonh R. (and countless versions of typos)

If Child_001 and Child_002 are even encoded to the database a number of days apart, the possibility of an error to occur increases. (Let’s say after a month when the second child, learning that one of his sibling was abducted, pledges to go on in a quest to rescue his big brother from aliens.)

(By the way… one of the target readers for these blogs of mine are the ComSci/IT students of our country who needs ‘database enlightenment’; for those who have been experts of this field already, you are free to move your arse out of here (for now) and read other more advanced stuff instead… probably about Source Control HowTo or How windows exploit the hyperthreading technology.)

Now if you’ll look back to the fields above, ParentID, FatherName and MotherName, ParentAddress, ParentsPhone and the other Parents-related information are redundant. A definite no no in the area of database structure planning.

So the first ‘level’ of improvement on this is to create a separate database for Kids and a different database for Parents. Something like this:

_KIDS DATABASE
ChildIDNO ChildName Etc…    
0000001 X      
0000002 Y (X’s bro)      
0000003 Z      
_PARENTS DATABASE
ChildIDNO Father Mother Etc…  
0000001 FatherofX MotherofX    
0000002 FatherofX MotherofX    
0000003 FatherofZ MotherofZ    

The KIDS database holds fields that are related to… well kids and the PARENTS database for PARENTS-related information such as contact number and the likes.

Now… is that enough improvement and normalization already..?

While it is better than the first table it is not that good enough yet. You can still see redundant records in the PARENTS table.

You can improve this further by creating another field PARENTS_ID on the KIDS table linked to the same field in the PARENTS table.

_KIDS DATABASE
ChildIDNO ChildName Parents_ID Etc…  
0000001 X 0000001    
0000002 Y (X’s bro) 0000001    
0000003 Z 0000002    
_PARENTS DATABASE
ChildIDNO Parents_ID Father Mother Etc…
0000001 0000001 FatherofX MotherofX  
0000003 0000002 FatherofZ MotherofZ  

Now is this fine already..?

Better than the first and second approaches but you can still improve things more.

Also… notice that Child_002 disappeared in this scheme.

But I’ll end things here for now and we’ll continue this series on another post which will include the solution.

I also have to tackle yet the issue I posted above, the issue between Data Normalization and a more usable interface. That too on the continuation of this post.

Normalization versus Easier Usability

Filed Under (work.BLOG) by WildFire on 14-09-2004

If you are to choose between the second level of data normalization or an easier usable interface, what would you prioritize?

If you’re not into a software-related career…

Filed Under (Random.links, work.BLOG) by WildFire on 09-09-2004

I spent more than half of this Blessed Mother Mary’s day (or make that yesterday since it is already 4AM (again)), in bed… sleeping.

Slept up to 12Noon, fired up and tweaked some codes for a couple of hours, took my lunch at 3PM then went off to dream away (Some dream episodes just hunger for sequels). Woke up around 6 in the evening and wondered how come time travels so fast.

I should’ve went to the office today to work on a freon-filtered room and tinker with Fedora Core 2 in between coding, which I have just finished downloading a couple of days ago.

I have burned the .iso images last night and was able to convince qs to ‘lend’ me her ‘not-so-old’ Pentium II 166MHz IBM Aptiva computer.

That computer currently runs on Windows XP SP2 so I don’t see any reason it wouldn’t run in a Linux-powered OS.

Yup XP SP2 can run in that 166Mhz/64EDO RAM machine. Although the prior Windows XP SP1 runs faster. SP2 tends to slow down almost everything.

Stress on the ‘everything’ and not the ‘almost’.

But then of course, the comparison here does not involve trojan/spyware-infested Windows XP SP1 machines.

Anyway, I was reading Stephen Sawyer’s post on why he is pursuing a different career after spending years in software development. It makes you think of a lot of things especially if you’re into software development.

EvenMore(DeepThinking++)… if you have slept too much for one day.

If you’re not into a software development related career, what do you think you would be doing right now?

What if it needs to be a job that shouldn’t be computer-related… what would that be?

Will you survive?

Feel free to transmit your binary thoughts here and let us hear some neuron decibel. (Note: You can post as GUEST… no need to register).

Function RantRelease(PissitivityLevel)

Filed Under (Random.scribbles, work.BLOG) by WildFire on 02-09-2004

Function RantRelease(PissitivityLevel)

In this digital world of ours, everything is but 1 and 0.

Equate those values to Output or LackofOutput.

There is no such thing as ‘I-fsckin’-did-my-best’ + IIF(PissitivityLevel > nTolerableValue, ‘!’, ‘.’)

Hell no. ‘Losers always boast of their best’. Those are Sean Connery’s words in that 1996 movie, The Rock.

Output or nothing.

Of course we can never control all the other factors, internal and external… but we have Error Traps to at least minimize, catch, record and refrain from doing such errors ‘recursively’.

We also have events triggered during those error occurences. Our behaviours, attitudes… our knee-jerk reactions. I admit though this is one department I should work on. I get terribly annoyed everytime I see a string 0000000s in my life.

Even if these are ‘first class zeros’.

When working for and with me, that is one character you should have.

Return IIF(nFumeReleased > (PissitivityLevel/2), PeaceofMind, Rocks)

Nose hair as Data Storage

Filed Under (GFX, Random.links, work.BLOG) by WildFire on 02-09-2004

During our client visit yesterday (just hours ago really since it is still 1:11AM and I’m still up), I asked qs to setup and configure the computers inside the internet laboratory while I was finalizing some database integrity checking.

Yup… these days she’s not only involved in database discussions, data flow concepts and usability testing, she’s also doing hands on configurations.

She was even able to override that hide START.RUN feature I included in the IUMS program.

Plus she showed me where MSCONFIG was hidden. For years I was thinking this was an ‘internal command’. I didn’t even bothered looking it up.

But anyway, while she was doing this cleaning of the startup garbage entries through MSCONFIG, running the Novell client application and entering the dummy username and password I created to test the program… she found herself attempting to copy and paste some values from PC-001 thinking she could paste it on PC-002.

Weird and funny really, but this occur to me once in a while. And probably you too have been in this kind of situation.

Which makes me think, what if we can really copy and paste things to a memory within our bodies, let’s say the hair on your fingers or your nose, which can easily be retrieved (and pasted) with a short cut key interfaced with a computer.

It could even be used for storage of passwords and stuff.

Yeah I know, you’d point me to those fingerprint/voice/iris-powered technologies. But I’m talking here about the little amount of data which you can store within your body parts and not using your body parts as a the key.

Some of you would probably lecture me of how the brain should be used… but hey if Microsoft was awarded a patent which involves the usage of body as a source of power (power conduit and data bus to be precise and that was more than two months ago), why not use other parts of the body aside from the brain for little harmless amounts of data storage?

But then again… probably I just need some rest.

Spiderman, anyone?

Unload(TheSuckinessState)

Filed Under (Random.scribbles, work.BLOG) by WildFire on 28-08-2004

I spent most of the day talking and working with a telecom technician who works for a company that provides spanking fast DSL internet connection.

That is if ‘spanking fast’ is defined as the urge to apply a quick blow in the arse to the person next to you every time you get annoyed with the speed. But seriously it is faster than my 56K dial-up internet connection at home.

I even had the chance to ride on their service mobile and talk about life with him, talk about food, the sea and raising children. He accompanied me to a computer hardware retailer, gave me a discount after the owner allowed us to test the component first before even paying for it.

Sometimes we often hear the word ‘sucks’ being added to something. Company-001 sucks. TechBlahBlah sucks.

The world sucks.

Most often we add this word because we’re dissatisfied… or probably because seeing the negative side is inherent to our human traits.

And we do this without even considering the reasons behind such thing.

This technician (I won’t name names nor I would name the company since I don’t like saying negative stuff to a Philippine-based company even if it is already owned by a foreign entity), works with his partner (yup just the two of them) servicing 100++ (or even greater) clients covering an area which is nTechnicians(raised to the power of 32(square miles)).

The company holds N number of employees nationwide five years ago, now they’re down to N/4 and N here is a five digit number having a val(substr(alltrim(str(N)), 2, 1)) > 6. They’re even planning to trim down even more.

Indeed… it is a sucky world out there.

But there’s nothing we could do to improve things by re-stating the obvious.

One must unload(TheSuckinessState).

How?

There are tons of ways really.

But none of them includes including the word ‘sucks’ in anything that disappoints a first person’s pathetic self centered soul.

CodeDump-20040825.153618 (Brute Lee)

Filed Under (Visual FoxPro, work.BLOG) by WildFire on 26-08-2004

Code Dump: the time where you take a break from your programming related tasks to talk about your programming related tasks.

In PROJECT::SOPHIEAI (IUMS: Internet Usage Monitoring System), USAGE.dbf holds the records that stores the log-in/log-off information of the users of a certain internet lab/cafe at a given time and space. Along with the IDNO number of the user of course and some other fields.

Violating the second rule of normalization (or was it the third rule), I also included the TotalNumberofHoursUsed per usage and the TotalFee paid.

If you follow strictly the normalization rules, you know that you don’t have to include in the database fields that can be derived from two or more fields that are already in the database.

For example if your database has fields named Field01 and Field02 with sample values 10 and 618 respectively, you don’t need a Field03 which will store 628, the total of Field01 + Field02. Normalization rule will then call you moronic and consider you an outcast of the database programming world.

You deserve to be eaten alive by vultures.

You deserve a punishment such as watching Barney re-runs again and again.

But in some cases, yes… believe me… there are times when you have to violate and override this rule. These are the cases when speed-related principles are far more important. Plus… considering that these days hard disk space is getting cheaper and time (since Mida’s era) is constantly gold, it justifies the normalization override process.

So back to PROJECT::SOPHIEAI.

Now because of some ‘outside factors’ (again), I need a patch that would make a different database, CRED_NET.dbf, which holds the fields TimeLeft and Credit be synchronized with the data USAGE.dbf holds.

Let’s say USAGE.dbf records for student 0001 are (let’s just take the important fields for discussion):

DATE IDNO TotalTime Fee
20040812 0001 01:00:00 25.00
20040815 0001 02:00:00 50.00

Now CRED_NET on the other hand holds how much is left for a student 0001. There are instances when the values on both databases don’t synchronize. Yes the existence of these databases violate the normalization rule once again but you have read the reasons above already, right?

And can you stop reminding me about normalization rules so we can go on?

So to correct things you execute this untweaked patch (I’ll call it the ‘brute force approach’… ‘Brute’… like ‘Brute Lee’)


   select CRED_NET
   set order to CCRENAME
   do while not eof()
      cIDNO = alltrim(CRED_NET.IDNO)

      **' ···································· 
      **' SECTOR.007.BEGIN

      select USAGE
      set order to CUSAIDNO
      go TOP
      do while not eof()
         if alltrim(USAGE.IDNO) == cIDNO
            cTimeCount = TimeCalc(cTimeCount, USAGE.TIMETOTAL, 1)
            nCreditsTotal = nCreditsTotal + USAGE.FEENET
         endif
         skip
      enddo

      **' ···································· 
      **' SECTOR.007.END

      select CRED_NET
      cTimeReflect = TimeCalc(cTimeCount, '40:00:00', 2)
      nCreditsReflect = 800.00 - nCreditsTotal
 
      rlock()
         replace CRED_NET.TIMELEFT with cTimeReflect
         replace CRED_NET.CREDIT with nCreditsReflect
      unlock

      skip
   enddo

The above code works… of course, but… like any process in this world that involves brute force, it is slow.

Now replace the SECTOR.007 part of the code above with this:

   select USAGE
set order to CUSAIDNO
set filter to alltrim(USAGE.IDNO) == cIDNO
go top
do while not eof()
cTimeCount = TimeCalc(cTimeCount, USAGE.TIMETOTAL, 1)
nCreditsTotal = nCreditsTotal + USAGE.FEENET
skip
enddo

You’ll see a HUGE difference in terms of execution speed.

TimeCalc is a function by the way that adds, substracts, multiplies and divides two time variables. Something which I’ll post later. (You can find the basic/raw version inside the Microsoft Help and Support Site though),

Of course when you’re doing these kinds of patches, don’t forget the progress bars. It is a good hypnotic-mechanism for the users to develop this affinity for your software.

CodeDump-20040825.153618.End

Now back to work.

Freelancin’ Risks 101

Filed Under (work.BLOG) by WildFire on 20-08-2004

Shit happens.

What a way to start a blog.

QS and I had a difficult day. Although our problems are unrelated and we’re not up against each other, still it doesn’t remove the fact that crap happens.

But let’s look at the good side of things… at least she’s blogging once again.

Although I do enjoy freelance software development very much, it doesn’t remove the fact that outside factors come in the way. These outside factors are often used to blame the programmers for every problems popping out of this world.

The user is using the program you created, sidetracked and visited a spyware/trojan-infested site, crashed the computer and spread the worm in the local network, eradicated his documents, impaired the OS which in turn hangs the program.

Guess who they’re blaming?

They blame the programmer and his Level42 idiot-proofed database application.

Of course this is just the simplest variation of certain problems a freelance developer encounters. I could go on and on enumerating them all.

Yes… ‘freelance software development’ may sound sweet to one’s ears, yet… it holds a lot of risks too.

While in a non-freelance software business, clients and some users tend to blame ‘the company’ for any other outside related bugs too, the developers have a better shield. In fact, some are even protected with seven headed salivating bulldogs guarding the programming zone.

While in worst cases, notorious (or shall we use ‘careless’ to be less harsh) programmers get fired or castrated, you seldom see them being blamed directly by users or clients. Experts would even sometimes blame the marketing department or the head for enslaving these borgs in four-sided cubicles.

You don’t see ‘the programmer Mr. Anderson coded this bug, redirect your hate mails to his email’ lines in support forums and company websites.

In some cases, it is the support telephone entities that receive these kind of ‘attacks’. Or the project heads who would professionally protect his team and defend his programmers to the last 8-bit of his blood

In the freelance world you’re on your own. You are responsible for the un-released memory-based variables you make that cause your program to crash the OS. You see unchecked bugs unfold before your eyes while you are presenting the program to your clients. You hear their problems directly. You interact with them. You feel their pain from using your ‘Duh-I-thought-I-solved-that-already’ programs.

You are responsible. No shields or bulldogs to protect you. You’re on your own.

But you do learn and grow.

Not that difficult really if the problem lies on the code or the ‘logistics’ of the program.

A lot harder when the problem lies on the users’ attitude, in the way they view computers, in the way they view life.

And a helluva-lot harder when you don’t know what really caused the problem.

Add the fact that your name is always on the line.

In the world of freelancing, if there’s one thing you have to hold dear and hold it dearly like it’s a 1024K halo-blue-ish diamond found behind the galactic borders of the Andromeda Galaxy only every 1168 lunar cycles… that would be your name… your reputation.

Yes… your reputation.

It can make you or break you.

What’s worse is when your name and reputation is on the line because of the things you don’t do. Because of the ‘outside factors’.

The blasted ‘outside factors’.

But like any other thing this world holds, it’s how you handle these things that counts.

And that too could make and break you.

But whatever happens… life goes on… and still, shit happens.

After-blog dangling references:

I’ll keep you updated on this problem and will make things less abstract once I have a full grasped of what the cause of the problem really is.

ADTX Borgs and FireFox hacks

Filed Under (Random.links, work.BLOG) by WildFire on 19-08-2004

3AM and I’m done wrapping up paper plans for tomorrow’s client visit. Make that later this day.

ADTX SYSTEMS (formerly APTI) is in need of programmers. My former classmate works in that company and she told us that they need at least 50 ‘coders’ immediately (ASAP).

That’s a large number of borgs… quite scary if you’d ask me.

And considering she did used the words ‘immediately’ and ‘ASAP’ in one e-mail, it means something.

They’re looking for Java Programmers (AD 04-007), Microcode/Firmware Engineers (AD04-008) and Device Driver Engineers (AD04-009).

Interested applicants are invited to send their resume, transcript of records and recent 2×2 picture to the address below stating position code:

ADTX Systems, Inc.
c/o Human Resources Department
3/F Multinational Bancorporation Centre
6805 Ayala Avenue, Makati City

Tel Nos: +63 (2) 889-5070 | +63 (2) 845-3875-77
Fax No.: +63 (2) 889-1800
E-mail: jobs [at] adtxsystems [dot] com

Or you can e-mail my classmate: beng [at] adtxsystems [dot] com. Doing so will help her and her co-programmers regain the sleep they’re missing these days.

On a different frequency, Avatar posted some FireFox-related hacks.

Old VB6 Application of ours…

Filed Under (work.BLOG) by WildFire on 18-08-2004

I received an e-mail from one of my college classmate who was also my officemate when I was still working in Davao. He told me that the database project we created 6 years ago was still pretty much alive.

Although I was only an assistant programmer in that project and it was Jerry who did most of the job, still… it is nice to know that the project we dubbed as BRAINS (Budget Resource Allocation Information System) is still being used.

It was also the first database application we developed after being freed from the cruel college un-ending digital chains and thorns. You know… the kind of situation that resembles the code below:


Function GrindThemMore(Project)
for i = 1 to nInfinity
Assign(Project[i])
SetComplexity(i*val('1'+replicate('0',17)))
SetDeadline(nTime = short, lRidiculous = .T., lMovable = .F.)
SetMind('They will work on the last minute anyway... so...')
AddLoad(tracks(Philo, 16) + tracks(Theo, 16) + tracks(English, 24))
lEyeBugs(cExtreme)
nToxicityLevel(Smell, 7*77)
if lStillBreathing
GrindThemMore(Project[i*42])
else
Deport.Student(aPool(OtherCourses))
**' Exit statement removed
endif
endfor
EndFunc

BRAINS was developed in VisualBasic.

Yes, I know lambasting VisualBasic is one of my favorite past times but I do have great respect for it when it is properly and intricately woven.

My friend, Jerry Flores knows this language very well.

He breathes VB.

He handles database normalization to the core.

How about we hear a blog from you, Mr. Jerry ‘VB Guru’ Flores?

Beakman also uses VisualBasic with ADO and SQL very well. The works he’s been putting on his Digital Nervous System is quite remarkable.

The Sybex book I’m currently reading holds a lot of VB6 samples too… focusing on SQL Server and ADO programming. Here’s the amazon.com link to that book in case you’re interested.

Although it was mentioned countless of times already that VB.NET != VB6 and it is not even fully backward compatible, VB.NET addresses most of the issues that were used to criticize the Visual Basic language.

But still, VisualFoxpro is my main artillery; there are just some matters that pushed me to delve more into SQL Server and ADO programming.

Something which I would probably share later.

Displaying database index tag names in combo boxes

Filed Under (Visual FoxPro, work.BLOG) by WildFire on 15-08-2004

Here’s a simple 2:00AM code I made. Its objective is to make a certain combo box automatically reflect the tag names for the databases you are currently using.

with thisform
DatabaseInitialization()
select FILEAREA
nTagCount = tagcount()
dimension aIndex(nTagCount)
for nCount = 1 to tagcount()
if !empty(tag(nCount))
store tag(nCount) to aIndex(nCount)
else
exit
endif

endfor
.cmbIndex.rowsourcetype = 5
.cmbIndex.rowsource = 'aIndex'
.cmbIndex.value = aIndex(1)
endwith

It’s too simple really but this was the first time I used this. I even had to refer to Foxpro’s help file in the formulation process.

The main purpose is to create a template form for the ‘File Utility’ type of modules. The term ‘File Utility’ was something I have acquired from College MacPros (Machine Problems). This is a part of those old DOS based Programs we had back then (created in either Pascal, C/C++, Clipper 5.2) which hold the records for your database-based values, or as one of my clients call it… directories.

This has been a practice which I find useful especially when you’re already in the maintenance mode of your program. Directories like this, however, should be planned in advance. The ‘Design phase’ of your project is a good place to start.

These directories can also be used inside combo boxes, and if in the future you would like to add values that those combo boxes display, you don’t need to touch the hard code. You just either edit the database or use your File Utility module.

Very handy too when your database application is being used by more than one client.

Let’s give an example.

Suppose you have a combo box for Profession. Of course you can choose the combo box builder wizard and enter the data by hand but that would be lame.

Totally lame that only castrated over-boozed programmers of the 60s do that.

You use a database approach and set the combo box to grab the values of that database.

     .cmbProf.rowsource = 'DATABASENAME.FIELDNAME'
.cmbProf.rowsourcetype = 6

… where cmbProf is your Profession combo box and 6 stands for (database) fields, the source of the values the combo box will display.

You can also use the Property box to set things. Other sources include value, alias, sql statement, query (.qpr), array, files, structure, popup, DoomPortal, BermudaTriangle, RiverofLesRough and so on.

Now back to the code above (Darn I’m wandering off once again), the algorithm gets the number of tags the compound index file has, gets the tag names and stores them in an array.

Now using the values in that array, you can place the code below in an object (a ‘Browse’ command button perhaps).

     select FILEAREA
set order to alltrim(.cmbIndex.value)
.GridProf.refresh

This will reflect the changes you want to view, which in my case is found in a grid that displays the sorted records.

Figure 292.1 Image too shy to enlarge itself since its design and alignment was not optimized yet. Check back later when Image.nConfidenceLevel++.

Peculiar…

Filed Under (Visual FoxPro, work.BLOG) by WildFire on 15-08-2004

Peculiar things happen once in a while in a programming language IDE and the VisualFoxpro’s IDE is not an exception.

Take this for an example:

close databases
close all

select 0
use FILEAREA shared
if !file('FILEAREA.cdx')
index on NUMTOSTR(AREAIDNO, 5) tag CAREIDNO
index on upper(alltrim(AREA)) tag CAREAREA
endif

Note: UDF NUMTOSTR(5, 3) returns '005'
Note: UDF is 'User Defined Function' (OK... you know that already)

So what is wrong with the above snippet?

Nothing really. In fact I’m using it on a different application and it’s fine. But tonight I’m getting the ‘File must be opened exclusively.’ error message. So I tried transferring it from the .PRG file to the frm.Init, removed the NUMTOSTR line temporarily, executed close all commands inside the command window, closed VisualFoxpro a couple of times and the error is still there.

No other application is using the database and I’m not even connected t0 the internet. (Just in case you’re entertaining that wild idea that someone in cyberspace is playing with my databases tonight)

So I thought ‘FILEAREA’ was an ultra-secret Foxpro reserved word and renamed the database to AREA.

Still, the problem exists.

Another reboot, fired up VisualFoxpro, executed the program and it ran sans the error message this time.

Weird.

So I tried recoding the things I made, re-used the NUMTSTR function, renamed the database back to FILEAREA and placed the code back to the DatabaseInitialization.prg.

Problem’s lost… I can’t even recreate it.

This is one of those weird stuff I encounter once in a while. You can’t even share it to someone whose skills are better than yours since it just disappeared out of nowhere. As a programmer this is quite puzzling. Programmers always have this inner desire to know the why and how of things. Why such thing exists. Why it exists that way.

When you can’t recreate the problem, you can’t prove that the problem isolation procedures you just did were the solution… that you used the right chant and growl frequencies.

You can’t even prove that such problem exists.

Really weird. You just end up storing it somewhere behind some portal deep within your brain…

… or you end up blogging about it.

Of cars and source codes (Part 001)

Filed Under (Random.scribbles, work.BLOG) by WildFire on 13-08-2004

Before I begin to scribble these thoughts that were bouncing around my mind for the past 16 hours let me tell first that I have great respect for the Open Source. From Torvalds, who my previous co-officemate system administrator worships (and I worship that SysAd during Wednesdays and Fridays), to the linux-kernel-super-computers, to the airplanes, air traffic controls and production plants that use it, the centibots, RedHat, SlashDot and lately Miguel de Icaza and Mono.

Throw in Python and Perl if you like, even Paul Graham and Prometheus.

Yes… too many to mention.

Include also the top universities in this country who are pushing Java and Open Source.

In fact the area of Open Source is too broad and deep to tackle. Let me just highlight the topic partially from Dean Mikhail’s post that had ignited these bouncing neurons in my mind.

Imagine a car with the hood sealed tight and the engine closed from the world — would you trust it blindly to get you to where you want to go. — Mikhail Online

In a perfect world, geeky car owners knowledgeable in how the internals of the car works, exist in every square block. In fact not only the car owners but every human knows how the car functions as well.

Besides, in a perfect world everyone has a Porsche Carrera GT as their ‘obsolete means of land transportation’ inside their 1 mile nanotech-protected garage, located in between two vehicles that have perfected the vertical takeoff.

(I won’t even mention that Monica Bellucci look alike chauffeur… she’s a cyborg anyway.)

Perhaps even 8 year olds know about internal combustion, the four-stroke combustion cycle, higher-octane gasoline, cooling and fuel injection systems. Add in the lubrication, exhaust, electrical and emission control systems.

These kids would even mod their cars to make it look like H-Wings from Star Wars (Too bad the mod pics are already ‘off-lined’).

OK… I’m exaggerating things.

But still, in reality things are not this way.

Far from it really.

Take Mr. Anderson’s car for example. Let’s say Mr. Anderson knows the logic behind his car that well. Inside, outside and beyond. Chances are Mr. Anderson has a wife who cares nothing about cars. Hansel and Greta, his two daughters in this world who can’t even move their focus away from their cell phones when riding that vehicle, don’t care either.

Now Mr. Anderson is beginning to wonder if those cell phones were attached to his daughters when they popped out to this world.

Expand that car to a bus… or to a train or a plane if you like. Sometimes humans even tend to know more about how a train works if something wrong happens like what occurred in MRT Kamuning Station this day. (I was on my way home from a certain client visit and I indirectly suffered from the jam.)

Try randomly asking passengers if they know how the engine works… chances are most of them (if not all) will give you that ‘duh-look’. One out of ten would even yell or glare at you for disturbing their peace, probably 2 would give you their cutest smiles with a ‘go away’ subliminal mindset in the background and probably one out of one hundred would bluff their way into discussing things.

Chances are you won’t even try asking for you know the outcome already.

Most of the time, these passengers don’t even care. As long as they arrive safely to their destination… be with their families… just in time for a rerun of their favorite TV show.

Sans the knowledge of how the engine works or what is behind those hoods, life goes on.

And it goes on peacefully.

Replace(variations(‘passengers’), ‘computer users’)

Point is… most computer users don’t give a smurf’s arse on the ‘internals’. Probably some of them would care knowing the logic behind things… but only few care about the source.

In fact try asking some programmers too how memory is managed, garbage collected, dangling references and the /3GB switch.

They would rather finished the tasks at hand than spend a time discussing these things to you. That is if they really know how things are done in depth.

Most users don’t care how machines and mathematics merged in the form of computers with binary numbers as the battlefield. As long as they can type, edit, save and print their assigned papers and spreadsheets the world is fine.

They don’t care how NudeAngelinaJolie1618.jpg was compressed, ‘digitized’, chopped into pieces and transform into bits once again as it passes fiber cables, lines, modems, routers and cyberspace when they’re sharing those things to their peers.

As long as their friend receives the file, laughs and does things which I won’t even mention here afterwards.

They just don’t care.

Sad… but true.

Even in my programming-related client visits, I have experienced this countless of times already. Sometimes from ‘normal users’… sometimes even from computer technicians. And I believe I’m not that boring when I talk. And I’m fresh as mint.

In fact my pet tiger and my three year old baby thinks I am interesting and cute. (OK… I am exaggerating things once again but yes the tiger exists)

Urgh. This is getting longer already… would you mind if I chop this for a while and continue this some other time?

No you won’t.

You don’t even care.

Lightning operation commando skills

Filed Under (work.BLOG) by WildFire on 13-08-2004

SMAH.client monthly visit… I was on a bus, pony-tailed my now getting longer hair so that I could feel something when I press my nape against the seat. It gives me that I’m-Neo-I-am-the-one feeling plugged into The Matrix.

I was planning this visit to be a ‘lightning operation’. Go in-Execute(Mission)-Go out. That kind of visit. I even made ‘one click’ automations for some updates and some batch files last night. Some database manipulations were done already at home so that I would be merely copying (after doing some backups of course) the files in the target computers.

I sneaked in past the guard and the ‘Big Boss’ and after around 17 minutes, the mission was completed. Usually by this time I consume my time talking to some staff, having those kind of normal discussions where you learn a lot (their ‘routine’ activities, gripes and stuff), you observe a lot (like how many fingers they really use when they’re typing and how many fingers are ‘pretending’ to be moving) and formulate some things in my mind based on these learning and observations.

This was not applicable this time. My mind was set for a ‘lightning operation’.

In. Execute. Out. Two down… one to go.

On my way out though, I saw the ‘Big Boss’ closing the lights in her office… preparing to take her lunch. Of course I could do a commando-type sneak with ease, which I learned from playing video games when I was a child, but that would be unprofessional.

Very unprofessional.

At least I have to say ‘hi’ or something.

That was when my being ‘feedable’ impaired the ‘lightning operation’. Don’t even bother searching for what that word means, I made that up.

Wherever I go, people I meet tend to want to ‘feed’ me, stuff some food in my belly. For Varumvha’s sake, I’m not even thin to start with.

So there I was spending the next couple of hours, chomping, reading the February 2004 edition of Windows and .NET Magazine while waiting, fixing some Excel-related corruption problems and the usual learning and observing activities.

I guess I still have a lot to improve in my lightning operation commando-like skills.

Thoughts derived from some food-less midnight work breaks…

Filed Under (Random.links, work.BLOG) by WildFire on 11-08-2004

11:42PM | Regular break from the normal midnight database operations.

My two year old is still watching Dinosaur in the background. Yup very much awake at this time of night… the making of a programmer right?

Dean Michael posted interesting blogs here and here. I’m still finishing some database migration related things for tomorrow’s client visit but I’ll post some thoughts later.

He also mentioned this site: TopCoder.com

I saw a dollar image in the front page. My interest dropped to sublevel 37.

On the pixel-side of things, I uploaded this Photoshop Shadow Tutorial I made 15 months ago. It is still unreleased from inside the Pixelcatalyst.Lair. Yes… one of those derivations from that ‘so-many-cool-things-to-do-so-limited-time’ dilemma.

PWA entry fee draws mixed reactions. What do you expect? I have always wanted to blog my thoughts about this since I found out that they’re now collecting P2,500 entry fees for that contest… err… awards to prevent ‘crappy sites’ from entering. Out of respect to some local web designers I’ve known for years, I’m refraining from posting some thoughts for now.

Let time and output tell if the move was appropriate and effective. I’m not using the words ‘good’ and ‘right’. Elusive words… these are.

In an indirect way, you can compare it to what the Philippine government is pushing these days… the thing about additional taxes. Should we focus more on how making tax collection efficient first before adding more burden to the people?

Should we solve things underneath first before implementing reckless series of patches over it?

Do check the statistics for uncollected revenues for the past 10 years and you’ll understand my sentiments, and the majority of the Filipino people’s sentiments as well.

Never mind my sentiments, I’m just hungry anyway.

Oh… we’re giving up already the idea that we can collect these things efficiently and we’ll just add another batch of ‘to-collect-things’ that highlight the inefficiency and feed Mr. Graft and Miss Corruption?

I’m not raising the white flag for RP’s situation though. Not now when I see my two year old watching Dinosaur at this time of the night.

But… I need to resume working.

Hopefully…

select 0
use
RESOURCES shared
if !file('RESOURCES.cdx')
index on alltrim(GoodGovernance) tag CRESGOOD
index on EfficientMeans tag CRESEFFI
index on ATested(Integrity, Passed) tag CRESINTE
index on Stress(DTOS(date())) tag CRESDATE
index on Listen(People(.voice)) tag CRESVOIC
else
CheckIntegrity('RESOURCES', Strict)
endif

… could be of help.

Some old-school-ic filterin’ code

Filed Under (Visual FoxPro, work.BLOG) by WildFire on 09-08-2004

Early dawn-worm-code snippet:

if .chkMonth.value != 0 .and. !isblank(.cmbMonth.value)
cFilterDate = upper(alltrim(.cmbMonth.value))
cFilterYear = "(year(DATAAMPM.DATE) == year(date()))"
cFilter = "(upper(alltrim(cmonth(DATAAMPM.DATE))) == cFilterDate)"
cFilter = cFilter + " .and. " + cFilterYear
**' cFileName = cFilterDate + alltrim(str(year(date())))

dDate = cFilterDate + alltrim(str(year(date())))
report form Report_AMPM preview for &cFilter
else
cMess = 'Please specify the month first' + chr(13) + ;
'and check the Monthly Report filter'
messagebox(cMess)
endif

One… the above code is not ‘extremely optimized’ and was done around 2:16AM. So get over it.

Two… I’m just testing the preformatted tag and the colors. I recall someone blogging about a tool that ‘autocolorizes’ code in blogs, but I just can’t remember the URL. At two in the morning I don’t want to be involve in any searches.

Three it’s nice to know that the ELSE statement functions as ‘Everything Else’ in most programming language. Foxpro included.

In the above code, given lCondition_01 = .chkMonth.value != 0 and lCondition_02 = !isblank(.cmbMonth.value), the ELSE clause would execute when:

A. lCondition_01 == .F. and lCondition_02 == .F.
B. lCondition_01 == .T. and lCondition_02 == .F.
C. lCondition_01 == .F. and lCondition_02 == .T.

… and not just when A is satisfied. Which if this was done in one of our Math subjects (Automata-related) back in college will be the only basis for the output.

The cFileName line has been weeded out in comments just for the sake of this post. It has been my practice to save and export some filtered queries (‘native Foxpro filter’ and SQL queries) generated by the program to an .xls file.

SMAG visit – 2004.0806

Filed Under (Random.links, Visual FoxPro, work.BLOG) by WildFire on 07-08-2004

Visited a client in Guagua, Pampanga today. Fixed a database corruption on one unit. Installed some ILS module updates. Meet W95.spaces.1445 (I’ve been cataloguing those kinds of meetings and it seems each company I visit cultivates their own ‘pets’).

cEntity = ‘pets’
cSimilarEntity = substr(cEntity, 1, 2) + ReverseString(substr(cEntity, 3, 2))

Introduced OpenOffice.org since they could afford to buy only one licensed copy of Microsoft Office 2003 this school year. Introduced MajorGeeks.com and explained OfficeXP’s save as old format capabilities.

Yes… one of the many advantages of ‘freelancing’ is having more room to educate people… the ‘normal users’ who need more enlightenment. Something you don’t have that much if you’re one of those ‘in-house-type-of-programmers’ here in this country.

Of course I’m not generalizing here. I’ve known some good in-house programmers who do not only excel in what they’re doing, but passionately ‘evangelize’ technological matters as well.

But recently I’ve seen too much work-related grumbling from them. Quite sad.

I am also an ‘in-house programmer’ in my regular job and I tell you there is a big difference.

Freelancers don’t have a boss… or at least we don’t call them ‘boss’ we call them ‘clients’, our time is flexible (or at least we think it is) and we can work in pajamas (not naked… contrary to popular belief, programmers don’t work naked).

You, my friend, are always welcome to the other side of the fence.

Later… 12:31AM and I still have to finish one report for tomorrow’s MILD.client visit.

···

Calvin Hsia shares an overview (and even some codes) on how to catalog and share digital pictures using Visual Foxpro, SQL and .NET. Very informative if you’d ask me. Makes you want to say Kenshin’s ‘There’s nothing I can’t do with this sword’ line.

Replace(LineAbove, ‘this sword’, ‘Foxpro’).

Fine-Tune Your Web Site for Windows XP Service Pack 2.

.NET linkwarp: Hyatt.lu

Ada Lovelace started her blogs. Keep it up, Leigh. Can we expect techblogs from Dennis and Exander too?

Gapingvoid.com is an insightful site. I added it in my aggregator a couple of days ago when I read the How to be Creative post. Number 13 is applicable in the field of software development:

Never compare your inside with somebody else’s outside.

Netcrucible: Sex and Cash

More Sex and Cash theories… probably I’ll post mine in the future.