rfc: rdbms - new type system

ke.han <>
Mon Feb 27 02:57:31 CET 2006


thanks for the reply.

Your type system is very flexible.  My recommendations are mostly about 
usability/readability; especially for large sets of attributes.
I have two basic thoughts on your type syntax:

1 - Its too complex/tedious when scanning a large list of attributes. 
It would be nice if the most common constraints have higher level 
shorthand notation like I've described.  (If it doesn't effect item 2) 
you could add these high level notations as simple interface on your 
existing syntax.

2 - I am making wild assumptions about how this is implemented. ;-).  I 
assume that things like..

 >> {{attr, age, type},
 >>   {'and', [{'>=', 0},
 >>            {'=<', 150}]},
 >>   {'or', undefined}}

..get implemented as a collection of funs or applies.  If this is so, 
having a higher level notation for these most common types would allow 
you to code more efficient single functions to handle them.  If my 
assumptions about implementation are wrong, then ;-)

As to the coercedFloat, I did not realize that modifying a value on 
write would slow things down much.  However, if my app code has to check 
everywhere when I retrieve this value, I'm going to slow things down anyway.

as to...

 >>   {{attr, age,
 >>   	[{integer, {interval, 0, 150},
 >> 	undefined]}
 >
 > Using [T1 .. Tn] as shorthand for
 > {'or',[T1..Tn]}?

yes, I think the times you want 'and' operation is when you commit a 
record and want to cross check different field values. In your notation, 
for example:

{{attr, person, record}
	{'and', {#person.firstName:length(), '<' ,255}},
	{'and', {#person.age, '<', 150}}}

I know the above is not correct, but thats the idea...

so yes, if you are doing a single value check (not checking multiple 
values in a record) then I implied "or" in a list of constraints is most 
welcome.

	{{attr, age,
		[{integer, {inclusive, 0, 100}},
		undefined]}


Also, why the 'type' atom?  isn't it implied we are defining types?

I'm also confused about the difference between type and typedef.  Why 
not just have a type and types can reuse/inherit other types?  What 
added value is there to differentiate?

thanks, ke han


Ulf Wiger (AL/EAB) wrote:
> ke.han wrote:
>> In general I would like to see more primitives
>> for the most common cases:
>> float, coercedFloat, number, integer
> 
> I have float, number and integer.
> 
> What would be the difference between 
> number and coercedFloat? (ok, so further
> down, you've explained it.)
> 
>> intervals of float, number, integer
> 
> I used to have {inclusive, Min, Max} 
> and {exclusive, Min, Max}. I thought I'd
> drop them in favour of 
> {'and',[{'>',Min},{'<',Max}]} and similar.
> One can of course choose to let the type
> be implicit, at least if both floats and
> integers are acceptable.
> 
> I decided to drop the interval notation
> since there are so many different useful
> intervals. Ex:
> 
> {typedef, natural, {'and',[integer,{'>=',0}]}}
> 
> I welcome suggestions on how to express
> it better.
> 
>> enums of any specified list
> 
> I can add enums. Good idea.
> 
>> accept undefined
> 
> I'll see if I can't make 'undefined' mean
> {'==', undefined} rather than "no type specified".
> 
>> the attr is a list of another defined type etc...
> 
> That would be {list, {type,T}}
> 
> 
>> I would prefer something like:
>>
>> {{attr, age, type},
>>   {'and', [{'>=', 0},
>>            {'=<', 150}]},
>>   {'or', undefined}}
> 
> Not sure how to parse this...
> 
>>   or perhaps these examples (changing your syntax even more):
>>
>>   {{attr, age,
>>   	[{integer, {interval, 0, 150},
>> 	undefined]}
> 
> Using [T1 .. Tn] as shorthand for 
> {'or',[T1..Tn]}? 
> 
> I've hesitated because I've thought that 
> it makes it easier to make mistakes in the
> type expressions. Perhaps I'm wrong...
> 
> 
>>    {{attr, time,
>>    	[integer,
>> 	{undefined, fun() -> erlang:now() end}]}  % if the 
>> value is undefined, set the value to be the current time.
> 
> I used to have a form of dynamic types, but decided to
> drop them for now. I'd like to take a conservative 
> stance on this for now. These things could be added
> later, I think.
> 
>> 0..1 and 0..n relationships are the most common cardinality in 
>> mainstream apps.  The app spec may say the cardinality should 
>> be 1..1 or 
>> 1..n, but the db needs to be able to handle empty lists and undefined 
>> relation prior to the app code enforcing these rules.
>>
>> I am imagining high-level declarations such as:
>>
>> {attr, person,
>> 	{record, person}}  % must be a record of type person
> 
> My current approach is that you have to 
> first specify what think a person record
> looks like, by adding a typedef:
> 
> {typedef, r_person,
>  {tuple, Arity, [{'==',person}|...]}}
> 
> I used to have a record type, but dropped it, since
> I thought using the tuple type would be acceptable.
> 
> 
>> {attr, person,
>> 	[{record, person}, 	% must be a record of type person
>> 	undefined]} 		% undefined is acceptable	
>>
>> {attr, people, {list, person}}  % people is a list of person 
>> type and if 
>> uninitialized will give an empty list. i.e.
>> never undefined
> 
> I've had that ambition, but since 'undefined'
> is just a default value set when the record is
> initialized, this would be better handled by
> specifying [] as a default value in the record
> definition.
> 
> Codd's rules for relational databases state
> that there must be a NULL value that is separate
> from anylegal value. Erlang doesn't have this,
> so 'rdbms' can't really achieve proper handling
> of null values.
> 
>> Need to be able to set a number type which
>> accepts both float and integers.
> 
> That would be the 'number' type.
> 
> 
>   This is an annoyance when using io_lib and others 
>> that expect 
>> a float and pass it 1 instead of 1.0.  This causes me to write 
>> conversion code in my MVC framework.
>>
>> Something like this would work:
>>
>> {attr, price, coercedFloat} % ensures that if setting 1 
>> instead of 1.0, 
>> you always get back 1.0
>> vs.
>> {attr, price, float} % only accepts float
>> 	
>> or
>>
>> {attr, price, number} %% accepts integers and float but does 
>> not coerce; 
>>   so you get back exactly what you put in
> 
> Ok, but then I'd either have to do type coersion 
> on reads and match operations, which would really
> slow things down, or coerce types in the type 
> checking on writes. Doing passive type checking is
> both easier and faster.
> 
>> So I see from your example how your defined types.
>> How are you defining relations?  Any relation
>> integrity constraints?
> 
> Yes, they are pretty much modeled after the 
> ANSI SQL 92 standard. They haven't changed 
> fundamentally since the 1.5 version, and are 
> described in jungerl, in rdbms/doc/rdbms.pdf.
> I've added some things, but haven't verified 
> them yet.
> 
> /Ulf W
> 




More information about the erlang-questions mailing list