Parameter relvar question

This forum is for anything about Rel that isn't more appropriate elsewhere.
Post Reply
steved
Posts: 49
Joined: Sun Sep 01, 2013 10:53 pm

Parameter relvar question

Post by steved »

Hi,

Operator P0 works as expected.

Code: Select all

VAR A BASE REL{X CHAR}KEY{X};

OPERATOR P0(B REL{X CHAR});
BEGIN;
INSERT B REL{TUP{X "E"}};
WRITELN B;
WRITELN COUNT(B);
DELETE B;
END;
END OPERATOR;

A:=REL{TUP{X "D"}};
CALL P0(A);

DROP OPERATOR P0(REL{X CHAR});
Operator P1 causes error. Could you please explain the error.

Code: Select all

OPERATOR P1(B REL{X CHAR});
BEGIN;
B:=UNION{B,REL{TUP{X "E"}}};
WRITELN B;
WRITELN COUNT(B);
DELETE B;
END;
END OPERATOR;

A:=REL{TUP{X "D"}};
CALL P1(A);

RELATION {X CHARACTER} {
	TUPLE {X "D"},
	TUPLE {X "E"}
}
2

ERROR: java.lang.ClassCastException: ca.mb.armchair.rel3.values.ValueRelation$4 cannot be cast to ca.mb.armchair.rel3.storage.relvars.Relvar
Line 1
	In P1(RELATION {X CHARACTER}) line 1

ca.mb.armchair.rel3.exceptions.ExceptionFatal: java.lang.ClassCastException: ca.mb.armchair.rel3.values.ValueRelation$4 cannot be cast to ca.mb.armchair.rel3.storage.relvars.Relvar
Line 1
	In P1(RELATION {X CHARACTER}) line 1

	at ca.mb.armchair.rel3.interpreter.Interpreter.run(Interpreter.java:76)
	at ca.mb.armchair.rel3.interpreter.Interpreter.interpret(Interpreter.java:211)
	at ca.mb.armchair.rel3.interpreter.Interpreter.interpret(Interpreter.java:221)
	at ca.mb.armchair.rel3.interpreter.Interpreter.interpret(Interpreter.java:225)
	at ca.mb.armchair.rel3.client.stream.ClientLocalConnection$2.execute(ClientLocalConnection.java:86)
	at ca.mb.armchair.rel3.client.stream.ClientLocalConnection.send(ClientLocalConnection.java:48)
	at ca.mb.armchair.rel3.client.stream.ClientLocalConnection.sendExecute(ClientLocalConnection.java:84)
	at ca.mb.armchair.rel3.client.string.ClientLocal.sendExecute(ClientLocal.java:57)
	at ca.mb.armchair.rel3.dbrowser.ui.PanelCommandline$40.doInBackground(PanelCommandline.java:1166)
	at javax.swing.SwingWorker$1.call(Unknown Source)
	at java.util.concurrent.FutureTask.run(Unknown Source)
	at javax.swing.SwingWorker.run(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.ClassCastException: ca.mb.armchair.rel3.values.ValueRelation$4 cannot be cast to ca.mb.armchair.rel3.storage.relvars.Relvar
	at ca.mb.armchair.rel3.vm.instructions.relvar.OpRelvarPurge.execute(OpRelvarPurge.java:16)
	at ca.mb.armchair.rel3.vm.Context.execute(Context.java:153)
	at ca.mb.armchair.rel3.vm.Context.call(Context.java:159)
	at ca.mb.armchair.rel3.vm.instructions.core.OpInvoke.execute(OpInvoke.java:16)
	at ca.mb.armchair.rel3.vm.Context.execute(Context.java:153)
	at ca.mb.armchair.rel3.vm.Context.call(Context.java:159)
	at ca.mb.armchair.rel3.vm.VirtualMachine.execute(VirtualMachine.java:116)
	at ca.mb.armchair.rel3.interpreter.Interpreter.execute(Interpreter.java:62)
	at ca.mb.armchair.rel3.interpreter.Interpreter.run(Interpreter.java:69)
	... 14 more

DROP OPERATOR P1(REL{X CHAR});
Thanks,
steve
Dave
Site Admin
Posts: 372
Joined: Sun Nov 27, 2005 7:19 pm

Re: Parameter relvar question

Post by Dave »

The problem is the 'DELETE B' line.

In the first example, for technical reasons, the parameter B can be updated by operations like 'DELETE B'.

In the second example, the parameter B cannot be updated by operations like 'DELETE B' because its value is the result of the 'UNION {...}' expression.

The error message should be friendlier -- and I'll make a note to make it friendlier in a future update -- but that's why it happened.

I suggest removing 'DELETE B'.
steved
Posts: 49
Joined: Sun Sep 01, 2013 10:53 pm

Re: Parameter relvar question

Post by steved »

Hi,

Here's another issue with a relvar parameter and a DELETE. This operator mimics
logic in a much larger program. After a DELETE COUNT() seems to be in question.

Code: Select all

VAR A BASE REL{X CHAR}KEY{X};

OPERATOR P1(B REL{X CHAR});
BEGIN;
INSERT B REL{TUP{X "A"},TUP{X "B"}};
WRITELN "B AFTER 1ST INSERT ";WRITELN B;
WRITELN "COUNT(B): ";WRITELN COUNT(B);
DELETE B;
INSERT B REL{TUP{X "C"},TUP{X "D"},TUP{X "E"},TUP{X "F"}};
WRITELN "B AFTER DELETE AND 2ND INSERT ";WRITELN B;
WRITELN "COUNT(B): ";WRITELN COUNT(B);
WRITELN "COUNT BY SUMMARIZE: ";WRITELN CNT FROM (SUMMARIZE B BY {}:{CNT:=COUNT()})ORDER(ASC CNT)[0];
END;
END OPERATOR;

CALL P1(A);

DROP OPERATOR P1(REL{X CHAR});
B AFTER 1ST INSERT
RELATION {X CHARACTER} {
TUPLE {X "A"},
TUPLE {X "B"}
}
COUNT(B):
2
B AFTER DELETE AND 2ND INSERT
RELATION {X CHARACTER} {
TUPLE {X "C"},
TUPLE {X "D"},
TUPLE {X "E"},
TUPLE {X "F"}
}
COUNT(B):
2
COUNT BY SUMMARIZE:
4

Thanks,
steve
Dave
Site Admin
Posts: 372
Joined: Sun Nov 27, 2005 7:19 pm

Re: Parameter relvar question

Post by Dave »

That's a curious result, and possibly related to the previous issue. Could you try assigning parameter B to a PRIVATE relvar, and then see what the results are with that relvar? I'd be curious to see if they're different.
steved
Posts: 49
Joined: Sun Sep 01, 2013 10:53 pm

Re: Parameter relvar question

Post by steved »

Hi,

There is no issue(s) with a private relvar.

Code: Select all

VAR A BASE REL{X CHAR}KEY{X};

OPERATOR P1(B REL{X CHAR});
BEGIN;
VAR F PRIVATE REL SAME_HEADING_AS(A)KEY{X};
INSERT B REL{TUP{X "A"},TUP{X "B"}};
F:=B;
WRITELN "B AFTER 1ST INSERT ";WRITELN B;
WRITELN "COUNT(B): ";WRITELN COUNT(B);
WRITELN "F AFTER 1ST INSERT ";WRITELN F;
WRITELN "COUNT(F): ";WRITELN COUNT(F);
DELETE B;
DELETE F;
INSERT B REL{TUP{X "C"},TUP{X "D"},TUP{X "E"},TUP{X "F"}};
F:=B;
WRITELN "B AFTER DELETE AND 2ND INSERT ";WRITELN B;
WRITELN "COUNT(B): ";WRITELN COUNT(B);
WRITELN "COUNT BY SUMMARIZE: ";WRITELN CNT FROM (SUMMARIZE B BY {}:{CNT:=COUNT()})ORDER(ASC CNT)[0];
WRITELN "F AFTER DELETE AND 2ND INSERT ";WRITELN F;
WRITELN "COUNT(F): ";WRITELN COUNT(F);
WRITELN "COUNT BY SUMMARIZE: ";WRITELN CNT FROM (SUMMARIZE F BY {}:{CNT:=COUNT()})ORDER(ASC CNT)[0];
END;
END OPERATOR;

CALL P1(A);

B AFTER 1ST INSERT
RELATION {X CHARACTER} {
TUPLE {X "A"},
TUPLE {X "B"}
}
COUNT(B):
2
F AFTER 1ST INSERT
RELATION {X CHARACTER} {
TUPLE {X "A"},
TUPLE {X "B"}
}
COUNT(F):
2
B AFTER DELETE AND 2ND INSERT
RELATION {X CHARACTER} {
TUPLE {X "C"},
TUPLE {X "D"},
TUPLE {X "E"},
TUPLE {X "F"}
}
COUNT(B):
2
COUNT BY SUMMARIZE:
4
F AFTER DELETE AND 2ND INSERT
RELATION {X CHARACTER} {
TUPLE {X "C"},
TUPLE {X "D"},
TUPLE {X "E"},
TUPLE {X "F"}
}
COUNT(F):
4
COUNT BY SUMMARIZE:
4

The idea behind the first couple of posts and subsequent ones on a parmeter relvar
is to establish the caveat(s) for successful propagation in an operator (or anonymous operator). That is, dynamic operations on the underlying relvar are propagated to the parameter and operations on the parameter are propagated to the underlying relvar. The benefits of being able to use this kind of propagation in different scopes should be obvious.

INSERTS are consistent with propagation.

Code: Select all

VAR C BASE REL{Y INT}KEY{Y};

OPERATOR P2(D REL{Y INT});
BEGIN;
EXECUTE "VAR T1 BASE INIT(REL{TUP{Z 'A'},TUP{Z 'B'}})KEY{Z};";
EXECUTE "C:=REL{TUP{Y COUNT(T1)}};";
EXECUTE "WRITELN C;";
WRITELN Y FROM D ORDER(ASC Y)[0];
EXECUTE "VAR T2 BASE INIT(REL{TUP{Z 'A'},TUP{Z 'B'},TUP{Z 'C'}})KEY{Z};";
EXECUTE "C:=REL{TUP{Y COUNT(T2)}};";
EXECUTE "WRITELN C;";
WRITELN Y FROM D ORDER(ASC Y)[0];
DELETE D;  //DELETE has no subsequent effect on propagation from underlying relvar to parameter.
INSERT D REL{TUP{Y -1}};
EXECUTE "VAR T3 BASE INIT(REL{TUP{Z 'A'},TUP{Z 'B'},TUP{Z 'C'},TUP{Z 'D'}})KEY{Z};";
EXECUTE "C:=REL{TUP{Y COUNT(T3)}};"; //The assignment to C rightfully defines the propagation to relvar D.
EXECUTE "WRITELN C;";
WRITELN Y FROM D ORDER(ASC Y)[0];
END;
END OPERATOR;

CALL P2(C);

RELATION {Y INTEGER} {
TUPLE {Y 2}
}
2
RELATION {Y INTEGER} {
TUPLE {Y 3}
}
3
RELATION {Y INTEGER} {
TUPLE {Y 4}
}
4

With ASSIGNMENT, data is not propagated to underlying relvar A.

Code: Select all

VAR A BASE REL{X CHAR}KEY{X};

OPERATOR P1(B REL{X CHAR});
BEGIN;
B:=REL{TUP{X "D"},TUP{X "E"}};
WRITELN B;
WRITELN COUNT(B);
EXECUTE "WRITELN A;";
EXECUTE "WRITELN COUNT(A);";
END;
END OPERATOR;

CALL P1(A);

RELATION {X CHARACTER} {
TUPLE {X "D"},
TUPLE {X "E"}
}
2
RELATION {X CHARACTER} {
}
0

ASSIGNMENT to relvar parameter disrupts propagation from underlying relvar to parameter.

Code: Select all

VAR C BASE REL{Y INT}KEY{Y};

OPERATOR P2(D REL{Y INT});
BEGIN;
EXECUTE "VAR T1 BASE INIT(REL{TUP{Z 'A'},TUP{Z 'B'}})KEY{Z};";
EXECUTE "C:=REL{TUP{Y COUNT(T1)}};";
EXECUTE "WRITELN C;";
WRITELN Y FROM D ORDER(ASC Y)[0];
DELETE D;
EXECUTE "VAR T2 BASE INIT(REL{TUP{Z 'A'},TUP{Z 'B'},TUP{Z 'C'}})KEY{Z};";
EXECUTE "C:=REL{TUP{Y COUNT(T2)}};";
EXECUTE "WRITELN C;";
WRITELN Y FROM D ORDER(ASC Y)[0];
D:=REL{TUP{Y -1}};
EXECUTE "VAR T3 BASE INIT(REL{TUP{Z 'A'},TUP{Z 'B'},TUP{Z 'C'},TUP{Z 'D'}})KEY{Z};";
EXECUTE "C:=REL{TUP{Y COUNT(T3)}};";
EXECUTE "WRITELN C;";
//(If at some point propagation isn't necessary this issue is moot).
WRITELN Y FROM D ORDER(ASC Y)[0];
END;
END OPERATOR;

CALL P2(C);
RELATION {Y INTEGER} {
	TUPLE {Y 2}
}
2
RELATION {Y INTEGER} {
	TUPLE {Y 3}
}
3
RELATION {Y INTEGER} {
	TUPLE {Y 4}
}
-1

Thanks,
steve
Dave
Site Admin
Posts: 372
Joined: Sun Nov 27, 2005 7:19 pm

Re: Parameter relvar question

Post by Dave »

Interesting. Any successful updates to a relation-valued parameter should be considered a bug. Any successful updates to a relvar passed as a parameter to an operator are definitely a bug. I will fix these in the next update.

Updates to scalar parameters are permitted, but only due to convention, but I may consider making all parameters read-only.
steved
Posts: 49
Joined: Sun Sep 01, 2013 10:53 pm

Re: Parameter relvar question

Post by steved »

Hi,

If I understand you correctly you think updates, what I called propagation,
is an error. Please tell me I'm wrong:(:). The whole point of my posts
was to illustrate that updates(propagation) is a great benefit to programmers.
I want to pass data between between underlying relvars and operator scope
relation valued parameters and I want to pass data between relation valued parameters
and their underlying relvars. Why would you want to destroy these capabilities. I can
live with the querks but don't take the whole ball of wax away.

thanks,
steve
Dave
Site Admin
Posts: 372
Joined: Sun Nov 27, 2005 7:19 pm

Re: Parameter relvar question

Post by Dave »

Wherever possible, functions (or operators) should be "pure". (See http://en.wikipedia.org/wiki/Pure_function) Obviously, this isn't always possible or reasonable. For that reason, Date & Darwen defined use of the UPDATES keyword in operator definitions, which explicitly identifies parameters that are passed by reference rather than by value. For example, Tutorial D should allow you to define an operator like:

Code: Select all

OPERATOR MyOp(p1 RELATION {x INTEGER, y CHAR}) UPDATES {p1};
    UPDATE p1: {x := x + 1, y := 'zot'};
END OPERATOR;
The above syntax is intended to indicate that parameter p1, updated inside MyOp, will propagate to the argument to parameter p1. Parameters not explicitly listed in the UPDATES clause should not allow updates to propagate to their arguments.

I've objected to it (and haven't implemented it in Rel) because it's not clear at the point of operator invocation whether an operator will update a parameter or not. For example, in the following invocation of operator MyOp2...

Code: Select all

VAR myrelvar REAL RELATION {x INTEGER, y CHAR} KEY {x};
myrelvar := RELATION {
   TUPLE {x 1, y 'zap'}
};
MyOp2(myrelvar);
...without seeing the definition of MyOp2 (which could be inside a library), can you tell whether myrelvar will be updated or not? The fact that you can't is, as far as I'm concerned, a serious flaw.

If there was a keyword that you had to use to indicate that an argument could be updated, then I would have no problem with it. For example, I would have no problem with the following:

Code: Select all

VAR myrelvar REAL RELATION {x INTEGER, y CHAR} KEY {x};
myrelvar := RELATION {
   TUPLE {x 1, y 'zap'}
};
MyOp(UPDATES myrelvar);
However, that's not how Tutorial D is defined.

Therefore, currently, I'm very hesitant to allow what you call propagation.
steved
Posts: 49
Joined: Sun Sep 01, 2013 10:53 pm

Re: Parameter relvar question

Post by steved »

hello,

Unfortunately ill health prevented me from continuing this topic in a much
more timely manner. But better late than never. So permit me to do what
users do: make a request. The benefits that come from the combination of being
able to update relvar parameters and the use of dynamic code (EXECUTE) is
something I hate to lose. I use it extensively without any side effects. It makes
application development so much easier and neater. So for those of us who would
like it available what about some sort of (internal) switch we can turn on.
Of course it would be set to no by default. You can make it very explicit
that the user takes it upon themself to assume any risk.

regards,
steve
Dave
Site Admin
Posts: 372
Joined: Sun Nov 27, 2005 7:19 pm

Re: Parameter relvar question

Post by Dave »

I shall think on this. Ideally, I'd like to support the UPDATES syntax for identifying updatable parameters and arguments.
Post Reply