Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add BBE for new Table implementation #496

Merged
merged 2 commits into from
May 14, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions examples/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,10 @@
"name": "Maps",
"url": "maps"
},
{
"name": "Table",
"url": "table"
},
{
"name": "Union Types",
"url": "union-type"
Expand Down
163 changes: 85 additions & 78 deletions examples/table/table.bal
Original file line number Diff line number Diff line change
@@ -1,91 +1,98 @@
import ballerina/io;
import ballerina/jsonutils;
import ballerina/xmlutils;

type Person record {|
readonly int id;
string name;
int age;
|};

// This is the `type` created to represent a data row.
// The type of the value of the id field is `readonly` and the field itself cannot be mutated.
lasinicl marked this conversation as resolved.
Show resolved Hide resolved
// id is the unique identifier of Employee.
lasinicl marked this conversation as resolved.
Show resolved Hide resolved
type Employee record {
int id;
readonly int id;
string name;
float salary;
};

// This is a `table` type.
// EmployeeTable type has members that are employees, and within a EmployeeTable each member is
lasinicl marked this conversation as resolved.
Show resolved Hide resolved
// uniquely identified within the table by its id field.
lasinicl marked this conversation as resolved.
Show resolved Hide resolved
type EmployeeTable table<Employee> key(id);

// You can define a `table` value where its members are of type `map` constrained by `any` type
lasinicl marked this conversation as resolved.
Show resolved Hide resolved
type CustomerTable table<map<any>>;

public function main() {
// This creates an in-memory `table` constrained by the `Employee` type with the `id` marked as the
// primary key in the column descriptor. Three data records are inserted into the `table`. The order of
// the data values should match the order of the column descriptor.
table<Employee> tbEmployee = table {
{key id, name, salary},
[
{1, "Mary", 300.5},
{2, "John", 200.5},
{3, "Jim", 330.5}
]
};
// Print the `table` data.
io:print("Table Information: ");
io:println(tbEmployee);

// Create `Employee` records.
Employee e1 = {id: 1, name: "Jane", salary: 300.50};
Employee e2 = {id: 2, name: "Anne", salary: 100.50};
Employee e3 = {id: 3, name: "John", salary: 400.50};
Employee e4 = {id: 4, name: "Peter", salary: 150.0};

// Create an in-memory `table` constrained by the `Employee` type with
// the `id` as the primary key. Two records are inserted into the `table`.
table<Employee> tb = table {
{key id, name, salary},
[
e1,
e2
]
};

Employee[] employees = [e3, e4];
// Add the created records to the `table`.
foreach var emp in employees {
var ret = tb.add(emp);
if (ret is ()) {
io:println("Adding record to table successful");
} else {
io:println("Adding to table failed: ", ret.reason());
}
}

// A `table` constructor works like a list constructor.
lasinicl marked this conversation as resolved.
Show resolved Hide resolved
// The table preserves the order of its members. Iterating over the table gives the
// members of the table in order.
lasinicl marked this conversation as resolved.
Show resolved Hide resolved
EmployeeTable employeeTab = table [
{ id: 1, name: "John", salary: 300.50 },
{ id: 2, name: "Bella", salary: 500.50 },
{ id: 3, name: "Peter", salary: 750.0 }
];

// Print the `table` data.
lasinicl marked this conversation as resolved.
Show resolved Hide resolved
io:println("Table Information: ", tb);

// Access the rows using the `foreach` loop.
io:println("Using foreach:");
foreach var x in tb {
io:println("Name: ", x.name);
}

// Access rows using the `while` loop.
io:println("Using while loop:");
while (tb.hasNext()) {
var ret = tb.getNext();
io:println("Name: ", ret.name);
}

// Convert the `table` to JSON format.
json retValJson = jsonutils:fromTable(tb);
io:println("JSON: ", retValJson.toJsonString());

// Convert the `table` to XML format.
xml retValXml = xmlutils:fromTable(tb);
io:println("XML: ", retValXml);

// Remove employees with salaries higher than 300.0
// from the table.
int|error count = tb.remove(isHigherSalary);
io:println("Deleted Count: ", count);

// Now the table contains the employees with salaries less than 300.0.
io:println(tb);
}
io:println("Employee Table Information: ", employeeTab);

// Returns the number of members of a `table`.
io:println("Total number of Employees: ", employeeTab.length());

// Adds a new member to Employee table
lasinicl marked this conversation as resolved.
Show resolved Hide resolved
Employee emp = { id: 4, name: "Max", salary: 900.0 };
employeeTab.add(emp);

// Member access using id field of an Employee
lasinicl marked this conversation as resolved.
Show resolved Hide resolved
io:println("New Employee: ", employeeTab[4]);

// Returns the member of a `table` with a given key.
io:println("Employee 1: ", employeeTab.get(1));

// Removes the member of `table` with a given key and returns it.
lasinicl marked this conversation as resolved.
Show resolved Hide resolved
io:println("Information of the removed Employee: ", employeeTab.remove(2));

// Gives a list of all keys of a `table`.
var personTblKeys = employeeTab.keys();
io:println("Employee table keys: ", personTblKeys);

// The members of a `table` can be returned as an `array`.
Employee[] tableToList = employeeTab.toArray();
io:println("Employee table to list: ", tableToList);

// Tables are an iterable type and tables support functional iteration operations such as `.forEach()`,
// `.map()`, `.filter()`, `.reduce()`.
lasinicl marked this conversation as resolved.
Show resolved Hide resolved
string filtered = "";
employeeTab.forEach(function (Employee employee) {
if (employee.salary < 400.0) {
filtered += employee.name;
filtered += " ";
}
});
io:println("Employees with salary < 400.0: ", filtered);

// `.map()` applies a function to each member of a table and returns a table of the result.
// The resulting table will have the same keys as the argument table.
table<Person> personTab = employeeTab.'map(function (Employee employee)
returns Person {
return { id: employee.id, name:employee.name, age:23 };
});
io:println("Person Table Information: ", personTab);

