From 19612d7d34895d043fde6a656edbdf8dcc7cc62d Mon Sep 17 00:00:00 2001 From: Eric Solender Date: Tue, 22 Feb 2022 12:18:58 -0500 Subject: [PATCH 01/20] pointed at tls branch of forked driver --- go.mod | 2 ++ go.sum | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/go.mod b/go.mod index 3fab09c..37e4ccc 100644 --- a/go.mod +++ b/go.mod @@ -19,3 +19,5 @@ require ( github.com/urfave/cli/v2 v2.0.0 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect ) + +replace github.com/neo4j/neo4j-go-driver/v4 => github.com/mindstand/neo4j-go-driver/v4 v4.3.4-0.20220222141004-33255dc85550 diff --git a/go.sum b/go.sum index 8931dbe..21e0b12 100644 --- a/go.sum +++ b/go.sum @@ -14,6 +14,7 @@ github.com/dchest/siphash v1.2.1 h1:4cLinnzVJDKxTCl9B01807Yiy+W7ZzVHj/KIroQRvT4= github.com/dchest/siphash v1.2.1/go.mod h1:q+IRvb2gOSrUnYoPqHiyHXS0FOBBOdl6tONBlVnOnt4= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= @@ -44,6 +45,8 @@ 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= github.com/mindstand/go-cypherdsl v0.2.0 h1:/B6A8DhWk2RksdJxruy3+ii3Hvrr5JU+2vL3/oJMLrI= github.com/mindstand/go-cypherdsl v0.2.0/go.mod h1:swzbrSTuq3CRgFglg3aVThG9GBQmHXz6AY81q9mRMto= +github.com/mindstand/neo4j-go-driver/v4 v4.3.4-0.20220222141004-33255dc85550 h1:K5JAVs3c5c2n1+jzLejM1vNd8qD8wgLvIyE4WD5tcu8= +github.com/mindstand/neo4j-go-driver/v4 v4.3.4-0.20220222141004-33255dc85550/go.mod h1:HQcN7yHl5H0hJKaYuF3TBH9m/Ym0C0ua4NHzKUr9uSc= github.com/neo4j/neo4j-go-driver/v4 v4.3.3 h1:QwM0IN1L6q1+N9cNqjv9Pmj4J4qCVauczQZdFsDafv8= github.com/neo4j/neo4j-go-driver/v4 v4.3.3/go.mod h1:G+DuMWSR9Auvbm6tk+fHNIegnfswAsmXgP/ibvwOY2Q= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= @@ -51,9 +54,11 @@ github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.14.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= +github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -104,6 +109,8 @@ golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211124211545-fe61309f8881 h1:TyHqChC80pFkXWraUUf6RuB5IqFdQieMLwwCJokV2pc= +golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= From 3a3938a5719f70c8bee96be71f62c8832842d11a Mon Sep 17 00:00:00 2001 From: Eric Solender Date: Tue, 22 Feb 2022 12:30:45 -0500 Subject: [PATCH 02/20] added tls to gogm config --- config.go | 11 ++++++++--- go.mod | 2 +- go.sum | 2 ++ gogm.go | 27 +++++++++++++++++---------- 4 files changed, 28 insertions(+), 14 deletions(-) diff --git a/config.go b/config.go index 83c6fa6..e741344 100644 --- a/config.go +++ b/config.go @@ -20,6 +20,7 @@ package gogm import ( + "crypto/tls" "errors" "fmt" "time" @@ -53,9 +54,13 @@ type Config struct { Realm string `yaml:"realm" json:"realm" mapstructure:"realm"` - // these security configurations will be ignored if the protocol does not contain +s - UseSystemCertPool bool `yaml:"use_system_cert_pool" mapstructure:"use_system_cert_pool"` - CAFileLocation string `yaml:"ca_file_location" mapstructure:"ca_file_location"` + // deprecated: in favor of tls config + //these security configurations will be ignored if the protocol does not contain +s + UseSystemCertPool bool `yaml:"use_system_cert_pool" mapstructure:"use_system_cert_pool"` + // deprecated: in favor of tls config + CAFileLocation string `yaml:"ca_file_location" mapstructure:"ca_file_location"` + + TLSConfig *tls.Config `yaml:"tls_config" mapstructure:"tls_config"` // Index Strategy defines the index strategy for GoGM IndexStrategy IndexStrategy `yaml:"index_strategy" json:"index_strategy" mapstructure:"index_strategy"` diff --git a/go.mod b/go.mod index 37e4ccc..1fc5fd0 100644 --- a/go.mod +++ b/go.mod @@ -20,4 +20,4 @@ require ( gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect ) -replace github.com/neo4j/neo4j-go-driver/v4 => github.com/mindstand/neo4j-go-driver/v4 v4.3.4-0.20220222141004-33255dc85550 +replace github.com/neo4j/neo4j-go-driver/v4 => github.com/mindstand/neo4j-go-driver/v4 v4.4.0-beta1.0.20220222145400-d3c6fddab3cc diff --git a/go.sum b/go.sum index 21e0b12..17a9020 100644 --- a/go.sum +++ b/go.sum @@ -47,6 +47,8 @@ github.com/mindstand/go-cypherdsl v0.2.0 h1:/B6A8DhWk2RksdJxruy3+ii3Hvrr5JU+2vL3 github.com/mindstand/go-cypherdsl v0.2.0/go.mod h1:swzbrSTuq3CRgFglg3aVThG9GBQmHXz6AY81q9mRMto= github.com/mindstand/neo4j-go-driver/v4 v4.3.4-0.20220222141004-33255dc85550 h1:K5JAVs3c5c2n1+jzLejM1vNd8qD8wgLvIyE4WD5tcu8= github.com/mindstand/neo4j-go-driver/v4 v4.3.4-0.20220222141004-33255dc85550/go.mod h1:HQcN7yHl5H0hJKaYuF3TBH9m/Ym0C0ua4NHzKUr9uSc= +github.com/mindstand/neo4j-go-driver/v4 v4.4.0-beta1.0.20220222145400-d3c6fddab3cc h1:PY2MtEh34XJ/r4rHgxqnsby9lpmijQLWVcC7h0s+pyU= +github.com/mindstand/neo4j-go-driver/v4 v4.4.0-beta1.0.20220222145400-d3c6fddab3cc/go.mod h1:NexOfrm4c317FVjekrhVV8pHBXgtMG5P6GeweJWCyo4= github.com/neo4j/neo4j-go-driver/v4 v4.3.3 h1:QwM0IN1L6q1+N9cNqjv9Pmj4J4qCVauczQZdFsDafv8= github.com/neo4j/neo4j-go-driver/v4 v4.3.3/go.mod h1:G+DuMWSR9Auvbm6tk+fHNIegnfswAsmXgP/ibvwOY2Q= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= diff --git a/gogm.go b/gogm.go index f9273d6..52b1624 100644 --- a/gogm.go +++ b/gogm.go @@ -21,6 +21,7 @@ package gogm import ( "context" + "crypto/tls" "crypto/x509" "errors" "fmt" @@ -166,27 +167,33 @@ func (g *Gogm) parseOgmTypes() error { } func (g *Gogm) initDriver(ctx context.Context) error { - var certPool *x509.CertPool isEncrypted := strings.Contains(g.config.Protocol, "+s") if isEncrypted { - if g.config.UseSystemCertPool { - var err error - certPool, err = x509.SystemCertPool() - if err != nil { - return fmt.Errorf("failed to get system cert pool") - } - } else { - certPool = x509.NewCertPool() + if g.config.TLSConfig == nil { + g.config.TLSConfig = &tls.Config{} } + // handle deprecated config support if g.config.CAFileLocation != "" { bytes, err := ioutil.ReadFile(g.config.CAFileLocation) if err != nil { return fmt.Errorf("failed to open ca file, %w", err) } + var certPool *x509.CertPool + if g.config.UseSystemCertPool { + var err error + certPool, err = x509.SystemCertPool() + if err != nil { + return fmt.Errorf("failed to get system cert pool") + } + } else { + certPool = x509.NewCertPool() + } + certPool.AppendCertsFromPEM(bytes) + g.config.TLSConfig.RootCAs = certPool } } @@ -198,7 +205,7 @@ func (g *Gogm) initDriver(ctx context.Context) error { neoConf.MaxConnectionPoolSize = g.config.PoolSize if isEncrypted { - neoConf.RootCAs = certPool + neoConf.TLSConfig = g.config.TLSConfig } } From 8056a23b40fa694bc90aeed03e674e71225645d3 Mon Sep 17 00:00:00 2001 From: Eric Solender Date: Mon, 14 Mar 2022 14:55:24 -0400 Subject: [PATCH 03/20] logging connection string --- gogm.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gogm.go b/gogm.go index 52b1624..0bf17d2 100644 --- a/gogm.go +++ b/gogm.go @@ -238,7 +238,9 @@ func (g *Gogm) initDriver(ctx context.Context) error { } func (g *Gogm) initDriverRoutine(neoConfig func(neoConf *neo4j.Config), doneChan chan error) { - driver, err := neo4j.NewDriver(g.config.ConnectionString(), neo4j.BasicAuth(g.config.Username, g.config.Password, g.config.Realm), neoConfig) + connStr := g.config.ConnectionString() + g.logger.Debugf("connection string: %s\n", connStr) + driver, err := neo4j.NewDriver(connStr, neo4j.BasicAuth(g.config.Username, g.config.Password, g.config.Realm), neoConfig) if err != nil { doneChan <- fmt.Errorf("failed to create driver, %w", err) return From c6d4739ae45ae60f015697dfeb177abf14f21f96 Mon Sep 17 00:00:00 2001 From: Eric Solender Date: Mon, 14 Mar 2022 15:42:41 -0400 Subject: [PATCH 04/20] updated driver version and ensure rootca is passed correctly --- go.mod | 2 +- go.sum | 2 ++ gogm.go | 3 +++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 1fc5fd0..48dcbda 100644 --- a/go.mod +++ b/go.mod @@ -20,4 +20,4 @@ require ( gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect ) -replace github.com/neo4j/neo4j-go-driver/v4 => github.com/mindstand/neo4j-go-driver/v4 v4.4.0-beta1.0.20220222145400-d3c6fddab3cc +replace github.com/neo4j/neo4j-go-driver/v4 => github.com/mindstand/neo4j-go-driver/v4 v4.4.0-beta1.0.20220314193855-8ea056066b14 diff --git a/go.sum b/go.sum index 17a9020..ecb8c7f 100644 --- a/go.sum +++ b/go.sum @@ -49,6 +49,8 @@ github.com/mindstand/neo4j-go-driver/v4 v4.3.4-0.20220222141004-33255dc85550 h1: github.com/mindstand/neo4j-go-driver/v4 v4.3.4-0.20220222141004-33255dc85550/go.mod h1:HQcN7yHl5H0hJKaYuF3TBH9m/Ym0C0ua4NHzKUr9uSc= github.com/mindstand/neo4j-go-driver/v4 v4.4.0-beta1.0.20220222145400-d3c6fddab3cc h1:PY2MtEh34XJ/r4rHgxqnsby9lpmijQLWVcC7h0s+pyU= github.com/mindstand/neo4j-go-driver/v4 v4.4.0-beta1.0.20220222145400-d3c6fddab3cc/go.mod h1:NexOfrm4c317FVjekrhVV8pHBXgtMG5P6GeweJWCyo4= +github.com/mindstand/neo4j-go-driver/v4 v4.4.0-beta1.0.20220314193855-8ea056066b14 h1:+C3FJ2je/N1/ejuLCg6W2/NM5V5D4T6NC6Pf2bAe8t4= +github.com/mindstand/neo4j-go-driver/v4 v4.4.0-beta1.0.20220314193855-8ea056066b14/go.mod h1:NexOfrm4c317FVjekrhVV8pHBXgtMG5P6GeweJWCyo4= github.com/neo4j/neo4j-go-driver/v4 v4.3.3 h1:QwM0IN1L6q1+N9cNqjv9Pmj4J4qCVauczQZdFsDafv8= github.com/neo4j/neo4j-go-driver/v4 v4.3.3/go.mod h1:G+DuMWSR9Auvbm6tk+fHNIegnfswAsmXgP/ibvwOY2Q= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= diff --git a/gogm.go b/gogm.go index 0bf17d2..181111e 100644 --- a/gogm.go +++ b/gogm.go @@ -206,6 +206,9 @@ func (g *Gogm) initDriver(ctx context.Context) error { if isEncrypted { neoConf.TLSConfig = g.config.TLSConfig + if g.config.TLSConfig.RootCAs != nil { + neoConf.RootCAs = g.config.TLSConfig.RootCAs + } } } From 6476371726836d11886af2d5a007015f62dc06c9 Mon Sep 17 00:00:00 2001 From: Eric Solender Date: Wed, 16 Mar 2022 14:26:41 -0400 Subject: [PATCH 05/20] added more logs --- gogm.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/gogm.go b/gogm.go index 181111e..999f5e3 100644 --- a/gogm.go +++ b/gogm.go @@ -176,23 +176,29 @@ func (g *Gogm) initDriver(ctx context.Context) error { // handle deprecated config support if g.config.CAFileLocation != "" { + g.logger.Debugf("loading ca file at location `%s`", g.config.CAFileLocation) bytes, err := ioutil.ReadFile(g.config.CAFileLocation) if err != nil { return fmt.Errorf("failed to open ca file, %w", err) } + g.logger.Debugf("successfully loaded ca file") var certPool *x509.CertPool if g.config.UseSystemCertPool { + g.logger.Debug("loading system cert pool") var err error certPool, err = x509.SystemCertPool() if err != nil { return fmt.Errorf("failed to get system cert pool") } + g.logger.Debug("successfully loaded system cert pool") } else { certPool = x509.NewCertPool() } - certPool.AppendCertsFromPEM(bytes) + if !certPool.AppendCertsFromPEM(bytes) { + return errors.New("failed to load CA into cert pool") + } g.config.TLSConfig.RootCAs = certPool } } From 5370c9fc119be97bd52cf9fb81aa1828328cdf4b Mon Sep 17 00:00:00 2001 From: Eric Solender Date: Thu, 7 Apr 2022 13:53:48 -0400 Subject: [PATCH 06/20] refactored indexing and added better errors --- gogm.go | 33 +++-- index.go | 44 +++++- index_v4.go | 378 +++++++++++++++++++++++----------------------------- 3 files changed, 222 insertions(+), 233 deletions(-) diff --git a/gogm.go b/gogm.go index 999f5e3..c6c8554 100644 --- a/gogm.go +++ b/gogm.go @@ -98,23 +98,28 @@ func NewContext(ctx context.Context, config *Config, pkStrategy *PrimaryKeyStrat func (g *Gogm) init(ctx context.Context) error { err := g.validate() if err != nil { - return err + return fmt.Errorf("failed to validate config, %w", err) } err = g.parseOgmTypes() if err != nil { - return err + return fmt.Errorf("failed to parse ogm types, %w", err) } g.logger.Debug("establishing neo connection") err = g.initDriver(ctx) if err != nil { - return err + return fmt.Errorf("failed to initialize driver, %w", err) } g.logger.Debug("initializing indices") - return g.initIndex(ctx) + err = g.initIndex(ctx) + if err != nil { + return fmt.Errorf("failed to init indices, %w", err) + } + + return nil } func (g *Gogm) validate() error { @@ -148,7 +153,7 @@ func (g *Gogm) parseOgmTypes() error { name := reflect.TypeOf(t).Elem().Name() dc, err := getStructDecoratorConfig(g, t, g.mappedRelations) if err != nil { - return err + return fmt.Errorf("failed to get structDecoratorConfig for %s, %w", name, err) } g.logger.Debugf("mapped type %s", name) @@ -266,22 +271,22 @@ func (g *Gogm) initDriverRoutine(neoConfig func(neoConf *neo4j.Config), doneChan // get neoversion sess := driver.NewSession(neo4j.SessionConfig{ - AccessMode: neo4j.AccessModeRead, - // DatabaseName: "neo4j", + AccessMode: neo4j.AccessModeRead, + DatabaseName: "neo4j", }) res, err := sess.Run("return 1", nil) if err != nil { - doneChan <- err + doneChan <- fmt.Errorf("failed to run test query, %w", err) return } else if err = res.Err(); err != nil { - doneChan <- err + doneChan <- fmt.Errorf("failed to run test query, %w", err) return } sum, err := res.Consume() if err != nil { - doneChan <- err + doneChan <- fmt.Errorf("failed to consume test query, %w", err) return } @@ -296,19 +301,19 @@ func (g *Gogm) initIndex(ctx context.Context) error { g.logger.Debug("dropping all known indexes") err := dropAllIndexesAndConstraints(ctx, g) if err != nil { - return err + return fmt.Errorf("failed to drop all known indexes, %w", err) } g.logger.Debug("creating all mapped indexes") err = createAllIndexesAndConstraints(ctx, g, g.mappedTypes) if err != nil { - return err + return fmt.Errorf("failed t create all indexes and constraints, %w", err) } g.logger.Debug("verifying all indexes") err = verifyAllIndexesAndConstraints(ctx, g, g.mappedTypes) if err != nil { - return err + return fmt.Errorf("failed to verify all indexes and contraints, %w", err) } return nil case VALIDATE_INDEX: @@ -316,7 +321,7 @@ func (g *Gogm) initIndex(ctx context.Context) error { g.logger.Debug("verifying all indexes") err := verifyAllIndexesAndConstraints(ctx, g, g.mappedTypes) if err != nil { - return err + return fmt.Errorf("failed to verify all indexes and contraints, %w", err) } return nil case IGNORE_INDEX: diff --git a/index.go b/index.go index e917bca..77b4e86 100644 --- a/index.go +++ b/index.go @@ -21,32 +21,62 @@ package gogm import ( "context" + "fmt" "github.com/cornelk/hashmap" ) //drops all known indexes func dropAllIndexesAndConstraints(ctx context.Context, gogm *Gogm) error { if gogm.boltMajorVersion >= 4 { - return dropAllIndexesAndConstraintsV4(ctx, gogm) + for _, db := range gogm.config.TargetDbs { + err := dropAllIndexesAndConstraintsV4(ctx, gogm, db) + if err != nil { + return fmt.Errorf("failed to drop indexes and constraints for db %s on db version 4+, %w", db, err) + } + } + } else { + err := dropAllIndexesAndConstraintsV3(ctx, gogm) + if err != nil { + return fmt.Errorf("failed to drop indexes and constraints on db version 3, %w", err) + } } - return dropAllIndexesAndConstraintsV3(ctx, gogm) + return nil } //creates all indexes func createAllIndexesAndConstraints(ctx context.Context, gogm *Gogm, mappedTypes *hashmap.HashMap) error { if gogm.boltMajorVersion >= 4 { - return createAllIndexesAndConstraintsV4(ctx, gogm, mappedTypes) + for _, db := range gogm.config.TargetDbs { + err := createAllIndexesAndConstraintsV4(ctx, gogm, mappedTypes, db) + if err != nil { + return fmt.Errorf("failed to create indexes and constraints for db %s on db version 4+, %w", db, err) + } + } + } else { + err := createAllIndexesAndConstraintsV3(ctx, gogm, mappedTypes) + if err != nil { + return fmt.Errorf("failed to create indexes and constraints on db version 3, %w", err) + } } - - return createAllIndexesAndConstraintsV3(ctx, gogm, mappedTypes) + return nil } //verifies all indexes func verifyAllIndexesAndConstraints(ctx context.Context, gogm *Gogm, mappedTypes *hashmap.HashMap) error { if gogm.boltMajorVersion >= 4 { - return verifyAllIndexesAndConstraintsV4(ctx, gogm, mappedTypes) + for _, db := range gogm.config.TargetDbs { + err := verifyAllIndexesAndConstraintsV4(ctx, gogm, mappedTypes, db) + if err != nil { + return fmt.Errorf("failed to verify indexes and constraints for db %s on db version 4+, %w", db, err) + } + } + } else { + err := verifyAllIndexesAndConstraintsV3(ctx, gogm, mappedTypes) + if err != nil { + return fmt.Errorf("failed to verify all indexes and contraints on db version 3, %w", err) + } } - return verifyAllIndexesAndConstraintsV3(ctx, gogm, mappedTypes) + return nil } diff --git a/index_v4.go b/index_v4.go index 289249c..d066345 100644 --- a/index_v4.go +++ b/index_v4.go @@ -93,278 +93,232 @@ func resultToStringArrV4(isConstraint bool, result [][]interface{}) ([]string, e } //drops all known indexes -func dropAllIndexesAndConstraintsV4(ctx context.Context, gogm *Gogm) error { - for _, db := range gogm.config.TargetDbs { - sess, err := gogm.NewSessionV2(SessionConfig{ - AccessMode: neo4j.AccessModeWrite, - DatabaseName: db, - }) - if err != nil { - return err - } - - err = sess.ManagedTransaction(ctx, func(tx TransactionV2) error { - res, _, err := tx.QueryRaw(ctx, "CALL db.constraints()", nil) - if err != nil { - return err - } - - if len(res) == 0 { - // no constraints to kill off, return from here - return nil - } - - constraints, err := resultToStringArrV4(true, res) - if err != nil { - return err - } +func dropAllIndexesAndConstraintsV4(ctx context.Context, gogm *Gogm, db string) error { + sess, err := gogm.NewSessionV2(SessionConfig{ + AccessMode: neo4j.AccessModeWrite, + DatabaseName: db, + }) + if err != nil { + return fmt.Errorf("failed to open session to db %s, %w", db, err) + } - //if there is anything, get rid of it - if len(constraints) != 0 { - for _, constraint := range constraints { - gogm.logger.Debugf("dropping constraint '%s'", constraint) - _, _, err := tx.QueryRaw(ctx, fmt.Sprintf("DROP CONSTRAINT %s IF EXISTS", constraint), nil) - if err != nil { - return err - } - } - } + defer sess.Close() - res, _, err = tx.QueryRaw(ctx, "CALL db.indexes()", nil) - if err != nil { - return tx.RollbackWithError(ctx, err) - } + res, _, err := sess.QueryRaw(ctx, "CALL db.constraints()", nil) + if err != nil { + return fmt.Errorf("failed to query current constraints, %w", err) + } - indexes, err := resultToStringArrV4(false, res) - if err != nil { - return err - } + if len(res) == 0 { + // no constraints to kill off, return from here + return nil + } - //if there is anything, get rid of it - if len(indexes) != 0 { - for _, index := range indexes { - if len(index) == 0 { - return errors.New("invalid index config") - } + constraints, err := resultToStringArrV4(true, res) + if err != nil { + return fmt.Errorf("failed to convert constraints to string array, %w", err) + } - _, _, err := tx.QueryRaw(ctx, fmt.Sprintf("DROP INDEX %s IF EXISTS", index), nil) - if err != nil { - return tx.RollbackWithError(ctx, err) - } + err = sess.ManagedTransaction(ctx, func(tx TransactionV2) error { + //if there is anything, get rid of it + if len(constraints) != 0 { + for _, constraint := range constraints { + gogm.logger.Debugf("dropping constraint '%s'", constraint) + _, _, err := tx.QueryRaw(ctx, fmt.Sprintf("DROP CONSTRAINT %s IF EXISTS", constraint), nil) + if err != nil { + return fmt.Errorf("failed to drop contraint `%s`, %w", constraint, err) } } - return nil - }) - if err != nil { - _err := sess.Close() - if err != nil { - err = fmt.Errorf("%s: %w", err, _err) - } - return fmt.Errorf("drop index transaction failed, %w", err) } - err = sess.Close() + res, _, err = tx.QueryRaw(ctx, "CALL db.indexes()", nil) if err != nil { - return err + return fmt.Errorf("failed to call db.indexes(), %w", err) } - } - return nil -} -//creates all indexes -func createAllIndexesAndConstraintsV4(ctx context.Context, gogm *Gogm, mappedTypes *hashmap.HashMap) error { - for _, db := range gogm.config.TargetDbs { - sess, err := gogm.NewSessionV2(SessionConfig{ - AccessMode: neo4j.AccessModeWrite, - DatabaseName: db, - }) + indexes, err := resultToStringArrV4(false, res) if err != nil { - return err - } - - //validate that we have to do anything - if mappedTypes == nil || mappedTypes.Len() == 0 { - return errors.New("must have types to map") + return fmt.Errorf("failed to convert result to string array, %w", err) } - numIndexCreated := 0 - //index and/or create unique constraints wherever necessary - //for node, structConfig := range mappedTypes{ - err = sess.ManagedTransaction(ctx, func(tx TransactionV2) error { - for nodes := range mappedTypes.Iter() { - node := nodes.Key.(string) - structConfig := nodes.Value.(structDecoratorConfig) - if structConfig.Fields == nil || len(structConfig.Fields) == 0 { - continue + //if there is anything, get rid of it + if len(indexes) != 0 { + for _, index := range indexes { + if len(index) == 0 { + return errors.New("invalid index config") } - var indexFields []string - - for _, config := range structConfig.Fields { - //pk is a special unique key - if config.PrimaryKey != "" || config.Unique { - numIndexCreated++ - _, _, err = tx.QueryRaw(ctx, buildConstraintQuery(true, node, structConfig.Label, config.Name), nil) - if err != nil { - return err - } - } else if config.Index { - indexFields = append(indexFields, config.Name) - } - } - - //create composite index - if len(indexFields) > 0 { - numIndexCreated++ - _, _, err = tx.QueryRaw(ctx, buildIndexQuery(structConfig.Label, indexFields...), nil) - if err != nil { - return err - } + _, _, err := tx.QueryRaw(ctx, fmt.Sprintf("DROP INDEX %s IF EXISTS", index), nil) + if err != nil { + return fmt.Errorf("failed to drop index %s, %w", index, err) } } - - gogm.logger.Debugf("created (%v) indexes", numIndexCreated) - return nil - }) - if err != nil { - _err := sess.Close() - if err != nil { - err = fmt.Errorf("%s: %w", err, _err) - } - return err - } - err = sess.Close() - if err != nil { - return err } + return nil + }) + if err != nil { + return fmt.Errorf("drop index and constraint transaction failed, %w", err) } + return nil } -//verifies all indexes -func verifyAllIndexesAndConstraintsV4(ctx context.Context, gogm *Gogm, mappedTypes *hashmap.HashMap) error { - for _, db := range gogm.config.TargetDbs { - sess, err := gogm.NewSessionV2(SessionConfig{ - AccessMode: neo4j.AccessModeWrite, - DatabaseName: db, - }) - if err != nil { - return err - } +//creates all indexes +func createAllIndexesAndConstraintsV4(ctx context.Context, gogm *Gogm, mappedTypes *hashmap.HashMap, db string) error { + sess, err := gogm.NewSessionV2(SessionConfig{ + AccessMode: neo4j.AccessModeWrite, + DatabaseName: db, + }) + if err != nil { + return fmt.Errorf("failed to open session to %s, %w", db, err) + } - //validate that we have to do anything - if mappedTypes == nil || mappedTypes.Len() == 0 { - return errors.New("must have types to map") - } + defer sess.Close() - var constraints []string - var indexes []string + //validate that we have to do anything + if mappedTypes == nil || mappedTypes.Len() == 0 { + return errors.New("must have types to map") + } - //build constraint strings + numIndexCreated := 0 + //index and/or create unique constraints wherever necessary + //for node, structConfig := range mappedTypes{ + err = sess.ManagedTransaction(ctx, func(tx TransactionV2) error { for nodes := range mappedTypes.Iter() { node := nodes.Key.(string) structConfig := nodes.Value.(structDecoratorConfig) - if structConfig.Fields == nil || len(structConfig.Fields) == 0 { continue } - fields := []string{} + var indexFields []string for _, config := range structConfig.Fields { - + //pk is a special unique key if config.PrimaryKey != "" || config.Unique { - t := fmt.Sprintf("CONSTRAINT ON (%s:%s) ASSERT %s.%s IS UNIQUE", node, structConfig.Label, node, config.Name) - constraints = append(constraints, t) - - indexes = append(indexes, fmt.Sprintf("INDEX ON :%s(%s)", structConfig.Label, config.Name)) - + numIndexCreated++ + _, _, err = tx.QueryRaw(ctx, buildConstraintQuery(true, node, structConfig.Label, config.Name), nil) + if err != nil { + return fmt.Errorf("failed to add constraint, %w", err) + } } else if config.Index { - fields = append(fields, config.Name) + indexFields = append(indexFields, config.Name) } } - f := "(" - for _, field := range fields { - f += field + //create composite index + if len(indexFields) > 0 { + numIndexCreated++ + _, _, err = tx.QueryRaw(ctx, buildIndexQuery(structConfig.Label, indexFields...), nil) + if err != nil { + return fmt.Errorf("failed to add index, %w", err) + } } + } - f += ")" + gogm.logger.Debugf("created (%v) indexes", numIndexCreated) + return nil + }) + if err != nil { + return fmt.Errorf("tx to add indexes and contraints failed, %w", err) + } - indexes = append(indexes, fmt.Sprintf("INDEX ON :%s%s", structConfig.Label, f)) + return nil +} - } +//verifies all indexes +func verifyAllIndexesAndConstraintsV4(ctx context.Context, gogm *Gogm, mappedTypes *hashmap.HashMap, db string) error { + sess, err := gogm.NewSessionV2(SessionConfig{ + AccessMode: neo4j.AccessModeWrite, + DatabaseName: db, + }) + if err != nil { + return fmt.Errorf("failed to open session %s, %w", db, err) + } - //get whats there now - foundResult, _, err := sess.QueryRaw(ctx, "CALL db.constraints", nil) - if err != nil { - _err := sess.Close() - if err != nil { - err = fmt.Errorf("%s: %w", err, _err) - } - return fmt.Errorf("no constraints found, %w", err) - } + defer sess.Close() - foundConstraints, err := resultToStringArrV4(true, foundResult) - if err != nil { - _err := sess.Close() - if err != nil { - err = fmt.Errorf("%s: %w", err, _err) - } - return fmt.Errorf("failed to convert result to string array, %w", err) - } + //validate that we have to do anything + if mappedTypes == nil || mappedTypes.Len() == 0 { + return errors.New("must have types to map") + } - foundInxdexResult, _, err := sess.QueryRaw(ctx, "CALL db.indexes()", nil) - if err != nil { - _err := sess.Close() - if err != nil { - err = fmt.Errorf("%s: %w", err, _err) - } - return fmt.Errorf("no indices found, %w", err) - } + var constraints []string + var indexes []string - foundIndexes, err := resultToStringArrV4(false, foundInxdexResult) - if err != nil { - _err := sess.Close() - if err != nil { - err = fmt.Errorf("%s: %w", err, _err) - } - return fmt.Errorf("failed to convert result to array, %w", err) - } + //build constraint strings + for nodes := range mappedTypes.Iter() { + node := nodes.Key.(string) + structConfig := nodes.Value.(structDecoratorConfig) - //verify from there - delta, found := arrayOperations.Difference(foundIndexes, indexes) - if !found { - err = fmt.Errorf("found differences in remote vs ogm for found indexes, %v", delta) - _err := sess.Close() - if _err != nil { - err = fmt.Errorf("%s: %w", err, _err) - } - return err + if structConfig.Fields == nil || len(structConfig.Fields) == 0 { + continue } - gogm.logger.Debugf("%+v", delta) + fields := []string{} + + for _, config := range structConfig.Fields { - var founds []string + if config.PrimaryKey != "" || config.Unique { + t := fmt.Sprintf("CONSTRAINT ON (%s:%s) ASSERT %s.%s IS UNIQUE", node, structConfig.Label, node, config.Name) + constraints = append(constraints, t) - founds = append(founds, foundConstraints...) + indexes = append(indexes, fmt.Sprintf("INDEX ON :%s(%s)", structConfig.Label, config.Name)) - delta, found = arrayOperations.Difference(founds, constraints) - if !found { - err = fmt.Errorf("found differences in remote vs ogm for found constraints, %v", delta) - _err := sess.Close() - if _err != nil { - err = fmt.Errorf("%s: %w", err, _err) + } else if config.Index { + fields = append(fields, config.Name) } - return err } - gogm.logger.Debugf("%+v", delta) - err = sess.Close() - if err != nil { - return err + f := "(" + for _, field := range fields { + f += field } + + f += ")" + + indexes = append(indexes, fmt.Sprintf("INDEX ON :%s%s", structConfig.Label, f)) + + } + + //get what's there now + foundResult, _, err := sess.QueryRaw(ctx, "CALL db.constraints", nil) + if err != nil { + return fmt.Errorf("no constraints found, %w", err) + } + + foundConstraints, err := resultToStringArrV4(true, foundResult) + if err != nil { + return fmt.Errorf("failed to convert result to string array, %w", err) + } + + foundInxdexResult, _, err := sess.QueryRaw(ctx, "CALL db.indexes()", nil) + if err != nil { + return fmt.Errorf("no indices found, %w", err) + } + + foundIndexes, err := resultToStringArrV4(false, foundInxdexResult) + if err != nil { + return fmt.Errorf("failed to convert result to array, %w", err) + } + + //verify from there + delta, found := arrayOperations.Difference(foundIndexes, indexes) + if !found { + return fmt.Errorf("found differences in remote vs ogm for found indexes, %v", delta) + } + + gogm.logger.Debugf("%+v", delta) + + var founds []string + + founds = append(founds, foundConstraints...) + + delta, found = arrayOperations.Difference(founds, constraints) + if !found { + return fmt.Errorf("found differences in remote vs ogm for found constraints, %v", delta) } + gogm.logger.Debugf("%+v", delta) return nil } From 3b7685d05a6905221561b078b623eab8bf5e1400 Mon Sep 17 00:00:00 2001 From: Eric Solender Date: Thu, 7 Apr 2022 14:03:07 -0400 Subject: [PATCH 07/20] fix tls --- go.mod | 4 +--- go.sum | 2 ++ gogm.go | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 48dcbda..a1345e8 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/gorilla/mux v1.8.0 github.com/kr/pretty v0.1.0 // indirect github.com/mindstand/go-cypherdsl v0.2.0 - github.com/neo4j/neo4j-go-driver/v4 v4.3.3 + github.com/neo4j/neo4j-go-driver/v4 v4.4.2-0.20220317151800-1a19fb114732 github.com/opentracing/opentracing-go v1.2.0 github.com/sirupsen/logrus v1.6.0 // indirect github.com/stretchr/objx v0.2.0 // indirect @@ -19,5 +19,3 @@ require ( github.com/urfave/cli/v2 v2.0.0 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect ) - -replace github.com/neo4j/neo4j-go-driver/v4 => github.com/mindstand/neo4j-go-driver/v4 v4.4.0-beta1.0.20220314193855-8ea056066b14 diff --git a/go.sum b/go.sum index ecb8c7f..f2986fb 100644 --- a/go.sum +++ b/go.sum @@ -53,6 +53,8 @@ github.com/mindstand/neo4j-go-driver/v4 v4.4.0-beta1.0.20220314193855-8ea056066b github.com/mindstand/neo4j-go-driver/v4 v4.4.0-beta1.0.20220314193855-8ea056066b14/go.mod h1:NexOfrm4c317FVjekrhVV8pHBXgtMG5P6GeweJWCyo4= github.com/neo4j/neo4j-go-driver/v4 v4.3.3 h1:QwM0IN1L6q1+N9cNqjv9Pmj4J4qCVauczQZdFsDafv8= github.com/neo4j/neo4j-go-driver/v4 v4.3.3/go.mod h1:G+DuMWSR9Auvbm6tk+fHNIegnfswAsmXgP/ibvwOY2Q= +github.com/neo4j/neo4j-go-driver/v4 v4.4.2-0.20220317151800-1a19fb114732 h1:nHwy/xxNFLe9MrQy0ub1JCyrh2p/bAW79uFDX3exjHQ= +github.com/neo4j/neo4j-go-driver/v4 v4.4.2-0.20220317151800-1a19fb114732/go.mod h1:NexOfrm4c317FVjekrhVV8pHBXgtMG5P6GeweJWCyo4= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= diff --git a/gogm.go b/gogm.go index c6c8554..24c1cba 100644 --- a/gogm.go +++ b/gogm.go @@ -216,7 +216,6 @@ func (g *Gogm) initDriver(ctx context.Context) error { neoConf.MaxConnectionPoolSize = g.config.PoolSize if isEncrypted { - neoConf.TLSConfig = g.config.TLSConfig if g.config.TLSConfig.RootCAs != nil { neoConf.RootCAs = g.config.TLSConfig.RootCAs } From a38dd68bdf57482bfb09d56824f385cd06762648 Mon Sep 17 00:00:00 2001 From: Eric Solender Date: Mon, 9 May 2022 14:21:15 -0400 Subject: [PATCH 08/20] added test to try to reproduce bug --- go.mod | 2 +- integration_test.go | 397 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 380 insertions(+), 19 deletions(-) diff --git a/go.mod b/go.mod index a1345e8..09269be 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/mindstand/gogm/v2 -go 1.13 +go 1.16 require ( github.com/adam-hanna/arrayOperations v0.2.6 diff --git a/integration_test.go b/integration_test.go index aa0d7d5..f89e9dd 100644 --- a/integration_test.go +++ b/integration_test.go @@ -68,19 +68,19 @@ func (integrationTest *IntegrationTestSuite) TearDownSuite() { func (integrationTest *IntegrationTestSuite) SetupSuite() { conf := Config{ - Username: "neo4j", - Password: "changeme", - Host: "0.0.0.0", - IsCluster: false, - Port: 7687, - PoolSize: 15, + Username: "neo4j", + Password: "password", + Host: "0.0.0.0", + Protocol: "bolt", + Port: 7687, + PoolSize: 15, // this is ignore because index management is part of the test IndexStrategy: IGNORE_INDEX, - EnableDriverLogs: true, + EnableDriverLogs: false, DefaultTransactionTimeout: 2 * time.Minute, } - gogm, err := New(&conf, UUIDPrimaryKeyStrategy, &a{}, &b{}, &c{}, &propTest{}, &narcissisticTestNode{}) + gogm, err := New(&conf, UUIDPrimaryKeyStrategy, &a{}, &b{}, &c{}, &propTest{}, &narcissisticTestNode{}, &Sides{}, &Middle{}) integrationTest.Require().Nil(err) integrationTest.Require().NotNil(gogm) integrationTest.gogm = gogm @@ -315,6 +315,367 @@ func (integrationTest *IntegrationTestSuite) TestIntegration() { integrationTest.Require().Nil(sess.Close()) } +type Sides struct { + BaseUUIDNode + Name string `gogm:"name=name"` + + MatchIncoming []*Middle `gogm:"direction=outgoing;relationship=incoming_test"` + MatchOutgoing []*Middle `gogm:"direction=incoming;relationship=outgoing_test"` +} + +type Middle struct { + BaseUUIDNode + + IncomingSides []*Sides `gogm:"direction=incoming;relationship=incoming_test"` + OutgoingSides []*Sides `gogm:"direction=outgoing;relationship=outgoing_test"` +} + +func (integrationTest *IntegrationTestSuite) TestMultiSaveEdgeCase() { + /* + (left)--(middle)--(right) + SaveDepth(left, 1) + SaveDepth(right,1) + + Problem is only (middle)--(right) is saved, not (left)--(middle) + */ + numMiddles := 15 + + for _, testCase := range []struct { + TestFunction func(t *testing.T) + Name string + }{ + { + Name: "incoming single non transaction test", + TestFunction: func(t *testing.T) { + req := require.New(t) + left, right := &Sides{Name: "left"}, &Sides{Name: "right"} + middle := &Middle{} + middle.IncomingSides = []*Sides{left, right} + left.MatchIncoming = []*Middle{middle} + right.MatchIncoming = []*Middle{middle} + + sess, err := integrationTest.gogm.NewSessionV2(SessionConfig{ + AccessMode: neo4j.AccessModeWrite, + }) + req.Nil(err) + req.NotNil(sess) + + req.Nil(sess.SaveDepth(context.Background(), left, 1)) + req.Nil(sess.SaveDepth(context.Background(), right, 1)) + req.Nil(sess.Close()) + + var matchMiddle Middle + sess, err = integrationTest.gogm.NewSessionV2(SessionConfig{ + AccessMode: neo4j.AccessModeRead, + }) + req.Nil(err) + req.NotNil(sess) + defer sess.Close() + req.Nil(sess.LoadDepth(context.Background(), &matchMiddle, middle.UUID, 1)) + + req.Equal(len(matchMiddle.IncomingSides), 2, "Expected size of middle") + }, + }, + { + Name: "incoming single transaction test", + TestFunction: func(t *testing.T) { + req := require.New(t) + left, right := &Sides{Name: "left"}, &Sides{Name: "right"} + middle := &Middle{} + middle.IncomingSides = []*Sides{left, right} + left.MatchIncoming = []*Middle{middle} + right.MatchIncoming = []*Middle{middle} + + sess, err := integrationTest.gogm.NewSessionV2(SessionConfig{ + AccessMode: neo4j.AccessModeWrite, + }) + req.Nil(err) + req.NotNil(sess) + + ctx := context.Background() + req.Nil(sess.ManagedTransaction(ctx, func(tx TransactionV2) error { + err = tx.SaveDepth(context.Background(), left, 1) + if err != nil { + return err + } + err = tx.SaveDepth(context.Background(), right, 1) + if err != nil { + return err + } + + return nil + })) + req.Nil(sess.Close()) + + var matchMiddle Middle + sess, err = integrationTest.gogm.NewSessionV2(SessionConfig{ + AccessMode: neo4j.AccessModeRead, + }) + req.Nil(err) + req.NotNil(sess) + defer sess.Close() + req.Nil(sess.LoadDepth(context.Background(), &matchMiddle, middle.UUID, 1)) + + req.Equal(len(matchMiddle.IncomingSides), 2, "Expected size of middle") + }, + }, + + { + Name: "incoming multi non transaction test", + TestFunction: func(t *testing.T) { + req := require.New(t) + left, right := &Sides{Name: "left"}, &Sides{Name: "right"} + + middles := make([]*Middle, numMiddles) + for i := 0; i < numMiddles; i++ { + middles[i] = &Middle{} + middles[i].IncomingSides = []*Sides{left, right} + } + + left.MatchIncoming = middles + right.MatchIncoming = middles + + sess, err := integrationTest.gogm.NewSessionV2(SessionConfig{ + AccessMode: neo4j.AccessModeWrite, + }) + req.Nil(err) + req.NotNil(sess) + + req.Nil(sess.SaveDepth(context.Background(), left, 1)) + req.Nil(sess.SaveDepth(context.Background(), right, 1)) + req.Nil(sess.Close()) + + sess, err = integrationTest.gogm.NewSessionV2(SessionConfig{ + AccessMode: neo4j.AccessModeRead, + }) + req.Nil(err) + req.NotNil(sess) + defer sess.Close() + var checkLeft, checkRight Sides + + req.Nil(sess.LoadDepth(context.Background(), &checkLeft, left.UUID, 1)) + req.Equal(len(checkLeft.MatchIncoming), numMiddles) + + req.Nil(sess.LoadDepth(context.Background(), &checkRight, right.UUID, 1)) + req.Equal(len(checkRight.MatchIncoming), numMiddles) + }, + }, + { + Name: "incoming multi transaction test", + TestFunction: func(t *testing.T) { + req := require.New(t) + left, right := &Sides{Name: "left"}, &Sides{Name: "right"} + + middles := make([]*Middle, numMiddles) + for i := 0; i < numMiddles; i++ { + middles[i] = &Middle{} + middles[i].IncomingSides = []*Sides{left, right} + } + + left.MatchIncoming = middles + right.MatchIncoming = middles + + sess, err := integrationTest.gogm.NewSessionV2(SessionConfig{ + AccessMode: neo4j.AccessModeWrite, + }) + req.Nil(err) + req.NotNil(sess) + + ctx := context.Background() + req.Nil(sess.ManagedTransaction(ctx, func(tx TransactionV2) error { + err = tx.SaveDepth(context.Background(), left, 1) + if err != nil { + return err + } + + return tx.SaveDepth(context.Background(), right, 1) + })) + req.Nil(sess.Close()) + + sess, err = integrationTest.gogm.NewSessionV2(SessionConfig{ + AccessMode: neo4j.AccessModeRead, + }) + req.Nil(err) + req.NotNil(sess) + defer sess.Close() + var checkLeft, checkRight Sides + + req.Nil(sess.LoadDepth(context.Background(), &checkLeft, left.UUID, 1)) + req.Equal(len(checkLeft.MatchIncoming), numMiddles) + + req.Nil(sess.LoadDepth(context.Background(), &checkRight, right.UUID, 1)) + req.Equal(len(checkRight.MatchIncoming), numMiddles) + }, + }, + + { + Name: "outgoing single transaction test", + TestFunction: func(t *testing.T) { + req := require.New(t) + left, right := &Sides{Name: "left"}, &Sides{Name: "right"} + middle := &Middle{} + middle.OutgoingSides = []*Sides{left, right} + left.MatchOutgoing = []*Middle{middle} + right.MatchOutgoing = []*Middle{middle} + + sess, err := integrationTest.gogm.NewSessionV2(SessionConfig{ + AccessMode: neo4j.AccessModeWrite, + }) + req.Nil(err) + req.NotNil(sess) + + req.Nil(sess.SaveDepth(context.Background(), left, 1)) + req.Nil(sess.SaveDepth(context.Background(), right, 1)) + req.Nil(sess.Close()) + + var matchMiddle Middle + sess, err = integrationTest.gogm.NewSessionV2(SessionConfig{ + AccessMode: neo4j.AccessModeRead, + }) + req.Nil(err) + req.NotNil(sess) + defer sess.Close() + req.Nil(sess.LoadDepth(context.Background(), &matchMiddle, middle.UUID, 1)) + + req.Equal(len(matchMiddle.OutgoingSides), 2, "Expected size of middle") + }, + }, + { + Name: "outgoing single non transaction test", + TestFunction: func(t *testing.T) { + req := require.New(t) + left, right := &Sides{Name: "left"}, &Sides{Name: "right"} + middle := &Middle{} + middle.OutgoingSides = []*Sides{left, right} + left.MatchOutgoing = []*Middle{middle} + right.MatchOutgoing = []*Middle{middle} + + sess, err := integrationTest.gogm.NewSessionV2(SessionConfig{ + AccessMode: neo4j.AccessModeWrite, + }) + req.Nil(err) + req.NotNil(sess) + + ctx := context.Background() + req.Nil(sess.ManagedTransaction(ctx, func(tx TransactionV2) error { + err = tx.SaveDepth(context.Background(), left, 1) + if err != nil { + return err + } + err = tx.SaveDepth(context.Background(), right, 1) + if err != nil { + return err + } + + return nil + })) + req.Nil(sess.Close()) + + var matchMiddle Middle + sess, err = integrationTest.gogm.NewSessionV2(SessionConfig{ + AccessMode: neo4j.AccessModeRead, + }) + req.Nil(err) + req.NotNil(sess) + defer sess.Close() + req.Nil(sess.LoadDepth(context.Background(), &matchMiddle, middle.UUID, 1)) + + req.Equal(len(matchMiddle.OutgoingSides), 2, "Expected size of middle") + }, + }, + + { + Name: "outgoing multi non transaction test", + TestFunction: func(t *testing.T) { + req := require.New(t) + left, right := &Sides{Name: "left"}, &Sides{Name: "right"} + + middles := make([]*Middle, numMiddles) + for i := 0; i < numMiddles; i++ { + middles[i] = &Middle{} + middles[i].OutgoingSides = []*Sides{left, right} + } + + left.MatchOutgoing = middles + right.MatchOutgoing = middles + + sess, err := integrationTest.gogm.NewSessionV2(SessionConfig{ + AccessMode: neo4j.AccessModeWrite, + }) + req.Nil(err) + req.NotNil(sess) + + req.Nil(sess.SaveDepth(context.Background(), left, 1)) + req.Nil(sess.SaveDepth(context.Background(), right, 1)) + req.Nil(sess.Close()) + + sess, err = integrationTest.gogm.NewSessionV2(SessionConfig{ + AccessMode: neo4j.AccessModeRead, + }) + req.Nil(err) + req.NotNil(sess) + defer sess.Close() + var checkLeft, checkRight Sides + + req.Nil(sess.LoadDepth(context.Background(), &checkLeft, left.UUID, 1)) + req.Equal(len(checkLeft.MatchOutgoing), numMiddles) + + req.Nil(sess.LoadDepth(context.Background(), &checkRight, right.UUID, 1)) + req.Equal(len(checkRight.MatchOutgoing), numMiddles) + }, + }, + { + Name: "outgoing multi transaction test", + TestFunction: func(t *testing.T) { + req := require.New(t) + left, right := &Sides{Name: "left"}, &Sides{Name: "right"} + + middles := make([]*Middle, numMiddles) + for i := 0; i < numMiddles; i++ { + middles[i] = &Middle{} + middles[i].OutgoingSides = []*Sides{left, right} + } + + left.MatchOutgoing = middles + right.MatchOutgoing = middles + + sess, err := integrationTest.gogm.NewSessionV2(SessionConfig{ + AccessMode: neo4j.AccessModeWrite, + }) + req.Nil(err) + req.NotNil(sess) + + ctx := context.Background() + req.Nil(sess.ManagedTransaction(ctx, func(tx TransactionV2) error { + err = tx.SaveDepth(context.Background(), left, 1) + if err != nil { + return err + } + + return tx.SaveDepth(context.Background(), right, 1) + })) + req.Nil(sess.Close()) + + sess, err = integrationTest.gogm.NewSessionV2(SessionConfig{ + AccessMode: neo4j.AccessModeRead, + }) + req.Nil(err) + req.NotNil(sess) + defer sess.Close() + var checkLeft, checkRight Sides + + req.Nil(sess.LoadDepth(context.Background(), &checkLeft, left.UUID, 1)) + req.Equal(len(checkLeft.MatchOutgoing), numMiddles) + + req.Nil(sess.LoadDepth(context.Background(), &checkRight, right.UUID, 1)) + req.Equal(len(checkRight.MatchOutgoing), numMiddles) + }, + }, + } { + integrationTest.T().Run(testCase.Name, testCase.TestFunction) + } +} + func (integrationTest *IntegrationTestSuite) TestIntegrationV2() { req := integrationTest.Require() log.Println("testIndexManagement") @@ -633,15 +994,15 @@ func testSaveV2(sess SessionV2, req *require.Assertions) { const testUuid1 = "f64953a5-8b40-4a87-a26b-6427e661570c" -func (i *IntegrationTestSuite) TestSchemaLoadStrategy() { - req := i.Require() +func (integrationTest *IntegrationTestSuite) TestSchemaLoadStrategy() { + req := integrationTest.Require() - i.gogm.config.LoadStrategy = SCHEMA_LOAD_STRATEGY + integrationTest.gogm.config.LoadStrategy = SCHEMA_LOAD_STRATEGY // create required nodes - testSchemaLoadStrategy_Setup(i.gogm, req) + testSchemaLoadStrategy_Setup(integrationTest.gogm, req) - sess, err := i.gogm.NewSessionV2(SessionConfig{AccessMode: AccessModeRead}) + sess, err := integrationTest.gogm.NewSessionV2(SessionConfig{AccessMode: AccessModeRead}) req.Nil(err) defer req.Nil(sess.Close()) @@ -650,7 +1011,7 @@ func (i *IntegrationTestSuite) TestSchemaLoadStrategy() { defer req.Nil(sess.Close()) // test raw query (verify SchemaLoadStrategy + Neo driver decoding) - query, err := SchemaLoadStrategyOne(i.gogm, "n", "a", "uuid", "uuid", false, 1, nil) + query, err := SchemaLoadStrategyOne(integrationTest.gogm, "n", "a", "uuid", "uuid", false, 1, nil) req.Nil(err, "error generating SchemaLoadStrategy query") cypher, err := query.ToCypher() @@ -730,12 +1091,12 @@ const testUuid2 = "f64953a5-8b40-4a87-a26b-6427e661570d" const testUuid3 = "f64953a5-8b40-4a87-a26b-6427e661571d" const testUuid4 = "f64953a5-8b40-4a87-a26b-6427e661572d" -func (i *IntegrationTestSuite) TestRelationshipWithinSingleType() { - req := i.Require() +func (integrationTest *IntegrationTestSuite) TestRelationshipWithinSingleType() { + req := integrationTest.Require() - testRelationshipWithinSingleType_Setup(i.gogm, req) + testRelationshipWithinSingleType_Setup(integrationTest.gogm, req) - sess, err := i.gogm.NewSessionV2(SessionConfig{AccessMode: AccessModeRead}) + sess, err := integrationTest.gogm.NewSessionV2(SessionConfig{AccessMode: AccessModeRead}) req.Nil(err) defer req.Nil(sess.Close()) From 8c58244d0b76547a88a6e55afff03887b94bdf9d Mon Sep 17 00:00:00 2001 From: Eric Solender Date: Mon, 9 May 2022 15:31:46 -0400 Subject: [PATCH 09/20] added save print statements --- integration_test.go | 396 +++++++++++++++++++++++++------------------- save.go | 8 + 2 files changed, 233 insertions(+), 171 deletions(-) diff --git a/integration_test.go b/integration_test.go index f89e9dd..8b0191b 100644 --- a/integration_test.go +++ b/integration_test.go @@ -80,7 +80,7 @@ func (integrationTest *IntegrationTestSuite) SetupSuite() { DefaultTransactionTimeout: 2 * time.Minute, } - gogm, err := New(&conf, UUIDPrimaryKeyStrategy, &a{}, &b{}, &c{}, &propTest{}, &narcissisticTestNode{}, &Sides{}, &Middle{}) + gogm, err := New(&conf, UUIDPrimaryKeyStrategy, &a{}, &b{}, &c{}, &propTest{}, &narcissisticTestNode{}, &Sides{}, &Middle{}, &Bottom{}) integrationTest.Require().Nil(err) integrationTest.Require().NotNil(gogm) integrationTest.gogm = gogm @@ -323,22 +323,32 @@ type Sides struct { MatchOutgoing []*Middle `gogm:"direction=incoming;relationship=outgoing_test"` } +type Bottom struct { + BaseUUIDNode + Name string `gogm:"name=name"` + Middle []*Middle `gogm:"direction=outgoing;relationship=bottom"` +} + type Middle struct { BaseUUIDNode - IncomingSides []*Sides `gogm:"direction=incoming;relationship=incoming_test"` - OutgoingSides []*Sides `gogm:"direction=outgoing;relationship=outgoing_test"` + IncomingSides []*Sides `gogm:"direction=incoming;relationship=incoming_test"` + OutgoingSides []*Sides `gogm:"direction=outgoing;relationship=outgoing_test"` + Bottom []*Bottom `gogm:"direction=incoming;relationship=bottom"` } func (integrationTest *IntegrationTestSuite) TestMultiSaveEdgeCase() { /* - (left)--(middle)--(right) - SaveDepth(left, 1) - SaveDepth(right,1) - - Problem is only (middle)--(right) is saved, not (left)--(middle) + (left)--(middle)--(right) + | + (Bottom) + SaveDepth(left, 1) + SaveDepth(right,1) + SaveDepth(bottom, 1) + + Problem is only (middle)--(right) is saved, not (left)--(middle) */ - numMiddles := 15 + numMiddles := 30 for _, testCase := range []struct { TestFunction func(t *testing.T) @@ -350,6 +360,10 @@ func (integrationTest *IntegrationTestSuite) TestMultiSaveEdgeCase() { req := require.New(t) left, right := &Sides{Name: "left"}, &Sides{Name: "right"} middle := &Middle{} + bottom := &Bottom{} + + bottom.Middle = []*Middle{middle} + middle.Bottom = []*Bottom{bottom} middle.IncomingSides = []*Sides{left, right} left.MatchIncoming = []*Middle{middle} right.MatchIncoming = []*Middle{middle} @@ -362,6 +376,7 @@ func (integrationTest *IntegrationTestSuite) TestMultiSaveEdgeCase() { req.Nil(sess.SaveDepth(context.Background(), left, 1)) req.Nil(sess.SaveDepth(context.Background(), right, 1)) + req.Nil(sess.SaveDepth(context.Background(), bottom, 1)) req.Nil(sess.Close()) var matchMiddle Middle @@ -374,6 +389,7 @@ func (integrationTest *IntegrationTestSuite) TestMultiSaveEdgeCase() { req.Nil(sess.LoadDepth(context.Background(), &matchMiddle, middle.UUID, 1)) req.Equal(len(matchMiddle.IncomingSides), 2, "Expected size of middle") + req.Equal(len(matchMiddle.Bottom), 1, "Expected size of bottom") }, }, { @@ -382,6 +398,10 @@ func (integrationTest *IntegrationTestSuite) TestMultiSaveEdgeCase() { req := require.New(t) left, right := &Sides{Name: "left"}, &Sides{Name: "right"} middle := &Middle{} + bottom := &Bottom{} + + bottom.Middle = []*Middle{middle} + middle.Bottom = []*Bottom{bottom} middle.IncomingSides = []*Sides{left, right} left.MatchIncoming = []*Middle{middle} right.MatchIncoming = []*Middle{middle} @@ -398,11 +418,17 @@ func (integrationTest *IntegrationTestSuite) TestMultiSaveEdgeCase() { if err != nil { return err } + err = tx.SaveDepth(context.Background(), right, 1) if err != nil { return err } + err = tx.SaveDepth(context.Background(), bottom, 1) + if err != nil { + return err + } + return nil })) req.Nil(sess.Close()) @@ -417,6 +443,7 @@ func (integrationTest *IntegrationTestSuite) TestMultiSaveEdgeCase() { req.Nil(sess.LoadDepth(context.Background(), &matchMiddle, middle.UUID, 1)) req.Equal(len(matchMiddle.IncomingSides), 2, "Expected size of middle") + req.Equal(len(matchMiddle.Bottom), 1, "Expected size of bottom") }, }, @@ -425,13 +452,15 @@ func (integrationTest *IntegrationTestSuite) TestMultiSaveEdgeCase() { TestFunction: func(t *testing.T) { req := require.New(t) left, right := &Sides{Name: "left"}, &Sides{Name: "right"} - + bottom := &Bottom{} middles := make([]*Middle, numMiddles) for i := 0; i < numMiddles; i++ { middles[i] = &Middle{} middles[i].IncomingSides = []*Sides{left, right} + middles[i].Bottom = []*Bottom{bottom} } + bottom.Middle = middles left.MatchIncoming = middles right.MatchIncoming = middles @@ -443,6 +472,7 @@ func (integrationTest *IntegrationTestSuite) TestMultiSaveEdgeCase() { req.Nil(sess.SaveDepth(context.Background(), left, 1)) req.Nil(sess.SaveDepth(context.Background(), right, 1)) + req.Nil(sess.SaveDepth(context.Background(), bottom, 1)) req.Nil(sess.Close()) sess, err = integrationTest.gogm.NewSessionV2(SessionConfig{ @@ -452,10 +482,14 @@ func (integrationTest *IntegrationTestSuite) TestMultiSaveEdgeCase() { req.NotNil(sess) defer sess.Close() var checkLeft, checkRight Sides + var checkBottom Bottom req.Nil(sess.LoadDepth(context.Background(), &checkLeft, left.UUID, 1)) req.Equal(len(checkLeft.MatchIncoming), numMiddles) + req.Nil(sess.LoadDepth(context.Background(), &checkBottom, bottom.UUID, 1)) + req.Equal(len(checkBottom.Middle), numMiddles) + req.Nil(sess.LoadDepth(context.Background(), &checkRight, right.UUID, 1)) req.Equal(len(checkRight.MatchIncoming), numMiddles) }, @@ -465,13 +499,16 @@ func (integrationTest *IntegrationTestSuite) TestMultiSaveEdgeCase() { TestFunction: func(t *testing.T) { req := require.New(t) left, right := &Sides{Name: "left"}, &Sides{Name: "right"} + bottom := &Bottom{} middles := make([]*Middle, numMiddles) for i := 0; i < numMiddles; i++ { middles[i] = &Middle{} middles[i].IncomingSides = []*Sides{left, right} + middles[i].Bottom = []*Bottom{bottom} } + bottom.Middle = middles left.MatchIncoming = middles right.MatchIncoming = middles @@ -488,127 +525,15 @@ func (integrationTest *IntegrationTestSuite) TestMultiSaveEdgeCase() { return err } - return tx.SaveDepth(context.Background(), right, 1) - })) - req.Nil(sess.Close()) - - sess, err = integrationTest.gogm.NewSessionV2(SessionConfig{ - AccessMode: neo4j.AccessModeRead, - }) - req.Nil(err) - req.NotNil(sess) - defer sess.Close() - var checkLeft, checkRight Sides - - req.Nil(sess.LoadDepth(context.Background(), &checkLeft, left.UUID, 1)) - req.Equal(len(checkLeft.MatchIncoming), numMiddles) - - req.Nil(sess.LoadDepth(context.Background(), &checkRight, right.UUID, 1)) - req.Equal(len(checkRight.MatchIncoming), numMiddles) - }, - }, - - { - Name: "outgoing single transaction test", - TestFunction: func(t *testing.T) { - req := require.New(t) - left, right := &Sides{Name: "left"}, &Sides{Name: "right"} - middle := &Middle{} - middle.OutgoingSides = []*Sides{left, right} - left.MatchOutgoing = []*Middle{middle} - right.MatchOutgoing = []*Middle{middle} - - sess, err := integrationTest.gogm.NewSessionV2(SessionConfig{ - AccessMode: neo4j.AccessModeWrite, - }) - req.Nil(err) - req.NotNil(sess) - - req.Nil(sess.SaveDepth(context.Background(), left, 1)) - req.Nil(sess.SaveDepth(context.Background(), right, 1)) - req.Nil(sess.Close()) - - var matchMiddle Middle - sess, err = integrationTest.gogm.NewSessionV2(SessionConfig{ - AccessMode: neo4j.AccessModeRead, - }) - req.Nil(err) - req.NotNil(sess) - defer sess.Close() - req.Nil(sess.LoadDepth(context.Background(), &matchMiddle, middle.UUID, 1)) - - req.Equal(len(matchMiddle.OutgoingSides), 2, "Expected size of middle") - }, - }, - { - Name: "outgoing single non transaction test", - TestFunction: func(t *testing.T) { - req := require.New(t) - left, right := &Sides{Name: "left"}, &Sides{Name: "right"} - middle := &Middle{} - middle.OutgoingSides = []*Sides{left, right} - left.MatchOutgoing = []*Middle{middle} - right.MatchOutgoing = []*Middle{middle} - - sess, err := integrationTest.gogm.NewSessionV2(SessionConfig{ - AccessMode: neo4j.AccessModeWrite, - }) - req.Nil(err) - req.NotNil(sess) - - ctx := context.Background() - req.Nil(sess.ManagedTransaction(ctx, func(tx TransactionV2) error { - err = tx.SaveDepth(context.Background(), left, 1) - if err != nil { - return err - } err = tx.SaveDepth(context.Background(), right, 1) if err != nil { return err } - return nil + return tx.SaveDepth(context.Background(), bottom, 1) })) req.Nil(sess.Close()) - var matchMiddle Middle - sess, err = integrationTest.gogm.NewSessionV2(SessionConfig{ - AccessMode: neo4j.AccessModeRead, - }) - req.Nil(err) - req.NotNil(sess) - defer sess.Close() - req.Nil(sess.LoadDepth(context.Background(), &matchMiddle, middle.UUID, 1)) - - req.Equal(len(matchMiddle.OutgoingSides), 2, "Expected size of middle") - }, - }, - - { - Name: "outgoing multi non transaction test", - TestFunction: func(t *testing.T) { - req := require.New(t) - left, right := &Sides{Name: "left"}, &Sides{Name: "right"} - - middles := make([]*Middle, numMiddles) - for i := 0; i < numMiddles; i++ { - middles[i] = &Middle{} - middles[i].OutgoingSides = []*Sides{left, right} - } - - left.MatchOutgoing = middles - right.MatchOutgoing = middles - - sess, err := integrationTest.gogm.NewSessionV2(SessionConfig{ - AccessMode: neo4j.AccessModeWrite, - }) - req.Nil(err) - req.NotNil(sess) - - req.Nil(sess.SaveDepth(context.Background(), left, 1)) - req.Nil(sess.SaveDepth(context.Background(), right, 1)) - req.Nil(sess.Close()) - sess, err = integrationTest.gogm.NewSessionV2(SessionConfig{ AccessMode: neo4j.AccessModeRead, }) @@ -616,61 +541,190 @@ func (integrationTest *IntegrationTestSuite) TestMultiSaveEdgeCase() { req.NotNil(sess) defer sess.Close() var checkLeft, checkRight Sides + var checkBottom Bottom req.Nil(sess.LoadDepth(context.Background(), &checkLeft, left.UUID, 1)) - req.Equal(len(checkLeft.MatchOutgoing), numMiddles) - - req.Nil(sess.LoadDepth(context.Background(), &checkRight, right.UUID, 1)) - req.Equal(len(checkRight.MatchOutgoing), numMiddles) - }, - }, - { - Name: "outgoing multi transaction test", - TestFunction: func(t *testing.T) { - req := require.New(t) - left, right := &Sides{Name: "left"}, &Sides{Name: "right"} - - middles := make([]*Middle, numMiddles) - for i := 0; i < numMiddles; i++ { - middles[i] = &Middle{} - middles[i].OutgoingSides = []*Sides{left, right} - } - - left.MatchOutgoing = middles - right.MatchOutgoing = middles - - sess, err := integrationTest.gogm.NewSessionV2(SessionConfig{ - AccessMode: neo4j.AccessModeWrite, - }) - req.Nil(err) - req.NotNil(sess) - - ctx := context.Background() - req.Nil(sess.ManagedTransaction(ctx, func(tx TransactionV2) error { - err = tx.SaveDepth(context.Background(), left, 1) - if err != nil { - return err - } - - return tx.SaveDepth(context.Background(), right, 1) - })) - req.Nil(sess.Close()) - - sess, err = integrationTest.gogm.NewSessionV2(SessionConfig{ - AccessMode: neo4j.AccessModeRead, - }) - req.Nil(err) - req.NotNil(sess) - defer sess.Close() - var checkLeft, checkRight Sides + req.Equal(len(checkLeft.MatchIncoming), numMiddles) - req.Nil(sess.LoadDepth(context.Background(), &checkLeft, left.UUID, 1)) - req.Equal(len(checkLeft.MatchOutgoing), numMiddles) + req.Nil(sess.LoadDepth(context.Background(), &checkBottom, bottom.UUID, 1)) + req.Equal(len(checkBottom.Middle), numMiddles) req.Nil(sess.LoadDepth(context.Background(), &checkRight, right.UUID, 1)) - req.Equal(len(checkRight.MatchOutgoing), numMiddles) + req.Equal(len(checkRight.MatchIncoming), numMiddles) }, }, + // + //{ + // Name: "outgoing single transaction test", + // TestFunction: func(t *testing.T) { + // req := require.New(t) + // left, right := &Sides{Name: "left"}, &Sides{Name: "right"} + // middle := &Middle{} + // bottom := &Bottom{} + // + // bottom.Middle = []*Middle{middle} + // middle.Bottom = []*Bottom{bottom} + // middle.OutgoingSides = []*Sides{left, right} + // left.MatchOutgoing = []*Middle{middle} + // right.MatchOutgoing = []*Middle{middle} + // + // sess, err := integrationTest.gogm.NewSessionV2(SessionConfig{ + // AccessMode: neo4j.AccessModeWrite, + // }) + // req.Nil(err) + // req.NotNil(sess) + // + // req.Nil(sess.SaveDepth(context.Background(), left, 1)) + // req.Nil(sess.SaveDepth(context.Background(), right, 1)) + // req.Nil(sess.Close()) + // + // var matchMiddle Middle + // sess, err = integrationTest.gogm.NewSessionV2(SessionConfig{ + // AccessMode: neo4j.AccessModeRead, + // }) + // req.Nil(err) + // req.NotNil(sess) + // defer sess.Close() + // req.Nil(sess.LoadDepth(context.Background(), &matchMiddle, middle.UUID, 1)) + // + // req.Equal(len(matchMiddle.OutgoingSides), 2, "Expected size of middle") + // }, + //}, + //{ + // Name: "outgoing single non transaction test", + // TestFunction: func(t *testing.T) { + // req := require.New(t) + // left, right := &Sides{Name: "left"}, &Sides{Name: "right"} + // middle := &Middle{} + // bottom := &Bottom{} + // + // bottom.Middle = []*Middle{middle} + // middle.Bottom = []*Bottom{bottom} + // middle.OutgoingSides = []*Sides{left, right} + // left.MatchOutgoing = []*Middle{middle} + // right.MatchOutgoing = []*Middle{middle} + // + // sess, err := integrationTest.gogm.NewSessionV2(SessionConfig{ + // AccessMode: neo4j.AccessModeWrite, + // }) + // req.Nil(err) + // req.NotNil(sess) + // + // ctx := context.Background() + // req.Nil(sess.ManagedTransaction(ctx, func(tx TransactionV2) error { + // err = tx.SaveDepth(context.Background(), left, 1) + // if err != nil { + // return err + // } + // err = tx.SaveDepth(context.Background(), right, 1) + // if err != nil { + // return err + // } + // + // return nil + // })) + // req.Nil(sess.Close()) + // + // var matchMiddle Middle + // sess, err = integrationTest.gogm.NewSessionV2(SessionConfig{ + // AccessMode: neo4j.AccessModeRead, + // }) + // req.Nil(err) + // req.NotNil(sess) + // defer sess.Close() + // req.Nil(sess.LoadDepth(context.Background(), &matchMiddle, middle.UUID, 1)) + // + // req.Equal(len(matchMiddle.OutgoingSides), 2, "Expected size of middle") + // }, + //}, + // + //{ + // Name: "outgoing multi non transaction test", + // TestFunction: func(t *testing.T) { + // req := require.New(t) + // left, right := &Sides{Name: "left"}, &Sides{Name: "right"} + // + // middles := make([]*Middle, numMiddles) + // for i := 0; i < numMiddles; i++ { + // middles[i] = &Middle{} + // middles[i].OutgoingSides = []*Sides{left, right} + // } + // + // left.MatchOutgoing = middles + // right.MatchOutgoing = middles + // + // sess, err := integrationTest.gogm.NewSessionV2(SessionConfig{ + // AccessMode: neo4j.AccessModeWrite, + // }) + // req.Nil(err) + // req.NotNil(sess) + // + // req.Nil(sess.SaveDepth(context.Background(), left, 1)) + // req.Nil(sess.SaveDepth(context.Background(), right, 1)) + // req.Nil(sess.Close()) + // + // sess, err = integrationTest.gogm.NewSessionV2(SessionConfig{ + // AccessMode: neo4j.AccessModeRead, + // }) + // req.Nil(err) + // req.NotNil(sess) + // defer sess.Close() + // var checkLeft, checkRight Sides + // + // req.Nil(sess.LoadDepth(context.Background(), &checkLeft, left.UUID, 1)) + // req.Equal(len(checkLeft.MatchOutgoing), numMiddles) + // + // req.Nil(sess.LoadDepth(context.Background(), &checkRight, right.UUID, 1)) + // req.Equal(len(checkRight.MatchOutgoing), numMiddles) + // }, + //}, + //{ + // Name: "outgoing multi transaction test", + // TestFunction: func(t *testing.T) { + // req := require.New(t) + // left, right := &Sides{Name: "left"}, &Sides{Name: "right"} + // + // middles := make([]*Middle, numMiddles) + // for i := 0; i < numMiddles; i++ { + // middles[i] = &Middle{} + // middles[i].OutgoingSides = []*Sides{left, right} + // } + // + // left.MatchOutgoing = middles + // right.MatchOutgoing = middles + // + // sess, err := integrationTest.gogm.NewSessionV2(SessionConfig{ + // AccessMode: neo4j.AccessModeWrite, + // }) + // req.Nil(err) + // req.NotNil(sess) + // + // ctx := context.Background() + // req.Nil(sess.ManagedTransaction(ctx, func(tx TransactionV2) error { + // err = tx.SaveDepth(context.Background(), left, 1) + // if err != nil { + // return err + // } + // + // return tx.SaveDepth(context.Background(), right, 1) + // })) + // req.Nil(sess.Close()) + // + // sess, err = integrationTest.gogm.NewSessionV2(SessionConfig{ + // AccessMode: neo4j.AccessModeRead, + // }) + // req.Nil(err) + // req.NotNil(sess) + // defer sess.Close() + // var checkLeft, checkRight Sides + // + // req.Nil(sess.LoadDepth(context.Background(), &checkLeft, left.UUID, 1)) + // req.Equal(len(checkLeft.MatchOutgoing), numMiddles) + // + // req.Nil(sess.LoadDepth(context.Background(), &checkRight, right.UUID, 1)) + // req.Equal(len(checkRight.MatchOutgoing), numMiddles) + // }, + //}, } { integrationTest.T().Run(testCase.Name, testCase.TestFunction) } diff --git a/save.go b/save.go index 8779813..228a72e 100644 --- a/save.go +++ b/save.go @@ -245,6 +245,8 @@ func relateNodes(transaction neo4j.Transaction, relations map[string][]*relCreat return fmt.Errorf("failed to build query, %w", err) } + fmt.Printf("\n\nrelateNodes --------\n%s\n%+v\n--------------\n\n", cyp, params) + res, err := transaction.Run(cyp, map[string]interface{}{ "rows": params, }) @@ -290,6 +292,8 @@ func removeRelations(transaction neo4j.Transaction, dels map[int64][]int64) erro return err } + fmt.Printf("\n\nremoveRelations --------\n%s\n%+v\n--------------\n\n", cyq, params) + res, err := transaction.Run(cyq, map[string]interface{}{ "rows": params, }) @@ -541,6 +545,8 @@ func createNodes(transaction neo4j.Transaction, crNodes map[string]map[uintptr]* return fmt.Errorf("failed to build query, %w", err) } + fmt.Printf("\n\ncreateNodes(new) --------\n%s\n%+v\n--------------\n\n", cyp, newRows) + res, err := transaction.Run(cyp, map[string]interface{}{ "rows": newRows, }) @@ -607,6 +613,8 @@ func createNodes(transaction neo4j.Transaction, crNodes map[string]map[uintptr]* return fmt.Errorf("failed to build query, %w", err) } + fmt.Printf("\n\ncreateNodes (update) --------\n%s\n%+v\n--------------\n\n", cyp, updateRows) + res, err := transaction.Run(cyp, map[string]interface{}{ "rows": updateRows, }) From bac98be4d1387484e598b210d4e02714d6b6e76b Mon Sep 17 00:00:00 2001 From: Eric Solender Date: Mon, 9 May 2022 15:54:31 -0400 Subject: [PATCH 10/20] added save print statements --- save.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/save.go b/save.go index 228a72e..37b897a 100644 --- a/save.go +++ b/save.go @@ -161,7 +161,7 @@ func relateNodes(transaction neo4j.Transaction, relations map[string][]*relCreat } for label, rels := range relations { - var params []interface{} + var _params []interface{} if len(rels) == 0 { continue @@ -184,7 +184,7 @@ func relateNodes(transaction neo4j.Transaction, relations map[string][]*relCreat rel.Params = map[string]interface{}{} } - params = append(params, map[string]interface{}{ + _params = append(_params, map[string]interface{}{ "startNodeId": startId, "endNodeId": endId, "props": rel.Params, @@ -245,10 +245,10 @@ func relateNodes(transaction neo4j.Transaction, relations map[string][]*relCreat return fmt.Errorf("failed to build query, %w", err) } - fmt.Printf("\n\nrelateNodes --------\n%s\n%+v\n--------------\n\n", cyp, params) + fmt.Printf("\n\nrelateNodes --------\n%s\n%+v\n--------------\n\n", cyp, _params) res, err := transaction.Run(cyp, map[string]interface{}{ - "rows": params, + "rows": _params, }) if err != nil { return fmt.Errorf("failed to relate nodes, %w", err) From 9b7af01e14e930c721379ce831982578316bae39 Mon Sep 17 00:00:00 2001 From: Eric Solender Date: Tue, 10 May 2022 12:38:31 -0400 Subject: [PATCH 11/20] added more print statements --- save.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/save.go b/save.go index 37b897a..4783d84 100644 --- a/save.go +++ b/save.go @@ -112,6 +112,7 @@ func saveDepth(gogm *Gogm, obj interface{}, depth int) neo4j.TransactionWork { return nil, fmt.Errorf("failed to calculate current relationships, %w", err) } + fmt.Printf("\n----curdelsbefore---\n%+v\n%+v\n%+v\n-----\n", oldRels, curRels, nodeIdRef) dels, err := calculateDels(oldRels, curRels, nodeIdRef) if err != nil { return nil, fmt.Errorf("failed to calculate relationships to delete, %w", err) @@ -137,6 +138,8 @@ func saveDepth(gogm *Gogm, obj interface{}, depth int) neo4j.TransactionWork { } if len(dels) != 0 { + fmt.Printf("\n----dels after---\n%+v\n%+v\n%+v\n-----\n", oldRels, curRels, nodeIdRef) + err := removeRelations(tx, dels) if err != nil { return nil, err From 96725870992781d115d29242cacdd4953f43c583 Mon Sep 17 00:00:00 2001 From: Eric Solender Date: Tue, 10 May 2022 12:52:36 -0400 Subject: [PATCH 12/20] added more print statements --- index_v3.go | 6 +++--- index_v4.go | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/index_v3.go b/index_v3.go index 131bc9b..6ab43b1 100644 --- a/index_v3.go +++ b/index_v3.go @@ -24,7 +24,7 @@ import ( "errors" "fmt" - "github.com/adam-hanna/arrayOperations" + arr "github.com/adam-hanna/arrayOperations" "github.com/cornelk/hashmap" dsl "github.com/mindstand/go-cypherdsl" "github.com/neo4j/neo4j-go-driver/v4/neo4j" @@ -274,7 +274,7 @@ func verifyAllIndexesAndConstraintsV3(ctx context.Context, gogm *Gogm, mappedTyp } //verify from there - delta, found := arrayOperations.Difference(foundIndexes, indexes) + delta, found := arr.Difference(foundIndexes, indexes) if !found { return fmt.Errorf("found differences in remote vs ogm for found indexes, %v", delta) } @@ -285,7 +285,7 @@ func verifyAllIndexesAndConstraintsV3(ctx context.Context, gogm *Gogm, mappedTyp founds = append(founds, foundConstraints...) - delta, found = arrayOperations.Difference(founds, constraints) + delta, found = arr.Difference(founds, constraints) if !found { return fmt.Errorf("found differences in remote vs ogm for found constraints, %v", delta) } diff --git a/index_v4.go b/index_v4.go index d066345..d89f070 100644 --- a/index_v4.go +++ b/index_v4.go @@ -24,7 +24,7 @@ import ( "errors" "fmt" - "github.com/adam-hanna/arrayOperations" + arr "github.com/adam-hanna/arrayOperations" "github.com/cornelk/hashmap" "github.com/neo4j/neo4j-go-driver/v4/neo4j" "strings" @@ -303,7 +303,7 @@ func verifyAllIndexesAndConstraintsV4(ctx context.Context, gogm *Gogm, mappedTyp } //verify from there - delta, found := arrayOperations.Difference(foundIndexes, indexes) + delta, found := arr.Difference(foundIndexes, indexes) if !found { return fmt.Errorf("found differences in remote vs ogm for found indexes, %v", delta) } @@ -314,7 +314,7 @@ func verifyAllIndexesAndConstraintsV4(ctx context.Context, gogm *Gogm, mappedTyp founds = append(founds, foundConstraints...) - delta, found = arrayOperations.Difference(founds, constraints) + delta, found = arr.Difference(founds, constraints) if !found { return fmt.Errorf("found differences in remote vs ogm for found constraints, %v", delta) } From 5fc5996061bc414e5dbd4e9062329dad74afded9 Mon Sep 17 00:00:00 2001 From: Eric Solender Date: Thu, 12 May 2022 10:53:06 -0400 Subject: [PATCH 13/20] Revert "added more print statements" This reverts commit 96725870992781d115d29242cacdd4953f43c583. --- index_v3.go | 6 +++--- index_v4.go | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/index_v3.go b/index_v3.go index 6ab43b1..131bc9b 100644 --- a/index_v3.go +++ b/index_v3.go @@ -24,7 +24,7 @@ import ( "errors" "fmt" - arr "github.com/adam-hanna/arrayOperations" + "github.com/adam-hanna/arrayOperations" "github.com/cornelk/hashmap" dsl "github.com/mindstand/go-cypherdsl" "github.com/neo4j/neo4j-go-driver/v4/neo4j" @@ -274,7 +274,7 @@ func verifyAllIndexesAndConstraintsV3(ctx context.Context, gogm *Gogm, mappedTyp } //verify from there - delta, found := arr.Difference(foundIndexes, indexes) + delta, found := arrayOperations.Difference(foundIndexes, indexes) if !found { return fmt.Errorf("found differences in remote vs ogm for found indexes, %v", delta) } @@ -285,7 +285,7 @@ func verifyAllIndexesAndConstraintsV3(ctx context.Context, gogm *Gogm, mappedTyp founds = append(founds, foundConstraints...) - delta, found = arr.Difference(founds, constraints) + delta, found = arrayOperations.Difference(founds, constraints) if !found { return fmt.Errorf("found differences in remote vs ogm for found constraints, %v", delta) } diff --git a/index_v4.go b/index_v4.go index d89f070..d066345 100644 --- a/index_v4.go +++ b/index_v4.go @@ -24,7 +24,7 @@ import ( "errors" "fmt" - arr "github.com/adam-hanna/arrayOperations" + "github.com/adam-hanna/arrayOperations" "github.com/cornelk/hashmap" "github.com/neo4j/neo4j-go-driver/v4/neo4j" "strings" @@ -303,7 +303,7 @@ func verifyAllIndexesAndConstraintsV4(ctx context.Context, gogm *Gogm, mappedTyp } //verify from there - delta, found := arr.Difference(foundIndexes, indexes) + delta, found := arrayOperations.Difference(foundIndexes, indexes) if !found { return fmt.Errorf("found differences in remote vs ogm for found indexes, %v", delta) } @@ -314,7 +314,7 @@ func verifyAllIndexesAndConstraintsV4(ctx context.Context, gogm *Gogm, mappedTyp founds = append(founds, foundConstraints...) - delta, found = arr.Difference(founds, constraints) + delta, found = arrayOperations.Difference(founds, constraints) if !found { return fmt.Errorf("found differences in remote vs ogm for found constraints, %v", delta) } From 6d92fd1e906614eb9a4d7063a5e39d0462ab72ea Mon Sep 17 00:00:00 2001 From: Eric Solender Date: Thu, 12 May 2022 11:11:39 -0400 Subject: [PATCH 14/20] test set up correctly --- integration_test.go | 328 +++++++------------------------------------- 1 file changed, 47 insertions(+), 281 deletions(-) diff --git a/integration_test.go b/integration_test.go index 8b0191b..be0618d 100644 --- a/integration_test.go +++ b/integration_test.go @@ -319,22 +319,20 @@ type Sides struct { BaseUUIDNode Name string `gogm:"name=name"` - MatchIncoming []*Middle `gogm:"direction=outgoing;relationship=incoming_test"` - MatchOutgoing []*Middle `gogm:"direction=incoming;relationship=outgoing_test"` + MatchIncoming []*Middle `gogm:"direction=incoming;relationship=outgoing_test"` } type Bottom struct { BaseUUIDNode Name string `gogm:"name=name"` - Middle []*Middle `gogm:"direction=outgoing;relationship=bottom"` + Middle []*Middle `gogm:"direction=incoming;relationship=bottom"` } type Middle struct { BaseUUIDNode - IncomingSides []*Sides `gogm:"direction=incoming;relationship=incoming_test"` - OutgoingSides []*Sides `gogm:"direction=outgoing;relationship=outgoing_test"` - Bottom []*Bottom `gogm:"direction=incoming;relationship=bottom"` + IncomingSides []*Sides `gogm:"direction=outgoing;relationship=outgoing_test"` + Bottom []*Bottom `gogm:"direction=outgoing;relationship=bottom"` } func (integrationTest *IntegrationTestSuite) TestMultiSaveEdgeCase() { @@ -351,106 +349,12 @@ func (integrationTest *IntegrationTestSuite) TestMultiSaveEdgeCase() { numMiddles := 30 for _, testCase := range []struct { - TestFunction func(t *testing.T) + TestFunction func(req *require.Assertions, db string) Name string }{ - { - Name: "incoming single non transaction test", - TestFunction: func(t *testing.T) { - req := require.New(t) - left, right := &Sides{Name: "left"}, &Sides{Name: "right"} - middle := &Middle{} - bottom := &Bottom{} - - bottom.Middle = []*Middle{middle} - middle.Bottom = []*Bottom{bottom} - middle.IncomingSides = []*Sides{left, right} - left.MatchIncoming = []*Middle{middle} - right.MatchIncoming = []*Middle{middle} - - sess, err := integrationTest.gogm.NewSessionV2(SessionConfig{ - AccessMode: neo4j.AccessModeWrite, - }) - req.Nil(err) - req.NotNil(sess) - - req.Nil(sess.SaveDepth(context.Background(), left, 1)) - req.Nil(sess.SaveDepth(context.Background(), right, 1)) - req.Nil(sess.SaveDepth(context.Background(), bottom, 1)) - req.Nil(sess.Close()) - - var matchMiddle Middle - sess, err = integrationTest.gogm.NewSessionV2(SessionConfig{ - AccessMode: neo4j.AccessModeRead, - }) - req.Nil(err) - req.NotNil(sess) - defer sess.Close() - req.Nil(sess.LoadDepth(context.Background(), &matchMiddle, middle.UUID, 1)) - - req.Equal(len(matchMiddle.IncomingSides), 2, "Expected size of middle") - req.Equal(len(matchMiddle.Bottom), 1, "Expected size of bottom") - }, - }, - { - Name: "incoming single transaction test", - TestFunction: func(t *testing.T) { - req := require.New(t) - left, right := &Sides{Name: "left"}, &Sides{Name: "right"} - middle := &Middle{} - bottom := &Bottom{} - - bottom.Middle = []*Middle{middle} - middle.Bottom = []*Bottom{bottom} - middle.IncomingSides = []*Sides{left, right} - left.MatchIncoming = []*Middle{middle} - right.MatchIncoming = []*Middle{middle} - - sess, err := integrationTest.gogm.NewSessionV2(SessionConfig{ - AccessMode: neo4j.AccessModeWrite, - }) - req.Nil(err) - req.NotNil(sess) - - ctx := context.Background() - req.Nil(sess.ManagedTransaction(ctx, func(tx TransactionV2) error { - err = tx.SaveDepth(context.Background(), left, 1) - if err != nil { - return err - } - - err = tx.SaveDepth(context.Background(), right, 1) - if err != nil { - return err - } - - err = tx.SaveDepth(context.Background(), bottom, 1) - if err != nil { - return err - } - - return nil - })) - req.Nil(sess.Close()) - - var matchMiddle Middle - sess, err = integrationTest.gogm.NewSessionV2(SessionConfig{ - AccessMode: neo4j.AccessModeRead, - }) - req.Nil(err) - req.NotNil(sess) - defer sess.Close() - req.Nil(sess.LoadDepth(context.Background(), &matchMiddle, middle.UUID, 1)) - - req.Equal(len(matchMiddle.IncomingSides), 2, "Expected size of middle") - req.Equal(len(matchMiddle.Bottom), 1, "Expected size of bottom") - }, - }, - { Name: "incoming multi non transaction test", - TestFunction: func(t *testing.T) { - req := require.New(t) + TestFunction: func(req *require.Assertions, db string) { left, right := &Sides{Name: "left"}, &Sides{Name: "right"} bottom := &Bottom{} middles := make([]*Middle, numMiddles) @@ -465,7 +369,8 @@ func (integrationTest *IntegrationTestSuite) TestMultiSaveEdgeCase() { right.MatchIncoming = middles sess, err := integrationTest.gogm.NewSessionV2(SessionConfig{ - AccessMode: neo4j.AccessModeWrite, + AccessMode: neo4j.AccessModeWrite, + DatabaseName: db, }) req.Nil(err) req.NotNil(sess) @@ -476,7 +381,8 @@ func (integrationTest *IntegrationTestSuite) TestMultiSaveEdgeCase() { req.Nil(sess.Close()) sess, err = integrationTest.gogm.NewSessionV2(SessionConfig{ - AccessMode: neo4j.AccessModeRead, + AccessMode: neo4j.AccessModeRead, + DatabaseName: db, }) req.Nil(err) req.NotNil(sess) @@ -496,8 +402,7 @@ func (integrationTest *IntegrationTestSuite) TestMultiSaveEdgeCase() { }, { Name: "incoming multi transaction test", - TestFunction: func(t *testing.T) { - req := require.New(t) + TestFunction: func(req *require.Assertions, db string) { left, right := &Sides{Name: "left"}, &Sides{Name: "right"} bottom := &Bottom{} @@ -513,7 +418,8 @@ func (integrationTest *IntegrationTestSuite) TestMultiSaveEdgeCase() { right.MatchIncoming = middles sess, err := integrationTest.gogm.NewSessionV2(SessionConfig{ - AccessMode: neo4j.AccessModeWrite, + AccessMode: neo4j.AccessModeWrite, + DatabaseName: db, }) req.Nil(err) req.NotNil(sess) @@ -535,7 +441,8 @@ func (integrationTest *IntegrationTestSuite) TestMultiSaveEdgeCase() { req.Nil(sess.Close()) sess, err = integrationTest.gogm.NewSessionV2(SessionConfig{ - AccessMode: neo4j.AccessModeRead, + AccessMode: neo4j.AccessModeRead, + DatabaseName: db, }) req.Nil(err) req.NotNil(sess) @@ -553,180 +460,39 @@ func (integrationTest *IntegrationTestSuite) TestMultiSaveEdgeCase() { req.Equal(len(checkRight.MatchIncoming), numMiddles) }, }, - // - //{ - // Name: "outgoing single transaction test", - // TestFunction: func(t *testing.T) { - // req := require.New(t) - // left, right := &Sides{Name: "left"}, &Sides{Name: "right"} - // middle := &Middle{} - // bottom := &Bottom{} - // - // bottom.Middle = []*Middle{middle} - // middle.Bottom = []*Bottom{bottom} - // middle.OutgoingSides = []*Sides{left, right} - // left.MatchOutgoing = []*Middle{middle} - // right.MatchOutgoing = []*Middle{middle} - // - // sess, err := integrationTest.gogm.NewSessionV2(SessionConfig{ - // AccessMode: neo4j.AccessModeWrite, - // }) - // req.Nil(err) - // req.NotNil(sess) - // - // req.Nil(sess.SaveDepth(context.Background(), left, 1)) - // req.Nil(sess.SaveDepth(context.Background(), right, 1)) - // req.Nil(sess.Close()) - // - // var matchMiddle Middle - // sess, err = integrationTest.gogm.NewSessionV2(SessionConfig{ - // AccessMode: neo4j.AccessModeRead, - // }) - // req.Nil(err) - // req.NotNil(sess) - // defer sess.Close() - // req.Nil(sess.LoadDepth(context.Background(), &matchMiddle, middle.UUID, 1)) - // - // req.Equal(len(matchMiddle.OutgoingSides), 2, "Expected size of middle") - // }, - //}, - //{ - // Name: "outgoing single non transaction test", - // TestFunction: func(t *testing.T) { - // req := require.New(t) - // left, right := &Sides{Name: "left"}, &Sides{Name: "right"} - // middle := &Middle{} - // bottom := &Bottom{} - // - // bottom.Middle = []*Middle{middle} - // middle.Bottom = []*Bottom{bottom} - // middle.OutgoingSides = []*Sides{left, right} - // left.MatchOutgoing = []*Middle{middle} - // right.MatchOutgoing = []*Middle{middle} - // - // sess, err := integrationTest.gogm.NewSessionV2(SessionConfig{ - // AccessMode: neo4j.AccessModeWrite, - // }) - // req.Nil(err) - // req.NotNil(sess) - // - // ctx := context.Background() - // req.Nil(sess.ManagedTransaction(ctx, func(tx TransactionV2) error { - // err = tx.SaveDepth(context.Background(), left, 1) - // if err != nil { - // return err - // } - // err = tx.SaveDepth(context.Background(), right, 1) - // if err != nil { - // return err - // } - // - // return nil - // })) - // req.Nil(sess.Close()) - // - // var matchMiddle Middle - // sess, err = integrationTest.gogm.NewSessionV2(SessionConfig{ - // AccessMode: neo4j.AccessModeRead, - // }) - // req.Nil(err) - // req.NotNil(sess) - // defer sess.Close() - // req.Nil(sess.LoadDepth(context.Background(), &matchMiddle, middle.UUID, 1)) - // - // req.Equal(len(matchMiddle.OutgoingSides), 2, "Expected size of middle") - // }, - //}, - // - //{ - // Name: "outgoing multi non transaction test", - // TestFunction: func(t *testing.T) { - // req := require.New(t) - // left, right := &Sides{Name: "left"}, &Sides{Name: "right"} - // - // middles := make([]*Middle, numMiddles) - // for i := 0; i < numMiddles; i++ { - // middles[i] = &Middle{} - // middles[i].OutgoingSides = []*Sides{left, right} - // } - // - // left.MatchOutgoing = middles - // right.MatchOutgoing = middles - // - // sess, err := integrationTest.gogm.NewSessionV2(SessionConfig{ - // AccessMode: neo4j.AccessModeWrite, - // }) - // req.Nil(err) - // req.NotNil(sess) - // - // req.Nil(sess.SaveDepth(context.Background(), left, 1)) - // req.Nil(sess.SaveDepth(context.Background(), right, 1)) - // req.Nil(sess.Close()) - // - // sess, err = integrationTest.gogm.NewSessionV2(SessionConfig{ - // AccessMode: neo4j.AccessModeRead, - // }) - // req.Nil(err) - // req.NotNil(sess) - // defer sess.Close() - // var checkLeft, checkRight Sides - // - // req.Nil(sess.LoadDepth(context.Background(), &checkLeft, left.UUID, 1)) - // req.Equal(len(checkLeft.MatchOutgoing), numMiddles) - // - // req.Nil(sess.LoadDepth(context.Background(), &checkRight, right.UUID, 1)) - // req.Equal(len(checkRight.MatchOutgoing), numMiddles) - // }, - //}, - //{ - // Name: "outgoing multi transaction test", - // TestFunction: func(t *testing.T) { - // req := require.New(t) - // left, right := &Sides{Name: "left"}, &Sides{Name: "right"} - // - // middles := make([]*Middle, numMiddles) - // for i := 0; i < numMiddles; i++ { - // middles[i] = &Middle{} - // middles[i].OutgoingSides = []*Sides{left, right} - // } - // - // left.MatchOutgoing = middles - // right.MatchOutgoing = middles - // - // sess, err := integrationTest.gogm.NewSessionV2(SessionConfig{ - // AccessMode: neo4j.AccessModeWrite, - // }) - // req.Nil(err) - // req.NotNil(sess) - // - // ctx := context.Background() - // req.Nil(sess.ManagedTransaction(ctx, func(tx TransactionV2) error { - // err = tx.SaveDepth(context.Background(), left, 1) - // if err != nil { - // return err - // } - // - // return tx.SaveDepth(context.Background(), right, 1) - // })) - // req.Nil(sess.Close()) - // - // sess, err = integrationTest.gogm.NewSessionV2(SessionConfig{ - // AccessMode: neo4j.AccessModeRead, - // }) - // req.Nil(err) - // req.NotNil(sess) - // defer sess.Close() - // var checkLeft, checkRight Sides - // - // req.Nil(sess.LoadDepth(context.Background(), &checkLeft, left.UUID, 1)) - // req.Equal(len(checkLeft.MatchOutgoing), numMiddles) - // - // req.Nil(sess.LoadDepth(context.Background(), &checkRight, right.UUID, 1)) - // req.Equal(len(checkRight.MatchOutgoing), numMiddles) - // }, - //}, } { - integrationTest.T().Run(testCase.Name, testCase.TestFunction) + integrationTest.T().Run(testCase.Name, func(t *testing.T) { + db := fmt.Sprintf("db-%s", uuid2.New().String()) + req := require.New(integrationTest.T()) + sess, err := integrationTest.gogm.NewSessionV2(SessionConfig{ + AccessMode: neo4j.AccessModeWrite, + DatabaseName: "system", + }) + req.NotNil(sess) + req.Nil(err) + ctx := context.Background() + _, info, err := sess.QueryRaw(ctx, "CREATE DATABASE $DB IF NOT EXISTS", map[string]interface{}{ + "DB": db, + }) + req.Nil(err) + req.NotNil(info) + req.NotNil(info.Counters()) + req.Equal(1, info.Counters().SystemUpdates()) + + time.Sleep(10 * time.Second) + + defer func() { + _, info, err := sess.QueryRaw(ctx, "DROP DATABASE $DB", map[string]interface{}{ + "DB": db, + }) + req.Nil(err) + req.NotNil(info) + req.NotNil(info.Counters()) + req.Equal(1, info.Counters().SystemUpdates()) + }() + + testCase.TestFunction(req, db) + }) } } From 78de89a178ae54d0514db80be45a81daa15aa30f Mon Sep 17 00:00:00 2001 From: Eric Solender Date: Thu, 12 May 2022 11:45:10 -0400 Subject: [PATCH 15/20] issue patched --- save.go | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/save.go b/save.go index 4783d84..00e85bf 100644 --- a/save.go +++ b/save.go @@ -442,13 +442,10 @@ func generateCurRels(gogm *Gogm, parentPtr uintptr, current *reflect.Value, curr var followId int64 if !followIdVal.IsNil() { followIdVal = followIdVal.Elem() - if followIdVal.IsZero() { - followId = 0 - } else { - followId = followIdVal.Int() - } + followId = followIdVal.Int() } else { - followId = 0 + // should not be nil, just skip this one + continue } //check the config is there for the specified field From b4cff62ac74abe182d83a627bada8f90ad4a7762 Mon Sep 17 00:00:00 2001 From: Eric Solender Date: Thu, 12 May 2022 11:47:56 -0400 Subject: [PATCH 16/20] removed print statements --- save.go | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/save.go b/save.go index 00e85bf..dc0f13c 100644 --- a/save.go +++ b/save.go @@ -112,7 +112,6 @@ func saveDepth(gogm *Gogm, obj interface{}, depth int) neo4j.TransactionWork { return nil, fmt.Errorf("failed to calculate current relationships, %w", err) } - fmt.Printf("\n----curdelsbefore---\n%+v\n%+v\n%+v\n-----\n", oldRels, curRels, nodeIdRef) dels, err := calculateDels(oldRels, curRels, nodeIdRef) if err != nil { return nil, fmt.Errorf("failed to calculate relationships to delete, %w", err) @@ -138,8 +137,6 @@ func saveDepth(gogm *Gogm, obj interface{}, depth int) neo4j.TransactionWork { } if len(dels) != 0 { - fmt.Printf("\n----dels after---\n%+v\n%+v\n%+v\n-----\n", oldRels, curRels, nodeIdRef) - err := removeRelations(tx, dels) if err != nil { return nil, err @@ -248,8 +245,6 @@ func relateNodes(transaction neo4j.Transaction, relations map[string][]*relCreat return fmt.Errorf("failed to build query, %w", err) } - fmt.Printf("\n\nrelateNodes --------\n%s\n%+v\n--------------\n\n", cyp, _params) - res, err := transaction.Run(cyp, map[string]interface{}{ "rows": _params, }) @@ -295,8 +290,6 @@ func removeRelations(transaction neo4j.Transaction, dels map[int64][]int64) erro return err } - fmt.Printf("\n\nremoveRelations --------\n%s\n%+v\n--------------\n\n", cyq, params) - res, err := transaction.Run(cyq, map[string]interface{}{ "rows": params, }) @@ -545,8 +538,6 @@ func createNodes(transaction neo4j.Transaction, crNodes map[string]map[uintptr]* return fmt.Errorf("failed to build query, %w", err) } - fmt.Printf("\n\ncreateNodes(new) --------\n%s\n%+v\n--------------\n\n", cyp, newRows) - res, err := transaction.Run(cyp, map[string]interface{}{ "rows": newRows, }) @@ -612,9 +603,7 @@ func createNodes(transaction neo4j.Transaction, crNodes map[string]map[uintptr]* if err != nil { return fmt.Errorf("failed to build query, %w", err) } - - fmt.Printf("\n\ncreateNodes (update) --------\n%s\n%+v\n--------------\n\n", cyp, updateRows) - + res, err := transaction.Run(cyp, map[string]interface{}{ "rows": updateRows, }) From 058d9b4e5824875726aceb64b4b00931ae6b12a6 Mon Sep 17 00:00:00 2001 From: Eric Solender Date: Thu, 12 May 2022 12:34:13 -0400 Subject: [PATCH 17/20] missed one spot --- save.go | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/save.go b/save.go index dc0f13c..d779f37 100644 --- a/save.go +++ b/save.go @@ -468,13 +468,10 @@ func generateCurRels(gogm *Gogm, parentPtr uintptr, current *reflect.Value, curr var followId int64 if !followIdVal.IsNil() { followIdVal = followIdVal.Elem() - if followIdVal.IsZero() { - followId = 0 - } else { - followId = followIdVal.Int() - } + followId = followIdVal.Int() } else { - followId = 0 + // should not be nil, just skip this one + continue } //check the config is there for the specified field @@ -603,7 +600,7 @@ func createNodes(transaction neo4j.Transaction, crNodes map[string]map[uintptr]* if err != nil { return fmt.Errorf("failed to build query, %w", err) } - + res, err := transaction.Run(cyp, map[string]interface{}{ "rows": updateRows, }) From e8f9325457b513a391fccc24a16a348c8bb0d9c7 Mon Sep 17 00:00:00 2001 From: Eric Solender Date: Thu, 12 May 2022 14:06:07 -0400 Subject: [PATCH 18/20] fix test --- integration_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration_test.go b/integration_test.go index be0618d..3beedf2 100644 --- a/integration_test.go +++ b/integration_test.go @@ -69,7 +69,7 @@ func (integrationTest *IntegrationTestSuite) TearDownSuite() { func (integrationTest *IntegrationTestSuite) SetupSuite() { conf := Config{ Username: "neo4j", - Password: "password", + Password: "changeme", Host: "0.0.0.0", Protocol: "bolt", Port: 7687, From 2d732957b79ac40d918ccc4c4efb1667237c52e4 Mon Sep 17 00:00:00 2001 From: Eric Solender Date: Thu, 12 May 2022 14:13:45 -0400 Subject: [PATCH 19/20] fix init code for backwards compatibility --- gogm.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gogm.go b/gogm.go index 24c1cba..7c1f8f4 100644 --- a/gogm.go +++ b/gogm.go @@ -270,8 +270,7 @@ func (g *Gogm) initDriverRoutine(neoConfig func(neoConf *neo4j.Config), doneChan // get neoversion sess := driver.NewSession(neo4j.SessionConfig{ - AccessMode: neo4j.AccessModeRead, - DatabaseName: "neo4j", + AccessMode: neo4j.AccessModeRead, }) res, err := sess.Run("return 1", nil) From cb8a672f4a5f936626c589f27c20a0cb12a58949 Mon Sep 17 00:00:00 2001 From: Eric Solender Date: Thu, 12 May 2022 14:30:45 -0400 Subject: [PATCH 20/20] skipping edge case test for v3 of neo --- integration_test.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/integration_test.go b/integration_test.go index 3beedf2..bca1ce4 100644 --- a/integration_test.go +++ b/integration_test.go @@ -336,6 +336,13 @@ type Middle struct { } func (integrationTest *IntegrationTestSuite) TestMultiSaveEdgeCase() { + // skipping multidb integration test for v3 + if integrationTest.gogm.boltMajorVersion < 4 { + integrationTest.T().Log("skipping because of incompatible version", integrationTest.gogm.boltMajorVersion) + integrationTest.T().Skip() + return + } + /* (left)--(middle)--(right) |