pg-dump2insert icon indicating copy to clipboard operation
pg-dump2insert copied to clipboard

convert a dump with insert instructions to copy

Open insinfo opened this issue 1 year ago • 2 comments

@freddez How to do the opposite of this, I need a tool that does the opposite, convert a dump with insert instructions to copy instructions, as I have a very large dump with insert instructions that takes 2 DAYS to restore and I need to convert it to copy instructions which is much faster to restore

insinfo avatar Sep 18 '24 12:09 insinfo

Sorry, I have no plan for that

freddez avatar Sep 23 '24 12:09 freddez

I'm trying to do this in dart

import 'dart:io';
import 'dart:convert';


//dart .\bin\pg_dump_converter.dart dart_test.sql dart_test_copy.sql

void main(List<String> arguments) async {
  if (arguments.length != 2) {
    print('Uso: dart pg_dump_converter.dart <arquivo_entrada> <arquivo_saida>');
    exit(1);
  }

  String inputFile = arguments[0];
  String outputFile = arguments[1];

  await convertInsertToCopy(inputFile, outputFile);
  print('Conversão concluída. Resultado salvo em $outputFile');
}

Future<void> convertInsertToCopy(String inputFile, String outputFile) async {
  int lineCount = 0;
  try {
    final inFile = File(inputFile);
    final outFile = File(outputFile);

    if (!await inFile.exists()) {
      throw Exception('Arquivo de entrada não existe.');
    }

    final regex = RegExp(r"INSERT INTO (.+) \((.+)\) VALUES \((.+)\);");
    String tableName = '';
    String fields = '';
    bool copyCommandWritten = false;

    final sink = outFile.openWrite();
    int matchCount = 0;

    await for (var line in inFile
        .openRead()
        .transform(utf8.decoder)
        .transform(LineSplitter())) {
      final match = regex.firstMatch(line);
      bool gravaFimCopy = false;

      if (match != null) {
        matchCount = matchCount + 1;
        gravaFimCopy = false;

        tableName = match.group(1) ?? '';
        fields = match.group(2) ?? '';
        String valuesMatch = match.group(3) ?? '';

        if (!copyCommandWritten) {
          // Escreve o comando COPY no início da primeira correspondência
          sink.writeln('COPY $tableName ($fields) FROM stdin;');
          copyCommandWritten = true;
        }

        final valuesWithCotes = valuesMatch.split(',');
        final values = <String>[];
        // Remove aspas dos valores e separa por vírgula
        for (var val in valuesWithCotes) {
          var v = val.trim();
           // print('lineCount $lineCount | v $v');
          if (v.startsWith("'") && v.endsWith("'") && v.length > 1) {
            if (v != "''") {
              //print('dentro | v $v');
              // Remove aspas simples
              v = v.substring(1, v.length - 1);
              
            } else {
              v = '';
            }
          } else if (v == 'NULL') {
            v = '\\N';
          }
          // Substitui aspas duplas por aspas simples
          values.add(v.replaceAll("''", "'"));
        }
        // Escreve os valores formatados no arquivo
        sink.writeln(values.join('\t'));
      } else {
        if (matchCount > 0) {
          gravaFimCopy = true;
          copyCommandWritten = false;
          matchCount = 0;
        }

        if (gravaFimCopy) {
          gravaFimCopy = false;
          sink.writeln('\\.');
        }
        // Mantém qualquer linha que não corresponda ao padrão INSERT
        sink.writeln(line);
      }
      //print('lineCount $lineCount');
      lineCount++;
    }
    await sink.flush();
    await sink.close();
  } catch (e, s) {
    throw Exception('Erro durante a conversão linha: $lineCount: $e $s');
  }
}

insinfo avatar Sep 23 '24 19:09 insinfo