How to get the count value from a go-sqlite3 query? - go

I am using go-sqlite3 to retrieve the number of rows with a column of a certain value:
query := "select count(notebook) from pages where notebook="
result, err := db.Query(fmt.Sprint(query, id))
Where id is passed to the function running the query.
How can I retrieve the count value from result?

This should work:
// Output will be stored here.
var output string
id := "1234"
// Prepare your query
query, err := db.Prepare("select count(notebook) from pages where notebook = ?")
if err != nil {
fmt.Printf("%s", err)
}
defer query.Close()
// Execute query using 'id' and place value into 'output'
err = query.QueryRow(id).Scan(&output)
// Catch errors
switch {
case err == sql.ErrNoRows:
fmt.Printf("No notebook with that ID.")
case err != nil:
fmt.Printf("%s", err)
default:
fmt.Printf("Counted %s notebooks\n", output)
}

Related

Does db.Query return ErrNoRows?

I can't seem to get ErrNoRows from my db.query when a sql query is expected to return no results.
results, err := database.Query("SELECT title FROM accountProject WHERE accountID=? AND MATCH(title) AGAINST(?)", accountID, query)
if err != nil {
if err == sql.ErrNoRows {
return errProjectDoesNotExist
}
return err
}
The value sql.ErrNoRows is not returned from DB.Query or DB.QueryContext. The first call to Rows.Next returns false when the result set has no rows.
The value sql.ErrNoRows is returned from a call to Row.Scan on a placeholder row returned from DB.QueryRow or DB.QueryRowContext. The DB.QueryRow* methods return a placeholder row on error instead of returning an error directly.
If the application is looking for zero or one rows, use QueryRow instead of Query.
row := database.QueryRow("SELECT title FROM accountProject WHERE accountID=? AND MATCH(title) AGAINST(?)", accountID, query)
err := row.Scan( .... address of variables here ... )
if err == sql.ErrNoRows {
return errProjectDoesNotExist
} else if err != nil {
return err
}

Reading BigQuery in Golang. Not all expected results are given. What to do?

Given that the SQL is running perfectly in Query Editor. Still after assigning it to a struct, the data seems to have different values. Why is it like that?
var RunQuery = func(req *http.Request, query string)(*bigquery.RowIterator, error){
ctx := appengine.NewContext(req)
ctxWithDeadline, _ := context.WithTimeout(ctx, 30*time.Minute)
bqClient, bqErr := bigquery.NewClient(ctxWithDeadline, project, option.WithCredentialsFile(serviceAccount))
if bqErr != nil {
log.Errorf(ctx, "%v", bqErr)
return nil, bqErr
}
q := bqClient.Query(query)
job, err := q.Run(ctx)
if err != nil {
log.Errorf(ctx, "%v", err)
return nil, err
}
status, err := job.Wait(ctx)
if err != nil {
log.Errorf(ctx, "%v", err)
return nil, err
}
if err := status.Err(); err != nil {
log.Errorf(ctx, "%v", err)
return nil, err
}
it, err := job.Read(ctx)
if err != nil {
log.Errorf(ctx, "%v", err)
return nil, err
}
log.Infof(ctx, "Total Rows: %v", it.TotalRows)
return it, nil
}
type Customers struct {
CustomerName string `bigquery:"customer_name"`
CustomerAge int `bigquery:"customer_age"`
}
var rowsRead int
func main() {
query := `SELECT
name as customer_name,
age as customer_age
FROM customer_table
WHERE customerStatus = '0'`
customerInformation, customerInfoErr := RunQuery(req, query, false)
if customerInfoErr != nil {
log.Errorf(ctx, "Fetching customer information error :: %v", customerInfoErr)
return
}
for {
var row Customers
err := customerInformation.Next(&row)
log.Infof(ctx, "row %v", row)
if err == iterator.Done {
log.Infof(ctx, "ITERATION COMPLETE. Rows read %v", rowsRead)
break
}
rowsRead++
}
}
Let's say i have Query Results of
customer_name|customer_age
cat | 2
dog | 3
horse | 10
But after assigning it to a struct the results was
customer_name|customer_age
"" | 2
dog | ""
"" | ""
Why is it like this? i even tested it on chunk where i set the limit to 1000, still the same results. But the query results in Query Editor is what i expect
Solved it using Value Loader bigquery.Value. Instead of using expected struct in mapping the query results. used map[string]bigquery.Value. Still don't know why mapping query results with expected struct is not working perfectly. Here is my solution.
for {
row := make(map[string]bigquery.Value)
err := customerInformation.Next(&row)
log.Infof(ctx, "row %v", row)
if err == iterator.Done {
log.Infof(ctx, "ITERATION COMPLETE. Rows read %v", rowsRead)
break
}
rowsRead++
}
From the documentation:
If dst is a pointer to a struct, each column in the schema will be matched with an exported field of the struct that has the same name, ignoring the case. Unmatched schema columns and struct fields will be ignored.
cloud.google.com/go/bigquery
Here you try to resolve customer_age to a struct property named CustomerAge. If you update it to Customer_Age or customer_age it should work.

Read BQ query result without struct

