Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vtexplain crash on multiple INNER JOINs #6918

Closed
mdkent opened this issue Oct 20, 2020 · 0 comments · Fixed by #7829
Closed

vtexplain crash on multiple INNER JOINs #6918

mdkent opened this issue Oct 20, 2020 · 0 comments · Fixed by #7829
Labels
Component: Query Serving Type: Enhancement Logical improvement (somewhere between a bug and feature)

Comments

@mdkent
Copy link

mdkent commented Oct 20, 2020

Overview of the Issue

vtexplain crashes on multiple INNER JOINs

Reproduction Steps

Given the following:

schema.sql

CREATE TABLE `accounts` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE `contacts` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `account_id` bigint(20) NOT NULL,
  `contactable_type` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `contactable_id` bigint(20) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE `users` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `account_id` bigint(20) NOT NULL,
  `identity_id` bigint(20) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

and vschema.json

{
  "main": {
    "sharded": true,
    "vindexes": {
      "hash": {
        "type": "hash"
      }
    },
    "tables": {
      "accounts": {
        "columnVindexes": [
          {
            "column": "id",
            "name": "hash"
          }
        ],
        "autoIncrement": {
          "column": "id",
          "sequence": "accounts_seq"
        }
      },
      "contacts": {
        "columnVindexes": [
          {
            "column": "account_id",
            "name": "hash"
          }
        ],
        "autoIncrement": {
          "column": "id",
          "sequence": "contacts_seq"
        }
      },
      "users": {
        "columnVindexes": [
          {
            "column": "account_id",
            "name": "hash"
          }
        ],
        "autoIncrement": {
          "column": "id",
          "sequence": "users_seq"
        }
      }
    }
  },
  "mainunsharded": {
    "tables": {
      "accounts_seq": {
        "type": "sequence"
      },
      "contacts_seq": {
        "type": "sequence"
      },
      "users_seq": {
        "type": "sequence"
      }
    }
  }
}  

Run

vtexplain -vschema-file vschema.json -schema-file schema.sql -output-mode text \
  -sql 'SELECT 1 FROM `accounts` INNER JOIN `contacts` ON `accounts`.`id` = `contacts`.`account_id` INNER JOIN `users` ON `contacts`.`contactable_id` = `users`.`id` LIMIT 1'

and see it crash with

E1020 11:16:47.466618   47768 exit.go:89] panic: runtime error: index out of range [0] with length 0
/usr/local/Cellar/go/1.15.2/libexec/src/runtime/panic.go:969 (0x1038a14)
	gopanic: done = runOpenDeferFrame(gp, d)
/usr/local/Cellar/go/1.15.2/libexec/src/runtime/panic.go:88 (0x1036704)
	goPanicIndex: panic(boundsError{x: int64(x), signed: true, y: y, code: boundsIndex})
/Users/mkent/go/src/vitess.io/vitess/go/vt/vtgate/engine/join.go:183 (0x17e4519)
	io/vitess/go/vt/vtgate/engine.joinFields: fields[i] = lfields[-index-1]
/Users/mkent/go/src/vitess.io/vitess/go/vt/vtgate/engine/join.go:67 (0x17e3d44)
	io/vitess/go/vt/vtgate/engine.(*Join).Execute: result.Fields = joinFields(lresult.Fields, rresult.Fields, jn.Cols)
/Users/mkent/go/src/vitess.io/vitess/go/vt/vtgate/engine/limit.go:68 (0x17e530d)
	io/vitess/go/vt/vtgate/engine.(*Limit).Execute: result, err := l.Input.Execute(vcursor, bindVars, wantfields)
/Users/mkent/go/src/vitess.io/vitess/go/vt/vtgate/plan_execute.go:155 (0x194c89a)
	io/vitess/go/vt/vtgate.(*Executor).executePlan.func1: qr, err := plan.Instructions.Execute(vcursor, bindVars, true)
/Users/mkent/go/src/vitess.io/vitess/go/vt/vtgate/plan_execute.go:100 (0x1934cdc)
	io/vitess/go/vt/vtgate.(*Executor).newExecute: return e.executePlan(ctx, plan, vcursor, bindVars, execStart)(logStats, safeSession)
/Users/mkent/go/src/vitess.io/vitess/go/vt/vtgate/executor.go:176 (0x192269a)
	io/vitess/go/vt/vtgate.(*Executor).execute: stmtType, qr, err := e.newExecute(ctx, safeSession, sql, bindVars, logStats)
/Users/mkent/go/src/vitess.io/vitess/go/vt/vtgate/executor.go:147 (0x19223a4)
	io/vitess/go/vt/vtgate.(*Executor).Execute: stmtType, result, err := e.execute(ctx, safeSession, sql, bindVars, logStats)
/Users/mkent/go/src/vitess.io/vitess/go/vt/vtexplain/vtexplain_vtgate.go:134 (0x1adde89)
	io/vitess/go/vt/vtexplain.vtgateExecute: _, err := vtgateExecutor.Execute(context.Background(), "VtexplainExecute", vtgate.NewSafeSession(vtgateSession), sql, nil)
/Users/mkent/go/src/vitess.io/vitess/go/vt/vtexplain/vtexplain.go:280 (0x1adb8d8)
	io/vitess/go/vt/vtexplain.explain: plans, tabletActions, err := vtgateExecute(sql)
/Users/mkent/go/src/vitess.io/vitess/go/vt/vtexplain/vtexplain.go:263 (0x1adb645)
	io/vitess/go/vt/vtexplain.Run: e, err := explain(sql)
/Users/mkent/go/src/vitess.io/vitess/go/cmd/vtexplain/vtexplain.go:172 (0x1ae7892)
	parseAndRun: plans, err := vtexplain.Run(sql)
/Users/mkent/go/src/vitess.io/vitess/go/cmd/vtexplain/vtexplain.go:132 (0x1ae73b1)
	main: err := parseAndRun()
/usr/local/Cellar/go/1.15.2/libexec/src/runtime/proc.go:204 (0x103b8c8)
	main: fn()
/usr/local/Cellar/go/1.15.2/libexec/src/runtime/asm_amd64.s:1374 (0x1071980)
	goexit: BYTE	$0x90	// NOP

The second JOIN seems to do it, as this passes:

$ vtexplain -vschema-file vschema.json -schema-file schema.sql -output-mode text -sql 'SELECT 1 AS one FROM `accounts` INNER JOIN `contacts` ON `accounts`.`id` = `contacts`.`account_id` LIMIT 1'
----------------------------------------------------------------------
SELECT 1 AS one FROM `accounts` INNER JOIN `contacts` ON `accounts`.`id` = `contacts`.`account_id` LIMIT 1

1 main/-80: select 1 as one from accounts join contacts on accounts.id = contacts.account_id limit 1
1 main/80-: select 1 as one from accounts join contacts on accounts.id = contacts.account_id limit 1

----------------------------------------------------------------------

Binary version

Installed via go get -v vitess.io/vitess/go/cmd/vtexplain but the version looks broken:

Version:  (Git branch '') built on  by @ using go1.15.2 darwin/amd64

Operating system and Environment details

OSX 10.15.6

@sougou sougou added Component: Query Serving P3 Type: Enhancement Logical improvement (somewhere between a bug and feature) labels Nov 13, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Component: Query Serving Type: Enhancement Logical improvement (somewhere between a bug and feature)
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants