{"action":"created","comment":{"url":"https://api.github.com/repos/citusdata/citus/pulls/comments/57454430","id":57454430,"diff_hunk":"@@ -0,0 +1,211 @@\n+/*-------------------------------------------------------------------------\n+ *\n+ * multi_transaction.c\n+ *     This file contains functions for managing 1PC or 2PC transactions\n+ *     across many shard placements.\n+ *\n+ * Copyright (c) 2016, Citus Data, Inc.\n+ *\n+ *-------------------------------------------------------------------------\n+ */\n+\n+#include \"postgres.h\"\n+#include \"libpq-fe.h\"\n+#include \"miscadmin.h\"\n+\n+#include \"access/xact.h\"\n+#include \"distributed/connection_cache.h\"\n+#include \"distributed/multi_transaction.h\"\n+#include \"lib/stringinfo.h\"\n+#include \"nodes/pg_list.h\"\n+\n+\n+/* Local functions forward declarations */\n+static StringInfo BuildTransactionName(int connectionId);\n+\n+\n+/*\n+ * PrepareTransactions prepares all transactions on connections in\n+ * connectionList for commit if the 2PC transaction manager is enabled.\n+ * On failure, it reports an error and stops.\n+ */\n+void\n+PrepareTransactions(List *connectionList)\n+{\n+\tListCell *connectionCell = NULL;\n+\n+\tforeach(connectionCell, connectionList)\n+\t{\n+\t\tTransactionConnection *transactionConnection =\n+\t\t\t(TransactionConnection *) lfirst(connectionCell);\n+\t\tPGconn *connection = transactionConnection->connection;\n+\t\tint64 connectionId = transactionConnection->connectionId;\n+\n+\t\tPGresult *result = NULL;\n+\t\tStringInfo command = makeStringInfo();\n+\t\tStringInfo transactionName = BuildTransactionName(connectionId);\n+\n+\t\tappendStringInfo(command, \"PREPARE TRANSACTION '%s'\", transactionName->data);\n+\n+\t\tresult = PQexec(connection, command->data);\n+\t\tif (PQresultStatus(result) != PGRES_COMMAND_OK)\n+\t\t{\n+\t\t\t/* a failure to prepare is an implicit rollback */\n+\t\t\ttransactionConnection->transactionState = TRANSACTION_STATE_CLOSED;\n+\n+\t\t\tReportRemoteError(connection, result);\n+\t\t\tPQclear(result);\n+\n+\t\t\tereport(ERROR, (errcode(ERRCODE_IO_ERROR),\n+\t\t\t\t\t\t\terrmsg(\"Failed to prepare transaction\")));\n+\t\t}\n+\n+\t\tPQclear(result);\n+\n+\t\ttransactionConnection->transactionState = TRANSACTION_STATE_PREPARED;\n+\t}\n+}\n+\n+\n+/*\n+ * AbortTransactions aborts all transactions on connections in connectionList.\n+ * On failure, it reports a warning and continues to abort all of them.\n+ */\n+void\n+AbortTransactions(List *connectionList)\n+{\n+\tListCell *connectionCell = NULL;\n+\n+\tforeach(connectionCell, connectionList)\n+\t{\n+\t\tTransactionConnection *transactionConnection =\n+\t\t\t(TransactionConnection *) lfirst(connectionCell);\n+\t\tPGconn *connection = transactionConnection->connection;\n+\t\tint64 connectionId = transactionConnection->connectionId;\n+\t\tchar *nodeName = ConnectionGetOptionValue(connection, \"host\");\n+\t\tchar *nodePort = ConnectionGetOptionValue(connection, \"port\");\n+\t\tPGresult *result = NULL;\n+\n+\t\tif (transactionConnection->transactionState == TRANSACTION_STATE_PREPARED)\n+\t\t{\n+\t\t\tStringInfo command = makeStringInfo();\n+\t\t\tStringInfo transactionName = BuildTransactionName(connectionId);\n+\n+\t\t\tappendStringInfo(command, \"ROLLBACK PREPARED '%s'\", transactionName->data);\n+\n+\t\t\tresult = PQexec(connection, command->data);\n+\t\t\tif (PQresultStatus(result) != PGRES_COMMAND_OK)\n+\t\t\t{\n+\t\t\t\t/* log a warning so the user may abort the transaction later */\n+\t\t\t\tereport(WARNING, (errmsg(\"Failed to roll back prepared transaction '%s'\",\n+\t\t\t\t\t\t\t\t\t\t transactionName->data),\n+\t\t\t\t\t\t\t\t  errhint(\"Run ROLLBACK TRANSACTION '%s' on %s:%s\",\n+\t\t\t\t\t\t\t\t\t\t  transactionName->data, nodeName, nodePort)));\n+\t\t\t}\n+\n+\t\t\tPQclear(result);\n+\t\t}\n+\t\telse if (transactionConnection->transactionState == TRANSACTION_STATE_OPEN)\n+\t\t{\n+\t\t\t/* try to roll back cleanly, if it fails then we won't commit anyway */\n+\t\t\tresult = PQexec(connection, \"ROLLBACK\");\n+\t\t\tPQclear(result);\n+\t\t}\n+\n+\t\ttransactionConnection->transactionState = TRANSACTION_STATE_CLOSED;\n+\t}\n+}\n+\n+\n+/*\n+ * CommitTransactions commits all transactions on connections in connectionList.\n+ * On failure, it reports a warning and continues committing all of them.\n+ */\n+void\n+CommitTransactions(List *connectionList)\n+{\n+\tListCell *connectionCell = NULL;\n+\n+\tforeach(connectionCell, connectionList)\n+\t{\n+\t\tTransactionConnection *transactionConnection =\n+\t\t\t(TransactionConnection *) lfirst(connectionCell);\n+\t\tPGconn *connection = transactionConnection->connection;\n+\t\tint64 connectionId = transactionConnection->connectionId;\n+\t\tchar *nodeName = ConnectionGetOptionValue(connection, \"host\");\n+\t\tchar *nodePort = ConnectionGetOptionValue(connection, \"port\");\n+\t\tPGresult *result = NULL;\n+\n+\t\tif (transactionConnection->transactionState == TRANSACTION_STATE_PREPARED)\n+\t\t{\n+\t\t\tStringInfo command = makeStringInfo();\n+\t\t\tStringInfo transactionName = BuildTransactionName(connectionId);\n+\n+\t\t\t/* we shouldn't be committing if any transactions are not prepared */\n+\t\t\tAssert(transactionConnection->transactionState == TRANSACTION_STATE_PREPARED);\n+\n+\t\t\tappendStringInfo(command, \"COMMIT PREPARED '%s'\", transactionName->data);\n+\n+\t\t\tresult = PQexec(connection, command->data);\n+\t\t\tif (PQresultStatus(result) != PGRES_COMMAND_OK)\n+\t\t\t{\n+\t\t\t\t/* log a warning so the user may commit the transaction later */\n+\t\t\t\tereport(WARNING, (errmsg(\"Failed to commit prepared transaction '%s'\",\n+\t\t\t\t\t\t\t\t\t\t transactionName->data),\n+\t\t\t\t\t\t\t\t  errhint(\"Run COMMIT TRANSACTION '%s' on %s:%s\",\n+\t\t\t\t\t\t\t\t\t\t  transactionName->data, nodeName, nodePort)));\n+\t\t\t}\n+\t\t}\n+\t\telse\n+\t\t{\n+\t\t\t/* we shouldn't be committing if any transactions are not open */\n+\t\t\tAssert(transactionConnection->transactionState == TRANSACTION_STATE_OPEN);\n+\n+\t\t\t/* try to commit, if it fails then the user might lose data */\n+\t\t\tresult = PQexec(connection, \"COMMIT\");\n+\t\t\tif (PQresultStatus(result) != PGRES_COMMAND_OK)\n+\t\t\t{\n+\t\t\t\tereport(WARNING, (errmsg(\"Failed to commit transaction on %s:%s\",\n+\t\t\t\t\t\t\t\t\t\t nodeName, nodePort)));\n+\t\t\t}\n+\t\t}\n+\n+\t\tPQclear(result);\n+\n+\t\ttransactionConnection->transactionState = TRANSACTION_STATE_CLOSED;\n+\t}\n+}\n+\n+\n+/*\n+ * BuildTransactionName constructs a unique transaction name from an ID.\n+ */\n+static StringInfo\n+BuildTransactionName(int connectionId)\n+{\n+\tStringInfo commandString = makeStringInfo();\n+\n+\tappendStringInfo(commandString, \"citus_%d_%u_%d\", MyProcPid,\n+\t\t\t\t\t GetCurrentTransactionId(), connectionId);","path":"src/backend/distributed/utils/multi_transaction.c","position":189,"original_position":189,"commit_id":"4e4c65220857a71506586e593eca5efb2b0a8a2d","original_commit_id":"a326205bc27b61fbf1265ed4f4bd0604b1efd67a","user":{"login":"marcocitus","id":7127240,"avatar_url":"https://avatars.githubusercontent.com/u/7127240?v=3","gravatar_id":"","url":"https://api.github.com/users/marcocitus","html_url":"https://github.com/marcocitus","followers_url":"https://api.github.com/users/marcocitus/followers","following_url":"https://api.github.com/users/marcocitus/following{/other_user}","gists_url":"https://api.github.com/users/marcocitus/gists{/gist_id}","starred_url":"https://api.github.com/users/marcocitus/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/marcocitus/subscriptions","organizations_url":"https://api.github.com/users/marcocitus/orgs","repos_url":"https://api.github.com/users/marcocitus/repos","events_url":"https://api.github.com/users/marcocitus/events{/privacy}","received_events_url":"https://api.github.com/users/marcocitus/received_events","type":"User","site_admin":false},"body":"Would GetTopTransactionId be suitable?","created_at":"2016-03-25T15:28:09Z","updated_at":"2016-03-25T15:28:09Z","html_url":"https://github.com/citusdata/citus/pull/366#discussion_r57454430","pull_request_url":"https://api.github.com/repos/citusdata/citus/pulls/366","_links":{"self":{"href":"https://api.github.com/repos/citusdata/citus/pulls/comments/57454430"},"html":{"href":"https://github.com/citusdata/citus/pull/366#discussion_r57454430"},"pull_request":{"href":"https://api.github.com/repos/citusdata/citus/pulls/366"}}},"pull_request":{"url":"https://api.github.com/repos/citusdata/citus/pulls/366","id":60846316,"html_url":"https://github.com/citusdata/citus/pull/366","diff_url":"https://github.com/citusdata/citus/pull/366.diff","patch_url":"https://github.com/citusdata/citus/pull/366.patch","issue_url":"https://api.github.com/repos/citusdata/citus/issues/366","number":366,"state":"open","locked":false,"title":"Add COPY support for hash- and range-partitioned tables","user":{"login":"marcocitus","id":7127240,"avatar_url":"https://avatars.githubusercontent.com/u/7127240?v=3","gravatar_id":"","url":"https://api.github.com/users/marcocitus","html_url":"https://github.com/marcocitus","followers_url":"https://api.github.com/users/marcocitus/followers","following_url":"https://api.github.com/users/marcocitus/following{/other_user}","gists_url":"https://api.github.com/users/marcocitus/gists{/gist_id}","starred_url":"https://api.github.com/users/marcocitus/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/marcocitus/subscriptions","organizations_url":"https://api.github.com/users/marcocitus/orgs","repos_url":"https://api.github.com/users/marcocitus/repos","events_url":"https://api.github.com/users/marcocitus/events{/privacy}","received_events_url":"https://api.github.com/users/marcocitus/received_events","type":"User","site_admin":false},"body":"I refactored the code from Postgres Professional for Citus. \r\n\r\nThe COPY implementation streams data via the master directly into shard placements using the copy protocol. All COPY options are expected to work, with the exception of the binary format. To speed up the COPY it implements its own shard pruning logic, which sorts the list of shards and then either does a hash look-up or a binary search.\r\n\r\nBy default COPY uses a 1-phase commit model, in which case it first finishes all the COPY commands and then commits them all. If an error occurs during the COPY, everything will safely roll back. If a failure occurs during commit, data could be lost. To solve this, the user could set citus.copy_transaction_manager to '2pc' and increase max_prepared_transactions on the worker. In that case 2-phase commit will be used, which lets the user manually roll back or commit prepared transactions. Instructions are logged on the master.\r\n\r\nCloses #33 ","created_at":"2016-02-26T14:07:23Z","updated_at":"2016-03-25T15:28:09Z","closed_at":null,"merged_at":null,"merge_commit_sha":"e96d8dfe3072b83f567c2b1f5b0ec10550396fa1","assignee":{"login":"anarazel","id":1598211,"avatar_url":"https://avatars.githubusercontent.com/u/1598211?v=3","gravatar_id":"","url":"https://api.github.com/users/anarazel","html_url":"https://github.com/anarazel","followers_url":"https://api.github.com/users/anarazel/followers","following_url":"https://api.github.com/users/anarazel/following{/other_user}","gists_url":"https://api.github.com/users/anarazel/gists{/gist_id}","starred_url":"https://api.github.com/users/anarazel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/anarazel/subscriptions","organizations_url":"https://api.github.com/users/anarazel/orgs","repos_url":"https://api.github.com/users/anarazel/repos","events_url":"https://api.github.com/users/anarazel/events{/privacy}","received_events_url":"https://api.github.com/users/anarazel/received_events","type":"User","site_admin":false},"milestone":null,"commits_url":"https://api.github.com/repos/citusdata/citus/pulls/366/commits","review_comments_url":"https://api.github.com/repos/citusdata/citus/pulls/366/comments","review_comment_url":"https://api.github.com/repos/citusdata/citus/pulls/comments{/number}","comments_url":"https://api.github.com/repos/citusdata/citus/issues/366/comments","statuses_url":"https://api.github.com/repos/citusdata/citus/statuses/4e4c65220857a71506586e593eca5efb2b0a8a2d","head":{"label":"citusdata:feature/copy","ref":"feature/copy","sha":"4e4c65220857a71506586e593eca5efb2b0a8a2d","user":{"login":"citusdata","id":2545424,"avatar_url":"https://avatars.githubusercontent.com/u/2545424?v=3","gravatar_id":"","url":"https://api.github.com/users/citusdata","html_url":"https://github.com/citusdata","followers_url":"https://api.github.com/users/citusdata/followers","following_url":"https://api.github.com/users/citusdata/following{/other_user}","gists_url":"https://api.github.com/users/citusdata/gists{/gist_id}","starred_url":"https://api.github.com/users/citusdata/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/citusdata/subscriptions","organizations_url":"https://api.github.com/users/citusdata/orgs","repos_url":"https://api.github.com/users/citusdata/repos","events_url":"https://api.github.com/users/citusdata/events{/privacy}","received_events_url":"https://api.github.com/users/citusdata/received_events","type":"Organization","site_admin":false},"repo":{"id":50874442,"name":"citus","full_name":"citusdata/citus","owner":{"login":"citusdata","id":2545424,"avatar_url":"https://avatars.githubusercontent.com/u/2545424?v=3","gravatar_id":"","url":"https://api.github.com/users/citusdata","html_url":"https://github.com/citusdata","followers_url":"https://api.github.com/users/citusdata/followers","following_url":"https://api.github.com/users/citusdata/following{/other_user}","gists_url":"https://api.github.com/users/citusdata/gists{/gist_id}","starred_url":"https://api.github.com/users/citusdata/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/citusdata/subscriptions","organizations_url":"https://api.github.com/users/citusdata/orgs","repos_url":"https://api.github.com/users/citusdata/repos","events_url":"https://api.github.com/users/citusdata/events{/privacy}","received_events_url":"https://api.github.com/users/citusdata/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/citusdata/citus","description":"Scalable PostgreSQL","fork":false,"url":"https://api.github.com/repos/citusdata/citus","forks_url":"https://api.github.com/repos/citusdata/citus/forks","keys_url":"https://api.github.com/repos/citusdata/citus/keys{/key_id}","collaborators_url":"https://api.github.com/repos/citusdata/citus/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/citusdata/citus/teams","hooks_url":"https://api.github.com/repos/citusdata/citus/hooks","issue_events_url":"https://api.github.com/repos/citusdata/citus/issues/events{/number}","events_url":"https://api.github.com/repos/citusdata/citus/events","assignees_url":"https://api.github.com/repos/citusdata/citus/assignees{/user}","branches_url":"https://api.github.com/repos/citusdata/citus/branches{/branch}","tags_url":"https://api.github.com/repos/citusdata/citus/tags","blobs_url":"https://api.github.com/repos/citusdata/citus/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/citusdata/citus/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/citusdata/citus/git/refs{/sha}","trees_url":"https://api.github.com/repos/citusdata/citus/git/trees{/sha}","statuses_url":"https://api.github.com/repos/citusdata/citus/statuses/{sha}","languages_url":"https://api.github.com/repos/citusdata/citus/languages","stargazers_url":"https://api.github.com/repos/citusdata/citus/stargazers","contributors_url":"https://api.github.com/repos/citusdata/citus/contributors","subscribers_url":"https://api.github.com/repos/citusdata/citus/subscribers","subscription_url":"https://api.github.com/repos/citusdata/citus/subscription","commits_url":"https://api.github.com/repos/citusdata/citus/commits{/sha}","git_commits_url":"https://api.github.com/repos/citusdata/citus/git/commits{/sha}","comments_url":"https://api.github.com/repos/citusdata/citus/comments{/number}","issue_comment_url":"https://api.github.com/repos/citusdata/citus/issues/comments{/number}","contents_url":"https://api.github.com/repos/citusdata/citus/contents/{+path}","compare_url":"https://api.github.com/repos/citusdata/citus/compare/{base}...{head}","merges_url":"https://api.github.com/repos/citusdata/citus/merges","archive_url":"https://api.github.com/repos/citusdata/citus/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/citusdata/citus/downloads","issues_url":"https://api.github.com/repos/citusdata/citus/issues{/number}","pulls_url":"https://api.github.com/repos/citusdata/citus/pulls{/number}","milestones_url":"https://api.github.com/repos/citusdata/citus/milestones{/number}","notifications_url":"https://api.github.com/repos/citusdata/citus/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/citusdata/citus/labels{/name}","releases_url":"https://api.github.com/repos/citusdata/citus/releases{/id}","deployments_url":"https://api.github.com/repos/citusdata/citus/deployments","created_at":"2016-02-01T21:58:39Z","updated_at":"2016-03-25T15:22:49Z","pushed_at":"2016-03-25T15:23:40Z","git_url":"git://github.com/citusdata/citus.git","ssh_url":"git@github.com:citusdata/citus.git","clone_url":"https://github.com/citusdata/citus.git","svn_url":"https://github.com/citusdata/citus","homepage":"https://www.citusdata.com","size":2084,"stargazers_count":635,"watchers_count":635,"language":"C","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":27,"mirror_url":null,"open_issues_count":320,"forks":27,"open_issues":320,"watchers":635,"default_branch":"master"}},"base":{"label":"citusdata:feature/copy-integration","ref":"feature/copy-integration","sha":"297bd5768d818c8fbe3c07ca397b1f3166f582eb","user":{"login":"citusdata","id":2545424,"avatar_url":"https://avatars.githubusercontent.com/u/2545424?v=3","gravatar_id":"","url":"https://api.github.com/users/citusdata","html_url":"https://github.com/citusdata","followers_url":"https://api.github.com/users/citusdata/followers","following_url":"https://api.github.com/users/citusdata/following{/other_user}","gists_url":"https://api.github.com/users/citusdata/gists{/gist_id}","starred_url":"https://api.github.com/users/citusdata/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/citusdata/subscriptions","organizations_url":"https://api.github.com/users/citusdata/orgs","repos_url":"https://api.github.com/users/citusdata/repos","events_url":"https://api.github.com/users/citusdata/events{/privacy}","received_events_url":"https://api.github.com/users/citusdata/received_events","type":"Organization","site_admin":false},"repo":{"id":50874442,"name":"citus","full_name":"citusdata/citus","owner":{"login":"citusdata","id":2545424,"avatar_url":"https://avatars.githubusercontent.com/u/2545424?v=3","gravatar_id":"","url":"https://api.github.com/users/citusdata","html_url":"https://github.com/citusdata","followers_url":"https://api.github.com/users/citusdata/followers","following_url":"https://api.github.com/users/citusdata/following{/other_user}","gists_url":"https://api.github.com/users/citusdata/gists{/gist_id}","starred_url":"https://api.github.com/users/citusdata/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/citusdata/subscriptions","organizations_url":"https://api.github.com/users/citusdata/orgs","repos_url":"https://api.github.com/users/citusdata/repos","events_url":"https://api.github.com/users/citusdata/events{/privacy}","received_events_url":"https://api.github.com/users/citusdata/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/citusdata/citus","description":"Scalable PostgreSQL","fork":false,"url":"https://api.github.com/repos/citusdata/citus","forks_url":"https://api.github.com/repos/citusdata/citus/forks","keys_url":"https://api.github.com/repos/citusdata/citus/keys{/key_id}","collaborators_url":"https://api.github.com/repos/citusdata/citus/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/citusdata/citus/teams","hooks_url":"https://api.github.com/repos/citusdata/citus/hooks","issue_events_url":"https://api.github.com/repos/citusdata/citus/issues/events{/number}","events_url":"https://api.github.com/repos/citusdata/citus/events","assignees_url":"https://api.github.com/repos/citusdata/citus/assignees{/user}","branches_url":"https://api.github.com/repos/citusdata/citus/branches{/branch}","tags_url":"https://api.github.com/repos/citusdata/citus/tags","blobs_url":"https://api.github.com/repos/citusdata/citus/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/citusdata/citus/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/citusdata/citus/git/refs{/sha}","trees_url":"https://api.github.com/repos/citusdata/citus/git/trees{/sha}","statuses_url":"https://api.github.com/repos/citusdata/citus/statuses/{sha}","languages_url":"https://api.github.com/repos/citusdata/citus/languages","stargazers_url":"https://api.github.com/repos/citusdata/citus/stargazers","contributors_url":"https://api.github.com/repos/citusdata/citus/contributors","subscribers_url":"https://api.github.com/repos/citusdata/citus/subscribers","subscription_url":"https://api.github.com/repos/citusdata/citus/subscription","commits_url":"https://api.github.com/repos/citusdata/citus/commits{/sha}","git_commits_url":"https://api.github.com/repos/citusdata/citus/git/commits{/sha}","comments_url":"https://api.github.com/repos/citusdata/citus/comments{/number}","issue_comment_url":"https://api.github.com/repos/citusdata/citus/issues/comments{/number}","contents_url":"https://api.github.com/repos/citusdata/citus/contents/{+path}","compare_url":"https://api.github.com/repos/citusdata/citus/compare/{base}...{head}","merges_url":"https://api.github.com/repos/citusdata/citus/merges","archive_url":"https://api.github.com/repos/citusdata/citus/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/citusdata/citus/downloads","issues_url":"https://api.github.com/repos/citusdata/citus/issues{/number}","pulls_url":"https://api.github.com/repos/citusdata/citus/pulls{/number}","milestones_url":"https://api.github.com/repos/citusdata/citus/milestones{/number}","notifications_url":"https://api.github.com/repos/citusdata/citus/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/citusdata/citus/labels{/name}","releases_url":"https://api.github.com/repos/citusdata/citus/releases{/id}","deployments_url":"https://api.github.com/repos/citusdata/citus/deployments","created_at":"2016-02-01T21:58:39Z","updated_at":"2016-03-25T15:22:49Z","pushed_at":"2016-03-25T15:23:40Z","git_url":"git://github.com/citusdata/citus.git","ssh_url":"git@github.com:citusdata/citus.git","clone_url":"https://github.com/citusdata/citus.git","svn_url":"https://github.com/citusdata/citus","homepage":"https://www.citusdata.com","size":2084,"stargazers_count":635,"watchers_count":635,"language":"C","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":27,"mirror_url":null,"open_issues_count":320,"forks":27,"open_issues":320,"watchers":635,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/citusdata/citus/pulls/366"},"html":{"href":"https://github.com/citusdata/citus/pull/366"},"issue":{"href":"https://api.github.com/repos/citusdata/citus/issues/366"},"comments":{"href":"https://api.github.com/repos/citusdata/citus/issues/366/comments"},"review_comments":{"href":"https://api.github.com/repos/citusdata/citus/pulls/366/comments"},"review_comment":{"href":"https://api.github.com/repos/citusdata/citus/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/citusdata/citus/pulls/366/commits"},"statuses":{"href":"https://api.github.com/repos/citusdata/citus/statuses/4e4c65220857a71506586e593eca5efb2b0a8a2d"}}}}