The Forum for Discussion about The Third Manifesto and Related Matters

You need to log in to create posts and topics.

Some issues with TTM

Quote from AntC on May 7, 2020, 11:47 am
  • RM Pro 8 no "compound" or "composite" attributes seems to contra-indicate TVAs or RVAs. Again, what needs to be stated is the objective rather than the implementation. Presumably something along the lines 'no repeating groups'; but what makes RVAs Relational and "compound" attributes not?

 

I re-checked the blue book on this one and what it says is, strongly paraphrased, if you find yourself in NEED of "composite attributes", then the TTM way to address that problem is tuple types (TVA's).

RM PRO 8 is about including "special support for composite columns", and it names Codd 1990 as a source for the idea.  The discussion in the blue book states that the same functionality can already be achieved with the type support described earlier in the book (and that's type support supporting tuple types).  The objective appears to be to say "if you, DBMS designer, might consider to follow Codd 1990 on this one, please be advised that we think this is a terrible idea".

Quote from Erwin on May 8, 2020, 12:02 pm
Quote from AntC on May 7, 2020, 11:47 am

 

  • RM Pre 4, 5 scalar data structures/types and Selectors. Is the Selector mechanism the only way to implement scalar data structures? Would it be anti-Relational if a candidate-D provided only TVAs and their Tuple-types? Tuple-types seem to satisfy most of the requirements about component access in those two Pres, except the implementation detail of positional parameters: is it anti-Relational to fail to provide positional access to components of non-scalars? This is in sharp contrast to RM Pro 1, 2 ruling out positional access to attributes or tuples.
    Multiple PossReps: what's the objective with those? Is it merely programming ergonomic convenience -- then why is it so necessary that every value for the type have a representation for each PossRep? Is it essential to treat each PossRep as of equal status? Is it anti-Relational to take one of the PossReps as 'base' and regard others as mapped to/from it, with a possibility those mappings are not total? (The D will presumably anyway need to cater for non-total operations, such as divide by zero or numeric overflow.)

 

While the similarities (between possreps with components and tuples with attributes) are striking, tuple types do not offer the equivalent of possrep constraints.

Fair point. Then are PossRep constraints an essential part of 'Relational'? Or is it acceptable that declared constraints apply only for Relvars?

You cannot have

POSSREP {X RATIONAL, Y RATIONAL} CONSTRAINT X>0
POSSREP {X RATIONAL, Y RATIONAL} CONSTRAINT X>0
POSSREP {X RATIONAL, Y RATIONAL} CONSTRAINT X>0

if tuple types are all there is, because this would create a situation where you have clearly distinct nonscalar types with the same heading (and of the same "nonscalar type type" - both tuple types or both relation types).  Which means you now are going to have to name them so the user can even make that distinction.  Which might get you into the userfriendliness problem that our other friend from below the equator calls "creating the type system".

(I presume you mean X >= 0.)

POSSREP { X NONNEGRAT, Y RATIONAL }

TYPE NONNEGRAT RENAMES RATIONAL CONSTRAINT NONNEGRAT >= 0;

But this doesn't handle constraints between X, Y.

Re. "Is it anti-Relational to take one of the PossReps as 'base' and regard others as mapped to/from it" : (I think no, because) that's exactly what SIRA_PRISE user-defined types do.  Someone must define the implementation.  D&D swipe that aspect of the problem under the covers by relegating it to some unspecified "storage structure definition language" (I don't recall the precise words).  I believe that if a type designer does think about the implementation, he'll find 99.99% of the times that by dealing with the physical aspect, he has already unveiled the first possrep of which it will make great sense to expose it at the logical level too.  My 2c.

Then another approach for your nonneg: the base representation is vanilla RATIONALs and not exposed. There's a PossRep (that looks like a TVA) that accepts only nonneg operands.

(I am of course continuing to ignore the IM; so types with a CONSTRAINT I'm not trying to support.)

Quote from Erwin on May 8, 2020, 12:35 pm
Quote from AntC on May 7, 2020, 11:47 am
  • RM Pre 6 Tuple types, operations, and RM Pre 12 Tuple variables, assignment, RM Pre 20 operators: why must tuples be first-class/is it anti-Relational to only support operations for singleton relations? Yes the abstract semantics for relations needs to define the structure in terms of tuples. That doesn't require tuples be realised concretely in the language AFAICS. Requiring it seems to preclude certain sorts of representations for relations -- such as 'vertical stores'. A D could support the TUP{ } type generator/pseudo-Selector as syntax purely within REL{ }.
  • RM Pre 8 comparison operator == "for every type T". Just no: indeed many of the types commonly held in databases support equality-comparison. Others don't (such as function types). Perhaps non-comparable types should be excluded from the database, but they shouldn't be excluded from the D's ecosystem. I'm not sure RM Pre 8 would support Image/Audio/document/BLOB types. Is it anti-Relational to hold those in a database?

 

(I think I already mentioned that re. TUP{} "outside" REL{}, SIRA_PRISE was once like that.  But it does not really provide a benefit for the user if support is that limited, does it ?  Unless of course the benefit is "If I have to do TUP{} everywhere then the system won't get built and you dear user won't have a system to use" ...)

I'm wondering more: what is it the user wants to do with stand-alone TUPs that can't be done with relational operations? The TUPs in the program must have come from the database -- i.e. relations. Or if they're from user/screen/API input, just wrap them in RELTUP{ }.

Not having an equality operator for some type precludes that type from entering the database a priori.  The absence of its equality operator makes testing tuple equality impossible, so makes duplicate testing impossible, and the whole sheboopla that entails.  It might be tolerable / condoneable for such types to exist within the language but be kept out of the database, it might be equally reasonable to demand from the type designer to just define equality no matter how useless it is in practice to the end-user.  Same way java defines Object.equals().  Inventorising all the distinct possible senses in which two pieces of audio or two pieces of video might be "equivalent" or not is not something anyone wants to do (nor should need to) when defining equality.  Audio sampled at 44K and sampled at 48K.  Same or not ?  Color photograph converted to grayscale.  Same or not ?  etc. etc.

We already have that two relation values are not join-compatible if they each have attributes same name but different type. Then we can extend that to say: not join compatible if attributes are same name and same type but equality is not defined for that type. IOW you need to project away or rename the Image/Audio.

Or (to detect duplicate values) a dumb binary/byte comparison or hash or something. Likely to allow as non-duplicates Images/Audio that are 'the same' by any human-observable features. For function types we'll get (fun(x) = x + x) ≠ (fun(y) = y + y) ≠ (fun(y) = y * 2).

Thanks to Erwin for being sympathetic to TTM's authors.  I might forward Antc's original complaint list to Chris one day, but not right now because I know he has far too many other distractions going on at the moment.  In any case, I'm sure his position will be the same as mine, which is what Erwin has already expressed as a pretty safe assumption.

Regarding tuple types, I assume Erwin has something like them but not as "first-class" types.  We thought "all types first-class", although a matter of opinion, would be acceptable as a dictum.  I mean, you need some kind of tuple literal in order to express a relation literal; and as a user of Rel I have found it occasionally handy to be able to write tuple expressions, other than literals, within relation expressions.  But BS12 didn't have first-class row types (as they would have been called) and I certainly wouldn't condemn an RDBMS for lacking them.

As for Antc's request for a distinction between VSSs and FSSs, we would never have wanted to do anything like that.  For one thing, I'm sure there are plenty of other suggestions that we could have made but weren't compelling enough to be VSSs.

All of that said, thanks to Antc for going to the trouble of documenting all his concerns and opening them up for discussion.

Hugh

Coauthor of The Third Manifesto and related books.
Quote from AntC on May 8, 2020, 12:59 pm
Quote from Erwin on May 8, 2020, 12:02 pm

While the similarities (between possreps with components and tuples with attributes) are striking, tuple types do not offer the equivalent of possrep constraints.

Fair point. Then are PossRep constraints an essential part of 'Relational'? Or is it acceptable that declared constraints apply only for Relvars?

No, they are an essential part of being a powerful, usable programming language.  TTM's goal is twofold, and "being relational" is only one of those two.

As for "declared constraints apply only for Relvars", that might be acceptable, but it might once again hurt in the "powerful, usable programming language" department.  Think the constraint enforcement machinery being available for working with programmatic assertions used so frequently in debugging, for example.

You cannot have

POSSREP {X RATIONAL, Y RATIONAL} CONSTRAINT X>0
POSSREP {X RATIONAL, Y RATIONAL} CONSTRAINT X>0
POSSREP {X RATIONAL, Y RATIONAL} CONSTRAINT X>0

if tuple types are all there is, because this would create a situation where you have clearly distinct nonscalar types with the same heading (and of the same "nonscalar type type" - both tuple types or both relation types).  Which means you now are going to have to name them so the user can even make that distinction.  Which might get you into the userfriendliness problem that our other friend from below the equator calls "creating the type system".

(I presume you mean X >= 0.)

POSSREP { X NONNEGRAT, Y RATIONAL }

TYPE NONNEGRAT RENAMES RATIONAL CONSTRAINT NONNEGRAT >= 0;

But this doesn't handle constraints between X, Y.

Re. "Is it anti-Relational to take one of the PossReps as 'base' and regard others as mapped to/from it" : (I think no, because) that's exactly what SIRA_PRISE user-defined types do.  Someone must define the implementation.  D&D swipe that aspect of the problem under the covers by relegating it to some unspecified "storage structure definition language" (I don't recall the precise words).  I believe that if a type designer does think about the implementation, he'll find 99.99% of the times that by dealing with the physical aspect, he has already unveiled the first possrep of which it will make great sense to expose it at the logical level too.  My 2c.

Then another approach for your nonneg: the base representation is vanilla RATIONALs and not exposed. There's a PossRep (that looks like a TVA) that accepts only nonneg operands.

(I am of course continuing to ignore the IM; so types with a CONSTRAINT I'm not trying to support.)

There are other cases which you're not going to solve that way.

TYPE RATIONAL POSSREP FRACTION_OF_INTEGERS {NOM INT, DENOM INT} CONSTRAINT COPRIME(NOM,DENOM);

(I now see you already said that so sorry if reading this felt like a waste of time.)

Your "other approach for my nonnegs" has for consequence that your language must still somehow facilitate the user ***specifying*** this "accepts only nonneg operands".  That ***is*** the constraint.  You can't make it disappear from the user's perspective and yet still apply and be there.  It's not going to come falling out of the sky.

Quote from dandl on May 8, 2020, 2:44 am

FWIW my view is you can't really avoid tuple types, but there is no inherent value in ever seeing an isolated tuple attribute/value/variable etc. I would see them 'bundled' into the relation type, but there are issues.

The first shop where I had to write java for a living had these things they called "DAO's" (Data Access Objects) they used all over the place.  It helped them avoid method argument lists that got so long it made the code entirely unreadable.  And those things ***are*** tuples.

Counts also as a reply to

"I'm wondering more: what is it the user wants to do with stand-alone TUPs that can't be done with relational operations? The TUPs in the program must have come from the database -- i.e. relations. Or if they're from user/screen/API input, just wrap them in RELTUP{ }."

Quote from dandl on May 7, 2020, 3:01 am

There are 6 distinct issues raised here. I can break them out as separate posts if preferred.

3.Reword RM Pre 6 and 7 to say that types with the same heading are the same type

RM Pre 6 and 7 refer to type equality without making it clear what is intended. Type equality is referred to in RM Pre 1 as a synonym for type identity ("the same type"). The same principle should be applied here, by the following wording.

Tuple types TUPLE H1 and TUPLE H2 shall be equal (that is, the same type) if and only if H1 = H2.

Relation types RELATION H1 and RELATION H2 shall be equal (that is, the same type) if and only if H1 = H2.

 

Just to point out that doing this is logically unnecessary.  What you describe (correctly) is already a consequence of the fact that tuple and relation types are ***generated*** (by feeding a heading to the generator).  If that generator is deterministic (and I hope noone is considering the possibility of making a DBMS engine dependent on non-deterministic, i.e. random, generators), it means that feeding in the very same heading will make the very same type come popping out.

Whether it is desirable to include such clarifications for better/easier/quicker/... understanding, is a matter of taste.

Quote from Erwin on May 8, 2020, 2:38 pm
Quote from dandl on May 8, 2020, 2:44 am

FWIW my view is you can't really avoid tuple types, but there is no inherent value in ever seeing an isolated tuple attribute/value/variable etc. I would see them 'bundled' into the relation type, but there are issues.

The first shop where I had to write java for a living had these things they called "DAO's" (Data Access Objects) they used all over the place.  It helped them avoid method argument lists that got so long it made the code entirely unreadable.  And those things ***are*** tuples.

Absolutely. If we're just talking data-only value objects then these are exactly the same as POCOs and POJOs. Mostly DAO/POCO/POJOs get written with the value type mechanisms (or can be). The only serious requirements in TTM are:

  • a unique heading as a set of strings, that match the ctor, getters and setters
  • dynamic access to attribute values to support of the RA.

It's chicken and egg: you can start from one and generate the others as code or by reflection, but that's really all you need. And if you have a good enough tuple type, a relation is nothing more or less than a set of tuples all the same type (and heading).

Now you have a D.

Andl - A New Database Language - andl.org
Quote from dandl on May 9, 2020, 1:35 am
Quote from Erwin on May 8, 2020, 2:38 pm
Quote from dandl on May 8, 2020, 2:44 am

FWIW my view is you can't really avoid tuple types, but there is no inherent value in ever seeing an isolated tuple attribute/value/variable etc. I would see them 'bundled' into the relation type, but there are issues.

The first shop where I had to write java for a living had these things they called "DAO's" (Data Access Objects) they used all over the place.  It helped them avoid method argument lists that got so long it made the code entirely unreadable.  And those things ***are*** tuples.

Absolutely. If we're just talking data-only value objects then these are exactly the same as POCOs and POJOs. Mostly DAO/POCO/POJOs get written with the value type mechanisms (or can be). The only serious requirements in TTM are:

  • a unique heading as a set of strings, that match the ctor, getters and setters
  • dynamic access to attribute values to support of the RA.

It's chicken and egg: you can start from one and generate the others as code or by reflection, but that's really all you need. And if you have a good enough tuple type, a relation is nothing more or less than a set of tuples all the same type (and heading).

Now you have a D.

It's only a D in the same sense that you also might "have a D" if you write SQL to only use "SELECT DISTINCT."

In other words, maybe it meets the pro/pre-scriptions in some legal sense, but it entirely misses the overall point: to be a better language for data management. Surely the fact that you have to rely on code generation or reflection -- or much manual circumlocution -- is enough to preclude RM Pre 26 compliance, even if everything else legally gets a pass?

I'm the forum administrator and lead developer of Rel. Email me at dave@armchair.mb.ca with the Subject 'TTM Forum'. Download Rel from https://reldb.org

It's only a D in the same sense that you also might "have a D" if you write SQL to only use "SELECT DISTINCT."

Even you know that isn't true. SQL has no type system remotely satisfying the requirements of D.

In other words, maybe it meets the pro/pre-scriptions in some legal sense, but it entirely misses the overall point: to be a better language for data management. Surely the fact that you have to rely on code generation or reflection -- or much manual circumlocution -- is enough to preclude RM Pre 26 compliance, even if everything else legally gets a pass?

It meets the prescriptions (of D) in the full sense. The developers of the world have already given us better languages for most aspects of data management, the only bit actually missing is a usable tuple type to allow a natural implementation of the RA. This shows how to solve that problem. The rest is free.

No, you don't have to rely on code generation or reflection, those are just aids that might help things along. The generics in C# do most of the heavy lifting.

In case you were wondering, here is some working code. I think you'll be able to work out what it does without my help. Obviously a real application would have a comprehensive library of tuple type definitions, so the ones shown here would not be needed.

    WriteLine(Supplier.S
      .Select(t => t.Status == 30)
      .Rename<TupS,TupSX>()
      .Project<TupSX,Tup1>());

public class TupSX : TupleBase { public readonly static string[] Heading = { "SNo", "SName", "Status", "Supplier City" }; }
public class Tup1 : TupleBase { public readonly static string[] Heading = { "Supplier City" }; }

Personally I think the world has made the right choice, by concentrating on general purpose languages and adding ever more powerful features on which a D can be built, if needed.

Andl - A New Database Language - andl.org