ronantakizawa/codereview-bench huggingface dataset:
Repository: hasura/graphql-engine
File: server/src-rsr/migrations/37_to_36.sql (SQL)

Code before:

CREATE OR REPLACE FUNCTION
  hdb_catalog.insert_event_log(schema_name text, table_name text, trigger_name text, op text, row_data json)
  RETURNS text AS $$
  DECLARE
    id text;
    payload json;
    session_variables json;
    server_version_num int;
    trace_context json;
  BEGIN
    id := gen_random_uuid();
    server_version_num := current_setting('server_version_num');
    IF server_version_num >= 90600 THEN
      session_variables := current_setting('hasura.user', 't');
      trace_context := current_setting('hasura.tracecontext');
    ELSE
      BEGIN
        session_variables := current_setting('hasura.user');
      EXCEPTION WHEN OTHERS THEN
                  session_variables := NULL;
      END;
      BEGIN
        trace_context := current_setting('hasura.tracecontext');
      EXCEPTION WHEN OTHERS THEN
        trace_context := NULL;
      END;
    END IF;
    payload := json_build_object(
      'op', op,
      'data', row_data,
      'session_variables', session_variables,
      'trace_context', trace_context
    );
    INSERT INTO hdb_catalog.event_log
                (id, schema_name, table_name, trigger_name, payload)
    VALUES
    (id, schema_name, table_name, trigger_name, payload);
    RETURN id;
  END;
$$ LANGUAGE plpgsql;

Review comment (suggestion):
You'll need to [explicitly pass `t`](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADMIN-SET-TABLE) to the second argument, `missing_ok`. 

Code after:
CREATE OR REPLACE FUNCTION 
  hdb_catalog.insert_event_log(schema_name text, table_name text, trigger_name text, op text, row_data json)
  RETURNS text AS $$
  DECLARE
    id text;
    payload json;
    session_variables json;
    server_version_num int;
  BEGIN
    id := gen_random_uuid();
    server_version_num := current_setting('server_version_num');
    IF server_version_num >= 90600 THEN
      session_variables := current_setting('hasura.user', 't');
    ELSE
      BEGIN
        session_variables := current_setting('hasura.user');
      EXCEPTION WHEN OTHERS THEN
                  session_variables := NULL;
      END;
    END IF;
    payload := json_build_object(
      'op', op,
      'data', row_data,
      'session_variables', session_variables
    );
    INSERT INTO hdb_catalog.event_log
                (id, schema_name, table_name, trigger_name, payload)
    VALUES
    (id, schema_name, table_name, trigger_name, payload);
    RETURN id;
  END;
$$ LANGUAGE plpgsql;
Repository: hasura/graphql-engine
File: console/src/components/Services/Data/TableModify/ColumnEditorList.js (JavaScript)

