Commit 90f4ed07906acbb91fca30874806b7bf72804f54

Authored by Marko Tikvić
1 parent 6f4b8a7111
Exists in master and in 1 other branch v2

sped up loadTable()

1 TODO: 1 TODO:
2 * http utility: 2 * http utility:
3 1. add parameters to the ProcessHeaders to enable/disable token/role-access-rights checks 3 1. add parameters to the ProcessHeaders to enable/disable token/role-access-rights checks
4 2. check for Content-Type header, if clients expects something other than JSON respond with appropriate HTTP code 4 2. check for Content-Type header, if clients expects something other than JSON respond with appropriate HTTP code
5 5
1 package restutility 1 package restutility
2 2
3 import ( 3 import (
4 "net/http" 4 "net/http"
5 "encoding/json" 5 "encoding/json"
6 ) 6 )
7 7
8 var _apiVersion = "" 8 var _apiVersion = "/api/v1"
9 var _authEndPoint = "" 9 var _authEndPoint = "/token"
10 10
11 func SetApiVersion(ver string) string { 11 func SetApiVersion(ver string) string {
12 _apiVersion = ver 12 _apiVersion = ver
13 return _apiVersion 13 return _apiVersion
14 } 14 }
15 15
16 func SetAuthEndpoint(ep string) { 16 func SetAuthEndpoint(ep string) {
17 _authEndPoint = ep 17 _authEndPoint = ep
18 } 18 }
19 19
20 ////
21 //// ERROR UTILITY
22 ////
23
24 const templateHttpErr500_EN = "An internal server error has occurred." 20 const templateHttpErr500_EN = "An internal server error has occurred."
25 const templateHttpErr500_RS = "Došlo je do greške na serveru." 21 const templateHttpErr500_RS = "Došlo je do greške na serveru."
26 const templateHttpErr400_EN = "Bad request: invalid request body." 22 const templateHttpErr400_EN = "Bad request: invalid request body."
27 const templateHttpErr400_RS = "Neispravan zahtev." 23 const templateHttpErr400_RS = "Neispravan zahtev."
28 24
29 type HttpError struct { 25 type HttpError struct {
30 Error []HttpErrorDesc `json:"error"` 26 Error []HttpErrorDesc `json:"error"`
31 Request string `json:"request"` 27 Request string `json:"request"`
32 } 28 }
33 29
34 type HttpErrorDesc struct { 30 type HttpErrorDesc struct {
35 Lang string `json:"lang"` 31 Lang string `json:"lang"`
36 Desc string `json:"description"` 32 Desc string `json:"description"`
37 } 33 }
38 34
39 func RespondWithHttpError(w http.ResponseWriter, 35 func RespondWithHttpError(w http.ResponseWriter,
40 req *http.Request, 36 req *http.Request,
41 code int, 37 code int,
42 httpErr []HttpErrorDesc) { 38 httpErr []HttpErrorDesc) {
43 39
44 err := HttpError{ 40 err := HttpError{
45 Error: httpErr, 41 Error: httpErr,
46 Request: req.Method + " " + req.URL.Path, 42 Request: req.Method + " " + req.URL.Path,
47 } 43 }
48 w.WriteHeader(code) 44 w.WriteHeader(code)
49 json.NewEncoder(w).Encode(err) 45 json.NewEncoder(w).Encode(err)
50 } 46 }
51 47
52 func RespondWithHttpError400(w http.ResponseWriter, req *http.Request) { 48 func RespondWithHttpError400(w http.ResponseWriter, req *http.Request) {
53 RespondWithHttpError(w, req, http.StatusBadRequest, []HttpErrorDesc{ 49 RespondWithHttpError(w, req, http.StatusBadRequest, []HttpErrorDesc{
54 {Lang: "en", Desc: templateHttpErr400_EN}, 50 {Lang: "en", Desc: templateHttpErr400_EN},
55 {Lang: "rs", Desc: templateHttpErr400_RS}, 51 {Lang: "rs", Desc: templateHttpErr400_RS},
56 }) 52 })
57 } 53 }
58 54
59 func RespondWithHttpError500(w http.ResponseWriter, req *http.Request) { 55 func RespondWithHttpError500(w http.ResponseWriter, req *http.Request) {
60 RespondWithHttpError(w, req, http.StatusInternalServerError, []HttpErrorDesc{ 56 RespondWithHttpError(w, req, http.StatusInternalServerError, []HttpErrorDesc{
61 {Lang: "en", Desc: templateHttpErr500_EN}, 57 {Lang: "en", Desc: templateHttpErr500_EN},
62 {Lang: "rs", Desc: templateHttpErr500_RS}, 58 {Lang: "rs", Desc: templateHttpErr500_RS},
63 }) 59 })
64 } 60 }
65 61
66 //// 62 //TODO: Add parameters to enable/disable roles authorization checks
67 //// HANDLER FUNC WRAPPER
68 ////
69
70 //TODO: Add parameters to enable/disable token and roles authorization checks
71 // Sets common headers and checks for token validity. 63 // Sets common headers and checks for token validity.
72 func ProcessHeaders(fn http.HandlerFunc, authEnabled bool) http.HandlerFunc { 64 func ProcessHeaders(handlerFunc http.HandlerFunc, authEnabled bool) http.HandlerFunc {
73 return func(w http.ResponseWriter, req *http.Request) { 65 return func(w http.ResponseWriter, req *http.Request) {
74 // @TODO: check Content-type header (must be application/json) 66 // @TODO: check Content-type header (must be application/json)
75 // ctype := w.Header.Get("Content-Type") 67 // ctype := w.Header.Get("Content-Type")
76 // if req.Method != "GET" && ctype != "application/json" { 68 // if req.Method != "GET" && ctype != "application/json" {
77 // replyWithHttpError(w, req, http.StatusBadRequest, 69 // replyWithHttpError(w, req, http.StatusBadRequest,
78 // "Not a supported content type: " + ctype) 70 // "Not a supported content type: " + ctype)
79 // } 71 // }
80 72
81 w.Header().Set("Access-Control-Allow-Origin", "*") 73 w.Header().Set("Access-Control-Allow-Origin", "*")
82 w.Header().Set("Access-Control-Allow-Methods", 74 w.Header().Set("Access-Control-Allow-Methods",
83 `POST, 75 `POST,
84 GET, 76 GET,
85 PUT, 77 PUT,
86 DELETE, 78 DELETE,
87 OPTIONS`) 79 OPTIONS`)
88 w.Header().Set("Access-Control-Allow-Headers", 80 w.Header().Set("Access-Control-Allow-Headers",
89 `Accept, 81 `Accept,
90 Content-Type, 82 Content-Type,
91 Content-Length, 83 Content-Length,
92 Accept-Encoding, 84 Accept-Encoding,
93 X-CSRF-Token, 85 X-CSRF-Token,
94 Authorization`) 86 Authorization`)
95 w.Header().Set("Content-Type", "application/json; charset=utf-8") 87 w.Header().Set("Content-Type", "application/json; charset=utf-8")
96 88
97 if req.Method == "OPTIONS" { 89 if req.Method == "OPTIONS" {
98 return 90 return
99 } 91 }
100 92
101 if authEnabled { 93 if authEnabled {
102 if req.URL.Path != _apiVersion + _authEndPoint { 94 if req.URL.Path != _apiVersion + _authEndPoint {
103 token := req.Header.Get("Authorization") 95 token := req.Header.Get("Authorization")
104 if _, err := ParseAPIToken(token); err != nil { 96 if _, err := ParseAPIToken(token); err != nil {
105 RespondWithHttpError(w, req, http.StatusUnauthorized, 97 RespondWithHttpError(w, req, http.StatusUnauthorized,
106 []HttpErrorDesc{ 98 []HttpErrorDesc{
107 {Lang: "en", Desc: "Unauthorized request."}, 99 {Lang: "en", Desc: "Unauthorized request."},
108 {Lang: "rs", Desc: "Neautorizovani zahtev."}, 100 {Lang: "rs", Desc: "Neautorizovani zahtev."},
109 }) 101 })
110 return 102 return
111 } 103 }
112 } 104 }
113 } 105 }
114 106
115 err := req.ParseForm() 107 err := req.ParseForm()
116 if err != nil { 108 if err != nil {
117 RespondWithHttpError(w, req, http.StatusBadRequest, 109 RespondWithHttpError400(w, req)
118 []HttpErrorDesc{
119 {Lang: "en", Desc: templateHttpErr400_EN},
120 {Lang: "rs", Desc: templateHttpErr400_RS},
121 })
122 return 110 return
123 } 111 }
124 112
125 // execute HandlerFunc 113 // execute HandlerFunc
126 fn(w, req) 114 handlerFunc(w, req)
127 } 115 }
128 } 116 }
129 117
130 ////
131 //// NOT FOUND HANDLER
132 ////
133
134 func NotFoundHandler(w http.ResponseWriter, req *http.Request) { 118 func NotFoundHandler(w http.ResponseWriter, req *http.Request) {
135 RespondWithHttpError(w, req, http.StatusNotFound, []HttpErrorDesc{ 119 RespondWithHttpError(w, req, http.StatusNotFound, []HttpErrorDesc{
136 {Lang: "en", Desc: "Not found."}, 120 {Lang: "en", Desc: "Not found."},
137 {Lang: "rs", Desc: "Traženi resurs ne postoji."}, 121 {Lang: "rs", Desc: "Traženi resurs ne postoji."},
138 }) 122 })
139 } 123 }
140 124
1 package restutility 1 package restutility
2 2
3 import ( 3 import (
4 "net/http" 4 "net/http"
5 "encoding/json" 5 "encoding/json"
6 "errors" 6 "errors"
7 "gopkg.in/rana/ora.v3" 7 "gopkg.in/rana/ora.v3"
8 "io" 8 "io"
9 "io/ioutil" 9 "io/ioutil"
10 ) 10 )
11 11
12 var allPayloads []payloadBuff 12 var allPayloads []payloadBuff
13 13
14 type LangMap map[string]map[string]string 14 type LangMap map[string]map[string]string
15 15
16 type Field struct { 16 type Field struct {
17 Parameter string `json:"param"` 17 Parameter string `json:"param"`
18 Type string `json:"type"` 18 Type string `json:"type"`
19 Visible bool `json:"visible"` 19 Visible bool `json:"visible"`
20 Editable bool `json:"editable"` 20 Editable bool `json:"editable"`
21 } 21 }
22 22
23 type CorrelationField struct { 23 type CorrelationField struct {
24 Result string `json:"result"` 24 Result string `json:"result"`
25 Elements []string `json:"elements"` 25 Elements []string `json:"elements"`
26 Type string `json:"type"` 26 Type string `json:"type"`
27 } 27 }
28 28
29 type Translation struct { 29 type Translation struct {
30 Language string `json:"language"` 30 Language string `json:"language"`
31 FieldsLabels map[string]string `json:"fieldsLabels"` 31 FieldsLabels map[string]string `json:"fieldsLabels"`
32 } 32 }
33 33
34 type payloadBuff struct { 34 type payloadBuff struct {
35 Type string `json:"tableType"` 35 Type string `json:"tableType"`
36 Method string `json:"method"` 36 Method string `json:"method"`
37 Params map[string]string `json:"params"` 37 Params map[string]string `json:"params"`
38 Lang []Translation `json:"lang"` 38 Lang []Translation `json:"lang"`
39 Fields []Field `json:"fields"` 39 Fields []Field `json:"fields"`
40 Correlations []CorrelationField `json:"correlationFields"` 40 Correlations []CorrelationField `json:"correlationFields"`
41 IdField string `json:"idField"` 41 IdField string `json:"idField"`
42 // Data can only hold slices of any type. It can't be used for itteration 42 // Data can only hold slices of any type. It can't be used for itteration
43 Data interface{} `json:"data"` 43 Data interface{} `json:"data"`
44 } 44 }
45 45
46 type Payload struct { 46 type Payload struct {
47 Method string `json:"method"` 47 Method string `json:"method"`
48 Params map[string]string `json:"params"` 48 Params map[string]string `json:"params"`
49 Lang []Translation `json:"lang"` 49 Lang []Translation `json:"lang"`
50 Fields []Field `json:"fields"` 50 Fields []Field `json:"fields"`
51 Correlations []CorrelationField `json:"correlationFields"` 51 Correlations []CorrelationField `json:"correlationFields"`
52 IdField string `json:"idField"` 52 IdField string `json:"idField"`
53 // Data can only hold slices of any type. It can't be used for itteration 53 // Data can only hold slices of any type. It can't be used for itteration
54 Data interface{} `json:"data"` 54 Data interface{} `json:"data"`
55 } 55 }
56 56
57 func NewPayload(r *http.Request, table string) Payload { 57 func NewPayload(r *http.Request, table string) Payload {
58 var pload Payload 58 var pload Payload
59 59
60 pload.Method = r.Method + " " + r.URL.Path 60 pload.Method = r.Method + " " + r.URL.Path
61 pload.Params = make(map[string]string, 0) 61
62 pload.Lang = loadTranslations(table) 62 if table != "" {
63 pload.Fields = loadFields(table) 63 pload.Params = make(map[string]string, 0)
64 pload.IdField = loadIdField(table) 64 pload.Lang = loadTranslations(table)
65 pload.Correlations = loadCorrelations(table) 65 pload.Fields = loadFields(table)
66 pload.IdField = loadIdField(table)
67 pload.Correlations = loadCorrelations(table)
68 }
66 69
67 return pload 70 return pload
68 } 71 }
69 72
70 func DeliverPayload(w http.ResponseWriter, payload Payload) { 73 func DeliverPayload(w http.ResponseWriter, payload Payload) {
71 json.NewEncoder(w).Encode(payload) 74 json.NewEncoder(w).Encode(payload)
72 payload.Data = nil 75 payload.Data = nil
73 } 76 }
74 77
75 func loadTranslations(id string) []Translation { 78 func loadTranslations(id string) []Translation {
76 translations := make([]Translation, 0) 79 translations := make([]Translation, 0)
77 80
78 for _, pload := range allPayloads { 81 for _, pload := range allPayloads {
79 if pload.Type == id { 82 if pload.Type == id {
80 for _, t := range pload.Lang { 83 for _, t := range pload.Lang {
81 //translations[t.Language] = t.FieldsLabels 84 //translations[t.Language] = t.FieldsLabels
82 translations = append(translations, Translation{ 85 translations = append(translations, Translation{
83 Language: t.Language, 86 Language: t.Language,
84 FieldsLabels: t.FieldsLabels, 87 FieldsLabels: t.FieldsLabels,
85 }) 88 })
86 } 89 }
87 } 90 }
88 } 91 }
89 92
90 return translations 93 return translations
91 } 94 }
92 95
93 func loadFields(id string) []Field { 96 func loadFields(id string) []Field {
94 fields := make([]Field, 0) 97 fields := make([]Field, 0)
95 98
96 for _, pload := range allPayloads { 99 for _, pload := range allPayloads {
97 if pload.Type == id{ 100 if pload.Type == id{
98 for _, f := range pload.Fields { 101 for _, f := range pload.Fields {
99 fields = append(fields, f) 102 fields = append(fields, f)
100 } 103 }
101 } 104 }
102 } 105 }
103 106
104 return fields 107 return fields
105 } 108 }
106 109
107 func loadIdField(id string) string { 110 func loadIdField(id string) string {
108 for _, pload := range allPayloads { 111 for _, pload := range allPayloads {
109 if pload.Type == id { 112 if pload.Type == id {
110 return pload.IdField 113 return pload.IdField
111 } 114 }
112 } 115 }
113 return "" 116 return ""
114 } 117 }
115 118
116 func loadCorrelations(id string) []CorrelationField { 119 func loadCorrelations(id string) []CorrelationField {
117 resp := make([]CorrelationField, 0) 120 resp := make([]CorrelationField, 0)
118 121
119 for _, pload := range allPayloads { 122 for _, pload := range allPayloads {
120 if pload.Type == id { 123 if pload.Type == id {
121 for _, f := range pload.Correlations { 124 for _, f := range pload.Correlations {
122 resp = append(resp, f) 125 resp = append(resp, f)
123 } 126 }
124 } 127 }
125 } 128 }
126 129
127 return resp 130 return resp
128 } 131 }
129 132
130 func InitTables(db *ora.Ses, project string) error { 133 func InitTables(db *ora.Ses, project string) error {
131 jsonbuf, _ := fetchTablesConfig(db, EqualQuotes(project)) 134 jsonbuf, _ := fetchTablesConfig(db, EqualQuotes(project))
132 json.Unmarshal(jsonbuf, &allPayloads) 135 json.Unmarshal(jsonbuf, &allPayloads)
133 if len(allPayloads) == 0 { 136 if len(allPayloads) == 0 {
134 return errors.New("tables config is corrupt") 137 return errors.New("tables config is corrupt")
135 } 138 }
136 return nil 139 return nil
137 } 140 }
138 141
139 func fetchTablesConfig(db *ora.Ses, project string) ([]byte, error) { 142 func fetchTablesConfig(db *ora.Ses, project string) ([]byte, error) {
140 stmt, err := db.Prep(`SELECT 143 stmt, err := db.Prep(`SELECT
141 JSON_CLOB 144 JSON_CLOB
142 FROM TABLES_CONFIG 145 FROM TABLES_CONFIG
143 WHERE PROJEKAT` + project, ora.S) 146 WHERE PROJEKAT` + project, ora.S)
144 defer stmt.Close() 147 defer stmt.Close()
145 148
146 if err != nil { 149 if err != nil {
147 return nil, err 150 return nil, err
148 } 151 }
149 152
150 rset, err := stmt.Qry() 153 rset, err := stmt.Qry()
151 if err != nil { 154 if err != nil {
152 return nil, err 155 return nil, err
153 } 156 }
154 157
155 bytes := make([]byte, 0) 158 bytes := make([]byte, 0)
156 if rset.Next() { 159 if rset.Next() {
157 lob := rset.Row[0].(io.Reader) 160 lob := rset.Row[0].(io.Reader)
158 bytes, err = ioutil.ReadAll(lob) 161 bytes, err = ioutil.ReadAll(lob)
159 if err != nil { 162 if err != nil {
160 // TODO: Find a fix for this. 163 // TODO: Find a fix for this.
161 // Ignore, it's some weird streaming read/write LOB error. 164 // Ignore, it's some weird streaming read/write LOB error.
162 //return nil, err 165 //return nil, err
163 } 166 }
164 } 167 }
165 168
166 return bytes, nil 169 return bytes, nil
167 } 170 }
168 171
169 172
1 package restutility 1 package restutility
2 2
3 import ( 3 import (
4 "gopkg.in/rana/ora.v3" 4 "gopkg.in/rana/ora.v3"
5 ) 5 )
6 6
7 type ListOptions struct { 7 type ListOptions struct {
8 GlobalFilter bool `json:"globalFilter"` 8 GlobalFilter bool `json:"globalFilter"`
9 LocalFilters bool `json:"localFilters"` 9 LocalFilters bool `json:"localFilters"`
10 RemoteFilters bool `json:"remoteFilters"` 10 RemoteFilters bool `json:"remoteFilters"`
11 Pagination bool `json:"pagination"` 11 Pagination bool `json:"pagination"`
12 PageSize uint64 `json:"pageSize"` 12 PageSize uint64 `json:"pageSize"`
13 Pivot bool `json:"pivot"` 13 Pivot bool `json:"pivot"`
14 Detail bool `json:"detail"` 14 Detail bool `json:"detail"`
15 } 15 }
16 16
17 type ListFilter struct { 17 type ListFilter struct {
18 ObjectType string `json:"-"` 18 ObjectType string `json:"-"`
19 FiltersField string `json:"filtersField"` 19 FiltersField string `json:"filtersField"`
20 DefaultValues string `json:"defaultValues"` 20 DefaultValues string `json:"defaultValues"`
21 FiltersType string `json:"filtersType"` 21 FiltersType string `json:"filtersType"`
22 FiltersLabel string `json:"filtersLabel"` 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
23 } 32 }
24 33
25 type ListGraph struct { 34 type ListGraph struct {
26 ObjectType string `json:"objectType"` 35 ObjectType string `json:"objectType"`
27 X string `json:"xField"` 36 X string `json:"xField"`
28 Y string `json:"yField"` 37 Y string `json:"yField"`
29 GroupField string `json:"groupField"` 38 GroupField string `json:"groupField"`
30 Label string `json:"label"` 39 Label string `json:"label"`
31 } 40 }
32 41
33 type ListActions struct { 42 type ListActions struct {
34 Create bool `json:"create"` 43 Create bool `json:"create"`
35 Update bool `json:"update"` 44 Update bool `json:"update"`
36 Delete bool `json:"delete"` 45 Delete bool `json:"delete"`
37 Export bool `json:"export"` 46 Export bool `json:"export"`
38 Print bool `json:"print"` 47 Print bool `json:"print"`
39 Graph bool `json:"graph"` 48 Graph bool `json:"graph"`
40 } 49 }
41 50
42 type ListChildNode struct { 51 type ListChildNode struct {
43 ObjectType string `json:"objectType"` 52 ObjectType string `json:"objectType"`
44 LabelField string `json:"label"` 53 LabelField string `json:"label"`
45 Icon string `json:"icon"` 54 Icon string `json:"icon"`
46 } 55 }
47 56
48 type ListParentNode struct { 57 type ListParentNode struct {
49 ObjectType string `json:"objectType"` 58 ObjectType string `json:"objectType"`
50 LabelField string `json:"labelField"` 59 LabelField string `json:"labelField"`
51 FilterField string `json:"filterField"` 60 FilterField string `json:"filterField"`
52 } 61 }
53 62
54 type ListPivot struct { 63 type ListPivot struct {
55 ObjectType string `json:"objectType"` 64 ObjectType string `json:"objectType"`
56 GroupField string `json:"groupField"` 65 GroupField string `json:"groupField"`
57 DistinctField string `json:"distinctField"` 66 DistinctField string `json:"distinctField"`
58 Value string `json:"valueField"` 67 Value string `json:"valueField"`
59 } 68 }
60 69
61 type ListDetails struct { 70 type ListDetails struct {
62 ObjectType string `json:"objectType"` 71 ObjectType string `json:"objectType"`
63 ParentObjectType string `json:"parentObjectType"` 72 ParentObjectType string `json:"parentObjectType"`
64 ParentFilterField string `json:"parentFilterField"` 73 ParentFilterField string `json:"parentFilterField"`
65 SingleDetail bool `json:"singleDetail"` 74 SingleDetail bool `json:"singleDetail"`
66 } 75 }
67 76
68 type ListConfig struct { 77 type ListConfig struct {
69 ObjectType string `json:"objectType"` 78 ObjectType string `json:"objectType"`
70 Title string `json:"title"` 79 Title string `json:"title"`
71 LazyLoad bool `json:"lazyLoad"` 80 LazyLoad bool `json:"lazyLoad"`
72 InlineEdit bool `json:"inlineEdit"` 81 InlineEdit bool `json:"inlineEdit"`
73 Options ListOptions `json:"options"` 82 Options ListOptions `json:"options"`
74 Filters []ListFilter `json:"defaultFilters"` 83 Filters []ListFilter `json:"defaultFilters"`
75 Graphs []ListGraph `json:"graphs"` 84 Graphs []ListGraph `json:"graphs"`
76 Actions ListActions `json:"actions"` 85 Actions ListActions `json:"actions"`
77 Parent []ListParentNode `json:"parent"` 86 Parent []ListParentNode `json:"parent"`
78 Children []ListChildNode `json:"children"` 87 Children []ListChildNode `json:"children"`
79 Pivots []ListPivot `json:"pivots"` 88 Pivots []ListPivot `json:"pivots"`
80 Details ListDetails `json:"details"` 89 Details ListDetails `json:"details"`
81 } 90 }
82 91
92 func GetListConfig(db *ora.Ses, objType string) (ListConfig, error) {
93 resp := NewDefaultList(objType)
94 var err error
95
96 err = setListParams(db, &resp, objType)
97 resp.Children, err = getListChildren(db, objType)
98 resp.Actions, err = getListActions(db, objType)
99 resp.Filters, err = getListFilters(db, objType)
100 resp.Options, err = getListOptions(db, objType)
101 resp.Parent, err = getListParent(db, objType)
102 resp.Graphs, err = getListGraph(db, objType)
103 resp.Pivots, err = getListPivot(db, objType)
104 resp.Details, err = getListDetails(db, objType)
105
106 if err != nil {
107 return ListConfig{}, err
108 }
109
110 return resp, nil
111 }
112
83 func GetListConfigObjectIdField(db *ora.Ses, otype string) string { 113 func GetListConfigObjectIdField(db *ora.Ses, otype string) string {
84 var resp string 114 var resp string
85 var err error 115 var err error
86 var stmt *ora.Stmt 116 var stmt *ora.Stmt
87 117
88 stmt, err = db.Prep(`SELECT 118 stmt, err = db.Prep(`SELECT
89 ID_FIELD 119 ID_FIELD
90 FROM LIST_CONFIG_ID_FIELD 120 FROM LIST_CONFIG_ID_FIELD
91 WHERE OBJECT_TYPE = '` + otype + `'`, 121 WHERE OBJECT_TYPE = '` + otype + `'`,
92 ora.S) 122 ora.S)
93 123
94 defer stmt.Close() 124 defer stmt.Close()
95 125
96 if err != nil { 126 if err != nil {
97 return "" 127 return ""
98 } 128 }
99 129
100 rset, err := stmt.Qry() 130 rset, err := stmt.Qry()
101 if rset.Next() { 131 if rset.Next() {
102 resp = rset.Row[0].(string) 132 resp = rset.Row[0].(string)
103 } 133 }
104 134
105 if rset.Err != nil { 135 if rset.Err != nil {
106 return "" 136 return ""
107 } 137 }
108 138
109 return resp 139 return resp
110 } 140 }
111 141
112 func NewDefaultList(objType string) ListConfig { 142 func NewDefaultList(objType string) ListConfig {
113 list := ListConfig{ 143 list := ListConfig{
114 ObjectType: objType, 144 ObjectType: objType,
115 Title: objType, 145 Title: objType,
116 LazyLoad: false, 146 LazyLoad: false,
117 Options: ListOptions{ 147 Options: ListOptions{
118 GlobalFilter: true, 148 GlobalFilter: true,
119 LocalFilters: true, 149 LocalFilters: true,
120 RemoteFilters: false, 150 RemoteFilters: false,
121 Pagination: true, 151 Pagination: true,
122 PageSize: 20, 152 PageSize: 20,
123 }, 153 },
124 Filters: nil, 154 Filters: nil,
125 Actions: ListActions{ 155 Actions: ListActions{
126 Create: false, 156 Create: false,
127 Update: false, 157 Update: false,
128 Delete: false, 158 Delete: false,
129 Export: false, 159 Export: false,
130 Print: false, 160 Print: false,
131 Graph: false, 161 Graph: false,
132 }, 162 },
133 Parent: nil, 163 Parent: nil,
134 Children: nil, 164 Children: nil,
135 } 165 }
136 166
137 return list 167 return list
138 } 168 }
139 169
140 func GetListConfig(db *ora.Ses, objType string) (ListConfig, error) {
141 resp := NewDefaultList(objType)
142 var err error
143
144 err = setListParams(db, &resp, objType)
145 resp.Children, err = getListChildren(db, objType)
146 resp.Actions, err = getListActions(db, objType)
147 resp.Filters, err = getListFilters(db, objType)
148 resp.Options, err = getListOptions(db, objType)
149 resp.Parent, err = getListParent(db, objType)
150 resp.Graphs, err = getListGraph(db, objType)
151 resp.Pivots, err = getListPivot(db, objType)
152 resp.Details, err = getListDetails(db, objType)
153
154 if err != nil {
155 return ListConfig{}, err
156 }
157
158 return resp, nil
159 }
160
161 func setListParams(db *ora.Ses, list *ListConfig, objType string) error { 170 func setListParams(db *ora.Ses, list *ListConfig, objType string) error {
162 var err error 171 var err error
163 var stmt *ora.Stmt 172 var stmt *ora.Stmt
164 query := `SELECT 173 query := `SELECT
165 OBJECT_TYPE, TITLE, LAZY_LOAD, INLINE_EDIT 174 OBJECT_TYPE, TITLE, LAZY_LOAD, INLINE_EDIT
166 FROM LIST_CONFIG 175 FROM LIST_CONFIG
167 WHERE OBJECT_TYPE = '` + objType + `'` 176 WHERE OBJECT_TYPE = '` + objType + `'`
168 177
169 stmt, err = db.Prep(query, ora.S, ora.S, ora.U32, ora.U32) 178 stmt, err = db.Prep(query, ora.S, ora.S, ora.U32, ora.U32)
170 if err != nil { 179 if err != nil {
171 return err 180 return err
172 } 181 }
173 defer stmt.Close() 182 defer stmt.Close()
174 183
175 rset, err := stmt.Qry() 184 rset, err := stmt.Qry()
176 if err != nil { 185 if err != nil {
177 return err 186 return err
178 } 187 }
179 if rset.Next() { 188 if rset.Next() {
180 otype := rset.Row[0].(string) 189 otype := rset.Row[0].(string)
181 if otype != "" { 190 if otype != "" {
182 list.ObjectType = otype 191 list.ObjectType = otype
183 } 192 }
184 193
185 title := rset.Row[1].(string) 194 title := rset.Row[1].(string)
186 if title != "" { 195 if title != "" {
187 list.Title = title 196 list.Title = title
188 } 197 }
189 list.LazyLoad = rset.Row[2].(uint32) != 0 198 list.LazyLoad = rset.Row[2].(uint32) != 0
190 list.InlineEdit = rset.Row[3].(uint32) != 0 199 list.InlineEdit = rset.Row[3].(uint32) != 0
191 } 200 }
192 if rset.Err != nil { 201 if rset.Err != nil {
193 return rset.Err 202 return rset.Err
194 } 203 }
195 return nil 204 return nil
196 } 205 }
197 206
198 func getListChildren(db *ora.Ses, objType string) ([]ListChildNode, error) { 207 func getListChildren(db *ora.Ses, objType string) ([]ListChildNode, error) {
199 resp := make([]ListChildNode, 0) 208 resp := make([]ListChildNode, 0)
200 var err error 209 var err error
201 var stmt *ora.Stmt 210 var stmt *ora.Stmt
202 query := `SELECT 211 query := `SELECT
203 OBJECT_TYPE, LABEL, ICON 212 OBJECT_TYPE, LABEL, ICON
204 FROM LIST_CONFIG_CHILD 213 FROM LIST_CONFIG_CHILD
205 WHERE PARENT_OBJECT_TYPE = '` + objType + `'` 214 WHERE PARENT_OBJECT_TYPE = '` + objType + `'`
206 215
207 stmt, err = db.Prep(query, ora.S, ora.S, ora.S) 216 stmt, err = db.Prep(query, ora.S, ora.S, ora.S)
208 if err != nil { 217 if err != nil {
209 return resp, err 218 return resp, err
210 } 219 }
211 defer stmt.Close() 220 defer stmt.Close()
212 221
213 rset, err := stmt.Qry() 222 rset, err := stmt.Qry()
214 if err != nil { 223 if err != nil {
215 return resp, err 224 return resp, err
216 } 225 }
217 for rset.Next() { 226 for rset.Next() {
218 resp = append(resp, ListChildNode{ 227 resp = append(resp, ListChildNode{
219 ObjectType: rset.Row[0].(string), 228 ObjectType: rset.Row[0].(string),
220 LabelField: rset.Row[1].(string), 229 LabelField: rset.Row[1].(string),
221 Icon: rset.Row[2].(string), 230 Icon: rset.Row[2].(string),
222 }) 231 })
223 } 232 }
224 if rset.Err != nil { 233 if rset.Err != nil {
225 return nil, rset.Err 234 return nil, rset.Err
226 } 235 }
227 236
228 return resp, nil 237 return resp, nil
229 } 238 }
230 239
231 func getListActions(db *ora.Ses, objType string) (ListActions, error) { 240 func getListActions(db *ora.Ses, objType string) (ListActions, error) {
232 var resp ListActions 241 var resp ListActions
233 var err error 242 var err error
234 var stmt *ora.Stmt 243 var stmt *ora.Stmt
235 query := `SELECT 244 query := `SELECT
236 ACTION_CREATE, ACTION_UPDATE, ACTION_DELETE, ACTION_EXPORT, 245 ACTION_CREATE, ACTION_UPDATE, ACTION_DELETE, ACTION_EXPORT,
237 ACTION_PRINT, ACTION_GRAPH 246 ACTION_PRINT, ACTION_GRAPH
238 FROM LIST_CONFIG 247 FROM LIST_CONFIG
239 WHERE OBJECT_TYPE = '` + objType + `'` 248 WHERE OBJECT_TYPE = '` + objType + `'`
240 249
241 stmt, err = db.Prep(query, ora.U32, ora.U32, ora.U32, ora.U32, 250 stmt, err = db.Prep(query, ora.U32, ora.U32, ora.U32, ora.U32,
242 ora.U32, ora.U32) 251 ora.U32, ora.U32)
243 if err != nil { 252 if err != nil {
244 return ListActions{}, err 253 return ListActions{}, err
245 } 254 }
246 defer stmt.Close() 255 defer stmt.Close()
247 256
248 rset, err := stmt.Qry() 257 rset, err := stmt.Qry()
249 if err != nil { 258 if err != nil {
250 return ListActions{}, err 259 return ListActions{}, err
251 } 260 }
252 if rset.Next() { 261 if rset.Next() {
253 resp.Create = rset.Row[0].(uint32) != 0 262 resp.Create = rset.Row[0].(uint32) != 0
254 resp.Update = rset.Row[1].(uint32) != 0 263 resp.Update = rset.Row[1].(uint32) != 0
255 resp.Delete = rset.Row[2].(uint32) != 0 264 resp.Delete = rset.Row[2].(uint32) != 0
256 resp.Export = rset.Row[3].(uint32) != 0 265 resp.Export = rset.Row[3].(uint32) != 0
257 resp.Print = rset.Row[4].(uint32) != 0 266 resp.Print = rset.Row[4].(uint32) != 0
258 resp.Graph = rset.Row[5].(uint32) != 0 267 resp.Graph = rset.Row[5].(uint32) != 0
259 } 268 }
260 if rset.Err != nil { 269 if rset.Err != nil {
261 return ListActions{}, rset.Err 270 return ListActions{}, rset.Err
262 } 271 }
263 return resp, nil 272 return resp, nil
264 } 273 }
265 274
266 func getListFilters(db *ora.Ses, objType string) ([]ListFilter, error) { 275 func getListFilters(db *ora.Ses, objType string) ([]ListFilter, error) {
267 resp := make([]ListFilter, 0) 276 resp := make([]ListFilter, 0)
268 filtersField, err := getFilterFields(db, objType) 277 filtersField, err := getFilterFields(db, objType)
269 if err != nil { 278 if err != nil {
270 return nil, err 279 return nil, err
271 } 280 }
272 for _, field := range filtersField { 281 for _, field := range filtersField {
273 filters, _ := getFiltersByFilterField(db, field) 282 filters, _ := getFiltersByFilterField(db, field)
274 for _, filter := range filters { 283 for _, filter := range filters {
275 resp = append(resp, ListFilter{ 284 var f ListFilter
276 ObjectType: objType, 285 f.ObjectType = objType
277 FiltersField: field, 286 f.FiltersField = field
278 DefaultValues: filter.DefaultValues, 287 f.DefaultValues = filter.DefaultValues
279 FiltersLabel: filter.Label, 288 f.FiltersLabel = filter.Label
280 FiltersType: filter.Type, 289 f.FiltersType = filter.Type
281 }) 290 if filter.Type == "dropdown" {
291 f.DropdownConfig, err = getFilterDropdownConfig(db, field)
292 if err != nil {
293 return nil, err
294 }
295 }
296 resp = append(resp, f)
282 } 297 }
283 } 298 }
284 299
285 return resp, nil 300 return resp, nil
286 } 301 }
287 302
288 func getFilterFields(db *ora.Ses, objType string) ([]string, error) { 303 func getFilterFields(db *ora.Ses, objType string) ([]string, error) {
289 filtersField := make([]string, 0) 304 filtersField := make([]string, 0)
290 var err error 305 var err error
291 var stmt *ora.Stmt 306 var stmt *ora.Stmt
292 query := `SELECT 307 query := `SELECT
293 FILTERS_FIELD 308 FILTERS_FIELD
294 FROM LIST_CONFIG_FILTERS 309 FROM LIST_CONFIG_FILTERS
295 WHERE OBJECT_TYPE = '` + objType + `'` 310 WHERE OBJECT_TYPE = '` + objType + `'`
296 311
297 stmt, err = db.Prep(query, ora.S) 312 stmt, err = db.Prep(query, ora.S)
298 if err != nil { 313 if err != nil {
299 return nil, err 314 return nil, err
300 } 315 }
301 defer stmt.Close() 316 defer stmt.Close()
302 317
303 rset, err := stmt.Qry() 318 rset, err := stmt.Qry()
304 if err != nil { 319 if err != nil {
305 return nil, err 320 return nil, err
306 } 321 }
307 for rset.Next() { 322 for rset.Next() {
308 filtersField = append(filtersField, rset.Row[0].(string)) 323 filtersField = append(filtersField, rset.Row[0].(string))
309 } 324 }
310 if rset.Err != nil { 325 if rset.Err != nil {
311 return nil, rset.Err 326 return nil, rset.Err
312 } 327 }
313 return filtersField, nil 328 return filtersField, nil
314 } 329 }
315 330
316 type TempFilter struct { 331 type TempFilter struct {
317 DefaultValues string 332 DefaultValues string
318 Label string 333 Label string
319 Type string 334 Type string
320 } 335 }
321 336
322 func getFiltersByFilterField(db *ora.Ses, filtersField string) ([]TempFilter, error) { 337 func getFiltersByFilterField(db *ora.Ses, filtersField string) ([]TempFilter, error) {
323 resp := make([]TempFilter, 0) 338 resp := make([]TempFilter, 0)
324 var err error 339 var err error
325 var stmt *ora.Stmt 340 var stmt *ora.Stmt
326 query := `SELECT 341 query := `SELECT
327 FILTERS_TYPE, FILTERS_LABEL, DEFAULT_VALUES 342 FILTERS_TYPE, FILTERS_LABEL, DEFAULT_VALUES
328 FROM LIST_FILTERS_FIELD 343 FROM LIST_FILTERS_FIELD
329 WHERE FILTERS_FIELD = '` + filtersField + `'` 344 WHERE FILTERS_FIELD = '` + filtersField + `'`
330 345
331 stmt, err = db.Prep(query, ora.S, ora.S, ora.S) 346 stmt, err = db.Prep(query, ora.S, ora.S, ora.S)
332 if err != nil { 347 if err != nil {
333 return resp, err 348 return resp, err
334 } 349 }
335 defer stmt.Close() 350 defer stmt.Close()
336 351
337 rset, err := stmt.Qry() 352 rset, err := stmt.Qry()
338 if err != nil { 353 if err != nil {
339 return resp, err 354 return resp, err
340 } 355 }
341 for rset.Next() { 356 for rset.Next() {
342 resp = append(resp, TempFilter{ 357 resp = append(resp, TempFilter{
343 Type: rset.Row[0].(string), 358 Type: rset.Row[0].(string),
344 Label: rset.Row[1].(string), 359 Label: rset.Row[1].(string),
345 DefaultValues: rset.Row[2].(string), 360 DefaultValues: rset.Row[2].(string),
346 }) 361 })
347 } 362 }
348 if rset.Err != nil { 363 if rset.Err != nil {
349 return resp, rset.Err 364 return resp, rset.Err
350 } 365 }
351 return resp, nil 366 return resp, nil
352 } 367 }
353 368
369 func getFilterDropdownConfig(db *ora.Ses, filtersField string) (Dropdown, error) {
370 var resp Dropdown
371 var err error
372 var stmt *ora.Stmt
373 query := `SELECT
374 FILTERS_FIELD, OBJECT_TYPE, ID_FIELD, LABEL_FIELD
375 FROM LIST_DROPDOWN_FILTER
376 WHERE FILTERS_FIELD = '` + filtersField + `'`
377
378 stmt, err = db.Prep(query, ora.S, ora.S, ora.S, ora.S)
379 if err != nil {
380 return resp, err
381 }
382 defer stmt.Close()
383
384 rset, err := stmt.Qry()
385 if err != nil {
386 return resp, err
387 }
388 if rset.Next() {
389 resp.FiltersField = rset.Row[0].(string)
390 resp.ObjectType = rset.Row[1].(string)
391 resp.IdField = rset.Row[2].(string)
392 resp.LabelField = rset.Row[3].(string)
393 }
394 if rset.Err != nil {
395 return resp, rset.Err
396 }
397 return resp, nil
398 }
399
354 func getListGraph(db *ora.Ses, objType string) ([]ListGraph, error) { 400 func getListGraph(db *ora.Ses, objType string) ([]ListGraph, error) {
355 resp := make([]ListGraph, 0) 401 resp := make([]ListGraph, 0)
356 var err error 402 var err error
357 var stmt *ora.Stmt 403 var stmt *ora.Stmt
358 query := `SELECT 404 query := `SELECT
359 OBJECT_TYPE, X_FIELD, Y_FIELD, GROUP_FIELD, LABEL 405 OBJECT_TYPE, X_FIELD, Y_FIELD, GROUP_FIELD, LABEL
360 FROM LIST_GRAPHS 406 FROM LIST_GRAPHS
361 WHERE OBJECT_TYPE = '` + objType + `'` 407 WHERE OBJECT_TYPE = '` + objType + `'`
362 408
363 stmt, err = db.Prep(query, ora.S, ora.S, ora.S, ora.S) 409 stmt, err = db.Prep(query, ora.S, ora.S, ora.S, ora.S)
364 if err != nil { 410 if err != nil {
365 return resp, err 411 return resp, err
366 } 412 }
367 defer stmt.Close() 413 defer stmt.Close()
368 414
369 rset, err := stmt.Qry() 415 rset, err := stmt.Qry()
370 if err != nil { 416 if err != nil {
371 return resp, err 417 return resp, err
372 } 418 }
373 for rset.Next() { 419 for rset.Next() {
374 resp = append(resp, ListGraph{ 420 resp = append(resp, ListGraph{
375 ObjectType: rset.Row[0].(string), 421 ObjectType: rset.Row[0].(string),
376 X: rset.Row[1].(string), 422 X: rset.Row[1].(string),
377 Y: rset.Row[2].(string), 423 Y: rset.Row[2].(string),
378 GroupField: rset.Row[3].(string), 424 GroupField: rset.Row[3].(string),
379 Label: rset.Row[4].(string), 425 Label: rset.Row[4].(string),
380 }) 426 })
381 } 427 }
382 if rset.Err != nil { 428 if rset.Err != nil {
383 return resp, rset.Err 429 return resp, rset.Err
384 } 430 }
385 return resp, nil 431 return resp, nil
386 } 432 }
387 433
388 func getListOptions(db *ora.Ses, objType string) (ListOptions, error) { 434 func getListOptions(db *ora.Ses, objType string) (ListOptions, error) {
389 var resp ListOptions 435 var resp ListOptions
390 var err error 436 var err error
391 var stmt *ora.Stmt 437 var stmt *ora.Stmt
392 query := `SELECT 438 query := `SELECT
393 GLOBAL_FILTER, LOCAL_FILTER, REMOTE_FILTER, PAGINATION, 439 GLOBAL_FILTER, LOCAL_FILTER, REMOTE_FILTER, PAGINATION,
394 PAGE_SIZE, PIVOT, DETAIL 440 PAGE_SIZE, PIVOT, DETAIL
395 FROM LIST_CONFIG 441 FROM LIST_CONFIG
396 WHERE OBJECT_TYPE = '` + objType + `'` 442 WHERE OBJECT_TYPE = '` + objType + `'`
397 443
398 stmt, err = db.Prep(query, ora.U32, ora.U32, ora.U32, ora.U32, 444 stmt, err = db.Prep(query, ora.U32, ora.U32, ora.U32, ora.U32,
399 ora.U64, ora.U64, ora.U32) 445 ora.U64, ora.U64, ora.U32)
400 if err != nil { 446 if err != nil {
401 return ListOptions{}, err 447 return ListOptions{}, err
402 } 448 }
403 defer stmt.Close() 449 defer stmt.Close()
404 450
405 rset, err := stmt.Qry() 451 rset, err := stmt.Qry()
406 if err != nil { 452 if err != nil {
407 return ListOptions{}, err 453 return ListOptions{}, err
408 } 454 }
409 if rset.Next() { 455 if rset.Next() {
410 resp.GlobalFilter = rset.Row[0].(uint32) != 0 456 resp.GlobalFilter = rset.Row[0].(uint32) != 0
411 resp.LocalFilters = rset.Row[1].(uint32) != 0 457 resp.LocalFilters = rset.Row[1].(uint32) != 0
412 resp.RemoteFilters = rset.Row[2].(uint32) != 0 458 resp.RemoteFilters = rset.Row[2].(uint32) != 0
413 resp.Pagination = rset.Row[3].(uint32) != 0 459 resp.Pagination = rset.Row[3].(uint32) != 0
414 resp.PageSize = rset.Row[4].(uint64) 460 resp.PageSize = rset.Row[4].(uint64)
415 resp.Pivot = rset.Row[5].(uint64) != 0 461 resp.Pivot = rset.Row[5].(uint64) != 0
416 resp.Detail = rset.Row[6].(uint32) != 0 462 resp.Detail = rset.Row[6].(uint32) != 0
417 } 463 }
418 if rset.Err != nil { 464 if rset.Err != nil {
419 return ListOptions{}, rset.Err 465 return ListOptions{}, rset.Err
420 } 466 }
421 return resp, nil 467 return resp, nil
422 } 468 }
423 469
424 func getListParent(db *ora.Ses, objType string) ([]ListParentNode, error) { 470 func getListParent(db *ora.Ses, objType string) ([]ListParentNode, error) {
425 resp := make([]ListParentNode, 0) 471 resp := make([]ListParentNode, 0)
426 var err error 472 var err error
427 var stmt *ora.Stmt 473 var stmt *ora.Stmt
428 query := `SELECT 474 query := `SELECT
429 PARENT_OBJECT_TYPE, PARENT_LABEL_FIELD, PARENT_FILTER_FIELD 475 PARENT_OBJECT_TYPE, PARENT_LABEL_FIELD, PARENT_FILTER_FIELD
430 FROM LIST_CONFIG_CHILD 476 FROM LIST_CONFIG_CHILD
431 WHERE OBJECT_TYPE = '` + objType + `'` 477 WHERE OBJECT_TYPE = '` + objType + `'`
432 478
433 stmt, err = db.Prep(query, ora.S, ora.S, ora.S) 479 stmt, err = db.Prep(query, ora.S, ora.S, ora.S)
434 if err != nil { 480 if err != nil {
435 return resp, err 481 return resp, err
436 } 482 }
437 defer stmt.Close() 483 defer stmt.Close()
438 484
439 rset, err := stmt.Qry() 485 rset, err := stmt.Qry()
440 if err != nil { 486 if err != nil {
441 return resp, err 487 return resp, err
442 } 488 }
443 for rset.Next() { 489 for rset.Next() {
444 resp = append(resp, ListParentNode{ 490 resp = append(resp, ListParentNode{
445 ObjectType: rset.Row[0].(string), 491 ObjectType: rset.Row[0].(string),
446 LabelField: rset.Row[1].(string), 492 LabelField: rset.Row[1].(string),
447 FilterField: rset.Row[2].(string), 493 FilterField: rset.Row[2].(string),
448 }) 494 })
449 } 495 }
450 if rset.Err != nil { 496 if rset.Err != nil {
451 return nil, rset.Err 497 return nil, rset.Err
452 } 498 }
453 499
454 return resp, nil 500 return resp, nil
455 } 501 }
456 502
457 func getListPivot(db *ora.Ses, objType string) ([]ListPivot, error) { 503 func getListPivot(db *ora.Ses, objType string) ([]ListPivot, error) {
458 resp := make([]ListPivot, 0) 504 resp := make([]ListPivot, 0)
459 var err error 505 var err error
460 var stmt *ora.Stmt 506 var stmt *ora.Stmt
461 query := `SELECT 507 query := `SELECT
462 OBJECT_TYPE, GROUP_FIELD, DISTINCT_FIELD, VALUE_FIELD 508 OBJECT_TYPE, GROUP_FIELD, DISTINCT_FIELD, VALUE_FIELD
463 FROM LIST_PIVOTS 509 FROM LIST_PIVOTS
464 WHERE OBJECT_TYPE = '` + objType + `'` 510 WHERE OBJECT_TYPE = '` + objType + `'`
465 511
466 stmt, err = db.Prep(query, ora.S, ora.S, ora.S, ora.S) 512 stmt, err = db.Prep(query, ora.S, ora.S, ora.S, ora.S)
467 if err != nil { 513 if err != nil {
468 return resp, err 514 return resp, err
469 } 515 }
470 defer stmt.Close() 516 defer stmt.Close()
471 517
472 rset, err := stmt.Qry() 518 rset, err := stmt.Qry()
473 if err != nil { 519 if err != nil {
474 return resp, err 520 return resp, err
475 } 521 }
476 for rset.Next() { 522 for rset.Next() {
477 resp = append(resp, ListPivot{ 523 resp = append(resp, ListPivot{
478 ObjectType: rset.Row[0].(string), 524 ObjectType: rset.Row[0].(string),
479 GroupField: rset.Row[1].(string), 525 GroupField: rset.Row[1].(string),
480 DistinctField: rset.Row[2].(string), 526 DistinctField: rset.Row[2].(string),
481 Value: rset.Row[3].(string), 527 Value: rset.Row[3].(string),
482 }) 528 })
483 } 529 }
484 if rset.Err != nil { 530 if rset.Err != nil {
485 return nil, rset.Err 531 return nil, rset.Err
486 } 532 }
487 533
488 return resp, nil 534 return resp, nil
489 } 535 }
490 536
491 func getListDetails(db *ora.Ses, objType string) (ListDetails, error) { 537 func getListDetails(db *ora.Ses, objType string) (ListDetails, error) {
492 var resp ListDetails 538 var resp ListDetails
493 var err error 539 var err error
494 var stmt *ora.Stmt 540 var stmt *ora.Stmt
495 query := `SELECT 541 query := `SELECT
496 OBJECT_TYPE, PARENT_OBJECT_TYPE, PARENT_FILTER_FIELD, SINGLE_DETAIL 542 OBJECT_TYPE, PARENT_OBJECT_TYPE, PARENT_FILTER_FIELD, SINGLE_DETAIL
497 FROM LIST_CONFIG_DETAIL 543 FROM LIST_CONFIG_DETAIL
498 WHERE PARENT_OBJECT_TYPE = '` + objType + `'` 544 WHERE PARENT_OBJECT_TYPE = '` + objType + `'`
499 545
500 stmt, err = db.Prep(query, ora.S, ora.S, ora.S, ora.U32) 546 stmt, err = db.Prep(query, ora.S, ora.S, ora.S, ora.U32)
501 if err != nil { 547 if err != nil {