Also, Lists have a 32K limit (unless you have turned on long string support).
You won't like my answer, and Intersystems doesn't agree with me, but..
LISTS ARE EVIL
Ok, boy do I feel better. I've been biting my tongue trying not to spout
off, but, hey, you asked!
The only possible reason I can see that they even came up with lists is that
they needed this abominable thing to pass data back and forth through the
interfaces to non-native development environment, ie .Net, Java, etc.
Arrays are superior in every way I can think of to lists.
Even with large strings turned on, lists are still more limited in size than
an arrays. Arrays can grow to the entire local storage if needed (up to
16m), lists can only get as big as the current long string support (around
3m). If they implemented local access to arrays as a process private global
instead of a local storage array, this limitation would go away also.
You can dynamically and randomly add/remove items from an array. Unless a
later versions have added new features, lists have to be rebuilt to add,
change, or remove an item. On large lists this can have significant
overhead, and is just generally a pain in the neck.
Arrays automatically project as an SQL child table. Lists don't project at
all.
Detecting if a value is a list is difficult, there is no $ISLIST function,
unless they've added it in 2008.x, and attempting to do list functions on a
non-list variable returns an error. Determining if a variable has array
elements is a simple $Data call.
And I'm even more non-standard in my thinking in that a relationship is
better than an array, and a child relationship is a better option than
either a list or an array property, if the total number of elements is not
subject to limits and likely to be a large number of elements. The reason I
say this is that a relationship property will not be loaded into local
memory until referenced (either explicitly or through swizzling), but a list
or child will be loaded into memory every time the object is opened. If you
have an invoice object, for example, with an array or list of the detail
line items, and the invoice has a thousand details, opening the object will
bring all thousand lines into local storage. If the detail line items are
children, then they would only be 'swizzled' and brought into local storage
if you reference the detail lines. If you frequently reference just the
'header' information, especially if you have included an 'invoice total' and
'invoice balance' property in the 'header', this can save a lot of overhead.
If someone else can explain why Intersystems has decided that lists are so
wonderful, I would be happy to revise my opinion.
Mark
"dawn" <dawnwo...@gmail.com> wrote in message
news:46452b01-fd21-4645...@y38g2000hsy.googlegroups.com...
>
> LISTS ARE EVIL
it depends...
>
> Detecting if a value is a list is difficult, there is no $ISLIST function,
> unless they've added it in 2008.x, and attempting to do list functions on a
> non-list variable returns an error. Determining if a variable has array
> elements is a simple $Data call.
first, version 2008.1 introduced a $listvalid(string) also as $lv(string)
function
second, with just one (or two ) line of code you can have the same function in earlier versions too. Put the following line into %ZLANGF00 routine:
// ListValid
ZZLV(x) Public { try { s ok='$lf(x,x) } catch { s ok=0 } q ok }
and voila, you have your $ZZLV(string) or call it listcheck... function.
hth and
have a nice day
Julius
--
///
I stopped using lists and arrays long time ago. Did not find any
advantage in using them.
Instead using another class to hold the data and simple object reference
to that class is the preferred approach. The code (COS & SQL) then is so
much more simpler = no messy SetAts, GetAts, RemoveAts and BlahBlahAts.
Regards
Sukesh Hoogan
Bombay, India
[Enterprise Resource Planning & Business Intelligence]
Could you provide an example of projecting a list as a child table?
I'm a newbie trying to develop classes for MV without using
CREATE.CLASS, and didn't think that projecting lists as child tables
was possible.
Thanks - Jack
On Fri, 25 Apr 2008 08:52:02 -0700 (PDT), dawn
<dawnwo...@gmail.com> wrote:
>
>All of our lists are projected for SQL, so I think this is not a
>current issue with Cache'. We project them two ways, in fact -- as a
>child table and as a delimited list (using a calculated property).
>
>
>cheers! --dawn
>
For One-to-Many relationship, the object reference is reversed.
The [Many] class references the [One] class.
This may surprise you and others. However, this is only small part of
the overall application logic, which has checks and balances to take
care of the other related issues.
Regards
Sukesh Hoogan
Bombay, India
[Enterprise Resource Planning & Business Intelligence]
http://sukeshhoogan.blogspot.com
"sukesh_hoogan" <"sukesh_hoogan <at> wrote in message
news:4815c...@info2.kinich.com...
A Company may decide to have details of the employee's family (for
whatever reasons). A family member may not be a employee of the Company
to start with. What happens when the member is employed by the Company
or was employed to start with and decides to part ways (in both cases
the/she is still related to an employee)? In my design, there is no
separate class for the family members, if it were so, how does one deal
with the above situations? Delete details from family class and put them
one in employee class or the other way around! Now that is surely going
to break up a lot of references and we would have a royal mess. Another
case - a contact person from a vendor (his/her details - maybe minimal -
are there as part of the VRM/CRM) is hired by the company. Again shift
his details from a "contact/vendor??" class to employee class? Still
another example - an employee retires and is hired as a consultant or
becomes a director of the Company?
Hence, all family members and also persons having dealings with the
group are created in Person class and their roles or any other
references are marked/edited as such (which can change over a period of
time) and the rest of the references remain intact.
All elements are treated as objects, including many many property
attributes and create them only once.
Based on this principle, the schema I use has been designed as such. It
may be very different from the traditional database designs.
To get all the objects in the [many] class based upon the selection
criteria in [one] class. For example - to retrieve the list of the
employees of a particular company.
"SELECT whatever FROM EmployeesClass WHERE CompanyRef->ID=?"
This works just as fine. 99% of my queries are just this type (no
parameters or at most one or two parameters). No extrinsic joins, no
foreign keys. I am no great fan of relational parent-child relationships.
Regards
Sukesh Hoogan
Bombay, India
[Enterprise Resource Planning & Business Intelligence]
http://sukeshhoogan.blogspot.com
-----Original Message-----
From: intersystems...@googlegroups.com [mailto:intersystems...@googlegroups.com] On Behalf Of Mark Sires
Sent: Monday, April 28, 2008 10:51 AM
To: intersystems...@intersystems.com
Subject: [Caché] Re: Collections vs Relationships
This is why I tend to use a lot of parent/child relationships. Since I have
a property in both the parent and child that point to each other, I get the
benefits that Sukesh gets using this method, but when I need to get to the
'children' from the parent, I have a property that gets me there easily.
Since child table is a separate table, it always gets projected the way I
expect it to, not the way the compiler decides to...
Mark
"sukesh_hoogan" <"sukesh_hoogan <at> wrote in message
news:4815c...@info2.kinich.com...
Property MyList As list Of %String(STORAGEDEFAULT = "array");
One caveat: if you modify a class where storage has already been
generated for the list property, adding the parameter does not recreate
the storage definition where this behavior is implemented.
Is this documented? Well....kinda, not in DocBook, it's documented in
the class documentation of %Library.CacheCollection, so....if you do
know it exists you can find the documentation of it, otherwise....well,
you may step into it playing with Studio inspector! :)
It's a pity that InterSystems implement (very little, let me say)
features customers have been demanding since ever and not even
mentioning it in the release notes, let alone the documentation.
This thread is an excellent example of how much/many users need this and
how little is known about the fact it is supported since a few versions!
Anyone in the ISC doc group listening?
Here is what the class documentation says:
parameter STORAGEDEFAULT;
STORAGEDEFAULT is the type of storage used for the collection if it is
not already allocated in a DATA definition in the active STORAGE
definition. LIST collections default to list storage and ARRAY
collections default to array storage (SUBNODE structure).
HTH
Enrico
That is one of the reasons I like parent/child. It is not uncommon for me
to want to reference the children once I have referenced the parent. Since
the 'child' rows are likely to be in the same database page as the parent,
referencing the children (unless there are a lot of them) is less likely to
require a page fetch. The overhead I am avoiding if I don't reference the
children is the overhead of opening each of the child objects.
Sukesh's method also works fine. It doesn't have the benefit of the
children being in the same page (not guaranteed, but is frequently true),
but does have other advantages. However, I would caution him against using
the -> join syntax in the WHERE clause of SQL statements. The SQL
deoptimizer, er, optimizer does NOT like this syntax, and will frequently
(about 99.9% of the time as far as I can tell) fall back to reading the
entire table to find matching rows. If you have an index on a property, it
will not be used if referenced by the -> syntax.
Mark
"Benjamin Spead" <Benjami...@intersystems.com> wrote in message
news:81F3EC83B5424847B6D2EF5C4D406705045D9313@Exchange1_backup...
see in-line
Mark Sires wrote:
> Benjamin,
>
> That is one of the reasons I like parent/child. It is not uncommon for me
> to want to reference the children once I have referenced the parent. Since
> the 'child' rows are likely to be in the same database page as the parent,
> referencing the children (unless there are a lot of them) is less likely to
> require a page fetch. The overhead I am avoiding if I don't reference the
> children is the overhead of opening each of the child objects.
>
> Sukesh's method also works fine. It doesn't have the benefit of the
> children being in the same page (not guaranteed, but is frequently true),
> but does have other advantages. However, I would caution him against using
> the -> join syntax in the WHERE clause of SQL statements. The SQL
> deoptimizer, er, optimizer does NOT like this syntax, and will frequently
> (about 99.9% of the time as far as I can tell) fall back to reading the
> entire table to find matching rows. If you have an index on a property, it
> will not be used if referenced by the -> syntax.
Thanks for your comments and the cautionary notice, I really appreciate
it. Did not know that SQL optimizer does not like the -> syntax.
However, I must state that I have not found any 'delays' in fetching
instances using the -> syntax. Almost all my queries are coded and
compiled in the relevant classes - no dynamic queries.