Skip to content

Commit 2ec911d

Browse files
author
Senthil Nathan
committed
Changes done for v1.1.2.
1 parent 1651510 commit 2ec911d

File tree

7 files changed

+432
-8
lines changed

7 files changed

+432
-8
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changes
22

3+
## v1.1.2
4+
* Oct/16/2021
5+
* Added a new function compare_tuple_attributes to compare the attribute values of two tuples that are based on the same schema and then give back a list containing the attribute names that have differing values in the two tuples being compared.
6+
37
## v1.1.1
48
* Sep/04/2021
59
* Added two new operational verbs: equalsCI and notEqualsCI.

README.md

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,14 +106,86 @@ if(error == 0) {
106106
// It is a void function that returns nothing.
107107
```
108108

109+
**compare_tuple_attributes** is another C++ native function provided via this toolkit. This function compares the attribute values of two tuples that are based on the same schema. It will give back a list containing attribute names that have differing values in the two tuples being compared. It supports primitive types (int32, float64, rstring etc.) as well as collection types (set, list and map). It also allows flat tuples as well as deeply nested tuples to be compared.
110+
111+
```
112+
// This namespace usage declaration is needed at the top of an application.
113+
use com.ibm.streamsx.eval_predicate::*;
114+
115+
// Schema can include other deeply nested types.
116+
type NestedType1_t = int32 x, float64 y, rstring z, list<int32> l;
117+
type NestedType2_t = NestedType1_t m, map<int32, boolean> n, timestamp o;
118+
type Test_t = boolean a, int32 b, uint64 c, float32 d, float64 e,
119+
rstring f, set<int32> g, list<rstring> h, map<int32, rstring> i,
120+
map<rstring, float64> j, NestedType2_t k;
121+
122+
// Create two tuples that are based on the same schema.
123+
mutable Test_t myTuple1 = {};
124+
mutable Test_t myTuple2 = {};
125+
mutable list<rstring> differingAttributes = [];
126+
127+
// Populate the tuple with some data.
128+
myTuple1.a = true;
129+
myTuple1.b = 456;
130+
myTuple1.c = 789ul;
131+
myTuple1.d = (float32)123.45;
132+
myTuple1.e = 987.65;
133+
myTuple1.f = "Life is mainly there to have fun.";
134+
myTuple1.g = {5, 9, 2, 6};
135+
myTuple1.h = ['One', 'Two', 'Three'];
136+
myTuple1.i = {1:'One', 2:'Two', 3:'Three'};
137+
myTuple1.j = {"One":1.0, "Two":2.0, "Three":3.0};
138+
myTuple1.k.m.x = 678;
139+
myTuple1.k.m.y = 936.27;
140+
myTuple1.k.m.z = "String inside a nested tuple.";
141+
myTuple1.k.m.l = [67, 78, 89];
142+
myTuple1.k.n = {1:true, 2:false, 3:true};
143+
myTuple1.k.o = getTimestamp();
144+
145+
// Make the second tuple same as the first tuple.
146+
myTuple2 = myTuple1;
147+
// Make some changes to certain attribute values in the second tuple.
148+
myTuple2.a = false;
149+
myTuple2.d = (float32)145.12;
150+
myTuple2.f = "Life is mainly there to have joy and peace.";
151+
myTuple2.i = {10:'Ten', 9:'Nine', 8:'Eight'};
152+
myTuple2.k.m.y = 27.93;
153+
myTuple2.k.m.z = "Different string inside a nested tuple.";
154+
myTuple2.k.n = {1:true, 2:true, 3:true};
155+
// Wait for 2 seconds for time to change.
156+
block(2.0);
157+
myTuple2.k.o = getTimestamp();
158+
159+
// Compare them now.
160+
compare_tuple_attributes(myTuple1, myTuple2, differingAttributes,
161+
error, $EVAL_PREDICATE_TRACING);
162+
163+
if(error == 0) {
164+
printStringLn("Compare tuple attributes function returned successfully. " +
165+
"differingAttributes = " + (rstring)differingAttributes);
166+
} else {
167+
printStringLn("Compare tuple attributes function returned an error. Error=" + (rstring)error);
168+
}
169+
}
170+
// Following is the usage description for the get_tuple_attribute_value function.
171+
//
172+
// Arg1: Your tuple1
173+
// Arg2: Your tuple2
174+
// Arg3: A mutable variable of list<string> type in which the
175+
// attribute names that differ in their values will be returned.
176+
// Arg4: A mutable int32 variable to receive non-zero error code if any.
177+
// Arg5: A boolean value to enable debug tracing inside this function.
178+
// It is a void function that returns nothing.
179+
```
180+
109181
## Design considerations
110182
This toolkit came into existence for a specific need with which a large enterprise customer approached the author of this toolkit. There is already a built-in function named *evalPredicate* that is available in the official IBM Streams product. However, that function has certain limitations. To fill that gap, this toolkit with its own **eval_predicate** function is being made available freely via the publicly accessible IBMStreams GitHub. The **eval_predicate** function from this toolkit differs from the *evalPredicate* built-in function in the IBM Streams product in the following ways.
111183

112184
1. This new eval_predicate function allows the user defined rule expression to access map based tuple attributes.
113185

114186
2. This new eval_predicate function allows the user defined rule expression to access nested tuple attributes.
115187

116-
3. This new eval_predicate function allows the user defined rule expression to have operation verbs such as contains, startsWith, endsWith, notContains, notStartsWith, notEndsWith, in, containsCI, startsWithCI, endsWithCI, notContainsCI, notStartsWithCI, notEndsWithCI, inCI, sizeEQ, sizeNE, sizeLT, sizeLE, sizeGT, sizeGE.
188+
3. This new eval_predicate function allows the user defined rule expression to have operation verbs such as contains, startsWith, endsWith, notContains, notStartsWith, notEndsWith, in, containsCI, startsWithCI, endsWithCI, notContainsCI, notStartsWithCI, notEndsWithCI, inCI, equalsCI, notEqualsCI, sizeEQ, sizeNE, sizeLT, sizeLE, sizeGT, sizeGE.
117189

118190
4. This new eval_predicate function supports the following operations inside the rule.
119191

@@ -123,7 +195,7 @@ This toolkit came into existence for a specific need with which a large enterpri
123195

124196
c. It supports these arithmetic operations: +, -, *, /, %
125197

126-
d. It supports these special operations for rstring, set, list and map: contains, startsWith, endsWith, notContains, notStartsWith, notEndsWith, in, containsCI, startsWithCI, endsWithCI, notContainsCI, notStartsWithCI, notEndsWithCI, inCI, sizeEQ, sizeNE, sizeLT, sizeLE, sizeGT, sizeGE
198+
d. It supports these special operations for rstring, set, list and map: contains, startsWith, endsWith, notContains, notStartsWith, notEndsWith, in, containsCI, startsWithCI, endsWithCI, notContainsCI, notStartsWithCI, notEndsWithCI, inCI, equalsCI, notEqualsCI, sizeEQ, sizeNE, sizeLT, sizeLE, sizeGT, sizeGE
127199

128200
e. No bitwise operations are supported at this time.
129201

com.ibm.streamsx.eval_predicate/EvalPredicateExample.spl

Lines changed: 91 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
/*
99
==================================================================
1010
First created on: Mar/05/2021
11-
Last modified on: Sep/04/2021
11+
Last modified on: Oct/16/2021
1212

1313
This is an example application that shows how to use the
1414
eval_predicate function to evaluate an SPL expression a.k.a
@@ -102,6 +102,13 @@ that is expressed via a user provided string input.
102102
In this example, you can search for get_tuple_attribute_value to
103103
see 10 different test cases on that topic.
104104

105+
Another feature available in the eval_prediate toolkit is to
106+
compare the attribute values of two tuples that are made of
107+
the same schema and to return a list containing the
108+
attribute names that differ in their values. In this example,
109+
you can search for compare_tuple_attributes to see a few
110+
test cases on that topic.
111+
105112
How can you use this new eval_predicate function?
106113
-------------------------------------------------
107114
Any other application that wants to use this function must
@@ -392,6 +399,89 @@ composite EvalPredicateExample {
392399
printStringLn("Testcase 2.6: Tuple attribute value was not fetched successfully. Error=" + (rstring)error);
393400
}
394401

402+
// Compare the attribute values of two tuples that are based on the same schema.
403+
// Arg1: Your tuple1
404+
// Arg2: Your tuple2
405+
// Arg3: A mutable variable of list<string> type in which the
406+
// attribute names that differ in their values will be returned.
407+
// Arg4: A mutable int32 variable to receive non-zero error code if any.
408+
// Arg5: A boolean value to enable debug tracing inside this function.
409+
//
410+
// 2.7
411+
// Compare two tuples that have no differing attribute values.
412+
//
413+
// Declare a nested tuple data structure to be used in this test case.
414+
type NestedType1_t = int32 x, float64 y, rstring z, list<int32> l;
415+
type NestedType2_t = NestedType1_t m, map<int32, boolean> n, timestamp o;
416+
type Test_t = boolean a, int32 b, uint64 c, float32 d, float64 e,
417+
rstring f, set<int32> g, list<rstring> h, map<int32, rstring> i,
418+
map<rstring, float64> j, NestedType2_t k;
419+
420+
// Create two tuples that are based on the same schema.
421+
mutable Test_t myTuple1 = {};
422+
mutable Test_t myTuple2 = {};
423+
mutable list<rstring> differingAttributes = [];
424+
425+
// Populate the tuple with some data.
426+
myTuple1.a = true;
427+
myTuple1.b = 456;
428+
myTuple1.c = 789ul;
429+
myTuple1.d = (float32)123.45;
430+
myTuple1.e = 987.65;
431+
myTuple1.f = "Life is mainly there to have fun.";
432+
myTuple1.g = {5, 9, 2, 6};
433+
myTuple1.h = ['One', 'Two', 'Three'];
434+
myTuple1.i = {1:'One', 2:'Two', 3:'Three'};
435+
myTuple1.j = {"One":1.0, "Two":2.0, "Three":3.0};
436+
myTuple1.k.m.x = 678;
437+
myTuple1.k.m.y = 936.27;
438+
myTuple1.k.m.z = "String inside a nested tuple.";
439+
myTuple1.k.m.l = [67, 78, 89];
440+
myTuple1.k.n = {1:true, 2:false, 3:true};
441+
myTuple1.k.o = getTimestamp();
442+
443+
// Make the second tuple same as the first tuple.
444+
myTuple2 = myTuple1;
445+
446+
// Compare them now.
447+
compare_tuple_attributes(myTuple1, myTuple2,
448+
differingAttributes, error, $EVAL_PREDICATE_TRACING);
449+
450+
if(error == 0) {
451+
printStringLn("Testcase 2.7: Compare tuple attributes function returned successfully. " +
452+
"differingAttributes = " + (rstring)differingAttributes);
453+
} else {
454+
printStringLn("Testcase 2.7: Compare tuple attributes function returned an error. Error=" + (rstring)error);
455+
}
456+
457+
// 2.8
458+
// Compare two tuples that have differing attribute values.
459+
//
460+
// Make the second tuple to have a few different attribute values than the first tuple.
461+
myTuple2.a = false;
462+
myTuple2.d = (float32)145.12;
463+
myTuple2.f = "Life is mainly there to have joy and peace.";
464+
myTuple2.i = {10:'Ten', 9:'Nine', 8:'Eight'};
465+
myTuple2.k.m.y = 27.93;
466+
myTuple2.k.m.z = "Different string inside a nested tuple.";
467+
myTuple2.k.n = {1:true, 2:true, 3:true};
468+
// Wait for 2 seconds for time to change.
469+
block(2.0);
470+
myTuple2.k.o = getTimestamp();
471+
472+
// Clear the list.
473+
differingAttributes = (list<rstring>)[];
474+
// Compare them now.
475+
compare_tuple_attributes(myTuple1, myTuple2,
476+
differingAttributes, error, $EVAL_PREDICATE_TRACING);
477+
478+
if(error == 0) {
479+
printStringLn("Testcase 2.8: Compare tuple attributes function returned successfully. " +
480+
"differingAttributes = " + (rstring)differingAttributes);
481+
} else {
482+
printStringLn("Testcase 2.8: Compare tuple attributes function returned an error. Error=" + (rstring)error);
483+
}
484+
395485
// ============== TESTCASE GROUP 3 ==============
396486
mutable City_t myCity = {};
397487
myCity.name = "White Plains";

com.ibm.streamsx.eval_predicate/FunctionalTests.spl

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
/*
99
==================================================================
1010
First created on: Mar/28/2021
11-
Last modified on: Sep/04/2021
11+
Last modified on: Oct/16/2021
1212

1313
This application is meant for doing several hundred
1414
functional tests to provide as much coverage as possible to
@@ -40,6 +40,13 @@ that is expressed via a user provided string input.
4040
You can search below for get_tuple_attribute_value to
4141
see a few dozen different test cases on that topic.
4242

43+
Another feature available in the eval_prediate toolkit is to
44+
compare the attribute values of two tuples that are made of
45+
the same schema and to return a list containing the
46+
attribute names that differ in their values. In this example,
47+
you can search for compare_tuple_attributes to see a few
48+
test cases on that topic.
49+
4350
How can you build this test application?
4451
----------------------------------------
4552
1) If you are a command line person, you can use the
@@ -8242,6 +8249,11 @@ composite FunctionalTests {
82428249

82438250
// In this operator, we will do tests for getting
82448251
// tuple attribute values in different ways.
8252+
// In addition, we will do test cases for comparing
8253+
// two tuples that are made of the same schema and
8254+
// then to return a list containing the attribute
8255+
// names that differ in their values across those
8256+
// two tuples.
82458257
() as FetchValueSink = Custom(MyTestData as MTD) {
82468258
logic
82478259
state: {
@@ -9042,6 +9054,90 @@ composite FunctionalTests {
90429054
} else {
90439055
printStringLn("Testcase C1.48: Tuple attribute value was not fetched successfully. Error=" + (rstring)error);
90449056
}
9057+
9058+
// Compare the attribute values of two tuples that are based on the same schema.
9059+
// Arg1: Your tuple1
9060+
// Arg2: Your tuple2
9061+
// Arg3: A mutable variable of list<string> type in which the
9062+
// attribute names that differ in their values will be returned.
9063+
// Arg4: A mutable int32 variable to receive non-zero error code if any.
9064+
// Arg5: A boolean value to enable debug tracing inside this function.
9065+
//
9066+
// C1.49
9067+
// Compare two tuples that have no differing attribute values.
9068+
//
9069+
// Declare a nested tuple data structure to be used in this test case.
9070+
type NestedType1_t = int32 x, float64 y, rstring z, list<int32> l;
9071+
type NestedType2_t = NestedType1_t m, map<int32, boolean> n, timestamp o;
9072+
type Test_t = boolean a, int32 b, uint64 c, float32 d, float64 e,
9073+
rstring f, set<int32> g, list<rstring> h, map<int32, rstring> i,
9074+
map<rstring, float64> j, NestedType2_t k;
9075+
9076+
// Create two tuples that are based on the same schema.
9077+
mutable Test_t myTuple1 = {};
9078+
mutable Test_t myTuple2 = {};
9079+
mutable list<rstring> differingAttributes = [];
9080+
9081+
// Populate the tuple with some data.
9082+
myTuple1.a = true;
9083+
myTuple1.b = 456;
9084+
myTuple1.c = 789ul;
9085+
myTuple1.d = (float32)123.45;
9086+
myTuple1.e = 987.65;
9087+
myTuple1.f = "Life is mainly there to have fun.";
9088+
myTuple1.g = {5, 9, 2, 6};
9089+
myTuple1.h = ['One', 'Two', 'Three'];
9090+
myTuple1.i = {1:'One', 2:'Two', 3:'Three'};
9091+
myTuple1.j = {"One":1.0, "Two":2.0, "Three":3.0};
9092+
myTuple1.k.m.x = 678;
9093+
myTuple1.k.m.y = 936.27;
9094+
myTuple1.k.m.z = "String inside a nested tuple.";
9095+
myTuple1.k.m.l = [67, 78, 89];
9096+
myTuple1.k.n = {1:true, 2:false, 3:true};
9097+
myTuple1.k.o = getTimestamp();
9098+
9099+
// Make the second tuple same as the first tuple.
9100+
myTuple2 = myTuple1;
9101+
9102+
// Compare them now.
9103+
compare_tuple_attributes(myTuple1, myTuple2,
9104+
differingAttributes, error, $EVAL_PREDICATE_TRACING);
9105+
9106+
if(error == 0) {
9107+
printStringLn("Testcase C1.49: Compare tuple attributes function returned successfully. " +
9108+
"differingAttributes = " + (rstring)differingAttributes);
9109+
} else {
9110+
printStringLn("Testcase C1.49: Compare tuple attributes function returned an error. Error=" + (rstring)error);
9111+
}
9112+
9113+
// C1.50
9114+
// Compare two tuples that have differing attribute values.
9115+
//
9116+
// Make the second tuple to have a few different attribute values than the first tuple.
9117+
myTuple2.a = false;
9118+
myTuple2.d = (float32)145.12;
9119+
myTuple2.f = "Life is mainly there to have joy and peace.";
9120+
myTuple2.i = {10:'Ten', 9:'Nine', 8:'Eight'};
9121+
myTuple2.k.m.y = 27.93;
9122+
myTuple2.k.m.z = "Different string inside a nested tuple.";
9123+
myTuple2.k.n = {1:true, 2:true, 3:true};
9124+
// Wait for 2 seconds for time to change.
9125+
block(2.0);
9126+
myTuple2.k.o = getTimestamp();
9127+
9128+
// Clear the list.
9129+
differingAttributes = (list<rstring>)[];
9130+
// Compare them now.
9131+
compare_tuple_attributes(myTuple1, myTuple2,
9132+
differingAttributes, error, $EVAL_PREDICATE_TRACING);
9133+
9134+
if(error == 0) {
9135+
printStringLn("Testcase C1.50: Compare tuple attributes function returned successfully. " +
9136+
"differingAttributes = " + (rstring)differingAttributes);
9137+
} else {
9138+
printStringLn("Testcase C1.50: Compare tuple attributes function returned an error. Error=" + (rstring)error);
9139+
}
9140+
90459141
// -------------------------
90469142

90479143
// Let us add below a few test cases for the

com.ibm.streamsx.eval_predicate/native.function/function.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,19 @@ It fetches the value of a user given attribute name if it is present in the user
2828
</description>
2929
<prototype>&lt;tuple T1, any T2> public void get_tuple_attribute_value(rstring attributeName, T1 myTuple, mutable T2 value, mutable int32 error, boolean trace)</prototype>
3030
</function>
31+
32+
<function>
33+
<description>
34+
It compares the attribute values of two tuples that are made of the same schema and returns a list containing the attribute names that have differing values.
35+
@param myTuple1 First of the two user given tuples to be compared. Type: Tuple
36+
@param myTuple2 Second of the two user given tuples to be compared. Type: Tuple
37+
@param differingAttributes A mutable list variable that will contain the attribute names that have differing values. Type: list&lt;rstring&gt;
38+
@param error A mutable variable that will contain a non-zero error code if an error occurs. Type: int32
39+
@param trace A boolean value to enable tracing inside this function. Type: boolean
40+
@return It returns nothing. Type: void
41+
</description>
42+
<prototype>&lt;tuple T1> public void compare_tuple_attributes(T1 myTuple1, T1 myTuple2, mutable list&lt;rstring&gt; differingAttributes, mutable int32 error, boolean trace)</prototype>
43+
</function>
3144
</functions>
3245

3346
<dependencies>

0 commit comments

Comments
 (0)