diff --git a/v1/Dockerfile b/Dockerfile similarity index 100% rename from v1/Dockerfile rename to Dockerfile diff --git a/README.md b/README.md index bfe253e..c5dd3d4 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,15 @@ # nebula-http-gateway Gateway to provide a http interface for the Nebula Graph service. + +## Run +```bash +// dev +// run api service +$ go get github.com/pilu/fresh +$ fresh main.go +``` + +## Required +- Go 11+ +- [beego](https://beego.me/) +- docker \ No newline at end of file diff --git a/v1/conf/app.conf b/conf/app.conf similarity index 100% rename from v1/conf/app.conf rename to conf/app.conf diff --git a/v1/controllers/db.go b/controllers/db.go similarity index 100% rename from v1/controllers/db.go rename to controllers/db.go diff --git a/v1/go.mod b/go.mod similarity index 64% rename from v1/go.mod rename to go.mod index 8c43006..6cb0731 100644 --- a/v1/go.mod +++ b/go.mod @@ -6,23 +6,26 @@ require ( github.com/OwnLocal/goes v1.0.0 // indirect github.com/astaxie/beego v1.12.3 github.com/elazarl/go-bindata-assetfs v1.0.1 // indirect - github.com/google/go-cmp v0.5.3 // indirect + github.com/google/go-cmp v0.5.4 // indirect github.com/kr/text v0.2.0 // indirect + github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect github.com/prometheus/client_golang v1.8.0 // indirect github.com/prometheus/common v0.15.0 // indirect github.com/satori/go.uuid v1.2.0 github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 // indirect github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726 // indirect github.com/siddontang/ledisdb v0.0.0-20181029004158-becf5f38d373 // indirect - github.com/vesoft-inc/nebula-clients/go v0.0.0-20201112071658-b2944cd3629b + github.com/vesoft-inc/nebula-clients/go v0.0.0-20201202024102-618cd50d07ad + github.com/vesoft-inc/nebula-go v1.1.0 github.com/vesoft-inc/nebula-go/v2 v2.0.0-20200921074558-805846e2abd7 - golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9 // indirect - golang.org/x/net v0.0.0-20201110031124-69a78807bb2b // indirect - golang.org/x/sys v0.0.0-20201117222635-ba5294a509c7 // indirect + golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392 // indirect + golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb // indirect + golang.org/x/sys v0.0.0-20201202213521-69691e467435 // indirect golang.org/x/text v0.3.4 // indirect golang.org/x/tools v0.0.0-20200117065230-39095c1d176c // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect google.golang.org/protobuf v1.25.0 // indirect - gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect ) diff --git a/v1/go.sum b/go.sum similarity index 94% rename from v1/go.sum rename to go.sum index 92d0712..737db0e 100644 --- a/v1/go.sum +++ b/go.sum @@ -130,6 +130,8 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3 h1:x95R7cp+rSeeqAMI2knLtQ0DKlaBhv2NrtrOvafPHRo= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -183,6 +185,8 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= @@ -335,15 +339,21 @@ github.com/ugorji/go v0.0.0-20171122102828-84cb69a8af83/go.mod h1:hnLbHMwcvSihnD github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/vesoft-inc/nebula-clients v0.0.0-20201106023157-58e2fe8abd18 h1:DXnPtehb+7MftKJWX51B8ic+sopdXFTDYGbIasnh6qE= +github.com/vesoft-inc/nebula-clients v0.0.0-20201130020811-fe3630e98056 h1:5OF3rQkjl02WRkCN8ZNnNve0VDkYTdEpPJu30VHJ0R0= github.com/vesoft-inc/nebula-clients/go v0.0.0-20201106023157-58e2fe8abd18 h1:33RqIHBukKkipxTQ5flTdeNY+m2yZim9h3cvlPuuqeQ= github.com/vesoft-inc/nebula-clients/go v0.0.0-20201106023157-58e2fe8abd18/go.mod h1:F/Qx0oOZ1IrUFU6Umn3l2Wqr1A9sRtHzZReDnzfOlp8= github.com/vesoft-inc/nebula-clients/go v0.0.0-20201112071658-b2944cd3629b h1:A4p6aC991rhIbh+wlZyRihdpErhg8UhU9cAuDCFGDp8= github.com/vesoft-inc/nebula-clients/go v0.0.0-20201112071658-b2944cd3629b/go.mod h1:F/Qx0oOZ1IrUFU6Umn3l2Wqr1A9sRtHzZReDnzfOlp8= +github.com/vesoft-inc/nebula-clients/go v0.0.0-20201130020811-fe3630e98056 h1:Jk7vMb99redyhItp0Et8hR72TgdT4Ij9KTZ30ToA/pc= +github.com/vesoft-inc/nebula-clients/go v0.0.0-20201130020811-fe3630e98056/go.mod h1:F/Qx0oOZ1IrUFU6Umn3l2Wqr1A9sRtHzZReDnzfOlp8= +github.com/vesoft-inc/nebula-clients/go v0.0.0-20201202024102-618cd50d07ad h1:dgcWHZMbiPpTjwV+sGcqa6lH5zUk6gE+yprUxWMP9gg= +github.com/vesoft-inc/nebula-clients/go v0.0.0-20201202024102-618cd50d07ad/go.mod h1:F/Qx0oOZ1IrUFU6Umn3l2Wqr1A9sRtHzZReDnzfOlp8= github.com/vesoft-inc/nebula-go v1.0.0-rc4 h1:vkYKgDhScrxGYXOqcKPv8gFSe7hmJPwWmYTtR/8mWnY= github.com/vesoft-inc/nebula-go v1.0.0-rc4/go.mod h1:sZwaFK3Cz1F1Pas/ZjLzVDEFcTNXYENKur89XYP0nbA= github.com/vesoft-inc/nebula-go v1.0.0-rc4.0.20200506095608-6a4605f65e02 h1:VfXZCAytmDdC+SNZTje2GU6HQiNFfyIM77oR7ZNf8SE= github.com/vesoft-inc/nebula-go v1.0.0-rc4.0.20200506095608-6a4605f65e02/go.mod h1:dM1R7vZjYCXZ20Kie4KYGS0UHxVDNYmDeMgb1PFPDmw= github.com/vesoft-inc/nebula-go v1.1.0 h1:o67dNlZphpCsVVkB4mk7ItqdG+1DvCfU0XTcB5mChDs= +github.com/vesoft-inc/nebula-go v1.1.0/go.mod h1:dM1R7vZjYCXZ20Kie4KYGS0UHxVDNYmDeMgb1PFPDmw= github.com/vesoft-inc/nebula-go/v2 v2.0.0-20200921074558-805846e2abd7 h1:nXU0BnXfk0Rq8oPEAs+uC93oMFsfTvXgkYYRmGVK2WI= github.com/vesoft-inc/nebula-go/v2 v2.0.0-20200921074558-805846e2abd7/go.mod h1:92I8vrIc2Rk7/oJO+1hTgjNhHiYfnsW2uu3Ofh0ECnI= github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc= @@ -372,6 +382,8 @@ golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9 h1:phUcVbl53swtrUN8kQEXFhUxPlIlWyBfKmidCu7P95o= golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392 h1:xYJJ3S178yv++9zXV/hnr29plCAGO9vAFG9dorqaFQc= +golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -404,6 +416,10 @@ golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201201195509-5d6afe98e0b7 h1:3uJsdck53FDIpWwLeAXlia9p4C8j0BO2xZrqzKpL0D8= +golang.org/x/net v0.0.0-20201201195509-5d6afe98e0b7/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb h1:eBmm0M9fYhWpKZLjQUUKka/LtIxf46G4fxeEz5KJr9U= +golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -438,6 +454,12 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201117222635-ba5294a509c7 h1:s330+6z/Ko3J0o6rvOcwXe5nzs7UT9tLKHoOXYn6uE0= golang.org/x/sys v0.0.0-20201117222635-ba5294a509c7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201126233918-771906719818 h1:f1CIuDlJhwANEC2MM87MBEVMr3jl5bifgsfj90XAF9c= +golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3 h1:kzM6+9dur93BcC2kVlYl34cHU+TYZLanmpSJHVMmL64= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201202213521-69691e467435 h1:25AvDqqB9PrNqj1FLf2/70I4W0L19qqoaFq3gjNwbKk= +golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -508,6 +530,10 @@ gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8X gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201128035030-22ab2dfb190c h1:3Ao+zLtE2wq/wqnKi1D1nmaRo1n6E9lEVLlXfdDYsQQ= +gopkg.in/check.v1 v1.0.0-20201128035030-22ab2dfb190c/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= @@ -525,6 +551,8 @@ gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ= diff --git a/v1/main.go b/main.go similarity index 100% rename from v1/main.go rename to main.go diff --git a/v1/routers/router.go b/routers/router.go similarity index 100% rename from v1/routers/router.go rename to routers/router.go diff --git a/service/dao/dao.go b/service/dao/dao.go new file mode 100644 index 0000000..d01217b --- /dev/null +++ b/service/dao/dao.go @@ -0,0 +1,327 @@ +package dao + +import ( + "errors" + "log" + pool "nebula-http-gateway/service/pool" + common "nebula-http-gateway/utils" + + nebula "github.com/vesoft-inc/nebula-clients/go" + nebulaType "github.com/vesoft-inc/nebula-clients/go/nebula" +) + +type ExecuteResult struct { + Headers []string `json:"headers"` + Tables []map[string]common.Any `json:"tables"` + TimeCost int32 `json:"timeCost"` +} + +func getValue(valWarp *nebula.ValueWrapper) (common.Any, error) { + var valType = valWarp.GetType() + if valType == "vertex" { + return valWarp.String(), nil + } else if valType == "edge" { + return valWarp.String(), nil + } else if valType == "path" { + return valWarp.String(), nil + } else if valType == "list" { + return valWarp.String(), nil + } else if valType == "map" { + return valWarp.String(), nil + } else if valType == "set" { + return valWarp.String(), nil + } else { + return getBasicValue(valWarp) + } +} + +func getBasicValue(valWarp *nebula.ValueWrapper) (common.Any, error) { + var valType = valWarp.GetType() + if valType == "null" { + value, err := valWarp.AsNull() + switch value { + case nebulaType.NullType___NULL__: + return "NULL", err + case nebulaType.NullType_NaN: + return "NaN", err + case nebulaType.NullType_BAD_DATA: + return "BAD_DATA", err + case nebulaType.NullType_BAD_TYPE: + return "BAD_TYPE", err + } + return "NULL", err + } else if valType == "bool" { + return valWarp.AsBool() + } else if valType == "int" { + return valWarp.AsInt() + } else if valType == "float" { + return valWarp.AsFloat() + } else if valType == "string" { + return valWarp.AsString() + } else if valType == "date" { + return valWarp.AsDate() + } else if valType == "time" { + return valWarp.AsTime() + } else if valType == "datetime" { + return valWarp.AsDateTime() + } + return "", nil +} + +func getVertexInfo(valWarp *nebula.ValueWrapper, data map[string]common.Any) (map[string]common.Any, error) { + node, err := valWarp.AsNode() + if err != nil { + return nil, err + } + id := node.GetID() + data["vid"] = id + tags := node.GetTags() + data["tags"] = tags + properties := make(map[string]map[string]common.Any) + for _, tagName := range tags { + props, err := node.Properties(tagName) + if err != nil { + return nil, err + } + _props := make(map[string]common.Any) + for k, v := range props { + value, err := getValue(v) + if err != nil { + return nil, err + } + _props[k] = value + } + properties[tagName] = _props + } + data["properties"] = properties + return data, nil +} + +func getEdgeInfo(valWarp *nebula.ValueWrapper, data map[string]common.Any) (map[string]common.Any, error) { + relationship, err := valWarp.AsRelationship() + if err != nil { + return nil, err + } + srcID := relationship.GetSrcVertexID() + data["srcID"] = srcID + dstID := relationship.GetDstVertexID() + data["dstID"] = dstID + edgeName := relationship.GetEdgeName() + data["edgeName"] = edgeName + rank := relationship.GetRanking() + data["rank"] = rank + properties := make(map[string]common.Any) + props := relationship.Properties() + for k, v := range props { + value, err := getValue(v) + if err != nil { + return nil, err + } + properties[k] = value + } + data["properties"] = properties + return data, nil +} + +func getPathInfo(valWarp *nebula.ValueWrapper, data map[string]common.Any) (map[string]common.Any, error) { + path, err := valWarp.AsPath() + if err != nil { + return nil, err + } + relationships := path.GetRelationships() + var _relationships []common.Any + for _, relation := range relationships { + _relation := make(map[string]common.Any) + srcID := relation.GetSrcVertexID() + _relation["srcID"] = srcID + dstID := relation.GetDstVertexID() + _relation["dstID"] = dstID + edgeName := relation.GetEdgeName() + _relation["edgeName"] = edgeName + rank := relation.GetRanking() + _relation["rank"] = rank + _relationships = append(_relationships, _relation) + } + data["relationships"] = _relationships + return data, nil +} + +func getListInfo(valWarp *nebula.ValueWrapper, data []common.Any, listType string) ([]common.Any, error) { + var valueList []nebula.ValueWrapper + var err error + if listType == "list" { + valueList, err = valWarp.AsList() + } else if listType == "set" { + valueList, err = valWarp.AsDedupList() + } + if err != nil { + return nil, err + } + for _, v := range valueList { + var props = make(map[string]common.Any) + vType := v.GetType() + props["type"] = vType + if vType == "vertex" { + props, err = getVertexInfo(&v, props) + } else if vType == "edge" { + props, err = getEdgeInfo(&v, props) + } else if vType == "list" { + var items = make([]common.Any, 0) + items, err = getListInfo(&v, items, "list") + props["items"] = items + } else if vType == "map" { + var items = make(map[string]common.Any) + items, err = getMapInfo(&v, items) + props["items"] = items + } else if vType == "set" { + var items = make([]common.Any, 0) + items, err = getListInfo(&v, items, "set") + props["items"] = items + } else { + basicVal, err := getBasicValue(&v) + if err != nil { + return data, err + } + props["value"] = basicVal + } + data = append(data, props) + } + return data, nil +} + +func getMapInfo(valWarp *nebula.ValueWrapper, data map[string]common.Any) (map[string]common.Any, error) { + valueMap, err := valWarp.AsMap() + if err != nil { + return nil, err + } + for k, v := range valueMap { + vType := v.GetType() + if vType == "vertex" { + var _props map[string]common.Any + _props, err = getVertexInfo(&v, _props) + data[k] = _props + } else if vType == "edge" { + var _props map[string]common.Any + _props, err = getEdgeInfo(&v, _props) + data[k] = _props + } else if vType == "list" { + var items = make([]common.Any, 0) + items, err = getListInfo(&v, items, "list") + data[k] = items + } else if vType == "map" { + var items = make(map[string]common.Any) + items, err = getMapInfo(&v, items) + data[k] = items + } else if vType == "set" { + var items = make([]common.Any, 0) + items, err = getListInfo(&v, items, "set") + data[k] = items + } else { + basicVal, err := getBasicValue(&v) + if err != nil { + return data, err + } + data[k] = basicVal + } + } + return data, nil +} + +// Connect return if the nebula connect succeed +func Connect(address string, port int, username string, password string) (nsid string, err error) { + nsid, err = pool.NewConnection(address, port, username, password) + if err != nil { + return "", err + } + return nsid, err +} + +func Disconnect(nsid string) { + pool.Disconnect(nsid) + return +} + +func Execute(nsid string, gql string) (result ExecuteResult, err error) { + result = ExecuteResult{ + Headers: make([]string, 0), + Tables: make([]map[string]common.Any, 0), + } + connection, err := pool.GetConnection(nsid) + if err != nil { + return result, err + } + + responseChannel := make(chan pool.ChannelResponse) + connection.RequestChannel <- pool.ChannelRequest{ + Gql: gql, + ResponseChannel: responseChannel, + } + response := <-responseChannel + if response.Error != nil { + return result, response.Error + } + resp := response.Result + if !resp.IsSucceed() { + log.Printf("ErrorCode: %v, ErrorMsg: %s", resp.GetErrorCode(), resp.GetErrorMsg()) + return result, errors.New(string(resp.GetErrorMsg())) + } + if !resp.IsEmpty() { + rowSize, rowErr := resp.GetRowSize() + colSize, colErr := resp.GetColSize() + if rowErr != nil { + return result, err + } + if colErr != nil { + return result, err + } + colNames := resp.GetColNames() + result.Headers = colNames + for i := 0; i < rowSize; i++ { + var rowValue = make(map[string]common.Any) + record, err := resp.GetRowValuesByIndex(i) + if err != nil { + return result, err + } + for j := 0; j < colSize; j++ { + rowData, err := record.GetValueByIndex(j) + if err != nil { + return result, err + } + value, err := getValue(rowData) + if err != nil { + return result, err + } + rowValue[result.Headers[j]] = value + valueType := rowData.GetType() + if valueType == "vertex" { + rowValue, err = getVertexInfo(rowData, rowValue) + rowValue["type"] = "vertex" + } else if valueType == "edge" { + rowValue, err = getEdgeInfo(rowData, rowValue) + rowValue["type"] = "edge" + } else if valueType == "path" { + rowValue, err = getPathInfo(rowData, rowValue) + rowValue["type"] = "path" + } else if valueType == "list" { + var info = make([]common.Any, 0) + info, err = getListInfo(rowData, info, "list") + rowValue[result.Headers[j]+"_info"] = info + } else if valueType == "set" { + var info = make([]common.Any, 0) + info, err = getListInfo(rowData, info, "set") + rowValue[result.Headers[j]+"_info"] = info + } else if valueType == "map" { + var info = make(map[string]common.Any) + info, err = getMapInfo(rowData, info) + rowValue[result.Headers[j]+"_info"] = info + } + if err != nil { + return result, err + } + } + result.Tables = append(result.Tables, rowValue) + } + } + result.TimeCost = resp.GetLatency() + return result, nil +} diff --git a/v1/service/pool/pool.go b/service/pool/pool.go similarity index 97% rename from v1/service/pool/pool.go rename to service/pool/pool.go index 3ea1d88..8f6bee1 100644 --- a/v1/service/pool/pool.go +++ b/service/pool/pool.go @@ -7,7 +7,6 @@ import ( uuid "github.com/satori/go.uuid" nebula "github.com/vesoft-inc/nebula-clients/go" - graph "github.com/vesoft-inc/nebula-clients/go/nebula/graph" ) type Account struct { @@ -16,7 +15,7 @@ type Account struct { } type ChannelResponse struct { - Result *graph.ExecutionResponse + Result *nebula.ResultSet Error error } diff --git a/v1/tests/controller/db_test.go b/tests/controller/db_test.go similarity index 87% rename from v1/tests/controller/db_test.go rename to tests/controller/db_test.go index 236026e..8cf060e 100644 --- a/v1/tests/controller/db_test.go +++ b/tests/controller/db_test.go @@ -1,17 +1,17 @@ package tests import ( - "testing" - "net/http" "bytes" - "io/ioutil" "encoding/json" - common "nebula-http-gateway/utils" + "io/ioutil" "log" + common "nebula-http-gateway/utils" + "net/http" + "testing" ) type Response struct { - Code int `json:"code"` + Code int `json:"code"` Data common.Any `json:"data"` Message string `json:"message"` } @@ -23,14 +23,14 @@ func Test_DB_Connect(t *testing.T) { requestMethod string requestBody []byte }{ - { + { "http://127.0.0.1:8080/api/db/connect", "POST", []byte(`{"username": "user", "password": "password", "host": "127.0.0.1:3699"}`), }, - { + { "http://127.0.0.1:8080/api/db/connect", "POST", []byte(`{"username": "user1", @@ -45,32 +45,31 @@ func Test_DB_Connect(t *testing.T) { client := &http.Client{} resp, err := client.Do(req) - - if err != nil { - t.Fail() - } + + if err != nil { + t.Fail() + } defer req.Body.Close() body, _ := ioutil.ReadAll(resp.Body) - + json.Unmarshal([]byte(body), &Response) - + if Response.Code != -1 && Response.Code != 0 { t.Fail() } } } - func Test_DB_Execute(t *testing.T) { /* - */ + */ cases := []struct { path string requestMethod string requestBody []byte }{ - { + { "http://127.0.0.1:8080/api/db/exec", "POST", []byte(`{"username" : "user", @@ -81,18 +80,18 @@ func Test_DB_Execute(t *testing.T) { } for _, tc := range cases { var Response Response - req, err := http.NewRequest(tc.requestMethod,tc.path, bytes.NewBuffer(tc.requestBody)) + req, err := http.NewRequest(tc.requestMethod, tc.path, bytes.NewBuffer(tc.requestBody)) req.Header.Set("Content-Type", "application/json") - + client := &http.Client{} resp, err := client.Do(req) - if err != nil { - log.Fatal(err) + if err != nil { + log.Fatal(err) } - + defer resp.Body.Close() - + body, _ := ioutil.ReadAll(resp.Body) json.Unmarshal([]byte(body), &Response) diff --git a/v1/utils/common.go b/utils/common.go similarity index 100% rename from v1/utils/common.go rename to utils/common.go diff --git a/v1/README.md b/v1/README.md deleted file mode 100644 index f5d7919..0000000 --- a/v1/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# nebula-http-gateway -this is a back end client service for nebula data server - -## Run -```bash -// dev -// run nebula server docker -$ cd scripts/ -$ docker-compose up -d - - -// run api service -$ go get github.com/pilu/fresh -$ fresh main.go -``` - -## Required -- Go 11+ -- [beego](https://beego.me/) -- docker \ No newline at end of file diff --git a/v1/service/dao/dao.go b/v1/service/dao/dao.go deleted file mode 100644 index e7a10c8..0000000 --- a/v1/service/dao/dao.go +++ /dev/null @@ -1,215 +0,0 @@ -package dao - -import ( - "bytes" - "errors" - "fmt" - "log" - pool "nebula-http-gateway/service/pool" - common "nebula-http-gateway/utils" - "strconv" - "strings" - - nebula "github.com/vesoft-inc/nebula-clients/go" - nebulaType "github.com/vesoft-inc/nebula-clients/go/nebula" -) - -type ExecuteResult struct { - Headers []string `json:"headers"` - Tables []map[string]common.Any `json:"tables"` - TimeCost int32 `json:"timeCost"` -} - -func getValue(value *nebulaType.Value) string { - if value.IsSetNVal() { // null - switch value.GetNVal() { - case nebulaType.NullType___NULL__: - return "NULL" - case nebulaType.NullType_NaN: - return "NaN" - case nebulaType.NullType_BAD_DATA: - return "BAD_DATA" - case nebulaType.NullType_BAD_TYPE: - return "BAD_TYPE" - } - return "NULL" - } else if value.IsSetBVal() { // bool - return strconv.FormatBool(value.GetBVal()) - } else if value.IsSetIVal() { // int64 - return strconv.FormatInt(value.GetIVal(), 10) - } else if value.IsSetFVal() { // float64 - val := strconv.FormatFloat(value.GetFVal(), 'g', -1, 64) - if !strings.Contains(val, ".") { - idx := strings.LastIndex(val, "e") - if idx == -1 { - val += ".0" - } else { - val = val[0:idx] + ".0" + val[idx:] - } - } - return val - } else if value.IsSetSVal() { // string - return string(value.GetSVal()) - } else if value.IsSetDVal() { // yyyy-mm-dd - date := value.GetDVal() - str := fmt.Sprintf("%d-%d-%d", date.GetYear(), date.GetMonth(), date.GetDay()) - return str - } else if value.IsSetTVal() { - time := value.GetTVal() - str := fmt.Sprintf("%d:%d:%d:%d", - time.GetHour(), time.GetMinute(), time.GetSec(), time.GetMicrosec()) - return str - } else if value.IsSetDtVal() { - datetime := value.GetDtVal() - str := fmt.Sprintf("%d-%d-%d %d:%d:%d:%d", - datetime.GetYear(), datetime.GetMonth(), datetime.GetDay(), - datetime.GetHour(), datetime.GetMinute(), datetime.GetSec(), datetime.GetMicrosec()) - return str - } else if value.IsSetVVal() { // Vertex - var buffer bytes.Buffer - vertex := value.GetVVal() - buffer.WriteString(`("`) - buffer.WriteString(string(vertex.GetVid())) - buffer.WriteString(`")`) - var tags []string - for _, tag := range vertex.GetTags() { - var props []string - for k, v := range tag.GetProps() { - props = append(props, fmt.Sprintf("%s: %s", k, getValue(v))) - } - tagName := string(tag.GetName()) - tagString := fmt.Sprintf(" :%s{%s}", tagName, strings.Join(props, ", ")) - tags = append(tags, tagString) - } - buffer.WriteString(strings.Join(tags, ",")) - return buffer.String() - } else if value.IsSetEVal() { // Edge - // (src)-[edge]->(dst)@ranking {props} - edge := value.GetEVal() - var buffer bytes.Buffer - src := string(edge.GetSrc()) - dst := string(edge.GetDst()) - if edge.GetType() < 0 { - src, dst = dst, src - } - var props []string - for k, v := range edge.GetProps() { - props = append(props, fmt.Sprintf("%s: %s", k, getValue(v))) - } - propsString := strings.Join(props, ", ") - buffer.WriteString(fmt.Sprintf(`("%s")-[%s]->("%s")@%d{%s}`, - src, edge.GetName(), dst, edge.GetRanking(), propsString)) - return buffer.String() - } else if value.IsSetPVal() { // Path - // (src)-[TypeName@ranking]->(dst)-[TypeName@ranking]->(dst) ... - var buffer bytes.Buffer - p := value.GetPVal() - srcVid := string(p.GetSrc().GetVid()) - buffer.WriteString(fmt.Sprintf("(%q)", srcVid)) - for _, step := range p.GetSteps() { - dstVid := string(step.GetDst().GetVid()) - buffer.WriteString(fmt.Sprintf("-[%s@%d]->(%q)", step.GetName(), step.GetRanking(), dstVid)) - } - return buffer.String() - } else if value.IsSetLVal() { // List - l := value.GetLVal() - var buffer bytes.Buffer - buffer.WriteString("[") - for _, v := range l.GetValues() { - buffer.WriteString(getValue(v)) - buffer.WriteString(", ") - } - if buffer.Len() > 1 { - buffer.Truncate(buffer.Len() - 2) - } - buffer.WriteString("]") - return buffer.String() - } else if value.IsSetMVal() { // Map - m := value.GetMVal() - var buffer bytes.Buffer - buffer.WriteString("{") - for k, v := range m.GetKvs() { - buffer.WriteString("\"" + k + "\"") - buffer.WriteString(":") - buffer.WriteString(getValue(v)) - buffer.WriteString(", ") - } - if buffer.Len() > 1 { - buffer.Truncate(buffer.Len() - 2) - } - buffer.WriteString("}") - return buffer.String() - } else if value.IsSetUVal() { // Set - s := value.GetUVal() - var buffer bytes.Buffer - buffer.WriteString("{") - for _, v := range s.GetValues() { - buffer.WriteString(getValue(v)) - buffer.WriteString(", ") - } - if buffer.Len() > 1 { - buffer.Truncate(buffer.Len() - 2) - } - buffer.WriteString("}") - return buffer.String() - } - return "" -} - -// Connect return if the nebula connect succeed -func Connect(address string, port int, username string, password string) (nsid string, err error) { - nsid, err = pool.NewConnection(address, port, username, password) - if err != nil { - return "", err - } - return nsid, err -} - -func Disconnect(nsid string) { - pool.Disconnect(nsid) - return -} - -func Execute(nsid string, gql string) (result ExecuteResult, err error) { - result = ExecuteResult{ - Headers: make([]string, 0), - Tables: make([]map[string]common.Any, 0), - } - connection, err := pool.GetConnection(nsid) - if err != nil { - return result, err - } - - responseChannel := make(chan pool.ChannelResponse) - connection.RequestChannel <- pool.ChannelRequest{ - Gql: gql, - ResponseChannel: responseChannel, - } - response := <-responseChannel - if response.Error != nil { - return result, response.Error - } - resp := response.Result - if nebula.IsError(response.Result) { - log.Printf("ErrorCode: %v, ErrorMsg: %s", resp.GetErrorCode(), resp.GetErrorMsg()) - return result, errors.New(string(resp.GetErrorMsg())) - } - if resp.GetData() != nil { - columns := resp.GetData().GetColumnNames() - for i := 0; i < len(columns); i++ { - result.Headers = append(result.Headers, string(columns[i])) - } - - rows := resp.GetData().GetRows() - for _, row := range rows { - var rowValue = make(map[string]common.Any) - for index, column := range row.GetValues() { - rowValue[result.Headers[index]] = getValue(column) - } - result.Tables = append(result.Tables, rowValue) - } - } - result.TimeCost = resp.LatencyInUs - - return result, nil -}