I'm trying to query a test keyspace like:
package main
import "fmt"
import _ "github.com/gocql/gocql"
var (
gocql string
)
func main() {
// connect to the cluster
cluster := gocql.NewCluster("127.0.0.1")
cluster.Keyspace = "dbaccess"
session, _ := cluster.CreateSession()
defer session.Close()
if err := session.Query("SELECT name, age FROM people WHERE name='doug'").Scan(&name, &age); err != nil {
log.Fatal(err)
}
fmt.Println(name, age)
}
But I get an error like:
12: gocql.NewCluster undefined (type string has no field or method NewCluster)
Does that mean it's trying to point to the method in the gocql/gocql folder but can't find it, or is the syntax wrong to import stuff or?
I think your problem is that you are declaring a gocql var as a string here:
var (
gocql string
)
You should just remove this and it should resolve that particular issue.
In addition your import statement:
import _ "github.com/gocql/gocql"
Shouldn't include an underscore (_) since you are explicitly using gocql and not just importing for its side effects.
Related
I have a Gorm delete with the returning result:
expirationDate := time.Now().UTC().Add(-(48 * time.hour))
var deletedUsers Users
res := gormDB.WithContext(ctx).
Table("my_users").
Clauses(clause.Returning{Columns: []clause.Column{{Name: "email"}}}).
Where("created_at < ?", expirationDate).
Delete(&deletedUsers)
Now the test with clauses always fails. e.g. :
sqlMock.ExpectExec(`DELETE`)
.WithArgs(expirationDate)
.WillReturnResult(sqlmock.NewResult(1, 1))
Receiving error:
"call to Query 'DELETE FROM "my_users" WHERE created_at < $1 RETURNING "email"' with args [{Name: Ordinal:1 Value:2023-01-18 06:15:34.694274 +0000 UTC}], was not expected, next expectation is: ExpectedExec => expecting Exec or ExecContext which:\n - matches sql: 'DELETE'\n - is with arguments:\n 0 - 2023-01-18 06:15:34.694274 +0000 UTC\n - should return Result having:\n LastInsertId: 1\n RowsAffected: 1"
I tried many other sqlMock expectations, but they have a similar issue.
Also, we don't have a return value in ExpectExec, only in ExpectQuery...
Any chance someone has to test the Gorm query with the Clauses?
I was able to successfully manage what you need. First, let me share the files I wrote, and then I'll walk you through all of the relevant changes. The files are repo.go for production and repo_test.go for the test code.
repo.go
package gormdelete
import (
"context"
"time"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)
type Users struct {
Email string
}
func Delete(ctx context.Context, gormDB *gorm.DB) error {
expirationDate := time.Now().UTC().Add(-(48 * time.Hour))
var deletedUsers Users
res := gormDB.WithContext(ctx).Table("my_users").Clauses(clause.Returning{Columns: []clause.Column{{Name: "email"}}}).Where("created_at < ?", expirationDate).Delete(&deletedUsers)
if res.Error != nil {
return res.Error
}
return nil
}
As you didn't provide the full file I tried to guess what was missing.
repo_test.go
package gormdelete
import (
"context"
"database/sql/driver"
"testing"
"time"
"github.com/DATA-DOG/go-sqlmock"
"github.com/stretchr/testify/assert"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
// this is taken directly from the docs
// https://github.com/DATA-DOG/go-sqlmock#matching-arguments-like-timetime
type AnyTime struct{}
// Match satisfies sqlmock.Argument interface
func (a AnyTime) Match(v driver.Value) bool {
_, ok := v.(time.Time)
return ok
}
func TestDelete(t *testing.T) {
db, mock, err := sqlmock.New()
if err != nil {
t.Fatalf("an error was not expected: %v", err)
}
conn, _ := db.Conn(context.Background())
gormDb, err := gorm.Open(postgres.New(postgres.Config{
Conn: conn,
}))
row := sqlmock.NewRows([]string{"email"}).AddRow("test#example.com")
mock.ExpectBegin()
mock.ExpectQuery("DELETE FROM \"my_users\" WHERE created_at < ?").WithArgs(AnyTime{}).WillReturnRows(row)
mock.ExpectCommit()
err = Delete(context.Background(), gormDb)
assert.Nil(t, err)
if err = mock.ExpectationsWereMet(); err != nil {
t.Errorf("not all expectations were met: %v", err)
}
}
Here, there are more changes that it's worth mentioning:
I instantiated the AnyTime as per the documentation (you can see the link in the comment).
Again, I guessed the setup of the db, mock, and gormDb but I think it should be more or less the same.
I switch the usage of ExpectExec to ExpectQuery as we'll have back a result set as specified by the Clauses method in your repo.go file.
You've to wrap the ExpectQuery within an ExpectBegin and an ExpectCommit.
Finally, pay attention to the difference in how the driver expects the parameters in the SQL statement. In the production code, you can choose to use ? or $1. However, in the test code, you can only use the ? otherwise it won't match the expectations.
Hope to help a little bit, otherwise, let me know!
Using Go, when fetching sheet data, the data is arriving with its applied cell formatting
i.e. "$123,456" while I need the original 123456.
is there something in the api that can remove formatting? like formatting: false
code:
package main
import (
"log"
"golang.org/x/net/context"
"golang.org/x/oauth2/google"
"gopkg.in/Iwark/spreadsheet.v2"
)
func main() {
service := authenticate()
spreadsheet, err := service.FetchSpreadsheet(spreadsheetID)
checkError(err)
sheet, err := spreadsheet.SheetByIndex(1)
checkError(err)
for _, row := range sheet.Rows {
var csvRow []string
for _, cell := range row {
csvRow = append(csvRow, cell.Value)
}
log.Println(csvRow)
}
}
// function to authenticate on Google
func authenticate() *spreadsheet.Service {
data, err := ioutil.ReadFile("secret.json")
checkError(err)
conf, err := google.JWTConfigFromJSON(data, spreadsheet.Scope)
checkError(err)
client := conf.Client(context.TODO())
service := spreadsheet.NewServiceWithClient(client)
return service
}
func checkError(err error) {
if err != nil {
panic(err.Error())
}
}
Yes, there is a way. In the Method: spreadsheets.values.get endpoint, there is a request parameter called valueRenderOption, which one of its values is UNFORMATTED_VALUE, as its name suggests, it will give you back all the data without format.
Try this Request with the range of values you want to play around with the API and see in that way the unformatted values it will return.
You want to retrieve $123,456 as 123456 from Google Spreadsheet.
$123,456 is shown by the cell format. It's actually the number.
You want to achieve this using gopkg.in/Iwark/spreadsheet.v2 with golang.
You have already been able to get and put values for Google Spreadsheet using the service account with Sheets API.
If my understanding is correct, how about this answer? Please think of this as just one of several possible answers.
Modification points:
When I saw the script of the library of gopkg.in/Iwark/spreadsheet.v2, I noticed that the values are retrieved by the method of spreadsheets.get in Sheets API.
Furthermore, it was found that spreadsheetId,properties.title,sheets(properties,data.rowData.values(formattedValue,note)) was used as the fields. It seems that the fields is constant.
The reason of your issue is that the values are retrieved with formattedValue. In your case, the values are required to be retrieved with userEnteredValue.
When you want to achieve your goal using the library of gopkg.in/Iwark/spreadsheet.v2, in order to reflect above to the library, it is required to modify the script of library.
Modified script:
Please modify the files of gopkg.in/Iwark/spreadsheet.v2 as follows. Of course, please backup the original files in order to back to the original library.
1. service.go
Modify the line 116 as follows.
From:
fields := "spreadsheetId,properties.title,sheets(properties,data.rowData.values(formattedValue,note))"
To:
fields := "spreadsheetId,properties.title,sheets(properties,data.rowData.values(formattedValue,note,userEnteredValue))"
2. sheet.go
Modify the line 52 as follows.
From:
Value: cellData.FormattedValue,
To:
Value: strconv.FormatFloat(cellData.UserEnteredValue.NumberValue, 'f', 4, 64),
And add "strconv" to import section like below.
import (
"encoding/json"
"strings"
"strconv"
)
3. cell_data.go
Modify the line 8 as follows.
From:
// UserEnteredFormat *CellFormat `json:"userEnteredFormat"`
To:
UserEnteredFormat struct {
NumberValue float64 `json:"numberValue"`
} `json:"userEnteredFormat"`
Result:
In this case, your script is not required to be modified. After above modification, when you run your script, you can see [123456.0000] at the console. As an important point, it seems that this library uses the values as the string type. In this modification, I used this. But if you want to use it as other type, please modify the library.
Other pattern:
As the other pattern for achieving your goal, how about using google-api-go-client? About this, you can see it at Go Quickstart. When google-api-go-client is used, the sample script becomes as follows. In this case, as a test case, the method of spreadsheets.get was used.
Sample script 1:
In this sample script, authenticate() and checkError() in your script are used by modifying.
package main
import (
"fmt"
"io/ioutil"
"net/http"
"golang.org/x/net/context"
"golang.org/x/oauth2/google"
"google.golang.org/api/sheets/v4"
)
func main() {
c := authenticate()
sheetsService, err := sheets.New(c)
checkError(err)
spreadsheetId := "###" // Please set the Spreadsheet ID.
ranges := []string{"Sheet1"} // Please set the sheet name.
resp, err := sheetsService.Spreadsheets.Get(spreadsheetId).Ranges(ranges...).Fields("sheets.data.rowData.values.userEnteredValue").Do()
checkError(err)
for _, row := range resp.Sheets[0].Data[0].RowData {
for _, col := range row.Values {
fmt.Println(col.UserEnteredValue)
}
}
}
func authenticate() *http.Client {
data, err := ioutil.ReadFile("serviceAccount_20190511.json")
checkError(err)
conf, err := google.JWTConfigFromJSON(data, sheets.SpreadsheetsScope)
checkError(err)
client := conf.Client(context.TODO())
return client
}
func checkError(err error) {
if err != nil {
panic(err.Error())
}
}
Sample script 2:
When spreadsheets.values.get is used, the script of main() is as follows.
func main() {
c := authenticate()
sheetsService, err := sheets.New(c)
checkError(err)
spreadsheetId := "###" // Please set the Spreadsheet ID.
sheetName := "Sheet1" // Please set the sheet name.
resp, err := sheetsService.Spreadsheets.Values.Get(spreadsheetId, sheetName).ValueRenderOption("UNFORMATTED_VALUE").Do()
checkError(err)
fmt.Println(resp.Values)
}
Here, UNFORMATTED_VALUE is used for retrieving the values without the cell format. This has already been answered by alberto vielma
References:
Method: spreadsheets.get
google-api-go-client
Go Quickstart
Method: spreadsheets.values.get
If I misunderstood your question and this was not the direction you want, I apologize.
import "go.mongodb.org/mongo-driver/bson"
import "go.mongodb.org/mongo-driver/bson/primitive"
import "go.mongodb.org/mongo-driver/mongo"
import "go.mongodb.org/mongo-driver/mongo/options"
func count() int{
collection := client.Database("thepolyglotdeveloper").Collection("people")
filter := bson.M{"sig": bson.M{ "$eq": "sdfsdf" }}//iv.Sig
cur,_ := collection.Find(context.TODO(), filter)
count,_ := collection.Count(context.TODO(), filter)
return count
}
func main(){
ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")
client, _ = mongo.Connect(ctx, clientOptions)
.....
}
The error received:-
# command-line-arguments
./example.go:131:23: collection.Count undefined (type *mongo.Collection has no field or method Count)
I believe that I am not using the correct method for the count. I am using it to find out is there any record the preexists with the filter in the database. Please suggest.
count,_ := collection.Count(context.TODO(), filter)
Is it the correct usage.
EstimatedDocumentCount and CountDocuments are the methods used to get the number of documents in the collection.
Refer General documentation for the MongoDB Go Driver to find out the available functions:
https://godoc.org/go.mongodb.org/mongo-driver/mongo
I want to perform an atomic transaction in redis using golang. How to do that ? What is the difference b/w Pileline and TxPieline and how to solve the problem using them.
I have visited the following link:
https://godoc.org/gopkg.in/redis.v5#example-Client-TxPipeline
But explanation is not elaborate.
Code from one of the examples from the library on how to use transaction.
package main
import (
"fmt"
"time"
"github.com/go-redis/redis"
)
var redisdb *redis.Client
func main() {
var incr *redis.IntCmd
_, err := redisdb.Pipelined(func(pipe redis.Pipeliner) error {
incr = pipe.Incr("pipelined_counter")
pipe.Expire("pipelined_counter", time.Hour)
return nil
})
fmt.Println(incr.Val(), err)
}
I'm trying to connect Golang with an AS/400 DB2 Database, i have iSeries Access Driver Installed on the machine, this is the code by now:
package main
import (
"odbc"
)
func main() {
conn, _ := odbc.Connect("DSN=DSN/SCHEME;UID=USER;PWD=PASS")
stmt, _ := conn.Prepare("SELECT * FROM SCHEME.TABLE")
stmt.Execute()
rows, _ := stmt.FetchAll()
for i, row := range rows {
println(i, row)
}
stmt.Close()
conn.Close()
}
I was able to do this using Python with a DSN-Less configuration on the ODBC driver with something like this:
con = pyodbc.connect('DRIVER=iSeries Access ODBC Driver;SYSTEM=DSN;UID=USR;PWD=PASS;DBQ=PRUEBA')
I tried on Golang with odbc, mgodbc and db2cli, always getting an invalid memory address or nil pointer dereference error.
Any help is appreciated, Thanks!
Update –
bitbucket.org/phiggins/db2cli is now listed on https://github.com/golang/go/wiki/SQLDrivers
We're using bitbucket.org/phiggins/db2cli, which is based off of the greatcode.google.com/p/odbc library, and it's been working great!
package main
import (
"database/sql"
"log"
"time"
_ "bitbucket.org/phiggins/db2cli"
)
func main() {
db, err := sql.Open("db2-cli", "DATABASE=testdb; HOSTNAME=db2.domain.com; PORT=1234; PROTOCOL=TCPIP; UID=user1; PWD=password1;")
if err != nil {
log.Fatalln(err)
}
defer db.Close()
var t time.Time
row := db.QueryRow("SELECT current date FROM sysibm.sysdummy1;")
err = row.Scan(&t)
if err != nil {
log.Fatalln(err)
}
log.Println(t)
}
I managed to get it working, first, you need to install mgodbc go package:
go get bitbucket.org/miquella/mgodbc
To install this package you must have a working MinGW installation with gcc on your path (Windows), if you use Linux you should have gcc by installed by default.
Then, using this code i got it working:
package main
import (
_ "bitbucket.org/miquella/mgodbc"
"fmt"
"os"
"database/sql"
)
var (
db *sql.DB
checkError = func(err error, num int) {
if err != nil {
fmt.Println(err, num)
os.Exit(1)
}
}
)
func main() {
// Replace the DBQ value with the name of your ODBC data source.
db, err := sql.Open("mgodbc", "DRIVER=iSeries Access ODBC Driver;SYSTEM=HOSTNAME;UID=USER;PWD=PASS;DBQ=SCHEMA")
checkError(err,1)
rows, err := db.Query("SELECT * FROM TABLE")
checkError(err,2)
for rows.Next(){
fmt.Println(rows)
}
defer rows.Close()
defer db.Close()
}
The only thing missing here, is that sql Go package doesn't cast the Query to String, then you get weird codes when querying, now i'm looking to solve that.
I'm using Go + https://bitbucket.org/phiggins/db2cli.
This go lib for DB2 is using the DB2 CLI driver, that I found here and configured as described on phiggins page: http://public.dhe.ibm.com/ibmdl/export/pub/software/data/db2/drivers/odbc_cli/
Here is my code:
package main
import (
"fmt"
_ "bitbucket.org/phiggins/db2cli"
"database/sql"
"log"
"time"
)
func main() {
// JDBC conn string = jdbc:as400://127.0.0.1/;libraries=MYCUSTOM,hhpgm,trk35null,GX,TRK35B5ptf,TRK35B5PG,IFWMS,INTERTRK;user=MYUSER;password=MYPASS;naming=system;block criteria="0"
db, err := sql.Open("db2-cli", "DATABASE=MYCUSTOM; HOSTNAME=127.0.0.1; UID=MYUSER; PWD=MYPASS;")
if err != nil {
log.Fatalln(err)
}
defer db.Close()
var t time.Time
row := db.QueryRow("SELECT current date FROM SYSIBM.SYSDUMMY1;")
err = row.Scan(&t)
if err != nil {
log.Fatalln(err)
}
log.Println(t)
}
But I'm not being able to connect.
The error that I'm receiving is:
$ go run main.go
2016/10/27 18:07:46 SQLDriverConnect: {08001} [IBM][CLI Driver] SQL30081N A communication error has been detected. Communication protocol being used: "TCP/IP". Communication API being used: "SOCKETS". Location where the error was detected: "127.0.0.1". Communication function detecting the error: "connect". Protocol specific error code(s): "61", "*", "*". SQLSTATE=08001
exit status 1
I'm on mac, so I identified that the "protocol specific error code" 61 is "#define ECONNREFUSED 61 /* Connection refused */" according to:
http://opensource.apple.com//source/xnu/xnu-1456.1.26/bsd/sys/errno.h
However, I can connect using a SQL client and a JDBC driver.
So, the question is, how can I convert the JDBC connection string to the format expected by the DB2 CLI driver?
JDBC connection string: jdbc:as400://127.0.0.1/;libraries=MYCUSTOM,hhpgm,trk35null,GX,TRK35B5ptf,TRK35B5PG,IFWMS,INTERTRK;user=MYUSER;password=MYPASS;naming=system;block criteria="0"
CLI connection string: "HOSTNAME=127.0.0.1; UID=MYUSER; PWD=MYPASS;"
Vanessa, you might need to define the value of the port for your connection string. I not sure what is the default port value so just put it in there to be safe.
Have you tried the golang driver available for Db2?
https://github.com/ibmdb/go_ibm_db