Example #1
0
// Next is called to populate the next row of data into the provided slice
func (rows *rows) Next(dest []driver.Value) error {
	//If this is the first time rows has been read, setup necessary field level information
	if rows.isBeforeFirst {
		for index, resultColumnDef := range rows.resultColumnDefs {
			//Set precision and scale for numeric fields
			if resultColumnDef.DataType == odbc.SQL_NUMERIC || resultColumnDef.DataType == odbc.SQL_DECIMAL {
				colIndex := odbc.SQLSMALLINT(index + 1)
				odbc.SQLSetDescField(rows.descHandle, colIndex, odbc.SQL_DESC_TYPE, uintptr(odbc.SQL_C_NUMERIC), 0)
				odbc.SQLSetDescField(rows.descHandle, colIndex, odbc.SQL_DESC_PRECISION, uintptr(resultColumnDef.Precision), 0)
				odbc.SQLSetDescField(rows.descHandle, colIndex, odbc.SQL_DESC_SCALE, uintptr(resultColumnDef.Scale), 0)
			}
		}

		//Update isBeforeFirst
		rows.isBeforeFirst = false
	}

	//Fetch a row of data
	ret := odbc.SQLFetch(rows.handle)
	if ret == odbc.SQL_NO_DATA {
		//No more data to read
		return io.EOF
	} else if isError(ret) {
		return errorStatement(rows.handle, rows.sqlStmt)
	}

	//Get a row of data
	err := rows.getRow(dest)
	if err != nil {
		return err
	}

	return nil
}
Example #2
0
func (stmt *statement) bindDate(index int, value time.Time, direction ParameterDirection) error {
	var bindVal odbc.SQL_DATE_STRUCT
	bindVal.Year = odbc.SQLSMALLINT(value.Year())
	bindVal.Month = odbc.SQLUSMALLINT(value.Month())
	bindVal.Day = odbc.SQLUSMALLINT(value.Day())

	stmt.bindValues[index] = &bindVal
	ret := odbc.SQLBindParameter(stmt.handle, odbc.SQLUSMALLINT(index), direction.SQLBindParameterType(), odbc.SQL_C_DATE, odbc.SQL_DATE, 10, 0, odbc.SQLPOINTER(unsafe.Pointer(stmt.bindValues[index].(*odbc.SQL_DATE_STRUCT))), 6, nil)
	if isError(ret) {
		return errorStatement(stmt.handle, fmt.Sprintf("Bind index: %v, Value: %v", index, bindVal))
	}
	return nil
}
Example #3
0
func handleError(handleType odbc.SQLSMALLINT, handle odbc.SQLHandle, driverInfo string) error {
	statusRecords := make([]StatusRecord, 0)
	if handle != 0 {
		for recNum := 1; ; recNum++ {
			sqlState := make([]uint16, sqlStateLength+1)
			var nativeError odbc.SQLINTEGER
			message := make([]uint16, errorMaxMessageLength+1)
			ret := odbc.SQLGetDiagRec(handleType, handle, odbc.SQLSMALLINT(recNum), uintptr(unsafe.Pointer(&sqlState[0])), &nativeError, uintptr(unsafe.Pointer(&message[0])), errorMaxMessageLength, nil)
			if ret == odbc.SQL_NO_DATA {
				break
			} else if !isError(ret) {
				sr := StatusRecord{State: syscall.UTF16ToString(sqlState), NativeError: int(nativeError), Message: syscall.UTF16ToString(message), DriverInfo: driverInfo}
				statusRecords = append(statusRecords, sr)
			} else {
				break
			}
		}
	}

	return &ODBCError{StatusRecords: statusRecords}
}
Example #4
0
// Returns a new connection to the database
func (d *lodbcDriver) Open(name string) (driver.Conn, error) {
	// Allocate the connection handle
	var connHandle odbc.SQLHandle
	ret := odbc.SQLAllocHandle(odbc.SQL_HANDLE_DBC, envHandle, &connHandle)
	if isError(ret) {
		return nil, errorEnvironment(envHandle)
	}

	// Establish the connection with the database
	nameSqlPtr := (*odbc.SQLCHAR)(unsafe.Pointer(syscall.StringToUTF16Ptr(name)))
	ret = odbc.SQLDriverConnect(connHandle, 0, nameSqlPtr, odbc.SQLSMALLINT(odbc.SQL_NTS), nil, 0, nil, odbc.SQL_DRIVER_NOPROMPT)
	if isError(ret) {
		return nil, errorConnection(connHandle)
	}

	// Create new connection
	var conn = &connection{handle: connHandle, isTransactionActive: false, statements: make(map[driver.Stmt]bool, 0)}

	//Add a finalizer
	runtime.SetFinalizer(conn, (*connection).Close)

	return conn, nil
}
Example #5
0
// Build metadata for each result column
func buildResultColumnDefinitions(stmtHandle odbc.SQLHandle, sqlStmt string) ([]resultColumnDef, odbc.SQLReturn) {

	//Get number of result columns
	var numColumns odbc.SQLSMALLINT
	ret := odbc.SQLNumResultCols(stmtHandle, &numColumns)
	if isError(ret) {
		errorStatement(stmtHandle, sqlStmt)
	}

	resultColumnDefs := make([]resultColumnDef, 0, numColumns)
	for colNum, lNumColumns := odbc.SQLSMALLINT(1), numColumns; colNum <= lNumColumns; colNum++ {
		//Get odbc.SQL type
		var sqlType odbc.SQLLEN
		ret := odbc.SQLColAttribute(stmtHandle, odbc.SQLUSMALLINT(colNum), odbc.SQL_COLUMN_TYPE, 0, 0, nil, &sqlType)
		if isError(ret) {
			errorStatement(stmtHandle, sqlStmt)
		}

		/* Disabled because it is no longer needed
		//Get length
		var length odbc.SQLLEN
		ret = odbc.SQLColAttribute(stmtHandle, odbc.SQLUSMALLINT(colNum), odbc.SQL_COLUMN_LENGTH, 0, 0, nil, &length)
		if isError(ret) {
			errorStatement(stmtHandle, sqlStmt)
		}

		//If the type is a CHAR or VARCHAR, add 4 to the length
		if odbc.SQLDataType(sqlType) == odbc.SQL_CHAR || odbc.SQLDataType(sqlType)  == odbc.SQL_VARCHAR || odbc.SQLDataType(sqlType)  == odbc.SQL_WCHAR || odbc.SQLDataType(sqlType)  == odbc.SQL_WVARCHAR {
			length = length + 4
		} */

		//Get name
		const namelength = 1000
		nameArr := make([]uint16, namelength)
		ret = odbc.SQLColAttribute(stmtHandle, odbc.SQLUSMALLINT(colNum), odbc.SQL_DESC_LABEL, uintptr(unsafe.Pointer(&nameArr[0])), namelength, nil, nil)
		if isError(ret) {
			errorStatement(stmtHandle, sqlStmt)
		}
		name := syscall.UTF16ToString(nameArr)

		//For numeric and decimal types, get the precision
		var precision odbc.SQLLEN
		if odbc.SQLDataType(sqlType) == odbc.SQL_NUMERIC || odbc.SQLDataType(sqlType) == odbc.SQL_DECIMAL {
			ret = odbc.SQLColAttribute(stmtHandle, odbc.SQLUSMALLINT(colNum), odbc.SQL_COLUMN_PRECISION, 0, 0, nil, &precision)
			if isError(ret) {
				errorStatement(stmtHandle, sqlStmt)
			}
		}

		//For numeric and decimal types, get the scale
		var scale odbc.SQLLEN
		if odbc.SQLDataType(sqlType) == odbc.SQL_NUMERIC || odbc.SQLDataType(sqlType) == odbc.SQL_DECIMAL {
			ret = odbc.SQLColAttribute(stmtHandle, odbc.SQLUSMALLINT(colNum), odbc.SQL_COLUMN_SCALE, 0, 0, nil, &scale)
			if isError(ret) {
				errorStatement(stmtHandle, sqlStmt)
			}
		}

		col := resultColumnDef{RecNum: colNum, DataType: odbc.SQLDataType(sqlType), Name: name, Precision: precision, Scale: scale}
		resultColumnDefs = append(resultColumnDefs, col)
	}

	return resultColumnDefs, odbc.SQL_SUCCESS
}