fix: network filter by ipv6 address (#23226)

Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
This commit is contained in:
Jian Qiu
2025-09-03 05:46:31 +08:00
committed by GitHub
co-authored by Qiu Jian
parent 8eb11e7865
commit 4781f552e2
19 changed files with 210 additions and 94 deletions
+2 -2
View File
@@ -87,14 +87,14 @@ require (
k8s.io/client-go v0.19.3
k8s.io/cluster-bootstrap v0.19.3
moul.io/http2curl/v2 v2.3.0
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250820024124-b54c4686c57c
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250902072442-5c3779f6481e
yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0
yunion.io/x/jsonutils v1.0.1-0.20250507052344-1abcf4f443b1
yunion.io/x/log v1.0.1-0.20240305175729-7cf2d6cd5a91
yunion.io/x/ovsdb v0.0.0-20230306173834-f164f413a900
yunion.io/x/pkg v1.10.4-0.20250820035218-6008459eb4f0
yunion.io/x/s3cli v0.0.0-20241221171442-1c11599d28e1
yunion.io/x/sqlchemy v1.1.3-0.20250806073422-e37f5197cec0
yunion.io/x/sqlchemy v1.1.3-0.20250902120005-3b18bc6371c7
yunion.io/x/structarg v0.0.0-20231017124457-df4d5009457c
)
+4 -4
View File
@@ -1271,8 +1271,8 @@ sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250820024124-b54c4686c57c h1:OfxElEPjNCFhPIq4RHwDCGl/FOppGey9lMnO3HsUUgA=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250820024124-b54c4686c57c/go.mod h1:FXxAEbdNfWXX9gjME3K2nJhkydHY5EKEUZb+RLEzVwQ=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250902072442-5c3779f6481e h1:NkyXNnsky4PIW4CdsuISwDzB6DAO1dF+x8MmkFA+98w=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250902072442-5c3779f6481e/go.mod h1:FXxAEbdNfWXX9gjME3K2nJhkydHY5EKEUZb+RLEzVwQ=
yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0 h1:msG4SiDSVU7CrXH06WuHlNEZXIooTcmNbfrIGHuIHBU=
yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0/go.mod h1:Uxuou9WQIeJXNpy7t2fPLL0BYLvLiMvGQwY7Qc6aSws=
yunion.io/x/jsonutils v0.0.0-20190625054549-a964e1e8a051/go.mod h1:4N0/RVzsYL3kH3WE/H1BjUQdFiWu50JGCFQuuy+Z634=
@@ -1290,7 +1290,7 @@ yunion.io/x/pkg v1.10.4-0.20250820035218-6008459eb4f0 h1:/vHcYqzQInxqR1jjS+e7A0o
yunion.io/x/pkg v1.10.4-0.20250820035218-6008459eb4f0/go.mod h1:0Bwxqd9MA3ACi119/l02FprY/o9gHahmYC2bsSbnVpM=
yunion.io/x/s3cli v0.0.0-20241221171442-1c11599d28e1 h1:1KJ3YYinydPHpDEQRXdr/T8SYcKZ5Er+m489H+PnaQ4=
yunion.io/x/s3cli v0.0.0-20241221171442-1c11599d28e1/go.mod h1:0iFKpOs1y4lbCxeOmq3Xx/0AcQoewVPwj62eRluioEo=
yunion.io/x/sqlchemy v1.1.3-0.20250806073422-e37f5197cec0 h1:Eha/ywh4foMJm7VJ8ibFOi+WPHacuTWtosAGpOld5vo=
yunion.io/x/sqlchemy v1.1.3-0.20250806073422-e37f5197cec0/go.mod h1:vCIZpqhZ5Jzaq3tFyrti/vv8BijQKtkzSgNT/uH4H5A=
yunion.io/x/sqlchemy v1.1.3-0.20250902120005-3b18bc6371c7 h1:0OccQYkey6OsNUZNxd6CpCB/espBPnwlLT/gjl9YbXM=
yunion.io/x/sqlchemy v1.1.3-0.20250902120005-3b18bc6371c7/go.mod h1:vCIZpqhZ5Jzaq3tFyrti/vv8BijQKtkzSgNT/uH4H5A=
yunion.io/x/structarg v0.0.0-20231017124457-df4d5009457c h1:QuLab2kSRECZRxo4Lo2KcYn6XjQFDGaZ1+x0pYDVVwQ=
yunion.io/x/structarg v0.0.0-20231017124457-df4d5009457c/go.mod h1:EP6NSv2C0zzqBDTKumv8hPWLb3XvgMZDHQRfyuOrQng=
+14 -8
View File
@@ -2664,9 +2664,11 @@ func (manager *SNetworkManager) ListItemFilter(
ipStart := sqlchemy.INET_ATON(q.Field("guest_ip_start"))
ipEnd := sqlchemy.INET_ATON(q.Field("guest_ip_end"))
ipConst := sqlchemy.INET_ATON(q.StringField(ip4Addr.String()))
ipCondtion = sqlchemy.AND(
sqlchemy.GE(ipEnd, uint32(ip4Addr)),
sqlchemy.LE(ipStart, uint32(ip4Addr)),
sqlchemy.GE(ipEnd, ipConst),
sqlchemy.LE(ipStart, ipConst),
)
if !exactIpMatch {
ipCondtion = sqlchemy.OR(
@@ -2677,18 +2679,20 @@ func (manager *SNetworkManager) ListItemFilter(
}
} else if ip6Addr, err := netutils.NewIPV6Addr(ipstr); err == nil {
// ipv6 address, exactly
ipStart := q.Field("guest_ip6_start")
ipEnd := q.Field("guest_ip6_end")
ipStart := sqlchemy.INET6_ATON(q.Field("guest_ip6_start"))
ipEnd := sqlchemy.INET6_ATON(q.Field("guest_ip6_end"))
ipConst := sqlchemy.INET6_ATON(q.StringField(ip6Addr.String()))
ipCondtion = sqlchemy.AND(
sqlchemy.GE(ipEnd, ip6Addr.String()),
sqlchemy.LE(ipStart, ip6Addr.String()),
sqlchemy.GE(ipEnd, ipConst),
sqlchemy.LE(ipStart, ipConst),
)
if !exactIpMatch {
ipCondtion = sqlchemy.OR(
ipCondtion,
sqlchemy.Contains(q.Field("guest_ip6_start"), ipstr),
sqlchemy.Contains(q.Field("guest_ip6_end"), ipstr),
sqlchemy.Contains(q.Field("guest_ip6_start"), ip6Addr.String()),
sqlchemy.Contains(q.Field("guest_ip6_end"), ip6Addr.String()),
)
}
} else {
@@ -2810,6 +2814,8 @@ func (manager *SNetworkManager) ListItemFilter(
q = q.In("wire_id", subq.SubQuery())
}
q.DebugQuery()
return q, nil
}
+2 -2
View File
@@ -1576,7 +1576,7 @@ sigs.k8s.io/structured-merge-diff/v4/value
# sigs.k8s.io/yaml v1.2.0
## explicit; go 1.12
sigs.k8s.io/yaml
# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250820024124-b54c4686c57c
# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250902072442-5c3779f6481e
## explicit; go 1.21
yunion.io/x/cloudmux/pkg/apis
yunion.io/x/cloudmux/pkg/apis/billing
@@ -1725,7 +1725,7 @@ yunion.io/x/pkg/utils
# yunion.io/x/s3cli v0.0.0-20241221171442-1c11599d28e1
## explicit; go 1.12
yunion.io/x/s3cli
# yunion.io/x/sqlchemy v1.1.3-0.20250806073422-e37f5197cec0
# yunion.io/x/sqlchemy v1.1.3-0.20250902120005-3b18bc6371c7
## explicit; go 1.17
yunion.io/x/sqlchemy
yunion.io/x/sqlchemy/backends
+6
View File
@@ -73,6 +73,7 @@ const (
CITY_HUAI_NAN = "HuaiNan" //淮南
CITY_SU_QIAN = "SuQian" //宿迁
CITY_DA_LIAN = "Dalian" //大连
CITY_TAI_BEI = "TaiBei" //台北
// 日本
CITY_TOKYO = "Tokyo" //东京
@@ -161,6 +162,7 @@ const (
CITY_QUEBEC = "Quebec" //魁北克市
CITY_TORONTO = "Toronto" //多伦多
CITY_MONTREAL = "Montreal" //蒙特利尔
CITY_CALGARY = "Calgary" //卡尔加里
// 爱尔兰
CITY_IRELAND = "Ireland" //爱尔兰
@@ -224,6 +226,9 @@ const (
// 卡塔尔
CITY_DOHA = "Doha" // 多哈
// 新西兰
CITY_NEW_ZEALAND = "New Zealand" // 新西兰
COUNTRY_CODE_CN = "CN" //中国
COUNTRY_CODE_JP = "JP" //日本
COUNTRY_CODE_SG = "SG" //新加坡
@@ -259,4 +264,5 @@ const (
COUNTRY_CODE_IT = "IT" //意大利
COUNTRY_CODE_ES = "ES" //西班牙
COUNTRY_CODE_QA = "QA" //卡塔尔
COUNTRY_CODE_NZ = "NZ" //新西兰
)
+18
View File
@@ -768,4 +768,22 @@ var (
City: CITY_NAGPUR,
CountryCode: COUNTRY_CODE_IN,
}
RegionNewZealand = cloudprovider.SGeographicInfo{
Latitude: -41.287,
Longitude: 174.776,
City: CITY_NEW_ZEALAND,
CountryCode: COUNTRY_CODE_NZ,
}
RegionTaipei = cloudprovider.SGeographicInfo{
Latitude: 25.038,
Longitude: 121.525,
City: CITY_TAI_BEI,
CountryCode: COUNTRY_CODE_CN,
}
RegionCalgary = cloudprovider.SGeographicInfo{
Latitude: 51.0486,
Longitude: -114.0708,
City: CITY_CALGARY,
CountryCode: COUNTRY_CODE_CA,
}
)
@@ -94,6 +94,9 @@ func (lbr *SLoadbalancerListenerRule) GetDomain() string {
}
func (lbr *SLoadbalancerListenerRule) GetPath() string {
if len(lbr.Url) == 0 {
return "/"
}
return lbr.Url
}
@@ -55,4 +55,11 @@ var LatitudeAndLongitude = map[string]cloudprovider.SGeographicInfo{
"ap-southeast-3": api.RegionJakarta,
"me-central-1": api.RegionDubai,
"il-central-1": api.RegionTelAviv,
"ap-southeast-6": api.RegionNewZealand,
"ap-east-2": api.RegionTaipei,
"mx-central-1": api.RegionMexico,
"ap-southeast-7": api.RegionBangkok,
"ap-southeast-5": api.RegionKualaLumpur,
"ca-west-1": api.RegionCalgary,
}
+6 -1
View File
@@ -20,6 +20,7 @@ import (
api "yunion.io/x/cloudmux/pkg/apis/compute"
"yunion.io/x/cloudmux/pkg/multicloud"
"yunion.io/x/pkg/util/netutils"
)
type SElbBackends struct {
@@ -99,7 +100,11 @@ func (self *SElbBackend) SyncConf(ctx context.Context, port, weight int) error {
}
func (self *SElbBackend) GetIpAddress() string {
return ""
_, err := netutils.NewIPV4Addr(self.Target.Id)
if err != nil {
return ""
}
return self.Target.Id
}
func (self *SRegion) SyncElbBackend(backendId, serverId string, oldPort, newPort int) error {
+5 -5
View File
@@ -38,11 +38,11 @@ type SElbCertificate struct {
cert *x509.Certificate
Path string `json:"Path"`
ServerCertificateName string `json:"ServerCertificateName"`
ServerCertificateID string `json:"ServerCertificateId"`
Arn string `json:"Arn"`
UploadDate time.Time `json:"UploadDate"`
Expiration time.Time `json:"Expiration"`
ServerCertificateName string `xml:"ServerCertificateName"`
ServerCertificateID string `xml:"ServerCertificateId"`
Arn string `xml:"Arn"`
UploadDate time.Time `xml:"UploadDate"`
Expiration time.Time `xml:"Expiration"`
PublicKey string
}
+39 -36
View File
@@ -42,22 +42,22 @@ type SElbListener struct {
lb *SElb
group *SElbBackendGroup
Port int `json:"Port"`
Protocol string `json:"Protocol"`
Port int `xml:"Port"`
Protocol string `xml:"Protocol"`
DefaultActions []DefaultAction `xml:"DefaultActions>member"`
SSLPolicy string `json:"SslPolicy"`
Certificates []Certificate `json:"Certificates"`
LoadBalancerArn string `json:"LoadBalancerArn"`
ListenerArn string `json:"ListenerArn"`
SSLPolicy string `xml:"SslPolicy"`
Certificates []Certificate `xml:"Certificates>member"`
LoadBalancerArn string `xml:"LoadBalancerArn"`
ListenerArn string `xml:"ListenerArn"`
}
type Certificate struct {
CertificateArn string `json:"CertificateArn"`
CertificateArn string `xml:"CertificateArn"`
}
type DefaultAction struct {
TargetGroupArn string `json:"TargetGroupArn"`
Type string `json:"Type"`
TargetGroupArn string `xml:"TargetGroupArn"`
Type string `xml:"Type"`
}
func (self *SElbListener) GetId() string {
@@ -371,7 +371,7 @@ func (self *SElbListener) CreateILoadBalancerListenerRule(rule *cloudprovider.SL
}
func (self *SElbListener) GetILoadBalancerListenerRuleById(ruleId string) (cloudprovider.ICloudLoadbalancerListenerRule, error) {
rule, err := self.lb.region.GetElbListenerRule(ruleId)
rule, err := self.lb.region.GetElbListenerRule(self.ListenerArn, ruleId)
if err != nil {
return nil, errors.Wrap(err, "GetElbListenerRule")
}
@@ -381,19 +381,13 @@ func (self *SElbListener) GetILoadBalancerListenerRuleById(ruleId string) (cloud
func (self *SElbListener) GetILoadbalancerListenerRules() ([]cloudprovider.ICloudLoadbalancerListenerRule, error) {
ret := []cloudprovider.ICloudLoadbalancerListenerRule{}
marker := ""
for {
part, marker, err := self.lb.region.GetElbListenerRules(self.ListenerArn, "", marker)
if err != nil {
return nil, err
}
for i := range part {
part[i].listener = self
ret = append(ret, &part[i])
}
if len(marker) == 0 || len(part) == 0 {
break
}
rules, err := self.lb.region.GetElbListenerRules(self.ListenerArn, "")
if err != nil {
return nil, err
}
for i := range rules {
rules[i].listener = self
ret = append(ret, &rules[i])
}
return ret, nil
}
@@ -595,7 +589,7 @@ func (self *SRegion) CreateElbListener(lbId string, opts *cloudprovider.SLoadbal
return nil, errors.Wrapf(cloudprovider.ErrNotFound, "after created")
}
func (self *SRegion) GetElbListenerRules(listenerId string, ruleId, marker string) ([]SElbListenerRule, string, error) {
func (self *SRegion) GetElbListenerRules(listenerId string, ruleId string) ([]SElbListenerRule, error) {
params := map[string]string{}
if len(listenerId) > 0 {
params["ListenerArn"] = listenerId
@@ -603,28 +597,37 @@ func (self *SRegion) GetElbListenerRules(listenerId string, ruleId, marker strin
if len(ruleId) > 0 {
params["RuleArns.member.1"] = ruleId
}
if len(marker) > 0 {
params["Marker"] = marker
ret := []SElbListenerRule{}
for {
part := struct {
Rules []SElbListenerRule `xml:"Rules>member"`
NextMarker string
}{}
err := self.elbRequest("DescribeRules", params, &part)
if err != nil {
return nil, errors.Wrapf(err, "DescribeRules")
}
ret = append(ret, part.Rules...)
if len(part.NextMarker) == 0 || len(part.Rules) == 0 {
break
}
params["Marker"] = part.NextMarker
}
ret := &SElbListenerRules{}
err := self.elbRequest("DescribeRules", params, ret)
if err != nil {
return nil, "", errors.Wrapf(err, "DescribeRules")
}
return ret.Rules, ret.NextMarker, nil
return ret, nil
}
func (self *SRegion) GetElbListenerRule(id string) (*SElbListenerRule, error) {
rules, _, err := self.GetElbListenerRules("", id, "")
func (self *SRegion) GetElbListenerRule(lisId, ruleId string) (*SElbListenerRule, error) {
rules, err := self.GetElbListenerRules(lisId, ruleId)
if err != nil {
return nil, errors.Wrapf(err, "GetElbListenerRules")
}
for i := range rules {
if rules[i].RuleArn == id {
if rules[i].RuleArn == ruleId {
return &rules[i], nil
}
}
return nil, errors.Wrapf(cloudprovider.ErrNotFound, id)
return nil, errors.Wrapf(cloudprovider.ErrNotFound, ruleId)
}
func (self *SRegion) DeleteElbListener(id string) error {
+22 -22
View File
@@ -40,45 +40,45 @@ type SElbListenerRule struct {
listener *SElbListener
region *SRegion
Priority string `json:"Priority"`
IsDefaultRule bool `json:"IsDefault"`
Actions []Action `json:"Actions"`
RuleArn string `json:"RuleArn"`
Conditions []Condition `json:"Conditions"`
Priority string `xml:"Priority"`
IsDefaultRule bool `xml:"IsDefault"`
Actions []Action `xml:"Actions>member"`
RuleArn string `xml:"RuleArn"`
Conditions []Condition `xml:"Conditions>member"`
}
type Action struct {
TargetGroupArn string `json:"TargetGroupArn"`
Type string `json:"Type"`
TargetGroupArn string `xml:"TargetGroupArn"`
Type string `xml:"Type"`
}
type Condition struct {
Field string `json:"field"`
HTTPRequestMethodConfig *Config `json:"httpRequestMethodConfig,omitempty"`
Values []string `json:"values"`
SourceIPConfig *Config `json:"sourceIpConfig,omitempty"`
QueryStringConfig *QueryStringConfig `json:"queryStringConfig,omitempty"`
HTTPHeaderConfig *HTTPHeaderConfig `json:"httpHeaderConfig,omitempty"`
PathPatternConfig *Config `json:"pathPatternConfig,omitempty"`
HostHeaderConfig *Config `json:"hostHeaderConfig,omitempty"`
Field string `xml:"Field"`
HTTPRequestMethodConfig *Config `xml:"HttpRequestMethodConfig"`
Values []string `xml:"Values>member"`
SourceIPConfig *Config `xml:"SourceIpConfig"`
QueryStringConfig *QueryStringConfig `xml:"QueryStringConfig"`
HTTPHeaderConfig *HTTPHeaderConfig `xml:"HttpHeaderConfig"`
PathPatternConfig *Config `xml:"PathPatternConfig"`
HostHeaderConfig *Config `xml:"HostHeaderConfig"`
}
type HTTPHeaderConfig struct {
HTTPHeaderName string `json:"HttpHeaderName"`
Values []string `json:"values"`
HTTPHeaderName string `xml:"HttpHeaderName"`
Values []string `xml:"Values>member"`
}
type Config struct {
Values []string `json:"values"`
Values []string `xml:"Values>member"`
}
type QueryStringConfig struct {
Values []Query `json:"values"`
Values []Query `xml:"Values>member"`
}
type Query struct {
Key string `json:"key"`
Value string `json:"value"`
Key string `xml:"key"`
Value string `xml:"value"`
}
func (self *SElbListenerRule) GetId() string {
@@ -99,7 +99,7 @@ func (self *SElbListenerRule) GetStatus() string {
}
func (self *SElbListenerRule) Refresh() error {
rule, err := self.region.GetElbListenerRule(self.RuleArn)
rule, err := self.region.GetElbListenerRule(self.listener.ListenerArn, self.RuleArn)
if err != nil {
return err
}
+13 -1
View File
@@ -74,6 +74,12 @@ var RegionLocations = map[string]string{
"me-central-1": "中东(阿联酋)",
"ap-southeast-3": "亚太地区(雅加达)",
"il-central-1": "以色列(特拉维夫)",
"ap-southeast-6": "亚太地区(新西兰)",
"ap-east-2": "亚太地区(台北)",
"mx-central-1": "北美地区(墨西哥)",
"ap-southeast-7": "亚太地区(泰国)",
"ap-southeast-5": "亚太地区(马来西亚)",
"ca-west-1": "加拿大(卡尔加里)",
}
// https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.RegionsAndAvailabilityZones.html
@@ -111,6 +117,12 @@ var RegionLocationsEN = map[string]string{
"me-central-1": "Middle East (UAE)",
"ap-southeast-3": "Asia Pacific (Jakarta)",
"il-central-1": "Israel (Tel Aviv)",
"ap-southeast-6": "Asia Pacific (New Zealand)",
"ap-east-2": "Asia Pacific (Taipei)",
"mx-central-1": "North America (Mexico)",
"ap-southeast-7": "Asia Pacific (Thailand)",
"ap-southeast-5": "Asia Pacific (Malaysia)",
"ca-west-1": "Canada (Calgary)",
}
const (
@@ -243,7 +255,7 @@ func (self *SRegion) eksRequest(apiName, path string, params map[string]interfac
return self.client.invoke(self.RegionId, EKS_SERVICE_NAME, EKS_SERVICE_ID, "2017-11-01", apiName, path, params, retval, true)
}
/////////////////////////////////////////////////////////////////////////////
// ///////////////////////////////////////////////////////////////////////////
func (self *SRegion) GetZones(id string) ([]SZone, error) {
params := map[string]string{
"Filter.1.Name": "region-name",
@@ -59,9 +59,12 @@ var LatitudeAndLongitude = map[string]cloudprovider.SGeographicInfo{
"us-south1": api.RegionDallas,
"southamerica-west1": api.RegionSantiago,
"me-west1": api.RegionTelAviv,
"me-central1": api.RegionDoha,
"me-central2": api.RegionDamman,
"me-west1": api.RegionTelAviv,
"me-central1": api.RegionDoha,
"me-central2": api.RegionDamman,
"africa-south1": api.RegionJohannesburg,
"europe-north2": api.RegionStockholm,
"northamerica-south1": api.RegionMexico,
}
var RegionNames = map[string]string{
@@ -116,4 +119,9 @@ var RegionNames = map[string]string{
// Dual-region
"nam4": "爱荷华和南卡罗来纳",
"eur4": "荷兰和芬兰",
"global": "全球",
"africa-south1": "约翰内斯堡",
"europe-north2": "斯德哥尔摩",
"northamerica-south1": "墨西哥",
}
+8 -6
View File
@@ -17,6 +17,7 @@ package qcloud
import (
"context"
"fmt"
"strings"
"yunion.io/x/jsonutils"
@@ -58,14 +59,15 @@ type Rule struct {
Targets []SLBBackend `json:"Targets"`
}
// ==========================================================
// backend InstanceId + protocol +Port + ip + rip全局唯一
// backend InstanceId + protocol + port + ip + rip全局唯一
func (self *SLBBackend) GetId() string {
if len(self.Domain) == 0 {
return fmt.Sprintf("%s/%s-%d", self.group.GetId(), self.InstanceId, self.Port)
ret := []string{self.group.GetId(), self.InstanceId, fmt.Sprintf("%d", self.Port)}
ret = append(ret, self.PrivateIPAddresses...)
if len(self.Domain) > 0 {
ret = append(ret, self.Domain)
ret = append(ret, self.Url)
}
return fmt.Sprintf("%s/%s-%d:%s%s", self.group.GetId(), self.InstanceId, self.Port, self.Domain, self.Url)
return strings.Join(ret, "/")
}
func (self *SLBBackend) GetName() string {
+2
View File
@@ -123,6 +123,8 @@ type IBackend interface {
DATE_FORMAT(name string, field IQueryField, format string) IQueryField
// INET_ATON
INET_ATON(field IQueryField) IQueryField
// INET6_ATON
INET6_ATON(field IQueryField) IQueryField
// AND_Val
AND_Val(name string, field IQueryField, v interface{}) IQueryField
// OR_Val
+8 -2
View File
@@ -31,7 +31,7 @@ func (dameng *SDamengBackend) GROUP_CONCAT2(name string, sep string, field sqlch
// INET_ATON represents the SQL function INET_ATON
func (dameng *SDamengBackend) INET_ATON(field sqlchemy.IQueryField) sqlchemy.IQueryField {
expr := ""
/*expr := ""
vars := make([]sqlchemy.IQueryField, 0)
expr += `TO_NUMBER(SUBSTR(%s,1,INSTR(%s,'.')-1))*POWER(256,3)+`
vars = append(vars, field, field)
@@ -41,7 +41,8 @@ func (dameng *SDamengBackend) INET_ATON(field sqlchemy.IQueryField) sqlchemy.IQu
vars = append(vars, field, field, field, field)
expr += `TO_NUMBER(SUBSTR(%s,INSTR(%s,'.',1,3)+1))`
vars = append(vars, field, field)
return sqlchemy.NewFunctionField("", false, expr, vars...)
return sqlchemy.NewFunctionField("", false, expr, vars...)*/
return sqlchemy.NewFunctionField("", false, `HEX(SF_INET_SORT(%s))`, field)
}
// cast field to string
@@ -58,3 +59,8 @@ func (dameng *SDamengBackend) CASTInt(field sqlchemy.IQueryField, fieldname stri
func (dameng *SDamengBackend) CASTFloat(field sqlchemy.IQueryField, fieldname string) sqlchemy.IQueryField {
return sqlchemy.NewFunctionField(fieldname, false, `CAST(%s AS REAL)`, field)
}
// INET6_ATON represents a SQL function INET6_ATON
func (dameng *SDamengBackend) INET6_ATON(field sqlchemy.IQueryField) sqlchemy.IQueryField {
return sqlchemy.NewFunctionField("", false, `HEX(SF_INET_SORT(%s))`, field)
}
+5
View File
@@ -154,6 +154,11 @@ func (bb *SBaseBackend) INET_ATON(field IQueryField) IQueryField {
return NewFunctionField("", false, `INET_ATON(%s)`, field)
}
// INET6_ATON represents a SQL function INET6_ATON
func (bb *SBaseBackend) INET6_ATON(field IQueryField) IQueryField {
return NewFunctionField("", false, `INET6_ATON(%s)`, field)
}
// SubStr represents a SQL function SUBSTR
func (bb *SBaseBackend) SUBSTR(name string, field IQueryField, pos, length int) IQueryField {
var rightStr string
+35 -2
View File
@@ -228,6 +228,8 @@ func REPLACE(name string, field IQueryField, old string, new string) IQueryField
type SConstField struct {
constVar interface{}
alias string
db *SDatabase
}
// Expression implementation of SConstField for IQueryField
@@ -260,7 +262,7 @@ func (s *SConstField) ConvertFromValue(val interface{}) interface{} {
// database implementation of SConstField for IQueryField
func (s *SConstField) database() *SDatabase {
return nil
return s.db
}
// Variables implementation of SConstField for IQueryField
@@ -278,10 +280,24 @@ func NewConstField(variable interface{}) *SConstField {
return &SConstField{constVar: variable}
}
// database implementation of SStringField for IQueryField
func (s *SConstField) WithField(f IQueryField) *SConstField {
s.db = f.database()
return s
}
func (q *SQuery) ConstField(variable interface{}) *SConstField {
f := NewConstField(variable)
f.db = q.db
return f
}
// SStringField is a query field of a string constant
type SStringField struct {
strConst string
alias string
db *SDatabase
}
// Expression implementation of SStringField for IQueryField
@@ -314,7 +330,7 @@ func (s *SStringField) ConvertFromValue(val interface{}) interface{} {
// database implementation of SStringField for IQueryField
func (s *SStringField) database() *SDatabase {
return nil
return s.db
}
// Variables implementation of SStringField for IQueryField
@@ -327,11 +343,23 @@ func (s *SStringField) IsAggregate() bool {
return true
}
// database implementation of SStringField for IQueryField
func (s *SStringField) WithField(f IQueryField) *SStringField {
s.db = f.database()
return s
}
// NewStringField returns an instance of SStringField
func NewStringField(strConst string) *SStringField {
return &SStringField{strConst: strConst}
}
func (q *SQuery) StringField(strConst string) *SStringField {
f := NewStringField(strConst)
f.db = q.db
return f
}
// CONCAT represents a SQL function CONCAT
func CONCAT(name string, fields ...IQueryField) IQueryField {
return getFieldBackend(fields...).CONCAT(name, fields...)
@@ -363,6 +391,11 @@ func INET_ATON(field IQueryField) IQueryField {
return getFieldBackend(field).INET_ATON(field)
}
// INET6_ATON represents a SQL function INET_ATON
func INET6_ATON(field IQueryField) IQueryField {
return getFieldBackend(field).INET6_ATON(field)
}
// TimestampAdd represents a SQL function TimestampAdd
func TimestampAdd(name string, field IQueryField, offsetSeconds int) IQueryField {
return TIMESTAMPADD(name, field, offsetSeconds)