func FormatError(ht C.SQLSMALLINT, h C.SQLHANDLE) (err *ODBCError) { sqlState := make([]uint16, 6) var nativeError C.SQLINTEGER messageText := make([]uint16, C.SQL_MAX_MESSAGE_LENGTH) var textLength C.SQLSMALLINT err = &ODBCError{} i := 0 for { i++ ret := C.SQLGetDiagRecW(C.SQLSMALLINT(ht), h, C.SQLSMALLINT(i), (*C.SQLWCHAR)(unsafe.Pointer(&sqlState[0])), &nativeError, (*C.SQLWCHAR)(unsafe.Pointer(&messageText[0])), C.SQL_MAX_MESSAGE_LENGTH, &textLength) if ret == C.SQL_INVALID_HANDLE || ret == C.SQL_NO_DATA { break } if i == 1 { // first error message save the SQLSTATE. err.SQLState = UTF16ToString(sqlState) err.NativeError = int(nativeError) } err.ErrorMessage += UTF16ToString(messageText) } return err }
func FormatError(ht C.SQLSMALLINT, h C.SQLHANDLE, val_ret int) (err *ODBCError) { sqlState := make([]byte, 6) var nativeError C.SQLINTEGER messageText := make([]byte, BUFFER_SIZE*10) var textLength C.SQLSMALLINT debugPrint("FormatError", val_ret) for { ret := C.SQLGetDiagRec(C.SQLSMALLINT(ht), h, C.SQLSMALLINT(val_ret), (*C.SQLCHAR)(unsafe.Pointer(&sqlState[0])), &nativeError, (*C.SQLCHAR)(unsafe.Pointer(&messageText[0])), BUFFER_SIZE*2, &textLength) switch ret { case C.SQL_INVALID_HANDLE: debugPrint("SQL_INVALID_HANDLE") err = &ODBCError{SQLState: string(sqlState), NativeError: int(nativeError), ErrorMessage: "SQL_INVALID_HANDLE"} case C.SQL_NO_DATA: case C.SQL_SUCCESS: debugPrint("SQL_SUCCESS") err = &ODBCError{SQLState: string(sqlState), NativeError: int(nativeError), ErrorMessage: string(messageText)} continue case C.SQL_SUCCESS_WITH_INFO: debugPrint("SQLGetDiagRec => SQL_SUCCESS_WITH_INFO") err = &ODBCError{SQLState: string(sqlState), NativeError: int(nativeError), ErrorMessage: "SQL_SUCCESS_WITH_INFO"} case C.SQL_ERROR: debugPrint("SQLGetDiagRec => SQL_ERROR", sqlState, nativeError, messageText) err = &ODBCError{SQLState: string(sqlState), NativeError: int(nativeError), ErrorMessage: "SQL_ERROR"} default: debugPrint("SQLGetDiagRec => OTHER_ERROR") err = &ODBCError{SQLState: string(sqlState), NativeError: int(nativeError), ErrorMessage: "OTHER_SQL_ERROR"} } break } return err }
func SQLGetDiagRec(handleType SQLSMALLINT, handle SQLHANDLE, recNumber SQLSMALLINT, sqlState *SQLWCHAR, nativeErrorPtr *SQLINTEGER, messageText *SQLWCHAR, bufferLength SQLSMALLINT, textLengthPtr *SQLSMALLINT) (ret SQLRETURN) { r := C.SQLGetDiagRecW(C.SQLSMALLINT(handleType), C.SQLHANDLE(handle), C.SQLSMALLINT(recNumber), (*C.SQLWCHAR)(unsafe.Pointer(sqlState)), (*C.SQLINTEGER)(nativeErrorPtr), (*C.SQLWCHAR)(unsafe.Pointer(messageText)), C.SQLSMALLINT(bufferLength), (*C.SQLSMALLINT)(textLengthPtr)) return SQLRETURN(r) }
func SQLGetData(statementHandle SQLHSTMT, colOrParamNum SQLUSMALLINT, targetType SQLSMALLINT, targetValuePtr SQLPOINTER, bufferLength SQLLEN, vallen *SQLLEN) (ret SQLRETURN) { r := C.SQLGetData(C.SQLHSTMT(statementHandle), C.SQLUSMALLINT(colOrParamNum), C.SQLSMALLINT(targetType), C.SQLPOINTER(targetValuePtr), C.SQLLEN(bufferLength), (*C.SQLLEN)(vallen)) return SQLRETURN(r) }
func SQLFreeHandle(handleType SQLSMALLINT, handle SQLHANDLE) (ret SQLRETURN) { r := C.SQLFreeHandle(C.SQLSMALLINT(handleType), C.SQLHANDLE(handle)) return SQLRETURN(r) }
func SQLEndTran(handleType SQLSMALLINT, handle SQLHANDLE, completionType SQLSMALLINT) (ret SQLRETURN) { r := C.SQLEndTran(C.SQLSMALLINT(handleType), C.SQLHANDLE(handle), C.SQLSMALLINT(completionType)) return SQLRETURN(r) }
func SQLDriverConnect(connectionHandle SQLHDBC, windowHandle SQLHWND, inConnectionString *SQLWCHAR, stringLength1 SQLSMALLINT, outConnectionString *SQLWCHAR, bufferLength SQLSMALLINT, stringLength2Ptr *SQLSMALLINT, driverCompletion SQLUSMALLINT) (ret SQLRETURN) { r := C.SQLDriverConnectW(C.SQLHDBC(connectionHandle), C.SQLHWND(windowHandle), (*C.SQLWCHAR)(unsafe.Pointer(inConnectionString)), C.SQLSMALLINT(stringLength1), (*C.SQLWCHAR)(unsafe.Pointer(outConnectionString)), C.SQLSMALLINT(bufferLength), (*C.SQLSMALLINT)(stringLength2Ptr), C.SQLUSMALLINT(driverCompletion)) return SQLRETURN(r) }
func SQLDescribeCol(statementHandle SQLHSTMT, columnNumber SQLUSMALLINT, columnName *SQLWCHAR, bufferLength SQLSMALLINT, nameLengthPtr *SQLSMALLINT, dataTypePtr *SQLSMALLINT, columnSizePtr *SQLULEN, decimalDigitsPtr *SQLSMALLINT, nullablePtr *SQLSMALLINT) (ret SQLRETURN) { r := C.SQLDescribeColW(C.SQLHSTMT(statementHandle), C.SQLUSMALLINT(columnNumber), (*C.SQLWCHAR)(unsafe.Pointer(columnName)), C.SQLSMALLINT(bufferLength), (*C.SQLSMALLINT)(nameLengthPtr), (*C.SQLSMALLINT)(dataTypePtr), (*C.SQLULEN)(columnSizePtr), (*C.SQLSMALLINT)(decimalDigitsPtr), (*C.SQLSMALLINT)(nullablePtr)) return SQLRETURN(r) }
func SQLBindParameter(statementHandle SQLHSTMT, parameterNumber SQLUSMALLINT, inputOutputType SQLSMALLINT, valueType SQLSMALLINT, parameterType SQLSMALLINT, columnSize SQLULEN, decimalDigits SQLSMALLINT, parameterValue SQLPOINTER, bufferLength SQLLEN, ind *SQLLEN) (ret SQLRETURN) { r := C.SQLBindParameter(C.SQLHSTMT(statementHandle), C.SQLUSMALLINT(parameterNumber), C.SQLSMALLINT(inputOutputType), C.SQLSMALLINT(valueType), C.SQLSMALLINT(parameterType), C.SQLULEN(columnSize), C.SQLSMALLINT(decimalDigits), C.SQLPOINTER(parameterValue), C.SQLLEN(bufferLength), (*C.SQLLEN)(ind)) return SQLRETURN(r) }
func SQLBindCol(statementHandle SQLHSTMT, columnNumber SQLUSMALLINT, targetType SQLSMALLINT, targetValuePtr SQLPOINTER, bufferLength SQLLEN, vallen *SQLLEN) (ret SQLRETURN) { r := C.SQLBindCol(C.SQLHSTMT(statementHandle), C.SQLUSMALLINT(columnNumber), C.SQLSMALLINT(targetType), C.SQLPOINTER(targetValuePtr), C.SQLLEN(bufferLength), (*C.SQLLEN)(vallen)) return SQLRETURN(r) }
func SQLAllocHandle(handleType SQLSMALLINT, inputHandle SQLHANDLE, outputHandle *SQLHANDLE) (ret SQLRETURN) { r := C.SQLAllocHandle(C.SQLSMALLINT(handleType), C.SQLHANDLE(inputHandle), (*C.SQLHANDLE)(outputHandle)) return SQLRETURN(r) }
func (stmt *Statement) BindParam(index int, param interface{}) *ODBCError { var ValueType C.SQLSMALLINT var ParameterType C.SQLSMALLINT var ColumnSize C.SQLULEN var DecimalDigits C.SQLSMALLINT var ParameterValuePtr C.SQLPOINTER var BufferLength C.SQLLEN var StrLen_or_IndPt C.SQLLEN v := reflect.ValueOf(param) if param == nil { ft, _, _, _, err := stmt.GetParamType(index) if err != nil { return err } ParameterType = C.SQLSMALLINT(ft) if ParameterType == C.SQL_UNKNOWN_TYPE { ParameterType = C.SQL_VARCHAR } ValueType = C.SQL_C_DEFAULT StrLen_or_IndPt = C.SQL_NULL_DATA ColumnSize = 1 } else { switch v.Kind() { case reflect.Bool: ParameterType = C.SQL_BIT ValueType = C.SQL_C_BIT var b [1]byte if v.Bool() { b[0] = 1 } else { b[0] = 0 } ParameterValuePtr = C.SQLPOINTER(unsafe.Pointer(&b[0])) BufferLength = 1 StrLen_or_IndPt = 0 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: switch v.Type().Kind() { case reflect.Int: case reflect.Int8, reflect.Int16, reflect.Int32: ParameterType = C.SQL_INTEGER ValueType = C.SQL_C_LONG var l C.long = C.long(v.Int()) ParameterValuePtr = C.SQLPOINTER(unsafe.Pointer(&l)) BufferLength = 4 StrLen_or_IndPt = 0 case reflect.Int64: ParameterType = C.SQL_BIGINT ValueType = C.SQL_C_SBIGINT var ll C.longlong = C.longlong(v.Int()) ParameterValuePtr = C.SQLPOINTER(unsafe.Pointer(&ll)) BufferLength = 8 StrLen_or_IndPt = 0 } case reflect.Float32, reflect.Float64: ParameterType = C.SQL_DOUBLE ValueType = C.SQL_C_DOUBLE var d C.double = C.double(v.Float()) ParameterValuePtr = C.SQLPOINTER(unsafe.Pointer(&d)) BufferLength = 8 StrLen_or_IndPt = 0 case reflect.Complex64, reflect.Complex128: case reflect.String: var slen C.SQLUINTEGER = C.SQLUINTEGER(len(v.String())) ParameterType = C.SQL_VARCHAR ValueType = C.SQL_C_CHAR s := []byte(v.String()) ParameterValuePtr = C.SQLPOINTER(unsafe.Pointer(&s[0])) ColumnSize = C.SQLULEN(slen) BufferLength = C.SQLLEN(slen + 1) StrLen_or_IndPt = C.SQLLEN(slen) default: fmt.Println("Not support type", v) } } ret := C.SQLBindParameter(C.SQLHSTMT(stmt.handle), C.SQLUSMALLINT(index), C.SQL_PARAM_INPUT, ValueType, ParameterType, ColumnSize, DecimalDigits, ParameterValuePtr, BufferLength, &StrLen_or_IndPt) if !Success(ret) { err := FormatError(C.SQL_HANDLE_STMT, stmt.handle) return err } return nil }
func (stmt *Statement) GetField(field_index int) (v interface{}, ftype int, flen int, err *ODBCError) { var field_type C.int var field_len C.SQLLEN var ll C.SQLSMALLINT ret := C._SQLColAttribute(C.SQLHSTMT(stmt.handle), C.SQLUSMALLINT(field_index+1), C.SQL_DESC_CONCISE_TYPE, C.SQLPOINTER(unsafe.Pointer(uintptr(0))), C.SQLSMALLINT(0), &ll, unsafe.Pointer(&field_type)) if !Success(ret) { // TODO return err } ret = C._SQLColAttribute(C.SQLHSTMT(stmt.handle), C.SQLUSMALLINT(field_index+1), C.SQL_DESC_LENGTH, C.SQLPOINTER(unsafe.Pointer(uintptr(0))), C.SQLSMALLINT(0), &ll, unsafe.Pointer(&field_len)) if !Success(ret) { // TODO return err } var fl C.SQLLEN = C.SQLLEN(field_len) switch int(field_type) { case C.SQL_BIT: var value C.BYTE ret = C.SQLGetData(C.SQLHSTMT(stmt.handle), C.SQLUSMALLINT(field_index+1), C.SQL_C_BIT, C.SQLPOINTER(unsafe.Pointer(&value)), 0, &fl) if fl == -1 { v = nil } else { v = byte(value) } case C.SQL_INTEGER, C.SQL_SMALLINT, C.SQL_TINYINT: var value C.long ret = C.SQLGetData(C.SQLHSTMT(stmt.handle), C.SQLUSMALLINT(field_index+1), C.SQL_C_LONG, C.SQLPOINTER(unsafe.Pointer(&value)), 0, &fl) if fl == -1 { v = nil } else { v = int(value) } case C.SQL_BIGINT: var value C.longlong ret = C.SQLGetData(C.SQLHSTMT(stmt.handle), C.SQLUSMALLINT(field_index+1), C.SQL_C_SBIGINT, C.SQLPOINTER(unsafe.Pointer(&value)), 0, &fl) if fl == -1 { v = nil } else { v = int64(value) } case C.SQL_FLOAT, C.SQL_REAL, C.SQL_DOUBLE: var value C.double ret = C.SQLGetData(C.SQLHSTMT(stmt.handle), C.SQLUSMALLINT(field_index+1), C.SQL_C_DOUBLE, C.SQLPOINTER(unsafe.Pointer(&value)), 0, &fl) if fl == -1 { v = nil } else { v = float64(value) } case C.SQL_CHAR, C.SQL_VARCHAR, C.SQL_LONGVARCHAR, C.SQL_WCHAR, C.SQL_WVARCHAR, C.SQL_WLONGVARCHAR: value := make([]uint16, int(field_len)+8) ret = C.SQLGetData(C.SQLHSTMT(stmt.handle), C.SQLUSMALLINT(field_index+1), C.SQL_C_WCHAR, C.SQLPOINTER(unsafe.Pointer(&value[0])), field_len+4, &fl) s := UTF16ToString(value) v = s case C.SQL_TYPE_TIMESTAMP, C.SQL_TYPE_DATE, C.SQL_TYPE_TIME, C.SQL_DATETIME: var value C.TIMESTAMP_STRUCT ret = C.SQLGetData(C.SQLHSTMT(stmt.handle), C.SQLUSMALLINT(field_index+1), C.SQL_C_TYPE_TIMESTAMP, C.SQLPOINTER(unsafe.Pointer(&value)), C.SQLLEN(unsafe.Sizeof(value)), &fl) if fl == -1 { v = nil } else { v = time.Date(int(value.year), time.Month(value.month), int(value.day), int(value.hour), int(value.minute), int(value.second), int(value.fraction), time.UTC) } case C.SQL_BINARY, C.SQL_VARBINARY, C.SQL_LONGVARBINARY: var vv int ret = C.SQLGetData(C.SQLHSTMT(stmt.handle), C.SQLUSMALLINT(field_index+1), C.SQL_C_BINARY, C.SQLPOINTER(unsafe.Pointer(&vv)), 0, &fl) if fl == -1 { v = nil } else { value := make([]byte, fl) ret = C.SQLGetData(C.SQLHSTMT(stmt.handle), C.SQLUSMALLINT(field_index+1), C.SQL_C_BINARY, C.SQLPOINTER(unsafe.Pointer(&value[0])), C.SQLLEN(fl), &fl) v = value } default: value := make([]byte, field_len) ret = C.SQLGetData(C.SQLHSTMT(stmt.handle), C.SQLUSMALLINT(field_index+1), C.SQL_C_BINARY, C.SQLPOINTER(unsafe.Pointer(&value[0])), field_len, &fl) v = value } if !Success(ret) { err = FormatError(C.SQL_HANDLE_STMT, stmt.handle) } return v, int(field_type), int(fl), err }
func (stmt *Statement) GetField(field_index int) (v interface{}, ftype int, flen int, err *ODBCError) { var field_type C.SQLINTEGER var field_len C.SQLINTEGER var ll C.SQLSMALLINT ret := C.SQLColAttribute(C.SQLHSTMT(stmt.handle), C.SQLUSMALLINT(field_index+1), C.SQL_DESC_CONCISE_TYPE, C.SQLPOINTER(unsafe.Pointer(uintptr(0))), C.SQLSMALLINT(0), &ll, &field_type) if !Success(ret) { debugPrint("GetFiled type Error") } ret = C.SQLColAttribute(C.SQLHSTMT(stmt.handle), C.SQLUSMALLINT(field_index+1), C.SQL_DESC_LENGTH, C.SQLPOINTER(unsafe.Pointer(uintptr(0))), C.SQLSMALLINT(0), &ll, &field_len) if !Success(ret) { debugPrint("GetFiled len Error") } var fl C.SQLLEN = C.SQLLEN(field_len) switch int(field_type) { case C.SQL_BIT, C.SQL_INTEGER, C.SQL_SMALLINT, C.SQL_TINYINT: var value C.HANDLE ret = C.SQLGetData(C.SQLHSTMT(stmt.handle), C.SQLUSMALLINT(field_index+1), C.SQL_C_LONG, C.SQLPOINTER(unsafe.Pointer(&value)), 0, &fl) if fl == -1 { v = nil } else { v = value } case C.SQL_FLOAT, C.SQL_REAL: var value C.double ret = C.SQLGetData(C.SQLHSTMT(stmt.handle), C.SQLUSMALLINT(field_index+1), C.SQL_C_DOUBLE, C.SQLPOINTER(unsafe.Pointer(&value)), 0, &fl) if fl == -1 { v = nil } else { v = value } case C.SQL_WCHAR, C.SQL_WVARCHAR, C.SQL_WLONGVARCHAR: value := make([]uint16, int(field_len)+8) ret = C.SQLGetData(C.SQLHSTMT(stmt.handle), C.SQLUSMALLINT(field_index+1), C.SQL_C_WCHAR, C.SQLPOINTER(unsafe.Pointer(&value[0])), C.SQLINTEGER(int(field_len)+4), &fl) s := UTF16ToString(value) v = s default: value := make([]byte, int(fl)+2) ret = C.SQLGetData(C.SQLHSTMT(stmt.handle), C.SQLUSMALLINT(field_index+1), C.SQL_C_CHAR, C.SQLPOINTER(unsafe.Pointer(&value[0])), C.SQLINTEGER(int(field_len)+4), &fl) s := string(value[0:]) v = s debugPrint("default type", value, fl, s) } if !Success(ret) { err = FormatError(C.SQL_HANDLE_STMT, stmt.handle, int(ret)) debugPrint("GetFiled Data Error", err) } return v, int(field_type), int(fl), err }