// Create `table` values with map constrained members.
lasinicl marked this conversation as resolved.
Show resolved Hide resolved
CustomerTable customerTab = table [
{ id: 13 , fname: "Dan", lname: "Bing" },
{ id: 23 , fname: "Hay" , lname: "Kelsey" }
];
io:println("Customer Table Information: ", customerTab);

// The table constructor can be used without a contextually expected type. Member access is not
lasinicl marked this conversation as resolved.
Show resolved Hide resolved
// allowed here.
var studentTab = table [
{ id: 44, fname: "Meena", lname: "Kaur" },
{ id: 55, fname: "Jay", address: "Palm Grove, NY"}
];
io:println("Student Table Information: ", studentTab);

// Check whether a given employee's salary is higher than 300.0.
function isHigherSalary(Employee emp) returns boolean {
return emp.salary > 300.0;
}
8 changes: 5 additions & 3 deletions examples/table/table.description
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
// The type `table` is a data structure that organizes information in rows and columns. This example demonstrates how to
// create an in-memory table using a type constraint, insert data to it, and then access/delete the data.<br/><br/>
// For more information on the underlying module,
// A `table` is a structural value, whose members are mapping values that represent rows of the table. A `table`
lasinicl marked this conversation as resolved.
Show resolved Hide resolved
// provides access to its members using a key that comes from the read-only fields of the member. It keeps its
// members in order, but does not provide random access to a member using its position in this order. The built-in
lasinicl marked this conversation as resolved.
Show resolved Hide resolved
// functions enable inserting, accessing, deleting data and applying functions on members of a `table`.
lasinicl marked this conversation as resolved.
Show resolved Hide resolved
// For more information on the underlying module,
// see the [lang.table module](https://ballerina.io/learn/api-docs/ballerina/lang.table/index.html).
35 changes: 17 additions & 18 deletions examples/table/table.out
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
# To run this sample, navigate to the directory that contains the
# `.bal` file, and execute the `ballerina run` command.
$ ballerina run table.bal
Table Information: id=1 name=Mary salary=300.5 id=2 name=John salary=200.5 id=3 name=Jim salary=330.5
Adding record to table successful
Adding record to table successful
Table Information: id=1 name=Jane salary=300.5 id=2 name=Anne salary=100.5 id=3 name=John salary=400.5 id=4 name=Peter salary=150.0
Using foreach:
Name: Jane
Name: Anne
Name: John
Name: Peter
Using while loop:
Name: Jane
Name: Anne
Name: John
Name: Peter
JSON: [{"id":1, "name":"Jane", "salary":300.5}, {"id":2, "name":"Anne", "salary":100.5}, {"id":3, "name":"John", "salary":400.5}, {"id":4, "name":"Peter", "salary":150.0}]
XML: <results><result><id>1</id><name>Jane</name><salary>300.5</salary></result><result><id>2</id><name>Anne</name><salary>100.5</salary></result><result><id>3</id><name>John</name><salary>400.5</salary></result><result><id>4</id><name>Peter</name><salary>150.0</salary></result></results>
Deleted Count: 2
id=2 name=Anne salary=100.5 id=4 name=Peter salary=150.0
Employee Table Information: id=1 name=John salary=300.5
id=2 name=Bella salary=500.5
id=3 name=Peter salary=750.0
Total number of Employees: 3
New Employee: id=4 name=Max salary=900.0
Employee 1: id=1 name=John salary=300.5
Information of the removed Employee: id=2 name=Bella salary=500.5
Employee table keys: 1 3 4
Employee table to list: id=1 name=John salary=300.5 id=3 name=Peter salary=750.0 id=4 name=Max salary=900.0
Employees with salary < 400.0: John
Person Table Information: id=1 name=John age=23
id=3 name=Peter age=23
id=4 name=Max age=23
Customer Table Information: id=13 fname=Dan lname=Bing
id=23 fname=Hay lname=Kelsey
Student Table Information: id=44 fname=Meena lname=Kaur
id=55 fname=Jay address=Palm Grove, NY
63 changes: 25 additions & 38 deletions examples/table/tests/table_test.bal
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import ballerina/test;
import ballerina/io;

