github.com/mdaxf/iac@v0.0.0-20240519030858-58a061660378/controllers/databaseop/databaseop.go (about)

     1  package databaseop
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"reflect"
     7  	"strings"
     8  	"time"
     9  
    10  	//"log"
    11  	"net/http"
    12  
    13  	"github.com/gin-gonic/gin"
    14  
    15  	"github.com/mdaxf/iac/controllers/common"
    16  	dbconn "github.com/mdaxf/iac/databases"
    17  	"github.com/mdaxf/iac/logger"
    18  )
    19  
    20  type DBController struct {
    21  }
    22  
    23  type DBData struct {
    24  	TableName  string                 `json."tablename"` // table name
    25  	Data       map[string]interface{} `json."data"`
    26  	Operation  string                 `json."operation"` // insert, update, delete
    27  	Keys       []string               `json."keys"`      // keys for update and delete
    28  	Where      map[string]interface{} `json."where"`     // where args for update and delete
    29  	NullValues map[string]interface{} `json."nullvalues"`
    30  	QueryStr   string                 `json."querystr"` // query string for query
    31  }
    32  
    33  type QueryInput struct {
    34  	QueryStr string `json."querystr"` // query string for query
    35  }
    36  
    37  // GetDatabyQuery retrieves data from the database based on the provided query.
    38  // It expects a JSON request body containing the query information.
    39  // The function returns the retrieved data as a JSON response.
    40  
    41  func (db *DBController) GetDatabyQuery(ctx *gin.Context) {
    42  	iLog := logger.Log{ModuleName: logger.API, User: "System", ControllerName: "GetDatabyQuery"}
    43  	startTime := time.Now()
    44  
    45  	defer func() {
    46  		elapsed := time.Since(startTime)
    47  		iLog.PerformanceWithDuration("controllers.databaseop.GetDatabyQuery", elapsed)
    48  	}()
    49  	/*
    50  		defer func() {
    51  			if err := recover(); err != nil {
    52  				iLog.Error(fmt.Sprintf("Get data by query error: %s", err))
    53  				ctx.JSON(http.StatusBadRequest, gin.H{"error": err})
    54  			}
    55  		}()
    56  
    57  		_, user, clientid, err := common.GetRequestUser(ctx)
    58  		if err != nil {
    59  			iLog.Error(fmt.Sprintf("GetDataFromRequest error: %s", err.Error()))
    60  			ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
    61  		}
    62  
    63  		iLog.ClientID = clientid
    64  		iLog.User = user
    65  		iLog.Debug(fmt.Sprintf("Get data by query"))
    66  
    67  		var data QueryInput
    68  		body, err := common.GetRequestBody(ctx)
    69  		if err != nil {
    70  			ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
    71  			return
    72  		}
    73  	*/
    74  	body, clientid, user, err := common.GetRequestBodyandUser(ctx)
    75  	if err != nil {
    76  		iLog.Error(fmt.Sprintf("Error reading body: %v", err))
    77  		ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
    78  		return
    79  	}
    80  	iLog.ClientID = clientid
    81  	iLog.User = user
    82  
    83  	var data QueryInput
    84  
    85  	iLog.Debug(fmt.Sprintf("GetDatabyQuery from respository with body: %s", body))
    86  
    87  	err = json.Unmarshal(body, &data)
    88  	if err != nil {
    89  		iLog.Error(fmt.Sprintf("GetDataFromRequest Unmarshal error: %s", err.Error()))
    90  		ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
    91  		return
    92  	}
    93  	iLog.Debug(fmt.Sprintf("GetDataFromRequest data: %s", data))
    94  
    95  	if err != nil {
    96  		iLog.Error(fmt.Sprintf("Get data by query error: %s", err.Error()))
    97  		ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
    98  		return
    99  	}
   100  	iLog.Debug(fmt.Sprintf("Get data by query: %s", data.QueryStr))
   101  	Query := data.QueryStr
   102  	// get data from database
   103  	result, err := dbconn.NewDBOperation("system", nil, "Execute Query Function").Query_Json(Query)
   104  
   105  	if err != nil {
   106  		iLog.Error(fmt.Sprintf("Get data from table error: %s", err.Error()))
   107  		ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
   108  		return
   109  	}
   110  	iLog.Debug(fmt.Sprintf("Get data from table result: %s", gin.H{"data": result}))
   111  	//jsondata, err := json.Marshal(result)
   112  
   113  	ctx.JSON(http.StatusOK, gin.H{"data": result})
   114  }
   115  
   116  /*
   117  	{
   118  	    "tablename": "EMPLOYEE",
   119  	    "data": {
   120  	        "EMPLOYEE":{
   121  	            "fields":["ID", "Name", "LoginName"],
   122  	            "subtables":{
   123  	                "EMPLOYEE_ROLE":{
   124  	                    "fields":[],
   125  	                    "links":["EMPLOYEE_ROLE.EmployeeID = EMPLOYEE.ID"],
   126  	                    "subtables": {
   127  	                        "ROLE":{
   128  	                            "fields":["ID As RoleID", "ROLE"],
   129  	                            "links": ["ROLE.ID = EMPLOYEE_ROLE.RoleID"]
   130  	                        }
   131  	                    }
   132  	                }
   133  	            }
   134  	        },
   135  	        "RESOURCE_":["facility", "productionline"]
   136  	    },
   137  	    "operation": "detail",
   138  	    "where": {
   139  	        "EMPLOYEE.ResourceID = RESOURCE_.ID":""
   140  
   141  
   142  	    }
   143  	}
   144  */
   145  
   146  // GetDataFromTables retrieves data from tables based on the request parameters.
   147  // It first extracts the user and client ID from the request context.
   148  // Then it calls GetDataFromRequest to get the data structure from the request body.
   149  // It constructs a query based on the data structure, user, client ID, and where conditions.
   150  // Finally, it executes the query and returns the result as JSON.
   151  
   152  func (db *DBController) GetDataFromTables(ctx *gin.Context) {
   153  	iLog := logger.Log{ModuleName: logger.API, User: "System", ControllerName: "GetDataFromTable"}
   154  	startTime := time.Now()
   155  
   156  	defer func() {
   157  		elapsed := time.Since(startTime)
   158  		iLog.PerformanceWithDuration("controllers.databaseop.GetDataFromTables", elapsed)
   159  	}()
   160  
   161  	/*	defer func() {
   162  		if err := recover(); err != nil {
   163  			iLog.Error(fmt.Sprintf("Get data from tables error: %s", err))
   164  			ctx.JSON(http.StatusBadRequest, gin.H{"error": err})
   165  		}
   166  	}()  */
   167  	_, user, clientid, err := common.GetRequestUser(ctx)
   168  	if err != nil {
   169  		iLog.Error(fmt.Sprintf("GetDataFromRequest error: %s", err.Error()))
   170  		ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
   171  	}
   172  
   173  	iLog.ClientID = clientid
   174  	iLog.User = user
   175  	iLog.Debug(fmt.Sprintf("Get data from table"))
   176  
   177  	data, err := db.GetDataFromRequest(ctx)
   178  	if err != nil {
   179  		iLog.Error(fmt.Sprintf("Get data from table error: %s", err.Error()))
   180  		ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
   181  		return
   182  	}
   183  	iLog.Debug(fmt.Sprintf("Get data from table: %s", data.TableName))
   184  
   185  	Query, TableNames, err := db.getDataStructForQuery(data.Data, user, clientid)
   186  	Wherestr := ""
   187  	iLog.Debug(fmt.Sprintf("get where condition: %s", data.Where))
   188  	for key, value := range data.Where {
   189  		iLog.Debug(fmt.Sprintf("get where condition: %s %s", key, value))
   190  		if value == "" {
   191  			Wherestr = fmt.Sprintf("%s %s ", Wherestr, key)
   192  		} else {
   193  			Wherestr = fmt.Sprintf("%s %s='%s'", Wherestr, key, value)
   194  		}
   195  	}
   196  	if Wherestr != "" {
   197  		Query = fmt.Sprintf("SELECT %s from %s where %s", Query, TableNames, Wherestr)
   198  	} else {
   199  		Query = fmt.Sprintf("SELECT %s from %s", Query, TableNames)
   200  	}
   201  	iLog.Debug(fmt.Sprintf("Get data from query: %s", Query))
   202  
   203  	// get data from database
   204  
   205  	result, err := dbconn.NewDBOperation("system", nil, "Execute Query Function").Query_Json(Query)
   206  
   207  	if err != nil {
   208  		iLog.Error(fmt.Sprintf("Get data from table error: %s", err.Error()))
   209  		ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
   210  		return
   211  	}
   212  	iLog.Debug(fmt.Sprintf("Get data from table result: %s", gin.H{"data": result}))
   213  	//jsondata, err := json.Marshal(result)
   214  
   215  	ctx.JSON(http.StatusOK, gin.H{"data": result})
   216  }
   217  
   218  // getDataStructForQuery retrieves the data structure and table name for a given query.
   219  // It takes a map of data, user string, and client ID string as input parameters.
   220  // It returns the query string, table name string, and an error if any.
   221  
   222  func (db *DBController) getDataStructForQuery(data map[string]interface{}, user string, clientid string) (string, string, error) {
   223  	iLog := logger.Log{ModuleName: logger.API, User: user, ClientID: clientid, ControllerName: "GetDataFromTable"}
   224  	/*	startTime := time.Now()
   225  		defer func() {
   226  			elapsed := time.Since(startTime)
   227  			iLog.PerformanceWithDuration("controllers.databaseop.getDataStructForQuery", elapsed)
   228  		}()
   229  
   230  		defer func() {
   231  			if err := recover(); err != nil {
   232  				iLog.Error(fmt.Sprintf("Get data struct for query error: %s", err))
   233  			}
   234  		}()
   235  	*/
   236  	iLog.Debug(fmt.Sprintf("get data struct for query"))
   237  	Query := ""
   238  	TableName := ""
   239  	for k, v := range data {
   240  		tablename := k
   241  		if TableName != "" {
   242  			TableName = fmt.Sprintf(" %s INNER JOIN %s ON 1=1 ", TableName, tablename)
   243  		} else {
   244  			TableName = fmt.Sprintf(" %s ", tablename)
   245  		}
   246  
   247  		// get table schema
   248  		var fields []string
   249  		if itemList, ok := v.([]interface{}); ok {
   250  			for _, field := range itemList {
   251  				fields = append(fields, field.(string))
   252  				if Query != "" {
   253  					Query = fmt.Sprintf("%s, %s.%s", Query, tablename, field.(string))
   254  				} else {
   255  					Query = fmt.Sprintf("%s %s.%s", Query, tablename, field.(string))
   256  				}
   257  			}
   258  
   259  		} else {
   260  			if item, ok := v.(map[string]interface{}); ok {
   261  
   262  				subquery, tablelinks, err := db.getmysqlsubtabls(tablename, item, false, user, clientid)
   263  				if err != nil {
   264  					return "", "", err
   265  				}
   266  				if Query != "" {
   267  					Query = fmt.Sprintf("%s, %s", Query, subquery)
   268  				} else {
   269  
   270  					Query = subquery
   271  				}
   272  
   273  				TableName = fmt.Sprintf("%s %s", TableName, tablelinks)
   274  			}
   275  		}
   276  
   277  	}
   278  	iLog.Debug(fmt.Sprintf("getDataStructForQuery Query: %s, %s", Query, TableName))
   279  	return strings.TrimRight(Query, ","), strings.TrimRight(TableName, ","), nil
   280  }
   281  
   282  // getmysqlsubtabls is a function that retrieves data from a MySQL table and its subtables.
   283  // It takes the following parameters:
   284  // - tablename: the name of the table to retrieve data from.
   285  // - data: a map containing additional data for the query, such as fields, subtables, and links.
   286  // - markasJson: a boolean indicating whether the result should be marked as JSON.
   287  // - user: the user performing the operation.
   288  // - clientid: the client ID associated with the operation.
   289  // The function returns the query string, table links, and an error (if any).
   290  
   291  func (db *DBController) getmysqlsubtabls(tablename string, data map[string]interface{}, markasJson bool, user string, clientid string) (string, string, error) {
   292  	iLog := logger.Log{ModuleName: logger.API, User: user, ClientID: clientid, ControllerName: "GetDataFromTable"}
   293  	Links := ""
   294  	Query := " "
   295  	TableLinks := ""
   296  	SubQuery := ""
   297  	SubLinks := ""
   298  	for k, v := range data {
   299  		if k == "fields" {
   300  			if itemList, ok := v.([]interface{}); ok {
   301  				for _, field := range itemList {
   302  					Query = fmt.Sprintf("%s %s.%s,", Query, tablename, field.(string))
   303  				}
   304  			}
   305  		} else if k == "subtables" {
   306  			if item, ok := v.(map[string]interface{}); ok {
   307  				for key, value := range item {
   308  					subquery, subtablelink, err := db.getmysqlsubtabls(key, value.(map[string]interface{}), true, user, clientid)
   309  					if err != nil {
   310  						return "", "", err
   311  					}
   312  					SubQuery = fmt.Sprintf("%s %s,", SubQuery, subquery)
   313  					SubLinks = fmt.Sprintf("%s  %s", SubLinks, subtablelink)
   314  				}
   315  			}
   316  		} else if k == "links" {
   317  			if itemList, ok := v.([]interface{}); ok {
   318  				for _, link := range itemList {
   319  					if Links == "" {
   320  						Links = link.(string)
   321  					} else {
   322  						Links = fmt.Sprintf("%s AND %s", Links, link.(string))
   323  					}
   324  				}
   325  			}
   326  		}
   327  	}
   328  
   329  	if SubQuery != "" {
   330  		Query = fmt.Sprintf("%s %s,", Query, SubQuery)
   331  	}
   332  
   333  	Query = strings.TrimRight(Query, ",")
   334  
   335  	if Links != "" && TableLinks != "" {
   336  		TableLinks = fmt.Sprintf("%s INNER JOIN %s ON %s", TableLinks, tablename, Links)
   337  	} else if Links != "" && TableLinks == "" {
   338  		TableLinks = fmt.Sprintf(" INNER JOIN %s ON %s", tablename, Links)
   339  	}
   340  
   341  	if SubLinks != "" {
   342  		TableLinks = fmt.Sprintf("%s  %s", TableLinks, SubLinks)
   343  	}
   344  	/*
   345  		if markasJson {
   346  			if Links != "" {
   347  				Query = fmt.Sprintf("SELECT %s from %s where %s", Query, tablename, Links)
   348  			} else {
   349  				Query = fmt.Sprintf("SELECT %s from %s", Query, tablename)
   350  			}
   351  
   352  			if dbconn.DatabaseType == "sqlserver" {
   353  				Query = fmt.Sprintf("%s FOR JSON PATH", Query)
   354  			} else if dbconn.DatabaseType == "mysql" {
   355  				Query = fmt.Sprintf("SELECT json_agg(t)  FROM ( %s ) t ", Query)
   356  			}
   357  			Query = fmt.Sprintf("(%s ) as \"%s\"", Query, tablename)
   358  		}
   359  	*/
   360  	iLog.Debug(fmt.Sprintf("getsubtabls Query: %s", Query))
   361  	return Query, TableLinks, nil
   362  
   363  }
   364  
   365  // getsubtabls is a recursive function that generates a SQL query for retrieving data from a table and its subtables.
   366  // It takes the table name, data map, markasJson flag, user, and clientid as parameters.
   367  // The function iterates over the data map and constructs the query based on the fields, subtables, and links specified.
   368  // If markasJson is true, the query is formatted to return the result as JSON.
   369  // The function returns the generated SQL query and any error encountered during the process.
   370  
   371  func (db *DBController) getsubtabls(tablename string, data map[string]interface{}, markasJson bool, user string, clientid string) (string, error) {
   372  	iLog := logger.Log{ModuleName: logger.API, User: user, ClientID: clientid, ControllerName: "GetDataFromTable"}
   373  	/*
   374  		"t1": {
   375  							"fields": ["field1", "field2", "field3"],
   376  							"subtables": {
   377  								"t2":{
   378  									"fields": ["field1", "field2", "field3"]   / fields can be empty for link table
   379  									"links": ["t1.field2 = t2.field1"]
   380  									"subtables": {
   381  										"t3":{
   382  											"fields": ["field1", "field2", "field3"]
   383  											"links": ["t2.field2 = t3.field1"]
   384  										}
   385  								},
   386  
   387  							}
   388  						},
   389  	*/
   390  
   391  	Links := ""
   392  	Query := " "
   393  	for k, v := range data {
   394  		if k == "fields" {
   395  			if itemList, ok := v.([]interface{}); ok {
   396  				for _, field := range itemList {
   397  					Query = fmt.Sprintf("%s %s.%s,", Query, tablename, field.(string))
   398  				}
   399  			}
   400  		} else if k == "subtables" {
   401  			if item, ok := v.(map[string]interface{}); ok {
   402  				for key, value := range item {
   403  					subquery, err := db.getsubtabls(key, value.(map[string]interface{}), true, user, clientid)
   404  					if err != nil {
   405  						return "", err
   406  					}
   407  					Query = fmt.Sprintf("%s %s,", Query, subquery)
   408  
   409  				}
   410  			}
   411  		} else if k == "links" {
   412  			if itemList, ok := v.([]interface{}); ok {
   413  				for _, link := range itemList {
   414  					if Links == "" {
   415  						Links = link.(string)
   416  					} else {
   417  						Links = fmt.Sprintf("%s AND %s", Links, link.(string))
   418  					}
   419  				}
   420  			}
   421  		}
   422  	}
   423  
   424  	Query = strings.TrimRight(Query, ",")
   425  
   426  	if markasJson {
   427  		if Links != "" {
   428  			Query = fmt.Sprintf("SELECT %s from %s where %s", Query, tablename, Links)
   429  		} else {
   430  			Query = fmt.Sprintf("SELECT %s from %s", Query, tablename)
   431  		}
   432  
   433  		if dbconn.DatabaseType == "sqlserver" {
   434  			Query = fmt.Sprintf("%s FOR JSON PATH", Query)
   435  		} else if dbconn.DatabaseType == "mysql" {
   436  			Query = fmt.Sprintf("SELECT json_agg(t)  FROM ( %s ) t ", Query)
   437  		}
   438  		Query = fmt.Sprintf("(%s ) as \"%s\"", Query, tablename)
   439  	}
   440  
   441  	iLog.Debug(fmt.Sprintf("getsubtabls Query: %s", Query))
   442  	return Query, nil
   443  }
   444  
   445  // InsertDataToTable inserts data into a table.
   446  // It retrieves the data from the request context and validates it.
   447  // If the table name is empty or there is no data to insert, it returns an error.
   448  // Otherwise, it performs the table insert operation and returns the ID of the inserted data.
   449  
   450  func (db *DBController) InsertDataToTable(ctx *gin.Context) error {
   451  	iLog := logger.Log{ModuleName: logger.API, User: "System", ControllerName: "InsertDataToTables"}
   452  	startTime := time.Now()
   453  	defer func() {
   454  		elapsed := time.Since(startTime)
   455  		iLog.PerformanceWithDuration("controllers.databaseop.InsertDataToTable", elapsed)
   456  	}()
   457  	/*
   458  		defer func() {
   459  			if err := recover(); err != nil {
   460  				iLog.Error(fmt.Sprintf("InsertDataToTable error: %s", err))
   461  				ctx.JSON(http.StatusBadRequest, gin.H{"error": err})
   462  			}
   463  		}()
   464  	*/
   465  	_, user, clientid, err := common.GetRequestUser(ctx)
   466  	if err != nil {
   467  		iLog.Error(fmt.Sprintf("GetDataFromRequest error: %s", err.Error()))
   468  		ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
   469  	}
   470  
   471  	iLog.ClientID = clientid
   472  	iLog.User = user
   473  	iLog.Debug(fmt.Sprintf("Insert data to table"))
   474  	data, err := db.GetDataFromRequest(ctx)
   475  
   476  	if err != nil {
   477  		iLog.Error(fmt.Sprintf("Insert data to table error: %s", err.Error()))
   478  		ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
   479  		return err
   480  	}
   481  
   482  	if data.TableName == "" {
   483  		iLog.Error(fmt.Sprintf("Insert data to table error: %s", "Table name is empty"))
   484  		ctx.JSON(http.StatusBadRequest, gin.H{"error": "Table name is empty"})
   485  		return err
   486  	}
   487  
   488  	iLog.Debug(fmt.Sprintf("Insert data to table: %s", data.TableName))
   489  
   490  	nullvalues := data.NullValues
   491  	fields := []string{}
   492  	values := []string{}
   493  	datatype := []int{}
   494  	for key, value := range data.Data {
   495  
   496  		iLog.Debug(fmt.Sprintf("Insert data to table: %s %s %s", key, value, reflect.TypeOf(value)))
   497  		if value != nil {
   498  			if nullvalues != nil {
   499  				if nullvalue, ok := nullvalues[key]; ok {
   500  					if value == nullvalue {
   501  						continue
   502  					}
   503  				}
   504  			}
   505  
   506  			fields = append(fields, key)
   507  
   508  			switch value.(type) {
   509  			case string:
   510  				datatype = append(datatype, 0)
   511  				values = append(values, value.(string))
   512  			case float64:
   513  				datatype = append(datatype, 2)
   514  				v := fmt.Sprintf("%f", value.(float64))
   515  				values = append(values, v)
   516  			case bool:
   517  				datatype = append(datatype, 3)
   518  				v := fmt.Sprintf("%t", value.(bool))
   519  				values = append(values, v)
   520  			case int:
   521  				datatype = append(datatype, 1)
   522  				v := fmt.Sprintf("%d", value.(int))
   523  				values = append(values, v)
   524  			default:
   525  				datatype = append(datatype, 0)
   526  				values = append(values, value.(string))
   527  			}
   528  		}
   529  	}
   530  
   531  	if len(fields) == 0 {
   532  		iLog.Error(fmt.Sprintf("Insert data to table error: %s", "No data to insert"))
   533  		ctx.JSON(http.StatusBadRequest, gin.H{"error": "No data to insert"})
   534  		return err
   535  	}
   536  
   537  	id, err := dbconn.NewDBOperation("system", nil, "Execute dtable insert").TableInsert(data.TableName, fields, values)
   538  
   539  	if err != nil {
   540  		iLog.Error(fmt.Sprintf("Insert data to table error: %s", err.Error()))
   541  		ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
   542  		return err
   543  	}
   544  
   545  	result := `{"id":` + fmt.Sprintf("%d", id) + `}`
   546  	ctx.JSON(http.StatusOK, gin.H{"data": result})
   547  
   548  	return nil
   549  }
   550  
   551  // UpdateDataToTable updates data in a table based on the request received.
   552  // It retrieves the data from the request, validates it, and performs the update operation.
   553  // If any errors occur during the process, it returns the error and sends an appropriate response to the client.
   554  // The function also logs the performance duration of the operation.
   555  
   556  func (db *DBController) UpdateDataToTable(ctx *gin.Context) error {
   557  	iLog := logger.Log{ModuleName: logger.API, User: "System", ControllerName: "UpdateDataToTables"}
   558  	startTime := time.Now()
   559  	defer func() {
   560  		elapsed := time.Since(startTime)
   561  		iLog.PerformanceWithDuration("controllers.databaseop.UpdateDataToTable", elapsed)
   562  	}()
   563  	/*
   564  		defer func() {
   565  			if err := recover(); err != nil {
   566  				iLog.Error(fmt.Sprintf("UpdateDataToTable error: %s", err))
   567  				ctx.JSON(http.StatusBadRequest, gin.H{"error": err})
   568  			}
   569  		}()  */
   570  	_, user, clientid, err := common.GetRequestUser(ctx)
   571  	if err != nil {
   572  		iLog.Error(fmt.Sprintf("GetDataFromRequest error: %s", err.Error()))
   573  		ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
   574  	}
   575  
   576  	iLog.ClientID = clientid
   577  	iLog.User = user
   578  	iLog.Debug(fmt.Sprintf("Update data to table"))
   579  
   580  	data, err := db.GetDataFromRequest(ctx)
   581  	if err != nil {
   582  		iLog.Error(fmt.Sprintf("Update data to table error: %s", err.Error()))
   583  		ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
   584  		return err
   585  	}
   586  
   587  	if data.TableName == "" {
   588  		iLog.Error(fmt.Sprintf("Update data to table error: %s", "Table name is empty"))
   589  		ctx.JSON(http.StatusBadRequest, gin.H{"error": "Table name is empty"})
   590  		return err
   591  	}
   592  	iLog.Debug(fmt.Sprintf("Update data to table: %s", data.TableName))
   593  	nullvalues := data.NullValues
   594  	fields := []string{}
   595  	values := []string{}
   596  	datatype := []int{}
   597  	for key, value := range data.Data {
   598  		iLog.Debug(fmt.Sprintf("Update data to table: %s %s %s", key, value, reflect.TypeOf(value)))
   599  		if value != nil {
   600  			if nullvalues != nil {
   601  				if nullvalue, ok := nullvalues[key]; ok {
   602  					if value == nullvalue {
   603  						continue
   604  					}
   605  				}
   606  			}
   607  			fields = append(fields, key)
   608  
   609  			switch value.(type) {
   610  			case string:
   611  				datatype = append(datatype, 0)
   612  				values = append(values, value.(string))
   613  			case float64:
   614  				datatype = append(datatype, 2)
   615  				v := fmt.Sprintf("%f", value.(float64))
   616  				values = append(values, v)
   617  			case bool:
   618  				datatype = append(datatype, 3)
   619  				v := fmt.Sprintf("%t", value.(bool))
   620  				values = append(values, v)
   621  			case int:
   622  				datatype = append(datatype, 1)
   623  				v := fmt.Sprintf("%d", value.(int))
   624  				values = append(values, v)
   625  			default:
   626  				datatype = append(datatype, 0)
   627  				values = append(values, value.(string))
   628  			}
   629  		}
   630  	}
   631  
   632  	if len(fields) == 0 {
   633  		iLog.Error(fmt.Sprintf("Update data to table error: %s", "No data to update"))
   634  		ctx.JSON(http.StatusBadRequest, gin.H{"error": "No data to update"})
   635  		return err
   636  	}
   637  
   638  	Wherestr := ""
   639  	iLog.Debug(fmt.Sprintf("get where condition: %s", data.Where))
   640  	for key, value := range data.Where {
   641  		iLog.Debug(fmt.Sprintf("get where condition: %s %s", key, value))
   642  		if value == "" {
   643  			Wherestr = fmt.Sprintf("%s %s ", Wherestr, key)
   644  		} else {
   645  			Wherestr = fmt.Sprintf("%s %s='%s'", Wherestr, key, value)
   646  		}
   647  	}
   648  
   649  	if Wherestr == "" {
   650  		iLog.Error(fmt.Sprintf("Update data to table error: %s", "No where condition"))
   651  		ctx.JSON(http.StatusBadRequest, gin.H{"error": "No where condition"})
   652  		return err
   653  	}
   654  
   655  	rowcount, err := dbconn.NewDBOperation("system", nil, "Execute dtable update").TableUpdate(data.TableName, fields, values, datatype, Wherestr)
   656  
   657  	if err != nil {
   658  		iLog.Error(fmt.Sprintf("Update data to table error: %s", err.Error()))
   659  		ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
   660  		return err
   661  	}
   662  
   663  	result := `{"rowcount":` + fmt.Sprintf("%d", rowcount) + `}`
   664  
   665  	ctx.JSON(http.StatusOK, gin.H{"data": result})
   666  	return nil
   667  }
   668  
   669  // DeleteDataFromTable deletes data from a table based on the provided conditions.
   670  // It takes a gin.Context as input and returns an error if any.
   671  // The function retrieves the user and client ID from the request context and logs the operation.
   672  // It then gets the data from the request and checks if the table name is empty.
   673  // If the table name is empty, it returns an error.
   674  // Otherwise, it constructs the WHERE condition based on the provided data and deletes the matching rows from the table.
   675  // The function returns the number of rows deleted as a JSON response.
   676  
   677  func (db *DBController) DeleteDataFromTable(ctx *gin.Context) error {
   678  	iLog := logger.Log{ModuleName: logger.API, User: "System", ControllerName: "DeleteDataFromTable"}
   679  	startTime := time.Now()
   680  	defer func() {
   681  		elapsed := time.Since(startTime)
   682  		iLog.PerformanceWithDuration("controllers.databaseop.DeleteDataFromTable", elapsed)
   683  	}()
   684  	/*
   685  		defer func() {
   686  			if err := recover(); err != nil {
   687  				iLog.Error(fmt.Sprintf("DeleteDataFromTable error: %s", err))
   688  				ctx.JSON(http.StatusBadRequest, gin.H{"error": err})
   689  			}
   690  		}()  */
   691  	_, user, clientid, err := common.GetRequestUser(ctx)
   692  	if err != nil {
   693  		iLog.Error(fmt.Sprintf("GetDataFromRequest error: %s", err.Error()))
   694  		ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
   695  	}
   696  
   697  	iLog.ClientID = clientid
   698  	iLog.User = user
   699  	iLog.Debug(fmt.Sprintf("Delete data to table"))
   700  
   701  	data, err := db.GetDataFromRequest(ctx)
   702  	if err != nil {
   703  		iLog.Error(fmt.Sprintf("Delete data to table error: %s", err.Error()))
   704  		ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
   705  		return err
   706  	}
   707  
   708  	if data.TableName == "" {
   709  		iLog.Error(fmt.Sprintf("Delete data to table error: %s", "Table name is empty"))
   710  		ctx.JSON(http.StatusBadRequest, gin.H{"error": "Table name is empty"})
   711  		return err
   712  	}
   713  	iLog.Debug(fmt.Sprintf("Delete data to table: %s", data.TableName))
   714  
   715  	Wherestr := ""
   716  	iLog.Debug(fmt.Sprintf("get where condition: %s", data.Where))
   717  	for key, value := range data.Where {
   718  		iLog.Debug(fmt.Sprintf("get where condition: %s %s", key, value))
   719  		if value == "" {
   720  			Wherestr = fmt.Sprintf("%s %s ", Wherestr, key)
   721  		} else {
   722  			Wherestr = fmt.Sprintf("%s %s='%s'", Wherestr, key, value)
   723  		}
   724  	}
   725  
   726  	if Wherestr == "" {
   727  		iLog.Error(fmt.Sprintf("Delete data to table error: %s", "No where condition"))
   728  		ctx.JSON(http.StatusBadRequest, gin.H{"error": "No where condition"})
   729  		return err
   730  	}
   731  
   732  	rowcount, err := dbconn.NewDBOperation("system", nil, "Execute dtable delete").TableDelete(data.TableName, Wherestr)
   733  
   734  	if err != nil {
   735  		iLog.Error(fmt.Sprintf("Delete data to table error: %s", err.Error()))
   736  		ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
   737  		return err
   738  	}
   739  
   740  	result := `{"rowcount":` + fmt.Sprintf("%d", rowcount) + `}`
   741  	ctx.JSON(http.StatusOK, gin.H{"data": result})
   742  
   743  	return nil
   744  
   745  }
   746  
   747  // GetDataFromRequest retrieves data from the request body and returns it as a DBData struct.
   748  // It also logs the performance duration of the function.
   749  // If there is an error during the process, it logs the error and returns an empty DBData struct.
   750  
   751  func (db *DBController) GetDataFromRequest(ctx *gin.Context) (DBData, error) {
   752  	iLog := logger.Log{ModuleName: logger.API, User: "System", ControllerName: "GetDataFromRequest"}
   753  	startTime := time.Now()
   754  	defer func() {
   755  		elapsed := time.Since(startTime)
   756  		iLog.PerformanceWithDuration("controllers.databaseop.GetDataFromRequest", elapsed)
   757  	}()
   758  
   759  	defer func() {
   760  		if err := recover(); err != nil {
   761  			iLog.Error(fmt.Sprintf("GetDataFromRequest error: %s", err))
   762  			ctx.JSON(http.StatusBadRequest, gin.H{"error": err})
   763  		}
   764  	}()
   765  
   766  	_, user, clientid, err := common.GetRequestUser(ctx)
   767  	if err != nil {
   768  		iLog.Error(fmt.Sprintf("GetDataFromRequest error: %s", err.Error()))
   769  		return DBData{}, err
   770  	}
   771  
   772  	iLog.ClientID = clientid
   773  	iLog.User = user
   774  
   775  	iLog.Debug(fmt.Sprintf("GetDataFromRequest"))
   776  
   777  	var data DBData
   778  	body, err := common.GetRequestBody(ctx)
   779  	iLog.Debug(fmt.Sprintf("GetDataFromRequest body: %s", body))
   780  	if err != nil {
   781  		iLog.Error(fmt.Sprintf("GetDataFromRequest error: %s", err.Error()))
   782  		return data, err
   783  	}
   784  	err = json.Unmarshal(body, &data)
   785  	if err != nil {
   786  		iLog.Error(fmt.Sprintf("GetDataFromRequest Unmarshal error: %s", err.Error()))
   787  		return data, err
   788  	}
   789  	iLog.Debug(fmt.Sprintf("GetDataFromRequest data: %s", data))
   790  	return data, nil
   791  }