text: export const preferJsonbToJson = {
    name: 'prefer-jsonb-to-json',
    docs: {
      description: 'Prefer JSONB to JSON types',
      url: '...',
    },
    process({ schemaObject, report }) {
      const validator =
        ({ name: tableName }) =>
        ({ name: columnName, type }) => {
          if (type === 'json') {
            report({
              rule: this.name,
              identifier: `${schemaObject.name}.${tableName}.${columnName}`,
              message: 'Prefer JSONB to JSON types',
              suggestedMigration: `ALTER TABLE "${schemaObject.name}"."${tableName}" ALTER COLUMN "${columnName}" TYPE JSONB;`,
            });
          }
        };
      schemaObject.tables.forEach((table) =>
        table.columns.forEach(validator(table))
      );
    },
  };
  
  export const preferTextToVarchar = {
    name: 'prefer-text-to-varchar',
    docs: {
      description: 'Prefer the text type over varchar',
      url: '...',
    },
    process({ schemaObject, report }) {
      const validator =
        ({ name: tableName }) =>
        ({ name: columnName, type }) => {
          if (type.startsWith('varchar')) {
            report({
              rule: this.name,
              identifier: `${schemaObject.name}.${tableName}.${columnName}`,
              message: `Prefer text to ${type} types`,
              suggestedMigration: `ALTER TABLE "${schemaObject.name}"."${tableName}" ALTER COLUMN "${columnName}" TYPE TEXT;`,
            });
          }
        };
      schemaObject.tables.forEach((table) =>
        table.columns.forEach(validator(table))
      );
    },
  };
  
  export const preferTimestamptz = {
    name: 'prefer-timestamptz-to-timestamp',
    docs: {
      description:
        'Prefer TIMESTAMPTZ to type TIMESTAMP because when you insert a value into a timestamptz column, PostgreSQL converts the timestamptz value into a UTC value and stores the UTC value in the table,\n' +
        'and when you query timestamptz from the database, PostgreSQL converts the UTC value back to the time value of the timezone set by the database server, the user, or the current database connection',
      url: 'https://www.postgresqltutorial.com/postgresql-timestamp/',
    },
    process({ schemaObject, report }) {
      const validator =
        ({ name: tableName }) =>
        ({ name: columnName, type }) => {
          if (type === 'timestamp') {
            report({
              rule: this.name,
              identifier: `${schemaObject.name}.${tableName}.${columnName}`,
              message: 'Prefer TIMESTAMPTZ to type TIMESTAMP',
              suggestedMigration: `ALTER TABLE "${schemaObject.name}"."${tableName}" ALTER COLUMN "${columnName}" TYPE TIMESTAMPTZ;`,
            });
          }
        };
      schemaObject.tables.forEach((table) =>
        table.columns.forEach(validator(table))
      );
    },
  };
  
  export const preferIdentity = {
    name: 'prefer-identity-to-serial',
    docs: {
      description:
        'The serial types have some weird behaviors that make schema, dependency, and permission management unnecessarily cumbersome.',
      url: 'https://www.2ndquadrant.com/en/blog/postgresql-10-identity-columns/',
    },
    process({ schemaObject, report }) {
      const validator =
        ({ name: tableName }) =>
        ({ name: columnName, rawInfo, defaultValue }) => {
          if (
            rawInfo.is_identity === 'NO' &&
            defaultValue !== null &&
            defaultValue.indexOf('nextval') >= 0
          ) {
            let sequenceName = defaultValue.match("'(.*)'")[1];
            sequenceName = sequenceName.replace(/"/g, '');
  
            report({
              rule: this.name,
              identifier: `${schemaObject.name}.${tableName}.${columnName}`,
              message: 'Prefer IDENTITY to type SERIAL',
              suggestedMigration: `ALTER TABLE "${schemaObject.name}"."${tableName}" ALTER "${columnName}" DROP DEFAULT;
  DROP SEQUENCE "schema"."${sequenceName}";
  ALTER TABLE "${schemaObject.name}"."${tableName}" ALTER "${columnName}" ADD GENERATED BY DEFAULT AS IDENTITY;
  SELECT setval('"${sequenceName}"', max("${columnName}")) FROM "schema"."${tableName}";`,
            });
          }
        };
      schemaObject.tables.forEach((table) =>
        table.columns.forEach(validator(table))
      );
    },
  };
  