Skip to content

Commit

Permalink
Merge pull request #571 from tablelandnetwork/bcalza/altertable
Browse files Browse the repository at this point in the history
adds support for ALTER TABLE
  • Loading branch information
brunocalza authored May 19, 2023
2 parents a4c0b53 + f2d4ad3 commit d24538c
Show file tree
Hide file tree
Showing 9 changed files with 107 additions and 25 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ require (
github.com/sethvargo/go-limiter v0.7.2
github.com/spf13/cobra v1.7.0
github.com/stretchr/testify v1.8.2
github.com/tablelandnetwork/sqlparser v0.0.0-20230516213554-c251484b2141
github.com/tablelandnetwork/sqlparser v0.0.0-20230518143735-838d223866f6
github.com/textileio/cli v1.0.2
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.37.0
go.opentelemetry.io/otel v1.14.0
Expand Down
20 changes: 4 additions & 16 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1295,22 +1295,10 @@ github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a h1:1ur3QoCqvE5fl+nylMaIr9PVV1w343YRDtsy+Rwu7XI=
github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48=
github.com/tablelandnetwork/sqlparser v0.0.0-20230328132500-785ebca8e351 h1:aHuHicCezduOZVQXPXFM5MJ+h73caB2OUvVjGffzIsc=
github.com/tablelandnetwork/sqlparser v0.0.0-20230328132500-785ebca8e351/go.mod h1:S+M/v3Q8X+236kQxMQziFcLId2Cscb1LzW06IUVhljE=
github.com/tablelandnetwork/sqlparser v0.0.0-20230420192826-7c549ca44bf8 h1:mC58HOJfkfPsqetYd4hpCp0ey5qb9/ZkIRZEx+d2b4U=
github.com/tablelandnetwork/sqlparser v0.0.0-20230420192826-7c549ca44bf8/go.mod h1:S+M/v3Q8X+236kQxMQziFcLId2Cscb1LzW06IUVhljE=
github.com/tablelandnetwork/sqlparser v0.0.0-20230502223534-5872144545c4 h1:YjROwj4D7PXJbKCNdpTZJM8TpfKhdFgdzzjh3RTY1wo=
github.com/tablelandnetwork/sqlparser v0.0.0-20230502223534-5872144545c4/go.mod h1:S+M/v3Q8X+236kQxMQziFcLId2Cscb1LzW06IUVhljE=
github.com/tablelandnetwork/sqlparser v0.0.0-20230502232446-6e10f18895a3 h1:QyOUHf3JEz3p3JrijVHRggaPKahuJLuxyslxlMmuXAc=
github.com/tablelandnetwork/sqlparser v0.0.0-20230502232446-6e10f18895a3/go.mod h1:S+M/v3Q8X+236kQxMQziFcLId2Cscb1LzW06IUVhljE=
github.com/tablelandnetwork/sqlparser v0.0.0-20230512140127-295f5d9328d3 h1:GG6+Ydq75q1sN+aryvtblhX/iH1QixsOzy3neOE0MOA=
github.com/tablelandnetwork/sqlparser v0.0.0-20230512140127-295f5d9328d3/go.mod h1:S+M/v3Q8X+236kQxMQziFcLId2Cscb1LzW06IUVhljE=
github.com/tablelandnetwork/sqlparser v0.0.0-20230512150513-bea6933a3c28 h1:LItobZtMndgp0gVAot6OYruJavXndkmHcJN4LaNjCLc=
github.com/tablelandnetwork/sqlparser v0.0.0-20230512150513-bea6933a3c28/go.mod h1:S+M/v3Q8X+236kQxMQziFcLId2Cscb1LzW06IUVhljE=
github.com/tablelandnetwork/sqlparser v0.0.0-20230516205558-f93193cec061 h1:hy+sHKMwf58mMdJoJO496mb8aDwiA10TmWlhNXfhHNg=
github.com/tablelandnetwork/sqlparser v0.0.0-20230516205558-f93193cec061/go.mod h1:S+M/v3Q8X+236kQxMQziFcLId2Cscb1LzW06IUVhljE=
github.com/tablelandnetwork/sqlparser v0.0.0-20230516213554-c251484b2141 h1:mLJmSw0iqfEQR6h/FxuhvDdsNNaDsu33kQkvldWhgIw=
github.com/tablelandnetwork/sqlparser v0.0.0-20230516213554-c251484b2141/go.mod h1:S+M/v3Q8X+236kQxMQziFcLId2Cscb1LzW06IUVhljE=
github.com/tablelandnetwork/sqlparser v0.0.0-20230517143402-3ab9022be0df h1:SUG49BUSuO9S6U3RjAV8a0NIDRByHj3kSt8/QR75rtI=
github.com/tablelandnetwork/sqlparser v0.0.0-20230517143402-3ab9022be0df/go.mod h1:S+M/v3Q8X+236kQxMQziFcLId2Cscb1LzW06IUVhljE=
github.com/tablelandnetwork/sqlparser v0.0.0-20230518143735-838d223866f6 h1:f8TRklEZmT4fJd7wE+oktjf4wQndJ5BqkwXOpuHrYBU=
github.com/tablelandnetwork/sqlparser v0.0.0-20230518143735-838d223866f6/go.mod h1:S+M/v3Q8X+236kQxMQziFcLId2Cscb1LzW06IUVhljE=
github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I=
github.com/textileio/cli v1.0.2 h1:qSp/x4d/9SZ93TxhgZnE5okRKqzqHqrzAwKAPjuPw50=
github.com/textileio/cli v1.0.2/go.mod h1:vTlCvvVyOmXXLwddCcBg3PDavfUsCkRBZoyr6Nu1lkc=
Expand Down
4 changes: 4 additions & 0 deletions internal/tableland/acl.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ const (
OpRevoke
// OpCreate is represents a CREATE query.
OpCreate
// OpAlter is represents a ALTER query.
OpAlter
)

// String returns the string representation of the operation.
Expand All @@ -107,6 +109,8 @@ func (op Operation) String() string {
return "OpRevoke"
case OpCreate:
return "OpCreate"
case OpAlter:
return "OpAlter"
}

return ""
Expand Down
19 changes: 13 additions & 6 deletions pkg/client/v1/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@ func TestCreate(t *testing.T) {
func TestWrite(t *testing.T) {
calls := setup(t)
tableName := requireCreate(t, calls)
requireWrite(t, calls, tableName)
requireReceipt(t, calls, requireInsert(t, calls, tableName), WaitFor(time.Second*10))
requireReceipt(t, calls, requireAlter(t, calls, tableName), WaitFor(time.Second*10))
}

func TestRead(t *testing.T) {
t.Run("status 200", func(t *testing.T) {
calls := setup(t)
tableName := requireCreate(t, calls)
hash := requireWrite(t, calls, tableName)
hash := requireInsert(t, calls, tableName)
requireReceipt(t, calls, hash, WaitFor(time.Second*10))

type result struct {
Expand Down Expand Up @@ -68,7 +69,7 @@ func TestGetReceipt(t *testing.T) {
t.Run("status 200", func(t *testing.T) {
calls := setup(t)
tableName := requireCreate(t, calls)
hash := requireWrite(t, calls, tableName)
hash := requireInsert(t, calls, tableName)
requireReceipt(t, calls, hash, WaitFor(time.Second*10))
})

Expand Down Expand Up @@ -152,8 +153,8 @@ func TestBlockNum(t *testing.T) {

// We create a table and do two inserts, that will increase our block number to 5.
tableName := requireCreate(t, calls)
requireReceipt(t, calls, requireWrite(t, calls, tableName), WaitFor(time.Second*10))
requireReceipt(t, calls, requireWrite(t, calls, tableName), WaitFor(time.Second*10))
requireReceipt(t, calls, requireInsert(t, calls, tableName), WaitFor(time.Second*10))
requireReceipt(t, calls, requireInsert(t, calls, tableName), WaitFor(time.Second*10))

type result struct {
BlockNumber int64 `json:"bn"`
Expand All @@ -171,12 +172,18 @@ func requireCreate(t *testing.T, calls clientCalls) string {
return tableName
}

func requireWrite(t *testing.T, calls clientCalls, table string) string {
func requireInsert(t *testing.T, calls clientCalls, table string) string {
hash := calls.write(fmt.Sprintf("insert into %s (bar) values('baz')", table))
require.NotEmpty(t, hash)
return hash
}

func requireAlter(t *testing.T, calls clientCalls, table string) string {
hash := calls.write(fmt.Sprintf("alter table %s rename bar to foo", table))
require.NotEmpty(t, hash)
return hash
}

func requireReceipt(t *testing.T, calls clientCalls, hash string, opts ...ReceiptOption) *apiv1.TransactionReceipt {
res, found := calls.receipt(hash, opts...)
require.True(t, found)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func TestReplayProductionHistory(t *testing.T) {
69: "b1136bd05118349be32372509f05c240180a93d3",
137: "12b3d0aa62b4e61b10ea81c16bf050f8c27b1dca",
420: "058bd19e7874fa3c9436b0cebbcf5846f7c347f3",
80001: "5c9709607bd9da6e5e80df04e9ec2b30b488793d",
80001: "92e3252755054c969a1e1118a8e3743b2b1768a7",
421613: "18ae0ef43cdedc548706c61dccae533411f9d514",
}

Expand Down
12 changes: 11 additions & 1 deletion pkg/eventprocessor/impl/executor/impl/txnscope_runsql.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ func (ts *txnScope) execWriteQueries(
return fmt.Errorf("executing grant stmt: %w", err)
}
case parsing.WriteStmt:
if err := ts.executeWriteStmt(ctx, stmt, controller, policy, beforeRowCount); err != nil {
if err := ts.executeWriteStmt(ctx, stmt, controller, policy, beforeRowCount, isOwner); err != nil {
return fmt.Errorf("executing write stmt: %w", err)
}
default:
Expand Down Expand Up @@ -220,7 +220,17 @@ func (ts *txnScope) executeWriteStmt(
addr common.Address,
policy tableland.Policy,
beforeRowCount int,
isOwner bool,
) error {
if ws.Operation() == tableland.OpAlter {
if !isOwner {
return &errQueryExecution{
Code: "ACL_NOT_OWNER",
Msg: "non owner cannot execute alter stmt",
}
}
}

controller, err := ts.getController(ctx, ws.GetTableID())
if err != nil {
return fmt.Errorf("checking controller is set: %w", err)
Expand Down
42 changes: 42 additions & 0 deletions pkg/eventprocessor/impl/executor/impl/txnscope_runsql_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,48 @@ func TestRunSQL_WriteQueriesWithPolicies(t *testing.T) {
})
}

func TestRunSQL_AlterTable(t *testing.T) {
t.Parallel()
ctx := context.Background()

ex, _ := newExecutorWithStringTable(t, 0)

bs, err := ex.NewBlockScope(ctx, 0)
require.NoError(t, err)

policy := ethereum.ITablelandControllerPolicy{
AllowInsert: true,
AllowUpdate: true,
AllowDelete: true,
WhereClause: "",
WithCheck: "",
UpdatableColumns: nil,
}

// create an event where isOwner is false
event := &ethereum.ContractRunSQL{
Caller: common.HexToAddress("0xb451cee4A42A652Fe77d373BAe66D42fd6B8D8FF"),
IsOwner: false,
TableId: big.NewInt(100),
Statement: "ALTER TABLE foo_1337_100 ADD COLUMN bar text",
Policy: policy,
}

var hashBytes [common.HashLength]byte
binary.LittleEndian.PutUint64(hashBytes[:], rand.Uint64())
txnHash := common.BytesToHash(hashBytes[:])

txnResult, err := bs.ExecuteTxnEvents(
context.Background(),
eventfeed.TxnEvents{
TxnHash: txnHash,
Events: []interface{}{event},
},
)
require.NoError(t, err)
require.Contains(t, *txnResult.Error, "non owner cannot execute alter stmt")
}

func TestRunSQL_RowCountLimit(t *testing.T) {
t.Parallel()
ctx := context.Background()
Expand Down
3 changes: 3 additions & 0 deletions pkg/parsing/impl/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,9 @@ func (pp *QueryValidator) ValidateMutatingQuery(
if _, ok := s.(*sqlparser.Delete); ok {
mutatingStmt.operation = tableland.OpDelete
}
if _, ok := s.(*sqlparser.AlterTable); ok {
mutatingStmt.operation = tableland.OpAlter
}
ret[i] = &writeStmt{mutatingStmt}
case sqlparser.GrantOrRevokeStatement:
if _, ok := s.(*sqlparser.Grant); ok {
Expand Down
28 changes: 28 additions & 0 deletions pkg/parsing/impl/validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,34 @@ func TestWriteQuery(t *testing.T) {
expErrType: nil,
},

// ALTER TABLE
{
name: "valid alter table",
query: "ALTER TABLE a_4_10 RENAME COLUMN a to b",
tableID: big.NewInt(10),
chainID: 4,
namePrefix: "a",
expErrType: nil,
},

{
name: "valid alter table",
query: "ALTER TABLE a_4_10 ADD COLUMN a int",
tableID: big.NewInt(10),
chainID: 4,
namePrefix: "a",
expErrType: nil,
},

{
name: "valid alter table",
query: "ALTER TABLE a_4_10 DROP COLUMN a",
tableID: big.NewInt(10),
chainID: 4,
namePrefix: "a",
expErrType: nil,
},

// Only reference a single table
{
name: "update different tables",
Expand Down

0 comments on commit d24538c

Please sign in to comment.