Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error Golang type code tcNull #24

Closed
ekp1k80 opened this issue Jul 13, 2018 · 1 comment
Closed

Error Golang type code tcNull #24

ekp1k80 opened this issue Jul 13, 2018 · 1 comment
Labels

Comments

@ekp1k80
Copy link

ekp1k80 commented Jul 13, 2018

Hi.
It happens that I have a database connection called Hana (Hana DB) with the programming language Go (Golang). Using the Iris framework.

What happens is that Go has problems with null data. You have to use special data types in the struct as (using the sql library that comes by default when installing Go) sql.NullString

The question is, I have a GetEmployeeData () function called when connecting to a certain URL and returning a JSON. The problem is that it does not return anything, a CONNECTION error REJECTED appears and in the console it prints an error: hdb.protocol 2018/07/13 16:31:06 option.go:120: type code tcNull not implemented exit status 1 The code was already tested in another SQL call in another function and it works, but this SQL I suppose that when returning 1 only Null or more it gives error.

The code is the following:
`func GetEmployeeData(ctx iris.Context) {

	const (
		driverName = "hdb"
		hdbDsn     = "hdb://SYSTEM:manager@62.28.253.218:30015"
	)
	//db, err := sql.Open(driverName, hdbDsn)
	//Crea una abstraccion de conexion a base de datos pero no conecta
	//Si no que prepara todo para la conexion
	db, err := sql.Open(driverName, hdbDsn)
	if err != nil {
		log.Fatal(err)
	}
	//Declaramos variable de QUERY

	//var peticion = GetCompanyData()
	//fmt.Println(peticion)
	// var companyData = GetCompanyData()
	var request = `Select
									"U_idcodigo",
									"U_idapenom",
									"U_idnumint",
									"U_ctestado",
									"U_idemail",
									"U_cttipfun",
									"U_uocodcar",
									TO_CHAR("U_uocarasi",'dd/mm/yyyy'),
									"U_uocodfun",
									TO_CHAR("U_uofunasi",'dd/mm/yyyy'),
									"U_idestciv",
									"U_idsexo",
									"U_idnacion",
									"U_codcat",
									"U_codesp",
									TO_CHAR("U_idfecnac",'dd/mm/yyyy'),
									"U_idfotogr",
									"U_dodirecc","
									U_docodpai",
									"U_doregion",
									"U_doprovin",
									"U_docomuna",
									"U_docodpos",
									"U_donummov",
									"U_cttipcon",
									TO_CHAR("U_ctfecing",'dd/mm/yyyy'),
									                                                                                                 
									"U_uolugpag",                                      
									"U_uolugtra",
									"U_uocodger",
									"U_uocoddep",
									"U_uocodsec",                        
									"U_rpforpag",
									"U_rpcodban",
									"U_rpctacte",
									"U_rptipocta",
									"U_rpunisal",
									"U_rpmoneda",
									TO_VARCHAR("U_rpsalar"),
									"U_tijor",
									TO_VARCHAR("U_hdia"),
									TO_VARCHAR("U_cthorcon"),
									"U_sindi",
									"U_jubil",
									"U_turno",
									TO_CHAR("U_turnoasi",'dd/mm/yyyy'),
									"U_comentar"
									FROM SBODemoCL."@A1A_MAFU"
									Where "U_idcodigo" = '7579684-6'`


	rows, err := db.Query(request)
	if err != nil {
		log.Fatal(err)
		fmt.Println("No funciono la peticion")
	}
	defer rows.Close()
	defer db.Close()
	fmt.Println("Funciono la peticion")

	type Employee struct {
		CodigoEmpleado sql.NullString `json:"CodigoEmpleado"` //CODIGO UNICO DE EMPLEADO
		Nombres        sql.NullString `json:"Nombres"`        //APELLIDO Y NOMBRE
		NroInterno     sql.NullString `json:"NroInterno"`     //NUMERO INTERNO EN EMPRESA
		Estado         sql.NullString `json:"Estado"`
		Email          sql.NullString `json:"Email"`        //CORREO ELECTRONICO
		TipoF          sql.NullString `json:"TipoF"`        //TIPO DE FUNCIONARIO
		Cargo          sql.NullString `json:"Cargo"`        //EL CARGO QUE OCUPA EL EMPLEADO
		FechaCargo     sql.NullString `json:"FechaCargo"`   //FECHA DE ASIGNACION DE CARGO
		Funcion        sql.NullString `json:"Funcion"`      //QUE FUNCION CUMPLE
		FechaFuncion   sql.NullString `json:"FechaFuncion"` //CUANDO SE LE ASIGNO SU FUNCION
		Civil          sql.NullString `json:"Civil"`        //ESTADO CIVIL
		Sexo           sql.NullString `json:"Sexo"`         //SI ES MASCULINO O FEMENINO
		Nacionalidad   sql.NullString `json:"Nacionalidad"` //SU NACIONALIDAD
		Categoría      sql.NullString `json:"Categoría"`    //SU CATEGORIA
		Especialidad   sql.NullString `json:"Especialidad"` //SU ESPECIALIDAD
		Nacimiento     sql.NullString `json:"Nacimiento"`   //FECHA DE NACIMIENTO
		Fotografia     sql.NullString `json:"Fotografia"`   //RUTA DE MAPA DE BITS DE IMAGEN SOBRE EL EMPLEADO
		Direccion      sql.NullString `json:"Direccion"`    //DIRECCION DE CASA DEL EMPLEADO
		Pais           sql.NullString `json:"Pais"`         //PAIS EN DONDE SE ENCUENTRA ACTUALMENTE
		Region         sql.NullString `json:"Region"`       //REGION DONDE SE ENCUENTRA ACTUALMENTE
		Provincia      sql.NullString `json:"Provincia"`    //PROVINCIA DONDE SE ENCUENTRA ACTUALMENTE
		Comuna         sql.NullString `json:"Comuna"`       //COMUNA DONDE SE ENCUENTRA ACTUALMENTE
		C_Postal       sql.NullString `json:"C_Postal"`     //SU CODIGO POSTAL
		Celular        sql.NullString `json:"Celular"`      //NUMERO DE CELULAR
		TipoContrato   sql.NullString `json:"TipoContrato"` //TIPO DE CONTRATO
		FechaIngreso   sql.NullString `json:"FechaIngreso"` //FECHA DE INGRESO A LA COMPAÑIA

		LugarPago      sql.NullString `json:"LugarPago"`      //LUGAR DONDE NORMALMENTE COBRA EL EMPLEADO
		LugarTrabajo   sql.NullString `json:"LugarTrabajo"`   //LUGAR DONDE NORMALMENTE TRABAJA EL EMPLEADO
		Gerencia       sql.NullString `json:"Gerencia"`       //¿Quien es su genente? No es claro
		Departamento   sql.NullString `json:"Departamento"`   //¿Si tiene departamento? ¿O la ubicacion de su departamento? ¿O con departamento se refieren a su partido o barrio?
		Seccion        sql.NullString `json:"Seccion"`        //¿? Tampoco me queda claro
		FormaPago      sql.NullString `json:"FormaPago"`      //COMO SE LE PAGA NORMALMENTE AL EMPLEADO
		Banco          sql.NullString `json:"Banco"`          //EL BANCO QUE SE UTILIZA PARA DEPOSITAR EL SALARIO DEL EMPLEADO
		CuentaBanco    sql.NullString `json:"CuentaBanco"`    //CUENTA BANCARIO DONDE SE DEPOSITA EL SALARIO
		UnidadSalarial sql.NullString `json:"UnidadSalarial"` //¿? Su unidad salarial
		Moneda         sql.NullString `json:"Moneda"`         //CON QUE TIPO DE MONEDA SE DEPOSITA SU SUELDO (EUROS, DOLARES, PESOS, ETC...)
		Sueldo         sql.NullString `json:"Sueldo"`         //SUELDO BASICO DEL EMPLEADO
		TipoJornada    sql.NullString `json:"TipoJornada"`    //TIPO DE JORNADA DEL EMPLEADO (CANTIDAD DE HORAS QUE TRABAJA)
		HorasDia       sql.NullString `json:"HorasDia"`       //HORAS DIARIAS QUE ESTIPULA EL CONTRATO
		HorasMes       sql.NullString `json:"HorasMes"`       //HORAS MENSUALES QUE ESTIPULA EL CONTRATO
		Sindicato      sql.NullString `json:"Sindicato"`      //SINDICATO AL QUE PERTENECE EL EMPLEADO
		Jubilido       sql.NullString `json:"Jubilido"`       //¿? Puede ser si es que esta jubilado o no
		Turno          sql.NullString `json:"Turno"`          //¿Turno de que?
		FechaTurno     sql.NullString `json:"FechaTurno"`     //FECHA EN QUE SE LE ASIGNO EL TURNO
		Comentarios    sql.NullString `json:"Comentarios"`    //Comentarios sobre el empleado
	}

	// numero := 0
	//
	// ac := accounting.Accounting{
	// 	Symbol:    "",                        //El símbolo
	// 	Precision: 2,                         // ¿Cuántos "centavos" queremos? (también llamado precisión)
	// 	Thousand:  companyData["ISeparator"], //Separador de miles
	// 	Decimal:   companyData["FSeparator"], //Separador de decimales
	// }

	employ := new(Employee)

	for rows.Next() {
		err := rows.Scan(
			&employ.CodigoEmpleado,
			&employ.Nombres,
			&employ.NroInterno,
			&employ.Estado,
			&employ.Email,
			&employ.TipoF,
			&employ.Cargo,
			&employ.FechaCargo,
			&employ.Funcion,
			&employ.FechaFuncion,
			&employ.Civil,
			&employ.Sexo,
			&employ.Nacionalidad,
			&employ.Categoría,
			&employ.Especialidad,
			&employ.Nacimiento,
			&employ.Fotografia,
			&employ.Direccion,
			&employ.Pais,
			&employ.Region,
			&employ.Provincia,
			&employ.Comuna,
			&employ.C_Postal,
			&employ.Celular,
			&employ.TipoContrato,
			&employ.FechaIngreso,

			&employ.LugarPago,
			&employ.LugarTrabajo,
			&employ.Gerencia,
			&employ.Departamento,
			&employ.Seccion,
			&employ.FormaPago,
			&employ.Banco,
			&employ.CuentaBanco,
			&employ.UnidadSalarial,
			&employ.Moneda,
			&employ.Sueldo,
			&employ.TipoJornada,
			&employ.HorasDia,
			&employ.HorasMes,
			&employ.Sindicato,
			&employ.Jubilido,
			&employ.Turno,
			&employ.FechaTurno,
			&employ.Comentarios,
		)
		if err != nil {
			log.Fatal(err)
		}
		// f, err := strconv.ParseFloat(valor6, 64)
		// salario := ac.FormatMoney(f)

	}

	err = rows.Err()

	if err != nil {
		log.Fatal(err)
		fmt.Println("Ocurrio un error")
	}
	ctx.JSON(employ)
}`

The libraries that are imported are the following:
`import (
"database/sql"
"fmt"
"log"
"strconv"

	"github.com/kataras/iris"
	"github.com/leekchan/accounting"
	// Register hdb driver.
	_ "github.com/SAP/go-hdb/driver"
)`

The error calls an option.go file. All the code of option go is the following:
` /*
Copyright 2014 SAP SE

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package protocol

import (
	"fmt"

	"github.com/SAP/go-hdb/internal/bufio"
)

type booleanType bool

func (t booleanType) String() string {
	return fmt.Sprintf("%t", t)
}

type intType int32

func (t intType) String() string {
	return fmt.Sprintf("%d", t)
}

type bigintType int64

func (t bigintType) String() string {
	return fmt.Sprintf("%d", t)
}

type doubleType float64

func (t doubleType) String() string {
	return fmt.Sprintf("%g", t)
}

type stringType []byte

type binaryStringType []byte

func (t binaryStringType) String() string {
	return fmt.Sprintf("%v", []byte(t))
}

//multi line options (number of lines in part header argumentCount)
type multiLineOptions []plainOptions

func (o multiLineOptions) size() int {
	size := 0
	for _, m := range o {
		size += m.size()
	}
	return size
}

//pointer: append multiLineOptions itself
func (o *multiLineOptions) read(rd *bufio.Reader, lineCnt int) {
	for i := 0; i < lineCnt; i++ {
		m := plainOptions{}
		cnt := rd.ReadInt16()
		m.read(rd, int(cnt))
		*o = append(*o, m)
	}
}

func (o multiLineOptions) write(wr *bufio.Writer) {
	for _, m := range o {
		wr.WriteInt16(int16(len(m)))
		m.write(wr)
	}
}

	type plainOptions map[int8]interface{}

	func (o plainOptions) size() int {
		size := 2 * len(o) //option + type
		for _, v := range o {
			switch v := v.(type) {
			default:
				outLogger.Fatalf("type %T not implemented", v)
			case booleanType:
				size++
			case intType:
				size += 4
			case bigintType:
				size += 8
			case doubleType:
				size += 8
			case stringType:
				size += (2 + len(v)) //length int16 + string length
			case binaryStringType:
				size += (2 + len(v)) //length int16 + string length
			}
		}
		return size
	}

	func (o plainOptions) read(rd *bufio.Reader, cnt int) {

		for i := 0; i < cnt; i++ {

			k := rd.ReadInt8()
			tc := rd.ReadB()

			switch TypeCode(tc) {

			default:
				outLogger.Fatalf("type code %s not implemented", TypeCode(tc))

			case tcBoolean:
				o[k] = booleanType(rd.ReadBool())

			case tcInteger:
				o[k] = intType(rd.ReadInt32())

			case tcBigint:
				o[k] = bigintType(rd.ReadInt64())

			case tcDouble:
				o[k] = doubleType(rd.ReadFloat64())

			case tcString:
				size := rd.ReadInt16()
				v := make([]byte, size)
				rd.ReadFull(v)
				o[k] = stringType(v)

			case tcBstring:
				size := rd.ReadInt16()
				v := make([]byte, size)
				rd.ReadFull(v)
				o[k] = binaryStringType(v)

			}
		}
	}

	func (o plainOptions) write(wr *bufio.Writer) {

		for k, v := range o {

			wr.WriteInt8(k)

			switch v := v.(type) {

			default:
				outLogger.Fatalf("type %T not implemented", v)

			case booleanType:
				wr.WriteInt8(int8(tcBoolean))
				wr.WriteBool(bool(v))

			case intType:
				wr.WriteInt8(int8(tcInteger))
				wr.WriteInt32(int32(v))

			case bigintType:
				wr.WriteInt8(int8(tcBigint))
				wr.WriteInt64(int64(v))

			case doubleType:
				wr.WriteInt8(int8(tcDouble))
				wr.WriteFloat64(float64(v))

			case stringType:
				wr.WriteInt8(int8(tcString))
				wr.WriteInt16(int16(len(v)))
				wr.Write(v)

			case binaryStringType:
				wr.WriteInt8(int8(tcBstring))
				wr.WriteInt16(int16(len(v)))
				wr.Write(v)
			}
		}
	}

`
Does anyone know how to fix the error?

@stfnmllr
Copy link
Contributor

Hi,

which go-hdb version are you using? Is it the latest one?

Trying to reproduce the issue (see go source file attached) gives

2018/07/14 11:40:56 sql: expected 46 destination arguments in Scan, not 45

meaning, that the amount of attributes in the select clause (46) does not match the number of scan fields used (45).
Please provide a corrected example code.

Best regards

issue24.go.zip

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants