R
R
Roman Sergeevich2021-05-04 19:00:42
go
Roman Sergeevich, 2021-05-04 19:00:42

How to read previously unknown table from database in golang?

func (*sql.Rows).Scan(dest ...interface{}) error
I need to turn a table from mysql into json whose structure is unknown in advance

Answer the question

In order to leave comments, you need to log in

2 answer(s)
R
Roman Sergeevich, 2021-05-05
@roman24hs

func sqlToJson(res *sql.Rows) ([]byte, error) {
  // создаем массив названий столбцов таблицы
  arrNamesColumns, _ := res.Columns()

  // получаем количество столбцов
  kolColumns := len(arrNamesColumns)

  // создаем отображения которое по ключу (названию столбца) будет хранить срез всех записей данного столбца
  resMap := make(map[string][]interface{}, kolColumns)

  // создаем срез который будет хранить все поля текущий строки таблицы в массиве байт
  tempLineByte := make([][]byte, kolColumns)

  // создаем срез который будет хранить ссылки на поля предыдущего среза
  // это нужно для метода Scan который принимает interface по ссылке таким образом записывая в него данные
  pTempLineByte := make([]interface{}, kolColumns)
  for i := 0; i < kolColumns; i++ {
    pTempLineByte[i] = &tempLineByte[i]
  }

  // создаем срез который будет хранить все поля текущий строки в соответствующим типе данных
  tempLine := make([]interface{}, kolColumns)

  // перебираем все строки тоблицы
  for res.Next() {
    // метод Scan записывает в срез tempLineByte текущую строку через срез pTempLineByte который хранит ссылки на поля tempLineByte
    err := res.Scan(pTempLineByte...)
    if err != nil {
      return nil, err
    }

    // перебираем все поля текущей строки
    for i := 0; i < kolColumns; i++ {
      // преобразовываем байтовое значение в значение соответствующего формата
      json.Unmarshal(tempLineByte[i], &tempLine[i])

      // если записалось значение nil то в поле была строка
      if tempLine[i] == nil {
        // добавляем значения в соответствующий ключу срез отображения resMap преобразуя его в строку
        resMap[arrNamesColumns[i]] = append(resMap[arrNamesColumns[i]], string(tempLineByte[i]))
      } else {
        // иначе добавлять в срез соответствующие значения tempLine
        resMap[arrNamesColumns[i]] = append(resMap[arrNamesColumns[i]], tempLine[i])
      }
    }
  }

  // преобразовываем отображения в json и возвращаем в массиве байт
  return json.Marshal(resMap)

  // p.s. чтобы получить привычный json нужно просто преобразовать этот массив байт в строку
  // также, может понадобится убрать из этой строки символы переноса \n которые могут быть в текстовых полях базы данных, так как с ними json считается неликвидным
}

R
Romses Panagiotis, 2021-05-05
@romesses

It's already late. Until the thought came up.
Try running a query first to get the field names and their types. Rows.Columns to get the field names and their order. We get . Then, knowing the names of the fields, you can get results with the help and during processing, get the data itself, which is already filled in an array of structures. Accordingly, the structures themselves are already serialized in the desired format.
SHOW COLUMNS FROM mytable
[]interface{}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question