(any|error)[] outputs = [];
int counter = 0;
Expand All @@ -19,43 +20,29 @@ public function mockPrint(any|error... s) {
function testFunc() {
// Invoking the main function.
main();
string op1 = "table<ballerina-examples/table:0.0.1:Employee> {index: [], primaryKey: [\"id\"], " +
"data: [{id:1, name:\"Mary\", salary:300.5}, {id:2, name:\"John\", salary:200.5}, " +
"{id:3, name:\"Jim\", salary:330.5}]}";
string op2 = "Adding record to table successful";
string op3 = "Adding record to table successful";
string op4 = "table<ballerina-examples/table:0.0.1:Employee> {index: [], primaryKey: [\"id\"],
data: [{id:1, name:\"Jane\", salary:300.5}, {id:2, name:\"Anne\", salary:100.5},
{id:3, name:\"John\", salary:400.5}, {id:4, name:\"Peter\", salary:150.0}]}";
string op5 = "Using foreach: ";
string op6 = "Name: Jane";
string op7 = "Name: Anne";
string op8 = "Name: John";
string op9 = "Name: Peter";
string op10 = "Using while loop: ";
string op11 = "Average of Low salary: 125.25";
string op12 = "Selected row count: 4";
string op13 = "Deleted row count: 2";
string js1 = "[{\"id\":1, \"name\":\"Jane\", \"salary\":300.5}, {\"id\":3, \"name\":\"John\", \"salary\":400.5}]";
xml xml1 = xml `<results><result><id>1</id><name>Jane</name><salary>300.5</salary></result><
result><id>3</id><name>John</name><salary>400.5</salary></result></results>`;

test:assertEquals(string.convert(outputs[0]), op1);
test:assertEquals(<string>outputs[1], op2);
test:assertEquals(<string>outputs[2], op3);
test:assertEquals(<string>outputs[5], op5);
test:assertEquals(<string>outputs[6], op6);
test:assertEquals(<string>outputs[7], op7);
test:assertEquals(<string>outputs[8], op8);
test:assertEquals(<string>outputs[9], op9);
test:assertEquals(<string>outputs[10], op10);
test:assertEquals(<string>outputs[11], op6);
test:assertEquals(<string>outputs[12], op7);
test:assertEquals(<string>outputs[13], op8);
test:assertEquals(<string>outputs[14], op9);
test:assertEquals(<string>outputs[15], op11);
test:assertEquals(<string>outputs[16], op12);
test:assertEquals(<string>outputs[18], op13);
test:assertEquals(string.convert(outputs[22]), js1);
test:assertEquals(outputs[24], xml1);
string op1 = "id=1 name=John salary=300.5 id=2 name=Bella salary=500.5 id=3 name=Peter salary=750.0";
string op2 = "Total number of Employees: 3";
string op3 = "New Employee: id=4 name=Max salary=900.0";
string op4 = "Employee 1: id=1 name=John salary=300.5";
string op5 = "Information of the removed Employee: id=2 name=Bella salary=500.5";
string op6 = "Employee table keys: 1 3 4";
string op7 = "Employee table to list: id=1 name=John salary=300.5 id=3 name=Peter salary=750.0 " +
"id=4 name=Max salary=900.0";
string op8 = "Employees with salary < 400.0: John";
string op9 = "Person Table Information: id=1 name=John age=23 id=3 name=Peter age=23 id=4 name=Max age=23";
string op10 = "Customer Table Information: id=13 fname=Dan lname=Bing id=23 fname=Hay lname=Kelsey";
string op11 = "Student Table Information: id=44 fname=Meena lname=Kaur id=55 fname=Jay address=Palm Grove, NY";

test:assertEquals(outputs[0], op1);
test:assertEquals(outputs[1], op2);
test:assertEquals(outputs[2], op3);
test:assertEquals(outputs[3], op4);
test:assertEquals(outputs[4], op5);
test:assertEquals(outputs[5], op6);
test:assertEquals(outputs[6], op7);
test:assertEquals(outputs[7], op8);
test:assertEquals(outputs[8], op9);
test:assertEquals(outputs[9], op10);
test:assertEquals(outputs[10], op11);
}