{"action":"created","comment":{"url":"https://api.github.com/repos/alfatraining/gocqlx/pulls/comments/155212863","pull_request_review_id":81491304,"id":155212863,"diff_hunk":"@@ -0,0 +1,113 @@\n+package migrate\n+\n+import (\n+\t\"context\"\n+\t\"errors\"\n+\t\"fmt\"\n+\t\"sort\"\n+\t\"time\"\n+\n+\t\"github.com/gocql/gocql\"\n+\t\"github.com/scylladb/gocqlx\"\n+\t\"github.com/scylladb/gocqlx/qb\"\n+)\n+\n+const (\n+\tinfoSchema = `CREATE TABLE IF NOT EXISTS gocqlx_migrate (\n+\tname text,\n+\tchecksum text,\n+\tdone tinyint,\n+\tstart_time timestamp,\n+\tend_time timestamp,\n+\tPRIMARY KEY(name)\n+)`\n+\tselectInfo = \"SELECT * FROM gocqlx_migrate\"\n+)\n+\n+// MigratorTable interface operates on the gocqlx_migrate table.\n+// Tests can substitute a mock implementation.\n+type MigratorTable interface {\n+\tList(ctx context.Context) ([]*Info, error)\n+\tExecute(ctx context.Context, stmt string, info Info) error\n+}\n+\n+type cassandraSessionMigrator struct {\n+\tsession *gocql.Session\n+\tstmt    string\n+\tnames   []string\n+\tiq      *gocqlx.Queryx\n+}\n+\n+// ErrNoSessionProvided is returned when trying to create a Cassandra migrator without a session.\n+var ErrNoSessionProvided = errors.New(\"no session provided to the Cassandra migrator\")\n+\n+// ErrInvalidCqlStmt is returned when trying to execute a non valid cql statment\n+var ErrInvalidCqlStmt = errors.New(\"invalid cql statment\")\n+\n+// ErrNoCqlStmt is returned when trying to execute a non cql statment i.e. \"This is not cql\"\n+var ErrNoCqlStmt = errors.New(\"no cql statment found\")\n+\n+// NewCassandraSessionMigrator creates a migrator that persits into and reads from a Cassandra database.\n+func NewCassandraSessionMigrator(session *gocql.Session) (MigratorTable, error) {\n+\tif session == nil {\n+\t\treturn nil, ErrNoSessionProvided\n+\t}\n+\tcsm := &cassandraSessionMigrator{session: session}\n+\tcsm.stmt, csm.names = qb.Insert(\"gocqlx_migrate\").Columns(\n+\t\t\"name\",\n+\t\t\"checksum\",\n+\t\t\"done\",\n+\t\t\"start_time\",\n+\t\t\"end_time\",\n+\t).ToCql()\n+\tcsm.iq = gocqlx.Query(csm.session.Query(csm.stmt) /*.WithContext(ctx)*/, csm.names)\n+\treturn csm, nil\n+}\n+\n+// Info contains information on migration applied on a database.\n+type Info struct {\n+\tName      string\n+\tChecksum  string\n+\tDone      int\n+\tStartTime time.Time\n+\tEndTime   time.Time\n+}\n+\n+// List returns already applied migrations.\n+func (csm *cassandraSessionMigrator) List(ctx context.Context) (v []*Info, err error) {\n+\tif err = ensureInfoTable(ctx, csm.session); err != nil {\n+\t\treturn nil, err\n+\t}\n+\n+\tif err = gocqlx.Select(&v, csm.session.Query(selectInfo).WithContext(ctx)); err != nil {\n+\t\tif err == gocql.ErrNotFound {\n+\t\t\treturn nil, nil\n+\t\t}\n+\t\treturn nil, err\n+\t}\n+\n+\tsort.Slice(v, func(i, j int) bool {\n+\t\treturn v[i].Name < v[j].Name\n+\t})\n+\treturn v, err\n+}\n+\n+func ensureInfoTable(ctx context.Context, session *gocql.Session) error {\n+\treturn gocqlx.Query(session.Query(infoSchema).WithContext(ctx), nil).ExecRelease()\n+}\n+\n+// Execute applies a single statement from a migration and, if successful, records it in the migrations table.\n+func (csm *cassandraSessionMigrator) Execute(ctx context.Context, stmt string, info Info) error {\n+\t// execute\n+\tq := gocqlx.Query(csm.session.Query(stmt).RetryPolicy(nil).WithContext(ctx), nil)\n+\tif err := q.ExecRelease(); err != nil {\n+\t\treturn fmt.Errorf(\"statement %d failed: %s\", info.Done, err)\n+\t}\n+\n+\t// update info\n+\tinfo.EndTime = time.Now()\n+\tif err := csm.iq.BindStruct(info).Exec(); err != nil {\n+\t\treturn ErrInvalidCqlStmt","path":"migrate/migrator_table.go","position":110,"original_position":110,"commit_id":"5b82f615e1182b5a5ba6c3c005008d86677830c7","original_commit_id":"5b82f615e1182b5a5ba6c3c005008d86677830c7","user":{"login":"annismckenzie","id":16936,"avatar_url":"https://avatars3.githubusercontent.com/u/16936?v=4","gravatar_id":"","url":"https://api.github.com/users/annismckenzie","html_url":"https://github.com/annismckenzie","followers_url":"https://api.github.com/users/annismckenzie/followers","following_url":"https://api.github.com/users/annismckenzie/following{/other_user}","gists_url":"https://api.github.com/users/annismckenzie/gists{/gist_id}","starred_url":"https://api.github.com/users/annismckenzie/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/annismckenzie/subscriptions","organizations_url":"https://api.github.com/users/annismckenzie/orgs","repos_url":"https://api.github.com/users/annismckenzie/repos","events_url":"https://api.github.com/users/annismckenzie/events{/privacy}","received_events_url":"https://api.github.com/users/annismckenzie/received_events","type":"User","site_admin":false},"body":"Although code at the call site cannot match against a specific error, you should return the underlying error here because it's very important for figuring out what went wrong.","created_at":"2017-12-06T11:39:31Z","updated_at":"2017-12-06T11:40:07Z","html_url":"https://github.com/alfatraining/gocqlx/pull/2#discussion_r155212863","pull_request_url":"https://api.github.com/repos/alfatraining/gocqlx/pulls/2","author_association":"NONE","_links":{"self":{"href":"https://api.github.com/repos/alfatraining/gocqlx/pulls/comments/155212863"},"html":{"href":"https://github.com/alfatraining/gocqlx/pull/2#discussion_r155212863"},"pull_request":{"href":"https://api.github.com/repos/alfatraining/gocqlx/pulls/2"}}},"pull_request":{"url":"https://api.github.com/repos/alfatraining/gocqlx/pulls/2","id":156705576,"html_url":"https://github.com/alfatraining/gocqlx/pull/2","diff_url":"https://github.com/alfatraining/gocqlx/pull/2.diff","patch_url":"https://github.com/alfatraining/gocqlx/pull/2.patch","issue_url":"https://api.github.com/repos/alfatraining/gocqlx/issues/2","number":2,"state":"open","locked":false,"title":"Create migrator table interface","user":{"login":"annismckenzie","id":16936,"avatar_url":"https://avatars3.githubusercontent.com/u/16936?v=4","gravatar_id":"","url":"https://api.github.com/users/annismckenzie","html_url":"https://github.com/annismckenzie","followers_url":"https://api.github.com/users/annismckenzie/followers","following_url":"https://api.github.com/users/annismckenzie/following{/other_user}","gists_url":"https://api.github.com/users/annismckenzie/gists{/gist_id}","starred_url":"https://api.github.com/users/annismckenzie/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/annismckenzie/subscriptions","organizations_url":"https://api.github.com/users/annismckenzie/orgs","repos_url":"https://api.github.com/users/annismckenzie/repos","events_url":"https://api.github.com/users/annismckenzie/events{/privacy}","received_events_url":"https://api.github.com/users/annismckenzie/received_events","type":"User","site_admin":false},"body":"Creating this here to polish and finish it.","created_at":"2017-12-06T11:30:51Z","updated_at":"2017-12-06T11:40:07Z","closed_at":null,"merged_at":null,"merge_commit_sha":"b89fdf4ba02a798daf1955357032a9c833b4afcb","assignee":null,"assignees":[],"requested_reviewers":[],"milestone":null,"commits_url":"https://api.github.com/repos/alfatraining/gocqlx/pulls/2/commits","review_comments_url":"https://api.github.com/repos/alfatraining/gocqlx/pulls/2/comments","review_comment_url":"https://api.github.com/repos/alfatraining/gocqlx/pulls/comments{/number}","comments_url":"https://api.github.com/repos/alfatraining/gocqlx/issues/2/comments","statuses_url":"https://api.github.com/repos/alfatraining/gocqlx/statuses/5b82f615e1182b5a5ba6c3c005008d86677830c7","head":{"label":"alfatraining:create-migrator-table-interface","ref":"create-migrator-table-interface","sha":"5b82f615e1182b5a5ba6c3c005008d86677830c7","user":{"login":"alfatraining","id":13946465,"avatar_url":"https://avatars1.githubusercontent.com/u/13946465?v=4","gravatar_id":"","url":"https://api.github.com/users/alfatraining","html_url":"https://github.com/alfatraining","followers_url":"https://api.github.com/users/alfatraining/followers","following_url":"https://api.github.com/users/alfatraining/following{/other_user}","gists_url":"https://api.github.com/users/alfatraining/gists{/gist_id}","starred_url":"https://api.github.com/users/alfatraining/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alfatraining/subscriptions","organizations_url":"https://api.github.com/users/alfatraining/orgs","repos_url":"https://api.github.com/users/alfatraining/repos","events_url":"https://api.github.com/users/alfatraining/events{/privacy}","received_events_url":"https://api.github.com/users/alfatraining/received_events","type":"Organization","site_admin":false},"repo":{"id":111672581,"name":"gocqlx","full_name":"alfatraining/gocqlx","owner":{"login":"alfatraining","id":13946465,"avatar_url":"https://avatars1.githubusercontent.com/u/13946465?v=4","gravatar_id":"","url":"https://api.github.com/users/alfatraining","html_url":"https://github.com/alfatraining","followers_url":"https://api.github.com/users/alfatraining/followers","following_url":"https://api.github.com/users/alfatraining/following{/other_user}","gists_url":"https://api.github.com/users/alfatraining/gists{/gist_id}","starred_url":"https://api.github.com/users/alfatraining/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alfatraining/subscriptions","organizations_url":"https://api.github.com/users/alfatraining/orgs","repos_url":"https://api.github.com/users/alfatraining/repos","events_url":"https://api.github.com/users/alfatraining/events{/privacy}","received_events_url":"https://api.github.com/users/alfatraining/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/alfatraining/gocqlx","description":"Go toolkit for ScyllaDB and Apache Cassandra®","fork":true,"url":"https://api.github.com/repos/alfatraining/gocqlx","forks_url":"https://api.github.com/repos/alfatraining/gocqlx/forks","keys_url":"https://api.github.com/repos/alfatraining/gocqlx/keys{/key_id}","collaborators_url":"https://api.github.com/repos/alfatraining/gocqlx/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/alfatraining/gocqlx/teams","hooks_url":"https://api.github.com/repos/alfatraining/gocqlx/hooks","issue_events_url":"https://api.github.com/repos/alfatraining/gocqlx/issues/events{/number}","events_url":"https://api.github.com/repos/alfatraining/gocqlx/events","assignees_url":"https://api.github.com/repos/alfatraining/gocqlx/assignees{/user}","branches_url":"https://api.github.com/repos/alfatraining/gocqlx/branches{/branch}","tags_url":"https://api.github.com/repos/alfatraining/gocqlx/tags","blobs_url":"https://api.github.com/repos/alfatraining/gocqlx/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/alfatraining/gocqlx/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/alfatraining/gocqlx/git/refs{/sha}","trees_url":"https://api.github.com/repos/alfatraining/gocqlx/git/trees{/sha}","statuses_url":"https://api.github.com/repos/alfatraining/gocqlx/statuses/{sha}","languages_url":"https://api.github.com/repos/alfatraining/gocqlx/languages","stargazers_url":"https://api.github.com/repos/alfatraining/gocqlx/stargazers","contributors_url":"https://api.github.com/repos/alfatraining/gocqlx/contributors","subscribers_url":"https://api.github.com/repos/alfatraining/gocqlx/subscribers","subscription_url":"https://api.github.com/repos/alfatraining/gocqlx/subscription","commits_url":"https://api.github.com/repos/alfatraining/gocqlx/commits{/sha}","git_commits_url":"https://api.github.com/repos/alfatraining/gocqlx/git/commits{/sha}","comments_url":"https://api.github.com/repos/alfatraining/gocqlx/comments{/number}","issue_comment_url":"https://api.github.com/repos/alfatraining/gocqlx/issues/comments{/number}","contents_url":"https://api.github.com/repos/alfatraining/gocqlx/contents/{+path}","compare_url":"https://api.github.com/repos/alfatraining/gocqlx/compare/{base}...{head}","merges_url":"https://api.github.com/repos/alfatraining/gocqlx/merges","archive_url":"https://api.github.com/repos/alfatraining/gocqlx/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/alfatraining/gocqlx/downloads","issues_url":"https://api.github.com/repos/alfatraining/gocqlx/issues{/number}","pulls_url":"https://api.github.com/repos/alfatraining/gocqlx/pulls{/number}","milestones_url":"https://api.github.com/repos/alfatraining/gocqlx/milestones{/number}","notifications_url":"https://api.github.com/repos/alfatraining/gocqlx/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/alfatraining/gocqlx/labels{/name}","releases_url":"https://api.github.com/repos/alfatraining/gocqlx/releases{/id}","deployments_url":"https://api.github.com/repos/alfatraining/gocqlx/deployments","created_at":"2017-11-22T10:54:52Z","updated_at":"2017-11-22T10:54:54Z","pushed_at":"2017-12-06T11:30:52Z","git_url":"git://github.com/alfatraining/gocqlx.git","ssh_url":"git@github.com:alfatraining/gocqlx.git","clone_url":"https://github.com/alfatraining/gocqlx.git","svn_url":"https://github.com/alfatraining/gocqlx","homepage":"","size":174,"stargazers_count":0,"watchers_count":0,"language":"Go","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":2,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0"},"forks":0,"open_issues":2,"watchers":0,"default_branch":"master"}},"base":{"label":"alfatraining:master","ref":"master","sha":"3a3f0a8f1db91aa7bffd04c91e081ef078b0a87a","user":{"login":"alfatraining","id":13946465,"avatar_url":"https://avatars1.githubusercontent.com/u/13946465?v=4","gravatar_id":"","url":"https://api.github.com/users/alfatraining","html_url":"https://github.com/alfatraining","followers_url":"https://api.github.com/users/alfatraining/followers","following_url":"https://api.github.com/users/alfatraining/following{/other_user}","gists_url":"https://api.github.com/users/alfatraining/gists{/gist_id}","starred_url":"https://api.github.com/users/alfatraining/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alfatraining/subscriptions","organizations_url":"https://api.github.com/users/alfatraining/orgs","repos_url":"https://api.github.com/users/alfatraining/repos","events_url":"https://api.github.com/users/alfatraining/events{/privacy}","received_events_url":"https://api.github.com/users/alfatraining/received_events","type":"Organization","site_admin":false},"repo":{"id":111672581,"name":"gocqlx","full_name":"alfatraining/gocqlx","owner":{"login":"alfatraining","id":13946465,"avatar_url":"https://avatars1.githubusercontent.com/u/13946465?v=4","gravatar_id":"","url":"https://api.github.com/users/alfatraining","html_url":"https://github.com/alfatraining","followers_url":"https://api.github.com/users/alfatraining/followers","following_url":"https://api.github.com/users/alfatraining/following{/other_user}","gists_url":"https://api.github.com/users/alfatraining/gists{/gist_id}","starred_url":"https://api.github.com/users/alfatraining/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alfatraining/subscriptions","organizations_url":"https://api.github.com/users/alfatraining/orgs","repos_url":"https://api.github.com/users/alfatraining/repos","events_url":"https://api.github.com/users/alfatraining/events{/privacy}","received_events_url":"https://api.github.com/users/alfatraining/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/alfatraining/gocqlx","description":"Go toolkit for ScyllaDB and Apache Cassandra®","fork":true,"url":"https://api.github.com/repos/alfatraining/gocqlx","forks_url":"https://api.github.com/repos/alfatraining/gocqlx/forks","keys_url":"https://api.github.com/repos/alfatraining/gocqlx/keys{/key_id}","collaborators_url":"https://api.github.com/repos/alfatraining/gocqlx/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/alfatraining/gocqlx/teams","hooks_url":"https://api.github.com/repos/alfatraining/gocqlx/hooks","issue_events_url":"https://api.github.com/repos/alfatraining/gocqlx/issues/events{/number}","events_url":"https://api.github.com/repos/alfatraining/gocqlx/events","assignees_url":"https://api.github.com/repos/alfatraining/gocqlx/assignees{/user}","branches_url":"https://api.github.com/repos/alfatraining/gocqlx/branches{/branch}","tags_url":"https://api.github.com/repos/alfatraining/gocqlx/tags","blobs_url":"https://api.github.com/repos/alfatraining/gocqlx/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/alfatraining/gocqlx/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/alfatraining/gocqlx/git/refs{/sha}","trees_url":"https://api.github.com/repos/alfatraining/gocqlx/git/trees{/sha}","statuses_url":"https://api.github.com/repos/alfatraining/gocqlx/statuses/{sha}","languages_url":"https://api.github.com/repos/alfatraining/gocqlx/languages","stargazers_url":"https://api.github.com/repos/alfatraining/gocqlx/stargazers","contributors_url":"https://api.github.com/repos/alfatraining/gocqlx/contributors","subscribers_url":"https://api.github.com/repos/alfatraining/gocqlx/subscribers","subscription_url":"https://api.github.com/repos/alfatraining/gocqlx/subscription","commits_url":"https://api.github.com/repos/alfatraining/gocqlx/commits{/sha}","git_commits_url":"https://api.github.com/repos/alfatraining/gocqlx/git/commits{/sha}","comments_url":"https://api.github.com/repos/alfatraining/gocqlx/comments{/number}","issue_comment_url":"https://api.github.com/repos/alfatraining/gocqlx/issues/comments{/number}","contents_url":"https://api.github.com/repos/alfatraining/gocqlx/contents/{+path}","compare_url":"https://api.github.com/repos/alfatraining/gocqlx/compare/{base}...{head}","merges_url":"https://api.github.com/repos/alfatraining/gocqlx/merges","archive_url":"https://api.github.com/repos/alfatraining/gocqlx/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/alfatraining/gocqlx/downloads","issues_url":"https://api.github.com/repos/alfatraining/gocqlx/issues{/number}","pulls_url":"https://api.github.com/repos/alfatraining/gocqlx/pulls{/number}","milestones_url":"https://api.github.com/repos/alfatraining/gocqlx/milestones{/number}","notifications_url":"https://api.github.com/repos/alfatraining/gocqlx/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/alfatraining/gocqlx/labels{/name}","releases_url":"https://api.github.com/repos/alfatraining/gocqlx/releases{/id}","deployments_url":"https://api.github.com/repos/alfatraining/gocqlx/deployments","created_at":"2017-11-22T10:54:52Z","updated_at":"2017-11-22T10:54:54Z","pushed_at":"2017-12-06T11:30:52Z","git_url":"git://github.com/alfatraining/gocqlx.git","ssh_url":"git@github.com:alfatraining/gocqlx.git","clone_url":"https://github.com/alfatraining/gocqlx.git","svn_url":"https://github.com/alfatraining/gocqlx","homepage":"","size":174,"stargazers_count":0,"watchers_count":0,"language":"Go","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":2,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0"},"forks":0,"open_issues":2,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/alfatraining/gocqlx/pulls/2"},"html":{"href":"https://github.com/alfatraining/gocqlx/pull/2"},"issue":{"href":"https://api.github.com/repos/alfatraining/gocqlx/issues/2"},"comments":{"href":"https://api.github.com/repos/alfatraining/gocqlx/issues/2/comments"},"review_comments":{"href":"https://api.github.com/repos/alfatraining/gocqlx/pulls/2/comments"},"review_comment":{"href":"https://api.github.com/repos/alfatraining/gocqlx/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/alfatraining/gocqlx/pulls/2/commits"},"statuses":{"href":"https://api.github.com/repos/alfatraining/gocqlx/statuses/5b82f615e1182b5a5ba6c3c005008d86677830c7"}},"author_association":"NONE"}}
{"actor":{"display_login":"annismckenzie"}}