package xugu import ( "bytes" "encoding/binary" "fmt" "strings" ) func parseDSN(dsn string) dsnConfig { // Initialize a dsnConfig struct var config dsnConfig // Split the string by semicolons pairs := strings.Split(dsn, ";") // Iterate over the pairs and map them to the struct fields for _, pair := range pairs { // Split each pair by the equals sign kv := strings.SplitN(pair, "=", 2) if len(kv) != 2 { continue } key, value := strings.TrimSpace(kv[0]), strings.Trim(strings.TrimSpace(kv[1]), "'") keyL := strings.ToLower(key) // Map the key to the appropriate struct field switch keyL { case "ip": config.IP = value case "port": config.Port = value case "db": config.Database = value case "user": config.User = value case "pwd": config.Password = value case "encryptor": config.Encryptor = value case "char_set": config.CharSet = value case "time_zone": config.TimeZone = value case "iso_level": config.IsoLevel = value case "lock_timeout": config.LockTimeout = value case "auto_commit": config.AutoCommit = value case "strict_commit": config.StrictCommit = value case "result": config.Result = value case "return_schema": config.ReturnSchema = value case "return_cursor_id": config.ReturnCursorID = value case "lob_ret": config.LobRet = value case "return_rowid": config.ReturnRowid = value case "version": config.Version = value } } return config } func generateLoginString(config dsnConfig) string { baseString := "login database = '%s' user = '%s' password = '%s' " additionalParams := "" if config.Encryptor != "" { additionalParams += fmt.Sprintf(" encryptor='%s'", config.Encryptor) } if config.CharSet != "" { additionalParams += fmt.Sprintf(" char_set='%s'", config.CharSet) } if config.TimeZone != "" { additionalParams += fmt.Sprintf(" time_zone='%s'", config.TimeZone) } if config.IsoLevel != "" { additionalParams += fmt.Sprintf(" iso_level='%s'", config.IsoLevel) } if config.LockTimeout != "" { additionalParams += fmt.Sprintf(" lock_timeout='%s'", config.LockTimeout) } if config.AutoCommit != "" { additionalParams += fmt.Sprintf(" auto_commit='%s'", config.AutoCommit) } if config.StrictCommit != "" { additionalParams += fmt.Sprintf(" strict_commit='%s'", config.StrictCommit) } if config.Result != "" { additionalParams += fmt.Sprintf(" result='%s'", config.Result) } if config.ReturnSchema != "" { additionalParams += fmt.Sprintf(" return_schema='%s'", config.ReturnSchema) } if config.ReturnCursorID != "" { additionalParams += fmt.Sprintf(" return_cursor_id='%s'", config.ReturnCursorID) } if config.LobRet != "" { additionalParams += fmt.Sprintf(" lob_ret='%s'", config.LobRet) } if config.ReturnRowid != "" { additionalParams += fmt.Sprintf(" return_rowid='%s'", config.ReturnRowid) } if config.Version != "" { additionalParams += fmt.Sprintf(" version='%s'", config.Version) } else { additionalParams += " version='201'" } finalString := fmt.Sprintf(baseString, config.Database, config.User, config.Password) if additionalParams != "" { finalString += additionalParams } //finalString += " version='201'" return finalString } // cgo_xgc_sql_type -> fun_sql_type // 判断sql类型 func switchSQLType(sql string) int { // 去掉首尾的空格、换行符和回车符 sql = strings.TrimSpace(sql) if len(sql) < 6 { return SQL_OTHER } // 取前6个字符并转为大写 kstr := strings.ToUpper(sql[:6]) // 根据SQL语句前缀判断类型 switch { case strings.HasPrefix(kstr, "SELECT"): if strings.Contains(sql, ";") && len(sql[strings.Index(sql, ";"):]) > 5 { return SQL_OTHER // 多结果集 } return SQL_SELECT case strings.HasPrefix(kstr, "INSERT"): return SQL_INSERT case strings.HasPrefix(kstr, "UPDATE"): return SQL_UPDATE case strings.HasPrefix(kstr, "DELETE"): return SQL_DELETE case strings.HasPrefix(kstr, "CREATE"): return SQL_CREATE case strings.HasPrefix(kstr, "ALTER "): return SQL_ALTER case strings.HasPrefix(kstr, "EXEC "): return SQL_PROCEDURE case strings.HasPrefix(kstr, "EXECUT"): return SQL_PROCEDURE case strings.HasPrefix(kstr, "STC"): return SQL_SELECT default: return SQL_OTHER } } func getSQLCType(typeID uint32) int32 { switch typeID { case TYPE_BOOL: return XG_C_BOOL case TYPE_I1: return XG_C_TINYINT case TYPE_I2: return XG_C_SHORT case TYPE_I4: return XG_C_INTEGER case TYPE_I8: return XG_C_BIGINT case TYPE_R4: return XG_C_FLOAT case TYPE_R8: return XG_C_DOUBLE case TYPE_NUM: return XG_C_NUMERIC case TYPE_DATETIME: return XG_C_DATETIME case TYPE_DATETIME_TZ: return XG_C_DATETIME_TZ case TYPE_INTERVAL_Y2M: return XG_C_INTERVAL_YEAR_TO_MONTH case TYPE_INTERVAL_D2S: return XG_C_INTERVAL_DAY_TO_SECOND case TYPE_GUID: return TYPE_GUID + 40 case TYPE_TIME_TZ: return XG_C_TIME_TZ case TYPE_DATE: return XG_C_DATE case TYPE_TIME: return XG_C_TIME case TYPE_BINARY: return XG_C_BINARY case TYPE_CLOB: return XG_C_CLOB case TYPE_BLOB: return XG_C_BLOB case TYPE_INTERVAL_Y, TYPE_INTERVAL_M, TYPE_INTERVAL_D, TYPE_INTERVAL_H, TYPE_INTERVAL_MI, TYPE_INTERVAL_S, TYPE_INTERVAL_D2H, TYPE_INTERVAL_D2M, TYPE_INTERVAL_H2M, TYPE_INTERVAL_H2S, TYPE_INTERVAL_M2S: return XG_C_INTERVAL default: return XG_C_CHAR } } // 整形转换成字节 func IntToBytes(n uint32, b byte) ([]byte, error) { switch b { case 1: tmp := int8(n) bytesBuffer := bytes.NewBuffer([]byte{}) binary.Write(bytesBuffer, binary.BigEndian, &tmp) return bytesBuffer.Bytes(), nil case 2: tmp := int16(n) bytesBuffer := bytes.NewBuffer([]byte{}) binary.Write(bytesBuffer, binary.BigEndian, &tmp) return bytesBuffer.Bytes(), nil case 3, 4: tmp := int32(n) bytesBuffer := bytes.NewBuffer([]byte{}) binary.Write(bytesBuffer, binary.BigEndian, &tmp) return bytesBuffer.Bytes(), nil } return nil, fmt.Errorf("IntToBytes b param is invaild") } // reverseBytes 反转 byte slice 的顺序 func reverseBytes(b []byte) []byte { reversed := make([]byte, len(b)) for i := range b { reversed[i] = b[len(b)-1-i] } return reversed } // 反转 uint32 类型 的大小端 func swapEndian(num uint32) uint32 { // 获取每个字节 b0 := byte(num & 0xFF) b1 := byte((num >> 8) & 0xFF) b2 := byte((num >> 16) & 0xFF) b3 := byte((num >> 24) & 0xFF) // 反转字节顺序并组合成新的 uint32 swappedNum := uint32(b0)<<24 | uint32(b1)<<16 | uint32(b2)<<8 | uint32(b3) return swappedNum }