-
Notifications
You must be signed in to change notification settings - Fork 53
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
Table proposal discussion #354
Comments
Comment from @sanjiva. Another variant of persistent tables is to be able to create the persistent table within Ballerina and use the Ballerina type to create the schema for the underlying database engine. Originally posted by @jclark in #286 (comment) |
Overall I think this proposal is not satisfactory. I will explain the reasons in subsequent comments. |
Compared to
Whereas what you really want to do is simply:
So why are we doing the immutable clone? One reason is to enable persistence/transactionality. The other reason is so that the table can enforce the primary key constraints. Otherwise you could get the following situation:
In #348, @hrennau makes the interesting suggestion of pushing the primary key concept into record. If we did this, then we could say that the fields corresponding to primary keys are immutable, thus preventing the situation described above. |
Another more minor thing, that |
Another idea underlying the tables proposal was that it would be the gateway to providing a convenient SQL-like language-integrated feature for manipulating tabular data. But in fact it is possible to provide such as feature on top of lists without needing a table data type, as the Query proposal shows. |
The most fundamental flaw in the proposal is this. It tries to both
But it is simply not possible to do both these things, while at the same time keeping to Ballerina's explicit error handling principle. Transactional reads on data can fail in a way that needs to be reported as an error value not as a panic (because the errors are expected and need to be handled by the programmer typically using a retry). For example, a transactional read from a database can fail because of a deadlock. But anydata requires read operations like With transactions, each transaction gets its own distinct, isolated view of the table. This feels like something behavioural not like pure data. |
Another fundamental issue is that it doesn't really solve the problem of providing convenient access to a relational database. It is not sufficient to look at each table in isolation. You really want to be able to capture the underlying Entity/Relationship data model, which involves multiple tables, as done by |
I think that the Table proposal is very important for the evolution of the Ballerina language (expressiveness, degree of being declarative). The proposal must neither be canceled, nor finalized prematurely. The main shortcoming of its current state may be the lack of "goals and requirements" beyond the very high-level paragraphs opening, and the very specific SQL interop section closing, the proposal. We might be more systematic; start with defining categories of goals, like (a) which kinds of entities to represent, (b) which categories of operations to support, (c) which logical operations to support, (d) kinds of operation support. How about an additional document which is equivalent to “Use cases” or “Requirements” documents preparing and guiding the devlopment of a W3C specification? Presently, important goals and requirements are scattered across discussions of various formal details – for example, the need of representing ordered SQL results pops up in the middle of the discussion of a formal detail. (While it is inevitable to let our minds shuttle, the resulting document should abstract from the process of its creation.) Currently, there is no coherent picture of goals and requirements; and guidance given by stated goals and requirements is reduced because perceived in isolation, rather than in context. To sketch the direction which I imagine the “Requirements” documents could take: Such a document would be written in an iterative way, enabling us to see new requirements readily in the context of the complete set of requirements already defined. |
Hello, it seems the count function got lost in version 1.0.0. Can it be put back?
|
Hi @snow6oy, It is already in the spec, Please refer to https://github.com/ballerina-platform/ballerina-spec/blob/master/lang/proposals/table/table.bal line no 11. |
@snow6oy It's called |
The below question is regarding the above condition of having the When we are dealing with SQL queries, sometimes the result of the query may contain some complex column names. Ex : SELECT COUNT(CustomerID), Country
FROM Customers
GROUP BY Country; The result of the above query will be a table with two columns named One alternative is to modify the SQL query with as to have a simple column name as follows. But that may not feasible in some cases. SELECT COUNT(CustomerID) as IDCount, Country
FROM Customers
GROUP BY Country; In the current ballerina table implementation we don’t have such restriction. I.e. only the order of the data types are considered and the corresponding ballerina table can have any name for the fields in the constraint record type of the table. |
@anupama-pathirage You can use a https://ballerina.io/spec/lang/2019R3/#QuotedIdentifier to define a record with any field name you want. |
@jclark Thanks for the reference. I missed the spec definition for QuotedIdentifier as only the alphanumerics are allowed at the moment in the current implementation. |
@jclark, @hasithaa, @anupama-pathirage Presently, the main usage of tables are with SQL client. And currently, when retrieving data, we return a To do that, what we can do is to return an iterator from SQL client and use that to construct the table. However, there are some implementation complexities with this approach. For example, the iterator should be aware of the value type it returns (i.e type Iterable object {
__iterator() returns Iterator {
...
}
}
// current implementation
type Iterator object {
next() returns record {| ConstrainType value; |}? {
...
}
}
// proposed implementation
type Iterator object {
next() returns record {| map<anydata|error> value; |}? {
...
}
} With this, if a user of a SQL client needs to retrieve information from a DB into a table, they can use this Iterator to do that. WDYT? |
@grainier It should be convenient for the user to be able to perform further processing on the results they get back from the SQL client, by e.g. using a query or using functional methods like foreach or map. So what we need is an Iterable with some more conveniences and a built-in type name. This is exactly what |
Conceptually it should work. But we may have to special case stream value in the implementation when representing an SQL result set. This is the exact same problem we faced with the table. (Cursor tables vs in-memory tables). For me, it is more natural to represent a SQL result set using an Iterable object. If we can find a way to extend type-param support for |
That would be true of the old design of
|
It is clear that this proposal is not the right approach. So closing this issue. |
This issue is to collect comments on the Tables proposal
The text was updated successfully, but these errors were encountered: