-
Notifications
You must be signed in to change notification settings - Fork 14
docs: updated snippets and samples for profile and analyze methods #1364
Conversation
docs: updated snippets and samples for profile and analyze methods.
a7a05a9
to
88db8d7
Compare
Codecov Report
@@ Coverage Diff @@
## master #1364 +/- ##
==========================================
+ Coverage 94.53% 94.54% +<.01%
==========================================
Files 186 184 -2
Lines 15135 15214 +79
==========================================
+ Hits 14308 14384 +76
- Misses 827 830 +3
Continue to review full report at Codecov.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few suggestions below, let me know if they do not make sense.
Reviewed 2 of 3 files at r1, 1 of 1 files at r3.
Reviewable status: all files reviewed, 6 unresolved discussions (waiting on @devbww, @devjgm, and @scotthart)
google/cloud/spanner/samples/samples.cc, line 1257 at r1 (raw file):
Previously, devbww (Bradley White) wrote…
A general question that I have also been struggling with: Is it better for the snippet to include any necessary
using
declarations andnamespace
alias declarations, or to omit them? That is, is the brevity worth the incompleteness?
I would prefer if we kept them, they avoid questions around "What is this spanner::
namespace? The audience for these snippets are folks that may have never used our libraries before.
google/cloud/spanner/samples/samples.cc, line 1270 at r3 (raw file):
if (!row) throw std::runtime_error(row.status().message()); std::cout << "AlbumId: " << std::get<0>(*row) << "\t"; std::cout << "AlbumTitle: " << std::get<1>(*row) << "\t";
nit: consider just discarding all the results, with a comment:
// Discard query values to keep this example brief.
google/cloud/spanner/samples/samples.cc, line 1432 at r3 (raw file):
using ::google::cloud::StatusOr; namespace spanner = ::google::cloud::spanner; //! [execute-dml]
See above, please move this up, in fact, consider including the whole function so folks don't wonder where client
came from.
google/cloud/spanner/samples/samples.cc, line 2177 at r3 (raw file):
"SELECT SingerId, FirstName, LastName FROM Singers")); if (!plan) throw std::runtime_error(plan.status().message()); if (plan->plan_nodes(0).kind() != google::spanner::v1::PlanNode::RELATIONAL &&
What do you think of wrapping these conditionals in a lambda that examples what they do?
auto is_partitionable_ = [](/*replace with actual type*/auto const& plan) {
if (plan.plan_nodes().empty()) return false;
if (plan.plan_nodes(0).kind() != google::spanner::v1::PlanNode::RELATIONAL) {
return false;
}
if (plan.plan_nodes(0).display_name() != "Distributed Union") {
// maybe even print why here...
return false;
}
return true;
};
if (!is_partionable(*plan)) throw std::runtime_error(...);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewable status: all files reviewed, 6 unresolved discussions (waiting on @coryan, @devbww, and @scotthart)
google/cloud/spanner/samples/samples.cc, line 1501 at r1 (raw file):
Previously, devbww (Bradley White) wrote…
Can this test ever fail?
If not, then maybe the type of dml_result
should drop the StatusOr part to indicate that it can never fail.
google/cloud/spanner/samples/samples.cc, line 1263 at r3 (raw file):
{{"start_title", spanner::Value("Aardvark")}, {"end_title", spanner::Value("Goo")}});
In order to keep the samples as as focused as possible on the thing they're trying to demonstrate (in this case, profiling), I suggest removing the query params, and just inline the values into the select statement string.
google/cloud/spanner/samples/samples.cc, line 1270 at r3 (raw file):
Previously, coryan (Carlos O'Ryan) wrote…
nit: consider just discarding all the results, with a comment:
// Discard query values to keep this example brief.
FWIW, I think this is a good idea. It would also allow the example to get rid of the RowType
alias, since we won't need to use StreamOf
google/cloud/spanner/samples/samples.cc, line 1442 at r3 (raw file):
{}
Since you're in here, you can remove the empty braces for the empty params.
google/cloud/spanner/samples/samples.cc, line 1491 at r3 (raw file):
"UPDATE Albums SET MarketingBudget = MarketingBudget * 2" " WHERE SingerId = 1 AND AlbumId = 1", {}));
Please remove the empty params braces.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewable status: 2 of 3 files reviewed, 4 unresolved discussions (waiting on @coryan and @devbww)
google/cloud/spanner/samples/samples.cc, line 1257 at r1 (raw file):
Previously, coryan (Carlos O'Ryan) wrote…
I would prefer if we kept them, they avoid questions around "What is this
spanner::
namespace? The audience for these snippets are folks that may have never used our libraries before.
Done.
google/cloud/spanner/samples/samples.cc, line 1501 at r1 (raw file):
Previously, devjgm (Greg Miller) wrote…
If not, then maybe the type of
dml_result
should drop the StatusOr part to indicate that it can never fail.
If the user chooses to call ProfileDml without using a Commit "transaction runner", then it could fail. For this particular implementation, it likely will not ever fail, but as this is example code, I figured checking was the thorough thing to do.
google/cloud/spanner/samples/samples.cc, line 1432 at r3 (raw file):
Previously, coryan (Carlos O'Ryan) wrote…
See above, please move this up, in fact, consider including the whole function so folks don't wonder where
client
came from.
I think the client is ubiquitous in all snippets as to not cause confusion.
google/cloud/spanner/samples/samples.cc, line 1491 at r3 (raw file):
Previously, devjgm (Greg Miller) wrote…
Please remove the empty params braces.
Removed them in all places in the file where calls to ExecuteDml and ProfileDml was including them.
google/cloud/spanner/samples/samples.cc, line 2177 at r3 (raw file):
Previously, coryan (Carlos O'Ryan) wrote…
What do you think of wrapping these conditionals in a lambda that examples what they do?
auto is_partitionable_ = [](/*replace with actual type*/auto const& plan) { if (plan.plan_nodes().empty()) return false; if (plan.plan_nodes(0).kind() != google::spanner::v1::PlanNode::RELATIONAL) { return false; } if (plan.plan_nodes(0).display_name() != "Distributed Union") { // maybe even print why here... return false; } return true; }; if (!is_partionable(*plan)) throw std::runtime_error(...);
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One item for discussion below, let me know what you think, I could be convinced that I am wrong.
Reviewed 1 of 1 files at r4.
Reviewable status: all files reviewed, 4 unresolved discussions (waiting on @devbww and @scotthart)
google/cloud/spanner/samples/samples.cc, line 1432 at r3 (raw file):
Previously, scotthart (Scott Hart) wrote…
I think the client is ubiquitous in all snippets as to not cause confusion.
FYI, and this is just a thought, but you know that, I know that, and a user that is reading many samples knows that. If this is the first sample they read (or they have not read them in a while) that would come as a complete surprise. I think each sample should stand on its own, but I could be convinced otherwise.
google/cloud/spanner/samples/samples.cc, line 2156 at r4 (raw file):
// `ExecutionPlan` can be partitioned. auto is_partitionable = [](spanner::ExecutionPlan const& plan) { return (plan.plan_nodes(0).kind() ==
nit: the parenthesis are not needed in this return
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewable status: 2 of 3 files reviewed, 4 unresolved discussions (waiting on @coryan, @devbww, @devjgm, and @scotthart)
google/cloud/spanner/samples/samples.cc, line 1501 at r1 (raw file):
Previously, scotthart (Scott Hart) wrote…
If the user chooses to call ProfileDml without using a Commit "transaction runner", then it could fail. For this particular implementation, it likely will not ever fail, but as this is example code, I figured checking was the thorough thing to do.
The observation is not about update
, the result of ProfileDml()
, but dml_result
, the output of the mutator, which is only assigned when the ProfileDml()
(and then the mutator) succeeds.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewable status: 2 of 3 files reviewed, 4 unresolved discussions (waiting on @coryan, @devbww, and @scotthart)
google/cloud/spanner/samples/samples.cc, line 1501 at r1 (raw file):
Previously, devbww (Bradley White) wrote…
The observation is not about
update
, the result ofProfileDml()
, butdml_result
, the output of the mutator, which is only assigned when theProfileDml()
(and then the mutator) succeeds.
Done.
google/cloud/spanner/samples/samples.cc, line 2156 at r4 (raw file):
Previously, coryan (Carlos O'Ryan) wrote…
nit: the parenthesis are not needed in this
return
.
Agreed, I thought it might improve the readability of this multiline, compound conditional.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewed 1 of 1 files at r5.
Reviewable status: all files reviewed, 2 unresolved discussions (waiting on @coryan and @scotthart)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewable status: all files reviewed, 2 unresolved discussions (waiting on @scotthart)
google/cloud/spanner/samples/samples.cc, line 2156 at r4 (raw file):
Previously, scotthart (Scott Hart) wrote…
Agreed, I thought it might improve the readability of this multiline, compound conditional.
Hmmm... Okay.
google/cloud/spanner/samples/samples.cc, line 2154 at r5 (raw file):
// `ExecutionPlan` can be partitioned. auto is_partitionable = [](spanner::ExecutionPlan const& plan) { return (plan.plan_nodes(0).kind() ==
What if plan_nodes()
is empty?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewable status: all files reviewed, 2 unresolved discussions (waiting on @coryan)
google/cloud/spanner/samples/samples.cc, line 1432 at r3 (raw file):
Previously, coryan (Carlos O'Ryan) wrote…
FYI, and this is just a thought, but you know that, I know that, and a user that is reading many samples knows that. If this is the first sample they read (or they have not read them in a while) that would come as a complete surprise. I think each sample should stand on its own, but I could be convinced otherwise.
Seeing as there are both flavors of snippets in this file, can we decide one way or the other if we include the entire function or not? Also, how should we handle situations where one function contains multiple snippets (maybe overlapping maybe not)?
google/cloud/spanner/samples/samples.cc, line 2154 at r5 (raw file):
Previously, coryan (Carlos O'Ryan) wrote…
What if
plan_nodes()
is empty?
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewed 1 of 1 files at r6.
Reviewable status:complete! all files reviewed, all discussions resolved
google/cloud/spanner/samples/samples.cc, line 1432 at r3 (raw file):
Previously, scotthart (Scott Hart) wrote…
Seeing as there are both flavors of snippets in this file, can we decide one way or the other if we include the entire function or not? Also, how should we handle situations where one function contains multiple snippets (maybe overlapping maybe not)?
For me is whether the snippet is self-contained, not whether it is a complete function or not. Though most of the time "whole function" == "self-contained". Having types, functions, or objects appear in a snippet without context (telling you at least what it is) can only lead to confusion.
Let's move this discussion elsewhere, we are just dragging here.
…oogleapis/google-cloud-cpp-spanner#1364) * docs: add snippets for AnalyzeSql and ExecutionPlan docs: updated snippets and samples for profile and analyze methods. * debug query plan * debug query plan * debug query plan * address review comments * address review comments * address review comments * address review comments
This change is![Reviewable](https://camo.githubusercontent.com/1541c4039185914e83657d3683ec25920c672c6c5c7ab4240ee7bff601adec0b/68747470733a2f2f72657669657761626c652e696f2f7265766965775f627574746f6e2e737667)