Lost in Extensions: About companion tables

After having a fairly smooth Friday, I was in my car driving to pick up my son when a migration consultant (let’s just call him Mike) called about a mutual customer. Mike told me something I don’t want to hear on Friday around 17:30:

We’ve just ran another conversion to prepare for testing next week, but somehow we’re missing records in the Item table. About 300, to be exact. It looks as if the service tier isn’t refreshing.

After discussing the problem for a while, and not figuring out what was going on, I promised to take a look after the usual family business. I just did.

At this customer we periodically migrate data from the old live environment to the acceptation environment (using SQL): some tables are wiped every run, but for performance reasons, others are migrated through incremental updates.

So I logged in, restarted all services and then had a quick look in the client. With a filter on our item, it returned an empty list – no other filters on the table, so the item clearly didn’t exist. So I tried to create it… and NAV told me that it already existed!

Right. Next to check were the usual things that go wrong when doing SQL conversions: low caps in code fields, dates or times with the wrong value etcetera (even though the behaviour of the client didn’t match up). As expected, there was nothing “off” visually.

Not wanting to waste time, I decided to run a trace, and quickly found out what was going on:

A few weeks ago, I built an extension containing a TableExtension object that extends the Item table, so now we have two Item tables:

  • The main table: CRONUZ_EU$Item
  • The companion table(s): CRONUZ_EU$Item$[random GUID]

The NAV/BC engine always generates it’s SQL statements with the included companion table, so there will never be a record in one of the companion tables that’s not in the main table, nor will the opposite situation exist.

Mikes original procedures update the CRONUZ_EU$Item table, but not the companion tables. However, the NAV/BC engines generates a SQL statement with a JOIN, not an OUTER JOIN. The result: SQL will return records only if a record with given primary key is found in both tables.

After adding all the missing records, of course, the problem was solved immediately. However, uninstalling the app with option -DoNotSaveData might also help.