github.com/mailru/activerecord@v1.12.2/internal/pkg/generator/tmpl/tarantool/main.tmpl (about) 1 package {{ .ARPkg }} 2 3 import ( 4 "bytes" 5 "context" 6 "fmt" 7 "log" 8 {{ if eq .Server.Conf "" -}} 9 "time" 10 {{ end }} 11 "strings" 12 13 "github.com/mailru/activerecord/pkg/activerecord" 14 "github.com/mailru/activerecord/pkg/tarantool" 15 tarantool2 "github.com/tarantool/go-tarantool" 16 "gopkg.in/vmihailenco/msgpack.v2" 17 18 {{- range $ind, $imp := .Imports }} 19 {{ if ne $imp.ImportName "" }}{{ $imp.ImportName }} {{ end }}"{{ $imp.Path }}" 20 {{- end }} 21 {{- range $i, $imp := addImport .FieldList }} 22 "{{ $imp }}" 23 {{- end }} 24 ) 25 26 {{ $pkgName := .ARPkg }} 27 {{ $serializers := .Serializers -}} 28 {{ $mutators := .Mutators -}} 29 {{ $PublicStructName := .ARPkgTitle -}} 30 {{ $LinkedObject := .LinkedObject }} 31 {{ $flags := .Flags }} 32 {{ $fields := .FieldList }} 33 {{ $procfields := .ProcOutFieldList }} 34 {{ $procInLen := len .ProcInFieldList }} 35 {{ $mutatorLen := len .Mutators }} 36 37 {{ if $fields }} 38 39 type {{ $PublicStructName }} struct { 40 tarantool.BaseField 41 {{- range $ind, $fstruct := .FieldList -}} 42 {{ $rtype := $fstruct.Format -}} 43 {{ $serlen := len $fstruct.Serializer -}} 44 {{ if ne $serlen 0 -}} 45 {{ $sname := index $fstruct.Serializer 0 -}} 46 {{ $serializer := index $serializers $sname -}} 47 {{ $rtype = $serializer.Type -}} 48 {{ end }} 49 field{{ $fstruct.Name }} {{ $rtype -}} 50 {{ end }} 51 } 52 53 const ( 54 namespace = "{{ .Container.ObjectName }}" 55 cntFields uint32 = {{ len .FieldList }} 56 {{- range $fieldname, $flag := .Flags -}} 57 {{ range $i, $flagname := $flag.Flags }} 58 {{ $fieldname }}{{ $flagname }}Flag = 1 << {{ $i -}} 59 {{ end -}} 60 {{ end }} 61 ) 62 63 {{ if eq .Server.Conf "" -}} 64 var boxOption, _ = tarantool.NewOptions( 65 "{{ .Server.Host }}:{{ .Server.Port }}", 66 activerecord.ModeMaster, 67 tarantool.WithTimeout(time.Millisecond * {{ .Server.Timeout }}), 68 ) 69 70 var optionCreator = func(sic activerecord.ShardInstanceConfig) (activerecord.OptionInterface, error) { 71 return boxOption, nil 72 } 73 74 var clusterInfo = activerecord.NewClusterInfo( 75 activerecord.WithShard([]activerecord.OptionInterface{boxOption}, []activerecord.OptionInterface{}), 76 ) 77 {{ end }} 78 var cfgName = "{{.Server.Conf }}" 79 80 func New(ctx context.Context) *{{ $PublicStructName }} { 81 newObj := {{ $PublicStructName }}{} 82 {{- if $fields }} 83 newObj.BaseField.UpdateOps = []tarantool2.Op{} 84 newObj.BaseField.Objects = map[string][]tarantool.ModelStruct{} 85 {{ end }} 86 return &newObj 87 } 88 89 func Create( 90 ctx context.Context, 91 {{- range $ind, $fstruct := .FieldList -}} 92 {{ $rtype := $fstruct.Format -}} 93 {{ $serlen := len $fstruct.Serializer -}} 94 {{ if ne $serlen 0 -}} 95 {{ $sname := index $fstruct.Serializer 0 -}} 96 {{ $serializer := index $serializers $sname -}} 97 {{ $rtype = $serializer.Type -}} 98 {{ end }} 99 v{{ $fstruct.Name }} {{ $rtype -}}, 100 {{- end -}} 101 ) (*{{ $PublicStructName }}, error) { 102 obj := New(ctx) 103 104 {{ range $ind, $fstruct := .FieldList }} 105 if err := obj.Set{{$fstruct.Name}}(v{{$fstruct.Name}}); err != nil { 106 return nil, fmt.Errorf("can't create new {{ $PublicStructName }}: %w", err) 107 } 108 {{ end }} 109 110 return obj, nil 111 } 112 113 func (obj *{{ $PublicStructName }}) packTuple() (any, error) { 114 tuple := make([]any, 0, cntFields) 115 116 var ( 117 v any 118 err error 119 ) 120 121 {{- range $ind, $fstruct := .FieldList -}} 122 {{ $rtype := $fstruct.Format -}} 123 {{ $serlen := len $fstruct.Serializer -}} 124 {{ if ne $serlen 0 }} 125 v, err = Marshal{{ $fstruct.Name }}(obj.field{{ $fstruct.Name }}) 126 if err != nil { 127 return nil, fmt.Errorf("can't pack tuple field '{{ $fstruct.Name }}': %w", err) 128 } 129 {{ else }} 130 v = obj.field{{ $fstruct.Name }} 131 {{ end }} 132 133 tuple = append(tuple, v) 134 {{ end }} 135 136 return tuple, err 137 } 138 139 140 func (obj *{{ $PublicStructName }}) DecodeMsgpack(dec *msgpack.Decoder) error { 141 l, err := dec.DecodeArrayLen() 142 if err != nil { 143 return err 144 } 145 146 if l != int(cntFields) { 147 return fmt.Errorf("unexpected count of fields") 148 } 149 150 {{ range $ind, $fstruct := .FieldList -}} 151 {{ $rtype := $fstruct.Format -}} 152 {{ $sname := $fstruct.Serializer.Name -}} 153 {{ if ne $sname "" -}} 154 {{ $serializer := index $serializers $sname -}} 155 {{ $serparams := $fstruct.Serializer.Params }} 156 var v{{ $fstruct.Name }} {{ $rtype }} 157 if err := dec.Decode(&v{{ $fstruct.Name }}); err != nil { 158 return fmt.Errorf("can't decode '{{ $fstruct.Name }}' field: %w", err) 159 } 160 161 if err := {{ $serializer.ImportName }}.{{ $serializer.Unmarshaler }}({{ $serparams }}v{{ $fstruct.Name }}, &obj.field{{ $fstruct.Name }}); err != nil { 162 return fmt.Errorf("can't unpack '{{ $fstruct.Name }}' field: %w", err) 163 } 164 {{- else }} 165 if err := dec.Decode(&obj.field{{ $fstruct.Name }}); err != nil { 166 return fmt.Errorf("can't decode field '{{ $fstruct.Name }}': %w", err) 167 } 168 {{ end }} 169 {{ end }} 170 171 return nil 172 } 173 174 func (obj *{{ $PublicStructName }}) PrimaryString() string { 175 ret := []string{ 176 {{- range $ind, $fstruct := .FieldList }} 177 {{- if $fstruct.PrimaryKey }} 178 {{- $packerparam := packerParam $fstruct.Format }} 179 {{- $tostr := $packerparam.ToString }} 180 {{ index $tostr 0 }}obj.Get{{ $fstruct.Name }}(){{ index $tostr 1 }}, 181 {{- end }} 182 {{- end }} 183 } 184 185 return strings.Join(ret, ", ") 186 } 187 188 189 {{ $pktype := "" }} 190 {{ $pklenfld := 1 }} 191 {{ $pkind := index .Indexes 0 }} 192 {{ range $num, $ind := .Indexes -}} 193 {{ $lenfld := len $ind.Fields -}} 194 {{ if $ind.Primary }} 195 {{ $pktype = $ind.Type }} 196 {{ $pklenfld = len $ind.Fields }} 197 {{ $pkind = $ind }} 198 func (obj *{{ $PublicStructName }}) Primary() {{ $ind.Type }} { 199 {{ if ne $lenfld 1 }} 200 return {{ $ind.Type }}{ 201 {{- range $_, $fieldNum := $ind.Fields }} 202 {{- $ifield := index $fields $fieldNum }} 203 {{ $ifield.Name }}: obj.Get{{ $ifield.Name }}(), 204 {{- end }} 205 } 206 {{ else }} 207 {{- range $_, $fieldNum := $ind.Fields }} 208 {{- $ifield := index $fields $fieldNum }} 209 return obj.Get{{ $ifield.Name }}() 210 {{- end }} 211 {{ end -}} 212 } 213 214 func (obj *{{ $PublicStructName }}) packPrimary() []any { 215 return []any{ 216 {{- range $_, $fieldNum := $ind.Fields }} 217 {{- $ifield := index $fields $fieldNum }} 218 {{ $rtype := $ifield.Format -}} 219 obj.Get{{ $ifield.Name }}(), 220 {{- end }} 221 } 222 } 223 224 func SelectByPrimary(ctx context.Context, pk {{ $ind.Type }}) (*{{ $PublicStructName }}, error) { 225 return {{ $ind.Selector }}(ctx, pk) 226 } 227 228 {{ end }} 229 {{ end }} 230 231 232 233 {{end}} 234 235 236 // Induces 237 238 {{ range $num, $ind := .Indexes -}} 239 {{ $lenfld := len $ind.Fields -}} 240 {{ if ne $lenfld 1 }} 241 type {{ $ind.Type }} struct { 242 {{- range $_, $fieldNum := $ind.Fields }} 243 {{- $ifield := index $fields $fieldNum }} 244 {{ $rtype := $ifield.Format -}} 245 {{ $serlen := len $ifield.Serializer -}} 246 {{ if ne $serlen 0 -}} 247 {{ $sname := index $ifield.Serializer 0 -}} 248 {{ $serializer := index $serializers $sname -}} 249 {{ $rtype = $serializer.Type -}} 250 {{ end }} 251 {{ $ifield.Name }} {{ $rtype -}} 252 {{- end }} 253 } 254 255 type {{ $ind.Type }}s []{{ $ind.Type }} 256 257 func (idx {{ $ind.Type }}) pack() []any { 258 return []any{ 259 {{- range $_, $fieldNum := $ind.Fields }} 260 {{- $ifield := index $fields $fieldNum }} 261 {{ $rtype := $ifield.Format -}} 262 idx.{{ $ifield.Name }}, 263 {{- end }} 264 } 265 } 266 267 // возвращает предикат для sql запроса формата IN (?,..) OR IN (?,..) и список параметров для него 268 func (idxs {{ $ind.Type }}s) buildSQLPredicateIN() (string, []any) { 269 args := make([]any, 0, len(idxs)) 270 271 var ( 272 buf strings.Builder 273 predicate string 274 ) 275 276 {{- range $_, $fieldNum := $ind.Fields }} 277 {{- $ifield := index $fields $fieldNum }} 278 {{ $rtype := $ifield.Format -}} 279 predicate = tarantool.BuildSQLPredicateIN("{{ $ifield.Name | lowerCase -}}", len(idxs)) 280 buf.WriteString(predicate) 281 282 for _, idx := range idxs { 283 args = append(args, idx.{{ $ifield.Name }}) 284 } 285 286 buf.WriteString(" AND ") 287 {{ end }} 288 289 buf.WriteString(" 1 = 1 ") 290 291 return buf.String(), args 292 } 293 {{- else -}} 294 {{ $ifld := index $ind.Fields 0 }} 295 {{ $ifield := index $fields $ifld }} 296 type {{ $ind.Name }}s []{{ $ind.Type }} 297 298 func (idxs {{ $ind.Name }}s) buildSQLPredicateIN() (string, []any) { 299 args := make([]any, 0, len(idxs)) 300 for _, key := range idxs { 301 args = append(args, key) 302 } 303 304 return tarantool.BuildSQLPredicateIN("{{ $ifield.Name | lowerCase -}}", len(idxs)), args 305 } 306 {{ end }} 307 308 func {{ $ind.Selector }}s(ctx context.Context, keys []{{ $ind.Type }}{{ if not $ind.Unique }}, limiter activerecord.SelectorLimiter{{ end }}) ([]*{{ $PublicStructName }}, error) { 309 ctx = activerecord.Logger().SetLoggerValueToContext(ctx, map[string]interface{}{"{{ $ind.Selector }}s": keys, "Repo": "{{ $PublicStructName }}"}) 310 311 inPredicate, args := {{ if ne $lenfld 1 -}} {{ $ind.Type }} {{- else }} {{ $ind.Name }} {{- end }}s(keys).buildSQLPredicateIN() 312 313 return executeSQL(ctx, "SELECT * FROM \"" + namespace + "\" WHERE " + inPredicate, args) 314 } 315 316 func {{ $ind.Selector }}(ctx context.Context, key {{ $ind.Type }}{{ if not $ind.Unique }}, limiter activerecord.SelectorLimiter{{ end }}) ({{ if $ind.Unique }}{{ else }}[]{{ end }}*{{ $PublicStructName }}, error) { 317 ctx = activerecord.Logger().SetLoggerValueToContext(ctx, map[string]interface{}{"{{ $ind.Selector }}": key, "Repo": "{{ $PublicStructName }}"}) 318 319 {{ if $ind.Unique }} 320 limiter := activerecord.EmptyLimiter() 321 {{ end }} 322 selected, err := selectBox(ctx, {{$ind.Num}}, {{ if ne $lenfld 1 -}} key.pack() {{- else }} []any{key} {{- end }}, tarantool2.IterEq, limiter) 323 if err != nil { 324 return nil, err 325 } 326 327 {{ if $ind.Unique -}} 328 if len(selected) > 0 { 329 if len(selected) > 1 { 330 activerecord.Logger().Error(ctx, "{{ $PublicStructName }}", "More than one tuple for uniq key ID '%s': %d", key, len(selected)) 331 } 332 333 return selected[0], nil 334 } 335 336 return nil, nil 337 {{- else }} 338 339 return selected, nil 340 {{- end }} 341 } 342 343 344 {{ end }} 345 // End Induces 346 347 348 // linked objects 349 {{ range $name, $fobj := .FieldObject -}} 350 {{ $linkedobj := index $LinkedObject $fobj.ObjectName }} 351 func (obj *{{ $PublicStructName }}) Get{{ $name }}(ctx context.Context) ({{ if not $fobj.Unique }}[]{{ end }}*{{ $linkedobj.Namespace.PackageName }}.{{ $linkedobj.Namespace.PublicName }}, error){ 352 {{- if $fobj.Unique }} 353 if ret, ok := obj.BaseField.Objects["{{ $name }}"]; ok && len(ret) == 1 { 354 return ret[0].(*{{ $linkedobj.Namespace.PackageName }}.{{ $linkedobj.Namespace.PublicName }}), nil 355 } 356 357 ret, err := {{ $linkedobj.Namespace.PackageName }}.SelectBy{{ $fobj.Key }}(ctx, obj.Get{{ $fobj.Field }}()) 358 if err != nil { 359 return nil, err 360 } 361 362 obj.BaseField.Objects["{{ $name }}"] = []tarantool.ModelStruct{ret} 363 {{- else }} 364 365 var ret []*{{ $linkedobj.Namespace.PackageName }}.{{ $linkedobj.Namespace.PublicName }} 366 367 if retI, ok := obj.BaseField.Objects["{{ $name }}"]; ok && len(retI) > 0 { 368 for _, ri := range retI { 369 ret = append(ret, ri.(*{{ $linkedobj.Namespace.PackageName }}.{{ $linkedobj.Namespace.PublicName }})) 370 } 371 372 return ret, nil 373 } 374 375 ret, err := {{ $linkedobj.Namespace.PackageName }}.SelectBy{{ $fobj.Key }}(ctx, obj.Get{{ $fobj.Field }}(), activerecord.NewLimiter(100)) //ToDo default limit for multi object 376 if err != nil { 377 return nil, err 378 } 379 380 if len(ret) == 100 { 381 activerecord.Logger().Warn(ctx, "limit for multiple linked object riched '{{ $linkedobj.Namespace.PackageName }}.{{ $linkedobj.Namespace.PublicName }}' '{{ $PublicStructName }}'") 382 } 383 384 for _, r := range ret { 385 obj.BaseField.Objects["{{ $name }}"] = append(obj.BaseField.Objects["{{ $name }}"], r) 386 } 387 {{- end }} 388 389 return ret, nil 390 } 391 392 {{ end -}} 393 // End linked objects 394 395 396 // Getters,Setters and Mutators 397 398 {{ range $ind, $fstruct := .FieldList -}} 399 {{ $rtype := $fstruct.Format -}} 400 {{ $sname := $fstruct.Serializer.Name -}} 401 {{ if ne $sname "" -}} 402 {{ $serializer := index $serializers $sname -}} 403 {{ $rtype = $serializer.Type -}} 404 func Marshal{{ $fstruct.Name }}({{ $fstruct.Name }} {{ $rtype }}) (any, error) { 405 {{ $serparams := $fstruct.Serializer.Params -}} 406 pvar, err := {{ $serializer.ImportName }}.{{ $serializer.Marshaler }}({{ $serparams }}{{ $fstruct.Name }}) 407 if err != nil { 408 return nil, fmt.Errorf("error marshal field {{ $fstruct.Name }}: %w", err) 409 } 410 411 return pvar, nil 412 } 413 414 {{ end -}} 415 416 func (obj *{{ $PublicStructName }}) Get{{ $fstruct.Name }}() {{ $rtype }} { 417 return obj.field{{ $fstruct.Name }} 418 } 419 420 func (obj *{{ $PublicStructName }}) Set{{ $fstruct.Name }}({{ $fstruct.Name }} {{ $rtype }}) error { 421 {{- if $fstruct.PrimaryKey }} 422 if obj.BaseField.Exists { 423 return fmt.Errorf("can't modify field included in primary key") 424 } 425 426 {{ end -}} 427 428 {{ if ne $sname "" -}} 429 {{ $serializer := index $serializers $sname -}} 430 {{ $serparams := $fstruct.Serializer.Params -}} 431 data, err := {{ $serializer.ImportName }}.{{ $serializer.Marshaler }}({{ $serparams }}{{ $fstruct.Name }}) 432 if err != nil { 433 return fmt.Errorf("error marshal field {{ $fstruct.Name }}: %w", err) 434 } 435 {{- else }} 436 data := {{ $fstruct.Name }} 437 {{ end }} 438 439 {{- if eq $fstruct.Format "string" "[]byte" -}} 440 {{- if gt $fstruct.Size 0 }} 441 442 if len(data) > {{ $fstruct.Size }} { 443 return fmt.Errorf("max length of field '{{ $PublicStructName }}.{{ $fstruct.Name }}' is '%d' (received '%d')", {{ $fstruct.Size }}, len(data)) 444 } 445 {{- else }} 446 447 logger := activerecord.Logger() 448 449 logger.Warn(context.TODO(), "{{ $PublicStructName }}", obj.PrimaryString(), fmt.Sprintf("Size for field '{{ $fstruct.Name }}' not set. Cur field size: %d. Object: '{{ $PublicStructName }}'", len(data))) 450 {{- end }} 451 {{- end }} 452 453 obj.BaseField.UpdateOps = append(obj.BaseField.UpdateOps, tarantool2.Op{"=", {{ $ind }}, data }) 454 obj.field{{ $fstruct.Name }} = {{ $fstruct.Name}} 455 456 {{- if ne $fstruct.ObjectLink "" }} 457 delete(obj.BaseField.Objects, "{{ $fstruct.ObjectLink }}") 458 {{- end }} 459 460 return nil 461 } 462 463 {{- range $i, $mut := $fstruct.Mutators -}} 464 {{ $customMutator := index $mutators $mut -}} 465 {{- if $customMutator.Name }} 466 467 {{ range $i, $f := $customMutator.PartialFields }} 468 // Set{{ $customMutator.Name }}{{ $f.Name }} is a stub for backport compatibility 469 func (obj *{{ $PublicStructName }}) Set{{ $customMutator.Name }}{{ $f.Name }}({{ $f.Name }} {{ $f.Type }}) error { 470 pVar := obj.Get{{ $fstruct.Name }}() 471 {{ $underlyingType := trimPrefix (printf "%s" $rtype) "*"}} 472 {{- $isPointer := hasPrefix (printf "%s" $rtype) "*" -}} 473 {{- if $isPointer -}} 474 if pVar == nil { 475 pVar = new({{$underlyingType}}) 476 } 477 {{ end}} 478 479 pVar.{{ $f.Name }} = {{ $f.Name }} 480 481 return obj.Set{{ $fstruct.Name }}(pVar) 482 } 483 {{ end }} 484 {{ else }} 485 {{ $mtype := $fstruct.Format }} 486 func (obj *{{ $PublicStructName }}) {{ $mut | snakeToCamelCase }}{{ $fstruct.Name }}(mutArg {{ $mtype }}) error { 487 {{- if eq $mut "inc" }} 488 if mutArg == 0 { 489 return nil 490 } 491 492 obj.BaseField.UpdateOps = append(obj.BaseField.UpdateOps, tarantool2.Op{Field: {{ $ind }}, Op: "+", Arg: mutArg}) 493 obj.field{{ $fstruct.Name }} += mutArg 494 {{- else if eq $mut "dec" }} 495 if mutArg == 0 { 496 return nil 497 } 498 499 obj.BaseField.UpdateOps = append(obj.BaseField.UpdateOps, tarantool2.Op{Field: {{ $ind }}, Op: "-", Arg: mutArg}) 500 obj.field{{ $fstruct.Name }} -= mutArg 501 {{- else if eq $mut "and" }} 502 if obj.field{{ $fstruct.Name }} == 0 || obj.field{{ $fstruct.Name }} & mutArg == obj.field{{ $fstruct.Name }} { 503 return nil 504 } 505 506 obj.BaseField.UpdateOps = append(obj.BaseField.UpdateOps, tarantool2.Op{Field: {{ $ind }}, Op: "&", Arg: mutArg}) 507 obj.field{{ $fstruct.Name }} &= mutArg 508 {{- else if eq $mut "or" "set_bit" }} 509 if mutArg == 0 || obj.field{{ $fstruct.Name }} | mutArg == obj.field{{ $fstruct.Name }} { 510 return nil 511 } 512 513 obj.BaseField.UpdateOps = append(obj.BaseField.UpdateOps, tarantool2.Op{Field: {{ $ind }}, Op: "|", Arg: mutArg}) 514 obj.field{{ $fstruct.Name }} |= mutArg 515 {{- else if eq $mut "clear_bit" }} 516 if mutArg == 0 || obj.field{{ $fstruct.Name }} & ^mutArg == obj.field{{ $fstruct.Name }} { 517 return nil 518 } 519 520 mutArg &= ^mutArg 521 522 obj.BaseField.UpdateOps = append(obj.BaseField.UpdateOps, tarantool2.Op{Field: {{ $ind }}, Op: "=", Arg: mutArg}) 523 obj.field{{ $fstruct.Name }} = mutArg 524 {{- else if eq $mut "xor" }} 525 if mutArg == 0 || obj.field{{ $fstruct.Name }} ^ mutArg == obj.field{{ $fstruct.Name }} { 526 return nil 527 } 528 529 obj.BaseField.UpdateOps = append(obj.BaseField.UpdateOps, tarantool2.Op{Field: {{ $ind }}, Op: "^", Arg: mutArg}) 530 obj.field{{ $fstruct.Name }} ^= mutArg 531 {{- else }} 532 Unknown mutator type in template!!! 533 {{- end }} 534 535 return nil 536 } 537 {{- end }} 538 {{ end}} 539 540 {{- $fl := index $flags $fstruct.Name }} 541 {{- if $fl }} 542 {{- range $i, $flag := $fl.Flags }} 543 544 func (obj *{{ $PublicStructName }}) Set{{ $fstruct.Name }}{{ $flag }}() error { 545 return obj.SetBit{{ $fstruct.Name }}( {{ $fstruct.Name }}{{ $flag }}Flag ) 546 } 547 548 func (obj *{{ $PublicStructName }}) Clear{{ $fstruct.Name }}{{ $flag }}() error { 549 return obj.ClearBit{{ $fstruct.Name }}( {{ $fstruct.Name }}{{ $flag }}Flag ) 550 } 551 552 func (obj *{{ $PublicStructName }}) Is{{ $fstruct.Name }}{{ $flag }}() bool { 553 return obj.Get{{ $fstruct.Name }}() & {{ $fstruct.Name }}{{ $flag }}Flag == {{ $fstruct.Name }}{{ $flag }}Flag 554 } 555 {{- end }} 556 {{- end }} 557 558 {{ end -}} 559 560 // End of Getters, Setters and Mutators 561 562 func SelectAll(ctx context.Context, limiter activerecord.SelectorLimiter) ([]*{{ $PublicStructName }}, error) { 563 ctx = activerecord.Logger().SetLoggerValueToContext(ctx, map[string]interface{}{"SelectAll": "", "Repo": "{{ $PublicStructName }}"}) 564 565 res, err := selectBox(ctx, 0, []any{}, tarantool2.IterAll, limiter) 566 if err != nil { 567 return res, err 568 } 569 570 return res, nil 571 } 572 573 func (obj *{{ $PublicStructName }}) Delete(ctx context.Context) error { 574 logger := activerecord.Logger() 575 metricTimer := activerecord.Metric().Timer("tarantool", "{{ $PublicStructName }}") 576 metricStatCnt := activerecord.Metric().StatCount("tarantool", "{{ $PublicStructName }}") 577 metricErrCnt := activerecord.Metric().ErrorCount("tarantool", "{{ $PublicStructName }}") 578 579 metricStatCnt.Inc(ctx, "delete_request", 1) 580 581 if !obj.BaseField.Exists { 582 return fmt.Errorf("can't delete not exists object") 583 } 584 585 connection, err := tarantool.Box(ctx, 0, activerecord.MasterInstanceType, cfgName, {{ if eq .Server.Conf "" -}}optionCreator{{ else }}nil{{ end -}}) 586 if err != nil { 587 metricErrCnt.Inc(ctx, "delete_preparebox", 1) 588 logger.Error(ctx, "PromoBunches", obj.PrimaryString(), fmt.Sprintf("Error get box '%s'", err)) 589 590 return err 591 } 592 593 _, errCall := connection.Delete(namespace, 0, obj.packPrimary()) 594 if errCall != nil { 595 metricErrCnt.Inc(ctx, "delete_box", 1) 596 logger.Error(ctx, "{{ $PublicStructName }}", obj.PrimaryString(), "Error delete from box", errCall, connection.Info()) 597 598 return errCall 599 } 600 601 metricStatCnt.Inc(ctx, "delete_success", 1) 602 603 obj.BaseField.Exists = false 604 obj.BaseField.UpdateOps = []tarantool2.Op{} 605 606 logger.Debug(ctx, "{{ $PublicStructName }}", obj.PrimaryString(), "Success delete") 607 608 metricTimer.Finish(ctx, "delete") 609 610 return nil 611 } 612 613 func (obj *{{ $PublicStructName }}) Update(ctx context.Context) error { 614 logger := activerecord.Logger() 615 metricTimer := activerecord.Metric().Timer("tarantool", "{{ $PublicStructName }}") 616 metricStatCnt := activerecord.Metric().StatCount("tarantool", "{{ $PublicStructName }}") 617 metricErrCnt := activerecord.Metric().ErrorCount("tarantool", "{{ $PublicStructName }}") 618 619 metricStatCnt.Inc(ctx, "update_request", 1) 620 621 if !obj.BaseField.Exists { 622 metricErrCnt.Inc(ctx, "update_notexists", 1) 623 return fmt.Errorf("can't update not exists object") 624 } 625 626 /* if obj.BaseField.Repaired { 627 metricStatCnt.Inc(ctx, "update_repaired", 1) 628 logger.Debug(ctx, "", obj.PrimaryString(), "Flag 'Repaired' is true! Insert instead Update") 629 630 return obj.Replace(ctx) 631 }*/ 632 633 connection, err := tarantool.Box(ctx, 0, activerecord.MasterInstanceType, cfgName, {{ if eq .Server.Conf "" -}}optionCreator{{ else }}nil{{ end -}}) 634 if err != nil { 635 metricErrCnt.Inc(ctx, "update_preparebox", 1) 636 logger.Error(ctx, "{{ $PublicStructName }}", obj.PrimaryString(), fmt.Sprintf("Error get box '%s'", err)) 637 return err 638 } 639 640 if len(obj.BaseField.UpdateOps) == 0 { 641 metricStatCnt.Inc(ctx, "update_empty", 1) 642 logger.Debug(ctx, "", obj.PrimaryString(), "Empty update") 643 644 return nil 645 } 646 647 _, errCall := connection.Update(namespace, 0, obj.packPrimary(), obj.UpdateOps) 648 if errCall != nil { 649 metricErrCnt.Inc(ctx, "update_box", 1) 650 logger.Error(ctx, "{{ $PublicStructName }}", obj.PrimaryString(), "Error update ia a box", errCall, connection.Info()) 651 return errCall 652 } 653 654 metricTimer.Timing(ctx, "update_box") 655 656 obj.BaseField.UpdateOps = []tarantool2.Op{} 657 658 logger.Debug(ctx, "{{ $PublicStructName }}", obj.PrimaryString(), "Success update") 659 660 metricStatCnt.Inc(ctx, "update_success", 1) 661 metricTimer.Finish(ctx, "update") 662 663 return nil 664 } 665 666 func (obj *{{ $PublicStructName }}) Insert(ctx context.Context) error { 667 logger := activerecord.Logger() 668 metricStatCnt := activerecord.Metric().StatCount("tarantool", "{{ $PublicStructName }}") 669 metricErrCnt := activerecord.Metric().ErrorCount("tarantool", "{{ $PublicStructName }}") 670 671 metricStatCnt.Inc(ctx, "insert_request", 1) 672 673 if obj.BaseField.Exists { 674 metricErrCnt.Inc(ctx, "insert_exists", 1) 675 return fmt.Errorf("can't insert already exists object") 676 } 677 678 connection, err := tarantool.Box(ctx, 0, activerecord.MasterInstanceType, cfgName, {{ if eq .Server.Conf "" -}}optionCreator{{ else }}nil{{ end -}}) 679 if err != nil { 680 metricErrCnt.Inc(ctx, "insertreplace_preparebox", 1) 681 logger.Error(ctx, "{{ $PublicStructName }}", obj.PrimaryString(), fmt.Sprintf("Error get box '%s'", err)) 682 return err 683 } 684 685 tuple, err := obj.packTuple() 686 if err != nil { 687 metricErrCnt.Inc(ctx, "insertreplace_packfield", 1) 688 689 return err 690 } 691 692 _, errCall := connection.Insert(namespace, tuple) 693 if errCall != nil { 694 metricErrCnt.Inc(ctx, "insertreplace_box", 1) 695 logger.Error(ctx, "{{ $PublicStructName }}", obj.PrimaryString(), "Error insert into box", errCall, connection.Info()) 696 697 return errCall 698 } 699 700 if err == nil { 701 metricStatCnt.Inc(ctx, "insert_success", 1) 702 } 703 704 obj.UpdateOps = []tarantool2.Op{} 705 obj.BaseField.Exists = true 706 707 return err 708 } 709 710 func (obj *{{ $PublicStructName }}) Replace(ctx context.Context) error { 711 logger := activerecord.Logger() 712 metricStatCnt := activerecord.Metric().StatCount("tarantool", "{{ $PublicStructName }}") 713 metricErrCnt := activerecord.Metric().ErrorCount("tarantool", "{{ $PublicStructName }}") 714 715 metricStatCnt.Inc(ctx, "replace_request", 1) 716 717 if !obj.BaseField.Exists { 718 metricErrCnt.Inc(ctx, "replace_notexists", 1) 719 return fmt.Errorf("can't replace not exists object") 720 } 721 722 connection, err := tarantool.Box(ctx, 0, activerecord.MasterInstanceType, cfgName, {{ if eq .Server.Conf "" -}}optionCreator{{ else }}nil{{ end -}}) 723 if err != nil { 724 metricErrCnt.Inc(ctx, "insertreplace_preparebox", 1) 725 logger.Error(ctx, "{{ $PublicStructName }}", obj.PrimaryString(), fmt.Sprintf("Error get box '%s'", err)) 726 727 return err 728 } 729 730 tuple, err := obj.packTuple() 731 if err != nil { 732 metricErrCnt.Inc(ctx, "insertreplace_packfield", 1) 733 734 return err 735 } 736 737 _, errCall := connection.Replace(namespace, tuple) 738 if errCall != nil { 739 metricErrCnt.Inc(ctx, "insertreplace_box", 1) 740 logger.Error(ctx, "PromoBunches", obj.PrimaryString(), "Error replace on box", errCall, connection.Info()) 741 742 return errCall 743 } 744 745 if err == nil { 746 metricStatCnt.Inc(ctx, "replace_success", 1) 747 } 748 749 obj.UpdateOps = []tarantool2.Op{} 750 obj.BaseField.Exists = true 751 752 return err 753 } 754 755 func (obj *{{ $PublicStructName }}) InsertOrReplace(ctx context.Context) error { 756 logger := activerecord.Logger() 757 metricStatCnt := activerecord.Metric().StatCount("tarantool", "{{ $PublicStructName }}") 758 metricErrCnt := activerecord.Metric().ErrorCount("tarantool", "{{ $PublicStructName }}") 759 760 metricStatCnt.Inc(ctx, "insertorreplace_request", 1) 761 762 connection, err := tarantool.Box(ctx, 0, activerecord.MasterInstanceType, cfgName, {{ if eq .Server.Conf "" -}}optionCreator{{ else }}nil{{ end -}}) 763 if err != nil { 764 metricErrCnt.Inc(ctx, "insertreplace_preparebox", 1) 765 logger.Error(ctx, "{{ $PublicStructName }}", obj.PrimaryString(), fmt.Sprintf("Error get box '%s'", err)) 766 return err 767 } 768 769 tuple, err := obj.packTuple() 770 if err != nil { 771 metricErrCnt.Inc(ctx, "insertreplace_packfield", 1) 772 773 return err 774 } 775 776 _, errCall := connection.Upsert(namespace, tuple, obj.UpdateOps) 777 if errCall != nil { 778 metricErrCnt.Inc(ctx, "insertreplace_box", 1) 779 logger.Error(ctx, "{{ $PublicStructName }}", obj.PrimaryString(), "Error upsert box", errCall, connection.Info()) 780 781 return errCall 782 } 783 784 if err == nil { 785 metricStatCnt.Inc(ctx, "insertorreplace_success", 1) 786 } 787 788 obj.UpdateOps = []tarantool2.Op{} 789 obj.BaseField.Exists = true 790 791 return err 792 } 793 794 func selectBox(ctx context.Context, indexnum uint32, keys []interface{}, iterType uint32, limiter activerecord.SelectorLimiter) ([]*{{ $PublicStructName }}, error) { 795 logger := activerecord.Logger() 796 ctx = logger.SetLoggerValueToContext(ctx, activerecord.ValueLogPrefix{"limiter": limiter.String()}) 797 metricTimer := activerecord.Metric().Timer("tarantool", "{{ $PublicStructName }}") 798 metricStatCnt := activerecord.Metric().StatCount("tarantool", "{{ $PublicStructName }}") 799 metricErrCnt := activerecord.Metric().ErrorCount("tarantool", "{{ $PublicStructName }}") 800 801 connection, err := tarantool.Box(ctx, 0, activerecord.ReplicaOrMasterInstanceType, cfgName, {{ if eq .Server.Conf "" -}}optionCreator{{ else }}nil{{ end -}}) 802 if err != nil { 803 metricErrCnt.Inc(ctx, "select_preparebox", 1) 804 logger.Error(ctx, fmt.Sprintf("Error get box '%s'", err)) 805 806 return nil, err 807 } 808 809 var res []*{{ $PublicStructName }} 810 811 limit := limiter.Limit() 812 if limiter.Limit() == 0 { 813 limit = math.MaxInt32 814 } 815 816 errCall := connection.SelectTyped(namespace, indexnum, limiter.Offset(), limit, iterType, keys, &res) 817 if errCall != nil { 818 metricErrCnt.Inc(ctx, "select_box", 1) 819 logger.Error(ctx, "Error select from box", errCall, connection.Info()) 820 821 return nil, errCall 822 } 823 824 metricTimer.Timing(ctx, "select_box") 825 metricStatCnt.Inc(ctx, "select_tuples_res", float64(len(res))) 826 827 if limiter.FullfillWarn() && len(res) == int(limiter.Limit()) { 828 logger.Warn(ctx, "Select limit reached. Result may less than db records.") 829 } 830 831 mode, ok := connection.InstanceMode().(activerecord.ServerModeType) 832 if !ok || mode == activerecord.ModeReplica { 833 if !ok { 834 logger.Error(ctx, "Invalid server mode type: %T", connection.InstanceMode()) 835 } 836 837 for _, r := range res { 838 r.BaseField.IsReplica = true 839 r.BaseField.ReadOnly = true 840 } 841 } 842 843 for _, r := range res { 844 r.BaseField.Objects = map[string][]tarantool.ModelStruct{} 845 r.BaseField.Exists = true 846 } 847 848 logger.Debug(ctx, "Success select") 849 850 metricTimer.Finish(ctx, "select") 851 852 return res, nil 853 } 854 855 func executeSQL(ctx context.Context, sqlText string, args []any) ([]*{{ $PublicStructName }}, error) { 856 logger := activerecord.Logger() 857 metricTimer := activerecord.Metric().Timer("tarantool", "{{ $PublicStructName }}") 858 metricStatCnt := activerecord.Metric().StatCount("tarantool", "{{ $PublicStructName }}") 859 metricErrCnt := activerecord.Metric().ErrorCount("tarantool", "{{ $PublicStructName }}") 860 861 connection, err := tarantool.Box(ctx, 0, activerecord.ReplicaOrMasterInstanceType, cfgName, {{ if eq .Server.Conf "" -}}optionCreator{{ else }}nil{{ end -}}) 862 if err != nil { 863 metricErrCnt.Inc(ctx, "execute_preparebox", 1) 864 logger.Error(ctx, fmt.Sprintf("Error get box '%s'", err)) 865 866 return nil, err 867 } 868 869 var res []*{{ $PublicStructName }} 870 871 if _, _, errCall := connection.ExecuteTyped(sqlText, args, &res); err != nil { 872 metricErrCnt.Inc(ctx, "execute_box", 1) 873 logger.Error(ctx, "Error execute from box", errCall, connection.Info()) 874 875 return nil, errCall 876 } 877 878 for _, r := range res { 879 r.BaseField.Exists = true 880 r.BaseField.Objects = map[string][]tarantool.ModelStruct{} 881 } 882 883 metricStatCnt.Inc(ctx, "execute_tuples_res", float64(len(res))) 884 885 logger.Debug(ctx, "Success execute") 886 887 metricTimer.Finish(ctx, "execute") 888 889 return res, nil 890 }