Code before:

      const isOk = getConfirmation(confirmMessage, true, colName);
      if (isOk) {
        const pk = [];
        let flag = true;
        for (const [_, value1] of tableSchema.primary_key.columns.entries()) {
          for (const [index2, value2] of tableSchema.columns.entries()) {
            if (value2.column_name.localeCompare(colName) == 0) {
              flag = false;
            } else {
              if (
                flag == true &&
                value1.localeCompare(value2.column_name) == 0
              ) {
                pk.push(index2);
              } else if (value1.localeCompare(value2.column_name) == 0) {
                pk.push(index2 - 1);
              }
            }
          }
          flag = true;
        }
        const pks = [];
        for (const [_, value1] of pk.sort().entries()) {
          pks.push(value1.toString());
        }
        pks.push('');
        dispatch(setPrimaryKeys(pks));
        dispatch(deleteColumnSql(col, tableSchema));
      }
    };

    const gqlCompatibilityWarning = () => {
      return (
        <GqlCompatibilityWarning
          identifier={colName}
          className={styles.add_mar_left_small}
        />
      );
    };

    const keyProperties = () => {
      const propertiesDisplay = [];

      const propertiesList = [];
      propertiesList.push(columnProperties.display_type_name);

      if (columnProperties.pkConstraint) {
        propertiesList.push('primary key');
      }


Review comment (suggestion):
You could do a similar operation like so : 
```suggestion
       const pks = [...pk.sort()];
```

Code after:
      if (isOk) {
        dispatch(deleteColumnSql(col, tableSchema));
      }
    };
    const gqlCompatibilityWarning = () => {
      return (
        <GqlCompatibilityWarning
          identifier={colName}
          className={styles.add_mar_left_small}
        />
      );
    };

    const keyProperties = () => {
      const propertiesDisplay = [];

      const propertiesList = [];
      propertiesList.push(columnProperties.display_type_name);

      if (columnProperties.pkConstraint) {
        propertiesList.push('primary key');
      }

      if (columnProperties.isUnique || columnProperties.isOnlyPrimaryKey) {
        propertiesList.push('unique');
      }

      if (columnProperties.isIdentity) {
        propertiesList.push('identity');
      }

      if (columnProperties.isNullable) {
        propertiesList.push('nullable');
      }

      if (columnProperties.default) {
        propertiesList.push(`default: ${columnProperties.default}`);
      }

      const keyPropertiesString = propertiesList.join(', ');

      propertiesDisplay.push(<i key={'props'}>{keyPropertiesString}</i>);

      propertiesDisplay.push(<br key={'br1'} />);

      propertiesDisplay.push(
        <span key={'comment'} className={styles.text_gray}>
          {columnProperties.comment && `${columnProperties.comment}`}
        </span>
      );
Repository: hasura/graphql-engine
File: console/src/components/Services/Data/TableModify/PrimaryKeyEditor.js (JavaScript)

Code before:
import React, { useState } from 'react';
import {
  DELETE_PK_WARNING,
  setPrimaryKeys,
  savePrimaryKeys,
} from './ModifyActions';
import PrimaryKeySelector from '../Common/Components/PrimaryKeySelector';
import ExpandableEditor from '../../../Common/Layout/ExpandableEditor/Editor';
import { showSuccessNotification } from '../../Common/Notification';
import { getUkeyPkeyConfig, getKeyDef } from '../Common/Components/utils';

import styles from './ModifyTable.scss';

import { getConfirmation } from '../../../Common/utils/jsUtils';

const PrimaryKeyEditor = ({
  tableSchema,
  pkModify,
  dispatch,
  currentSchema,
}) => {
  const columns = tableSchema.columns;
  const tablePrimaryKeyColumns = tableSchema.primary_key
    ? tableSchema.primary_key.columns
    : [];


Review comment (suggestion):
```suggestion
import React, { useEffect } from 'react';
```

Code after:
import React, { useEffect } from 'react';
import {
  DELETE_PK_WARNING,
  setPrimaryKeys,
  savePrimaryKeys,
} from './ModifyActions';
import PrimaryKeySelector from '../Common/Components/PrimaryKeySelector';
import ExpandableEditor from '../../../Common/Layout/ExpandableEditor/Editor';
import { showSuccessNotification } from '../../Common/Notification';
import { getUkeyPkeyConfig, getKeyDef } from '../Common/Components/utils';

import styles from './ModifyTable.scss';

import { getConfirmation } from '../../../Common/utils/jsUtils';

const PrimaryKeyEditor = ({
  tableSchema,
  pkModify,
  dispatch,
  currentSchema,
}) => {
  const columns = tableSchema.columns;
  const tablePrimaryKeyColumns = tableSchema.primary_key
    ? tableSchema.primary_key.columns
    : [];
Repository: hasura/graphql-engine
File: server/src-rsr/initialise.sql (SQL)

Code before:


CREATE TABLE hdb_catalog.event_triggers
(
  name TEXT PRIMARY KEY,
  type TEXT NOT NULL,
  schema_name TEXT NOT NULL,
  table_name TEXT NOT NULL,
  configuration JSON,
  comment TEXT,
  FOREIGN KEY (schema_name, table_name)
  REFERENCES hdb_catalog.hdb_table(table_schema, table_name) ON UPDATE CASCADE
);

CREATE TABLE hdb_catalog.event_log
(
  id TEXT DEFAULT gen_random_uuid() PRIMARY KEY,
  schema_name TEXT NOT NULL,
  table_name TEXT NOT NULL,
  trigger_name TEXT NOT NULL,
  payload JSONB NOT NULL,
  delivered BOOLEAN NOT NULL DEFAULT FALSE,
  error BOOLEAN NOT NULL DEFAULT FALSE,
  tries INTEGER NOT NULL DEFAULT 0,
  created_at TIMESTAMP DEFAULT NOW(),
  locked TIMESTAMP,
  next_retry_at TIMESTAMP,
  archived BOOLEAN NOT NULL DEFAULT FALSE
);

CREATE INDEX ON hdb_catalog.event_log (trigger_name);
CREATE INDEX ON hdb_catalog.event_log (locked);
CREATE INDEX ON hdb_catalog.event_log (delivered);
CREATE INDEX ON hdb_catalog.event_log (created_at);

CREATE TABLE hdb_catalog.event_invocation_logs
(
  id TEXT DEFAULT gen_random_uuid() PRIMARY KEY,
  event_id TEXT,
  status INTEGER,
  request JSON,
  response JSON,
  created_at TIMESTAMP DEFAULT NOW(),

  FOREIGN KEY (event_id) REFERENCES hdb_catalog.event_log (id)
);

CREATE INDEX ON hdb_catalog.event_invocation_logs (event_id);

CREATE TABLE hdb_catalog.hdb_function
(

Review comment (suggestion):
```suggestion
  /* when locked IS NULL the event is unlocked and can be processed */
  locked TIMESTAMP,
```

Code after:


CREATE TABLE hdb_catalog.event_triggers
(
  name TEXT PRIMARY KEY,
  type TEXT NOT NULL,
  schema_name TEXT NOT NULL,
  table_name TEXT NOT NULL,
  configuration JSON,
  comment TEXT,
  FOREIGN KEY (schema_name, table_name)
  REFERENCES hdb_catalog.hdb_table(table_schema, table_name) ON UPDATE CASCADE
);

CREATE TABLE hdb_catalog.event_log
(
  id TEXT DEFAULT gen_random_uuid() PRIMARY KEY,
  schema_name TEXT NOT NULL,
  table_name TEXT NOT NULL,
  trigger_name TEXT NOT NULL,
  payload JSONB NOT NULL,
  delivered BOOLEAN NOT NULL DEFAULT FALSE,
  error BOOLEAN NOT NULL DEFAULT FALSE,
  tries INTEGER NOT NULL DEFAULT 0,
  created_at TIMESTAMP DEFAULT NOW(),
  /* when locked IS NULL the event is unlocked and can be processed */
  locked TIMESTAMPTZ,
  next_retry_at TIMESTAMP,
  archived BOOLEAN NOT NULL DEFAULT FALSE
);

CREATE INDEX ON hdb_catalog.event_log (trigger_name);
CREATE INDEX ON hdb_catalog.event_log (locked);
CREATE INDEX ON hdb_catalog.event_log (delivered);
CREATE INDEX ON hdb_catalog.event_log (created_at);

CREATE TABLE hdb_catalog.event_invocation_logs
(
  id TEXT DEFAULT gen_random_uuid() PRIMARY KEY,
  event_id TEXT,
  status INTEGER,
  request JSON,
  response JSON,
  created_at TIMESTAMP DEFAULT NOW(),

  FOREIGN KEY (event_id) REFERENCES hdb_catalog.event_log (id)
);

CREATE INDEX ON hdb_catalog.event_invocation_logs (event_id);

CREATE TABLE hdb_catalog.hdb_function
Repository: hasura/graphql-engine
File: console/src/components/Login/Actions.ts (TypeScript)

Code before:
import Endpoints, { globalCookiePolicy } from '../../Endpoints';
import { UPDATE_DATA_HEADERS } from '../Services/Data/DataActions';
import { saveAdminSecretState } from '../AppState';
import { ADMIN_SECRET_HEADER_KEY, CLI_CONSOLE_MODE } from '../../constants';
import requestAction from '../../utils/requestAction';
import { Dispatch } from '../../types';
import globals from '../../Globals';
// Type deffinition for the verifyLogin Action
type VerifyLoginOptions = {
  adminSecret: string;
  shouldPersist: boolean;
  successCallback: () => void;
  errorCallback: (err: Error) => void;
  dispatch: Dispatch;
};

export const verifyLogin = ({
  adminSecret,
  shouldPersist,
  successCallback,
  errorCallback,
  dispatch,
}: VerifyLoginOptions) => {
  const url = Endpoints.getSchema;
  const requestOptions: RequestInit = {
    credentials: globalCookiePolicy,
    method: 'POST',
    headers: {
      [ADMIN_SECRET_HEADER_KEY]: adminSecret,
      'content-type': 'application/json',
    },
    body: JSON.stringify({
      type: 'select',

Review comment (suggestion):
```suggestion
import globals from '../../Globals';

```

Code after:
import Endpoints, { globalCookiePolicy } from '../../Endpoints';
import { UPDATE_DATA_HEADERS } from '../Services/Data/DataActions';
import { saveAdminSecretState } from '../AppState';
import { ADMIN_SECRET_HEADER_KEY, CLI_CONSOLE_MODE } from '../../constants';
import requestAction from '../../utils/requestAction';
import { Dispatch } from '../../types';
import globals from '../../Globals';

type VerifyLoginOptions = {
  adminSecret: string;
  shouldPersist: boolean;
  successCallback: () => void;
  errorCallback: (err: Error) => void;
  dispatch: Dispatch;
};

export const verifyLogin = ({
  adminSecret,
  shouldPersist,
  successCallback,
  errorCallback,
  dispatch,
}: VerifyLoginOptions) => {
  const url = Endpoints.getSchema;
  const requestOptions: RequestInit = {
    credentials: globalCookiePolicy,
    method: 'POST',
    headers: {
      [ADMIN_SECRET_HEADER_KEY]: adminSecret,
      'content-type': 'application/json',
    },
    body: JSON.stringify({
      type: 'select',
Repository: hasura/graphql-engine
File: console/src/components/Services/Events/Common/Components/EventsTable.tsx (TypeScript)

Code before:
    runQuery,
    columns,
    identifier,
    onCancelEvent,
  } = props;

  const expanderIcon = {
    expander: true,
    Header: '',
    accessor: 'expander',
    Expander: ({ isExpanded }: { isExpanded: boolean }) => {
      return (
        <Button
          color="white"
          size="xs"
          title={isExpanded ? 'Collapse row' : 'Expand row'}
          // This is needed to remove focus on button when clicked (to avoid button style change)
          onMouseDown={e => {
            e.preventDefault();
          }}
        >
          {isExpanded ? (
            <i className="fa fa-expand" />
          ) : (
            <i className="fa fa-compress" />
          )}
        </Button>
      );
    },
  };

  if (rows.length === 0) {
    return <div className={styles.add_mar_top}>No data available</div>;
  }

  const sortedColumns = columns.sort(ordinalColSort);

  let shouldSortColumn = true;

  const sortByColumn = (col: string) => {
    // Remove all the existing order_bys

    const existingColSort = filterState.sorts.find(s => s.column === col);
    if (existingColSort && existingColSort.type === 'asc') {
      runQuery({
        sorts: [makeOrderBy(col, 'desc')],
      });
    } else {
      runQuery({
        sorts: [makeOrderBy(col, 'asc')],
      });

Review comment (suggestion):
```suggestion
          {isExpanded ? (
            <i className="fa fa-compress" />
          ) : (
            <i className="fa fa-expand" />
          )}
```

Code after:
const EventsTable: React.FC<Props> = props => {
  const {
    rows,
    count,
    filterState,
    runQuery,
    columns,
    identifier,
    onCancelEvent,
  } = props;

  if (rows.length === 0) {
    return <div className={styles.add_mar_top}>No data available</div>;
  }

  const sortedColumns = columns.sort(ordinalColSort);

  let shouldSortColumn = true;

  const sortByColumn = (col: string) => {
    // Remove all the existing order_bys

    const existingColSort = filterState.sorts.find(s => s.column === col);
    if (existingColSort && existingColSort.type === 'asc') {
      runQuery({
        sorts: [makeOrderBy(col, 'desc')],
      });
    } else {
      runQuery({
        sorts: [makeOrderBy(col, 'asc')],
      });
    }
  };

  const changePage = (page: number) => {
    if (filterState.offset !== page * filterState.limit) {
      runQuery({
        offset: page * filterState.limit,
      });
    }
  };

  const changePageSize = (size: number) => {
    if (filterState.limit !== size) {
      runQuery({
        limit: size,
      });
    }
  };

  const onCancelHandler = (id: string, scheduledAt: string) => {
Repository: hasura/graphql-engine
File: console/src/components/Services/Events/Common/Components/InvocationLogsTable.tsx (TypeScript)

Code before:
      });
    } else {
      runQuery({
        sorts: [makeOrderBy(col, 'asc')],
      });
    }
  };

  const changePage = (page: number) => {
    if (filterState.offset !== page * filterState.limit) {
      runQuery({
        offset: page * filterState.limit,
      });
    }
  };

  const changePageSize = (size: number) => {
    if (filterState.limit !== size) {
      runQuery({
        limit: size,
      });
    }
  };

  const gridHeadings: any = [
    {
      expander: true,
      Header: '',
      accessor: 'expander',
      Expander: ({ isExpanded }: { isExpanded: boolean }) => {
        return (
          <Button
            color="white"
            size="xs"
            title={isExpanded ? 'Collapse row' : 'Expand row'}
            // This is needed to remove focus on button when clicked (to avoid button style change)
            onMouseDown={e => {
              e.preventDefault();
            }}
          >
            {isExpanded ? (
              <i className="fa fa-expand" />
            ) : (
              <i className="fa fa-compress" />
            )}
          </Button>
        );
      },
    },
  ];


Review comment (refactor):
This is duplicated. Can you move it to some utility file and use both here and in `EventsTable.tsx`?

Code after:
    );
  };

  if (rows.length === 0) {
    return <div className={styles.add_mar_top}>No data available</div>;
  }

  const sortedColumns = columns.sort(ordinalColSort);

  let shouldSortColumn = true;

  const sortByColumn = (col: string) => {
    // Remove all the existing order_bys

    const existingColSort = filterState.sorts.find(s => s.column === col);
    if (existingColSort && existingColSort.type === 'asc') {
      runQuery({
        sorts: [makeOrderBy(col, 'desc')],
      });
    } else {
      runQuery({
        sorts: [makeOrderBy(col, 'asc')],
      });
    }
  };

  const changePage = (page: number) => {
    if (filterState.offset !== page * filterState.limit) {
      runQuery({
        offset: page * filterState.limit,
      });
    }
  };

  const changePageSize = (size: number) => {
    if (filterState.limit !== size) {
      runQuery({
        limit: size,
      });
    }
  };

  const expanderActions: GridHeadingProps = {
    expander: true,
    Header: '',
    accessor: 'expander',
    Expander: ({ isExpanded, viewIndex }) => {
      const row = rows[viewIndex];
      return (
        <>
          {columns.includes('redeliver') && (
Repository: hasura/graphql-engine
File: console/src/components/Services/Events/Common/Components/EventsTable.tsx (TypeScript)

Code before:
import { makeOrderBy } from '../../../../Common/utils/v1QueryUtils';
import { convertDateTimeToLocale } from '../../../../Common/utils/jsUtils';
import {
  getEventStatusIcon,
  getEventDeliveryIcon,
  getExpanderButton,
} from './utils';
import Button from '../../../../Common/Button';

type CancelButtonProps = {
  id: string;
  onClickHandler: (e: React.MouseEvent) => void;
};

const CancelEventButton: React.FC<CancelButtonProps> = ({
  id,
  onClickHandler,
}) => (
  <Button
    key={id}
    className={styles.add_mar_right_small}
    onClick={onClickHandler}
    color="white"
    size="xs"
    title="Cancel Event"
    onMouseDown={(e: React.MouseEvent) => {
      e.preventDefault();
    }}
  >
    <i className="fa fa-close" />
  </Button>
);

interface Props extends FilterTableProps {
  onCancelEvent?: (
    id: string,
    scheduledAt: string,
    onSuccess: () => void
  ) => void;
}

const EventsTable: React.FC<Props> = props => {
  const {
    rows,
    count,
    filterState,
    runQuery,
    columns,
    identifier,
    onCancelEvent,
  } = props;

Review comment (suggestion):
No need for typings here. This will be inferred automatically. 
```suggestion
    onMouseDown={(e) => {
```

Code after:
import { sanitiseRow } from '../../utils';
import { makeOrderBy } from '../../../../Common/utils/v1QueryUtils';
import { convertDateTimeToLocale } from '../../../../Common/utils/jsUtils';
import { getEventStatusIcon, getEventDeliveryIcon } from './utils';
import Button from '../../../../Common/Button';

type CancelButtonProps = {
  id: string;
  onClickHandler: (e: React.MouseEvent) => void;
};

const CancelEventButton: React.FC<CancelButtonProps> = ({
  id,
  onClickHandler,
}) => (
  <Button
    key={id}
    className={styles.add_mar_right_small}
    onClick={onClickHandler}
    color="white"
    size="xs"
    title="Cancel Event"
    onMouseDown={e => {
      e.preventDefault();
    }}
  >
    <i className="fa fa-close" />
  </Button>
);

interface Props extends FilterTableProps {
  onCancelEvent?: (
    id: string,
    scheduledAt: string,
    onSuccess: () => void
  ) => void;
}

const EventsTable: React.FC<Props> = props => {
  const {
    rows,
    count,
    filterState,
    runQuery,
    columns,
    identifier,
    onCancelEvent,
  } = props;

  if (rows.length === 0) {
    return <div className={styles.add_mar_top}>No data available</div>;
Repository: hasura/graphql-engine
File: console/src/components/Services/Events/Common/Components/utils.tsx (TypeScript)

Code before:
    case 'delivered':
      return <CheckIcon title="This event has been delivered" />;
    case 'error':
      return <CrossIcon title="This event failed with an error" />;
    default:
      return null;
  }
};

export const getEventDeliveryIcon = (delivered: boolean) => {
  return delivered ? (
    <CheckIcon title="This event has been delivered" />
  ) : (
    <CrossIcon title="This event has not been delivered" />
  );
};

export const getInvocationLogStatus = (status: number) => {
  return status < 300 ? <CheckIcon /> : <CrossIcon />;
};

export const getExpanderButton = (isExpanded: boolean) => (
  <Button
    color="white"
    size="xs"
    title={isExpanded ? 'Collapse row' : 'Expand row'}
    // This is needed to remove focus on button when clicked (to avoid button style change)
    onMouseDown={(e: React.MouseEvent) => {
      e.preventDefault();
    }}
  >
    {isExpanded ? (
      <i className="fa fa-compress" />
    ) : (
      <i className="fa fa-expand" />
    )}
  </Button>
);


Review comment (suggestion):
There's an _expand_ icon for collapsing and _collapse_ icon for expanding. 
<img width="300" alt="Screenshot 2020-09-14 at 22 45 22" src="https://user-images.githubusercontent.com/9019397/93136314-fb250700-f6db-11ea-9970-c1054ebb20bf.png">
<img width="203" alt="Screenshot 2020-09-14 at 22 45 36" src="https://user-images.githubusercontent.com/9019397/93136326-037d4200-f6dc-11ea-8a6d-6ab670ed8026.png">






Code after:
import React from 'react';
import CheckIcon from '../../../../Common/Icons/Check';
import CrossIcon from '../../../../Common/Icons/Cross';
import ClockIcon from '../../../../Common/Icons/Clock';
import Skull from '../../../../Common/Icons/Invalid';

export const getEventStatusIcon = (status: string) => {
  switch (status) {
    case 'scheduled':
      return <ClockIcon title="This event has been scheduled" />;
    case 'dead':
      return <Skull title="This event is dead and will never be delivered" />;
    case 'delivered':
      return <CheckIcon title="This event has been delivered" />;
    case 'error':
      return <CrossIcon title="This event failed with an error" />;
    default:
      return null;
  }
};

export const getEventDeliveryIcon = (delivered: boolean) => {
  return delivered ? (
    <CheckIcon title="This event has been delivered" />
  ) : (
    <CrossIcon title="This event has not been delivered" />
  );
};

export const getInvocationLogStatus = (status: number) => {
  return status < 300 ? <CheckIcon /> : <CrossIcon />;
};