Commit 8bc396eb9662db719a885c160c81a6e8a7003564

Authored by Marko Tikvić
1 parent 4c5e428df5
Exists in master and in 1 other branch v2

reverted changes

... ... @@ -249,7 +249,8 @@ func initMetadata(project string) error {
249 249 }
250 250 count++
251 251 }
252   - logger.Log("webutility: successfully loaded %d/%d (%.1f%%) entities\n", success, count, float32(success)/float32(count)*100.0)
  252 + perc := float32(success/count) * 100.0
  253 + logger.Log("loaded %d/%d (%.1f%%) entities\n", success, count, perc)
253 254  
254 255 return nil
255 256 }
... ...
... ... @@ -0,0 +1,613 @@
  1 +package webutility
  2 +
  3 +import "gopkg.in/rana/ora.v4"
  4 +
  5 +type ListOptions struct {
  6 + GlobalFilter bool `json:"globalFilter"`
  7 + LocalFilters bool `json:"localFilters"`
  8 + RemoteFilters bool `json:"remoteFilters"`
  9 + Pagination bool `json:"pagination"`
  10 + PageSize uint64 `json:"pageSize"`
  11 + Pivot bool `json:"pivot"`
  12 + Detail bool `json:"detail"`
  13 + Total bool `json:"total"`
  14 +}
  15 +
  16 +type ListFilter struct {
  17 + Position uint32 `json:"-"`
  18 + ObjectType string `json:"-"`
  19 + FiltersField string `json:"filtersField"`
  20 + DefaultValues string `json:"defaultValues"`
  21 + FiltersType string `json:"filtersType"`
  22 + FiltersLabel string `json:"filtersLabel"`
  23 + DropdownConfig Dropdown `json:"dropdownConfig"`
  24 +}
  25 +
  26 +type Dropdown struct {
  27 + ObjectType string `json:"objectType"`
  28 + FiltersField string `json:"filtersField"`
  29 + IDField string `json:"idField"`
  30 + LabelField string `json:"labelField"`
  31 +}
  32 +
  33 +type ListGraph struct {
  34 + ObjectType string `json:"objectType"`
  35 + X string `json:"xField"`
  36 + Y string `json:"yField"`
  37 + GroupField string `json:"groupField"`
  38 + Label string `json:"label"`
  39 +}
  40 +
  41 +type ListActions struct {
  42 + Create bool `json:"create"`
  43 + Update bool `json:"update"`
  44 + Delete bool `json:"delete"`
  45 + Export bool `json:"export"`
  46 + Print bool `json:"print"`
  47 + Graph bool `json:"graph"`
  48 +}
  49 +
  50 +type ListNavNode struct {
  51 + ObjectType string `json:"objectType"`
  52 + LabelField string `json:"label"`
  53 + Icon string `json:"icon"`
  54 + ParentObjectType string `json:"parentObjectType"`
  55 + ParentIDField string `json:"parentIdField"`
  56 + ParentFilterField string `json:"parentFilterField"`
  57 +}
  58 +
  59 +type ListParentNode struct {
  60 + ObjectType string `json:"objectType"`
  61 + LabelField string `json:"labelField"`
  62 + FilterField string `json:"filterField"`
  63 +}
  64 +
  65 +type ListPivot struct {
  66 + ObjectType string `json:"objectType"`
  67 + GroupField string `json:"groupField"`
  68 + DistinctField string `json:"distinctField"`
  69 + Value string `json:"valueField"`
  70 +}
  71 +
  72 +type ListDetails struct {
  73 + ObjectType string `json:"objectType"`
  74 + ParentObjectType string `json:"parentObjectType"`
  75 + ParentFilterField string `json:"parentFilterField"`
  76 + SingleDetail bool `json:"singleDetail"`
  77 +}
  78 +
  79 +type ListConfig struct {
  80 + ObjectType string `json:"objectType"`
  81 + Title string `json:"title"`
  82 + LazyLoad bool `json:"lazyLoad"`
  83 + InlineEdit bool `json:"inlineEdit"`
  84 + Options ListOptions `json:"options"`
  85 + Filters []ListFilter `json:"defaultFilters"`
  86 + Graphs []ListGraph `json:"graphs"`
  87 + Actions ListActions `json:"actions"`
  88 + Parent []ListParentNode `json:"parent"`
  89 + Navigation []ListNavNode `json:"navigation"`
  90 + Pivots []ListPivot `json:"pivots"`
  91 + Details ListDetails `json:"details"`
  92 +}
  93 +
  94 +// GetListConfig returns list configuration for the provided object type for the front-end application
  95 +// or an error if it fails.
  96 +func GetListConfig(db *ora.Ses, objType string) (ListConfig, error) {
  97 + resp := newDefaultList(objType)
  98 + var err error
  99 +
  100 + err = setListParams(db, &resp, objType)
  101 + resp.Navigation, err = getListNavigation(db, objType)
  102 + resp.Actions, err = getListActions(db, objType)
  103 + resp.Filters, err = getListFilters(db, objType)
  104 + resp.Options, err = getListOptions(db, objType)
  105 + resp.Parent, err = getListParent(db, objType)
  106 + resp.Graphs, err = getListGraph(db, objType)
  107 + resp.Pivots, err = getListPivot(db, objType)
  108 + resp.Details, err = getListDetails(db, objType)
  109 +
  110 + if err != nil {
  111 + return ListConfig{}, err
  112 + }
  113 +
  114 + return resp, nil
  115 +}
  116 +
  117 +// GetListConfigObjectIDField takes in database connection and an object type and it returns the
  118 +// ID field name for the provided object type.
  119 +func GetListConfigObjectIDField(db *ora.Ses, otype string) string {
  120 + var resp string
  121 + var err error
  122 + var stmt *ora.Stmt
  123 +
  124 + stmt, err = db.Prep(`SELECT
  125 + ID_FIELD
  126 + FROM LIST_CONFIG_ID_FIELD
  127 + WHERE OBJECT_TYPE = '`+otype+`'`,
  128 + ora.S)
  129 +
  130 + defer stmt.Close()
  131 +
  132 + if err != nil {
  133 + return ""
  134 + }
  135 +
  136 + rset, err := stmt.Qry()
  137 + if rset.Next() {
  138 + resp = rset.Row[0].(string)
  139 + }
  140 +
  141 + if rset.Err() != nil {
  142 + return ""
  143 + }
  144 +
  145 + return resp
  146 +}
  147 +
  148 +// newDefaultList returns default configuration for the provided object type.
  149 +func newDefaultList(objType string) ListConfig {
  150 + list := ListConfig{
  151 + ObjectType: objType,
  152 + Title: objType,
  153 + LazyLoad: false,
  154 + Options: ListOptions{
  155 + GlobalFilter: true,
  156 + LocalFilters: true,
  157 + RemoteFilters: false,
  158 + Pagination: true,
  159 + PageSize: 20,
  160 + },
  161 + Filters: nil,
  162 + Actions: ListActions{
  163 + Create: false,
  164 + Update: false,
  165 + Delete: false,
  166 + Export: false,
  167 + Print: false,
  168 + Graph: false,
  169 + },
  170 + Parent: nil,
  171 + Navigation: nil,
  172 + }
  173 +
  174 + return list
  175 +}
  176 +
  177 +// setListParams sets the default parameters of the provided configuration list for the provided object type.
  178 +func setListParams(db *ora.Ses, list *ListConfig, objType string) error {
  179 + var err error
  180 + var stmt *ora.Stmt
  181 + query := `SELECT
  182 + OBJECT_TYPE, TITLE, LAZY_LOAD, INLINE_EDIT
  183 + FROM LIST_CONFIG
  184 + WHERE OBJECT_TYPE = '` + objType + `'`
  185 +
  186 + stmt, err = db.Prep(query, ora.S, ora.S, ora.U32, ora.U32)
  187 + if err != nil {
  188 + return err
  189 + }
  190 + defer stmt.Close()
  191 +
  192 + rset, err := stmt.Qry()
  193 + if err != nil {
  194 + return err
  195 + }
  196 + if rset.Next() {
  197 + otype := rset.Row[0].(string)
  198 + if otype != "" {
  199 + list.ObjectType = otype
  200 + }
  201 +
  202 + title := rset.Row[1].(string)
  203 + if title != "" {
  204 + list.Title = title
  205 + }
  206 + list.LazyLoad = rset.Row[2].(uint32) != 0
  207 + list.InlineEdit = rset.Row[3].(uint32) != 0
  208 + }
  209 + if rset.Err() != nil {
  210 + return rset.Err()
  211 + }
  212 + return nil
  213 +}
  214 +
  215 +// getListNavigation returns list navigation node slice for the provided objectType.
  216 +func getListNavigation(db *ora.Ses, listObjType string) ([]ListNavNode, error) {
  217 + resp := make([]ListNavNode, 0)
  218 + var err error
  219 + var stmt *ora.Stmt
  220 + query := `SELECT
  221 + a.OBJECT_TYPE, a.PARENT_OBJECT_TYPE, a.LABEL, a.ICON, a.PARENT_FILTER_FIELD, b.PARENT_ID_FIELD, b.RB
  222 + FROM LIST_CONFIG_NAVIGATION b
  223 + JOIN LIST_CONFIG_CHILD a ON b.PARENT_CHILD_ID = a.PARENT_CHILD_ID
  224 + WHERE b.LIST_OBJECT_TYPE = '` + listObjType + `'
  225 + ORDER BY b.RB ASC`
  226 +
  227 + stmt, err = db.Prep(query, ora.S, ora.S, ora.S, ora.S, ora.S)
  228 + if err != nil {
  229 + return resp, err
  230 + }
  231 + defer stmt.Close()
  232 +
  233 + rset, err := stmt.Qry()
  234 + if err != nil {
  235 + return resp, err
  236 + }
  237 + for rset.Next() {
  238 + resp = append(resp, ListNavNode{
  239 + ObjectType: rset.Row[0].(string),
  240 + ParentObjectType: rset.Row[1].(string),
  241 + LabelField: rset.Row[2].(string),
  242 + Icon: rset.Row[3].(string),
  243 + ParentFilterField: rset.Row[4].(string),
  244 + ParentIDField: rset.Row[5].(string),
  245 + // RB is ignored
  246 + })
  247 + }
  248 + if rset.Err() != nil {
  249 + return nil, rset.Err()
  250 + }
  251 +
  252 + return resp, nil
  253 +}
  254 +
  255 +// getListActions returns list actions for the provided object type.
  256 +func getListActions(db *ora.Ses, objType string) (ListActions, error) {
  257 + var resp ListActions
  258 + var err error
  259 + var stmt *ora.Stmt
  260 + query := `SELECT
  261 + ACTION_CREATE, ACTION_UPDATE, ACTION_DELETE, ACTION_EXPORT,
  262 + ACTION_PRINT, ACTION_GRAPH
  263 + FROM LIST_CONFIG
  264 + WHERE OBJECT_TYPE = '` + objType + `'`
  265 +
  266 + stmt, err = db.Prep(query, ora.U32, ora.U32, ora.U32, ora.U32,
  267 + ora.U32, ora.U32)
  268 + if err != nil {
  269 + return ListActions{}, err
  270 + }
  271 + defer stmt.Close()
  272 +
  273 + rset, err := stmt.Qry()
  274 + if err != nil {
  275 + return ListActions{}, err
  276 + }
  277 + if rset.Next() {
  278 + resp.Create = rset.Row[0].(uint32) != 0
  279 + resp.Update = rset.Row[1].(uint32) != 0
  280 + resp.Delete = rset.Row[2].(uint32) != 0
  281 + resp.Export = rset.Row[3].(uint32) != 0
  282 + resp.Print = rset.Row[4].(uint32) != 0
  283 + resp.Graph = rset.Row[5].(uint32) != 0
  284 + }
  285 + if rset.Err() != nil {
  286 + return ListActions{}, rset.Err()
  287 + }
  288 + return resp, nil
  289 +}
  290 +
  291 +// getListFiters returns list filter slice for the provided object type.
  292 +func getListFilters(db *ora.Ses, objType string) ([]ListFilter, error) {
  293 + resp := make([]ListFilter, 0)
  294 + filtersFields, err := getFilterFieldsAndPosition(db, objType)
  295 + if err != nil {
  296 + return nil, err
  297 + }
  298 + for field, pos := range filtersFields {
  299 + filters, _ := getFiltersByFilterField(db, field)
  300 + for _, filter := range filters {
  301 + var f ListFilter
  302 + f.Position = pos
  303 + f.ObjectType = objType
  304 + f.FiltersField = field
  305 + f.DefaultValues = filter.DefaultValues
  306 + f.FiltersLabel = filter.Label
  307 + f.FiltersType = filter.Type
  308 + if filter.Type == "dropdown" {
  309 + f.DropdownConfig, err = getFilterDropdownConfig(db, field)
  310 + if err != nil {
  311 + return nil, err
  312 + }
  313 + }
  314 + resp = append(resp, f)
  315 + }
  316 + }
  317 +
  318 + sortFilters(resp)
  319 +
  320 + return resp, nil
  321 +}
  322 +
  323 +// getFilterFieldsAndPosition returns a map of filter fields and their respective position in the menu.
  324 +func getFilterFieldsAndPosition(db *ora.Ses, objType string) (map[string]uint32, error) {
  325 + filtersField := make(map[string]uint32, 0)
  326 + var err error
  327 + var stmt *ora.Stmt
  328 + query := `SELECT
  329 + FILTERS_FIELD, RB
  330 + FROM LIST_CONFIG_FILTERS
  331 + WHERE OBJECT_TYPE = '` + objType + `'`
  332 +
  333 + stmt, err = db.Prep(query, ora.S, ora.U32)
  334 + if err != nil {
  335 + return nil, err
  336 + }
  337 + defer stmt.Close()
  338 +
  339 + rset, err := stmt.Qry()
  340 + if err != nil {
  341 + return nil, err
  342 + }
  343 + for rset.Next() {
  344 + filtersField[rset.Row[0].(string)] = rset.Row[1].(uint32)
  345 + }
  346 + if rset.Err() != nil {
  347 + return nil, rset.Err()
  348 + }
  349 + return filtersField, nil
  350 +}
  351 +
  352 +type _filter struct {
  353 + DefaultValues string
  354 + Label string
  355 + Type string
  356 +}
  357 +
  358 +// getFiltersByFilterField returns filter slice for the provided filter field.
  359 +func getFiltersByFilterField(db *ora.Ses, filtersField string) ([]_filter, error) {
  360 + resp := make([]_filter, 0)
  361 + var err error
  362 + var stmt *ora.Stmt
  363 + query := `SELECT
  364 + FILTERS_TYPE, FILTERS_LABEL, DEFAULT_VALUES
  365 + FROM LIST_FILTERS_FIELD
  366 + WHERE FILTERS_FIELD = '` + filtersField + `'`
  367 +
  368 + stmt, err = db.Prep(query, ora.S, ora.S, ora.S)
  369 + if err != nil {
  370 + return resp, err
  371 + }
  372 + defer stmt.Close()
  373 +
  374 + rset, err := stmt.Qry()
  375 + if err != nil {
  376 + return resp, err
  377 + }
  378 + for rset.Next() {
  379 + resp = append(resp, _filter{
  380 + Type: rset.Row[0].(string),
  381 + Label: rset.Row[1].(string),
  382 + DefaultValues: rset.Row[2].(string),
  383 + })
  384 + }
  385 + if rset.Err() != nil {
  386 + return resp, rset.Err()
  387 + }
  388 + return resp, nil
  389 +}
  390 +
  391 +// getFilterDropdownConfig returns dropdown menu for the provided filter field.
  392 +func getFilterDropdownConfig(db *ora.Ses, filtersField string) (Dropdown, error) {
  393 + var resp Dropdown
  394 + var err error
  395 + var stmt *ora.Stmt
  396 + query := `SELECT
  397 + FILTERS_FIELD, OBJECT_TYPE, ID_FIELD, LABEL_FIELD
  398 + FROM LIST_DROPDOWN_FILTER
  399 + WHERE FILTERS_FIELD = '` + filtersField + `'`
  400 +
  401 + stmt, err = db.Prep(query, ora.S, ora.S, ora.S, ora.S)
  402 + if err != nil {
  403 + return resp, err
  404 + }
  405 + defer stmt.Close()
  406 +
  407 + rset, err := stmt.Qry()
  408 + if err != nil {
  409 + return resp, err
  410 + }
  411 + if rset.Next() {
  412 + resp.FiltersField = rset.Row[0].(string)
  413 + resp.ObjectType = rset.Row[1].(string)
  414 + resp.IDField = rset.Row[2].(string)
  415 + resp.LabelField = rset.Row[3].(string)
  416 + }
  417 + if rset.Err() != nil {
  418 + return resp, rset.Err()
  419 + }
  420 + return resp, nil
  421 +}
  422 +
  423 +// sortFilters bubble sorts provided filters slice by position field.
  424 +func sortFilters(filters []ListFilter) {
  425 + done := false
  426 + var temp ListFilter
  427 + for !done {
  428 + done = true
  429 + for i := 0; i < len(filters)-1; i++ {
  430 + if filters[i].Position > filters[i+1].Position {
  431 + done = false
  432 + temp = filters[i]
  433 + filters[i] = filters[i+1]
  434 + filters[i+1] = temp
  435 + }
  436 + }
  437 + }
  438 +}
  439 +
  440 +// getListGraph return list graph slice for the provided object type.
  441 +func getListGraph(db *ora.Ses, objType string) ([]ListGraph, error) {
  442 + resp := make([]ListGraph, 0)
  443 + var err error
  444 + var stmt *ora.Stmt
  445 + query := `SELECT
  446 + OBJECT_TYPE, X_FIELD, Y_FIELD, GROUP_FIELD, LABEL
  447 + FROM LIST_GRAPHS
  448 + WHERE OBJECT_TYPE = '` + objType + `'`
  449 +
  450 + stmt, err = db.Prep(query, ora.S, ora.S, ora.S, ora.S)
  451 + if err != nil {
  452 + return resp, err
  453 + }
  454 + defer stmt.Close()
  455 +
  456 + rset, err := stmt.Qry()
  457 + if err != nil {
  458 + return resp, err
  459 + }
  460 + for rset.Next() {
  461 + resp = append(resp, ListGraph{
  462 + ObjectType: rset.Row[0].(string),
  463 + X: rset.Row[1].(string),
  464 + Y: rset.Row[2].(string),
  465 + GroupField: rset.Row[3].(string),
  466 + Label: rset.Row[4].(string),
  467 + })
  468 + }
  469 + if rset.Err() != nil {
  470 + return resp, rset.Err()
  471 + }
  472 + return resp, nil
  473 +}
  474 +
  475 +// getListOptions returns list options for the provided object type.
  476 +func getListOptions(db *ora.Ses, objType string) (ListOptions, error) {
  477 + var resp ListOptions
  478 + var err error
  479 + var stmt *ora.Stmt
  480 + query := `SELECT
  481 + GLOBAL_FILTER, LOCAL_FILTER, REMOTE_FILTER, PAGINATION,
  482 + PAGE_SIZE, PIVOT, DETAIL, TOTAL
  483 + FROM LIST_CONFIG
  484 + WHERE OBJECT_TYPE = '` + objType + `'`
  485 +
  486 + stmt, err = db.Prep(query, ora.U32, ora.U32, ora.U32, ora.U32,
  487 + ora.U64, ora.U64, ora.U32, ora.U32)
  488 + if err != nil {
  489 + return ListOptions{}, err
  490 + }
  491 + defer stmt.Close()
  492 +
  493 + rset, err := stmt.Qry()
  494 + if err != nil {
  495 + return ListOptions{}, err
  496 + }
  497 + if rset.Next() {
  498 + resp.GlobalFilter = rset.Row[0].(uint32) != 0
  499 + resp.LocalFilters = rset.Row[1].(uint32) != 0
  500 + resp.RemoteFilters = rset.Row[2].(uint32) != 0
  501 + resp.Pagination = rset.Row[3].(uint32) != 0
  502 + resp.PageSize = rset.Row[4].(uint64)
  503 + resp.Pivot = rset.Row[5].(uint64) != 0
  504 + resp.Detail = rset.Row[6].(uint32) != 0
  505 + resp.Total = rset.Row[7].(uint32) != 0
  506 + }
  507 + if rset.Err() != nil {
  508 + return ListOptions{}, rset.Err()
  509 + }
  510 + return resp, nil
  511 +}
  512 +
  513 +// getListParent returns list parent node slice for the provided object type.
  514 +func getListParent(db *ora.Ses, objType string) ([]ListParentNode, error) {
  515 + resp := make([]ListParentNode, 0)
  516 + var err error
  517 + var stmt *ora.Stmt
  518 + query := `SELECT
  519 + PARENT_OBJECT_TYPE, PARENT_LABEL_FIELD, PARENT_FILTER_FIELD
  520 + FROM LIST_CONFIG_CHILD
  521 + WHERE OBJECT_TYPE = '` + objType + `'`
  522 +
  523 + stmt, err = db.Prep(query, ora.S, ora.S, ora.S)
  524 + if err != nil {
  525 + return resp, err
  526 + }
  527 + defer stmt.Close()
  528 +
  529 + rset, err := stmt.Qry()
  530 + if err != nil {
  531 + return resp, err
  532 + }
  533 + for rset.Next() {
  534 + resp = append(resp, ListParentNode{
  535 + ObjectType: rset.Row[0].(string),
  536 + LabelField: rset.Row[1].(string),
  537 + FilterField: rset.Row[2].(string),
  538 + })
  539 + }
  540 + if rset.Err() != nil {
  541 + return nil, rset.Err()
  542 + }
  543 +
  544 + return resp, nil
  545 +}
  546 +
  547 +// getListPivot list pivot slice for the provided object type.
  548 +func getListPivot(db *ora.Ses, objType string) ([]ListPivot, error) {
  549 + resp := make([]ListPivot, 0)
  550 + var err error
  551 + var stmt *ora.Stmt
  552 + query := `SELECT
  553 + OBJECT_TYPE, GROUP_FIELD, DISTINCT_FIELD, VALUE_FIELD
  554 + FROM LIST_PIVOTS
  555 + WHERE OBJECT_TYPE = '` + objType + `'`
  556 +
  557 + stmt, err = db.Prep(query, ora.S, ora.S, ora.S, ora.S)
  558 + if err != nil {
  559 + return resp, err
  560 + }
  561 + defer stmt.Close()
  562 +
  563 + rset, err := stmt.Qry()
  564 + if err != nil {
  565 + return resp, err
  566 + }
  567 + for rset.Next() {
  568 + resp = append(resp, ListPivot{
  569 + ObjectType: rset.Row[0].(string),
  570 + GroupField: rset.Row[1].(string),
  571 + DistinctField: rset.Row[2].(string),
  572 + Value: rset.Row[3].(string),
  573 + })
  574 + }
  575 + if rset.Err() != nil {
  576 + return nil, rset.Err()
  577 + }
  578 +
  579 + return resp, nil
  580 +}
  581 +
  582 +// getListDetails returns list details for the provided object type.
  583 +func getListDetails(db *ora.Ses, objType string) (ListDetails, error) {
  584 + var resp ListDetails
  585 + var err error
  586 + var stmt *ora.Stmt
  587 + query := `SELECT
  588 + OBJECT_TYPE, PARENT_OBJECT_TYPE, PARENT_FILTER_FIELD, SINGLE_DETAIL
  589 + FROM LIST_CONFIG_DETAIL
  590 + WHERE PARENT_OBJECT_TYPE = '` + objType + `'`
  591 +
  592 + stmt, err = db.Prep(query, ora.S, ora.S, ora.S, ora.U32)
  593 + if err != nil {
  594 + return resp, err
  595 + }
  596 + defer stmt.Close()
  597 +
  598 + rset, err := stmt.Qry()
  599 + if err != nil {
  600 + return resp, err
  601 + }
  602 + if rset.Next() {
  603 + resp.ObjectType = rset.Row[0].(string)
  604 + resp.ParentObjectType = rset.Row[1].(string)
  605 + resp.ParentFilterField = rset.Row[2].(string)
  606 + resp.SingleDetail = rset.Row[3].(uint32) != 0
  607 + }
  608 + if rset.Err() != nil {
  609 + return resp, rset.Err()
  610 + }
  611 +
  612 + return resp, nil
  613 +}