Has anybody tried storing result from a query to a map?
I want to able to read data from BQ tables without having the need to define a struct that matches the BQ table schema.
I have tried following https://kylewbanks.com/blog/query-result-to-map-in-golang, but I want to use a RowIterator instead of the approach in this link.
Here's the code I am struggling with:
//Removed error handling for brewity
ctx := context.Background()
client, _ := bigquery.NewClient(ctx, ProjectID)
query := fmt.Sprintf("SELECT * FROM `%s.%s.%s` LIMIT 5;", ProjectID, DatasetId, ResourceName)
queryResult := client.Query(query)
it, _ := queryResult.Read(ctx)
for {
row := make(map[string]bigquery.Value)
err := it.Next(&row)
if err == iterator.Done {
break
}
if err != nil {
fmt.Printf("Error happened")
}}
I am not sure how to proceed after this, I would ideally like to convert the data into a JSON format.
for {
var values []bigquery.Value
err := it.Next(&values)
if err == iterator.Done {
break
}
if err != nil {
// TODO: Handle error.
}
fmt.Println(values)
}
Place rows into slice as you can store a row using anything that implements the ValueLoader interface, or with a slice or map of bigquery.Value
ref: godocs bq

Calling rows.Err() in a multiple result set query with rows.NextResultSet()

I'm building a query with multiple result sets, following the example given, here. Important bits copied below for convenience.
My question is, should rows.Err() be called after each for rows.Next() {...} loop, rather than once at the very end as shown in the example? Why / why not? My understanding is that rows.Err() will catch errors, "... encountered during iteration", whereas rows.NextResultSet() will catch, "... [errors] advancing to [the next result set]". Seems like I would want to catch errors during each iteration, no? Thanks!
rows, err := db.Query(q, age)
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
var (
id int64
name string
)
if err := rows.Scan(&id, &name); err != nil {
log.Fatal(err)
}
fmt.Printf("id %d name is %s\n", id, name)
}
if !rows.NextResultSet() {
log.Fatal("expected more result sets", rows.Err())
}
var roleMap = map[int64]string{
1: "user",
2: "admin",
3: "gopher",
}
for rows.Next() {
var (
id int64
role int64
)
if err := rows.Scan(&id, &role); err != nil {
log.Fatal(err)
}
fmt.Printf("id %d has role %s\n", id, roleMap[role])
}
if err := rows.Err(); err != nil {
log.Fatal(err)
}
You can find from source code of Next or Err or NextResultSet function that there is lasterr member of Rows structure which can be set by several ways and Err always return it if it isn't EOF.
Those ways are:
Next gets some error, sets lasterr and always returns false (so for rows.Next() {... doesn't iterate more and it is enough to check rows.Err() only after the loop.
NextResultSet also sets lasterr whenever it gets error and also returns false.
So answer is yes, it should. Because if NextResultSet after Next returns false its error replaces error from Next.

golang Couchbase n1ql query pass params to?

I'm trying to find a way to pass parameters to query, but not quite sure how. The API on the web site looks a little bit outdated?
myQuery := gocb.NewN1qlQuery("SELECT * FROM default")
rows, err := myBucket.ExecuteN1qlQuery(myQuery)
if err != nil {
fmt.Printf("N1QL query error: %s\n", err)
}
var row interface{}
for rows.Next(&row) {
fmt.Printf("Row: %+v\n", row)
}
if err := rows.Close(); err != nil {
fmt.Printf("N1QL query error: %s\n", err)
}
Because, actually ExecuteN1qlQuery takes two params:
func (b *Bucket) ExecuteN1qlQuery(q *N1qlQuery, params interface{}) (ViewResults, error)
I am not sure just how to use it... Like I would like to create a query with placeholders, and pass values to ExecuteN1qlQuery via params. Like with SQL (prepare -> execute). For example something like that:
myQuery := gocb.NewN1qlQuery("SELECT * FROM default where a=? and b=?")
rows, err := myBucket.ExecuteN1qlQuery(myQuery,[]string{"b","c"})
if err != nil {
fmt.Printf("N1QL query error: %s\n", err)
}
var row interface{}
for rows.Next(&row) {
fmt.Printf("Row: %+v\n", row)
}
if err := rows.Close(); err != nil {
fmt.Printf("N1QL query error: %s\n", err)
}
The example you posted for how to do do this is from our developer guide repo on github:
https://github.com/couchbaselabs/devguide-examples/blob/master/go/query-placeholders.go.
Basically, you're using $ which references an interface and a corresponding positional parameter beginning with 1.
For your example it would look something like:
// Setup a new query with a placeholder
myQuery := gocb.NewN1qlQuery("SELECT * FROM default where a=$1 and b=$2")
// Setup an array for parameters
var myParams []interface{}
myParams = append(myParams,"foo")
myParams = append(myParams,"bar")
// Execute Query
rows, err := bucket.ExecuteN1qlQuery(myQuery, myParams)
if err != nil {
fmt.Println("ERROR EXECUTING N1QL QUERY:", err)
}
// Iterate through rows and print output
var row interface{}
for rows.Next(&row) {
fmt.Printf("Results: %+v\n", row)
}
Just found example
myQuery := gocb.NewN1qlQuery("SELECT airportname, city, country FROM `travel-sample` " +
"WHERE type='airport' AND city=$1 ")
// Setup an array for parameters
var myParams []interface{}
myParams = append(myParams, "Reno")
// Execute Query
rows, err := bucket.ExecuteN1qlQuery(myQuery, myParams)

Resources