Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Calling Stored Procedures #6

Closed
ebirukov opened this issue Apr 17, 2023 · 6 comments · Fixed by #8 or mailru/activerecord-cookbook#2
Closed

Calling Stored Procedures #6

ebirukov opened this issue Apr 17, 2023 · 6 comments · Fixed by #8 or mailru/activerecord-cookbook#2
Assignees

Comments

@ebirukov
Copy link
Contributor

ebirukov commented Apr 17, 2023

Declaration example

//ar:serverConf:box1
//ar:procedure:bar.foo
//ar:backend:octopus
type FieldsFoo struct {
  InParams1 string `ar:""`
  InParams2 string `ar:""`
  Output  string `ar:"serializer:Output"`
  //InOutParam any - it is possible to set InOut parameters for relational database https://pkg.go.dev/database/sql#Out
}

or
//ar:serverConf:box1
//ar:namespace:bar.foo
//ar:backend:octopus
type ProcFieldsFoo struct {
  InParams1 string `ar:""`
  InParams2 string `ar:""`
  Output  string `ar:"serializer:Output"`
  //InOutParam any - it is possible to set InOut parameters for relational database https://pkg.go.dev/database/sql#Out
}


type (
  ParamsProcFoo struct {
    Params bool `ar:"fields:InParams1,InParams2;"`
  }

  SerializersFoo struct {
    Output *repository.Data `ar:"unmarshaler:MapstructureUnmarshal;marshaler:MapstructureMarshal"`
  }
)

code generated by this declaration

func CallProcedure(ctx context.Context, params ParamsFoo) (*Foo, error) {
  ...
  c, _ := box(ctx, 0, activerecord.ReplicaInstanceType)
  output, _ := octopus.CallLua(ctx, c, "bar.foo", params.Params1, params.Params2)
  ...
  return result(params, output), nil
}

Usage:

dict, err := foo.CallProcedure(ctx, ParamsFoo{InParams1:"1",InParams1:"2"}) )
var out *repository.Data
out = dict.GetOutput()
@sklukin
Copy link
Contributor

sklukin commented Apr 18, 2023

Output это же по факту пустой интерфейс?

Хотелось бы все таки строгой типизации. Что бы приходящие данные натягивались на структуру, а параметры лежали в отдельной структуре. По типу индексов, но параметры

@ebirukov
Copy link
Contributor Author

ebirukov commented Apr 18, 2023

Output это же по факту пустой интерфейс?

Хотелось бы все таки строгой типизации. Что бы приходящие данные натягивались на структуру, а параметры лежали в отдельной структуре. По типу индексов, но параметры

По задумке выходные параметры могут иметь сериализаторы аналогично существующим полям структур Fields
SerializersFoo struct {
Output *repository.Data ar:"unmarshaler:MapstructureUnmarshal;marshaler:MapstructureMarshal"
}

но они необязательны и можно описывать так

  //ar:serverConf:box1
//ar:namespace:bar.foo
//ar:backend:octopus
type ProcFieldsFoo struct {
  InParams1 string `ar:""`
  InParams2 string `ar:""`
  Output *repository.Data `ar:""`
}

@Nikolo
Copy link
Contributor

Nikolo commented Apr 18, 2023

//ar:serverConf:box1
//ar:namespace:bar.foo
//ar:backend:octopus
type ProcFieldsFoo struct {
ID uint64 ar:"input;output"
Name string ar:"output"
Email string ar:"input;output"
}

type ProcFieldsFoo struct {
ID uint64 ar:"input:2;output"
Name string ar:"output"
Email string ar:"input:1;output"
Status bool ar:"input:3"
}

@ebirukov
Copy link
Contributor Author

ebirukov commented Apr 20, 2023

generator mvp
and example

//ar:serverHost:box1
//ar:namespace:bar.foo
//ar:backend:octopus
type ProcFieldsFoo struct {
	SearchQuery string `ar:"input"`
	TraceID     string `ar:"input;output"`
	Status      string `ar:"output"`
	JsonRawData string `ar:"output"`
}
	params := foo.FooParams{
		SearchQuery: "who are you",
		TraceID:     "",
	}

	res, err := foo.Call(ctx, params)
	
	resultStatus := res.GetStatus()
	reqID := res.GetTraceID()
	rawJson := res.GetJsonRawData()

@ebirukov
Copy link
Contributor Author

ebirukov commented Apr 23, 2023

для вышеприведенной модели описания есть неоднозначность, возвращаемые параметры луашной процедуры можно реализовать двумя способами:

  1. с несколькими возвращаемыми значениями
    func foo() return "out1", "out2". В этом случае в результате вызова вернется несколько туплов с одним значением
  2. с одним возвращаемым значение в виде тупла
    func foo() return box.tuple.new({"out1", "out2"}) и тогда вернется один тупл с несколькими значениями

В общем случае октопус возвращает двумерную модель и возникает неоднозначность мепинга результата на поля описанной в активрекорд структуры, разделять на поля тупл с несколькими значениями или брать в качестве значения единичный элемент тупла

Чтобы поддержать оба варианта приходит в голову решение добавить тег типа raw:N, col:K в описание поля в декларации активрекод, чтобы описаывать какое значение K из тупла N мепить на поле в декларации.
Но кажется такое не актуально для реляционных БД и добавит сложности в описание
Для нашего варианта с луашным банком вариант 1 не нужен, не знаю может ли он использоваться еще где-то в проектах с тарантулом и потребуется ли вообще
@Nikolo насколько вариант 1 с несколькими возвращаемыми значениями в луашных процедурах актуален для тарантул реализации activerecord?

This was linked to pull requests Apr 30, 2023
ebirukov pushed a commit that referenced this issue May 2, 2023
- output proc fields order index
- fix octopus box config
@Nikolo Nikolo closed this as completed in #8 May 2, 2023
@ebirukov
Copy link
Contributor Author

ebirukov commented May 3, 2023

support storage procedure call was released

docs
example declaration
generated api
example test

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants