How does if condition works in golang


(ravuri sai ram akhil) #1

I am trying to develop a go driver for IBM (db2) database.
For windows the API definition is : -
(i will load the dll and use the functions)

func SQLColAttribute(statementHandle SQLHSTMT, ColumnNumber SQLUSMALLINT, FieldIdentifier SQLUSMALLINT, CharacterAttributePtr SQLPOINTER, BufferLength SQLSMALLINT, StringLengthPtr *SQLSMALLINT, NumericAttributePtr *SQLLEN) (ret SQLRETURN) {
	r0, _, _ := syscall.Syscall9(procSQLColAttribute.Addr(), 7, uintptr(statementHandle), uintptr(ColumnNumber), uintptr(FieldIdentifier), uintptr(CharacterAttributePtr), uintptr(BufferLength), uintptr(unsafe.Pointer(StringLengthPtr)), uintptr(unsafe.Pointer(NumericAttributePtr)), 0, 0)
	ret = SQLRETURN(r0)
	return
}

For other platforms it is : -
(using cgo that means i will include the sqlcli.h file and then import C)

func SQLColAttribute(statementHandle SQLHSTMT, ColumnNumber SQLUSMALLINT, FieldIdentifier SQLUSMALLINT, CharacterAttributePtr SQLPOINTER, BufferLength SQLSMALLINT, StringLengthPtr *SQLSMALLINT, NumericAttributePtr SQLPOINTER) (ret SQLRETURN) {
        r := C.SQLColAttribute(C.SQLHSTMT(statementHandle),C.SQLUSMALLINT(ColumnNumber),C.SQLUSMALLINT(FieldIdentifier),C.SQLPOINTER(CharacterAttributePtr),C.SQLSMALLINT(BufferLength),(*C.SQLSMALLINT)(StringLengthPtr),(C.SQLPOINTER)(NumericAttributePtr))
        return SQLRETURN(r)
}

My Code of using the functions:-

func (r *Rows) ColumnTypeLength(index int) (length int64, ok bool) {
	if runtime.GOOS == "windows" {
	    ret := api.SQLColAttribute(r.os.h, api.SQLUSMALLINT(index+1), api.SQL_DESC_LENGTH, api.SQLPOINTER(unsafe.Pointer(nil)), 0, (*api.SQLSMALLINT)(nil), (*api.SQLLEN)(&length)))
	   if IsError(ret) {
		fmt.Println(ret)
		return 0, false
	   }
	 return length, true
 } else {
	ret := api.SQLColAttribute(r.os.h, api.SQLUSMALLINT(index+1), api.SQL_DESC_LENGTH, api.SQLPOINTER(unsafe.Pointer(nil)), 0, (*api.SQLSMALLINT)(nil), api.SQLPOINTER(unsafe.Pointer(&length)))
	if IsError(ret) {
		fmt.Println(ret)
		return 0, false
	}
	return length, true
    }
}

Error:
when i run the code in windows it produces that

# github.com/ibmdb/go_ibm_db
C:\Users\rakhil\go\src\github.com\ibmdb\go_ibm_db\rows.go:55:165: cannot use api.SQLPOINTER(unsafe.Pointer(&length)) (type api.SQLPOINTER) as type *api.SQLLEN in argument to api.SQLColAttribute

when i run the code in linux it produces that

cannot convert &length (type *int64) to type *api.SQLLEN

why is that go compiling the code without checking the if condition or else is there any other way to run the code.

Thanks.


(Lutz Horn) #2

Which is line 55 in rows.go?


(ravuri sai ram akhil) #3

line 55

ret := api.SQLColAttribute(r.os.h, api.SQLUSMALLINT(index+1), api.SQL_DESC_LENGTH, api.SQLPOINTER(unsafe.Pointer(nil)), 0, (*api.SQLSMALLINT)(nil), api.SQLPOINTER(unsafe.Pointer(&length)))

(Lutz Horn) #4

So your question is why this

is not true under Windows?


(ravuri sai ram akhil) #5

My Question is

In SQLColAttribute the last parameter(NumericAttributePtr) is SQLLEN in windows and SQLPOINTER in other platforms.
So, I have used if condition to take care of it but, it runs both if and else code and produces the error.


(Lutz Horn) #6

That’s impossible if/else never run both.


(ravuri sai ram akhil) #7

How to take care of it ? as i cannot write two functions because the decleration is in sql package(database/sql).


(Lutz Horn) #8

if and runtime.GOOS work as expected:

package main

import (
	"fmt"
	"runtime"
)

func main() {
	if runtime.GOOS == "linux" {
		fmt.Println("This is Linux: " + runtime.GOOS)
	} else {
		fmt.Println("This is not Linux: " + runtime.GOOS)
	}
}

See https://play.golang.org/p/wVdvlIf4-ON


(ravuri sai ram akhil) #9

suppose this is rows.go file:-

// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package go_ibm_db

import (
	"database/sql/driver"
	"fmt"
	"io"
	"reflect"
	"unsafe"

	"github.com/ibmdb/go_ibm_db/api"
)

type Rows struct {
	os *ODBCStmt
}

func (r *Rows) Columns() []string {
	names := make([]string, len(r.os.Cols))
	for i := 0; i < len(names); i++ {
		names[i] = r.os.Cols[i].Name()
	}
	return names
}

func (r *Rows) ColumnTypeLength(index int) (length int64, ok bool) {
       if runtime.GOOS == "windows" {
        ret := api.SQLColAttribute(r.os.h, api.SQLUSMALLINT(index+1), api.SQL_DESC_LENGTH, api.SQLPOINTER(unsafe.Pointer(nil)), 0, (*api.SQLSMALLINT)(nil), (*api.SQLLEN)(&length)))
	    if IsError(ret) {
		    fmt.Println(ret)
		    return 0, false
	}
	return length, true
    } else {
	ret := api.SQLColAttribute(r.os.h, api.SQLUSMALLINT(index+1), api.SQL_DESC_LENGTH, api.SQLPOINTER(unsafe.Pointer(nil)), 0, (*api.SQLSMALLINT)(nil), api.SQLPOINTER(unsafe.Pointer(&length)))
	if IsError(ret) {
		fmt.Println(ret)
		return 0, false
	}
	return length, true
    }
}


func (r *Rows) Next(dest []driver.Value) error {
	ret := api.SQLFetch(r.os.h)
	if ret == api.SQL_NO_DATA {
		return io.EOF
	}
	if IsError(ret) {
		return NewError("SQLFetch", r.os.h)
	}
	for i := range dest {
		v, err := r.os.Cols[i].Value(r.os.h, i)
		if err != nil {
			return err
		}
		dest[i] = v
	}
	return nil
}

func (r *Rows) Close() error {
	return r.os.closeByRows()
}


(ravuri sai ram akhil) #10

For normal file it was running perfectly when it comes to that rows.go file it is running weirdly.


(Lutz Horn) #11

BTW, did you look at https://github.com/golang/go/wiki/SQLDrivers#drivers for DB2 drivers?


(ravuri sai ram akhil) #12

None of them will support SQLColAttribute api.
github.com/ibmdb/go_ibm_db is ours and we are trying to support that api then we got this kind of error.


(ravuri sai ram akhil) #13

@NobbZ can u help me on this.

Thanks


(Norbert Melzer) #14

I’m not sure how.


(ravuri sai ram akhil) #15

np. Thanks.


(ravuri sai ram akhil) #16

Is there any way to detect the OS at compile time @lutzhorn
because runtime.GOOS will detect it at runtime.


(Lutz Horn) #17

Which OS? The one you compile on?


(ravuri sai ram akhil) #18

YES. where my program will run.


(Lutz Horn) #19

The OS you compile on is not necessarily the one you run the application on. So which one:

  • A: the OS you compile the application on
  • B: the OS you run the compiled application on

(ravuri sai ram akhil) #20

option A