예제 #1
0
파일: ora.go 프로젝트: ricsmania/ora
// OpenEnv opens an Oracle environment.
//
// Optionally specify a cfg parameter. If cfg is nil, default cfg values are
// applied.
func OpenEnv(cfg *EnvCfg) (env *Env, err error) {
	_drv.mu.Lock()
	defer _drv.mu.Unlock()
	log(_drv.cfg.Log.OpenEnv)
	if cfg == nil { // ensure cfg
		tmp := *_drv.cfg.Env // copy by value to ensure independent cfgs
		cfg = &tmp
	}
	var csIDAl32UTF8 C.ub2
	if csIDAl32UTF8 == 0 { // Get the code for AL32UTF8
		var ocienv *C.OCIEnv
		r := C.OCIEnvCreate(&ocienv, C.OCI_DEFAULT|C.OCI_THREADED, nil, nil, nil, nil, 0, nil)
		if r == C.OCI_ERROR {
			return nil, errF("Unable to create environment handle (Return code = %d).", r)
		}
		csName := []byte("AL32UTF8\x00") // http://docs.oracle.com/cd/B10501_01/server.920/a96529/ch8.htm#14284
		csIDAl32UTF8 = C.OCINlsCharSetNameToId(unsafe.Pointer(ocienv), (*C.oratext)(&csName[0]))
		C.OCIHandleFree(unsafe.Pointer(ocienv), C.OCI_HTYPE_ENV)
	}
	// OCI_DEFAULT  - The default value, which is non-UTF-16 encoding.
	// OCI_THREADED - Uses threaded environment. Internal data structures not exposed to the user are protected from concurrent accesses by multiple threads.
	// OCI_OBJECT   - Uses object features such as OCINumber, OCINumberToInt, OCINumberFromInt. These are used in oracle-go type conversions.
	env = _drv.envPool.Get().(*Env) // set *Env
	r := C.OCIEnvNlsCreate(
		&env.ocienv, //OCIEnv        **envhpp,
		C.OCI_DEFAULT|C.OCI_OBJECT|C.OCI_THREADED, //ub4           mode,
		nil,          //void          *ctxp,
		nil,          //void          *(*malocfp)
		nil,          //void          *(*ralocfp)
		nil,          //void          (*mfreefp)
		0,            //size_t        xtramemsz,
		nil,          //void          **usrmempp
		csIDAl32UTF8, //ub2           charset,
		csIDAl32UTF8) //ub2           ncharset );
	if r == C.OCI_ERROR {
		return nil, errF("Unable to create environment handle (Return code = %d).", r)
	}
	ocierr, err := env.allocOciHandle(C.OCI_HTYPE_ERROR) // alloc oci error handle
	if err != nil {
		return nil, errE(err)
	}

	env.ocierr = (*C.OCIError)(ocierr)
	if env.id == 0 {
		env.id = _drv.envId.nextId()
	}
	env.cfg = *cfg
	_drv.openEnvs.add(env)

	return env, nil
}
예제 #2
0
// Create and initialize a new environment object
func NewEnvironment() (*Environment, error) {
	var err error

	// create a new object for the Oracle environment
	env := &Environment{
		FixedWidth:                   false,
		MaxBytesPerCharacter:         4,
		maxStringBytes:               MAX_STRING_CHARS,
		numberToStringFormatBuffer:   []byte("TM9"),
		numberFromStringFormatBuffer: []byte("999999999999999999999999999999999999999999999999999999999999999"),
		nlsNumericCharactersBuffer:   []byte("NLS_NUMERIC_CHARACTERS='.,'"),
	}

	if CSID_AL32UTF8 == 0 {
		// create the new environment handle
		if err = checkStatus(C.OCIEnvNlsCreate(&env.handle,
			C.OCI_DEFAULT|C.OCI_THREADED, nil, nil, nil, nil, 0, nil, 0, 0),
			false); err != nil { //, C.ub2(873), 0),
			setErrAt(err, "Unable to acquire Oracle environment handle")
			return nil, err
		}
		buffer := []byte("AL32UTF8\000")
		CSID_AL32UTF8 = C.OCINlsCharSetNameToId(unsafe.Pointer(env.handle),
			(*C.oratext)(&buffer[0]))
		C.OCIHandleFree(unsafe.Pointer(&env.handle), C.OCI_HTYPE_ENV)
		// log.Printf("csid=%d", CSID_AL32UTF8)
	}
	if err = checkStatus(C.OCIEnvNlsCreate(
		&env.handle, C.OCI_DEFAULT|C.OCI_THREADED, nil, nil, nil, nil, 0, nil,
		CSID_AL32UTF8, CSID_AL32UTF8), false); err != nil {
		setErrAt(err, "Unable to acquire Oracle environment handle with AL32UTF8 charset")
		return nil, err
	}
	// log.Printf("env=%+v err=%+v", env.handle, err)

	// create the error handle
	if err = ociHandleAlloc(unsafe.Pointer(env.handle),
		C.OCI_HTYPE_ERROR, (*unsafe.Pointer)(unsafe.Pointer(&env.errorHandle)),
		"env.errorHandle"); err != nil || env.handle == nil {
		return nil, err
	}

	var sb4 C.sb4
	// acquire max bytes per character
	if err = env.CheckStatus(C.OCINlsNumericInfoGet(unsafe.Pointer(env.handle),
		env.errorHandle, &sb4, C.OCI_NLS_CHARSET_MAXBYTESZ),
		"Environment_New(): get max bytes per character"); err != nil {
		return nil, err
	}
	env.MaxBytesPerCharacter = uint(sb4)
	env.maxStringBytes = MAX_STRING_CHARS * env.MaxBytesPerCharacter
	// log.Printf("maxBytesPerCharacter=%d", env.maxBytesPerCharacter)

	// acquire whether character set is fixed width
	if err = env.CheckStatus(C.OCINlsNumericInfoGet(unsafe.Pointer(env.handle),
		env.errorHandle, &sb4, C.OCI_NLS_CHARSET_FIXEDWIDTH),
		"Environment_New(): determine if charset fixed width"); err != nil {
		return nil, err
	}
	env.FixedWidth = sb4 > 0

	var e error
	// determine encodings to use for Unicode values
	if env.Encoding, e = env.GetCharacterSetName(C.OCI_ATTR_ENV_CHARSET_ID); e != nil {
		return nil, e
	}
	if env.Nencoding, e = env.GetCharacterSetName(C.OCI_ATTR_ENV_NCHARSET_ID); e != nil {
		return nil, e
	}

	return env, nil
}