ENG-6260 initial changeset. Remove executor/plannode Table* caching for ...

...safer truncates, refactor plannodes to reduce/normalize boilerplate.
The purpose of the smart pointer is to take care of the memory management in all cases, especially when there is an exception. This code was made much more complicated by the fact that it started using the smart pointer earlier than was required (in my opinion). It is enough that the function return a pointer and have the caller -- in one line of code -- save the pointer as s smart pointer. Creating the smart pointer inside the function on each return statement added ugliness for no increased safety -- the return from the function is not going to throw an exception. Also, you have to be more careful when setting one smart pointer from another to use the correct type of smart pointer with the correct semantics about sharing or transferring ownership. You end up having to use shared_ptr (with expensive reference counting) instead of the cheaper scoped_ptr.  Even when using shared_ptr, you don't have to do as much processing when setting directly from a newly allocated C++ pointer -- it always just means "take first-time ownership".