nuclei/pkg/js/utils/util.go
Dwi Siswanto 87ed0b2bb9
build: bump all direct modules (#6290)
* chore: fix non-constant fmt string in call

Signed-off-by: Dwi Siswanto <git@dw1.io>

* build: bump all direct modules

Signed-off-by: Dwi Siswanto <git@dw1.io>

* chore(hosterrorscache): update import path

Signed-off-by: Dwi Siswanto <git@dw1.io>

* fix(charts): break changes

Signed-off-by: Dwi Siswanto <git@dw1.io>

* build: pinned `github.com/zmap/zcrypto` to v0.0.0-20240512203510-0fef58d9a9db

Signed-off-by: Dwi Siswanto <git@dw1.io>

* chore: golangci-lint auto fixes

Signed-off-by: Dwi Siswanto <git@dw1.io>

* chore: satisfy lints

Signed-off-by: Dwi Siswanto <git@dw1.io>

* build: migrate `github.com/xanzy/go-gitlab` => `gitlab.com/gitlab-org/api/client-go`

Signed-off-by: Dwi Siswanto <git@dw1.io>

* feat(json): update build constraints

Signed-off-by: Dwi Siswanto <git@dw1.io>

* chore: dont panicking on close err

Signed-off-by: Dwi Siswanto <git@dw1.io>

---------

Signed-off-by: Dwi Siswanto <git@dw1.io>
2025-07-01 00:40:44 +07:00

91 lines
2.3 KiB
Go

package utils
import (
"database/sql"
)
// SQLResult holds the result of a SQL query.
//
// It contains the count of rows, the columns present, and the actual row data.
type SQLResult struct {
Count int // Count is the number of rows returned.
Columns []string // Columns is the slice of column names.
Rows []interface{} // Rows is a slice of row data, where each row is a map of column name to value.
}
// UnmarshalSQLRows converts sql.Rows into a more structured SQLResult.
//
// This function takes *sql.Rows as input and attempts to unmarshal the data into
// a SQLResult struct. It handles different SQL data types by using the appropriate
// sql.Null* types during scanning. It returns a pointer to a SQLResult or an error.
//
// The function closes the sql.Rows when finished.
func UnmarshalSQLRows(rows *sql.Rows) (*SQLResult, error) {
defer func() {
_ = rows.Close()
}()
columnTypes, err := rows.ColumnTypes()
if err != nil {
return nil, err
}
result := &SQLResult{}
result.Columns, err = rows.Columns()
if err != nil {
return nil, err
}
count := len(columnTypes)
for rows.Next() {
result.Count++
scanArgs := make([]interface{}, count)
for i, v := range columnTypes {
switch v.DatabaseTypeName() {
case "VARCHAR", "TEXT", "UUID", "TIMESTAMP":
scanArgs[i] = new(sql.NullString)
case "BOOL":
scanArgs[i] = new(sql.NullBool)
case "INT4":
scanArgs[i] = new(sql.NullInt64)
default:
scanArgs[i] = new(sql.NullString)
}
}
err := rows.Scan(scanArgs...)
if err != nil {
// Return the result accumulated so far along with the error.
return result, err
}
masterData := make(map[string]interface{})
for i, v := range columnTypes {
if z, ok := (scanArgs[i]).(*sql.NullBool); ok {
masterData[v.Name()] = z.Bool
continue
}
if z, ok := (scanArgs[i]).(*sql.NullString); ok {
masterData[v.Name()] = z.String
continue
}
if z, ok := (scanArgs[i]).(*sql.NullInt64); ok {
masterData[v.Name()] = z.Int64
continue
}
if z, ok := (scanArgs[i]).(*sql.NullFloat64); ok {
masterData[v.Name()] = z.Float64
continue
}
if z, ok := (scanArgs[i]).(*sql.NullInt32); ok {
masterData[v.Name()] = z.Int32
continue
}
masterData[v.Name()] = scanArgs[i]
}
result.Rows = append(result.Rows, masterData)
}
return result, nil
}