Skip to content

Commit 710be90

Browse files
andref5andrefarinaengdb
authored andcommitted
feat: add table-format arg to sql command
1 parent 87489b8 commit 710be90

2 files changed

Lines changed: 152 additions & 21 deletions

File tree

cbt.go

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -870,9 +870,18 @@ var commands = []struct {
870870
Name: "sql",
871871
Desc: "Execute a SQL query on an Instance",
872872
do: doSql,
873-
Usage: "cbt sql <QUERY>\n\n" +
874-
"See https://cloud.google.com/bigtable/docs/reference/sql/googlesql-reference-overview for more information.\n" +
875-
"Note that this does not support parameterized queries.\n",
873+
Usage: "cbt sql <QUERY> [args ...]\n\n" +
874+
" table-format=<true|false> Whether to return the results in a table format (Default: true)\n\n" +
875+
" Examples:\n" +
876+
" cbt sql 'SELECT cell_data[\"os_build\"] as os_build, cell_data[\"os_name\"] as os_name FROM mobile-time-series LIMIT 10'\n" +
877+
" cbt sql 'SELECT FORMAT(\"%s,%s,%s\",\n" +
878+
" SAFE_CONVERT_BYTES_TO_STRING(cell_data[\"os_build\"]),\n" +
879+
" SAFE_CONVERT_BYTES_TO_STRING(cell_data[\"os_name\"]),\n" +
880+
" SAFE_CONVERT_BYTES_TO_STRING(cell_data[\"os_version\"])\n" +
881+
" ) AS osBuild_osName_osVersion\n" +
882+
" FROM mobile-time-series' table-format=false\n\n" +
883+
" See https://cloud.google.com/bigtable/docs/reference/sql/googlesql-reference-overview for more information.\n" +
884+
" Note that this does not support parameterized queries.\n",
876885
Required: ProjectAndInstanceRequired,
877886
},
878887
}
@@ -2057,8 +2066,8 @@ func getFormattedValue(row bigtable.ResultRow, index int) (string, error) {
20572066
}
20582067

20592068
func doSql(ctx context.Context, args ...string) {
2060-
if len(args) != 1 {
2061-
log.Fatalf("usage: cbt sql <QUERY>")
2069+
if len(args) < 1 {
2070+
log.Fatalf("usage: cbt sql <QUERY> [args ...]")
20622071
}
20632072
query := args[0]
20642073

@@ -2071,6 +2080,17 @@ func doSql(ctx context.Context, args ...string) {
20712080
if err != nil {
20722081
log.Fatalf("While binding statement: %v", err)
20732082
}
2083+
parsed, err := parseArgs(args[1:], []string{"table-format"})
2084+
if err != nil {
2085+
log.Fatal(err)
2086+
}
2087+
tableFormat := true
2088+
if tableFormatStr := parsed["table-format"]; tableFormatStr != "" {
2089+
tableFormat, err = strconv.ParseBool(tableFormatStr)
2090+
if err != nil {
2091+
log.Fatal(err)
2092+
}
2093+
}
20742094

20752095
// Execute the query, writing the result into the table util.
20762096
table := tablewriter.NewWriter(os.Stdout)
@@ -2079,13 +2099,24 @@ func doSql(ctx context.Context, args ...string) {
20792099
table.SetAlignment(tablewriter.ALIGN_LEFT)
20802100
table.SetAutoWrapText(false)
20812101

2102+
var headerSeen bool
20822103
boundStmt.Execute(ctx, func(row bigtable.ResultRow) bool {
2083-
// Okay to output the header multiple times, only the first one has an effect.
20842104
hs := make([]string, len(row.Metadata.Columns))
2085-
for i := 0; i < len(row.Metadata.Columns); i++ {
2086-
hs[i] = row.Metadata.Columns[i].Name
2105+
if !headerSeen {
2106+
for i := 0; i < len(row.Metadata.Columns); i++ {
2107+
hs[i] = row.Metadata.Columns[i].Name
2108+
if !tableFormat {
2109+
fmt.Print(hs[i])
2110+
}
2111+
}
2112+
}
2113+
if !headerSeen {
2114+
table.SetHeader(hs)
2115+
if !tableFormat {
2116+
fmt.Print("\n")
2117+
}
2118+
headerSeen = true
20872119
}
2088-
table.SetHeader(hs)
20892120

20902121
// Write out all values in the table.
20912122
vs := make([]string, len(row.Metadata.Columns))
@@ -2095,11 +2126,19 @@ func doSql(ctx context.Context, args ...string) {
20952126
log.Fatalf("Could not get formatted value for column %v: %v", row.Metadata.Columns[i], err)
20962127
}
20972128
vs[i] = v
2129+
if !tableFormat {
2130+
fmt.Print(v)
2131+
}
20982132
}
20992133
table.Append(vs)
2134+
if !tableFormat {
2135+
fmt.Print("\n")
2136+
}
21002137
return true
21012138
})
2102-
table.Render()
2139+
if tableFormat {
2140+
table.Render()
2141+
}
21032142
}
21042143

21052144
func doSampleRowKeys(ctx context.Context, args ...string) {

cbtdoc.go

Lines changed: 103 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
//go:generate go run cbt.go gcpolicy.go cbtconfig.go valueformatting.go -o cbtdoc.go doc
1818

1919
/*
20-
The `cbt` CLI is a command-line interface that lets you interact with Cloud Bigtable.
20+
The `cbt` CLI is a command-line interface that lets you interact with Bigtable.
2121
See the [cbt CLI overview](https://cloud.google.com/bigtable/docs/cbt-overview) to learn how to install the `cbt` CLI.
2222
Before you use the `cbt` CLI, you should be familiar with the [Bigtable overview](https://cloud.google.com/bigtable/docs/overview).
2323
@@ -30,6 +30,7 @@ Usage:
3030
3131
The commands are:
3232
33+
addtocell Add a value to an aggregate cell (write)
3334
count Count rows in a table
3435
createappprofile Create app profile for an instance
3536
createcluster Create a cluster in the configured instance
@@ -57,12 +58,16 @@ The commands are:
5758
notices Display licence information for any third-party dependencies
5859
read Read rows
5960
set Set value of a cell (write)
60-
addtocell Add a value to an aggregate cell (write)
61+
checkandmutate Set a value based on the presence of any cell that matches the constraints
62+
readmodifywrite Update a cell with incremental operations based on the latest value of the cell
6163
setgcpolicy Set the garbage-collection policy (age, versions) for a column family
64+
setvaluetype Update column family's value type.
6265
updateappprofile Update app profile for an instance
6366
updatecluster Update a cluster in the configured instance
6467
version Print the current cbt version
6568
waitforreplication Block until all the completed writes have been replicated to all the clusters
69+
samplerowkeys Sample the row keys in a table
70+
sql Execute a SQL query on an Instance
6671
6772
The options are:
6873
@@ -79,8 +84,8 @@ Example: cbt -instance=my-instance ls
7984
8085
Use "cbt help \<command>" for more information about a command.
8186
82-
Preview features are not currently available to most Cloud Bigtable customers. Alpha
83-
features might be changed in backward-incompatible ways and are not recommended
87+
Preview features are not available to most Bigtable customers, they
88+
might be changed in backward-incompatible ways and are not recommended
8489
for production use. They are not subject to any SLA or deprecation policy.
8590
8691
Syntax rules for the Bash shell apply to the `cbt` CLI. This means, for example,
@@ -104,6 +109,23 @@ options to your ~/.cbtrc file in the following format:
104109
105110
All values are optional and can be overridden at the command prompt.
106111
112+
Add a value to an aggregate cell (write)
113+
114+
Usage:
115+
116+
cbt addtocell <table-id> <row-key> [app-profile=<app-profile-id>] <family>:<column>=<val>[@<timestamp>] ...
117+
118+
app-profile=<app profile id> The app profile ID to use for the request
119+
<family>:<column>=<val>[@<timestamp>] may be repeated to set multiple cells.
120+
121+
If <val> can be parsed as an integer it will be used as one, otherwise the call will fail.
122+
timestamp is an optional integer.
123+
If the timestamp cannot be parsed, '@<timestamp>' will be interpreted as part of the value.
124+
For most uses, a timestamp is the number of microseconds since 1970-01-01 00:00:00 UTC.
125+
126+
Examples:
127+
cbt addtocell table1 user1 sum_cf:col1=1@12345
128+
107129
# Count rows in a table
108130
109131
Usage:
@@ -126,6 +148,7 @@ Usage:
126148
Usage:
127149
128150
cbt createcluster <cluster-id> <zone> <num-nodes> <storage-type>
151+
129152
cluster-id Permanent, unique ID for the cluster in the instance
130153
zone The zone in which to create the cluster
131154
num-nodes The number of nodes to create
@@ -146,6 +169,7 @@ Usage:
146169
Usage:
147170
148171
cbt createinstance <instance-id> <display-name> <cluster-id> <zone> <num-nodes> <storage-type>
172+
149173
instance-id Permanent, unique ID for the instance
150174
display-name Description of the instance
151175
cluster-id Permanent, unique ID for the cluster in the instance
@@ -161,10 +185,11 @@ Usage:
161185
162186
cbt createtable <table-id> [families=<family>:<gcpolicy-expression>:<type-expression>,...]
163187
[splits=<split-row-key-1>,<split-row-key-2>,...]
188+
164189
families Column families and their associated garbage collection (gc) policies and types.
165190
Put gc policies in quotes when they include shell operators && and ||. For gcpolicy,
166191
see "setgcpolicy".
167-
Currently only the type "intsum" is supported.
192+
Types "intsum", "intmin", "intmax", and "inthll" are supported.
168193
splits Row key(s) where the table should initially be split
169194
170195
Example: cbt createtable mobile-time-series "families=stats_summary:maxage=10d||maxversions=1,stats_detail:maxage=10d||maxversions=1" splits=tablet,phone
@@ -198,6 +223,7 @@ Usage:
198223
Usage:
199224
200225
cbt deletecolumn <table-id> <row-key> <family> <column> [app-profile=<app-profile-id>]
226+
201227
app-profile=<app-profile-id> The app profile ID to use for the request
202228
203229
Example: cbt deletecolumn mobile-time-series phone#4c410523#20190501 stats_summary os_name
@@ -223,6 +249,7 @@ Usage:
223249
Usage:
224250
225251
cbt deleterow <table-id> <row-key> [app-profile=<app-profile-id>]
252+
226253
app-profile=<app-profile-id> The app profile ID to use for the request
227254
228255
Example: cbt deleterow mobile-time-series phone#4c410523#20190501
@@ -260,6 +287,7 @@ Usage:
260287
Usage:
261288
262289
cbt import <table-id> <input-file> [app-profile=<app-profile-id>] [column-family=<family-name>] [batch-size=<500>] [workers=<1>] [timestamp=<now|value-encoded>]
290+
263291
app-profile=<app-profile-id> The app profile ID to use for the request
264292
column-family=<family-name> The column family label to use
265293
batch-size=<500> The max number of rows per batch write request
@@ -314,6 +342,7 @@ Usage:
314342
Usage:
315343
316344
cbt lookup <table-id> <row-key> [columns=<family>:<qualifier>,...] [cells-per-column=<n>] [app-profile=<app profile id>]
345+
317346
row-key String or raw bytes. Raw bytes must be enclosed in single quotes and have a dollar-sign prefix
318347
columns=<family>:<qualifier>,... Read only these columns, comma-separated
319348
cells-per-column=<n> Read only this number of cells per column
@@ -351,6 +380,7 @@ Usage:
351380
Usage:
352381
353382
cbt read <table-id> [authorized-view=<authorized-view-id>] [start=<row-key>] [end=<row-key>] [prefix=<row-key-prefix>] [regex=<regex>] [columns=<family>:<qualifier>,...] [count=<n>] [cells-per-column=<n>] [app-profile=<app-profile-id>]
383+
354384
authorized-view=<authorized-view-id> Read from the specified authorized view of the table
355385
start=<row-key> Start reading at this row
356386
end=<row-key> Stop reading before this row
@@ -379,6 +409,7 @@ Set value of a cell (write)
379409
Usage:
380410
381411
cbt set <table-id> <row-key> [authorized-view=<authorized-view-id>] [app-profile=<app-profile-id>] <family>:<column>=<val>[@<timestamp>] ...
412+
382413
authorized-view=<authorized-view-id> Write to the specified authorized view of the table
383414
app-profile=<app profile id> The app profile ID to use for the request
384415
<family>:<column>=<val>[@<timestamp>] may be repeated to set multiple cells.
@@ -391,27 +422,49 @@ Usage:
391422
cbt set mobile-time-series phone#4c410523#20190501 stats_summary:connected_cell=1@12345 stats_summary:connected_cell=0@1570041766
392423
cbt set mobile-time-series phone#4c410523#20190501 stats_summary:os_build=PQ2A.190405.003 stats_summary:os_name=android
393424
394-
Add a value to an aggregate cell (write)
425+
# Set a value based on the presence of any cell that matches the constraints
395426
396427
Usage:
397428
398-
cbt addtocell <table-id> <row-key> [app-profile=<app-profile-id>] <family>:<column>=<val>[@<timestamp>] ...
399-
app-profile=<app profile id> The app profile ID to use for the request
400-
<family>:<column>=<val>[@<timestamp>] may be repeated to set multiple cells.
429+
cbt checkandmutate <table-id> <rowkey> [columns=<family:qualifier>,...] [true=<family>:<column>=<val>[@<timestamp>]] [false=<family>:<column>=<val>[@<timestamp>]]
401430
431+
row-key String or raw bytes. Raw bytes must be enclosed in single quotes and have a dollar-sign prefix
432+
columns=<family>:<qualifier>,... Test for values in these columns, comma-separated (optional)
433+
<family>:<column>=<val>[@<timestamp>] A mutation to set if the lookup returned a cell value
402434
If <val> can be parsed as an integer it will be used as one, otherwise the call will fail.
403435
timestamp is an optional integer.
404436
If the timestamp cannot be parsed, '@<timestamp>' will be interpreted as part of the value.
405437
For most uses, a timestamp is the number of microseconds since 1970-01-01 00:00:00 UTC.
406438
407-
Examples:
408-
cbt addtocell table1 user1 sum_cf:col1=1@12345
439+
At least one or both true=... or false=... must be provided. Optionally columns=... will restrict the existence test to the indicated columns.
440+
441+
Examples:
442+
cbt checkandmutate mobile-time-series phone#4c410523#20190501 false=presence:=1
443+
cbt checkandmutate mobile-time-series phone#4c410523#20190501 columns=stats_summary:os_build true=stats_summary:connected_cell=1@12345
444+
445+
# Update a cell with incremental operations based on the latest value of the cell
446+
447+
Usage:
448+
449+
cbt readmodifywrite <table-id> <rowkey> <family> <qualifier> [append=<val>] [increment=<delta>]
450+
451+
row-key String or raw bytes. Raw bytes must be enclosed in single quotes and have a dollar-sign prefix
452+
family Column family
453+
qualifier Column qualifier
454+
append=<val> Append the given value to the cell
455+
If the cell is unset, it will be treated as an empty value.
456+
increment=<delta> Increment the cell by the given integer delta
457+
If the cell is unset, it will be treated as zero. If the cell is set and is not an 8-byte value, the operation will fail.
458+
459+
Examples:
460+
cbt readmodifywrite mobile-time-series phone#4c410523#20190501 stats_summary boot_count increment=1
409461
410462
# Set the garbage-collection policy (age, versions) for a column family
411463
412464
Usage:
413465
414466
cbt setgcpolicy <table> <family> ((maxage=<d> | maxversions=<n>) [(and|or) (maxage=<d> | maxversions=<n>),...] | never) [force]
467+
415468
force: Optional flag to override warnings when relaxing the garbage-collection policy on replicated clusters.
416469
This may cause your clusters to be temporarily inconsistent, make sure you understand the risks
417470
listed at https://cloud.google.com/bigtable/docs/garbage-collection#increasing
@@ -424,11 +477,23 @@ Usage:
424477
cbt setgcpolicy mobile-time-series stats_detail maxage=10d
425478
cbt setgcpolicy mobile-time-series stats_summary maxage=10d or maxversions=1 force
426479
480+
Update column family's value type.
481+
482+
Usage:
483+
484+
cbt setvaluetype <table> <family> <type>
485+
type: The type to be updated.
486+
Supported type(s): stringutf8bytes: UTF8 encoded string
487+
Updating to or from aggregate types is currently unsupported.
488+
Example:
489+
cbt setvaluetype mobile-time-series vendor-info stringutf8bytes
490+
427491
# Update app profile for an instance
428492
429493
Usage:
430494
431495
cbt updateappprofile <instance-id> <profile-id> <description>(route-any | [ route-to=<cluster-id> : transactional-writes]) [-force]
496+
432497
force: Optional flag to override any warnings causing the command to fail
433498
434499
Example: cbt updateappprofile my-instance multi-cluster-app-profile-1 "Use this one." route-any
@@ -438,6 +503,7 @@ Usage:
438503
Usage:
439504
440505
cbt updatecluster <cluster-id> [num-nodes=<num-nodes>]
506+
441507
cluster-id Permanent, unique ID for the cluster in the instance
442508
num-nodes The new number of nodes
443509
@@ -454,5 +520,31 @@ Usage:
454520
Usage:
455521
456522
cbt waitforreplication <table-id>
523+
524+
# Sample the row keys in a table
525+
526+
Usage:
527+
528+
cbt samplerowkeys <table-id>
529+
530+
# Execute a SQL query on an Instance
531+
532+
Usage:
533+
534+
cbt sql <QUERY> [args ...]
535+
536+
table-format=<true|false> Whether to return the results in a table format (Default: true)
537+
538+
Examples:
539+
cbt sql 'SELECT cell_data["os_build"] as os_build, cell_data["os_name"] as os_name FROM mobile-time-series LIMIT 10'
540+
cbt sql 'SELECT FORMAT("%s,%s,%s",
541+
SAFE_CONVERT_BYTES_TO_STRING(cell_data["os_build"]),
542+
SAFE_CONVERT_BYTES_TO_STRING(cell_data["os_name"]),
543+
SAFE_CONVERT_BYTES_TO_STRING(cell_data["os_version"])
544+
) AS osBuild_osName_osVersion
545+
FROM mobile-time-series' table-format=false
546+
547+
See https://cloud.google.com/bigtable/docs/reference/sql/googlesql-reference-overview for more information.
548+
Note that this does not support parameterized queries.
457549
*/
458550
package main

0 commit comments

Comments
 (0)