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

[GAIAPLAT-672] Implement connect/disconnect translation in gaiat #841

Merged
merged 18 commits into from
Aug 20, 2021

Conversation

simone-gaia
Copy link
Contributor

@simone-gaia simone-gaia commented Aug 17, 2021

Add the connect/disconnect handling logic in gaiat.

  • Add declarative_connect_disconnect_handler_t in gaiat + relative matchers.
  • Changed disconnect() semantic for 1:1 relationship to make it possible only in the form table.link.disconnect(). Link name must be specified and no arguments required.
  • Create GaiaTable attribute to add to the classes that represent tables in the DB.
  • Delete err_invalid_table_name message because it is a duplicate of err_table_not_found.
  • Add link_data_t to table_data_t in table_navigation.h
  • Disable .clang-tidy variables casing warnings for clang code.

@@ -3025,6 +3028,140 @@ class declarative_break_continue_handler_t : public MatchFinder::MatchCallback
Rewriter& m_rewriter;
};

// AST handler that is called when declarative break or continue are used in the rule.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whoopsy.

{
// Changes connect() to insert() for 1:N relationships.
// TODO https://gaiaplatform.atlassian.net/browse/GAIAPLAT-1181
m_rewriter.ReplaceText(method_call_expr->getExprLoc(), c_connect_length, "insert");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have full EDC support for this and remove ? I.e. the spec says it should handle the cases when records already connected etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. This is supported in the 1:1 connect disconnect (at EDC level) but not for 1:n. I would implement this in EDC to make the 2 APIs somewhat symmetric.

Created a task for it: https://gaiaplatform.atlassian.net/browse/GAIAPLAT-1193

method_call_expr->getExprLoc().getLocWithOffset(c_disconnect_length + 1),
method_call_expr->getEndLoc());

param_loc.dump(*result.SourceManager);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need this

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Damn, forgot it.

Copy link
Contributor

@LaurentiuCristofor LaurentiuCristofor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no special observations. The logic should be reviewed by Greg.

auto src_table_iter = table_data.find(src_table_name);
if (src_table_iter == table_data.end())
{
cerr << "Table '" << src_table_name << "' was not found in the catalog." << endl;
Copy link
Contributor

@daxhaw daxhaw Aug 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to check in my changes before yours and then you can pick up the error strings. Ideally there is one you can use like err_table_not_found.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've pushed to master. Thanks!

@@ -56,6 +56,9 @@ bool g_is_rule_prolog_specified = false;
constexpr int c_encoding_shift = 16;
constexpr int c_encoding_mask = 0xFFFF;

constexpr size_t c_connect_length = 7;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: maybe c_connect_keyword_length would be more descriptive.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -3025,6 +3028,140 @@ class declarative_break_continue_handler_t : public MatchFinder::MatchCallback
Rewriter& m_rewriter;
};

// AST handler that is called when declarative break or continue are used in the rule.
class declarative_connect_disconnect_handler_t : public MatchFinder::MatchCallback
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it make sense to break this up into two handlers? (connect handler and disconnect handler)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's what I started with until I realized that the code is 95% the same. An alternative would be to have a parent class that handles all the common logic and subclasses with specializations.

I can go down this route if you wish.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, parent class or a helper function that both call. Just then you wouldn't have to check which keyword it is "connect" or "disconnect" and the two cases are different. I don't mind having single-purpose matchers.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, when we are going to add connect/disconnect to the EDC containers the code will be exactly the same.

bool need_link_field = false;

const auto* method_call_expr = result.Nodes.getNodeAs<CXXMemberCallExpr>("connectDisconnectCall");
bool is_connect = method_call_expr->getMethodDecl()->getName().str() == "connect";
Copy link
Contributor

@daxhaw daxhaw Aug 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Someday I'd like to consolidate all our declarative language keywords into a single string table... (not saying you should do this now, but maybe move the string to a c_connect_keyword constant.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but maybe move the string to a c_connect_keyword constant.

Done.


if (link_name.empty())
{
cerr << "Impossible to find a link between table " << src_table_name << " and table " << dest_table_name << endl;
Copy link
Contributor

@daxhaw daxhaw Aug 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider rewording from "Impossible to ..." to something like "A link does not exist between ...". Then add to DiagnosticSemaKinds.td (in alphabetical order) where our Gaia errors are at the bottom of the file grouped by err, note, and warn. Then use the gaiat::diag().emit(...) construct to report an LLVM error. Of course, these changes will only be visible after I merge PR-820.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider rewording from "Impossible to ..." to something like "A link does not exist between ...". T

Done.

WIll do the rest after you merge your PR.


TEST_F(test_connect_disconnect, test_connect_1_n)
{
gaia::rules::initialize_rules_engine();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like these two lines (init rules engine and unsubscribe) are used in every test. Consider moving to Setup.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. @waynelwarren can we do the same for other tests?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I can take a look at this.


using namespace gaia::barn_storage;

ruleset test_connect_disconnect
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably handled below but why no disconnect rule/test here? I feel misled by the ruleset name :).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should not be here, removed. We squeeze all the tests into one ruleset, and then we create different tests files for each type of test. This greatly improves compile time.

Copy link
Contributor

@daxhaw daxhaw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly nits and a confusion about the integration tests. Cool to see this functionality almost in!

Copy link
Contributor

@waynelwarren waynelwarren left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. I have built and tested this branch. Added one small test.

* simple new disconnect/remove test

* using size() method rather than scanning members
@@ -9526,7 +9526,7 @@ def err_duplicate_field : Error<
"Duplicate field '%0' found in table '%1'. Qualify your field with the "
"table name (table.field) to disambiguate field names that occur in more "
"than one table. You can also restrict the list of tables to search by "
"specifing them in the ruleset 'tables' attribute.">;
"specifying them in the ruleset 'tables' attribute.">;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Thanks!

@@ -9578,8 +9578,6 @@ def err_invalid_parent_table : Error<
"Incorrect parent table in the relationship '%0'.">;
def err_invalid_table_field : Error<
"Field '%0' has no table in the catalog.">;
def err_invalid_table_name : Error<
Copy link
Contributor

@daxhaw daxhaw Aug 20, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need this error any more? Ah, I guess this was a dup with err_table_not_found. Another good catch.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep. This is subsumed by err_table_not_found.

@@ -70,7 +70,7 @@ ruleset test38

ruleset test39
{
on_update(value) // expected-error {{Duplicate field 'value' found in table 'actuator'. Qualify your field with the table name (table.field) to disambiguate field names that occur in more than one table. You can also restrict the list of tables to search by specifing them in the ruleset 'tables' attribute.}}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😭 Thank you for fixing this up for me. Embarrassing.

Copy link
Contributor

@daxhaw daxhaw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good.

@simone-gaia simone-gaia merged commit 52c350d into master Aug 20, 2021
@LaurentiuCristofor LaurentiuCristofor deleted the rondelli-conn-disconn-gaiat-2 branch October 15, 2021 20:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants