Sunday, September 29, 2019

Many rivers to cross

This is the latest installment of the DCI (now Detective Superintendent) Banks series. Previous reviews have started Once again it's the end of July, and as always, there is a new DCI Banks book to devour ... this year the book seems to be late, being published on 19 September. Ten days have passed and I have read the book twice.

I suggested last time that the entire Zelda plot-line ...does set up a story line which could be the next Banks book: I guessed this correctly. Like most novels of this ilk, there are two separate story lines, although this time they barely connect. One story is about Zelda and one is about a murder on Banks' "turf". 

The book was engrossing although it doesn't impress me - or connect with me - as some of the other books. One lesson which can be taken from the book applies to the field of problem solving - after all, being a detective means solving problems, specifically how and when someone was killed. In the first pages, a minor police character (who has had bigger roles in earlier novels) suggests a line of enquiry, and this line is followed almost until the end when it appears to be false. So much for keeping one's options open.

DI Annie Cabbot is relegated to a supporting role and hardly gets anything to do, so we are certainly not privy to her inner thoughts. Earlier star Winsome Jackson is barely mentioned, having a problematic pregnancy, so most of the police side of the novel is carried by Banks and DC Gerry Masterson. Presumably this is because so many pages are devoted to the Zelda story line.

There are some nice musical touches: Banks goes to a Richard Thompson concert at the beginning of the book and is suitably impressed (although his daughter isn't). He is the recipient of a Martin D-28 guitar (no less; models can be bought on Ebay from 1300 - 10,00 Euro! List price at the Martin guitars site is 'only' $3,599) sent by his musician son, Brian, who announces that his group, the Blue Lights, is breaking up and that he is considering a new career as a producer. It will be interesting to see whether this leads anywhere.

And of course, author Peter Robinson continues to title his books after classic songs, this one by Jimmy Cliff (and probably a more well known version by Joe Cocker), which has one of the lamest rhymes I have ever heard. A very minor character says this sentence.


Many rivers to cross
But I can't seem to find my way over
Wandering, I am lost
As I travel along the white cliffs of Dover

Are there any better rhymes with "over"?

Saturday, September 28, 2019

Understanding the UNLINK command in Priority

I get the feeling that 'UNLINK' is one of the most misunderstood commands in Priority (and I'm not insinuating that I understand it perfectly).

First, what does LINK do? The LINK mechanism creates a temporary copy of a given database table. And what does UNLINK do? The UNLINK command stores the temporary file in the specified (linked) file and undoes the link. More importantly, The linked file is initially empty of data. All subsequent operations that refer to the original table are actually executed upon that temporary file, until the UNLINK command is encountered. You cannot link the same table more than once prior to an UNLINK. If you do, the second (and any subsequent) LINK to that table will return a value of –1.

Developers use the LINK/UNLINK commands frequently in two main contexts. The most frequent use is in procedures, where a linked table (most frequently STACK4) is used to store data collected during the procedure; this data is then passed on to a connected report which uses the linked table. One soon discovers that there is no need to call UNLINK at the end of the procedure.

In more complicated procedures, consisting of several steps, the linked table might be referenced in several of those steps, in which case it is prudent to unlink the table at the end of each step and relink it at the beginning of the next step. Not calling UNLINK will lead to problems as I mentioned in an earlier tip.

The second most frequent use is again in procedures where data is stored prior to it being used to update data in a screen by means of an interface. Again, one discovers that the procedure will work correctly even if the UNLINK is omitted.

So what's the problem? One can (and one frequently does) write interface code which is run in a screen trigger. There are several important (and not particularly documented) differences between code which runs in a procedure and code which runs in a trigger. The most obvious difference (in the case of linked files) is that one cannot link a table to an external parameter as one normally does (e.g. LINK STACK4 TO :$.STK) because the concept of an external parameter is inappropriate in the context of a trigger. Instead, one has to create a temporary file (SELECT SQL.TMPFILE INTO :TMPFILE) then link a table to this temporary file (LINK GENERALLOAD TO :TMPFILE). One always checks whether the link succeeds; should the link fail, one can call an error message in a procedure, but in triggers, one normally silently jumps over the interface code when the link fails. As a result, whatever the trigger is supposed to do does not happen.

I have been receiving complaints from a group of users that certain functionality in one screen has disappeared. Every time I check their complaints, I find that the code works. I wasn't listening closely enough: in certain circumstances (which for them is the normal way of working), the code does not work and a certain field does not get updated. I could see where the specific code was but it seemed correct to me. In order to help me further understand the problem, I inserted debugging code, which would give me the result of the SELECT SQL.TMPFILE operation and the subsequent LINK operation. Once I had this, the problem became clearer.

The SELECT statement worked correctly, but the LINK was returning a value of -1, which is explained as you cannot link the same table more than once prior to an UNLINK. The penny dropped: linking Generalload to the temporary file was failing because Generalload was already linked. But where?

My initial reaction was to alias the generalload table (LINK GENERALLOAD TB6 TO :TMPFILE) and use the alias for all insert commands within the trigger. This caused the update to work properly. Thinking about this further, I realised that there must be at least one other trigger for this screen which does not UNLINK generalload. I looked at all the triggers for this screen and discovered to my horror that there were five or six cases where I had neglected to UNLINK generalload after using it in interface code. Today I had the opportunity to add all the missing UNLINKs.

The reason why one can get away with not using UNLINK in a procedure is that the code is called only once. A screen activates multiple triggers and so it is essential that every LINK is matched with an UNLINK. Make this a habit to do this always!

It's a shame that the syntax checker does not attempt to check unmatched LINKs. The checker does find several kinds of mistake, but there are a few which it doesn't look for. I have noted somewhere that whilst a repeated declaration for a cursor is noted, not closing the cursor is undetected. Unmatched LINKs fall in the same category of mistake. I get the feeling that the syntax checker was written many years ago, has not been updated and no one knows how to update it.

Friday, September 27, 2019

Blood test results

As I expected, I received most of the results from my blood tests yesterday evening.

The most important result, as far as I am concerned, is the level of free glucose in the blood. This has dropped from 110 mg/dL to a much more reasonable 96 mg/dL,  taking me out of the pre-diabetes range, although of course there is still room for improvement. On the other hand, the  hemoglobin A1C % had a more modest reduction from 6.1 to 6.0, which is still outside the recommended range. This test is for glucose bound to red blood cells and indicates a value that was correct to about three months ago. 

An interesting result was the value for uric acid; a high level of this compound in the blood causes it to crystallise out of the blood, leading to gout, from which my father suffers. My level has almost always been over 8 mg/dL, which is off the scale; this time it had dropped to 6.9 mg/dL, which is within the normal range.

Both HDL (good) cholesterol and LDL (bad) cholesterol levels increased slightly. The most important number for all the cholesterol tests is the ratio between total cholesterol and HDL: the lower the better. My ratio is now 3.8, which is the lowest value that I have ever achieved - good!

The final important result for me is haemoglobin: this has risen from 13.0 g/dL to 13.6 g/dL, a value that now brings me onto the lower values of the scale - as opposed to having too low a level and being in danger of anaemia. 

All these improvements can be attributed to dietary changes along with the vast increase in exercise over the past six months. These results are very encouraging, meaning that I should continue doing what I have been doing. I am supposed to make an appointment with my dietician in order to discuss these results, but as we are now entering the high holiday period, I imagine that the appointment will be in November (if not December).

One change which I have yet to adopt is eating red or yellow bell pepper slices at home whenever I feel hungry. I have to make the habit of cutting up one pepper on Friday morning and another on Saturday morning so that I always have the slices available. If I can do this during the week, there is no reason why I can't do this at the weekend. The primary gain is the reduction in calories, but also bell peppers are very good sources of vitamin C, which in turn helps the absorption of iron.

Thursday, September 26, 2019

Two important events

Two important events in my mundane life occurred today.

I had a demi-annual blood test; I should have most of the results by this evening. The results for free glucose, bound glucose, cholesterol and haemoglobin are of great interest and will cast light upon the changes in life-style which I have made over the past six months. Of course, these results will also influence how I continue.

I submitted the first version of my draft doctoral thesis this morning. As 'Introduction to Business Research 3' (chapter 1.3.2) states: The final draft thesis is submitted to the DBA Research Committee for final review prior to going forward for viva voce examination. After reviewing the final draft thesis, the DBA Research Committee may require modifications before accepting the thesis. The thesis can go forward for viva voce examination only when it has been accepted by the DBA Research Committee.  According to my supervisor, only one person reads the thesis without passing it on to the research committee, as opposed to two people reading and making recommendations to the committee. This difference is important as the next meeting of the research committee is scheduled for mid-November which means about seven weeks of doing nothing for the doctorate.

So I've cleared my desk of obligations; I now have several days' holiday in front of me (it's the Jewish New Year on Sunday, so after today, my next day of work is next Wednesday) with nothing planned to fill them. Maybe I'll work on the video of Pisa/Torino from last year.

Tuesday, September 24, 2019

Grand-daughter pictures

Grand-daughter #2 recently evolved from a static blob to a mobile blob (age 10 months), crawling all around the house. Unfortunately, I'm rarely at home when the grand-children come to visit so I don't have many opportunities to be with her. The other day, though, I did come home early and had the chance to play with both my grand-daughters. We also used the opportunity to take a few photos - I don't think that I have a single photograph with this grand-daughter. So here we are.

I look strange to myself in the pictures where I am not wearing glasses, so I'm presenting here one with and one without.


Wednesday, September 11, 2019

Mobile phone problem ... solved

I am writing this for my own benefit should the same problem occur in the future.

Today I was in Karmiel where I had meetings all day, so I set the phone to 'vibrate' and also used the AutoSMS app, which sends a message to anyone who tries to contact me. The phone was working at lunchtime because I could send WhatsApp messages. On the way home, I noticed that I couldn't unlock my phone: the lock screen would appear, I would enter the PIN which was accepted and then the screen would go blank. This happened time and time again.

The easy way to solve this would be to turn the phone off - but I couldn't achieve this. After reading the manual, I discovered why I couldn't turn the phone off: I was pressing the wrong buttons. There are three buttons on the right hand side of the phone, from top to bottom: volume up, volume down and power. In order to turn the phone off, one presses the power and volume down buttons for a few seconds (that is, the bottom two buttons on the right hand side).

Voila! I managed to turn the phone off. When I turned it back on, everything was working again. The first thing which I did was turn off the AutoSMS app - this might have been the cause of the problem.

Tuesday, September 03, 2019

Priority tip: another thing to be aware of

I'm going to describe something which isn't a bug in the strict sense of the word, but will cause Priority to act in a way that we don't want and is unexpected.

There is code in almost every screen to record changes; frequently, there are fields in the screen for which changes are not logged and so we have to add them to our own screen triggers, using the same mechanism for storing the changes. There is a table called GEN_CHANGE_LOG which holds data about changes for most screens and there is a standard procedure for entering data into this table (#INCLUDE TRANSORDER_p/BUF2-CH).

Now down to specifics: I added code a few years ago to the PARTPARAM screen to record changes in the default warehouse of the part using the above procedure. The original value of the field being checked is stored in a variable called OLDVALUE and the new value is stored in - you guessed it - NEWVALUE. As the name of the trigger came after the standard POST-UPDATE-CH trigger, my code executed after the standard code. This shouldn't be a problem as the order of checking should make no difference. 

But unfortunately it does. I noticed in the changes log for a few parts that the default warehouse had been changed from 'M' to 'M'. How could this be, when the warehouse names are something like M271 or M504? Why was the trigger storing only one character when the field itself has four characters? I looked at the standard trigger and noted that it was saving the value of a field that could be either Y or empty. Priority handles single character strings in a different manner from longer strings; this gave me the clue that somehow the standard trigger was defining the length of OLDVALUE and NEWVALUE to be single character strings, so that when my trigger executed, only the first character of the value would be stored.

There's no way of redefining the length of a string (AFAIK) in Priority, so I had to look at the problem with some lateral thinking. The solution was to change the name of my trigger so that it executed before the standard trigger. I implemented this and checked: lo and behold! Now warehouse names are being stored in their entirety and are not truncated.