I use https://github.com/kyleconroy/sqlc
This is a library for generating code.
My query
-- name: SetAssignmentsResult :exec
UPDATE assignments
SET status = 'ACCEPTED',
result = $1
WHERE task_id = $2
AND item_id = $3
AND marker_id = $4;
sqlc generate this code
type SetAssignmentsResultParams struct {
Result pqtype.NullRawMessage `json:"result"`
TaskID uuid.UUID `json:"task_id"`
ItemID uuid.UUID `json:"item_id"`
MarkerID uuid.NullUUID `json:"marker_id"`
}
func (q *Queries) SetAssignmentsResult(ctx context.Context, arg SetAssignmentsResultParams) error {
_, err := q.exec(ctx, q.setAssignmentsResultStmt, setAssignmentsResult,
arg.Result,
arg.TaskID,
arg.ItemID,
arg.MarkerID,
)
return err
}
My code
err := repo.SetResult(ctx,
godb.SetAssignmentsResultParams{
Result: pqtype.NullRawMessage{RawMessage: []byte(`{"test": "0.0.0.0:8080"}`),
Valid: true,
},
TaskID: IDs[0],
ItemID: IDs[1],
MarkerID: uuid.NullUUID{
UUID: IDs[2],
Valid: true,
},
}
Return error: ERROR: invalid input syntax for type json (SQLSTATE 22P02)
Important. If you use an empty json, then everything works
err := repo.SetResult(ctx,
godb.SetAssignmentsResultParams{
pqtype.NullRawMessage{},
IDs[0],
IDs[1],
uuid.NullUUID{IDs[2], true},
},
Related
I wrote simple script to receive all data from wigle api using wigleapiv2, definitely this endpoint /api/v2/network/search. But I faced the problem, that I can receive only 1000 unique ssid's. I'm changing URL every iteration, and put in URL previous page's searchAfter. How can I fix it and receive all data from certain latitude and longitude?
Here an example of first iteration Uri (https://api.wigle.net/api/v2/network/search?closestLat=12.9&closestLong=1.2&latrange1=1.9&latrange2=1.8&longrange1=1.2&longrange2=1.4)
And here an example of remaining iterations uris (https://api.wigle.net/api/v2/network/search?closestLat=12.9&closestLong=1.2&latrange1=1.9&latrange2=1.8&longrange1=1.2&longrange2=1.4&searchAfter=1976621348&first=1). For every iteration I'm changing searchAfter and first.
It would be great id someone can say me where I'm doing wrong:)
I've tried to using only first or search after parameters, but it has the same result. One mark that I noticed, that when I'm using only searchAfter param I can receive only 100 unique ssids, but when I'm using both (searchAfter and first) I can receive 1000 unique ssids.
Here my main.go code
var (
wg = sync.WaitGroup{}
receiveResp = make(chan []*response.WiFiNetworkWithLocation, 100)
)
func main() {
startTime := time.Now()
viper.AddConfigPath(".")
viper.SetConfigFile("config.json")
if err := viper.ReadInConfig(); err != nil {
log.Fatal("error trying read from config: %w", err)
}
u := user.NewUser(viper.GetString("users.user.username"), viper.GetString("users.user.password"))
db, err := postgres.NewPG()
if err != nil {
log.Fatalf("Cannot create postgres connection: %v", err)
}
postgres.WG.Add(1)
go getResponse(u)
go parseResponse(db)
postgres.WG.Wait()
fmt.Printf("Execution time: %v ", time.Since(startTime))
}
func getResponse(u *user.Creds) {
url := fmt.Sprintf("%s? closestLat=%s&closestLong=%s&latrange1=%s&latrange2=%s&longrange1=%s&longrange2=%s",
viper.GetString("wigle.url"),
viper.GetString("queries.closestLat"),
viper.GetString("queries.closestLong"),
viper.GetString("queries.latrange1"),
viper.GetString("queries.latrange2"),
viper.GetString("queries.longrange1"),
viper.GetString("queries.longrange2"),
)
j := 0
i := 0
for {
i++
fmt.Println(url)
req, err := http.NewRequest("GET", url, bytes.NewBuffer([]byte("")))
if err != nil {
log.Printf("Failed wraps request: %v", err)
continue
}
req.SetBasicAuth(u.Username, u.Password)
c := http.Client{}
resp, err := c.Do(req)
if err != nil {
log.Printf("Failed send request: %v", err)
continue
}
bytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Printf("Failed read response body: %v", err)
continue
}
var r response.NetSearchResponse
if err := json.Unmarshal(bytes, &r); err != nil {
log.Printf("Failed unmarshal: %v", err)
continue
}
receiveResp <- r.Results
fmt.Println(r.TotalResults, r.SearchAfter)
if r.SearchAfter == "" {
postgres.WG.Done()
return
}
url = fmt.Sprintf("%s? closestLat=%s&closestLong=%s&latrange1=%s&latrange2=%s&longrange1=%s&longrange2=%s&searchAfter=%s&first=%v" ,
viper.GetString("wigle.url"),
viper.GetString("queries.closestLat"),
viper.GetString("queries.closestLong"),
viper.GetString("queries.latrange1"),
viper.GetString("queries.latrange2"),
viper.GetString("queries.longrange1"),
viper.GetString("queries.longrange2"),
r.SearchAfter,
i,
)
j++
fmt.Println(j)
}
func parseResponse(db *sql.DB) {
for {
select {
case responses := <-receiveResp:
clearResponses := make([]response.WiFiNetworkWithLocation, 0, len(responses))
for _, val := range responses {
clearResponses = append(clearResponses, *val)
}
postgres.WG.Add(1)
go postgres.SaveToDB(db, "test", clearResponses)
}
}
}
I have a list of item type and item numbers like follows:
items := models.ItemKeys{
ItemKeys: []models.ItemKey{
{
ItemType: "type1",
ItemNumber: "10347114",
},
{
ItemType: "type2",
ItemNumber: "40428383",
},
{
ItemType: "type3",
ItemNumber: "90351753",
},
},
}
I would like to produce this kind of query:
SELECT * FROM item
WHERE (item_type, item_number) IN (('type1','10347114'), ('type2','40428383'), ('type3','90351753'))
it is worth mentioning that I'm using pq package (https://github.com/lib/pq). I happen to find there is a way using ANY instead. However, when I try it, it says sql: converting argument $1 type: pq: Unable to convert models.ItemKeys to array
Here is my current code:
rows, err := r.Db.QueryContext(ctx, "SELECT * "+
"FROM item "+
"WHERE (item_type, item_number) = ANY($1) "+
"AND deleted_dtime IS NULL", pq.Array(items))
Does anyone have a clue how to do it correctly?
You could do the following:
inSQL, args := "", []interface{}{}
for i, itemKey := range items.ItemKeys {
n := i * 2
inSQL += fmt.Sprintf("($%d,$%d),", n+1, n+2)
args = append(args, itemKey.ItemType, itemKey.ItemNumber)
}
inSQL = inSQL[:len(inSQL)-1] // drop last ","
query := `SELECT * FROM item WHERE (item_type, item_number) IN (` + inSQL + `) AND deleted_dtime IS NULL`
// query: SELECT * FROM item WHERE (item_type, item_number) IN (($1,$2),($3,$4),($5,$6)) AND deleted_dtime IS NULL
// args: ["type1" "10347114" "type2" "40428383" "type3" "90351753"]
rows, err := r.Db.QueryContext(ctx, query, args...)
// ...
I am new to golang . and I want to get my response as multiple result. I do some method but I need to change that one
impartErrl := ph.profileService.ValidateSchema(gojsonschema.NewStringLoader(string(b)))
if impartErrl != nil {
ctx.JSON(http.StatusBadRequest, impart.ErrorResponse(impartErrl))
return
}
func (ps *profileService) ValidateSchema(document gojsonschema.JSONLoader) (errors []impart.Error) {
result, err := gojsonschema.Validate(ps.schemaValidator, document)
if err != nil {
ps.SugaredLogger.Error(err.Error())
return impart.ErrorResponse(
impart.NewError(impart.ErrBadRequest, "unable to validate schema"),
)
}
if result.Valid() {
return nil
}
// msg := fmt.Sprintf("%v validations errors.\n", len(result.Errors()))
msg := "validations errors"
for i, desc := range result.Errors() {
msg += fmt.Sprintf("%v: %s\n", i, desc)
er := impart.NewError(impart.ErrValidationError, fmt.Sprintf("%s ", desc), impart.ErrorKey(desc.Field()))
errors = append(errors, er)
}
return errors
}
func NewError(err error, msg string, args ...interface{}) Error {
key := GetErrorKey(args...)
return impartError{
err: err,
msg: msg,
key: key,
}
}
func ErrorResponse(err interface{}) []Error {
var errorResponse []Error
switch err.(type) {
case Error:
errorResponse = []Error{err.(Error)}
case []Error:
errorResponse = err.([]Error)
default:
errorResponse = []Error{
NewError(ErrUnknown, fmt.Sprintf("%v", err)),
}
}
return errorResponse
}
type Error interface {
error
HttpStatus() int
ToJson() string
Err() error
Msg() string
}
Now I am getting the output as
[
{
"error": "validation error",
"msg": "email: Does not match format 'email' ",
"key": "email"
},
{
"error": "validation error",
"msg": "screenName: String length must be greater than or equal to 4 ",
"key": "screenName"
}
]
but I require my response as
{
0 :{
"error": "validation error",
"msg": "email: Does not match format 'email' ",
"key": "email"
},
1 : {
"error": "unable to complete the request",
"msg": "invalid screen name, must be alphanumeric characters only",
"key": "screen_name"
}
}
How can I get these type of response. ? because in ios app while parsing the response [] showing error. so I need to change the output.
please help me.
The ErrorResponse func should return a map[int]Error instead of []Error. As Example:
func ErrorResponse(err interface{}) map[int]Error {
errorResponse := map[int]Error{}
switch e := err.(type) {
case Error:
errorResponse[0] = e
case []Error:
for i, k := range e {
errorResponse[i] = k
}
default:
errorResponse[0] = NewError(ErrUnknown, fmt.Sprintf("%v", err))
}
return errorResponse
}
I want to take limit and offset values from my frontend. For that, I have written the following routing path
func (s *Server) stockRoutes() {
s.r.Route("/stock", func(r chi.Router) {
r.Get("/{limit}{offset}", s.ListStocks(s.ctx))
r.Route("/{id}", func(r chi.Router) {
r.Get("/", s.GetStock(s.ctx))
r.Put("/", s.UpdateStockDetails(s.ctx))
})
})
}
I am handling the request in the following fashion. I am parsing the values of limit and offset
func (s *Server) ListStocks(ctx context.Context) http.HandlerFunc {
return func(rw http.ResponseWriter, r *http.Request) {
param, _ := strconv.Atoi(chi.URLParam(r, "limit"))
param2, _ := strconv.Atoi(chi.URLParam(r, "offset"))
limit := int32(param)
offset := int32(param2)
arg := db.ListStocksParams{
Limit: limit,
Offset: offset,
}
stocks, err := s.store.ListStocks(ctx, arg)
if err != nil {
http.Error(rw, "error returning list of stocks", http.StatusInternalServerError)
return
}
log.Printf("%+v", stocks)
json.NewEncoder(rw).Encode(stocks)
}
}
Using postman, I am sending a request in the following way http://localhost:8000/stock?limit=5&offset=0.
Can anyone help me understand what I am doing wrong?
I am new to working with AWS particularly s3. I am using the aws go sdk. I am trying to set bucket life cycle rules in the method below;
func SetLifecycle(svc *s3.S3, bucket , id , status, md5 string) (*s3.PutBucketLifecycleConfigurationOutput, error) {
input := &s3.PutBucketLifecycleConfigurationInput{
Bucket: aws.String(bucket),
LifecycleConfiguration: &s3.BucketLifecycleConfiguration{
Rules: []*s3.LifecycleRule{
{
ID: aws.String(id),
Status: aws.String(status),
},
},
},
}
req, resp := svc.PutBucketLifecycleConfigurationRequest(input)
req.HTTPRequest.Header.Set("Content-Md5", string(md5))
err := req.Send()
return resp, err
}
And calling the above method in a test:
func (suite *HeadSuite) TestLifecycleSet() {
assert := suite
//acl := map[string]string{"Authorization": ""}
bucket := GetBucketName()
err := CreateBucket(svc, bucket)
content := strings.NewReader("Enabled")
h := md5.New()
content.WriteTo(h)
sum := h.Sum(nil)
b := make([]byte, base64.StdEncoding.EncodedLen(len(sum)))
base64.StdEncoding.Encode(b,sum)
md5 := string(b)
_, err = SetLifecycle(svc, bucket, "rule1", "Enabled", md5)
assert.Nil(err)
}
I keep getting an error NotImplemented. Why would this be happening? I had originally not added a content-md5 header which I added after reading the putbucketlifecycle documentation. However , I still get an error.
I did not require calculation of the MD5 header. However, I noticed that I needed to set a prefix, which is specified in the documentation. In addition, what version of the SDK are you using?
Here's a working example below
input := &s3.PutBucketLifecycleConfigurationInput{
Bucket: aws.String(bucket),
LifecycleConfiguration: &s3.BucketLifecycleConfiguration{
Rules: []*s3.LifecycleRule{
{
Prefix: aws.String(prefix),
Status: aws.String(status),
ID: aws.String(id),
Expiration: &s3.LifecycleExpiration{
Days: aws.Int64(1),
},
},
},
},
}
req, resp := svc.PutBucketLifecycleConfigurationRequest(input)
if err := req.Send(); err != nil {
panic(err)
}