... ...
... ... @@ -0,0 +1,56 @@
  1 +package webutility
  2 +
  3 +import "gopkg.in/rana/ora.v4"
  4 +
  5 +type SelectConfig struct {
  6 + ListObjType string `json:"listObjectType"`
  7 + ObjType string `json:"objectType"`
  8 + Type string `json:"type"`
  9 + IdField string `json:"idField"`
  10 + LabelField string `json:"labelField"`
  11 + ValueField string `json:"valueField"`
  12 +}
  13 +
  14 +// GetSelectConfig returns select configuration slice for the given object type.
  15 +func GetSelectConfig(db *ora.Ses, otype string) ([]SelectConfig, error) {
  16 + resp := make([]SelectConfig, 0)
  17 + var err error
  18 + var stmt *ora.Stmt
  19 + query := `SELECT
  20 + a.LIST_OBJECT_TYPE,
  21 + a.OBJECT_TYPE,
  22 + a.ID_FIELD,
  23 + a.LABEL_FIELD,
  24 + a.TYPE,
  25 + b.FIELD
  26 + FROM LIST_SELECT_CONFIG a, LIST_VALUE_FIELD b
  27 + WHERE a.LIST_OBJECT_TYPE` + otype + `
  28 + AND b.LIST_TYPE = a.LIST_OBJECT_TYPE
  29 + AND b.OBJECT_TYPE = a.OBJECT_TYPE`
  30 +
  31 + stmt, err = db.Prep(query, ora.S, ora.S, ora.S, ora.S, ora.S, ora.S)
  32 + defer stmt.Close()
  33 + if err != nil {
  34 + return nil, err
  35 + }
  36 +
  37 + rset, err := stmt.Qry()
  38 + if err != nil {
  39 + return nil, err
  40 + }
  41 + for rset.Next() {
  42 + resp = append(resp, SelectConfig{
  43 + ListObjType: rset.Row[0].(string),
  44 + ObjType: rset.Row[1].(string),
  45 + IdField: rset.Row[2].(string),
  46 + LabelField: rset.Row[3].(string),
  47 + Type: rset.Row[4].(string),
  48 + ValueField: rset.Row[5].(string),
  49 + })
  50 + }
  51 + if rset.Err() != nil {
  52 + return nil, rset.Err()
  53 + }
  54 +
  55 + return resp, nil
  56 +}
... ...