diff --git a/pkg/datastore/postgres/repositories/address_repository.go b/pkg/datastore/postgres/repositories/address_repository.go new file mode 100644 index 00000000..9927d099 --- /dev/null +++ b/pkg/datastore/postgres/repositories/address_repository.go @@ -0,0 +1,40 @@ +// Copyright 2018 Vulcanize +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package repositories + +import ( + "database/sql" + "github.com/ethereum/go-ethereum/common" + "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" +) + +type AddressRepository struct { + *postgres.DB +} + +func (repo AddressRepository) CreateOrGetAddress(address string) (int, error) { + stringAddressToCommonAddress := common.HexToAddress(address) + hexAddress := stringAddressToCommonAddress.Hex() + + var addressId int + getErr := repo.DB.Get(&addressId, `SELECT id FROM public.addresses WHERE address = $1`, hexAddress) + if getErr == sql.ErrNoRows { + insertErr := repo.DB.QueryRow(`INSERT INTO public.addresses (address) VALUES($1) RETURNING id`, hexAddress).Scan(&addressId) + return addressId, insertErr + } + + return addressId, getErr +} + diff --git a/pkg/datastore/postgres/repositories/address_repository_test.go b/pkg/datastore/postgres/repositories/address_repository_test.go new file mode 100644 index 00000000..417bc9ab --- /dev/null +++ b/pkg/datastore/postgres/repositories/address_repository_test.go @@ -0,0 +1,89 @@ +// Copyright 2018 Vulcanize +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package repositories_test + +import ( + . "github.com/onsi/ginkgo" + "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" + "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres/repositories" + "github.com/vulcanize/vulcanizedb/pkg/fakes" + "github.com/vulcanize/vulcanizedb/test_config" + "strings" + + . "github.com/onsi/gomega" +) + +var _ = Describe("address repository", func() { + var ( + db *postgres.DB + repo repositories.AddressRepository + address = fakes.FakeAddress.Hex() + ) + BeforeEach(func() { + db = test_config.NewTestDB(test_config.NewTestNode()) + test_config.CleanTestDB(db) + repo = repositories.AddressRepository{DB: db} + }) + + type dbAddress struct { + Id int + Address string + } + + It("creates an address record", func() { + addressId, createErr := repo.CreateOrGetAddress(address) + Expect(createErr).NotTo(HaveOccurred()) + + var actualAddress dbAddress + getErr := db.Get(&actualAddress, `SELECT id, address FROM public.addresses LIMIT 1`) + Expect(getErr).NotTo(HaveOccurred()) + expectedAddress := dbAddress{Id: addressId, Address: address} + Expect(actualAddress).To(Equal(expectedAddress)) + }) + + It("returns the existing record id if the address already exists", func() { + _, createErr := repo.CreateOrGetAddress(address) + Expect(createErr).NotTo(HaveOccurred()) + + _, getErr := repo.CreateOrGetAddress(address) + Expect(getErr).NotTo(HaveOccurred()) + + var addressCount int + addressErr := repo.DB.Get(&addressCount, `SELECT count(*) FROM public.addresses`) + Expect(addressErr).NotTo(HaveOccurred()) + }) + + It("gets upper-cased addresses", func() { + //insert it as all upper + upperAddress := strings.ToUpper(address) + upperAddressId, createErr := repo.CreateOrGetAddress(upperAddress) + Expect(createErr).NotTo(HaveOccurred()) + + mixedCaseAddressId, getErr := repo.CreateOrGetAddress(address) + Expect(getErr).NotTo(HaveOccurred()) + Expect(upperAddressId).To(Equal(mixedCaseAddressId)) + }) + + It("gets lower-cased addresses", func() { + //insert it as all upper + lowerAddress := strings.ToLower(address) + upperAddressId, createErr := repo.CreateOrGetAddress(lowerAddress) + Expect(createErr).NotTo(HaveOccurred()) + + mixedCaseAddressId, getErr := repo.CreateOrGetAddress(address) + Expect(getErr).NotTo(HaveOccurred()) + Expect(upperAddressId).To(Equal(mixedCaseAddressId)) + }) +}) \ No newline at end of file diff --git a/pkg/datastore/repository.go b/pkg/datastore/repository.go index db0c220b..ffcebfa8 100644 --- a/pkg/datastore/repository.go +++ b/pkg/datastore/repository.go @@ -21,6 +21,10 @@ import ( "github.com/vulcanize/vulcanizedb/pkg/filters" ) +type AddressRepository interface { + GetOrCreateAddress(address string) (int, error) +} + type BlockRepository interface { CreateOrUpdateBlock(block core.Block) (int64, error) GetBlock(blockNumber int64) (core.Block, error)