diff --git a/.gitignore b/.gitignore index ea61e09..24d6437 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1 @@ /target/ -/.idea/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..b68384b --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,30 @@ +image: maven:3.6.3-jdk-8 + +stages: + - test + - build + +include: + - template: Security/SAST.gitlab-ci.yml + +build: + stage: build + script: + - time mvn package appassembler:assemble -D skipTests + - mv target/dbgit dbgit + only: + refs: + - master + artifacts: + expire_in: never + paths: + - dbgit +test: + stage: test + script: + - time mvn test + allow_failure: true + +cache: + paths: + - .m2/repository diff --git a/.rultor.yml b/.rultor.yml new file mode 100644 index 0000000..54df89d --- /dev/null +++ b/.rultor.yml @@ -0,0 +1,16 @@ +env: + MAVEN_OPTS: "-XX:MaxPermSize=256m -Xmx1g" +assets: + pgSecret.txt: rocket-3/dbgit-test#pgSecret.txt + gitSecret.txt: rocket-3/dbgit-test#gitSecret.txt +install: |- + java -version --batch-mode + mvn -version --batch-mode + mvn clean install package appassembler:assemble -D skipTests --batch-mode --quiet + chmod u+r+x target/dbgit/bin/dbgit +merge: + script: |- + mvn test -Dtest=${tests:-'*selfTest,*DbGitIntegrationTestBasic*'} --batch-mode +deploy: + script: |- + mvn test -Dtest=${tests:-'*selfTest,*DbGitIntegrationTestBasic*'} --batch-mode diff --git a/pom.xml b/pom.xml index 5d3197f..d0efc3f 100644 --- a/pom.xml +++ b/pom.xml @@ -8,6 +8,12 @@ jar + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.2 + + org.apache.maven.plugins @@ -68,7 +74,23 @@ + + + false + ${project.basedir}/src/main/resources + + logback-test.xml + + + + + + ${project.basedir}/src/main/resources/ + + logback.xml + + ${project.basedir}/src/main/resources/scripts ${project.build.directory}/dbgit @@ -98,8 +120,15 @@ - ${project.basedir}/src/main/resources - ${project.build.directory}/dbgit + ${project.basedir}/src/main/resources/example + ${project.build.directory}/dbgit/example + + .dblink + + + + ${project.basedir}/src/main/resources/ + ${project.build.directory}/dbgit/ dbgitconfig @@ -117,14 +146,6 @@ - - - junit - junit - 4.12 - test - - @@ -195,6 +216,11 @@ 1.4 + + org.junit.jupiter + junit-jupiter + 5.7.2 + @@ -230,12 +256,12 @@ - com.oracle.jdbc + com.oracle.ojdbc ojdbc8 - 18.3.0.0 + 19.3.0.0 - + com.microsoft.sqlserver mssql-jdbc 7.0.0.jre8 @@ -246,6 +272,12 @@ jsr305 3.0.0 + + org.junit.platform + junit-platform-commons + 1.7.0 + compile + diff --git a/src/main/java/de/siegmar/fastcsv/reader/CsvContainer.java b/src/main/java/de/siegmar/fastcsv/reader/CsvContainer.java new file mode 100644 index 0000000..e638e0a --- /dev/null +++ b/src/main/java/de/siegmar/fastcsv/reader/CsvContainer.java @@ -0,0 +1,76 @@ +/* + * Copyright 2015 Oliver Siegmar + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package de.siegmar.fastcsv.reader; + +import java.util.Collections; +import java.util.List; + +/** + * Class for holding a complete CSV file. + * + * @author Oliver Siegmar + */ +public final class CsvContainer { + + private final List header; + private final List rows; + + CsvContainer(final List header, final List rows) { + this.header = header; + this.rows = rows; + } + + /** + * Returns the number of rows in this container. + * + * @return the number of rows in this container + */ + public int getRowCount() { + return rows.size(); + } + + /** + * Returns the header row - might be {@code null} if no header exists. + * The returned list is unmodifiable. + * + * @return the header row - might be {@code null} if no header exists + */ + public List getHeader() { + return header; + } + + /** + * Returns a CsvRow by its index (starting with 0). + * + * @param index index of the row to return + * @return the row by its index + * @throws IndexOutOfBoundsException if index is out of range + */ + public CsvRow getRow(final int index) { + return rows.get(index); + } + + /** + * Returns an unmodifiable list of rows. + * + * @return an unmodifiable list of rows + */ + public List getRows() { + return Collections.unmodifiableList(rows); + } + +} diff --git a/src/main/java/de/siegmar/fastcsv/reader/CsvParser.java b/src/main/java/de/siegmar/fastcsv/reader/CsvParser.java new file mode 100644 index 0000000..19bb1b4 --- /dev/null +++ b/src/main/java/de/siegmar/fastcsv/reader/CsvParser.java @@ -0,0 +1,144 @@ +/* + * Copyright 2015 Oliver Siegmar + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package de.siegmar.fastcsv.reader; + +import java.io.Closeable; +import java.io.IOException; +import java.io.Reader; +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * This class is responsible for parsing CSV data from the passed-in Reader. + * + * @author Oliver Siegmar + */ +public final class CsvParser implements Closeable { + + private final RowReader rowReader; + private final boolean containsHeader; + private final boolean skipEmptyRows; + private final boolean errorOnDifferentFieldCount; + + private Map headerMap; + private List headerList; + private long lineNo; + private int firstLineFieldCount = -1; + + CsvParser(final Reader reader, final char fieldSeparator, final char textDelimiter, + final boolean containsHeader, final boolean skipEmptyRows, + final boolean errorOnDifferentFieldCount) { + + rowReader = new RowReader(reader, fieldSeparator, textDelimiter); + this.containsHeader = containsHeader; + this.skipEmptyRows = skipEmptyRows; + this.errorOnDifferentFieldCount = errorOnDifferentFieldCount; + } + + /** + * Returns the header fields - {@code null} if no header exists. The returned list is + * unmodifiable. Use {@link CsvReader#setContainsHeader(boolean)} to enable header parsing. + * Also note, that the header is only available after first invocation of + * {@link #nextRow()}. + * + * @return the header fields + * @throws IllegalStateException if header parsing is not enabled or {@link #nextRow()} wasn't + * called before. + */ + public List getHeader() { + if (!containsHeader) { + throw new IllegalStateException("No header available - header parsing is disabled"); + } + if (lineNo == 0) { + throw new IllegalStateException("No header available - call nextRow() first"); + } + return headerList; + } + + /** + * Reads a complete {@link CsvRow} that might be made up of multiple lines in the underlying + * CSV file. + * + * @return a CsvRow or {@code null} if end of file reached + * @throws IOException if an error occurred while reading data + */ + public CsvRow nextRow() throws IOException { + while (!rowReader.isFinished()) { + final long startingLineNo = lineNo + 1; + final RowReader.Line line = rowReader.readLine(); + final String[] currentFields = line.getFields(); + lineNo += line.getLines(); + + final int fieldCount = currentFields.length; + + // reached end of data in a new line? + if (fieldCount == 0) { + break; + } + + // skip empty rows + if (skipEmptyRows && fieldCount == 1 && currentFields[0].isEmpty()) { + continue; + } + + // check the field count consistency on every row + if (errorOnDifferentFieldCount) { + if (firstLineFieldCount == -1) { + firstLineFieldCount = fieldCount; + } else if (fieldCount != firstLineFieldCount) { + throw new IOException( + String.format("Line %d has %d fields, but first line has %d fields", + lineNo, fieldCount, firstLineFieldCount)); + } + } + + final List fieldList = Arrays.asList(currentFields); + + // initialize header + if (containsHeader && headerList == null) { + initHeader(fieldList); + continue; + } + + return new CsvRow(startingLineNo, headerMap, fieldList); + } + + return null; + } + + private void initHeader(final List currentFields) { + headerList = Collections.unmodifiableList(currentFields); + + final Map localHeaderMap = new LinkedHashMap<>(currentFields.size()); + for (int i = 0; i < currentFields.size(); i++) { + final String field = currentFields.get(i); + if (field != null && !field.isEmpty() && !localHeaderMap.containsKey(field)) { + localHeaderMap.put(field, i); + } + } + headerMap = Collections.unmodifiableMap(localHeaderMap); + } + + @Override + public void close() throws IOException { + rowReader.close(); + } + +} diff --git a/src/main/java/de/siegmar/fastcsv/reader/CsvReader.java b/src/main/java/de/siegmar/fastcsv/reader/CsvReader.java new file mode 100644 index 0000000..9e929b2 --- /dev/null +++ b/src/main/java/de/siegmar/fastcsv/reader/CsvReader.java @@ -0,0 +1,206 @@ +/* + * Copyright 2015 Oliver Siegmar + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package de.siegmar.fastcsv.reader; + +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * This is the main class for reading CSV data. + * + * @author Oliver Siegmar + */ +public final class CsvReader { + + /** + * Field separator character (default: ',' - comma). + */ + private char fieldSeparator = ','; + + /** + * Text delimiter character (default: '"' - double quotes). + */ + private char textDelimiter = '"'; + + /** + * Read first line as header line? (default: false). + */ + private boolean containsHeader; + + /** + * Skip empty rows? (default: true) + */ + private boolean skipEmptyRows = true; + + /** + * Throw an exception if CSV data contains different field count? (default: false). + */ + private boolean errorOnDifferentFieldCount; + + /** + * Sets the field separator character (default: ',' - comma). + */ + public void setFieldSeparator(final char fieldSeparator) { + this.fieldSeparator = fieldSeparator; + } + + /** + * Sets the text delimiter character (default: '"' - double quotes). + */ + public void setTextDelimiter(final char textDelimiter) { + this.textDelimiter = textDelimiter; + } + + /** + * Specifies if the first line should be the header (default: false). + */ + public void setContainsHeader(final boolean containsHeader) { + this.containsHeader = containsHeader; + } + + /** + * Specifies if empty rows should be skipped (default: true). + */ + public void setSkipEmptyRows(final boolean skipEmptyRows) { + this.skipEmptyRows = skipEmptyRows; + } + + /** + * Specifies if an exception should be thrown, if CSV data contains different field count + * (default: false). + */ + public void setErrorOnDifferentFieldCount(final boolean errorOnDifferentFieldCount) { + this.errorOnDifferentFieldCount = errorOnDifferentFieldCount; + } + + /** + * Reads an entire file and returns a CsvContainer containing the data. + * + * @param file the file to read data from. + * @param charset the character set to use - must not be {@code null}. + * @return the entire file's data - never {@code null}. + * @throws IOException if an I/O error occurs. + */ + public CsvContainer read(final File file, final Charset charset) throws IOException { + return read( + Objects.requireNonNull(file.toPath(), "file must not be null"), + Objects.requireNonNull(charset, "charset must not be null") + ); + } + + /** + * Reads an entire file and returns a CsvContainer containing the data. + * + * @param path the file to read data from. + * @param charset the character set to use - must not be {@code null}. + * @return the entire file's data - never {@code null}. + * @throws IOException if an I/O error occurs. + */ + public CsvContainer read(final Path path, final Charset charset) throws IOException { + Objects.requireNonNull(path, "path must not be null"); + Objects.requireNonNull(charset, "charset must not be null"); + try (final Reader reader = newPathReader(path, charset)) { + return read(reader); + } + } + + /** + * Reads from the provided reader until the end and returns a CsvContainer containing the data. + * + * This library uses built-in buffering, so you do not need to pass in a buffered Reader + * implementation such as {@link java.io.BufferedReader}. + * Performance may be even likely better if you do not. + * + * @param reader the data source to read from. + * @return the entire file's data - never {@code null}. + * @throws IOException if an I/O error occurs. + */ + public CsvContainer read(final Reader reader) throws IOException { + final CsvParser csvParser = + parse(Objects.requireNonNull(reader, "reader must not be null")); + + final List rows = new ArrayList<>(); + CsvRow csvRow; + while ((csvRow = csvParser.nextRow()) != null) { + rows.add(csvRow); + } + + final List header = containsHeader ? csvParser.getHeader() : null; + return new CsvContainer(header, rows); + } + + /** + * Constructs a new {@link CsvParser} for the specified arguments. + * + * @param path the file to read data from. + * @param charset the character set to use - must not be {@code null}. + * @return a new CsvParser - never {@code null}. + * @throws IOException if an I/O error occurs. + */ + public CsvParser parse(final Path path, final Charset charset) throws IOException { + return parse(newPathReader( + Objects.requireNonNull(path, "path must not be null"), + Objects.requireNonNull(charset, "charset must not be null") + )); + } + + /** + * Constructs a new {@link CsvParser} for the specified arguments. + * + * @param file the file to read data from. + * @param charset the character set to use - must not be {@code null}. + * @return a new CsvParser - never {@code null}. + * @throws IOException if an I/O error occurs. + */ + public CsvParser parse(final File file, final Charset charset) throws IOException { + return parse( + Objects.requireNonNull(file, "file must not be null").toPath(), + Objects.requireNonNull(charset, "charset must not be null") + ); + } + + /** + * Constructs a new {@link CsvParser} for the specified arguments. + * + * This library uses built-in buffering, so you do not need to pass in a buffered Reader + * implementation such as {@link java.io.BufferedReader}. + * Performance may be even likely better if you do not. + * + * @param reader the data source to read from. + * @return a new CsvParser - never {@code null}. + * @throws IOException if an I/O error occurs. + */ + public CsvParser parse(final Reader reader) throws IOException { + return new CsvParser(Objects.requireNonNull(reader, "reader must not be null"), + fieldSeparator, textDelimiter, containsHeader, skipEmptyRows, + errorOnDifferentFieldCount); + } + + private static Reader newPathReader(final Path path, final Charset charset) throws IOException { + return new InputStreamReader(Files.newInputStream(path, StandardOpenOption.READ), charset); + } + +} diff --git a/src/main/java/de/siegmar/fastcsv/reader/CsvRow.java b/src/main/java/de/siegmar/fastcsv/reader/CsvRow.java new file mode 100644 index 0000000..cc6e076 --- /dev/null +++ b/src/main/java/de/siegmar/fastcsv/reader/CsvRow.java @@ -0,0 +1,165 @@ +/* + * Copyright 2015 Oliver Siegmar + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package de.siegmar.fastcsv.reader; + +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * This class represents a single CSV row. + * + * @author Oliver Siegmar + */ +public final class CsvRow { + + /** + * The original line number (empty lines may be skipped). + */ + private final long originalLineNumber; + + private final Map headerMap; + private final List fields; + + CsvRow(final long originalLineNumber, final Map headerMap, + final List fields) { + + this.originalLineNumber = originalLineNumber; + this.headerMap = headerMap; + this.fields = fields; + } + + /** + * Returns the original line number (starting with 1). On multi-line rows this is the starting + * line number. Empty lines could be skipped via {@link CsvReader#setSkipEmptyRows(boolean)}. + * + * @return the original line number + */ + public long getOriginalLineNumber() { + return originalLineNumber; + } + + /** + * Gets a field value by its index (starting with 0). + * + * @param index index of the field to return + * @return field value + * @throws IndexOutOfBoundsException if index is out of range + */ + public String getField(final int index) { + return fields.get(index); + } + + /** + * Gets a field value by its name. + * + * @param name field name + * @return field value, {@code null} if this row has no such field + * @throws IllegalStateException if CSV is read without headers - + * see {@link CsvReader#containsHeader} + */ + public String getField(final String name) { + if (headerMap == null) { + throw new IllegalStateException("No header available"); + } + + final Integer col = headerMap.get(name); + if (col != null && col < fields.size()) { + return fields.get(col); + } + + return null; + } + + /** + * Gets all fields of this row as an unmodifiable List. + * + * @return all fields of this row + */ + public List getFields() { + return Collections.unmodifiableList(fields); + } + + /** + * Gets an unmodifiable map of header names and field values of this row. + * + * The map will always contain all header names - even if their value is {@code null}. + * + * @return an unmodifiable map of header names and field values of this row + * @throws IllegalStateException if CSV is read without headers - see + * {@link CsvReader#containsHeader} + */ + public Map getFieldMap() { + if (headerMap == null) { + throw new IllegalStateException("No header available"); + } + + final Map fieldMap = new LinkedHashMap<>(headerMap.size()); + for (final Map.Entry header : headerMap.entrySet()) { + final String key = header.getKey(); + final Integer col = headerMap.get(key); + final String val = col != null && col < fields.size() ? fields.get(col) : null; + fieldMap.put(key, val); + } + + return Collections.unmodifiableMap(fieldMap); + } + + /** + * Gets the number of fields of this row. + * + * @return the number of fields of this row + */ + public int getFieldCount() { + return fields.size(); + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("CsvRow{"); + sb.append("originalLineNumber="); + sb.append(originalLineNumber); + sb.append(", "); + + sb.append("fields="); + if (headerMap != null) { + sb.append('{'); + for (final Iterator> it = + getFieldMap().entrySet().iterator(); it.hasNext();) { + + final Map.Entry entry = it.next(); + sb.append(entry.getKey()); + sb.append('='); + if (entry.getValue() != null) { + sb.append(entry.getValue()); + } + if (it.hasNext()) { + sb.append(", "); + } + } + sb.append('}'); + } else { + sb.append(fields.toString()); + } + + sb.append('}'); + return sb.toString(); + } + +} diff --git a/src/main/java/de/siegmar/fastcsv/reader/ReusableStringBuilder.java b/src/main/java/de/siegmar/fastcsv/reader/ReusableStringBuilder.java new file mode 100644 index 0000000..1938a6e --- /dev/null +++ b/src/main/java/de/siegmar/fastcsv/reader/ReusableStringBuilder.java @@ -0,0 +1,90 @@ +/* + * Copyright 2015 Oliver Siegmar + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package de.siegmar.fastcsv.reader; + +import java.util.Arrays; + +/** + * Resettable / reusable and thus high performance replacement for StringBuilder. + * + * This class is intended for internal use only. + * + * @author Oliver Siegmar + */ + +final class ReusableStringBuilder { + + private static final String EMPTY = ""; + + private char[] buf; + private int pos; + + /** + * Initializes the buffer with the specified capacity. + * + * @param initialCapacity the initial buffer capacity. + */ + ReusableStringBuilder(final int initialCapacity) { + buf = new char[initialCapacity]; + } + + /** + * Appends a character to the buffer, resizing the buffer if needed. + * + * @param c the character to add to the buffer + */ + public void append(final char c) { + if (pos == buf.length) { + buf = Arrays.copyOf(buf, buf.length * 2); + } + buf[pos++] = c; + } + + public void append(final char[] src, final int srcPos, final int length) { + if (pos + length > buf.length) { + int newSize = buf.length * 2; + while (pos + length > newSize) { + newSize *= 2; + } + buf = Arrays.copyOf(buf, newSize); + } + System.arraycopy(src, srcPos, buf, pos, length); + pos += length; + } + + /** + * @return {@code true} if the buffer contains content + */ + public boolean hasContent() { + return pos > 0; + } + + /** + * Returns the string representation of the buffer and resets the buffer. + * + * @return the string representation of the buffer + */ + public String toStringAndReset() { + if (pos > 0) { + final String s = new String(buf, 0, pos); + pos = 0; + return s; + } + return EMPTY; + } + +} diff --git a/src/main/java/de/siegmar/fastcsv/reader/RowReader.java b/src/main/java/de/siegmar/fastcsv/reader/RowReader.java new file mode 100644 index 0000000..a7a2265 --- /dev/null +++ b/src/main/java/de/siegmar/fastcsv/reader/RowReader.java @@ -0,0 +1,219 @@ +/* + * Copyright 2018 Oliver Siegmar + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package de.siegmar.fastcsv.reader; + +import java.io.Closeable; +import java.io.IOException; +import java.io.Reader; +import java.util.Arrays; + +final class RowReader implements Closeable { + + private static final char LF = '\n'; + private static final char CR = '\r'; + private static final int BUFFER_SIZE = 8192; + + private static final int FIELD_MODE_RESET = 0; + private static final int FIELD_MODE_QUOTED = 1; + private static final int FIELD_MODE_NON_QUOTED = 2; + private static final int FIELD_MODE_QUOTE_ON = 4; + private static final int FIELD_MODE_QUOTED_EMPTY = 8; + + private final Reader reader; + private final char fieldSeparator; + private final char textDelimiter; + private final char[] buf = new char[BUFFER_SIZE]; + private final Line line = new Line(32); + private final ReusableStringBuilder currentField = new ReusableStringBuilder(512); + private int bufPos; + private int bufLen; + private int prevChar = -1; + private int copyStart; + private boolean finished; + + RowReader(final Reader reader, final char fieldSeparator, final char textDelimiter) { + this.reader = reader; + this.fieldSeparator = fieldSeparator; + this.textDelimiter = textDelimiter; + } + + /* + * ugly, performance optimized code begins + */ + Line readLine() throws IOException { + // get fields local for higher performance + final Line localLine = line.reset(); + final ReusableStringBuilder localCurrentField = currentField; + final char[] localBuf = buf; + int localBufPos = bufPos; + int localPrevChar = prevChar; + int localCopyStart = copyStart; + + int copyLen = 0; + int fieldMode = FIELD_MODE_RESET; + int lines = 1; + + while (true) { + if (bufLen == localBufPos) { + // end of buffer + + if (copyLen > 0) { + localCurrentField.append(localBuf, localCopyStart, copyLen); + } + bufLen = reader.read(localBuf, 0, localBuf.length); + + if (bufLen < 0) { + // end of data + finished = true; + + if (localPrevChar == fieldSeparator + || (fieldMode & FIELD_MODE_QUOTED_EMPTY) == FIELD_MODE_QUOTED_EMPTY + || localCurrentField.hasContent() + ) { + localLine.addField(localCurrentField.toStringAndReset()); + } + + break; + } + + localCopyStart = localBufPos = copyLen = 0; + } + + final char c = localBuf[localBufPos++]; + + if ((fieldMode & FIELD_MODE_QUOTE_ON) != 0) { + if (c == textDelimiter) { + // End of quoted text + fieldMode &= ~FIELD_MODE_QUOTE_ON; + if (copyLen > 0) { + localCurrentField.append(localBuf, localCopyStart, copyLen); + copyLen = 0; + } else { + fieldMode |= FIELD_MODE_QUOTED_EMPTY; + } + localCopyStart = localBufPos; + } else { + if (c == CR || c == LF && prevChar != CR) { + lines++; + } + copyLen++; + } + } else { + if (c == fieldSeparator) { + if (copyLen > 0) { + localCurrentField.append(localBuf, localCopyStart, copyLen); + copyLen = 0; + } + localLine.addField(localCurrentField.toStringAndReset()); + localCopyStart = localBufPos; + fieldMode = FIELD_MODE_RESET; + } else if (c == textDelimiter && (fieldMode & FIELD_MODE_NON_QUOTED) == 0) { + // Quoted text starts + fieldMode = FIELD_MODE_QUOTED | FIELD_MODE_QUOTE_ON; + + if (localPrevChar == textDelimiter) { + // escaped quote + copyLen++; + } else { + localCopyStart = localBufPos; + } + } else if (c == CR) { + if (copyLen > 0) { + localCurrentField.append(localBuf, localCopyStart, copyLen); + } + localLine.addField(localCurrentField.toStringAndReset()); + localPrevChar = c; + localCopyStart = localBufPos; + break; + } else if (c == LF) { + if (localPrevChar != CR) { + if (copyLen > 0) { + localCurrentField.append(localBuf, localCopyStart, copyLen); + } + localLine.addField(localCurrentField.toStringAndReset()); + localPrevChar = c; + localCopyStart = localBufPos; + break; + } + localCopyStart = localBufPos; + } else { + copyLen++; + if (fieldMode == FIELD_MODE_RESET) { + fieldMode = FIELD_MODE_NON_QUOTED; + } + } + } + + localPrevChar = c; + } + + // restore fields + bufPos = localBufPos; + prevChar = localPrevChar; + copyStart = localCopyStart; + + localLine.setLines(lines); + return localLine; + } + + @Override + public void close() throws IOException { + reader.close(); + } + + public boolean isFinished() { + return finished; + } + + static final class Line { + + private String[] fields; + private int linePos; + private int lines; + + Line(final int initialCapacity) { + fields = new String[initialCapacity]; + } + + Line reset() { + linePos = 0; + lines = 1; + return this; + } + + void addField(final String field) { + if (linePos == fields.length) { + fields = Arrays.copyOf(fields, fields.length * 2); + } + fields[linePos++] = field; + } + + String[] getFields() { + return Arrays.copyOf(fields, linePos); + } + + int getLines() { + return lines; + } + + void setLines(final int lines) { + this.lines = lines; + } + + } + +} diff --git a/src/main/java/de/siegmar/fastcsv/writer/CsvAppender.java b/src/main/java/de/siegmar/fastcsv/writer/CsvAppender.java new file mode 100644 index 0000000..b9401d9 --- /dev/null +++ b/src/main/java/de/siegmar/fastcsv/writer/CsvAppender.java @@ -0,0 +1,146 @@ +/* + * Copyright 2015 Oliver Siegmar + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package de.siegmar.fastcsv.writer; + +import java.io.Closeable; +import java.io.Flushable; +import java.io.IOException; +import java.io.Writer; + +/** + * This is the main class for writing CSV data. + * + * @author Oliver Siegmar + */ +public final class CsvAppender implements Closeable, Flushable { + + private static final char LF = '\n'; + private static final char CR = '\r'; + + private final Writer writer; + private final char fieldSeparator; + private final char textDelimiter; + private final boolean alwaysDelimitText; + private final char[] lineDelimiter; + + private boolean newline = true; + + CsvAppender(final Writer writer, final char fieldSeparator, final char textDelimiter, + final boolean alwaysDelimitText, final char[] lineDelimiter) { + this.writer = new FastBufferedWriter(writer); + this.fieldSeparator = fieldSeparator; + this.textDelimiter = textDelimiter; + this.alwaysDelimitText = alwaysDelimitText; + this.lineDelimiter = lineDelimiter; + } + + /** + * Appends a field to the current row. Automatically adds field separator and text delimiters + * as required. + * + * @param value the field to append ({@code null} is handled as empty string) + * @throws IOException if a write error occurs + */ + public void appendField(final String value) throws IOException { + if (!newline) { + writer.write(fieldSeparator); + } else { + newline = false; + } + + if (value == null) { + if (alwaysDelimitText) { + writer.write(textDelimiter); + writer.write(textDelimiter); + } + return; + } + + boolean needsTextDelimiter = alwaysDelimitText; + boolean containsTextDelimiter = false; + + for (int i = 0; i < value.length(); i++) { + final char c = value.charAt(i); + if (c == textDelimiter) { + containsTextDelimiter = needsTextDelimiter = true; + break; + } else if (c == fieldSeparator || c == LF || c == CR) { + needsTextDelimiter = true; + } + } + + if (needsTextDelimiter) { + writer.write(textDelimiter); + } + + if (containsTextDelimiter) { + for (int i = 0; i < value.length(); i++) { + final char c = value.charAt(i); + if (c == textDelimiter) { + writer.write(textDelimiter); + } + writer.write(c); + } + } else { + writer.write(value); + } + + if (needsTextDelimiter) { + writer.write(textDelimiter); + } + } + + /** + * Appends a complete line - one or more fields and new line character(s) at the end. + * + * @param values the fields to append ({@code null} values are handled as empty strings) + * @throws IOException if a write error occurs + */ + public void appendLine(final String... values) throws IOException { + for (final String value : values) { + appendField(value); + } + endLine(); + } + + /** + * Appends new line character(s) to the current line. + * + * @throws IOException if a write error occurs + */ + public void endLine() throws IOException { + writer.write(lineDelimiter); + newline = true; + } + + /** + * {@inheritDoc} + */ + @Override + public void close() throws IOException { + writer.close(); + } + + /** + * {@inheritDoc} + */ + @Override + public void flush() throws IOException { + writer.flush(); + } + +} diff --git a/src/main/java/de/siegmar/fastcsv/writer/CsvWriter.java b/src/main/java/de/siegmar/fastcsv/writer/CsvWriter.java new file mode 100644 index 0000000..da1482d --- /dev/null +++ b/src/main/java/de/siegmar/fastcsv/writer/CsvWriter.java @@ -0,0 +1,191 @@ +/* + * Copyright 2015 Oliver Siegmar + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package de.siegmar.fastcsv.writer; + +import java.io.File; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.util.Collection; +import java.util.Objects; + +/** + * This is the main class for writing CSV data. + * + * @author Oliver Siegmar + */ +public final class CsvWriter { + + /** + * Field separator character (default: ',' - comma). + */ + private char fieldSeparator = ','; + + /** + * Text delimiter character (default: '"' - double quotes). + */ + private char textDelimiter = '"'; + + /** + * Should fields always delimited using the {@link #textDelimiter}? (default: false). + */ + private boolean alwaysDelimitText; + + /** + * The line delimiter character(s) to be used (default: {@link System#lineSeparator()}). + */ + private char[] lineDelimiter = System.lineSeparator().toCharArray(); + + /** + * Sets the field separator character (default: ',' - comma). + */ + public void setFieldSeparator(final char fieldSeparator) { + this.fieldSeparator = fieldSeparator; + } + + /** + * Sets the text delimiter character (default: '"' - double quotes). + */ + public void setTextDelimiter(final char textDelimiter) { + this.textDelimiter = textDelimiter; + } + + /** + * Sets if fields should always delimited using the {@link #textDelimiter} (default: false). + */ + public void setAlwaysDelimitText(final boolean alwaysDelimitText) { + this.alwaysDelimitText = alwaysDelimitText; + } + + /** + * Sets the line delimiter character(s) to be used (default: {@link System#lineSeparator()}). + */ + public void setLineDelimiter(final char[] lineDelimiter) { + this.lineDelimiter = lineDelimiter.clone(); + } + + /** + * Writes all specified data to the file. + * + * @param file where the data should be written to. + * @param data lines/columns to be written. + * @throws IOException if a write error occurs + * @throws NullPointerException if file, charset or data is null + */ + public void write(final File file, final Charset charset, final Collection data) + throws IOException { + + write( + Objects.requireNonNull(file, "file must not be null").toPath(), + Objects.requireNonNull(charset, "charset must not be null"), + data + ); + } + + /** + * Writes all specified data to the path. + * + * @param path where the data should be written to. + * @param data lines/columns to be written. + * @throws IOException if a write error occurs + * @throws NullPointerException if path, charset or data is null + */ + public void write(final Path path, final Charset charset, final Collection data) + throws IOException { + + Objects.requireNonNull(path, "path must not be null"); + Objects.requireNonNull(charset, "charset must not be null"); + try (final Writer writer = newWriter(path, charset)) { + write(writer, data); + } + } + + /** + * Writes all specified data to the writer. + * + * @param writer where the data should be written to. + * @param data lines/columns to be written. + * @throws IOException if a write error occurs + * @throws NullPointerException if writer or data is null + */ + public void write(final Writer writer, final Collection data) throws IOException { + Objects.requireNonNull(data, "data must not be null"); + final CsvAppender appender = append(writer); + for (final String[] values : data) { + appender.appendLine(values); + } + appender.flush(); + } + + /** + * Constructs a {@link CsvAppender} for the specified File. + * + * @param file the file to write data to. + * @param charset the character set to be used for writing data to the file. + * @return a new CsvAppender instance + * @throws IOException if a write error occurs + * @throws NullPointerException if file or charset is null + */ + public CsvAppender append(final File file, final Charset charset) throws IOException { + return append( + Objects.requireNonNull(file, "file must not be null").toPath(), + Objects.requireNonNull(charset, "charset must not be null") + ); + } + + /** + * Constructs a {@link CsvAppender} for the specified Path. + * + * @param path the Path (file) to write data to. + * @param charset the character set to be used for writing data to the file. + * @return a new CsvAppender instance + * @throws IOException if a write error occurs + * @throws NullPointerException if path or charset is null + */ + public CsvAppender append(final Path path, final Charset charset) throws IOException { + return append(newWriter( + Objects.requireNonNull(path, "path must not be null"), + Objects.requireNonNull(charset, "charset must not be null") + )); + } + + /** + * Constructs a {@link CsvAppender} for the specified Writer. + * + * This library uses built-in buffering, so you do not need to pass in a buffered Writer + * implementation such as {@link java.io.BufferedWriter}. + * Performance may be even likely better if you do not. + * + * @param writer the Writer to use for writing CSV data. + * @return a new CsvAppender instance + * @throws NullPointerException if writer is null + */ + public CsvAppender append(final Writer writer) { + return new CsvAppender(Objects.requireNonNull(writer, "writer must not be null"), + fieldSeparator, textDelimiter, alwaysDelimitText, lineDelimiter); + } + + private static Writer newWriter(final Path path, final Charset charset) throws IOException { + return new OutputStreamWriter(Files.newOutputStream(path, StandardOpenOption.CREATE, + StandardOpenOption.TRUNCATE_EXISTING), charset); + } + +} diff --git a/src/main/java/de/siegmar/fastcsv/writer/FastBufferedWriter.java b/src/main/java/de/siegmar/fastcsv/writer/FastBufferedWriter.java new file mode 100644 index 0000000..bf3805a --- /dev/null +++ b/src/main/java/de/siegmar/fastcsv/writer/FastBufferedWriter.java @@ -0,0 +1,80 @@ +/* + * Copyright 2015 Oliver Siegmar + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package de.siegmar.fastcsv.writer; + +import java.io.IOException; +import java.io.Writer; + +/** + * Unsynchronized and thus high performance replacement for BufferedWriter. + * + * This class is intended for internal use only. + * + * @author Oliver Siegmar + */ +final class FastBufferedWriter extends Writer { + + private static final int BUFFER_SIZE = 8192; + + private Writer out; + private char[] buf = new char[BUFFER_SIZE]; + private int pos; + + FastBufferedWriter(final Writer writer) { + this.out = writer; + } + + @Override + public void write(final char[] cbuf, final int off, final int len) throws IOException { + if (pos + len >= buf.length) { + flushBuffer(); + } + + if (len >= buf.length) { + out.write(cbuf, off, len); + } else { + System.arraycopy(cbuf, off, buf, pos, len); + pos += len; + } + } + + @Override + public void write(final int c) throws IOException { + if (pos == buf.length) { + flushBuffer(); + } + buf[pos++] = (char) c; + } + + @Override + public void close() throws IOException { + flushBuffer(); + out.close(); + } + + @Override + public void flush() throws IOException { + flushBuffer(); + out.flush(); + } + + private void flushBuffer() throws IOException { + out.write(buf, 0, pos); + pos = 0; + } + +} diff --git a/src/main/java/ru/fusionsoft/dbgit/App.java b/src/main/java/ru/fusionsoft/dbgit/App.java index d72e2c5..0c2f173 100644 --- a/src/main/java/ru/fusionsoft/dbgit/App.java +++ b/src/main/java/ru/fusionsoft/dbgit/App.java @@ -1,108 +1,129 @@ package ru.fusionsoft.dbgit; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.net.URL; + +import java.sql.Connection; +import java.sql.SQLException; +import java.text.MessageFormat; import org.apache.commons.cli.CommandLine; -import org.slf4j.LoggerFactory; +import org.junit.platform.commons.util.ExceptionUtils; + -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.joran.JoranConfigurator; -import ch.qos.logback.classic.util.ContextInitializer; -import ch.qos.logback.core.joran.spi.JoranException; -import ch.qos.logback.core.util.StatusPrinter; import ru.fusionsoft.dbgit.command.RequestCmd; +import ru.fusionsoft.dbgit.core.DBConnection; import ru.fusionsoft.dbgit.core.DBGitLang; import ru.fusionsoft.dbgit.core.DBGitPath; import ru.fusionsoft.dbgit.core.ExceptionDBGit; import ru.fusionsoft.dbgit.utils.ConsoleWriter; import ru.fusionsoft.dbgit.utils.LoggerUtil; +public class App { + + public static void main( String[] args ) { + //configureLogback(); + + try { + DBGitPath.createLogDir(); + DBGitPath.deleteOldLogs(); + executeDbGitCommand(args); + } catch (Error | Exception e) { + final String msg = DBGitLang.getInstance() + .getValue("errors", "executionError") + .toString(); + + System.err.println(MessageFormat.format( + "\n{0}: {1}", + msg, + ExceptionUtils.readStackTrace(e) + )); + + LoggerUtil.getGlobalLogger().error(msg, e); + rollbackConnection(); + System.exit(1); + } finally { + DBGitPath.clearTempDir(); + } + + } -/** - * Hello world! - * - */ -public class App -{ public static void executeDbGitCommand(String[] args) throws Exception { RequestCmd cmd = RequestCmd.getInstance(); - CommandLine cmdLine = cmd.parseCommand(args); - if (cmdLine.hasOption('h')) { cmd.printHelpAboutCommand(cmd.getCommand()); - return ; + return; } - cmd.getCurrentCommand().execute(cmdLine); } - - private static void configureLogback() throws JoranException, IOException { - LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); - JoranConfigurator jc = new JoranConfigurator(); - jc.setContext(context); - context.reset(); - - // overriding the log directory property programmatically - String logDirProperty = ".";// ... get alternative log directory location - - context.putProperty("LOG_DIR", logDirProperty); - //System.out.rintln(CProperties.getProperty("log_root_level")); - context.putProperty("log_root_level", "debug"); - - - ClassLoader classLoader = App.class.getClassLoader(); - File file = new File(classLoader.getResource("logback.xml").getFile()); - FileInputStream fis = new FileInputStream(file); - jc.doConfigure(fis); - - - /* - // this assumes that the logback.xml file is in the root of the bundle. - URL logbackConfigFileUrl = new URL("logback.xml"); - jc.doConfigure(logbackConfigFileUrl.openStream()); - */ + + private static void rollbackConnection() { + if (DBConnection.hasInstance()) try { + DBConnection dbConnection = DBConnection.getInstance(); + Connection connection = dbConnection.getConnect(); + if (connection != null && ! connection.isClosed()) { + connection.rollback(); + connection.close(); + } + } catch (Exception ex) { + if (ex instanceof ExceptionDBGit || ex instanceof SQLException) { + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("errors", "onExceptionTransactionRollbackError") + .withParams(ex.getLocalizedMessage()) + , 0 + ); + } else { + ConsoleWriter.printlnRed( + ex.getLocalizedMessage(), + 0 + ); + } + } } - - private static void updateLogback() { - LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory(); - - ContextInitializer ci = new ContextInitializer(loggerContext); - URL url = ci.findURLOfDefaultConfigurationFile(true); - try { - JoranConfigurator configurator = new JoranConfigurator(); - configurator.setContext(loggerContext); - loggerContext.reset(); - configurator.doConfigure(url); - } catch (JoranException je) { - // StatusPrinter will handle this - } - StatusPrinter.printInCaseOfErrorsOrWarnings(loggerContext); - } - - public static void main( String[] args ) throws Exception - { - //configureLogback(); - - try { - DBGitPath.createLogDir(); - DBGitPath.deleteOldLogs(); - - executeDbGitCommand(args); - - } catch (Exception e) { - ConsoleWriter.printlnRed(DBGitLang.getInstance().getValue("errors", "executionError") + ": " + e.getMessage()); - LoggerUtil.getGlobalLogger().error(e.getMessage(), e); - } finally { - DBGitPath.clearTempDir(); - } - - } +// private static void configureLogback() throws JoranException, IOException { +// LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); +// JoranConfigurator jc = new JoranConfigurator(); +// jc.setContext(context); +// context.reset(); +// +// // overriding the log directory property programmatically +// String logDirProperty = ".";// ... get alternative log directory location +// +// context.putProperty("LOG_DIR", logDirProperty); +// //System.out.rintln(CProperties.getProperty("log_root_level")); +// context.putProperty("log_root_level", "debug"); +// +// +// ClassLoader classLoader = App.class.getClassLoader(); +// File file = new File(classLoader.getResource("logback.xml").getFile()); +// FileInputStream fis = new FileInputStream(file); +// jc.doConfigure(fis); +// +// +// /* +// // this assumes that the logback.xml file is in the root of the bundle. +// URL logbackConfigFileUrl = new URL("logback.xml"); +// jc.doConfigure(logbackConfigFileUrl.openStream()); +// */ +// } +// +// private static void updateLogback() { +// LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory(); +// +// ContextInitializer ci = new ContextInitializer(loggerContext); +// URL url = ci.findURLOfDefaultConfigurationFile(true); +// +// try { +// JoranConfigurator configurator = new JoranConfigurator(); +// configurator.setContext(loggerContext); +// loggerContext.reset(); +// configurator.doConfigure(url); +// } catch (JoranException je) { +// // StatusPrinter will handle this +// } +// StatusPrinter.printInCaseOfErrorsOrWarnings(loggerContext); +// } } diff --git a/src/main/java/ru/fusionsoft/dbgit/adapters/AdapterFactory.java b/src/main/java/ru/fusionsoft/dbgit/adapters/AdapterFactory.java index 274f868..b3f76a8 100644 --- a/src/main/java/ru/fusionsoft/dbgit/adapters/AdapterFactory.java +++ b/src/main/java/ru/fusionsoft/dbgit/adapters/AdapterFactory.java @@ -5,6 +5,7 @@ import ru.fusionsoft.dbgit.core.DBConnection; import ru.fusionsoft.dbgit.core.ExceptionDBGit; import ru.fusionsoft.dbgit.core.SchemaSynonym; +import ru.fusionsoft.dbgit.mssql.DBAdapterMssql; import ru.fusionsoft.dbgit.mysql.DBAdapterMySql; import ru.fusionsoft.dbgit.oracle.DBAdapterOracle; import ru.fusionsoft.dbgit.postgres.DBAdapterPostgres; @@ -32,6 +33,8 @@ public static IDBAdapter createAdapter(Connection conn) throws ExceptionDBGit { adapter = new DBAdapterOracle(); } else if (conn.getClass().getName().equals("org.postgresql.jdbc.PgConnection")) { adapter = new DBAdapterPostgres(); + } else if (conn.getClass().getName().equals("com.microsoft.sqlserver.jdbc.SQLServerConnection")) { + adapter = new DBAdapterMssql(); } else { adapter = new DBAdapterMySql(); } diff --git a/src/main/java/ru/fusionsoft/dbgit/adapters/DBAdapter.java b/src/main/java/ru/fusionsoft/dbgit/adapters/DBAdapter.java index 09160fd..ff75722 100644 --- a/src/main/java/ru/fusionsoft/dbgit/adapters/DBAdapter.java +++ b/src/main/java/ru/fusionsoft/dbgit/adapters/DBAdapter.java @@ -1,8 +1,12 @@ package ru.fusionsoft.dbgit.adapters; +import com.axiomalaska.jdbc.NamedParameterPreparedStatement; +import com.diogonunes.jcdp.color.api.Ansi; import ru.fusionsoft.dbgit.core.*; import ru.fusionsoft.dbgit.core.db.FieldType; import ru.fusionsoft.dbgit.data_table.*; +import ru.fusionsoft.dbgit.dbobjects.DBOptionsObject; +import ru.fusionsoft.dbgit.dbobjects.DBRole; import ru.fusionsoft.dbgit.dbobjects.DBTableField; import ru.fusionsoft.dbgit.meta.*; import ru.fusionsoft.dbgit.utils.ConsoleWriter; @@ -11,53 +15,67 @@ import java.io.OutputStream; import java.sql.Connection; import java.sql.ResultSet; +import java.sql.SQLException; import java.sql.Timestamp; import java.text.MessageFormat; -import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.stream.Collectors; /** *
The base adapter adapter class. Contains general solutions independent of a particular database
*
Базовый класс адаптера БД. Содержит общие решения, независимые от конкретной БД
- * + * * @author mikle * */ public abstract class DBAdapter implements IDBAdapter { protected Connection connect; protected Boolean isExec = true; - protected OutputStream streamSql = null; + protected OutputStream streamSql = null; protected DBGitLang lang = DBGitLang.getInstance(); @Override public void setConnection(Connection conn) { connect = conn; } - @Override - public Connection getConnection() { + public Connection getConnection() { try { int maxTriesCount = DBGitConfig.getInstance().getInteger("core", "TRY_COUNT", DBGitConfig.getInstance().getIntegerGlobal("core", "TRY_COUNT", 1000)); - int pauseTimeSeconds = DBGitConfig.getInstance().getInteger("core", "TRY_DELAY", DBGitConfig.getInstance().getIntegerGlobal("core", "TRY_DELAY", 1000)); + int pauseTimeSeconds = DBGitConfig.getInstance().getInteger("core", "TRY_DELAY", DBGitConfig.getInstance().getIntegerGlobal("core", "TRY_DELAY", 2)); int currentTry = 0; - if (connect.isValid(0)) + if (connect.isValid(0)){ + connect.setAutoCommit(false); return connect; - - else { - ConsoleWriter.println("Connection lost, trying to reconnect..."); + } else { + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("general", "dbAdapter", "connectionLost") + , messageLevel-1 + ); while (currentTry <= maxTriesCount) { TimeUnit.SECONDS.sleep(pauseTimeSeconds); currentTry++; - ConsoleWriter.println("Try " + currentTry); + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("general", "dbAdapter", "reconnectTry") + .withParams(String.valueOf(currentTry)) + , messageLevel + ); DBConnection conn = DBConnection.getInstance(false); if (conn.testingConnection()) { - conn.flushConnection(); +// conn.flushConnection(); conn = DBConnection.getInstance(true); - ConsoleWriter.println("Successful reconnect"); + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("general", "dbAdapter", "reconnectTrySuccess") + , messageLevel + ); connect = conn.getConnect(); + connect.setAutoCommit(false); return connect; } } @@ -75,12 +93,10 @@ public void setDumpSqlCommand(OutputStream stream, Boolean isExec) { this.streamSql = stream; this.isExec = isExec; } - @Override public OutputStream getStreamOutputSqlCommand() { return streamSql; } - @Override public Boolean isExecSql() { return isExec; @@ -91,172 +107,96 @@ public void restoreDataBase(IMapMetaObject updateObjs) throws Exception { Connection connect = getConnection(); DBGitLang lang = DBGitLang.getInstance(); - IMapMetaObject currStep = updateObjs; - try { - List tables = new ArrayList(); - List tablesData = new ArrayList(); - - List createdSchemas = new ArrayList(); - List createdRoles = new ArrayList(); - SortedListMetaObject restoreObjs = updateObjs.getSortedList(); -/* - restoreObjs.sortFromFree().forEach( (x) -> { - ConsoleWriter.detailsPrintlnGreen(MessageFormat.format( - "{0}. {1} {2}" - ,restoreObjs.sortFromFree().indexOf(x) - ,x.getName() - ,(x.getUnderlyingDbObject() != null) && (x.getUnderlyingDbObject().getDependencies() != null) && (x.getUnderlyingDbObject().getDependencies().size() > 0) - ? "depends on (" + String.join(", ", x.getUnderlyingDbObject().getDependencies()) + ")" - : "" - )); - }); -*/ - - //if(toMakeBackup){ - //IDBBackupAdapter ba = getBackupAdapterFactory().getBackupAdapter(this); - //ba.backupDatabase(updateObjs); - //} - - - for (IMetaObject obj : restoreObjs.sortFromFree()) { - Integer step = 0; - - String schemaName = getSchemaName(obj); - if (schemaName != null) { - schemaName = (SchemaSynonym.getInstance().getSchema(schemaName) != null) - ? SchemaSynonym.getInstance().getSchema(schemaName) - : schemaName; - } - - boolean res = false; - Timestamp timestampBefore = new Timestamp(System.currentTimeMillis()); - DBGitIgnore ignore = DBGitIgnore.getInstance(); - if (step == 0) { - IDBConvertAdapter convertAdapter = getConvertAdapterFactory().getConvertAdapter(obj.getType().getValue()); - - boolean isContainsNative = false; - if (obj instanceof MetaTable) { - MetaTable table = (MetaTable) obj; - for (DBTableField field : table.getFields().values()) { if (field.getTypeUniversal().equals("native")) { isContainsNative = true; break; } } - } + SortedListMetaObject tables = new SortedListMetaObject(updateObjs.values().stream().filter(x->x instanceof MetaTable ).collect(Collectors.toList())); + SortedListMetaObject tablesExists = new SortedListMetaObject(updateObjs.values().stream().filter(x->x instanceof MetaTable && isExists(x)).collect(Collectors.toList())); - if (isContainsNative) { - ConsoleWriter.println(DBGitLang.getInstance().getValue("general", "restore", "unsupportedTypes").withParams(obj.getName())); - continue; - } + Set createdSchemas = getSchemes().values().stream().map(DBOptionsObject::getName).collect(Collectors.toSet()); + Set createdRoles = getRoles().values().stream().map(DBRole::getName).collect(Collectors.toSet()); - if (convertAdapter != null) { - if (!createdSchemas.contains(schemaName) && schemaName != null) { - createSchemaIfNeed(schemaName); - createdSchemas.add(schemaName); - } + // remove table indexes and constraints, which is step(-2) of restoreMetaObject(MetaTable) + ConsoleWriter.println(lang.getValue("general", "restore", "droppingTablesConstraints"), messageLevel); + for (IMetaObject table : tablesExists.sortFromDependencies()) { + ConsoleWriter.println(lang.getValue("general", "restore", "droppingTableConstraints").withParams(table.getName()), messageLevel+1); + getFactoryRestore().getAdapterRestore(DBGitMetaType.DBGitTable, this).restoreMetaObject(table, -2); + } - String ownerName = getOwnerName(obj); - if (!ignore.matchOne("*." + DBGitMetaType.DBGitRole.getValue()) && !getRoles().containsKey(ownerName) && !createdRoles.contains(ownerName) && ownerName != null) { - createRoleIfNeed(ownerName); - createdRoles.add(ownerName); - } + for (IMetaObject obj : updateObjs.getSortedList().sortFromReferenced()) { + Timestamp timestampBefore = new Timestamp(System.currentTimeMillis()); + int step = 0; + boolean res = false; - obj = convertAdapter.convert(getDbType(), getDbVersion(), obj); - } + IDBAdapterRestoreMetaData restoreAdapter = getFactoryRestore().getAdapterRestore(obj.getType(), this) ; + if(restoreAdapter == null) throw new Exception("restore adapter is null"); +// ConsoleWriter.printlnGreen(lang.getValue("general", "restore", "restoreType").withParams(obj.getType().toString().substring(5), obj.getName())); - if ( - step == 0 - && DBGitConfig.getInstance().getBoolean("core", "TO_MAKE_BACKUP", true) && schemaName != null - && getBackupAdapterFactory().getBackupAdapter(this).isExists(schemaName, obj.getName().substring(obj.getName().indexOf("/") + 1, obj.getName().indexOf("."))) - ) { - obj = getBackupAdapterFactory().getBackupAdapter(this).backupDBObject(obj); - } - } + obj = tryConvert(obj); + createRoleIfNeed(obj, createdRoles); + createSchemaIfNeed(obj, createdSchemas); while (!res) { - if (obj.getDbType() == null) { - ConsoleWriter.println(lang.getValue("errors", "emptyDbType")); - break; - } - - if (getFactoryRestore().getAdapterRestore(obj.getType(), this) == null || - !obj.getDbType().equals(getDbType())) - break; - - if (!createdSchemas.contains(schemaName) && schemaName != null) { - createSchemaIfNeed(schemaName); - createdSchemas.add(schemaName); - } + if(step==0) printRestoreMessage(obj); + //if(step!=0) ConsoleWriter.print(" (step " + step + ")"); + res = restoreAdapter.restoreMetaObject(obj, step++); - String ownerName = getOwnerName(obj); - if (!ignore.matchOne("*." + DBGitMetaType.DBGitRole.getValue()) && !getRoles().containsKey(ownerName) && !createdRoles.contains(ownerName) && ownerName != null) { - createRoleIfNeed(ownerName); - createdRoles.add(ownerName); - } - - if (obj instanceof MetaTable) { - MetaTable table = (MetaTable) obj; - if (!tables.contains(table)) - tables.add(table); - } - - if (obj instanceof MetaTableData) { - MetaTableData tableData = (MetaTableData) obj; - if (!tables.contains(tableData)) - tablesData.add(tableData); - } - - //call restoreAdapter.restoreMetaObject with the next 'step' until it returns true - res = getFactoryRestore().getAdapterRestore(obj.getType(), this).restoreMetaObject(obj, step); - step++; - - if (step > 100) { - throw new Exception(lang.getValue("errors", "restore", "restoreErrorDidNotReturnTrue").toString()); - } + if (step > 100) { throw new Exception(lang.getValue("errors", "restore", "restoreErrorDidNotReturnTrue").toString()); } } - Timestamp timestampAfter = new Timestamp(System.currentTimeMillis()); - Long diff = timestampAfter.getTime() - timestampBefore.getTime(); - ConsoleWriter.println("(" + diff + " " + lang.getValue("general", "add", "ms") +")"); + + Long timeDiff = new Timestamp(System.currentTimeMillis()).getTime() - timestampBefore.getTime(); +// ConsoleWriter.detailsPrintColor(MessageFormat.format(" ({1} {2})" +// , obj.getName() +// , timeDiff +// , lang.getValue("general", "add", "ms")), 0, Ansi.FColor.CYAN +// ); } - for (MetaTable table : tables) { + // restore table constraints, which is step(-1) of restoreMetaObject(MetaTable) + ConsoleWriter.println(lang.getValue("general", "restore", "restoringTablesConstraints"), messageLevel); + for (IMetaObject table : tables.sortFromReferenced()) { getFactoryRestore().getAdapterRestore(DBGitMetaType.DBGitTable, this).restoreMetaObject(table, -1); } -/* - for (MetaTableData tableData : tablesData) { - getFactoryRestore().getAdapterRestore(DBGitMetaType.DbGitTableData, this).restoreMetaObject(tableData, -2); - } -*/ connect.commit(); } catch (Exception e) { - connect.rollback(); - ConsoleWriter.detailsPrintlnRed(e.getLocalizedMessage()); - e.printStackTrace(); throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "restoreError").toString(), e); } finally { - //connect.setAutoCommit(false); } + + } + private void printRestoreMessage(IMetaObject obj) { + String leafName = ""; + if(obj instanceof MetaSequence){ leafName = "restoreSeq"; } + if(obj instanceof MetaView){ leafName = "restoreView"; } + if(obj instanceof MetaTrigger){ leafName = "restoreTrigger"; } + if(obj instanceof MetaSchema){ leafName = "restoreSchema"; } + if(obj instanceof MetaUDT){ leafName = "restoreUDT"; } + if(obj instanceof MetaEnum){ leafName = "restoreEnum"; } + if(obj instanceof MetaDomain){ leafName = "restoreDomain"; } + if(obj instanceof MetaRole){ leafName = "restoreRole"; } + if(obj instanceof MetaProcedure){ leafName = "restorePrc"; } + if(obj instanceof MetaPackage){ leafName = "restorePkg"; } + if(obj instanceof MetaUser){ leafName = "restoreUser"; } + if(obj instanceof MetaFunction){ leafName = "restoreFnc"; } + if(obj instanceof MetaTable){ leafName = "restoreTable"; } + if(obj instanceof MetaTableSpace){ leafName = "restoreTablespace"; } + if(obj instanceof MetaTableData){ leafName = "restoreTableData"; } + ConsoleWriter.println(lang.getValue("general", "restore", leafName).withParams(obj.getName()), 2); } @Override public void deleteDataBase(IMapMetaObject deleteObjs) throws Exception { deleteDataBase(deleteObjs, false); } - public void deleteDataBase(IMapMetaObject deleteObjs, boolean isDeleteFromIndex) throws Exception { Connection connect = getConnection(); DBGitIndex index = DBGitIndex.getInctance(); try { - //start transaction - boolean toMakeBackup = DBGitConfig.getInstance().getBoolean("core", "TO_MAKE_BACKUP", true); - - List deleteObjsSorted = deleteObjs.getSortedList().sortFromDependant(); - + List deleteObjsSorted = deleteObjs.getSortedList().sortFromDependencies(); for (IMetaObject obj : deleteObjsSorted) { - if (toMakeBackup) { obj = getBackupAdapterFactory().getBackupAdapter(this).backupDBObject(obj); } getFactoryRestore().getAdapterRestore(obj.getType(), this).removeMetaObject(obj); if(isDeleteFromIndex) index.removeItem(obj); } - connect.commit(); } catch (Exception e) { connect.rollback(); @@ -266,6 +206,7 @@ public void deleteDataBase(IMapMetaObject deleteObjs, boolean isDeleteFromIndex) } } + public String cleanString(String str) { String dt = str.replace("\r\n", "\n"); while (dt.contains(" \n")) dt = dt.replace(" \n", "\n"); @@ -274,28 +215,84 @@ public String cleanString(String str) { return dt; } - public void rowToProperties(ResultSet rs, StringProperties properties) { - try { - for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) { - if (rs.getString(i) == null) continue ; + private IMetaObject tryConvert(IMetaObject obj) throws Exception { + if ( obj.getDbType() == null) throw new Exception(lang.getValue("errors", "emptyDbType").toString()); - properties.addChild(rs.getMetaData().getColumnName(i).toLowerCase(), cleanString(rs.getString(i))); + if (isSameDbType(obj) ){ + if(isSameDbVersion(obj) || obj.getDbVersionNumber() <= getDbVersionNumber()){ + return obj; + } + } else { + if ( checkContainsNativeFields(obj)) { + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("general", "restore", "unsupportedTypes") + .withParams(obj.getName()) + , messageLevel + ); } - } catch(Exception e) { - throw new ExceptionDBGitRunTime(e); + } + + IDBConvertAdapter convertAdapter = getConvertAdapterFactory().getConvertAdapter(obj.getType().getValue()); + if (convertAdapter != null) return convertAdapter.convert(getDbType(), getDbVersion(), obj); + else { + String msg = DBGitLang.getInstance().getValue("errors", "convert", "cannotFindAdapter").withParams( + obj.getName(), obj.getDbType().toString(), obj.getDbVersion() + , getDbType().toString() + , String.valueOf(getDbVersionNumber()) + ); + throw new Exception(msg); + } + } + private void createSchemaIfNeed(IMetaObject obj, Set createdSchemas) throws Exception { + String schemaName = getSchemaSynonymName(obj); + if(schemaName == null){ + ConsoleWriter.detailsPrintlnRed(DBGitLang.getInstance() + .getValue("errors", "adapter", "nullSchema") + .withParams(obj.getName()) + , messageLevel + ); + return; + } + if (!createdSchemas.contains(schemaName)) { + createSchemaIfNeed(schemaName); + createdSchemas.add(schemaName); } } + private void createRoleIfNeed(IMetaObject obj, Set createdRoles) throws ExceptionDBGit { +// boolean isRolesUnignored = !DBGitIgnore.getInstance().matchOne("*." + DBGitMetaType.DBGitRole.getValue()); + String ownerName = getOwnerName(obj); + + if(ownerName != null){ + if ( !createdRoles.contains(ownerName)) { + createRoleIfNeed(ownerName); + createdRoles.add(ownerName); + } + } - private String getSchemaName(IMetaObject obj) { - if (obj instanceof MetaSql) - return ((MetaSql) obj).getSqlObject().getSchema(); - else if (obj instanceof MetaTable) - return ((MetaTable) obj).getTable().getSchema(); - else if (obj instanceof MetaSequence) - return ((MetaSequence) obj).getSequence().getSchema(); - else return null; + } + protected boolean isExists(IMetaObject obj){ + try{ + IDBBackupAdapter backupAdapter = getBackupAdapterFactory().getBackupAdapter(AdapterFactory.createAdapter()); + return backupAdapter.isExists( + obj.getUnderlyingDbObject().getSchema(), + obj.getUnderlyingDbObject().getName() + ); + } catch (Exception ex) { + return false; + } } + private boolean checkContainsNativeFields(IMetaObject obj){ + if (obj instanceof MetaTable) { + MetaTable table = (MetaTable) obj; + for (DBTableField field : table.getFields().values()) { + if (field.getTypeUniversal().equals(FieldType.NATIVE)) { + return true; + } + } + } + return false; + } private String getOwnerName(IMetaObject obj) { if (obj instanceof MetaSql) return ((MetaSql) obj).getSqlObject().getOwner(); @@ -305,6 +302,41 @@ else if (obj instanceof MetaSequence) return ((MetaSequence) obj).getSequence().getOptions().get("owner").getData(); else return null; } + private String getSchemaName(IMetaObject obj) { + if (obj instanceof MetaSql) + return ((MetaSql) obj).getSqlObject().getSchema(); + else if (obj instanceof MetaTable) + return ((MetaTable) obj).getTable().getSchema(); + else if (obj instanceof MetaSequence) + return ((MetaSequence) obj).getSequence().getSchema(); + else if (obj instanceof MetaTableData) + return ((MetaTableData) obj).getTable().getSchema(); + else return null; + } + private String getSchemaSynonymName(String schemaName) throws Exception { + String schemaSynonym = schemaName != null + ? SchemaSynonym.getInstance().getSchema(schemaName) + : null; + + return (schemaSynonym != null) + ? schemaSynonym + : schemaName; + } + private String getSchemaSynonymName(IMetaObject obj) throws Exception { + return getSchemaSynonymName(getSchemaName(obj)); + } + public Double getDbVersionNumber(){ + Matcher matcher = Pattern.compile("\\D*(\\d+)\\.(\\d+)").matcher(getDbVersion()); + matcher.find(); + Double result = Double.valueOf(matcher.group(0)+matcher.group(1)); + return result; + } + private boolean isSameDbType(IMetaObject obj){ + return obj.getDbType().equals(getDbType()); + } + private boolean isSameDbVersion(IMetaObject obj){ + return obj.getDbVersion().equals(getDbVersion()); + } public void registryMappingTypes() { FactoryCellData.regMappingTypes(FieldType.BINARY, MapFileData.class); @@ -313,6 +345,25 @@ public void registryMappingTypes() { FactoryCellData.regMappingTypes(FieldType.NATIVE, StringData.class); FactoryCellData.regMappingTypes(FieldType.NUMBER, LongData.class); FactoryCellData.regMappingTypes(FieldType.STRING, StringData.class); + FactoryCellData.regMappingTypes(FieldType.STRING_NATIVE, StringData.class); FactoryCellData.regMappingTypes(FieldType.TEXT, TextFileData.class); } + + public String escapeNameIfNeeded(String name) { + return name; + } + + public NamedParameterPreparedStatement preparedStatement(Connection connection, String sql, Map values) throws SQLException, ExceptionDBGit { + NamedParameterPreparedStatement stmt = NamedParameterPreparedStatement.createNamedParameterPreparedStatement(getConnection(), sql); + + for(Map.Entry entry : values.entrySet()){ + Object value = entry.getValue(); + if (value instanceof String) stmt.setString(entry.getKey(), (String) value); + else if (value instanceof Long) stmt.setLong(entry.getKey(), (Long) value); + else if (value instanceof Float) stmt.setDouble(entry.getKey(), ((Float) value).floatValue()); + else throw new ExceptionDBGit("Unsupported type of value, see stacktrace"); + } + + return stmt; + } } diff --git a/src/main/java/ru/fusionsoft/dbgit/adapters/DBAdapterProxy.java b/src/main/java/ru/fusionsoft/dbgit/adapters/DBAdapterProxy.java index 8ffda91..8f7797d 100644 --- a/src/main/java/ru/fusionsoft/dbgit/adapters/DBAdapterProxy.java +++ b/src/main/java/ru/fusionsoft/dbgit/adapters/DBAdapterProxy.java @@ -8,6 +8,8 @@ import ru.fusionsoft.dbgit.core.SchemaSynonym; import ru.fusionsoft.dbgit.core.db.DbType; import ru.fusionsoft.dbgit.dbobjects.DBConstraint; +import ru.fusionsoft.dbgit.dbobjects.DBDomain; +import ru.fusionsoft.dbgit.dbobjects.DBEnum; import ru.fusionsoft.dbgit.dbobjects.DBFunction; import ru.fusionsoft.dbgit.dbobjects.DBIndex; import ru.fusionsoft.dbgit.dbobjects.DBPackage; @@ -22,6 +24,7 @@ import ru.fusionsoft.dbgit.dbobjects.DBTableSpace; import ru.fusionsoft.dbgit.dbobjects.DBTrigger; import ru.fusionsoft.dbgit.dbobjects.DBUser; +import ru.fusionsoft.dbgit.dbobjects.DBUserDefinedType; import ru.fusionsoft.dbgit.dbobjects.DBView; import ru.fusionsoft.dbgit.meta.IMapMetaObject; @@ -186,7 +189,37 @@ public Map getUsers() { public Map getRoles() { return adapter.getRoles(); } - + + @Override + public Map getUDTs(String schema) { + return adapter.getUDTs(schema); + } + + @Override + public Map getDomains(String schema) { + return adapter.getDomains(schema); + } + + @Override + public Map getEnums(String schema) { + return adapter.getEnums(schema); + } + + @Override + public DBUserDefinedType getUDT(String schema, String name) { + return adapter.getUDT(schema, name); + } + + @Override + public DBDomain getDomain(String schema, String name) { + return adapter.getDomain(schema, name); + } + + @Override + public DBEnum getEnum(String schema, String name) { + return adapter.getEnum(schema, name); + } + public T schemaSynonymMap(T object) { if (object == null) return null; @@ -227,6 +260,11 @@ public String getDbVersion() { return adapter.getDbVersion(); } + @Override + public Double getDbVersionNumber() { + return adapter.getDbVersionNumber(); + } + @Override public IFactoryDBConvertAdapter getConvertAdapterFactory() { return adapter.getConvertAdapterFactory(); @@ -253,6 +291,11 @@ public boolean isReservedWord(String word) { return adapter.isReservedWord(word); } + @Override + public String escapeNameIfNeeded(String name) { + return adapter.escapeNameIfNeeded(name); + } + @Override public DBTableData getTableDataPortion(String schema, String nameTable, int portionIndex, int tryNumber) { return adapter.getTableDataPortion(schema, nameTable, portionIndex, tryNumber); diff --git a/src/main/java/ru/fusionsoft/dbgit/adapters/DBBackupAdapter.java b/src/main/java/ru/fusionsoft/dbgit/adapters/DBBackupAdapter.java index d9d71e5..10db25e 100644 --- a/src/main/java/ru/fusionsoft/dbgit/adapters/DBBackupAdapter.java +++ b/src/main/java/ru/fusionsoft/dbgit/adapters/DBBackupAdapter.java @@ -1,7 +1,16 @@ package ru.fusionsoft.dbgit.adapters; -import ru.fusionsoft.dbgit.core.DBGitConfig; +import ru.fusionsoft.dbgit.core.DBGitIndex; import ru.fusionsoft.dbgit.core.DBGitLang; +import ru.fusionsoft.dbgit.core.GitMetaDataManager; +import ru.fusionsoft.dbgit.meta.*; +import ru.fusionsoft.dbgit.statement.StatementLogging; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; + +import java.text.MessageFormat; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; public abstract class DBBackupAdapter implements IDBBackupAdapter { protected IDBAdapter adapter = null; @@ -10,7 +19,9 @@ public abstract class DBBackupAdapter implements IDBBackupAdapter { private boolean saveToSchema; protected DBGitLang lang = DBGitLang.getInstance(); - + protected DBGitIndex dbGitIndex; + + public void setAdapter(IDBAdapter adapter) { this.adapter = adapter; } @@ -34,5 +45,147 @@ public void saveToSchema(boolean saveToSchema) { public boolean isSaveToSchema() { return saveToSchema; } + + + public boolean isExists(IMetaObject imo) { + NameMeta nm = new NameMeta(imo.getName()); + try { + return isExists(nm.getSchema(), nm.getName()); + } catch (Exception ex){ + throw new RuntimeException(ex); + } + } + + public void backupDatabase(IMapMetaObject updateObjs) throws Exception { + + // Condition: we rewrite refs on backup objects adding BACKUP$ prefix on them + // -> we need to find and add to backup list all updateObjs dependencies + + // Condition: old backups can refer on each other + // -> we need to drop old backups of the objects + old backup dependencies + + // collect yet existing backups of restore objects +// Timestamp timestampBefore = new Timestamp(System.currentTimeMillis()); + dbGitIndex = DBGitIndex.getInctance(); + + StatementLogging stLog = new StatementLogging(adapter.getConnection(), adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + IMapMetaObject dbObjs = GitMetaDataManager.getInstance().loadDBMetaData(true); + + IMapMetaObject dbToBackup = new TreeMapMetaObject(dbObjs.values().stream() + .filter( x-> updateObjs.containsKey(x.getName()) ) + .collect(Collectors.toList())); + + List dbNotToBackup = dbObjs.values().stream() + .filter(x -> !updateObjs.containsKey(x.getName())) + .collect(Collectors.toList()); + + IMapMetaObject dbExistingBackups = new TreeMapMetaObject(dbObjs.values().stream() + .filter(this::isBackupObject) + .collect(Collectors.toList())); + + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("general", "backup", "tryToBackup") + .withParams( + String.valueOf(dbToBackup.size()), + String.valueOf(updateObjs.size())) + , 1 + ); + + + // collect restore objects dependencies to satisfy all backups create needs + // so dependencies will be backed up too + Map restoreObjsDependencies; + do{ + restoreObjsDependencies = dbNotToBackup.stream().filter( notToBackup -> + notToBackup.getUnderlyingDbObject() != null && + dbToBackup.values().stream().anyMatch( + toBackup -> toBackup.dependsOn(notToBackup) + ) + ).collect(Collectors.toMap(IMetaObject::getName, Function.identity() )); + + dbNotToBackup.removeAll(restoreObjsDependencies.values()); + dbToBackup.putAll(restoreObjsDependencies); + + if(restoreObjsDependencies.size() > 0) { + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("general", "backup", "dependingBackups") + .withParams( + String.valueOf(restoreObjsDependencies.size()), + String.join(" ,", restoreObjsDependencies.keySet()) + ), 2 + ); + } + } while (restoreObjsDependencies.size() > 0); + + //so we have a full backup list, let's get a drop list + if(dbToBackup.size() > 0){ + Set suspectBackupNames = dbToBackup.values().stream() + .map( x->getBackupNameMeta(x).getMetaName()) + .collect(Collectors.toSet()); + + List dropList = new ArrayList<>(); + + IMapMetaObject dbDroppingBackups = new TreeMapMetaObject(dbExistingBackups.values().stream() + .filter(existingBackup -> suspectBackupNames.contains(existingBackup.getName())) + .collect(Collectors.toList())); + + List dbDroppingBackupsDeps = dbExistingBackups.values().stream() + .filter( dbBackup -> + !dbDroppingBackups.containsKey(dbBackup.getName()) + && dbDroppingBackups.values().stream().anyMatch(dbBackup::dependsOn) + ).collect(Collectors.toList()); + + dropList.addAll(dbDroppingBackups.values()); + dropList.addAll(dbDroppingBackupsDeps); + List dropListSorted = new SortedListMetaObject(dropList).sortFromDependencies(); + + if(dropList.size() > 0) ConsoleWriter.println(DBGitLang.getInstance() + .getValue("general", "backup", "rewritingBackups") + .withParams( + String.valueOf(dbDroppingBackups.size()), + String.valueOf(dbDroppingBackupsDeps.size()) + ), messageLevel-1 + ); + + //drop backups in one place + for(IMetaObject imo : dropListSorted){ + ConsoleWriter.detailsPrintln(lang.getValue("general", "backup", "droppingBackup").withParams(imo.getName()), messageLevel); + dropIfExists(imo, stLog); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + } + + if(dbToBackup.size() > 0) ConsoleWriter.println(DBGitLang.getInstance() + .getValue("general", "backup", "creatingBackups") + .withParams( + String.valueOf(dbToBackup.size()) + ), messageLevel-1 + ); + + + //create backups + for(IMetaObject imo : dbToBackup.getSortedList().sortFromReferenced()){ + backupDBObject(imo); + } + + // Timestamp timestampAfter = new Timestamp(System.currentTimeMillis()); + // ConsoleWriter.detailsPrintLn(MessageFormat.format("({0})", + // lang.getValue("general", "add", "ms").withParams(String.valueOf(timestampAfter.getTime() - timestampBefore.getTime())) + // )); + } + + } + + public NameMeta getBackupNameMeta(IMetaObject imo){ + NameMeta nm = new NameMeta(imo.getName()); + String backupName = isSaveToSchema() ? nm.getName() : PREFIX + nm.getName(); + String backupSchema = isSaveToSchema() ? PREFIX + nm.getSchema() : nm.getSchema(); + return new NameMeta(backupSchema, backupName, (DBGitMetaType) imo.getType()); + } + + public boolean isBackupObject(IMetaObject imo) { + if(dbGitIndex != null && dbGitIndex.getTreeItems().containsKey(imo.getName())) return false; + NameMeta nm = new NameMeta(imo); + return nm.getName().contains(PREFIX) || nm.getSchema().contains(PREFIX); + } } diff --git a/src/main/java/ru/fusionsoft/dbgit/adapters/DBRestoreAdapter.java b/src/main/java/ru/fusionsoft/dbgit/adapters/DBRestoreAdapter.java index 4b8f1ee..4680c27 100644 --- a/src/main/java/ru/fusionsoft/dbgit/adapters/DBRestoreAdapter.java +++ b/src/main/java/ru/fusionsoft/dbgit/adapters/DBRestoreAdapter.java @@ -18,7 +18,9 @@ public abstract class DBRestoreAdapter implements IDBAdapterRestoreMetaData { protected IDBAdapter adapter = null; protected DBGitLang lang = DBGitLang.getInstance(); - + public static int messageLevel = 3; + + public void setAdapter(IDBAdapter adapter) { this.adapter = adapter; } diff --git a/src/main/java/ru/fusionsoft/dbgit/adapters/IDBAdapter.java b/src/main/java/ru/fusionsoft/dbgit/adapters/IDBAdapter.java index 502806c..0d366f6 100644 --- a/src/main/java/ru/fusionsoft/dbgit/adapters/IDBAdapter.java +++ b/src/main/java/ru/fusionsoft/dbgit/adapters/IDBAdapter.java @@ -7,6 +7,8 @@ import ru.fusionsoft.dbgit.core.ExceptionDBGit; import ru.fusionsoft.dbgit.core.db.DbType; import ru.fusionsoft.dbgit.dbobjects.DBConstraint; +import ru.fusionsoft.dbgit.dbobjects.DBDomain; +import ru.fusionsoft.dbgit.dbobjects.DBEnum; import ru.fusionsoft.dbgit.dbobjects.DBFunction; import ru.fusionsoft.dbgit.dbobjects.DBIndex; import ru.fusionsoft.dbgit.dbobjects.DBPackage; @@ -21,6 +23,7 @@ import ru.fusionsoft.dbgit.dbobjects.DBTableSpace; import ru.fusionsoft.dbgit.dbobjects.DBTrigger; import ru.fusionsoft.dbgit.dbobjects.DBUser; +import ru.fusionsoft.dbgit.dbobjects.DBUserDefinedType; import ru.fusionsoft.dbgit.dbobjects.DBView; import ru.fusionsoft.dbgit.meta.IMapMetaObject; @@ -36,6 +39,7 @@ public interface IDBAdapter { public static final int MAX_ROW_COUNT_FETCH = 10000; public static final int LIMIT_FETCH = 1; public static final int NOLIMIT_FETCH = 2; + public static final int messageLevel = 2; public void setConnection(Connection conn); @@ -142,14 +146,21 @@ public interface IDBAdapter { public Map getUsers(); public Map getRoles(); - + Map getUDTs(String schema); + Map getDomains(String schema); + Map getEnums(String schema); + DBUserDefinedType getUDT(String schema, String name); + DBDomain getDomain(String schema, String name); + DBEnum getEnum(String schema, String name); + public boolean userHasRightsToGetDdlOfOtherUsers(); public IFactoryDBBackupAdapter getBackupAdapterFactory(); public IFactoryDBConvertAdapter getConvertAdapterFactory(); public DbType getDbType(); - public String getDbVersion(); + public String getDbVersion(); + public Double getDbVersionNumber(); public void createSchemaIfNeed(String schemaName) throws ExceptionDBGit; public void createRoleIfNeed(String roleName) throws ExceptionDBGit; @@ -157,6 +168,8 @@ public interface IDBAdapter { public String getDefaultScheme() throws ExceptionDBGit; boolean isReservedWord(String word); - + + public String escapeNameIfNeeded(String name); + /*Если будет нужно - сюда можно добавить подписчиков на события*/ } diff --git a/src/main/java/ru/fusionsoft/dbgit/adapters/IDBBackupAdapter.java b/src/main/java/ru/fusionsoft/dbgit/adapters/IDBBackupAdapter.java index 0c7284f..dd6474b 100644 --- a/src/main/java/ru/fusionsoft/dbgit/adapters/IDBBackupAdapter.java +++ b/src/main/java/ru/fusionsoft/dbgit/adapters/IDBBackupAdapter.java @@ -1,18 +1,27 @@ package ru.fusionsoft.dbgit.adapters; +import ru.fusionsoft.dbgit.core.ExceptionDBGit; +import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; +import ru.fusionsoft.dbgit.meta.IMapMetaObject; import ru.fusionsoft.dbgit.meta.IMetaObject; +import ru.fusionsoft.dbgit.meta.NameMeta; import ru.fusionsoft.dbgit.statement.StatementLogging; +import java.sql.SQLException; + public interface IDBBackupAdapter { - public static final String PREFIX = "BACKUP$"; - + public static final String PREFIX = "BACKUP$"; + static int messageLevel = 3; + public void setAdapter(IDBAdapter adapter); public IDBAdapter getAdapter(); - public IMetaObject backupDBObject(IMetaObject obj) throws Exception; - + public IMetaObject backupDBObject(IMetaObject obj) throws Exception; + + public void backupDatabase(IMapMetaObject backupObjs) throws Exception; + public void restoreDBObject(IMetaObject obj) throws Exception; public boolean isToSaveData(); @@ -25,5 +34,9 @@ public interface IDBBackupAdapter { public boolean isSaveToSchema(); - public boolean isExists(String owner, String objectName) throws Exception; + public boolean isExists(String owner, String objectName) throws SQLException; + + public void dropIfExists(String owner, String objectName, StatementLogging stLog) throws SQLException; + + public void dropIfExists(IMetaObject imo, StatementLogging stLog) throws SQLException, Exception; } diff --git a/src/main/java/ru/fusionsoft/dbgit/adapters/IDBConvertAdapter.java b/src/main/java/ru/fusionsoft/dbgit/adapters/IDBConvertAdapter.java index aa11dab..ac1930e 100644 --- a/src/main/java/ru/fusionsoft/dbgit/adapters/IDBConvertAdapter.java +++ b/src/main/java/ru/fusionsoft/dbgit/adapters/IDBConvertAdapter.java @@ -7,5 +7,6 @@ import ru.fusionsoft.dbgit.meta.MetaTable; public interface IDBConvertAdapter { + public static int messageLevel = 2; public IMetaObject convert(DbType dbType, String dbVersion, IMetaObject obj) throws ExceptionDBGit; } diff --git a/src/main/java/ru/fusionsoft/dbgit/adapters/IFactoryDBAdapterRestoteMetaData.java b/src/main/java/ru/fusionsoft/dbgit/adapters/IFactoryDBAdapterRestoteMetaData.java index de1b8ff..a66bf9d 100644 --- a/src/main/java/ru/fusionsoft/dbgit/adapters/IFactoryDBAdapterRestoteMetaData.java +++ b/src/main/java/ru/fusionsoft/dbgit/adapters/IFactoryDBAdapterRestoteMetaData.java @@ -6,5 +6,6 @@ import ru.fusionsoft.dbgit.meta.IDBGitMetaType; public interface IFactoryDBAdapterRestoteMetaData { + static int messageLevel = 1; public IDBAdapterRestoreMetaData getAdapterRestore(IDBGitMetaType tp, IDBAdapter adapter); } diff --git a/src/main/java/ru/fusionsoft/dbgit/command/CmdAdd.java b/src/main/java/ru/fusionsoft/dbgit/command/CmdAdd.java index 854dfe4..592e14e 100644 --- a/src/main/java/ru/fusionsoft/dbgit/command/CmdAdd.java +++ b/src/main/java/ru/fusionsoft/dbgit/command/CmdAdd.java @@ -4,7 +4,7 @@ import java.io.FileOutputStream; import java.io.OutputStreamWriter; import java.sql.Timestamp; -import java.util.Set; +import java.util.List; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.Options; @@ -79,21 +79,23 @@ public void execute(CommandLine cmdLine) throws Exception { DBGitConfig.getInstance().setValue("CURRENT_OBJECT", obj.getName().replace(".csv", ".tbl")); Timestamp timestampBefore = new Timestamp(System.currentTimeMillis()); - ConsoleWriter.detailsPrintLn(getLang().getValue("general", "add", "processingObject") + " " + obj.getName()); - ConsoleWriter.detailsPrint(getLang().getValue("general", "add", "savingToFile"), 2); + ConsoleWriter.detailsPrintln(getLang().getValue("general", "add", "processingObject") + .withParams(obj.getName()) + , messageLevel + ); + ConsoleWriter.detailsPrintln(getLang().getValue("general", "add", "savingToFile"), messageLevel+1); //TODO obj.saveToFile(); - ConsoleWriter.detailsPrintlnGreen(getLang().getValue("general", "ok")); - ConsoleWriter.detailsPrint(getLang().getValue("general", "addToGit"), 2); + ConsoleWriter.detailsPrintGreen(getLang().getValue("general", "ok")); + ConsoleWriter.detailsPrintln(getLang().getValue("general", "addToGit"), messageLevel+1); countSave += obj.addToGit(); - ConsoleWriter.detailsPrintlnGreen(getLang().getValue("general", "ok")); + ConsoleWriter.detailsPrintGreen(getLang().getValue("general", "ok")); Timestamp timestampAfter = new Timestamp(System.currentTimeMillis()); Long diff = timestampAfter.getTime() - timestampBefore.getTime(); - ConsoleWriter.detailsPrint(getLang().getValue("general", "time").withParams(diff.toString()), 2); - ConsoleWriter.detailsPrintLn(""); + ConsoleWriter.detailsPrint(getLang().getValue("general", "time").withParams(diff.toString())); index.addItem(obj); @@ -116,15 +118,16 @@ public void execute(CommandLine cmdLine) throws Exception { isFirstPortion = (DBGitConfig.getInstance().getInteger("core", "CURRENT_PORTION", 0) == 0); while (gmdm.loadNextPortion((MetaTable) obj)) { - ConsoleWriter.detailsPrint(getLang().getValue("general", "add", "writing").toString(), 2); + ConsoleWriter.detailsPrintln(getLang().getValue("general", "add", "writing").toString(), messageLevel+1); try { //gmdm.getCurrent().serialize(out); Integer count = 0; - Set fields = null; + List fields = null; for (RowData rd : gmdm.getCurrent().getmapRows().values()) { if (count == 0 && isFirstPortion) { - fields = rd.getData().keySet(); + //fields = rd.getData().keySet(); + fields = gmdm.getCurrent().getFields(); csvPrinter.printRecord(fields); isFirstPortion = false; } @@ -136,7 +139,6 @@ public void execute(CommandLine cmdLine) throws Exception { } catch (Exception e) { - e.printStackTrace(); throw new ExceptionDBGit(e); } } @@ -154,8 +156,8 @@ public void execute(CommandLine cmdLine) throws Exception { index.saveDBIndex(); index.addToGit(); } else { - ConsoleWriter.printlnRed(getLang().getValue("errors", "add", "cantFindObjectInDb").withParams(nameObj)); + ConsoleWriter.printlnRed(getLang().getValue("errors", "add", "cantFindObjectInDb").withParams(nameObj), messageLevel); } - ConsoleWriter.println(getLang().getValue("general", "done")); + ConsoleWriter.println(getLang().getValue("general", "done"), messageLevel); } } diff --git a/src/main/java/ru/fusionsoft/dbgit/command/CmdCheckout.java b/src/main/java/ru/fusionsoft/dbgit/command/CmdCheckout.java index b6538d1..5acda93 100644 --- a/src/main/java/ru/fusionsoft/dbgit/command/CmdCheckout.java +++ b/src/main/java/ru/fusionsoft/dbgit/command/CmdCheckout.java @@ -1,88 +1,125 @@ -package ru.fusionsoft.dbgit.command; - -import org.apache.commons.cli.CommandLine; -import org.apache.commons.cli.CommandLine.Builder; -import org.apache.commons.cli.Option; -import org.apache.commons.cli.Options; - -import ru.fusionsoft.dbgit.core.DBGit; -import ru.fusionsoft.dbgit.core.DBGitIndex; -import ru.fusionsoft.dbgit.core.ExceptionDBGit; -import ru.fusionsoft.dbgit.utils.ConsoleWriter; - -public class CmdCheckout implements IDBGitCommand { - - private Options opts = new Options(); - - public CmdCheckout() { - opts.addOption("b", false, getLang().getValue("help", "checkout-b").toString()); - opts.addOption("r", false, getLang().getValue("help", "checkout-r").toString()); - opts.addOption("u", false, getLang().getValue("help", "checkout-u").toString()); - opts.addOption("nodb", false, getLang().getValue("help", "checkout-no-db").toString()); - opts.addOption("upgrade", false, getLang().getValue("help", "checkout-u").toString()); - } - - @Override - public String getCommandName() { - return "checkout"; - } - - @Override - public String getParams() { - return " "; - } - - @Override - public String getHelperInfo() { - return getLang().getValue("help", "checkout").toString(); - } - - @Override - public Options getOptions() { - return opts; - } - - @Override - public void execute(CommandLine cmdLine) throws Exception { - - String[] args = cmdLine.getArgs(); - ConsoleWriter.setDetailedLog(cmdLine.hasOption("v")); - - if (!cmdLine.hasOption("u") && !cmdLine.hasOption("nodb")) - checkVersion(); - - if (args == null || args.length == 0) { - throw new ExceptionDBGit(getLang().getValue("errors", "checkout", "badCommand")); - } else if (args.length == 1) { - DBGit.getInstance().gitCheckout(args[0], null, cmdLine.hasOption("b")); - } else if (args.length == 2) { - DBGit.getInstance().gitCheckout(args[0], args[1], cmdLine.hasOption("b")); - } - - Builder builder = new CommandLine.Builder(); - - if (cmdLine.hasOption("u")) { - CmdDump dumpCommand = new CmdDump(); - builder.addOption(new Option("u", false, "")); - - if (cmdLine.hasOption("v")) { - builder.addOption(new Option("v", false, "")); - } - - dumpCommand.execute(builder.build()); - } else if (!cmdLine.hasOption("nodb")) { - CmdRestore restoreCommand = new CmdRestore(); - - if (cmdLine.hasOption("r")) { - builder.addOption(new Option("r", false, "")); - } - if (cmdLine.hasOption("v")) { - builder.addOption(new Option("v", false, "")); - } - - restoreCommand.execute(builder.build()); - } - - } - -} +package ru.fusionsoft.dbgit.command; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.CommandLine.Builder; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; + +import org.eclipse.jgit.lib.Ref; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.revwalk.RevWalk; +import ru.fusionsoft.dbgit.core.DBGit; +import ru.fusionsoft.dbgit.core.DBGitLang; +import ru.fusionsoft.dbgit.core.ExceptionDBGit; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; + +public class CmdCheckout implements IDBGitCommand { + + private Options opts = new Options(); + + public CmdCheckout() { + opts.addOption("b", false, getLang().getValue("help", "checkout-b").toString()); + opts.addOption("r", false, getLang().getValue("help", "checkout-r").toString()); + opts.addOption("u", false, getLang().getValue("help", "checkout-u").toString()); + opts.addOption("nodb", false, getLang().getValue("help", "checkout-no-db").toString()); + opts.addOption("noowner", false, getLang().getValue("help", "checkout-no-owner").toString()); + opts.addOption("upgrade", false, getLang().getValue("help", "checkout-u").toString()); + opts.addOption("ls", false, getLang().getValue("help", "checkout-ls").toString()); + } + + @Override + public String getCommandName() { + return "checkout"; + } + + @Override + public String getParams() { + return " "; + } + + @Override + public String getHelperInfo() { + return getLang().getValue("help", "checkout").toString(); + } + + @Override + public Options getOptions() { + return opts; + } + + @Override + public void execute(CommandLine cmdLine) throws Exception { + + String[] args = cmdLine.getArgs(); + ConsoleWriter.setDetailedLog(cmdLine.hasOption("v")); + + Repository repo = DBGit.getInstance().getRepository(); + Ref head = repo.getAllRefs().get("HEAD"); + + if (cmdLine.hasOption("ls")){ + try(RevWalk walk = new RevWalk(repo)){ + + String branch = repo.getBranch(); + String headNumber = head.getObjectId().getName(); + String headName = head.getName(); + String message = walk.parseCommit(head.getObjectId()).getShortMessage(); + + System.out.println(DBGitLang.getInstance() + .getValue("general", "checkout", "printBranchAndCommit") + .withParams( + !branch.equals(headNumber) ? branch + ": " + headNumber : headNumber, + headName, + message + ) +// , messageLevel + ); + + } + return; + } + + if (!cmdLine.hasOption("u") && !cmdLine.hasOption("nodb")) + checkVersion(); + if (args == null || args.length == 0) { + throw new ExceptionDBGit(getLang().getValue("errors", "checkout", "badCommand")); + } else if (args.length == 1) { + DBGit.getInstance().gitCheckout(args[0], null, cmdLine.hasOption("b")); + } else if (args.length == 2) { + DBGit.getInstance().gitCheckout(args[0], args[1], cmdLine.hasOption("b")); + } + + Builder builder = new CommandLine.Builder(); + + if (cmdLine.hasOption("u")) { + CmdDump dumpCommand = new CmdDump(); + builder.addOption(new Option("u", false, "")); + + if (cmdLine.hasOption("v")) { + builder.addOption(new Option("v", false, "")); + } + + dumpCommand.execute(builder.build()); + } else if (!cmdLine.hasOption("nodb")) { + CmdRestore restoreCommand = new CmdRestore(); + + if (cmdLine.hasOption("r")) { + builder.addOption(new Option("r", false, "")); + } + if (cmdLine.hasOption("noowner")) { + builder.addOption(new Option("noowner", false, "")); + } + if (cmdLine.hasOption("v")) { + builder.addOption(new Option("v", false, "")); + } + if (cmdLine.hasOption("s")) { + Option scriptOption = new Option("s", true, ""); + scriptOption.getValuesList().add(cmdLine.getOptionValue("s")); + builder.addOption(scriptOption); + } + + restoreCommand.execute(builder.build()); + } + + } + +} diff --git a/src/main/java/ru/fusionsoft/dbgit/command/CmdClone.java b/src/main/java/ru/fusionsoft/dbgit/command/CmdClone.java index 697407f..85a161d 100644 --- a/src/main/java/ru/fusionsoft/dbgit/command/CmdClone.java +++ b/src/main/java/ru/fusionsoft/dbgit/command/CmdClone.java @@ -6,10 +6,17 @@ import ru.fusionsoft.dbgit.core.DBGit; import ru.fusionsoft.dbgit.core.ExceptionDBGit; +import java.io.File; + public class CmdClone implements IDBGitCommand { private Options opts = new Options(); - + + public CmdClone() { + opts.addOption("directory", true, "subdirectory to clone into"/*getLang + ().getValue("help", "commit-a").toString()*/); + } + @Override public String getCommandName() { return "clone"; @@ -36,6 +43,7 @@ public void execute(CommandLine cmdLine) throws Exception { String link = ""; String remote = ""; + File directory = cmdLine.hasOption("directory") ? new File(cmdLine.getOptionValue("directory")) : null; if (args.length > 2) { throw new ExceptionDBGit(getLang().getValue("errors", "paramsNumberIncorrect")); } else if (args.length == 1) { @@ -45,7 +53,7 @@ public void execute(CommandLine cmdLine) throws Exception { remote = args[1]; } - DBGit.gitClone(link, remote); + DBGit.gitClone(link, remote, directory); } diff --git a/src/main/java/ru/fusionsoft/dbgit/command/CmdCommit.java b/src/main/java/ru/fusionsoft/dbgit/command/CmdCommit.java index 6c006be..e5fa306 100644 --- a/src/main/java/ru/fusionsoft/dbgit/command/CmdCommit.java +++ b/src/main/java/ru/fusionsoft/dbgit/command/CmdCommit.java @@ -54,7 +54,7 @@ public void execute(CommandLine cmdLine) throws Exception { checkVersion(); - ConsoleWriter.println(getLang().getValue("general", "commit", "commiting")); + ConsoleWriter.println(getLang().getValue("general", "commit", "commiting"), messageLevel); DBGitIndex.getInctance().addLinkToGit(); DBGitIndex.getInctance().addIgnoreToGit(); DBGit.getInstance().gitCommit(cmdLine.hasOption("a"), msg, filePath); diff --git a/src/main/java/ru/fusionsoft/dbgit/command/CmdDump.java b/src/main/java/ru/fusionsoft/dbgit/command/CmdDump.java index 16a0b1d..caec41b 100644 --- a/src/main/java/ru/fusionsoft/dbgit/command/CmdDump.java +++ b/src/main/java/ru/fusionsoft/dbgit/command/CmdDump.java @@ -1,108 +1,120 @@ -package ru.fusionsoft.dbgit.command; - -import java.sql.Timestamp; -import java.util.Map; - -import org.apache.commons.cli.CommandLine; -import org.apache.commons.cli.Options; - -import ru.fusionsoft.dbgit.core.DBGit; -import ru.fusionsoft.dbgit.core.DBGitIndex; -import ru.fusionsoft.dbgit.core.DBGitPath; -import ru.fusionsoft.dbgit.core.ExceptionDBGit; -import ru.fusionsoft.dbgit.core.GitMetaDataManager; -import ru.fusionsoft.dbgit.meta.IMapMetaObject; -import ru.fusionsoft.dbgit.meta.IMetaObject; -import ru.fusionsoft.dbgit.utils.ConsoleWriter; - -public class CmdDump implements IDBGitCommand { - private Options opts = new Options(); - - public CmdDump() { - opts.addOption("a", false, getLang().getValue("help", "dump-a").toString()); - opts.addOption("f", false, getLang().getValue("help", "dump-f").toString()); - opts.addOption("u", false, getLang().getValue("help", "dump-u").toString()); - } - - public String getCommandName() { - return "dump"; - } - - public String getParams() { - return ""; - } - - public String getHelperInfo() { - return getLang().getValue("help", "dump").toString(); - } - - public Options getOptions() { - return opts; - } - @Override - public void execute(CommandLine cmdLine) throws Exception { - Boolean isAddToGit = cmdLine.hasOption('a'); - Boolean isAllDump = cmdLine.hasOption('f'); - - ConsoleWriter.setDetailedLog(cmdLine.hasOption("v")); - - GitMetaDataManager gmdm = GitMetaDataManager.getInstance(); - - DBGitIndex index = DBGitIndex.getInctance(); - - if (!cmdLine.hasOption("u")) - checkVersion(); - - ConsoleWriter.detailsPrintLn(getLang().getValue("general", "dump", "checking")); - - IMapMetaObject fileObjs = gmdm.loadFileMetaDataForce(); - - ConsoleWriter.detailsPrintLn(getLang().getValue("general", "dump", "dumping")); - - for (IMetaObject obj : fileObjs.values()) { - Timestamp timestampBefore = new Timestamp(System.currentTimeMillis()); - ConsoleWriter.detailsPrintLn(getLang().getValue("general", "dump", "processing").withParams(obj.getName())); - String hash = obj.getHash(); - ConsoleWriter.detailsPrint(getLang().getValue("general", "dump", "hash") + ": " + hash + "\n", 2); - - ConsoleWriter.detailsPrint(getLang().getValue("general", "dump", "loading") + "\n", 2); - if (!gmdm.loadFromDB(obj)) { - ConsoleWriter.println(getLang().getValue("general", "dump", "cantFindInDb").withParams(obj.getName())); - continue; - } - ConsoleWriter.detailsPrint(getLang().getValue("general", "dump", "dbHash") + ": " + obj.getHash() + "\n", 2); - - if (isAllDump || !obj.getHash().equals(hash)) { - if (!obj.getHash().equals(hash)) - ConsoleWriter.detailsPrint(getLang().getValue("general", "dump", "hashesDifferent"), 2); - else - ConsoleWriter.detailsPrint(getLang().getValue("general", "dump", "fSwitchFound"), 2); - //сохранили файл если хеш разный - obj.saveToFile(); - ConsoleWriter.detailsPrintlnGreen(getLang().getValue("general", "ok")); - ConsoleWriter.detailsPrint(getLang().getValue("general", "dump", "addToIndex"), 2); - index.addItem(obj); - ConsoleWriter.detailsPrintlnGreen(getLang().getValue("general", "ok")); - - if (isAddToGit) { - ConsoleWriter.detailsPrint(getLang().getValue("general", "addToGit"), 2); - obj.addToGit(); - ConsoleWriter.detailsPrintlnGreen(getLang().getValue("general", "ok")); - } - } else { - ConsoleWriter.detailsPrint(getLang().getValue("general", "dump", "hashesMatch") + "\n", 2); - } - Timestamp timestampAfter = new Timestamp(System.currentTimeMillis()); - Long diff = timestampAfter.getTime() - timestampBefore.getTime(); - ConsoleWriter.detailsPrint(getLang().getValue("general", "time").withParams(diff.toString()), 2); - ConsoleWriter.detailsPrintLn(""); - } - - index.saveDBIndex(); - if (isAddToGit) { - ConsoleWriter.detailsPrintLn(getLang().getValue("general", "addToGit")); - index.addToGit(); - } - ConsoleWriter.println(getLang().getValue("general", "done")); - } -} +package ru.fusionsoft.dbgit.command; + +import java.sql.Timestamp; +import java.util.Map; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Options; + +import ru.fusionsoft.dbgit.core.*; +import ru.fusionsoft.dbgit.meta.IMapMetaObject; +import ru.fusionsoft.dbgit.meta.IMetaObject; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; + +public class CmdDump implements IDBGitCommand { + private Options opts = new Options(); + + public CmdDump() { + opts.addOption("a", false, getLang().getValue("help", "dump-a").toString()); + opts.addOption("f", false, getLang().getValue("help", "dump-f").toString()); + opts.addOption("u", false, getLang().getValue("help", "dump-u").toString()); + } + + public String getCommandName() { + return "dump"; + } + + public String getParams() { + return ""; + } + + public String getHelperInfo() { + return getLang().getValue("help", "dump").toString(); + } + + public Options getOptions() { + return opts; + } + @Override + public void execute(CommandLine cmdLine) throws Exception { + Boolean isAddToGit = cmdLine.hasOption('a'); + Boolean isAllDump = cmdLine.hasOption('f'); + + ConsoleWriter.setDetailedLog(cmdLine.hasOption("v")); + + GitMetaDataManager gmdm = GitMetaDataManager.getInstance(); + + DBGitIndex index = DBGitIndex.getInctance(); + + if (!cmdLine.hasOption("u")) + checkVersion(); + + ConsoleWriter.detailsPrintln(getLang().getValue("general", "dump", "checking"), messageLevel); + + IMapMetaObject fileObjs = gmdm.loadFileMetaDataForce(); + + ConsoleWriter.detailsPrintln(getLang().getValue("general", "dump", "dumping"), messageLevel); + + for (IMetaObject obj : fileObjs.values()) { + Timestamp timestampBefore = new Timestamp(System.currentTimeMillis()); + ConsoleWriter.detailsPrintln(getLang().getValue("general", "dump", "processing") + .withParams(obj.getName()) + , messageLevel + ); + String hash = obj.getHash(); + + ConsoleWriter.detailsPrintln(DBGitLang.getInstance() + .getValue("general", "dump", "hash") + .withParams(hash) + , messageLevel+1 + ); + + ConsoleWriter.detailsPrintln(getLang().getValue("general", "dump", "loading"), messageLevel+1); + if (!gmdm.loadFromDB(obj)) { + ConsoleWriter.println(getLang().getValue("general", "dump", "cantFindInDb") + .withParams(obj.getName()) + , messageLevel + ); + continue; + } + ConsoleWriter.detailsPrintln(getLang().getValue("general", "dump", "dbHash") + .withParams(obj.getHash()), messageLevel+1 + ); + + if (isAllDump || !obj.getHash().equals(hash)) { + if (!obj.getHash().equals(hash)) + ConsoleWriter.detailsPrintln(getLang().getValue("general", "dump", "hashesDifferent") + , messageLevel+1 + ); + else + ConsoleWriter.detailsPrintln(getLang().getValue("general", "dump", "fSwitchFound") + , messageLevel+1 + ); + //сохранили файл если хеш разный + obj.saveToFile(); + ConsoleWriter.detailsPrintGreen(getLang().getValue("general", "ok")); + ConsoleWriter.detailsPrintln(getLang().getValue("general", "dump", "addToIndex"), messageLevel+1); + index.addItem(obj); + ConsoleWriter.detailsPrintGreen(getLang().getValue("general", "ok")); + + if (isAddToGit) { + ConsoleWriter.detailsPrintln(getLang().getValue("general", "addToGit"), messageLevel+1); + obj.addToGit(); + ConsoleWriter.detailsPrintGreen(getLang().getValue("general", "ok")); + } + } else { + ConsoleWriter.detailsPrintln(getLang().getValue("general", "dump", "hashesMatch"), messageLevel+1); + } + Timestamp timestampAfter = new Timestamp(System.currentTimeMillis()); + Long diff = timestampAfter.getTime() - timestampBefore.getTime(); + ConsoleWriter.detailsPrint(getLang().getValue("general", "time").withParams(diff.toString())); + } + + index.saveDBIndex(); + if (isAddToGit) { + ConsoleWriter.detailsPrintln(getLang().getValue("general", "addToGit"), messageLevel+1); + index.addToGit(); + } + ConsoleWriter.println(getLang().getValue("general", "done"), messageLevel); + } +} diff --git a/src/main/java/ru/fusionsoft/dbgit/command/CmdFetch.java b/src/main/java/ru/fusionsoft/dbgit/command/CmdFetch.java index 2779dc5..f7cf5c0 100644 --- a/src/main/java/ru/fusionsoft/dbgit/command/CmdFetch.java +++ b/src/main/java/ru/fusionsoft/dbgit/command/CmdFetch.java @@ -37,7 +37,7 @@ public void execute(CommandLine cmdLine) throws Exception { String[] args = cmdLine.getArgs(); String remote = ""; - ConsoleWriter.println(getLang().getValue("general", "fetch", "fetching")); + ConsoleWriter.println(getLang().getValue("general", "fetch", "fetching"), messageLevel); if (args.length == 1) { remote = args[0]; diff --git a/src/main/java/ru/fusionsoft/dbgit/command/CmdHelp.java b/src/main/java/ru/fusionsoft/dbgit/command/CmdHelp.java index fedfc7d..e146cf4 100644 --- a/src/main/java/ru/fusionsoft/dbgit/command/CmdHelp.java +++ b/src/main/java/ru/fusionsoft/dbgit/command/CmdHelp.java @@ -31,7 +31,7 @@ public Options getOptions() { } @Override public void execute(CommandLine cmdLine) throws Exception { - ConsoleWriter.println(getLang().getValue("help", "common")); + ConsoleWriter.println(getLang().getValue("help", "common"), messageLevel); } } diff --git a/src/main/java/ru/fusionsoft/dbgit/command/CmdInit.java b/src/main/java/ru/fusionsoft/dbgit/command/CmdInit.java index 8aace6b..f57e10c 100644 --- a/src/main/java/ru/fusionsoft/dbgit/command/CmdInit.java +++ b/src/main/java/ru/fusionsoft/dbgit/command/CmdInit.java @@ -42,7 +42,6 @@ public void execute(CommandLine cmdLine) throws Exception { } DBGit.gitInit(dir); - } } diff --git a/src/main/java/ru/fusionsoft/dbgit/command/CmdLink.java b/src/main/java/ru/fusionsoft/dbgit/command/CmdLink.java index 02b7900..f4f343a 100644 --- a/src/main/java/ru/fusionsoft/dbgit/command/CmdLink.java +++ b/src/main/java/ru/fusionsoft/dbgit/command/CmdLink.java @@ -21,6 +21,7 @@ public class CmdLink implements IDBGitCommand { public CmdLink() { opts.addOption("d", false, getLang().getValue("help", "link-d").toString()); + opts.addOption("ls", false, getLang().getValue("help", "link-ls").toString()); } public String getCommandName() { @@ -43,21 +44,27 @@ public Options getOptions() { @Override public void execute(CommandLine cmdLine) throws Exception { + DBConnection conn = DBConnection.getInstance(false); + if(cmdLine.hasOption("ls")) { +// ConsoleWriter.printlnGreen(DBConnection.loadFileDBLink(new Properties()), messageLevel); + System.out.println(DBConnection.loadFileDBLink(new Properties())); + return; + } + + String[] args = cmdLine.getArgs(); - if(args == null || args.length == 0) { throw new ExceptionDBGit(getLang().getValue("errors", "link", "emptyLink")); } - + String url = args[0]; Properties props = CreateProperties(Arrays.copyOfRange(args, 1, args.length)); - - DBConnection conn = DBConnection.getInstance(false); - if(conn.testingConnection(url, props)) { - DBConnection.createFileDBLink(url, props, cmdLine.hasOption("d")); - DBGitPath.createDefaultDbignore(DBGitPath.getFullPath(), url, props); - } + DBConnection.createFileDBLink(url, props, cmdLine.hasOption("d")); + DBGitPath.createDefaultDbignore(DBGitPath.getFullPath(), url, props); + if(!conn.testingConnection(url, props)) { + throw new ExceptionDBGit("Db connection link seems not working"); + } } public Properties CreateProperties(String[] args) { diff --git a/src/main/java/ru/fusionsoft/dbgit/command/CmdRestore.java b/src/main/java/ru/fusionsoft/dbgit/command/CmdRestore.java index 0907889..07eb480 100644 --- a/src/main/java/ru/fusionsoft/dbgit/command/CmdRestore.java +++ b/src/main/java/ru/fusionsoft/dbgit/command/CmdRestore.java @@ -1,167 +1,228 @@ -package ru.fusionsoft.dbgit.command; - -import java.io.File; -import java.io.FileOutputStream; -import java.nio.file.Files; -import java.text.SimpleDateFormat; -import java.util.Date; - -import com.google.common.collect.Lists; -import org.apache.commons.cli.CommandLine; -import org.apache.commons.cli.Options; - -import ru.fusionsoft.dbgit.adapters.AdapterFactory; -import ru.fusionsoft.dbgit.adapters.IDBAdapter; -import ru.fusionsoft.dbgit.core.*; -import ru.fusionsoft.dbgit.meta.*; -import ru.fusionsoft.dbgit.utils.ConsoleWriter; -import ru.fusionsoft.dbgit.utils.LoggerUtil; - -public class CmdRestore implements IDBGitCommand { - private Options opts = new Options(); - - public CmdRestore() { - opts.addOption("s", true, getLang().getValue("help", "restore-s").toString()); - opts.addOption("r", false, getLang().getValue("help", "restore-r").toString()); - } - - public String getCommandName() { - return "restore"; - } - - public String getParams() { - return ""; - } - - public String getHelperInfo() { - return getLang().getValue("help", "restore").toString(); - } - - public Options getOptions() { - return opts; - } - - @Override - public void execute(CommandLine cmdLine) throws Exception { - - try { - AdapterFactory.createAdapter(); - } catch (NullPointerException e) { - ConsoleWriter.println(getLang().getValue("errors", "restore", "cantConnect")); - System.exit(0); - } - GitMetaDataManager gmdm = GitMetaDataManager.getInstance(); - IMapMetaObject dbObjs = gmdm.loadDBMetaData(); - IMapMetaObject fileObjs = gmdm.loadFileMetaData(); - IMapMetaObject updateObjs = new TreeMapMetaObject(); - IMapMetaObject deleteObjs = new TreeMapMetaObject(); - - SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss"); - File scriptFile = new File(DBGitPath.getScriptsPath() + "script-" + format.format(new Date()) + ".sql"); - - //Console output - ConsoleWriter.setDetailedLog(cmdLine.hasOption("v")); - - boolean toMakeBackup = DBGitConfig.getInstance().getBoolean("core", "TO_MAKE_BACKUP", true); - if(toMakeBackup) ConsoleWriter.println(getLang().getValue("general", "restore", "willMakeBackup").toString()); - - if (cmdLine.hasOption("r")) { ConsoleWriter.println(getLang().getValue("general", "restore", "toMakeChanges").toString()); } - else { ConsoleWriter.println(getLang().getValue("general", "restore", "notMakeChanges").withParams(scriptFile.getAbsolutePath())); } - - //File output - FileOutputStream fop = null; - FileOutputStream scriptOutputStream = null; - - DBGitPath.createScriptsDir(); - if (!scriptFile.exists()) { scriptFile.createNewFile(); } - scriptOutputStream = new FileOutputStream(scriptFile); - - IDBAdapter adapter = AdapterFactory.createAdapter(); - adapter.setDumpSqlCommand(scriptOutputStream, cmdLine.hasOption("r")); - - //delete that not present in HEAD - try { - DBGitIndex index = DBGitIndex.getInctance(); - DBGitIgnore ignore = DBGitIgnore.getInstance(); - - ConsoleWriter.println(getLang().getValue("general", "restore", "seekingToRemove")); - for (ItemIndex item : Lists.newArrayList(index.getTreeItems().values())) { - if (ignore.matchOne(item.getName())) continue; - if (item.getIsDelete()) { - if( !dbObjs.containsKey(item.getName()) ) { - ConsoleWriter.println(getLang().getValue("general", "restore", "notExists").withParams(item.getName())); - index.removeItem(item.getName()); - } else { - try { - IMetaObject obj = MetaObjectFactory.createMetaObject(item.getName()); - gmdm.loadFromDB(obj); - if (item.getHash().equals(obj.getHash())) { - deleteObjs.put(obj); - if (deleteObjs.size() == 1) ConsoleWriter.println(getLang().getValue("general", "restore", "toRemove")); - ConsoleWriter.println(" " + obj.getName()); - } - } catch(ExceptionDBGit e) { - LoggerUtil.getGlobalLogger().error(getLang().getValue("errors", "restore", "cantConnect") + ": " + item.getName(), e); - } - } - } - } - if (deleteObjs.size() == 0){ - ConsoleWriter.println(getLang().getValue("general", "restore", "nothingToRemove")); - } else { - if (cmdLine.hasOption("r")) ConsoleWriter.println(getLang().getValue("general", "restore", "removing")); - gmdm.deleteDataBase(deleteObjs, true); - } - - ConsoleWriter.println(getLang().getValue("general", "restore", "seekingToRestore")); - for (IMetaObject obj : fileObjs.values()) { - Boolean isRestore = false; - try { - IMetaObject dbObj = IMetaObject.create(obj.getName()); - gmdm.loadFromDB(dbObj); - isRestore = !dbObj.getHash().equals(obj.getHash()); - } catch (ExceptionDBGit e) { - isRestore = true; - e.printStackTrace(); - } catch (ExceptionDBGitRunTime e) { - isRestore = true; - e.printStackTrace(); - } - if (isRestore) { - //запомнили файл если хеш разный или объекта нет - updateObjs.put(obj); - - if (updateObjs.size() == 1) ConsoleWriter.println(getLang().getValue("general", "restore", "toRestore")); - ConsoleWriter.println(" " + obj.getName()); - } - } - - if (updateObjs.size() == 0){ - ConsoleWriter.println(getLang().getValue("general", "restore", "nothingToRestore")); - } - if (cmdLine.hasOption("r")) { - ConsoleWriter.println(getLang().getValue("general", "restore", "restoring")); - } - gmdm.restoreDataBase(updateObjs); - - } finally { - if (scriptOutputStream != null) { - scriptOutputStream.flush(); - scriptOutputStream.close(); - } - if (cmdLine.hasOption("s")) { - String scriptName = cmdLine.getOptionValue("s"); - ConsoleWriter.detailsPrintLn(getLang().getValue("general", "restore", "scriptWillSaveTo").withParams(scriptName)); - - File file = new File(scriptName); - if (!file.exists()) { - Files.copy(scriptFile.toPath(), file.toPath()); - ConsoleWriter.detailsPrintLn(getLang().getValue("general", "restore", "created").withParams(scriptName)); - } - } - } - ConsoleWriter.println(getLang().getValue("general", "done")); - } - - -} +package ru.fusionsoft.dbgit.command; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Map; +import java.util.stream.Collectors; + +import com.diogonunes.jcdp.color.api.Ansi; +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Options; + +import ru.fusionsoft.dbgit.adapters.AdapterFactory; +import ru.fusionsoft.dbgit.adapters.IDBAdapter; +import ru.fusionsoft.dbgit.core.*; +import ru.fusionsoft.dbgit.meta.*; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; +import ru.fusionsoft.dbgit.utils.LoggerUtil; + +public class CmdRestore implements IDBGitCommand { + private Options opts = new Options(); + + public CmdRestore() { + opts.addOption("s", true, getLang().getValue("help", "restore-s").toString()); + opts.addOption("r", false, getLang().getValue("help", "restore-r").toString()); + } + + public String getCommandName() { + return "restore"; + } + + public String getParams() { + return ""; + } + + public String getHelperInfo() { + return getLang().getValue("help", "restore").toString(); + } + + public Options getOptions() { + return opts; + } + + @Override + public void execute(CommandLine cmdLine) throws Exception { + IDBAdapter adapter = null; + File autoScriptFile = createScriptFile(); + FileOutputStream scriptOutputStream = new FileOutputStream(autoScriptFile); + GitMetaDataManager gmdm = GitMetaDataManager.getInstance(); + + ConsoleWriter.setDetailedLog(cmdLine.hasOption("v")); + ConsoleWriter.println(getLang().getValue("general", "restore", "do"), 0); + + boolean toMakeChanges = cmdLine.hasOption("r"); + boolean toMakeBackup = DBGitConfig.getInstance().getBoolean("core", "TO_MAKE_BACKUP", true); + // from cmdLine to temporary config bypass + // can be used as other config data by restore adapters + DBGitConfig.getInstance().setToIgnoreOnwer(cmdLine.hasOption("noowner")); + + try { + adapter = AdapterFactory.createAdapter(); + adapter.setDumpSqlCommand(scriptOutputStream, toMakeChanges); + } catch (NullPointerException e) { + ConsoleWriter.println(getLang().getValue("errors", "restore", "cantConnect"), messageLevel); + System.exit(0); + } + + IMapMetaObject dbObjs = gmdm.loadDBMetaData(); + IMapMetaObject fileObjs = gmdm.loadFileMetaData(); + IMapMetaObject updateObjs = new TreeMapMetaObject(); + IMapMetaObject deleteObjs = new TreeMapMetaObject(); + + if (toMakeBackup) { ConsoleWriter.printlnColor(getLang().getValue("general", "restore", "willMakeBackup").toString(), Ansi.FColor.GREEN, messageLevel+1); } + else { ConsoleWriter.printlnColor(getLang().getValue("general", "restore", "wontMakeBackup").toString(), Ansi.FColor.GREEN, messageLevel+1); } + if (toMakeChanges) { ConsoleWriter.printlnColor(getLang().getValue("general", "restore", "toMakeChanges").toString(), Ansi.FColor.GREEN, messageLevel+1); } + else { ConsoleWriter.printlnColor(getLang().getValue("general", "restore", "notMakeChanges").withParams(autoScriptFile.getAbsolutePath()), Ansi.FColor.GREEN, messageLevel+1); } + + //delete that not present in HEAD + try { + DBGitIndex index = DBGitIndex.getInctance(); + DBGitIgnore ignore = DBGitIgnore.getInstance(); + + ConsoleWriter.println(getLang().getValue("general", "restore", "seekingToRemove"),1); +// ConsoleWriter.print(getLang().getValue("general", "restore", "toRemove")); + + for ( ItemIndex item : index.getTreeItems().values() ) { + if ( ignore.matchOne(item.getName()) ) continue; + + if ( item.getIsDelete() ) { + + if ( !dbObjs.containsKey(item.getName()) ) { + ConsoleWriter.println(getLang().getValue("general", "restore", "notExists").withParams(item.getName()), 2); + index.removeItem(item.getName()); + } else { + + try { + IMetaObject obj = MetaObjectFactory.createMetaObject(item.getName()); + gmdm.loadFromDB(obj); + if (item.getHash().equals(obj.getHash())) { + deleteObjs.put(obj); + + ConsoleWriter.println(getLang().getValue("general", "restore", "objectToRemove").withParams(obj.getName()), 2); + } + } catch(ExceptionDBGit e) { + throw e; + //LoggerUtil.getGlobalLogger().error(getLang().getValue("errors", "restore", "cantConnect") + ": " + item.getName(), e); + } + } + } + } + if (deleteObjs.size() == 0) ConsoleWriter.println(getLang().getValue("general", "restore", "nothingToRemove").toString(), 2); + + + ConsoleWriter.println(getLang().getValue("general", "restore", "seekingToRestore"),1); + for (IMetaObject obj : fileObjs.values()) { + + //запомнили файл если хеш разный или объекта нет + if (checkNeedsRestore(obj)) { + updateObjs.put(obj); +// if (updateObjs.size() == 1){ +// ConsoleWriter.print(getLang().getValue("general", "restore", "toRestore")); +// } + ConsoleWriter.println(obj.getName(), 2); + } + } + if (updateObjs.size() == 0){ + ConsoleWriter.println(getLang().getValue("general", "restore", "nothingToRestore").toString(), 2); + } + + // to fix pk constraint re-creation error + // collect other file objects that depend on update objects + // to re-create their fk constraints too, so we: + + // 0. enrich update list with fk-dependant objects from database + // 1. drop all of constraints + // 2. re-create all constraints in default sorted order + + // # steps 1,2 are in GitMetaDataManager::restoreDatabase + + ConsoleWriter.println(getLang().getValue("general", "restore", "seekingToRestoreAdditional"),1); + Map affectedTables = new TreeMapMetaObject(); + Map foundTables = new TreeMapMetaObject(); + do { + foundTables = + dbObjs.values().stream() + .filter(excluded -> { + return excluded instanceof MetaTable + && ! updateObjs.containsKey(excluded.getName()) + && updateObjs.values().stream().anyMatch(excluded::dependsOn); + }) + .collect(Collectors.toMap(IMetaObject::getName, val -> val)); + affectedTables.putAll(foundTables); + updateObjs.putAll(foundTables); + } while (!foundTables.isEmpty()); + + if(affectedTables.isEmpty()){ + ConsoleWriter.println(getLang().getValue("general", "restore", "nothingToRestoreAdditional"), 2); + } else { + affectedTables.forEach((k,v)->ConsoleWriter.println(k, 2)); + } + + + + if(toMakeBackup && toMakeChanges) { + IMapMetaObject backupObjs = new TreeMapMetaObject(); + backupObjs.putAll(deleteObjs); + backupObjs.putAll(updateObjs); + adapter.getBackupAdapterFactory().getBackupAdapter(adapter).backupDatabase(backupObjs); + } + + if (deleteObjs.size() != 0){ + if (toMakeChanges) ConsoleWriter.println(getLang().getValue("general", "restore", "removing"),1); + gmdm.deleteDataBase(deleteObjs, true); + } + + + if (toMakeChanges) { + ConsoleWriter.println(getLang().getValue("general", "restore", "restoring"),1); + } + gmdm.restoreDataBase(updateObjs); + + + } finally { + if (scriptOutputStream != null) { + scriptOutputStream.flush(); + scriptOutputStream.close(); + } + if (cmdLine.hasOption("s")) { + String scriptName = cmdLine.getOptionValue("s"); + File file = new File(scriptName); + + if (!file.exists()) { + ConsoleWriter.println(getLang().getValue("general", "restore", "scriptWillSaveTo").withParams(scriptName),1); + Files.copy(autoScriptFile.toPath(), file.toPath()); + } else { + ConsoleWriter.println(getLang().getValue("errors", "restore", "fileAlreadyExists").withParams(scriptName),1); + } + } + } + ConsoleWriter.println(getLang().getValue("general", "done"), messageLevel); + } + + private boolean checkNeedsRestore(IMetaObject obj){ + boolean isRestore = false; + try { + IMetaObject dbObj = IMetaObject.create(obj.getName()); + final boolean exists = GitMetaDataManager.getInstance().loadFromDB(dbObj); + isRestore = !exists || !dbObj.getHash().equals(obj.getHash()); + } catch (ExceptionDBGit e) { + throw new ExceptionDBGitRunTime(e); +// isRestore = true; +// e.printStackTrace(); + } + return isRestore; + } + private File createScriptFile() throws ExceptionDBGit, IOException { + DBGitPath.createScriptsDir(); + SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss"); + File scriptFile = new File(DBGitPath.getScriptsPath() + "script-" + format.format(new Date()) + ".sql"); +// System.out.println(scriptFile.getAbsolutePath()); + if (!scriptFile.exists()) { scriptFile.createNewFile(); } + return scriptFile; + } + +} diff --git a/src/main/java/ru/fusionsoft/dbgit/command/CmdRm.java b/src/main/java/ru/fusionsoft/dbgit/command/CmdRm.java index 0213c6b..3855497 100644 --- a/src/main/java/ru/fusionsoft/dbgit/command/CmdRm.java +++ b/src/main/java/ru/fusionsoft/dbgit/command/CmdRm.java @@ -1,119 +1,129 @@ -package ru.fusionsoft.dbgit.command; - -import java.sql.Timestamp; -import java.util.stream.Collectors; - -import org.apache.commons.cli.CommandLine; -import org.apache.commons.cli.Options; - -import ru.fusionsoft.dbgit.core.*; -import ru.fusionsoft.dbgit.meta.IMapMetaObject; -import ru.fusionsoft.dbgit.meta.IMetaObject; -import ru.fusionsoft.dbgit.meta.MetaObjectFactory; -import ru.fusionsoft.dbgit.meta.TreeMapMetaObject; -import ru.fusionsoft.dbgit.utils.ConsoleWriter; -import ru.fusionsoft.dbgit.utils.MaskFilter; - -public class CmdRm implements IDBGitCommand { - private Options opts = new Options(); - - public CmdRm() { - opts.addOption("db", false, getLang().getValue("help", "rm-db").toString()); - opts.addOption("idx", false, getLang().getValue("help", "rm-idx").toString()); - } - - public String getCommandName() { - return "rm"; - } - - public String getParams() { - return ""; - } - - public String getHelperInfo() { - return getLang().getValue("help", "rm").toString(); - } - - public Options getOptions() { - return opts; - } - - @Override - public void execute(CommandLine cmdLine) throws Exception { - if (cmdLine.getArgs().length == 0) { - throw new ExceptionDBGit(getLang().getValue("errors", "rm", "badCommand")); - } - - checkVersion(); - - ConsoleWriter.setDetailedLog(cmdLine.hasOption("v")); - boolean forgetImmediately = cmdLine.hasOption("idx") && !cmdLine.hasOption("db"); - - String nameObj = cmdLine.getArgs()[0]; - MaskFilter maskAdd = new MaskFilter(nameObj); - - DBGitIndex index = DBGitIndex.getInctance(); - - ConsoleWriter.detailsPrintLn(getLang().getValue("general", "rm", "checking")); - - GitMetaDataManager gmdm = GitMetaDataManager.getInstance(); - IMapMetaObject dbObjs = gmdm.loadFileMetaDataForce(); - dbObjs.putAll(gmdm.loadDBMetaData()); - - IMapMetaObject deleteObjs = new TreeMapMetaObject(); - - Integer countDelete = 0; - - ConsoleWriter.detailsPrintLn(getLang().getValue("general", "rm", "deleting")); - for (ItemIndex idxItem : index.getTreeItems().values()) { - if (maskAdd.match(idxItem.getName())) { - Timestamp timestampBefore = new Timestamp(System.currentTimeMillis()); - ConsoleWriter.detailsPrintLn(getLang().getValue("general", "rm", "processing").withParams(idxItem.getName())); - ConsoleWriter.detailsPrint(getLang().getValue("general", "rm", "removingFromGit"), 2); - - IMetaObject metaObject = dbObjs.get(idxItem.getName()); - if(metaObject != null){ - deleteObjs.put(metaObject); - countDelete += metaObject.removeFromGit(); - } else { - countDelete += gmdm.removeFromGit(idxItem); - metaObject = IMetaObject.create(idxItem.getName()); - } - - ConsoleWriter.detailsPrintlnGreen(getLang().getValue("general", "ok")); - ConsoleWriter.detailsPrint(getLang().getValue("general", "rm", "markingToDelete") + " ... ", 2); - index.markItemToDelete(metaObject); - ConsoleWriter.detailsPrintlnGreen(getLang().getValue("general", "ok")); - - - Timestamp timestampAfter = new Timestamp(System.currentTimeMillis()); - Long diff = timestampAfter.getTime() - timestampBefore.getTime(); - ConsoleWriter.detailsPrint(getLang().getValue("general", "time").withParams(diff.toString()), 2); - ConsoleWriter.detailsPrintLn(""); - } - } - if (forgetImmediately) { - ConsoleWriter.detailsPrint(getLang().getValue("general", "rm", "removingFromIndex"), 2); - index.getTreeItems().values().stream().filter(ItemIndex::getIsDelete).collect(Collectors.toList()).forEach(x->index.getTreeItems().remove(x.getName())); - index.saveDBIndex(); - index.addToGit(); - ConsoleWriter.detailsPrintlnGreen(getLang().getValue("general", "ok")); - } - - if (cmdLine.hasOption("db")) { - ConsoleWriter.detailsPrint(getLang().getValue("general", "rm", "removingFromDb"), 2); - gmdm.deleteDataBase(deleteObjs, true); - ConsoleWriter.detailsPrintlnGreen(getLang().getValue("general", "ok")); - } - - if (countDelete > 0) { - index.saveDBIndex(); - index.addToGit(); - } else { - ConsoleWriter.printlnRed(getLang().getValue("errors", "rm", "cantFindFile").withParams(nameObj)); - } - ConsoleWriter.println(getLang().getValue("general", "done")); - } - - -} +package ru.fusionsoft.dbgit.command; + +import java.sql.Timestamp; +import java.util.stream.Collectors; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Options; + +import ru.fusionsoft.dbgit.core.*; +import ru.fusionsoft.dbgit.meta.IMapMetaObject; +import ru.fusionsoft.dbgit.meta.IMetaObject; +import ru.fusionsoft.dbgit.meta.MetaObjectFactory; +import ru.fusionsoft.dbgit.meta.TreeMapMetaObject; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; +import ru.fusionsoft.dbgit.utils.MaskFilter; + +public class CmdRm implements IDBGitCommand { + private Options opts = new Options(); + + public CmdRm() { + opts.addOption("db", false, getLang().getValue("help", "rm-db").toString()); + opts.addOption("idx", false, getLang().getValue("help", "rm-idx").toString()); + } + + public String getCommandName() { + return "rm"; + } + + public String getParams() { + return ""; + } + + public String getHelperInfo() { + return getLang().getValue("help", "rm").toString(); + } + + public Options getOptions() { + return opts; + } + + @Override + public void execute(CommandLine cmdLine) throws Exception { + if (cmdLine.getArgs().length == 0) { + throw new ExceptionDBGit(getLang().getValue("errors", "rm", "badCommand")); + } + + checkVersion(); + + ConsoleWriter.setDetailedLog(cmdLine.hasOption("v")); + boolean forgetImmediately = cmdLine.hasOption("idx") && !cmdLine.hasOption("db"); + + String nameObj = cmdLine.getArgs()[0]; + MaskFilter maskAdd = new MaskFilter(nameObj); + + DBGitIndex index = DBGitIndex.getInctance(); + + ConsoleWriter.detailsPrintln(getLang().getValue("general", "rm", "checking"), messageLevel+1); + + GitMetaDataManager gmdm = GitMetaDataManager.getInstance(); + IMapMetaObject dbObjs = gmdm.loadFileMetaDataForce(); + dbObjs.putAll(gmdm.loadDBMetaData()); + + IMapMetaObject deleteObjs = new TreeMapMetaObject(); + + Integer countDelete = 0; + + ConsoleWriter.detailsPrintln(getLang().getValue("general", "rm", "deleting"), messageLevel+1); + for (ItemIndex idxItem : index.getTreeItems().values()) { + if (maskAdd.match(idxItem.getName())) { + Timestamp timestampBefore = new Timestamp(System.currentTimeMillis()); + ConsoleWriter.detailsPrintln(getLang().getValue("general", "rm", "processing") + .withParams(idxItem.getName()) + , messageLevel+1 + ); + ConsoleWriter.detailsPrintln(getLang().getValue("general", "rm", "removingFromGit"), messageLevel+2); + + IMetaObject metaObject = dbObjs.get(idxItem.getName()); + if(metaObject != null){ + deleteObjs.put(metaObject); + countDelete += metaObject.removeFromGit(); + } else { + countDelete += gmdm.removeFromGit(idxItem); + metaObject = IMetaObject.create(idxItem.getName()); + } + + ConsoleWriter.detailsPrintGreen(getLang().getValue("general", "ok")); + ConsoleWriter.detailsPrintln(getLang().getValue("general", "rm", "markingToDelete") + " ... ", messageLevel+2); + index.markItemToDelete(metaObject); + ConsoleWriter.detailsPrintGreen(getLang().getValue("general", "ok")); + + + Timestamp timestampAfter = new Timestamp(System.currentTimeMillis()); + Long diff = timestampAfter.getTime() - timestampBefore.getTime(); + ConsoleWriter.detailsPrint(getLang().getValue("general", "time").withParams(diff.toString())); + } + } + if (forgetImmediately) { + ConsoleWriter.detailsPrintln(getLang().getValue("general", "rm", "removingFromIndex"), messageLevel+1); + index.getTreeItems().values() + .stream() + .filter(ItemIndex::getIsDelete) + .collect(Collectors.toList()) + .forEach( + x->index.getTreeItems() + .remove(x.getName()) + ); + + index.saveDBIndex(); + index.addToGit(); + ConsoleWriter.detailsPrintGreen(getLang().getValue("general", "ok")); + } + + if (cmdLine.hasOption("db")) { + ConsoleWriter.detailsPrintln(getLang().getValue("general", "rm", "removingFromDb"), messageLevel+1); + gmdm.deleteDataBase(deleteObjs, true); + ConsoleWriter.detailsPrintGreen(getLang().getValue("general", "ok")); + } + + if (countDelete > 0) { + index.saveDBIndex(); + index.addToGit(); + } else { + ConsoleWriter.printlnRed(getLang().getValue("errors", "rm", "cantFindFile").withParams(nameObj), messageLevel+1); + } + ConsoleWriter.println(getLang().getValue("general", "done"), messageLevel); + } + + +} diff --git a/src/main/java/ru/fusionsoft/dbgit/command/CmdStatus.java b/src/main/java/ru/fusionsoft/dbgit/command/CmdStatus.java index b3648e0..a5feb01 100644 --- a/src/main/java/ru/fusionsoft/dbgit/command/CmdStatus.java +++ b/src/main/java/ru/fusionsoft/dbgit/command/CmdStatus.java @@ -7,14 +7,9 @@ import com.diogonunes.jcdp.color.api.Ansi.FColor; -import ru.fusionsoft.dbgit.core.DBGit; -import ru.fusionsoft.dbgit.core.DBGitIndex; -import ru.fusionsoft.dbgit.core.DBGitPath; -import ru.fusionsoft.dbgit.core.GitMetaDataManager; -import ru.fusionsoft.dbgit.core.SchemaSynonym; +import ru.fusionsoft.dbgit.core.*; import ru.fusionsoft.dbgit.meta.IMapMetaObject; import ru.fusionsoft.dbgit.meta.IMetaObject; -import ru.fusionsoft.dbgit.meta.MetaTableData; import ru.fusionsoft.dbgit.meta.TreeMapMetaObject; import ru.fusionsoft.dbgit.utils.ConsoleWriter; @@ -56,23 +51,23 @@ public void execute(CommandLine cmdLine) throws Exception { DBGit dbGit = DBGit.getInstance(); boolean hasConflicts = DBGitIndex.getInctance().hasConflicts(); String repoVersion = DBGitIndex.getInctance().getRepoVersion(); - ConsoleWriter.println(getLang().getValue("general", "status", "repVersion").withParams(repoVersion)); - ConsoleWriter.println(getLang().getValue("general", "status", "dbgitVersion").withParams(DBGitIndex.VERSION)); - + ConsoleWriter.println(getLang().getValue("general", "status", "repVersion").withParams(repoVersion), messageLevel); + ConsoleWriter.println(getLang().getValue("general", "status", "dbgitVersion").withParams(DBGitIndex.VERSION), messageLevel); + if (!DBGitIndex.getInctance().isCorrectVersion()) - ConsoleWriter.println(getLang().getValue("general", "status", "differentVersions")); + ConsoleWriter.println(getLang().getValue("general", "status", "differentVersions"), messageLevel); if (hasConflicts) { - ConsoleWriter.println(getLang().getValue("general", "status", "conflicts")); + ConsoleWriter.println(getLang().getValue("general", "status", "conflicts"), messageLevel); } SchemaSynonym ss = SchemaSynonym.getInstance(); if (ss.getCountSynonym() > 0) { - ConsoleWriter.printlnGreen(getLang().getValue("general", "status", "usedSynonyms")); - ConsoleWriter.printlnGreen(getLang().getValue("general", "status", "synSchema")); + ConsoleWriter.printlnGreen(getLang().getValue("general", "status", "usedSynonyms"), messageLevel); + ConsoleWriter.printlnGreen(getLang().getValue("general", "status", "synSchema"), messageLevel); for (Entry el : ss.getMapSchema().entrySet()) { - ConsoleWriter.println(el.getKey() + " - " + el.getValue()); + ConsoleWriter.println(el.getKey() + " - " + el.getValue(), messageLevel+1); } } @@ -107,40 +102,40 @@ public void execute(CommandLine cmdLine) throws Exception { addedObjs.put(fileObjs.get(name)); } - ConsoleWriter.println(getLang().getValue("general", "status", "changesToCommit")); + ConsoleWriter.println(getLang().getValue("general", "status", "changesToCommit"), messageLevel); for(IMetaObject obj : addedObjs.values()) { - printObect(obj, FColor.GREEN, 1); + printObect(obj, FColor.GREEN, messageLevel+1); } - ConsoleWriter.println(" "); + ConsoleWriter.printLineBreak(); - ConsoleWriter.println(getLang().getValue("general", "status", "notStaged")); + ConsoleWriter.println(getLang().getValue("general", "status", "notStaged"), messageLevel); for(IMetaObject obj : changeObjs.values()) { printObect(obj, FColor.RED, 1); } - ConsoleWriter.println(" "); - + ConsoleWriter.printLineBreak(); + - ConsoleWriter.println(getLang().getValue("general", "status", "untracked")); + ConsoleWriter.println(getLang().getValue("general", "status", "untracked"), messageLevel); for (String name : dbObjs.keySet()) { if (!fileObjs.containsKey(name)) { - ConsoleWriter.println(name, 1); + ConsoleWriter.println(name, messageLevel+1); } } - ConsoleWriter.println(" "); + ConsoleWriter.printLineBreak(); - ConsoleWriter.println(getLang().getValue("general", "status", "localNotStaged")); + ConsoleWriter.println(getLang().getValue("general", "status", "localNotStaged"), messageLevel); for (String modified : DBGit.getInstance().getModifiedFiles()) { - ConsoleWriter.printlnColor(modified, FColor.RED, 1); + ConsoleWriter.printlnColor(modified, FColor.RED, messageLevel+1); } - ConsoleWriter.println(" "); + ConsoleWriter.printLineBreak(); - ConsoleWriter.println(getLang().getValue("general", "status", "localToCommit")); + ConsoleWriter.println(getLang().getValue("general", "status", "localToCommit"), messageLevel); for (String modified : DBGit.getInstance().getChanged()) { - ConsoleWriter.printlnColor(modified, FColor.GREEN, 1); + ConsoleWriter.printlnColor(modified, FColor.GREEN , messageLevel+1); } - ConsoleWriter.println(" "); + ConsoleWriter.printLineBreak(); } public void printObect(IMetaObject obj, FColor color, Integer level) { diff --git a/src/main/java/ru/fusionsoft/dbgit/command/CmdSynonymSchema.java b/src/main/java/ru/fusionsoft/dbgit/command/CmdSynonymSchema.java index e1e41a9..b4febfe 100644 --- a/src/main/java/ru/fusionsoft/dbgit/command/CmdSynonymSchema.java +++ b/src/main/java/ru/fusionsoft/dbgit/command/CmdSynonymSchema.java @@ -39,9 +39,9 @@ public void execute(CommandLine cmdLine) throws Exception { Boolean isShow = cmdLine.hasOption('s'); if (isShow) { - ConsoleWriter.printlnGreen(getLang().getValue("general", "status", "synSchema")); + ConsoleWriter.printlnGreen(getLang().getValue("general", "status", "synSchema"), messageLevel); for (Entry el : ss.getMapSchema().entrySet()) { - ConsoleWriter.println(el.getKey() + " - " + el.getValue()); + ConsoleWriter.println(el.getKey() + " - " + el.getValue(), messageLevel+1); } return ; } @@ -66,6 +66,6 @@ public void execute(CommandLine cmdLine) throws Exception { } ss.saveFile(); - ConsoleWriter.println(getLang().getValue("general", "done")); + ConsoleWriter.println(getLang().getValue("general", "done"), messageLevel); } } diff --git a/src/main/java/ru/fusionsoft/dbgit/command/CmdValid.java b/src/main/java/ru/fusionsoft/dbgit/command/CmdValid.java index 7e7c241..c5ba535 100644 --- a/src/main/java/ru/fusionsoft/dbgit/command/CmdValid.java +++ b/src/main/java/ru/fusionsoft/dbgit/command/CmdValid.java @@ -43,9 +43,9 @@ public void execute(CommandLine cmdLine) throws Exception { //возможно за списком файлов нужно будет сходить в гит индекс try { Map fileObjs = gmdm.loadFileMetaData(); - ConsoleWriter.printlnGreen(getLang().getValue("general", "valid", "allOk")); + ConsoleWriter.printlnGreen(getLang().getValue("general", "valid", "allOk"), messageLevel); } catch (Exception e) { - ConsoleWriter.printlnRed(e.getMessage()); + ConsoleWriter.printlnRed(e.getMessage(), messageLevel); } } diff --git a/src/main/java/ru/fusionsoft/dbgit/command/IDBGitCommand.java b/src/main/java/ru/fusionsoft/dbgit/command/IDBGitCommand.java index 0554dff..d7e2187 100644 --- a/src/main/java/ru/fusionsoft/dbgit/command/IDBGitCommand.java +++ b/src/main/java/ru/fusionsoft/dbgit/command/IDBGitCommand.java @@ -15,6 +15,8 @@ * */ public interface IDBGitCommand { + public static int messageLevel = 0; + public void execute(CommandLine cmdLine) throws Exception; public String getCommandName(); diff --git a/src/main/java/ru/fusionsoft/dbgit/command/RequestCmd.java b/src/main/java/ru/fusionsoft/dbgit/command/RequestCmd.java index ac12e4f..d693219 100644 --- a/src/main/java/ru/fusionsoft/dbgit/command/RequestCmd.java +++ b/src/main/java/ru/fusionsoft/dbgit/command/RequestCmd.java @@ -96,11 +96,9 @@ protected static Options addHelpOptions(Options opts) throws ExceptionDBGit { if (opts.getOption("h") == null) { opts.addOption("h", false, DBGitLang.getInstance().getValue("help", "h").toString()); } - if (opts.getOption("v") == null) { opts.addOption("v", false, DBGitLang.getInstance().getValue("help", "v").toString()); } - return opts; } @@ -108,11 +106,8 @@ public void printHelpAboutCommand(String command) throws Exception { if (!commands.containsKey(command)) { throw new ExceptionCmdNotFound(DBGitLang.getInstance().getValue("errors", "commandNotFound").withParams(command)); } - IDBGitCommand cmdObj = commands.get(command); - HelpFormatter helpFormatter = new HelpFormatter(); - helpFormatter.printHelp( "dbgit "+command+" "+cmdObj.getParams(), cmdObj.getHelperInfo(), @@ -123,62 +118,66 @@ public void printHelpAboutCommand(String command) throws Exception { } - public static void main( String[] args ) throws Exception - { - ConsoleWriter.println( "dbgit utils - Hello!"); - - //configureLogback(); - - try { - CommandLineParser clParse = new DefaultParser(); - Options opts = new Options(); - opts.addOption("a", false, "Option A"); - opts.addOption("b", true, "Option B"); - opts.addOption("c", false, "Option C"); - opts.addOption("f", false, "Flag F"); - - addHelpOptions(opts); - - CommandLine cmdLine = clParse.parse(opts, args); - System.out.println(cmdLine.getArgs().length); - - System.out.println(cmdLine.hasOption('a')); - System.out.println(cmdLine.hasOption('c')); - - - HelpFormatter helpFormatter = new HelpFormatter(); - //helpFormatter.setArgName("argument"); - helpFormatter.printHelp("this help", "header", opts, "footer", true); - - - /* - printHelp( - opts, // опции по которым составляем help - 80, // ширина строки вывода - "Options", // строка предшествующая выводу - "-- HELP --", // строка следующая за выводом - 3, // число пробелов перед выводом опции - 5, // число пробелов перед выводом опцисания опции - true, // выводить ли в строке usage список команд - System.out // куда производить вывод - ); - - */ - - for (int i = 0; i < cmdLine.getArgs().length; i++) { - System.out.println(cmdLine.getArgs()[i]); - } - - - - ConsoleWriter.println( "execute command success!"); - } catch (Exception e) { - ConsoleWriter.printlnRed("Error execute dbgit: "+e.getMessage()); - LoggerUtil.getGlobalLogger().error(e.getMessage(), e); - } - - } - - - +// public static void main( String[] args ) throws Exception +// { +// ConsoleWriter.println( "dbgit utils - Hello!", 0); +// +// //configureLogback(); +// +// try { +// CommandLineParser clParse = new DefaultParser(); +// Options opts = new Options(); +// opts.addOption("a", false, "Option A"); +// opts.addOption("b", true, "Option B"); +// opts.addOption("c", false, "Option C"); +// opts.addOption("f", false, "Flag F"); +// +// addHelpOptions(opts); +// +// CommandLine cmdLine = clParse.parse(opts, args); +// System.out.println(cmdLine.getArgs().length); +// +// System.out.println(cmdLine.hasOption('a')); +// System.out.println(cmdLine.hasOption('c')); +// +// +// HelpFormatter helpFormatter = new HelpFormatter(); +// //helpFormatter.setArgName("argument"); +// helpFormatter.printHelp("this help", "header", opts, "footer", true); +// +// +// /* +// printHelp( +// opts, // опции по которым составляем help +// 80, // ширина строки вывода +// "Options", // строка предшествующая выводу +// "-- HELP --", // строка следующая за выводом +// 3, // число пробелов перед выводом опции +// 5, // число пробелов перед выводом опцисания опции +// true, // выводить ли в строке usage список команд +// System.out // куда производить вывод +// ); +// +// */ +// +// for (int i = 0; i < cmdLine.getArgs().length; i++) { +// System.out.println(cmdLine.getArgs()[i]); +// } +// +// +// +// ConsoleWriter.println(DBGitLang.getInstance() +// .getValue("general", "commandSuccess") +// , 0 +// ); +// } catch (Exception e) { +// ConsoleWriter.printlnRed(DBGitLang.getInstance() +// .getValue("errors", "cmdException") +// .withParams(e.getMessage()) +// , 0 +// ); +// LoggerUtil.getGlobalLogger().error(e.getMessage(), e); +// } +// +// } } diff --git a/src/main/java/ru/fusionsoft/dbgit/core/DBConnection.java b/src/main/java/ru/fusionsoft/dbgit/core/DBConnection.java index fb714e9..d5d045f 100644 --- a/src/main/java/ru/fusionsoft/dbgit/core/DBConnection.java +++ b/src/main/java/ru/fusionsoft/dbgit/core/DBConnection.java @@ -1,145 +1,154 @@ -package ru.fusionsoft.dbgit.core; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileWriter; -import java.sql.Connection; -import java.sql.DriverManager; -import java.util.Enumeration; -import java.util.Properties; - -import org.slf4j.Logger; - -import ru.fusionsoft.dbgit.utils.ConsoleWriter; -import ru.fusionsoft.dbgit.utils.LoggerUtil; - -/** - * Class for real connection to Database. Load parameters connection from .dblink file - * DBConnection is Singleton - * - * @author mikle - * - */ -public class DBConnection { - private static DBConnection dbGitConnection = null; - private Connection connect = null; - private Logger logger = LoggerUtil.getLogger(this.getClass()); - private DBGitLang lang = DBGitLang.getInstance(); - - private DBConnection(Boolean isConnect) throws ExceptionDBGit { - try { - Properties props = new Properties(); - String url = loadFileDBLink(props); - - if (url != null && isConnect) { - props.put("characterEncoding", "UTF-8"); - connect = DriverManager.getConnection(url, props); - connect.setAutoCommit(false); - } - } catch(Exception e) { - logger.error(lang.getValue("errors", "connectionError").toString(), e); - throw new ExceptionDBGit(e); - } - - } - - public void flushConnection() { - dbGitConnection = null; - } - - public static DBConnection getInstance() throws ExceptionDBGit { - return getInstance(true); - } - - public static DBConnection getInstance(Boolean isConnect) throws ExceptionDBGit { - if (dbGitConnection == null) { - dbGitConnection = new DBConnection(isConnect); - } - return dbGitConnection; - } - - public Connection getConnect() throws ExceptionDBGit { - return connect; - } - - public boolean testingConnection() { - try { - Properties props = new Properties(); - String url = loadFileDBLink(props); - - Connection conTest = DriverManager.getConnection(url, props); - ConsoleWriter.printlnGreen(lang.getValue("general", "link", "connectionEstablished")); - conTest.close(); - conTest = null; - return true; - } catch(Exception e) { - ConsoleWriter.printlnRed(lang.getValue("errors", "link", "cantConnect") + ": " + e.getMessage()); - return false; - } - } - - public boolean testingConnection(String url, Properties props) { - try { - Connection conTest = DriverManager.getConnection(url, props); - ConsoleWriter.printlnGreen(lang.getValue("general", "link", "connectionEstablished")); - conTest.close(); - conTest = null; - return true; - } catch(Exception e) { - ConsoleWriter.printlnRed(lang.getValue("errors", "link", "cantConnect") + ": " + e.getMessage()); - return false; - } - } - - public static void createFileDBLink(String url, Properties props, boolean isDefault) throws ExceptionDBGit { - try{ - File file; - - if (isDefault) - file = new File(DBGitPath.getFullPath(DBGitPath.DB_LINK_DEF_FILE)); - else - file = new File(DBGitPath.getFullPath(DBGitPath.DB_LINK_FILE)); - - DBGitPath.createDir(file.getParent()); - - DBGitPath.createDefaultDbgitConfig(DBGitPath.getFullPath()); - DBGitPath.createLogDir(); - DBGitPath.createScriptsDir(); - - FileWriter writer = new FileWriter(file.getAbsolutePath()); - writer.write("url="+url+"\n"); - Enumeration e = props.propertyNames(); - - while (e.hasMoreElements()) { - String key = (String) e.nextElement(); - writer.write(key+"="+ props.getProperty(key)+"\n"); - } - writer.close(); - ConsoleWriter.println(DBGitLang.getInstance().getValue("general", "link", "dblinkCreated").withParams(DBGitPath.getFullPath(DBGitPath.DB_LINK_FILE))); - } catch(Exception e) { - throw new ExceptionDBGit(e); - } - } - - public static String loadFileDBLink(Properties props) throws ExceptionDBGit { - try{ - File file = new File(DBGitPath.getFullPath(DBGitPath.DB_LINK_FILE)); - File fileDef = new File(DBGitPath.getFullPath(DBGitPath.DB_LINK_DEF_FILE)); - - if (!file.exists() && !fileDef.exists()) { - return null; - } - - FileInputStream fis = new FileInputStream(file.exists() ? file : fileDef); - props.load(fis); - fis.close(); - - String url = props.getProperty("url"); - props.remove("url"); - - return url; - } catch(Exception e) { - throw new ExceptionDBGit(DBGitLang.getInstance().getValue("errors", "fileLoadError").withParams(DBGitPath.DB_LINK_FILE), e); - } - } -} +package ru.fusionsoft.dbgit.core; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileWriter; +import java.sql.Connection; +import java.sql.DriverManager; +import java.util.Enumeration; +import java.util.Properties; + +import org.slf4j.Logger; + +import ru.fusionsoft.dbgit.utils.ConsoleWriter; +import ru.fusionsoft.dbgit.utils.LoggerUtil; + +/** + * Class for real connection to Database. Load parameters connection from .dblink file + * DBConnection is Singleton + * + * @author mikle + * + */ +public class DBConnection { + private static DBConnection dbGitConnection = null; + private static int messageLevel = 1; + private Connection connect = null; + private Logger logger = LoggerUtil.getLogger(this.getClass()); + private DBGitLang lang = DBGitLang.getInstance(); + + private DBConnection(Boolean isConnect) throws ExceptionDBGit { + try { + Properties props = new Properties(); + String url = loadFileDBLink(props); + + if (url != null && isConnect) { + props.put("characterEncoding", "UTF-8"); + connect = DriverManager.getConnection(url, props); + connect.setAutoCommit(false); + } + } catch(Exception e) { + logger.error(lang.getValue("errors", "connectionError").toString(), e); + throw new ExceptionDBGit(e); + } + + } + + public void flushConnection() { + dbGitConnection = null; + } + + public static DBConnection getInstance() throws ExceptionDBGit { + return getInstance(true); + } + + public static DBConnection getInstance(Boolean isConnect) throws ExceptionDBGit { + if (dbGitConnection == null) { + dbGitConnection = new DBConnection(isConnect); + } + return dbGitConnection; + } + + public Connection getConnect() throws ExceptionDBGit { + return connect; + } + + public boolean testingConnection() { + try { + Properties props = new Properties(); + String url = loadFileDBLink(props); + + Connection conTest = DriverManager.getConnection(url, props); + ConsoleWriter.printlnGreen(lang.getValue("general", "link", "connectionEstablished"), messageLevel); + conTest.close(); + conTest = null; + return true; + } catch(Exception e) { + ConsoleWriter.printlnRed(lang.getValue("errors", "link", "cantConnect").withParams(e.getMessage()), messageLevel); + return false; + } + } + + public boolean testingConnection(String url, Properties props) { + try { + Connection conTest = DriverManager.getConnection(url, props); + ConsoleWriter.printlnGreen(lang.getValue("general", "link", "connectionEstablished"), messageLevel); + conTest.close(); + conTest = null; + return true; + } catch(Exception e) { + ConsoleWriter.printlnRed(lang.getValue("errors", "link", "cantConnect").withParams(e.getMessage()), messageLevel); + return false; + } + } + + public static void createFileDBLink(String url, Properties props, boolean isDefault) throws ExceptionDBGit { + try{ + File file; + + if (isDefault) + file = new File(DBGitPath.getFullPath(DBGitPath.DB_LINK_DEF_FILE)); + else + file = new File(DBGitPath.getFullPath(DBGitPath.DB_LINK_FILE)); + + DBGitPath.createDir(file.getParent()); + + DBGitPath.createDefaultDbgitConfig(DBGitPath.getFullPath()); + DBGitPath.createLogDir(); + DBGitPath.createScriptsDir(); + + FileWriter writer = new FileWriter(file.getAbsolutePath()); + writer.write("url="+url+"\n"); + Enumeration e = props.propertyNames(); + + while (e.hasMoreElements()) { + String key = (String) e.nextElement(); + writer.write(key+"="+ props.getProperty(key)+"\n"); + } + writer.close(); + ConsoleWriter.detailsPrintln( + DBGitLang.getInstance().getValue("general", "link", "dblinkCreated") + .withParams(DBGitPath.getFullPath(DBGitPath.DB_LINK_FILE)) + , messageLevel + ); + } catch(Exception e) { + throw new ExceptionDBGit(e); + } + } + + public static String loadFileDBLink(Properties props) throws ExceptionDBGit { + try{ + File file = new File(DBGitPath.getFullPath(DBGitPath.DB_LINK_FILE)); + File fileDef = new File(DBGitPath.getFullPath(DBGitPath.DB_LINK_DEF_FILE)); + + if (!file.exists() && !fileDef.exists()) { + return null; + } + + FileInputStream fis = new FileInputStream(file.exists() ? file : fileDef); + props.load(fis); + fis.close(); + + String url = props.getProperty("url"); + props.remove("url"); + + return url; + } catch(Exception e) { + throw new ExceptionDBGit(DBGitLang.getInstance().getValue("errors", "fileLoadError").withParams(DBGitPath.DB_LINK_FILE), e); + } + } + + public static boolean hasInstance(){ + return dbGitConnection != null; + } +} diff --git a/src/main/java/ru/fusionsoft/dbgit/core/DBGit.java b/src/main/java/ru/fusionsoft/dbgit/core/DBGit.java index 26979fc..16076de 100644 --- a/src/main/java/ru/fusionsoft/dbgit/core/DBGit.java +++ b/src/main/java/ru/fusionsoft/dbgit/core/DBGit.java @@ -1,27 +1,23 @@ package ru.fusionsoft.dbgit.core; import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.Set; -import org.eclipse.jgit.api.CheckoutCommand; -import org.eclipse.jgit.api.FetchCommand; -import org.eclipse.jgit.api.Git; -import org.eclipse.jgit.api.InitCommand; +import org.eclipse.jgit.api.*; import org.eclipse.jgit.api.ListBranchCommand.ListMode; -import org.eclipse.jgit.api.MergeCommand; -import org.eclipse.jgit.api.MergeResult; -import org.eclipse.jgit.api.PullCommand; -import org.eclipse.jgit.api.RemoteAddCommand; -import org.eclipse.jgit.api.RemoteRemoveCommand; import org.eclipse.jgit.api.ResetCommand.ResetType; -import org.eclipse.jgit.api.Status; +import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.dircache.DirCache; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.storage.file.FileRepositoryBuilder; import org.eclipse.jgit.transport.CredentialsProvider; import org.eclipse.jgit.transport.PushResult; @@ -35,58 +31,84 @@ import ru.fusionsoft.dbgit.utils.MaskFilter; public class DBGit { - private static DBGit dbGit = null; - private Repository repository; - private Git git; + private static DBGit instance; + final private Repository repository; + final private Git git; + final private static int messageLevel = 0; - private DBGit() throws ExceptionDBGit { + + private DBGit() { try { FileRepositoryBuilder builder = new FileRepositoryBuilder(); repository = builder - .readEnvironment() // scan environment GIT_* variables - .findGitDir() // scan up the file system tree - .build(); + .setGitDir( + Paths.get("") + .resolve(".git") + .toAbsolutePath() + .toFile() + ) + .build(); git = new Git(repository); - } catch (Exception e) { - throw new ExceptionDBGit(e); + instance = this; + } catch (IOException e) { + final String msg = "Could not build file repository, never intended to do anything after that..."; + throw new ExceptionDBGitRunTime(msg, e); } + } - public static DBGit getInstance() throws ExceptionDBGit { - if (dbGit == null) { + private DBGit(String url) { + try { + //TODO find out where this 'url' is in 'repository' FileRepositoryBuilder builder = new FileRepositoryBuilder(); + repository = builder + .setGitDir(new File(url)) + .build(); + + git = new Git(repository); + } catch (Exception e) { + throw new ExceptionDBGitRunTime(e); + } + } + + public static DBGit getInstance() { + if (instance == null) { - if (builder.readEnvironment().findGitDir().getGitDir() == null) { - throw new ExceptionDBGit(DBGitLang.getInstance().getValue("errors", "gitRepNotFound")); + if (!repositoryExists()) { + final DBGitLang msg = DBGitLang.getInstance().getValue("errors", "gitRepNotFound"); + throw new ExceptionDBGitRunTime(msg); } - dbGit = new DBGit(); + instance = new DBGit(); } - return dbGit; + return instance; } - public static boolean checkIfRepositoryExists() throws ExceptionDBGit { - if (dbGit == null) { - FileRepositoryBuilder builder = new FileRepositoryBuilder(); - - if (builder.readEnvironment().findGitDir().getGitDir() == null) { - return false; - } else { - return true; + public static void initUrlInstance(String gitDirUrl, boolean force) { + if (instance != null) { + if(!force) { + final String msg = "DBGit is already initialized, btw u can set 'force' to 'true' or never make singletons..."; + throw new ExceptionDBGitRunTime(msg); } + instance.repository.close(); + instance.git.close(); + } + instance = new DBGit(gitDirUrl); + } - } else - return true; + public static boolean repositoryExists() { + if (instance == null) { + FileRepositoryBuilder builder = new FileRepositoryBuilder(); + return builder.readEnvironment().findGitDir().getGitDir() != null; + } + else return true; } public Repository getRepository() { return repository; } - public void setRepository(Repository repository) { - this.repository = repository; - } public String getRootDirectory() { return repository.getDirectory().getParent(); @@ -192,7 +214,7 @@ public void gitCommit(boolean existsSwitchA, String msg, String path) throws Exc for (IMetaObject obj : fileObjs.values()) { String hash = obj.getHash(); if (!gmdm.loadFromDB(obj)) { - ConsoleWriter.println(DBGitLang.getInstance().getValue("errors", "commit", "cantFindObject")); + ConsoleWriter.println(DBGitLang.getInstance().getValue("errors", "commit", "cantFindObject"), messageLevel); obj.removeFromGit(); index.markItemToDelete(obj); index.saveDBIndex(); @@ -226,56 +248,121 @@ public void gitCommit(boolean existsSwitchA, String msg, String path) throws Exc res = git.commit().setAll(existsSwitchA).setOnly(DBGitPath.DB_GIT_PATH + "/" + path).call(); } } - ConsoleWriter.printlnGreen(DBGitLang.getInstance().getValue("general", "commit", "commit") + ": " + res.getName()); - ConsoleWriter.printlnGreen(res.getAuthorIdent().getName() + "<" + res.getAuthorIdent().getEmailAddress() + ">, " + res.getAuthorIdent().getWhen()); + ConsoleWriter.printlnGreen(DBGitLang.getInstance().getValue("general", "commit", "commit") + ": " + res.getName() + , messageLevel + ); + ConsoleWriter.printlnGreen(res.getAuthorIdent().getName() + "<" + res.getAuthorIdent().getEmailAddress() + ">, " + res.getAuthorIdent().getWhen() + , messageLevel + ); } catch (Exception e) { throw new ExceptionDBGit(e); } } - public void gitCheckout(String branch, String commit, boolean isNewBranch) throws ExceptionDBGit { - try { - ConsoleWriter.detailsPrintLn(DBGitLang.getInstance().getValue("general", "checkout", "toCreateBranch") + ": " + isNewBranch); - ConsoleWriter.detailsPrintLn(DBGitLang.getInstance().getValue("general", "checkout", "branchName") + ": " + branch); - if (commit != null) - ConsoleWriter.detailsPrintLn(DBGitLang.getInstance().getValue("general", "checkout", "commitName") + ": " + commit); - - Ref result; - if (git.getRepository().findRef(branch) != null || isNewBranch) { - - CheckoutCommand checkout = git.checkout().setCreateBranch(isNewBranch).setName(branch); - - if (commit != null) - checkout = checkout.setStartPoint(commit); - else { - if (git.branchList().setListMode(ListMode.REMOTE).call().stream() - .filter(ref -> ref.getName().equals("refs/remotes/origin/" + branch)) - .count() > 0) - checkout = checkout.setStartPoint("remotes/origin/" + branch); - } - - result = checkout.call(); + public void printCurrentCommit() throws IOException { + try (RevWalk walk = new RevWalk(repository)) { + ConsoleWriter.detailsPrintlnGreen( + DBGitLang.getInstance().getValue("general", "checkout", "commitMessage") + .withParams(walk.parseCommit(repository.getAllRefs().get("HEAD").getObjectId()).getShortMessage()) + , messageLevel + 1 + ); + } + } + + public boolean nameInLocalRepoExistence(String name) throws IOException { + return git.getRepository().findRef(name) != null; + } + + public boolean nameInRemoteRepoExistence(String name) throws GitAPIException { + return git.branchList().setListMode(ListMode.REMOTE).call().stream() + .anyMatch(ref -> ref.getName().equals("refs/remotes/origin/" + name)); + } + + public void gitCheckoutName(String name) throws Exception { + final CheckoutCommand checkoutCommand = git.checkout().setName(name); + + if (nameInLocalRepoExistence(name)) { + ConsoleWriter.detailsPrintlnGreen( + DBGitLang.getInstance().getValue("general", "checkout", "branchName").withParams(name), messageLevel + 1 + ); + if(nameInRemoteRepoExistence(name)) { + checkoutCommand.setStartPoint("origin/" + name); + } + } else { + ConsoleWriter.detailsPrintlnGreen( + DBGitLang.getInstance().getValue("general", "checkout", "commitName").withParams(name), messageLevel + 1 + ); + } - ConsoleWriter.printlnGreen(result.getName()); + checkoutCommand.call(); + printCurrentCommit(); + } + + public void gitCheckoutNewBranch(String branchName, String commitHash) throws Exception { + final CheckoutCommand checkoutCommand = git.checkout(); + ConsoleWriter.println(DBGitLang.getInstance().getValue("general", "checkout", "branchName").withParams(branchName), messageLevel + 1); + if(commitHash != null) { + ConsoleWriter.println(DBGitLang.getInstance().getValue("general", "checkout", "commitName").withParams(commitHash), messageLevel + 1); + } + ConsoleWriter.println(DBGitLang.getInstance().getValue("general", "checkout", "toCreateBranch").withParams(String.valueOf(true)), messageLevel + 1); + + checkoutCommand.setCreateBranch(true); + checkoutCommand.setName(branchName); + if(commitHash != null) { + if(nameInLocalRepoExistence(commitHash)) { + checkoutCommand.setStartPoint(commitHash); } else { - MaskFilter maskAdd = new MaskFilter(branch); - - int counter = 0; - for (String path: getGitIndexFiles(DBGitPath.DB_GIT_PATH)) { - if (maskAdd.match(path)) { - result = git.checkout().setName(git.getRepository().getBranch()).addPath(DBGitPath.DB_GIT_PATH + "/" + path).call(); - counter++; - } - } - String s = ""; - if (counter != 1) s = "s"; - ConsoleWriter.println(DBGitLang.getInstance().getValue("general", "checkout", "updatedFromIndex").withParams(String.valueOf(counter), s)); + throw new ExceptionDBGit("Can not find the local commit specified: " + commitHash); + } + } else if (nameInRemoteRepoExistence(branchName)){ + checkoutCommand.setStartPoint("origin/" + branchName); + } + //else { + // you would checkout HEAD - create new branch from current one's HEAD + // https://stackoverflow.com/a/37131407 + //} + checkoutCommand.call(); + } + + public void gitCheckoutFileName(String fileName) throws Exception{ + MaskFilter maskAdd = new MaskFilter(fileName); + ConsoleWriter.println("Checking out files...", messageLevel+1); + + int counter = 0; + for (String path : getGitIndexFiles(DBGitPath.DB_GIT_PATH)) { + if (maskAdd.match(path)) { + git.checkout() + .setName(git.getRepository() + .getBranch()) + .addPath(DBGitPath.DB_GIT_PATH + "/"+ path) + .call(); + counter++; + } + } + String messageTailChars = counter != 1 ? "s" : ""; + ConsoleWriter.println( + DBGitLang.getInstance().getValue("general", "checkout", "updatedFromIndex") + .withParams(String.valueOf(counter), messageTailChars) + , messageLevel+1 + ); + } + + public void gitCheckout(String arg1, String arg2, boolean isNewBranch) throws ExceptionDBGit { + try { + ConsoleWriter.println(DBGitLang.getInstance().getValue("general", "checkout", "do"), messageLevel); + if(isNewBranch) { + gitCheckoutNewBranch(arg1, arg2); + } else { +// if(nameInRemoteRepoExistence(arg1) || nameInLocalRepoExistence(arg1)) { + gitCheckoutName(arg1); +// } else { +// gitCheckoutFileName(arg1); +// } } - } catch (Exception e) { - throw new ExceptionDBGit(e.getLocalizedMessage()); + throw new ExceptionDBGit("Failed to do checkout", e); } } @@ -289,7 +376,7 @@ public void gitMerge(Set branches) throws ExceptionDBGit { MergeResult result = merge.call(); - ConsoleWriter.println(result.getMergeStatus().toString()); + ConsoleWriter.println(result.getMergeStatus().toString(), 1); } catch (Exception e) { throw new ExceptionDBGit(e); @@ -306,9 +393,16 @@ public void gitPull(String remote, String remoteBranch) throws ExceptionDBGit { if (remoteBranch.length() > 0) pull = pull.setRemoteBranchName(remoteBranch); - ConsoleWriter.printlnGreen(pull.setCredentialsProvider(getCredentialsProviderByName(pull.getRemote())).call().toString()); + ConsoleWriter.printlnGreen( + pull.setCredentialsProvider(getCredentialsProviderByName(pull.getRemote())).call() + .toString() + , 1 + ); } catch (Exception e) { - ConsoleWriter.println("Repo is empty!"); + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("errors", "pull", "emptyGitRepository") + , 0 + ); //throw new ExceptionDBGit(e); } } @@ -317,32 +411,81 @@ public void gitPush(String remoteName) throws ExceptionDBGit { try { git.log().call(); } catch (Exception e) { - ConsoleWriter.println("No commits found!"); + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("general", "push", "noCommitsFound") + , messageLevel + ); return; } try { - ConsoleWriter.detailsPrintLn("Entered to gitPush"); - ConsoleWriter.detailsPrintLn("remoteName: " + (remoteName.equals("") ? Constants.DEFAULT_REMOTE_NAME : remoteName)); - - Iterable result = git.push() - .setCredentialsProvider(getCredentialsProviderByName(remoteName.equals("") ? Constants.DEFAULT_REMOTE_NAME : remoteName)) - .setRemote(remoteName.equals("") ? Constants.DEFAULT_REMOTE_NAME : remoteName).call(); - - ConsoleWriter.detailsPrintLn("Push called "); - - result.forEach(pushResult -> { - if (pushResult == null) - ConsoleWriter.detailsPrintLn("Push result is null!!! "); - pushResult.toString(); - for (RemoteRefUpdate res : pushResult.getRemoteUpdates()) { - if (res.getStatus() == RemoteRefUpdate.Status.UP_TO_DATE) - ConsoleWriter.println("Everything up-to-date"); - else { - ConsoleWriter.println(res.toString()); + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("general", "push", "remoteName") + .withParams((remoteName.equals("") ? Constants.DEFAULT_REMOTE_NAME : remoteName)) + , messageLevel+1 + ); + + try { + + Iterable result = git + .push() + .setCredentialsProvider( + getCredentialsProviderByName( + remoteName.equals("") + ? Constants.DEFAULT_REMOTE_NAME + : remoteName + ) + ) + .setRemote( + remoteName.equals("") + ? Constants.DEFAULT_REMOTE_NAME + : remoteName + ) + .call(); + + + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("general", "push", "called") + , messageLevel+1 + ); + + result.forEach(pushResult -> { + if (pushResult == null){ + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("general", "push", "nullResult") + , 1 + ); + } else { + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("general", "push", "callResult") + .withParams(pushResult.toString()) + , messageLevel+1 + ); } - } - }); + for (RemoteRefUpdate res : pushResult.getRemoteUpdates()) { + if (res.getStatus() == RemoteRefUpdate.Status.UP_TO_DATE){ + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("general", "push", "upToDate") + , 1 + ); + } + else { + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("general", "push", "result") + .withParams(res.toString()) + , 1 + ); + } + } + }); + + } catch (Exception ex) { + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("general", "push", "callResult") + .withParams(ex.getLocalizedMessage()) + , messageLevel + 1 + ); + } } catch (Exception e) { throw new ExceptionDBGit(e); @@ -363,19 +506,28 @@ public static void gitInit(String dirPath) throws ExceptionDBGit { init.call(); - ConsoleWriter.println(DBGitLang.getInstance().getValue("general", "init", "created")); + ConsoleWriter.println(DBGitLang.getInstance().getValue("general", "init", "created"), messageLevel); } catch (Exception e) { throw new ExceptionDBGit(e); } } - public static void gitClone(String link, String remoteName) throws ExceptionDBGit { + public static void gitClone(String link, String remoteName, File directory) throws ExceptionDBGit { try { - Git.cloneRepository().setURI(link).setCredentialsProvider(getCredentialsProvider(link)) - .setRemote(remoteName.equals("") ? Constants.DEFAULT_REMOTE_NAME : remoteName).call(); + String actualRemoteName = remoteName.equals("") ? Constants.DEFAULT_REMOTE_NAME : remoteName; + CredentialsProvider cp = getCredentialsProvider(link); + CloneCommand cc = Git.cloneRepository() + .setURI(link) + .setRemote(actualRemoteName) + .setCredentialsProvider(cp) + .setDirectory(directory); - ConsoleWriter.println(DBGitLang.getInstance().getValue("general", "clone", "cloned")); + final Git call = cc.call(); + call.getRepository().close(); + call.close(); + + ConsoleWriter.println(DBGitLang.getInstance().getValue("general", "clone", "cloned"), messageLevel); } catch (Exception e) { throw new ExceptionDBGit(e); @@ -387,7 +539,7 @@ public void gitRemote(String command, String name, String uri) throws ExceptionD try { switch (command) { case "" : { - git.remoteList().call().forEach(remote -> ConsoleWriter.println(remote.getName())); + git.remoteList().call().forEach(remote -> ConsoleWriter.println(remote.getName(), messageLevel+1)); break; } @@ -396,8 +548,9 @@ public void gitRemote(String command, String name, String uri) throws ExceptionD remote.setName(name); remote.setUri(new URIish(uri)); remote.call(); + remote.getRepository().close(); - ConsoleWriter.printlnGreen(DBGitLang.getInstance().getValue("general", "remote", "added")); + ConsoleWriter.printlnGreen(DBGitLang.getInstance().getValue("general", "remote", "added"), messageLevel); break; } @@ -406,13 +559,14 @@ public void gitRemote(String command, String name, String uri) throws ExceptionD RemoteRemoveCommand remote = git.remoteRemove(); remote.setName(name); remote.call(); + remote.getRepository().close(); - ConsoleWriter.printlnGreen(DBGitLang.getInstance().getValue("general", "remote", "removed")); + ConsoleWriter.printlnGreen(DBGitLang.getInstance().getValue("general", "remote", "removed"), messageLevel); break; } - default : ConsoleWriter.println(DBGitLang.getInstance().getValue("general", "remote", "unknown")); + default : ConsoleWriter.println(DBGitLang.getInstance().getValue("general", "remote", "unknown"), messageLevel); } } catch (Exception e) { @@ -426,7 +580,7 @@ public void gitReset(String mode) throws ExceptionDBGit { git.reset().call(); else git.reset().setMode(ResetType.valueOf(mode)).call(); - ConsoleWriter.println(DBGitLang.getInstance().getValue("general", "done")); + ConsoleWriter.println(DBGitLang.getInstance().getValue("general", "done"), messageLevel); } catch (Exception e) { throw new ExceptionDBGit(e); } @@ -434,8 +588,14 @@ public void gitReset(String mode) throws ExceptionDBGit { public void gitFetch(String remote) throws ExceptionDBGit { try { - FetchCommand fetch = git.fetch() - .setCredentialsProvider(getCredentialsProviderByName(remote.equals("") ? Constants.DEFAULT_REMOTE_NAME : remote)); + FetchCommand fetch = git + .fetch() + .setCredentialsProvider(getCredentialsProviderByName( + remote.equals("") + ? Constants.DEFAULT_REMOTE_NAME + : remote + ) + ); if (remote.length() > 0) fetch = fetch.setRemote(remote); @@ -443,17 +603,25 @@ public void gitFetch(String remote) throws ExceptionDBGit { fetch = fetch.setRemote(Constants.DEFAULT_REMOTE_NAME); fetch.call(); + fetch.getRepository().close(); - ConsoleWriter.println(DBGitLang.getInstance().getValue("general", "done")); + ConsoleWriter.println(DBGitLang.getInstance().getValue("general", "done"), messageLevel); } catch (Exception e) { throw new ExceptionDBGit(e); } } private CredentialsProvider getCredentialsProviderByName(String remoteName) throws ExceptionDBGit { - ConsoleWriter.detailsPrintLn("Getting link to repo... "); + ConsoleWriter.detailsPrintln(DBGitLang.getInstance() + .getValue("general", "gettingRepoLink") + , messageLevel + ); String link = git.getRepository().getConfig().getString("remote", remoteName, "url"); - ConsoleWriter.detailsPrintLn("link:" + link); + ConsoleWriter.detailsPrintln(DBGitLang.getInstance() + .getValue("general", "repoLink") + .withParams(link) + , messageLevel + ); if (link != null) return getCredentialsProvider(link); @@ -468,12 +636,15 @@ private CredentialsProvider getCredentialsProvider() throws ExceptionDBGit { private static CredentialsProvider getCredentialsProvider(String link) throws ExceptionDBGit { try { - ConsoleWriter.detailsPrintLn("Getting credentials..."); URIish uri = new URIish(link); - ConsoleWriter.detailsPrintLn("uri login = " + uri.getUser()); - ConsoleWriter.detailsPrintLn("uri pass = " + uri.getPass()); + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("general", "showDbCredentials") + .withParams( uri.getScheme(), uri.getUser(), uri.getHost(), uri.getRawPath()) + , 0 + ); + /* Pattern patternPass = Pattern.compile("(?<=:(?!\\/))(.*?)(?=@)"); Pattern patternLogin = Pattern.compile("(?<=\\/\\/)(.*?)(?=:(?!\\/))"); @@ -499,6 +670,10 @@ private static CredentialsProvider getCredentialsProvider(String link) throws Ex ConsoleWriter.detailsPrintLn("login: " + login); ConsoleWriter.detailsPrintLn("pass: " + pass);*/ + if(uri.getUser() == null) { + ConsoleWriter.detailsPrintlnRed(DBGitLang.getInstance().getValue("errors", "gitLoginNotFound"), messageLevel); + return null; + } return new UsernamePasswordCredentialsProvider(uri.getUser(), uri.getPass()); } catch (Exception e) { throw new ExceptionDBGit(e); diff --git a/src/main/java/ru/fusionsoft/dbgit/core/DBGitConfig.java b/src/main/java/ru/fusionsoft/dbgit/core/DBGitConfig.java index a58c575..d81c84c 100644 --- a/src/main/java/ru/fusionsoft/dbgit/core/DBGitConfig.java +++ b/src/main/java/ru/fusionsoft/dbgit/core/DBGitConfig.java @@ -1,155 +1,182 @@ -package ru.fusionsoft.dbgit.core; - -import java.io.File; - -import org.ini4j.Ini; - -import ru.fusionsoft.dbgit.utils.ConsoleWriter; - -public class DBGitConfig { - - private static DBGitConfig config = null; - private Ini ini = null; - private Ini iniGlobal = null; - - private DBGitConfig() throws Exception { - - if (DBGit.checkIfRepositoryExists()) { - File file = new File(DBGitPath.getFullPath() + "/" + DBGitPath.DBGIT_CONFIG); - if (file.exists()) - ini = new Ini(file); - } - - String path = new File(DBGitConfig.class.getProtectionDomain().getCodeSource().getLocation() - .toURI()).getAbsolutePath(); - - //for debug: - if (path.contains("classes")) path = path + "/../dbgit"; - - while (!new File(path + "/dbgitconfig").exists()) { - int i = path.lastIndexOf("/"); - if (i == -1) i = path.lastIndexOf("\\"); - - path = path.substring(0, i); - } - - if (new File(path + "/bin/dbgitconfig").exists()) - path = path + "/bin/dbgitconfig"; - else - path = path + "/dbgitconfig"; - - File fileGlobal = new File(path); - if (fileGlobal.exists()) - iniGlobal = new Ini(fileGlobal); - } - - public static DBGitConfig getInstance() throws Exception { - if (config == null) - config = new DBGitConfig(); - - return config; - } - - public String getString(String section, String option, String defaultValue) { - return getString(section, option, defaultValue, false); - } - - public Boolean getBoolean(String section, String option, Boolean defaultValue) { - return getBoolean(section, option, defaultValue, false); - } - - public Integer getInteger(String section, String option, Integer defaultValue) { - return getInteger(section, option, defaultValue, false); - } - - public Double getDouble(String section, String option, Double defaultValue) { - return getDouble(section, option, defaultValue, false); - } - - public String getStringGlobal(String section, String option, String defaultValue) { - return getString(section, option, defaultValue, true); - } - - public Boolean getBooleanGlobal(String section, String option, Boolean defaultValue) { - return getBoolean(section, option, defaultValue, true); - } - - public Integer getIntegerGlobal(String section, String option, Integer defaultValue) { - return getInteger(section, option, defaultValue, true); - } - - public Double getDoubleGlobal(String section, String option, Double defaultValue) { - return getDouble(section, option, defaultValue, true); - } - - private String getString(String section, String option, String defaultValue, boolean global) { - try { - String result = global ? iniGlobal.get(section, option) : ini.get(section, option); - return result == null ? defaultValue : result; - } catch (Exception e) { - return defaultValue; - } - } - - private Boolean getBoolean(String section, String option, Boolean defaultValue, boolean global) { - try { - String result = global ? iniGlobal.get(section, option) : ini.get(section, option); - - return result == null ? defaultValue : Boolean.valueOf(result); - } catch (Exception e) { - return defaultValue; - } - } - - private Integer getInteger(String section, String option, Integer defaultValue, boolean global) { - try { - String result = global ? iniGlobal.get(section, option) : ini.get(section, option); - return result == null ? defaultValue : Integer.valueOf(result); - } catch (Exception e) { - return defaultValue; - } - } - - private Double getDouble(String section, String option, Double defaultValue, boolean global) { - try { - String result = global ? iniGlobal.get(section, option) : ini.get(section, option); - return result == null ? defaultValue : Double.valueOf(result); - } catch (Exception e) { - return defaultValue; - } - } - - public void setValue(String parameter, String value) throws ExceptionDBGit { - setValue(parameter, value, false); - } - - public void setValueGlobal(String parameter, String value) throws ExceptionDBGit { - setValue(parameter, value, true); - } - - public void setValue(String parameter, String value, boolean global) throws ExceptionDBGit { - try { - if (global) { - if (!iniGlobal.get("core").containsKey(parameter)) - ConsoleWriter.detailsPrintLn(DBGitLang.getInstance().getValue("errors", "config", "noParameter").withParams(parameter)); - else { - iniGlobal.get("core").put(parameter, value); - iniGlobal.store(iniGlobal.getFile()); - } - } else { - if (ini == null) - throw new ExceptionDBGit(DBGitLang.getInstance().getValue("errors", "gitRepNotFound")); - - if (!ini.get("core").containsKey(parameter)) - ConsoleWriter.detailsPrintLn(DBGitLang.getInstance().getValue("errors", "config", "noParameter").withParams(parameter)); - else { - ini.get("core").put(parameter, value); - ini.store(new File(DBGitPath.getFullPath() + "/" + DBGitPath.DBGIT_CONFIG)); - } - } - } catch (Exception e) { - throw new ExceptionDBGit(e); - } - } - -} +package ru.fusionsoft.dbgit.core; + +import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.HashMap; +import java.util.Map; + +import org.ini4j.Ini; + +import ru.fusionsoft.dbgit.utils.ConsoleWriter; + +public class DBGitConfig { + private static int messageLevel = 1; + private static DBGitConfig config = null; + private Ini ini = null; + private Ini iniGlobal = null; + private Map transientConfig = new HashMap<>(); + + private DBGitConfig() { + try{ + findAndSetIni(); + findAndSetIniGlobal(); + } catch (Exception anyKindOfException){ + //no reason to continue anything + throw new ExceptionDBGitRunTime(anyKindOfException); + } + } + + public static DBGitConfig getInstance() { + if (config == null) config = new DBGitConfig(); + return config; + } + + private void findAndSetIniGlobal() throws URISyntaxException, IOException { + String path = new File(DBGitConfig.class.getProtectionDomain() + .getCodeSource().getLocation().toURI() + ).getAbsolutePath(); + + //for debug: + if (path.contains("classes")) path = path + "/../dbgit"; + + while (!new File(path + "/dbgitconfig").exists()) { + int i = path.lastIndexOf("/"); + if (i == -1) i = path.lastIndexOf("\\"); + + path = path.substring(0, i); + } + + if (new File(path + "/bin/dbgitconfig").exists()) + path = path + "/bin/dbgitconfig"; + else + path = path + "/dbgitconfig"; + + File fileGlobal = new File(path); + if (fileGlobal.exists()) iniGlobal = new Ini(fileGlobal); + } + + private void findAndSetIni() throws IOException { + if (DBGit.repositoryExists()) { + File file = new File(DBGitPath.getFullPath() + "/" + DBGitPath.DBGIT_CONFIG); + if (file.exists()) ini = new Ini(file); + } + } + + private Ini getIni() throws IOException { + if(ini == null){ + findAndSetIni(); + } + return ini; + } + + public String getString(String section, String option, String defaultValue) { + return getString(section, option, defaultValue, false); + } + public Boolean getBoolean(String section, String option, Boolean defaultValue) { + return getBoolean(section, option, defaultValue, false); + } + public Integer getInteger(String section, String option, Integer defaultValue) { + return getInteger(section, option, defaultValue, false); + } + public Double getDouble(String section, String option, Double defaultValue) { + return getDouble(section, option, defaultValue, false); + } + public String getStringGlobal(String section, String option, String defaultValue) { + return getString(section, option, defaultValue, true); + } + public Boolean getBooleanGlobal(String section, String option, Boolean defaultValue) { + return getBoolean(section, option, defaultValue, true); + } + public Integer getIntegerGlobal(String section, String option, Integer defaultValue) { + return getInteger(section, option, defaultValue, true); + } + public Double getDoubleGlobal(String section, String option, Double defaultValue) { + return getDouble(section, option, defaultValue, true); + } + private String getString(String section, String option, String defaultValue, boolean global) { + try { + String result = global ? iniGlobal.get(section, option) : getIni().get(section, option); + return result == null ? defaultValue : result; + } catch (Exception e) { + return defaultValue; + } + } + private Boolean getBoolean(String section, String option, Boolean defaultValue, boolean global) { + try { + String result = global ? iniGlobal.get(section, option) : getIni().get(section, option); + + return result == null ? defaultValue : Boolean.valueOf(result); + } catch (Exception e) { + return defaultValue; + } + } + private Integer getInteger(String section, String option, Integer defaultValue, boolean global) { + try { + String result = global ? iniGlobal.get(section, option) : getIni().get(section, option); + return result == null ? defaultValue : Integer.valueOf(result); + } catch (Exception e) { + return defaultValue; + } + } + private Double getDouble(String section, String option, Double defaultValue, boolean global) { + try { + String result = global ? iniGlobal.get(section, option) : getIni().get(section, option); + return result == null ? defaultValue : Double.valueOf(result); + } catch (Exception e) { + return defaultValue; + } + } + public void setValue(String parameter, String value) throws ExceptionDBGit { + setValue(parameter, value, false); + } + public void setValueGlobal(String parameter, String value) throws ExceptionDBGit { + setValue(parameter, value, true); + } + public void setValue(String parameter, String value, boolean global) throws ExceptionDBGit { + try { + if (global) { + if (!iniGlobal.get("core").containsKey(parameter) /*&& !parameter.equals("CURRENT_OBJECT")*/) + ConsoleWriter.detailsPrintln( + DBGitLang.getInstance().getValue("errors", "config", "noParameter").withParams(parameter) + , messageLevel + ); + else { + iniGlobal.get("core").put(parameter, value); + iniGlobal.store(iniGlobal.getFile()); + } + } else { + if (getIni() == null) + throw new ExceptionDBGit(DBGitLang.getInstance().getValue("errors", "gitRepNotFound")); + + if (!ini.get("core").containsKey(parameter) && ! parameter.equals("CURRENT_OBJECT")) + ConsoleWriter.detailsPrintln(DBGitLang.getInstance().getValue("errors", "config", "noParameter").withParams(parameter), messageLevel); + else { + getIni().get("core").put(parameter, value); + getIni().store(new File(DBGitPath.getFullPath() + "/" + DBGitPath.DBGIT_CONFIG)); + } + } + } catch (Exception e) { + throw new ExceptionDBGit(e); + } + } + + + public static String TO_IGNORE_OWNER = "noowner"; + + public void setValueTransient(String parameter, String value) throws ExceptionDBGit{ + transientConfig.put(parameter, value); + } + + public String getValueTransient(String parameter, String defaultValue){ + return transientConfig.getOrDefault(parameter, defaultValue); + } + + public void setToIgnoreOnwer(boolean value) throws ExceptionDBGit{ + transientConfig.put(TO_IGNORE_OWNER, value ? "true" : "false"); + } + + public boolean getToIgnoreOnwer(boolean defaultValue){ + return Boolean.valueOf(getValueTransient(TO_IGNORE_OWNER, defaultValue ? "true" : "false")); + } +} diff --git a/src/main/java/ru/fusionsoft/dbgit/core/DBGitIgnore.java b/src/main/java/ru/fusionsoft/dbgit/core/DBGitIgnore.java index a93928a..e5c4330 100644 --- a/src/main/java/ru/fusionsoft/dbgit/core/DBGitIgnore.java +++ b/src/main/java/ru/fusionsoft/dbgit/core/DBGitIgnore.java @@ -6,7 +6,7 @@ import java.util.HashMap; import java.util.Map; -import ru.fusionsoft.dbgit.utils.ConsoleWriter; +import ru.fusionsoft.dbgit.adapters.DBBackupAdapter; import ru.fusionsoft.dbgit.utils.MaskFilter; /** @@ -23,23 +23,39 @@ public class DBGitIgnore { private Map exclusions = new HashMap<>(); - private DBGitIgnore() throws ExceptionDBGit { + DBGitIgnore() throws ExceptionDBGit { // load file DBIgnore loadFileDBIgnore(); } - + + public DBGitIgnore(Map filters, Map exclusions) { + this.filters = filters; + this.exclusions = exclusions; + } + protected void loadFileDBIgnore() throws ExceptionDBGit { + loadFileDBIgnore(false); + } + protected void loadFileDBIgnore(boolean withBackupSchemas) throws ExceptionDBGit { try{ File file = new File(DBGitPath.getRootPath(DBGitPath.DB_GIT_PATH+"/"+DBGitPath.DB_IGNORE_FILE)); if (!file.exists()) return ; + //boolean isBackupToScheme = DBGitConfig.getInstance().getBoolean("core", "BACKUP_TO_SCHEME", false); BufferedReader br = new BufferedReader(new FileReader(file)); - for(String line; (line = br.readLine()) != null; ) { + for(String line; (line = br.readLine()) != null; ) { + if (line.startsWith("!")) { MaskFilter mask = new MaskFilter(line.substring(1)); exclusions.put(line.substring(1), mask); + if(withBackupSchemas /*&&isBackupToScheme*/){ + String schemaPart = line.substring(1,line.indexOf("/")+1); + String backupSchemeObjExclusion = line.replace(schemaPart, DBBackupAdapter.PREFIX + schemaPart).substring(1); + MaskFilter backupSchemeObjMask = new MaskFilter(backupSchemeObjExclusion); + exclusions.put(backupSchemeObjExclusion, backupSchemeObjMask); + } } else { MaskFilter mask = new MaskFilter(line); @@ -86,7 +102,7 @@ public boolean matchSchema(String schemaName) { } for (MaskFilter mask : filters.values()) { - if (mask.getMask().indexOf("/") == -1) return true; + if (mask.getMask().indexOf("/") == -1) return false; if (mask.match(schemaName) || mask.getMask().toUpperCase().substring(0, mask.getMask().indexOf("/")).equals(schemaName.toUpperCase())) { return true; } diff --git a/src/main/java/ru/fusionsoft/dbgit/core/DBGitIndex.java b/src/main/java/ru/fusionsoft/dbgit/core/DBGitIndex.java index a5bd414..735eff8 100644 --- a/src/main/java/ru/fusionsoft/dbgit/core/DBGitIndex.java +++ b/src/main/java/ru/fusionsoft/dbgit/core/DBGitIndex.java @@ -9,7 +9,7 @@ public class DBGitIndex { public static final String VERSION = "0.3.1"; - + private static DBGitIndex gitIndex = null; private TreeMapItemIndex treeItems; private boolean hasConflicts = false; @@ -60,7 +60,7 @@ protected ItemIndex editItem(IMetaObject obj, Boolean isDelete) { public ItemIndex addItem(IMetaObject obj) { return editItem(obj, false); } - + public ItemIndex markItemToDelete(IMetaObject obj) { return editItem(obj, true); } @@ -77,8 +77,7 @@ public boolean removeItem(String name) { saveDBIndex(); return true; } catch (Exception ex){ - ex.printStackTrace(); - return false; + throw new ExceptionDBGitRunTime("Remove item from index error", ex); } } diff --git a/src/main/java/ru/fusionsoft/dbgit/core/DBGitLang.java b/src/main/java/ru/fusionsoft/dbgit/core/DBGitLang.java index a899a65..b4c0698 100644 --- a/src/main/java/ru/fusionsoft/dbgit/core/DBGitLang.java +++ b/src/main/java/ru/fusionsoft/dbgit/core/DBGitLang.java @@ -2,6 +2,7 @@ import java.io.File; import java.io.FileInputStream; +import java.util.Arrays; import java.util.Map; import org.yaml.snakeyaml.Yaml; @@ -29,11 +30,16 @@ private DBGitLang() { path = path.substring(0, i); } - mapValue = (Map) - new Yaml().load(new FileInputStream(new File(path + "/lang/" + - DBGitConfig.getInstance().getString("core", "LANG", DBGitConfig.getInstance().getStringGlobal("core", "LANG", "no")).toLowerCase() + ".yaml"))); + mapValue = new Yaml().load( + new FileInputStream( + new File( + path + + "/lang/" + + DBGitConfig.getInstance().getString("core", "LANG", DBGitConfig.getInstance().getStringGlobal("core", "LANG", "no")).toLowerCase() + + ".yaml") + ) + ); } catch (Exception e) { - ConsoleWriter.println(e.getLocalizedMessage()); throw new ExceptionDBGitRunTime(e); } } @@ -43,7 +49,7 @@ public static DBGitLang getInstance() { return lang; } - public DBGitLang getValue(String... args) { + public DBGitLang getValue(String... args) throws ExceptionDBGitRunTime { Object val = mapValue; value = ""; for (String arg : args) { @@ -52,8 +58,13 @@ public DBGitLang getValue(String... args) { val = newVal.get(arg); } - if (val != null) + if (val != null){ value = val.toString(); + if(value.equals("")) throw new ExceptionDBGitRunTime("Empty `lang` value for " + Arrays.toString(args)); + } + else { + throw new ExceptionDBGitRunTime("Cannot find `lang` value for " + Arrays.toString(args)); + } return this; } diff --git a/src/main/java/ru/fusionsoft/dbgit/core/DBGitPath.java b/src/main/java/ru/fusionsoft/dbgit/core/DBGitPath.java index 435cd21..437f33b 100644 --- a/src/main/java/ru/fusionsoft/dbgit/core/DBGitPath.java +++ b/src/main/java/ru/fusionsoft/dbgit/core/DBGitPath.java @@ -5,16 +5,11 @@ import java.sql.DriverManager; import java.text.SimpleDateFormat; import java.util.Calendar; -import java.util.Date; import java.util.GregorianCalendar; import java.util.Properties; -import java.util.stream.Stream; - -import javax.print.attribute.standard.DateTimeAtCompleted; import ru.fusionsoft.dbgit.adapters.AdapterFactory; import ru.fusionsoft.dbgit.meta.DBGitMetaType; -import ru.fusionsoft.dbgit.utils.ConsoleWriter; import ru.fusionsoft.dbgit.utils.Convertor; /** @@ -89,7 +84,7 @@ public static String getScriptsPath() throws ExceptionDBGit { return dbGit.getRootDirectory()+"/" + DB_GIT_PATH + "/" + SCRIPT_PATH + "/"; } - public static String getFullPath() throws ExceptionDBGit { + public static String getFullPath() { DBGit dbGit = DBGit.getInstance(); return dbGit.getRootDirectory()+"/"+DB_GIT_PATH + "/"; } @@ -100,7 +95,7 @@ public static String getRootPath(String path) throws ExceptionDBGit { } public static boolean isRepositoryExists() throws ExceptionDBGit { - return DBGit.checkIfRepositoryExists(); + return DBGit.repositoryExists(); } public static String getRootPath() throws ExceptionDBGit { @@ -166,8 +161,8 @@ public static boolean createDefaultDbgitConfig(String path) throws ExceptionDBGi writer.write("LOG_ROTATE = 31\n"); writer.write("LANG = ENG\n"); writer.write("SCRIPT_ROTATE = 31\n"); - writer.write("TO_MAKE_BACKUP = true\n"); - writer.write("BACKUP_TO_SCHEME = false\n"); + writer.write("TO_MAKE_BACKUP = false\n"); + writer.write("BACKUP_TO_SCHEME = true\n"); writer.write("BACKUP_TABLEDATA = true\n"); writer.write("PORTION_SIZE = 50000\n"); writer.write("TRY_COUNT = 1000\n"); @@ -200,7 +195,6 @@ public static boolean createDefaultDbignore(String path, String url, Properties return false; } catch(Exception e) { - e.printStackTrace(); throw new ExceptionDBGit(e); } } diff --git a/src/main/java/ru/fusionsoft/dbgit/core/ExceptionDBGit.java b/src/main/java/ru/fusionsoft/dbgit/core/ExceptionDBGit.java index 58f3804..8cb9527 100644 --- a/src/main/java/ru/fusionsoft/dbgit/core/ExceptionDBGit.java +++ b/src/main/java/ru/fusionsoft/dbgit/core/ExceptionDBGit.java @@ -1,10 +1,14 @@ package ru.fusionsoft.dbgit.core; +import org.apache.commons.lang3.exception.ExceptionUtils; import org.slf4j.Logger; import ru.fusionsoft.dbgit.utils.ConsoleWriter; import ru.fusionsoft.dbgit.utils.LoggerUtil; +import java.sql.Connection; +import java.sql.SQLException; + /** * Base class for all Exception in dbgit project * @@ -14,30 +18,17 @@ public class ExceptionDBGit extends Exception { private static final long serialVersionUID = -4613368557825624023L; - private Logger logger = LoggerUtil.getLogger(this.getClass()); public ExceptionDBGit(Object msg) { - ConsoleWriter.printlnRed(msg); - System.exit(1); - //super(msg); - } - - public ExceptionDBGit(String msg) { - ConsoleWriter.printlnRed(msg); - System.exit(1); - //super(msg); + super(String.valueOf(msg)); } - - public ExceptionDBGit(String message, Throwable cause) { - ConsoleWriter.printlnRed(message); - logger.error(message, cause); - System.exit(1); - //super(message, cause); + public ExceptionDBGit(Object message, Throwable cause) { + super(String.valueOf(message), cause); } - public ExceptionDBGit(Throwable cause) { - logger.error(cause.getLocalizedMessage(), cause); - //super(cause); + super(cause); } + + } diff --git a/src/main/java/ru/fusionsoft/dbgit/core/ExceptionDBGitObjectNotFound.java b/src/main/java/ru/fusionsoft/dbgit/core/ExceptionDBGitObjectNotFound.java index 0d27866..04a5b09 100644 --- a/src/main/java/ru/fusionsoft/dbgit/core/ExceptionDBGitObjectNotFound.java +++ b/src/main/java/ru/fusionsoft/dbgit/core/ExceptionDBGitObjectNotFound.java @@ -1,6 +1,6 @@ package ru.fusionsoft.dbgit.core; -public class ExceptionDBGitObjectNotFound extends ExceptionDBGit { +public class ExceptionDBGitObjectNotFound extends Error { private static final long serialVersionUID = 2163408974338332577L; diff --git a/src/main/java/ru/fusionsoft/dbgit/core/ExceptionDBGitRestore.java b/src/main/java/ru/fusionsoft/dbgit/core/ExceptionDBGitRestore.java index c9527e5..3ade4de 100644 --- a/src/main/java/ru/fusionsoft/dbgit/core/ExceptionDBGitRestore.java +++ b/src/main/java/ru/fusionsoft/dbgit/core/ExceptionDBGitRestore.java @@ -1,23 +1,12 @@ package ru.fusionsoft.dbgit.core; -import ru.fusionsoft.dbgit.utils.ConsoleWriter; - public class ExceptionDBGitRestore extends ExceptionDBGit { private static final long serialVersionUID = -8714585942496838509L; - public ExceptionDBGitRestore(String msg) { - super(msg); - ConsoleWriter.println("\n" + msg); - } - - public ExceptionDBGitRestore(String message, Throwable cause) { - super(message, cause); - ConsoleWriter.println("\n" + message + "\n" + cause.getLocalizedMessage()); - } - - public ExceptionDBGitRestore(Throwable cause) { - super(cause); - ConsoleWriter.println(cause.getLocalizedMessage()); - } + public ExceptionDBGitRestore(Object msg) { super(msg); } + public ExceptionDBGitRestore(Object message, Throwable cause) { super(message, cause); } + public ExceptionDBGitRestore(Throwable cause) { super(cause); } + + } diff --git a/src/main/java/ru/fusionsoft/dbgit/core/ExceptionDBGitRunTime.java b/src/main/java/ru/fusionsoft/dbgit/core/ExceptionDBGitRunTime.java index f730db4..10dda5e 100644 --- a/src/main/java/ru/fusionsoft/dbgit/core/ExceptionDBGitRunTime.java +++ b/src/main/java/ru/fusionsoft/dbgit/core/ExceptionDBGitRunTime.java @@ -1,29 +1,19 @@ package ru.fusionsoft.dbgit.core; -import org.slf4j.Logger; - -import ru.fusionsoft.dbgit.utils.ConsoleWriter; -import ru.fusionsoft.dbgit.utils.LoggerUtil; public class ExceptionDBGitRunTime extends RuntimeException { private static final long serialVersionUID = 958722213419205629L; - private Logger logger = LoggerUtil.getLogger(this.getClass()); - - public ExceptionDBGitRunTime(String msg) { - super(msg); + + public ExceptionDBGitRunTime(Object msg) { + super(msg.toString()); } - - public ExceptionDBGitRunTime(String message, Throwable cause) { - ConsoleWriter.printlnRed(message); - logger.error(message, cause); - System.exit(1); - //super(message, cause); + + public ExceptionDBGitRunTime(Object message, Throwable cause) { + super(message.toString(), cause); } - + public ExceptionDBGitRunTime(Throwable cause) { - //super(cause); - logger.error(cause.getLocalizedMessage(), cause); + super(cause); } - } diff --git a/src/main/java/ru/fusionsoft/dbgit/core/ExceptionDBGitTableData.java b/src/main/java/ru/fusionsoft/dbgit/core/ExceptionDBGitTableData.java new file mode 100644 index 0000000..9bd2cc8 --- /dev/null +++ b/src/main/java/ru/fusionsoft/dbgit/core/ExceptionDBGitTableData.java @@ -0,0 +1,29 @@ +package ru.fusionsoft.dbgit.core; + +public class ExceptionDBGitTableData extends Exception{ + private int errorFlag; + + public ExceptionDBGitTableData(int errorFlag) { + this.errorFlag = errorFlag; + } + + public ExceptionDBGitTableData(String message, int errorFlag) { + super(message); + this.errorFlag = errorFlag; + } + + public ExceptionDBGitTableData(String message, Throwable cause, int errorFlag) { + super(message, cause); + this.errorFlag = errorFlag; + } + + public ExceptionDBGitTableData(Throwable cause, int errorFlag) { + super(cause); + this.errorFlag = errorFlag; + } + + public ExceptionDBGitTableData(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, int errorFlag) { + super(message, cause, enableSuppression, writableStackTrace); + this.errorFlag = errorFlag; + } +} diff --git a/src/main/java/ru/fusionsoft/dbgit/core/GitMetaDataManager.java b/src/main/java/ru/fusionsoft/dbgit/core/GitMetaDataManager.java index 04af7ae..bf50d04 100644 --- a/src/main/java/ru/fusionsoft/dbgit/core/GitMetaDataManager.java +++ b/src/main/java/ru/fusionsoft/dbgit/core/GitMetaDataManager.java @@ -1,388 +1,415 @@ -package ru.fusionsoft.dbgit.core; - -import java.io.IOException; -import java.sql.SQLException; -import java.sql.Timestamp; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import ru.fusionsoft.dbgit.adapters.AdapterFactory; -import ru.fusionsoft.dbgit.adapters.IDBAdapter; -import ru.fusionsoft.dbgit.dbobjects.DBOptionsObject; -import ru.fusionsoft.dbgit.dbobjects.DBSQLObject; -import ru.fusionsoft.dbgit.dbobjects.DBSchema; -import ru.fusionsoft.dbgit.dbobjects.DBSequence; -import ru.fusionsoft.dbgit.dbobjects.DBTable; -import ru.fusionsoft.dbgit.meta.DBGitMetaType; -import ru.fusionsoft.dbgit.meta.IMapMetaObject; -import ru.fusionsoft.dbgit.meta.IMetaObject; -import ru.fusionsoft.dbgit.meta.MetaObjOptions; -import ru.fusionsoft.dbgit.meta.MetaObjectFactory; -import ru.fusionsoft.dbgit.meta.MetaSequence; -import ru.fusionsoft.dbgit.meta.MetaSql; -import ru.fusionsoft.dbgit.meta.MetaTable; -import ru.fusionsoft.dbgit.meta.MetaTableData; -import ru.fusionsoft.dbgit.meta.TreeMapMetaObject; -import ru.fusionsoft.dbgit.utils.ConsoleWriter; - -/** - *
Manager of meta description objects.
- *
Менеджер объектов метаописания.
- * - * @author mikle - * - */ -public class GitMetaDataManager { - private static GitMetaDataManager manager = null; - - protected IMapMetaObject dbObjs; - protected IMapMetaObject fileObjs; - - private MetaTableData currentPortion = null; - private int currentPortionIndex = 0; - - protected GitMetaDataManager() { - dbObjs = new TreeMapMetaObject(); - fileObjs = new TreeMapMetaObject(); - } - - public static GitMetaDataManager getInstance() { - if (manager == null) { - manager = new GitMetaDataManager(); - } - return manager; - } - - private void addToMapDBOptionsObject( - IMapMetaObject objs, - Map map, - DBGitMetaType type - ) throws ExceptionDBGit { - if (map == null) return ; - - DBGitIgnore ignore = DBGitIgnore.getInstance(); - - for (DBOptionsObject item : map.values()) { - MetaObjOptions obj = (MetaObjOptions)MetaObjectFactory.createMetaObject(type); - obj.setObjectOption(item); - - if (ignore.matchOne(obj.getName())) continue ; - - objs.put(obj); - } - } - - private void addToMapSqlObject( - IMapMetaObject objs, - Map map, - DBGitMetaType type - ) throws ExceptionDBGit { - if (map == null) return ; - - DBGitIgnore ignore = DBGitIgnore.getInstance(); - - for (DBSQLObject item : map.values()) { - MetaSql obj = (MetaSql)MetaObjectFactory.createMetaObject(type); - obj.setSqlObject(item); - - if (ignore.matchOne(obj.getName())) continue ; - - objs.put(obj); - } - } - - public boolean loadFromDB(IMetaObject obj) throws ExceptionDBGit { - boolean result = obj.loadFromDB(); - if (result) - dbObjs.put(obj); - return result; - } - - public IMetaObject getCacheDBMetaObject(String name) { - return dbObjs.get(name); - } - - /** - * Get cache meta objects load from bd - * @return - */ - public IMapMetaObject getCacheDBMetaData() { - return dbObjs; - } - - /** - * Get cache meta objects load from files - * @return - */ - public IMapMetaObject getCacheFileMetaData() { - return fileObjs; - } - - public boolean loadNextPortion(MetaTable tbl) throws ExceptionDBGit { - if (currentPortion == null || !tbl.getName().replace(".tbl", ".csv") .equalsIgnoreCase(currentPortion.getName())) - currentPortionIndex = 0; - - ConsoleWriter.detailsPrint(DBGitLang.getInstance().getValue("general", "add", "loading") + " " + currentPortionIndex + ", ", 2); - currentPortion = new MetaTableData(tbl.getTable()); - - if (currentPortion.getmapRows() != null) - currentPortion.getmapRows().clear(); - - if (!currentPortion.loadPortionFromDB(currentPortionIndex)) return false; - ConsoleWriter.detailsPrint(DBGitLang.getInstance().getValue("general", "add", "size") + " " + currentPortion.getmapRows().size() + "\n", 2); - - currentPortionIndex++; - try { - DBGitConfig.getInstance().setValue("CURRENT_PORTION", String.valueOf(currentPortionIndex)); - } catch (Exception e) { - throw new ExceptionDBGit(e); - } - - return currentPortion.getmapRows().size() > 0; - } - - public MetaTableData getCurrent() { - return currentPortion; - } - - public void setCurrentPortion(int currentPortionIndex) { - this.currentPortionIndex = currentPortionIndex; - } - - /** - * Load meta data from DB - * @return - */ - public IMapMetaObject loadDBMetaData() throws ExceptionDBGit { - IDBAdapter adapter = AdapterFactory.createAdapter(); - - DBGitIgnore ignore = DBGitIgnore.getInstance(); - - dbObjs.clear(); - Map tbls = new HashMap(); - - if (!ignore.matchOne("*." + DBGitMetaType.DBGitUser.getValue())) - addToMapDBOptionsObject(dbObjs, adapter.getUsers(), DBGitMetaType.DBGitUser); - - if (!ignore.matchOne("*." + DBGitMetaType.DBGitRole.getValue())) - addToMapDBOptionsObject(dbObjs, adapter.getRoles(), DBGitMetaType.DBGitRole); - //addToMapDBOptionsObject(dbObjs, adapter.getTableSpaces(), DBGitMetaType.DBGitTableSpace); - - Map schemes; - if (adapter.userHasRightsToGetDdlOfOtherUsers()) { - schemes = adapter.getSchemes(); - } else { - schemes = new HashMap(); - try { - schemes.put(adapter.getConnection().getSchema(), new DBSchema(adapter.getConnection().getSchema())); - ConsoleWriter.println(DBGitLang.getInstance().getValue("errors", "meta", "cantGetOtherUsersObjects")); - } catch (SQLException e) { - throw new ExceptionDBGit(DBGitLang.getInstance().getValue("errors", "meta", "cantGetCurrentSchema")); - } - } - - addToMapDBOptionsObject(dbObjs, schemes, DBGitMetaType.DBGitSchema); - - //load sequence - for (DBSchema schema : schemes.values()) { - if (ignore.matchSchema(schema.getName())) continue; - if (!ignore.matchOne(schema.getName() + "/*." + DBGitMetaType.DBGitSequence.getValue())) { - for (DBSequence seq : adapter.getSequences(schema.getName()).values()) { - MetaSequence metaSeq = new MetaSequence(); - metaSeq.setSequence(seq); - if (ignore.matchOne(metaSeq.getName())) continue ; - dbObjs.put(metaSeq); - } - } - - } - - - //load tables - for (DBSchema sch : schemes.values()) { - if (ignore.matchSchema(sch.getName())) continue; - - if (!ignore.matchOne(sch.getName() + "/*." + DBGitMetaType.DBGitTable.getValue())) { - for (DBTable tbl : adapter.getTables(sch.getName()).values()) { - MetaTable tblMeta = new MetaTable(tbl); - if (ignore.matchOne(tblMeta.getName())) { - continue ; - } - if ( tblMeta.loadFromDB(tbl) ) { - dbObjs.put(tblMeta); - tbls.put(tblMeta.getName(), tblMeta); - } - } - } - } - - //triggers, packages, functions, procedures, views - for (DBSchema schema : schemes.values()) { - if (ignore.matchSchema(schema.getName())) continue; - - if (!ignore.matchOne(schema.getName() + "/*." + DBGitMetaType.DbGitTrigger.getValue())) - addToMapSqlObject(dbObjs, adapter.getTriggers(schema.getName()), DBGitMetaType.DbGitTrigger); - if (!ignore.matchOne(schema.getName() + "/*." + DBGitMetaType.DbGitPackage.getValue())) - addToMapSqlObject(dbObjs, adapter.getPackages(schema.getName()), DBGitMetaType.DbGitPackage); - if (!ignore.matchOne(schema.getName() + "/*." + DBGitMetaType.DbGitFunction.getValue())) - addToMapSqlObject(dbObjs, adapter.getFunctions(schema.getName()), DBGitMetaType.DbGitFunction); - if (!ignore.matchOne(schema.getName() + "/*." + DBGitMetaType.DbGitProcedure.getValue())) - addToMapSqlObject(dbObjs, adapter.getProcedures(schema.getName()), DBGitMetaType.DbGitProcedure); - if (!ignore.matchOne(schema.getName() + "/*." + DBGitMetaType.DbGitView.getValue())) - addToMapSqlObject(dbObjs, adapter.getViews(schema.getName()), DBGitMetaType.DbGitView); - } - - //data tables - /* - for (MetaTable tbl : tbls.values()) { - MetaTableData data = new MetaTableData(tbl.getTable()); - - if (ignore.matchOne(data.getName())) continue ; - - if (data.loadFromDB()) - dbObjs.put(data); - } - */ - IMapMetaObject customObjs = adapter.loadCustomMetaObjects(); - if (customObjs != null) { - IMapMetaObject customObjsNoIgnore = new TreeMapMetaObject(); - for (IMetaObject item : customObjs.values()) { - if (ignore.matchOne(item.getName())) continue ; - customObjsNoIgnore.put(item); - } - dbObjs.putAll(customObjs); - } - - return dbObjs; - } - - public IMapMetaObject loadFileMetaData() throws ExceptionDBGit { - return loadFileMetaData(false); - } - - public IMapMetaObject loadFileMetaDataForce() throws ExceptionDBGit { - return loadFileMetaData(true); - } - - /** - * Load meta data from git files - * @return - */ - public IMapMetaObject loadFileMetaData(boolean force) throws ExceptionDBGit { - try { - IMapMetaObject objs = new TreeMapMetaObject(); - DBGit dbGit = DBGit.getInstance(); - - List files = dbGit.getGitIndexFiles(DBGitPath.DB_GIT_PATH); - boolean isSuccessful = true; - - for (int i = 0; i < files.size(); i++) { - String filename = files.get(i); - if (DBGitPath.isServiceFile(filename)) continue; -// ConsoleWriter.detailsPrint(filename + "...", 1); - - if (force) { - IMetaObject obj = loadMetaFile(filename); - - if (obj != null) - objs.put(obj); - -// ConsoleWriter.detailsPrintlnGreen(DBGitLang.getInstance().getValue("errors", "meta", "ok")); - } else { - try { - Timestamp timestampBefore = new Timestamp(System.currentTimeMillis()); - IMetaObject obj = loadMetaFile(filename); - - Timestamp timestampAfter = new Timestamp(System.currentTimeMillis()); - Long diff = timestampAfter.getTime() - timestampBefore.getTime(); - -// ConsoleWriter.detailsPrintlnGreen(DBGitLang.getInstance().getValue("errors", "meta", "okTime").withParams(diff.toString())); - - if (obj != null) { - objs.put(obj); - } - } catch (Exception e) { - isSuccessful = false; - ConsoleWriter.detailsPrintlnRed(DBGitLang.getInstance().getValue("errors", "meta", "fail")); - e.printStackTrace(); - ConsoleWriter.detailsPrintLn(e.getMessage()); - - IMetaObject obj = MetaObjectFactory.createMetaObject(filename); - - if (obj != null) - objs.put(obj); - } - } - } - - if (!isSuccessful && !force) { - throw new ExceptionDBGit(DBGitLang.getInstance().getValue("errors", "meta", "invalidFiles")); - } - - return objs; - } catch(Exception e) { - throw new ExceptionDBGit(e); - } - } - - public IMetaObject loadMetaFile(String metaName) throws ExceptionDBGit { - AdapterFactory.createAdapter(); - if (fileObjs.containsKey(metaName)) - return fileObjs.get(metaName); - try { - IMetaObject obj = MetaObjectFactory.createMetaObject(metaName); - obj = obj.loadFromFile(); - if (obj != null) { - fileObjs.put(obj); - } - return obj; - } catch(Exception e) { - throw new ExceptionDBGit(e); - } - } - - /** - * Restore map meta object to DB - * @param updateObjs - */ - public void restoreDataBase(IMapMetaObject updateObjs) throws Exception { - IDBAdapter adapter = AdapterFactory.createAdapter(); - - adapter.startUpdateDB(); - - adapter.restoreDataBase(updateObjs); - - adapter.endUpdateDB(); - - } - - /** - * Delete map meta object from DB and index if specified - * @param deleteObjs - * @param isDeleteFromIndex should I delete dropped object entry from dbindex? - */ - public void deleteDataBase(IMapMetaObject deleteObjs, boolean isDeleteFromIndex) throws Exception { - IDBAdapter adapter = AdapterFactory.createAdapter(); - adapter.deleteDataBase(deleteObjs, isDeleteFromIndex); - } - - /** - * Delete map meta object from DB - * @param deleteObjs - */ - public void deleteDataBase(IMapMetaObject deleteObjs) throws Exception { - IDBAdapter adapter = AdapterFactory.createAdapter(); - adapter.deleteDataBase(deleteObjs, false); - } - - public int removeFromGit(ItemIndex itemIndex) throws ExceptionDBGit { - DBGit dbGit = DBGit.getInstance(); - IMetaObject dummyImo = IMetaObject.create(itemIndex.getName()); - dbGit.removeFileFromIndexGit(DBGitPath.DB_GIT_PATH+"/"+ dummyImo.getFileName()); - return 1; - } -} +package ru.fusionsoft.dbgit.core; + +import java.io.IOException; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import ru.fusionsoft.dbgit.adapters.AdapterFactory; +import ru.fusionsoft.dbgit.adapters.IDBAdapter; +import ru.fusionsoft.dbgit.dbobjects.DBOptionsObject; +import ru.fusionsoft.dbgit.dbobjects.DBSQLObject; +import ru.fusionsoft.dbgit.dbobjects.DBSchema; +import ru.fusionsoft.dbgit.dbobjects.DBSequence; +import ru.fusionsoft.dbgit.dbobjects.DBTable; +import ru.fusionsoft.dbgit.meta.DBGitMetaType; +import ru.fusionsoft.dbgit.meta.IMapMetaObject; +import ru.fusionsoft.dbgit.meta.IMetaObject; +import ru.fusionsoft.dbgit.meta.MetaObjOptions; +import ru.fusionsoft.dbgit.meta.MetaObjectFactory; +import ru.fusionsoft.dbgit.meta.MetaSequence; +import ru.fusionsoft.dbgit.meta.MetaSql; +import ru.fusionsoft.dbgit.meta.MetaTable; +import ru.fusionsoft.dbgit.meta.MetaTableData; +import ru.fusionsoft.dbgit.meta.TreeMapMetaObject; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; + +/** + *
Manager of meta description objects.
+ *
Менеджер объектов метаописания.
+ * + * @author mikle + * + */ +public class GitMetaDataManager { + private static GitMetaDataManager manager = null; + + protected IMapMetaObject dbObjs; + protected IMapMetaObject fileObjs; + + private MetaTableData currentPortion = null; + private int currentPortionIndex = 0; + private static int messageLevel = 1; + + protected GitMetaDataManager() { + dbObjs = new TreeMapMetaObject(); + fileObjs = new TreeMapMetaObject(); + } + + public static GitMetaDataManager getInstance() { + if (manager == null) { + manager = new GitMetaDataManager(); + } + return manager; + } + + private void addToMapDBOptionsObject( + IMapMetaObject objs, + Map map, + DBGitMetaType type + ) throws ExceptionDBGit { + if (map == null) return ; + + DBGitIgnore ignore = DBGitIgnore.getInstance(); + + for (DBOptionsObject item : map.values()) { + MetaObjOptions obj = (MetaObjOptions)MetaObjectFactory.createMetaObject(type); + obj.setObjectOption(item); + + if (ignore.matchOne(obj.getName())) continue ; + + objs.put(obj); + } + } + + private void addToMapSqlObject( + IMapMetaObject objs, + Map map, + DBGitMetaType type + ) throws ExceptionDBGit { + if (map == null) return ; + + DBGitIgnore ignore = DBGitIgnore.getInstance(); + + for (DBSQLObject item : map.values()) { + MetaSql obj = (MetaSql)MetaObjectFactory.createMetaObject(type); + obj.setSqlObject(item); + + if (ignore.matchOne(obj.getName())) continue ; + + objs.put(obj); + } + } + + public boolean loadFromDB(IMetaObject obj) throws ExceptionDBGit { + try { + boolean result = obj.loadFromDB(); + if (result) dbObjs.put(obj); + return result; + } catch (ExceptionDBGitObjectNotFound ex) { + return false; + } + } + + public IMetaObject getCacheDBMetaObject(String name) { + return dbObjs.get(name); + } + + /** + * Get cache meta objects load from bd + * @return + */ + public IMapMetaObject getCacheDBMetaData() { + return dbObjs; + } + + /** + * Get cache meta objects load from files + * @return + */ + public IMapMetaObject getCacheFileMetaData() { + return fileObjs; + } + + public boolean loadNextPortion(MetaTable tbl) throws ExceptionDBGit { + if (currentPortion == null || !tbl.getName().replace(".tbl", ".csv") .equalsIgnoreCase(currentPortion.getName())) + currentPortionIndex = 0; + + ConsoleWriter.detailsPrintln(DBGitLang.getInstance().getValue("general", "add", "loading") + " " + currentPortionIndex + ", ", messageLevel); + currentPortion = new MetaTableData(tbl.getTable()); + + if (currentPortion.getmapRows() != null) + currentPortion.getmapRows().clear(); + + if (!currentPortion.loadPortionFromDB(currentPortionIndex)) return false; + ConsoleWriter.detailsPrintln(DBGitLang.getInstance().getValue("general", "add", "size") + " " + currentPortion.getmapRows().size() , messageLevel); + + currentPortionIndex++; + try { + DBGitConfig.getInstance().setValue("CURRENT_PORTION", String.valueOf(currentPortionIndex)); + } catch (Exception e) { + throw new ExceptionDBGit(e); + } + + return currentPortion.getmapRows().size() > 0; + } + + public MetaTableData getCurrent() { + return currentPortion; + } + + public void setCurrentPortion(int currentPortionIndex) { + this.currentPortionIndex = currentPortionIndex; + } + + /** + * Load meta data from DB + * @return + */ + public IMapMetaObject loadDBMetaData(boolean includeBackupSchemas) throws ExceptionDBGit { + IDBAdapter adapter = AdapterFactory.createAdapter(); + + DBGitIgnore ignore = (includeBackupSchemas) + ? new DBGitIgnore() { @Override protected void loadFileDBIgnore() throws ExceptionDBGit { loadFileDBIgnore(true); }} + : DBGitIgnore.getInstance(); + + dbObjs.clear(); + Map tbls = new HashMap(); + + if (!ignore.matchOne("*." + DBGitMetaType.DBGitUser.getValue())) + addToMapDBOptionsObject(dbObjs, adapter.getUsers(), DBGitMetaType.DBGitUser); + + if (!ignore.matchOne("*." + DBGitMetaType.DBGitRole.getValue())) + addToMapDBOptionsObject(dbObjs, adapter.getRoles(), DBGitMetaType.DBGitRole); + //addToMapDBOptionsObject(dbObjs, adapter.getTableSpaces(), DBGitMetaType.DBGitTableSpace); + + Map schemes; + if (adapter.userHasRightsToGetDdlOfOtherUsers()) { + schemes = adapter.getSchemes(); + } else { + schemes = new HashMap(); + try { + final DBSchema dbSchema = new DBSchema(adapter.getConnection().getSchema()); + schemes.put(adapter.getConnection().getSchema(), dbSchema); + ConsoleWriter.println(DBGitLang.getInstance().getValue("errors", "meta", "cantGetOtherUsersObjects"), messageLevel); + } catch (SQLException e) { + throw new ExceptionDBGit(DBGitLang.getInstance().getValue("errors", "meta", "cantGetCurrentSchema").toString(), e); + } + } + + addToMapDBOptionsObject(dbObjs, schemes, DBGitMetaType.DBGitSchema); + + //load sequence + for (DBSchema schema : schemes.values()) { + if (ignore.matchSchema(schema.getName())) continue; + if (!ignore.matchOne(schema.getName() + "/*." + DBGitMetaType.DBGitSequence.getValue())) { + for (DBSequence seq : adapter.getSequences(schema.getName()).values()) { + MetaSequence metaSeq = new MetaSequence(); + metaSeq.setSequence(seq); + if (ignore.matchOne(metaSeq.getName())) continue ; + dbObjs.put(metaSeq); + } + } + + } + + + //load tables + for (DBSchema sch : schemes.values()) { + if (ignore.matchSchema(sch.getName())) continue; + + if (!ignore.matchOne(sch.getName() + "/*." + DBGitMetaType.DBGitTable.getValue())) { + for (DBTable tbl : adapter.getTables(sch.getName()).values()) { + MetaTable tblMeta = new MetaTable(tbl); + if (ignore.matchOne(tblMeta.getName())) { + continue ; + } + if ( tblMeta.loadFromDB(tbl) ) { + dbObjs.put(tblMeta); + tbls.put(tblMeta.getName(), tblMeta); + } + } + } + } + + //triggers, packages, functions, procedures, views + for (DBSchema schema : schemes.values()) { + if (ignore.matchSchema(schema.getName())) continue; + + if (!ignore.matchOne(schema.getName() + "/*." + DBGitMetaType.DbGitTrigger.getValue())) + addToMapSqlObject(dbObjs, adapter.getTriggers(schema.getName()), DBGitMetaType.DbGitTrigger); + if (!ignore.matchOne(schema.getName() + "/*." + DBGitMetaType.DbGitPackage.getValue())) + addToMapSqlObject(dbObjs, adapter.getPackages(schema.getName()), DBGitMetaType.DbGitPackage); + if (!ignore.matchOne(schema.getName() + "/*." + DBGitMetaType.DbGitFunction.getValue())) + addToMapSqlObject(dbObjs, adapter.getFunctions(schema.getName()), DBGitMetaType.DbGitFunction); + if (!ignore.matchOne(schema.getName() + "/*." + DBGitMetaType.DbGitProcedure.getValue())) + addToMapSqlObject(dbObjs, adapter.getProcedures(schema.getName()), DBGitMetaType.DbGitProcedure); + if (!ignore.matchOne(schema.getName() + "/*." + DBGitMetaType.DbGitView.getValue())) + addToMapSqlObject(dbObjs, adapter.getViews(schema.getName()), DBGitMetaType.DbGitView); + if (!ignore.matchOne(schema.getName() + "/*." + DBGitMetaType.DBGitEnum.getValue())) + addToMapSqlObject(dbObjs, adapter.getEnums(schema.getName()), DBGitMetaType.DBGitEnum); + if (!ignore.matchOne(schema.getName() + "/*." + DBGitMetaType.DBGitUserDefinedType.getValue())) + addToMapSqlObject(dbObjs, adapter.getUDTs(schema.getName()), DBGitMetaType.DBGitUserDefinedType); + if (!ignore.matchOne(schema.getName() + "/*." + DBGitMetaType.DBGitDomain.getValue())) + addToMapSqlObject(dbObjs, adapter.getDomains(schema.getName()), DBGitMetaType.DBGitDomain); + } + + //data tables + /* + for (MetaTable tbl : tbls.values()) { + MetaTableData data = new MetaTableData(tbl.getTable()); + + if (ignore.matchOne(data.getName())) continue ; + + if (data.loadFromDB()) + dbObjs.put(data); + } + */ + IMapMetaObject customObjs = adapter.loadCustomMetaObjects(); + if (customObjs != null) { + IMapMetaObject customObjsNoIgnore = new TreeMapMetaObject(); + for (IMetaObject item : customObjs.values()) { + if (ignore.matchOne(item.getName())) continue ; + customObjsNoIgnore.put(item); + } + dbObjs.putAll(customObjs); + } + + return dbObjs; + } + + public IMapMetaObject loadDBMetaData() throws ExceptionDBGit { + return loadDBMetaData(false); + } + + + public IMapMetaObject loadFileMetaData() throws ExceptionDBGit { + return loadFileMetaData(false); + } + + public IMapMetaObject loadFileMetaDataForce() throws ExceptionDBGit { + return loadFileMetaData(true); + } + + /** + * Load meta data from git files + * @return + */ + public IMapMetaObject loadFileMetaData(boolean force) throws ExceptionDBGit { + try { + IMapMetaObject objs = new TreeMapMetaObject(); + DBGit dbGit = DBGit.getInstance(); + + List files = dbGit.getGitIndexFiles(DBGitPath.DB_GIT_PATH); + boolean isSuccessful = true; + + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("general", "meta", "loadFiles") + .withParams("") + , messageLevel + ); + + for (int i = 0; i < files.size(); i++) { + String filename = files.get(i); + if (DBGitPath.isServiceFile(filename)) continue; + + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("general", "meta", "loadFile") + .withParams(filename) + , messageLevel+1 + ); + + if (force) { + IMetaObject obj = loadMetaFile(filename); + + if (obj != null) { + objs.put(obj); + } + + } else { + try { + IMetaObject obj = loadMetaFile(filename); + + if (obj != null) { + objs.put(obj); + } + } catch (Exception e) { +// ConsoleWriter.printlnRed(DBGitLang.getInstance().getValue("errors", "meta", "loadMetaFile") + final String msg = DBGitLang.getInstance() + .getValue("errors", "meta", "cantLoadMetaFile") + .withParams(filename); + throw new ExceptionDBGit(msg, e); +// isSuccessful = false; +// ConsoleWriter.detailsPrintln(e.getMessage(), messageLevel); +// IMetaObject obj = MetaObjectFactory.createMetaObject(filename); +// objs.put(obj); + } + } + } + +// if (!isSuccessful && !force) { +// throw new ExceptionDBGit(DBGitLang.getInstance().getValue("errors", "meta", "invalidFiles")); +// } + + return objs; + } catch(Exception e) { + throw new ExceptionDBGit(e); + } + } + + public IMetaObject loadMetaFile(String metaName) throws ExceptionDBGit { + return loadMetaFile(metaName, true); + } + + public IMetaObject loadMetaFile(String metaName, boolean forceLoad) throws ExceptionDBGit { + AdapterFactory.createAdapter(); + if (!forceLoad && fileObjs.containsKey(metaName)) return fileObjs.get(metaName); + try + { + IMetaObject obj = MetaObjectFactory.createMetaObject(metaName); + obj = obj.loadFromFile(); + if (obj != null) { + fileObjs.put(obj); + } + return obj; + } catch(Exception e) { + throw new ExceptionDBGit(e.getLocalizedMessage(), e); + } + } + + /** + * Restore map meta object to DB + * @param updateObjs + */ + public void restoreDataBase(IMapMetaObject updateObjs) throws Exception { + IDBAdapter adapter = AdapterFactory.createAdapter(); + + adapter.startUpdateDB(); + + adapter.restoreDataBase(updateObjs); + + adapter.endUpdateDB(); + + } + + /** + * Delete map meta object from DB and index if specified + * @param deleteObjs + * @param isDeleteFromIndex should I delete dropped object entry from dbindex? + */ + public void deleteDataBase(IMapMetaObject deleteObjs, boolean isDeleteFromIndex) throws Exception { + IDBAdapter adapter = AdapterFactory.createAdapter(); + adapter.deleteDataBase(deleteObjs, isDeleteFromIndex); + } + + /** + * Delete map meta object from DB + * @param deleteObjs + */ + public void deleteDataBase(IMapMetaObject deleteObjs) throws Exception { + IDBAdapter adapter = AdapterFactory.createAdapter(); + adapter.deleteDataBase(deleteObjs, false); + } + + public int removeFromGit(ItemIndex itemIndex) throws ExceptionDBGit { + DBGit dbGit = DBGit.getInstance(); + IMetaObject dummyImo = IMetaObject.create(itemIndex.getName()); + dbGit.removeFileFromIndexGit(DBGitPath.DB_GIT_PATH+"/"+ dummyImo.getFileName()); + return 1; + } +} diff --git a/src/main/java/ru/fusionsoft/dbgit/core/NotImplementedExceptionDBGitRuntime.java b/src/main/java/ru/fusionsoft/dbgit/core/NotImplementedExceptionDBGitRuntime.java new file mode 100644 index 0000000..4356f0a --- /dev/null +++ b/src/main/java/ru/fusionsoft/dbgit/core/NotImplementedExceptionDBGitRuntime.java @@ -0,0 +1,7 @@ +package ru.fusionsoft.dbgit.core; + +public class NotImplementedExceptionDBGitRuntime extends ExceptionDBGitRunTime { + public NotImplementedExceptionDBGitRuntime(){ + super("Stub class can not use this method"); + } +} diff --git a/src/main/java/ru/fusionsoft/dbgit/core/db/FieldType.java b/src/main/java/ru/fusionsoft/dbgit/core/db/FieldType.java index 88bebb6..ba8c754 100644 --- a/src/main/java/ru/fusionsoft/dbgit/core/db/FieldType.java +++ b/src/main/java/ru/fusionsoft/dbgit/core/db/FieldType.java @@ -9,7 +9,10 @@ public enum FieldType { NATIVE("native"), NUMBER("number"), STRING("string"), - TEXT("text"); + STRING_NATIVE("string native"), + ENUM("enum"), + TEXT("text"), + UNDEFINED(""); private String typeName; diff --git a/src/main/java/ru/fusionsoft/dbgit/data_table/BooleanData.java b/src/main/java/ru/fusionsoft/dbgit/data_table/BooleanData.java index cc62bb8..f07d46c 100644 --- a/src/main/java/ru/fusionsoft/dbgit/data_table/BooleanData.java +++ b/src/main/java/ru/fusionsoft/dbgit/data_table/BooleanData.java @@ -7,13 +7,14 @@ public class BooleanData implements ICellData { - private Boolean value; + private boolean value; + private boolean isNull = false; @Override - public boolean loadFromDB(ResultSet rs, String fieldname) throws Exception { - value = rs.getBoolean(fieldname); + public boolean loadFromDB(ResultSet rs, String fieldName) throws Exception { + value = rs.getBoolean(fieldName); if (rs.wasNull()) { - value = null; + isNull = true; } return true; } @@ -25,7 +26,14 @@ public String serialize(DBTable tbl) throws Exception { @Override public void deserialize(String data) throws Exception { - this.value = (data == null) ? null : Boolean.valueOf(data); + //this.value = (data == null) ? null : Boolean.valueOf(data); + if (data == null) { + isNull = true; + value = false; + } else { + isNull = false; + value = Boolean.parseBoolean(data); + } } @Override @@ -40,7 +48,7 @@ public int removeFromGit() throws ExceptionDBGit { @Override public String convertToString() throws Exception { - return value != null ? value.toString() : null; + return !isNull ? String.valueOf(value) : null; } @Override @@ -49,12 +57,13 @@ public Object getWriterForRapair() { } public Boolean getValue() { + if (isNull) return null; return value; } @Override public String getSQLData() { - return (value == null) ? "''" : "\'"+value.toString()+"\'"; + return (isNull) ? "''" : "\'"+String.valueOf(value)+"\'"; } } diff --git a/src/main/java/ru/fusionsoft/dbgit/data_table/DateData.java b/src/main/java/ru/fusionsoft/dbgit/data_table/DateData.java index 0aaa665..095d34e 100644 --- a/src/main/java/ru/fusionsoft/dbgit/data_table/DateData.java +++ b/src/main/java/ru/fusionsoft/dbgit/data_table/DateData.java @@ -10,27 +10,41 @@ import ru.fusionsoft.dbgit.utils.Convertor; public class DateData implements ICellData { - Date value; - SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss"); + //private Date value; + private long value; + private boolean isNull = false; + public static SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss"); @Override public boolean loadFromDB(ResultSet rs, String fieldname) throws Exception { - value = rs.getDate(fieldname); + if (rs.getDate(fieldname) == null) { + isNull = true; + value = 0; + } else + value = rs.getDate(fieldname).getTime(); + return true; } @Override public String serialize(DBTable tbl) throws Exception { - return value == null ? null : format.format(value); + return isNull ? null : format.format(new Date(value)); } @Override public void deserialize(String data) throws Exception { - value = (data == null) ? null :new Date(format.parse(data).getTime()); + //value = (data == null) ? null :new Date(format.parse(data).getTime()); + if (data == null) { + isNull = true; + value = 0; + } else { + isNull = false; + value = format.parse(data).getTime(); + } } public void setValue(Date value) { - this.value = value; + this.value = value.getTime(); } @Override @@ -45,7 +59,7 @@ public int removeFromGit() throws ExceptionDBGit { @Override public String convertToString() throws Exception { - return (value == null) ? null : format.format(value); + return isNull ? null : format.format(new Date(value)); } @Override @@ -55,11 +69,11 @@ public Object getWriterForRapair() { @Override public String getSQLData() { - return (value == null) ? "''" : "\'"+format.format(value)+"\'"; + return isNull ? "''" : "\'"+format.format(new Date(value))+"\'"; } public Date getDate() { - return value; + return new Date(value); } } diff --git a/src/main/java/ru/fusionsoft/dbgit/data_table/LongData.java b/src/main/java/ru/fusionsoft/dbgit/data_table/LongData.java index 2bab5bf..0e04dd0 100644 --- a/src/main/java/ru/fusionsoft/dbgit/data_table/LongData.java +++ b/src/main/java/ru/fusionsoft/dbgit/data_table/LongData.java @@ -6,13 +6,14 @@ public class LongData implements ICellData { - private Long value; + private double value; + private boolean isNull = false; @Override public boolean loadFromDB(ResultSet rs, String fieldname) throws Exception { - value = rs.getLong(fieldname); + value = rs.getDouble(fieldname); if (rs.wasNull()) { - value = null; + isNull = true; } return true; } @@ -24,7 +25,14 @@ public String serialize(DBTable tbl) throws Exception { @Override public void deserialize(String data) throws Exception { - this.value = (data == null) ? null : Long.decode(data); + if (data == null) { + isNull = true; + value = 0; + } else { + isNull = false; + value = Double.parseDouble(data); + } + //this.value = (data == null) ? null : Long.decode(data); //this.value = Long.decode(data); /* try { @@ -37,14 +45,14 @@ public void deserialize(String data) throws Exception { @Override public String convertToString() { - return value != null ? value.toString() : null; + return !isNull ? String.valueOf(value) : null; } - public Long getValue() { + public double getValue() { return value; } - public void setValue(Long value) { + public void setValue(double value) { this.value = value; } @@ -62,7 +70,10 @@ public int removeFromGit() { @Override public String getSQLData() { - return (value == null) ? "''" : "\'"+value.toString()+"\'"; + return (isNull) ? "''" : "\'"+String.valueOf(value)+"\'"; + } + + public boolean isNull() { + return isNull; } - } diff --git a/src/main/java/ru/fusionsoft/dbgit/data_table/MapFileData.java b/src/main/java/ru/fusionsoft/dbgit/data_table/MapFileData.java index 32f6b1d..d127076 100644 --- a/src/main/java/ru/fusionsoft/dbgit/data_table/MapFileData.java +++ b/src/main/java/ru/fusionsoft/dbgit/data_table/MapFileData.java @@ -5,6 +5,8 @@ import java.nio.file.Files; import java.nio.file.StandardCopyOption; import java.sql.ResultSet; +import java.util.HashSet; +import java.util.Set; import ru.fusionsoft.dbgit.core.DBGit; import ru.fusionsoft.dbgit.core.DBGitLang; @@ -18,7 +20,10 @@ public class MapFileData implements ICellData { private String srcFile = null; private File tmpFile = null; - private String hash = null; + private static Set filesNotFound = new HashSet<>(); + private static int messageLevel = 2; + + //private String hash = null; public InputStream getBlobData(ResultSet rs, String fieldname) throws Exception { return rs.getBinaryStream(fieldname); @@ -44,7 +49,10 @@ public String serialize(DBTable tbl) throws Exception { DBGitPath.createDir(wrtFile.getAbsolutePath()); Files.move(tmpFile.toPath(), wrtFile.toPath(), StandardCopyOption.REPLACE_EXISTING); - ConsoleWriter.println(DBGitLang.getInstance().getValue("general", "dataTable", "writeData").withParams(srcFile)); + ConsoleWriter.println(DBGitLang.getInstance().getValue("general", "dataTable", "writeData") + .withParams(srcFile) + , messageLevel + ); tmpFile = null; } return srcFile; @@ -52,9 +60,15 @@ public String serialize(DBTable tbl) throws Exception { @Override public void deserialize(String data) throws Exception { - File fp = new File(DBGitPath.getFullPath()+"/"+data); - if (fp.exists()) { - this.srcFile = data; + if(data != null){ + File fp = new File(DBGitPath.getFullPath()+"/"+data); + if (fp.exists()) { + this.srcFile = data; + } else { + int lastIndex = data.lastIndexOf('/'); + lastIndex = lastIndex == 0 ? data.lastIndexOf('\\') : lastIndex; + filesNotFound.add(data.substring(0, lastIndex)); + } } } @@ -68,17 +82,18 @@ public Object getWriterForRapair() { } public String getHash() throws Exception { - if (hash == null) { + //if (hash == null) { + String hash; String path = null; if (tmpFile != null) path = tmpFile.getAbsolutePath(); if (srcFile != null) path = DBGitPath.getFullPath()+"/"+srcFile; if (path == null) return ""; - + CalcHash ch = new CalcHash(); ch.addDataFile(path); hash = ch.calcHashStr(); - } + //} return hash; } @@ -110,6 +125,10 @@ public String getSQLData() { public File getFile() throws ExceptionDBGit { return new File(DBGitPath.getFullPath() + srcFile); } + + public static Set getFilesNotFound(){ + return filesNotFound; + } } diff --git a/src/main/java/ru/fusionsoft/dbgit/data_table/RowData.java b/src/main/java/ru/fusionsoft/dbgit/data_table/RowData.java index eb68e56..a3e58f7 100644 --- a/src/main/java/ru/fusionsoft/dbgit/data_table/RowData.java +++ b/src/main/java/ru/fusionsoft/dbgit/data_table/RowData.java @@ -1,125 +1,194 @@ -package ru.fusionsoft.dbgit.data_table; - -import java.io.IOException; -import java.sql.ResultSet; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; - -import org.apache.commons.csv.CSVPrinter; -import org.apache.commons.csv.CSVRecord; - -import ru.fusionsoft.dbgit.core.DBGitLang; -import ru.fusionsoft.dbgit.core.ExceptionDBGit; -import ru.fusionsoft.dbgit.core.ExceptionDBGitRunTime; -import ru.fusionsoft.dbgit.dbobjects.DBTable; -import ru.fusionsoft.dbgit.meta.MetaTable; -import ru.fusionsoft.dbgit.utils.CalcHash; -import ru.fusionsoft.dbgit.utils.ConsoleWriter; - -public class RowData { - protected Map data = new LinkedHashMap<>(); - protected String hashRow; - protected String key; - protected MetaTable metaTable; - - public RowData(ResultSet rs, MetaTable metaTable) throws Exception { - this.metaTable = metaTable; - loadDataFromRS(rs); - } - - public RowData(CSVRecord record, MetaTable metaTable, CSVRecord titleColumns) throws Exception { - this.metaTable = metaTable; - loadDataFromCSVRecord(record, titleColumns); - } - - public void loadDataFromRS(ResultSet rs) throws Exception { - for (int i = 0; i < rs.getMetaData().getColumnCount(); i++) { - String columnName = rs.getMetaData().getColumnName(i+1); - - if (columnName.equalsIgnoreCase("DBGIT_ROW_NUM")) - continue; - - ICellData cd = FactoryCellData.createCellData(metaTable.getFieldsMap().get(columnName).getTypeUniversal()); - - if (cd.loadFromDB(rs, rs.getMetaData().getColumnName(i+1))) - data.put(columnName, cd); - } - - hashRow = calcRowHash(); - - key = calcRowKey(metaTable.getIdColumns()); - } - - public void loadDataFromCSVRecord(CSVRecord record, CSVRecord titleColumns) throws Exception { - - if (record.size() != titleColumns.size()) { - throw new ExceptionDBGit(DBGitLang.getInstance().getValue("errors", "dataTable", "differentCount")); - } - - for (int i = 0; i < record.size(); i++) { - String columnName = titleColumns.get(i); - if (metaTable.getFieldsMap().get(columnName) == null) { - throw new ExceptionDBGitRunTime(DBGitLang.getInstance().getValue("errors", "dataTable", "fieldNotFound").withParams(columnName)); - } - - ICellData cd = FactoryCellData.createCellData(metaTable.getFieldsMap().get(columnName).getTypeUniversal()); - cd.deserialize(record.get(i)); - - data.put(columnName, cd); - } - hashRow = calcRowHash(); - - key = calcRowKey(metaTable.getIdColumns()); - } - - public void saveDataToCsv(CSVPrinter csvPrinter, DBTable tbl) throws Exception { - for (ICellData cd : getData().values()) - csvPrinter.print(cd.serialize(tbl)); - - csvPrinter.println(); - } - - public String calcRowKey(List idColumns) throws Exception { - if (idColumns.size() > 0) { - StringBuilder keyBuilder = new StringBuilder(); - for (String nmId : idColumns) { - keyBuilder.append(data.get(nmId).convertToString()+"_"); - } - return keyBuilder.toString(); - } else { - return hashRow; - } - } - - public String calcRowHash() throws Exception { - CalcHash ch = new CalcHash(); - for (ICellData cd : data.values()) { - String str = cd.convertToString(); - if ( str != null) - ch.addData(str); - } - return ch.calcHashStr(); - } - - public Map getData() { - return data; - } - - public String getHashRow() { - return hashRow; - } - - public String getKey() { - return key; - } - - public MetaTable getMetaTable() { - return metaTable; - } - - -} +package ru.fusionsoft.dbgit.data_table; + +import java.sql.ResultSet; +import java.text.MessageFormat; +import java.util.*; + +import de.siegmar.fastcsv.reader.CsvRow; +import java.util.stream.Collectors; + +import org.apache.commons.csv.CSVPrinter; +import org.apache.commons.csv.CSVRecord; + +import ru.fusionsoft.dbgit.core.DBGitLang; +import ru.fusionsoft.dbgit.core.ExceptionDBGit; +import ru.fusionsoft.dbgit.core.ExceptionDBGitRunTime; +import ru.fusionsoft.dbgit.dbobjects.DBTable; +import ru.fusionsoft.dbgit.meta.MetaTable; +import ru.fusionsoft.dbgit.utils.CalcHash; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; + +public class RowData { + //protected Map data = new LinkedHashMap<>(); + private List rowList = new ArrayList<>(); + private String hashRow; + //protected String key; + //protected MetaTable metaTable; + + public RowData(ResultSet rs, MetaTable metaTable) throws Exception { + //this.metaTable = metaTable; + loadDataFromRS(rs, metaTable); + } + + public RowData(CsvRow record, MetaTable metaTable, CsvRow titleColumns) throws Exception { + //this.metaTable = metaTable; + loadDataFromCSVRecord(record, titleColumns, metaTable); + } + + @Deprecated + public RowData(CSVRecord record, MetaTable metaTable, CSVRecord titleColumns) throws Exception { + //this.metaTable = metaTable; + loadDataFromCSVRecord(record, titleColumns, metaTable); + } + + private void loadDataFromRS(ResultSet rs, MetaTable metaTable) throws Exception { + for (int i = 0; i < rs.getMetaData().getColumnCount(); i++) { + String columnName = rs.getMetaData().getColumnName(i+1); + + if (columnName.equalsIgnoreCase("DBGIT_ROW_NUM")) + continue; + + ICellData cd = FactoryCellData.createCellData(metaTable.getFieldsMap().get(columnName).getTypeUniversal()); + + if (cd.loadFromDB(rs, rs.getMetaData().getColumnName(i+1))) + rowList.add(cd); + //data.put(columnName, cd); + } + + hashRow = calcRowHash().substring(0, 24); + + //key = calcRowKey(metaTable.getIdColumns()); + } + + private void loadDataFromCSVRecord(CsvRow record, CsvRow titleColumns, MetaTable metaTable) throws Exception { + if (record.getFieldCount() != titleColumns.getFieldCount()) { + throw new ExceptionDBGit(DBGitLang.getInstance().getValue("errors", "dataTable", "differentCount")); + } + + for (int i = 0; i < record.getFieldCount(); i++) { + String columnName = titleColumns.getField(i); + if (metaTable.getFieldsMap().get(columnName) == null) { + throw new ExceptionDBGitRunTime(DBGitLang.getInstance().getValue("errors", "dataTable", "fieldNotFound").withParams(columnName)); + } + + ICellData cd = FactoryCellData.createCellData(metaTable.getFieldsMap().get(columnName).getTypeUniversal()); + cd.deserialize(record.getField(i).equals("") ? null : record.getField(i)); + + rowList.add(cd); + //data.put(columnName, cd); + } + hashRow = calcRowHash().substring(0, 24); + + //key = calcRowKey(metaTable.getIdColumns()); + + } + + @Deprecated + private void loadDataFromCSVRecord(CSVRecord record, CSVRecord titleColumns, MetaTable metaTable) throws Exception { + + if (record.size() != titleColumns.size()) { + throw new ExceptionDBGit(DBGitLang.getInstance().getValue("errors", "dataTable", "differentCount")); + } + + for (int i = 0; i < record.size(); i++) { + String columnName = titleColumns.get(i); + if (metaTable.getFieldsMap().get(columnName) == null) { + throw new ExceptionDBGitRunTime(DBGitLang.getInstance().getValue("errors", "dataTable", "fieldNotFound").withParams(columnName)); + } + + ICellData cd = FactoryCellData.createCellData(metaTable.getFieldsMap().get(columnName).getTypeUniversal()); + cd.deserialize(record.get(i)); + + rowList.add(cd); + //data.put(columnName, cd); + } + hashRow = calcRowHash().substring(0, 24); + + //key = calcRowKey(metaTable.getIdColumns()); + } + + public void saveDataToCsv(CSVPrinter csvPrinter, DBTable tbl) throws Exception { + //for (ICellData cd : getData().values()) + for (ICellData cd : rowList) + csvPrinter.print(cd.serialize(tbl)); + + csvPrinter.println(); + } + /* + public String calcRowKey(List idColumns) throws Exception { + if (idColumns.size() > 0) { + StringBuilder keyBuilder = new StringBuilder(); + for (String nmId : idColumns) { + keyBuilder.append(data.get(nmId).convertToString()+"_"); + } + return keyBuilder.toString(); + } else { + return hashRow; + } + } + */ + public String calcRowKey(List idColumns) throws Exception { + return hashRow; + /* + if (idColumns.size() > 0) { + StringBuilder keyBuilder = new StringBuilder(); + for (Integer nmId : idColumns) { + keyBuilder.append(rowList.get(nmId).convertToString()+"_"); + } + return keyBuilder.toString(); + } else { + return hashRow; + }*/ + } + + + public String calcRowHash() throws Exception { + CalcHash ch = new CalcHash(); + //for (ICellData cd : data.values()) { + for (ICellData cd : rowList) { + String str = cd.convertToString(); + if ( str != null) + ch.addData(str); + } + return ch.calcHashStr(); + } + + public Map getData(List fields) { + Map res = new LinkedHashMap<>(); + + int i = 0; + for (ICellData cd : rowList) { + res.put(fields.get(i), cd); + i++; + } + + return res; + } + + public Map getData() { + Map res = new HashMap<>(); + + int i = 0; + for (ICellData cd : rowList) { + res.put(String.valueOf(i), cd); + i++; + } + + return res; + } + + public List getListData() { + return rowList; + } + + public String getHashRow() { + return hashRow; + } + + public String getKey() { + //return key; + return hashRow; + } + + +} diff --git a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBCode.java b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBCode.java index beb735d..da9597e 100644 --- a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBCode.java +++ b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBCode.java @@ -1,6 +1,8 @@ package ru.fusionsoft.dbgit.dbobjects; -import ru.fusionsoft.dbgit.meta.DBGitMetaType; +import ru.fusionsoft.dbgit.utils.StringProperties; + +import java.util.Set; /** * Base class for all Objects BD with code style @@ -8,17 +10,10 @@ * */ public class DBCode extends DBSQLObject { - /* - private DBGitMetaType type; //pkg, fun, prc, trg - - public DBGitMetaType getType() { - return type; - } + public DBCode() { + } - public void setType(DBGitMetaType type) { - this.type = type; - } - - */ - + public DBCode(String name, StringProperties options, String schema, String owner, Set dependencies, String sql) { + super(name, options, schema, owner, dependencies, sql); + } } diff --git a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBConstraint.java b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBConstraint.java index 4eebd98..6ba5390 100644 --- a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBConstraint.java +++ b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBConstraint.java @@ -1,12 +1,24 @@ package ru.fusionsoft.dbgit.dbobjects; import ru.fusionsoft.dbgit.utils.CalcHash; +import ru.fusionsoft.dbgit.utils.StringProperties; +import ru.fusionsoft.dbgit.yaml.YamlOrder; import java.util.Objects; +import java.util.Set; public class DBConstraint extends DBSQLObject { + + @YamlOrder(4) private String constraintType; - + + public DBConstraint() { } + public DBConstraint(String name, StringProperties options, String schema, String owner, Set dependencies, String sql, String constraintType) { + super(name, options, schema, owner, dependencies, sql); + this.constraintType = constraintType; + } + + public String getConstraintType() { return constraintType; } @@ -14,26 +26,4 @@ public void setConstraintType(String constraintType) { this.constraintType = constraintType; } - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - DBConstraint that = (DBConstraint) o; - return Objects.equals(constraintType, that.constraintType) - && getName().equalsIgnoreCase(that.getName()) - && getSchema().equalsIgnoreCase(that.getSchema()) - && getSql().replaceAll("\\s+", "").equalsIgnoreCase(that.getSql().replaceAll("\\s+", "")); -// && getOptions().get("tablespace").getData().equalsIgnoreCase(that.getOptions().get("tablespace").getData()); - } - - public String getHash() { - CalcHash ch = new CalcHash(); - ch.addData(getSchema()); - ch.addData(getName()); - ch.addData(getSql().replaceAll("\\s+", "").toLowerCase()); - //TODO !!! - - return ch.calcHashStr(); - } - } diff --git a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBDomain.java b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBDomain.java new file mode 100644 index 0000000..92c437d --- /dev/null +++ b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBDomain.java @@ -0,0 +1,13 @@ +package ru.fusionsoft.dbgit.dbobjects; + +import java.util.Set; +import ru.fusionsoft.dbgit.utils.StringProperties; + +public class DBDomain extends DBSQLObject { + public DBDomain() { + } + + public DBDomain(String name, StringProperties options, String schema, String owner, Set dependencies, String sql) { + super(name, options, schema, owner, dependencies, sql); + } +} diff --git a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBEnum.java b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBEnum.java new file mode 100644 index 0000000..dae9f76 --- /dev/null +++ b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBEnum.java @@ -0,0 +1,13 @@ +package ru.fusionsoft.dbgit.dbobjects; + +import java.util.Set; +import ru.fusionsoft.dbgit.utils.StringProperties; + +public class DBEnum extends DBSQLObject { + public DBEnum() { + } + + public DBEnum(String name, StringProperties options, String schema, String owner, Set dependencies, String sql) { + super(name, options, schema, owner, dependencies, sql); + } +} diff --git a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBFunction.java b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBFunction.java index 0f11f51..c257530 100644 --- a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBFunction.java +++ b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBFunction.java @@ -1,15 +1,13 @@ package ru.fusionsoft.dbgit.dbobjects; + import ru.fusionsoft.dbgit.utils.StringProperties; +import java.util.Set; + public class DBFunction extends DBCode { - - public DBFunction() { - - } - public DBFunction(String name) { - super(); - this.name = name; + public DBFunction() { } + public DBFunction(String name, StringProperties options, String schema, String owner, Set dependencies, String sql) { + super(name, options, schema, owner, dependencies, sql); } - } diff --git a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBIndex.java b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBIndex.java index 32ada71..96941ad 100644 --- a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBIndex.java +++ b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBIndex.java @@ -3,36 +3,14 @@ import ru.fusionsoft.dbgit.utils.CalcHash; import ru.fusionsoft.dbgit.utils.StringProperties; -public class DBIndex extends DBSQLObject { - //private DBTable table; - private StringProperties options = new StringProperties(); - public DBIndex() { - super(); - } - public DBIndex(String name) { - super(); - this.name = name; - } - +import java.util.Set; - public StringProperties getOptions() { - return options; - } +public class DBIndex extends DBSQLObject { - public void setOptions(StringProperties options) { - this.options = options; - } + public DBIndex() { - public String getSql() { - return options.get("ddl") != null ? options.get("ddl").toString() : ""; } - - public String getHash() { - CalcHash ch = new CalcHash(); - ch.addData(getSchema()); - ch.addData(getName()); - ch.addData(getSql().replaceAll("\\s+", "").toLowerCase()); - return ch.calcHashStr(); + public DBIndex(String name, StringProperties options, String schema, String owner, Set dependencies, String sql) { + super(name, options, schema, owner, dependencies, sql); } - } diff --git a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBOptionsObject.java b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBOptionsObject.java index eb6d57a..ab9106b 100644 --- a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBOptionsObject.java +++ b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBOptionsObject.java @@ -2,43 +2,64 @@ import ru.fusionsoft.dbgit.utils.CalcHash; import ru.fusionsoft.dbgit.utils.StringProperties; +import ru.fusionsoft.dbgit.yaml.YamlOrder; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; public class DBOptionsObject implements IDBObject { - private String name; - private StringProperties options = new StringProperties(); - - public DBOptionsObject() {} + + @YamlOrder(0) + String name; + + @YamlOrder(99) + StringProperties options; public DBOptionsObject(String name) { - this.setName(name); + this.name = name; + this.options = new StringProperties(); } - public DBOptionsObject(String name, StringProperties options) { - this.setName(name); - this.setOptions(options); + this.name = name; + this.options = options; + } + + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof DBOptionsObject)) return false; + + DBOptionsObject that = (DBOptionsObject) o; + return this.getHash().equals(that.getHash()); + } + + @Override + public int hashCode() { + return Objects.hash(getHash()); } - + + public String getHash() { + CalcHash ch = new CalcHash(); + ch.addData(this.name); + ch.addData(this.options.toString()); + + return ch.calcHashStr(); + } + public StringProperties getOptions() { return options; } - public void setOptions(StringProperties opt) { options = opt; } - public String getName() { return name; } - public void setName(String name) { this.name = name; } - public String getHash() { - CalcHash ch = new CalcHash(); - ch.addData(this.getName()); - ch.addData(this.getOptions().toString()); - return ch.calcHashStr(); - } } diff --git a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBPackage.java b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBPackage.java index 0a657c5..d5b5ee3 100644 --- a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBPackage.java +++ b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBPackage.java @@ -1,12 +1,13 @@ package ru.fusionsoft.dbgit.dbobjects; +import ru.fusionsoft.dbgit.utils.StringProperties; + +import java.util.Set; + public class DBPackage extends DBCode { - public DBPackage() { } - - public DBPackage(String name) { - super(); - this.name = name; - } - + public DBPackage() { } + public DBPackage(String name, StringProperties options, String schema, String owner, Set dependencies, String sql) { + super(name, options, schema, owner, dependencies, sql); + } } diff --git a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBProcedure.java b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBProcedure.java index 9865343..d4b9767 100644 --- a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBProcedure.java +++ b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBProcedure.java @@ -1,11 +1,13 @@ package ru.fusionsoft.dbgit.dbobjects; +import ru.fusionsoft.dbgit.utils.StringProperties; + +import java.util.Set; + public class DBProcedure extends DBCode { public DBProcedure() { } - - public DBProcedure(String name) { - super(); - this.name = name; + public DBProcedure(String name, StringProperties options, String schema, String owner, Set dependencies, String sql) { + super(name, options, schema, owner, dependencies, sql); } } diff --git a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBRole.java b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBRole.java index c31eff4..196d46d 100644 --- a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBRole.java +++ b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBRole.java @@ -1,10 +1,10 @@ package ru.fusionsoft.dbgit.dbobjects; +import ru.fusionsoft.dbgit.utils.StringProperties; + public class DBRole extends DBOptionsObject { - public DBRole() {} - public DBRole(String name) { - super(name); + public DBRole(String name, StringProperties options) { + super(name, options); } - } diff --git a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBSQLObject.java b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBSQLObject.java index 6305c8f..48e4309 100644 --- a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBSQLObject.java +++ b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBSQLObject.java @@ -1,10 +1,9 @@ package ru.fusionsoft.dbgit.dbobjects; +import java.util.Collections; import ru.fusionsoft.dbgit.utils.CalcHash; -import ru.fusionsoft.dbgit.utils.ConsoleWriter; import ru.fusionsoft.dbgit.utils.StringProperties; -import java.util.HashSet; import java.util.Set; /** @@ -15,38 +14,33 @@ public class DBSQLObject extends DBSchemaObject { protected String sql; - protected String owner; - private StringProperties options = new StringProperties(); + + public DBSQLObject() { + super("", new StringProperties(), "", "", Collections.emptySet()); + } + + public DBSQLObject(String name, StringProperties options, String schema, String owner, Set dependencies, String sql) { + super(name, options, schema, owner, dependencies); + this.sql = sql; + } public String getHash() { CalcHash ch = new CalcHash(); - ch.addData(getSchema()); - ch.addData(getName()); - ch.addData(getSql().trim().replaceAll("\\s+", "")); - if (getOwner() != null) - ch.addData(getOwner()); + + ch.addData(this.name); + ch.addData(this.schema); + ch.addData(this.owner); + ch.addData(this.options.toString()); + ch.addData(this.sql); return ch.calcHashStr(); } public String getSql() { - return options.get("ddl") != null ? options.get("ddl").toString() : ""; - } - public void setSql(String ddl) { if(options.get("ddl") != null) options.get("ddl").setData(ddl); } - - public String getOwner() { - return owner; - } - - public void setOwner(String owner) { - this.owner=owner; + return this.sql; } - public StringProperties getOptions() { - return options; - } - - public void setOptions(StringProperties options) { - this.options = options; + public void setSql(String ddl) { + this.sql = ddl; } } diff --git a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBSchema.java b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBSchema.java index d8b444f..18ace79 100644 --- a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBSchema.java +++ b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBSchema.java @@ -1,11 +1,13 @@ package ru.fusionsoft.dbgit.dbobjects; +import ru.fusionsoft.dbgit.utils.StringProperties; + public class DBSchema extends DBOptionsObject { - public DBSchema() { - super(""); + public DBSchema(String name, StringProperties options) { + super(name, options); } - + public DBSchema(String name) { super(name); } diff --git a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBSchemaObject.java b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBSchemaObject.java index c01c5a8..16caad4 100644 --- a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBSchemaObject.java +++ b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBSchemaObject.java @@ -1,6 +1,10 @@ package ru.fusionsoft.dbgit.dbobjects; +import java.util.Collections; +import ru.fusionsoft.dbgit.utils.StringProperties; +import ru.fusionsoft.dbgit.yaml.YamlOrder; + import java.util.HashSet; import java.util.Set; @@ -9,17 +13,25 @@ * @author mikle * */ -public abstract class DBSchemaObject implements IDBObject { - protected String name; +public abstract class DBSchemaObject extends DBOptionsObject { + + @YamlOrder(1) protected String schema; - private Set dependencies = new HashSet<>(); - - public String getName() { - return name; - } - public void setName(String name) { - this.name = name; + + @YamlOrder(2) + protected String owner; + + @YamlOrder(3) + private Set dependencies; + + + public DBSchemaObject(String name, StringProperties options, String schema, String owner, Set dependencies) { + super(name, options); + this.schema = schema; + this.owner = owner == null ? "" : owner; + this.dependencies = dependencies == null ? Collections.emptySet() : dependencies; } + public String getSchema() { return schema; } @@ -33,5 +45,12 @@ public Set getDependencies() { public void setDependencies(Set dependencies) { this.dependencies = dependencies; } + + public String getOwner() { + return owner; + } + public void setOwner(String owner) { + this.owner=owner; + } } diff --git a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBSequence.java b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBSequence.java index 93aa73a..1fee320 100644 --- a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBSequence.java +++ b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBSequence.java @@ -1,41 +1,48 @@ package ru.fusionsoft.dbgit.dbobjects; +import java.util.Collections; import ru.fusionsoft.dbgit.utils.CalcHash; import ru.fusionsoft.dbgit.utils.StringProperties; +import java.util.Set; + public class DBSequence extends DBSchemaObject { protected Long value; - private StringProperties options = new StringProperties(); - - public DBSequence() { } - - public DBSequence(String name) { this.name = name; } - public Long getValue() { - return value; + public DBSequence(){ + super("", new StringProperties(), "", "", Collections.emptySet()); } - - public void setValue(Long value) { + public DBSequence(String name, StringProperties options, String schema, String owner, Set dependencies, Long value) { + super(name, options, schema, owner, dependencies); this.value = value; } - - public StringProperties getOptions() { - return options; - } - - public void setOptions(StringProperties options) { - this.options = options; + + public StringProperties persistentOptions() { + //Immutable, yeah + StringProperties props = new StringProperties(getOptions().getData()); + props.setChildren(getOptions().getChildren()); + props.deleteChild("blocking_table"); + return props; } - + @Override public String getHash() { - + CalcHash ch = new CalcHash(); - ch.addData(getSchema()); - ch.addData(getName()); - ch.addData(getOptions().toString()); - ch.addData(getValue().toString()); + ch.addData(this.schema); + ch.addData(this.name); + ch.addData(this.owner); + ch.addData(persistentOptions().toString()); + ch.addData(String.valueOf(this.value)); return ch.calcHashStr(); } + + public Long getValue() { + return value; + } + + public void setValue(Long value) { + this.value = value; + } } diff --git a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBTable.java b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBTable.java index 36beb5a..78e7778 100644 --- a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBTable.java +++ b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBTable.java @@ -1,45 +1,101 @@ package ru.fusionsoft.dbgit.dbobjects; +import ru.fusionsoft.dbgit.core.NotImplementedExceptionDBGitRuntime; import ru.fusionsoft.dbgit.utils.CalcHash; -import ru.fusionsoft.dbgit.utils.ConsoleWriter; import ru.fusionsoft.dbgit.utils.StringProperties; +import ru.fusionsoft.dbgit.yaml.YamlOrder; + +import java.util.Collections; +import java.util.Set; public class DBTable extends DBSchemaObject { - private StringProperties options = new StringProperties(); - private String comment = ""; - public DBTable() { - super(); - } + @YamlOrder(4) + private String comment; - public DBTable(String name) { - super(); - this.name = name; + public DBTable() { + super("", new StringProperties(), "", "", Collections.emptySet()); } - public StringProperties getOptions() { - return options; + public DBTable(String name, StringProperties options, String schema, String owner, Set dependencies, String comment) { + super(name, options, schema, owner, dependencies); + this.comment = comment == null ? "" : comment; } - public void setOptions(StringProperties options) { - this.options = options; - } - public String getHash() { - CalcHash ch = new CalcHash(); - ch.addData(this.getName()); - ch.addData(this.getOptions().toString().replaceAll("\\s+", "")); - + CalcHash ch = new CalcHash()/*{ + public CalcHash addData(String str){ + ConsoleWriter.detailsPrintlnRed(str); + return super.addData(str); + } + }*/; + ch.addData(this.name); + ch.addData(this.schema); + ch.addData(this.owner); + ch.addData(this.options.toString()); + ch.addData(this.comment); return ch.calcHashStr(); } public void setComment(String comment) { - this.comment = comment; + this.comment = comment == null ? "" : comment; } public String getComment() { return this.comment; } + public static class OnlyNameDBTable extends DBTable{ + + public OnlyNameDBTable(String name, String schema) { + super(name, new StringProperties(), schema, "", Collections.emptySet(), ""); + } + + @Override + public String getHash() { + throw new NotImplementedExceptionDBGitRuntime(); + } + + @Override + public void setComment(String comment) { + throw new NotImplementedExceptionDBGitRuntime(); + } + + @Override + public String getComment() { + throw new NotImplementedExceptionDBGitRuntime(); + } + + @Override + public Set getDependencies() { + throw new NotImplementedExceptionDBGitRuntime(); + } + + @Override + public void setDependencies(Set dependencies) { + throw new NotImplementedExceptionDBGitRuntime(); + } + + @Override + public String getOwner() { + throw new NotImplementedExceptionDBGitRuntime(); + } + + @Override + public void setOwner(String owner) { + throw new NotImplementedExceptionDBGitRuntime(); + } + + @Override + public StringProperties getOptions() { + throw new NotImplementedExceptionDBGitRuntime(); + } + + @Override + public void setOptions(StringProperties opt) { + throw new NotImplementedExceptionDBGitRuntime(); + } + } + } diff --git a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBTableData.java b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBTableData.java index 6d4fedd..affce1d 100644 --- a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBTableData.java +++ b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBTableData.java @@ -1,30 +1,58 @@ package ru.fusionsoft.dbgit.dbobjects; +import ru.fusionsoft.dbgit.core.ExceptionDBGitRunTime; +import ru.fusionsoft.dbgit.core.ExceptionDBGitTableData; + +import java.io.Closeable; +import java.sql.Connection; import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; -public class DBTableData { +public class DBTableData implements AutoCloseable, Closeable { public static final int ERROR_LIMIT_ROWS = 1; - protected int errorFlag = 0; - protected ResultSet resultSet; - - public int getErrorFlag() { - return errorFlag; - } + final protected int errorFlag ; + final protected ResultSet resultSet; + final protected Statement statement; - public void setErrorFlag(int errorFlag) { + public DBTableData(Connection connection, String query) throws SQLException { + this.errorFlag = 0; + this.statement = connection.createStatement(); + this.resultSet = statement.executeQuery(query); + } + public DBTableData(int errorFlag) { this.errorFlag = errorFlag; + this.resultSet = null; + this.statement = null; } - + public int errorFlag() { + return errorFlag; + } + public ResultSet resultSet() throws ExceptionDBGitTableData { - public ResultSet getResultSet() { return resultSet; +// TODO find usages and adapt to recover from the ExceptionDBGitTableData +// if(resultSet != null){ +// return resultSet; +// } else { +// final String msg = DBGitLang.getInstance() +// .getValue("errors", "dataTable", "errorTableData") +// .withParams(String.valueOf(errorFlag)); +// +// throw new ExceptionDBGitTableData(msg, errorFlag); +// } } - public void setResultSet(ResultSet resultSet) { - this.resultSet = resultSet; + + @Override + public void close() { + try{ + this.resultSet.close(); + this.statement.close(); + } catch (SQLException ex){ + throw new ExceptionDBGitRunTime(ex); + } } - - -} +} \ No newline at end of file diff --git a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBTableField.java b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBTableField.java index c0c4e71..7343a20 100644 --- a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBTableField.java +++ b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBTableField.java @@ -2,82 +2,127 @@ import ru.fusionsoft.dbgit.core.db.FieldType; import ru.fusionsoft.dbgit.utils.CalcHash; -import ru.fusionsoft.dbgit.utils.ConsoleWriter; +import ru.fusionsoft.dbgit.yaml.YamlOrder; + +import java.nio.channels.IllegalSelectorException; +import java.util.Objects; public class DBTableField implements IDBObject, Comparable { - private String name; - private String description; - private String typeSQL; - private FieldType typeUniversal; - private int length; - private int scale; - private int precision; - private boolean fixed; - private Integer order = 0; - private Boolean isNullable; - private Boolean isNameExactly = false; - private String defaultValue; - + + @YamlOrder(0) + private String name = ""; + @YamlOrder(1) + private String description = ""; + @YamlOrder(2) private Boolean isPrimaryKey = false; + @YamlOrder(3) + private Boolean isNullable = false; + @YamlOrder(4) + private String typeSQL = ""; + @YamlOrder(5) + private FieldType typeUniversal = FieldType.UNDEFINED; + @YamlOrder(6) + private Integer order = -1; + @YamlOrder(7) + private String defaultValue = ""; + @YamlOrder(8) + private int length = 0; + @YamlOrder(9) + private int scale = 0; + @YamlOrder(10) + private int precision = 0; + @YamlOrder(11) + private boolean fixed = false; + + public DBTableField() { + //Just for things that want to introspect my guts and use setters + this.order = -1; + this.defaultValue = ""; + this.description = ""; + this.fixed = false; + this.isNullable = false; + this.isPrimaryKey = false; + this.length = 0; + this.name = ""; + this.precision = 0; + this.scale = 0; + this.typeSQL = ""; + this.typeUniversal = FieldType.UNDEFINED; + } + + public DBTableField(String name, String description, Boolean isPrimaryKey, Boolean isNullable, String typeSQL, FieldType typeUniversal, Integer order, String defaultValue, int length, int scale, int precision, boolean fixed) { + this.name = name; + this.description = description == null ? "" : description; + this.isPrimaryKey = isPrimaryKey; + this.isNullable = isNullable; + this.typeSQL = typeSQL; + this.typeUniversal = typeUniversal; + this.order = order; + this.defaultValue = defaultValue == null ? "" : defaultValue; + this.length = length; + this.scale = scale; + this.precision = precision; + this.fixed = fixed; + } - public Boolean getIsPrimaryKey() { - return isPrimaryKey; + @Override + public int compareTo(DBTableField o) { + int res = - isPrimaryKey.compareTo(o.getIsPrimaryKey()); + if (res != 0) return res; + return order.compareTo(o.getOrder()); +// return name.compareTo(o.getName()); } - public void setIsPrimaryKey(Boolean isPrimaryKey) { - this.isPrimaryKey = isPrimaryKey; + @Override public boolean equals(Object obj){ + boolean equals = obj == this; + if(!equals && obj instanceof DBTableField){ + return ((DBTableField) obj).getHash().equals(this.getHash()); + } + return equals; + } + + @Override + public int hashCode() { + return Objects.hash(getHash()); } public String getHash() { CalcHash ch = new CalcHash(); - ch.addData(this.getName()); - ch.addData(this.getTypeSQL()); - - ch.addData(isPrimaryKey.toString()); + + ch.addData(this.name); + ch.addData(this.typeSQL); + ch.addData(this.order); + ch.addData(this.isPrimaryKey); + ch.addData(this.isNullable); + ch.addData(this.description); + ch.addData(this.defaultValue); + ch.addData(this.fixed); + ch.addData(this.length); + ch.addData(this.precision); + ch.addData(this.scale); return ch.calcHashStr(); } - public Boolean getIsNullable() { return isNullable; } - - public void setIsNullable(Boolean isNullable) { this.isNullable = isNullable; } - public void setTypeUniversal(FieldType typeUniversal) { - this.typeUniversal = typeUniversal; + public Boolean getIsPrimaryKey() { + return isPrimaryKey; } - + + public Boolean getIsNullable() { return isNullable; } + public FieldType getTypeUniversal() { return typeUniversal; } - - public void setLength(int length) { - this.length = length; - } - - public int getLength() { - return length; - } - public void setScale(int scale) { - this.scale = scale; - } - - public int getScale() { - return scale; + public int getLength() { + return length; } - public void setPrecision(int precision) { - this.precision = precision; - } - public int getPrecision() { return precision; } - public void setFixed(boolean fixed) { - this.fixed = fixed; - } - public boolean getFixed() { return fixed; } @@ -86,56 +131,73 @@ public String getName() { return name; } - public void setName(String name) { - this.name = name; - } - public String getTypeSQL() { return typeSQL; } - public void setTypeSQL(String typeSQL) { - this.typeSQL = typeSQL; - } - - public void setOrder(Integer order) { - this.order = order; - } - public Integer getOrder() { return order; } - - public void setNameExactly(Boolean isNameExactly) { - this.isNameExactly = isNameExactly; - } - - public Boolean getNameExactly() { - return isNameExactly; - } - + public String getDefaultValue() { return this.defaultValue; } - public void setDefaultValue(String defaultValue) { - this.defaultValue = defaultValue; + public int getScale() { + return scale; } public String getDescription() { return this.description; } - public void setDescription(String description) { - this.description = description; + public void setIsPrimaryKey(Boolean isPrimaryKey) { + this.isPrimaryKey = isPrimaryKey; } - - @Override - public int compareTo(DBTableField o) { - int res = - isPrimaryKey.compareTo(o.getIsPrimaryKey()); - if (res != 0) return res; - return name.compareTo(o.getName()); + + public void setTypeUniversal(FieldType typeUniversal) { + this.typeUniversal = typeUniversal == null ? FieldType.UNDEFINED : typeUniversal; + } + + public void setIsNullable(Boolean isNullable) { this.isNullable = isNullable; } + + public void setLength(int length) { + this.length = length; } + + public void setScale(int scale) { + this.scale = scale; + } + + public void setPrecision(int precision) { + this.precision = precision; + } + + public void setFixed(boolean fixed) { + this.fixed = fixed; + } + + public void setName(String name) { + this.name = name; + } + + public void setOrder(Integer order) { + this.order = order; + } + + public void setTypeSQL(String typeSQL) { + this.typeSQL = typeSQL; + } + + public void setDefaultValue(String defaultValue) { + this.defaultValue = defaultValue == null ? "" : defaultValue; + } + + public void setDescription(String description) { + this.description = description == null ? "" : description; + } + + } diff --git a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBTableSpace.java b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBTableSpace.java index 7213cd9..b4c6b38 100644 --- a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBTableSpace.java +++ b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBTableSpace.java @@ -1,12 +1,10 @@ package ru.fusionsoft.dbgit.dbobjects; +import ru.fusionsoft.dbgit.utils.StringProperties; + public class DBTableSpace extends DBOptionsObject { - - public DBTableSpace() { - super(""); - } - - public DBTableSpace(String name) { - super(name); + + public DBTableSpace(String name, StringProperties options) { + super(name, options); } } diff --git a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBTrigger.java b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBTrigger.java index 7c9aa09..d38c4f1 100644 --- a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBTrigger.java +++ b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBTrigger.java @@ -2,11 +2,12 @@ import ru.fusionsoft.dbgit.utils.StringProperties; +import java.util.Set; + public class DBTrigger extends DBCode { - public DBTrigger() { - - } - public DBTrigger(String name) { - this.name = name; + + public DBTrigger() { } + public DBTrigger(String name, StringProperties options, String schema, String owner, Set dependencies, String sql) { + super(name, options, schema, owner, dependencies, sql); } } diff --git a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBUser.java b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBUser.java index e27d3ed..90820ed 100644 --- a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBUser.java +++ b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBUser.java @@ -3,11 +3,7 @@ import ru.fusionsoft.dbgit.utils.StringProperties; public class DBUser extends DBOptionsObject { - public DBUser() {} - - public DBUser(String name) { - super(name); + public DBUser(String name, StringProperties options) { + super(name, options); } - - public DBUser(String name, StringProperties options) { super(name, options); } } diff --git a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBUserDefinedType.java b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBUserDefinedType.java new file mode 100644 index 0000000..cf064a9 --- /dev/null +++ b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBUserDefinedType.java @@ -0,0 +1,13 @@ +package ru.fusionsoft.dbgit.dbobjects; + +import java.util.Set; +import ru.fusionsoft.dbgit.utils.StringProperties; + +public class DBUserDefinedType extends DBSQLObject { + public DBUserDefinedType() { + } + + public DBUserDefinedType(String name, StringProperties options, String schema, String owner, Set dependencies, String sql) { + super(name, options, schema, owner, dependencies, sql); + } +} diff --git a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBView.java b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBView.java index e0ede68..a543ec4 100644 --- a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBView.java +++ b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBView.java @@ -1,13 +1,13 @@ package ru.fusionsoft.dbgit.dbobjects; +import ru.fusionsoft.dbgit.utils.StringProperties; + +import java.util.Set; + public class DBView extends DBSQLObject { - public DBView(String name) { - super(); - this.name = name; + public DBView() { } + public DBView(String name, StringProperties options, String schema, String owner, Set dependencies, String sql) { + super(name, options, schema, owner, dependencies, sql); } - public DBView() { - super(); - } - } diff --git a/src/main/java/ru/fusionsoft/dbgit/meta/DBGitMetaType.java b/src/main/java/ru/fusionsoft/dbgit/meta/DBGitMetaType.java index 73b678c..78452b6 100644 --- a/src/main/java/ru/fusionsoft/dbgit/meta/DBGitMetaType.java +++ b/src/main/java/ru/fusionsoft/dbgit/meta/DBGitMetaType.java @@ -46,6 +46,36 @@ public Integer getPriority() { } }, + DBGitUserDefinedType("udt"){ + public Class getMetaClass() { + return MetaUDT.class; + } + + public Integer getPriority() { + return 11; + } + }, + + DBGitEnum("enum"){ + public Class getMetaClass() { + return MetaEnum.class; + } + + public Integer getPriority() { + return 12; + } + }, + + DBGitDomain("domain"){ + public Class getMetaClass() { + return MetaDomain.class; + } + + public Integer getPriority() { + return 13; + } + }, + DBGitSequence("seq"){ public Class getMetaClass() { return MetaSequence.class; @@ -134,8 +164,7 @@ public Class getMetaClass() { public Integer getPriority() { return 210; } - } - ; + }; private static Map listAllTypes; static { diff --git a/src/main/java/ru/fusionsoft/dbgit/meta/IMetaObject.java b/src/main/java/ru/fusionsoft/dbgit/meta/IMetaObject.java index 025d763..7e5468b 100644 --- a/src/main/java/ru/fusionsoft/dbgit/meta/IMetaObject.java +++ b/src/main/java/ru/fusionsoft/dbgit/meta/IMetaObject.java @@ -7,6 +7,8 @@ import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Constructor; +import java.util.Map; + import ru.fusionsoft.dbgit.core.DBGitLang; import ru.fusionsoft.dbgit.core.DBGitPath; @@ -16,61 +18,65 @@ /** *
- * A class that implements the meta description of an object. - * These objects store information about the objects of the database. + * A class that implements the meta description of an object. + * These objects store information about the objects of the database. * Saved on the disk under the control of git. -  * Used by adapters to restore the state of the database. + * Used by adapters to restore the state of the database. *
- * + * *
- * Класс реализующий мета описание объекта. - * Данные объекты хранят в себе информацию об объектах БД. + * Класс реализующий мета описание объекта. + * Данные объекты хранят в себе информацию об объектах БД. * Сохраняются на диске под управлением гит. * Используются адаптерами для восстановления состояния БД. *
- * + * * @author mikle * */ public interface IMetaObject { - public static final String EMPTY_HASH = ""; + public static final String EMPTY_HASH = ""; public static final int MAX_FILE_NAME_LENGTH = 130; + public static int messageLevel = 1; + /** - * + * * @return Type meta object */ public IDBGitMetaType getType(); - + /** - * Full name meta object with path and extension type - * Example myschema/mytable.tbl + * Full name meta object with path and extension type + * Example myschema/mytable.tbl * @return */ public String getName(); public void setName(String name) throws ExceptionDBGit; - + public DbType getDbType(); - + public void setDbType(DbType dbType); - + public String getDbVersion(); - public void setDbVersion(String dbVersion); + public Double getDbVersionNumber(); + public void setDbVersion(String dbVersion); + public String getFileName(); - + public void setDbType(); - + public void setDbVersion(); - + /** * Save data to stream * @param stream * @throws IOException */ public boolean serialize(OutputStream stream) throws Exception; - + /** * Load object from stream * @param stream @@ -79,6 +85,12 @@ public interface IMetaObject { */ public IMetaObject deSerialize(InputStream stream) throws Exception; + public default IMetaObject deSerialize(File file) throws Exception { + return this; + }; + + public Map toMap(); + /** * load current object from DB */ @@ -104,7 +116,6 @@ default boolean saveToFile(String basePath) throws ExceptionDBGit { return res; } catch (Exception e) { - e.printStackTrace(); throw new ExceptionDBGit(e); } } @@ -124,31 +135,41 @@ default IMetaObject loadFromFile(String basePath) throws Exception { String filename = DBGitPath.getFullPath(basePath); File file = new File(filename+"/"+getFileName()); FileInputStream fis = new FileInputStream(file); - IMetaObject meta = this.deSerialize(fis); + IMetaObject meta; + if (!file.getPath().endsWith(".csv")) + meta = this.deSerialize(fis); + else + meta = this.deSerialize(file); fis.close(); if (meta != null && meta.getName().isEmpty()) { meta.setName(this.getName()); } - + return meta; } - + default IMetaObject loadFromFile() throws Exception { return loadFromFile(null); } - + public int addToGit() throws ExceptionDBGit; - + public int removeFromGit() throws ExceptionDBGit; default DBSchemaObject getUnderlyingDbObject(){ //All in one place if(this instanceof MetaSql) return ((MetaSql) this).getSqlObject(); + if(this instanceof MetaSequence) return ((MetaSequence) this).getSequence(); if(this instanceof MetaTable) return ((MetaTable) this).getTable(); return null; } + default boolean dependsOn(IMetaObject obj){ + if (this.getUnderlyingDbObject() == null || this.getUnderlyingDbObject().getDependencies() == null) return false; + return this.getUnderlyingDbObject().getDependencies().contains(obj.getName()); + } + static IMetaObject create(String name) throws ExceptionDBGit { NameMeta nm = new NameMeta(name); if (nm.getType() == null) throw new ExceptionDBGit(DBGitLang.getInstance().getValue("errors", "meta", "parseError").withParams(name)); diff --git a/src/main/java/ru/fusionsoft/dbgit/meta/MetaBase.java b/src/main/java/ru/fusionsoft/dbgit/meta/MetaBase.java index 03d33e3..30d10cb 100644 --- a/src/main/java/ru/fusionsoft/dbgit/meta/MetaBase.java +++ b/src/main/java/ru/fusionsoft/dbgit/meta/MetaBase.java @@ -1,137 +1,164 @@ -package ru.fusionsoft.dbgit.meta; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.charset.Charset; - -import org.yaml.snakeyaml.DumperOptions; -import org.yaml.snakeyaml.Yaml; -import org.yaml.snakeyaml.DumperOptions.ScalarStyle; -import org.yaml.snakeyaml.nodes.Tag; - -import ru.fusionsoft.dbgit.adapters.AdapterFactory; -import ru.fusionsoft.dbgit.core.DBGit; -import ru.fusionsoft.dbgit.core.DBGitPath; -import ru.fusionsoft.dbgit.core.ExceptionDBGit; -import ru.fusionsoft.dbgit.core.ExceptionDBGitRunTime; -import ru.fusionsoft.dbgit.core.db.DbType; -import ru.fusionsoft.dbgit.utils.ConsoleWriter; -import ru.fusionsoft.dbgit.yaml.DBGitYamlConstructor; -import ru.fusionsoft.dbgit.yaml.DBGitYamlRepresenter; -import ru.fusionsoft.dbgit.yaml.YamlOrder; - - -/** - * Base class for all meta objects - * @author mikle - * - */ -public abstract class MetaBase implements IMetaObject { - @YamlOrder(0) - protected String name; - - @YamlOrder(1) - protected DbType dbType; - - @YamlOrder(1) - protected String dbVersion; - - @Override - public String getName() { - return name; - } - - @Override - public void setDbType(DbType dbType) { - this.dbType = dbType; - } - - @Override - public DbType getDbType() { - return dbType; - } - - @Override - public void setDbVersion(String dbVersion) { - this.dbVersion = dbVersion; - } - - @Override - public String getDbVersion() { - return dbVersion; - } - - @Override - public void setName(String name) throws ExceptionDBGit { - this.name = name; - } - - @Override - public String getFileName() { - return getName(); - } - - /** - *
When you save the yaml object, the library ignores properties for which there is no getter and setter
- *
При сохранении объекта yaml библиотека игнорирует свойства для которых нет геттера и сеттера
- * @param stream - * @throws IOException - */ - public boolean yamlSerialize(OutputStream stream) throws IOException { - Yaml yaml = createYaml(); - String output = yaml.dumpAs(this, Tag.MAP, DumperOptions.FlowStyle.BLOCK); - - stream.write(output.getBytes(Charset.forName("UTF-8"))); - return true; - } - - public IMetaObject yamlDeSerialize(InputStream stream) { - Yaml yaml = createYaml(); - - IMetaObject meta = yaml.loadAs(stream, this.getClass()); - return meta; - } - - public Yaml createYaml() { - DumperOptions options = new DumperOptions(); - options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); - options.setPrettyFlow(true); - Yaml yaml = new Yaml(new DBGitYamlConstructor(), new DBGitYamlRepresenter(), options); - return yaml; - } - - @Override - public int addToGit() throws ExceptionDBGit { - DBGit dbGit = DBGit.getInstance(); - dbGit.addFileToIndexGit(DBGitPath.DB_GIT_PATH+"/"+getFileName()); - return 1; - } - - @Override - public int removeFromGit() throws ExceptionDBGit { - DBGit dbGit = DBGit.getInstance(); - dbGit.removeFileFromIndexGit(DBGitPath.DB_GIT_PATH+"/"+getFileName()); - return 1; - } - - public void setDbType() { - try { - setDbType(AdapterFactory.createAdapter().getDbType()); - } catch (ExceptionDBGit e) { - throw new ExceptionDBGitRunTime(e.getLocalizedMessage()); - } - - } - - public void setDbVersion() { - try { - setDbVersion(AdapterFactory.createAdapter().getDbVersion()); - } catch (ExceptionDBGit e) { - throw new ExceptionDBGitRunTime(e.getLocalizedMessage()); - } - - } - - -} +package ru.fusionsoft.dbgit.meta; + +import java.io.*; +import java.nio.charset.Charset; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.nodes.Tag; + +import ru.fusionsoft.dbgit.adapters.AdapterFactory; +import ru.fusionsoft.dbgit.core.DBGit; +import ru.fusionsoft.dbgit.core.DBGitPath; +import ru.fusionsoft.dbgit.core.ExceptionDBGit; +import ru.fusionsoft.dbgit.core.ExceptionDBGitRunTime; +import ru.fusionsoft.dbgit.core.db.DbType; +import ru.fusionsoft.dbgit.utils.StringProperties; +import ru.fusionsoft.dbgit.yaml.DBGitYamlConstructor; +import ru.fusionsoft.dbgit.yaml.DBGitYamlRepresenter; +import ru.fusionsoft.dbgit.yaml.YamlOrder; + + +/** + * Base class for all meta objects + * @author mikle + * + */ +public abstract class MetaBase implements IMetaObject { + @YamlOrder(0) + protected String name; + + @YamlOrder(1) + protected DbType dbType; + + @YamlOrder(2) + protected String dbVersion; + + @Override + public String getName() { + return name; + } + + @Override + public void setDbType(DbType dbType) { + this.dbType = dbType; + } + + @Override + public DbType getDbType() { + return dbType; + } + + @Override + public void setDbVersion(String dbVersion) { + this.dbVersion = dbVersion; + } + + @Override + public String getDbVersion() { + return dbVersion; + } + + @Override + public Double getDbVersionNumber() { + Matcher matcher = Pattern.compile("\\D*(\\d+)\\.(\\d+)").matcher(getDbVersion()); + matcher.find(); + Double result = Double.valueOf(matcher.group(0)+matcher.group(1)); + return result; + } + + @Override + public void setName(String name) throws ExceptionDBGit { + this.name = name; + } + + @Override + public String getFileName() { + return getName(); + } + + /** + *
When you save the yaml object, the library ignores properties for which there is no getter and setter
+ *
При сохранении объекта yaml библиотека игнорирует свойства для которых нет геттера и сеттера
+ * @param stream + * @throws IOException + */ + public boolean yamlSerialize(OutputStream stream) throws IOException { + Yaml yaml = createYaml(); + String output = yaml.dumpAs(this, Tag.MAP, DumperOptions.FlowStyle.BLOCK); + + stream.write(output.getBytes(Charset.forName("UTF-8"))); + return true; + } + + public IMetaObject yamlDeSerialize(InputStream stream) { + Yaml yaml = createYaml(); + //Map some = yaml.loadAs(stream, Map.class); + IMetaObject meta = yaml.loadAs(stream, this.getClass()); + return meta; + } + + public Map toMap() { + Yaml yaml = createYaml(); + String output = yaml.dumpAs(this, Tag.MAP, DumperOptions.FlowStyle.BLOCK); + Map meta = yaml.loadAs(output, Map.class); + return meta; + } + + public Yaml createYaml() { + DumperOptions options = new DumperOptions(); + options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); + options.setPrettyFlow(true); + + Yaml yaml = new Yaml(new DBGitYamlConstructor(), new DBGitYamlRepresenter(), options); + return yaml; + } + + @Override + public int addToGit() throws ExceptionDBGit { + DBGit dbGit = DBGit.getInstance(); + dbGit.addFileToIndexGit(DBGitPath.DB_GIT_PATH+"/"+getFileName()); + return 1; + } + + @Override + public int removeFromGit() throws ExceptionDBGit { + DBGit dbGit = DBGit.getInstance(); + dbGit.removeFileFromIndexGit(DBGitPath.DB_GIT_PATH+"/"+getFileName()); + return 1; + } + + public void setDbType() { + try { + setDbType(AdapterFactory.createAdapter().getDbType()); + } catch (ExceptionDBGit e) { + throw new ExceptionDBGitRunTime(e.getLocalizedMessage()); + } + + } + + public void setDbVersion() { + try { + setDbVersion(AdapterFactory.createAdapter().getDbVersion()); + } catch (ExceptionDBGit e) { + throw new ExceptionDBGitRunTime(e.getLocalizedMessage()); + } + + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof MetaBase)) return false; + MetaBase metaBase = (MetaBase) o; + return getHash().equals(metaBase.getHash()); + } + + @Override + public int hashCode() { + return getHash().hashCode(); + } +} diff --git a/src/main/java/ru/fusionsoft/dbgit/meta/MetaDomain.java b/src/main/java/ru/fusionsoft/dbgit/meta/MetaDomain.java new file mode 100644 index 0000000..a7aa969 --- /dev/null +++ b/src/main/java/ru/fusionsoft/dbgit/meta/MetaDomain.java @@ -0,0 +1,40 @@ +package ru.fusionsoft.dbgit.meta; + +import ru.fusionsoft.dbgit.adapters.AdapterFactory; +import ru.fusionsoft.dbgit.adapters.IDBAdapter; +import ru.fusionsoft.dbgit.core.ExceptionDBGit; +import ru.fusionsoft.dbgit.dbobjects.DBDomain; +import ru.fusionsoft.dbgit.dbobjects.DBSQLObject; + +public class MetaDomain extends MetaSql { + public MetaDomain() { + } + + public MetaDomain(DBSQLObject sqlObject) throws ExceptionDBGit { + super(sqlObject); + } + + /** + * @return Type meta object + */ + @Override + public final IDBGitMetaType getType() { + return DBGitMetaType.DBGitDomain; + } + + /** + * load current object from DB + */ + @Override + public final boolean loadFromDB() throws ExceptionDBGit { + final IDBAdapter adapter = AdapterFactory.createAdapter(); + final NameMeta nm = MetaObjectFactory.parseMetaName(name); + final DBDomain dbObject = adapter.getDomain(nm.getSchema(), nm.getName()); + + if (dbObject != null) { + setSqlObject(dbObject); + return true; + } else + return false; + } +} diff --git a/src/main/java/ru/fusionsoft/dbgit/meta/MetaEnum.java b/src/main/java/ru/fusionsoft/dbgit/meta/MetaEnum.java new file mode 100644 index 0000000..fd41f51 --- /dev/null +++ b/src/main/java/ru/fusionsoft/dbgit/meta/MetaEnum.java @@ -0,0 +1,32 @@ +package ru.fusionsoft.dbgit.meta; + +import ru.fusionsoft.dbgit.adapters.AdapterFactory; +import ru.fusionsoft.dbgit.adapters.IDBAdapter; +import ru.fusionsoft.dbgit.core.ExceptionDBGit; +import ru.fusionsoft.dbgit.dbobjects.DBEnum; + +public class MetaEnum extends MetaSql { + /** + * @return Type meta object + */ + @Override + public IDBGitMetaType getType() { + return DBGitMetaType.DBGitEnum; + } + + /** + * load current object from DB + */ + @Override + public boolean loadFromDB() throws ExceptionDBGit { + final IDBAdapter adapter = AdapterFactory.createAdapter(); + final NameMeta nm = MetaObjectFactory.parseMetaName(name); + final DBEnum dbObject = adapter.getEnum(nm.getSchema(), nm.getName()); + + if (dbObject != null) { + setSqlObject(dbObject); + return true; + } else + return false; + } +} diff --git a/src/main/java/ru/fusionsoft/dbgit/meta/MetaFunction.java b/src/main/java/ru/fusionsoft/dbgit/meta/MetaFunction.java index 9823362..09d6a0e 100644 --- a/src/main/java/ru/fusionsoft/dbgit/meta/MetaFunction.java +++ b/src/main/java/ru/fusionsoft/dbgit/meta/MetaFunction.java @@ -11,7 +11,7 @@ public class MetaFunction extends MetaSql { public MetaFunction() { super(); } - + public MetaFunction(DBFunction fun) throws ExceptionDBGit { super(fun); } @@ -21,14 +21,12 @@ public DBGitMetaType getType() { return DBGitMetaType.DbGitFunction; } - @Override - public String getName() { - return name; - } - @Override public String getFileName(){ String res = name.replace(".fnc", ""); + String schemaName = ""; + if (res.contains("/")) + schemaName = res.substring(0, res.indexOf("/")); if (this.getSqlObject() != null && this.getSqlObject().getOptions() != null && this.getSqlObject().getOptions().get("arguments") != null) res = res + "_" + this.getSqlObject().getOptions().get("arguments").getData() @@ -41,7 +39,7 @@ public String getFileName(){ .replace("::", ""); if (res.endsWith("_")) res = res.substring(0, res.length() - 1); - if (res.length() > MAX_FILE_NAME_LENGTH) { + if (res.length() > (schemaName.length() + 1 + MAX_FILE_NAME_LENGTH)) { String resTemp = res.substring(0, MAX_FILE_NAME_LENGTH); int resInt = res.length() - MAX_FILE_NAME_LENGTH; res = resTemp + "_" + resInt; @@ -51,7 +49,7 @@ public String getFileName(){ return res; } - + @Override public boolean loadFromDB() throws ExceptionDBGit { IDBAdapter adapter = AdapterFactory.createAdapter(); diff --git a/src/main/java/ru/fusionsoft/dbgit/meta/MetaObjOptions.java b/src/main/java/ru/fusionsoft/dbgit/meta/MetaObjOptions.java index 8063e44..d4f5d8b 100644 --- a/src/main/java/ru/fusionsoft/dbgit/meta/MetaObjOptions.java +++ b/src/main/java/ru/fusionsoft/dbgit/meta/MetaObjOptions.java @@ -4,15 +4,14 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.Map; +import java.util.Objects; -import ru.fusionsoft.dbgit.adapters.AdapterFactory; -import ru.fusionsoft.dbgit.adapters.IDBAdapter; import ru.fusionsoft.dbgit.core.DBGitLang; import ru.fusionsoft.dbgit.core.ExceptionDBGit; import ru.fusionsoft.dbgit.core.ExceptionDBGitObjectNotFound; import ru.fusionsoft.dbgit.dbobjects.DBOptionsObject; -import ru.fusionsoft.dbgit.dbobjects.DBUser; import ru.fusionsoft.dbgit.utils.CalcHash; +import ru.fusionsoft.dbgit.yaml.YamlOrder; /** * Base Meta class for data use DBOptionsObject information. This data is tree string properties. @@ -21,6 +20,7 @@ */ public abstract class MetaObjOptions extends MetaBase { + @YamlOrder(4) private DBOptionsObject objectOption = null; public MetaObjOptions() { @@ -48,7 +48,7 @@ public boolean serialize(OutputStream stream) throws IOException { } @Override - public IMetaObject deSerialize(InputStream stream) throws IOException{ + public IMetaObject deSerialize(InputStream stream) { return yamlDeSerialize(stream); } @@ -75,4 +75,16 @@ public void setObjectOptionFromMap(Map map) t setObjectOption(map.get(nm.getName())); } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof MetaObjOptions)) return false; + MetaObjOptions that = (MetaObjOptions) o; + return getObjectOption().getHash().equals(that.getObjectOption().getHash()); + } + + @Override + public int hashCode() { + return Objects.hash(getObjectOption()); + } } diff --git a/src/main/java/ru/fusionsoft/dbgit/meta/MetaObjectFactory.java b/src/main/java/ru/fusionsoft/dbgit/meta/MetaObjectFactory.java index ca303bd..0beb554 100644 --- a/src/main/java/ru/fusionsoft/dbgit/meta/MetaObjectFactory.java +++ b/src/main/java/ru/fusionsoft/dbgit/meta/MetaObjectFactory.java @@ -46,21 +46,18 @@ public static IMetaObject createMetaObject(IDBGitMetaType tp) throws ExceptionDB } - public static NameMeta parseMetaName(String name) throws ExceptionDBGit { - try { - NameMeta nm = new NameMeta(); - - Integer pos = name.lastIndexOf("/"); - if (pos > 0) { - nm.setSchema(name.substring(0, pos)); - } - Integer posDot = name.lastIndexOf("."); - nm.setName(name.substring(pos+1, posDot)); - nm.setType(DBGitMetaType.valueByCode(name.substring(posDot + 1))); + public static NameMeta parseMetaName(String name) { + NameMeta nm = new NameMeta(); - return nm; - } catch(Exception e) { - throw new ExceptionDBGitRunTime(DBGitLang.getInstance().getValue("errors", "meta", "parseError").withParams(name), e); + Integer pos = name.lastIndexOf("/"); + if (pos > 0) { + nm.setSchema(name.substring(0, pos)); } + Integer posDot = name.lastIndexOf("."); + nm.setName(name.substring(pos+1, posDot)); + nm.setType(DBGitMetaType.valueByCode(name.substring(posDot + 1))); + + return nm; + } } diff --git a/src/main/java/ru/fusionsoft/dbgit/meta/MetaProcedure.java b/src/main/java/ru/fusionsoft/dbgit/meta/MetaProcedure.java index 7335917..46a8a61 100644 --- a/src/main/java/ru/fusionsoft/dbgit/meta/MetaProcedure.java +++ b/src/main/java/ru/fusionsoft/dbgit/meta/MetaProcedure.java @@ -29,6 +29,9 @@ public String getName() { @Override public String getFileName(){ String res = name.replace(".prc", ""); + String schemaName = ""; + if (res.contains("/")) + schemaName = res.substring(0, res.indexOf("/")); if (this.getSqlObject() != null && this.getSqlObject().getOptions() != null && this.getSqlObject().getOptions().get("arguments") != null) res = res + "_" + this.getSqlObject().getOptions().get("arguments").getData() @@ -41,7 +44,7 @@ public String getFileName(){ .replace("::", ""); if (res.endsWith("_")) res = res.substring(0, res.length() - 1); - if (res.length() > MAX_FILE_NAME_LENGTH) { + if (res.length() > (schemaName.length() + 1 + MAX_FILE_NAME_LENGTH)) { String resTemp = res.substring(0, MAX_FILE_NAME_LENGTH); int resInt = res.length() - MAX_FILE_NAME_LENGTH; res = resTemp + "_" + resInt; diff --git a/src/main/java/ru/fusionsoft/dbgit/meta/MetaSql.java b/src/main/java/ru/fusionsoft/dbgit/meta/MetaSql.java index 78667f9..7319170 100644 --- a/src/main/java/ru/fusionsoft/dbgit/meta/MetaSql.java +++ b/src/main/java/ru/fusionsoft/dbgit/meta/MetaSql.java @@ -1,18 +1,10 @@ package ru.fusionsoft.dbgit.meta; +import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.io.StringWriter; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.util.Map; -import org.apache.commons.io.IOUtils; - -import ru.fusionsoft.dbgit.core.DBGitLang; import ru.fusionsoft.dbgit.core.ExceptionDBGit; -import ru.fusionsoft.dbgit.core.ExceptionDBGitObjectNotFound; -import ru.fusionsoft.dbgit.dbobjects.DBOptionsObject; import ru.fusionsoft.dbgit.dbobjects.DBSQLObject; /** @@ -21,19 +13,18 @@ * */ public abstract class MetaSql extends MetaBase { - - + protected DBSQLObject sqlObject; public MetaSql() { setDbType(); setDbVersion(); } - + public MetaSql(DBSQLObject sqlObject) throws ExceptionDBGit { this(); setSqlObject(sqlObject); - } - + } + public DBSQLObject getSqlObject() { return sqlObject; } @@ -45,7 +36,7 @@ public void setSqlObject(DBSQLObject sqlObject) throws ExceptionDBGit { } @Override - public boolean serialize(OutputStream stream) throws Exception { + public boolean serialize(OutputStream stream) throws IOException { /* String owner = "owner: "+getSqlObject().getOwner()+"\n"; stream.write(owner.getBytes(Charset.forName("UTF-8"))); @@ -59,7 +50,7 @@ public boolean serialize(OutputStream stream) throws Exception { } @Override - public IMetaObject deSerialize(InputStream stream) throws Exception { + public IMetaObject deSerialize(InputStream stream) { NameMeta nm = MetaObjectFactory.parseMetaName(getName()); /* sqlObject = new DBSQLObject(); @@ -83,12 +74,13 @@ public IMetaObject deSerialize(InputStream stream) throws Exception { public String getHash() { return sqlObject != null ? sqlObject.getHash() : EMPTY_HASH; } - public void setObjectOptionFromMap(Map map) throws ExceptionDBGit { - NameMeta nm = MetaObjectFactory.parseMetaName(getName()); - if (!map.containsKey(nm.getName())) { - throw new ExceptionDBGitObjectNotFound(DBGitLang.getInstance().getValue("errors", "meta", "notFound").withParams(getName())); - } - setSqlObject(map.get(nm.getName())); - } + +// public void setSqlObjectFromMap(Map map) throws ExceptionDBGit { +// NameMeta nm = MetaObjectFactory.parseMetaName(getName()); +// if (!map.containsKey(nm.getName())) { +// throw new ExceptionDBGitObjectNotFound(DBGitLang.getInstance().getValue("errors", "meta", "notFound").withParams(getName())); +// } +// setSqlObject(map.get(nm.getName())); +// } } diff --git a/src/main/java/ru/fusionsoft/dbgit/meta/MetaTable.java b/src/main/java/ru/fusionsoft/dbgit/meta/MetaTable.java index 96bbcb1..927a338 100644 --- a/src/main/java/ru/fusionsoft/dbgit/meta/MetaTable.java +++ b/src/main/java/ru/fusionsoft/dbgit/meta/MetaTable.java @@ -11,55 +11,49 @@ import ru.fusionsoft.dbgit.adapters.IDBAdapter; import ru.fusionsoft.dbgit.core.DBGitIndex; import ru.fusionsoft.dbgit.core.ExceptionDBGit; -import ru.fusionsoft.dbgit.core.ExceptionDBGitRunTime; -import ru.fusionsoft.dbgit.core.ItemIndex; -import ru.fusionsoft.dbgit.dbobjects.DBConstraint; -import ru.fusionsoft.dbgit.dbobjects.DBIndex; -import ru.fusionsoft.dbgit.dbobjects.DBSchema; -import ru.fusionsoft.dbgit.dbobjects.DBTable; -import ru.fusionsoft.dbgit.dbobjects.DBTableField; +import ru.fusionsoft.dbgit.core.ExceptionDBGitObjectNotFound; +import ru.fusionsoft.dbgit.dbobjects.*; import ru.fusionsoft.dbgit.utils.CalcHash; -import ru.fusionsoft.dbgit.utils.ConsoleWriter; import ru.fusionsoft.dbgit.yaml.YamlOrder; /** - * Meta class for db Table + * Meta class for db Table * @author mikle * */ -public class MetaTable extends MetaBase { +public class MetaTable extends MetaBase { - @YamlOrder(1) + @YamlOrder(3) private DBTable table; - - @YamlOrder(2) + + @YamlOrder(4) //private IMapFields fields = new TreeMapFields(); private Map fields = new TreeMap<>(); - - @YamlOrder(3) + + @YamlOrder(5) private Map indexes = new TreeMap<>(); - - @YamlOrder(4) + + @YamlOrder(6) private Map constraints = new TreeMap<>(); - public MetaTable() { + public MetaTable() { setDbType(); setDbVersion(); } - + public MetaTable(String namePath) { setDbType(); setDbVersion(); this.name = namePath; } - + public MetaTable(DBTable tbl) { setDbType(); setDbVersion(); setTable(tbl); } - + @Override public DBGitMetaType getType() { return DBGitMetaType.DBGitTable; @@ -71,7 +65,7 @@ public boolean serialize(OutputStream stream) throws IOException { } @Override - public IMetaObject deSerialize(InputStream stream) throws IOException { + public IMetaObject deSerialize(InputStream stream) { return yamlDeSerialize(stream); } @@ -79,12 +73,15 @@ public IMetaObject deSerialize(InputStream stream) throws IOException { public boolean loadFromDB() throws ExceptionDBGit { IDBAdapter adapter = AdapterFactory.createAdapter(); NameMeta nm = MetaObjectFactory.parseMetaName(getName()); - - DBTable tbl = adapter.getTable(nm.getSchema(), nm.getName()); - if (tbl != null) - return loadFromDB(tbl); - else + try { + DBTable tbl = adapter.getTable(nm.getSchema(), nm.getName()); + if (tbl != null) + return loadFromDB(tbl); + else + return false; + } catch (ExceptionDBGitObjectNotFound exnf) { return false; + } } public boolean loadFromDB(DBTable tbl) throws ExceptionDBGit { @@ -126,7 +123,13 @@ public boolean loadFromDB(DBTable tbl) throws ExceptionDBGit { @Override public String getHash() { - CalcHash ch = new CalcHash(); + CalcHash ch = new CalcHash()/*{ + @Override + public CalcHash addData(String str){ + ConsoleWriter.printlnRed(str); + return super.addData(str); + } + }*/; ch.addData(this.getName()); if (getTable() != null) { @@ -142,20 +145,17 @@ public String getHash() { } - if (indexes != null) { - for (String item : indexes.keySet()) { - ch.addData(item); - ch.addData(indexes.get(item).getHash()); + for (String item : indexes.keySet()) { + if(constraints.containsKey(item)) continue; + ch.addData(item); + ch.addData(indexes.get(item).getHash()); - } } - - if (constraints != null) { - for (String item : constraints.keySet()) { - ch.addData(item); - ch.addData(constraints.get(item).getHash()); - } + for (String item : constraints.keySet()) { + ch.addData(item); + ch.addData(constraints.get(item).getHash()); + } return ch.calcHashStr(); @@ -213,15 +213,27 @@ public void setConstraints(Map constraints) { this.constraints.putAll(constraints); } - public List getIdColumns() { - List idColumns = new ArrayList<>(); - + public List getIdColumns() { + List idColumns = new ArrayList<>(); + + int i = 0; for (DBTableField field : fields.values()) { if (field.getIsPrimaryKey()) { - idColumns.add(field.getName()); + //idColumns.add(field.getName()); + idColumns.add(i); } + i++; } return idColumns; } +// private String truncateHash(String hash){ +// return hash.substring( +// 0, +// 2 +// ) + hash.substring( +// hash.length() - 3, +// hash.length() - 1 +// ); +// } } diff --git a/src/main/java/ru/fusionsoft/dbgit/meta/MetaTableData.java b/src/main/java/ru/fusionsoft/dbgit/meta/MetaTableData.java index 34f4400..fa3042d 100644 --- a/src/main/java/ru/fusionsoft/dbgit/meta/MetaTableData.java +++ b/src/main/java/ru/fusionsoft/dbgit/meta/MetaTableData.java @@ -1,374 +1,453 @@ -package ru.fusionsoft.dbgit.meta; - -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.nio.charset.Charset; -import java.sql.ResultSet; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; -import java.util.concurrent.TimeUnit; - -import org.apache.commons.codec.binary.Base64; -import org.apache.commons.csv.CSVFormat; -import org.apache.commons.csv.CSVParser; -import org.apache.commons.csv.CSVPrinter; -import org.apache.commons.csv.CSVRecord; -import org.apache.commons.csv.QuoteMode; - -import com.diogonunes.jcdp.color.api.Ansi.FColor; - -import ru.fusionsoft.dbgit.adapters.AdapterFactory; -import ru.fusionsoft.dbgit.adapters.IDBAdapter; -import ru.fusionsoft.dbgit.core.DBGit; -import ru.fusionsoft.dbgit.core.DBGitConfig; -import ru.fusionsoft.dbgit.core.DBGitLang; -import ru.fusionsoft.dbgit.core.DBGitPath; -import ru.fusionsoft.dbgit.core.ExceptionDBGit; -import ru.fusionsoft.dbgit.core.ExceptionDBGitRunTime; -import ru.fusionsoft.dbgit.core.GitMetaDataManager; -import ru.fusionsoft.dbgit.data_table.ICellData; -import ru.fusionsoft.dbgit.data_table.RowData; -import ru.fusionsoft.dbgit.data_table.TreeMapRowData; -import ru.fusionsoft.dbgit.dbobjects.DBTable; -import ru.fusionsoft.dbgit.dbobjects.DBTableData; -import ru.fusionsoft.dbgit.utils.CalcHash; -import ru.fusionsoft.dbgit.utils.ConsoleWriter; - -/** - * Meta class for Table data - * @author mikle - * - */ -public class MetaTableData extends MetaBase { - protected DBTable table = null; - private DBTableData dataTable = null; - - private TreeMapRowData mapRows = null; - - public MetaTableData() { - setDbType(); - setDbVersion(); - } - - public MetaTableData(DBTable tbl) throws ExceptionDBGit { - setDbType(); - setDbVersion(); - setTable(tbl); - } - - - public DBTable getTable() { - return table; - } - - public TreeMap getmapRows() { - return mapRows; - } - - public DBTableData getDataTable() { - return dataTable; - } - - public void setMapRows(TreeMapRowData mapRows) { - this.mapRows = mapRows; - } - - public void setDataTable(DBTableData dataTable) { - this.dataTable = dataTable; - } - - public void setTable(DBTable table) throws ExceptionDBGit { - this.table = table; - setName(table.getSchema()+"/"+table.getName()+"."+getType().getValue()); - } - - - - @Override - public void setName(String name) throws ExceptionDBGit { - if (table == null) { - NameMeta nm = MetaObjectFactory.parseMetaName(name); - table = new DBTable(); - table.setSchema(nm.getSchema()); - table.setName(nm.getName()); - } - - super.setName(name); - } - - @Override - public DBGitMetaType getType() { - return DBGitMetaType.DbGitTableData; - } - - public CSVFormat getCSVFormat() { - return CSVFormat.DEFAULT - //.withRecordSeparator("\n") - .withDelimiter(';') - .withNullString("") - .withQuote('"') - //.withQuoteMode(QuoteMode.ALL) - ; - } - - public MetaTable getMetaTable() throws ExceptionDBGit { - String metaTblName = table.getSchema()+"/"+table.getName()+"."+DBGitMetaType.DBGitTable.getValue(); - GitMetaDataManager gmdm = GitMetaDataManager.getInstance(); - - IMapMetaObject dbObjs = gmdm.getCacheDBMetaData(); - MetaTable metaTable = (MetaTable) dbObjs.get(metaTblName); - if (metaTable == null ) { - metaTable = new MetaTable(); - metaTable.loadFromDB(table); - } - return metaTable; - } - - public MetaTable getMetaTableFromFile() throws ExceptionDBGit { - String metaTblName = table.getSchema()+"/"+table.getName()+"."+DBGitMetaType.DBGitTable.getValue(); - GitMetaDataManager gmdm = GitMetaDataManager.getInstance(); - - MetaTable metaTable = (MetaTable)gmdm.loadMetaFile(metaTblName); - if (metaTable != null) - return metaTable; - - return getMetaTable(); - } - - - @Override - public boolean serialize(OutputStream stream) throws Exception { - Integer count = 0; - Set fields = null; - - if (mapRows == null) { - return false; - } - - CSVPrinter csvPrinter = new CSVPrinter(new OutputStreamWriter(stream), getCSVFormat()); - - for (RowData rd : mapRows.values()) { - if (count == 0) { - fields = rd.getData().keySet(); - csvPrinter.printRecord(fields); - } - - rd.saveDataToCsv(csvPrinter, getTable()); - - count++; - } - csvPrinter.close(); - return true; - } - - @Override - public IMetaObject deSerialize(InputStream stream) throws Exception { - - MetaTable metaTable = getMetaTableFromFile(); - - CSVParser csvParser = new CSVParser(new InputStreamReader(stream), getCSVFormat()); - List csvRecords = csvParser.getRecords(); - - if (csvRecords.size() > 0) { - CSVRecord titleColumns = csvRecords.get(0); - - mapRows = new TreeMapRowData(); - - for (int i = 1; i < csvRecords.size(); i++) { - RowData rd = new RowData(csvRecords.get(i), metaTable, titleColumns); - mapRows.put(rd); - } - } - - csvParser.close(); - - //saveToFile("test"); - - return this; - } - - public boolean loadPortionFromDB(int currentPortionIndex) throws ExceptionDBGit { - return loadPortionFromDB(currentPortionIndex, 0); - } - - public boolean loadPortionFromDB(int currentPortionIndex, int tryNumber) throws ExceptionDBGit { - try { - IDBAdapter adapter = AdapterFactory.createAdapter(); - MetaTable metaTable = getMetaTable(); - if (metaTable.getFields().size() == 0) - return false; - - dataTable = adapter.getTableDataPortion(table.getSchema(), table.getName(), currentPortionIndex, 0); - - ResultSet rs = dataTable.getResultSet(); - - if (dataTable.getErrorFlag() > 0) { - ConsoleWriter.printlnColor(DBGitLang.getInstance().getValue("errors", "meta", "tooManyRecords"). - withParams(getName(), String.valueOf(IDBAdapter.MAX_ROW_COUNT_FETCH)), FColor.RED, 0); - return false; - } - - mapRows = new TreeMapRowData(); - - while(rs.next()){ - RowData rd = new RowData(rs, metaTable); - mapRows.put(rd); - } - return true; - } catch (Exception e) { - e.printStackTrace(); - ConsoleWriter.println(e.getMessage()); - ConsoleWriter.println(e.getLocalizedMessage()); - - try { - if (tryNumber <= DBGitConfig.getInstance().getInteger("core", "TRY_COUNT", DBGitConfig.getInstance().getIntegerGlobal("core", "TRY_COUNT", 1000))) { - try { - TimeUnit.SECONDS.sleep(DBGitConfig.getInstance().getInteger("core", "TRY_DELAY", DBGitConfig.getInstance().getIntegerGlobal("core", "TRY_DELAY", 1000))); - } catch (InterruptedException e1) { - throw new ExceptionDBGitRunTime(e1.getMessage()); - } - ConsoleWriter.println("Error while getting portion of data, try " + tryNumber); - return loadPortionFromDB(currentPortionIndex, tryNumber++); - } - } catch (Exception e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } - - if (e instanceof ExceptionDBGit) - throw (ExceptionDBGit)e; - throw new ExceptionDBGit(e); - } - } - - @Override - public boolean loadFromDB() throws ExceptionDBGit { - try { - IDBAdapter adapter = AdapterFactory.createAdapter(); - - MetaTable metaTable = getMetaTable(); - - if (metaTable.getFields().size() == 0) - return false; - - List idColumns = metaTable.getIdColumns(); - - dataTable = adapter.getTableData(table.getSchema(), table.getName()); - - if (dataTable.getErrorFlag() > 0) { - ConsoleWriter.printlnColor(DBGitLang.getInstance().getValue("errors", "meta", "tooManyRecords"). - withParams(getName(), String.valueOf(IDBAdapter.MAX_ROW_COUNT_FETCH)), FColor.RED, 0); - return false; - } - - ResultSet rs = dataTable.getResultSet(); - - mapRows = new TreeMapRowData(); - - //System.out.println("load from db file "+getName()); - while(rs.next()){ - RowData rd = new RowData(rs, metaTable); - mapRows.put(rd); - } - return true; - /* - System.out.println("******************************************"); - System.out.println(); - */ - } catch (Exception e) { - e.printStackTrace(); - if (e instanceof ExceptionDBGit) - throw (ExceptionDBGit)e; - throw new ExceptionDBGit(e); - } - - } - - public void diff(MetaTableData ob) throws Exception { - if (mapRows.size() != ob.mapRows.size()) { - System.out.println(DBGitLang.getInstance().getValue("general", "meta", "diffSize1").withParams(String.valueOf(mapRows.size()), String.valueOf(ob.mapRows.size()))); - } - for (String rowHash : mapRows.keySet()) { - RowData r1 = mapRows.get(rowHash); - RowData r2 = ob.mapRows.get(rowHash); - - System.out.println(rowHash); - System.out.println(r1.getData()+ " "+ r2.getData()); - - if (r1.getData().size() != r2.getData().size()) { - System.out.println(DBGitLang.getInstance().getValue("general", "meta", "diffSize2").withParams(rowHash)); - } - - for (String col : r1.getData().keySet()) { - String d1 = r1.getData().get(col).convertToString(); - String d2 = r2.getData().get(col).convertToString(); - - if (d1 != d2) { - if (!d1.equals(r2.getData().get(col))) { - System.out.println(DBGitLang.getInstance().getValue("general", "meta", "diffDataRow"). - withParams(rowHash, col, r1.getData().get(col).toString(), r2.getData().get(col).toString())); - } - } - } - } - } - - - @Override - public String getHash() { - CalcHash ch = new CalcHash(); - if (mapRows == null) - return EMPTY_HASH; - - if (mapRows.size() == 0) - return EMPTY_HASH; - - //System.out.println(getName()); - int n = 0; - for (RowData rd : mapRows.values()) { - ch.addData(rd.getHashRow()); - //System.out.println("row "+n+" "+rd.getHashRow()); - n++; - } - - return ch.calcHashStr(); - } - - @Override - public int addToGit() throws ExceptionDBGit { - int count = super.addToGit(); - - if (mapRows == null) return count; - - for (RowData rd : mapRows.values()) { - for (ICellData cd : rd.getData().values()) { - count += cd.addToGit(); - } - } - - return count; - } - - @Override - public int removeFromGit() throws ExceptionDBGit { - int count = super.removeFromGit(); - - if (mapRows == null) - return 1; - - for (RowData rd : mapRows.values()) { - for (ICellData cd : rd.getData().values()) { - count += cd.removeFromGit(); - } - } - - return count; - } - -} +package ru.fusionsoft.dbgit.meta; + +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.sql.ResultSet; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.TreeMap; +import java.util.concurrent.TimeUnit; + +import de.siegmar.fastcsv.reader.CsvParser; +import de.siegmar.fastcsv.reader.CsvReader; +import de.siegmar.fastcsv.reader.CsvRow; + +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVParser; +import org.apache.commons.csv.CSVPrinter; +import org.apache.commons.csv.CSVRecord; + +import com.diogonunes.jcdp.color.api.Ansi.FColor; + +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.slf4j.Logger; +import ru.fusionsoft.dbgit.adapters.AdapterFactory; +import ru.fusionsoft.dbgit.adapters.IDBAdapter; +import ru.fusionsoft.dbgit.core.DBGitConfig; +import ru.fusionsoft.dbgit.core.DBGitLang; +import ru.fusionsoft.dbgit.core.ExceptionDBGit; +import ru.fusionsoft.dbgit.core.ExceptionDBGitRunTime; +import ru.fusionsoft.dbgit.core.GitMetaDataManager; +import ru.fusionsoft.dbgit.data_table.ICellData; +import ru.fusionsoft.dbgit.data_table.MapFileData; +import ru.fusionsoft.dbgit.data_table.RowData; +import ru.fusionsoft.dbgit.data_table.TreeMapRowData; +import ru.fusionsoft.dbgit.dbobjects.DBTable; +import ru.fusionsoft.dbgit.dbobjects.DBTableData; +import ru.fusionsoft.dbgit.utils.CalcHash; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; +import ru.fusionsoft.dbgit.utils.LoggerUtil; + +/** + * Meta class for Table data + * @author mikle + * + */ +public class MetaTableData extends MetaBase { + private Logger logger = LoggerUtil.getLogger(this.getClass()); + protected DBTable table = null; + private DBTableData dataTable = null; + + private TreeMapRowData mapRows = null; + private List fields = new ArrayList<>(); + + public MetaTableData() { + setDbType(); + setDbVersion(); + } + + public MetaTableData(DBTable tbl) throws ExceptionDBGit { + setDbType(); + setDbVersion(); + setTable(tbl); + } + + + public DBTable getTable() { + return table; + } + + public TreeMap getmapRows() { + return mapRows; + } + + public DBTableData getDataTable() { + return dataTable; + } + + public void setMapRows(TreeMapRowData mapRows) { + this.mapRows = mapRows; + } + + public void setDataTable(DBTableData dataTable) { + this.dataTable = dataTable; + } + + public void setTable(DBTable table) throws ExceptionDBGit { + this.table = table; + setName(table.getSchema()+"/"+table.getName()+"."+getType().getValue()); + } + + public void setFields(List fields) { + this.fields = fields; + } + + @Override + public void setName(String name) throws ExceptionDBGit { + if (table == null) { + NameMeta nm = MetaObjectFactory.parseMetaName(name); + table = new DBTable.OnlyNameDBTable(nm.getName(), nm.getSchema()); + } + + super.setName(name); + } + + @Override + public DBGitMetaType getType() { + return DBGitMetaType.DbGitTableData; + } + + public CSVFormat getCSVFormat() { + return CSVFormat.DEFAULT + //.withRecordSeparator("\n") + .withDelimiter(';') + .withNullString("") + .withQuote('"') + //.withQuoteMode(QuoteMode.ALL) + ; + } + + public MetaTable getMetaTable() throws ExceptionDBGit { + String metaTblName = table.getSchema()+"/"+table.getName()+"."+DBGitMetaType.DBGitTable.getValue(); + GitMetaDataManager gmdm = GitMetaDataManager.getInstance(); + + IMapMetaObject dbObjs = gmdm.getCacheDBMetaData(); + MetaTable metaTable = (MetaTable) dbObjs.get(metaTblName); + if (metaTable == null ) { + metaTable = new MetaTable(); + metaTable.loadFromDB(table); + } + return metaTable; + } + + public MetaTable getMetaTableFromFile() throws ExceptionDBGit { + String metaTblName = table.getSchema()+"/"+table.getName()+"."+DBGitMetaType.DBGitTable.getValue(); + GitMetaDataManager gmdm = GitMetaDataManager.getInstance(); + + MetaTable metaTable = (MetaTable)gmdm.loadMetaFile(metaTblName); + if (metaTable != null) + return metaTable; + + //TODO ... which is not from file, but from db + return getMetaTable(); + } + + + @Override + public boolean serialize(OutputStream stream) throws Exception { + Integer count = 0; + Set fields = null; + + if (mapRows == null) { + return false; + } + + CSVPrinter csvPrinter = new CSVPrinter(new OutputStreamWriter(stream), getCSVFormat()); + + for (RowData rd : mapRows.values()) { + if (count == 0) { + fields = rd.getData(this.fields).keySet(); + csvPrinter.printRecord(fields); + } + + rd.saveDataToCsv(csvPrinter, getTable()); + + count++; + } + csvPrinter.close(); + return true; + } + + @Override + public IMetaObject deSerialize(File file) throws Exception { + MetaTable metaTable = getMetaTableFromFile(); + + CsvReader csvReader = new CsvReader(); + csvReader.setFieldSeparator(';'); + csvReader.setContainsHeader(false); + int i = 1; + + try (CsvParser csvParser = csvReader.parse(file, StandardCharsets.UTF_8)) { + CsvRow row; + boolean flag = false; + mapRows = new TreeMapRowData(); + CsvRow titleColumns = null; + + + while ((row = csvParser.nextRow()) != null) { + if (!flag) { + titleColumns = row; + fields = row.getFields(); +// System.err.println("fields = " + fields); + } else { + RowData rd = new RowData(row, metaTable, titleColumns); + mapRows.put(rd); + i++; + } + flag = true; + } + } catch (Throwable ex){ + ConsoleWriter.detailsPrint(DBGitLang.getInstance().getValue("general", "meta", "loadRow").withParams(String.valueOf(i) )); + warnFilesNotFound(); + throw ex; + } + ConsoleWriter.detailsPrint(DBGitLang.getInstance().getValue("general", "meta", "loadedRow").withParams(String.valueOf(i) )); + warnFilesNotFound(); + + return this; + } + + + @Override + @Deprecated + public IMetaObject deSerialize(InputStream stream) throws Exception { + + MetaTable metaTable = getMetaTableFromFile(); + + CSVParser csvParser = new CSVParser(new InputStreamReader(stream), getCSVFormat()); + List csvRecords = csvParser.getRecords(); + + if (csvRecords.size() > 0) { + CSVRecord titleColumns = csvRecords.get(0); + fields.clear(); + for (int i = 0; i < csvRecords.get(0).size(); i++) { + fields.add(csvRecords.get(0).get(i)); + } + + mapRows = new TreeMapRowData(); + + for (int i = 1; i < csvRecords.size(); i++) { + RowData rd = new RowData(csvRecords.get(i), metaTable, titleColumns); + mapRows.put(rd); + } + } + + + csvParser.close(); + + //saveToFile("test"); + + return this; + } + + public boolean loadPortionFromDB(int currentPortionIndex) throws ExceptionDBGit { + return loadPortionFromDB(currentPortionIndex, 0); + } + + public boolean loadPortionFromDB(int currentPortionIndex, int tryNumber) throws ExceptionDBGit { + try { + IDBAdapter adapter = AdapterFactory.createAdapter(); + MetaTable metaTable = getMetaTable(); + if (metaTable.getFields().size() == 0) + return false; + + dataTable = adapter.getTableDataPortion(table.getSchema(), table.getName(), currentPortionIndex, 0); + + ResultSet rs = dataTable.resultSet(); + + if (dataTable.errorFlag() > 0) { + final String tooManyRecordsMsg = DBGitLang.getInstance().getValue("errors", "meta", "tooManyRecords").withParams(getName(), String.valueOf(IDBAdapter.MAX_ROW_COUNT_FETCH)); + ConsoleWriter.printlnColor(tooManyRecordsMsg, FColor.RED, 0); + return false; + } + + mapRows = new TreeMapRowData(); + + boolean flag = false; + while(rs.next()){ + + if (!flag) { + fields.clear(); + for (int i = 0; i < rs.getMetaData().getColumnCount(); i++) { + String columnName = rs.getMetaData().getColumnName(i + 1); + if (columnName.equalsIgnoreCase("DBGIT_ROW_NUM")) + continue; + fields.add(columnName); + } + } + + flag = true; + RowData rd = new RowData(rs, metaTable); + mapRows.put(rd); + } + + + + return true; + } catch (Exception e) { + + ConsoleWriter.println(e.getLocalizedMessage(), messageLevel); + ConsoleWriter.detailsPrintln(ExceptionUtils.getStackTrace(e), messageLevel); + logger.error(DBGitLang.getInstance().getValue("errors", "adapter", "tableData").toString(), e); + + try { + if (tryNumber <= DBGitConfig.getInstance().getInteger("core", "TRY_COUNT", DBGitConfig.getInstance().getIntegerGlobal("core", "TRY_COUNT", 1000))) { + try { + TimeUnit.SECONDS.sleep(DBGitConfig.getInstance().getInteger("core", "TRY_DELAY", DBGitConfig.getInstance().getIntegerGlobal("core", "TRY_DELAY", 1000))); + } catch (InterruptedException e1) { + throw new ExceptionDBGitRunTime(e1.getMessage()); + } + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("errors", "dataTable", "tryAgain") + .withParams(String.valueOf(tryNumber)) + , messageLevel + ); + return loadPortionFromDB(currentPortionIndex, tryNumber++); + } + } catch (Exception e1) { + throw new ExceptionDBGitRunTime(e1); + // TODO Auto-generated catch block +// e1.printStackTrace(); + } + + if (e instanceof ExceptionDBGit) throw (ExceptionDBGit)e; + throw new ExceptionDBGit(e); + } + } + + @Override + public boolean loadFromDB() throws ExceptionDBGit { + try { + IDBAdapter adapter = AdapterFactory.createAdapter(); + + MetaTable metaTable = getMetaTable(); + + if (metaTable.getFields().size() == 0) + return false; + + dataTable = adapter.getTableData(table.getSchema(), table.getName()); + + if (dataTable.errorFlag() > 0) { + ConsoleWriter.printlnColor(DBGitLang.getInstance().getValue("errors", "meta", "tooManyRecords"). + withParams(getName(), String.valueOf(IDBAdapter.MAX_ROW_COUNT_FETCH)), FColor.RED, 0); + return false; + } + + ResultSet rs = dataTable.resultSet(); + + mapRows = new TreeMapRowData(); + + //System.out.println("load from db file "+getName()); + while(rs.next()){ + RowData rd = new RowData(rs, metaTable); + mapRows.put(rd); + } + return true; + /* + System.out.println("******************************************"); + System.out.println(); + */ + } catch (Exception e) { + throw new ExceptionDBGit("Error loading table data from DB", e); + } + + } + + public void diff(MetaTableData ob) throws Exception { + if (mapRows.size() != ob.mapRows.size()) { + System.out.println(DBGitLang.getInstance().getValue("general", "meta", "diffSize1").withParams(String.valueOf(mapRows.size()), String.valueOf(ob.mapRows.size()))); + } + for (String rowHash : mapRows.keySet()) { + RowData r1 = mapRows.get(rowHash); + RowData r2 = ob.mapRows.get(rowHash); + + System.out.println(rowHash); + System.out.println(r1.getData(fields)+ " "+ r2.getData(ob.fields)); + + if (r1.getData(fields).size() != r2.getData(ob.fields).size()) { + System.out.println(DBGitLang.getInstance().getValue("general", "meta", "diffSize2").withParams(rowHash)); + } + + for (String col : r1.getData(fields).keySet()) { + String d1 = r1.getData(fields).get(col).convertToString(); + String d2 = r2.getData(ob.fields).get(col).convertToString(); + + if (d1 != d2) { + if (!d1.equals(r2.getData(ob.fields).get(col))) { + System.out.println(DBGitLang.getInstance().getValue("general", "meta", "diffDataRow"). + withParams(rowHash, col, r1.getData(fields).get(col).toString(), r2.getData(ob.fields).get(col).toString())); + } + } + } + } + } + + + @Override + public String getHash() { + CalcHash ch = new CalcHash(); + if (mapRows == null) + return EMPTY_HASH; + + if (mapRows.size() == 0) + return EMPTY_HASH; + + //System.out.println(getName()); + int n = 0; + for (RowData rd : mapRows.values()) { + ch.addData(rd.getHashRow()); + //System.out.println("row "+n+" "+rd.getHashRow()); + n++; + } + + return ch.calcHashStr(); + } + + @Override + public int addToGit() throws ExceptionDBGit { + int count = super.addToGit(); + + if (mapRows == null) return count; + + for (RowData rd : mapRows.values()) { + for (ICellData cd : rd.getData(fields).values()) { + count += cd.addToGit(); + } + } + + return count; + } + + @Override + public int removeFromGit() throws ExceptionDBGit { + int count = super.removeFromGit(); + + if (mapRows == null) + return 1; + + for (RowData rd : mapRows.values()) { + for (ICellData cd : rd.getData(fields).values()) { + count += cd.removeFromGit(); + } + } + + return count; + } + + public List getFields() { + return fields; + } + + private void warnFilesNotFound(){ + Set filesNotFound = MapFileData.getFilesNotFound(); + if(filesNotFound != null && filesNotFound.size() > 0){ + ConsoleWriter.detailsPrintlnColor(DBGitLang.getInstance().getValue("errors", "dataTable", "filesNotFound") + .withParams(String.join(";", filesNotFound)) + , FColor.YELLOW, messageLevel + ); + filesNotFound.clear(); + } + + } +} diff --git a/src/main/java/ru/fusionsoft/dbgit/meta/MetaUDT.java b/src/main/java/ru/fusionsoft/dbgit/meta/MetaUDT.java new file mode 100644 index 0000000..014fd0d --- /dev/null +++ b/src/main/java/ru/fusionsoft/dbgit/meta/MetaUDT.java @@ -0,0 +1,40 @@ +package ru.fusionsoft.dbgit.meta; + +import ru.fusionsoft.dbgit.adapters.AdapterFactory; +import ru.fusionsoft.dbgit.adapters.IDBAdapter; +import ru.fusionsoft.dbgit.core.ExceptionDBGit; +import ru.fusionsoft.dbgit.dbobjects.DBSQLObject; +import ru.fusionsoft.dbgit.dbobjects.DBUserDefinedType; + +public class MetaUDT extends MetaSql { + public MetaUDT() { + } + + public MetaUDT(DBSQLObject sqlObject) throws ExceptionDBGit { + super(sqlObject); + } + + /** + * @return Type meta object + */ + @Override + public final IDBGitMetaType getType() { + return DBGitMetaType.DBGitUserDefinedType; + } + + /** + * load current object from DB + */ + @Override + public final boolean loadFromDB() throws ExceptionDBGit { + final IDBAdapter adapter = AdapterFactory.createAdapter(); + final NameMeta nm = MetaObjectFactory.parseMetaName(name); + final DBUserDefinedType dbObject = adapter.getUDT(nm.getSchema(), nm.getName()); + + if (dbObject != null) { + setSqlObject(dbObject); + return true; + } else + return false; + } +} diff --git a/src/main/java/ru/fusionsoft/dbgit/meta/SortedListMetaObject.java b/src/main/java/ru/fusionsoft/dbgit/meta/SortedListMetaObject.java index 35b6f91..16fd538 100644 --- a/src/main/java/ru/fusionsoft/dbgit/meta/SortedListMetaObject.java +++ b/src/main/java/ru/fusionsoft/dbgit/meta/SortedListMetaObject.java @@ -1,12 +1,14 @@ package ru.fusionsoft.dbgit.meta; +import com.diogonunes.jcdp.color.api.Ansi; import com.google.common.collect.Sets; import ru.fusionsoft.dbgit.core.DBGitLang; +import ru.fusionsoft.dbgit.core.ExceptionDBGit; import ru.fusionsoft.dbgit.dbobjects.DBSQLObject; import ru.fusionsoft.dbgit.dbobjects.DBTable; import ru.fusionsoft.dbgit.utils.ConsoleWriter; -import java.sql.Timestamp; + import java.util.*; import java.util.stream.Collectors; @@ -21,28 +23,47 @@ public class SortedListMetaObject { private List listFromFree; private Collection collection; - SortedListMetaObject(Collection fromCollection){ + public SortedListMetaObject(Collection fromCollection){ collection = new ArrayList<>(fromCollection); calculateImoCrossDependencies(); } + public Collection getCollection(){ + return collection; +} + public List sortFromDependencies() throws ExceptionDBGit { + if (listFromDependant == null) { + listFromDependant = createSortedList(false); + } + return listFromDependant; + + } + public List sortFromReferenced() throws ExceptionDBGit { + if (listFromFree == null) { + listFromFree = createSortedList(true); + } + return listFromFree; + } + private void calculateImoCrossDependencies(){ - Timestamp timestampBefore = new Timestamp(System.currentTimeMillis()); for(DBGitMetaType metaType : Sets.newHashSet(DBGitMetaType.DBGitTable, DBGitMetaType.DbGitFunction)){ - List objectsOfType = collection.stream().filter(x->x.getType().equals(metaType) ).collect(Collectors.toList()); + List objectsOfType = collection.stream() + .filter( x->x.getType().equals(metaType) ) + .collect(Collectors.toList()); + + Map realNamesToMetaNames = objectsOfType.stream().collect(Collectors.toMap( - x->x.getUnderlyingDbObject().getSchema() + "." + x.getUnderlyingDbObject().getName(), - IMetaObject::getName - ) - ); + x-> x.getUnderlyingDbObject().getSchema() + "." + x.getUnderlyingDbObject().getName(), + IMetaObject::getName + )); for(IMetaObject imo : objectsOfType){ if(imo.getType().equals(DBGitMetaType.DbGitFunction)){ DBSQLObject dbsql = (DBSQLObject) imo.getUnderlyingDbObject(); Set deps = realNamesToMetaNames.keySet().stream() - .filter( x -> dbsql.getSql().contains(x) && !(dbsql.getSchema()+"."+dbsql.getName()).equals(x) ) + .filter( x -> dbsql.getSql().contains(x) /*&& !(dbsql.getSchema()+"."+dbsql.getName()).equals(x)*/ ) .map(realNamesToMetaNames::get) .collect(Collectors.toSet()); dbsql.setDependencies(deps); @@ -50,88 +71,77 @@ private void calculateImoCrossDependencies(){ if(imo.getType().equals(DBGitMetaType.DBGitTable)){ DBTable dbTable = (DBTable) imo.getUnderlyingDbObject(); Set deps = realNamesToMetaNames.values().stream() - .filter( x -> dbTable.getDependencies().contains(x) && !x.equals(imo.getName()) ) - .collect(Collectors.toSet()); - dbTable.setDependencies(deps); + .filter( x -> dbTable.getDependencies().contains(x) /*&& !x.equals(imo.getName())*/ ) + .collect(Collectors.toSet()); + dbTable.getDependencies().addAll(deps); } } } - Timestamp timestampAfter = new Timestamp(System.currentTimeMillis()); - Long diff = timestampAfter.getTime() - timestampBefore.getTime(); - ConsoleWriter.detailsPrintlnGreen(DBGitLang.getInstance().getValue("general", "time").withParams(diff.toString())); - }; + } - public List sortFromDependant(){ - if (listFromDependant == null) { - listFromDependant = new ArrayList<>(); - Arrays.stream(DBGitMetaType.values()) - .sorted(Comparator.comparing(DBGitMetaType::getPriority).reversed()) - .forEach(tp -> { - - List objectsOfType = collection.stream().filter(x -> x.getType().equals(tp)).collect(Collectors.toList()); - if (!objectsOfType.isEmpty()) { - - if (tp.equals(DBGitMetaType.DBGitTable ) || (objectsOfType.get(0) instanceof MetaSql)) { - List objectsL0 = objectsOfType.stream().filter(x -> x.getUnderlyingDbObject().getDependencies().size() == 0).collect(Collectors.toList()); - - objectsOfType.removeAll(objectsL0); - while (!objectsOfType.isEmpty()) { - Set namesL0 = objectsL0.stream().map(IMetaObject::getName).collect(Collectors.toSet()); - List objectsL1 = objectsOfType - .stream() - .filter(x -> namesL0.containsAll(x.getUnderlyingDbObject().getDependencies())) - .sorted(imoDependenceComparator.reversed()) - .collect(Collectors.toList()); - objectsOfType.removeAll(objectsL1); - objectsL0.addAll(0, objectsL1); - } - listFromDependant.addAll(objectsL0); - } else { - listFromDependant.addAll(objectsOfType); - } + public List createSortedList(boolean isSortedFromFree) throws ExceptionDBGit { + List list = new ArrayList<>(); + Comparator typeComparator = isSortedFromFree + ? Comparator.comparing(DBGitMetaType::getPriority) + : Comparator.comparing(DBGitMetaType::getPriority).reversed(); + Comparator imoComparator = isSortedFromFree + ? imoDependenceComparator + : imoDependenceComparator.reversed(); + + List types = Arrays + .stream(DBGitMetaType.values()) + .sorted(typeComparator) + .collect(Collectors.toList()); + + for (DBGitMetaType tp : types) { + List objectsOfType = collection.stream().filter(x -> x.getType().equals(tp)).collect(Collectors.toList()); + if (!objectsOfType.isEmpty()) { + if (tp.equals(DBGitMetaType.DBGitTable) || objectsOfType.get(0) instanceof MetaSql) { + Set namesAllOfType = objectsOfType.stream().map(IMetaObject::getName).collect(Collectors.toSet()); + List objectsL0 = objectsOfType.stream() + .filter(x -> { + Set deps = x.getUnderlyingDbObject().getDependencies(); + return deps.size() == 0 || ( deps.size() == 1 && deps.contains(x.getName()) ); + }) + .collect(Collectors.toList()); + + objectsOfType.removeAll(objectsL0); + while (!objectsOfType.isEmpty()) { + Set namesL0 = objectsL0.stream().map(IMetaObject::getName).collect(Collectors.toSet()); + List objectsL1 = objectsOfType + .stream() + .filter(x -> { + Set actualDeps = new HashSet<>(x.getUnderlyingDbObject().getDependencies()); + actualDeps.retainAll(namesAllOfType); //only deps of same type + actualDeps.remove(x.getName()); + return namesL0.containsAll(actualDeps); + }) + .sorted(imoComparator) + .collect(Collectors.toList()); + if (objectsL1.isEmpty()) { + warnNotAdded(objectsOfType); + throw new ExceptionDBGit("infinite loop"); } - }); + objectsOfType.removeAll(objectsL1); + if(isSortedFromFree) { objectsL0.addAll(objectsL1); } + else { objectsL0.addAll(0, objectsL1); } + } + list.addAll(objectsL0); + } else { + list.addAll(objectsOfType); + } + } } - return listFromDependant; - - }; - public List sortFromFree(){ - if (listFromFree == null) { - listFromFree = new ArrayList<>(); - Arrays.stream(DBGitMetaType.values()) - .sorted(Comparator.comparing(DBGitMetaType::getPriority)) - .forEach(tp -> { - - List objectsOfType = collection.stream().filter(x -> x.getType().equals(tp)).collect(Collectors.toList()); - if (!objectsOfType.isEmpty()) { - - if (tp.equals(DBGitMetaType.DBGitTable) || objectsOfType.get(0) instanceof MetaSql) { - List objectsL0 = objectsOfType.stream().filter(x -> x.getUnderlyingDbObject().getDependencies().size() == 0).collect(Collectors.toList()); - - objectsOfType.removeAll(objectsL0); - while (!objectsOfType.isEmpty()) { - Set namesL0 = objectsL0.stream().map(IMetaObject::getName).collect(Collectors.toSet()); - List objectsL1 = objectsOfType - .stream() - .filter(x -> namesL0.containsAll(x.getUnderlyingDbObject().getDependencies())) - .sorted(imoDependenceComparator) - .collect(Collectors.toList()); - objectsOfType.removeAll(objectsL1); - objectsL0.addAll(objectsL1); - } - listFromFree.addAll(objectsL0); - } else { - listFromFree.addAll(objectsOfType); - } - } +// int i = 0; +// for(IMetaObject imo : list){ +// ConsoleWriter.printlnRed(MessageFormat.format("{0}. {1}", i++, imo.getName())); +// } + return list; + } - }); - } - return listFromFree; - }; public static Comparator imoTypeComparator = Comparator.comparing(x->x.getType().getPriority()); public static Comparator imoDependenceComparator = (o1, o2) -> { @@ -152,4 +162,13 @@ public List sortFromFree(){ return result; }; + public void warnNotAdded(List remained){ + ConsoleWriter.printlnRed(DBGitLang.getInstance() + .getValue("errors", "unsatisfiedDependencies") + , 1 + ); + + remained.forEach( x -> ConsoleWriter.printlnColor(x.getName(), Ansi.FColor.MAGENTA, 1) ); + } + } diff --git a/src/main/java/ru/fusionsoft/dbgit/meta/TreeMapMetaObject.java b/src/main/java/ru/fusionsoft/dbgit/meta/TreeMapMetaObject.java index ac1db18..d167b3d 100644 --- a/src/main/java/ru/fusionsoft/dbgit/meta/TreeMapMetaObject.java +++ b/src/main/java/ru/fusionsoft/dbgit/meta/TreeMapMetaObject.java @@ -36,11 +36,11 @@ public int compare(String nm1, String nm2) { } - public TreeMapMetaObject(List from){ + public TreeMapMetaObject(Collection from){ this(); this.putAll(from.stream().collect(Collectors.toMap(IMetaObject::getName, key->key))); } - + @Override public IMapMetaObject put(IMetaObject obj) { put(obj.getName(), obj); diff --git a/src/main/java/ru/fusionsoft/dbgit/mssql/DBAdapterMssql.java b/src/main/java/ru/fusionsoft/dbgit/mssql/DBAdapterMssql.java new file mode 100644 index 0000000..f33d99d --- /dev/null +++ b/src/main/java/ru/fusionsoft/dbgit/mssql/DBAdapterMssql.java @@ -0,0 +1,1398 @@ +package ru.fusionsoft.dbgit.mssql; + +import com.google.common.collect.ImmutableMap; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.slf4j.Logger; +import ru.fusionsoft.dbgit.adapters.DBAdapter; +import ru.fusionsoft.dbgit.adapters.IFactoryDBAdapterRestoteMetaData; +import ru.fusionsoft.dbgit.adapters.IFactoryDBBackupAdapter; +import ru.fusionsoft.dbgit.adapters.IFactoryDBConvertAdapter; +import ru.fusionsoft.dbgit.core.*; +import ru.fusionsoft.dbgit.core.db.DbType; +import ru.fusionsoft.dbgit.core.db.FieldType; +import ru.fusionsoft.dbgit.data_table.*; +import ru.fusionsoft.dbgit.dbobjects.*; +import ru.fusionsoft.dbgit.meta.IMapMetaObject; +import ru.fusionsoft.dbgit.meta.TreeMapMetaObject; +import ru.fusionsoft.dbgit.statement.StatementLogging; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; +import ru.fusionsoft.dbgit.utils.LoggerUtil; +import ru.fusionsoft.dbgit.utils.StringProperties; + +import java.sql.*; +import java.util.*; +import java.util.concurrent.TimeUnit; + + +public class DBAdapterMssql extends DBAdapter { + + public static final String DEFAULT_MAPPING_TYPE = "varchar"; + private static final HashSet systemSchemas = new HashSet<>(Arrays.asList( + "db_denydatawriter", + "db_datawriter", + "db_accessadmin", + "db_ddladmin", + "db_securityadmin", + "db_denydatareader", + "db_backupoperator", + "db_datareader", + "db_owner", + "sys", + "INFORMATION_SCHEMA" + )); + + //Stubs for MSSQL adapter, marked as "TODO Auto-generated method stub" + //And some unfinished implementations marked as "TODO MSSQL *" + + private Logger logger = LoggerUtil.getLogger(this.getClass()); + private FactoryDBAdapterRestoreMssql restoreFactory = new FactoryDBAdapterRestoreMssql(); + private FactoryDbConvertAdapterMssql convertFactory = new FactoryDbConvertAdapterMssql(); + private FactoryDBBackupAdapterMssql backupFactory = new FactoryDBBackupAdapterMssql(); + + @Override + public IFactoryDBAdapterRestoteMetaData getFactoryRestore() { + return restoreFactory; + } + + @Override + public void startUpdateDB() { + // TODO Auto-generated method stub + } + + @Override + public void endUpdateDB() { + // TODO Auto-generated method stub + } + + @Override + public IMapMetaObject loadCustomMetaObjects() { + return new TreeMapMetaObject(Collections.emptyList()); + } + + @Override + public Map getSchemes() { + final Map listScheme = new HashMap<>(); + try (ResultSet rs = getConnection().getMetaData().getSchemas()){ + + // made without query + // Statement stmt = connect.createStatement(); + // ResultSet rs = stmt.executeQuery(query); + while(rs.next()){ + final String name = rs.getString("TABLE_SCHEM"); + + // May also get catalog names that belong to scheme as "TABLE_CATALOG" + if(!systemSchemas.contains(name)) { + final DBSchema scheme = new DBSchema(name, new StringProperties(rs)); + listScheme.put(name, scheme); + } + } + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "schemes").toString(); + throw new ExceptionDBGitRunTime(msg, e); + } + + return listScheme; + } + + @Override + public Map getTableSpaces() { + final Map listTableSpace = new HashMap<>(); + final String query = "SELECT \n" + + "[SFG].name AS [File Group Name],\n" + + "[SFG].*,\n" + + "[SDB].name AS [Database Name],\n" + + "[F].name AS [File Name],\n" + + "[SDBF].name AS [Database File Name],\n" + + "[SDBF].physical_name\n" + + "INTO #fgroups\n" + + "FROM [master].sys.master_files AS [F]\n" + + "INNER JOIN sys.databases AS [SDB]\n" + + " ON [SDB].database_id = [F].database_id\n" + + "INNER JOIN sys.database_files AS [SDBF]\n" + + " ON [SDBF].[file_id] = [F].[file_id]\n" + + "INNER JOIN sys.filegroups AS [SFG]\n" + + " ON [sfg].data_space_id = [F].data_space_id\n" + + "SELECT \n" + + " [File Group Name],\n" + + " [data_space_id],\n" + + " [type],\n" + + " [type_desc],\n" + + " [is_default],\n" + + " [is_system],\n" + + " [is_read_only],\n" + + " [filegroup_guid],\n" + + " [log_filegroup_id],\n" + + " STUFF((\n" + + " SELECT DISTINCT ', ' + [Database Name] \n" + + " FROM #fgroups \n" + + " WHERE ([File Group Name] = Results.[File Group Name]) \n" + + " FOR XML PATH(''),TYPE).value('(./text())[1]','VARCHAR(MAX)')\n" + + " ,1,2,'') AS DatabaseNames, \n" + + " STUFF((\n" + + " SELECT DISTINCT ', ' + [Database File Name] \n" + + " FROM #fgroups \n" + + " WHERE ([File Group Name] = Results.[File Group Name]) \n" + + " FOR XML PATH(''),TYPE).value('(./text())[1]','VARCHAR(MAX)')\n" + + " ,1,2,'') AS DatabaseFileNames,\n" + + " STUFF((\n" + + " SELECT DISTINCT ', ' + [File Name] \n" + + " FROM #fgroups \n" + + " WHERE ([File Group Name] = Results.[File Group Name]) \n" + + " FOR XML PATH(''),TYPE).value('(./text())[1]','VARCHAR(MAX)')\n" + + " ,1,2,'') AS FileNames,\n" + + " STUFF((\n" + + " SELECT DISTINCT ', ' + [physical_name] \n" + + " FROM #fgroups \n" + + " WHERE ([File Group Name] = Results.[File Group Name]) \n" + + " FOR XML PATH(''),TYPE).value('(./text())[1]','VARCHAR(MAX)')\n" + + " ,1,2,'') AS PhysicalNames\n" + + "FROM #fgroups Results\n" + + "GROUP BY [File Group Name],[data_space_id],\n" + + " [type],\n" + + " [type_desc],\n" + + " [is_default],\n" + + " [is_system],\n" + + " [is_read_only],\n" + + " [filegroup_guid],\n" + + " [log_filegroup_id]\n" + + "DROP TABLE #fgroups\n"; + + + try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);){ + + while(rs.next()){ + final String name = rs.getString("File Group Name"); + final DBTableSpace dbTableSpace = new DBTableSpace(name, new StringProperties(rs)); + listTableSpace.put(name, dbTableSpace); + } + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "tablespace").toString(); + throw new ExceptionDBGitRunTime(msg, e); + } + + return listTableSpace; + } + + @Override + public Map getSequences(String schema) { + final Map listSequence = new HashMap(); + final String query = + "SELECT seq.*,\n" + + "TYPE_NAME(seq.system_type_id) as typeName,\n" + + "SCHEMA_NAME(seq.schema_id) as owner \n" + + "FROM sys.objects, sys.SEQUENCES seq \n" + + "WHERE sys.objects.object_id = seq.object_id \n" + + "AND SCHEMA_NAME(seq.schema_id) = '"+schema+"'"; + + try(Statement stmtValue = getConnection().createStatement(); ResultSet rs = stmtValue.executeQuery(query)){ + + while(rs.next()){ + final String ownerSeq = "dbo"; + final String nameSeq = rs.getString("name"); + final Long valueSeq = rs.getLong("current_value"); + final DBSequence seq = new DBSequence(nameSeq, new StringProperties(rs), schema, ownerSeq, Collections.emptySet(), valueSeq); + listSequence.put(nameSeq, seq); + } + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "seq").toString(); + throw new ExceptionDBGitRunTime(msg, e); + } + + return listSequence; + } + + @Override + public DBSequence getSequence(String schema, String name) { + final String query = + "SELECT seq.*,\n" + + "USER_NAME(objectproperty(seq.object_id,'OwnerId')) as owner,\n" + + "TYPE_NAME(seq.system_type_id) as typeName, " + + "SCHEMA_NAME(seq.schema_id) as schemaName " + + "FROM sys.objects, sys.SEQUENCES seq " + + "WHERE sys.objects.object_id = seq.object_id " + + "AND SCHEMA_NAME(seq.schema_id) = '"+schema+"' " + + "AND seq.name = '" + name + "'\n"; + + try(Statement stmtValue = getConnection().createStatement(); ResultSet rs = stmtValue.executeQuery(query)){ + + if(rs.next()){ + final String ownerSeq = "dbo"; + final String nameSeq = rs.getString("name"); + final Long valueSeq = rs.getLong("current_value"); + return new DBSequence(nameSeq, new StringProperties(rs), schema, ownerSeq, Collections.emptySet(), valueSeq); + } else { + final String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); + throw new ExceptionDBGitObjectNotFound(msg); + } + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "seq").toString(); + throw new ExceptionDBGitRunTime(msg, e); + } + } + + @Override + public Map getTables(String schema) { + final Map listTable = new HashMap<>(); + final String query = + "SELECT TABLE_NAME as 'name', TABLE_CATALOG as 'database', TABLE_SCHEMA as 'schema'\n" + + "FROM INFORMATION_SCHEMA.TABLES \n" + + "WHERE INFORMATION_SCHEMA.TABLES.TABLE_SCHEMA = '" + schema + "'\n" + + "AND INFORMATION_SCHEMA.TABLES.TABLE_TYPE = 'BASE TABLE'"; + + try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);) { + while(rs.next()){ + //TODO retrieve table comment + //TODO retrieve table owner + final String nameTable = rs.getString("name"); + final String ownerTable = ""; + final String commentTable = ""; + final StringProperties options = new StringProperties(rs); + final Set dependencies = rs.getArray("dependencies") != null + ? new HashSet<>(Arrays.asList((String[])rs.getArray("dependencies").getArray())) + : Collections.emptySet(); + + final DBTable table = new DBTable(nameTable, options, schema, ownerTable, dependencies, commentTable); + listTable.put(nameTable, table); + } + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "tables").toString(); + throw new ExceptionDBGitRunTime(msg, e); + } + return listTable; + } + + @Override + public DBTable getTable(String schema, String name) { + final String query = + "SELECT\n" + + " o.name tableName, t.TABLE_SCHEMA schemaName, t.TABLE_CATALOG catalogName,\n" + + " CASE WHEN o.principal_id is NOT NULL THEN (SELECT name FROM sys.database_principals dp WHERE dp.principal_id=o.principal_id)\n" + + " ELSE (SELECT dp.name FROM sys.database_principals dp,sys.schemas s WHERE s.schema_id=o.schema_id and s.principal_id=dp.principal_id)\n" + + " END as owner\n" + + "FROM sys.objects o, INFORMATION_SCHEMA.TABLES t\n" + + "WHERE o.type='U' AND o.name = t.TABLE_NAME AND t.TABLE_NAME = '"+name+"' AND t.TABLE_SCHEMA = '"+schema+"'"; + + try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);) { + if (rs.next()){ + //TODO retrieve table comment + //TODO retrieve table owner + final String nameTable = rs.getString("name"); + final String ownerTable = ""; + final String commentTable = ""; + final StringProperties options = new StringProperties(rs); + final Set dependencies = rs.getArray("dependencies") != null + ? new HashSet<>(Arrays.asList((String[])rs.getArray("dependencies").getArray())) + : Collections.emptySet(); + + return new DBTable(nameTable, options, schema, ownerTable, dependencies, commentTable); + } else { + final String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); + throw new ExceptionDBGitObjectNotFound(msg); + } + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "tables").toString(); + throw new ExceptionDBGitRunTime(msg, e); + } + } + + @Override + public Map getTableFields(String schema, String nameTable) { + final Map listField = new HashMap<>(); + final String query = + "SELECT DISTINCT\n" + + " c.TABLE_SCHEMA as schemaName,\n" + + " c.TABLE_NAME as tableName,\n" + + " c.COLUMN_NAME as columnName,\n" + + " c.ORDINAL_POSITION as columnOrder,\n" + + " c.DATA_TYPE as mssqlType,\n" + + " CASE WHEN lower(c.DATA_TYPE) in ('bigint', 'int', 'float', 'decimal', 'money', 'numeric', 'real', 'smallint', 'smallmoney', 'tinyint') then 'number' \n" + + " when lower(c.DATA_TYPE) in ('char','varchar','xml','nchar','nvarchar', 'uniqueidentifier') then 'string'\n" + + " when lower(c.DATA_TYPE) in ('bit') then 'boolean'\n" + + " when lower(c.DATA_TYPE) in ('datetime', 'smalldatetime', 'time') then 'date'\n" + + " when lower(c.DATA_TYPE) in ('text','ntext') then 'text'\n" + + " when lower(c.DATA_TYPE) in ('timestamp', 'binary', 'varbinary', 'geometry', 'geography') then 'binary'\n" + + " else 'native'\n" + + " end dbgitType,\n" + + " CASE WHEN 1 IN ( \n" + + " SELECT OBJECTPROPERTY(OBJECT_ID(CONSTRAINT_SCHEMA + '.' + QUOTENAME(CONSTRAINT_NAME)),'IsPrimaryKey')\n" + + " FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE\n" + + " WHERE c.COLUMN_NAME = COLUMN_NAME AND c.TABLE_NAME = TABLE_NAME\n" + + " )\n" + + " THEN 1 ELSE 0 END isPk,\n" + + " c.IS_NULLABLE as isNullable,\n" + + " c.NUMERIC_SCALE as scale,\n" + + " c.CHARACTER_MAXIMUM_LENGTH as length,\n" + + " CASE WHEN lower(c.DATA_TYPE) in ('char', 'nchar') then '1' else '0' end isFixed," + + " c.NUMERIC_PRECISION as precision\n" + + "FROM INFORMATION_SCHEMA.COLUMNS as c\n" + + "WHERE TABLE_SCHEMA = '" + schema + "' AND TABLE_NAME = '" + nameTable + "'"; + + try(Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);) { + + while(rs.next()){ + final DBTableField field = DBTableFieldFromRs(rs); + listField.put(field.getName(), field); + } + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "tableData").toString(); + throw new ExceptionDBGitRunTime(msg, e); + } + + return listField; + } + + private DBTableField DBTableFieldFromRs(ResultSet rs) throws SQLException { + final boolean isPrimaryKey = rs.getString("isPk").equals("1"); + final boolean isFixed = rs.getBoolean("isFixed"); + final boolean isNullable = rs.getBoolean("isNullable"); + final String columnName = rs.getString("columnName").toLowerCase(); + //TODO make find out column comment + final String columnDesc = ""; + //TODO make find out column default value + final String columnDefault = ""; + final String typeSQL = getFieldType(rs); + final FieldType typeUniversal = FieldType.fromString(rs.getString("dbgitType").toUpperCase()); + final int length = rs.getInt("length"); + final int scale = rs.getInt("scale"); + final int precision = rs.getInt("precision"); + final int order = rs.getInt("order"); + + return new DBTableField( + columnName, + columnDesc == null ? "" : columnDesc, + isPrimaryKey, isNullable, + typeSQL, typeUniversal, order, + columnDefault == null ? "" : columnDefault, + length, precision, scale, isFixed + ); + + } + + protected String getFieldType(ResultSet rs) throws SQLException { + + final StringBuilder type = new StringBuilder(); + final Integer max_length = rs.getInt("length"); + final String mssqlType = rs.getString("mssqlType"); + final boolean isNotNull = rs.getString("isNullable").equals("NO"); + + type.append(mssqlType); + if (!rs.wasNull()) { + type.append("("+max_length.toString()+")"); + } + if (isNotNull){ + type.append(" NOT NULL"); + } + + return type.toString(); + + } + + public Map getIndexesWithPks(String schema, String nameTable) { + final Map indexes = new HashMap<>(); + final String query = + " SELECT DB_NAME() AS databaseName,\n" + + " sc.name as schemaName, \n" + + " t.name AS tableName,\n" + + " col.name as columnName,\n" + + " si.name AS indexName,\n" + + " si.is_primary_key isPk," + + " si.index_id as indexId,\n" + + " si.type_desc as typeName, \n" + + " CASE si.index_id WHEN 0 THEN NULL\n" + + " ELSE \n" + + " CASE is_primary_key WHEN 1 THEN\n" + + " N'ALTER TABLE ' + QUOTENAME(sc.name) + N'.' + QUOTENAME(t.name) + N' ADD CONSTRAINT ' + QUOTENAME(si.name) + N' PRIMARY KEY ' +\n" + + " CASE WHEN si.index_id > 1 THEN N'NON' ELSE N'' END + N'CLUSTERED '\n" + + " ELSE N'CREATE ' + \n" + + " CASE WHEN si.is_unique = 1 then N'UNIQUE ' ELSE N'' END +\n" + + " CASE WHEN si.index_id > 1 THEN N'NON' ELSE N'' END + N'CLUSTERED ' +\n" + + " N'INDEX ' + QUOTENAME(si.name) + N' ON ' + QUOTENAME(sc.name) + N'.' + QUOTENAME(t.name) + N' '\n" + + " END +\n" + + " /* key def */ N'(' + key_definition + N')' +\n" + + " /* includes */ CASE WHEN include_definition IS NOT NULL THEN \n" + + " N' INCLUDE (' + include_definition + N')'\n" + + " ELSE N''\n" + + " END +\n" + + " /* filters */ CASE WHEN filter_definition IS NOT NULL THEN \n" + + " N' WHERE ' + filter_definition ELSE N''\n" + + " END +\n" + + " /* with clause - compression goes here */\n" + + " CASE WHEN row_compression_partition_list IS NOT NULL OR page_compression_partition_list IS NOT NULL \n" + + " THEN N' WITH (' +\n" + + " CASE WHEN row_compression_partition_list IS NOT NULL THEN\n" + + " N'DATA_COMPRESSION = ROW ' + CASE WHEN psc.name IS NULL THEN N'' ELSE + N' ON PARTITIONS (' + row_compression_partition_list + N')' END\n" + + " ELSE N'' END +\n" + + " CASE WHEN row_compression_partition_list IS NOT NULL AND page_compression_partition_list IS NOT NULL THEN N', ' ELSE N'' END +\n" + + " CASE WHEN page_compression_partition_list IS NOT NULL THEN\n" + + " N'DATA_COMPRESSION = PAGE ' + CASE WHEN psc.name IS NULL THEN N'' ELSE + N' ON PARTITIONS (' + page_compression_partition_list + N')' END\n" + + " ELSE N'' END\n" + + " + N')'\n" + + " ELSE N''\n" + + " END +\n" + + " ' ON ' + CASE WHEN psc.name is null \n" + + " THEN ISNULL(QUOTENAME(fg.name),N'')\n" + + " ELSE psc.name + N' (' + partitioning_column.column_name + N')' \n" + + " END\n" + + " + N';'\n" + + " END AS ddl,\n" + + " si.has_filter,\n" + + " si.is_unique,\n" + + " ISNULL(pf.name, NULL) AS partition_function,\n" + + " ISNULL(psc.name, fg.name) AS partition_scheme_or_filegroup\n" + + "FROM sys.indexes AS si \n" + + "JOIN sys.index_columns ic ON si.object_id = ic.object_id and si.index_id = ic.index_id \n" + + "JOIN sys.columns col ON ic.object_id = col.object_id and ic.column_id = col.column_id \n" + + "JOIN sys.tables AS t ON si.object_id=t.object_id\n" + + "JOIN sys.schemas AS sc ON t.schema_id=sc.schema_id\n" + + "LEFT JOIN sys.dm_db_index_usage_stats AS stat ON \n" + + " stat.database_id = DB_ID() \n" + + " and si.object_id=stat.object_id \n" + + " and si.index_id=stat.index_id\n" + + "LEFT JOIN sys.partition_schemes AS psc ON si.data_space_id=psc.data_space_id\n" + + "LEFT JOIN sys.partition_functions AS pf ON psc.function_id=pf.function_id\n" + + "LEFT JOIN sys.filegroups AS fg ON si.data_space_id=fg.data_space_id\n" + + "OUTER APPLY ( SELECT STUFF (\n" + + " (SELECT N', ' + QUOTENAME(c.name) +\n" + + " CASE ic.is_descending_key WHEN 1 then N' DESC' ELSE N'' END\n" + + " FROM sys.index_columns AS ic \n" + + " JOIN sys.columns AS c ON \n" + + " ic.column_id=c.column_id \n" + + " and ic.object_id=c.object_id\n" + + " WHERE ic.object_id = si.object_id\n" + + " and ic.index_id=si.index_id\n" + + " and ic.key_ordinal > 0\n" + + " ORDER BY ic.key_ordinal FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,2,'')) AS keys ( key_definition )\n" + + "OUTER APPLY (\n" + + " SELECT MAX(QUOTENAME(c.name)) AS column_name\n" + + " FROM sys.index_columns AS ic \n" + + " JOIN sys.columns AS c ON \n" + + " ic.column_id=c.column_id \n" + + " and ic.object_id=c.object_id\n" + + " WHERE ic.object_id = si.object_id\n" + + " and ic.index_id=si.index_id\n" + + " and ic.partition_ordinal = 1) AS partitioning_column\n" + + "OUTER APPLY ( SELECT STUFF (\n" + + " (SELECT N', ' + QUOTENAME(c.name)\n" + + " FROM sys.index_columns AS ic \n" + + " JOIN sys.columns AS c ON \n" + + " ic.column_id=c.column_id \n" + + " and ic.object_id=c.object_id\n" + + " WHERE ic.object_id = si.object_id\n" + + " and ic.index_id=si.index_id\n" + + " and ic.is_included_column = 1\n" + + " ORDER BY c.name FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,2,'')) AS includes ( include_definition )\n" + + "OUTER APPLY ( SELECT STUFF (\n" + + " (SELECT N', ' + CAST(p.partition_number AS VARCHAR(32))\n" + + " FROM sys.partitions AS p\n" + + " WHERE p.object_id = si.object_id\n" + + " and p.index_id=si.index_id\n" + + " and p.data_compression = 1\n" + + " ORDER BY p.partition_number FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,2,'')) AS row_compression_clause ( row_compression_partition_list )\n" + + "OUTER APPLY ( SELECT STUFF (\n" + + " (SELECT N', ' + CAST(p.partition_number AS VARCHAR(32))\n" + + " FROM sys.partitions AS p\n" + + " WHERE p.object_id = si.object_id\n" + + " and p.index_id=si.index_id\n" + + " and p.data_compression = 2\n" + + " ORDER BY p.partition_number FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,2,'')) AS page_compression_clause ( page_compression_partition_list )\n" + + "WHERE si.type IN (1,2) /* clustered, nonclustered */\n" + +// "AND si.is_primary_key = 0 /* no PKs */\n" + + "AND si.is_hypothetical = 0 /* bugged feature, always better to delete, no need to store and reconstruct them */\n" + + "AND upper(t.name) = upper('" + nameTable + "') AND upper(sc.name) = upper('" + schema + "')" + + "OPTION (RECOMPILE);"; + + try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);){ + + while(rs.next()){ + final String name = rs.getString("indexName"); + final String owner = rs.getString("owner"); + final String sql = rs.getString("ddl"); + final DBIndex index = new DBIndex(name, new StringProperties(rs), schema, owner, Collections.emptySet(), sql); + + indexes.put(index.getName(), index); + } + + return indexes; + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "indexes").toString(); + throw new ExceptionDBGitRunTime(msg, e); + } + } + + @Override + public Map getIndexes(String schema, String nameTable){ + final Map indexes = getIndexesWithPks(schema, nameTable); + + indexes.values().removeIf(x->x.getOptions().getChildren().get("ispk").getData().equals("1")); + return indexes; + } + + @Override + public Map getConstraints(String schema, String nameTable) { + final Map constraints = new HashMap<>(); + final ArrayList queries = new ArrayList<>(); + //TODO [] in object names + //check + queries.add( + "SELECT sc.name as schemaName, t.name as tableName, col.name as columnName, c.name as constraintName, c.name as indexName, c.type_desc as constraintType, \n" + + "'ALTER TABLE ' + sc.name + '.' + t.name + ' ADD CONSTRAINT ' + c.name + ' CHECK ' + c.definition + ';' as ddl\n" + + "FROM sys.check_constraints c\n" + + "JOIN sys.tables t ON c.parent_object_id = t.object_id \n" + + "LEFT OUTER JOIN sys.columns col on col.column_id = c.parent_column_id AND col.object_id = c.parent_object_id\n" + + "JOIN sys.schemas AS sc ON t.schema_id=sc.schema_id \n" + + "WHERE t.name = :name AND sc.name = :schema"); + //default + queries.add( + "SELECT sc.name AS schemaName, t.name AS tableName, col.name AS columnName, c.name AS constraintName, c.type_desc AS constraintType, \n" + + "'ALTER TABLE ' + sc.name + '.' + t.name + ' ADD CONSTRAINT ' + c.name+ ' DEFAULT ' \n" + + " + CASE WHEN ISNUMERIC(ic.COLUMN_DEFAULT) = 1 \n" + + " THEN TRY_CONVERT(nvarchar, TRY_CONVERT(numeric, ic.COLUMN_DEFAULT))\n" + + " ELSE '' + ic.COLUMN_DEFAULT + '' END\n" + + " + ' FOR [' + col.name + '];' AS ddl\n" + + "FROM sys.default_constraints c\n" + + "JOIN sys.tables t ON c.parent_object_id = t.object_id \n" + + "JOIN sys.columns col ON col.default_object_id = c.object_id\n" + + "JOIN sys.schemas AS sc ON t.schema_id=sc.schema_id \n" + + "JOIN INFORMATION_SCHEMA.COLUMNS ic on t.name = ic.TABLE_NAME AND col.name = ic.COLUMN_NAME \n" + + "WHERE t.name = :name AND sc.name = :schema\n" + ); + //unique + queries.add( + "SELECT TC.TABLE_SCHEMA AS schemaName, TC.TABLE_NAME AS tableName, CC.Column_Name AS columnName, TC.Constraint_Name AS constraintName, TC.CONSTRAINT_TYPE AS constraintType,\n" + + "'ALTER TABLE ' + TC.TABLE_SCHEMA + '.' + TC.TABLE_NAME + ' ADD CONSTRAINT ' + TC.CONSTRAINT_NAME + ' UNIQUE NONCLUSTERED ([' + CC.COLUMN_NAME + ']);' AS ddl\n" + + "FROM INFORMATION_SCHEMA.table_constraints TC\n" + + "INNER JOIN INFORMATION_SCHEMA.constraint_column_usage CC on TC.Constraint_Name = CC.Constraint_Name\n" + + "WHERE TC.constraint_type = 'Unique' AND TC.TABLE_NAME = :name AND TC.TABLE_SCHEMA = :schema ---- PARAMETER 1,2\n" + ); + //foreign + queries.add( + "SELECT ss.name as schemaName, t.name as tableName, sc.name as columnName, o.name as constraintName, o.type_desc as constraintType, refss.name as refSchemaName, refst.name as refTableName, refsc.name as refColumnName, " + + "'ALTER TABLE ' + ss.name + '.' + t.name + ' ADD CONSTRAINT ' + o.name + ' FOREIGN KEY ('+ sc.name + ') references ' + refss.name + '.' + refst.name + '(' + refsc.name + ');' as ddl\n" + + "FROM sys.foreign_key_columns c\n" + + "JOIN sys.objects o ON c.constraint_object_id = o.object_id\n" + + "LEFT OUTER JOIN sys.tables t on t.object_id = c.parent_object_id \n" + + "LEFT OUTER JOIN sys.schemas ss on ss.schema_id = o.schema_id \n" + + "LEFT OUTER JOIN sys.columns sc on sc.object_id = c.parent_object_id AND sc.column_id = c.parent_column_id\n" + + "LEFT OUTER JOIN sys.tables refst on refst.object_id = c.referenced_object_id\n" + + "LEFT OUTER JOIN sys.schemas refss on refss.schema_id = refst.schema_id\n" + + "LEFT OUTER JOIN sys.columns refsc on refsc.object_id = c.referenced_object_id AND refsc.column_id = c.referenced_column_id \n" + + "WHERE t.name = :name AND ss.name = :schema\n" + ); + + + final Iterator it = queries.iterator(); + while (it.hasNext()) { + final String query = it.next(); + try ( + PreparedStatement stmt = preparedStatement(getConnection(), query, ImmutableMap.of("name", nameTable, "schema" , schema)); + ResultSet rs = stmt.executeQuery(query); + ){ + + while (rs.next()) { + final String name = rs.getString("constraintName"); + final String type = rs.getString("constraintType"); + final String sql = rs.getString("ddl"); + final String owner = schema; + + final DBConstraint con = new DBConstraint(name, new StringProperties(rs), schema, owner, Collections.emptySet(), sql, type); + constraints.put(con.getName(), con); + } + } catch (Exception ex){ + final String msg = lang.getValue("errors", "adapter", "constraints").toString(); + throw new ExceptionDBGitRunTime(msg, ex); + } + } + + //primary keys + final Map indexes = getIndexesWithPks(schema, nameTable); + indexes.values().removeIf(x->x.getOptions().getChildren().get("ispk").getData().equals("0")); + + for( DBIndex pki : indexes.values() ){ + final String constraintType = pki.getOptions().getChildren().get("typename").getData(); + final DBConstraint pkc = new DBConstraint( + pki.getName(), + pki.getOptions(), + pki.getSchema(), + pki.getOwner(), + new HashSet<>(pki.getDependencies()), + pki.getSql(), + constraintType + ); + pkc.setOptions(pki.getOptions()); + constraints.put(pkc.getName(), pkc); + } + + return constraints; + + } + + @Override + public Map getViews(String schema) { + final Map listView = new HashMap(); + final String query = + "SELECT \n" + + " sp.name as ownerName, sp.type_desc as ownerType, ss.name AS schemaName, sv.name AS viewName, sm.definition as ddl, \n" + + " sv.type_desc as typeName, sm.uses_ansi_nulls, sm.uses_quoted_identifier, sm.is_schema_bound, \n" + + " OBJECTPROPERTYEX(sv.object_id,'IsIndexable') AS IsIndexable,\n" + + " OBJECTPROPERTYEX(sv.object_id,'IsIndexed') AS IsIndexed\n" + + "FROM sys.views sv\n" + + "JOIN sys.schemas ss ON sv.schema_id = ss.schema_id\n" + + "LEFT OUTER JOIN sys.sql_modules sm on sv.object_id = sm.object_id\n" + + "LEFT OUTER JOIN sys.database_principals sp on sv.principal_id = sp.principal_id"; + + try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);){ + + while(rs.next()){ + final String name = rs.getString("viewName"); + final String schemaName = rs.getString("schemaName"); + final String owner = rs.getString("ownerName"); + final String sql = rs.getString("ddl"); + + final DBView view = new DBView(name, new StringProperties(rs), schema, owner, Collections.emptySet(), sql); + listView.put(name, view); + } + return listView; + + } catch(Exception e) { + final DBGitLang msg = lang.getValue("errors", "adapter", "views"); + throw new ExceptionDBGitRunTime(msg, e); + } + } + + @Override + public DBView getView(String schema, String name) { + //TODO single-version query with ExceptionDBGitNotFound + try { + return getViews(schema).get(name); + } catch(Exception e) { + final DBGitLang msg = lang.getValue("errors", "adapter", "views"); + throw new ExceptionDBGitRunTime(msg, e); + } + } + + @Override + public Map getPackages(String schema) { + // No such implementation in MSSQL + return Collections.emptyMap(); + } + + @Override + public DBPackage getPackage(String schema, String name) { + // No such implementation in MSSQL + throw new ExceptionDBGitRunTime(new ExceptionDBGitObjectNotFound("cannot get packages on mssql")); + } + + @Override + public Map getProcedures(String schema) { + final Map listProcedure = new HashMap(); + final String query = + "SELECT s.name schemaName, o.name procedureName, o.type_desc as typeName, definition ddl, USER_NAME(so.uid) AS owner \n" + + "FROM sys.sql_modules m\n" + + "JOIN sys.procedures p ON m.object_id = p.object_id\n" + + "JOIN sys.objects o \n" + + " ON o.object_id = p.object_id \n" + + " AND Left(o.name, 3) NOT IN ('sp_', 'xp_', 'ms_') \n" + + "JOIN sys.schemas s ON s.schema_id = o.schema_id\n" + + "JOIN sysobjects so on o.object_id = so.id\n" + + "WHERE s.name = '" + schema + "'\n"; + + try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);){ + while(rs.next()){ + final String name = rs.getString("procedureName"); + final String owner = rs.getString("owner"); + final String sql = rs.getString("ddl"); + final StringProperties options = new StringProperties(rs); + final DBProcedure proc = new DBProcedure(name, options, schema, owner, Collections.emptySet(), sql); + listProcedure.put(name, proc); + } + }catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "prc").toString(); + throw new ExceptionDBGitRunTime(msg, e); + } + return listProcedure; + } + + @Override + public DBProcedure getProcedure(String schema, String name) { + final String query = + "SELECT s.name schemaName, o.name procedureName, o.type_desc as typeName, definition ddl, USER_NAME(so.uid) AS owner \n" + + "FROM sys.sql_modules m\n" + + "JOIN sys.procedures p ON m.object_id = p.object_id\n" + + "JOIN sys.objects o \n" + + " ON o.object_id = p.object_id \n" + + " AND Left(o.name, 3) NOT IN ('sp_', 'xp_', 'ms_') -- filter out system ones\n" + + "JOIN sys.schemas s ON s.schema_id = o.schema_id\n" + + "JOIN sysobjects so on o.object_id = so.id \n" + + "WHERE s.name = '" + schema + "' AND o.name = '" + name + "'"; + + try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);){ + + if (!rs.next()) throw new ExceptionDBGitObjectNotFound(""); + + final String owner = rs.getString("owner"); + final String procedureName = rs.getString("procedureName"); + final String sql = rs.getString("ddl"); + final StringProperties options = new StringProperties(rs); + + return new DBProcedure(procedureName, options, schema, owner, Collections.emptySet(), sql); + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "prc").toString(); + throw new ExceptionDBGitRunTime(msg, e); + } + } + + @Override + public Map getFunctions(String schema) { + final Map listFunction = new HashMap<>(); + final String query = + "SELECT ss.name schemaName, o.name functionName, type_desc typeName, definition ddl, USER_NAME(so.uid) owner \n" + + "FROM sys.sql_modules m \n" + + "INNER JOIN sys.objects o ON m.object_id = o.object_id\n" + + "INNER JOIN sysobjects so ON m.object_id = so.id\n" + + "INNER JOIN sys.schemas ss ON ss.schema_id = o.schema_id\n" + + "WHERE type_desc like '%function%' AND ss.name = '" + schema + "'\n"; + + try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);){ + + while(rs.next()){ + + final String name = rs.getString("functionName"); + final String owner = rs.getString("owner"); + final String sql = rs.getString("ddl"); + final StringProperties options = new StringProperties(rs); + + final DBFunction func = new DBFunction(name, options, schema, owner, Collections.emptySet(), sql); + listFunction.put(name, func); + } + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "fnc").toString(); + throw new ExceptionDBGitRunTime(msg, e); + } + return listFunction; + } + + @Override + public DBFunction getFunction(String schema, String name) { + final String query = + "SELECT ss.name schemaName, o.name functionName, type_desc typeName, definition ddl, USER_NAME(so.uid) owner \n" + + "FROM sys.sql_modules m \n" + + "INNER JOIN sys.objects o ON m.object_id = o.object_id\n" + + "INNER JOIN sysobjects so ON m.object_id = so.id\n" + + "INNER JOIN sys.schemas ss ON ss.schema_id = o.schema_id\n" + + "WHERE type_desc like '%function%' AND ss.name = '" + schema + "' AND o.name = '" + name + "'\n"; + + try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);){ + + if (!rs.next()) throw new ExceptionDBGitObjectNotFound(""); + + final String functionName = rs.getString("functionName"); + final String owner = rs.getString("owner"); + final String sql = rs.getString("ddl"); + final StringProperties options = new StringProperties(rs); + + return new DBFunction(functionName, options, schema, owner, Collections.emptySet(), sql); + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "fnc").toString(); + throw new ExceptionDBGitRunTime(msg, e); + } + } + + //TODO Discuss scenario when we get an encrypted TRIGGER, IMO display a warning, + // it is not possible to get definition of an encrypted trigger + + public Map getTriggers(String schema) { + final Map listTrigger = new HashMap(); + final String query = + "SELECT \n" + + " s.name schemaName, \n" + + " o.name triggerName, \n" + + " USER_NAME(o.uid) owner, \n" + + " OBJECT_NAME(parent_obj) tableName, \n" + + " m.definition as ddl, \n" + + " OBJECTPROPERTY(id, 'IsEncrypted') AS encrypted \n" + + "FROM sysobjects o\n" + + "INNER JOIN sys.tables t ON o.parent_obj = t.object_id \n" + + "INNER JOIN sys.schemas s ON t.schema_id = s.schema_id \n" + + "INNER JOIN sys.sql_modules m ON m.object_id = o.id\n" + + "WHERE o.type = 'TR' AND s.name = '" + schema + "'\n"; + + try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);){ + + while(rs.next()){ + final String name = rs.getString("triggerName"); + final String owner = rs.getString("owner"); + final String sql = rs.getString("ddl"); + final StringProperties options = new StringProperties(rs); + + DBTrigger trigger = new DBTrigger(name, options, schema, owner, Collections.emptySet(), sql); + listTrigger.put(name, trigger); + } + return listTrigger; + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "triggers").toString(); + throw new ExceptionDBGitRunTime(msg, e); + } + } + + public DBTrigger getTrigger(String schema, String name) { + final String query = + "SELECT \n" + + " s.name schemaName, \n" + + " o.name triggerName, \n" + + " USER_NAME(o.uid) owner, \n" + + " OBJECT_NAME(parent_obj) tableName, \n" + + " m.definition as ddl, \n" + + " OBJECTPROPERTY(id, 'IsEncrypted') AS encrypted \n" + + "FROM sysobjects o\n" + + "INNER JOIN sys.tables t ON o.parent_obj = t.object_id \n" + + "INNER JOIN sys.schemas s ON t.schema_id = s.schema_id \n" + + "INNER JOIN sys.sql_modules m ON m.object_id = o.id\n" + + "WHERE o.type = 'TR' AND s.name = '" + schema + "' AND o.name = '" + name + "'\n"; + + try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);){ + + if(!rs.next()) throw new ExceptionDBGitObjectNotFound(""); + + final String tname = rs.getString("triggerName"); + final String owner = rs.getString("owner"); + final String sql = rs.getString("ddl"); + final StringProperties options = new StringProperties(rs); + + return new DBTrigger(name, options, schema, owner, Collections.emptySet(), sql); + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "triggers").toString(); + throw new ExceptionDBGitRunTime(msg, e); + } + } + + @Override + public DBTableData getTableData(String schema, String nameTable) { + final String dataQuery = "SELECT * FROM [" + schema + "].[" + nameTable + "]"; + + final int maxRowsCount = DBGitConfig.getInstance().getInteger( + "core", "MAX_ROW_COUNT_FETCH", + DBGitConfig.getInstance().getIntegerGlobal("core", "MAX_ROW_COUNT_FETCH", MAX_ROW_COUNT_FETCH) + ); + + final boolean isLimitedFetch = DBGitConfig.getInstance().getBoolean( + "core", "LIMIT_FETCH", + DBGitConfig.getInstance().getBooleanGlobal("core", "LIMIT_FETCH", true) + ); + + try{ + + if (isLimitedFetch) { + final String rowsCountQuery = + "SELECT COALESCE(SUM(PART.rows), 0) AS rowsCount\n" + + "FROM sys.tables TBL\n" + + "INNER JOIN sys.partitions PART ON TBL.object_id = PART.object_id\n" + + "INNER JOIN sys.indexes IDX ON PART.object_id = IDX.object_id AND PART.index_id = IDX.index_id\n" + + "INNER JOIN sys.schemas S ON S.schema_id = TBL.schema_id\n" + + "WHERE TBL.name = '"+nameTable+"' AND S.name = '"+schema+"' AND IDX.index_id < 2\n" + + "GROUP BY TBL.object_id, TBL.name"; + + try( + Statement st = getConnection().createStatement(); + ResultSet rs = st.executeQuery(rowsCountQuery); + ){ + if(!rs.next()) throw new ExceptionDBGitRunTime("rows coubt resultset is empty"); + if (rs.getInt("rowsCount") > maxRowsCount) { + return new DBTableData(DBTableData.ERROR_LIMIT_ROWS); + } + } + + } + + return new DBTableData(getConnection(), dataQuery); + + } catch (Exception e){ + final String msg = DBGitLang.getInstance().getValue("errors", "adapter", "tableData").toString(); + throw new ExceptionDBGitRunTime(msg, e); + } + + } + + @Override + public DBTableData getTableDataPortion(String schema, String nameTable, int portionIndex, int tryNumber) { + + final int portionSize = DBGitConfig.getInstance().getInteger( "core", "PORTION_SIZE", + DBGitConfig.getInstance().getIntegerGlobal("core", "PORTION_SIZE", 1000) + ); + + final int dataOffset = portionSize * portionIndex; + final String dataQuery = + "SELECT * " + + "FROM " + schema + "." + nameTable + " " + + "ORDER BY (SELECT NULL) " + + "OFFSET " + dataOffset + " ROWS " + + "FETCH NEXT " + portionSize + " ROWS ONLY "; + + try { + + /* For version <= SQL Server 2005 + + int begin = 1 + portionSize*portionIndex; + int end = portionSize + portionSize*portionIndex; + + ResultSet rs = st.executeQuery( + "SELECT * FROM (" + + " SELECT *, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) rownum" + + " FROM dbo.Product" + + ") t" + + "WHERE rownum BETWEEN " + begin + " AND "+ end + ); + */ + + return new DBTableData(getConnection(), dataQuery); + + } catch (Exception e) { + + final int maxTriesCount = DBGitConfig.getInstance().getInteger("core", "TRY_COUNT", DBGitConfig.getInstance().getIntegerGlobal("core", "TRY_COUNT", 1000)); + final int tryDelay = DBGitConfig.getInstance().getInteger("core", "TRY_DELAY", DBGitConfig.getInstance().getIntegerGlobal("core", "TRY_DELAY", 1000)); + + ConsoleWriter.println(e.getLocalizedMessage(), messageLevel); + ConsoleWriter.detailsPrintln(ExceptionUtils.getStackTrace(e), messageLevel); + logger.error(lang.getValue("errors", "adapter", "tableData").toString(), e); + + if (tryNumber <= maxTriesCount) { + + final String waitMessage = DBGitLang.getInstance() + .getValue("errors", "dataTable", "wait") + .withParams(String.valueOf(tryDelay)); + + final String tryAgainMessage = DBGitLang.getInstance() + .getValue("errors", "dataTable", "tryAgain") + .withParams(String.valueOf(tryNumber)); + + ConsoleWriter.println(waitMessage, messageLevel); + try { TimeUnit.SECONDS.sleep(tryDelay); } catch (InterruptedException e1) { + throw new ExceptionDBGitRunTime(e1.getMessage()); + } + + ConsoleWriter.println(tryAgainMessage, messageLevel); + return getTableDataPortion(schema, nameTable, portionIndex, tryNumber++); + + } else { + final String msg = DBGitLang.getInstance().getValue("errors", "adapter", "tableData").toString(); + throw new ExceptionDBGitRunTime(msg, e); + } + } + } + + @Override + public Map getUsers() { + final Map listUser = new HashMap(); + final String query = + "DECLARE @crlf VARCHAR(2)\n" + + "SELECT \n" + + " u.name userName, sp.name loginName, sp.default_database_name databaseName, dp.default_schema_name as schemaName,\n" + + " CASE WHEN sp.is_disabled IS NULL THEN 1 ELSE sp.is_disabled END isDisabledLogin,\n" + + " CASE WHEN sp.name IS NOT NULL THEN 'CREATE LOGIN [' + sp.name + '] WITH PASSWORD = ' \n" + + " + UPPER(master.dbo.fn_varbintohexstr (CAST(LOGINPROPERTY(sp.name,'PASSWORDHASH') as VARBINARY (256)))) + ' HASHED; ' ELSE '' END \n" + + " + CASE WHEN sp.is_disabled IS NOT NULL AND sp.is_disabled = 0 AND dr.permission_name IS NOT NULL THEN 'GRANT CONNECT SQL TO [' + sp.name + ']; ' ELSE '' END \n" + + " + 'CREATE USER [' + u.name + '] ' \n" + + " + CASE WHEN sp.name IS NOT NULL THEN 'FOR LOGIN [' + sp.name + ']' ELSE '' END\n" + + " + CASE WHEN dp.default_schema_name IS NOT NULL THEN ' WITH DEFAULT_SCHEMA = [' + dp.default_schema_name + ']' ELSE '' END + ';' \n" + + " AS ddl, \n" + + " UPPER(master.dbo.fn_varbintohexstr (CAST(LOGINPROPERTY(sp.name,'PASSWORDHASH') as VARBINARY (256)))) passwordHash\n" + + "FROM sys.sysusers u \n" + + "INNER JOIN sys.database_principals dp ON dp.sid = u.sid\n" + + "LEFT OUTER JOIN sys.server_principals sp ON sp.sid = u.sid\n" + + "LEFT OUTER JOIN sys.database_permissions dr ON dr.grantee_principal_id = dp.principal_id AND dr.permission_name = 'CONNECT'\n" + + "WHERE dp.type_desc = 'SQL_USER' AND u.name NOT IN ('dbo','guest') AND u.name NOT LIKE '##MS%'"; + + try ( + Statement stmt = getConnection().createStatement(); + ResultSet rs = stmt.executeQuery(query); + ){ + + while(rs.next()){ + final String name = rs.getString(1); + final StringProperties options = new StringProperties(rs); + + DBUser user = new DBUser(name, options); + listUser.put(name, user); + } + + } catch(Exception e) { + final DBGitLang msg = lang.getValue("errors", "adapter", "users"); + throw new ExceptionDBGitRunTime(msg, e); + } + + return listUser; + } + + @Override + public Map getRoles() { + final Map listRole = new HashMap(); + final String usersQuery = + "SELECT \n" + + " dp.name roleName, dp.is_fixed_role isFixedRole,\n" + + " CASE WHEN dp.is_fixed_role = 0 AND dp.name != 'public' THEN dbo.GetRoleDDL(dp.name) ELSE '' " + + " END roleDDL,\n" + + " dbo.GetRoleMembersDDL(dp.name) membersDDL,\n" + + " CASE WHEN dp.is_fixed_role = 1 OR dp.name = 'public'" + + " THEN dbo.GetRoleMembersDDL(dp.name) " + + " ELSE dbo.GetRoleDDL(dp.name) + dbo.GetRoleMembersDDL(dp.name) " + + " END ddl\n" + + "FROM sys.database_principals dp\n" + + "WHERE dp.type = 'R'\n" + + "DROP FUNCTION GetRoleDDL\n" + + "DROP FUNCTION GetRoleMembersDDL"; + + List setupQueries = Arrays.asList( + "IF OBJECT_ID(N'GetRoleDDL', N'FN') IS NOT NULL DROP FUNCTION GetRoleDDL\n" + + "IF OBJECT_ID(N'GetRoleMembersDDL', N'FN') IS NOT NULL DROP FUNCTION GetRoleMembersDDL\n" + , + "CREATE FUNCTION dbo.GetRoleDDL(@roleName VARCHAR(255))\n" + + "RETURNS VARCHAR(MAX)\n" + + "BEGIN\n" + + " -- Script out the Role\n" + + " DECLARE @roleDesc VARCHAR(MAX)\n" + + " SET @roleDesc = 'CREATE ROLE [' + @roleName + '];'\n" + + " DECLARE @rolePerm VARCHAR(MAX)\n" + + " SET @rolePerm = ''\n" + + " SELECT @rolePerm = @rolePerm +\n" + + " CASE dp.state\n" + + " WHEN 'D' THEN 'DENY '\n" + + " WHEN 'G' THEN 'GRANT '\n" + + " WHEN 'R' THEN 'REVOKE '\n" + + " WHEN 'W' THEN 'GRANT '\n" + + " END + \n" + + " dp.permission_name + ' ' +\n" + + " CASE dp.class\n" + + " WHEN 0 THEN ''\n" + + " WHEN 1 THEN --table or column subset on the table\n" + + " CASE WHEN dp.major_id < 0 THEN\n" + + " + 'ON [sys].[' + OBJECT_NAME(dp.major_id) + '] '\n" + + " ELSE\n" + + " + 'ON [' +\n" + + " (SELECT SCHEMA_NAME(schema_id) + '].[' + name FROM sys.objects WHERE object_id = dp.major_id)\n" + + " + -- optionally concatenate column names\n" + + " CASE WHEN MAX(dp.minor_id) > 0 \n" + + " THEN '] ([' + REPLACE(\n" + + " (SELECT name + '], [' \n" + + " FROM sys.columns \n" + + " WHERE object_id = dp.major_id \n" + + " AND column_id IN (SELECT minor_id \n" + + " FROM sys.database_permissions \n" + + " WHERE major_id = dp.major_id\n" + + " AND USER_NAME(grantee_principal_id) IN (@roleName)\n" + + " )\n" + + " FOR XML PATH('')\n" + + " ) --replace final square bracket pair\n" + + " + '])', ', []', '')\n" + + " ELSE ']'\n" + + " END + ' '\n" + + " END\n" + + " WHEN 3 THEN 'ON SCHEMA::[' + SCHEMA_NAME(dp.major_id) + '] '\n" + + " WHEN 4 THEN 'ON ' + (SELECT RIGHT(type_desc, 4) + '::[' + name FROM sys.database_principals WHERE principal_id = dp.major_id) + '] '\n" + + " WHEN 5 THEN 'ON ASSEMBLY::[' + (SELECT name FROM sys.assemblies WHERE assembly_id = dp.major_id) + '] '\n" + + " WHEN 6 THEN 'ON TYPE::[' + (SELECT name FROM sys.types WHERE user_type_id = dp.major_id) + '] '\n" + + " WHEN 10 THEN 'ON XML SCHEMA COLLECTION::[' + (SELECT SCHEMA_NAME(schema_id) + '.' + name FROM sys.xml_schema_collections WHERE xml_collection_id = dp.major_id) + '] '\n" + + " WHEN 15 THEN 'ON MESSAGE TYPE::[' + (SELECT name FROM sys.service_message_types WHERE message_type_id = dp.major_id) + '] '\n" + + " WHEN 16 THEN 'ON CONTRACT::[' + (SELECT name FROM sys.service_contracts WHERE service_contract_id = dp.major_id) + '] '\n" + + " WHEN 17 THEN 'ON SERVICE::[' + (SELECT name FROM sys.services WHERE service_id = dp.major_id) + '] '\n" + + " WHEN 18 THEN 'ON REMOTE SERVICE BINDING::[' + (SELECT name FROM sys.remote_service_bindings WHERE remote_service_binding_id = dp.major_id) + '] '\n" + + " WHEN 19 THEN 'ON ROUTE::[' + (SELECT name FROM sys.routes WHERE route_id = dp.major_id) + '] '\n" + + " WHEN 23 THEN 'ON FULLTEXT CATALOG::[' + (SELECT name FROM sys.fulltext_catalogs WHERE fulltext_catalog_id = dp.major_id) + '] '\n" + + " WHEN 24 THEN 'ON SYMMETRIC KEY::[' + (SELECT name FROM sys.symmetric_keys WHERE symmetric_key_id = dp.major_id) + '] '\n" + + " WHEN 25 THEN 'ON CERTIFICATE::[' + (SELECT name FROM sys.certificates WHERE certificate_id = dp.major_id) + '] '\n" + + " WHEN 26 THEN 'ON ASYMMETRIC KEY::[' + (SELECT name FROM sys.asymmetric_keys WHERE asymmetric_key_id = dp.major_id) + '] '\n" + + " END COLLATE SQL_Latin1_General_CP1_CI_AS\n" + + " + 'TO [' + @roleName + ']' + \n" + + " CASE dp.state WHEN 'W' THEN ' WITH GRANT OPTION' ELSE '' END + ';'\n" + + " FROM sys.database_permissions dp\n" + + " WHERE USER_NAME(dp.grantee_principal_id) IN (@roleName)\n" + + " GROUP BY dp.state, dp.major_id, dp.permission_name, dp.class\n" + + " SELECT @roleDesc = @roleDesc + CASE WHEN @rolePerm IS NOT NULL THEN @rolePerm ELSE '' END\n" + + " RETURN @roleDesc\n" + + "END \n" + , + "CREATE FUNCTION dbo.GetRoleMembersDDL(@roleName VARCHAR(255))\n" + + "RETURNS VARCHAR(MAX)\n" + + "BEGIN\n" + + " -- Script out the Role\n" + + " DECLARE @roleDesc VARCHAR(MAX)\n" + + " SET @roleDesc = ''\n" + + " -- Display users within Role. Code stubbed by Joe Spivey\n" + + " SELECT @roleDesc = @roleDesc + 'EXECUTE sp_AddRoleMember ''' + roles.name + ''', ''' + users.name + ''';' \n" + + " FROM sys.database_principals users\n" + + " INNER JOIN sys.database_role_members link \n" + + " ON link.member_principal_id = users.principal_id\n" + + " INNER JOIN sys.database_principals roles \n" + + " ON roles.principal_id = link.role_principal_id\n" + + " WHERE roles.name = @roleName\n" + + " RETURN @roleDesc\n" + + "END \n" + ); + + try (Statement stmt = getConnection().createStatement();) { + + for(String expr : setupQueries){ + stmt.execute(expr); + } + + try(ResultSet rs = stmt.executeQuery(usersQuery);){ + while(rs.next()){ + final String name = rs.getString("rolename"); + final StringProperties options = new StringProperties(rs); + + DBRole role = new DBRole(name, options); + listRole.put(name, role); + } + } + + }catch(Exception e) { + final DBGitLang msg = lang.getValue("errors", "adapter", "roles"); + throw new ExceptionDBGitRunTime(msg, e); + } + return listRole; + } + + @Override + public Map getUDTs(String schema) { + return Collections.emptyMap(); + } + + @Override + public Map getDomains(String schema) { + return Collections.emptyMap(); + } + + @Override + public Map getEnums(String schema) { + return Collections.emptyMap(); + } + + @Override + public DBUserDefinedType getUDT(String schema, String name) { + final String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); + throw new ExceptionDBGitObjectNotFound(msg); + } + + @Override + public DBDomain getDomain(String schema, String name) { + final String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); + throw new ExceptionDBGitObjectNotFound(msg); + } + + @Override + public DBEnum getEnum(String schema, String name) { + final String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); + throw new ExceptionDBGitObjectNotFound(msg); + } + + @Override + public boolean userHasRightsToGetDdlOfOtherUsers() { + try{ + + Connection connect = getConnection(); + Statement stmt = connect.createStatement(); + ResultSet rs = stmt.executeQuery( + "SELECT CASE WHEN EXISTS " + + "(SELECT * FROM fn_my_permissions(NULL, 'DATABASE') WHERE permission_name LIKE '%DEFINITION%') " + + "THEN 1 ELSE 0 END hasRights;" + ); + rs.next(); + boolean hasRights = rs.getBoolean(1); + stmt.close(); + return hasRights; + + }catch(Exception e) { + logger.error(lang.getValue("errors", "adapter", "roles") + ": " + e.getMessage()); + throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "roles") + ": " + e.getMessage()); + } + } + + @Override + public IFactoryDBBackupAdapter getBackupAdapterFactory() { + return backupFactory; + } + + @Override + public IFactoryDBConvertAdapter getConvertAdapterFactory() { + return convertFactory; + } + + @Override + public DbType getDbType() { + return DbType.MSSQL; + } + + @Override + public String getDbVersion() { + try { + Statement stmt = getConnection().createStatement(); + + //Gives 8.00, 9.00, 10.00 and 10.50 for SQL 2000, 2005, 2008 and 2008R2 respectively. + String query = "SELECT left(cast(serverproperty('productversion') as varchar), 4)"; + + ResultSet resultSet = stmt.executeQuery(query); + resultSet.next(); + String result = resultSet.getString(1); + + resultSet.close(); + stmt.close(); + return result; + + } catch (SQLException e) { return "";} + } + + @Override + public void createSchemaIfNeed(String schemaName) throws ExceptionDBGit { + try { + if(!getSchemes().containsKey(schemaName)) { + StatementLogging stLog = new StatementLogging(connect, getStreamOutputSqlCommand(), isExecSql()); + stLog.execute( + "IF NOT EXISTS ( SELECT * FROM sys.schemas WHERE name = N'" + schemaName + "' )\n" + + "EXEC('CREATE SCHEMA ["+schemaName+"]');" + ); + + stLog.close(); + } + } catch (SQLException e) { + throw new ExceptionDBGit(lang.getValue("errors", "adapter", "createSchema") + ": " + e.getLocalizedMessage()); + } + + } + + @Override + public void createRoleIfNeed(String roleName) throws ExceptionDBGit { + try { + if(!getRoles().containsKey(roleName)) { + StatementLogging stLog = new StatementLogging(connect, getStreamOutputSqlCommand(), isExecSql()); + stLog.execute( + "IF NOT EXISTS ( SELECT * FROM sys.schemas WHERE name = N'" + roleName + "' )\n" + + "EXEC('CREATE ROLE ["+roleName+"]');" + ); + + stLog.close(); + } + } catch (SQLException e) { + throw new ExceptionDBGit(lang.getValue("errors", "adapter", "createSchema") + ": " + e.getLocalizedMessage()); + } + + } + + @Override + public String getDefaultScheme() throws ExceptionDBGit { + try{ + Statement stmt = getConnection().createStatement(); + + String query = "SELECT SCHEMA_NAME()"; + + ResultSet resultSet = stmt.executeQuery(query); + resultSet.next(); + String result = resultSet.getString(1); + + resultSet.close(); + stmt.close(); + return result; + } + catch (SQLException e){ + throw new ExceptionDBGit(lang.getValue("errors", "adapter", "createSchema") + ": " + e.getLocalizedMessage()); + } + } + + @Override + @SuppressWarnings("SpellCheckingInspection") + public boolean isReservedWord(String word) { + + Set reservedWords = new HashSet<>(Arrays.asList( + "DD", "EXTERNAL", "PROCEDURE", "ALL", "FETCH", "PUBLIC", "ALTER", "FILE", "RAISERROR", + "AND", "FILLFACTOR", "READ", "ANY", "FOR", "READTEXT", "AS", "FOREIGN", "RECONFIGURE", + "ASC", "FREETEXT", "REFERENCES", "AUTHORIZATION", "FREETEXTTABLE", "REPLICATION", + "BACKUP", "FROM", "RESTORE", "BEGIN", "FULL", "RESTRICT", "BETWEEN", "FUNCTION", "RETURN", + "BREAK", "GOTO", "REVERT", "BROWSE", "GRANT", "REVOKE", "BULK", "GROUP", "RIGHT", "BY", + "HAVING", "ROLLBACK", "CASCADE", "HOLDLOCK", "ROWCOUNT", "CASE", "IDENTITY", "ROWGUIDCOL", + "CHECK", "IDENTITY_INSERT", "RULE", "CHECKPOINT", "IDENTITYCOL", "SAVE", "CLOSE", "IF", + "SCHEMA", "CLUSTERED", "IN", "SECURITYAUDIT", "COALESCE", "INDEX", "SELECT", "COLLATE", + "INNER", "SEMANTICKEYPHRASETABLE", "COLUMN", "INSERT", "SEMANTICSIMILARITYDETAILSTABLE", + "COMMIT", "INTERSECT", "SEMANTICSIMILARITYTABLE", "COMPUTE", "INTO", "SESSION_USER", + "CONSTRAINT", "IS", "SET", "CONTAINS", "JOIN", "SETUSER", "CONTAINSTABLE", "KEY", "SHUTDOWN", + "CONTINUE", "KILL", "SOME", "CONVERT", "LEFT", "STATISTICS", "CREATE", "LIKE", "SYSTEM_USER", + "CROSS", "LINENO", "TABLE", "CURRENT", "LOAD", "TABLESAMPLE", "CURRENT_DATE", "MERGE", + "TEXTSIZE", "CURRENT_TIME", "NATIONAL", "THEN", "CURRENT_TIMESTAMP", "NOCHECK", "TO", + "CURRENT_USER", "NONCLUSTERED", "В начало", "CURSOR", "NOT", "TRAN", "DATABASE", "NULL", + "TRANSACTION", "DBCC", "NULLIF", "TRIGGER", "DEALLOCATE", "OF", "TRUNCATE", "DECLARE", + "OFF", "TRY_CONVERT", "DEFAULT", "OFFSETS", "TSEQUAL", "DELETE", "ON", "UNION", "DENY", + "OPEN", "UNIQUE", "DESC", "OPENDATASOURCE", "UNPIVOT", "DISK", "OPENQUERY", "UPDATE", + "DISTINCT", "OPENROWSET", "UPDATETEXT", "DISTRIBUTED", "OPENXML", "USE", "DOUBLE", + "OPTION", "ПОЛЬЗОВАТЕЛЬ", "DROP", "OR", "VALUES", "DUMP", "OVER", "WAITFOR", "ERRLVL", + "PERCENT", "PIVOT", "PLAN", "WHILE", "на", "PRINT", "WRITETEXT", "EXIT", "PROC", "OVERLAPS", + "ADA", "ADD", "EXTERNAL", "PASCAL", "ALL", "EXTRACT", "POSITION", "PRECISION", "ALTER", + "FETCH", "AND", "ANY", "PRIMARY", "FOR", "СЛУЖБЫ", "ANALYSIS SERVICES", "FOREIGN", + "ASC", "FORTRAN", "PROCEDURE", "PUBLIC", "FROM", "READ", "AUTHORIZATION", "ПОЛНОЕ", + "REAL", "AVG", "REFERENCES", "BEGIN", "BETWEEN", "RESTRICT", "GOTO", "REVOKE", "BIT_LENGTH", + "GRANT", "RIGHT", "GROUP", "ROLLBACK", "BY", "HAVING", "CASCADE", "SCHEMA", "IDENTITY", + "CASE", "IN", "INCLUDE", "SELECT", "INDEX", "CHAR_LENGTH", "SESSION_USER", "SET", + "CHARACTER_LENGTH", "INNER", "CHECK", "CLOSE", "INSENSITIVE", "SOME", "COALESCE", "INSERT", + "COLLATE", "SQLCA", "COLUMN", "INTERSECT", "SQLCODE", "COMMIT", "SQLERROR", "INTO", "IS", + "CONSTRAINT", "SUBSTRING", "JOIN", "SUM", "CONTINUE", "KEY", "SYSTEM_USER", "CONVERT", + "TABLE", "COUNT", "THEN", "CREATE", "LEFT", "CROSS", "TIMESTAMP", "CURRENT", "LIKE", + "CURRENT_DATE", "CURRENT_TIME", "LOWER", "Кому", "CURRENT_TIMESTAMP", "CURRENT_USER", + "MAX", "TRANSACTION", "CURSOR", "MIN", "TRANSLATE", "TRIM", "DEALLOCATE", "UNION", "NATIONAL", + "UNIQUE", "DECLARE", "DEFAULT", "UPDATE", "UPPER", "DELETE", "NONE", "USER", "DESC", "NOT", + "NULL", "VALUE", "NULLIF", "VALUES", "OCTET_LENGTH", "VARYING", "DISTINCT", "OF", "VIEW", + "ON", "WHEN", "DOUBLE", "DROP", "OPEN", "WHERE", "ELSE", "OPTION", "WITH", "END", "OR", "ORDER", + "ESCAPE", "OUTER", "EXCEPT", "ABSOLUTE", "HOST", "RELATIVE", "ACTION", "HOUR", "RELEASE", + "ADMIN", "IGNORE", "RESULT", "AFTER", "IMMEDIATE", "RETURNS", "AGGREGATE", "INDICATOR", + "ROLE", "ALIAS", "INITIALIZE", "ROLLUP", "ALLOCATE", "INITIALLY", "ROUTINE", "ARE", "INOUT", + "ROW", "ARRAY", "INPUT", "ROWS", "ASENSITIVE", "INT", "SAVEPOINT", "ASSERTION", "INTEGER", + "SCROLL", "ASYMMETRIC", "INTERSECTION", "SCOPE", "AT", "INTERVAL", "SEARCH", "ATOMIC", + "ISOLATION", "SECOND", "BEFORE", "ITERATE", "SECTION", "BINARY", "LANGUAGE", "SENSITIVE", + "BIT", "LARGE", "SEQUENCE", "BLOB", "LAST", "SESSION", "BOOLEAN", "LATERAL", "SETS", "BOTH", + "LEADING", "SIMILAR", "BREADTH", "LESS", "SIZE", "CALL", "LEVEL", "SMALLINT", "CALLED", + "LIKE_REGEX", "SPACE", "CARDINALITY", "LIMIT", "SPECIFIC", "CASCADED", "LN", "SPECIFICTYPE", + "CAST", "LOCAL", "SQL", "CATALOG", "LOCALTIME", "SQLEXCEPTION", "CHAR", "LOCALTIMESTAMP", + "SQLSTATE", "CHARACTER", "LOCATOR", "SQLWARNING", "CLASS", "MAP", "START", "CLOB", "MATCH", + "STATE", "COLLATION", "MEMBER", "STATEMENT", "COLLECT", "METHOD", "STATIC", "COMPLETION", + "MINUTE", "STDDEV_POP", "CONDITION", "MOD", "STDDEV_SAMP", "CONNECT", "MODIFIES", "STRUCTURE", + "CONNECTION", "MODIFY", "SUBMULTISET", "CONSTRAINTS", "MODULE", "SUBSTRING_REGEX", + "CONSTRUCTOR", "MONTH", "SYMMETRIC", "CORR", "MULTISET", "SYSTEM", "CORRESPONDING", + "NAMES", "TEMPORARY", "COVAR_POP", "NATURAL", "TERMINATE", "COVAR_SAMP", "NCHAR", "THAN", + "CUBE", "NCLOB", "TIME", "CUME_DIST", "NEW", "TIMESTAMP", "CURRENT_CATALOG", "NEXT", + "TIMEZONE_HOUR", "CURRENT_DEFAULT_TRANSFORM_GROUP", "NO", "TIMEZONE_MINUTE", + "CURRENT_PATH", "None", "TRAILING", "CURRENT_ROLE", "NORMALIZE", "TRANSLATE_REGEX", + "CURRENT_SCHEMA", "NUMERIC", "TRANSLATION", "CURRENT_TRANSFORM_GROUP_FOR_TYPE", + "OBJECT", "TREAT", "CYCLE", "OCCURRENCES_REGEX", "TRUE", "DATA", "OLD", "UESCAPE", "DATE", + "ONLY", "UNDER", "DAY", "OPERATION", "UNKNOWN", "DEC", "ORDINALITY", "UNNEST", "DECIMAL", + "OUT", "USAGE", "DEFERRABLE", "OVERLAY", "USING", "DEFERRED", "OUTPUT", "Value", "DEPTH", + "PAD", "VAR_POP", "DEREF", "Параметр", "VAR_SAMP", "DESCRIBE", "PARAMETERS", "VARCHAR", + "DESCRIPTOR", "PARTIAL", "VARIABLE", "DESTROY", "PARTITION", "WHENEVER", "DESTRUCTOR", + "PATH", "WIDTH_BUCKET", "DETERMINISTIC", "POSTFIX", "WITHOUT", "DICTIONARY", "PREFIX", + "WINDOW", "DIAGNOSTICS", "PREORDER", "WITHIN", "DISCONNECT", "PREPARE", "WORK", "DOMAIN", + "PERCENT_RANK", "WRITE", "DYNAMIC", "PERCENTILE_CONT", "XMLAGG", "EACH", "PERCENTILE_DISC", + "XMLATTRIBUTES", "ELEMENT", "POSITION_REGEX", "XMLBINARY", "END-EXEC", "PRESERVE", + "XMLCAST", "EQUALS", "PRIOR", "XMLCOMMENT", "EVERY", "PRIVILEGES", "XMLCONCAT", + "EXCEPTION", "RANGE", "XMLDOCUMENT", "FALSE", "READS", "XMLELEMENT", "FILTER", "REAL", + "XMLEXISTS", "FIRST", "RECURSIVE", "XMLFOREST", "FLOAT", "REF", "XMLITERATE", "FOUND", + "REFERENCING", "XMLNAMESPACES", "FREE", "REGR_AVGX", "XMLPARSE", "FULLTEXTTABLE", + "REGR_AVGY", "XMLPI", "FUSION", "REGR_COUNT", "XMLQUERY", "GENERAL", "REGR_INTERCEPT", + "XMLSERIALIZE", "GET", "REGR_R2", "XMLTABLE", "GLOBAL", "REGR_SLOPE", "XMLTEXT", "GO", + "REGR_SXX", "XMLVALIDATE", "GROUPING", "REGR_SXY", "YEAR", "HOLD", "REGR_SYY", "ZONE" + )); + + + String[] words = word.split("\\s"); + for (String str : words) { + if(reservedWords.contains(str.toUpperCase())) return true; + } + return false; + } + +} diff --git a/src/main/java/ru/fusionsoft/dbgit/mssql/DBBackupAdapterMssql.java b/src/main/java/ru/fusionsoft/dbgit/mssql/DBBackupAdapterMssql.java new file mode 100644 index 0000000..27e5ee0 --- /dev/null +++ b/src/main/java/ru/fusionsoft/dbgit/mssql/DBBackupAdapterMssql.java @@ -0,0 +1,297 @@ +package ru.fusionsoft.dbgit.mssql; + +import ru.fusionsoft.dbgit.adapters.DBBackupAdapter; +import ru.fusionsoft.dbgit.core.DBGitPath; +import ru.fusionsoft.dbgit.core.ExceptionDBGit; +import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; +import ru.fusionsoft.dbgit.core.SchemaSynonym; +import ru.fusionsoft.dbgit.dbobjects.DBConstraint; +import ru.fusionsoft.dbgit.dbobjects.DBIndex; +import ru.fusionsoft.dbgit.dbobjects.DBTableField; +import ru.fusionsoft.dbgit.meta.*; +import ru.fusionsoft.dbgit.statement.StatementLogging; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; +import ru.fusionsoft.dbgit.utils.StringProperties; + +import java.io.File; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.text.MessageFormat; +import java.util.Objects; + +@SuppressWarnings("Duplicates") +public class DBBackupAdapterMssql extends DBBackupAdapter { + + @Override + public IMetaObject backupDBObject(IMetaObject obj) throws SQLException, ExceptionDBGit { + + Connection connection = adapter.getConnection(); + StatementLogging stLog = new StatementLogging(connection, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + + try { + if (obj instanceof MetaSql) { + MetaSql metaSql = (MetaSql) obj; + String objectName = metaSql.getSqlObject().getName(); + metaSql.loadFromDB(); + + String ddl = metaSql.getSqlObject().getSql(); + String schema = metaSql.getSqlObject().getSchema(); + + if (isSaveToSchema()) { + createSchema(stLog, schema); + } + + ConsoleWriter.detailsPrintln(lang.getValue("general", "backup", "tryingToCopy").withParams(objectName, getFullDbName(schema, objectName)), messageLevel); + + ddl = ddl.replace(schema + "." + objectName, getFullDbName(schema, objectName)); + + stLog.execute(ddl); + + File file = new File(DBGitPath.getFullPath() + metaSql.getFileName()); + if (file.exists()) + obj = metaSql.loadFromFile(); + + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + } + else if (obj instanceof MetaTable) { + + MetaTable metaTable = (MetaTable) obj; + metaTable.loadFromDB(); + String objectName = metaTable.getTable().getName(); + String schema = metaTable.getTable().getSchema(); + schema = (SchemaSynonym.getInstance().getSchema(schema) == null) ? schema : SchemaSynonym.getInstance().getSchema(schema); + String tableSam = getFullDbName(schema, objectName); + String origTableName = schema + "." + objectName; + + + if(!isExists(schema, objectName)) { + File file = new File(DBGitPath.getFullPath() + metaTable.getFileName()); + if (file.exists()) + obj = metaTable.loadFromFile(); + return obj; + } + + if (isSaveToSchema()) { + createSchema(stLog, schema); + } + + ConsoleWriter.detailsPrintln(lang.getValue("general", "backup", "tryingToCopy").withParams(objectName, getFullDbName(schema, objectName)), messageLevel); + + dropIfExists(isSaveToSchema() ? PREFIX + schema : schema, + isSaveToSchema() ? objectName : PREFIX + objectName, stLog); + + String ddl = ""; + if (isToSaveData()) { + // Fields + data + ddl = "create table " + tableSam + " as (select * from " + schema + "." + objectName + ")" +";\n"; + + // Schema + ddl += "alter schema "+ adapter.getDefaultScheme() + " transfer "+ tableSam + ";\n"; + } else { + // Fields + ddl ="create table " + tableSam + "("; + for (DBTableField field : metaTable.getFields().values()) { + ddl += MessageFormat.format("\n[{0}] {1},", field.getName(), field.getTypeSQL()); + } + ddl = ddl.substring(0, ddl.length()-1); + ddl += "\n);\n"; + + // Schema + ddl += "alter schema "+ adapter.getDefaultScheme() + " transfer "+ tableSam + ";\n"; + } + + for (DBConstraint constraint : metaTable.getConstraints().values()) { + String constraintSql = constraint.getSql().replace( + "ALTER TABLE " + origTableName + " ADD CONSTRAINT " + constraint.getName(), + "alter table "+ tableSam +" add constraint " + PREFIX + constraint.getName() + " " + ); + ddl += constraintSql + "\n"; + } + + for (DBIndex index : metaTable.getIndexes().values()) { + String indexDdl = index.getSql() + "\n"; + indexDdl = indexDdl + .replace(index.getName(), PREFIX + index.getName()) + .replace("["+objectName+"]", "["+PREFIX+objectName+"]"); + if (indexDdl.length() > 3) + ddl += indexDdl; + } + stLog.execute(ddl); + + File file = new File(DBGitPath.getFullPath() + metaTable.getFileName()); + if (file.exists()) + obj = metaTable.loadFromFile(); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + } + else if (obj instanceof MetaSequence) { + MetaSequence metaSequence = (MetaSequence) obj; + metaSequence.loadFromDB(); + + String objectName = metaSequence.getSequence().getName(); + String schema = metaSequence.getSequence().getSchema(); + + if (isSaveToSchema()) { + createSchema(stLog, schema); + } + + String sequenceName = getFullDbName(schema, objectName); + + ConsoleWriter.detailsPrintln(lang.getValue("general", "backup", "tryingToCopy").withParams(objectName, getFullDbName(schema, objectName)), messageLevel); + + StringProperties props = metaSequence.getSequence().getOptions(); + String seqName = props.get("name").getData(); + String seqTypeName = props.get("typename").getData(); + String seqStart = props.get("start_value").getData(); + String seqIncr = props.get("increment").getData(); + StringProperties seqMin = props.get("minimum_value"); + StringProperties seqMax = props.get("maximum_value"); + boolean seqCycle = props.get("is_cycling").getData().equals("1"); + boolean seqHasCache = props.get("is_cached").getData().equals("1"); + //there may be default cache size + StringProperties seqCacheSize = props.get("cache_size"); + String seqOwner = props.get("owner").getData(); + + Objects.requireNonNull(seqTypeName); + + String ddl = "CREATE SEQUENCE " + sequenceName + " AS " + seqTypeName + + " START WITH " + seqStart + + " INCREMENT BY " + seqIncr + + (Objects.nonNull(seqMin) ? " MINVALUE " + seqMin.getData() : " NO MINVALUE ") + + (Objects.nonNull(seqMax) ? " MAXVALUE " + seqMax.getData() : " NO MAXVALUE ") + + ((seqHasCache) + ? " CACHE " + (seqCacheSize != null ? seqCacheSize : " ") + : " NO CACHE") + + ((seqCycle) ? " CYCLE " : " NO CYCLE " + "\n"); + + ddl += MessageFormat.format( + "ALTER SCHEMA {0} TRANSFER {1}.{2}", + adapter.getConnection().getSchema(), seqOwner, seqName + ); + + dropIfExists(isSaveToSchema() ? PREFIX + schema : schema, + isSaveToSchema() ? objectName : PREFIX + objectName, stLog); + + stLog.execute(ddl); + + File file = new File(DBGitPath.getFullPath() + metaSequence.getFileName()); + if (file.exists()) + obj = metaSequence.loadFromFile(); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + } + + } catch (SQLException e1) { + throw new ExceptionDBGitRestore( + lang.getValue("errors", "restore", "objectRestoreError") + .withParams(obj.getName() + ": " + e1.getLocalizedMessage()) + , e1 + ); + } catch (Exception e) { + throw new ExceptionDBGit(lang.getValue("errors", "backup", "backupError").withParams(obj.getName()), e); + } finally { + stLog.close(); + connection.commit(); + } + return obj; + } + + @Override + public void restoreDBObject(IMetaObject obj) throws Exception { + // TODO Auto-generated method stub + + } + + private String getFullDbName(String schema, String objectName) { + if (isSaveToSchema()) + return PREFIX + schema + "." + objectName; + else + return schema + "." + PREFIX + objectName; + } + + public void dropIfExists(String owner, String objectName, StatementLogging stLog) throws SQLException { + String query = + "SELECT CASE \n" + + "WHEN type IN ('PC', 'P') THEN 'PROCEDURE'\n" + + "WHEN type IN ('FN', 'FS', 'FT', 'IF', 'TF') THEN 'FUNCTION' \n" + + "WHEN type = 'AF' THEN 'AGGREGATE' \n" + + "WHEN type = 'U' THEN 'TABLE' \n" + + "WHEN type = 'V' THEN 'VIEW' \n" + + "WHEN type IN ('SQ', 'SO') THEN 'SEQUENCE' \n" + + "END type\n" + + "FROM sys.objects so\n" + + "WHERE lower(name) = lower('"+objectName+"') \n" + + "AND lower(SCHEMA_NAME(schema_id)) = lower('"+owner+"')"; + + try(Statement st = adapter.getConnection().createStatement(); ResultSet rs = st.executeQuery(query)) { + while (rs.next()) { + String type = rs.getString("type"); + stLog.execute(MessageFormat.format("DROP {0} {1}.{2}", type, owner, objectName)); + } + } + + } + + @Override + public void dropIfExists(IMetaObject imo, StatementLogging stLog) throws SQLException { + NameMeta nm = new NameMeta(imo); + String typeString = "'none'"; + switch((DBGitMetaType) nm.getType()){ + case DBGitTable: typeString = "'TABLE'"; break; + case DbGitFunction: typeString = "'FUNCTION'"; break; + case DbGitProcedure:typeString = "'PROCEDURE'"; break; + case DbGitView: typeString = "'VIEW'"; break; + case DBGitSequence: typeString = "'SEQUENCE'"; break; + } + + String query = MessageFormat.format( + "SELECT CASE \n" + + "WHEN type IN ('PC', 'P') THEN 'PROCEDURE'\n" + + "WHEN type IN ('FN', 'FS', 'FT', 'IF', 'TF', 'AF') THEN 'FUNCTION' \n" + + "WHEN type = 'U' THEN 'TABLE' \n" + + "WHEN type = 'V' THEN 'VIEW' \n" + + "WHEN type IN ('SQ', 'SO') THEN 'SEQUENCE' \n" + + "END type\n" + + "FROM sys.objects so\n" + + "WHERE lower(SCHEMA_NAME(schema_id)) = lower('{0}') \n" + + "AND lower(name) = lower('{1}') \n" + + "AND type IN ({2})", + nm.getSchema(), + nm.getName(), + typeString + ); + + try(Statement st = adapter.getConnection().createStatement(); ResultSet rs = st.executeQuery(query)) { + while (rs.next()) { + String type = rs.getString("type"); + stLog.execute(MessageFormat.format("DROP {0} {1}.{2}", type, nm.getSchema(), nm.getName())); + } + } + } + + @Override + public boolean isExists(String owner, String objectName) throws SQLException { + Statement st = adapter.getConnection().createStatement(); + ResultSet rs = st.executeQuery( + "SELECT CASE WHEN OBJECT_ID('"+owner+"."+objectName+"') IS NOT NULL THEN 1 ELSE 0 END" + ); + + rs.next(); + return rs.getInt(1) == 1; + } + + @Override + public boolean createSchema(StatementLogging stLog, String schema) { + try { + if (!adapter.getSchemes().containsKey(schema)) { + ConsoleWriter.detailsPrintln(lang.getValue("general", "backup", "creatingSchema").withParams(PREFIX + schema), messageLevel); + stLog.execute(MessageFormat.format("CREATE SCHEMA {0}{1}", PREFIX, schema)); + } + return true; + } catch (SQLException e) { + ConsoleWriter.println(lang.getValue("errors", "backup", "cannotCreateSchema").withParams(e.getLocalizedMessage()), messageLevel); + return false; + } + } + +} diff --git a/src/main/java/ru/fusionsoft/dbgit/mssql/DBRestoreFunctionMssql.java b/src/main/java/ru/fusionsoft/dbgit/mssql/DBRestoreFunctionMssql.java new file mode 100644 index 0000000..3bde897 --- /dev/null +++ b/src/main/java/ru/fusionsoft/dbgit/mssql/DBRestoreFunctionMssql.java @@ -0,0 +1,75 @@ +package ru.fusionsoft.dbgit.mssql; + +import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter; +import ru.fusionsoft.dbgit.adapters.IDBAdapter; +import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; +import ru.fusionsoft.dbgit.dbobjects.DBFunction; +import ru.fusionsoft.dbgit.dbobjects.DBSQLObject; +import ru.fusionsoft.dbgit.meta.IMetaObject; +import ru.fusionsoft.dbgit.meta.MetaFunction; +import ru.fusionsoft.dbgit.statement.StatementLogging; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; + +import java.sql.Connection; +import java.text.MessageFormat; +import java.util.Map; + +public class DBRestoreFunctionMssql extends DBRestoreAdapter { + + @Override + public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + try { + if (obj instanceof MetaFunction) { + MetaFunction restoreFunction = (MetaFunction)obj; + DBSQLObject restoringDBF = restoreFunction.getSqlObject(); + String functionName = restoreFunction.getSqlObject().getName(); + Map functions = adapter.getFunctions(restoreFunction.getSqlObject().getSchema()); + + if(functions.containsKey(functionName)){ + DBFunction existingDBF = functions.get(functionName); + boolean ddlsDiffer = !restoringDBF.getSql().equals(existingDBF.getSql()); + boolean ownersDiffer = !restoringDBF.getOwner().equals(existingDBF.getOwner()); + + if(ddlsDiffer) { + st.execute(MessageFormat.format("DROP FUNCTION {0}.{1}", existingDBF.getOwner(), existingDBF.getName())); + st.execute(restoreFunction.getSqlObject().getSql()); + } + if(ownersDiffer) { + //TODO remove sp_changeowner usage in other methods + String ddl = MessageFormat.format( + "ALTER SCHEMA {0} TRANSFER {1}.{2}", + restoringDBF.getOwner(), existingDBF.getOwner(), functionName + ); + st.execute(ddl); + } + } else { + st.execute(restoreFunction.getSqlObject().getSql()); + } + //TODO Восстановление привилегий + } + else + { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "function", obj.getType().getValue() + )); + } + } catch (Exception e) { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); + } finally { + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + st.close(); + } + return true; + } + + @Override + public void removeMetaObject(IMetaObject obj) throws Exception { + // TODO Auto-generated method stub + + } + +} diff --git a/src/main/java/ru/fusionsoft/dbgit/mssql/DBRestoreProcedureMssql.java b/src/main/java/ru/fusionsoft/dbgit/mssql/DBRestoreProcedureMssql.java new file mode 100644 index 0000000..5e50e36 --- /dev/null +++ b/src/main/java/ru/fusionsoft/dbgit/mssql/DBRestoreProcedureMssql.java @@ -0,0 +1,69 @@ +package ru.fusionsoft.dbgit.mssql; + +import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter; +import ru.fusionsoft.dbgit.adapters.IDBAdapter; +import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; +import ru.fusionsoft.dbgit.dbobjects.DBProcedure; +import ru.fusionsoft.dbgit.dbobjects.DBSQLObject; +import ru.fusionsoft.dbgit.meta.IMetaObject; +import ru.fusionsoft.dbgit.meta.MetaProcedure; +import ru.fusionsoft.dbgit.statement.StatementLogging; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; + +import java.sql.Connection; +import java.text.MessageFormat; +import java.util.Map; + +public class DBRestoreProcedureMssql extends DBRestoreAdapter { + + @Override + public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + try { + if (obj instanceof MetaProcedure) { + MetaProcedure restoreProcedure = (MetaProcedure)obj; + DBSQLObject restoringProc = restoreProcedure.getSqlObject(); + String procedureName = restoringProc.getName(); + String procedureSchema = restoringProc.getSchema(); + + if(adapter.getProcedures(procedureSchema).containsKey(procedureName)) { + DBProcedure existingProc = adapter.getProcedure(procedureSchema, procedureName); + + if(!restoringProc.getSql().equals(existingProc.getSql())) { + st.execute(MessageFormat.format("DROP PROCEDURE {0}.{1}", existingProc.getOwner(), existingProc.getName())); + st.execute(restoreProcedure.getSqlObject().getSql(), "/"); + //TODO Восстановление привилегий + } + } + else{ + st.execute(restoreProcedure.getSqlObject().getSql(), "/"); + //TODO Восстановление привилегий + } + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + } + else + { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "procedure", obj.getType().getValue() + )); + } + + } + catch (Exception e) { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); + } finally { + st.close(); + } + + return true; + } + + @Override + public void removeMetaObject(IMetaObject obj) throws Exception { + // TODO Auto-generated method stub + } + +} diff --git a/src/main/java/ru/fusionsoft/dbgit/mssql/DBRestoreRoleMssql.java b/src/main/java/ru/fusionsoft/dbgit/mssql/DBRestoreRoleMssql.java new file mode 100644 index 0000000..e8be46f --- /dev/null +++ b/src/main/java/ru/fusionsoft/dbgit/mssql/DBRestoreRoleMssql.java @@ -0,0 +1,82 @@ +package ru.fusionsoft.dbgit.mssql; + +import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter; +import ru.fusionsoft.dbgit.adapters.IDBAdapter; +import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; +import ru.fusionsoft.dbgit.dbobjects.DBRole; +import ru.fusionsoft.dbgit.meta.IMetaObject; +import ru.fusionsoft.dbgit.meta.MetaRole; +import ru.fusionsoft.dbgit.statement.StatementLogging; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; +import ru.fusionsoft.dbgit.utils.StringProperties; + +import java.sql.Connection; +import java.text.MessageFormat; +import java.util.Map; + +public class DBRestoreRoleMssql extends DBRestoreAdapter{ + + @Override + public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + try { + if (obj instanceof MetaRole) { + MetaRole restoreRole = (MetaRole)obj; + Map roles = adapter.getRoles(); + StringProperties opts = restoreRole.getObjectOption().getOptions(); + String restoreDdl = opts.get("ddl") != null ? opts.get("ddl").getData() : ""; + String restoreRoleName = restoreRole.getObjectOption().getName(); + String simpleCreateRoleDdl = MessageFormat.format("CREATE ROLE [{0}];", restoreRoleName); + + boolean exist = false; + + if(!(roles.isEmpty() || roles == null)) { + for(DBRole role:roles.values()) { + + if(restoreRole.getObjectOption().getName().equals(role.getName())){ + exist = true; + + String existingDdl = role.getOptions().get("ddl") != null ? role.getOptions().get("ddl").getData() : ""; + boolean isEqualDdls = restoreDdl + .replaceAll("\\s+", "") + .equals(existingDdl.replaceAll("\\s+", "")); + + if(!isEqualDdls){ + if(!restoreDdl.isEmpty()) st.execute(restoreDdl); + else st.execute(simpleCreateRoleDdl); + //TODO Восстановление привилегий вместо simpleCreateRoleDdl + } + } + } + } + + if(!exist){ + if(!restoreDdl.isEmpty()) st.execute(restoreDdl); + else st.execute(simpleCreateRoleDdl); + } + connect.commit(); + } + else { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "role", obj.getType().getValue() + )); + } + } catch (Exception e) { + ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail"), 0); + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); + } finally { + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + st.close(); + } + return true; + } + @Override + public void removeMetaObject(IMetaObject obj) throws Exception { + // TODO Auto-generated method stub + + } + +} diff --git a/src/main/java/ru/fusionsoft/dbgit/mssql/DBRestoreSchemaMssql.java b/src/main/java/ru/fusionsoft/dbgit/mssql/DBRestoreSchemaMssql.java new file mode 100644 index 0000000..356e63e --- /dev/null +++ b/src/main/java/ru/fusionsoft/dbgit/mssql/DBRestoreSchemaMssql.java @@ -0,0 +1,70 @@ +package ru.fusionsoft.dbgit.mssql; + +import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter; +import ru.fusionsoft.dbgit.adapters.IDBAdapter; +import ru.fusionsoft.dbgit.core.DBGitConfig; +import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; +import ru.fusionsoft.dbgit.dbobjects.DBSchema; +import ru.fusionsoft.dbgit.meta.IMetaObject; +import ru.fusionsoft.dbgit.meta.MetaSchema; +import ru.fusionsoft.dbgit.statement.StatementLogging; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; + +import java.sql.Connection; +import java.util.Map; + + +public class DBRestoreSchemaMssql extends DBRestoreAdapter { + @Override + public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + try { + if (obj instanceof MetaSchema) { + MetaSchema restoreSchema = (MetaSchema)obj; + Map schs = adapter.getSchemes(); + boolean exist = false; + if(!(schs.isEmpty() || schs == null)) { + for(DBSchema sch:schs.values()) { + if(restoreSchema.getObjectOption().getName().equals(sch.getName())){ + exist = true; + // TODO MSSQL restore Schema script + + if(!DBGitConfig.getInstance().getToIgnoreOnwer(false)){ + if(!restoreSchema.getObjectOption().getOptions().getChildren().get("usename").getData().equals(sch.getOptions().getChildren().get("usename").getData())) { + st.execute("ALTER SCHEMA "+ restoreSchema.getObjectOption().getName() +" OWNER TO "+ + restoreSchema.getObjectOption().getOptions().getChildren().get("usename").getData()); + } + } + } + } + } + if(!exist){ + + st.execute("CREATE SCHEMA "+restoreSchema.getObjectOption().getName() +" AUTHORIZATION "+ + restoreSchema.getObjectOption().getOptions().getChildren().get("usename").getData()); + //TODO Восстановление привилегий + } + } + else + { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "schema", obj.getType().getValue() + )); + } + } catch (Exception e) { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); + } finally { + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + st.close(); + } + return true; + } + + public void removeMetaObject(IMetaObject obj) { + // TODO Auto-generated method stub + } + +} diff --git a/src/main/java/ru/fusionsoft/dbgit/mssql/DBRestoreSequenceMssql.java b/src/main/java/ru/fusionsoft/dbgit/mssql/DBRestoreSequenceMssql.java new file mode 100644 index 0000000..5b48f14 --- /dev/null +++ b/src/main/java/ru/fusionsoft/dbgit/mssql/DBRestoreSequenceMssql.java @@ -0,0 +1,102 @@ +package ru.fusionsoft.dbgit.mssql; + +import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter; +import ru.fusionsoft.dbgit.adapters.IDBAdapter; +import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; +import ru.fusionsoft.dbgit.dbobjects.DBSequence; +import ru.fusionsoft.dbgit.meta.IMetaObject; +import ru.fusionsoft.dbgit.meta.MetaSequence; +import ru.fusionsoft.dbgit.statement.StatementLogging; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; +import ru.fusionsoft.dbgit.utils.StringProperties; + +import java.sql.Connection; +import java.text.MessageFormat; +import java.util.Map; +import java.util.Objects; + +public class DBRestoreSequenceMssql extends DBRestoreAdapter { + + @Override + public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + try { + if (obj instanceof MetaSequence) { + + MetaSequence restoreSeq = (MetaSequence)obj; + String seqSchema = restoreSeq.getSequence().getSchema(); + StringProperties props = restoreSeq.getSequence().getOptions(); + String seqName = props.get("name").getData(); + String sequenceSam = seqSchema+"."+seqName; + + + //check existence + Map seqs = adapter.getSequences(seqSchema); + boolean exist = false; + for(DBSequence seq:seqs.values()){ + String currentName = seq.getOptions().getChildren().get("name").getData(); + if(currentName.equalsIgnoreCase(seqName)){ + exist = true; + break; + } + } + + String ddl = exist + ? ("ALTER SEQUENCE " + sequenceSam) + : ("CREATE SEQUENCE " + props.get("name").getData()); + + ddl += " AS " + props.get("typename").getData() + + " START WITH " + props.get("start_value").getData() + + " INCREMENT BY " + props.get("increment").getData() + + ( Objects.nonNull(props.get("minimum_value")) + ? " MINVALUE " + props.get("minimum_value").getData() + : " NO MINVALUE " + ) + + (Objects.nonNull(props.get("maximum_value")) + ? " MAXVALUE " + props.get("maximum_value").getData() + : " NO MAXVALUE " + ) + + ((props.get("is_cached").getData().equals("1")) + ? " CACHE " + (props.get("cache_size") != null + ? props.get("cache_size").getData() : " " ) + : " NO CACHE") + + ((props.get("is_cycling").getData().equals("1")) + ? " CYCLE " + : " NO CYCLE " + + "\n"); + + ddl += MessageFormat.format( + "ALTER SCHEMA {0} TRANSFER {1}.{2}", + adapter.getConnection().getSchema(), + props.get("owner").getData(), + props.get("name").getData() + ); + + //TODO Восстановление привилегий + st.execute(ddl); + } + else + { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "sequence", obj.getType().getValue() + )); + } + } catch (Exception e) { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); + } finally { + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + st.close(); + } + return true; + } + + @Override + public void removeMetaObject(IMetaObject obj) throws Exception { + // TODO Auto-generated method stub + + } + +} diff --git a/src/main/java/ru/fusionsoft/dbgit/mssql/DBRestoreTableDataMssql.java b/src/main/java/ru/fusionsoft/dbgit/mssql/DBRestoreTableDataMssql.java new file mode 100644 index 0000000..cd0e06a --- /dev/null +++ b/src/main/java/ru/fusionsoft/dbgit/mssql/DBRestoreTableDataMssql.java @@ -0,0 +1,593 @@ +package ru.fusionsoft.dbgit.mssql; + +import com.google.common.collect.MapDifference; +import com.google.common.collect.MapDifference.ValueDifference; +import com.google.common.collect.Maps; +import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter; +import ru.fusionsoft.dbgit.adapters.IDBAdapter; +import ru.fusionsoft.dbgit.core.ExceptionDBGit; +import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; +import ru.fusionsoft.dbgit.core.GitMetaDataManager; +import ru.fusionsoft.dbgit.core.SchemaSynonym; +import ru.fusionsoft.dbgit.data_table.*; +import ru.fusionsoft.dbgit.dbobjects.DBConstraint; +import ru.fusionsoft.dbgit.meta.IMetaObject; +import ru.fusionsoft.dbgit.meta.MetaTable; +import ru.fusionsoft.dbgit.meta.MetaTableData; +import ru.fusionsoft.dbgit.statement.PrepareStatementLogging; +import ru.fusionsoft.dbgit.statement.StatementLogging; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; + +import java.io.*; +import java.sql.Connection; +import java.sql.ResultSet; +import java.text.SimpleDateFormat; +import java.util.*; + +public class DBRestoreTableDataMssql extends DBRestoreAdapter { + + @Override + public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { + if (obj instanceof MetaTableData) { + MetaTableData currentTableData; + MetaTableData restoreTableData = (MetaTableData)obj; + GitMetaDataManager gitMetaMng = GitMetaDataManager.getInstance(); + //TODO не факт что в кеше есть мета описание нашей таблицы, точнее ее не будет если при старте ресторе таблицы в бд не было совсем + + IMetaObject currentMetaObj = gitMetaMng.getCacheDBMetaObject(obj.getName()); + + if (currentMetaObj instanceof MetaTableData || currentMetaObj == null) { + + if(Integer.valueOf(step).equals(0)) { + removeTableConstraintsMssql(restoreTableData.getMetaTable()); + return false; + } + if(Integer.valueOf(step).equals(1)) { + String schema = getPhisicalSchema(restoreTableData.getTable().getSchema()); + schema = (SchemaSynonym.getInstance().getSchema(schema) == null) ? schema : SchemaSynonym.getInstance().getSchema(schema); + + if (currentMetaObj != null) { + currentTableData = (MetaTableData) currentMetaObj; + } else { + currentTableData = new MetaTableData(); + currentTableData.setTable(restoreTableData.getTable()); + currentTableData.getTable().setSchema(schema); + + currentTableData.setMapRows(new TreeMapRowData()); + currentTableData.setDataTable(restoreTableData.getDataTable()); + } + currentTableData.getmapRows().clear(); + + if (getAdapter().getTable(schema, currentTableData.getTable().getName()) != null) { + currentTableData.setDataTable(getAdapter().getTableData(schema, currentTableData.getTable().getName())); + + ResultSet rs = currentTableData.getDataTable().resultSet(); + + TreeMapRowData mapRows = new TreeMapRowData(); + + MetaTable metaTable = new MetaTable(currentTableData.getTable()); + metaTable.loadFromDB(currentTableData.getTable()); + + if (rs != null) { + while(rs.next()) { + RowData rd = new RowData(rs, metaTable); + mapRows.put(rd.calcRowKey(metaTable.getIdColumns()), rd); + } + } + currentTableData.setMapRows(mapRows); + } + /* + ConsoleWriter.println("curr:"); + currentTableData.getmapRows().keySet().forEach(key -> ConsoleWriter.println("hash: " + key)); + ConsoleWriter.println("rest:"); + restoreTableData.getmapRows().keySet().forEach(key -> ConsoleWriter.println("hash: " + key)); + */ + restoreTableDataMssql(restoreTableData,currentTableData); + return false; + } + if(Integer.valueOf(step).equals(-2)) { + restoreTableConstraintMssql(restoreTableData.getMetaTable()); + return false; + } + return true; + } + else + { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "table data cached", obj.getType().getValue() + )); + } + } + else { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "table data", obj.getType().getValue() + )); + } + } + + public void restoreTableDataMssql(MetaTableData restoreTableData, MetaTableData currentTableData) throws Exception{ + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + try { + if (restoreTableData.getmapRows() == null) + restoreTableData.setMapRows(new TreeMapRowData()); + + String fields = ""; + if (restoreTableData.getmapRows().size() > 0) + fields = keysToString(restoreTableData.getmapRows().firstEntry().getValue().getData().keySet()) + " values "; + MapDifference diffTableData = Maps.difference(restoreTableData.getmapRows(),currentTableData.getmapRows()); + String schema = getPhisicalSchema(restoreTableData.getTable().getSchema()); + + schema = (SchemaSynonym.getInstance().getSchema(schema) == null) ? schema : SchemaSynonym.getInstance().getSchema(schema); + String tblName = schema + "." + restoreTableData.getTable().getName(); + + + // TODO MSSQL restore TableData script + ResultSet rsTypes = st.executeQuery("select column_name, data_type from information_schema.columns \r\n" + + "where lower(table_schema||'.'||table_name) = lower('" + tblName + "')"); + + HashMap colTypes = new HashMap(); + while (rsTypes.next()) { + colTypes.put(rsTypes.getString("column_name"), rsTypes.getString("data_type")); + } + + + if(!diffTableData.entriesOnlyOnLeft().isEmpty()) { + + ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "inserting"), messageLevel); + + for(RowData rowData:diffTableData.entriesOnlyOnLeft().values()) { + ArrayList fieldsList = new ArrayList(rowData.getData().keySet()); + + String insertQuery = "insert into "+tblName + + fields+valuesToString(rowData.getData().values(), colTypes, fieldsList) + ";\n"; + + ConsoleWriter.detailsPrintln(insertQuery, messageLevel+1); + + PrepareStatementLogging ps = new PrepareStatementLogging(connect, insertQuery, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + int i = 0; + + for (ICellData data : rowData.getData().values()) { + i++; + ConsoleWriter.detailsPrintln(data.getSQLData(), messageLevel+1); + + ResultSet rs = st.executeQuery("select data_type from information_schema.columns \r\n" + + "where lower(table_schema||'.'||table_name) = lower('" + tblName + "') and lower(column_name) = '" + fieldsList.get(i - 1) + "'"); + + boolean isBoolean = false; + while (rs.next()) { + if (rs.getString("data_type").contains("boolean")) { + isBoolean = true; + } + } + + //ps = setValues(data, i, ps, isBoolean); + } + + //if (adapter.isExecSql()) + // ps.execute(); + //ps.close(); + + st.execute(insertQuery); + } + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + } + + if(!diffTableData.entriesOnlyOnRight().isEmpty()){ + ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "deleting"), messageLevel); + String deleteQuery=""; + Map primarykeys = new HashMap(); + for(RowData rowData:diffTableData.entriesOnlyOnRight().values()) { + Map tempcols = rowData.getData(); + String[] keysArray = rowData.getKey().split("_"); + for(String key:keysArray) { + for (String o : tempcols.keySet()) { + if (tempcols.get(o) == null || tempcols.get(o).convertToString() == null) continue; + if (tempcols.get(o).convertToString().equals(key)) { + primarykeys.put(o, tempcols.get(o).convertToString()); + tempcols.remove(o); + break; + } + } + } + String delFields="("; + String delValues="("; + StringJoiner fieldJoiner = new StringJoiner(","); + StringJoiner valuejoiner = new StringJoiner(","); + for (Map.Entry entry : primarykeys.entrySet()) { + fieldJoiner.add("\""+entry.getKey()+"\""); + valuejoiner.add("\'"+entry.getValue()+"\'"); + } + delFields+=fieldJoiner.toString()+")"; + delValues+=valuejoiner.toString()+")"; + primarykeys.clear(); + if (delValues.length() > 3) + deleteQuery+="delete from " + tblName+ + " where " + delFields + " = " + delValues + ";\n"; + if(deleteQuery.length() > 50000 ){ + st.execute(deleteQuery); + deleteQuery = ""; + } + } + if(deleteQuery.length()>1) { + st.execute(deleteQuery); + } + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + } + + if(!diffTableData.entriesDiffering().isEmpty()) { + ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "updating"), messageLevel); + String updateQuery=""; + Map primarykeys = new HashMap(); + for(ValueDifference diffRowData:diffTableData.entriesDiffering().values()) { + if(!diffRowData.leftValue().getHashRow().equals(diffRowData.rightValue().getHashRow())) { + Map tempCols = diffRowData.leftValue().getData(); + String[] keysArray = diffRowData.leftValue().getKey().split("_"); + for(String key:keysArray) { + for (String o : tempCols.keySet()) { + if (tempCols.get(o) == null || tempCols.get(o).convertToString() == null) continue; + if (tempCols.get(o).convertToString().equals(key)) { + primarykeys.put(o, tempCols.get(o).convertToString()); + tempCols.remove(o); + break; + } + } + } + if(!tempCols.isEmpty()) { + String keyFields="("; + String keyValues="("; + StringJoiner fieldJoiner = new StringJoiner(","); + StringJoiner valuejoiner = new StringJoiner(","); + for (Map.Entry entry : primarykeys.entrySet()) { + fieldJoiner.add("\""+entry.getKey()+"\""); + valuejoiner.add("\'"+entry.getValue()+"\'"); + } + keyFields+=fieldJoiner.toString()+")"; + keyValues+=valuejoiner.toString()+")"; + primarykeys.clear(); + + StringJoiner updfieldJoiner = new StringJoiner(","); + StringJoiner updvaluejoiner = new StringJoiner(","); + String updFields="("; + String updValues="("; + + for (Map.Entry entry : tempCols.entrySet()) { + updfieldJoiner.add("\""+entry.getKey()+"\""); + //updvaluejoiner.add("\'"+entry.getValue().convertToString()+"\'"); + //updvaluejoiner.add("?"); + } + + ArrayList fieldsList = new ArrayList(diffRowData.leftValue().getData().keySet()); + + updFields+=updfieldJoiner.toString()+")"; + updValues+=updvaluejoiner.toString()+")"; + + updateQuery="update "+tblName+ + " set "+updFields + " = " + valuesToString(tempCols.values(), colTypes, fieldsList) + " where " + keyFields+ "=" +keyValues+";\n"; + + ConsoleWriter.detailsPrintln(updateQuery, messageLevel+1); + + PrepareStatementLogging ps = new PrepareStatementLogging(connect, updateQuery, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + int i = 0; + + ConsoleWriter.detailsPrintln("vals for " + keyValues + ":" + diffRowData.leftValue().getData().values(), messageLevel); + for (ICellData data : diffRowData.leftValue().getData().values()) { + i++; + ConsoleWriter.detailsPrintln(data.getSQLData(), messageLevel+1); + + ResultSet rs = st.executeQuery("select data_type from information_schema.columns \r\n" + + "where lower(table_schema||'.'||table_name) = lower('" + tblName + "') and lower(column_name) = '" + fieldsList.get(i - 1) + "'"); + + boolean isBoolean = false; + while (rs.next()) { + if (rs.getString("data_type").toLowerCase().contains("boolean")) { + isBoolean = true; + } + } + //ps = setValues(data, i, ps, isBoolean); + } + /* + if (adapter.isExecSql()) + ps.execute(); + ps.close(); + updateQuery = ""; + */ + + + + //if(updateQuery.length() > 50000 ){ + st.execute(updateQuery); + updateQuery = ""; + //} + + } + + } + } + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + if(updateQuery.length()>1) { + ConsoleWriter.println(updateQuery, messageLevel+1); + st.execute(updateQuery); + } + } + + } catch (Exception e) { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(restoreTableData.getTable().getSchema() + "." + restoreTableData.getTable().getName()), e); + } finally { + st.close(); + } + } + + public String valuesToString(Collection datas, HashMap colTypes, ArrayList fieldsList) throws ExceptionDBGit, IOException { + String values="("; + StringJoiner joiner = new StringJoiner(","); + int i = 0; + for (ICellData data : datas) { + boolean isBoolean = ((colTypes.get(fieldsList.get(i)) != null) && (colTypes.get(fieldsList.get(i)).toLowerCase().contains("boolean"))); + if (data instanceof MapFileData) { + if (((MapFileData) data).getFile() == null || ((MapFileData) data).getFile().getName().contains("null")) { + joiner.add("null"); + } else { + + FileInputStream fis = new FileInputStream(((MapFileData) data).getFile()); + + int byteRead; + StringBuilder sb = new StringBuilder(); + + while ((byteRead = fis.read()) != -1) { + String hex = Integer.toHexString(byteRead); + if (hex.length() == 1) hex = "0" + hex; + + sb.append(hex); + } + fis.close(); + joiner.add("decode('" + sb.toString() + "', 'hex')"); + + /* + joiner1.add("decode('" + sb.toString().replace("'", "''") + .replace("\\", "\\\\") + .replace("\n", "' || chr(10) || '") + .replace("\0", "' || '\\000' || '") + + "', 'escape')");*/ + } + } else if (data instanceof TextFileData) { + if (((TextFileData) data).getFile() == null || ((TextFileData) data).getFile().getName().contains("null")) { + joiner.add("null"); + } else { + FileInputStream fis = new FileInputStream(((MapFileData) data).getFile()); + BufferedReader br = new BufferedReader(new InputStreamReader(fis)); + + StringBuilder sb = new StringBuilder(); + String line; + while(( line = br.readLine()) != null ) { + sb.append( line ); + sb.append( '\n' ); + } + br.close(); + + fis.close(); + joiner.add("'" + sb.toString().replace("'", "''") + .replace("\\", "\\\\") + .replace("\n", "' || chr(10) || '") + .replace("\0", "' || '\\000' || '") + + "'"); + } + } else if (data instanceof DateData) { + Date date = ((DateData) data).getDate(); + SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss"); + if (date != null) + joiner.add("TO_TIMESTAMP('" + format.format(date) + "', 'YYYYMMDDHH24MISS')"); + else + joiner.add("null"); + } else if (data instanceof BooleanData) { + if (((BooleanData) data).getValue() != null) + joiner.add(((BooleanData) data).getValue().toString()); + else + joiner.add("null"); + } else if (data instanceof LongData) { + String dt = data.getSQLData().replace("'", ""); + + if (isBoolean) { + if (dt == null || dt.equals("")) + joiner.add("null"); + else if (dt.equals("1")) + joiner.add("true"); + else + joiner.add("false"); + } else { + if (!dt.equals("")) + joiner.add(dt); + else + joiner.add("null"); + } + } else { + String dt = ((StringData) data).getValue(); + if (isBoolean) { + if (dt == null || dt.equals("")) + joiner.add("null"); + else if (dt.startsWith("t") || dt.startsWith("T") || dt.equals("1") || dt.startsWith("y") || dt.startsWith("Y")) + joiner.add("true"); + else + joiner.add("false"); + } else { + if (dt != null) + joiner.add("'" + dt.replace("'", "''") + "'"); + else + joiner.add("null"); + } + //joiner.add(data.getSQLData()); + + } + + //joiner.add("?"); + i++; + } + //ConsoleWriter.println("joiner: " + joiner1); + values+=joiner.toString()+")"; + return values; + } + + public String keysToString(Set keys) { + String fields=""; + if(keys.size()>1) { + String[] fieldsArray = keys.toArray(new String[keys.size()]); + fields="("+fieldsArray[0]; + for(int i=1;i "[" + field.getName() + "]" + " " + field.getTypeSQL()) + .collect(Collectors.joining(", ")) + + ")"; + st.execute(ddl); + + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + } + restoreTableFieldsMssql(restoreTable, tblName, tblSchema, st); + + Map constraints = adapter.getConstraints(tblSchema, tblName); + + if(constraints.keySet().size() > 0) { + removeTableConstraintsMssql(obj); + } + + // set primary key + if (constraints.keySet().size() == 0) { + restoreTablePksMssql(restoreTable, st); + } + } + else { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "table", obj.getType().getValue() + )); + } + } catch (Exception e) { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); + } finally { + st.close(); + } + } + + public void restoreTableIndexesMssql(IMetaObject obj) throws Exception { + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "restoreIndex").withParams(obj.getName()), messageLevel); + try { + if (obj instanceof MetaTable) { + MetaTable restoreTable = (MetaTable)obj; + String schema = getPhisicalSchema(restoreTable.getTable().getSchema()); + schema = (SchemaSynonym.getInstance().getSchema(schema) == null) ? schema : SchemaSynonym.getInstance().getSchema(schema); + Map tables = adapter.getTables(schema); + boolean exist = false; + + //find current table + if(!(tables.isEmpty() || tables == null)) { + for(DBTable currentTable:tables.values()) { + if(restoreTable.getTable().getName().equals(currentTable.getName())){ + exist = true; + + Map currentIndexes = adapter.getIndexes(schema, currentTable.getName()); + MapDifference diffInd = Maps.difference(restoreTable.getIndexes(), currentIndexes); + Map restoringIdxsUnique = diffInd.entriesOnlyOnLeft(); + Map existingIdxsUnique = diffInd.entriesOnlyOnRight(); + Map> mergingIdxs = diffInd.entriesDiffering(); + + //restore missing + if(!restoringIdxsUnique.isEmpty()) { + for(DBIndex ind : restoringIdxsUnique.values()) { + st.execute(ind.getSql()); + } + } + + //drop not matched + if(!existingIdxsUnique.isEmpty()) { + for(DBIndex ind:existingIdxsUnique.values()) { + st.execute("DROP INDEX "+schema+"."+ind.getName()); + } + } + + //process intersects + if(!mergingIdxs.isEmpty()) { + for(ValueDifference idx : mergingIdxs.values()) { + //so just drop and create again + String ddl; + if(idx.rightValue().getOptions().get("is_unique").getData().equals("0")){ + ddl = MessageFormat.format( + "DROP INDEX [{2}] ON [{0}].[{1}] ", + schema, currentTable.getName(), idx.rightValue().getName() + ); + } + else{ + ddl = MessageFormat.format( + "ALTER TABLE [{0}].[{1}] DROP CONSTRAINT [{2}]", + schema, currentTable.getName(), idx.rightValue().getName() + ); + } + st.execute(ddl); + st.execute(idx.leftValue().getSql()); + } + } + + } + } + } + if(!exist){ + /*for(DBIndex ind:restoreTable.getIndexes().values()) { + st.execute(ind.getSql()); + }*/ + String errText = lang.getValue("errors", "meta", "notFound").withParams(obj.getName()); + throw new ExceptionDBGitRestore(errText); + } + } + else + { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); + } + } catch (Exception e) { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); + } finally { + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + st.close(); + } + } + + private void restoreTableConstraintMssql(IMetaObject obj) throws Exception { + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "restoreConstr").withParams(obj.getName()), messageLevel); + try { + if (obj instanceof MetaTable) { + MetaTable restoreTable = (MetaTable)obj; + String schema = getPhisicalSchema(restoreTable.getTable().getSchema()); + schema = (SchemaSynonym.getInstance().getSchema(schema) == null) ? schema : SchemaSynonym.getInstance().getSchema(schema); + for(DBConstraint constraint :restoreTable.getConstraints().values()) { + if(!getIsPk(constraint)) { + String ddl = constraint.getSql(); + ddl = ddl.replaceFirst("ALTER TABLE\\s+\\[?\\w+\\]?.\\[?\\w+\\]?\\s+ADD\\s+CONSTRAINT\\s+\\[?\\w+\\]?\\s+", ""); + ddl = MessageFormat.format( + "ALTER TABLE {0}.{1} ADD CONSTRAINT [{2}] {3}", + schema, restoreTable.getTable().getName(), constraint.getName(), ddl + ) + .replace(" "+constraint.getSchema()+".", " "+schema+".") + .replace("REFERENCES ", "REFERENCES " + schema + "."); + + st.execute(ddl); + } + } + } + else + { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "table", obj.getType().getValue() + )); + } + } catch (Exception e) { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); + } finally { + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + st.close(); + } + } + + public void removeMetaObject(IMetaObject obj) throws Exception { + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + + try { + MetaTable tblMeta = (MetaTable)obj; + DBTable tbl = tblMeta.getTable(); + + if (tbl == null) return; + + String schema = getPhisicalSchema(tbl.getSchema()); + schema = (SchemaSynonym.getInstance().getSchema(schema) == null) ? schema : SchemaSynonym.getInstance().getSchema(schema); + st.execute( + "IF EXISTS ( SELECT * FROM sys.tables t WHERE t.name = N'"+tbl.getName()+"' AND t.schema = "+schema+")\n" + + "DROP TABLE ["+schema+"].["+tbl.getName()+"];" + ); + + } catch (Exception e) { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRemoveError").withParams(obj.getName()), e); + } finally { + st.close(); + } + } + + private boolean isTablePresent(String schemaName, String tableName){ + Map tables = adapter.getTables(schemaName); + if(tables != null && !tables.isEmpty()) { + for(DBTable current:tables.values()) { + if(tableName.equalsIgnoreCase(current.getName())){ + return true; + } + } + } + return false; + } + + private void restoreTableFieldsMssql(MetaTable restoreTable, String tblName, String tblSchema, StatementLogging st) throws SQLException { + //restore tabl fields + String tblSam = tblSchema+"."+tblName; + Map currentFields = adapter.getTableFields(tblSchema, restoreTable.getTable().getName().toLowerCase()); + MapDifference diffTableFields = Maps.difference(restoreTable.getFields(),currentFields); + Map restoringUniqueFields = diffTableFields.entriesOnlyOnLeft(); + Map existingUniqueFields = diffTableFields.entriesOnlyOnRight(); + Map> mergingFields = diffTableFields.entriesDiffering(); + + + if( !restoringUniqueFields.isEmpty()){ + ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "addColumns"), messageLevel); + + List values = restoringUniqueFields.values() + .stream() + .sorted(Comparator.comparing(DBTableField::getOrder)) + .collect(Collectors.toList()); + + for(DBTableField tblField : values) { + String fieldDdl = MessageFormat.format("ALTER TABLE {0} ADD [{1}] {2}", tblSam, tblField.getName(), tblField.getTypeSQL()); + st.execute(fieldDdl); + } + + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + } + + if( !existingUniqueFields.isEmpty()) { + ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "droppingColumns"), messageLevel); + + for(DBTableField tblField:existingUniqueFields.values()) { + String fieldDdl = MessageFormat.format("ALTER TABLE {1} DROP COLUMN [{2}]", tblSam, tblField.getName()); + st.execute(fieldDdl); + } + + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + } + + if(!mergingFields.isEmpty()) { + ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "modifyColumns"), messageLevel); + + for(ValueDifference fld : mergingFields.values()) { + DBTableField oldValue = fld.rightValue(); + DBTableField newValue = fld.leftValue(); + + if(!newValue.getName().equals(oldValue.getName())) { + String fieldDdl = MessageFormat.format( + "EXEC sp_RENAME '{1}.{2}' , '{3}', 'COLUMN'", + tblSam, oldValue.getName(), newValue.getName() + ); + st.execute(fieldDdl); + } + + //if types differ + if( !newValue.getTypeSQL().equals(oldValue.getTypeSQL()) ) { + st.execute("ALTER TABLE "+ tblName +" ALTER COLUMN "+ newValue.getName() +" "+ newValue.getTypeSQL()); + } + } + + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + } + } + + private void removeTableConstraintsMssql(IMetaObject obj) throws Exception { + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + try { + if (obj instanceof MetaTable) { + MetaTable table = (MetaTable)obj; + String schema = getPhisicalSchema(table.getTable().getSchema()); + schema = (SchemaSynonym.getInstance().getSchema(schema) == null) ? schema : SchemaSynonym.getInstance().getSchema(schema); + //String s = "SELECT COUNT(*) as constraintscount FROM pg_catalog.pg_constraint r WHERE r.conrelid = '"+table.getTable().getSchema()+"."+table.getTable().getName()+"'::regclass"; + //ResultSet rs = st.executeQuery("SELECT COUNT(*) as constraintscount FROM pg_catalog.pg_constraint r WHERE r.conrelid = '"+table.getTable().getSchema()+"."+table.getTable().getName()+"'::regclass"); + //rs.next(); + //Integer constraintsCount = Integer.valueOf(rs.getString("constraintscount")); + //if(constraintsCount.intValue()>0) { + Map constraints = table.getConstraints(); + for(DBConstraint constrs :constraints.values()) { + if (!constrs.getConstraintType().equalsIgnoreCase("p")) + st.execute("alter table "+ schema+"."+table.getTable().getName() +" drop constraint IF EXISTS "+constrs.getName()); + } + //} + } + else + { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "table", obj.getType().getValue() + )); + } + } catch (Exception e) { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); + } + } + + private boolean getIsPk(DBConstraint dbConstraint){ + StringProperties prop = dbConstraint.getOptions().get("ispk"); + return prop != null && prop.getData().equals("1"); + } + + private void restoreTablePksMssql(MetaTable restoreTable, StatementLogging st) throws SQLException { + ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "addPk"), messageLevel); + String tblSchema = restoreTable.getTable().getSchema(); + String tblName = restoreTable.getTable().getName(); + boolean flagPkCreated = false; + + List pkConstraints = Lists.newArrayList(restoreTable.getConstraints().values()); + pkConstraints.removeIf( x-> !getIsPk(x) ); + if(pkConstraints.size() > 1) throw new SQLException(); + + for(DBConstraint pk : pkConstraints){ + String ddl = pk.getSql(); + ddl = ddl.replaceFirst("ALTER TABLE\\s+\\[?\\w+\\]?.\\[?\\w+\\]?\\s+ADD\\s+CONSTRAINT\\s+\\[?\\w+\\]?\\s+", ""); + ddl = MessageFormat.format( + "ALTER TABLE {0}.{1} ADD CONSTRAINT [{2}] {3}", + tblSchema, tblName, pk.getName(), ddl + ); + ddl = ddl.replace(" "+pk.getSchema()+".", " "+restoreTable.getTable().getSchema()+"."); + + st.execute(ddl); + } + + + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + flagPkCreated = true; + + if (!flagPkCreated) { + for(DBTableField field: restoreTable.getFields().values()) { + if (field.getIsPrimaryKey()) { + ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "addPk"), messageLevel); + + String ddl = MessageFormat.format( + "ALTER TABLE {0} ADD CONSTRAINT PK_{1}_{2} PRIMARY KEY([{2}])", + tblName, restoreTable.getTable().getName(), field.getName() + ); + st.execute(ddl); + + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); break; + } + } + } + } + +} diff --git a/src/main/java/ru/fusionsoft/dbgit/mssql/DBRestoreTableSpaceMssql.java b/src/main/java/ru/fusionsoft/dbgit/mssql/DBRestoreTableSpaceMssql.java new file mode 100644 index 0000000..4ac2efc --- /dev/null +++ b/src/main/java/ru/fusionsoft/dbgit/mssql/DBRestoreTableSpaceMssql.java @@ -0,0 +1,96 @@ +package ru.fusionsoft.dbgit.mssql; + +import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter; +import ru.fusionsoft.dbgit.adapters.IDBAdapter; +import ru.fusionsoft.dbgit.core.DBGitConfig; +import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; +import ru.fusionsoft.dbgit.dbobjects.DBTableSpace; +import ru.fusionsoft.dbgit.meta.IMetaObject; +import ru.fusionsoft.dbgit.meta.MetaTableSpace; +import ru.fusionsoft.dbgit.statement.StatementLogging; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; + +import java.sql.Connection; +import java.util.Map; + +public class DBRestoreTableSpaceMssql extends DBRestoreAdapter{ + + @Override + public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + try { + if (obj instanceof MetaTableSpace) { + MetaTableSpace restoreTableSpace = (MetaTableSpace)obj; + Map tblspaces = adapter.getTableSpaces(); + boolean exist = false; + if(!(tblspaces.isEmpty() || tblspaces == null)) { + for(DBTableSpace tblspace:tblspaces.values()) { + if(restoreTableSpace.getObjectOption().getName().equals(tblspace.getName())){ + exist = true; + + String restorename = restoreTableSpace.getObjectOption().getName(); + String restoreowner = restoreTableSpace.getObjectOption().getOptions().getChildren().get("usename").getData(); + String restoreloc = restoreTableSpace.getObjectOption().getOptions().getChildren().get("pg_tablespace_location").getData(); + + // TODO MSSQL restore MetaObject script + st.execute("alter tablespace "+ restorename +" reset (seq_page_cost, random_page_cost, effective_io_concurrency)"); + + String currentname = tblspace.getName(); + String currentowner = tblspace.getOptions().getChildren().get("usename").getData(); + String currentloc = tblspace.getOptions().getChildren().get("pg_tablespace_location").getData(); + + + if(!DBGitConfig.getInstance().getToIgnoreOnwer(false)){ + if(!restoreowner.equals(currentowner)) { + st.execute("alter tablespace "+ restorename +" owner to "+ restoreowner); + } + } + if(restoreTableSpace.getObjectOption().getOptions().getChildren().containsKey("spcoptions")) { + String options = restoreTableSpace.getObjectOption().getOptions().getChildren().get("spcoptions").getData().replaceAll("[\\{\\}]", ""); + st.execute("alter tablespace "+ restorename +" set ("+ options+")"); + } + + + /*if() { + //TODO Restore location ??? + }*/ + //TODO Восстановление привилегий + } + } + } + if(!exist){ + + //TODO Восстановление привилегий + } + else { + + } + } + else + { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "tablespace", obj.getType().getValue() + )); + } + } catch (Exception e) { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError") + .withParams(obj.getName()) + , e + ); + } finally { + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + st.close(); + } + return true; + } + + @Override + public void removeMetaObject(IMetaObject obj) throws Exception { + // TODO Auto-generated method stub + + } + +} diff --git a/src/main/java/ru/fusionsoft/dbgit/mssql/DBRestoreTriggerMssql.java b/src/main/java/ru/fusionsoft/dbgit/mssql/DBRestoreTriggerMssql.java new file mode 100644 index 0000000..dcd0a3e --- /dev/null +++ b/src/main/java/ru/fusionsoft/dbgit/mssql/DBRestoreTriggerMssql.java @@ -0,0 +1,95 @@ +package ru.fusionsoft.dbgit.mssql; + +import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter; +import ru.fusionsoft.dbgit.adapters.IDBAdapter; +import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; +import ru.fusionsoft.dbgit.dbobjects.DBFunction; +import ru.fusionsoft.dbgit.dbobjects.DBSQLObject; +import ru.fusionsoft.dbgit.dbobjects.DBTrigger; +import ru.fusionsoft.dbgit.meta.IMetaObject; +import ru.fusionsoft.dbgit.meta.MetaFunction; +import ru.fusionsoft.dbgit.meta.MetaTrigger; +import ru.fusionsoft.dbgit.statement.StatementLogging; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; + +import java.sql.Connection; +import java.text.MessageFormat; +import java.util.Map; + +public class DBRestoreTriggerMssql extends DBRestoreAdapter { + + + @Override + public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + try { + if (obj instanceof MetaTrigger) { + MetaTrigger restoreTrigger = (MetaTrigger)obj; + DBSQLObject restoringDBT = restoreTrigger.getSqlObject(); + String triggerName = restoringDBT.getName(); + String triggerSchema = restoringDBT.getSchema(); + Map triggers = adapter.getTriggers(triggerSchema); + + if(triggers.containsKey(triggerName)){ + DBTrigger existingDBT = triggers.get(triggerName); + boolean ddlsDiffer = !restoringDBT.getSql().equals(existingDBT.getSql()); + + if(ddlsDiffer) { + st.execute(MessageFormat.format("DROP TRIGGER {0}.{1}", existingDBT.getOwner(), existingDBT.getName())); + st.execute(restoreTrigger.getSqlObject().getSql()); + } + + //TODO should never differ, I guess + //boolean ownersDiffer = !restoringDBF.getOwner().equals(existingDBF.getOwner()); + /*if(ownersDiffer) { + String ddl = MessageFormat.format( + "ALTER SCHEMA {0} TRANSFER {1}.{2}", + restoringDBF.getOwner(), existingDBF.getOwner(), triggerName + ); + st.execute(ddl); + }*/ + } else { + String ddl = restoringDBT.getSql(); + if(!ddl.isEmpty()){ + st.execute(ddl); + } else { + ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "encrypted").withParams(triggerName), messageLevel); + } + } + } + else + { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "trigger", obj.getType().getValue() + )); + } + + } + catch (Exception e) { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); + } finally { + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + st.close(); + } + + + + + + + + + + return true; + } + + @Override + public void removeMetaObject(IMetaObject obj) throws Exception { + // TODO Auto-generated method stub + + } + +} diff --git a/src/main/java/ru/fusionsoft/dbgit/mssql/DBRestoreUserMssql.java b/src/main/java/ru/fusionsoft/dbgit/mssql/DBRestoreUserMssql.java new file mode 100644 index 0000000..d757fa3 --- /dev/null +++ b/src/main/java/ru/fusionsoft/dbgit/mssql/DBRestoreUserMssql.java @@ -0,0 +1,82 @@ +package ru.fusionsoft.dbgit.mssql; + +import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter; +import ru.fusionsoft.dbgit.adapters.IDBAdapter; +import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; +import ru.fusionsoft.dbgit.meta.IMetaObject; +import ru.fusionsoft.dbgit.meta.MetaUser; +import ru.fusionsoft.dbgit.statement.StatementLogging; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; +import ru.fusionsoft.dbgit.utils.StringProperties; + +import java.sql.Connection; +import java.text.MessageFormat; +import java.util.Objects; + +public class DBRestoreUserMssql extends DBRestoreAdapter{ + + @Override + public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + try { + if (obj instanceof MetaUser) { + MetaUser usr = (MetaUser)obj; + StringProperties opts = usr.getObjectOption().getOptions(); + StringProperties ddl = opts.get("ddl"); + boolean isMssqlDdl = Objects.nonNull(ddl) && ddl.getData().contains("CREATE LOGIN"); + + if(isMssqlDdl) { st.execute(ddl.getData()); } else { + + StringProperties loginName = opts.get("loginName"); + StringProperties userName = opts.get("userName"); + StringProperties passwordHash = opts.get("passwordHash"); + StringProperties isDisabledLogin = opts.get("isDisabledLogin"); + StringProperties defaultSchema = opts.get("schemaName"); + + String loginNameActual = (loginName != null) ? loginName.getData() : usr.getName(); + String userNameActual = (userName != null) ? userName.getData() : usr.getName(); + + String withPasswordTerm = (passwordHash != null) + ? MessageFormat.format("WITH PASSWORD = {0} HASHED", passwordHash.getData()) : ""; + + String grantConnectTerm = (isDisabledLogin == null || isDisabledLogin.getData().equals("0")) + ? MessageFormat.format("GRANT CONNECT SQL TO [{0}];", loginNameActual) : ""; + + String withDefaultSchemaTerm = (defaultSchema != null) + ? MessageFormat.format("WITH DEFAULT SCHEMA {0}", defaultSchema.getData()) : ""; + + String createLoginTerm = MessageFormat.format("CREATE LOGIN [{0}] {1}; {2} CREATE USER [{3}] FOR LOGIN {0} {4};", + loginNameActual, + withPasswordTerm, + grantConnectTerm, + userNameActual, + withDefaultSchemaTerm + ); + st.execute(createLoginTerm); + } + } + else + { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "user", obj.getType().getValue() + )); + } + } catch (Exception e) { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); + } finally { + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + st.close(); + } + return true; + } + + @Override + public void removeMetaObject(IMetaObject obj) throws Exception { + // TODO Auto-generated method stub + + } + +} diff --git a/src/main/java/ru/fusionsoft/dbgit/mssql/DBRestoreViewMssql.java b/src/main/java/ru/fusionsoft/dbgit/mssql/DBRestoreViewMssql.java new file mode 100644 index 0000000..86da9c0 --- /dev/null +++ b/src/main/java/ru/fusionsoft/dbgit/mssql/DBRestoreViewMssql.java @@ -0,0 +1,81 @@ +package ru.fusionsoft.dbgit.mssql; + +import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter; +import ru.fusionsoft.dbgit.adapters.IDBAdapter; +import ru.fusionsoft.dbgit.core.DBGitConfig; +import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; +import ru.fusionsoft.dbgit.dbobjects.DBView; +import ru.fusionsoft.dbgit.meta.IMetaObject; +import ru.fusionsoft.dbgit.meta.MetaView; +import ru.fusionsoft.dbgit.statement.StatementLogging; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; + +import java.sql.Connection; +import java.util.Map; + +public class DBRestoreViewMssql extends DBRestoreAdapter { + + @Override + public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + try { + if (obj instanceof MetaView) { + MetaView restoreView = (MetaView)obj; + Map views = adapter.getViews(restoreView.getSqlObject().getSchema()); + boolean exist = false; + if(!(views.isEmpty() || views == null)) { + for(DBView vw:views.values()) { + if(restoreView.getSqlObject().getName().equals(vw.getName())){ + exist = true; + // TODO MSSQL restore View script + if(!restoreView.getSqlObject().getSql().equals(vw.getSql())) { + st.execute(restoreView.getSqlObject().getName() +" AS\n"+restoreView.getSqlObject().getSql()); + } + + if(!restoreView.getSqlObject().getOwner().equals(vw.getOwner())) { + //st.execute("ALTER VIEW "+restoreView.getSqlObject().getName() +" OWNER TO "+restoreView.getSqlObject().getOwner()); + } + //TODO Восстановление привилегий + } + } + } + if(!exist){ + String query = restoreView.getSqlObject().getSql(); + + if (!query.endsWith(";")) query = query + ";"; + query = query + "\n"; + + if(!DBGitConfig.getInstance().getToIgnoreOnwer(false)){ + query+= "ALTER VIEW "+restoreView.getSqlObject().getName() +" OWNER TO \""+restoreView.getSqlObject().getOwner()+"\";\n"; + } + + st.execute(query); + + //TODO Восстановление привилегий + } + } + else + { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "view", obj.getType().getValue() + )); + } + } catch (Exception e) { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); + } finally { + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + st.close(); + } + return true; + } + + @Override + public void removeMetaObject(IMetaObject obj) throws Exception { + // TODO Auto-generated method stub + + } + +} diff --git a/src/main/java/ru/fusionsoft/dbgit/mssql/FactoryDBAdapterRestoreMssql.java b/src/main/java/ru/fusionsoft/dbgit/mssql/FactoryDBAdapterRestoreMssql.java new file mode 100644 index 0000000..c80150e --- /dev/null +++ b/src/main/java/ru/fusionsoft/dbgit/mssql/FactoryDBAdapterRestoreMssql.java @@ -0,0 +1,53 @@ +package ru.fusionsoft.dbgit.mssql; + +import ru.fusionsoft.dbgit.adapters.IDBAdapter; +import ru.fusionsoft.dbgit.adapters.IDBAdapterRestoreMetaData; +import ru.fusionsoft.dbgit.adapters.IFactoryDBAdapterRestoteMetaData; +import ru.fusionsoft.dbgit.core.DBGitLang; +import ru.fusionsoft.dbgit.meta.DBGitMetaType; +import ru.fusionsoft.dbgit.meta.IDBGitMetaType; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + + +public class FactoryDBAdapterRestoreMssql implements IFactoryDBAdapterRestoteMetaData { + + private static final Map restoreAdapters; + static { + Map aMap = new HashMap(); + aMap.put(DBGitMetaType.DBGitSchema.getValue(), new DBRestoreSchemaMssql()); + aMap.put(DBGitMetaType.DBGitTableSpace.getValue(), new DBRestoreTableSpaceMssql()); + aMap.put(DBGitMetaType.DBGitRole.getValue(), new DBRestoreRoleMssql()); + aMap.put(DBGitMetaType.DBGitSequence.getValue(), new DBRestoreSequenceMssql()); + aMap.put(DBGitMetaType.DBGitTable.getValue(), new DBRestoreTableMssql()); + aMap.put(DBGitMetaType.DbGitTableData.getValue(), new DBRestoreTableDataMssql()); + aMap.put(DBGitMetaType.DbGitProcedure.getValue(), new DBRestoreProcedureMssql()); + aMap.put(DBGitMetaType.DbGitFunction.getValue(), new DBRestoreFunctionMssql()); + aMap.put(DBGitMetaType.DbGitTrigger.getValue(), new DBRestoreTriggerMssql()); + aMap.put(DBGitMetaType.DbGitView.getValue(), new DBRestoreViewMssql()); + aMap.put(DBGitMetaType.DBGitUser.getValue(), new DBRestoreUserMssql()); + + + + //TODO other restore adapter + + restoreAdapters = Collections.unmodifiableMap(aMap); + } + + @Override + public IDBAdapterRestoreMetaData getAdapterRestore(IDBGitMetaType tp, IDBAdapter adapter) { + if (!restoreAdapters.containsKey(tp.getValue())) { + //return new DBRestoreMetaNotSupport(); + ConsoleWriter.println(DBGitLang.getInstance().getValue("errors", "restore", "cannotRestore").withParams(tp.getValue()), messageLevel); + return null; + } + + IDBAdapterRestoreMetaData re = restoreAdapters.get(tp.getValue()); + re.setAdapter(adapter); + return re; + } + +} diff --git a/src/main/java/ru/fusionsoft/dbgit/mssql/FactoryDBBackupAdapterMssql.java b/src/main/java/ru/fusionsoft/dbgit/mssql/FactoryDBBackupAdapterMssql.java new file mode 100644 index 0000000..a05b497 --- /dev/null +++ b/src/main/java/ru/fusionsoft/dbgit/mssql/FactoryDBBackupAdapterMssql.java @@ -0,0 +1,24 @@ +package ru.fusionsoft.dbgit.mssql; + +import ru.fusionsoft.dbgit.adapters.IDBAdapter; +import ru.fusionsoft.dbgit.adapters.IDBBackupAdapter; +import ru.fusionsoft.dbgit.adapters.IFactoryDBBackupAdapter; +import ru.fusionsoft.dbgit.core.DBGitConfig; + +public class FactoryDBBackupAdapterMssql implements IFactoryDBBackupAdapter { + + private IDBBackupAdapter backupAdapter = null; + + @Override + public IDBBackupAdapter getBackupAdapter(IDBAdapter adapter) throws Exception { + if (backupAdapter == null) { + backupAdapter = new DBBackupAdapterMssql(); + backupAdapter.setAdapter(adapter); + backupAdapter.saveToSchema(DBGitConfig.getInstance().getBoolean("core", "BACKUP_TO_SCHEME", false)); + backupAdapter.setToSaveData(DBGitConfig.getInstance().getBoolean("core", "BACKUP_TABLEDATA", false)); + } + + return backupAdapter; + } + +} diff --git a/src/main/java/ru/fusionsoft/dbgit/mssql/FactoryDbConvertAdapterMssql.java b/src/main/java/ru/fusionsoft/dbgit/mssql/FactoryDbConvertAdapterMssql.java new file mode 100644 index 0000000..d20e7b3 --- /dev/null +++ b/src/main/java/ru/fusionsoft/dbgit/mssql/FactoryDbConvertAdapterMssql.java @@ -0,0 +1,39 @@ +package ru.fusionsoft.dbgit.mssql; + +import ru.fusionsoft.dbgit.adapters.IDBConvertAdapter; +import ru.fusionsoft.dbgit.adapters.IFactoryDBConvertAdapter; +import ru.fusionsoft.dbgit.core.DBGitLang; +import ru.fusionsoft.dbgit.meta.DBGitMetaType; +import ru.fusionsoft.dbgit.mssql.converters.TableConverterMssql; +import ru.fusionsoft.dbgit.mssql.converters.TableDataConverterMssql; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public class FactoryDbConvertAdapterMssql implements IFactoryDBConvertAdapter { + + private static final Map converters; + + static { + Map aMap = new HashMap(); + aMap.put(DBGitMetaType.DBGitTable.getValue(), new TableConverterMssql()); + aMap.put(DBGitMetaType.DbGitTableData.getValue(), new TableDataConverterMssql()); + + converters = Collections.unmodifiableMap(aMap); + } + + @Override + public IDBConvertAdapter getConvertAdapter(String objectType) throws Exception { + if (!converters.containsKey(objectType)) { + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("errors", "convert", "cannotConvert") + .withParams(objectType) + , 1 + ); + return null; + } else + return converters.get(objectType); + } +} diff --git a/src/main/java/ru/fusionsoft/dbgit/mssql/converters/TableConverterMssql.java b/src/main/java/ru/fusionsoft/dbgit/mssql/converters/TableConverterMssql.java new file mode 100644 index 0000000..c5c0f50 --- /dev/null +++ b/src/main/java/ru/fusionsoft/dbgit/mssql/converters/TableConverterMssql.java @@ -0,0 +1,60 @@ +package ru.fusionsoft.dbgit.mssql.converters; + +import ru.fusionsoft.dbgit.adapters.IDBConvertAdapter; +import ru.fusionsoft.dbgit.adapters.IFactoryDBConvertAdapter; +import ru.fusionsoft.dbgit.core.ExceptionDBGit; +import ru.fusionsoft.dbgit.core.db.DbType; +import ru.fusionsoft.dbgit.dbobjects.DBConstraint; +import ru.fusionsoft.dbgit.dbobjects.DBIndex; +import ru.fusionsoft.dbgit.dbobjects.DBTableField; +import ru.fusionsoft.dbgit.meta.IMetaObject; +import ru.fusionsoft.dbgit.meta.MetaTable; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class TableConverterMssql implements IDBConvertAdapter { + + @Override + public IMetaObject convert(DbType dbType, String dbVersion, IMetaObject obj) throws ExceptionDBGit { + + /* + if (dbType.equals(obj.getDbType())) + return obj; + + if (obj instanceof MetaTable) { + + MetaTable table = (MetaTable) obj; + + ConsoleWriter.println("Processing table " + table.getName()); + + //types + for (DBTableField field : table.getFields().values()) { + if (obj.getDbType().equals(IFactoryDBConvertAdapter.MSSQL)) + field.setTypeSQL(typeFromOracle(field)); + } + + //indexes + for (DBIndex index : table.getIndexes().values()) { + if (obj.getDbType().equals(IFactoryDBConvertAdapter.MSSQL)) + index.getOptions().get("ddl").setData(indexFromOracle(index)); + } + + //constraints + for (DBConstraint constraint : table.getConstraints().values()) { + if (obj.getDbType().equals(IFactoryDBConvertAdapter.MSSQL)) + constraint.getOptions().get("ddl").setData(constraintFromOracle(constraint)); + } + + } else { + throw new ExceptionDBGit("Cannot convert " + obj.getName()); + } + + obj.setDbType(IFactoryDBConvertAdapter.MSSQL); + */ + + return obj; + } + +} diff --git a/src/main/java/ru/fusionsoft/dbgit/mssql/converters/TableDataConverterMssql.java b/src/main/java/ru/fusionsoft/dbgit/mssql/converters/TableDataConverterMssql.java new file mode 100644 index 0000000..576fa1c --- /dev/null +++ b/src/main/java/ru/fusionsoft/dbgit/mssql/converters/TableDataConverterMssql.java @@ -0,0 +1,22 @@ +package ru.fusionsoft.dbgit.mssql.converters; + +import ru.fusionsoft.dbgit.adapters.IDBConvertAdapter; +import ru.fusionsoft.dbgit.core.ExceptionDBGit; +import ru.fusionsoft.dbgit.core.db.DbType; +import ru.fusionsoft.dbgit.meta.IMetaObject; + +public class TableDataConverterMssql implements IDBConvertAdapter { + + /* + @Override + public IMetaObject convert(String dbType, String dbVersion, IMetaObject obj) throws ExceptionDBGit { + //TODO MSSQL TableData convert method + return obj; + } + */ + + @Override + public IMetaObject convert(DbType dbType, String dbVersion, IMetaObject obj) throws ExceptionDBGit { + return obj; + } +} diff --git a/src/main/java/ru/fusionsoft/dbgit/mysql/DBAdapterMySql.java b/src/main/java/ru/fusionsoft/dbgit/mysql/DBAdapterMySql.java index 1d93259..563da91 100644 --- a/src/main/java/ru/fusionsoft/dbgit/mysql/DBAdapterMySql.java +++ b/src/main/java/ru/fusionsoft/dbgit/mysql/DBAdapterMySql.java @@ -6,12 +6,12 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; +import java.text.MessageFormat; +import java.util.*; import java.util.concurrent.TimeUnit; +import com.google.common.collect.ImmutableMap; +import org.apache.commons.lang3.exception.ExceptionUtils; import org.slf4j.Logger; import com.axiomalaska.jdbc.NamedParameterPreparedStatement; @@ -20,18 +20,12 @@ import ru.fusionsoft.dbgit.adapters.IFactoryDBAdapterRestoteMetaData; import ru.fusionsoft.dbgit.adapters.IFactoryDBBackupAdapter; import ru.fusionsoft.dbgit.adapters.IFactoryDBConvertAdapter; -import ru.fusionsoft.dbgit.core.DBGitConfig; -import ru.fusionsoft.dbgit.core.DBGitLang; -import ru.fusionsoft.dbgit.core.ExceptionDBGit; -import ru.fusionsoft.dbgit.core.ExceptionDBGitRunTime; +import ru.fusionsoft.dbgit.core.*; import ru.fusionsoft.dbgit.core.db.DbType; import ru.fusionsoft.dbgit.core.db.FieldType; -import ru.fusionsoft.dbgit.data_table.DateData; -import ru.fusionsoft.dbgit.data_table.FactoryCellData; -import ru.fusionsoft.dbgit.data_table.LongData; -import ru.fusionsoft.dbgit.data_table.MapFileData; -import ru.fusionsoft.dbgit.data_table.StringData; import ru.fusionsoft.dbgit.dbobjects.DBConstraint; +import ru.fusionsoft.dbgit.dbobjects.DBDomain; +import ru.fusionsoft.dbgit.dbobjects.DBEnum; import ru.fusionsoft.dbgit.dbobjects.DBFunction; import ru.fusionsoft.dbgit.dbobjects.DBIndex; import ru.fusionsoft.dbgit.dbobjects.DBPackage; @@ -45,8 +39,10 @@ import ru.fusionsoft.dbgit.dbobjects.DBTableSpace; import ru.fusionsoft.dbgit.dbobjects.DBTrigger; import ru.fusionsoft.dbgit.dbobjects.DBUser; +import ru.fusionsoft.dbgit.dbobjects.DBUserDefinedType; import ru.fusionsoft.dbgit.dbobjects.DBView; import ru.fusionsoft.dbgit.meta.IMapMetaObject; +import ru.fusionsoft.dbgit.meta.TreeMapMetaObject; import ru.fusionsoft.dbgit.statement.StatementLogging; import ru.fusionsoft.dbgit.utils.ConsoleWriter; import ru.fusionsoft.dbgit.utils.LoggerUtil; @@ -58,48 +54,141 @@ public class DBAdapterMySql extends DBAdapter { private FactoryDBRestoreAdapterMySql restoreFactory = new FactoryDBRestoreAdapterMySql(); private FactoryDBConvertAdapterMySql convertFactory = new FactoryDBConvertAdapterMySql(); private FactoryDBBackupAdapterMySql backupFactory = new FactoryDBBackupAdapterMySql(); + public final static Set reservedWords = new HashSet<>(); + + public String escapeNameIfNeeded(String name) { + boolean shouldBeEscaped = false; + //TODO Permitted characters in unquoted identifiers: + //ASCII: [0-9,a-z,A-Z$_] (basic Latin letters, digits 0-9, dollar, underscore) + //Extended: U+0080 .. U+FFFF + //Permitted characters in quoted identifiers include the full Unicode Basic Multilingual Plane (BMP), except U+0000: + //ASCII: U+0001 .. U+007F + //Extended: U+0080 .. U+FFFF + if(reservedWords.contains(name.toUpperCase())) shouldBeEscaped = true; + if(name.charAt(0) == '`' || name.charAt(name.length()-1) == '`') shouldBeEscaped = false; + if(shouldBeEscaped){ + return MessageFormat.format("`{0}`", name); + } + return name; + } @Override public IFactoryDBAdapterRestoteMetaData getFactoryRestore() { return restoreFactory; } + @Override + public IFactoryDBConvertAdapter getConvertAdapterFactory() { + return convertFactory; + } + @Override + public IFactoryDBBackupAdapter getBackupAdapterFactory() { + return backupFactory; + } @Override - public void startUpdateDB() { + public boolean userHasRightsToGetDdlOfOtherUsers() { + return true; + } + + @Override + public DbType getDbType() { + return DbType.MYSQL; + } + @Override + public String getDbVersion() { + try ( + PreparedStatement stmt = getConnection().prepareStatement("SELECT version()"); + ResultSet resultSet = stmt.executeQuery(); + ) { + if(!resultSet.next()) throw new ExceptionDBGitRunTime("failed to get db version resultset"); + final String result = resultSet.getString(1); + + return result; + } catch (SQLException e) { + throw new ExceptionDBGitRunTime("failed to get db version resultset"); + } + } + @Override + public String getDefaultScheme() { + try { + return getConnection().getCatalog(); + } catch (SQLException e) { + final DBGitLang msg = lang.getValue("errors", "adapter", "getSchema"); + throw new ExceptionDBGitRunTime(msg); + } + } + + @Override + public void createSchemaIfNeed(String schemaName) throws ExceptionDBGit { + final String query = + "select count(*) cnt " + + "from information_schema.schemata " + + "where upper(schema_name) = '" + schemaName.toUpperCase() + "'"; + + try ( + Statement st = connect.createStatement(); + ResultSet rs = st.executeQuery(query); + ) { + + if(!rs.next()) throw new ExceptionDBGitRunTime("failed to get schemas count resultset"); + + if (rs.getInt("cnt") == 0){ + try(StatementLogging stLog = new StatementLogging(connect, getStreamOutputSqlCommand(), isExecSql());) { + stLog.execute("create schema " + schemaName); + } + } + + } catch (SQLException e) { + final DBGitLang msg = lang.getValue("errors", "adapter", "createSchema"); + throw new ExceptionDBGit(msg); + } + } + @Override + public void createRoleIfNeed(String roleName) throws ExceptionDBGit { // TODO Auto-generated method stub } + @Override + public boolean isReservedWord(String word) { + return reservedWords.contains(word.toUpperCase()); + } + + @Override + public void startUpdateDB() { + // TODO Auto-generated method stub + } @Override public void endUpdateDB() { // TODO Auto-generated method stub - } @Override public IMapMetaObject loadCustomMetaObjects() { - return null; + return new TreeMapMetaObject(Collections.emptyList()); } @Override public Map getSchemes() { - Map listScheme = new HashMap(); - try { - String query = "select schema_name\r\n" + - "from information_schema.schemata"; - Connection connect = getConnection(); - Statement stmt = connect.createStatement(); + final Map listScheme = new HashMap(); + final String query = + "select schema_name\r\n" + + "from information_schema.schemata"; + + try ( + Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query); + ){ + while(rs.next()){ - String name = rs.getString("schema_name"); - DBSchema scheme = new DBSchema(name); - rowToProperties(rs, scheme.getOptions()); - listScheme.put(name, scheme); - } - stmt.close(); - }catch(Exception e) { - logger.error(lang.getValue("errors", "adapter", "schemes").toString(), e); - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "schemes").toString(), e); + final String name = rs.getString("schema_name"); + final DBSchema scheme = new DBSchema(name, new StringProperties(rs)); + listScheme.put(name, scheme); + } + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "schemes").toString(); + throw new ExceptionDBGitRunTime(msg, e); } return listScheme; @@ -107,586 +196,691 @@ public Map getSchemes() { @Override public Map getTableSpaces() { - // TODO Auto-generated method stub - return null; + return Collections.emptyMap(); } @Override public Map getSequences(String schema) { - Map sequences = new HashMap(); - try { - String query = "select column_name, table_name, column_type, extra from information_schema.columns" + - " where extra like '%auto_increment%' and table_schema='" + schema + "'"; - Connection connect = getConnection(); - Statement stmt = connect.createStatement(); + final Map sequences = new HashMap<>(); + final String query = + " select column_name, table_name, column_type, extra " + + " from information_schema.columns" + + " where extra like '%auto_increment%' and table_schema='" + schema + "'"; + + try( + Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query); + ) { + while(rs.next()) { - String name = rs.getString("column_name"); - DBSequence seq = new DBSequence(name); - Statement stmtValue = connect.createStatement(); - ResultSet rsValue = stmtValue.executeQuery("select coalesce(max(" + rs.getString("column_name") + "), 0) as nextval" + - " from " + schema + ".`" + rs.getString("table_name") + "`"); - rsValue.next(); - seq.setSchema(schema); - seq.setValue(rsValue.getLong("nextval")); - sequences.put(name, seq); - stmtValue.close(); + + final String valueQuery = + " select coalesce(max(" + rs.getString("column_name") + "), 0) as nextval" + + " from " + schema + ".`" + rs.getString("table_name") + "`"; + + try(Statement stmtValue = getConnection().createStatement(); ResultSet rsValue = stmtValue.executeQuery(valueQuery)){ + if(rsValue.next()){ + final String name = rs.getString("column_name"); + final String owner = ""; + final Long value = rsValue.getLong("nextval"); + final DBSequence seq = new DBSequence(name, new StringProperties(rs), schema, owner, Collections.emptySet(), value); + sequences.put(name, seq); + } + } + } - stmt.close(); } catch(Exception e) { - logger.error(lang.getValue("errors", "adapter", "seq").toString(), e); - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "seq").toString(), e); + final String msg = lang.getValue("errors", "adapter", "seq").toString(); + throw new ExceptionDBGitRunTime(msg, e); } return sequences; } @Override public DBSequence getSequence(String schema, String name) { - DBSequence seq = null; - try { - String query = "select column_name, table_name, column_type, extra from information_schema.columns" + - " where extra like '%auto_increment%' and table_schema='" + schema + "' and column_name='" + name + "'"; - Connection connect = getConnection(); - Statement stmt = connect.createStatement(); + final String query = + "select column_name, table_name, column_type, extra from information_schema.columns" + + " where extra like '%auto_increment%' and table_schema='" + schema + "' and column_name='" + name + "'"; + + try ( + Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query); + ){ + if(rs.next()) { - seq = new DBSequence(name); - Statement stmtValue = connect.createStatement(); - ResultSet rsValue = stmtValue.executeQuery("select coalesce(max(" + rs.getString("column_name") + "), 0) as nextval" + - " from " + schema + ".`" + rs.getString("table_name") + "`"); - rsValue.next(); - seq.setSchema(schema); - seq.setValue(rsValue.getLong("nextval")); - stmtValue.close(); + final String valueQuery = + "select coalesce(max(" + rs.getString("column_name") + "), 0) as nextval" + + " from " + schema + ".`" + rs.getString("table_name") + "`"; + + try( + Statement stmtValue = connect.createStatement(); + ResultSet rsValue = stmtValue.executeQuery(valueQuery) + ){ + if(!rsValue.next()) throw new ExceptionDBGitRunTime("failed to get seq value resultset"); + + final String nameSeq = rs.getString("column_name"); + final String ownerSeq = ""; + final Long valueSeq = rsValue.getLong("nextval"); + + return new DBSequence(nameSeq, new StringProperties(rs), schema, ownerSeq, Collections.emptySet(), valueSeq); + } + } else { + final String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); + throw new ExceptionDBGitObjectNotFound(msg); } - stmt.close(); + } catch (Exception e) { - logger.error(lang.getValue("errors", "adapter", "seq").toString(), e); - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "seq").toString(), e); + final String msg = lang.getValue("errors", "adapter", "seq").toString(); + throw new ExceptionDBGitRunTime(msg, e); } - return seq; + } @Override public Map getTables(String schema) { - Map listTable = new HashMap(); - try { - String query = "SELECT T.TABLE_NAME, T.TABLE_SCHEMA " + - "FROM information_schema.tables T WHERE TABLE_SCHEMA = '" + schema + "' and TABLE_TYPE = 'BASE TABLE'"; - Connection connect = getConnection(); - - Statement stmt = connect.createStatement(); + final Map listTable = new HashMap<>(); + final String query = + "SELECT T.TABLE_NAME, T.TABLE_SCHEMA " + + "FROM information_schema.tables T WHERE TABLE_SCHEMA = '" + schema + "' and TABLE_TYPE = 'BASE TABLE'"; + + try ( + Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query); - + ){ + while(rs.next()){ - String nameTable = rs.getString("TABLE_NAME"); - DBTable table = new DBTable(nameTable); - table.setSchema(schema); - rowToProperties(rs, table.getOptions()); - - Statement stmtDdl = connect.createStatement(); - ResultSet rsDdl = stmtDdl.executeQuery("show create table " + schema + ".`" + nameTable + "`"); - rsDdl.next(); - - table.getOptions().addChild("ddl", cleanString(rsDdl.getString(2))); - + //TODO retrieve table comment + //TODO retrieve table owner + + final String nameTable = rs.getString("TABLE_NAME"); + final String ownerTable = ""; + final String commentTable = ""; + final String ddlQuery = "show create table " + schema + ".`" + nameTable + "`"; + final StringProperties options = new StringProperties(rs); + final Set dependencies = rs.getArray("dependencies") != null + ? new HashSet<>(Arrays.asList((String[])rs.getArray("dependencies").getArray())) + : Collections.emptySet(); + + try( + Statement stmtDdl = getConnection().createStatement(); + ResultSet rsDdl = stmtDdl.executeQuery(ddlQuery); + ){ + if(!rsDdl.next()) throw new ExceptionDBGitRunTime("failed to get table ddl resultset"); + options.addChild("ddl", cleanString(rsDdl.getString(2))); + } + + final DBTable table = new DBTable(nameTable, options, schema, ownerTable, dependencies, commentTable); listTable.put(nameTable, table); - - stmtDdl.close(); - rsDdl.close(); + } - rs.close(); - stmt.close(); - }catch(Exception e) { - logger.error(lang.getValue("errors", "adapter", "tables").toString(), e); - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "tables").toString(), e); + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "tables").toString(); + throw new ExceptionDBGitRunTime(msg, e); } + return listTable; } @Override public DBTable getTable(String schema, String name) { - try { - String query = "SELECT T.TABLE_NAME, T.TABLE_SCHEMA " + - "FROM information_schema.tables T WHERE TABLE_SCHEMA = '" + schema + "' AND T.TABLE_NAME = '" + name + "'"; - Connection connect = getConnection(); - - Statement stmt = connect.createStatement(); - ResultSet rs = stmt.executeQuery(query); + final String query = + "SELECT T.TABLE_NAME, T.TABLE_SCHEMA FROM information_schema.tables T" + + " WHERE TABLE_SCHEMA = '" + schema + "'" + + " AND T.TABLE_NAME = '" + name + "'"; - DBTable table = null; - - while(rs.next()) { - String nameTable = rs.getString("TABLE_NAME"); - table = new DBTable(nameTable); - table.setSchema(schema); - - Statement stmtDdl = connect.createStatement(); - ResultSet rsDdl = stmtDdl.executeQuery("show create table " + schema + ".`" + nameTable + "`"); - rsDdl.next(); - table.getOptions().addChild("ddl", cleanString(rsDdl.getString(2))); - rowToProperties(rs, table.getOptions()); - stmtDdl.close(); - rsDdl.close(); + try (Statement stmt = connect.createStatement(); ResultSet rs = stmt.executeQuery(query);){ + + if (rs.next()){ + //TODO retrieve table comment + //TODO retrieve table owner + final String nameTable = rs.getString("TABLE_NAME"); + final String ownerTable = ""; + final String commentTable = ""; + final StringProperties options = new StringProperties(rs); + final Set dependencies = rs.getArray("dependencies") != null + ? new HashSet<>(Arrays.asList((String[])rs.getArray("dependencies").getArray())) + : Collections.emptySet(); + + final String ddlQuery = "show create table " + schema + ".`" + nameTable + "`"; + try(Statement stmtDdl = getConnection().createStatement(); ResultSet rsDdl = stmtDdl.executeQuery(ddlQuery);){ + rsDdl.next(); + options.addChild("ddl", cleanString(rsDdl.getString(2))); + } + return new DBTable(nameTable, options, schema, ownerTable, dependencies, commentTable); + + } else { + final String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); + throw new ExceptionDBGitObjectNotFound(msg); } - rs.close(); - stmt.close(); - - return table; - - }catch(Exception e) { - logger.error(lang.getValue("errors", "adapter", "tables").toString(), e); - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "tables").toString(), e); + + } catch(Exception e) { + String msg = lang.getValue("errors", "adapter", "tables").toString(); + throw new ExceptionDBGitRunTime(msg, e); } + } @Override public Map getTableFields(String schema, String nameTable) { - try { - Map listField = new HashMap(); - - String query = - "SELECT distinct col.column_name,col.is_nullable,col.data_type,col.character_maximum_length, tc.constraint_name, " + - "case\r\n" + - " when lower(data_type) in ('tinyint', 'smallint', 'mediumint', 'int', 'bigint', 'float', 'double', 'decimal') then 'number' \r\n" + - " when lower(data_type) in ('tinytext', 'text', 'char', 'mediumtext', 'longtext', 'varchar') then 'string'\r\n" + - " when lower(data_type) in ('datetime', 'timestamp', 'date') then 'date'\r\n" + - " when lower(data_type) in ('boolean') then 'boolean'\r\n" + - " when lower(data_type) in ('blob', 'mediumblob', 'longblob', 'binary', 'varbinary') then 'binary'" + - " else 'native'\r\n" + - " end tp, " + - " case when lower(data_type) in ('char', 'character') then true else false end fixed, " + - "col.* FROM " + - "information_schema.columns col " + - "left join information_schema.key_column_usage kc on col.table_schema = kc.table_schema and col.table_name = kc.table_name and col.column_name=kc.column_name " + - "left join information_schema.table_constraints tc on col.table_schema = kc.table_schema and col.table_name = kc.table_name and kc.constraint_name = tc.constraint_name and tc.constraint_type = 'PRIMARY KEY' " + - "where col.table_schema = :schema and col.table_name = :table " + - "order by col.column_name "; - Connection connect = getConnection(); - - NamedParameterPreparedStatement stmt = NamedParameterPreparedStatement.createNamedParameterPreparedStatement(connect, query); - stmt.setString("schema", schema); - stmt.setString("table", nameTable); + final Map listField = new HashMap(); + final String query = + "SELECT DISTINCT " + + " col.column_name, col.is_nullable, col.data_type, col.character_maximum_length, tc.constraint_name, " + + " case\r\n" + + " when lower(data_type) in ('tinyint', 'smallint', 'mediumint', 'int', 'bigint', 'float', 'double', 'decimal') then 'number' \r\n" + + " when lower(data_type) in ('tinytext', 'text', 'char', 'mediumtext', 'longtext', 'varchar') then 'string'\r\n" + + " when lower(data_type) in ('datetime', 'timestamp', 'date') then 'date'\r\n" + + " when lower(data_type) in ('boolean') then 'boolean'\r\n" + + " when lower(data_type) in ('blob', 'mediumblob', 'longblob', 'binary', 'varbinary') then 'binary'" + + " else 'native'\r\n" + + " end tp, " + + " case " + + " when lower(data_type) in ('char', 'character') " + + " then true else false " + + " end fixed, " + + " col.* " + + "FROM information_schema.columns col " + + "LEFT JOIN information_schema.key_column_usage kc on col.table_schema = kc.table_schema and col.table_name = kc.table_name and col.column_name=kc.column_name " + + "LEFT JOIN information_schema.table_constraints tc on col.table_schema = kc.table_schema and col.table_name = kc.table_name and kc.constraint_name = tc.constraint_name and tc.constraint_type = 'PRIMARY KEY' " + + "WHERE col.table_schema = :schema and col.table_name = :table " + + "ORDER BY col.column_name "; + try ( + PreparedStatement stmt = preparedStatement(getConnection(), query, ImmutableMap.of("schema", schema, "table", nameTable)); ResultSet rs = stmt.executeQuery(); - while(rs.next()){ - DBTableField field = new DBTableField(); - field.setName(rs.getString("column_name").toLowerCase()); - if (rs.getString("constraint_name") != null) { - field.setIsPrimaryKey(true); - } - String typeSQL = getFieldType(rs); - field.setTypeSQL(typeSQL); - field.setIsNullable( !typeSQL.toLowerCase().contains("not null")); - field.setTypeUniversal(FieldType.fromString(rs.getString("tp"))); - field.setFixed(false); - field.setLength(rs.getInt("character_maximum_length")); - field.setPrecision(rs.getInt("numeric_precision")); - field.setScale(rs.getInt("numeric_scale")); - field.setFixed(rs.getBoolean("fixed")); + ) { + + while(rs.next()){ + + //TODO make restore defaultValue, description (comment) and order in MySQL + final String columnName = rs.getString("column_name").toLowerCase(); + final String typeSQL = getFieldType(rs); + final FieldType typeUniversal = FieldType.fromString(rs.getString("tp")); + final String defaultValue = rs.getString("column_name") != null ? rs.getString("column_name").toLowerCase() : ""; + final String description = rs.getString("column_comment") != null ? rs.getString("column_comment").toLowerCase() : ""; + final int order = rs.getInt("ordinal_position"); + final boolean isPrimaryKey = rs.getString("constraint_name") != null; + final boolean isFixed = rs.getBoolean("isFixed"); + final boolean isNullable = !typeSQL.toLowerCase().contains("not null"); + final int length = rs.getInt("character_maximum_length"); + final int precision = rs.getInt("numeric_precision"); + final int scale = rs.getInt("numeric_scale"); + + final DBTableField field = new DBTableField( + columnName, description, isPrimaryKey, isNullable, + typeSQL, typeUniversal, order, defaultValue, + length, scale, precision, isFixed + ); + listField.put(field.getName(), field); } - stmt.close(); - - return listField; - }catch(Exception e) { - logger.error(lang.getValue("errors", "adapter", "tables").toString(), e); - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "tables").toString(), e); - } + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "tableData").toString(); + throw new ExceptionDBGitRunTime(msg, e); + } + + return listField; } @Override public Map getIndexes(String schema, String nameTable) { - try { - Map indexes = new HashMap<>(); - String query = "select TABLE_NAME, INDEX_NAME, INDEX_TYPE, NON_UNIQUE, GROUP_CONCAT(COLUMN_NAME separator '`, `') as FIELDS " - + "from INFORMATION_SCHEMA.STATISTICS where TABLE_SCHEMA = '" + schema + "' and INDEX_NAME != 'PRIMARY' " - + "group by TABLE_NAME, INDEX_NAME, INDEX_TYPE, NON_UNIQUE order by TABLE_NAME, INDEX_NAME;"; - Connection connect = getConnection(); - Statement stmt = connect.createStatement(); + final Map indexes = new HashMap<>(); + final String query = + "select TABLE_NAME, INDEX_NAME, INDEX_TYPE, NON_UNIQUE, GROUP_CONCAT(COLUMN_NAME separator '`, `') as FIELDS " + + "from INFORMATION_SCHEMA.STATISTICS where TABLE_SCHEMA = '" + schema + "' and INDEX_NAME != 'PRIMARY' " + + "group by TABLE_NAME, INDEX_NAME, INDEX_TYPE, NON_UNIQUE order by TABLE_NAME, INDEX_NAME;"; + + try( + Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query); + ) { + while(rs.next()) { - DBIndex index = new DBIndex(rs.getString("INDEX_NAME")); - index.setSchema(schema); - index.setOwner(schema); - rowToProperties(rs, index.getOptions()); - - String ddl = "create " + (rs.getInt("NON_UNIQUE") == 1 ? "" : "unique ") - + "index `" + rs.getString("INDEX_NAME") - + "` using " + rs.getString("INDEX_TYPE") - + " on " + schema + ".`" + rs.getString("TABLE_NAME") + "`" - + "(`" + rs.getString("FIELDS") + "`)"; - - index.getOptions().addChild("ddl", cleanString(ddl)); - indexes.put(rs.getString("INDEX_NAME"), index); + + //TODO find real owner + final String indexName = rs.getString("INDEX_NAME"); + final String sql = cleanString( + "create " + (rs.getInt("NON_UNIQUE") == 1 ? "" : "unique ") + + "index `" + indexName + + "` using " + rs.getString("INDEX_TYPE") + + " on " + schema + ".`" + rs.getString("TABLE_NAME") + "`" + + "(`" + rs.getString("FIELDS") + "`)" + ); + + final DBIndex index = new DBIndex(indexName, new StringProperties(rs), schema, schema, Collections.emptySet(), sql); + indexes.put(indexName, index); } - stmt.close(); - return indexes; + } catch(Exception e) { - logger.error(e.getMessage()); - System.out.println(e.getMessage()); - throw new ExceptionDBGitRunTime(e.getMessage()); + final String msg = lang.getValue("errors", "adapter", "indexes").toString(); + throw new ExceptionDBGitRunTime(msg, e); } + + return indexes; } @Override public Map getConstraints(String schema, String nameTable) { - Map constraints = new HashMap<>(); - return constraints; + return Collections.emptyMap(); } @Override public Map getViews(String schema) { - Map listView = new HashMap(); - try { - String query = "show full tables in " + schema + " where TABLE_TYPE like 'VIEW'"; - Connection connect = getConnection(); - Statement stmt = connect.createStatement(); + final Map listView = new HashMap(); + final String query = "show full tables in " + schema + " where TABLE_TYPE like 'VIEW'"; + + try ( + Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query); + ) { + while(rs.next()){ - DBView view = new DBView(rs.getString(1)); - view.setSchema(schema); - view.setOwner(schema); - rowToProperties(rs, view.getOptions()); - - Statement stmtDdl = connect.createStatement(); - ResultSet rsDdl = stmtDdl.executeQuery("show create view " + schema + "." + rs.getString(1)); - rsDdl.next(); - - view.getOptions().addChild("ddl", cleanString(rsDdl.getString(2))); - listView.put(rs.getString(1), view); - - stmtDdl.close(); - rsDdl.close(); + + //TODO try find real owner + final String name = rs.getString(1); + final String ddlQuery = "show create view " + schema + "." + name; + String sql = ""; + + try( + Statement stmtDdl = getConnection().createStatement(); + ResultSet rsDdl = stmtDdl.executeQuery(ddlQuery); + ){ + if(rsDdl.next()){ + sql = cleanString(rsDdl.getString(2)); + } else { + String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); + throw new ExceptionDBGitObjectNotFound(msg); + } + } + + final DBView view = new DBView(name, new StringProperties(rs), schema, schema, Collections.emptySet(), sql); + listView.put(name, view); } - stmt.close(); - return listView; + } catch(Exception e) { - logger.error(e.getMessage()); - System.out.println(e.getMessage()); - throw new ExceptionDBGitRunTime(e.getMessage()); + final DBGitLang msg = lang.getValue("errors", "adapter", "views"); + throw new ExceptionDBGitRunTime(msg, e); } + + return listView; + } @Override public DBView getView(String schema, String name) { - DBView view = new DBView(name); - view.setSchema(schema); - view.setOwner(schema); - try { - Statement stmtDdl = connect.createStatement(); - ResultSet rsDdl = stmtDdl.executeQuery("show create view " + schema + ".`" + name + "`"); - if(rsDdl.next()) - view.getOptions().addChild("ddl", cleanString(rsDdl.getString(2))); - stmtDdl.close(); - rsDdl.close(); - return view; - }catch(Exception e) { - logger.error(e.getMessage()); - throw new ExceptionDBGitRunTime(e.getMessage()); + //TODO find real owner + final String query = "show create view " + schema + ".`" + name + "`"; + + try ( + Statement stmtDdl = getConnection().createStatement(); + ResultSet rsDdl = stmtDdl.executeQuery(query); + ) { + + if(rsDdl.next()) { + final String sql = cleanString(rsDdl.getString(2)); + return new DBView(name, new StringProperties(rsDdl), schema, schema, Collections.emptySet(), sql); + } else { + String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); + throw new ExceptionDBGitObjectNotFound(msg); + } + + } catch(Exception e) { + final DBGitLang msg = lang.getValue("errors", "adapter", "views"); + throw new ExceptionDBGitRunTime(msg, e); } - + } @Override public Map getPackages(String schema) { - Map packages = new HashMap(); - return packages; + return Collections.emptyMap(); } @Override public DBPackage getPackage(String schema, String name) { - // TODO Auto-generated method stub - return null; + throw new ExceptionDBGitRunTime(new ExceptionDBGitObjectNotFound("cannot get packages on mysql")); } @Override public Map getProcedures(String schema) { - Map procedures = new HashMap(); - return procedures; + return Collections.emptyMap(); } @Override public DBProcedure getProcedure(String schema, String name) { - // TODO Auto-generated method stub - return null; + throw new ExceptionDBGitRunTime(new ExceptionDBGitObjectNotFound("cannot get procedure on mysql")); } @Override public Map getFunctions(String schema) { - Map listFunction = new HashMap(); - try { - String query = "SELECT R.routine_schema as \"schema\", R.definer as \"rolname\", R.specific_name as \"name\"," + - "group_concat(concat(P.parameter_name, \" \", P.data_type)) as \"arguments\", R.routine_definition as \"ddl\"\r\n" + - "FROM information_schema.routines as R, information_schema.parameters as P\r\n" + - "WHERE P.parameter_mode='IN' and P.routine_type=R.routine_type and P.specific_schema=R.routine_schema and\r\n" + - "P.specific_name=R.specific_name and R.routine_type='FUNCTION' and R.routine_schema='" + schema + "' GROUP BY R.specific_name,1,2,5,P.ordinal_position ORDER BY P.ordinal_position"; + final Map listFunction = new HashMap(); + final String query = + "SELECT R.routine_schema as \"schema\", R.definer as \"rolname\", R.specific_name as \"name\"," + + "group_concat(concat(P.parameter_name, \" \", P.data_type)) as \"arguments\", R.routine_definition as \"ddl\"\r\n" + + "FROM information_schema.routines as R, information_schema.parameters as P\r\n" + + "WHERE P.parameter_mode='IN' and P.routine_type=R.routine_type and P.specific_schema=R.routine_schema and\r\n" + + "P.specific_name=R.specific_name and R.routine_type='FUNCTION' and R.routine_schema='" + schema + "'" + + " GROUP BY R.specific_name,1,2,5,P.ordinal_position ORDER BY P.ordinal_position"; + + try ( Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query); + ) { + while(rs.next()) { - String name = rs.getString("name"); - String owner = rs.getString("rolname"); - String args = rs.getString("arguments"); - DBFunction func = new DBFunction(name); - func.setSchema(schema); - func.setOwner(owner); - rowToProperties(rs, func.getOptions()); + final String name = rs.getString("name"); + final String owner = rs.getString("rolname"); + final String sql = rs.getString("ddl"); + + DBFunction func = new DBFunction(name, new StringProperties(rs), schema, owner, Collections.emptySet(), sql); + //String args = rs.getString("arguments"); //func.setArguments(args); listFunction.put(name, func); } - stmt.close(); + } catch(Exception e) { throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "fnc").toString(), e); } + return listFunction; } @Override public DBFunction getFunction(String schema, String name) { - DBFunction function = new DBFunction(name); - try { - String query = "SELECT R.routine_schema as \"schema\", R.definer as \"rolname\", R.specific_name as \"name\"," + - "group_concat(concat(P.parameter_name, \" \", P.data_type)) as \"arguments\", R.routine_definition as \"ddl\"\r\n" + - "FROM information_schema.routines as R, information_schema.parameters as P\r\n" + - "WHERE P.parameter_mode='IN' and P.routine_type=R.routine_type and P.specific_schema=R.routine_schema and\r\n" + - "P.specific_name=R.specific_name and R.routine_type='FUNCTION' and R.routine_schema='" + schema + "' and R.specific_name='" + name + "'\r\n" + - "GROUP BY R.specific_name,1,2,5,P.ordinal_position ORDER BY P.ordinal_position"; - Statement stmt = getConnection().createStatement(); - ResultSet rs = stmt.executeQuery(query); + final DBFunction function = null; + + final String query = + "SELECT R.routine_schema as \"schema\", R.definer as \"rolname\", R.specific_name as \"name\"," + + "group_concat(concat(P.parameter_name, \" \", P.data_type)) as \"arguments\", R.routine_definition as \"ddl\"\r\n" + + "FROM information_schema.routines as R, information_schema.parameters as P\r\n" + + "WHERE P.parameter_mode='IN' and P.routine_type=R.routine_type and P.specific_schema=R.routine_schema and\r\n" + + "P.specific_name=R.specific_name and R.routine_type='FUNCTION' and R.routine_schema='" + schema + "'" + + " and R.specific_name='" + name + "'\r\n" + + "GROUP BY R.specific_name,1,2,5,P.ordinal_position ORDER BY P.ordinal_position"; + + try ( + Statement stmt = getConnection().createStatement(); + ResultSet rs = stmt.executeQuery(query); + ) { + if(rs.next()) { - String owner = rs.getString("rolname"); - String args = rs.getString("arguments"); - function.setSchema(schema); - function.setOwner(owner); - rowToProperties(rs, function.getOptions()); + final String owner = rs.getString("rolname"); + final String sql = rs.getString("ddl"); + + //String args = rs.getString("arguments"); //function.setArguments(args); + return new DBFunction(name, new StringProperties(rs), schema, owner, Collections.emptySet(), sql); + } else { + final String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); + throw new ExceptionDBGitObjectNotFound(msg); } - stmt.close(); - } catch(Exception e) { - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "fnc").toString(), e); + + } catch (Exception e) { + final String msg = lang.getValue("errors", "adapter", "fnc").toString(); + throw new ExceptionDBGitRunTime(msg, e); } - return function; + } @Override public Map getTriggers(String schema) { - Map listTrigger = new HashMap(); - try { - String query = "show triggers in " + schema; - - Connection connect = getConnection(); - Statement stmt = connect.createStatement(); + + final Map listTrigger = new HashMap(); + final String query = "show triggers in " + schema; + + try ( + Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query); + ) { while(rs.next()){ - String name = rs.getString(1); - DBTrigger trigger = new DBTrigger(name); - trigger.setSchema(schema); - trigger.setOwner(schema); - - Statement stmtDdl = connect.createStatement(); - ResultSet rsDdl = stmtDdl.executeQuery("show create trigger " + schema + "." + rs.getString(1)); - rsDdl.next(); - - trigger.getOptions().addChild("ddl", cleanString(rsDdl.getString(3))); - - stmtDdl.close(); - rsDdl.close(); - - rowToProperties(rs, trigger.getOptions()); - listTrigger.put(name, trigger); + //TODO find real owner + final String name = rs.getString(1); + final String ddlQuery = "show create trigger " + schema + "." + name; + + try( + Statement stmtDdl = getConnection().createStatement(); + ResultSet rsDdl = stmtDdl.executeQuery(ddlQuery); + ){ + if(!rsDdl.next()) throw new ExceptionDBGitRunTime("failed to get ddl resultset"); + + final String sql = rsDdl.getString(3); + final StringProperties options = new StringProperties(rs); + final DBTrigger trigger = new DBTrigger(name, options, schema, schema, Collections.emptySet(), sql); + + listTrigger.put(name, trigger); + } + } - stmt.close(); - return listTrigger; - }catch(Exception e) { - throw new ExceptionDBGitRunTime(e); + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "triggers").toString(); + throw new ExceptionDBGitRunTime(msg, e); } + + return listTrigger; } @Override public DBTrigger getTrigger(String schema, String name) { - DBTrigger trigger = new DBTrigger(name); - try { - trigger.setSchema(schema); - trigger.setOwner(schema); - - Statement stmtDdl = connect.createStatement(); - ResultSet rsDdl = stmtDdl.executeQuery("show create trigger " + schema + "." + name); - rsDdl.next(); - - trigger.getOptions().addChild("ddl", cleanString(rsDdl.getString(3))); - - stmtDdl.close(); - rsDdl.close(); - - return trigger; - - }catch(Exception e) { - throw new ExceptionDBGitRunTime(e); + final String query = "show create trigger " + schema + "." + name; + + try ( + Statement stmtDdl = getConnection().createStatement(); + ResultSet rsDdl = stmtDdl.executeQuery(query); + ) { + + if(rsDdl.next()){ + + final StringProperties options = new StringProperties(rsDdl); + final String sql = rsDdl.getString("SQL Original Statement"); + return new DBTrigger(name, options, schema, schema, Collections.emptySet(), sql); + + } else { + final String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); + throw new ExceptionDBGitObjectNotFound(msg); + } + + } catch(Exception e) { + throw new ExceptionDBGitRunTime(e); } + } @Override public DBTableData getTableData(String schema, String nameTable) { - String tableName = schema + ".`" + nameTable + "`"; try { - DBTableData data = new DBTableData(); - - int maxRowsCount = DBGitConfig.getInstance().getInteger("core", "MAX_ROW_COUNT_FETCH", DBGitConfig.getInstance().getIntegerGlobal("core", "MAX_ROW_COUNT_FETCH", MAX_ROW_COUNT_FETCH)); - - if (DBGitConfig.getInstance().getBoolean("core", "LIMIT_FETCH", DBGitConfig.getInstance().getBooleanGlobal("core", "LIMIT_FETCH", true))) { - Statement st = getConnection().createStatement(); - String query = "select COALESCE(count(*), 0) kolvo from ( select 1 from "+ - tableName + " limit " + (maxRowsCount + 1) + " ) tbl"; - ResultSet rs = st.executeQuery(query); - rs.next(); - if (rs.getInt("kolvo") > maxRowsCount) { - data.setErrorFlag(DBTableData.ERROR_LIMIT_ROWS); - return data; + + final int maxRowsCount = DBGitConfig.getInstance().getInteger( + "core", "MAX_ROW_COUNT_FETCH", + DBGitConfig.getInstance().getIntegerGlobal("core", "MAX_ROW_COUNT_FETCH", MAX_ROW_COUNT_FETCH) + ); + final boolean toLimitFetch = DBGitConfig.getInstance().getBoolean( + "core", "LIMIT_FETCH", + DBGitConfig.getInstance().getBooleanGlobal("core", "LIMIT_FETCH", true) + ); + + final String tableName = schema + ".`" + nameTable + "`"; + final String dataQuery = "select * from " + tableName; + final String rowsCountQuery = + "select COALESCE(count(*), 0) kolvo " + + "from ( " + + " select 1 " + + " from " + tableName + " " + + " limit " + (maxRowsCount + 1) + " " + + ") tbl"; + + if (toLimitFetch) { + + try ( + Statement st = getConnection().createStatement(); + ResultSet rs = st.executeQuery(rowsCountQuery); + ){ + if(!rs.next()) throw new ExceptionDBGitRunTime("Could not execute rows count query"); + if (rs.getInt("kolvo") > maxRowsCount) { + return new DBTableData(DBTableData.ERROR_LIMIT_ROWS); + } } - - rs = st.executeQuery("select * from "+tableName); - data.setResultSet(rs); - return data; + } - - return data; + return new DBTableData(getConnection(), dataQuery); + } catch(Exception e) { + final String msg = DBGitLang.getInstance().getValue("errors", "adapter", "tableData").toString(); + throw new ExceptionDBGitRunTime(msg, e); + } + } + + @Override + public DBTableData getTableDataPortion(String schema, String nameTable, int portionIndex, int tryNumber) { + final int portionSize = DBGitConfig.getInstance().getInteger("core", "PORTION_SIZE", DBGitConfig.getInstance().getIntegerGlobal("core", "PORTION_SIZE", 1000)); + final int beginRowNum = 1 + portionSize * portionIndex; + final int endRowNum = portionSize + portionSize * portionIndex; + + final String dataQuery = + "SELECT * " + "\n" + + "FROM (" + "\n" + + " SELECT " + "\n" + + " f.*, " + "\n" + + " ROW_NUMBER() OVER (" + "\n" + + " ORDER BY (" + "\n" + + " select group_concat(column_name separator ', ') " + "\n" + + " from information_schema.columns " + "\n" + + " where table_schema='" + schema + "' " + "\n" + + " and table_name='" + nameTable + "' " + "\n" + + " and upper(column_key)='PRI'" + "\n" + + " )" + "\n" + + " ) DBGIT_ROW_NUM " + "\n" + + " FROM " + schema + "." + nameTable + " f" + "\n" + + ") s \n" + + "WHERE DBGIT_ROW_NUM BETWEEN " + beginRowNum + " AND " + endRowNum; + + try { + + return new DBTableData(getConnection(), dataQuery); + + } catch(Exception e) { + + final int maxTriesCount = DBGitConfig.getInstance().getInteger("core", "TRY_COUNT", DBGitConfig.getInstance().getIntegerGlobal("core", "TRY_COUNT", 1000)); + final int tryDelay = DBGitConfig.getInstance().getInteger("core", "TRY_DELAY", DBGitConfig.getInstance().getIntegerGlobal("core", "TRY_DELAY", 1000)); + + ConsoleWriter.println(e.getLocalizedMessage(), messageLevel); + ConsoleWriter.detailsPrintln(ExceptionUtils.getStackTrace(e), messageLevel); logger.error(lang.getValue("errors", "adapter", "tableData").toString(), e); - try { - getConnection().rollback(); - } catch (Exception e2) { - logger.error(lang.getValue("errors", "adapter", "rollback").toString(), e2); + + if (tryNumber <= maxTriesCount) { + + final String waitMessage = DBGitLang.getInstance() + .getValue("errors", "dataTable", "wait") + .withParams(String.valueOf(tryDelay)); + + final String tryAgainMessage = DBGitLang.getInstance() + .getValue("errors", "dataTable", "tryAgain") + .withParams(String.valueOf(tryNumber)); + + ConsoleWriter.println(waitMessage, messageLevel); + try { TimeUnit.SECONDS.sleep(tryDelay); } catch (InterruptedException e1) { + throw new ExceptionDBGitRunTime(e1.getMessage()); + } + + ConsoleWriter.println(tryAgainMessage, messageLevel); + return getTableDataPortion(schema, nameTable, portionIndex, tryNumber++); + + } else { + final String msg = DBGitLang.getInstance().getValue("errors", "adapter", "tableData").toString(); + throw new ExceptionDBGitRunTime(msg, e); } - throw new ExceptionDBGitRunTime(e.getMessage()); + } } @Override public Map getUsers() { - Map users = new HashMap(); - try { - String query = "select User, authentication_string from mysql.user"; + final Map users = new HashMap(); + final String query = "select User, authentication_string from mysql.user"; + + try ( Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query); + ) { + while(rs.next()) { - String name = rs.getString(1); - String password = rs.getString(2); - StringProperties options = new StringProperties(); + final String name = rs.getString(1); + final String password = rs.getString(2); + final StringProperties options = new StringProperties(); options.addChild("password", password); - DBUser user = new DBUser(name, options); + + final DBUser user = new DBUser(name, options); users.put(name, user); } - stmt.close(); - }catch(Exception e) { - logger.error(e.getMessage()); - throw new ExceptionDBGitRunTime(e.getMessage()); + + } catch(Exception e) { + throw new ExceptionDBGitRunTime(e); } + return users; } @Override - public Map getRoles() { - Map roles = new HashMap(); - return roles; - } + public Map getRoles() { return Collections.emptyMap(); } @Override - public boolean userHasRightsToGetDdlOfOtherUsers() { - return true; + public Map getUDTs(String schema) { + return Collections.emptyMap(); } @Override - public IFactoryDBBackupAdapter getBackupAdapterFactory() { - return backupFactory; + public Map getDomains(String schema) { + return Collections.emptyMap(); } @Override - public DbType getDbType() { - return DbType.MYSQL; + public Map getEnums(String schema) { + return Collections.emptyMap(); } @Override - public String getDbVersion() { - try { - PreparedStatement stmt = getConnection().prepareStatement("SELECT version()"); - ResultSet resultSet = stmt.executeQuery(); - resultSet.next(); - - String result = resultSet.getString(1); - resultSet.close(); - stmt.close(); - - return result; - } catch (SQLException e) { - return ""; - } + public DBUserDefinedType getUDT(String schema, String name) { + final String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); + throw new ExceptionDBGitObjectNotFound(msg); } @Override - public void createSchemaIfNeed(String schemaName) throws ExceptionDBGit { - try { - Statement st = connect.createStatement(); - ResultSet rs = st.executeQuery("select count(*) cnt from information_schema.schemata where upper(schema_name) = '" + - schemaName.toUpperCase() + "'"); - - rs.next(); - if (rs.getInt("cnt") == 0) { - StatementLogging stLog = new StatementLogging(connect, getStreamOutputSqlCommand(), isExecSql()); - stLog.execute("create schema " + schemaName); - - stLog.close(); - } - - rs.close(); - st.close(); - } catch (SQLException e) { - throw new ExceptionDBGit(lang.getValue("errors", "adapter", "createSchema") + ": " + e.getLocalizedMessage()); - } + public DBDomain getDomain(String schema, String name) { + final String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); + throw new ExceptionDBGitObjectNotFound(msg); } @Override - public void createRoleIfNeed(String roleName) throws ExceptionDBGit { - // TODO Auto-generated method stub - + public DBEnum getEnum(String schema, String name) { + final String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); + throw new ExceptionDBGitObjectNotFound(msg); } protected String getFieldType(ResultSet rs) { try { - StringBuilder type = new StringBuilder(); - type.append(rs.getString("data_type")); - - BigDecimal max_length = rs.getBigDecimal("character_maximum_length"); + final StringBuilder type = new StringBuilder(); + if (!rs.wasNull()) { - type.append("(" + max_length + ")"); - } - if (rs.getString("is_nullable").equals("NO")){ - type.append(" NOT NULL"); + final String typePart = rs.getString("data_type"); + final String lengthPart = "(" + rs.getBigDecimal("character_maximum_length") + ")"; + final String nullablePart = rs.getString("is_nullable").equals("NO") ? " NOT NULL" : ""; + type.append( typePart ); + type.append( lengthPart ); + type.append( nullablePart ); } - - return type.toString(); - }catch(Exception e) { - logger.error(lang.getValue("errors", "adapter", "tables").toString(), e); - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "tables").toString(), e); - } - } - @Override - public String getDefaultScheme() throws ExceptionDBGit { - try { - return getConnection().getCatalog(); - } catch (SQLException e) { - throw new ExceptionDBGit(lang.getValue("errors", "adapter", "getSchema") + ": " + e.getLocalizedMessage()); + return type.toString(); + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "tables").toString(); + throw new ExceptionDBGitRunTime(msg, e); } } - - @Override - public IFactoryDBConvertAdapter getConvertAdapterFactory() { - return convertFactory; + private NamedParameterPreparedStatement getParamStatement(String query) throws SQLException { + return NamedParameterPreparedStatement.createNamedParameterPreparedStatement(getConnection(), query); } - @Override - public boolean isReservedWord(String word) { - Set reservedWords = new HashSet<>(); + static { reservedWords.add("ACCESSIBLE"); reservedWords.add("ACCOUNT"); reservedWords.add("ACTION"); @@ -1472,49 +1666,5 @@ public boolean isReservedWord(String word) { reservedWords.add("VCPU"); reservedWords.add("VISIBLE"); reservedWords.add("WINDOW"); - return reservedWords.contains(word.toUpperCase()); - } - - @Override - public DBTableData getTableDataPortion(String schema, String nameTable, int portionIndex, int tryNumber) { - DBTableData data = new DBTableData(); - try { - int portionSize = DBGitConfig.getInstance().getInteger("core", "PORTION_SIZE", DBGitConfig.getInstance().getIntegerGlobal("core", "PORTION_SIZE", 1000)); - - int begin = 1 + portionSize * portionIndex; - int end = portionSize + portionSize * portionIndex; - - Statement st = getConnection().createStatement(); - ResultSet rs = st.executeQuery("SELECT * FROM \r\n" + - "(SELECT f.*, ROW_NUMBER() OVER (ORDER BY (select group_concat(column_name separator ', ') from information_schema.columns where \r\n" + - "table_schema='" + schema + "' and table_name='" + nameTable + "' and upper(column_key)='PRI')) DBGIT_ROW_NUM FROM " + schema + "." + nameTable + " f) s \r\n" + - "WHERE DBGIT_ROW_NUM BETWEEN " + begin + " and " + end); - data.setResultSet(rs); - return data; - } catch(Exception e) { - logger.error(lang.getValue("errors", "adapter", "tableData").toString(), e); - - try { - if (tryNumber <= DBGitConfig.getInstance().getInteger("core", "TRY_COUNT", DBGitConfig.getInstance().getIntegerGlobal("core", "TRY_COUNT", 1000))) { - try { - TimeUnit.SECONDS.sleep(DBGitConfig.getInstance().getInteger("core", "TRY_DELAY", DBGitConfig.getInstance().getIntegerGlobal("core", "TRY_DELAY", 1000))); - } catch (InterruptedException e1) { - throw new ExceptionDBGitRunTime(e1.getMessage()); - } - ConsoleWriter.println("Error while getting portion of data, try " + tryNumber); - getTableDataPortion(schema, nameTable, portionIndex, tryNumber++); - } - } catch (Exception e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } - - try { - getConnection().rollback(); - } catch (Exception e2) { - logger.error(lang.getValue("errors", "adapter", "rollback").toString(), e2); - } - throw new ExceptionDBGitRunTime(e.getMessage()); - } } } diff --git a/src/main/java/ru/fusionsoft/dbgit/mysql/DBBackupAdapterMySql.java b/src/main/java/ru/fusionsoft/dbgit/mysql/DBBackupAdapterMySql.java index 5d36215..d5556ab 100644 --- a/src/main/java/ru/fusionsoft/dbgit/mysql/DBBackupAdapterMySql.java +++ b/src/main/java/ru/fusionsoft/dbgit/mysql/DBBackupAdapterMySql.java @@ -1,10 +1,13 @@ package ru.fusionsoft.dbgit.mysql; import ru.fusionsoft.dbgit.adapters.DBBackupAdapter; +import ru.fusionsoft.dbgit.meta.DBGitMetaType; import ru.fusionsoft.dbgit.core.DBGitPath; import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; import ru.fusionsoft.dbgit.core.SchemaSynonym; import ru.fusionsoft.dbgit.meta.IMetaObject; +import ru.fusionsoft.dbgit.meta.NameMeta; +import ru.fusionsoft.dbgit.postgres.DBAdapterPostgres; import ru.fusionsoft.dbgit.meta.MetaSequence; import ru.fusionsoft.dbgit.meta.MetaSql; import ru.fusionsoft.dbgit.meta.MetaTable; @@ -16,6 +19,7 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; +import java.text.MessageFormat; public class DBBackupAdapterMySql extends DBBackupAdapter { @Override @@ -32,7 +36,7 @@ public IMetaObject backupDBObject(IMetaObject obj) throws Exception { if (isSaveToSchema()) { createSchema(stLog, schema); } - ConsoleWriter.detailsPrint(lang.getValue("general", "backup", "tryingToCopy").withParams(objectName, getFullDbName(schema, objectName)), 1); + ConsoleWriter.detailsPrintln(lang.getValue("general", "backup", "tryingToCopy").withParams(objectName, getFullDbName(schema, objectName)), messageLevel); ////dropIfExists(isSaveToSchema() ? PREFIX + schema : schema, //// isSaveToSchema() ? objectName : PREFIX + objectName, stLog); //ddl = ddl.replace(schema + "." + objectName, getFullDbName(schema, objectName)); @@ -41,7 +45,7 @@ public IMetaObject backupDBObject(IMetaObject obj) throws Exception { File file = new File(DBGitPath.getFullPath() + metaSql.getFileName()); if (file.exists()) obj = metaSql.loadFromFile(); - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); } else if (obj instanceof MetaTable) { MetaTable metaTable = (MetaTable) obj; metaTable.loadFromDB(); @@ -60,7 +64,9 @@ public IMetaObject backupDBObject(IMetaObject obj) throws Exception { if (isSaveToSchema()) { createSchema(stLog, schema); } - ConsoleWriter.detailsPrint(lang.getValue("general", "backup", "tryingToCopy").withParams(tableName, getFullDbName(schema, tableName)), 1); + ConsoleWriter.detailsPrintln(lang.getValue("general", "backup", "tryingToCopy").withParams(tableName, getFullDbName(schema, tableName)) + , messageLevel + ); //dropIfExists( //isSaveToSchema() ? PREFIX + schema : schema, //isSaveToSchema() ? tableName : PREFIX + tableName, stLog @@ -104,7 +110,7 @@ public IMetaObject backupDBObject(IMetaObject obj) throws Exception { File file = new File(DBGitPath.getFullPath() + metaTable.getFileName()); if (file.exists()) obj = metaTable.loadFromFile(); - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); } else if (obj instanceof MetaSequence) { MetaSequence metaSequence = (MetaSequence) obj; metaSequence.loadFromDB(); @@ -114,7 +120,9 @@ public IMetaObject backupDBObject(IMetaObject obj) throws Exception { createSchema(stLog, schema); } String sequenceName = getFullDbName(schema, objectName); - ConsoleWriter.detailsPrint(lang.getValue("general", "backup", "tryingToCopy").withParams(objectName, getFullDbName(schema, objectName)), 1); + ConsoleWriter.detailsPrintln(lang.getValue("general", "backup", "tryingToCopy").withParams(objectName, getFullDbName(schema, objectName)) + , messageLevel + ); //String ddl = "create sequence " + sequenceName + "\n" //+ (metaSequence.getSequence().getOptions().get("cycle_option").toString().equals("YES") ? "CYCLE\n" : "") //+ " INCREMENT " + metaSequence.getSequence().getOptions().get("increment").toString() + "\n" @@ -130,14 +138,9 @@ public IMetaObject backupDBObject(IMetaObject obj) throws Exception { File file = new File(DBGitPath.getFullPath() + metaSequence.getFileName()); if (file.exists()) obj = metaSequence.loadFromFile(); - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); } - } catch (SQLException e1) { - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError"). - withParams(obj.getName() + ": " + e1.getLocalizedMessage())); } catch (Exception e) { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - connection.rollback(); throw new ExceptionDBGitRestore(lang.getValue("errors", "backup", "backupError").withParams(obj.getName()), e); } finally { connection.commit(); @@ -158,7 +161,7 @@ private String getFullDbName(String schema, String objectName) { return schema + "." + PREFIX + objectName; } - private void dropIfExists(String owner, String objectName, StatementLogging stLog) throws Exception { + public void dropIfExists(String owner, String objectName, StatementLogging stLog) throws SQLException { Statement st = adapter.getConnection().createStatement(); ResultSet rs = st.executeQuery("select * from (\r\n" + " SELECT 'TABLE' tp, table_name obj_name, table_schema sch FROM information_schema.tables \r\n" + @@ -176,6 +179,40 @@ private void dropIfExists(String owner, String objectName, StatementLogging stLo st.close(); } + @Override + public void dropIfExists(IMetaObject imo, StatementLogging stLog) throws SQLException { + + NameMeta nm = new NameMeta(imo); + DBGitMetaType type = (DBGitMetaType) nm.getType(); + + Statement st = adapter.getConnection().createStatement(); + ResultSet rs = st.executeQuery(MessageFormat.format("select * from (\r\n" + + " SELECT 'TABLE' tp, table_name obj_name, table_schema sch FROM information_schema.tables WHERE 1={0}\r\n" + + " union select 'VIEW' tp, table_name obj_name, table_schema sch from information_schema.views WHERE 1={1}\r\n" + + " union select 'TRIGGER' tp, trigger_name obj_name, trigger_schema sch from information_schema.triggers WHERE 1={2}\r\n" + + " union select 'FUNCTION' tp, routine_name obj_name, routine_schema sch from information_schema.routines WHERE 1={3}\r\n" + + ") all_objects\r\n" + + "where sch = '{4}' and obj_name = '{5}'", + type.equals(DBGitMetaType.DBGitTable) ? "1" : "0", + type.equals(DBGitMetaType.DbGitView) ? "1" : "0", + type.equals(DBGitMetaType.DbGitTrigger) ? "1" : "0", + type.equals(DBGitMetaType.DbGitFunction) ? "1" : "0", + nm.getSchema(), nm.getName() + )); + + while (rs.next()) { + stLog.execute(MessageFormat.format("DROP {0} {1}.{2}", + rs.getString("tp"), + nm.getSchema(), + adapter.escapeNameIfNeeded(nm.getName())) + ); + } + + rs.close(); + st.close(); + + } + @Override public boolean createSchema(StatementLogging stLog, String schema) { try { @@ -185,7 +222,7 @@ public boolean createSchema(StatementLogging stLog, String schema) { rs.next(); if (rs.getInt("cnt") == 0) { - ConsoleWriter.detailsPrintLn(lang.getValue("general", "backup", "creatingSchema").withParams(PREFIX + schema)); + ConsoleWriter.detailsPrintln(lang.getValue("general", "backup", "creatingSchema").withParams(PREFIX + schema), messageLevel); stLog.execute("create schema " + PREFIX + schema); } @@ -194,13 +231,13 @@ public boolean createSchema(StatementLogging stLog, String schema) { return true; } catch (SQLException e) { - ConsoleWriter.println(lang.getValue("errors", "backup", "cannotCreateSchema").withParams(e.getLocalizedMessage())); + ConsoleWriter.println(lang.getValue("errors", "backup", "cannotCreateSchema").withParams(e.getLocalizedMessage()), messageLevel); return false; } } @Override - public boolean isExists(String owner, String objectName) throws Exception { + public boolean isExists(String owner, String objectName) throws SQLException { Statement st = adapter.getConnection().createStatement(); ResultSet rs = st.executeQuery("select count(*) cnt from (\r\n" + " SELECT 'TABLE' tp, table_name obj_name, table_schema sch FROM information_schema.tables \r\n" + diff --git a/src/main/java/ru/fusionsoft/dbgit/mysql/DBRestoreSchemaMySql.java b/src/main/java/ru/fusionsoft/dbgit/mysql/DBRestoreSchemaMySql.java index a300130..c4f2e8d 100644 --- a/src/main/java/ru/fusionsoft/dbgit/mysql/DBRestoreSchemaMySql.java +++ b/src/main/java/ru/fusionsoft/dbgit/mysql/DBRestoreSchemaMySql.java @@ -17,20 +17,21 @@ public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { IDBAdapter adapter = getAdapter(); Connection connect = adapter.getConnection(); StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "restoreSchema").withParams(obj.getName()), 1); try { if (obj instanceof MetaSchema) { MetaSchema restoreSchema = (MetaSchema) obj; st.execute("CREATE SCHEMA IF NOT EXISTS " + restoreSchema.getObjectOption().getName()); } else { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); + + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "schema", obj.getType().getValue() + )); } } catch (Exception e) { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); } finally { - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); st.close(); } return false; diff --git a/src/main/java/ru/fusionsoft/dbgit/mysql/DBRestoreTableDataMySql.java b/src/main/java/ru/fusionsoft/dbgit/mysql/DBRestoreTableDataMySql.java index c1697ed..bf1da5e 100644 --- a/src/main/java/ru/fusionsoft/dbgit/mysql/DBRestoreTableDataMySql.java +++ b/src/main/java/ru/fusionsoft/dbgit/mysql/DBRestoreTableDataMySql.java @@ -54,7 +54,7 @@ public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { currentTableData.getmapRows().clear(); if (getAdapter().getTable(schema, currentTableData.getTable().getName()) != null) { currentTableData.setDataTable(getAdapter().getTableData(schema, currentTableData.getTable().getName())); - ResultSet rs = currentTableData.getDataTable().getResultSet(); + ResultSet rs = currentTableData.getDataTable().resultSet(); TreeMapRowData mapRows = new TreeMapRowData(); MetaTable metaTable = new MetaTable(currentTableData.getTable()); metaTable.loadFromDB(currentTableData.getTable()); @@ -75,12 +75,16 @@ public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { } return true; } else { - ////TODO WTF???? - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); - //return true; + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "table data cached", obj.getType().getValue() + )); } } else { - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "table data", obj.getType().getValue() + )); } } @@ -100,20 +104,19 @@ public void restoreTableDataMySql(MetaTableData restoreTableData, MetaTableData String schema = getPhisicalSchema(restoreTableData.getTable().getSchema()); schema = (SchemaSynonym.getInstance().getSchema(schema) == null) ? schema : SchemaSynonym.getInstance().getSchema(schema); String tblName = schema + ".`" + restoreTableData.getTable().getName() + "`"; - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "tableData").withParams(tblName) + "\n", 1); if (!diffTableData.entriesOnlyOnLeft().isEmpty()) { - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "inserting"), 2); + ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "inserting"), messageLevel); for (RowData rowData : diffTableData.entriesOnlyOnLeft().values()) { String fields = String.join("`, `", rowData.getData().keySet()); String values = String.join(", ", rowData.getData().values().stream().map(row -> valueToString(row)).collect(Collectors.toList())); String insertQuery = "insert into " + tblName + "(`" + fields + "`) values (" + values + ");"; - ConsoleWriter.detailsPrintLn(insertQuery); + ConsoleWriter.detailsPrintln(insertQuery, messageLevel); st.execute(insertQuery); } - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); } if (!diffTableData.entriesOnlyOnRight().isEmpty()) { - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "deleting"), 2); + ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "deleting"), messageLevel); String ddl = ""; for (RowData rowData : diffTableData.entriesOnlyOnRight().values()) { Map primarykeys = new HashMap(); @@ -136,10 +139,10 @@ public void restoreTableDataMySql(MetaTableData restoreTableData, MetaTableData if (!ddl.isEmpty()) st.execute("delete from " + tblName + " where " + ddl); } - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); } if (!diffTableData.entriesDiffering().isEmpty()) { - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "updating"), 2); + ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "updating"), messageLevel); String updateQuery = ""; //Map primarykeys = new HashMap(); for (ValueDifference diffRowData : diffTableData.entriesDiffering().values()) { @@ -212,14 +215,14 @@ public void restoreTableDataMySql(MetaTableData restoreTableData, MetaTableData } } } - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); if (!updateQuery.isEmpty()) { - ConsoleWriter.println(updateQuery); + //TODO not a real restore, just print + ConsoleWriter.println(updateQuery, messageLevel); //st.execute(updateQuery); } } } catch (Exception e) { - ConsoleWriter.println(lang.getValue("errors", "restore", "objectRestoreError").withParams(e.getLocalizedMessage())); throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(restoreTableData.getTable().getSchema() + "." + restoreTableData.getTable().getName()), e); } finally { st.close(); @@ -231,7 +234,7 @@ private static String valueToString(ICellData cell) { if(cell instanceof BooleanData) value += ((BooleanData) cell).getValue(); else if(cell instanceof LongData) - value += ((LongData) cell).getValue() != null ? String.valueOf(((LongData) cell).getValue()) : ""; + value += !((LongData) cell).isNull() ? String.valueOf(((LongData) cell).getValue()) : ""; else if(cell instanceof StringData) value += ((StringData) cell).getValue() != null ? ("'" + ((StringData) cell).getValue() .replace("\\", "\\\\") diff --git a/src/main/java/ru/fusionsoft/dbgit/mysql/DBRestoreTableMySql.java b/src/main/java/ru/fusionsoft/dbgit/mysql/DBRestoreTableMySql.java index 29c79ff..699e1a4 100644 --- a/src/main/java/ru/fusionsoft/dbgit/mysql/DBRestoreTableMySql.java +++ b/src/main/java/ru/fusionsoft/dbgit/mysql/DBRestoreTableMySql.java @@ -54,7 +54,7 @@ public void removeMetaObject(IMetaObject obj) throws Exception { schema = (SchemaSynonym.getInstance().getSchema(schema) == null) ? schema : SchemaSynonym.getInstance().getSchema(schema); st.execute("drop table if exists " + schema + "." + tbl.getName()); } catch (Exception e) { - ConsoleWriter.println(lang.getValue("errors", "restore", "objectRestoreError").withParams(e.getLocalizedMessage())); + ConsoleWriter.println(lang.getValue("errors", "restore", "objectRestoreError").withParams(e.getLocalizedMessage()), 0); throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRemoveError").withParams(obj.getName()), e); } finally { st.close(); @@ -64,15 +64,14 @@ public void removeMetaObject(IMetaObject obj) throws Exception { public void restoreTableMySql(IMetaObject obj) throws Exception { IDBAdapter adapter = getAdapter(); Connection connect = adapter.getConnection(); - StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - try { + + try (StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql());){ if (obj instanceof MetaTable) { MetaTable restoreTable = (MetaTable) obj; String schema = getPhisicalSchema(restoreTable.getTable().getSchema().toLowerCase()); schema = (SchemaSynonym.getInstance().getSchema(schema) == null) ? schema : SchemaSynonym.getInstance().getSchema(schema); String tblName = schema + ".`" + restoreTable.getTable().getName() + "`"; - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "restoreTable").withParams(tblName) + "\n", 1); - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "createTable"), 2); + ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "createTable"), messageLevel); StringBuilder pk = new StringBuilder(); String ddl = "CREATE TABLE IF NOT EXISTS " + tblName + " (" + restoreTable @@ -84,27 +83,27 @@ public void restoreTableMySql(IMetaObject obj) throws Exception { if (f.getIsPrimaryKey()) pk.append(f.getName() + "`, `"); return "`" + f.getName() + "` " - + f.getTypeSQL() + (f.getFixed() ? "(" + f.getLength() + ")" : "") - + (f.getIsNullable() ? "" : " NOT NULL") - + (f.getDefaultValue() == null ? "" : - (f.getDefaultValue().toLowerCase().contains("nextval(") ? " AUTO_INCREMENT" : "")) - //+ (f.getDefaultValue() == null ? "" : " default " + f.getDefaultValue()) - + (f.getDescription() == null ? "" : " comment '" + f.getDescription() + "'"); + + f.getTypeSQL() + (f.getFixed() ? "(" + f.getLength() + ")" : "") + + (f.getIsNullable() ? "" : " NOT NULL") + + (f.getDefaultValue() == null ? "" : + (f.getDefaultValue().toLowerCase().contains("nextval(") ? " AUTO_INCREMENT" : "")) + //+ (f.getDefaultValue() == null ? "" : " default " + f.getDefaultValue()) + + (f.getDescription() == null ? "" : " comment '" + f.getDescription() + "'"); } ).collect(Collectors.joining(", ")) + (pk.length() > 1 ? ", PRIMARY KEY (`" + pk.replace(pk.length() - 4, pk.length(), "").toString() + "`)" : "") //FIXME: add foreign keys + ");"; st.execute(ddl); - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); } else { - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "table", obj.getType().getValue() + )); } } catch (Exception e) { - ConsoleWriter.println(lang.getValue("errors", "restore", "objectRestoreError").withParams(e.getLocalizedMessage())); throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); - } finally { - st.close(); } } @@ -112,7 +111,7 @@ public void restoreTableIndexesMySql(IMetaObject obj) throws Exception { IDBAdapter adapter = getAdapter(); Connection connect = adapter.getConnection(); StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "restoreIndex").withParams(obj.getName()), 1); + ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "restoreIndex").withParams(obj.getName()), messageLevel); try { if (obj instanceof MetaTable) { MetaTable restoreTable = (MetaTable)obj; @@ -172,19 +171,18 @@ public void restoreTableIndexesMySql(IMetaObject obj) throws Exception { //} } else { String errText = lang.getValue("errors", "meta", "notFound").withParams(obj.getName()); - ConsoleWriter.detailsPrintlnRed(errText); throw new ExceptionDBGitRestore(errText); } } else { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "table", obj.getType().getValue() + )); } } catch (Exception e) { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - ConsoleWriter.println(lang.getValue("errors", "restore", "objectRestoreError").withParams(e.getLocalizedMessage())); throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); } finally { - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); st.close(); } } @@ -193,7 +191,7 @@ private void restoreTableConstraintMySql(IMetaObject obj) throws Exception { IDBAdapter adapter = getAdapter(); Connection connect = adapter.getConnection(); StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "restoreConstr").withParams(obj.getName()), 1); + ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "restoreConstr").withParams(obj.getName()), messageLevel); try { if (obj instanceof MetaTable) { MetaTable restoreTable = (MetaTable)obj; @@ -225,15 +223,15 @@ private void restoreTableConstraintMySql(IMetaObject obj) throws Exception { } } } else { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); } } catch (Exception e) { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - ConsoleWriter.println(lang.getValue("errors", "restore", "objectRestoreError").withParams(e.getLocalizedMessage())); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "table", obj.getType().getValue() + )); } finally { - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); st.close(); } } diff --git a/src/main/java/ru/fusionsoft/dbgit/mysql/DBRestoreUserMySql.java b/src/main/java/ru/fusionsoft/dbgit/mysql/DBRestoreUserMySql.java index ddebfa7..4110a4b 100644 --- a/src/main/java/ru/fusionsoft/dbgit/mysql/DBRestoreUserMySql.java +++ b/src/main/java/ru/fusionsoft/dbgit/mysql/DBRestoreUserMySql.java @@ -16,7 +16,6 @@ public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { IDBAdapter adapter = getAdapter(); Connection connect = adapter.getConnection(); StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "restoreUser").withParams(obj.getName()), 1); try { if (obj instanceof MetaUser) { MetaUser usr = (MetaUser)obj; @@ -24,14 +23,15 @@ public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { } else { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "user", obj.getType().getValue() + )); } } catch (Exception e) { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); } finally { - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); st.close(); } return true; diff --git a/src/main/java/ru/fusionsoft/dbgit/mysql/DBRestoreViewMySql.java b/src/main/java/ru/fusionsoft/dbgit/mysql/DBRestoreViewMySql.java index 56cedbd..76b1f2d 100644 --- a/src/main/java/ru/fusionsoft/dbgit/mysql/DBRestoreViewMySql.java +++ b/src/main/java/ru/fusionsoft/dbgit/mysql/DBRestoreViewMySql.java @@ -17,22 +17,21 @@ public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { IDBAdapter adapter = getAdapter(); Connection connect = adapter.getConnection(); StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "restoreView").withParams(obj.getName()), 1); try { if (obj instanceof MetaView) { MetaView restoreView = (MetaView)obj; String ddl = restoreView.getSqlObject().getSql(); st.execute(ddl); - //connect.commit();//FIXME ???? } else { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "view", obj.getType().getValue() + )); } } catch (Exception e) { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); } finally { - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); st.close(); } return true; diff --git a/src/main/java/ru/fusionsoft/dbgit/mysql/FactoryDBConvertAdapterMySql.java b/src/main/java/ru/fusionsoft/dbgit/mysql/FactoryDBConvertAdapterMySql.java index b3444e0..3e42fa1 100644 --- a/src/main/java/ru/fusionsoft/dbgit/mysql/FactoryDBConvertAdapterMySql.java +++ b/src/main/java/ru/fusionsoft/dbgit/mysql/FactoryDBConvertAdapterMySql.java @@ -2,6 +2,7 @@ import ru.fusionsoft.dbgit.adapters.IDBConvertAdapter; import ru.fusionsoft.dbgit.adapters.IFactoryDBConvertAdapter; +import ru.fusionsoft.dbgit.core.DBGitLang; import ru.fusionsoft.dbgit.meta.DBGitMetaType; import ru.fusionsoft.dbgit.mysql.converters.*; import ru.fusionsoft.dbgit.utils.ConsoleWriter; @@ -27,7 +28,11 @@ public class FactoryDBConvertAdapterMySql implements IFactoryDBConvertAdapter { @Override public IDBConvertAdapter getConvertAdapter(String objectType) throws Exception { if (!converters.containsKey(objectType)) { - ConsoleWriter.println("Cannot convert " + objectType + "!"); + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("errors", "convert", "cannotConvert") + .withParams(objectType) + , 1 + ); return null; } else return converters.get(objectType); diff --git a/src/main/java/ru/fusionsoft/dbgit/mysql/FactoryDBRestoreAdapterMySql.java b/src/main/java/ru/fusionsoft/dbgit/mysql/FactoryDBRestoreAdapterMySql.java index b55d02f..93a657d 100644 --- a/src/main/java/ru/fusionsoft/dbgit/mysql/FactoryDBRestoreAdapterMySql.java +++ b/src/main/java/ru/fusionsoft/dbgit/mysql/FactoryDBRestoreAdapterMySql.java @@ -37,7 +37,7 @@ public class FactoryDBRestoreAdapterMySql implements IFactoryDBAdapterRestoteMet public IDBAdapterRestoreMetaData getAdapterRestore(IDBGitMetaType tp, IDBAdapter adapter) { if (!restoreAdapters.containsKey(tp.getValue())) { //return new DBRestoreMetaNotSupport(); - ConsoleWriter.println(DBGitLang.getInstance().getValue("errors", "restore", "cannotRestore").withParams(tp.getValue())); + ConsoleWriter.println(DBGitLang.getInstance().getValue("errors", "restore", "cannotRestore").withParams(tp.getValue()), messageLevel); return null; } diff --git a/src/main/java/ru/fusionsoft/dbgit/mysql/converters/SchemaConverterMySql.java b/src/main/java/ru/fusionsoft/dbgit/mysql/converters/SchemaConverterMySql.java index 030c440..10a7453 100644 --- a/src/main/java/ru/fusionsoft/dbgit/mysql/converters/SchemaConverterMySql.java +++ b/src/main/java/ru/fusionsoft/dbgit/mysql/converters/SchemaConverterMySql.java @@ -2,6 +2,7 @@ import ru.fusionsoft.dbgit.adapters.IDBConvertAdapter; import ru.fusionsoft.dbgit.core.DBConnection; +import ru.fusionsoft.dbgit.core.DBGitLang; import ru.fusionsoft.dbgit.core.ExceptionDBGit; import ru.fusionsoft.dbgit.core.db.DbType; import ru.fusionsoft.dbgit.meta.IMetaObject; @@ -17,7 +18,11 @@ public IMetaObject convert(DbType dbType, String dbVersion, IMetaObject obj) thr if (obj instanceof MetaSchema) { MetaSchema schema = (MetaSchema) obj; schema.setDbType(DbType.MYSQL); - ConsoleWriter.println("Processing schema " + schema.getName()); + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("general", "convert", "convertingSchema") + .withParams(schema.getName()) + , messageLevel + ); //ConsoleWriter.printlnGreen("URL=" + DBConnection.getInstance().dbName); switch(objDbType) { case POSTGRES: diff --git a/src/main/java/ru/fusionsoft/dbgit/mysql/converters/TableConverterMySql.java b/src/main/java/ru/fusionsoft/dbgit/mysql/converters/TableConverterMySql.java index fa38060..aec60b1 100644 --- a/src/main/java/ru/fusionsoft/dbgit/mysql/converters/TableConverterMySql.java +++ b/src/main/java/ru/fusionsoft/dbgit/mysql/converters/TableConverterMySql.java @@ -1,6 +1,7 @@ package ru.fusionsoft.dbgit.mysql.converters; import ru.fusionsoft.dbgit.adapters.IDBConvertAdapter; +import ru.fusionsoft.dbgit.core.DBGitLang; import ru.fusionsoft.dbgit.core.ExceptionDBGit; import ru.fusionsoft.dbgit.core.db.DbType; import ru.fusionsoft.dbgit.dbobjects.DBConstraint; @@ -21,7 +22,11 @@ public IMetaObject convert(DbType dbType, String dbVersion, IMetaObject obj) thr return obj; if (obj instanceof MetaTable) { MetaTable table = (MetaTable) obj; - ConsoleWriter.println("Processing table " + table.getName()); + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("general", "convert", "processingTable") + .withParams(table.getName()) + , messageLevel + ); //types for (DBTableField field : table.getFields().values()) field.setTypeSQL(typeFromAnotherDB(objDbType, field)); @@ -56,17 +61,29 @@ public IMetaObject convert(DbType dbType, String dbVersion, IMetaObject obj) thr } private String indexFromPostgres(DBIndex index) { - ConsoleWriter.println("Converting table index " + index.getName() + " from postgresql to mysql..."); + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("general", "convert", "convertingIndex") + .withParams(index.getName(), "postgresql", "mysql") + , messageLevel + ); return ""; } private String indexFromOracle(DBIndex index) { - ConsoleWriter.println("Converting table index " + index.getName() + " from oracle to mysql..."); + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("general", "convert", "convertingIndex") + .withParams(index.getName(), "oracle", "mysql") + , messageLevel + ); return ""; } private String constraintFromOracle(DBConstraint constraint) {//TODO: change - ConsoleWriter.println("Converting table constraint " + constraint.getName() + " from oracle to mysql..."); + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("general", "convert", "convertingConstraint") + .withParams(constraint.getName(), "oracle", "mysql") + , messageLevel + ); Pattern patternConstraint = Pattern.compile("(?<=" + constraint.getName() + ")(.*?)(?=\\))", Pattern.MULTILINE); Matcher matcher = patternConstraint.matcher(constraint.getSql()); if (matcher.find()) @@ -76,7 +93,11 @@ private String constraintFromOracle(DBConstraint constraint) {//TODO: change } private String constraintFromPostgres(MetaTable table, DBConstraint constraint) {//TODO: change - ConsoleWriter.println("Converting table constraint " + constraint.getName() + " from postgresql to mysql..."); + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("general", "convert", "convertingConstraint") + .withParams(constraint.getName(), "postgresql", "mysql") + , messageLevel + ); String ddl = constraint.getOptions().get("ddl") .toString() @@ -92,7 +113,11 @@ private String constraintFromPostgres(MetaTable table, DBConstraint constraint) } private String typeFromAnotherDB(DbType dbType, DBTableField field) { - ConsoleWriter.println("Converting table field " + field.getName() + " from " + dbType.toString().toLowerCase() + " to mysql..."); + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("general", "convert", "convertingField") + .withParams(field.getName(), dbType.toString().toLowerCase(), "mysql") + , messageLevel + ); String result; switch (field.getTypeUniversal()) { case STRING: diff --git a/src/main/java/ru/fusionsoft/dbgit/mysql/converters/ViewConverterMySql.java b/src/main/java/ru/fusionsoft/dbgit/mysql/converters/ViewConverterMySql.java index 3209836..2f4deff 100644 --- a/src/main/java/ru/fusionsoft/dbgit/mysql/converters/ViewConverterMySql.java +++ b/src/main/java/ru/fusionsoft/dbgit/mysql/converters/ViewConverterMySql.java @@ -1,6 +1,7 @@ package ru.fusionsoft.dbgit.mysql.converters; import ru.fusionsoft.dbgit.adapters.IDBConvertAdapter; +import ru.fusionsoft.dbgit.core.DBGitLang; import ru.fusionsoft.dbgit.core.ExceptionDBGit; import ru.fusionsoft.dbgit.core.db.DbType; import ru.fusionsoft.dbgit.meta.IMetaObject; @@ -17,7 +18,11 @@ public IMetaObject convert(DbType dbType, String dbVersion, IMetaObject obj) thr if (obj instanceof MetaView) { MetaView view = (MetaView) obj; view.setDbType(DbType.MYSQL); - ConsoleWriter.println("Processing view " + view.getName()); + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("general", "convert", "convertingView") + .withParams(view.getName()) + , messageLevel + ); switch(objDbType) { case POSTGRES: String ddl = view.getSqlObject().getSql(); diff --git a/src/main/java/ru/fusionsoft/dbgit/oracle/DBAdapterOracle.java b/src/main/java/ru/fusionsoft/dbgit/oracle/DBAdapterOracle.java index bf595c5..032af9a 100644 --- a/src/main/java/ru/fusionsoft/dbgit/oracle/DBAdapterOracle.java +++ b/src/main/java/ru/fusionsoft/dbgit/oracle/DBAdapterOracle.java @@ -5,23 +5,18 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; import java.util.concurrent.TimeUnit; -import java.util.Set; +import org.apache.commons.lang3.exception.ExceptionUtils; import ru.fusionsoft.dbgit.adapters.DBAdapter; import ru.fusionsoft.dbgit.adapters.IDBAdapter; import ru.fusionsoft.dbgit.adapters.IDBAdapterRestoreMetaData; import ru.fusionsoft.dbgit.adapters.IFactoryDBAdapterRestoteMetaData; import ru.fusionsoft.dbgit.adapters.IFactoryDBBackupAdapter; import ru.fusionsoft.dbgit.adapters.IFactoryDBConvertAdapter; -import ru.fusionsoft.dbgit.core.DBGitConfig; -import ru.fusionsoft.dbgit.core.DBGitLang; -import ru.fusionsoft.dbgit.core.ExceptionDBGit; -import ru.fusionsoft.dbgit.core.ExceptionDBGitRunTime; +import ru.fusionsoft.dbgit.core.*; import ru.fusionsoft.dbgit.core.db.DbType; import ru.fusionsoft.dbgit.core.db.FieldType; import ru.fusionsoft.dbgit.data_table.BooleanData; @@ -32,6 +27,8 @@ import ru.fusionsoft.dbgit.data_table.StringData; import ru.fusionsoft.dbgit.data_table.TextFileData; import ru.fusionsoft.dbgit.dbobjects.DBConstraint; +import ru.fusionsoft.dbgit.dbobjects.DBDomain; +import ru.fusionsoft.dbgit.dbobjects.DBEnum; import ru.fusionsoft.dbgit.dbobjects.DBFunction; import ru.fusionsoft.dbgit.dbobjects.DBIndex; import ru.fusionsoft.dbgit.dbobjects.DBPackage; @@ -46,28 +43,37 @@ import ru.fusionsoft.dbgit.dbobjects.DBTableSpace; import ru.fusionsoft.dbgit.dbobjects.DBTrigger; import ru.fusionsoft.dbgit.dbobjects.DBUser; +import ru.fusionsoft.dbgit.dbobjects.DBUserDefinedType; import ru.fusionsoft.dbgit.dbobjects.DBView; import ru.fusionsoft.dbgit.meta.IMapMetaObject; import ru.fusionsoft.dbgit.meta.IMetaObject; +import ru.fusionsoft.dbgit.meta.TreeMapMetaObject; import ru.fusionsoft.dbgit.oracle.FactoryDBAdapterRestoreOracle; import ru.fusionsoft.dbgit.statement.StatementLogging; import ru.fusionsoft.dbgit.utils.ConsoleWriter; import ru.fusionsoft.dbgit.utils.LoggerUtil; import org.slf4j.Logger; +import ru.fusionsoft.dbgit.utils.StringProperties; public class DBAdapterOracle extends DBAdapter { - private Logger logger = LoggerUtil.getLogger(this.getClass()); - private FactoryDBAdapterRestoreOracle restoreFactory = new FactoryDBAdapterRestoreOracle(); - private FactoryDbConvertAdapterOracle convertFactory = new FactoryDbConvertAdapterOracle(); - private FactoryDBBackupAdapterOracle backupFactory = new FactoryDBBackupAdapterOracle(); + final private Logger logger = LoggerUtil.getLogger(this.getClass()); + final private FactoryDBAdapterRestoreOracle restoreFactory = new FactoryDBAdapterRestoreOracle(); + final private FactoryDbConvertAdapterOracle convertFactory = new FactoryDbConvertAdapterOracle(); + final private FactoryDBBackupAdapterOracle backupFactory = new FactoryDBBackupAdapterOracle(); + final private static Set reservedWords = new HashSet<>(); - private String s; @Override public IFactoryDBAdapterRestoteMetaData getFactoryRestore() { return restoreFactory; } + @Override + public IFactoryDBBackupAdapter getBackupAdapterFactory() { return backupFactory; } + @Override + public IFactoryDBConvertAdapter getConvertAdapterFactory() { + return convertFactory; + } @Override public void startUpdateDB() { @@ -80,34 +86,131 @@ public void endUpdateDB() { // TODO Auto-generated method stub } - + + @Override + public boolean userHasRightsToGetDdlOfOtherUsers() { + try { + String userName = getConnection().getSchema(); + + if (userName.equalsIgnoreCase("SYS")) + return true; + + PreparedStatement stmt = getConnection().prepareStatement + ("SELECT count(1) cnt FROM DBA_ROLE_PRIVS WHERE GRANTEE = ? and GRANTED_ROLE = 'SELECT_CATALOG_ROLE'"); + stmt.setString(1, userName); + ResultSet resultSet = stmt.executeQuery(); + resultSet.next(); + + if (resultSet.getInt(1) == 0) { + return false; + } else { + return true; + } + } catch (SQLException e) { + logger.error(e.getMessage()); + return false; + } + } + + @Override + public DbType getDbType() { + return DbType.ORACLE; + } + @Override + public String getDbVersion() { + final String query = "SELECT version FROM V$INSTANCE"; + try ( + PreparedStatement stmt = getConnection().prepareStatement(query); + ResultSet resultSet = stmt.executeQuery(); + ) { + + if(!resultSet.next()) throw new ExceptionDBGitRunTime("get db version resultset is empty"); + final String result = resultSet.getString("version"); + + return result; + + } catch (SQLException e) { + throw new ExceptionDBGitRunTime(e); + } + } + @Override + public String getDefaultScheme() throws ExceptionDBGit { + try { + return getConnection().getSchema(); + } catch (SQLException e) { + final DBGitLang msg = lang.getValue("errors", "adapter", "getSchema"); + throw new ExceptionDBGit(msg, e); + } + } + + @Override + public void createSchemaIfNeed(String schemaName) throws ExceptionDBGit { + final String userCountQuery = "select count(*) cnt from all_users where USERNAME = '" + schemaName.toUpperCase() + "'"; + try ( + Statement st = connect.createStatement(); + ResultSet rs = st.executeQuery(userCountQuery); + ) { + + if(!rs.next()) throw new ExceptionDBGitRunTime("get schema count empty resultset"); + if (rs.getInt("cnt") == 0) { + try(StatementLogging stLog = new StatementLogging(connect, getStreamOutputSqlCommand(), isExecSql());){ + + final String configureUserQuery = "ALTER USER \"" + schemaName.toUpperCase() + "\" QUOTA UNLIMITED ON SYSTEM"; + final String createUserQuery = + "create USER \"" + schemaName.toUpperCase() + "\"\r\n" + + "IDENTIFIED BY \"" + schemaName.toUpperCase() + "\"\r\n" + + "DEFAULT TABLESPACE \"SYSTEM\"\r\n" + + "TEMPORARY TABLESPACE \"TEMP\"\r\n" + + "ACCOUNT UNLOCK"; + + stLog.execute(createUserQuery); + stLog.execute(configureUserQuery); + } + } + + } catch (SQLException e) { + final DBGitLang msg = lang.getValue("errors", "adapter", "createSchema"); + throw new ExceptionDBGit(msg, e); + } + + } + @Override + public void createRoleIfNeed(String roleName) throws ExceptionDBGit { + //TODO implement + } + + @Override + public boolean isReservedWord(String word) { + return reservedWords.contains(word.toUpperCase()); + } + @Override public IMapMetaObject loadCustomMetaObjects() { - return null; + return new TreeMapMetaObject(Collections.emptyList()); } @Override public Map getSchemes() { - Map listScheme = new HashMap(); - try { - String query = "SELECT DISTINCT OWNER\n" + - "FROM DBA_OBJECTS WHERE OWNER != 'PUBLIC' AND OWNER != 'SYSTEM'\n" + - "AND OWNER != 'SYS' AND OWNER != 'APPQOSSYS' AND OWNER != 'OUTLN' \n" + - "AND OWNER != 'DIP' AND OWNER != 'DBSNMP' AND OWNER != 'ORACLE_OCM'\n" + - "ORDER BY OWNER"; - Connection connect = getConnection(); - Statement stmt = connect.createStatement(); - ResultSet rs = stmt.executeQuery(query); + final Map listScheme = new HashMap(); + final String query = + "SELECT DISTINCT OWNER\n" + + "FROM DBA_OBJECTS WHERE OWNER != 'PUBLIC' AND OWNER != 'SYSTEM'\n" + + "AND OWNER != 'SYS' AND OWNER != 'APPQOSSYS' AND OWNER != 'OUTLN' \n" + + "AND OWNER != 'DIP' AND OWNER != 'DBSNMP' AND OWNER != 'ORACLE_OCM'\n" + + "ORDER BY OWNER"; + + try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);){ + while(rs.next()){ - String name = rs.getString("OWNER"); - DBSchema scheme = new DBSchema(name); - rowToProperties(rs, scheme.getOptions()); - listScheme.put(name, scheme); - } - stmt.close(); - }catch(Exception e) { - logger.error(lang.getValue("errors", "adapter", "schemes").toString(), e); - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "schemes").toString(), e); + final String name = rs.getString("OWNER"); + final DBSchema scheme = new DBSchema(name, new StringProperties(rs)); + + listScheme.put(name, scheme); + } + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "schemes").toString(); + throw new ExceptionDBGitRunTime(msg, e); } return listScheme; @@ -115,788 +218,783 @@ public Map getSchemes() { @Override public Map getTableSpaces() { - Map listTableSpace = new HashMap(); - try { - String query = "SELECT owner,\n" + - " segment_name,\n" + - " partition_name,\n" + - " segment_type,\n" + - " bytes \n" + - " FROM dba_segments \n" + - " WHERE OWNER != 'PUBLIC' AND OWNER != 'SYSTEM'\n" + - "AND OWNER != 'SYS' AND OWNER != 'APPQOSSYS' AND OWNER != 'OUTLN' \n" + - "AND OWNER != 'DIP' AND OWNER != 'DBSNMP' AND OWNER != 'ORACLE_OCM' and segment_name not like 'SYS%'"; - Connection connect = getConnection(); - Statement stmt = connect.createStatement(); - ResultSet rs = stmt.executeQuery(query); + final Map listTableSpace = new HashMap(); + final String query = + "SELECT owner,\n" + + " segment_name,\n" + + " partition_name,\n" + + " segment_type,\n" + + " bytes \n" + + " FROM dba_segments \n" + + " WHERE OWNER != 'PUBLIC' AND OWNER != 'SYSTEM'\n" + + "AND OWNER != 'SYS' AND OWNER != 'APPQOSSYS' AND OWNER != 'OUTLN' \n" + + "AND OWNER != 'DIP' AND OWNER != 'DBSNMP' AND OWNER != 'ORACLE_OCM' and segment_name not like 'SYS%'"; + + try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);){ + while(rs.next()){ - String name = rs.getString("segment_name"); - DBTableSpace dbTableSpace = new DBTableSpace(name); - rowToProperties(rs, dbTableSpace.getOptions()); + final String name = rs.getString("segment_name"); + final DBTableSpace dbTableSpace = new DBTableSpace(name, new StringProperties(rs)); listTableSpace.put(name, dbTableSpace); - } - stmt.close(); - }catch(Exception e) { - logger.error(e.getMessage()); - throw new ExceptionDBGitRunTime(e.getMessage()); + } + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "tablespace").toString(); + throw new ExceptionDBGitRunTime(msg, e); } + return listTableSpace; } @Override public Map getSequences(String schema) { - Map listSequence = new HashMap(); - try { - Connection connect = getConnection(); - //variant 1 from DBA_OBJECTS - /*String query = - "SELECT ROWNUM AS NUM, OWNER, OBJECT_NAME, SUBOBJECT_NAME, OBJECT_TYPE, STATUS,\n" + - "(select dbms_metadata.get_ddl('SEQUENCE', O.OBJECT_NAME) AS DDL from dual) AS DDL\n" + - "FROM DBA_OBJECTS O WHERE OBJECT_TYPE = 'SEQUENCE' AND OWNER = :schema";*/ - - //variant 2 from DBA_SEQUENCES - String query = - "SELECT S.SEQUENCE_NAME, (SELECT dbms_metadata.get_ddl('SEQUENCE', S.SEQUENCE_NAME, S.SEQUENCE_OWNER) from dual) AS DDL,\n" + - "order_flag, increment_by, last_number, min_value, max_value, cache_size \n" + - "FROM DBA_SEQUENCES S WHERE S.SEQUENCE_OWNER = '" + schema + "'"; - - Statement stmt = connect.createStatement(); - ResultSet rs = stmt.executeQuery(query); + final Map listSequence = new HashMap(); + + //variant 1 from DBA_OBJECTS + /*String query = + "SELECT ROWNUM AS NUM, OWNER, OBJECT_NAME, SUBOBJECT_NAME, OBJECT_TYPE, STATUS,\n" + + "(select dbms_metadata.get_ddl('SEQUENCE', O.OBJECT_NAME) AS DDL from dual) AS DDL\n" + + "FROM DBA_OBJECTS O WHERE OBJECT_TYPE = 'SEQUENCE' AND OWNER = :schema";*/ + + //variant 2 from DBA_SEQUENCES + final String query = + "SELECT S.SEQUENCE_NAME, (SELECT dbms_metadata.get_ddl('SEQUENCE', S.SEQUENCE_NAME, S.SEQUENCE_OWNER) from dual) AS DDL,\n" + + "order_flag, increment_by, last_number, min_value, max_value, cache_size \n" + + "FROM DBA_SEQUENCES S WHERE S.SEQUENCE_OWNER = '" + schema + "'"; + + try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);) { while(rs.next()){ - String nameSeq = rs.getString("SEQUENCE_NAME"); - DBSequence sequence = new DBSequence(); - sequence.setName(nameSeq); - sequence.setSchema(schema); - sequence.setValue(0L); - rowToProperties(rs, sequence.getOptions()); + //TODO find real sequence value + final long valueSeq = 0L; + final String nameSeq = rs.getString("SEQUENCE_NAME"); + final String ownerSeq = ""; + final DBSequence sequence = new DBSequence(nameSeq, new StringProperties(rs), schema, ownerSeq, Collections.emptySet(), valueSeq); listSequence.put(nameSeq, sequence); } - stmt.close(); - }catch(Exception e) { - logger.error(lang.getValue("errors", "adapter", "sequences").toString(), e); - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "sequences").toString(), e); + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "seq").toString(); + throw new ExceptionDBGitRunTime(msg, e); } + return listSequence; } @Override public DBSequence getSequence(String schema, String name) { - try { - Connection connect = getConnection(); - String query = - "SELECT S.SEQUENCE_NAME, (SELECT dbms_metadata.get_ddl('SEQUENCE', S.SEQUENCE_NAME, S.SEQUENCE_OWNER) from dual) AS DDL, \n" + - "order_flag, increment_by, last_number, min_value, max_value, cache_size \n" + - "FROM DBA_SEQUENCES S WHERE S.SEQUENCE_OWNER = '" + schema + "' AND S.SEQUENCE_NAME = '" + name + "'"; - - Statement stmt = connect.createStatement(); - ResultSet rs = stmt.executeQuery(query); - - DBSequence sequence = null; - while (rs.next()) { - String nameSeq = rs.getString("SEQUENCE_NAME"); - sequence = new DBSequence(); - sequence.setName(nameSeq); - sequence.setSchema(schema); - sequence.setValue(0L); - rowToProperties(rs, sequence.getOptions()); + final String query = + "SELECT S.SEQUENCE_NAME, (SELECT dbms_metadata.get_ddl('SEQUENCE', S.SEQUENCE_NAME, S.SEQUENCE_OWNER) from dual) AS DDL, \n" + + "order_flag, increment_by, last_number, min_value, max_value, cache_size \n" + + "FROM DBA_SEQUENCES S WHERE S.SEQUENCE_OWNER = '" + schema + "' AND S.SEQUENCE_NAME = '" + name + "'"; + + try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);) { + if (rs.next()) { + //TODO find real sequence value + final long valueSeq = 0L; + final String nameSeq = rs.getString("SEQUENCE_NAME"); + final String ownerSeq = ""; + return new DBSequence(nameSeq, new StringProperties(rs), schema, ownerSeq, Collections.emptySet(), valueSeq); + } else { + final String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); + throw new ExceptionDBGitObjectNotFound(msg); } - stmt.close(); - return sequence; - }catch(Exception e) { - logger.error(lang.getValue("errors", "adapter", "sequences").toString(), e); - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "sequences").toString(), e); + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "sequence").toString(); + throw new ExceptionDBGitRunTime(msg, e); } } @Override public Map getTables(String schema) { - Map listTable = new HashMap(); - try { - String query = "SELECT T.TABLE_NAME, T.OWNER, (SELECT dbms_metadata.get_ddl('TABLE', T.TABLE_NAME, T.OWNER) from dual) AS DDL\n" + - "FROM DBA_TABLES T WHERE upper(OWNER) = upper('" + schema + "') and nested = 'NO' and (iot_type <> 'IOT_OVERFLOW' or iot_type is null)"; - Connection connect = getConnection(); - - Statement stmt = connect.createStatement(); - ResultSet rs = stmt.executeQuery(query); - + final Map listTable = new HashMap(); + final String query = + "SELECT T.TABLE_NAME, T.OWNER, (SELECT dbms_metadata.get_ddl('TABLE', T.TABLE_NAME, T.OWNER) from dual) AS DDL\n" + + "FROM DBA_TABLES T WHERE upper(OWNER) = upper('" + schema + "') and nested = 'NO' and (iot_type <> 'IOT_OVERFLOW' or iot_type is null)"; + + try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);) { while(rs.next()){ - String nameTable = rs.getString("TABLE_NAME"); - DBTable table = new DBTable(nameTable); - table.setSchema(schema); - rowToProperties(rs, table.getOptions()); + //TODO retrieve table comment + //TODO retrieve table owner + final String nameTable = rs.getString("TABLE_NAME"); + final String ownerTable = ""; + final String commentTable = ""; + final StringProperties options = new StringProperties(rs); + final Set dependencies = rs.getArray("dependencies") != null + ? new HashSet<>(Arrays.asList((String[])rs.getArray("dependencies").getArray())) + : Collections.emptySet(); + + final DBTable table = new DBTable(nameTable, options, schema, ownerTable, dependencies, commentTable); listTable.put(nameTable, table); } - stmt.close(); - }catch(Exception e) { - logger.error(lang.getValue("errors", "adapter", "tables").toString(), e); - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "tables").toString(), e); + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "tables").toString(); + throw new ExceptionDBGitRunTime(msg, e); } + return listTable; } @Override public DBTable getTable(String schema, String name) { - try { - String query = "SELECT T.TABLE_NAME, T.OWNER, (SELECT dbms_metadata.get_ddl('TABLE', T.TABLE_NAME, T.OWNER) from dual) AS DDL\n" + - "FROM DBA_TABLES T WHERE upper(T.OWNER) = upper('" + schema + "') AND upper(T.TABLE_NAME) = upper('" + name + "')"; - Connection connect = getConnection(); - - Statement stmt = connect.createStatement(); - ResultSet rs = stmt.executeQuery(query); - DBTable table = null; - - while(rs.next()) { - String nameTable = rs.getString("TABLE_NAME"); - table = new DBTable(nameTable); - table.setSchema(schema); - rowToProperties(rs, table.getOptions()); + final String query = + "SELECT T.TABLE_NAME, T.OWNER, (SELECT dbms_metadata.get_ddl('TABLE', T.TABLE_NAME, T.OWNER) from dual) AS DDL\n" + + "FROM DBA_TABLES T WHERE upper(T.OWNER) = upper('" + schema + "') AND upper(T.TABLE_NAME) = upper('" + name + "')"; + + try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);) { + + if (rs.next()) { + //TODO retrieve table comment + //TODO retrieve table owner + final String nameTable = rs.getString("TABLE_NAME"); + final String ownerTable = ""; + final String commentTable = ""; + final StringProperties options = new StringProperties(rs); + final Set dependencies = rs.getArray("dependencies") != null + ? new HashSet<>(Arrays.asList((String[])rs.getArray("dependencies").getArray())) + : Collections.emptySet(); + + return new DBTable(nameTable, options, schema, ownerTable, dependencies, commentTable); + } else { + final String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); + throw new ExceptionDBGitObjectNotFound(msg); } - - stmt.close(); - return table; - - }catch(Exception e) { - logger.error(lang.getValue("errors", "adapter", "tables").toString(), e); - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "tables").toString(), e); + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "tables").toString(); + throw new ExceptionDBGitRunTime(msg, e); } + } @Override public Map getTableFields(String schema, String nameTable) { - try { - Map listField = new HashMap(); - - String query1 = - "SELECT column_name FROM all_constraints cons, all_cons_columns cols\n"+ - "WHERE upper(cols.table_name) = upper('" + nameTable + "')\n"+ - "AND cons.constraint_type = 'P'\n" + - "AND cons.constraint_name = cols.constraint_name\n" + - "AND cons.owner = cols.owner"; - Connection connect = getConnection(); - - Statement stmt = connect.createStatement(); - ResultSet rs1 = stmt.executeQuery(query1); - - String s = ""; - - while (rs1.next()) - s = rs1.getString("COLUMN_NAME").toLowerCase(); - - String query = - "SELECT case \r\n" + - " when lower(data_type) in ('number', 'numeric', 'dec', 'decimal', 'pls_integer') then 'number'\r\n" + - " when lower(data_type) in ('varchar2', 'varchar', 'char', 'nchar', 'nvarchar2') then 'string'\r\n" + - " when substr(lower(data_type), 1, instr(data_type, '(') - 1) in ('date', 'timestamp') then 'date'\r\n" + - " when lower(data_type) in ('date', 'timestamp') then 'date'\r\n" + - " when lower(data_type) in ('clob') then 'text'\r\n" + - " when lower(data_type) in ('blob') then 'binary'" + - " else 'native'\r\n" + - " end type, " + - " case when lower(data_type) in ('char', 'nchar') then 1 else 0 end fixed, " + - " ROWNUM AS NUM, TC.* FROM DBA_TAB_COLS TC \n" + - "WHERE lower(table_name) = lower('" + nameTable + "') AND lower(OWNER) = lower('" + schema + "') ORDER BY column_id"; - - ResultSet rs = stmt.executeQuery(query); - while(rs.next()){ - DBTableField field = new DBTableField(); - field.setName(rs.getString("COLUMN_NAME").toLowerCase()); - if (rs.getString("COLUMN_NAME").toLowerCase().equals(s)) { - field.setIsPrimaryKey(true); - } - String typeSQL = getFieldType(rs); - field.setTypeSQL(typeSQL); - field.setIsNullable( !typeSQL.toLowerCase().contains("not null")); - field.setTypeUniversal(FieldType.fromString(rs.getString("TYPE").toUpperCase())); - field.setLength(rs.getInt("DATA_LENGTH")); - field.setScale(rs.getInt("DATA_SCALE")); - field.setPrecision(rs.getInt("DATA_PRECISION")); - field.setFixed(rs.getBoolean("fixed")); - field.setOrder(rs.getInt("column_id")); + final Map listField = new HashMap(); + + final String pkNameQuery = + "SELECT column_name FROM all_constraints cons, all_cons_columns cols\n"+ + "WHERE upper(cols.table_name) = upper('" + nameTable + "')\n"+ + "AND cons.constraint_type = 'P'\n" + + "AND cons.constraint_name = cols.constraint_name\n" + + "AND cons.owner = cols.owner"; + + final String query = + "SELECT " + + " case \r\n" + + " when lower(data_type) in ('number', 'numeric', 'dec', 'decimal', 'pls_integer') then 'number'\r\n" + + " when lower(data_type) in ('varchar2', 'varchar', 'char', 'nchar', 'nvarchar2') then 'string'\r\n" + + " when substr(lower(data_type), 1, instr(data_type, '(') - 1) in ('date', 'timestamp') then 'date'\r\n" + + " when lower(data_type) in ('date', 'timestamp') then 'date'\r\n" + + " when lower(data_type) in ('clob') then 'text'\r\n" + + " when lower(data_type) in ('blob') then 'binary'" + + " else 'native'\r\n" + + " end type, " + + " case " + + " when lower(data_type) in ('char', 'nchar') then 1 else 0 " + + " end fixed, " + + " ROWNUM AS NUM, " + + " TC.* \n" + + " DTC.COMMENTS \n" + + "FROM DBA_TAB_COLS TC \n" + + "LEFT OUTER JOIN dba_tables T " + + " ON T.TABLE_NAME = TC.TABLE_NAME " + + " AND T.COLUMN_NAME = TC.COLUMN_NAME \n" + + " AND T.OWNER = TC.OWNER \n" + + //So I checked the documentation it turns out Oracle 10g added a column called DROPPED to the USER_/ALL_/DBA_TABLES views. + ( (getDbVersionNumber() >= 10) ? + " AND T.DROPPED = 'NO' \n" : "" ) + + "LEFT OUTER JOIN dba_tab_comment TCOM " + + " ON TCOM.OWNER = T.OWNER " + + " AND TCOM.TABLE_NAME = T.TABLE_NAME " + + " AND TCOM.COLUMN_NAME = TC.COLUMN_NAME " + + "WHERE lower(table_name) = lower('" + nameTable + "') AND lower(OWNER) = lower('" + schema + "') ORDER BY column_id"; + + try ( + Statement stmt = getConnection().createStatement(); + ResultSet pkRs = stmt.executeQuery(pkNameQuery); + ResultSet fieldsRs = stmt.executeQuery(query); + ){ + + final Set pkColumnNames = new HashSet<>(); + while (pkRs.next()) { pkColumnNames.add(pkRs.getString("COLUMN_NAME").toLowerCase()); } + while(fieldsRs.next()){ + //TODO make restore 'description', 'column default' + final String columnName = fieldsRs.getString("COLUMN_NAME").toLowerCase(); + final String columnDesc = fieldsRs.getString("COMMENTS"); + final Long columnDefault = fieldsRs.getLong("DATA_DEFAULT"); + final String typeSQL = getFieldType(fieldsRs); + final FieldType typeUniversal = FieldType.fromString(fieldsRs.getString("TYPE").toUpperCase()); + final int order = fieldsRs.getInt("column_id"); + final boolean isPrimaryKey = pkColumnNames.contains(columnName); + final boolean isNullable = !typeSQL.toLowerCase().contains("not null"); + final boolean fixed = fieldsRs.getBoolean("fixed"); + final int dataLength = fieldsRs.getInt("DATA_LENGTH"); + final int dataScale = fieldsRs.getInt("DATA_SCALE"); + final int dataPrecision = fieldsRs.getInt("DATA_PRECISION"); + + + final DBTableField field = new DBTableField( + columnName, + columnDesc != null ? columnDesc : "", + isPrimaryKey, + isNullable, + typeSQL, typeUniversal, order, + columnDefault != null ? String.valueOf(columnDefault) : "", + dataLength, dataScale, dataPrecision, fixed + ); + + listField.put(field.getName(), field); } - - stmt.close(); - - return listField; - }catch(Exception e) { - logger.error(lang.getValue("errors", "adapter", "tables").toString(), e); - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "tables").toString(), e); - } + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "tableData").toString(); + throw new ExceptionDBGitRunTime(msg, e); + } + + return listField; } - protected String getFieldType(ResultSet rs) { - try { - StringBuilder type = new StringBuilder(); - type.append(rs.getString("DATA_TYPE")); - - Integer max_length = rs.getInt("CHAR_LENGTH"); - if (!rs.wasNull() && !rs.getString("DATA_TYPE").contains("(")) { - type.append("("+max_length.toString()+")"); - } - - if (rs.getString("NULLABLE").equals("N")){ - type.append(" NOT NULL"); - } - - return type.toString(); - }catch(Exception e) { - logger.error(lang.getValue("errors", "adapter", "tables").toString(), e); - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "tables").toString(), e); - } + protected String getFieldType(ResultSet rs) throws SQLException { + final StringBuilder type = new StringBuilder(); + final Integer max_length = rs.getInt("CHAR_LENGTH"); + final String data_type = rs.getString("DATA_TYPE"); + + type.append(data_type); + + if (!rs.wasNull() && !data_type.contains("(")) { + type.append("("+max_length.toString()+")"); + } + + if (rs.getString("NULLABLE").equals("N")){ + type.append(" NOT NULL"); + } + + return type.toString(); } @Override public Map getIndexes(String schema, String nameTable) { - Map indexes = new HashMap<>(); - try { - String query = "SELECT ind.index_name, (select dbms_metadata.get_ddl('INDEX', ind.INDEX_NAME, owner) AS DDL from dual) AS DDL\n" + - "FROM all_indexes ind\n" + - "WHERE upper(table_name) = upper('" + nameTable + "') AND upper(owner) = upper('" + schema + "')"; - - Statement stmt = connect.createStatement(); - ResultSet rs = stmt.executeQuery(query); + final Map indexes = new HashMap<>(); + final String query = + "SELECT ind.index_name, (select dbms_metadata.get_ddl('INDEX', ind.INDEX_NAME, owner) AS DDL from dual) AS DDL\n" + + "FROM all_indexes ind\n" + + "WHERE upper(table_name) = upper('" + nameTable + "') AND upper(owner) = upper('" + schema + "')"; + + try (Statement stmt = connect.createStatement(); ResultSet rs = stmt.executeQuery(query);){ while(rs.next()){ - DBIndex index = new DBIndex(); - index.setName(rs.getString("INDEX_NAME")); - index.setSchema(schema); - rowToProperties(rs, index.getOptions()); + //TODO find real owner + final String name = rs.getString("INDEX_NAME"); + final String sql = rs.getString("DDL"); + final DBIndex index = new DBIndex(name, new StringProperties(rs), schema, schema, Collections.emptySet(), sql); indexes.put(index.getName(), index); } - stmt.close(); - - return indexes; - - }catch(Exception e) { - logger.error(lang.getValue("errors", "adapter", "indexes").toString()); - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "indexes").toString(), e); + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "indexes").toString(); + throw new ExceptionDBGitRunTime(msg, e); } + + return indexes; } @Override public Map getConstraints(String schema, String nameTable) { - Map constraints = new HashMap<>(); - try { - String query = "SELECT cons.constraint_type, cons.CONSTRAINT_NAME, (select dbms_metadata.get_ddl('CONSTRAINT', cons.constraint_name, owner) AS DDL from dual) AS DDL\n" + - "FROM all_constraints cons\n" + - "WHERE upper(owner) = upper('" + schema + "') and upper(table_name) = upper('" + nameTable + "') and constraint_name not like 'SYS%' and cons.constraint_type = 'P'"; + final Map constraints = new HashMap<>(); + + final String query = + "SELECT cons.constraint_type, cons.CONSTRAINT_NAME, (select dbms_metadata.get_ddl('CONSTRAINT', cons.constraint_name, owner) AS DDL from dual) AS DDL\n" + + "FROM all_constraints cons\n" + + "WHERE upper(owner) = upper('" + schema + "') and upper(table_name) = upper('" + nameTable + "') and constraint_name not like 'SYS%' and cons.constraint_type = 'P'"; + + try (Statement stmt = connect.createStatement(); ResultSet rs = stmt.executeQuery(query);) { - Statement stmt = connect.createStatement(); - ResultSet rs = stmt.executeQuery(query); - while(rs.next()){ - DBConstraint con = new DBConstraint(); - con.setName(rs.getString("CONSTRAINT_NAME")); - //This is DDL? - con.setConstraintType(rs.getString("CONSTRAINT_TYPE")); - con.setSchema(schema); - rowToProperties(rs, con.getOptions()); + //TODO find real owner + final String name = rs.getString("CONSTRAINT_NAME"); + final String sql = rs.getString("DDL"); + final String type = rs.getString("CONSTRAINT_TYPE"); + final String owner = schema; + final StringProperties options = new StringProperties(rs); + + final DBConstraint con = new DBConstraint(name, options, schema, owner, Collections.emptySet(), sql, type); constraints.put(con.getName(), con); } - stmt.close(); - - return constraints; - - }catch(Exception e) { - logger.error(lang.getValue("errors", "adapter", "constraints").toString()); - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "constraints").toString(), e); + + } + catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "constraints").toString(); + throw new ExceptionDBGitRunTime(msg, e); } + + return constraints; } @Override public Map getViews(String schema) { - Map listView = new HashMap(); - try { - String query = "SELECT f.owner, f.object_name, (select dbms_metadata.get_ddl('VIEW', f.object_name, f.owner) AS DDL from dual) AS DDL \n" + - "FROM all_objects f WHERE f.owner = '" + schema + "' and f.object_type = 'VIEW'"; - Connection connect = getConnection(); - Statement stmt = connect.createStatement(); - ResultSet rs = stmt.executeQuery(query); + final Map listView = new HashMap(); + final String query = + "SELECT f.owner, f.object_name, (select dbms_metadata.get_ddl('VIEW', f.object_name, f.owner) AS DDL from dual) AS DDL \n" + + "FROM all_objects f " + + "WHERE f.owner = '" + schema + "' and f.object_type = 'VIEW'"; + + try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);) { + while(rs.next()){ - DBView view = new DBView(rs.getString("OBJECT_NAME")); - view.setSchema(rs.getString("OWNER")); - view.setOwner(rs.getString("OWNER")); - rowToProperties(rs, view.getOptions()); - listView.put(rs.getString("OBJECT_NAME"), view); + final String name = rs.getString("OBJECT_NAME"); + final String owner = rs.getString("OWNER"); + final String sql = rs.getString("DDL"); + final StringProperties options = new StringProperties(rs); + final Set dependencies = Collections.emptySet(); + + final DBView view = new DBView(name, options, schema, owner, dependencies, sql); + listView.put(name, view); } - stmt.close(); - return listView; - }catch(Exception e) { - logger.error(lang.getValue("errors", "adapter", "views") + ": "+ e.getMessage()); - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "views") + ": " + e.getMessage()); + + } catch(Exception e) { + final DBGitLang msg = lang.getValue("errors", "adapter", "views"); + throw new ExceptionDBGitRunTime(msg, e); } + + return listView; } @Override public DBView getView(String schema, String name) { - DBView view = new DBView(name); - view.setSchema(schema); - try { - String query = "SELECT f.owner, f.object_name, (select dbms_metadata.get_ddl('VIEW', f.object_name, f.owner) AS DDL from dual) AS DDL \n" + - "FROM all_objects f WHERE f.owner = '" + schema + "' and f.object_type = 'VIEW' and f.object_name = '" + name + "'"; - Connection connect = getConnection(); - Statement stmt = connect.createStatement(); - ResultSet rs = stmt.executeQuery(query); - - view.setOwner(schema); - - while (rs.next()) { - view.setOwner(rs.getString("OWNER")); - rowToProperties(rs, view.getOptions()); - } - stmt.close(); - return view; - - }catch(Exception e) { - logger.error(lang.getValue("errors", "adapter", "views").toString() + ": "+ e.getMessage()); - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "views").toString() + ": "+ e.getMessage()); + + final String query = + "SELECT f.owner, f.object_name, (select dbms_metadata.get_ddl('VIEW', f.object_name, f.owner) AS DDL from dual) AS DDL \n" + + "FROM all_objects f WHERE f.owner = '" + schema + "' and f.object_type = 'VIEW' and f.object_name = '" + name + "'"; + + try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query); ){ + + if (!rs.next()) throw new ExceptionDBGitObjectNotFound("view is not found in db"); + + final String owner = rs.getString("owner"); + final String sql = rs.getString("DDL"); + final StringProperties options = new StringProperties(rs); + return new DBView(name, options, schema, owner, Collections.emptySet(), sql); + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "views").toString(); + throw new ExceptionDBGitRunTime(msg, e); } + } public Map getTriggers(String schema) { - Map listTrigger = new HashMap(); - try { - String query = "SELECT tr.owner, tr.trigger_name, tr.trigger_type, tr.table_name," + - " (select dbms_metadata.get_ddl('TRIGGER', tr.trigger_name, tr.owner) AS DDL from dual) AS DDL\n" + - "FROM all_triggers tr\n" + - "WHERE owner = '"+ schema +"'"; - - Connection connect = getConnection(); - Statement stmt = connect.createStatement(); - - ResultSet rs = stmt.executeQuery(query); + + final Map listTrigger = new HashMap(); + final String query = + "SELECT tr.owner, tr.trigger_name, tr.trigger_type, tr.table_name," + + " (select dbms_metadata.get_ddl('TRIGGER', tr.trigger_name, tr.owner) AS DDL from dual) AS DDL\n" + + "FROM all_triggers tr\n" + + "WHERE owner = '"+ schema +"'"; + + try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);) { + while(rs.next()){ - String name = rs.getString("TRIGGER_NAME"); - String sql = rs.getString("DDL"); - DBTrigger trigger = new DBTrigger(name); - trigger.setSchema(schema); + //TODO find real owner //what means owner? oracle/postgres or owner like database user/schema - trigger.setOwner("oracle"); - rowToProperties(rs, trigger.getOptions()); + final String owner = rs.getString("owner"); + final String name = rs.getString("TRIGGER_NAME"); + final String sql = rs.getString("DDL"); + final StringProperties options = new StringProperties(rs); + + final DBTrigger trigger = new DBTrigger(name, options, schema, owner, Collections.emptySet(), sql); listTrigger.put(name, trigger); } - stmt.close(); - return listTrigger; - }catch(Exception e) { - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "triggers").toString(), e); + + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "triggers").toString(); + throw new ExceptionDBGitRunTime(msg, e); } + + return listTrigger; } public DBTrigger getTrigger(String schema, String name) { - DBTrigger trigger = null; - try { - String query = "SELECT tr.owner, tr.trigger_name, tr.trigger_type, tr.table_name, (select dbms_metadata.get_ddl('TRIGGER', tr.trigger_name, tr.owner) AS DDL from dual) AS DDL\n" + - "FROM all_triggers tr\n" + - "WHERE owner = '" + schema + "' and trigger_name = '" + name + "'"; - - Statement stmt = connect.createStatement(); - ResultSet rs = stmt.executeQuery(query); - while(rs.next()){ - trigger = new DBTrigger(name); - trigger.setSchema(schema); - //what means owner? oracle/postgres or owner like database user/schema - trigger.setOwner("oracle"); - rowToProperties(rs, trigger.getOptions()); - } - stmt.close(); - return trigger; - }catch(Exception e) { - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "triggers").toString(), e); + final String query = + "SELECT tr.owner, tr.trigger_name, tr.trigger_type, tr.table_name, (select dbms_metadata.get_ddl('TRIGGER', tr.trigger_name, tr.owner) AS DDL from dual) AS DDL\n" + + "FROM all_triggers tr\n" + + "WHERE owner = '" + schema + "' and trigger_name = '" + name + "'"; + + try (Statement stmt = connect.createStatement(); ResultSet rs = stmt.executeQuery(query);) { + + if(!rs.next()) throw new ExceptionDBGitObjectNotFound("trigger is not found in database"); + + final String owner = rs.getString("owner"); + final String sql = rs.getString("DDL"); + final StringProperties options = new StringProperties(rs); + + return new DBTrigger(name, options, schema, owner, Collections.emptySet(), sql); + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "triggers").toString(); + throw new ExceptionDBGitRunTime(msg, e); } + } @Override public Map getPackages(String schema) { - Map listPackage = new HashMap(); - try { - String query = "SELECT f.owner, f.object_name, (select dbms_metadata.get_ddl('PACKAGE', f.object_name, f.owner) AS DDL from dual) AS DDL \n" + - "FROM all_objects f WHERE f.owner = '" + schema + "' and f.object_type = 'PACKAGE'"; - Connection connect = getConnection(); - Statement stmt = connect.createStatement(); - ResultSet rs = stmt.executeQuery(query); + final Map listPackage = new HashMap(); + final String query = + "SELECT f.owner, f.object_name, (select dbms_metadata.get_ddl('PACKAGE', f.object_name, f.owner) AS DDL from dual) AS DDL \n" + + "FROM all_objects f WHERE f.owner = '" + schema + "' and f.object_type = 'PACKAGE'"; + + try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query); ){ + while(rs.next()){ - String name = rs.getString("OBJECT_NAME"); - String owner = rs.getString("OWNER"); + final String name = rs.getString("OBJECT_NAME"); + final String owner = rs.getString("OWNER"); + final String sql = rs.getString("DDL"); + final StringProperties options = new StringProperties(rs); + //String args = rs.getString("arguments"); - DBPackage pack = new DBPackage(name); - pack.setSchema(schema); - pack.setOwner(owner); - rowToProperties(rs,pack.getOptions()); //pack.setArguments(args); + + final DBPackage pack = new DBPackage(name, options, schema, owner, Collections.emptySet(), sql); listPackage.put(name, pack); } - stmt.close(); - }catch(Exception e) { - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "pkg").toString(), e); + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "pkg").toString(); + throw new ExceptionDBGitRunTime(msg, e); } + return listPackage; } @Override public DBPackage getPackage(String schema, String name) { - try { - String query = "SELECT f.owner, f.object_name, (select dbms_metadata.get_ddl('PACKAGE', f.object_name, f.owner) AS DDL from dual) AS DDL \n" + - "FROM all_objects f WHERE f.owner = '" + schema + "' and f.object_type = 'PACKAGE' and f.object_name = '" + name + "'"; - Connection connect = getConnection(); - Statement stmt = connect.createStatement(); - ResultSet rs = stmt.executeQuery(query); - - DBPackage pack = null; - while (rs.next()) { - pack = new DBPackage(name); - String owner = rs.getString("OWNER"); - //String args = rs.getString("arguments"); - pack.setSchema(schema); - pack.setOwner(owner); - //pack.setArguments(args); - rowToProperties(rs,pack.getOptions()); - } - stmt.close(); - - return pack; - - }catch(Exception e) { - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "views").toString(), e); + final String query = + "SELECT f.owner, f.object_name, (select dbms_metadata.get_ddl('PACKAGE', f.object_name, f.owner) AS DDL from dual) AS DDL \n" + + "FROM all_objects f WHERE f.owner = '" + schema + "' and f.object_type = 'PACKAGE' and f.object_name = '" + name + "'"; + + try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);) { + + if (!rs.next()) throw new ExceptionDBGitObjectNotFound("package is not found in db"); + + final String owner = rs.getString("OWNER"); + final String sql = rs.getString("DDL"); + final StringProperties options = new StringProperties(rs); + + //String args = rs.getString("arguments"); + //pack.setArguments(args); + return new DBPackage(name, options, schema, owner, Collections.emptySet(), sql); + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "views").toString(); + throw new ExceptionDBGitRunTime(msg, e); } + } @Override public Map getProcedures(String schema) { - Map listProcedure = new HashMap(); - try { - String query = "SELECT f.owner, f.object_name, (select listagg(DATA_TYPE, ' ' ) within group (order by DATA_TYPE) from ALL_ARGUMENTS " + - "WHERE object_name = f.OBJECT_NAME AND owner = f.owner) arguments, (select dbms_metadata.get_ddl('PROCEDURE', f.object_name, f.owner) AS DDL from dual) AS DDL \n" + - "FROM all_objects f WHERE f.owner = '" + schema + "' and f.object_type = 'PROCEDURE'"; - Connection connect = getConnection(); - Statement stmt = connect.createStatement(); - ResultSet rs = stmt.executeQuery(query); + final Map listProcedure = new HashMap(); + final String query = + "SELECT f.owner, f.object_name, (select listagg(DATA_TYPE, ' ' ) within group (order by DATA_TYPE) from ALL_ARGUMENTS " + + "WHERE object_name = f.OBJECT_NAME AND owner = f.owner) arguments, (select dbms_metadata.get_ddl('PROCEDURE', f.object_name, f.owner) AS DDL from dual) AS DDL \n" + + "FROM all_objects f WHERE f.owner = '" + schema + "' " + + "AND f.object_type = 'PROCEDURE'"; + + try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);) { + while(rs.next()){ - String name = rs.getString("OBJECT_NAME"); - String owner = rs.getString("OWNER"); + final String name = rs.getString("OBJECT_NAME"); + final String owner = rs.getString("OWNER"); + final String sql = rs.getString("DDL"); + final StringProperties options = new StringProperties(rs); + //String args = rs.getString("arguments"); - DBProcedure proc = new DBProcedure(name); - proc.setSchema(schema); - proc.setOwner(owner); - proc.setName(name); - rowToProperties(rs,proc.getOptions()); //proc.setArguments(args); + final DBProcedure proc = new DBProcedure(name, options, schema, owner, Collections.emptySet(), sql); listProcedure.put(name, proc); } - stmt.close(); - }catch(Exception e) { - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "prc").toString(), e); + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "prc").toString(); + throw new ExceptionDBGitRunTime(msg, e); } + return listProcedure; } @Override public DBProcedure getProcedure(String schema, String name) { - try { - String query = "SELECT f.owner, f.object_name, (select listagg(DATA_TYPE, ' ' ) within group (order by DATA_TYPE) from ALL_ARGUMENTS " + - "WHERE object_name = f.OBJECT_NAME AND owner = f.owner) arguments, (select dbms_metadata.get_ddl('PROCEDURE', f.object_name, f.owner) AS DDL from dual) AS DDL \n" + - "FROM all_objects f WHERE f.owner = '" + schema + "' and f.object_type = 'PROCEDURE' and f.object_name = '" + name + "'"; - Connection connect = getConnection(); - Statement stmt = connect.createStatement(); - ResultSet rs = stmt.executeQuery(query); - DBProcedure proc = null; - - while (rs.next()) { - proc = new DBProcedure(rs.getString("OBJECT_NAME")); - String owner = rs.getString("OWNER"); - //String args = rs.getString("arguments"); - proc.setSchema(schema); - proc.setOwner(owner); - //proc.setArguments(args); - rowToProperties(rs,proc.getOptions()); - } - stmt.close(); - - return proc; - - }catch(Exception e) { - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "prc").toString(), e); + + final String query = + "SELECT f.owner, f.object_name, (select listagg(DATA_TYPE, ' ' ) within group (order by DATA_TYPE) from ALL_ARGUMENTS " + + "WHERE object_name = f.OBJECT_NAME AND owner = f.owner) arguments, (select dbms_metadata.get_ddl('PROCEDURE', f.object_name, f.owner) AS DDL from dual) AS DDL \n" + + "FROM all_objects f WHERE f.owner = '" + schema + "' and f.object_type = 'PROCEDURE' and f.object_name = '" + name + "'"; + + try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);) { + + if (!rs.next()) throw new ExceptionDBGitObjectNotFound("procedure is not found in database"); + + final String objName = rs.getString("OBJECT_NAME"); + final String owner = rs.getString("OWNER"); + final String sql = rs.getString("DDL"); + final StringProperties options = new StringProperties(rs); + + return new DBProcedure(name, options, schema, owner, Collections.emptySet(), sql); + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "prc").toString(); + throw new ExceptionDBGitRunTime(msg, e); } + } @Override public Map getFunctions(String schema) { - Map listFunction = new HashMap(); - try { - String query = "SELECT f.owner, f.object_name, (select listagg(DATA_TYPE, ' ' ) within group (order by DATA_TYPE) from ALL_ARGUMENTS \r\n" + - "WHERE object_name = f.OBJECT_NAME AND owner = f.owner) arguments, (select dbms_metadata.get_ddl('FUNCTION', f.object_name, f.owner) AS DDL from dual) AS DDL \n" + - "FROM all_objects f WHERE f.owner = '" + schema + "' and f.object_type = 'FUNCTION'"; - Connection connect = getConnection(); - Statement stmt = connect.createStatement(); - ResultSet rs = stmt.executeQuery(query); + final Map listFunction = new HashMap(); + final String query = + "SELECT f.owner, f.object_name, (select listagg(DATA_TYPE, ' ' ) within group (order by DATA_TYPE) from ALL_ARGUMENTS \r\n" + + "WHERE object_name = f.OBJECT_NAME AND owner = f.owner) arguments, (select dbms_metadata.get_ddl('FUNCTION', f.object_name, f.owner) AS DDL from dual) AS DDL \n" + + "FROM all_objects f WHERE f.owner = '" + schema + "' and f.object_type = 'FUNCTION'"; + + try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);) { while(rs.next()){ - String name = rs.getString("OBJECT_NAME"); - String sql = rs.getString("DDL"); - String owner = rs.getString("OWNER"); + final String name = rs.getString("OBJECT_NAME"); + final String sql = rs.getString("DDL"); + final String owner = rs.getString("OWNER"); + final StringProperties options = new StringProperties(rs); + //String args = rs.getString("arguments"); - DBFunction func = new DBFunction(name); - func.setSchema(schema); - func.setOwner(owner); - rowToProperties(rs,func.getOptions()); //func.setArguments(args); + final DBFunction func = new DBFunction(name, options, schema, owner, Collections.emptySet(), sql); listFunction.put(name, func); } - stmt.close(); - }catch(Exception e) { - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "fnc").toString(), e); + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "fnc").toString(); + throw new ExceptionDBGitRunTime(msg, e); } + return listFunction; } @Override public DBFunction getFunction(String schema, String name) { - try { - String query = "SELECT f.owner, f.object_name, (select listagg(DATA_TYPE, ' ' ) within group (order by DATA_TYPE) from ALL_ARGUMENTS " + - "WHERE object_name = f.OBJECT_NAME AND owner = f.owner) arguments, (select dbms_metadata.get_ddl('FUNCTION', f.object_name, f.owner) AS DDL from dual) AS DDL \n" + - "FROM all_objects f WHERE f.owner = '" + schema +"' and " + - "f.object_type = 'FUNCTION' and f.object_name = '" + name +"'"; - Connection connect = getConnection(); - Statement stmt = connect.createStatement(); - ResultSet rs = stmt.executeQuery(query); - DBFunction func = null; - - while (rs.next()) { - func = new DBFunction(rs.getString("OBJECT_NAME")); - String owner = rs.getString("OWNER"); - //String args = rs.getString("arguments"); - func.setSchema(schema); - func.setOwner(owner); - //func.setArguments(args); - rowToProperties(rs,func.getOptions()); - } - stmt.close(); - - return func; - - }catch(Exception e) { - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "fnc").toString(), e); + + final String query = + "SELECT f.owner, f.object_name, (select listagg(DATA_TYPE, ' ' ) within group (order by DATA_TYPE) from ALL_ARGUMENTS " + + "WHERE object_name = f.OBJECT_NAME AND owner = f.owner) arguments, (select dbms_metadata.get_ddl('FUNCTION', f.object_name, f.owner) AS DDL from dual) AS DDL \n" + + "FROM all_objects f WHERE f.owner = '" + schema +"' and " + + "f.object_type = 'FUNCTION' and f.object_name = '" + name +"'"; + + try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);) { + + if (!rs.next()) throw new ExceptionDBGitObjectNotFound("function is not found in database"); + + final String objName = rs.getString("OBJECT_NAME"); + final String owner = rs.getString("OWNER"); + final String sql = rs.getString("DDL"); + final StringProperties options = new StringProperties(rs); + + + //String args = rs.getString("arguments"); + //func.setArguments(args); + return new DBFunction(objName, options, schema, owner, Collections.emptySet(), sql); + + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "fnc").toString(); + throw new ExceptionDBGitRunTime(msg, e); } + } @Override public DBTableData getTableDataPortion(String schema, String nameTable, int portionIndex, int tryNumber) { - DBTableData data = new DBTableData(); - + + final int portionSize = DBGitConfig.getInstance().getInteger("core", "PORTION_SIZE", DBGitConfig.getInstance().getIntegerGlobal("core", "PORTION_SIZE", 1000)); + final int begin = 1 + portionSize*portionIndex; + final int end = portionSize + portionSize*portionIndex; + + final String dataQuery = + "SELECT * FROM (" + + " SELECT f.*, ROW_NUMBER() OVER (ORDER BY rowid) DBGIT_ROW_NUM " + + " FROM " + schema + "." + nameTable + " f" + + ") " + + "WHERE DBGIT_ROW_NUM BETWEEN " + begin + " and " + end; + try { - int portionSize = DBGitConfig.getInstance().getInteger("core", "PORTION_SIZE", DBGitConfig.getInstance().getIntegerGlobal("core", "PORTION_SIZE", 1000)); - - int begin = 1 + portionSize*portionIndex; - int end = portionSize + portionSize*portionIndex; - - Statement st = getConnection().createStatement(); - ResultSet rs = st.executeQuery(" SELECT * FROM \r\n" + - " (SELECT f.*, ROW_NUMBER() OVER (ORDER BY rowid) DBGIT_ROW_NUM FROM " + schema + "." + nameTable + " f)\r\n" + - " WHERE DBGIT_ROW_NUM BETWEEN " + begin + " and " + end); - data.setResultSet(rs); - return data; + + return new DBTableData(getConnection(), dataQuery); + } catch(Exception e) { - ConsoleWriter.println("Connection lost!"); + + final int maxTriesCount = DBGitConfig.getInstance().getInteger("core", "TRY_COUNT", DBGitConfig.getInstance().getIntegerGlobal("core", "TRY_COUNT", 1000)); + final int tryDelay = DBGitConfig.getInstance().getInteger("core", "TRY_DELAY", DBGitConfig.getInstance().getIntegerGlobal("core", "TRY_DELAY", 1000)); + + ConsoleWriter.println(e.getLocalizedMessage(), messageLevel); + ConsoleWriter.detailsPrintln(ExceptionUtils.getStackTrace(e), messageLevel); logger.error(lang.getValue("errors", "adapter", "tableData").toString(), e); - try { - if (tryNumber <= DBGitConfig.getInstance().getInteger("core", "TRY_COUNT", DBGitConfig.getInstance().getIntegerGlobal("core", "TRY_COUNT", 1000))) { - try { - TimeUnit.SECONDS.sleep(DBGitConfig.getInstance().getInteger("core", "TRY_DELAY", DBGitConfig.getInstance().getIntegerGlobal("core", "TRY_DELAY", 1000))); - } catch (InterruptedException e1) { - throw new ExceptionDBGitRunTime(e1.getMessage()); - } - ConsoleWriter.println("Error while getting portion of data, try " + tryNumber); - return getTableDataPortion(schema, nameTable, portionIndex, tryNumber++); + if (tryNumber <= maxTriesCount) { + + final String waitMessage = DBGitLang.getInstance() + .getValue("errors", "dataTable", "wait") + .withParams(String.valueOf(tryDelay)); + + final String tryAgainMessage = DBGitLang.getInstance() + .getValue("errors", "dataTable", "tryAgain") + .withParams(String.valueOf(tryNumber)); + + ConsoleWriter.println(waitMessage, messageLevel); + try { TimeUnit.SECONDS.sleep(tryDelay); } catch (InterruptedException e1) { + throw new ExceptionDBGitRunTime(e1.getMessage()); } - } catch (Exception e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } - try { - getConnection().rollback(); - } catch (Exception e2) { - logger.error(lang.getValue("errors", "adapter", "rollback").toString(), e2); + ConsoleWriter.println(tryAgainMessage, messageLevel); + return getTableDataPortion(schema, nameTable, portionIndex, tryNumber++); + + } else { + final String msg = DBGitLang.getInstance().getValue("errors", "adapter", "tableData").toString(); + throw new ExceptionDBGitRunTime(msg, e); } - throw new ExceptionDBGitRunTime(e.getMessage()); } } @Override public DBTableData getTableData(String schema, String nameTable) { - String tableName = schema + "." + nameTable; + final String tableName = schema + "." + nameTable; + final Boolean isFetchLimited = DBGitConfig.getInstance().getBoolean("core", "LIMIT_FETCH", DBGitConfig.getInstance().getBooleanGlobal("core", "LIMIT_FETCH", true)); + final int maxRowsCount = DBGitConfig.getInstance().getInteger("core", "MAX_ROW_COUNT_FETCH", DBGitConfig.getInstance().getIntegerGlobal("core", "MAX_ROW_COUNT_FETCH", MAX_ROW_COUNT_FETCH)); + final String dataQuery = "select * from " + tableName; try { - DBTableData data = new DBTableData(); - - int maxRowsCount = DBGitConfig.getInstance().getInteger("core", "MAX_ROW_COUNT_FETCH", DBGitConfig.getInstance().getIntegerGlobal("core", "MAX_ROW_COUNT_FETCH", MAX_ROW_COUNT_FETCH)); - - if (DBGitConfig.getInstance().getBoolean("core", "LIMIT_FETCH", DBGitConfig.getInstance().getBooleanGlobal("core", "LIMIT_FETCH", true))) { - Statement st = getConnection().createStatement(); - String query = "select COALESCE(count(*), 0) row_count from ( select 1 from "+ - tableName+" where ROWNUM <= " + (maxRowsCount + 1) + " ) tbl"; - ResultSet rs = st.executeQuery(query); - rs.next(); - if (rs.getInt("row_count") > maxRowsCount) { - data.setErrorFlag(DBTableData.ERROR_LIMIT_ROWS); - return data; + + if (isFetchLimited) { + final String rowsCountQuery = + "select COALESCE(count(*), 0) row_count " + + "from ( " + + " select 1 " + + " from " + tableName+ " " + + " where ROWNUM <= " + (maxRowsCount + 1) + " " + + ") tbl"; + try(Statement st = getConnection().createStatement(); ResultSet rs = st.executeQuery(rowsCountQuery);){ + + if(!rs.next()) throw new ExceptionDBGitRunTime("empty rows count resultset"); + + if (rs.getInt("row_count") > maxRowsCount) { + return new DBTableData(DBTableData.ERROR_LIMIT_ROWS); + } + } - } - Statement st = getConnection().createStatement(); - ResultSet rs = st.executeQuery("select * from "+tableName); - data.setResultSet(rs); - return data; - - } catch(Exception e) { - logger.error(lang.getValue("errors", "adapter", "tableData").toString(), e); - try { - getConnection().rollback(); - } catch (Exception e2) { - logger.error(lang.getValue("errors", "adapter", "rollback").toString(), e2); } - throw new ExceptionDBGitRunTime(e.getMessage()); + + return new DBTableData(getConnection(), dataQuery); + + } catch(Exception e) { + final String msg = DBGitLang.getInstance().getValue("errors", "adapter", "tableData").toString(); + throw new ExceptionDBGitRunTime(msg, e); } } -/* - @Override - public DBTableRow getTableRow(String schema, String nameTable, Object id) { - // TODO Auto-generated method stub - return null; - } -*/ + @Override public Map getUsers() { - Map listUser = new HashMap(); - try { - String query = "SELECT USERNAME FROM DBA_USERS WHERE USERNAME != 'PUBLIC' AND USERNAME != 'SYSTEM'\n" + - "AND USERNAME != 'SYS' AND USERNAME != 'APPQOSSYS' AND USERNAME != 'OUTLN' \n" + - "AND USERNAME != 'DIP' AND USERNAME != 'DBSNMP' AND USERNAME != 'ORACLE_OCM' ORDER BY USERNAME"; - Connection connect = getConnection(); - Statement stmt = connect.createStatement(); + final Map listUser = new HashMap(); + final String query = + "SELECT USERNAME FROM DBA_USERS WHERE USERNAME != 'PUBLIC' AND USERNAME != 'SYSTEM'\n" + + "AND USERNAME != 'SYS' AND USERNAME != 'APPQOSSYS' AND USERNAME != 'OUTLN' \n" + + "AND USERNAME != 'DIP' AND USERNAME != 'DBSNMP' AND USERNAME != 'ORACLE_OCM' ORDER BY USERNAME"; + + try ( + Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query); + ){ + while(rs.next()){ - String name = rs.getString(1); - DBUser user = new DBUser(name); + final String name = rs.getString(1); + final StringProperties options = new StringProperties(rs); + + final DBUser user = new DBUser(name, options); listUser.put(name, user); } - stmt.close(); - }catch(Exception e) { - logger.error(lang.getValue("errors", "adapter", "users") + ": " +e.getMessage()); - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "users") + ": " + e.getMessage()); + + } catch(Exception e) { + final DBGitLang msg = lang.getValue("errors", "adapter", "users"); + throw new ExceptionDBGitRunTime(msg, e); } + return listUser; } @Override public Map getRoles() { - Map listRole = new HashMap(); - try { - String query = "SELECT R.GRANTEE, \n" + - "R.GRANTED_ROLE, R.ADMIN_OPTION, R.DEFAULT_ROLE FROM DBA_ROLE_PRIVS R \n" + - "WHERE R.GRANTEE = (SELECT USERNAME FROM DBA_USERS WHERE USERNAME = R.GRANTEE AND\n" + - "USERNAME != 'PUBLIC' AND USERNAME != 'SYSTEM'\n" + - "AND USERNAME != 'SYS' AND USERNAME != 'APPQOSSYS' AND USERNAME != 'OUTLN' \n" + - "AND USERNAME != 'DIP' AND USERNAME != 'DBSNMP' AND USERNAME != 'ORACLE_OCM')"; - Connection connect = getConnection(); - Statement stmt = connect.createStatement(); + final Map listRole = new HashMap(); + final String query = + "SELECT R.GRANTEE, \n" + + "R.GRANTED_ROLE, R.ADMIN_OPTION, R.DEFAULT_ROLE FROM DBA_ROLE_PRIVS R \n" + + "WHERE R.GRANTEE = (SELECT USERNAME FROM DBA_USERS WHERE USERNAME = R.GRANTEE AND\n" + + "USERNAME != 'PUBLIC' AND USERNAME != 'SYSTEM'\n" + + "AND USERNAME != 'SYS' AND USERNAME != 'APPQOSSYS' AND USERNAME != 'OUTLN' \n" + + "AND USERNAME != 'DIP' AND USERNAME != 'DBSNMP' AND USERNAME != 'ORACLE_OCM')"; + try ( + Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query); + ) { + while(rs.next()){ - String name = rs.getString("GRANTED_ROLE"); - DBRole role = new DBRole(name); - rowToProperties(rs, role.getOptions()); + final String name = rs.getString("GRANTED_ROLE"); + final StringProperties options = new StringProperties(rs); + + final DBRole role = new DBRole(name, options); listRole.put(name, role); } - stmt.close(); - }catch(Exception e) { - logger.error(lang.getValue("errors", "adapter", "roles") + ": " + e.getMessage()); - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "roles") + ": " + e.getMessage()); + + } catch(Exception e) { + final DBGitLang msg = lang.getValue("errors", "adapter", "roles"); + throw new ExceptionDBGitRunTime(msg, e); } + return listRole; } @Override - public boolean userHasRightsToGetDdlOfOtherUsers() { - try { - String userName = getConnection().getSchema(); - - if (userName.equalsIgnoreCase("SYS")) - return true; - - PreparedStatement stmt = getConnection().prepareStatement - ("SELECT count(1) cnt FROM DBA_ROLE_PRIVS WHERE GRANTEE = ? and GRANTED_ROLE = 'SELECT_CATALOG_ROLE'"); - stmt.setString(1, userName); - ResultSet resultSet = stmt.executeQuery(); - resultSet.next(); - - if (resultSet.getInt(1) == 0) { - return false; - } else { - return true; - } - } catch (SQLException e) { - logger.error(e.getMessage()); - return false; - } + public Map getUDTs(String schema) { + return Collections.emptyMap(); } @Override - public IFactoryDBBackupAdapter getBackupAdapterFactory() { - return backupFactory; + public Map getDomains(String schema) { + return Collections.emptyMap(); } @Override - public DbType getDbType() { - return DbType.ORACLE; + public Map getEnums(String schema) { + return Collections.emptyMap(); } - + @Override - public String getDbVersion() { - try { - PreparedStatement stmt = getConnection().prepareStatement("SELECT version FROM V$INSTANCE"); - ResultSet resultSet = stmt.executeQuery(); - resultSet.next(); - - String result = resultSet.getString("version"); - resultSet.close(); - stmt.close(); - - return result; - } catch (SQLException e) { - return ""; - } + public DBUserDefinedType getUDT(String schema, String name) { + final String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); + throw new ExceptionDBGitObjectNotFound(msg); } @Override - public void createSchemaIfNeed(String schemaName) throws ExceptionDBGit { - try { - Statement st = connect.createStatement(); - ResultSet rs = st.executeQuery("select count(*) cnt from all_users where USERNAME = '" + schemaName.toUpperCase() + "'"); - rs.next(); - if (rs.getInt("cnt") == 0) { - StatementLogging stLog = new StatementLogging(connect, getStreamOutputSqlCommand(), isExecSql()); - stLog.execute("create USER \"" + schemaName.toUpperCase() + "\"\r\n" + - "IDENTIFIED BY \"" + schemaName.toUpperCase() + "\"\r\n" + - "DEFAULT TABLESPACE \"SYSTEM\"\r\n" + - "TEMPORARY TABLESPACE \"TEMP\"\r\n" + - "ACCOUNT UNLOCK"); - - stLog.execute("ALTER USER \"" + schemaName.toUpperCase() + "\" QUOTA UNLIMITED ON SYSTEM"); - stLog.close(); - } - - rs.close(); - st.close(); - } catch (SQLException e) { - throw new ExceptionDBGit(lang.getValue("errors", "adapter", "createSchema") + ": " + e.getLocalizedMessage()); - } - + public DBDomain getDomain(String schema, String name) { + final String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); + throw new ExceptionDBGitObjectNotFound(msg); } @Override - public boolean isReservedWord(String word) { - Set reservedWords = new HashSet<>(); + public DBEnum getEnum(String schema, String name) { + final String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); + throw new ExceptionDBGitObjectNotFound(msg); + } + static { reservedWords.add("ACCESS"); reservedWords.add("ADD"); reservedWords.add("ALL"); @@ -1006,27 +1104,5 @@ public boolean isReservedWord(String word) { reservedWords.add("WHENEVER"); reservedWords.add("WHERE"); reservedWords.add("WITH"); - - return reservedWords.contains(word.toUpperCase()); - } - - @Override - public IFactoryDBConvertAdapter getConvertAdapterFactory() { - return convertFactory; - } - - - @Override - public void createRoleIfNeed(String roleName) throws ExceptionDBGit { - } - - @Override - public String getDefaultScheme() throws ExceptionDBGit { - try { - return getConnection().getSchema(); - } catch (SQLException e) { - throw new ExceptionDBGit(lang.getValue("errors", "adapter", "getSchema") + ": " + e.getLocalizedMessage()); - } - } } diff --git a/src/main/java/ru/fusionsoft/dbgit/oracle/DBBackupAdapterOracle.java b/src/main/java/ru/fusionsoft/dbgit/oracle/DBBackupAdapterOracle.java index 6b2e12a..c896ff0 100644 --- a/src/main/java/ru/fusionsoft/dbgit/oracle/DBBackupAdapterOracle.java +++ b/src/main/java/ru/fusionsoft/dbgit/oracle/DBBackupAdapterOracle.java @@ -8,19 +8,17 @@ import ru.fusionsoft.dbgit.adapters.DBBackupAdapter; import ru.fusionsoft.dbgit.core.DBGitPath; +import ru.fusionsoft.dbgit.core.ExceptionDBGit; import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; import ru.fusionsoft.dbgit.dbobjects.DBConstraint; -import ru.fusionsoft.dbgit.meta.IMetaObject; -import ru.fusionsoft.dbgit.meta.MetaSequence; -import ru.fusionsoft.dbgit.meta.MetaSql; -import ru.fusionsoft.dbgit.meta.MetaTable; +import ru.fusionsoft.dbgit.meta.*; import ru.fusionsoft.dbgit.statement.StatementLogging; import ru.fusionsoft.dbgit.utils.ConsoleWriter; public class DBBackupAdapterOracle extends DBBackupAdapter { @Override - public IMetaObject backupDBObject(IMetaObject obj) throws Exception { + public IMetaObject backupDBObject(IMetaObject obj) throws SQLException, ExceptionDBGit { Connection connection = adapter.getConnection(); StatementLogging stLog = new StatementLogging(connection, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); @@ -32,7 +30,7 @@ public IMetaObject backupDBObject(IMetaObject obj) throws Exception { String ddl = metaSql.getSqlObject().getSql(); String schema = metaSql.getSqlObject().getSchema(); - ConsoleWriter.detailsPrint(lang.getValue("general", "backup", "tryingToCopy").withParams(objectName, getFullDbName(schema, objectName)), 1); + ConsoleWriter.detailsPrintln(lang.getValue("general", "backup", "tryingToCopy").withParams(objectName, getFullDbName(schema, objectName)), messageLevel); ddl = replaceNames(ddl, schema, objectName, stLog); @@ -56,7 +54,7 @@ public IMetaObject backupDBObject(IMetaObject obj) throws Exception { if (file.exists()) obj = metaSql.loadFromFile(); - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); } else if (obj instanceof MetaTable) { MetaTable metaTable = (MetaTable) obj; metaTable.loadFromDB(); @@ -66,10 +64,8 @@ public IMetaObject backupDBObject(IMetaObject obj) throws Exception { if(!isExists(schema, objectName)) return obj; - ConsoleWriter.detailsPrint(lang.getValue("general", "backup", "tryingToCopy").withParams(objectName, getFullDbName(schema, objectName)), 1); - - dropIfExists(isSaveToSchema() ? PREFIX + schema : schema, - isSaveToSchema() ? objectName : PREFIX + objectName, stLog); + ConsoleWriter.detailsPrintln(lang.getValue("general", "backup", "tryingToCopy").withParams(objectName, getFullDbName(schema, objectName)), messageLevel); + if (isToSaveData()) { String ddl = "create table " + (isSaveToSchema() ? "" : schema + ".") + @@ -102,7 +98,7 @@ public IMetaObject backupDBObject(IMetaObject obj) throws Exception { if (file.exists()) obj = metaTable.loadFromFile(); - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); } else if (obj instanceof MetaSequence) { MetaSequence metaSequence = (MetaSequence) obj; metaSequence.loadFromDB(); @@ -112,7 +108,7 @@ public IMetaObject backupDBObject(IMetaObject obj) throws Exception { String ddl = metaSequence.getSequence().getOptions().get("ddl").toString(); - ConsoleWriter.detailsPrint(lang.getValue("general", "backup", "tryingToCopy").withParams(objectName, getFullDbName(schema, objectName)), 1); + ConsoleWriter.detailsPrintln(lang.getValue("general", "backup", "tryingToCopy").withParams(objectName, getFullDbName(schema, objectName)), messageLevel); ddl = replaceNames(ddl, schema, objectName, stLog); @@ -122,11 +118,10 @@ public IMetaObject backupDBObject(IMetaObject obj) throws Exception { if (file.exists()) obj = metaSequence.loadFromFile(); - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); } } catch (Exception e) { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); throw new ExceptionDBGitRestore(lang.getValue("errors", "backup", "backupError").withParams(obj.getName()), e); } finally { stLog.close(); @@ -147,7 +142,7 @@ public void restoreDBObject(IMetaObject obj) throws Exception { } - private void dropIfExists(String owner, String objectName, StatementLogging stLog) throws Exception { + public void dropIfExists(String owner, String objectName, StatementLogging stLog) throws SQLException { Statement st = adapter.getConnection().createStatement(); ResultSet rs = st.executeQuery("select * from all_objects where owner = '" + owner + "' and object_name = '" + objectName + "' and OBJECT_TYPE not like 'PACKAGE BODY'"); @@ -159,9 +154,24 @@ private void dropIfExists(String owner, String objectName, StatementLogging stLo rs.close(); st.close(); } - + + @Override + public void dropIfExists(IMetaObject imo, StatementLogging stLog) throws SQLException, Exception { + NameMeta nm = new NameMeta(imo); + Statement st = adapter.getConnection().createStatement(); + ResultSet rs = st.executeQuery("select * from all_objects where owner = '" + nm.getSchema() + "' and object_name = '" + nm.getName() + "' and OBJECT_TYPE not like 'PACKAGE BODY'"); + + while (rs.next()) { + //ConsoleWriter.detailsPrintLn("Dropping " + owner + "." + objectName); + stLog.execute("drop " + rs.getString("OBJECT_TYPE") + " " + nm.getSchema() + "." + nm.getName()); + } + + rs.close(); + st.close(); + } + @Override - public boolean isExists(String owner, String objectName) throws Exception { + public boolean isExists(String owner, String objectName) throws SQLException { Statement st = adapter.getConnection().createStatement(); ResultSet rs = st.executeQuery("select count(*) cnt from all_objects where owner = '" + owner + "' and object_name = '" + objectName + "' and OBJECT_TYPE not like 'PACKAGE BODY'"); @@ -194,7 +204,7 @@ public boolean createSchema(StatementLogging stLog, String schema){ ResultSet rs = st.executeQuery("select count(*) cnt from all_users where USERNAME = '" + PREFIX + schema + "'"); rs.next(); if (rs.getInt("cnt") == 0) { - ConsoleWriter.detailsPrintLn(lang.getValue("general", "backup", "creatingSchema").withParams(PREFIX + schema)); + ConsoleWriter.detailsPrintln(lang.getValue("general", "backup", "creatingSchema").withParams(PREFIX + schema), messageLevel); stLog.execute("create USER \"" + PREFIX + schema + "\"\r\n" + "IDENTIFIED BY \"" + PREFIX + schema + "\"\r\n" + "DEFAULT TABLESPACE \"SYSTEM\"\r\n" + @@ -209,7 +219,7 @@ public boolean createSchema(StatementLogging stLog, String schema){ return true; } catch (SQLException e) { - ConsoleWriter.println(lang.getValue("errors", "backup", "cannotCreateSchema").withParams(e.getLocalizedMessage())); + ConsoleWriter.println(lang.getValue("errors", "backup", "cannotCreateSchema").withParams(e.getLocalizedMessage()), messageLevel); return false; } diff --git a/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestoreFunctionOracle.java b/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestoreFunctionOracle.java index 24023e7..736d146 100644 --- a/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestoreFunctionOracle.java +++ b/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestoreFunctionOracle.java @@ -19,7 +19,6 @@ public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { IDBAdapter adapter = getAdapter(); Connection connect = adapter.getConnection(); StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "restoreFnc").withParams(obj.getName()), 1); try { if (obj instanceof MetaFunction) { MetaFunction restoreFunction = (MetaFunction)obj; @@ -44,14 +43,15 @@ public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { } else { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "function", obj.getType().getValue() + )); } } catch (Exception e) { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); } finally { - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); st.close(); } return true; diff --git a/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestorePackageOracle.java b/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestorePackageOracle.java index 3a020f1..36c6b73 100644 --- a/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestorePackageOracle.java +++ b/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestorePackageOracle.java @@ -23,8 +23,7 @@ public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { IDBAdapter adapter = getAdapter(); Connection connect = adapter.getConnection(); st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "restorePkg").withParams(obj.getName()), 1); - try { + try { if (obj instanceof MetaPackage) { MetaPackage restorePackage = (MetaPackage) obj; Map pkgs = adapter.getPackages(restorePackage.getSqlObject().getSchema()); @@ -45,17 +44,18 @@ public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { executeSql(restorePackage.getSqlObject().getSql()); //TODO Восстановление привилегий } - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); } else { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "package", obj.getType().getValue() + )); } } catch (Exception e) { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); } finally { st.close(); diff --git a/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestoreProcedureOracle.java b/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestoreProcedureOracle.java index 68562b7..16c04a0 100644 --- a/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestoreProcedureOracle.java +++ b/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestoreProcedureOracle.java @@ -20,8 +20,7 @@ public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { IDBAdapter adapter = getAdapter(); Connection connect = adapter.getConnection(); StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "restorePrc").withParams(obj.getName()), 1); - try { + try { if (obj instanceof MetaProcedure) { MetaProcedure restoreProcedure = (MetaProcedure)obj; Map prcds = adapter.getProcedures(restoreProcedure.getSqlObject().getSchema()); @@ -41,17 +40,18 @@ public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { st.execute(restoreProcedure.getSqlObject().getSql(), "/"); //TODO Восстановление привилегий } - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); } else { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "procedure", obj.getType().getValue() + )); } } catch (Exception e) { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); } finally { st.close(); diff --git a/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestoreRoleOracle.java b/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestoreRoleOracle.java index 34d7b1d..4fbe8c9 100644 --- a/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestoreRoleOracle.java +++ b/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestoreRoleOracle.java @@ -19,7 +19,6 @@ public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { IDBAdapter adapter = getAdapter(); Connection connect = adapter.getConnection(); StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "restoreRole").withParams(obj.getName()), 1); try { if (obj instanceof MetaRole) { MetaRole restoreRole = (MetaRole)obj; @@ -60,15 +59,16 @@ public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { } //TODO restore memberOfRole - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); } else { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "role", obj.getType().getValue() + )); } } catch (Exception e) { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); } finally { st.close(); diff --git a/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestoreSchemaOracle.java b/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestoreSchemaOracle.java index 124f148..ae867ba 100644 --- a/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestoreSchemaOracle.java +++ b/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestoreSchemaOracle.java @@ -18,7 +18,6 @@ public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { IDBAdapter adapter = getAdapter(); Connection connect = adapter.getConnection(); StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "restoreSchema").withParams(obj.getName()), 1); try { if (obj instanceof MetaSchema) { MetaSchema restoreSchema = (MetaSchema)obj; @@ -44,15 +43,16 @@ public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { setPassword(restoreSchema)); //TODO Восстановление привилегий } - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); } else { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "schema", obj.getType().getValue() + )); } } catch (Exception e) { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); } finally { st.close(); diff --git a/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestoreSequenceOracle.java b/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestoreSequenceOracle.java index 44846c9..49f5b2b 100644 --- a/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestoreSequenceOracle.java +++ b/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestoreSequenceOracle.java @@ -19,7 +19,6 @@ public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { IDBAdapter adapter = getAdapter(); Connection connect = adapter.getConnection(); StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "restoreSeq").withParams(obj.getName()), 1); try { if (obj instanceof MetaSequence) { MetaSequence restoreSeq = (MetaSequence)obj; @@ -82,15 +81,16 @@ public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { st.execute(query); //TODO Восстановление привилегий } - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); } else { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "sequence", obj.getType().getValue() + )); } } catch (Exception e) { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); } finally { st.close(); diff --git a/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestoreTableDataOracle.java b/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestoreTableDataOracle.java index 9736ced..0f0bc42 100644 --- a/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestoreTableDataOracle.java +++ b/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestoreTableDataOracle.java @@ -1,15 +1,9 @@ package ru.fusionsoft.dbgit.oracle; -import java.io.BufferedReader; -import java.io.File; import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.IOException; -import java.io.InputStreamReader; -import java.sql.Clob; import java.sql.Connection; import java.sql.ResultSet; -import java.sql.SQLException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collection; @@ -17,7 +11,6 @@ import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; -import java.util.Set; import java.util.StringJoiner; import java.util.TreeMap; import java.util.stream.Collectors; @@ -29,10 +22,7 @@ import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter; import ru.fusionsoft.dbgit.adapters.IDBAdapter; -import ru.fusionsoft.dbgit.core.ExceptionDBGit; -import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; -import ru.fusionsoft.dbgit.core.GitMetaDataManager; -import ru.fusionsoft.dbgit.core.SchemaSynonym; +import ru.fusionsoft.dbgit.core.*; import ru.fusionsoft.dbgit.data_table.BooleanData; import ru.fusionsoft.dbgit.data_table.DateData; import ru.fusionsoft.dbgit.data_table.ICellData; @@ -46,7 +36,6 @@ import ru.fusionsoft.dbgit.meta.IMetaObject; import ru.fusionsoft.dbgit.meta.MetaTable; import ru.fusionsoft.dbgit.meta.MetaTableData; -import ru.fusionsoft.dbgit.statement.PrepareStatementLogging; import ru.fusionsoft.dbgit.statement.StatementLogging; import ru.fusionsoft.dbgit.utils.ConsoleWriter; @@ -84,14 +73,14 @@ public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { if (getAdapter().getTable(schema, currentTableData.getTable().getName()) != null) { currentTableData.setDataTable(getAdapter().getTableData(schema, currentTableData.getTable().getName())); - ResultSet rs = currentTableData.getDataTable().getResultSet(); + ResultSet rs = currentTableData.getDataTable().resultSet(); TreeMapRowData mapRows = new TreeMapRowData(); MetaTable metaTable = new MetaTable(currentTableData.getTable()); metaTable.loadFromDB(currentTableData.getTable()); - ConsoleWriter.println("ids: " + metaTable.getIdColumns()); +// ConsoleWriter.println("ids: " + metaTable.getIdColumns()); if (rs != null) { while(rs.next()) { @@ -111,7 +100,10 @@ public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { return true; } else { - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "table data", obj.getType().getValue() + )); } } @@ -123,7 +115,6 @@ private void restoreTableDataOracle(MetaTableData restoreTableData, MetaTableDat try { String tblName = getPhisicalSchema(restoreTableData.getTable().getSchema()) + "." + restoreTableData.getTable().getName(); - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "tableData").withParams(tblName) + "\n", 1); String insertQuery= ""; @@ -146,7 +137,7 @@ private void restoreTableDataOracle(MetaTableData restoreTableData, MetaTableDat } if(!diffTableData.entriesOnlyOnLeft().isEmpty()) { - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "inserting"), 2); + ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "inserting"), messageLevel); for(RowData rowData:diffTableData.entriesOnlyOnLeft().values()) { ArrayList fieldsList = new ArrayList(rowData.getData().keySet()); @@ -166,26 +157,28 @@ private void restoreTableDataOracle(MetaTableData restoreTableData, MetaTableDat } } - ConsoleWriter.detailsPrintLn(insertQuery); + ConsoleWriter.detailsPrintln(insertQuery, messageLevel); if (needSeparator) st.execute(insertQuery, "/"); else st.execute(insertQuery); } - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); } if(!diffTableData.entriesOnlyOnRight().isEmpty()) { boolean isSuccessful = true; - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "deleting"), 2); + ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "deleting"), messageLevel); for(RowData rowData : diffTableData.entriesOnlyOnRight().values()) { Map primarykeys = getKeys(rowData); if (primarykeys.size() == 0) { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - ConsoleWriter.printlnRed(lang.getValue("errors", "restore", "pkNotFound").withParams(tblName)); +// ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); + ConsoleWriter.printlnRed(lang.getValue("errors", "restore", "pkNotFound") + .withParams(tblName), messageLevel + ); isSuccessful = false; break; } @@ -198,20 +191,20 @@ private void restoreTableDataOracle(MetaTableData restoreTableData, MetaTableDat st.execute(deleteQuery); } - if (isSuccessful) ConsoleWriter.detailsPrintlnGreen("OK"); + if (isSuccessful) ConsoleWriter.detailsPrintlnGreen(DBGitLang.getInstance().getValue("general", "meta", "ok"), messageLevel); } if(!diffTableData.entriesDiffering().isEmpty()) { boolean isSuccessful = true; - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "updating"), 2); + ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "updating"), messageLevel); for (ValueDifference diffRowData:diffTableData.entriesDiffering().values()) { if (!diffRowData.leftValue().getHashRow().equals(diffRowData.rightValue().getHashRow())) { Map primarykeys = getKeys(diffRowData.leftValue()); if (primarykeys.size() == 0) { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - ConsoleWriter.printlnRed(lang.getValue("general", "restore", "pkNotFound").withParams(tblName)); + ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail"), messageLevel); + ConsoleWriter.printlnRed(lang.getValue("general", "restore", "pkNotFound").withParams(tblName),messageLevel); isSuccessful = false; break; } @@ -248,12 +241,13 @@ private void restoreTableDataOracle(MetaTableData restoreTableData, MetaTableDat } } - if (isSuccessful) ConsoleWriter.detailsPrintlnGreen("OK"); + if (isSuccessful) ConsoleWriter.detailsPrintlnGreen(DBGitLang.getInstance().getValue("general", "meta", "ok"), messageLevel); } } catch (Exception e) { - ConsoleWriter.println(lang.getValue("errors", "restore", "objectRestoreError").withParams(e.getLocalizedMessage())); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(restoreTableData.getTable().getSchema() + "." + restoreTableData.getTable().getName()), e); + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(restoreTableData.getTable().getSchema() + "." + restoreTableData.getTable().getName()) + , e + ); } finally { st.close(); } @@ -271,8 +265,8 @@ private Map getKeys(RowData rowData) { primarykeys.put(entry.getKey(), entry.getValue().convertToString()); } } catch (Exception e) { - ConsoleWriter.printlnRed(lang.getValue("general", "restore", "pkNotFound").withParams("")); - ConsoleWriter.printlnRed(e.getMessage()); + ConsoleWriter.printlnRed(lang.getValue("general", "restore", "pkNotFound").withParams(""),messageLevel); + ConsoleWriter.detailsPrintlnRed(e.getMessage(), messageLevel); } } }); @@ -282,7 +276,7 @@ private Map getKeys(RowData rowData) { private void restoreTableConstraintOracle(MetaTable table) throws Exception { - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "restoreConstr").withParams(table.getName()), 1); + ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "restoreConstr").withParams(table.getName()), messageLevel); IDBAdapter adapter = getAdapter(); Connection connect = adapter.getConnection(); StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); @@ -293,14 +287,12 @@ private void restoreTableConstraintOracle(MetaTable table) throws Exception { if(!constraint.getConstraintType().equalsIgnoreCase("p")) { String query = "alter table " + schema + "." + table.getTable().getName() + " add constraint "+ constraint.getName() + " " +constraint.getOptions().get("ddl").toString(); - ConsoleWriter.println(query); + ConsoleWriter.println(query, messageLevel); st.execute(query); } } - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); } catch (Exception e) { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - ConsoleWriter.println(lang.getValue("errors", "restore", "objectRestoreError").withParams(e.getLocalizedMessage())); throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(table.getTable().getName()), e); } finally { st.close(); @@ -308,7 +300,7 @@ private void restoreTableConstraintOracle(MetaTable table) throws Exception { } private void removeTableConstraintsOracle(MetaTable table) throws Exception { - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "delConstr").withParams(table.getName()), 1); + ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "delConstr").withParams(table.getName()), messageLevel); IDBAdapter adapter = getAdapter(); StatementLogging st = new StatementLogging(adapter.getConnection(), adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); String schema = getPhisicalSchema(table.getTable().getSchema()); @@ -327,15 +319,15 @@ private void removeTableConstraintsOracle(MetaTable table) throws Exception { //String query = "if (OBJECT_ID(" + schema + "." + constraint.getName() + ")) then begin alter table " + schema + "." + table.getTable().getName() // + " drop constraint " + constraint.getName() + "; end"; - ConsoleWriter.println(dropQuery); + ConsoleWriter.println(dropQuery, messageLevel); st.execute(dropQuery, "/"); } } - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); } catch (Exception e) { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - ConsoleWriter.println(lang.getValue("errors", "restore", "objectRestoreError").withParams(e.getLocalizedMessage())); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "cannotRestore").withParams(schema + "." + table.getTable().getName()), e); + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "cannotRestore").withParams(schema + "." + table.getTable().getName()) + , e + ); } finally { st.close(); } diff --git a/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestoreTableOracle.java b/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestoreTableOracle.java index 0cecf82..d06d879 100644 --- a/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestoreTableOracle.java +++ b/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestoreTableOracle.java @@ -1,431 +1,427 @@ -package ru.fusionsoft.dbgit.oracle; - -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.Comparator; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import com.google.common.collect.MapDifference; -import com.google.common.collect.Maps; -import com.google.common.collect.MapDifference.ValueDifference; - -import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter; -import ru.fusionsoft.dbgit.adapters.IDBAdapter; -import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; -import ru.fusionsoft.dbgit.core.SchemaSynonym; -import ru.fusionsoft.dbgit.dbobjects.DBConstraint; -import ru.fusionsoft.dbgit.dbobjects.DBIndex; -import ru.fusionsoft.dbgit.dbobjects.DBTable; -import ru.fusionsoft.dbgit.dbobjects.DBTableField; -import ru.fusionsoft.dbgit.meta.IMetaObject; -import ru.fusionsoft.dbgit.meta.MetaTable; -import ru.fusionsoft.dbgit.statement.StatementLogging; -import ru.fusionsoft.dbgit.utils.ConsoleWriter; - -public class DBRestoreTableOracle extends DBRestoreAdapter { - - @Override - public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { - if(Integer.valueOf(step).equals(0)) { - restoreTableOracle(obj); - return false; - } - /*if(Integer.valueOf(step).equals(1)) { - restoreTableFieldsOracle(obj); - return false; - }*/ - if(Integer.valueOf(step).equals(-21)) { - restoreTableIndexesOracle(obj); - return false; - } - if(Integer.valueOf(step).equals(-1)) { - restoreTableConstraintOracle(obj); - return false; - } - return true; - } - - public void restoreTableOracle(IMetaObject obj) throws Exception - { - IDBAdapter adapter = getAdapter(); - Connection connect = adapter.getConnection(); - StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - try { - if (obj instanceof MetaTable) { - - MetaTable restoreTable = (MetaTable)obj; - String schema = getPhisicalSchema(restoreTable.getTable().getSchema()); - schema = (SchemaSynonym.getInstance().getSchema(schema) == null) ? schema : SchemaSynonym.getInstance().getSchema(schema); - String tblName = schema+"."+restoreTable.getTable().getName(); - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "restoreTable").withParams(tblName) + "\n", 1); - - Map tables = adapter.getTables(schema.toUpperCase()); - boolean exist = false; - if(!(tables.isEmpty() || tables == null)) { - for(DBTable table:tables.values()) { - if(restoreTable.getTable().getName().equalsIgnoreCase(table.getName())){ - exist = true; - - } - } - } - if(!exist){ - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "createTable"), 2); - String ddl = ""; - if (restoreTable.getTable().getOptions().get("ddl") != null) - ddl = restoreTable.getTable().getOptions().get("ddl").getData() - .replace("\"" + restoreTable.getTable().getSchema().toUpperCase() + "\"", "\"" + schema.toUpperCase() + "\""); - else { - DBTable table = restoreTable.getTable(); - - Comparator comparator = (o1, o2) -> o1.getOrder().compareTo(o2.getOrder()); - - ddl = "create table " + schema + "." + table.getName() + - " (" + restoreTable.getFields().values().stream() - .sorted(comparator) - .map(field -> "" + (adapter.isReservedWord(field.getName()) ? "\"" + field.getName() + "\" " : field.getName()) + " " + field.getTypeSQL()) - .collect(Collectors.joining(", ")) + ")"; - } - st.execute(ddl); - - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); - } else { - //restore tabl fields - Map currentFileds = adapter.getTableFields(schema, restoreTable.getTable().getName().toLowerCase()); - MapDifference diffTableFields = Maps.difference(restoreTable.getFields(),currentFileds); - - if(!diffTableFields.entriesOnlyOnLeft().isEmpty()){ - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "addColumns"), 2); - - Comparator comparator = (o1, o2) -> o1.getOrder().compareTo(o2.getOrder()); - - List values = diffTableFields.entriesOnlyOnLeft().values().stream().collect(Collectors.toList()); - values.sort(comparator); - - for(DBTableField tblField : values) { - st.execute("alter table "+ tblName +" add " + tblField.getName() + " " + tblField.getTypeSQL()); - } - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); - } - - if(!diffTableFields.entriesOnlyOnRight().isEmpty()) { - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "droppingColumns"), 2); - for(DBTableField tblField:diffTableFields.entriesOnlyOnRight().values()) { - st.execute("alter table "+ tblName +" drop column "+ tblField.getName()); - } - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); - } - - if(!diffTableFields.entriesDiffering().isEmpty()) { - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "modifyColumns"), 2); - - for(ValueDifference tblField:diffTableFields.entriesDiffering().values()) { - if(!tblField.leftValue().getName().equals(tblField.rightValue().getName())) { - st.execute("alter table "+ tblName +" rename column "+ tblField.rightValue().getName() +" to "+ tblField.leftValue().getName()); - } - - if(!tblField.leftValue().getTypeUniversal().equals(tblField.rightValue().getTypeUniversal())) { - st.execute("alter table "+ tblName +" modify "+ tblField.leftValue().getName() +" "+ tblField.leftValue().getTypeSQL()); - } - } - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); - } - } - - ResultSet rs = st.executeQuery("SELECT COUNT(cons.constraint_name) constraintscount \n" + - "FROM all_constraints cons \n" + - "WHERE upper(owner) = upper('" + schema + "') and upper(table_name) = upper('" + restoreTable.getTable().getName()+ "') and constraint_name not like 'SYS%' and cons.constraint_type = 'P'"); - rs.next(); - Integer constraintsCount = Integer.valueOf(rs.getString("constraintscount")); - if(constraintsCount.intValue()>0) { - removeTableConstraintsOracle(obj); - } - // set primary key - boolean flagPkCreated = false; - for(DBConstraint tableconst: restoreTable.getConstraints().values()) { - if(tableconst.getConstraintType().equals("p")) { - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "addPk"), 2); - - if (tableconst.getOptions().get("ddl").toString().toLowerCase().startsWith("alter table")) - st.execute(tableconst.getOptions().get("ddl").toString().replace(" " +tableconst.getSchema() + ".", " " + schema + ".")); - else if (tableconst.getOptions().get("ddl").toString().toLowerCase().startsWith("primary key")) - st.execute("alter table "+ tblName +" add constraint PK_"+ tableconst.getName() + tableconst.getOptions().get("ddl").toString()); - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); - flagPkCreated = true; - break; - } - } - - if (!flagPkCreated) { - for(DBTableField field: restoreTable.getFields().values()) { - if (field.getIsPrimaryKey()) { - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "addPk"), 2); - st.execute("alter table "+ tblName +" add constraint pk_" + restoreTable.getTable().getName() + "_" + field.getName() + " PRIMARY KEY (" + field.getName() + ")"); - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); - break; - } - } - } - - - } - else - { - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); - } - } catch (SQLException e1) { - ConsoleWriter.detailsPrintlnRed(lang.getValue(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()) + "\n"+ e1.getLocalizedMessage())); - //throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()) + "\n"+ e1.getLocalizedMessage()); - } catch (Exception e) { - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); - } finally { - st.close(); - } - } - - public void restoreTableFieldsOracle(IMetaObject obj) throws Exception - { - IDBAdapter adapter = getAdapter(); - Connection connect = adapter.getConnection(); - StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - try { - if (obj instanceof MetaTable) { - MetaTable restoreTable = (MetaTable)obj; - String schema = getPhisicalSchema(restoreTable.getTable().getSchema()); - schema = (SchemaSynonym.getInstance().getSchema(schema) == null) ? schema : SchemaSynonym.getInstance().getSchema(schema); - String tblName = schema+"."+restoreTable.getTable().getName(); - Map tables = adapter.getTables(schema); - boolean exist = false; - if(!(tables.isEmpty() || tables == null)) { - for(DBTable table:tables.values()) { - if(restoreTable.getTable().getName().equals(table.getName())){ - exist = true; - } - } - } - if(!exist){ - st.execute(restoreTable.getTable().getOptions().get("ddl").getData()); - } - //restore tabl fields - Map currentFileds = adapter.getTableFields(schema, restoreTable.getTable().getName()); - MapDifference diffTableFields = Maps.difference(restoreTable.getFields(),currentFileds); - - if(!diffTableFields.entriesOnlyOnLeft().isEmpty()){ - for(DBTableField tblField:diffTableFields.entriesOnlyOnLeft().values()) { - st.execute("alter table "+ tblName +" add " + tblField.getName() + " " + tblField.getTypeSQL()); - } - } - - if(!diffTableFields.entriesOnlyOnRight().isEmpty()) { - for(DBTableField tblField:diffTableFields.entriesOnlyOnRight().values()) { - st.execute("alter table "+ tblName +" drop column "+ tblField.getName()); - } - } - - if(!diffTableFields.entriesDiffering().isEmpty()) { - for(ValueDifference tblField:diffTableFields.entriesDiffering().values()) { - if(!tblField.leftValue().getName().equals(tblField.rightValue().getName())) { - st.execute("alter table "+ tblName +" rename column "+ tblField.rightValue().getName() +" to "+ tblField.leftValue().getName()); - } - - if(!tblField.leftValue().getTypeSQL().equals(tblField.rightValue().getTypeSQL())) { - st.execute("alter table "+ tblName +" modify "+ tblField.leftValue().getName() +" "+ tblField.leftValue().getTypeSQL()); - } - } - } - - ResultSet rs = st.executeQuery("SELECT COUNT(cons.constraint_name)\n" + - "FROM all_constraints cons \n" + - "WHERE upper(owner) = upper('" + schema + "') and upper(table_name) = upper('" + tblName+ "') and constraint_name not like 'SYS%' and cons.constraint_type = 'P'"); - rs.next(); - Integer constraintsCount = Integer.valueOf(rs.getString("constraintscount")); - if(constraintsCount.intValue()>0) { - removeTableConstraintsOracle(obj); - } - // set primary key - for(DBConstraint tableconst: restoreTable.getConstraints().values()) { - if(tableconst.getConstraintType().equals("p")) { - st.execute(restoreTable.getConstraints().get("constraintDef").getOptions().get("ddl").toString()); - //st.execute("alter table "+ tblName +" add constraint PK_"+ tableconst.getName() + " primary key ("+tableconst.getName() + ")"); - break; - } - } - } - else - { - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); - } - } catch (SQLException e1) { - ConsoleWriter.detailsPrintlnRed(lang.getValue(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()) + "\n"+ e1.getLocalizedMessage())); - //throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()) + "\n"+ e1.getLocalizedMessage()); - } catch (Exception e) { - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); - } finally { - st.close(); - } - } - - public void restoreTableIndexesOracle(IMetaObject obj) throws Exception - { - IDBAdapter adapter = getAdapter(); - Connection connect = adapter.getConnection(); - StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "restoreIndex").withParams(obj.getName()), 1); - try { - if (obj instanceof MetaTable) { - MetaTable restoreTable = (MetaTable)obj; - String schema = getPhisicalSchema(restoreTable.getTable().getSchema()); - schema = (SchemaSynonym.getInstance().getSchema(schema) == null) ? schema : SchemaSynonym.getInstance().getSchema(schema); - Map tables = adapter.getTables(schema); - boolean exist = false; - if(!(tables.isEmpty() || tables == null)) { - for(DBTable table:tables.values()) { - if(restoreTable.getTable().getName().equals(table.getName())){ - exist = true; - Map currentIndexes = adapter.getIndexes(schema, table.getName()); - MapDifference diffInd = Maps.difference(restoreTable.getIndexes(), currentIndexes); - if(!diffInd.entriesOnlyOnLeft().isEmpty()) { - for(DBIndex ind:diffInd.entriesOnlyOnLeft().values()) { - ConsoleWriter.println(ind.getSql()); - if (ind.getSql().length() > 5 ) - st.execute(ind.getSql()); - } - } - if(!diffInd.entriesOnlyOnRight().isEmpty()) { - for(DBIndex ind:diffInd.entriesOnlyOnRight().values()) { - st.execute("drop index "+schema+"."+ind.getName()); - } - } - - //not fact, will check in future - } - } - } - if(!exist){ - for(DBIndex ind:restoreTable.getIndexes().values()) { - st.execute(ind.getSql()); - } - } - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); - } - else - { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); - } - } catch (SQLException e1) { - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()) + "\n"+ e1.getLocalizedMessage()); - } catch (Exception e) { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); - } finally { - st.close(); - } - } - - public void restoreTableConstraintOracle(IMetaObject obj) throws Exception { - IDBAdapter adapter = getAdapter(); - Connection connect = adapter.getConnection(); - StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "restoreConstr").withParams(obj.getName()), 1); - try { - if (obj instanceof MetaTable) { - MetaTable restoreTable = (MetaTable)obj; - String schema = getPhisicalSchema(restoreTable.getTable().getSchema()); - schema = (SchemaSynonym.getInstance().getSchema(schema) == null) ? schema : SchemaSynonym.getInstance().getSchema(schema); - for(DBConstraint constrs :restoreTable.getConstraints().values()) { - if(!constrs.getConstraintType().equalsIgnoreCase("P")) { - //String tblName = schema+"."+restoreTable.getTable().getName(); - - st.execute(constrs.getOptions().get("ddl").toString().replace(" " + constrs.getSchema() + ".", " " + schema + ".")); - } - } - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); - } - else - { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); - } - } catch (SQLException e1) { - ConsoleWriter.detailsPrintlnRed(lang.getValue(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()) + "\n"+ e1.getLocalizedMessage())); - //throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()) + "\n"+ e1.getLocalizedMessage()); - } catch (Exception e) { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); - } finally { - st.close(); - } - } - - public void removeTableConstraintsOracle(IMetaObject obj) throws Exception { - IDBAdapter adapter = getAdapter(); - Connection connect = adapter.getConnection(); - StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - try { - if (obj instanceof MetaTable) { - MetaTable table = (MetaTable)obj; - String schema = getPhisicalSchema(table.getTable().getSchema()); - schema = (SchemaSynonym.getInstance().getSchema(schema) == null) ? schema : SchemaSynonym.getInstance().getSchema(schema); - Map constraints = table.getConstraints(); - for(DBConstraint constrs :constraints.values()) { - - String dropQuery = "declare cnt number;\r\n" + - "begin \r\n" + - "select count(*) into cnt from ALL_CONSTRAINTS where upper(CONSTRAINT_NAME) = upper('" + constrs.getName() + "') and upper(owner) = upper('" + schema + "');\r\n" + - " if (cnt > 0) \r\n" + - " then \r\n" + - " execute immediate('alter table " + schema + "." + table.getTable().getName() + " drop constraint " + constrs.getName() + "');\r\n" + - " end if;\r\n" + - "end;"; - - - st.execute(dropQuery, "/"); - } - //} - } - else - { - throw new ExceptionDBGitRestore("Error restore: Unable to remove TableConstraints."); - } - - } catch (SQLException e1) { - ConsoleWriter.detailsPrintlnRed(lang.getValue(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()) + "\n"+ e1.getLocalizedMessage())); - //throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()) + "\n"+ e1.getLocalizedMessage()); - } catch (Exception e) { - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); - } - } - - /*public void removeIndexesOracle(IMetaObject obj) throws Exception { - - }*/ - - public void removeMetaObject(IMetaObject obj) throws Exception { - IDBAdapter adapter = getAdapter(); - Connection connect = adapter.getConnection(); - StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - - try { - - MetaTable tblMeta = (MetaTable)obj; - DBTable tbl = tblMeta.getTable(); - //String schema = getPhisicalSchema(tbl.getSchema()); - - st.execute("DROP TABLE " +tbl.getName()); - - // TODO Auto-generated method stub - } catch (SQLException e1) { - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()) + "\n"+ e1.getLocalizedMessage()); - } catch (Exception e) { - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRemoveError").withParams(obj.getName()), e); - } finally { - st.close(); - } - } - -} +package ru.fusionsoft.dbgit.oracle; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import com.google.common.collect.MapDifference; +import com.google.common.collect.Maps; +import com.google.common.collect.MapDifference.ValueDifference; + +import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter; +import ru.fusionsoft.dbgit.adapters.IDBAdapter; +import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; +import ru.fusionsoft.dbgit.core.SchemaSynonym; +import ru.fusionsoft.dbgit.dbobjects.DBConstraint; +import ru.fusionsoft.dbgit.dbobjects.DBIndex; +import ru.fusionsoft.dbgit.dbobjects.DBTable; +import ru.fusionsoft.dbgit.dbobjects.DBTableField; +import ru.fusionsoft.dbgit.meta.IMetaObject; +import ru.fusionsoft.dbgit.meta.MetaTable; +import ru.fusionsoft.dbgit.statement.StatementLogging; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; + +public class DBRestoreTableOracle extends DBRestoreAdapter { + + @Override + public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { + if(Integer.valueOf(step).equals(0)) { + restoreTableOracle(obj); + return false; + } + /*if(Integer.valueOf(step).equals(1)) { + restoreTableFieldsOracle(obj); + return false; + }*/ + if(Integer.valueOf(step).equals(-21)) { + restoreTableIndexesOracle(obj); + return false; + } + if(Integer.valueOf(step).equals(-1)) { + restoreTableConstraintOracle(obj); + return false; + } + return true; + } + + public void restoreTableOracle(IMetaObject obj) throws Exception + { + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + try { + if (obj instanceof MetaTable) { + + MetaTable restoreTable = (MetaTable)obj; + String schema = getPhisicalSchema(restoreTable.getTable().getSchema()); + schema = (SchemaSynonym.getInstance().getSchema(schema) == null) ? schema : SchemaSynonym.getInstance().getSchema(schema); + String tblName = schema+"."+restoreTable.getTable().getName(); + + Map tables = adapter.getTables(schema.toUpperCase()); + boolean exist = false; + if(!(tables.isEmpty() || tables == null)) { + for(DBTable table:tables.values()) { + if(restoreTable.getTable().getName().equalsIgnoreCase(table.getName())){ + exist = true; + + } + } + } + if(!exist){ + ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "createTable"), messageLevel); + String ddl = ""; + if (restoreTable.getTable().getOptions().get("ddl") != null) + ddl = restoreTable.getTable().getOptions().get("ddl").getData() + .replace("\"" + restoreTable.getTable().getSchema().toUpperCase() + "\"", "\"" + schema.toUpperCase() + "\""); + else { + DBTable table = restoreTable.getTable(); + + Comparator comparator = Comparator.comparing(DBTableField::getOrder); + + ddl = "create table " + schema + "." + table.getName() + + " (" + restoreTable.getFields().values().stream() + .sorted(comparator) + .map(field -> "" + (adapter.isReservedWord(field.getName()) ? "\"" + field.getName() + "\" " : field.getName()) + " " + field.getTypeSQL()) + .collect(Collectors.joining(", ")) + ")"; + } + st.execute(ddl); + + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + } else { + //restore tabl fields + Map currentFileds = adapter.getTableFields(schema, restoreTable.getTable().getName().toLowerCase()); + MapDifference diffTableFields = Maps.difference(restoreTable.getFields(),currentFileds); + + if(!diffTableFields.entriesOnlyOnLeft().isEmpty()){ + ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "addColumns"), messageLevel); + + Comparator comparator = Comparator.comparing(DBTableField::getOrder); + + List values = diffTableFields.entriesOnlyOnLeft().values().stream().collect(Collectors.toList()); + values.sort(comparator); + + for(DBTableField tblField : values) { + st.execute("alter table "+ tblName +" add " + tblField.getName() + " " + tblField.getTypeSQL()); + } + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + } + + if(!diffTableFields.entriesOnlyOnRight().isEmpty()) { + ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "droppingColumns"), messageLevel); + for(DBTableField tblField:diffTableFields.entriesOnlyOnRight().values()) { + st.execute("alter table "+ tblName +" drop column "+ tblField.getName()); + } + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + } + + if(!diffTableFields.entriesDiffering().isEmpty()) { + ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "modifyColumns"), messageLevel); + + for(ValueDifference tblField:diffTableFields.entriesDiffering().values()) { + if(!tblField.leftValue().getName().equals(tblField.rightValue().getName())) { + st.execute("alter table "+ tblName +" rename column "+ tblField.rightValue().getName() +" to "+ tblField.leftValue().getName()); + } + + if(!tblField.leftValue().getTypeUniversal().equals(tblField.rightValue().getTypeUniversal())) { + st.execute("alter table "+ tblName +" modify "+ tblField.leftValue().getName() +" "+ tblField.leftValue().getTypeSQL()); + } + } + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + } + } + + ResultSet rs = st.executeQuery("SELECT COUNT(cons.constraint_name) constraintscount \n" + + "FROM all_constraints cons \n" + + "WHERE upper(owner) = upper('" + schema + "') and upper(table_name) = upper('" + restoreTable.getTable().getName()+ "') and constraint_name not like 'SYS%' and cons.constraint_type = 'P'"); + rs.next(); + Integer constraintsCount = Integer.valueOf(rs.getString("constraintscount")); + if(constraintsCount.intValue()>0) { + removeTableConstraintsOracle(obj); + } + // set primary key + boolean flagPkCreated = false; + for(DBConstraint tableconst: restoreTable.getConstraints().values()) { + if(tableconst.getConstraintType().equals("p")) { + ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "addPk"), messageLevel); + + if (tableconst.getOptions().get("ddl").toString().toLowerCase().startsWith("alter table")) + st.execute(tableconst.getOptions().get("ddl").toString().replace(" " +tableconst.getSchema() + ".", " " + schema + ".")); + else if (tableconst.getOptions().get("ddl").toString().toLowerCase().startsWith("primary key")) + st.execute("alter table "+ tblName +" add constraint PK_"+ tableconst.getName() + tableconst.getOptions().get("ddl").toString()); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + flagPkCreated = true; + break; + } + } + + if (!flagPkCreated) { + for(DBTableField field: restoreTable.getFields().values()) { + if (field.getIsPrimaryKey()) { + ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "addPk"), messageLevel); + st.execute("alter table "+ tblName +" add constraint pk_" + restoreTable.getTable().getName() + "_" + field.getName() + " PRIMARY KEY (" + field.getName() + ")"); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + break; + } + } + } + + + } + else + { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "table", obj.getType().getValue() + )); + } + } catch (Exception e) { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); + } finally { + st.close(); + } + } + + public void restoreTableFieldsOracle(IMetaObject obj) throws Exception { + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + try { + if (obj instanceof MetaTable) { + MetaTable restoreTable = (MetaTable)obj; + String schema = getPhisicalSchema(restoreTable.getTable().getSchema()); + schema = (SchemaSynonym.getInstance().getSchema(schema) == null) ? schema : SchemaSynonym.getInstance().getSchema(schema); + String tblName = schema+"."+restoreTable.getTable().getName(); + Map tables = adapter.getTables(schema); + boolean exist = false; + if(!(tables.isEmpty() || tables == null)) { + for(DBTable table:tables.values()) { + if(restoreTable.getTable().getName().equals(table.getName())){ + exist = true; + } + } + } + if(!exist){ + st.execute(restoreTable.getTable().getOptions().get("ddl").getData()); + } + //restore tabl fields + Map currentFileds = adapter.getTableFields(schema, restoreTable.getTable().getName()); + MapDifference diffTableFields = Maps.difference(restoreTable.getFields(),currentFileds); + + if(!diffTableFields.entriesOnlyOnLeft().isEmpty()){ + for(DBTableField tblField:diffTableFields.entriesOnlyOnLeft().values()) { + st.execute("alter table "+ tblName +" add " + tblField.getName() + " " + tblField.getTypeSQL()); + } + } + + if(!diffTableFields.entriesOnlyOnRight().isEmpty()) { + for(DBTableField tblField:diffTableFields.entriesOnlyOnRight().values()) { + st.execute("alter table "+ tblName +" drop column "+ tblField.getName()); + } + } + + if(!diffTableFields.entriesDiffering().isEmpty()) { + for(ValueDifference tblField:diffTableFields.entriesDiffering().values()) { + if(!tblField.leftValue().getName().equals(tblField.rightValue().getName())) { + st.execute("alter table "+ tblName +" rename column "+ tblField.rightValue().getName() +" to "+ tblField.leftValue().getName()); + } + + if(!tblField.leftValue().getTypeSQL().equals(tblField.rightValue().getTypeSQL())) { + st.execute("alter table "+ tblName +" modify "+ tblField.leftValue().getName() +" "+ tblField.leftValue().getTypeSQL()); + } + } + } + + ResultSet rs = st.executeQuery("SELECT COUNT(cons.constraint_name)\n" + + "FROM all_constraints cons \n" + + "WHERE upper(owner) = upper('" + schema + "') and upper(table_name) = upper('" + tblName+ "') and constraint_name not like 'SYS%' and cons.constraint_type = 'P'"); + rs.next(); + Integer constraintsCount = Integer.valueOf(rs.getString("constraintscount")); + if(constraintsCount.intValue()>0) { + removeTableConstraintsOracle(obj); + } + // set primary key + for(DBConstraint tableconst: restoreTable.getConstraints().values()) { + if(tableconst.getConstraintType().equals("p")) { + st.execute(restoreTable.getConstraints().get("constraintDef").getOptions().get("ddl").toString()); + //st.execute("alter table "+ tblName +" add constraint PK_"+ tableconst.getName() + " primary key ("+tableconst.getName() + ")"); + break; + } + } + } + else + { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "table", obj.getType().getValue() + )); + } + } catch (Exception e) { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); + } finally { + st.close(); + } + } + + public void restoreTableIndexesOracle(IMetaObject obj) throws Exception { + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + + ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "restoreIndex").withParams(obj.getName()), messageLevel); + try { + if (obj instanceof MetaTable) { + MetaTable restoreTable = (MetaTable)obj; + String schema = getPhisicalSchema(restoreTable.getTable().getSchema()); + schema = (SchemaSynonym.getInstance().getSchema(schema) == null) ? schema : SchemaSynonym.getInstance().getSchema(schema); + Map tables = adapter.getTables(schema); + boolean exist = false; + if(!(tables.isEmpty() || tables == null)) { + for(DBTable table:tables.values()) { + if(restoreTable.getTable().getName().equals(table.getName())){ + exist = true; + Map currentIndexes = adapter.getIndexes(schema, table.getName()); + MapDifference diffInd = Maps.difference(restoreTable.getIndexes(), currentIndexes); + if(!diffInd.entriesOnlyOnLeft().isEmpty()) { + for(DBIndex ind:diffInd.entriesOnlyOnLeft().values()) { +// ConsoleWriter.println(ind.getSql()); + if (ind.getSql().length() > 5 ) + st.execute(ind.getSql()); + } + } + if(!diffInd.entriesOnlyOnRight().isEmpty()) { + for(DBIndex ind:diffInd.entriesOnlyOnRight().values()) { + st.execute("drop index "+schema+"."+ind.getName()); + } + } + + //not fact, will check in future + } + } + } + if(!exist){ + for(DBIndex ind:restoreTable.getIndexes().values()) { + st.execute(ind.getSql()); + } + } + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + } + else + { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "table", obj.getType().getValue() + )); + } + } catch (Exception e) { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError") + .withParams(obj.getName()) + , e + ); + } finally { + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + st.close(); + } + } + + public void restoreTableConstraintOracle(IMetaObject obj) throws Exception { + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "restoreConstr") + .withParams(obj.getName()) + , messageLevel + ); + try { + if (obj instanceof MetaTable) { + MetaTable restoreTable = (MetaTable)obj; + String schema = getPhisicalSchema(restoreTable.getTable().getSchema()); + schema = (SchemaSynonym.getInstance().getSchema(schema) == null) ? schema : SchemaSynonym.getInstance().getSchema(schema); + for(DBConstraint constrs :restoreTable.getConstraints().values()) { + if(!constrs.getConstraintType().equalsIgnoreCase("P")) { + //String tblName = schema+"."+restoreTable.getTable().getName(); + + st.execute(constrs.getOptions().get("ddl").toString().replace(" " + constrs.getSchema() + ".", " " + schema + ".")); + } + } + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + } + else + { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "table", obj.getType().getValue() + )); + } + } catch (Exception e) { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); + } finally { + st.close(); + } + } + + public void removeTableConstraintsOracle(IMetaObject obj) throws Exception { + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + try { + if (obj instanceof MetaTable) { + MetaTable table = (MetaTable)obj; + String schema = getPhisicalSchema(table.getTable().getSchema()); + schema = (SchemaSynonym.getInstance().getSchema(schema) == null) ? schema : SchemaSynonym.getInstance().getSchema(schema); + Map constraints = table.getConstraints(); + for(DBConstraint constrs :constraints.values()) { + + String dropQuery = "declare cnt number;\r\n" + + "begin \r\n" + + "select count(*) into cnt from ALL_CONSTRAINTS where upper(CONSTRAINT_NAME) = upper('" + constrs.getName() + "') and upper(owner) = upper('" + schema + "');\r\n" + + " if (cnt > 0) \r\n" + + " then \r\n" + + " execute immediate('alter table " + schema + "." + table.getTable().getName() + " drop constraint " + constrs.getName() + "');\r\n" + + " end if;\r\n" + + "end;"; + + + st.execute(dropQuery, "/"); + } + //} + } + else + { + throw new ExceptionDBGitRestore("Error restore: Unable to remove TableConstraints."); + } + + } catch (Exception e) { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); + } + } + + /*public void removeIndexesOracle(IMetaObject obj) throws Exception { + + }*/ + + public void removeMetaObject(IMetaObject obj) throws Exception { + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + + try { + + MetaTable tblMeta = (MetaTable)obj; + DBTable tbl = tblMeta.getTable(); + //String schema = getPhisicalSchema(tbl.getSchema()); + + st.execute("DROP TABLE " +tbl.getName()); + + // TODO Auto-generated method stub + } catch (Exception e) { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRemoveError").withParams(obj.getName()), e); + } finally { + st.close(); + } + } + +} diff --git a/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestoreTriggerOracle.java b/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestoreTriggerOracle.java index 3f9a13f..35aa832 100644 --- a/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestoreTriggerOracle.java +++ b/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestoreTriggerOracle.java @@ -21,8 +21,7 @@ public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { IDBAdapter adapter = getAdapter(); Connection connect = adapter.getConnection(); st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "restoreTrigger").withParams(obj.getName()), 1); - try { + try { if (obj instanceof MetaTrigger) { MetaTrigger restoreTrigger = (MetaTrigger)obj; Map trgs = adapter.getTriggers(restoreTrigger.getSqlObject().getSchema()); @@ -42,17 +41,18 @@ public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { executeSql(restoreTrigger.getSqlObject().getSql()); //TODO Восстановление привилегий } - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); } else { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "trigger", obj.getType().getValue() + )); } } catch (Exception e) { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); } finally { st.close(); diff --git a/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestoreViewOracle.java b/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestoreViewOracle.java index 96de107..0df3c02 100644 --- a/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestoreViewOracle.java +++ b/src/main/java/ru/fusionsoft/dbgit/oracle/DBRestoreViewOracle.java @@ -21,7 +21,6 @@ public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { IDBAdapter adapter = getAdapter(); Connection connect = adapter.getConnection(); StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "restoreView").withParams(obj.getName()), 1); try { if (obj instanceof MetaView) { MetaView restoreView = (MetaView)obj; @@ -44,15 +43,16 @@ public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { st.execute(restoreView.getSqlObject().getSql()); //TODO Восстановление привилегий } - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); } else { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "view", obj.getType().getValue() + )); } } catch (Exception e) { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); } finally { st.close(); diff --git a/src/main/java/ru/fusionsoft/dbgit/oracle/FactoryDBAdapterRestoreOracle.java b/src/main/java/ru/fusionsoft/dbgit/oracle/FactoryDBAdapterRestoreOracle.java index a1808a8..23ed6b6 100644 --- a/src/main/java/ru/fusionsoft/dbgit/oracle/FactoryDBAdapterRestoreOracle.java +++ b/src/main/java/ru/fusionsoft/dbgit/oracle/FactoryDBAdapterRestoreOracle.java @@ -1,12 +1,9 @@ package ru.fusionsoft.dbgit.oracle; -import java.sql.Connection; import java.util.Collections; import java.util.HashMap; import java.util.Map; -import ru.fusionsoft.dbgit.adapters.DBRestoreMetaNotSupport; -import ru.fusionsoft.dbgit.adapters.DBRestoreMetaSql; import ru.fusionsoft.dbgit.adapters.IDBAdapter; import ru.fusionsoft.dbgit.adapters.IDBAdapterRestoreMetaData; import ru.fusionsoft.dbgit.adapters.IFactoryDBAdapterRestoteMetaData; @@ -43,7 +40,10 @@ public IDBAdapterRestoreMetaData getAdapterRestore(IDBGitMetaType tp, IDBAdapter if (!restoreAdapters.containsKey(tp.getValue())) { //return new DBRestoreMetaNotSupport(); - ConsoleWriter.println(DBGitLang.getInstance().getValue("errors", "restore", "cannotRestore").withParams(tp.getValue())); + ConsoleWriter.println(DBGitLang.getInstance().getValue("errors", "restore", "cannotRestore") + .withParams(tp.getValue()) + , messageLevel + ); return null; } diff --git a/src/main/java/ru/fusionsoft/dbgit/oracle/FactoryDbConvertAdapterOracle.java b/src/main/java/ru/fusionsoft/dbgit/oracle/FactoryDbConvertAdapterOracle.java index 2ff1b70..ce70254 100644 --- a/src/main/java/ru/fusionsoft/dbgit/oracle/FactoryDbConvertAdapterOracle.java +++ b/src/main/java/ru/fusionsoft/dbgit/oracle/FactoryDbConvertAdapterOracle.java @@ -6,6 +6,7 @@ import ru.fusionsoft.dbgit.adapters.IDBConvertAdapter; import ru.fusionsoft.dbgit.adapters.IFactoryDBConvertAdapter; +import ru.fusionsoft.dbgit.core.DBGitLang; import ru.fusionsoft.dbgit.core.ExceptionDBGit; import ru.fusionsoft.dbgit.meta.DBGitMetaType; import ru.fusionsoft.dbgit.oracle.converters.TableConverterOracle; @@ -27,7 +28,11 @@ public class FactoryDbConvertAdapterOracle implements IFactoryDBConvertAdapter { @Override public IDBConvertAdapter getConvertAdapter(String objectType) throws Exception { if (!converters.containsKey(objectType)) { - ConsoleWriter.println("Cannot convert " + objectType + "!"); + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("errors", "convert", "cannotConvert") + .withParams(objectType) + , 1 + ); return null; } else return converters.get(objectType); diff --git a/src/main/java/ru/fusionsoft/dbgit/oracle/converters/TableConverterOracle.java b/src/main/java/ru/fusionsoft/dbgit/oracle/converters/TableConverterOracle.java index f423a9b..b194886 100644 --- a/src/main/java/ru/fusionsoft/dbgit/oracle/converters/TableConverterOracle.java +++ b/src/main/java/ru/fusionsoft/dbgit/oracle/converters/TableConverterOracle.java @@ -5,6 +5,7 @@ import ru.fusionsoft.dbgit.adapters.IDBConvertAdapter; import ru.fusionsoft.dbgit.adapters.IFactoryDBConvertAdapter; +import ru.fusionsoft.dbgit.core.DBGitLang; import ru.fusionsoft.dbgit.core.ExceptionDBGit; import ru.fusionsoft.dbgit.core.db.DbType; import ru.fusionsoft.dbgit.dbobjects.DBConstraint; @@ -25,9 +26,13 @@ public IMetaObject convert(DbType dbType, String dbVersion, IMetaObject obj) thr if (obj instanceof MetaTable) { MetaTable table = (MetaTable) obj; - - ConsoleWriter.println("Processing table " + table.getName()); - + + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("general", "convert", "convertingTable") + .withParams(table.getName()) + , messageLevel + ); + //types for (DBTableField field : table.getFields().values()) field.setTypeSQL(typeFromAnotherDB(objDbType, field)); @@ -54,14 +59,23 @@ public IMetaObject convert(DbType dbType, String dbVersion, IMetaObject obj) thr } private String indexFromPostgres(DBIndex index) { - ConsoleWriter.println("Converting table index " + index.getName() + " from postgresql to oracle..."); - + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("general", "convert", "convertingIndex") + .withParams(index.getName(), "postgresql", "oracle") + , messageLevel + ); + return ""; } private String constraintFromPostgres(MetaTable table, DBConstraint constraint) { - ConsoleWriter.println("Converting table constraint " + constraint.getName() + " from postgresql to oracle..."); - + + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("general", "convert", "convertingConstraint") + .withParams(constraint.getName(), "postgresql", "oracle") + , messageLevel + ); + String ddl = constraint.getOptions().get("ddl") .toString() .replace("ON UPDATE CASCADE", "") @@ -76,7 +90,13 @@ private String constraintFromPostgres(MetaTable table, DBConstraint constraint) } private String typeFromAnotherDB(DbType dbType, DBTableField field) { - ConsoleWriter.println("Converting table field " + field.getName() + " from " + dbType.toString().toLowerCase() + " to oracle..."); + + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("general", "convert", "convertingField") + .withParams(field.getName(), dbType.toString(), "oracle") + , messageLevel + ); + String result = ""; switch (field.getTypeUniversal()) { case STRING: diff --git a/src/main/java/ru/fusionsoft/dbgit/postgres/DBAdapterPostgres.java b/src/main/java/ru/fusionsoft/dbgit/postgres/DBAdapterPostgres.java index 0c93100..14b7f95 100644 --- a/src/main/java/ru/fusionsoft/dbgit/postgres/DBAdapterPostgres.java +++ b/src/main/java/ru/fusionsoft/dbgit/postgres/DBAdapterPostgres.java @@ -1,1661 +1,1957 @@ -package ru.fusionsoft.dbgit.postgres; - - -import java.sql.*; -import java.text.MessageFormat; -import java.util.*; -import java.util.concurrent.TimeUnit; - -import ru.fusionsoft.dbgit.adapters.AdapterFactory; -import ru.fusionsoft.dbgit.adapters.DBAdapter; -import ru.fusionsoft.dbgit.adapters.IFactoryDBAdapterRestoteMetaData; -import ru.fusionsoft.dbgit.adapters.IFactoryDBBackupAdapter; -import ru.fusionsoft.dbgit.adapters.IFactoryDBConvertAdapter; -import ru.fusionsoft.dbgit.core.DBGitConfig; -import ru.fusionsoft.dbgit.core.ExceptionDBGit; -import ru.fusionsoft.dbgit.core.ExceptionDBGitObjectNotFound; -import ru.fusionsoft.dbgit.core.ExceptionDBGitRunTime; -import ru.fusionsoft.dbgit.core.db.DbType; -import ru.fusionsoft.dbgit.core.db.FieldType; -import ru.fusionsoft.dbgit.data_table.MapFileData; -import ru.fusionsoft.dbgit.data_table.BooleanData; -import ru.fusionsoft.dbgit.data_table.DateData; -import ru.fusionsoft.dbgit.data_table.FactoryCellData; -import ru.fusionsoft.dbgit.data_table.LongData; -import ru.fusionsoft.dbgit.data_table.StringData; -import ru.fusionsoft.dbgit.data_table.TextFileData; -import ru.fusionsoft.dbgit.dbobjects.DBConstraint; -import ru.fusionsoft.dbgit.dbobjects.DBFunction; -import ru.fusionsoft.dbgit.dbobjects.DBIndex; -import ru.fusionsoft.dbgit.dbobjects.DBPackage; -import ru.fusionsoft.dbgit.dbobjects.DBProcedure; -import ru.fusionsoft.dbgit.dbobjects.DBRole; -import ru.fusionsoft.dbgit.dbobjects.DBSchema; -import ru.fusionsoft.dbgit.dbobjects.DBSequence; -import ru.fusionsoft.dbgit.dbobjects.DBTable; -import ru.fusionsoft.dbgit.dbobjects.DBTableData; -import ru.fusionsoft.dbgit.dbobjects.DBTableField; -import ru.fusionsoft.dbgit.dbobjects.DBTableRow; -import ru.fusionsoft.dbgit.dbobjects.DBTableSpace; -import ru.fusionsoft.dbgit.dbobjects.DBTrigger; -import ru.fusionsoft.dbgit.dbobjects.DBUser; -import ru.fusionsoft.dbgit.dbobjects.DBView; -import ru.fusionsoft.dbgit.meta.IMapMetaObject; -import ru.fusionsoft.dbgit.meta.IMetaObject; -import ru.fusionsoft.dbgit.statement.StatementLogging; -import ru.fusionsoft.dbgit.utils.ConsoleWriter; -import ru.fusionsoft.dbgit.utils.LoggerUtil; -import org.slf4j.Logger; - -import com.axiomalaska.jdbc.NamedParameterPreparedStatement; - - -public class DBAdapterPostgres extends DBAdapter { - private Logger logger = LoggerUtil.getLogger(this.getClass()); - private FactoryDBAdapterRestorePostgres restoreFactory = new FactoryDBAdapterRestorePostgres(); - private FactoryDbConvertAdapterPostgres convertFactory = new FactoryDbConvertAdapterPostgres(); - private FactoryDBBackupAdapterPostgres backupFactory = new FactoryDBBackupAdapterPostgres(); - private static Set reservedWords = new HashSet<>(); - - @Override - public IFactoryDBAdapterRestoteMetaData getFactoryRestore() { - return restoreFactory; - } - - @Override - public void startUpdateDB() { - // TODO Auto-generated method stub - - } - - @Override - public void endUpdateDB() { - // TODO Auto-generated method stub - - } - - @Override - public IMapMetaObject loadCustomMetaObjects() { - return null; - } - - @Override - public Map getSchemes() { - Map listScheme = new HashMap(); - try { - String query = "select nspname,usename,nspacl from pg_namespace,pg_user where nspname!='pg_toast' and nspname!='pg_temp_1'"+ - "and nspname!='pg_toast_temp_1' and nspname!='pg_catalog'"+ - "and nspname!='information_schema' and nspname!='pgagent'"+ - "and nspname!='pg_temp_3' and nspname!='pg_toast_temp_3'"+ - "and usesysid = nspowner"; - Connection connect = getConnection(); - Statement stmt = connect.createStatement(); - ResultSet rs = stmt.executeQuery(query); - while(rs.next()){ - String name = rs.getString("nspname"); - DBSchema scheme = new DBSchema(name); - rowToProperties(rs, scheme.getOptions()); - listScheme.put(name, scheme); - } - stmt.close(); - }catch(Exception e) { - logger.error(lang.getValue("errors", "adapter", "schemes").toString(), e); - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "schemes").toString(), e); - } - - return listScheme; - } - - @Override - public Map getTableSpaces() { - Map listTableSpace = new HashMap(); - try { - String query = "SELECT tblspaces.spcname,tblspaces.spcacl,tblspaces.spcoptions,users.usename,pg_tablespace_location(tblspacesoid.oid) " + - "FROM pg_tablespace as tblspaces,pg_user as users,(Select oid FROM pg_tablespace where spcname!='pg_default' and spcname!='pg_global') as tblspacesoid " + - "WHERE users.usesysid=tblspaces.spcowner and spcname!='pg_default' and spcname!='pg_global' and tblspacesoid.oid=tblspaces.oid"; - Connection connect = getConnection(); - Statement stmt = connect.createStatement(); - ResultSet rs = stmt.executeQuery(query); - while(rs.next()){ - String name = rs.getString("spcname"); - DBTableSpace dbTableSpace = new DBTableSpace(name); - rowToProperties(rs, dbTableSpace.getOptions()); - listTableSpace.put(name, dbTableSpace); - } - stmt.close(); - }catch(Exception e) { - logger.error(e.getMessage()); - throw new ExceptionDBGitRunTime(e.getMessage()); - } - return listTableSpace; - } - - @Override - public Map getSequences(String schema) { - Map listSequence = new HashMap(); - try { - Connection connect = getConnection(); - String query = - "select s.sequence_name, rol.rolname as owner, s.start_value, s.minimum_value, s.maximum_value, s.increment, s.cycle_option " + - "from pg_class cls " + - " join pg_roles rol on rol.oid = cls.relowner " + - " join pg_namespace nsp on nsp.oid = cls.relnamespace " + - " join information_schema.sequences s on cls.relname = s.sequence_name " + - "where nsp.nspname not in ('information_schema', 'pg_catalog') " + - " and nsp.nspname not like 'pg_toast%' " + - " and cls.relkind = 'S' and s.sequence_schema = :schema "; - - NamedParameterPreparedStatement stmt = NamedParameterPreparedStatement.createNamedParameterPreparedStatement(connect, query); - stmt.setString("schema", schema); - - ResultSet rs = stmt.executeQuery(); - while(rs.next()){ - String nameSeq = rs.getString("sequence_name"); - DBSequence sequence = new DBSequence(); - sequence.setName(nameSeq); - sequence.setSchema(schema); - sequence.setValue(0L); - rowToProperties(rs, sequence.getOptions()); - listSequence.put(nameSeq, sequence); - } - stmt.close(); - }catch(Exception e) { - logger.error(e.getMessage(), e); - throw new ExceptionDBGitRunTime(e.getMessage(), e); - } - return listSequence; - } - - @Override - public DBSequence getSequence(String schema, String name) { - try { - Connection connect = getConnection(); - String query = - "select s.sequence_name, rol.rolname as owner, s.start_value, s.minimum_value, s.maximum_value, s.increment, s.cycle_option " + - "from pg_class cls " + - " join pg_roles rol on rol.oid = cls.relowner " + - " join pg_namespace nsp on nsp.oid = cls.relnamespace " + - " join information_schema.sequences s on cls.relname = s.sequence_name " + - "where nsp.nspname not in ('information_schema', 'pg_catalog') " + - " and nsp.nspname not like 'pg_toast%' " + - " and cls.relkind = 'S' and s.sequence_schema = :schema and s.sequence_name = :name "; - - NamedParameterPreparedStatement stmt = NamedParameterPreparedStatement.createNamedParameterPreparedStatement(connect, query); - stmt.setString("schema", schema); - stmt.setString("name", name); - - ResultSet rs = stmt.executeQuery(); - DBSequence sequence = null; - while (rs.next()) { - String nameSeq = rs.getString("sequence_name"); - sequence = new DBSequence(); - sequence.setName(nameSeq); - sequence.setSchema(schema); - sequence.setValue(0L); - rowToProperties(rs, sequence.getOptions()); - } - stmt.close(); - return sequence; - }catch(Exception e) { - logger.error(e.getMessage(), e); - throw new ExceptionDBGitRunTime(e.getMessage(), e); - } - } - - @Override - public Map getTables(String schema) { - Map listTable = new HashMap(); - try { - String query = - "select \n" + - " tablename as table_name,\n" + - " tableowner as owner,\n" + - " tablespace,hasindexes,hasrules,hastriggers, \n" + - " obj_description(to_regclass(schemaname || '.\"' || tablename || '\"')::oid) table_comment, ( \n" + - " select array_agg(distinct n2.nspname || '/' || c2.relname || '.tbl') as dependencies\n" + - " FROM pg_catalog.pg_constraint c \n" + - " JOIN ONLY pg_catalog.pg_class c1 ON c1.oid = c.conrelid\n" + - " JOIN ONLY pg_catalog.pg_class c2 ON c2.oid = c.confrelid\n" + - " JOIN ONLY pg_catalog.pg_namespace n2 ON n2.oid = c2.relnamespace\n" + - " WHERE c.conrelid = to_regclass(schemaname || '.\"' || tablename || '\"')::oid\n" + - " and c1.relkind = 'r' AND c.contype = 'f'\n" + - " )\n" + - "from pg_tables \n" + - "where upper(schemaname) = upper(:schema)"; - Connection connect = getConnection(); - - NamedParameterPreparedStatement stmt = NamedParameterPreparedStatement.createNamedParameterPreparedStatement(connect, query); - stmt.setString("schema", schema); - - ResultSet rs = stmt.executeQuery(); - while(rs.next()){ - String nameTable = rs.getString("table_name"); - DBTable table = new DBTable(nameTable); - table.setSchema(schema); - table.setComment(rs.getString("table_comment")); - if(rs.getArray("dependencies") != null){ - table.setDependencies(new HashSet<>(Arrays.asList((String[])rs.getArray("dependencies").getArray()))); - } else table.setDependencies(new HashSet<>()); - rowToProperties(rs, table.getOptions()); - listTable.put(nameTable, table); - } - stmt.close(); - }catch(Exception e) { - logger.error(lang.getValue("errors", "adapter", "tables").toString(), e); - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "tables").toString(), e); - } - return listTable; - } - - @Override - public DBTable getTable(String schema, String name) { - String query = - "select \n" + - " tablename as table_name,\n" + - " tableowner as owner,\n" + - " tablespace,hasindexes,hasrules,hastriggers, \n" + - " obj_description(to_regclass(schemaname || '.\"' || tablename || '\"')::oid) table_comment, ( \n" + - " select array_agg(distinct n2.nspname || '/' || c2.relname || '.tbl') as dependencies\n" + - " FROM pg_catalog.pg_constraint c \n" + - " JOIN ONLY pg_catalog.pg_class c1 ON c1.oid = c.conrelid\n" + - " JOIN ONLY pg_catalog.pg_class c2 ON c2.oid = c.confrelid\n" + - " JOIN ONLY pg_catalog.pg_namespace n2 ON n2.oid = c2.relnamespace\n" + - " WHERE c.conrelid = to_regclass(schemaname || '.\"' || tablename || '\"')::oid\n" + - " and c1.relkind = 'r' AND c.contype = 'f'\n" + - " )" + - "from pg_tables \n" + - "where upper(schemaname) = upper('"+schema+"') \n" + - "and tablename = '"+name+"'\n"; - try { - - Connection connect = getConnection(); - - Statement stmt = connect.createStatement(); - - ResultSet rs = stmt.executeQuery(query); - - DBTable table = null; - - while (rs.next()) { - String nameTable = rs.getString("table_name"); - table = new DBTable(nameTable); - table.setSchema(schema); - table.setComment(rs.getString("table_comment")); - if(rs.getArray("dependencies") != null){ - table.setDependencies(new HashSet<>(Arrays.asList((String[])rs.getArray("dependencies").getArray()))); - } else table.setDependencies(new HashSet<>()); - rowToProperties(rs, table.getOptions()); - } - stmt.close(); - return table; - - }catch(Exception e) { - logger.error(lang.getValue("errors", "adapter", "tables").toString(), e); - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "tables").toString(), e); - } - } - - @Override - public Map getTableFields(String schema, String nameTable) { - - try { - Map listField = new HashMap(); - - String query = - "SELECT distinct col.column_name,col.is_nullable,col.data_type, col.udt_name::regtype dtype,col.character_maximum_length, col.column_default, tc.constraint_name, " + - "case\r\n" + - " when lower(data_type) in ('integer', 'numeric', 'smallint', 'double precision', 'bigint') then 'number' \r\n" + - " when lower(data_type) in ('character varying', 'char', 'character', 'varchar') then 'string'\r\n" + - " when lower(data_type) in ('timestamp without time zone', 'timestamp with time zone', 'date') then 'date'\r\n" + - " when lower(data_type) in ('boolean') then 'boolean'\r\n" + - " when lower(data_type) in ('text') then 'text'\r\n" + - " when lower(data_type) in ('bytea') then 'binary'" + - " else 'native'\r\n" + - " end tp, " + - " case when lower(data_type) in ('char', 'character') then true else false end fixed, " + - " pgd.description," + - "col.* FROM " + - "information_schema.columns col " + - "left join information_schema.key_column_usage kc on col.table_schema = kc.table_schema and col.table_name = kc.table_name and col.column_name=kc.column_name " + - "left join information_schema.table_constraints tc on col.table_schema = kc.table_schema and col.table_name = kc.table_name and kc.constraint_name = tc.constraint_name and tc.constraint_type = 'PRIMARY KEY' " + - "left join pg_catalog.pg_statio_all_tables st on st.schemaname = col.table_schema and st.relname = col.table_name " + - "left join pg_catalog.pg_description pgd on (pgd.objoid=st.relid and pgd.objsubid=col.ordinal_position) " + - "where upper(col.table_schema) = upper(:schema) and col.table_name = :table " + - "order by col.column_name "; - Connection connect = getConnection(); - - NamedParameterPreparedStatement stmt = NamedParameterPreparedStatement.createNamedParameterPreparedStatement(connect, query); - stmt.setString("schema", schema); - stmt.setString("table", nameTable); - - ResultSet rs = stmt.executeQuery(); - while(rs.next()){ - DBTableField field = new DBTableField(); - - field.setName(rs.getString("column_name")); - field.setDescription(rs.getString("description")); - field.setNameExactly(!rs.getString("column_name").equals(rs.getString("column_name").toLowerCase())); - if (rs.getString("constraint_name") != null) { - field.setIsPrimaryKey(true); - } - String typeSQL = getFieldType(rs); - field.setTypeSQL(typeSQL); - field.setIsNullable( !typeSQL.toLowerCase().contains("not null")); - field.setTypeUniversal(FieldType.fromString(rs.getString("tp"))); - field.setFixed(false); - field.setLength(rs.getInt("character_maximum_length")); - field.setPrecision(rs.getInt("numeric_precision")); - field.setScale(rs.getInt("numeric_scale")); - field.setFixed(rs.getBoolean("fixed")); - field.setOrder(rs.getInt("ordinal_position")); - field.setDefaultValue(rs.getString("column_default")); - listField.put(field.getName(), field); - } - stmt.close(); - - return listField; - }catch(Exception e) { - logger.error(lang.getValue("errors", "adapter", "tables").toString(), e); - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "tables").toString(), e); - } - } - - protected String getFieldType(ResultSet rs) { - try { - StringBuilder type = new StringBuilder(); - type.append(rs.getString("dtype")); - - Integer max_length = rs.getInt("character_maximum_length"); - if (!rs.wasNull()) { - type.append("("+max_length.toString()+")"); - } - if (rs.getString("is_nullable").equals("NO")){ - type.append(" NOT NULL"); - } - - return type.toString(); - }catch(Exception e) { - logger.error(lang.getValue("errors", "adapter", "tables").toString(), e); - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "tables").toString(), e); - } - } - - @Override - public Map getIndexes(String schema, String nameTable) { - Map indexes = new HashMap<>(); - try { - String query = "select i.schemaname,\r\n" + - "i.tablename, \r\n" + - "i.indexname, \r\n" + - "i.tablespace, \r\n" + - "i.indexdef as ddl \r\n" + - "from \r\n" + - "pg_indexes as i JOIN pg_class as cl \r\n" + - " on i.indexname = cl.relname\r\n" + - "JOIN pg_index AS idx \r\n" + - " ON cl.oid = idx.indexrelid\r\n" + - "where i.tablename not like 'pg%' and i.schemaname = :schema and i.tablename = :table and idx.indisprimary = false -- and idx.indisunique=false "; - - Connection connect = getConnection(); - NamedParameterPreparedStatement stmt = NamedParameterPreparedStatement.createNamedParameterPreparedStatement(connect, query); - stmt.setString("schema", schema); - stmt.setString("table", nameTable); - - ResultSet rs = stmt.executeQuery(); - while(rs.next()){ - DBIndex index = new DBIndex(); - index.setName(rs.getString("indexname")); - index.setSchema(schema); - rowToProperties(rs, index.getOptions()); - indexes.put(index.getName(), index); - } - stmt.close(); - - return indexes; - - }catch(Exception e) { - logger.error(lang.getValue("errors", "adapter", "indexes").toString()); - throw new ExceptionDBGitRunTime(e.getMessage()); - } - - } - - @Override - public Map getConstraints(String schema, String nameTable) { - Map constraints = new HashMap<>(); - try { - /* - String query = "select conname as constraint_name,contype as constraint_type, " + - " pg_catalog.pg_get_constraintdef(r.oid, true) as ddl " + - "from " + - " pg_class c " + - " join pg_namespace n on n.oid = c.relnamespace " + - " join pg_catalog.pg_constraint r on r.conrelid = c.relfilenode " + - "WHERE " + - " relname = :table and nspname = :schema and c.relkind = 'r'"; - */ - - - String query = "SELECT conname as constraint_name,contype as constraint_type, \r\n" + - " pg_catalog.pg_get_constraintdef(con.oid, true) as ddl\r\n" + - " FROM pg_catalog.pg_constraint con\r\n" + - " INNER JOIN pg_catalog.pg_class rel\r\n" + - " ON rel.oid = con.conrelid\r\n" + - " INNER JOIN pg_catalog.pg_namespace nsp\r\n" + - " ON nsp.oid = connamespace\r\n" + - " WHERE nsp.nspname = :schema\r\n" + - " AND rel.relname = :table"; - - - - Connection connect = getConnection(); - NamedParameterPreparedStatement stmt = NamedParameterPreparedStatement.createNamedParameterPreparedStatement(connect, query); - stmt.setString("table", nameTable); - stmt.setString("schema", schema); - - ResultSet rs = stmt.executeQuery(); - while(rs.next()){ - DBConstraint con = new DBConstraint(); - con.setName(rs.getString("constraint_name")); - con.setConstraintType(rs.getString("constraint_type")); - con.setSchema(schema); - rowToProperties(rs, con.getOptions()); - constraints.put(con.getName(), con); - } - stmt.close(); - - return constraints; - - }catch(Exception e) { - logger.error(lang.getValue("errors", "adapter", "constraints").toString()); - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "constraints").toString(), e); - } - } - - @Override - public Map getViews(String schema) { - Map listView = new HashMap(); - try { - String query = - "select nsp.nspname as object_schema, cls.relname as object_name, rol.rolname as owner, \n" + - "'create or replace view ' || nsp.nspname || '.' || cls.relname || ' as ' || pg_get_viewdef(cls.oid) as ddl, (\n" + - " select array_agg(distinct source_ns.nspname || '/' || source_table.relname || '.vw') as dependencySam\n" + - " from pg_depend \n" + - " join pg_rewrite ON pg_depend.objid = pg_rewrite.oid \n" + - " join pg_class as dependent_view ON pg_rewrite.ev_class = dependent_view.oid \n" + - " join pg_class as source_table ON pg_depend.refobjid = source_table.oid AND source_table.relkind = 'v'\n" + - " join pg_attribute ON pg_attribute.attrelid = pg_depend.refobjid \n" + - " and pg_attribute.attnum = pg_depend.refobjsubid \n" + - " join pg_namespace dependent_ns ON dependent_ns.oid = dependent_view.relnamespace\n" + - " join pg_namespace source_ns ON source_ns.oid = source_table.relnamespace\n" + - " where pg_attribute.attnum > 0 \n" + - " and dependent_view.relname = cls.relname\n" + - ") as dependencies\n" + - "from pg_class cls \n" + - "join pg_roles rol on rol.oid = cls.relowner \n" + - "join pg_namespace nsp on nsp.oid = cls.relnamespace \n" + - "where nsp.nspname not in ('information_schema', 'pg_catalog') \n" + - "and nsp.nspname not like 'pg_toast%' \n" + - "and cls.relkind = 'v' \n" + - "and nsp.nspname = '"+schema+"' \n"; - - Connection connect = getConnection(); - Statement stmt = connect.createStatement(); - ResultSet rs = stmt.executeQuery(query); - - while(rs.next()){ - DBView view = new DBView(rs.getString("object_name")); - view.setSchema(rs.getString("object_schema")); - view.setOwner(rs.getString("owner")); - rowToProperties(rs, view.getOptions()); - if(rs.getArray("dependencies") != null){ - view.setDependencies(new HashSet<>(Arrays.asList((String[])rs.getArray("dependencies").getArray()))); - } - listView.put(rs.getString("object_name"), view); - } - - stmt.close(); - return listView; - } catch (Exception e) { - logger.error(e.getMessage()); - System.out.println(lang.getValue("errors", "adapter", "views") + ": "+ e.getMessage()); - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "views") + ": "+ e.getMessage()); - } - } - - @Override - public DBView getView(String schema, String name) { - DBView view = new DBView(name); - view.setSchema(schema); - view.setDependencies(new HashSet<>()); - - try { - - String query = - "select nsp.nspname as object_schema, cls.relname as object_name, rol.rolname as owner, \n" + - "'create or replace view ' || nsp.nspname || '.' || cls.relname || ' as ' || pg_get_viewdef(cls.oid) as ddl, (\n" + - " select array_agg(distinct source_ns.nspname || '/' || source_table.relname || '.vw') as dependencySam\n" + - " from pg_depend \n" + - " join pg_rewrite ON pg_depend.objid = pg_rewrite.oid \n" + - " join pg_class as dependent_view ON pg_rewrite.ev_class = dependent_view.oid \n" + - " join pg_class as source_table ON pg_depend.refobjid = source_table.oid AND source_table.relkind = 'v'\n" + - " join pg_attribute ON pg_attribute.attrelid = pg_depend.refobjid \n" + - " and pg_attribute.attnum = pg_depend.refobjsubid \n" + - " join pg_namespace dependent_ns ON dependent_ns.oid = dependent_view.relnamespace\n" + - " join pg_namespace source_ns ON source_ns.oid = source_table.relnamespace\n" + - " where pg_attribute.attnum > 0 \n" + - " and dependent_view.relname = cls.relname\n" + - ") as dependencies\n" + - "from pg_class cls \n" + - "join pg_roles rol on rol.oid = cls.relowner \n" + - "join pg_namespace nsp on nsp.oid = cls.relnamespace \n" + - "where nsp.nspname not in ('information_schema', 'pg_catalog') \n" + - "and nsp.nspname not like 'pg_toast%' \n" + - "and cls.relkind = 'v' \n" + - "and nsp.nspname = '"+schema+"' \n" + - "and cls.relname='"+name+"'\n"; - - Connection connect = getConnection(); - Statement stmt = connect.createStatement(); - ResultSet rs = stmt.executeQuery(query); - - while (rs.next()) { - view.setOwner(rs.getString("owner")); - if(rs.getArray("dependencies") != null){ - view.setDependencies(new HashSet<>(Arrays.asList((String[])rs.getArray("dependencies").getArray()))); - } - rowToProperties(rs, view.getOptions()); - } - - - stmt.close(); - return view; - - }catch(Exception e) { - logger.error(lang.getValue("errors", "adapter", "views") + ": "+ e.getMessage()); - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "views") + ": "+ e.getMessage()); - } - } - - @Override - public Map getTriggers(String schema) { - Map listTrigger = new HashMap(); - try { - String query = "SELECT trg.tgname, tbl.relname as trigger_table ,pg_get_triggerdef(trg.oid) AS ddl \r\n" + - "FROM pg_trigger trg\r\n" + - "JOIN pg_class tbl on trg.tgrelid = tbl.oid\r\n" + - "JOIN pg_namespace ns ON ns.oid = tbl.relnamespace\r\n" + - "and trg.tgconstraint=0 and ns.nspname like \'"+schema+"\'"; - Connection connect = getConnection(); - Statement stmt = connect.createStatement(); - ResultSet rs = stmt.executeQuery(query); - while(rs.next()){ - String name = rs.getString("tgname"); - String sql = rs.getString("ddl"); - DBTrigger trigger = new DBTrigger(name); - trigger.setSchema(schema); - trigger.setOwner("postgres"); - rowToProperties(rs, trigger.getOptions()); - listTrigger.put(name, trigger); - } - stmt.close(); - return listTrigger; - }catch(Exception e) { - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "triggers").toString(), e); - } - } - @Override - public DBTrigger getTrigger(String schema, String name) { - DBTrigger trigger = null; - try { - String query = "SELECT trg.tgname, tbl.relname as trigger_table ,pg_get_triggerdef(trg.oid) AS ddl \r\n" + - "FROM pg_trigger trg\r\n" + - "JOIN pg_class tbl on trg.tgrelid = tbl.oid\r\n" + - "JOIN pg_namespace ns ON ns.oid = tbl.relnamespace\r\n" + - "and trg.tgconstraint=0 and ns.nspname like \'"+schema+"\' and trg.tgname like \'"+name+"\'"; - Connection connect = getConnection(); - Statement stmt = connect.createStatement(); - ResultSet rs = stmt.executeQuery(query); - while(rs.next()){ - String sql = rs.getString("ddl"); - trigger = new DBTrigger(name); - trigger.setSchema(schema); - trigger.setOwner("postgres"); - rowToProperties(rs, trigger.getOptions()); - } - stmt.close(); - return trigger; - }catch(Exception e) { - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "triggers").toString(), e); - } - - } - @Override - public Map getPackages(String schema) { - // TODO Auto-generated method stub - return null; - } - - @Override - public DBPackage getPackage(String schema, String name) { - // TODO Auto-generated method stub - return null; - } - - @Override - public Map getProcedures(String schema) { - Map mapProcs = new HashMap<>(); - try { - String query = - "SELECT n.nspname AS \"schema\", u.rolname, p.proname AS \"name\", \n" + - " pg_catalog.pg_get_function_arguments(p.oid) AS \"arguments\",\n" + - " pg_get_functiondef(p.oid) AS ddl\n" + - "FROM pg_catalog.pg_proc p\n" + - " JOIN pg_catalog.pg_roles u ON u.oid = p.proowner\n" + - " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace\n" + - "WHERE p.prokind = 'p' \n" + - " AND n.nspname not in('pg_catalog', 'information_schema')\n" + - " AND n.nspname = '"+schema+"'"; - - Connection connect = getConnection(); - Statement stmt = connect.createStatement(); - ResultSet rs = stmt.executeQuery(query); - while(rs.next()){ - String name = rs.getString("name"); - String owner = rs.getString("rolname"); - DBProcedure proc = new DBProcedure(name); - proc.setSchema(schema); - proc.setOwner(owner); - rowToProperties(rs,proc.getOptions()); - - mapProcs.put(mapProcs.containsKey(name) ? name + "_" + proc.getHash() : name, proc); - } - stmt.close(); - }catch(Exception e) { - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "prc").toString(), e); - } - return mapProcs; - } - - @Override - public DBProcedure getProcedure(String schema, String name) { - DBProcedure proc = null; - try { - String query = - "SELECT n.nspname AS \"schema\", u.rolname, p.proname AS \"name\", \n" + - " pg_catalog.pg_get_function_arguments(p.oid) AS \"arguments\",\n" + - " pg_get_functiondef(p.oid) AS ddl\n" + - "FROM pg_catalog.pg_proc p\n" + - " JOIN pg_catalog.pg_roles u ON u.oid = p.proowner\n" + - " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace\n" + - "WHERE p.prokind = 'p' \n" + - " AND n.nspname not in('pg_catalog', 'information_schema')\n" + - " AND n.nspname = '"+schema+"'" + - " AND p.proname = '"+name+"'"; - - Connection connect = getConnection(); - Statement stmt = connect.createStatement(); - ResultSet rs = stmt.executeQuery(query); - while(rs.next()){ - proc = new DBProcedure(rs.getString("name")); - proc.setOwner(rs.getString("rolname")); - proc.setSchema(schema); - rowToProperties(rs,proc.getOptions()); - } - stmt.close(); - }catch(Exception e) { - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "prc").toString(), e); - } - return proc; - } - - @Override - public Map getFunctions(String schema) { - Map listFunction = new HashMap(); - try { - String query = - "SELECT n.nspname AS \"schema\", u.rolname, p.proname AS \"name\", \n" + - " pg_catalog.pg_get_function_arguments(p.oid) AS \"arguments\",\n" + - " pg_get_functiondef(p.oid) AS ddl\n" + - "FROM pg_catalog.pg_proc p\n" + - " JOIN pg_catalog.pg_roles u ON u.oid = p.proowner\n" + - " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace\n" + - "WHERE p.prokind = 'f' \n" + - " AND n.nspname not in('pg_catalog', 'information_schema')\n" + - " AND n.nspname = '"+schema+"'"; - - Connection connect = getConnection(); - Statement stmt = connect.createStatement(); - ResultSet rs = stmt.executeQuery(query); - while(rs.next()){ - String name = rs.getString("name"); - String owner = rs.getString("rolname"); - String args = rs.getString("arguments"); - DBFunction func = new DBFunction(name); - func.setSchema(schema); - func.setOwner(owner); - rowToProperties(rs,func.getOptions()); - //func.setArguments(args); - - listFunction.put(listFunction.containsKey(name) ? name + "_" + func.getHash() : name, func); - } - stmt.close(); - }catch(Exception e) { - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "fnc").toString(), e); - } - return listFunction; - } - - @Override - public DBFunction getFunction(String schema, String name) { - - try { - String query = - "SELECT n.nspname AS \"schema\", u.rolname, p.proname AS \"name\", \n" + - " pg_catalog.pg_get_function_arguments(p.oid) AS \"arguments\",\n" + - " pg_get_functiondef(p.oid) AS ddl\n" + - "FROM pg_catalog.pg_proc p\n" + - " JOIN pg_catalog.pg_roles u ON u.oid = p.proowner\n" + - " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace\n" + - "WHERE p.prokind = 'f' \n" + - " AND n.nspname not in('pg_catalog', 'information_schema')\n" + - " AND n.nspname = '"+schema+"' AND p.proname = '"+name+"'"; - Connection connect = getConnection(); - Statement stmt = connect.createStatement(); - ResultSet rs = stmt.executeQuery(query); - - DBFunction func = null; - while (rs.next()) { - func = new DBFunction(rs.getString("name")); - String owner = rs.getString("rolname"); - String args = rs.getString("arguments"); - func.setSchema(schema); - func.setOwner(owner); - //func.setArguments(args); - rowToProperties(rs,func.getOptions()); - } - stmt.close(); - - return func; - - }catch(Exception e) { - throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "fnc").toString(), e); - } - } - - @Override - public DBTableData getTableDataPortion(String schema, String nameTable, int portionIndex, int tryNumber) { - DBTableData data = new DBTableData(); - - try { - int maxRowsCount = DBGitConfig.getInstance().getInteger("core", "MAX_ROW_COUNT_FETCH", DBGitConfig.getInstance().getIntegerGlobal("core", "MAX_ROW_COUNT_FETCH", MAX_ROW_COUNT_FETCH)); - - if (DBGitConfig.getInstance().getBoolean("core", "LIMIT_FETCH", DBGitConfig.getInstance().getBooleanGlobal("core", "LIMIT_FETCH", true))) { - Statement st = getConnection().createStatement(); - String query = "select COALESCE(count(*), 0) kolvo from ( select 1 from "+ - schema + "." + DBAdapterPostgres.escapeNameIfNeeded(nameTable) + " limit " + (maxRowsCount + 1) + " ) tbl"; - ResultSet rs = st.executeQuery(query); - rs.next(); - if (rs.getInt("kolvo") > maxRowsCount) { - data.setErrorFlag(DBTableData.ERROR_LIMIT_ROWS); - return data; - } - } - - int portionSize = DBGitConfig.getInstance().getInteger("core", "PORTION_SIZE", DBGitConfig.getInstance().getIntegerGlobal("core", "PORTION_SIZE", 1000)); - - int begin = 1 + portionSize*portionIndex; - int end = portionSize + portionSize*portionIndex; - - Statement st = getConnection().createStatement(); - String query = " SELECT * FROM \r\n" + - " (SELECT f.*, ROW_NUMBER() OVER (ORDER BY ctid) DBGIT_ROW_NUM FROM " + schema + "." + DBAdapterPostgres.escapeNameIfNeeded(nameTable) + " f) s\r\n" + - " WHERE DBGIT_ROW_NUM BETWEEN " + begin + " and " + end; - ResultSet rs = st.executeQuery(query); - - data.setResultSet(rs); - return data; - } catch(Exception e) { - ConsoleWriter.println("err: " + e.getLocalizedMessage()); - - logger.error(lang.getValue("errors", "adapter", "tableData").toString(), e); - - try { - if (tryNumber <= DBGitConfig.getInstance().getInteger("core", "TRY_COUNT", DBGitConfig.getInstance().getIntegerGlobal("core", "TRY_COUNT", 1000))) { - try { - TimeUnit.SECONDS.sleep(DBGitConfig.getInstance().getInteger("core", "TRY_DELAY", DBGitConfig.getInstance().getIntegerGlobal("core", "TRY_DELAY", 1000))); - } catch (InterruptedException e1) { - throw new ExceptionDBGitRunTime(e1.getMessage()); - } - ConsoleWriter.println("Error while getting portion of data, try " + tryNumber); - getTableDataPortion(schema, nameTable, portionIndex, tryNumber++); - } - } catch (Exception e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } - - try { - getConnection().rollback(); - } catch (Exception e2) { - logger.error(lang.getValue("errors", "adapter", "rollback").toString(), e2); - } - throw new ExceptionDBGitRunTime(e.getMessage()); - } - } - - @Override - public DBTableData getTableData(String schema, String nameTable) { - String tableName = schema+"."+ DBAdapterPostgres.escapeNameIfNeeded(nameTable); - try { - DBTableData data = new DBTableData(); - - int maxRowsCount = DBGitConfig.getInstance().getInteger("core", "MAX_ROW_COUNT_FETCH", DBGitConfig.getInstance().getIntegerGlobal("core", "MAX_ROW_COUNT_FETCH", MAX_ROW_COUNT_FETCH)); - - if (DBGitConfig.getInstance().getBoolean("core", "LIMIT_FETCH", DBGitConfig.getInstance().getBooleanGlobal("core", "LIMIT_FETCH", true))) { - Statement st = getConnection().createStatement(); - String query = "select COALESCE(count(*), 0) kolvo from ( select 1 from "+ - tableName + " limit " + (maxRowsCount + 1) + " ) tbl"; - ResultSet rs = st.executeQuery(query); - rs.next(); - if (rs.getInt("kolvo") > maxRowsCount) { - data.setErrorFlag(DBTableData.ERROR_LIMIT_ROWS); - return data; - } - } - Statement st = getConnection().createStatement(); - ResultSet rs = st.executeQuery("select * from "+tableName); - data.setResultSet(rs); - - //TODO other state - - return data; - } catch(Exception e) { - logger.error(lang.getValue("errors", "adapter", "tableData").toString(), e); - try { - getConnection().rollback(); - } catch (Exception e2) { - logger.error(lang.getValue("errors", "adapter", "rollback").toString(), e2); - } - throw new ExceptionDBGitRunTime(e.getMessage()); - } - } - - @Override - public Map getUsers() { - Map listUser = new HashMap(); - try { - String query = "select *from pg_user"; - Connection connect = getConnection(); - Statement stmt = connect.createStatement(); - ResultSet rs = stmt.executeQuery(query); - while(rs.next()){ - String name = rs.getString(1); - DBUser user = new DBUser(name); - listUser.put(name, user); - } - stmt.close(); - }catch(Exception e) { - logger.error(e.getMessage()); - throw new ExceptionDBGitRunTime(e.getMessage()); - } - //connect.cre - //select *from pg_catalog.pg_namespace; - return listUser; - } - - @Override - public Map getRoles() { - Map listRole = new HashMap(); - try { - String query = "select *,array_to_string(array(SELECT rolname " + - "FROM pg_roles,pg_auth_members " + - "WHERE member = auth.oid and roleid=oid), ', ') as rolmemberof from pg_authid as auth where auth.rolname not like 'pg_%'"; - Connection connect = getConnection(); - Statement stmt = connect.createStatement(); - ResultSet rs = stmt.executeQuery(query); - while(rs.next()){ - String name = rs.getString("rolname"); - DBRole role = new DBRole(name); - rowToProperties(rs, role.getOptions()); - listRole.put(name, role); - } - stmt.close(); - }catch(Exception e) { - logger.error(e.getMessage()); - throw new ExceptionDBGitRunTime(e.getMessage()); - } - return listRole; - } - - @Override - public boolean userHasRightsToGetDdlOfOtherUsers() { - return true; - } - - @Override - public IFactoryDBBackupAdapter getBackupAdapterFactory() { - return backupFactory; - } - - @Override - public DbType getDbType() { - return DbType.POSTGRES; - } - - @Override - public String getDbVersion() { - try { - PreparedStatement stmt = getConnection().prepareStatement("SHOW server_version"); - ResultSet resultSet = stmt.executeQuery(); - resultSet.next(); - - String result = resultSet.getString("server_version"); - resultSet.close(); - stmt.close(); - - return result; - } catch (SQLException e) { - return ""; - } - } - - @Override - public IFactoryDBConvertAdapter getConvertAdapterFactory() { - return convertFactory; - } - - @Override - public void createSchemaIfNeed(String schemaName) throws ExceptionDBGit { - try { - Statement st = connect.createStatement(); - ResultSet rs = st.executeQuery("select count(*) cnt from information_schema.schemata where upper(schema_name) = '" + - schemaName.toUpperCase() + "'"); - - rs.next(); - if (rs.getInt("cnt") == 0) { - StatementLogging stLog = new StatementLogging(connect, getStreamOutputSqlCommand(), isExecSql()); - stLog.execute("create schema " + schemaName + ";\n"); - - stLog.close(); - } - - connect.commit(); - rs.close(); - st.close(); - } catch (SQLException e) { - throw new ExceptionDBGit(lang.getValue("errors", "adapter", "createSchema") + ": " + e.getLocalizedMessage()); - } - - } - - @Override - public void createRoleIfNeed(String roleName) throws ExceptionDBGit { - try { - Statement st = connect.createStatement(); - ResultSet rs = st.executeQuery("select count(*) cnt from pg_catalog.pg_roles where upper(rolname) = '" + - roleName.toUpperCase() + "'"); - - rs.next(); - if (rs.getInt("cnt") == 0) { - StatementLogging stLog = new StatementLogging(connect, getStreamOutputSqlCommand(), isExecSql()); - stLog.execute("CREATE ROLE " + roleName + " LOGIN PASSWORD '" + roleName + "'"); - - stLog.close(); - } - - connect.commit(); - rs.close(); - st.close(); - } catch (SQLException e) { - throw new ExceptionDBGit(lang.getValue("errors", "adapter", "createSchema") + ": " + e.getLocalizedMessage()); - } - } - - @Override - public String getDefaultScheme() throws ExceptionDBGit { - return "public"; - } - - @Override - public boolean isReservedWord(String word) { - return reservedWords.contains(word.toUpperCase()); - } - - - public static String escapeNameIfNeeded(String name){ - boolean shouldBeEscaped = !name.equals(name.toLowerCase()) || name.contains(".") || reservedWords.contains(name.toUpperCase()); //TODO maybe check on isReservedWord? - if(name.startsWith("\"") && name.endsWith("\"")) shouldBeEscaped = false; - return MessageFormat.format("{1}{0}{1}", name, shouldBeEscaped ? "\"" : ""); - } - - static { - reservedWords.add("A"); - reservedWords.add("ABORT"); - reservedWords.add("ABS"); - reservedWords.add("ABSOLUTE"); - reservedWords.add("ACCESS"); - reservedWords.add("ACTION"); - reservedWords.add("ADA"); - reservedWords.add("ADD"); - reservedWords.add("ADMIN"); - reservedWords.add("AFTER"); - reservedWords.add("AGGREGATE"); - reservedWords.add("ALIAS"); - reservedWords.add("ALL"); - reservedWords.add("ALLOCATE"); - reservedWords.add("ALSO"); - reservedWords.add("ALTER"); - reservedWords.add("ALWAYS"); - reservedWords.add("ANALYSE"); - reservedWords.add("ANALYZE"); - reservedWords.add("AND"); - reservedWords.add("ANY"); - reservedWords.add("ARE"); - reservedWords.add("ARRAY"); - reservedWords.add("AS"); - reservedWords.add("ASC"); - reservedWords.add("ASENSITIVE"); - reservedWords.add("ASSERTION"); - reservedWords.add("ASSIGNMENT"); - reservedWords.add("ASYMMETRIC"); - reservedWords.add("AT"); - reservedWords.add("ATOMIC"); - reservedWords.add("ATTRIBUTE"); - reservedWords.add("ATTRIBUTES"); - reservedWords.add("AUTHORIZATION"); - reservedWords.add("AVG"); - reservedWords.add("BACKWARD"); - reservedWords.add("BEFORE"); - reservedWords.add("BEGIN"); - reservedWords.add("BERNOULLI"); - reservedWords.add("BETWEEN"); - reservedWords.add("BIGINT"); - reservedWords.add("BINARY"); - reservedWords.add("BIT"); - reservedWords.add("BITVAR"); - reservedWords.add("BIT_LENGTH"); - reservedWords.add("BLOB"); - reservedWords.add("BOOLEAN"); - reservedWords.add("BOTH"); - reservedWords.add("BREADTH"); - reservedWords.add("BY"); - reservedWords.add("C"); - reservedWords.add("CACHE"); - reservedWords.add("CALL"); - reservedWords.add("CALLED"); - reservedWords.add("CARDINALITY"); - reservedWords.add("CASCADE"); - reservedWords.add("CASCADED"); - reservedWords.add("CASE"); - reservedWords.add("CAST"); - reservedWords.add("CATALOG"); - reservedWords.add("CATALOG_NAME"); - reservedWords.add("CEIL"); - reservedWords.add("CEILING"); - reservedWords.add("CHAIN"); - reservedWords.add("CHAR"); - reservedWords.add("CHARACTER"); - reservedWords.add("CHARACTERISTICS"); - reservedWords.add("CHARACTERS"); - reservedWords.add("CHARACTER_LENGTH"); - reservedWords.add("CHARACTER_SET_CATALOG"); - reservedWords.add("CHARACTER_SET_NAME"); - reservedWords.add("CHARACTER_SET_SCHEMA"); - reservedWords.add("CHAR_LENGTH"); - reservedWords.add("CHECK"); - reservedWords.add("CHECKED"); - reservedWords.add("CHECKPOINT"); - reservedWords.add("CLASS"); - reservedWords.add("CLASS_ORIGIN"); - reservedWords.add("CLOB"); - reservedWords.add("CLOSE"); - reservedWords.add("CLUSTER"); - reservedWords.add("COALESCE"); - reservedWords.add("COBOL"); - reservedWords.add("COLLATE"); - reservedWords.add("COLLATION"); - reservedWords.add("COLLATION_CATALOG"); - reservedWords.add("COLLATION_NAME"); - reservedWords.add("COLLATION_SCHEMA"); - reservedWords.add("COLLECT"); - reservedWords.add("COLUMN"); - reservedWords.add("COLUMN_NAME"); - reservedWords.add("COMMAND_FUNCTION"); - reservedWords.add("COMMAND_FUNCTION_CODE"); - reservedWords.add("COMMENT"); - reservedWords.add("COMMIT"); - reservedWords.add("COMMITTED"); - reservedWords.add("COMPLETION"); - reservedWords.add("CONDITION"); - reservedWords.add("CONDITION_NUMBER"); - reservedWords.add("CONNECT"); - reservedWords.add("CONNECTION"); - reservedWords.add("CONNECTION_NAME"); - reservedWords.add("CONSTRAINT"); - reservedWords.add("CONSTRAINTS"); - reservedWords.add("CONSTRAINT_CATALOG"); - reservedWords.add("CONSTRAINT_NAME"); - reservedWords.add("CONSTRAINT_SCHEMA"); - reservedWords.add("CONSTRUCTOR"); - reservedWords.add("CONTAINS"); - reservedWords.add("CONTINUE"); - reservedWords.add("CONVERSION"); - reservedWords.add("CONVERT"); - reservedWords.add("COPY"); - reservedWords.add("CORR"); - reservedWords.add("CORRESPONDING"); - reservedWords.add("COUNT"); - reservedWords.add("COVAR_POP"); - reservedWords.add("COVAR_SAMP"); - reservedWords.add("CREATE"); - reservedWords.add("CREATEDB"); - reservedWords.add("CREATEROLE"); - reservedWords.add("CREATEUSER"); - reservedWords.add("CROSS"); - reservedWords.add("CSV"); - reservedWords.add("CUBE"); - reservedWords.add("CUME_DIST"); - reservedWords.add("CURRENT"); - reservedWords.add("CURRENT_DATE"); - reservedWords.add("CURRENT_DEFAULT_TRANSFORM_GROUP"); - reservedWords.add("CURRENT_PATH"); - reservedWords.add("CURRENT_ROLE"); - reservedWords.add("CURRENT_TIME"); - reservedWords.add("CURRENT_TIMESTAMP"); - reservedWords.add("CURRENT_TRANSFORM_GROUP_FOR_TYPE"); - reservedWords.add("CURRENT_USER"); - reservedWords.add("CURSOR"); - reservedWords.add("CURSOR_NAME"); - reservedWords.add("CYCLE"); - reservedWords.add("DATA"); - reservedWords.add("DATABASE"); - reservedWords.add("DATE"); - reservedWords.add("DATETIME_INTERVAL_CODE"); - reservedWords.add("DATETIME_INTERVAL_PRECISION"); - reservedWords.add("DAY"); - reservedWords.add("DEALLOCATE"); - reservedWords.add("DEC"); - reservedWords.add("DECIMAL"); - reservedWords.add("DECLARE"); - reservedWords.add("DEFAULT"); - reservedWords.add("DEFAULTS"); - reservedWords.add("DEFERRABLE"); - reservedWords.add("DEFERRED"); - reservedWords.add("DEFINED"); - reservedWords.add("DEFINER"); - reservedWords.add("DEGREE"); - reservedWords.add("DELETE"); - reservedWords.add("DELIMITER"); - reservedWords.add("DELIMITERS"); - reservedWords.add("DENSE_RANK"); - reservedWords.add("DEPTH"); - reservedWords.add("DEREF"); - reservedWords.add("DERIVED"); - reservedWords.add("DESC"); - reservedWords.add("DESCRIBE"); - reservedWords.add("DESCRIPTOR"); - reservedWords.add("DESTROY"); - reservedWords.add("DESTRUCTOR"); - reservedWords.add("DETERMINISTIC"); - reservedWords.add("DIAGNOSTICS"); - reservedWords.add("DICTIONARY"); - reservedWords.add("DISABLE"); - reservedWords.add("DISCONNECT"); - reservedWords.add("DISPATCH"); - reservedWords.add("DISTINCT"); - reservedWords.add("DO"); - reservedWords.add("DOMAIN"); - reservedWords.add("DOUBLE"); - reservedWords.add("DROP"); - reservedWords.add("DYNAMIC"); - reservedWords.add("DYNAMIC_FUNCTION"); - reservedWords.add("DYNAMIC_FUNCTION_CODE"); - reservedWords.add("EACH"); - reservedWords.add("ELEMENT"); - reservedWords.add("ELSE"); - reservedWords.add("ENABLE"); - reservedWords.add("ENCODING"); - reservedWords.add("ENCRYPTED"); - reservedWords.add("END"); - reservedWords.add("END-EXEC"); - reservedWords.add("EQUALS"); - reservedWords.add("ESCAPE"); - reservedWords.add("EVERY"); - reservedWords.add("EXCEPT"); - reservedWords.add("EXCEPTION"); - reservedWords.add("EXCLUDE"); - reservedWords.add("EXCLUDING"); - reservedWords.add("EXCLUSIVE"); - reservedWords.add("EXEC"); - reservedWords.add("EXECUTE"); - reservedWords.add("EXISTING"); - reservedWords.add("EXISTS"); - reservedWords.add("EXP"); - reservedWords.add("EXPLAIN"); - reservedWords.add("EXTERNAL"); - reservedWords.add("EXTRACT"); - reservedWords.add("FALSE"); - reservedWords.add("FETCH"); - reservedWords.add("FILTER"); - reservedWords.add("FINAL"); - reservedWords.add("FIRST"); - reservedWords.add("FLOAT"); - reservedWords.add("FLOOR"); - reservedWords.add("FOLLOWING"); - reservedWords.add("FOR"); - reservedWords.add("FORCE"); - reservedWords.add("FOREIGN"); - reservedWords.add("FORTRAN"); - reservedWords.add("FORWARD"); - reservedWords.add("FOUND"); - reservedWords.add("FREE"); - reservedWords.add("FREEZE"); - reservedWords.add("FROM"); - reservedWords.add("FULL"); - reservedWords.add("FUNCTION"); - reservedWords.add("FUSION"); - reservedWords.add("G"); - reservedWords.add("GENERAL"); - reservedWords.add("GENERATED"); - reservedWords.add("GET"); - reservedWords.add("GLOBAL"); - reservedWords.add("GO"); - reservedWords.add("GOTO"); - reservedWords.add("GRANT"); - reservedWords.add("GRANTED"); - reservedWords.add("GREATEST"); - reservedWords.add("GROUP"); - reservedWords.add("GROUPING"); - reservedWords.add("HANDLER"); - reservedWords.add("HAVING"); - reservedWords.add("HEADER"); - reservedWords.add("HIERARCHY"); - reservedWords.add("HOLD"); - reservedWords.add("HOST"); - reservedWords.add("HOUR"); - reservedWords.add("IDENTITY"); - reservedWords.add("IGNORE"); - reservedWords.add("ILIKE"); - reservedWords.add("IMMEDIATE"); - reservedWords.add("IMMUTABLE"); - reservedWords.add("IMPLEMENTATION"); - reservedWords.add("IMPLICIT"); - reservedWords.add("IN"); - reservedWords.add("INCLUDING"); - reservedWords.add("INCREMENT"); - reservedWords.add("INDEX"); - reservedWords.add("INDICATOR"); - reservedWords.add("INFIX"); - reservedWords.add("INHERIT"); - reservedWords.add("INHERITS"); - reservedWords.add("INITIALIZE"); - reservedWords.add("INITIALLY"); - reservedWords.add("INNER"); - reservedWords.add("INOUT"); - reservedWords.add("INPUT"); - reservedWords.add("INSENSITIVE"); - reservedWords.add("INSERT"); - reservedWords.add("INSTANCE"); - reservedWords.add("INSTANTIABLE"); - reservedWords.add("INSTEAD"); - reservedWords.add("INT"); - reservedWords.add("INTEGER"); - reservedWords.add("INTERSECT"); - reservedWords.add("INTERSECTION"); - reservedWords.add("INTERVAL"); - reservedWords.add("INTO"); - reservedWords.add("INVOKER"); - reservedWords.add("IS"); - reservedWords.add("ISNULL"); - reservedWords.add("ISOLATION"); - reservedWords.add("ITERATE"); - reservedWords.add("JOIN"); - reservedWords.add("K"); - reservedWords.add("KEY"); - reservedWords.add("KEY_MEMBER"); - reservedWords.add("KEY_TYPE"); - reservedWords.add("LANCOMPILER"); - reservedWords.add("LANGUAGE"); - reservedWords.add("LARGE"); - reservedWords.add("LAST"); - reservedWords.add("LATERAL"); - reservedWords.add("LEADING"); - reservedWords.add("LEAST"); - reservedWords.add("LEFT"); - reservedWords.add("LENGTH"); - reservedWords.add("LESS"); - reservedWords.add("LEVEL"); - reservedWords.add("LIKE"); - reservedWords.add("LIMIT"); - reservedWords.add("LISTEN"); - reservedWords.add("LN"); - reservedWords.add("LOAD"); - reservedWords.add("LOCAL"); - reservedWords.add("LOCALTIME"); - reservedWords.add("LOCALTIMESTAMP"); - reservedWords.add("LOCATION"); - reservedWords.add("LOCATOR"); - reservedWords.add("LOCK"); - reservedWords.add("LOGIN"); - reservedWords.add("LOWER"); - reservedWords.add("M"); - reservedWords.add("MAP"); - reservedWords.add("MATCH"); - reservedWords.add("MATCHED"); - reservedWords.add("MAX"); - reservedWords.add("MAXVALUE"); - reservedWords.add("MEMBER"); - reservedWords.add("MERGE"); - reservedWords.add("MESSAGE_LENGTH"); - reservedWords.add("MESSAGE_OCTET_LENGTH"); - reservedWords.add("MESSAGE_TEXT"); - reservedWords.add("METHOD"); - reservedWords.add("MIN"); - reservedWords.add("MINUTE"); - reservedWords.add("MINVALUE"); - reservedWords.add("MOD"); - reservedWords.add("MODE"); - reservedWords.add("MODIFIES"); - reservedWords.add("MODIFY"); - reservedWords.add("MODULE"); - reservedWords.add("MONTH"); - reservedWords.add("MORE"); - reservedWords.add("MOVE"); - reservedWords.add("MULTISET"); - reservedWords.add("MUMPS"); - reservedWords.add("NAME"); - reservedWords.add("NAMES"); - reservedWords.add("NATIONAL"); - reservedWords.add("NATURAL"); - reservedWords.add("NCHAR"); - reservedWords.add("NCLOB"); - reservedWords.add("NESTING"); - reservedWords.add("NEW"); - reservedWords.add("NEXT"); - reservedWords.add("NO"); - reservedWords.add("NOCREATEDB"); - reservedWords.add("NOCREATEROLE"); - reservedWords.add("NOCREATEUSER"); - reservedWords.add("NOINHERIT"); - reservedWords.add("NOLOGIN"); - reservedWords.add("NONE"); - reservedWords.add("NORMALIZE"); - reservedWords.add("NORMALIZED"); - reservedWords.add("NOSUPERUSER"); - reservedWords.add("NOT"); - reservedWords.add("NOTHING"); - reservedWords.add("NOTIFY"); - reservedWords.add("NOTNULL"); - reservedWords.add("NOWAIT"); - reservedWords.add("NULL"); - reservedWords.add("NULLABLE"); - reservedWords.add("NULLIF"); - reservedWords.add("NULLS"); - reservedWords.add("NUMBER"); - reservedWords.add("NUMERIC"); - reservedWords.add("OBJECT"); - reservedWords.add("OCTETS"); - reservedWords.add("OCTET_LENGTH"); - reservedWords.add("OF"); - reservedWords.add("OFF"); - reservedWords.add("OFFSET"); - reservedWords.add("OIDS"); - reservedWords.add("OLD"); - reservedWords.add("ON"); - reservedWords.add("ONLY"); - reservedWords.add("OPEN"); - reservedWords.add("OPERATION"); - reservedWords.add("OPERATOR"); - reservedWords.add("OPTION"); - reservedWords.add("OPTIONS"); - reservedWords.add("OR"); - reservedWords.add("ORDER"); - reservedWords.add("ORDERING"); - reservedWords.add("ORDINALITY"); - reservedWords.add("OTHERS"); - reservedWords.add("OUT"); - reservedWords.add("OUTER"); - reservedWords.add("OUTPUT"); - reservedWords.add("OVER"); - reservedWords.add("OVERLAPS"); - reservedWords.add("OVERLAY"); - reservedWords.add("OVERRIDING"); - reservedWords.add("OWNER"); - reservedWords.add("PAD"); - reservedWords.add("PARAMETER"); - reservedWords.add("PARAMETERS"); - reservedWords.add("PARAMETER_MODE"); - reservedWords.add("PARAMETER_NAME"); - reservedWords.add("PARAMETER_ORDINAL_POSITION"); - reservedWords.add("PARAMETER_SPECIFIC_CATALOG"); - reservedWords.add("PARAMETER_SPECIFIC_NAME"); - reservedWords.add("PARAMETER_SPECIFIC_SCHEMA"); - reservedWords.add("PARTIAL"); - reservedWords.add("PARTITION"); - reservedWords.add("PASCAL"); - reservedWords.add("PASSWORD"); - reservedWords.add("PATH"); - reservedWords.add("PERCENTILE_CONT"); - reservedWords.add("PERCENTILE_DISC"); - reservedWords.add("PERCENT_RANK"); - reservedWords.add("PLACING"); - reservedWords.add("PLI"); - reservedWords.add("POSITION"); - reservedWords.add("POSTFIX"); - reservedWords.add("POWER"); - reservedWords.add("PRECEDING"); - reservedWords.add("PRECISION"); - reservedWords.add("PREFIX"); - reservedWords.add("PREORDER"); - reservedWords.add("PREPARE"); - reservedWords.add("PREPARED"); - reservedWords.add("PRESERVE"); - reservedWords.add("PRIMARY"); - reservedWords.add("PRIOR"); - reservedWords.add("PRIVILEGES"); - reservedWords.add("PROCEDURAL"); - reservedWords.add("PROCEDURE"); - reservedWords.add("PUBLIC"); - reservedWords.add("QUOTE"); - reservedWords.add("RANGE"); - reservedWords.add("RANK"); - reservedWords.add("READ"); - reservedWords.add("READS"); - reservedWords.add("REAL"); - reservedWords.add("RECHECK"); - reservedWords.add("RECURSIVE"); - reservedWords.add("REF"); - reservedWords.add("REFERENCES"); - reservedWords.add("REFERENCING"); - reservedWords.add("REGR_AVGX"); - reservedWords.add("REGR_AVGY"); - reservedWords.add("REGR_COUNT"); - reservedWords.add("REGR_INTERCEPT"); - reservedWords.add("REGR_R2"); - reservedWords.add("REGR_SLOPE"); - reservedWords.add("REGR_SXX"); - reservedWords.add("REGR_SXY"); - reservedWords.add("REGR_SYY"); - reservedWords.add("REINDEX"); - reservedWords.add("RELATIVE"); - reservedWords.add("RELEASE"); - reservedWords.add("RENAME"); - reservedWords.add("REPEATABLE"); - reservedWords.add("REPLACE"); - reservedWords.add("RESET"); - reservedWords.add("RESTART"); - reservedWords.add("RESTRICT"); - reservedWords.add("RESULT"); - reservedWords.add("RETURN"); - reservedWords.add("RETURNED_CARDINALITY"); - reservedWords.add("RETURNED_LENGTH"); - reservedWords.add("RETURNED_OCTET_LENGTH"); - reservedWords.add("RETURNED_SQLSTATE"); - reservedWords.add("RETURNS"); - reservedWords.add("REVOKE"); - reservedWords.add("RIGHT"); - reservedWords.add("ROLE"); - reservedWords.add("ROLLBACK"); - reservedWords.add("ROLLUP"); - reservedWords.add("ROUTINE"); - reservedWords.add("ROUTINE_CATALOG"); - reservedWords.add("ROUTINE_NAME"); - reservedWords.add("ROUTINE_SCHEMA"); - reservedWords.add("ROW"); - reservedWords.add("ROWS"); - reservedWords.add("ROW_COUNT"); - reservedWords.add("ROW_NUMBER"); - reservedWords.add("RULE"); - reservedWords.add("SAVEPOINT"); - reservedWords.add("SCALE"); - reservedWords.add("SCHEMA"); - reservedWords.add("SCHEMA_NAME"); - reservedWords.add("SCOPE"); - reservedWords.add("SCOPE_CATALOG"); - reservedWords.add("SCOPE_NAME"); - reservedWords.add("SCOPE_SCHEMA"); - reservedWords.add("SCROLL"); - reservedWords.add("SEARCH"); - reservedWords.add("SECOND"); - reservedWords.add("SECTION"); - reservedWords.add("SECURITY"); - reservedWords.add("SELECT"); - reservedWords.add("SELF"); - reservedWords.add("SENSITIVE"); - reservedWords.add("SEQUENCE"); - reservedWords.add("SERIALIZABLE"); - reservedWords.add("SERVER_NAME"); - reservedWords.add("SESSION"); - reservedWords.add("SESSION_USER"); - reservedWords.add("SET"); - reservedWords.add("SETOF"); - reservedWords.add("SETS"); - reservedWords.add("SHARE"); - reservedWords.add("SHOW"); - reservedWords.add("SIMILAR"); - reservedWords.add("SIMPLE"); - reservedWords.add("SIZE"); - reservedWords.add("SMALLINT"); - reservedWords.add("SOME"); - reservedWords.add("SOURCE"); - reservedWords.add("SPACE"); - reservedWords.add("SPECIFIC"); - reservedWords.add("SPECIFICTYPE"); - reservedWords.add("SPECIFIC_NAME"); - reservedWords.add("SQL"); - reservedWords.add("SQLCODE"); - reservedWords.add("SQLERROR"); - reservedWords.add("SQLEXCEPTION"); - reservedWords.add("SQLSTATE"); - reservedWords.add("SQLWARNING"); - reservedWords.add("SQRT"); - reservedWords.add("STABLE"); - reservedWords.add("START"); - reservedWords.add("STATE"); - reservedWords.add("STATEMENT"); - reservedWords.add("STATIC"); - reservedWords.add("STATISTICS"); - reservedWords.add("STDDEV_POP"); - reservedWords.add("STDDEV_SAMP"); - reservedWords.add("STDIN"); - reservedWords.add("STDOUT"); - reservedWords.add("STORAGE"); - reservedWords.add("STRICT"); - reservedWords.add("STRUCTURE"); - reservedWords.add("STYLE"); - reservedWords.add("SUBCLASS_ORIGIN"); - reservedWords.add("SUBLIST"); - reservedWords.add("SUBMULTISET"); - reservedWords.add("SUBSTRING"); - reservedWords.add("SUM"); - reservedWords.add("SUPERUSER"); - reservedWords.add("SYMMETRIC"); - reservedWords.add("SYSID"); - reservedWords.add("SYSTEM"); - reservedWords.add("SYSTEM_USER"); - reservedWords.add("TABLE"); - reservedWords.add("TABLESAMPLE"); - reservedWords.add("TABLESPACE"); - reservedWords.add("TABLE_NAME"); - reservedWords.add("TEMP"); - reservedWords.add("TEMPLATE"); - reservedWords.add("TEMPORARY"); - reservedWords.add("TERMINATE"); - reservedWords.add("THAN"); - reservedWords.add("THEN"); - reservedWords.add("TIES"); - reservedWords.add("TIME"); - reservedWords.add("TIMESTAMP"); - reservedWords.add("TIMEZONE_HOUR"); - reservedWords.add("TIMEZONE_MINUTE"); - reservedWords.add("TO"); - reservedWords.add("TOAST"); - reservedWords.add("TOP_LEVEL_COUNT"); - reservedWords.add("TRAILING"); - reservedWords.add("TRANSACTION"); - reservedWords.add("TRANSACTIONS_COMMITTED"); - reservedWords.add("TRANSACTIONS_ROLLED_BACK"); - reservedWords.add("TRANSACTION_ACTIVE"); - reservedWords.add("TRANSFORM"); - reservedWords.add("TRANSFORMS"); - reservedWords.add("TRANSLATE"); - reservedWords.add("TRANSLATION"); - reservedWords.add("TREAT"); - reservedWords.add("TRIGGER"); - reservedWords.add("TRIGGER_CATALOG"); - reservedWords.add("TRIGGER_NAME"); - reservedWords.add("TRIGGER_SCHEMA"); - reservedWords.add("TRIM"); - reservedWords.add("TRUE"); - reservedWords.add("TRUNCATE"); - reservedWords.add("TRUSTED"); - reservedWords.add("TYPE"); - reservedWords.add("UESCAPE"); - reservedWords.add("UNBOUNDED"); - reservedWords.add("UNCOMMITTED"); - reservedWords.add("UNDER"); - reservedWords.add("UNENCRYPTED"); - reservedWords.add("UNION"); - reservedWords.add("UNIQUE"); - reservedWords.add("UNKNOWN"); - reservedWords.add("UNLISTEN"); - reservedWords.add("UNNAMED"); - reservedWords.add("UNNEST"); - reservedWords.add("UNTIL"); - reservedWords.add("UPDATE"); - reservedWords.add("UPPER"); - reservedWords.add("USAGE"); - reservedWords.add("USER"); - reservedWords.add("USER_DEFINED_TYPE_CATALOG"); - reservedWords.add("USER_DEFINED_TYPE_CODE"); - reservedWords.add("USER_DEFINED_TYPE_NAME"); - reservedWords.add("USER_DEFINED_TYPE_SCHEMA"); - reservedWords.add("USING"); - reservedWords.add("VACUUM"); - reservedWords.add("VALID"); - reservedWords.add("VALIDATOR"); - reservedWords.add("VALUE"); - reservedWords.add("VALUES"); - reservedWords.add("VARCHAR"); - reservedWords.add("VARIABLE"); - reservedWords.add("VARYING"); - reservedWords.add("VAR_POP"); - reservedWords.add("VAR_SAMP"); - reservedWords.add("VERBOSE"); - reservedWords.add("VIEW"); - reservedWords.add("VOLATILE"); - reservedWords.add("WHEN"); - reservedWords.add("WHENEVER"); - reservedWords.add("WHERE"); - reservedWords.add("WIDTH_BUCKET"); - reservedWords.add("WINDOW"); - reservedWords.add("WITH"); - reservedWords.add("WITHIN"); - reservedWords.add("WITHOUT"); - reservedWords.add("WORK"); - reservedWords.add("WRITE"); - reservedWords.add("YEAR"); - reservedWords.add("ZONE"); - } -} +package ru.fusionsoft.dbgit.postgres; + + +import java.sql.*; +import java.text.MessageFormat; +import java.time.Period; +import java.util.*; +import java.util.concurrent.TimeUnit; + +import com.diogonunes.jcdp.color.api.Ansi; +import com.google.common.collect.ImmutableMap; +import java.util.stream.Collectors; +import org.apache.commons.lang3.exception.ExceptionUtils; +import ru.fusionsoft.dbgit.adapters.*; +import ru.fusionsoft.dbgit.core.*; +import ru.fusionsoft.dbgit.core.db.DbType; +import ru.fusionsoft.dbgit.core.db.FieldType; +import ru.fusionsoft.dbgit.dbobjects.*; +import ru.fusionsoft.dbgit.meta.IMapMetaObject; +import ru.fusionsoft.dbgit.meta.IMetaObject; +import ru.fusionsoft.dbgit.meta.TreeMapMetaObject; +import ru.fusionsoft.dbgit.statement.StatementLogging; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; +import ru.fusionsoft.dbgit.utils.LoggerUtil; +import org.slf4j.Logger; + +import com.axiomalaska.jdbc.NamedParameterPreparedStatement; +import ru.fusionsoft.dbgit.utils.StringProperties; + + +public class DBAdapterPostgres extends DBAdapter { + private final Logger logger = LoggerUtil.getLogger(this.getClass()); + private final FactoryDBAdapterRestorePostgres restoreFactory = new FactoryDBAdapterRestorePostgres(); + private final FactoryDbConvertAdapterPostgres convertFactory = new FactoryDbConvertAdapterPostgres(); + private final FactoryDBBackupAdapterPostgres backupFactory = new FactoryDBBackupAdapterPostgres(); + private final static Set reservedWords = new HashSet<>(); + + @Override + public IFactoryDBAdapterRestoteMetaData getFactoryRestore() { + return restoreFactory; + } + + @Override + public void startUpdateDB() { + // TODO Auto-generated method stub + + } + + @Override + public void endUpdateDB() { + // TODO Auto-generated method stub + + } + + @Override + public IMapMetaObject loadCustomMetaObjects() { + return new TreeMapMetaObject(Collections.emptyList()); + } + + @Override + public Map getSchemes() { + final Map listScheme = new HashMap(); + final String query = + "select nspname,usename,nspacl from pg_namespace,pg_user where nspname!='pg_toast' and nspname!='pg_temp_1'"+ + "and nspname!='pg_toast_temp_1' and nspname!='pg_catalog'"+ + "and nspname!='information_schema' and nspname!='pgagent'"+ + "and nspname!='pg_temp_3' and nspname!='pg_toast_temp_3'"+ + "and usesysid = nspowner"; + + try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);){ + + while(rs.next()){ + final String name = rs.getString("nspname"); + final DBSchema scheme = new DBSchema(name, new StringProperties(rs)); + listScheme.put(name, scheme); + } + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "schemes").toString(); + throw new ExceptionDBGitRunTime(msg, e); + } + + return listScheme; + + } + + @Override + public Map getTableSpaces() { + final Map listTableSpace = new HashMap(); + final String query = + "SELECT tblspaces.spcname,tblspaces.spcacl,tblspaces.spcoptions,users.usename,pg_tablespace_location(tblspacesoid.oid) " + + "FROM pg_tablespace as tblspaces,pg_user as users,(Select oid FROM pg_tablespace where spcname!='pg_default' and spcname!='pg_global') as tblspacesoid " + + "WHERE users.usesysid=tblspaces.spcowner and spcname!='pg_default' and spcname!='pg_global' and tblspacesoid.oid=tblspaces.oid"; + + try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);){ + + while(rs.next()){ + final String name = rs.getString("spcname"); + final DBTableSpace dbTableSpace = new DBTableSpace(name, new StringProperties(rs)); + listTableSpace.put(name, dbTableSpace); + } + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "tablespace").toString(); + throw new ExceptionDBGitRunTime(msg, e); + } + return listTableSpace; + } + + @Override + public Map getSequences(String schema) { + final Map listSequence = new HashMap<>(); + final String query = MessageFormat.format( + "select s.sequence_name, rol.rolname as owner, s.start_value, s.minimum_value, s.maximum_value, s.increment, s.cycle_option, cl.relname as blocking_table \n" + + "from pg_class cls \n" + + " join pg_roles rol on rol.oid = cls.relowner \n" + + " join pg_namespace nsp on nsp.oid = cls.relnamespace \n" + + " join information_schema.sequences s on cls.relname = s.sequence_name \n" + + " left join pg_depend d on d.objid=cls.oid and d.classid=''pg_class''::regclass and d.refclassid=''pg_class''::regclass\n" + + " left join pg_class cl on cl.oid = d.refobjid and d.deptype=''a'' \n" + + "where nsp.nspname not in (''information_schema'', ''pg_catalog'')\n" + + " and nsp.nspname not like ''pg_toast%'' \n" + + " and cls.relkind = ''S'' and s.sequence_schema = ''{0}''", + schema + ); + + try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);) { + + while(rs.next()){ + final String nameSeq = rs.getString("sequence_name"); + final String ownerSeq = rs.getString("blocking_table"); + final Long valueSeq = 0L; + //TODO find actual value + + final DBSequence sequence = new DBSequence(nameSeq, new StringProperties(rs), schema, ownerSeq, Collections.emptySet(), valueSeq); + listSequence.put(nameSeq, sequence); + } + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "sequence").toString(); + throw new ExceptionDBGitRunTime(msg, e); + } + + return listSequence; + } + + @Override + public DBSequence getSequence(String schema, String name) { + + final String query = + "select s.sequence_name, rol.rolname as owner, s.start_value, s.minimum_value, s.maximum_value, s.increment, s.cycle_option, cl.relname as blocking_table \n" + + "from pg_class cls \n" + + " join pg_roles rol on rol.oid = cls.relowner \n" + + " join pg_namespace nsp on nsp.oid = cls.relnamespace \n" + + " join information_schema.sequences s on cls.relname = s.sequence_name \n" + + " left join pg_depend d on d.objid=cls.oid and d.classid='pg_class'::regclass and d.refclassid='pg_class'::regclass\n" + + " left join pg_class cl on cl.oid = d.refobjid and d.deptype='a' \n" + + "where nsp.nspname not in ('information_schema', 'pg_catalog') \n" + + " and nsp.nspname not like 'pg_toast%' \n" + + " and cls.relkind = 'S' and s.sequence_schema = :schema and s.sequence_name = :name "; + + try ( + PreparedStatement stmt = preparedStatement(getConnection(), query, ImmutableMap.of("schema", schema, "name", name)); + ResultSet rs = stmt.executeQuery(); + ) { + if (rs.next()) { + //TODO find actual value + final Long valueSeq = 0L; + final String nameSeq = rs.getString("sequence_name"); + final String ownerSeq = rs.getString("blocking_table"); + return new DBSequence(nameSeq, new StringProperties(rs), schema, ownerSeq, Collections.emptySet(), valueSeq); + + } else { + final String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); + throw new ExceptionDBGitObjectNotFound(msg); + } + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "sequence").toString(); + throw new ExceptionDBGitRunTime(msg, e); + } + } + + @Override + public Map getTables(String schema) { + final Map listTable = new HashMap(); + final String query = + "SELECT \n" + + " tablename AS table_name,\n" + + " tableowner AS owner,\n" + + " tablespace, hasindexes, hasrules, hastriggers, \n" + + " obj_description( " + + " (('\"' || schemaname || '\".\"' || tablename || '\"')::regclass)::oid" + + " ) AS table_comment,\n" + + " (\n" + + " SELECT array_agg( distinct n2.nspname || '/' || c2.relname || '.tbl' ) AS dependencies\n" + + " FROM pg_catalog.pg_constraint c \n" + + " JOIN ONLY pg_catalog.pg_class c1 ON c1.oid = c.conrelid\n" + + " JOIN ONLY pg_catalog.pg_class c2 ON c2.oid = c.confrelid\n" + + " JOIN ONLY pg_catalog.pg_namespace n2 ON n2.oid = c2.relnamespace\n" + + " WHERE c.conrelid = (('\"' || schemaname || '\".\"' || tablename || '\"')::regclass)::oid\n" + + " and c1.relkind = 'r' AND c.contype = 'f'\n" + + " ) " + + " AS dependencies, \n" + + ( (getDbVersionNumber() >= 10) + ? " pg_get_partkeydef((\n" + + " SELECT oid \n" + + " FROM pg_class \n" + + " WHERE relname = tablename \n" + + " AND relnamespace = (select oid from pg_namespace where nspname = :schema )\n" + + " )) \n" + + " AS partkeydef, \n" + + " pg_get_expr(child.relpartbound, child.oid) " + + " AS pg_get_expr, \n" + : " " + ) + + " parent.relname AS parent \n" + + "FROM pg_tables \n" + + "LEFT OUTER JOIN pg_inherits on (SELECT oid FROM pg_class WHERE relname = tablename and relnamespace = (select oid from pg_namespace where nspname = :schema)) = pg_inherits.inhrelid \n" + + "LEFT OUTER JOIN pg_class parent ON pg_inherits.inhparent = parent.oid \n" + + "LEFT OUTER JOIN pg_class child ON pg_inherits.inhrelid = child.oid \n" + + "WHERE upper(schemaname) = upper(:schema)"; + + try ( + PreparedStatement stmt = preparedStatement(getConnection(), query, ImmutableMap.of("schema", schema)); + ResultSet rs = stmt.executeQuery(); + ) { + + + while(rs.next()){ + final String nameTable = rs.getString("table_name"); + final String ownerTable = rs.getString("owner"); + final String commentTable = rs.getString("table_comment"); + final Set dependencies = rs.getArray("dependencies") != null + ? new HashSet<>(Arrays.asList((String[])rs.getArray("dependencies").getArray())) + : Collections.emptySet(); + + if (rs.getString("parent") != null) { + dependencies.add(schema + "/" + rs.getString("parent") + ".tbl"); + } + + final DBTable table = new DBTable(nameTable, new StringProperties(rs), schema, ownerTable, dependencies, commentTable); + listTable.put(nameTable, table); + } + } catch (Exception e) { + final String msg = lang.getValue("errors", "adapter", "tables").toString(); + throw new ExceptionDBGitRunTime(msg, e); + } + return listTable; + } + + @Override + public DBTable getTable(String schema, String name) { + final String query = + "SELECT \n" + + " tablename AS table_name,\n" + + " tableowner AS owner,\n" + + " tablespace, hasindexes, hasrules, hastriggers, \n" + + " obj_description((('\"' || schemaname || '\".\"' || tablename || '\"')::regclass)::oid) AS table_comment,\n" + + " (\n" + + " SELECT array_agg( distinct n2.nspname || '/' || c2.relname || '.tbl' ) AS dependencies\n" + + " FROM pg_catalog.pg_constraint c \n" + + " JOIN ONLY pg_catalog.pg_class c1 ON c1.oid = c.conrelid\n" + + " JOIN ONLY pg_catalog.pg_class c2 ON c2.oid = c.confrelid\n" + + " JOIN ONLY pg_catalog.pg_namespace n2 ON n2.oid = c2.relnamespace\n" + + " WHERE c.conrelid = (('\"' || schemaname || '\".\"' || tablename || '\"')::regclass)::oid\n" + + " and c1.relkind = 'r' AND c.contype = 'f'\n" + + " ) " + + " AS dependencies, \n" + + ( (getDbVersionNumber() >= 10) + ? " pg_get_partkeydef((\n" + + " SELECT oid \n" + + " FROM pg_class \n" + + " WHERE relname = tablename \n" + + " AND relnamespace = (select oid from pg_namespace where nspname = :schema )\n" + + " )) \n" + + " AS partkeydef, \n" + + " pg_get_expr(child.relpartbound, child.oid) " + + " AS pg_get_expr, \n" + : " " + ) + + " parent.relname AS parent \n" + + "FROM pg_tables \n" + + "LEFT OUTER JOIN pg_inherits on (SELECT oid FROM pg_class WHERE relname = tablename and relnamespace = (select oid from pg_namespace where nspname = :schema)) = pg_inherits.inhrelid \n" + + "LEFT OUTER JOIN pg_class parent ON pg_inherits.inhparent = parent.oid \n" + + "LEFT OUTER JOIN pg_class child ON pg_inherits.inhrelid = child.oid \n" + + "WHERE upper(schemaname) = upper(:schema)" + + "AND tablename = :name"; + try ( + PreparedStatement stmt = preparedStatement(getConnection(), query, ImmutableMap.of("schema", schema, "name", name)); + ResultSet rs = stmt.executeQuery(); + ) { + + if (rs.next()) { + final String nameTable = rs.getString("table_name"); + final String ownerTable = rs.getString("owner"); + final String commentTable = rs.getString("table_comment"); + final Set dependencies = rs.getArray("dependencies") != null + ? new HashSet<>(Arrays.asList((String[])rs.getArray("dependencies").getArray())) + : Collections.emptySet(); + + if (rs.getString("parent") != null) { + dependencies.add(schema + "/" + rs.getString("parent") + ".tbl"); + } + + return new DBTable(nameTable, new StringProperties(rs), schema, ownerTable, dependencies, commentTable); + + } else { + final String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); + throw new ExceptionDBGitObjectNotFound(msg); + } + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "tables").toString(); + throw new ExceptionDBGitRunTime(msg, e); + } + } + + @Override + public Map getTableFields(String schema, String nameTable) { + Map listField = new HashMap(); + String query = + "SELECT distinct col.column_name,col.is_nullable,col.data_type, col.udt_name::regtype dtype,col.character_maximum_length, col.column_default, tc.constraint_name, " + + "case\r\n" + + " when lower(data_type) in ('integer', 'numeric', 'smallint', 'double precision', 'bigint') then 'number' \r\n" + + " when lower(data_type) in ('character varying', 'char', 'character', 'varchar') then 'string'\r\n" + + " when lower(data_type) in ('timestamp without time zone', 'timestamp with time zone', 'date') then 'date'\r\n" + + " when lower(data_type) in ('boolean') then 'boolean'\r\n" + + " when lower(data_type) in ('text') then 'text'\r\n" + + " when lower(data_type) in ('bytea') then 'binary'" + + " else 'native'\r\n" + + " end tp, " + + " case when lower(data_type) in ('char', 'character') then true else false end fixed, " + + " pgd.description," + + "col.* FROM " + + "information_schema.columns col " + + "left join information_schema.key_column_usage kc on col.table_schema = kc.table_schema and col.table_name = kc.table_name and col.column_name=kc.column_name " + + "left join information_schema.table_constraints tc on col.table_schema = kc.table_schema and col.table_name = kc.table_name and kc.constraint_name = tc.constraint_name and tc.constraint_type = 'PRIMARY KEY' " + + "left join pg_catalog.pg_statio_all_tables st on st.schemaname = col.table_schema and st.relname = col.table_name " + + "left join pg_catalog.pg_description pgd on (pgd.objoid=st.relid and pgd.objsubid=col.ordinal_position) " + + "where upper(col.table_schema) = upper(:schema) and col.table_name = :table " + + "order by col.column_name "; + + try ( + PreparedStatement stmt = preparedStatement(getConnection(), query, ImmutableMap.of("schema", schema, "table", nameTable)); + ResultSet rs = stmt.executeQuery(); + ) { + + + while(rs.next()){ + final String typeSQL = getFieldType(rs); + final String nameField = rs.getString("column_name"); + final String descField = rs.getString("description"); + final String columnDefault = rs.getString("column_default"); + final boolean isFixed = rs.getBoolean("fixed"); + final boolean isPrimaryKey = rs.getString("constraint_name") != null; + final boolean isNullable = !typeSQL.toLowerCase().contains("not null"); + final FieldType typeUniversal = FieldType.fromString(rs.getString("tp")); +// System.out.println(( +// nameField +// + " > " +// + typeSQL +// + " (" +// + typeUniversal.toString() +// + ")" +// )); + final FieldType actualTypeUniversal = typeUniversal.equals(FieldType.TEXT) ? FieldType.STRING_NATIVE : typeUniversal; + final int length = rs.getInt("character_maximum_length"); + final int precision = rs.getInt("numeric_precision"); + final int scale = rs.getInt("numeric_scale"); + final int ordinalPosition = rs.getInt("ordinal_position"); + + + final DBTableField field = new DBTableField( + nameField, descField, isPrimaryKey, isNullable, + typeSQL, actualTypeUniversal, ordinalPosition, columnDefault, + length, scale, precision, isFixed + ); + + listField.put(nameField, field); + } + + + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "tableData").toString(); + throw new ExceptionDBGitRunTime(msg, e); + } + + return listField; + } + + private String getFieldType(ResultSet rs) { + try { + final StringBuilder type = new StringBuilder(); + type.append(rs.getString("dtype")); + + Integer max_length = rs.getInt("character_maximum_length"); + if (!rs.wasNull()) { + type.append("("+max_length.toString()+")"); + } + if (rs.getString("is_nullable").equals("NO")){ + type.append(" NOT NULL"); + } + + return type.toString(); + } catch(Exception e) { + final String msg = lang.getValue("errors", "adapter", "tables").toString(); + throw new ExceptionDBGitRunTime(msg, e); + } + } + + @Override + public Map getIndexes(String schema, String nameTable) { + final Map indexes = new HashMap<>(); + final String query = + "SELECT " + + " i.schemaname,\r\n" + + " i.tablename, \r\n" + + " i.indexname, \r\n" + + " i.tablespace, \r\n" + + " i.indexdef AS ddl, \r\n" + + " t.tableowner AS owner \r\n" + + "FROM pg_indexes AS i " + + "JOIN pg_class AS cl ON i.indexname = cl.relname\r\n" + + "JOIN pg_index AS idx ON cl.oid = idx.indexrelid\r\n" + + "JOIN pg_tables AS t ON i.schemaname = t.schemaname AND i.tablename = t.tablename\r\n" + + "WHERE i.tablename not like 'pg%' " + + "AND i.schemaname = :schema " + + "AND i.tablename = :table and idx.indisprimary = false " + + "-- AND idx.indisunique=false "; + + try ( + PreparedStatement stmt = preparedStatement(getConnection(), query, ImmutableMap.of("schema", schema, "table", nameTable)); + ResultSet rs = stmt.executeQuery(); + ){ + + while(rs.next()){ + final String name = rs.getString("indexname"); + final String owner = rs.getString("owner"); + final String ddl = rs.getString("ddl"); + + final DBIndex index = new DBIndex(name, new StringProperties(rs), schema, owner, Collections.emptySet(), ddl); + indexes.put(name, index); + } + + return indexes; + + } catch(Exception e) { + String msg = lang.getValue("errors", "adapter", "indexes").toString(); + throw new ExceptionDBGitRunTime(msg, e); + } + + } + + @Override + public Map getConstraints(String schema, String nameTable) { + final Map constraints = new HashMap<>(); + /* + String query = "select conname as constraint_name,contype as constraint_type, " + + " pg_catalog.pg_get_constraintdef(r.oid, true) as ddl " + + "from " + + " pg_class c " + + " join pg_namespace n on n.oid = c.relnamespace " + + " join pg_catalog.pg_constraint r on r.conrelid = c.relfilenode " + + "WHERE " + + " relname = :table and nspname = :schema and c.relkind = 'r'"; + */ + + final String query = + "SELECT " + + " t.tableowner as owner," + + " conname as constraint_name," + + " contype as constraint_type, \r\n" + + " pg_catalog.pg_get_constraintdef(con.oid, true) as ddl\r\n" + + "FROM pg_catalog.pg_constraint con\r\n" + + "INNER JOIN pg_catalog.pg_class rel ON rel.oid = con.conrelid\r\n" + + "INNER JOIN pg_catalog.pg_namespace nsp ON nsp.oid = connamespace\r\n" + + "INNER JOIN pg_tables t ON nsp.nspname = t.schemaname AND rel.relname = t.tablename\r\n" + + "WHERE nsp.nspname = :schema\r\n" + + "AND rel.relname = :table"; + + try ( + PreparedStatement stmt = preparedStatement(getConnection(), query, ImmutableMap.of("schema", schema, "table", nameTable)); + ResultSet rs = stmt.executeQuery(); + ){ + + while(rs.next()){ + final String name = rs.getString("constraint_name"); + final String type = rs.getString("constraint_type"); + final String owner = rs.getString("owner"); + final String ddl = rs.getString("ddl"); + final StringProperties options = new StringProperties(rs); + final DBConstraint con = new DBConstraint(name, options, schema, owner, Collections.emptySet(), ddl, type); + + constraints.put(con.getName(), con); + } + + return constraints; + + } catch(Exception e) { + String msg = lang.getValue("errors", "adapter", "constraints").toString(); + throw new ExceptionDBGitRunTime(msg, e); + } + } + + @Override + public Map getViews(String schema) { + final Map listView = new HashMap(); + final String query = + "select nsp.nspname as object_schema, cls.relname as object_name, rol.rolname as owner, \n" + + "'create or replace view ' || nsp.nspname || '.' || cls.relname || ' as ' || pg_get_viewdef(cls.oid) as ddl, (\n" + + " select array_agg(distinct source_ns.nspname || '/' || source_table.relname || '.vw') as dependencySam\n" + + " from pg_depend \n" + + " join pg_rewrite ON pg_depend.objid = pg_rewrite.oid \n" + + " join pg_class as dependent_view ON pg_rewrite.ev_class = dependent_view.oid \n" + + " join pg_class as source_table ON pg_depend.refobjid = source_table.oid AND source_table.relkind = 'v'\n" + + " join pg_attribute ON pg_attribute.attrelid = pg_depend.refobjid \n" + + " and pg_attribute.attnum = pg_depend.refobjsubid \n" + + " join pg_namespace dependent_ns ON dependent_ns.oid = dependent_view.relnamespace\n" + + " join pg_namespace source_ns ON source_ns.oid = source_table.relnamespace\n" + + " where pg_attribute.attnum > 0 \n" + + " and dependent_view.relname = cls.relname\n" + + ") as dependencies\n" + + "from pg_class cls \n" + + "join pg_roles rol on rol.oid = cls.relowner \n" + + "join pg_namespace nsp on nsp.oid = cls.relnamespace \n" + + "where nsp.nspname not in ('information_schema', 'pg_catalog') \n" + + "and cls.relname not in ('pg_buffercache', 'pg_stat_statements') \n" + + "and nsp.nspname not like 'pg_toast%' \n" + + "and cls.relkind = 'v' \n" + + "and nsp.nspname = '"+schema+"' \n"; + + try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);){ + + while(rs.next()){ + final String objectName = rs.getString("object_name"); + final String objectSchema = rs.getString("object_schema"); + final String owner = rs.getString("owner"); + final String ddl = rs.getString("ddl"); + final StringProperties options = new StringProperties(rs); + final Set dependencies = rs.getArray("dependencies") == null + ? Collections.emptySet() + : new HashSet<>(Arrays.asList((String[])rs.getArray("dependencies").getArray())); + + DBView view = new DBView(objectName, options, objectSchema, owner, dependencies, ddl); + listView.put(rs.getString("object_name"), view); + } + + } catch (Exception e) { + final DBGitLang msg = lang.getValue("errors", "adapter", "views"); + throw new ExceptionDBGitRunTime(msg, e); + } + + return listView; + } + + @Override + public DBView getView(String schema, String name) { + + String query = + "select nsp.nspname as object_schema, cls.relname as object_name, rol.rolname as owner, \n" + + "'create or replace view ' || nsp.nspname || '.' || cls.relname || ' as ' || pg_get_viewdef(cls.oid) as ddl, (\n" + + " select array_agg(distinct source_ns.nspname || '/' || source_table.relname || '.vw') as dependencySam\n" + + " from pg_depend \n" + + " join pg_rewrite ON pg_depend.objid = pg_rewrite.oid \n" + + " join pg_class as dependent_view ON pg_rewrite.ev_class = dependent_view.oid \n" + + " join pg_class as source_table ON pg_depend.refobjid = source_table.oid AND source_table.relkind = 'v'\n" + + " join pg_attribute ON pg_attribute.attrelid = pg_depend.refobjid \n" + + " and pg_attribute.attnum = pg_depend.refobjsubid \n" + + " join pg_namespace dependent_ns ON dependent_ns.oid = dependent_view.relnamespace\n" + + " join pg_namespace source_ns ON source_ns.oid = source_table.relnamespace\n" + + " where pg_attribute.attnum > 0 \n" + + " and dependent_view.relname = cls.relname\n" + + ") as dependencies\n" + + "from pg_class cls \n" + + "join pg_roles rol on rol.oid = cls.relowner \n" + + "join pg_namespace nsp on nsp.oid = cls.relnamespace \n" + + "where nsp.nspname not in ('information_schema', 'pg_catalog') \n" + + "and nsp.nspname not like 'pg_toast%' \n" + + "and cls.relkind = 'v' \n" + + "and nsp.nspname = '"+schema+"' \n" + + "and cls.relname='"+name+"'\n"; + + + + + try(Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);){ + + if (rs.next()) { + String owner = rs.getString("owner"); + String ddl = rs.getString("ddl"); + StringProperties options = new StringProperties(rs); + Set dependencies = rs.getArray("dependencies") == null + ? Collections.emptySet() + : new HashSet<>(Arrays.asList((String[])rs.getArray("dependencies").getArray())); + + return new DBView(name, options, schema, owner, dependencies, ddl); + + } else { + String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); + throw new ExceptionDBGitObjectNotFound(msg); + } + + } catch(Exception e) { + DBGitLang msg = lang.getValue("errors", "adapter", "views"); + throw new ExceptionDBGitRunTime(msg, e); + } + } + + @Override + public Map getTriggers(String schema) { + Map listTrigger = new HashMap(); + String query = + "SELECT trg.tgname, tbl.relname as trigger_table ,pg_get_triggerdef(trg.oid) AS ddl \r\n" + + "FROM pg_trigger trg\r\n" + + "JOIN pg_class tbl on trg.tgrelid = tbl.oid\r\n" + + "JOIN pg_namespace ns ON ns.oid = tbl.relnamespace\r\n" + + "and trg.tgconstraint=0 and ns.nspname like \'"+schema+"\'"; + + try ( + Statement stmt = getConnection().createStatement(); + ResultSet rs = stmt.executeQuery(query); + ) { + + while(rs.next()){ + String name = rs.getString("tgname"); + String owner = "postgres"; + String sql = rs.getString("ddl"); + StringProperties options = new StringProperties(rs); + Set dependencies = Collections.emptySet(); +// rs.getArray("dependencies") == null +// ? Collections.emptySet() +// : new HashSet<>(Arrays.asList((String[])rs.getArray("dependencies").getArray())); + + DBTrigger trigger = new DBTrigger(name, options, schema, owner, dependencies, sql); + listTrigger.put(name, trigger); + } + + }catch(Exception e) { + throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "triggers").toString(), e); + } + + return listTrigger; + } + @Override + public DBTrigger getTrigger(String schema, String name) { + String query = + "SELECT trg.tgname, tbl.relname as trigger_table ,pg_get_triggerdef(trg.oid) AS ddl \r\n" + + "FROM pg_trigger trg\r\n" + + "JOIN pg_class tbl on trg.tgrelid = tbl.oid\r\n" + + "JOIN pg_namespace ns ON ns.oid = tbl.relnamespace\r\n" + + "AND trg.tgconstraint=0 and ns.nspname like \'"+schema+"\' and trg.tgname like \'"+name+"\'"; + + try (Statement stmt = getConnection().createStatement();ResultSet rs = stmt.executeQuery(query);){ + + if(rs.next()){ + String sql = rs.getString("ddl"); + String owner = "postgres"; + + StringProperties options = new StringProperties(rs); + Set dependencies = rs.getArray("dependencies") == null + ? Collections.emptySet() + : new HashSet<>(Arrays.asList((String[])rs.getArray("dependencies").getArray())); + + return new DBTrigger(name, options, schema, owner, dependencies, sql); + + } else { + String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); + throw new ExceptionDBGitObjectNotFound(msg); + } + + } catch(Exception e) { + throw new ExceptionDBGitRunTime(lang.getValue("errors", "adapter", "triggers").toString(), e); + } + + } + @Override + public Map getPackages(String schema) { + return Collections.emptyMap(); + } + + @Override + public DBPackage getPackage(String schema, String name) { + throw new ExceptionDBGitRunTime(new ExceptionDBGitObjectNotFound("cannot get packages on postgres")); + + } + + @Override + public Map getProcedures(String schema) { + Map mapProcs = new HashMap<>(); + String query = + "SELECT n.nspname AS \"schema\", u.rolname, p.proname AS \"name\", \n" + + " pg_catalog.pg_get_function_arguments(p.oid) AS \"arguments\",\n" + + " pg_get_functiondef(p.oid) AS ddl\n" + + "FROM pg_catalog.pg_proc p\n" + + " JOIN pg_catalog.pg_roles u ON u.oid = p.proowner\n" + + " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace\n" + + ( (getDbVersionNumber() >= 10) + ? "WHERE p.prokind = 'p' \n" + : "WHERE 1=0 \n" + ) + + " AND n.nspname not in('pg_catalog', 'information_schema')\n" + + " AND n.nspname = '"+schema+"'"; + + try (Statement stmt = getConnection().createStatement();ResultSet rs = stmt.executeQuery(query);){ + + while(rs.next()){ + String name = rs.getString("name"); + String owner = rs.getString("rolname"); + String sql = rs.getString("ddl"); + StringProperties options = new StringProperties(rs); + Set dependencies = rs.getArray("dependencies") == null + ? Collections.emptySet() + : new HashSet<>(Arrays.asList((String[])rs.getArray("dependencies").getArray())); + + DBProcedure proc = new DBProcedure(name, options, schema, owner, dependencies, sql); + + String nameInMap = mapProcs.containsKey(name) ? name + "_" + proc.getHash() : name; + mapProcs.put(nameInMap, proc); + } + + } catch(Exception e) { + String msg = lang.getValue("errors", "adapter", "prc").toString(); + throw new ExceptionDBGitRunTime(msg, e); + } + + return mapProcs; + } + + @Override + public DBProcedure getProcedure(String schema, String name) { + String query = + "SELECT n.nspname AS \"schema\", u.rolname, p.proname AS \"name\", \n" + + " pg_catalog.pg_get_function_arguments(p.oid) AS \"arguments\",\n" + + " pg_get_functiondef(p.oid) AS ddl\n" + + "FROM pg_catalog.pg_proc p\n" + + " JOIN pg_catalog.pg_roles u ON u.oid = p.proowner\n" + + " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace\n" + + ( (getDbVersionNumber() >= 10) + ? "WHERE p.prokind = 'p' \n" + : "WHERE 1=0 \n" + ) + + " AND n.nspname not in('pg_catalog', 'information_schema')\n" + + " AND n.nspname = '"+schema+"'" + + " AND p.proname = '"+name+"'"; + + try (Statement stmt = getConnection().createStatement();ResultSet rs = stmt.executeQuery(query);){ + + if(rs.next()){ + String owner = rs.getString("rolname"); + String sql = rs.getString("ddl"); + StringProperties options = new StringProperties(rs); + Set dependencies = rs.getArray("dependencies") == null + ? Collections.emptySet() + : new HashSet<>(Arrays.asList((String[])rs.getArray("dependencies").getArray())); + + return new DBProcedure(name, options, schema, owner, dependencies, sql); + + } else { + String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); + throw new ExceptionDBGitObjectNotFound(msg); + } + } catch(Exception e) { + String msg = lang.getValue("errors", "adapter", "prc").toString(); + throw new ExceptionDBGitRunTime(msg, e); + } + } + + @Override + public Map getFunctions(String schema) { + Map listFunction = new HashMap(); + String query = + "SELECT n.nspname AS \"schema\", u.rolname, p.proname AS \"name\", \n" + + " pg_catalog.pg_get_function_arguments(p.oid) AS \"arguments\",\n" + + " pg_get_functiondef(p.oid) AS ddl\n" + + "FROM pg_catalog.pg_proc p\n" + + " JOIN pg_catalog.pg_roles u ON u.oid = p.proowner\n" + + " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace\n" + + ( (getDbVersionNumber() >= 10) + ? "WHERE p.prokind = 'f' \n" + : "WHERE p.proisagg is false " + )+ + "AND n.nspname not in('pg_catalog', 'information_schema')\n" + + "AND n.nspname = '"+schema+"'"; + + try (Statement stmt = getConnection().createStatement();ResultSet rs = stmt.executeQuery(query);){ + + while(rs.next()){ + String name = rs.getString("name"); + String owner = rs.getString("rolname"); + String sql = rs.getString("ddl"); + StringProperties options = new StringProperties(rs); + Set dependencies = Collections.emptySet(); +// rs.getArray("dependencies") == null +// ? Collections.emptySet() +// : new HashSet<>(Arrays.asList((String[])rs.getArray("dependencies").getArray())); + + DBFunction dbFunction = new DBFunction(name, options, schema, owner, dependencies, sql); + + String nameInMap = listFunction.containsKey(name) ? name + "_" + dbFunction.getHash() : name; + listFunction.put(nameInMap, dbFunction); + } + + }catch(Exception e) { + String msg = lang.getValue("errors", "adapter", "fnc").toString(); + throw new ExceptionDBGitRunTime(msg, e); + } + return listFunction; + } + + @Override + public DBFunction getFunction(String schema, String name) { + String query = + "SELECT n.nspname AS \"schema\", u.rolname, p.proname AS \"name\", \n" + + " pg_catalog.pg_get_function_arguments(p.oid) AS \"arguments\",\n" + + " pg_get_functiondef(p.oid) AS ddl\n" + + "FROM pg_catalog.pg_proc p\n" + + " JOIN pg_catalog.pg_roles u ON u.oid = p.proowner\n" + + " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace\n" + + ( (getDbVersionNumber() >= 10) + ? "WHERE p.prokind = 'f' \n" + : "WHERE 1=1 \n" + ) + + "AND n.nspname not in('pg_catalog', 'information_schema')\n" + + "AND n.nspname = '"+schema+"' AND p.proname = '"+name+"'"; + + try (Statement stmt = getConnection().createStatement();ResultSet rs = stmt.executeQuery(query);){ + + + if (rs.next()) { + String owner = rs.getString("rolname"); + String sql = rs.getString("ddl"); + StringProperties options = new StringProperties(rs); + Set dependencies = rs.getArray("dependencies") == null + ? Collections.emptySet() + : new HashSet<>(Arrays.asList((String[])rs.getArray("dependencies").getArray())); + + return new DBFunction(name, options, schema, owner, dependencies, sql); + //String args = rs.getString("arguments"); + //func.setArguments(args); + + } else { + String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); + throw new ExceptionDBGitObjectNotFound(msg); + } + + + } catch(Exception e) { + String msg = lang.getValue("errors", "adapter", "fnc").toString(); + throw new ExceptionDBGitRunTime(msg, e); + } + } + + @Override + public DBTableData getTableDataPortion(String schema, String nameTable, int portionIndex, int tryNumber) { + final DBGitConfig config = DBGitConfig.getInstance(); + try { + final boolean isFetchLimitedDefault = config.getBooleanGlobal("core", "LIMIT_FETCH", true); + final boolean isFetchLimited = config.getBoolean("core", "LIMIT_FETCH", isFetchLimitedDefault); + final int maxRowsCountDefault = config.getIntegerGlobal("core", "MAX_ROW_COUNT_FETCH", MAX_ROW_COUNT_FETCH); + final int maxRowsCount = config.getInteger("core", "MAX_ROW_COUNT_FETCH", maxRowsCountDefault); + final int portionSize = config.getInteger("core", "PORTION_SIZE", config.getIntegerGlobal("core", "PORTION_SIZE", 1000)); + final int portionBegin = 1 + portionSize*portionIndex; + final int portionEnd = portionSize + portionSize*portionIndex; + + final String tableRowsCountQuery = + "select COALESCE(count(*), 0) kolvo " + + "from ( " + + " select 1 from " + escapeNameIfNeeded(schema) + "." + escapeNameIfNeeded(nameTable) + + " limit " + (maxRowsCount + 1) + " " + + ") tbl"; + + final String dataQuery = + " SELECT * FROM \r\n" + + " (SELECT f.*, ROW_NUMBER() OVER (ORDER BY ctid) DBGIT_ROW_NUM FROM " + escapeNameIfNeeded(schema) + "." + escapeNameIfNeeded(nameTable) + " f) s\r\n" + + " WHERE DBGIT_ROW_NUM BETWEEN " + portionBegin + " and " + portionEnd; + + + if (isFetchLimited) { + try(Statement st = getConnection().createStatement(); ResultSet rs = st.executeQuery(tableRowsCountQuery);){ + if(!rs.next()) { + String msg = "error fetch table rows count"; + throw new ExceptionDBGitRunTime(msg); + } else if (rs.getInt("kolvo") > maxRowsCount) { + return new DBTableData(DBTableData.ERROR_LIMIT_ROWS); + } + } + + } + + return new DBTableData(getConnection(), dataQuery); + + + } catch(Exception e) { + + final int maxTriesCount = DBGitConfig.getInstance().getInteger("core", "TRY_COUNT", DBGitConfig.getInstance().getIntegerGlobal("core", "TRY_COUNT", 1000)); + final int tryDelay = DBGitConfig.getInstance().getInteger("core", "TRY_DELAY", DBGitConfig.getInstance().getIntegerGlobal("core", "TRY_DELAY", 1000)); + + ConsoleWriter.println(e.getLocalizedMessage(), messageLevel); + ConsoleWriter.detailsPrintln(ExceptionUtils.getStackTrace(e), messageLevel); + logger.error(lang.getValue("errors", "adapter", "tableData").toString(), e); + + if (tryNumber <= maxTriesCount) { + + final String waitMessage = DBGitLang.getInstance() + .getValue("errors", "dataTable", "wait") + .withParams(String.valueOf(tryDelay)); + + final String tryAgainMessage = DBGitLang.getInstance() + .getValue("errors", "dataTable", "tryAgain") + .withParams(String.valueOf(tryNumber)); + + ConsoleWriter.println(waitMessage, messageLevel); + try { TimeUnit.SECONDS.sleep(tryDelay); } catch (InterruptedException e1) { + throw new ExceptionDBGitRunTime(e1.getMessage()); + } + + ConsoleWriter.println(tryAgainMessage, messageLevel); + return getTableDataPortion(schema, nameTable, portionIndex, tryNumber++); + + } else { + final String msg = DBGitLang.getInstance().getValue("errors", "adapter", "tableData").toString(); + throw new ExceptionDBGitRunTime(msg, e); + } + } + } + + @Override + public DBTableData getTableData(String schema, String nameTable) { + final String tableName = escapeNameIfNeeded(schema)+"."+ escapeNameIfNeeded(nameTable); + final int maxRowsCount = DBGitConfig.getInstance().getInteger("core", "MAX_ROW_COUNT_FETCH", DBGitConfig.getInstance().getIntegerGlobal("core", "MAX_ROW_COUNT_FETCH", MAX_ROW_COUNT_FETCH)); + final Boolean isFetchLimited = DBGitConfig.getInstance().getBoolean("core", "LIMIT_FETCH", DBGitConfig.getInstance().getBooleanGlobal("core", "LIMIT_FETCH", true)); + try { + if (isFetchLimited) { + + String query = + "select COALESCE(count(*), 0) kolvo " + + "from ( " + + " select 1 from "+ tableName + + " limit " + (maxRowsCount + 1) + + " ) tbl"; + + try(Statement st = getConnection().createStatement(); ResultSet rs = st.executeQuery(query);){ + if(!rs.next()) throw new ExceptionDBGitRunTime("Could not execute rows count query"); + if (rs.getInt("kolvo") > maxRowsCount) { + return new DBTableData(DBTableData.ERROR_LIMIT_ROWS); + } + } + } + + final String tdQuery = "select * from " + tableName; + return new DBTableData(getConnection(), tdQuery); + //TODO other state + //TODO find out what does 'other state' todo comment mean... + + } catch(Exception e) { + final String msg = DBGitLang.getInstance().getValue("errors", "adapter", "tableData").toString(); + throw new ExceptionDBGitRunTime(msg, e); + } + } + + @Override + public Map getUsers() { + Map listUser = new HashMap(); + String query = "select * from pg_user"; + try (Statement stmt = getConnection().createStatement();ResultSet rs = stmt.executeQuery(query);){ + + while(rs.next()){ + String name = rs.getString(1); + StringProperties options = new StringProperties(rs); + + DBUser user = new DBUser(name, options); + listUser.put(name, user); + } + } catch(Exception e) { + throw new ExceptionDBGitRunTime(e); + } + //select *from pg_catalog.pg_namespace; + return listUser; + } + + @Override + public Map getRoles() { + Map listRole = new HashMap(); + String query = + "SELECT r.rolname, r.rolsuper, r.rolinherit,\n" + + " r.rolcreaterole, r.rolcreatedb, r.rolcanlogin, \n" + + " r.rolreplication," + ((getDbVersionNumber() > 9.5) ? "r.rolbypassrls,\n" : "\n") + + " r.rolconnlimit, r.rolpassword, r.rolvaliduntil,\n" + + " ARRAY(SELECT b.rolname\n" + + " FROM pg_catalog.pg_auth_members m\n" + + " JOIN pg_catalog.pg_roles b ON (m.roleid = b.oid)\n" + + " WHERE m.member = r.oid) as memberof\n" + + "FROM pg_catalog.pg_roles r\n" + + "WHERE r.rolname !~ '^pg_'\n" + + "ORDER BY 1;"; + try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);) { + + while(rs.next()){ + String name = rs.getString("rolname"); + StringProperties options = new StringProperties(rs); + + DBRole role = new DBRole(name, options); + listRole.put(name, role); + } + + } catch(Exception e) { + throw new ExceptionDBGitRunTime(e); + } + + return listRole; + } + + @Override + public Map getUDTs(String schema) { + final Map objects = new HashMap<>(); + final String query = + "SELECT \n" + + " n.nspname AS schema,\n" + + " t.typname AS name, \n" + + " r.rolname AS owner,\n" + + " pg_catalog.obj_description ( t.oid, 'pg_type' ) AS description\n" + + "FROM pg_type t \n" + + "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace \n" + + "LEFT JOIN pg_roles r ON r.oid = t.typowner\n" + + "WHERE (t.typrelid = 0 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid)) \n" + + "AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem AND el.typarray = t.oid)\n" + + "AND t.typtype = 'c'\n" + + "AND n.nspname = '"+schema+"'"; + + try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);) { + while (rs.next()) { + final String name = rs.getString("name"); + final String owner = rs.getString("owner"); + final List attributesSqls = new ArrayList<>(); + final String attributesQuery = + "SELECT \n" + + " attribute_name AS \"name\", \n" + + " data_type AS \"type\", \n" + + " ordinal_position AS \"order\"\n" + + "FROM information_schema.attributes a\n" + + "WHERE udt_schema = '"+schema+"' AND udt_name = '"+name+"'\n" + + "ORDER BY ordinal_position"; + try (Statement stmt2 = getConnection().createStatement(); ResultSet attributeRs = stmt2.executeQuery( + attributesQuery)) { + while (attributeRs.next()) { + final String attrName = attributeRs.getString("name"); + final String attrType = attributeRs.getString("type"); + final String udtAttrDefinition = MessageFormat.format( + "{0} {1}", + escapeNameIfNeeded(attrName), + attrType + ); + attributesSqls.add(udtAttrDefinition); + } + } + final StringProperties options = new StringProperties(); + final String sql = MessageFormat.format( + "CREATE TYPE {0}.{1} AS (\n{2}\n);\n" + + "ALTER TYPE {0}.{1} OWNER TO {3};", + escapeNameIfNeeded(schema), + escapeNameIfNeeded(name), + String.join(",\n ", attributesSqls), + owner + ); + + DBUserDefinedType object = new DBUserDefinedType(name, options, schema, owner, Collections.emptySet(), sql); + options.addChild("attributes", String.join(",", attributesSqls)); + options.addChild("description", rs.getString("description")); + objects.put(name, object); + } + + } catch (Exception e) { + throw new ExceptionDBGitRunTime(e); + } + + return objects; + } + + @Override + public Map getDomains(String schema) { + System.out.println("getting domains"); + final Map objects = new HashMap<>(); + final String query = + "SELECT \n" + + " n.nspname,\n" + + " t.typname, \n" + + " dom.data_type, \n" + + " dom.domain_default,\n" + + " r.rolname,\n" + + " pg_catalog.obj_description ( t.oid, 'pg_type' ) AS description\n" + + "FROM pg_type t \n" + + "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace \n" + + "RIGHT JOIN information_schema.domains dom ON dom.domain_name = t.typname AND dom.domain_schema = n.nspname\n" + + "LEFT JOIN pg_roles r ON r.oid = t.typowner\n" + + "WHERE (t.typrelid = 0 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid)) \n" + + "AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem AND el.typarray = t.oid)\n" + + "AND n.nspname NOT IN ('pg_catalog', 'information_schema')\n" + + "AND dom.domain_schema = '"+schema+"'"; + + try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);) { + + while (rs.next()) { + final String name = rs.getString("typname"); + final String owner = rs.getString("rolname"); + final String type = rs.getString("data_type"); + final String defaultValue = rs.getString("domain_default"); + + final List constraintSqls = new ArrayList<>(); + final String constraintsQuery = + "SELECT con.conname, con.convalidated, con.consrc\n" + + "FROM information_schema.domains dom\n" + + "INNER JOIN information_schema.domain_constraints dcon ON dcon.domain_schema = dom.domain_schema AND dcon.domain_name = dom.domain_name\n" + + "INNER JOIN pg_catalog.pg_constraint con ON dcon.constraint_name = con.conname\n" + + "WHERE dom.domain_schema = '"+schema+"' AND dom.domain_name = '"+name+"'"; + try (Statement stmt2 = getConnection().createStatement(); ResultSet conRs = stmt2.executeQuery(constraintsQuery)) { + while (conRs.next()) { + final String conName = conRs.getString("conname"); + final String conSrc = conRs.getString("consrc"); + final Boolean conIsValidated = conRs.getBoolean("convalidated"); + constraintSqls.add(MessageFormat.format( + "ALTER DOMAIN {0}.{1} ADD CONSTRAINT {2} CHECK {3} {4};", + escapeNameIfNeeded(schema), + escapeNameIfNeeded(name), + escapeNameIfNeeded(conName), + conSrc, + conIsValidated ? "" : "NOT VALID" + )); + } + } + + final StringProperties options = new StringProperties(rs); + final String sql = MessageFormat.format( + "CREATE DOMAIN {0}.{1} AS {2} {3}; ALTER DOMAIN {0}.{1} OWNER TO {4};\n{5}", + escapeNameIfNeeded(schema), escapeNameIfNeeded(name), type, defaultValue != null ? "DEFAULT " + defaultValue : "", owner, + String.join("\n", constraintSqls) + ); + + DBDomain object = new DBDomain(name, options, schema, owner, Collections.emptySet(), sql); + objects.put(name, object); + } + + } catch (Exception e) { + throw new ExceptionDBGitRunTime(e); + } + + return objects; + } + + @Override + public Map getEnums(String schema) { + System.out.println("getting enums"); + final Map objects = new HashMap<>(); + final String query = + "SELECT t.typname, r.rolname, pg_catalog.obj_description ( t.oid, 'pg_type' ) AS description," + + "ARRAY( \n" + + " SELECT e.enumlabel\n" + + " FROM pg_catalog.pg_enum e\n" + + " WHERE e.enumtypid = t.oid\n" + + " ORDER BY e.oid \n" + + ") AS elements\n" + + "FROM pg_type t \n" + + "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace \n" + + "LEFT JOIN pg_roles r ON r.oid = t.typowner\n" + + "WHERE (t.typrelid = 0 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid)) \n" + + "AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem AND el.typarray = t.oid)\n" + + "AND n.nspname NOT IN ('pg_catalog', 'information_schema')\n" + + "AND n.nspname = '"+schema+"'" + + "AND t.typtype = 'e'"; + + try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);) { + + while (rs.next()) { + final String name = rs.getString("typname"); + final String owner = rs.getString("rolname"); + final String elements = String.join( + ",", + Arrays.stream((String[]) rs.getArray("elements").getArray()).map( x->"'"+x+"'").collect(Collectors.toList()) + ); + final StringProperties options = new StringProperties(); + final String sql = MessageFormat.format( + "CREATE TYPE {0}.{1} AS ENUM ({2});\nALTER TYPE {0}.{1} OWNER TO {3}", + schema, name, elements, owner + ); + + DBEnum object = new DBEnum(name, options, schema, owner, Collections.emptySet(), sql); + options.addChild("elements", elements); + objects.put(name, object); + } + + } catch (Exception e) { + throw new ExceptionDBGitRunTime(e); + } + + return objects; + } + + @Override + public DBUserDefinedType getUDT(String schema, String name) { + final Map udTs = getUDTs(schema); + if (udTs.containsKey(name)) { + return udTs.get(name); + } else { + throw new ExceptionDBGitObjectNotFound(lang.getValue("errors", "adapter", "objectNotFoundInDb").toString()); + } + } + + @Override + public DBDomain getDomain(String schema, String name) { + final Map domains = getDomains(schema); + if (domains.containsKey(name)) { + return domains.get(name); + } else { + throw new ExceptionDBGitObjectNotFound(lang.getValue("errors", "adapter", "objectNotFoundInDb").toString()); + } + } + + @Override + public DBEnum getEnum(String schema, String name) { + final Map enums = getEnums(schema); + if (enums.containsKey(name)) { + return enums.get(name); + } else { + throw new ExceptionDBGitObjectNotFound(lang.getValue("errors", "adapter", "objectNotFoundInDb").toString()); + } + } + + @Override + public boolean userHasRightsToGetDdlOfOtherUsers() { return true; } + @Override + public IFactoryDBBackupAdapter getBackupAdapterFactory() { return backupFactory; } + @Override + public IFactoryDBConvertAdapter getConvertAdapterFactory() { return convertFactory; } + @Override + public DbType getDbType() { return DbType.POSTGRES; } + @Override + public String getDbVersion() { + final String query = "SHOW server_version"; + try ( + PreparedStatement stmt = getConnection().prepareStatement(query); + ResultSet resultSet = stmt.executeQuery(); + ) { + + if(!resultSet.next()){ + final String msg = "failed to get schema data"; + throw new ExceptionDBGitRunTime(msg); + } + + return resultSet.getString("server_version"); + + } catch (SQLException e) { + final String msg = "failed to get database version"; + throw new ExceptionDBGitRunTime(msg, e); + } + } + @Override + public String getDefaultScheme() throws ExceptionDBGit { return "public"; } + @Override + public boolean isReservedWord(String word) { return reservedWords.contains(word.toUpperCase()); } + + @Override + public void createSchemaIfNeed(String schemaName) { + final String query = + "select count(*) cnt " + + "from information_schema.schemata " + + "where upper(schema_name) = '" + schemaName.toUpperCase() + "'"; + + try (Statement st = connect.createStatement(); ResultSet rs = st.executeQuery(query);){ + + if(!rs.next()) { + final String msg = "failed to get schema data"; + throw new ExceptionDBGitRunTime(msg); + } + + if (rs.getInt("cnt") == 0) { + try(StatementLogging stLog = new StatementLogging(connect, getStreamOutputSqlCommand(), isExecSql());){ + stLog.execute("create schema " + schemaName + ";\n"); + } + } else { + return; + } + + } catch (SQLException e) { + final String msg = lang.getValue("errors", "adapter", "createSchema").toString(); + throw new ExceptionDBGitRunTime(msg, e); + } + + } + + @Override + public void createRoleIfNeed(String roleName) { + final String query = + "select count(*) cnt " + + "from pg_catalog.pg_roles " + + "where upper(rolname) = '" + roleName.toUpperCase() + "'"; + + try (Statement st = connect.createStatement(); ResultSet rs = st.executeQuery(query);) { + + if(!rs.next()) { + final String msg = "failed to get role data"; + throw new ExceptionDBGitRunTime(msg); + } + + if (rs.getInt("cnt") == 0){ + try(StatementLogging stLog = new StatementLogging(connect, getStreamOutputSqlCommand(), isExecSql());) { + //TODO which kind of PASSWORD that equals to ROLE NAME? + stLog.execute("CREATE ROLE " + roleName + " LOGIN PASSWORD '" + roleName + "'"); + } + } else { + return; + } + + } catch (SQLException e) { + final DBGitLang msg = lang.getValue("errors", "adapter", "createSchema"); + throw new ExceptionDBGitRunTime(msg, e); + } + } + + public String escapeNameIfNeeded(String name){ + boolean shouldBeEscaped = !name.equals(name.toLowerCase()) + || name.contains(".") + || name.contains(".") + || reservedWords.contains(name.toUpperCase()); + if(name.startsWith("\"") && name.endsWith("\"")) shouldBeEscaped = false; + return MessageFormat.format("{1}{0}{1}", name, shouldBeEscaped ? "\"" : ""); + } + + static { + reservedWords.add("A"); + reservedWords.add("ABORT"); + reservedWords.add("ABS"); + reservedWords.add("ABSOLUTE"); + reservedWords.add("ACCESS"); + reservedWords.add("ACTION"); + reservedWords.add("ADA"); + reservedWords.add("ADD"); + reservedWords.add("ADMIN"); + reservedWords.add("AFTER"); + reservedWords.add("AGGREGATE"); + reservedWords.add("ALIAS"); + reservedWords.add("ALL"); + reservedWords.add("ALLOCATE"); + reservedWords.add("ALSO"); + reservedWords.add("ALTER"); + reservedWords.add("ALWAYS"); + reservedWords.add("ANALYSE"); + reservedWords.add("ANALYZE"); + reservedWords.add("AND"); + reservedWords.add("ANY"); + reservedWords.add("ARE"); + reservedWords.add("ARRAY"); + reservedWords.add("AS"); + reservedWords.add("ASC"); + reservedWords.add("ASENSITIVE"); + reservedWords.add("ASSERTION"); + reservedWords.add("ASSIGNMENT"); + reservedWords.add("ASYMMETRIC"); + reservedWords.add("AT"); + reservedWords.add("ATOMIC"); + reservedWords.add("ATTRIBUTE"); + reservedWords.add("ATTRIBUTES"); + reservedWords.add("AUTHORIZATION"); + reservedWords.add("AVG"); + reservedWords.add("BACKWARD"); + reservedWords.add("BEFORE"); + reservedWords.add("BEGIN"); + reservedWords.add("BERNOULLI"); + reservedWords.add("BETWEEN"); + reservedWords.add("BIGINT"); + reservedWords.add("BINARY"); + reservedWords.add("BIT"); + reservedWords.add("BITVAR"); + reservedWords.add("BIT_LENGTH"); + reservedWords.add("BLOB"); + reservedWords.add("BOOLEAN"); + reservedWords.add("BOTH"); + reservedWords.add("BREADTH"); + reservedWords.add("BY"); + reservedWords.add("C"); + reservedWords.add("CACHE"); + reservedWords.add("CALL"); + reservedWords.add("CALLED"); + reservedWords.add("CARDINALITY"); + reservedWords.add("CASCADE"); + reservedWords.add("CASCADED"); + reservedWords.add("CASE"); + reservedWords.add("CAST"); + reservedWords.add("CATALOG"); + reservedWords.add("CATALOG_NAME"); + reservedWords.add("CEIL"); + reservedWords.add("CEILING"); + reservedWords.add("CHAIN"); + reservedWords.add("CHAR"); + reservedWords.add("CHARACTER"); + reservedWords.add("CHARACTERISTICS"); + reservedWords.add("CHARACTERS"); + reservedWords.add("CHARACTER_LENGTH"); + reservedWords.add("CHARACTER_SET_CATALOG"); + reservedWords.add("CHARACTER_SET_NAME"); + reservedWords.add("CHARACTER_SET_SCHEMA"); + reservedWords.add("CHAR_LENGTH"); + reservedWords.add("CHECK"); + reservedWords.add("CHECKED"); + reservedWords.add("CHECKPOINT"); + reservedWords.add("CLASS"); + reservedWords.add("CLASS_ORIGIN"); + reservedWords.add("CLOB"); + reservedWords.add("CLOSE"); + reservedWords.add("CLUSTER"); + reservedWords.add("COALESCE"); + reservedWords.add("COBOL"); + reservedWords.add("COLLATE"); + reservedWords.add("COLLATION"); + reservedWords.add("COLLATION_CATALOG"); + reservedWords.add("COLLATION_NAME"); + reservedWords.add("COLLATION_SCHEMA"); + reservedWords.add("COLLECT"); + reservedWords.add("COLUMN"); + reservedWords.add("COLUMN_NAME"); + reservedWords.add("COMMAND_FUNCTION"); + reservedWords.add("COMMAND_FUNCTION_CODE"); + reservedWords.add("COMMENT"); + reservedWords.add("COMMIT"); + reservedWords.add("COMMITTED"); + reservedWords.add("COMPLETION"); + reservedWords.add("CONDITION"); + reservedWords.add("CONDITION_NUMBER"); + reservedWords.add("CONNECT"); + reservedWords.add("CONNECTION"); + reservedWords.add("CONNECTION_NAME"); + reservedWords.add("CONSTRAINT"); + reservedWords.add("CONSTRAINTS"); + reservedWords.add("CONSTRAINT_CATALOG"); + reservedWords.add("CONSTRAINT_NAME"); + reservedWords.add("CONSTRAINT_SCHEMA"); + reservedWords.add("CONSTRUCTOR"); + reservedWords.add("CONTAINS"); + reservedWords.add("CONTINUE"); + reservedWords.add("CONVERSION"); + reservedWords.add("CONVERT"); + reservedWords.add("COPY"); + reservedWords.add("CORR"); + reservedWords.add("CORRESPONDING"); + reservedWords.add("COUNT"); + reservedWords.add("COVAR_POP"); + reservedWords.add("COVAR_SAMP"); + reservedWords.add("CREATE"); + reservedWords.add("CREATEDB"); + reservedWords.add("CREATEROLE"); + reservedWords.add("CREATEUSER"); + reservedWords.add("CROSS"); + reservedWords.add("CSV"); + reservedWords.add("CUBE"); + reservedWords.add("CUME_DIST"); + reservedWords.add("CURRENT"); + reservedWords.add("CURRENT_DATE"); + reservedWords.add("CURRENT_DEFAULT_TRANSFORM_GROUP"); + reservedWords.add("CURRENT_PATH"); + reservedWords.add("CURRENT_ROLE"); + reservedWords.add("CURRENT_TIME"); + reservedWords.add("CURRENT_TIMESTAMP"); + reservedWords.add("CURRENT_TRANSFORM_GROUP_FOR_TYPE"); + reservedWords.add("CURRENT_USER"); + reservedWords.add("CURSOR"); + reservedWords.add("CURSOR_NAME"); + reservedWords.add("CYCLE"); + reservedWords.add("DATA"); + reservedWords.add("DATABASE"); + reservedWords.add("DATE"); + reservedWords.add("DATETIME_INTERVAL_CODE"); + reservedWords.add("DATETIME_INTERVAL_PRECISION"); + reservedWords.add("DAY"); + reservedWords.add("DEALLOCATE"); + reservedWords.add("DEC"); + reservedWords.add("DECIMAL"); + reservedWords.add("DECLARE"); + reservedWords.add("DEFAULT"); + reservedWords.add("DEFAULTS"); + reservedWords.add("DEFERRABLE"); + reservedWords.add("DEFERRED"); + reservedWords.add("DEFINED"); + reservedWords.add("DEFINER"); + reservedWords.add("DEGREE"); + reservedWords.add("DELETE"); + reservedWords.add("DELIMITER"); + reservedWords.add("DELIMITERS"); + reservedWords.add("DENSE_RANK"); + reservedWords.add("DEPTH"); + reservedWords.add("DEREF"); + reservedWords.add("DERIVED"); + reservedWords.add("DESC"); + reservedWords.add("DESCRIBE"); + reservedWords.add("DESCRIPTOR"); + reservedWords.add("DESTROY"); + reservedWords.add("DESTRUCTOR"); + reservedWords.add("DETERMINISTIC"); + reservedWords.add("DIAGNOSTICS"); + reservedWords.add("DICTIONARY"); + reservedWords.add("DISABLE"); + reservedWords.add("DISCONNECT"); + reservedWords.add("DISPATCH"); + reservedWords.add("DISTINCT"); + reservedWords.add("DO"); + reservedWords.add("DOMAIN"); + reservedWords.add("DOUBLE"); + reservedWords.add("DROP"); + reservedWords.add("DYNAMIC"); + reservedWords.add("DYNAMIC_FUNCTION"); + reservedWords.add("DYNAMIC_FUNCTION_CODE"); + reservedWords.add("EACH"); + reservedWords.add("ELEMENT"); + reservedWords.add("ELSE"); + reservedWords.add("ENABLE"); + reservedWords.add("ENCODING"); + reservedWords.add("ENCRYPTED"); + reservedWords.add("END"); + reservedWords.add("END-EXEC"); + reservedWords.add("EQUALS"); + reservedWords.add("ESCAPE"); + reservedWords.add("EVERY"); + reservedWords.add("EXCEPT"); + reservedWords.add("EXCEPTION"); + reservedWords.add("EXCLUDE"); + reservedWords.add("EXCLUDING"); + reservedWords.add("EXCLUSIVE"); + reservedWords.add("EXEC"); + reservedWords.add("EXECUTE"); + reservedWords.add("EXISTING"); + reservedWords.add("EXISTS"); + reservedWords.add("EXP"); + reservedWords.add("EXPLAIN"); + reservedWords.add("EXTERNAL"); + reservedWords.add("EXTRACT"); + reservedWords.add("FALSE"); + reservedWords.add("FETCH"); + reservedWords.add("FILTER"); + reservedWords.add("FINAL"); + reservedWords.add("FIRST"); + reservedWords.add("FLOAT"); + reservedWords.add("FLOOR"); + reservedWords.add("FOLLOWING"); + reservedWords.add("FOR"); + reservedWords.add("FORCE"); + reservedWords.add("FOREIGN"); + reservedWords.add("FORTRAN"); + reservedWords.add("FORWARD"); + reservedWords.add("FOUND"); + reservedWords.add("FREE"); + reservedWords.add("FREEZE"); + reservedWords.add("FROM"); + reservedWords.add("FULL"); + reservedWords.add("FUNCTION"); + reservedWords.add("FUSION"); + reservedWords.add("G"); + reservedWords.add("GENERAL"); + reservedWords.add("GENERATED"); + reservedWords.add("GET"); + reservedWords.add("GLOBAL"); + reservedWords.add("GO"); + reservedWords.add("GOTO"); + reservedWords.add("GRANT"); + reservedWords.add("GRANTED"); + reservedWords.add("GREATEST"); + reservedWords.add("GROUP"); + reservedWords.add("GROUPING"); + reservedWords.add("HANDLER"); + reservedWords.add("HAVING"); + reservedWords.add("HEADER"); + reservedWords.add("HIERARCHY"); + reservedWords.add("HOLD"); + reservedWords.add("HOST"); + reservedWords.add("HOUR"); + reservedWords.add("IDENTITY"); + reservedWords.add("IGNORE"); + reservedWords.add("ILIKE"); + reservedWords.add("IMMEDIATE"); + reservedWords.add("IMMUTABLE"); + reservedWords.add("IMPLEMENTATION"); + reservedWords.add("IMPLICIT"); + reservedWords.add("IN"); + reservedWords.add("INCLUDING"); + reservedWords.add("INCREMENT"); + reservedWords.add("INDEX"); + reservedWords.add("INDICATOR"); + reservedWords.add("INFIX"); + reservedWords.add("INHERIT"); + reservedWords.add("INHERITS"); + reservedWords.add("INITIALIZE"); + reservedWords.add("INITIALLY"); + reservedWords.add("INNER"); + reservedWords.add("INOUT"); + reservedWords.add("INPUT"); + reservedWords.add("INSENSITIVE"); + reservedWords.add("INSERT"); + reservedWords.add("INSTANCE"); + reservedWords.add("INSTANTIABLE"); + reservedWords.add("INSTEAD"); + reservedWords.add("INT"); + reservedWords.add("INTEGER"); + reservedWords.add("INTERSECT"); + reservedWords.add("INTERSECTION"); + reservedWords.add("INTERVAL"); + reservedWords.add("INTO"); + reservedWords.add("INVOKER"); + reservedWords.add("IS"); + reservedWords.add("ISNULL"); + reservedWords.add("ISOLATION"); + reservedWords.add("ITERATE"); + reservedWords.add("JOIN"); + reservedWords.add("K"); + reservedWords.add("KEY"); + reservedWords.add("KEY_MEMBER"); + reservedWords.add("KEY_TYPE"); + reservedWords.add("LANCOMPILER"); + reservedWords.add("LANGUAGE"); + reservedWords.add("LARGE"); + reservedWords.add("LAST"); + reservedWords.add("LATERAL"); + reservedWords.add("LEADING"); + reservedWords.add("LEAST"); + reservedWords.add("LEFT"); + reservedWords.add("LENGTH"); + reservedWords.add("LESS"); + reservedWords.add("LEVEL"); + reservedWords.add("LIKE"); + reservedWords.add("LIMIT"); + reservedWords.add("LISTEN"); + reservedWords.add("LN"); + reservedWords.add("LOAD"); + reservedWords.add("LOCAL"); + reservedWords.add("LOCALTIME"); + reservedWords.add("LOCALTIMESTAMP"); + reservedWords.add("LOCATION"); + reservedWords.add("LOCATOR"); + reservedWords.add("LOCK"); + reservedWords.add("LOGIN"); + reservedWords.add("LOWER"); + reservedWords.add("M"); + reservedWords.add("MAP"); + reservedWords.add("MATCH"); + reservedWords.add("MATCHED"); + reservedWords.add("MAX"); + reservedWords.add("MAXVALUE"); + reservedWords.add("MEMBER"); + reservedWords.add("MERGE"); + reservedWords.add("MESSAGE_LENGTH"); + reservedWords.add("MESSAGE_OCTET_LENGTH"); + reservedWords.add("MESSAGE_TEXT"); + reservedWords.add("METHOD"); + reservedWords.add("MIN"); + reservedWords.add("MINUTE"); + reservedWords.add("MINVALUE"); + reservedWords.add("MOD"); + reservedWords.add("MODE"); + reservedWords.add("MODIFIES"); + reservedWords.add("MODIFY"); + reservedWords.add("MODULE"); + reservedWords.add("MONTH"); + reservedWords.add("MORE"); + reservedWords.add("MOVE"); + reservedWords.add("MULTISET"); + reservedWords.add("MUMPS"); + reservedWords.add("NAME"); + reservedWords.add("NAMES"); + reservedWords.add("NATIONAL"); + reservedWords.add("NATURAL"); + reservedWords.add("NCHAR"); + reservedWords.add("NCLOB"); + reservedWords.add("NESTING"); + reservedWords.add("NEW"); + reservedWords.add("NEXT"); + reservedWords.add("NO"); + reservedWords.add("NOCREATEDB"); + reservedWords.add("NOCREATEROLE"); + reservedWords.add("NOCREATEUSER"); + reservedWords.add("NOINHERIT"); + reservedWords.add("NOLOGIN"); + reservedWords.add("NONE"); + reservedWords.add("NORMALIZE"); + reservedWords.add("NORMALIZED"); + reservedWords.add("NOSUPERUSER"); + reservedWords.add("NOT"); + reservedWords.add("NOTHING"); + reservedWords.add("NOTIFY"); + reservedWords.add("NOTNULL"); + reservedWords.add("NOWAIT"); + reservedWords.add("NULL"); + reservedWords.add("NULLABLE"); + reservedWords.add("NULLIF"); + reservedWords.add("NULLS"); + reservedWords.add("NUMBER"); + reservedWords.add("NUMERIC"); + reservedWords.add("OBJECT"); + reservedWords.add("OCTETS"); + reservedWords.add("OCTET_LENGTH"); + reservedWords.add("OF"); + reservedWords.add("OFF"); + reservedWords.add("OFFSET"); + reservedWords.add("OIDS"); + reservedWords.add("OLD"); + reservedWords.add("ON"); + reservedWords.add("ONLY"); + reservedWords.add("OPEN"); + reservedWords.add("OPERATION"); + reservedWords.add("OPERATOR"); + reservedWords.add("OPTION"); + reservedWords.add("OPTIONS"); + reservedWords.add("OR"); + reservedWords.add("ORDER"); + reservedWords.add("ORDERING"); + reservedWords.add("ORDINALITY"); + reservedWords.add("OTHERS"); + reservedWords.add("OUT"); + reservedWords.add("OUTER"); + reservedWords.add("OUTPUT"); + reservedWords.add("OVER"); + reservedWords.add("OVERLAPS"); + reservedWords.add("OVERLAY"); + reservedWords.add("OVERRIDING"); + reservedWords.add("OWNER"); + reservedWords.add("PAD"); + reservedWords.add("PARAMETER"); + reservedWords.add("PARAMETERS"); + reservedWords.add("PARAMETER_MODE"); + reservedWords.add("PARAMETER_NAME"); + reservedWords.add("PARAMETER_ORDINAL_POSITION"); + reservedWords.add("PARAMETER_SPECIFIC_CATALOG"); + reservedWords.add("PARAMETER_SPECIFIC_NAME"); + reservedWords.add("PARAMETER_SPECIFIC_SCHEMA"); + reservedWords.add("PARTIAL"); + reservedWords.add("PARTITION"); + reservedWords.add("PASCAL"); + reservedWords.add("PASSWORD"); + reservedWords.add("PATH"); + reservedWords.add("PERCENTILE_CONT"); + reservedWords.add("PERCENTILE_DISC"); + reservedWords.add("PERCENT_RANK"); + reservedWords.add("PLACING"); + reservedWords.add("PLI"); + reservedWords.add("POSITION"); + reservedWords.add("POSTFIX"); + reservedWords.add("POWER"); + reservedWords.add("PRECEDING"); + reservedWords.add("PRECISION"); + reservedWords.add("PREFIX"); + reservedWords.add("PREORDER"); + reservedWords.add("PREPARE"); + reservedWords.add("PREPARED"); + reservedWords.add("PRESERVE"); + reservedWords.add("PRIMARY"); + reservedWords.add("PRIOR"); + reservedWords.add("PRIVILEGES"); + reservedWords.add("PROCEDURAL"); + reservedWords.add("PROCEDURE"); +// reservedWords.add("PUBLIC"); + reservedWords.add("QUOTE"); + reservedWords.add("RANGE"); + reservedWords.add("RANK"); + reservedWords.add("READ"); + reservedWords.add("READS"); + reservedWords.add("REAL"); + reservedWords.add("RECHECK"); + reservedWords.add("RECURSIVE"); + reservedWords.add("REF"); + reservedWords.add("REFERENCES"); + reservedWords.add("REFERENCING"); + reservedWords.add("REGR_AVGX"); + reservedWords.add("REGR_AVGY"); + reservedWords.add("REGR_COUNT"); + reservedWords.add("REGR_INTERCEPT"); + reservedWords.add("REGR_R2"); + reservedWords.add("REGR_SLOPE"); + reservedWords.add("REGR_SXX"); + reservedWords.add("REGR_SXY"); + reservedWords.add("REGR_SYY"); + reservedWords.add("REINDEX"); + reservedWords.add("RELATIVE"); + reservedWords.add("RELEASE"); + reservedWords.add("RENAME"); + reservedWords.add("REPEATABLE"); + reservedWords.add("REPLACE"); + reservedWords.add("RESET"); + reservedWords.add("RESTART"); + reservedWords.add("RESTRICT"); + reservedWords.add("RESULT"); + reservedWords.add("RETURN"); + reservedWords.add("RETURNED_CARDINALITY"); + reservedWords.add("RETURNED_LENGTH"); + reservedWords.add("RETURNED_OCTET_LENGTH"); + reservedWords.add("RETURNED_SQLSTATE"); + reservedWords.add("RETURNS"); + reservedWords.add("REVOKE"); + reservedWords.add("RIGHT"); + reservedWords.add("ROLE"); + reservedWords.add("ROLLBACK"); + reservedWords.add("ROLLUP"); + reservedWords.add("ROUTINE"); + reservedWords.add("ROUTINE_CATALOG"); + reservedWords.add("ROUTINE_NAME"); + reservedWords.add("ROUTINE_SCHEMA"); + reservedWords.add("ROW"); + reservedWords.add("ROWS"); + reservedWords.add("ROW_COUNT"); + reservedWords.add("ROW_NUMBER"); + reservedWords.add("RULE"); + reservedWords.add("SAVEPOINT"); + reservedWords.add("SCALE"); + reservedWords.add("SCHEMA"); + reservedWords.add("SCHEMA_NAME"); + reservedWords.add("SCOPE"); + reservedWords.add("SCOPE_CATALOG"); + reservedWords.add("SCOPE_NAME"); + reservedWords.add("SCOPE_SCHEMA"); + reservedWords.add("SCROLL"); + reservedWords.add("SEARCH"); + reservedWords.add("SECOND"); + reservedWords.add("SECTION"); + reservedWords.add("SECURITY"); + reservedWords.add("SELECT"); + reservedWords.add("SELF"); + reservedWords.add("SENSITIVE"); + reservedWords.add("SEQUENCE"); + reservedWords.add("SERIALIZABLE"); + reservedWords.add("SERVER_NAME"); + reservedWords.add("SESSION"); + reservedWords.add("SESSION_USER"); + reservedWords.add("SET"); + reservedWords.add("SETOF"); + reservedWords.add("SETS"); + reservedWords.add("SHARE"); + reservedWords.add("SHOW"); + reservedWords.add("SIMILAR"); + reservedWords.add("SIMPLE"); + reservedWords.add("SIZE"); + reservedWords.add("SMALLINT"); + reservedWords.add("SOME"); + reservedWords.add("SOURCE"); + reservedWords.add("SPACE"); + reservedWords.add("SPECIFIC"); + reservedWords.add("SPECIFICTYPE"); + reservedWords.add("SPECIFIC_NAME"); + reservedWords.add("SQL"); + reservedWords.add("SQLCODE"); + reservedWords.add("SQLERROR"); + reservedWords.add("SQLEXCEPTION"); + reservedWords.add("SQLSTATE"); + reservedWords.add("SQLWARNING"); + reservedWords.add("SQRT"); + reservedWords.add("STABLE"); + reservedWords.add("START"); + reservedWords.add("STATE"); + reservedWords.add("STATEMENT"); + reservedWords.add("STATIC"); + reservedWords.add("STATISTICS"); + reservedWords.add("STDDEV_POP"); + reservedWords.add("STDDEV_SAMP"); + reservedWords.add("STDIN"); + reservedWords.add("STDOUT"); + reservedWords.add("STORAGE"); + reservedWords.add("STRICT"); + reservedWords.add("STRUCTURE"); + reservedWords.add("STYLE"); + reservedWords.add("SUBCLASS_ORIGIN"); + reservedWords.add("SUBLIST"); + reservedWords.add("SUBMULTISET"); + reservedWords.add("SUBSTRING"); + reservedWords.add("SUM"); + reservedWords.add("SUPERUSER"); + reservedWords.add("SYMMETRIC"); + reservedWords.add("SYSID"); + reservedWords.add("SYSTEM"); + reservedWords.add("SYSTEM_USER"); + reservedWords.add("TABLE"); + reservedWords.add("TABLESAMPLE"); + reservedWords.add("TABLESPACE"); + reservedWords.add("TABLE_NAME"); + reservedWords.add("TEMP"); + reservedWords.add("TEMPLATE"); + reservedWords.add("TEMPORARY"); + reservedWords.add("TERMINATE"); + reservedWords.add("THAN"); + reservedWords.add("THEN"); + reservedWords.add("TIES"); + reservedWords.add("TIME"); + reservedWords.add("TIMESTAMP"); + reservedWords.add("TIMEZONE_HOUR"); + reservedWords.add("TIMEZONE_MINUTE"); + reservedWords.add("TO"); + reservedWords.add("TOAST"); + reservedWords.add("TOP_LEVEL_COUNT"); + reservedWords.add("TRAILING"); + reservedWords.add("TRANSACTION"); + reservedWords.add("TRANSACTIONS_COMMITTED"); + reservedWords.add("TRANSACTIONS_ROLLED_BACK"); + reservedWords.add("TRANSACTION_ACTIVE"); + reservedWords.add("TRANSFORM"); + reservedWords.add("TRANSFORMS"); + reservedWords.add("TRANSLATE"); + reservedWords.add("TRANSLATION"); + reservedWords.add("TREAT"); + reservedWords.add("TRIGGER"); + reservedWords.add("TRIGGER_CATALOG"); + reservedWords.add("TRIGGER_NAME"); + reservedWords.add("TRIGGER_SCHEMA"); + reservedWords.add("TRIM"); + reservedWords.add("TRUE"); + reservedWords.add("TRUNCATE"); + reservedWords.add("TRUSTED"); + reservedWords.add("TYPE"); + reservedWords.add("UESCAPE"); + reservedWords.add("UNBOUNDED"); + reservedWords.add("UNCOMMITTED"); + reservedWords.add("UNDER"); + reservedWords.add("UNENCRYPTED"); + reservedWords.add("UNION"); + reservedWords.add("UNIQUE"); + reservedWords.add("UNKNOWN"); + reservedWords.add("UNLISTEN"); + reservedWords.add("UNNAMED"); + reservedWords.add("UNNEST"); + reservedWords.add("UNTIL"); + reservedWords.add("UPDATE"); + reservedWords.add("UPPER"); + reservedWords.add("USAGE"); + reservedWords.add("USER"); + reservedWords.add("USER_DEFINED_TYPE_CATALOG"); + reservedWords.add("USER_DEFINED_TYPE_CODE"); + reservedWords.add("USER_DEFINED_TYPE_NAME"); + reservedWords.add("USER_DEFINED_TYPE_SCHEMA"); + reservedWords.add("USING"); + reservedWords.add("VACUUM"); + reservedWords.add("VALID"); + reservedWords.add("VALIDATOR"); + reservedWords.add("VALUE"); + reservedWords.add("VALUES"); + reservedWords.add("VARCHAR"); + reservedWords.add("VARIABLE"); + reservedWords.add("VARYING"); + reservedWords.add("VAR_POP"); + reservedWords.add("VAR_SAMP"); + reservedWords.add("VERBOSE"); + reservedWords.add("VIEW"); + reservedWords.add("VOLATILE"); + reservedWords.add("WHEN"); + reservedWords.add("WHENEVER"); + reservedWords.add("WHERE"); + reservedWords.add("WIDTH_BUCKET"); + reservedWords.add("WINDOW"); + reservedWords.add("WITH"); + reservedWords.add("WITHIN"); + reservedWords.add("WITHOUT"); + reservedWords.add("WORK"); + reservedWords.add("WRITE"); + reservedWords.add("YEAR"); + reservedWords.add("ZONE"); + } +} diff --git a/src/main/java/ru/fusionsoft/dbgit/postgres/DBBackupAdapterPostgres.java b/src/main/java/ru/fusionsoft/dbgit/postgres/DBBackupAdapterPostgres.java index 9210d7e..faac3af 100644 --- a/src/main/java/ru/fusionsoft/dbgit/postgres/DBBackupAdapterPostgres.java +++ b/src/main/java/ru/fusionsoft/dbgit/postgres/DBBackupAdapterPostgres.java @@ -1,18 +1,17 @@ package ru.fusionsoft.dbgit.postgres; import java.io.File; -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; +import java.lang.reflect.Type; +import java.sql.*; import java.text.MessageFormat; +import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; +import ru.fusionsoft.dbgit.adapters.DBAdapter; import ru.fusionsoft.dbgit.adapters.DBBackupAdapter; -import ru.fusionsoft.dbgit.core.DBGitPath; -import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; -import ru.fusionsoft.dbgit.core.SchemaSynonym; +import ru.fusionsoft.dbgit.core.*; import ru.fusionsoft.dbgit.dbobjects.DBConstraint; import ru.fusionsoft.dbgit.dbobjects.DBIndex; import ru.fusionsoft.dbgit.meta.*; @@ -22,7 +21,7 @@ public class DBBackupAdapterPostgres extends DBBackupAdapter { @Override - public IMetaObject backupDBObject(IMetaObject obj) throws Exception { + public IMetaObject backupDBObject(IMetaObject obj) throws SQLException, ExceptionDBGit { Connection connection = adapter.getConnection(); StatementLogging stLog = new StatementLogging(connection, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); @@ -40,7 +39,7 @@ public IMetaObject backupDBObject(IMetaObject obj) throws Exception { createSchema(stLog, schema); } - ConsoleWriter.detailsPrint(lang.getValue("general", "backup", "tryingToCopy").withParams(objectName, getFullDbName(schema, objectName)), 1); + ConsoleWriter.detailsPrintln(lang.getValue("general", "backup", "tryingToCopy").withParams(objectName, getFullDbName(schema, objectName)), messageLevel); //dropIfExists(isSaveToSchema() ? PREFIX + schema : schema, // isSaveToSchema() ? objectName : PREFIX + objectName, stLog); @@ -55,11 +54,12 @@ public IMetaObject backupDBObject(IMetaObject obj) throws Exception { if (file.exists()) obj = metaSql.loadFromFile(); - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + } else if (obj instanceof MetaTable) { MetaTable metaTable = (MetaTable) obj; - metaTable.loadFromDB(); + String tableName = metaTable.getTable().getName(); String schema = metaTable.getTable().getSchema(); schema = (SchemaSynonym.getInstance().getSchema(schema) == null) ? schema : SchemaSynonym.getInstance().getSchema(schema); @@ -68,67 +68,95 @@ public IMetaObject backupDBObject(IMetaObject obj) throws Exception { String tableSamRe = schema + "\\.\\\"?" + Pattern.quote(tableName) + "\\\"?"; if(!isExists(schema, tableName)) { + //so don't actually backup, as I see... File file = new File(DBGitPath.getFullPath() + metaTable.getFileName()); if (file.exists()) obj = metaTable.loadFromFile(); return obj; } - if (isSaveToSchema()) { - createSchema(stLog, schema); - } + if (isSaveToSchema()) { createSchema(stLog, schema); } - ConsoleWriter.detailsPrint(lang.getValue("general", "backup", "tryingToCopy").withParams(tableName, getFullDbName(schema, tableName)), 1); - - dropIfExists( - isSaveToSchema() ? PREFIX + schema : schema, - isSaveToSchema() ? tableName : PREFIX + tableName, stLog - ); - - StringBuilder tableDdl = new StringBuilder(MessageFormat.format( - "create table {0} as (select * from {1}.{2} where 1={3}) {4};\n alter table {0} owner to {5};\n" + ConsoleWriter.detailsPrintln(lang.getValue("general", "backup", "tryingToCopy").withParams(tableName, getFullDbName(schema, tableName)), messageLevel); + + StringBuilder tableDdlSb = new StringBuilder(MessageFormat.format( + "create table {0} as (select * from {1}.{2} where 1={3}) {4};" , backupTableSam - , schema - , DBAdapterPostgres.escapeNameIfNeeded(tableName) - , isToSaveData() ? "1" : "0" + , adapter.escapeNameIfNeeded(schema) + , adapter.escapeNameIfNeeded(tableName) + , isToSaveData() ? "1" : "0" //TableData , metaTable.getTable().getOptions().getChildren().containsKey("tablespace") ? " tablespace " + metaTable.getTable().getOptions().get("tablespace").getData() : "" , metaTable.getTable().getOptions().get("owner").getData() )); + if(!DBGitConfig.getInstance().getToIgnoreOnwer(false)){ + String owner = metaTable.getTable().getOptions().get("owner").getData(); + tableDdlSb.append(MessageFormat.format("\nalter table {0} owner to \"{1}\";\n", backupTableSam, owner)); + } + + + Map fkRefReplaces = new HashMap<>(); + for (String fk : metaTable.getTable().getDependencies()){ + String fkname = fk.substring(fk.indexOf('/')+1,fk.lastIndexOf('.')) ; + String fkschema = fk.substring(0,fk.indexOf('/')) ; + + String nameDb = "("+fkschema+ "\\.)?" + "\\\"?" + Pattern.quote(adapter.escapeNameIfNeeded(fkname)) + "\\\"?(?=\\()"; + String nameReplacement = isSaveToSchema() + ? Matcher.quoteReplacement(adapter.escapeNameIfNeeded(PREFIX+fkschema) + "." + fkname) + : Matcher.quoteReplacement(fkschema + "." + adapter.escapeNameIfNeeded(PREFIX+fkname)); + fkRefReplaces.put(nameDb, nameReplacement); + } + + for (DBIndex index : metaTable.getIndexes().values()) { String indexName = index.getName(); String indexNameRe = "\\\"?" + Pattern.quote(indexName) + "\\\"?"; - String backupIndexNameRe = Matcher.quoteReplacement(DBAdapterPostgres.escapeNameIfNeeded(PREFIX + indexName)); + String backupIndexNameRe = Matcher.quoteReplacement(adapter.escapeNameIfNeeded( + PREFIX + indexName + + ((metaTable.getConstraints().containsKey(index.getName())) ? "_idx" : "") + )); + + String indexSql = index.getSql().replaceAll(indexNameRe, backupIndexNameRe).replaceAll(tableSamRe, backupTableSamRe); + String indexDdl = MessageFormat.format( "{0} {1};\n" - , index.getSql().replaceAll(indexNameRe, backupIndexNameRe).replaceAll(tableSamRe, backupTableSamRe) + , indexSql , metaTable.getTable().getOptions().getChildren().containsKey("tablespace") ? " tablespace "+index.getOptions().get("tablespace").getData() : "" ); - if (indexDdl.length() > 3) { tableDdl.append(indexDdl); } + if (indexDdl.length() > 3) { tableDdlSb.append(indexDdl); } } - for (DBConstraint constraint : metaTable.getConstraints().values()) { - String name = DBAdapterPostgres.escapeNameIfNeeded(PREFIX + constraint.getName()); + for (DBConstraint constraint : metaTable.getConstraints().values().stream().sorted(Comparator.comparing(x->!x.getName().toLowerCase().contains("pk"))).collect(Collectors.toList())) { + String name = adapter.escapeNameIfNeeded(PREFIX + constraint.getName()); + String constrName = constraint.getName(); + String constrNameRe = "\\\"?" + Pattern.quote(constrName) + "\\\"?"; + String backupConstrNameRe = Matcher.quoteReplacement(adapter.escapeNameIfNeeded(PREFIX + constrName)); + String constrDef = constraint.getSql().replaceAll(constrNameRe, backupConstrNameRe); + for(String reference : fkRefReplaces.keySet()){ constrDef = constrDef.replaceAll(reference, fkRefReplaces.get(reference)); } + + String constrDdl = MessageFormat.format( "alter table {0} add {1};\n" ,backupTableSam ,metaTable.getIndexes().containsKey(constraint.getName()) + && constraint.getOptions().get("constraint_type").getData().equals("p") ? "primary key using index " + name - : "constraint " + name + " " + constraint.getSql() + : "constraint " + name + " " + constrDef ); - if (constrDdl.length() > 3) { tableDdl.append(constrDdl); } + if (constrDdl.length() > 3) { tableDdlSb.append(constrDdl); } } - stLog.execute(tableDdl.toString()); + + stLog.execute(tableDdlSb.toString()); - File file = new File(DBGitPath.getFullPath() + metaTable.getFileName()); + File file = new File(DBGitPath.getFullPath() + metaTable.getFileName()); if (file.exists()) obj = metaTable.loadFromFile(); - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); } else if (obj instanceof MetaSequence) { MetaSequence metaSequence = (MetaSequence) obj; metaSequence.loadFromDB(); @@ -142,7 +170,7 @@ public IMetaObject backupDBObject(IMetaObject obj) throws Exception { String sequenceName = getFullDbName(schema, objectName); - ConsoleWriter.detailsPrint(lang.getValue("general", "backup", "tryingToCopy").withParams(objectName, getFullDbName(schema, objectName)), 1); + ConsoleWriter.detailsPrintln(lang.getValue("general", "backup", "tryingToCopy").withParams(objectName, getFullDbName(schema, objectName)), messageLevel); String ddl = "create sequence " + sequenceName + "\n" + (metaSequence.getSequence().getOptions().get("cycle_option").toString().equals("YES") ? "CYCLE\n" : "") @@ -150,8 +178,10 @@ public IMetaObject backupDBObject(IMetaObject obj) throws Exception { + " START " + metaSequence.getSequence().getOptions().get("start_value").toString() + "\n" + " MINVALUE " + metaSequence.getSequence().getOptions().get("minimum_value").toString() + "\n" + " MAXVALUE " + metaSequence.getSequence().getOptions().get("maximum_value").toString() + ";\n"; - - ddl += "alter sequence "+ sequenceName + " owner to "+ metaSequence.getSequence().getOptions().get("owner").getData()+";\n"; + + if(!DBGitConfig.getInstance().getToIgnoreOnwer(false)){ + ddl += "alter sequence "+ sequenceName + " owner to \""+ metaSequence.getSequence().getOptions().get("owner").getData()+"\";\n"; + } dropIfExists( isSaveToSchema() ? PREFIX + schema : schema, @@ -163,18 +193,17 @@ public IMetaObject backupDBObject(IMetaObject obj) throws Exception { File file = new File(DBGitPath.getFullPath() + metaSequence.getFileName()); if (file.exists()) obj = metaSequence.loadFromFile(); - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); } } catch (SQLException e1) { - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError"). - withParams(obj.getName() + ": " + e1.getLocalizedMessage())); + throw new ExceptionDBGit( + lang.getValue("errors", "backup", "backupError").withParams(obj.getName()) + , e1 + ); } catch (Exception e) { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - connection.rollback(); throw new ExceptionDBGitRestore(lang.getValue("errors", "backup", "backupError").withParams(obj.getName()), e); } finally { - connection.commit(); stLog.close(); } return obj; @@ -188,15 +217,15 @@ public void restoreDBObject(IMetaObject obj) throws Exception { private String getFullDbName(String schema, String objectName) { if (isSaveToSchema()){ - return PREFIX + schema + "." + DBAdapterPostgres.escapeNameIfNeeded(objectName); + return adapter.escapeNameIfNeeded(PREFIX + schema) + "." + adapter.escapeNameIfNeeded(objectName); } else { - return schema + "." + DBAdapterPostgres.escapeNameIfNeeded(PREFIX + objectName); + return adapter.escapeNameIfNeeded(schema) + "." + adapter.escapeNameIfNeeded(PREFIX + objectName); } } - private void dropIfExists(String owner, String objectName, StatementLogging stLog) throws Exception { + public void dropIfExists(String owner, String objectName, StatementLogging stLog) throws SQLException { Statement st = adapter.getConnection().createStatement(); ResultSet rs = st.executeQuery("select * from (\r\n" + " SELECT 'TABLE' tp, table_name obj_name, table_schema sch FROM information_schema.tables \r\n" + @@ -208,18 +237,51 @@ private void dropIfExists(String owner, String objectName, StatementLogging stLo "where sch = '" + owner.toLowerCase() + "' and obj_name = '"+objectName+"'"); while (rs.next()) { - stLog.execute("drop " + rs.getString("tp") + " " + owner + "." + DBAdapterPostgres.escapeNameIfNeeded(objectName)); + stLog.execute("drop " + rs.getString("tp") + " " + adapter.escapeNameIfNeeded(owner) + "." + adapter.escapeNameIfNeeded(objectName)); } rs.close(); st.close(); } + public void dropIfExists(IMetaObject imo, StatementLogging stLog) throws Exception { + NameMeta nm = new NameMeta(imo); + DBGitMetaType type = (DBGitMetaType) nm.getType(); + + Statement st = adapter.getConnection().createStatement(); + ResultSet rs = st.executeQuery(MessageFormat.format("select * from (\r\n" + + " SELECT ''TABLE'' tp, table_name obj_name, table_schema sch FROM information_schema.tables WHERE 1={0}\r\n" + + " union select ''VIEW'' tp, table_name obj_name, table_schema sch from information_schema.views WHERE 1={1}\r\n" + + " union select ''SEQUENCE'' tp, sequence_name obj_name, sequence_schema sch from information_schema.sequences WHERE 1={2}\r\n" + + " union select ''TRIGGER'' tp, trigger_name obj_name, trigger_schema sch from information_schema.triggers WHERE 1={3}\r\n" + + " union select ''FUNCTION'' tp, routine_name obj_name, routine_schema sch from information_schema.routines WHERE 1={4}\r\n" + + ") all_objects\r\n" + + "where sch = ''{5}'' and obj_name = ''{6}''", + type.equals(DBGitMetaType.DBGitTable) ? "1" : "0", + type.equals(DBGitMetaType.DbGitView) ? "1" : "0", + type.equals(DBGitMetaType.DBGitSequence) ? "1" : "0", + type.equals(DBGitMetaType.DbGitTrigger) ? "1" : "0", + type.equals(DBGitMetaType.DbGitFunction) ? "1" : "0", + nm.getSchema(), nm.getName() + )); + + while (rs.next()) { + stLog.execute(MessageFormat.format("DROP {0} {1}.{2}", + rs.getString("tp"), + adapter.escapeNameIfNeeded(nm.getSchema()), + adapter.escapeNameIfNeeded(nm.getName()) + )); + } + + rs.close(); + st.close(); + } @Override - public boolean isExists(String owner, String objectName) throws Exception { + public boolean isExists(String owner, String objectName) throws SQLException { Statement st = adapter.getConnection().createStatement(); - ResultSet rs = st.executeQuery("select count(*) cnt from (\r\n" + - " SELECT 'TABLE' tp, table_name obj_name, table_schema sch FROM information_schema.tables \r\n" + + ResultSet rs = st.executeQuery( + "select count(*) cnt from (\r\n" + + " SELECT 'TABLE' tp, table_name obj_name, table_schema sch FROM information_schema.tables \r\n" + " union select 'VIEW' tp, table_name obj_name, table_schema sch from information_schema.views\r\n" + " union select 'SEQUENCE' tp, sequence_name obj_name, sequence_schema sch from information_schema.sequences\r\n" + " union select 'TRIGGER' tp, trigger_name obj_name, trigger_schema sch from information_schema.triggers\r\n" + @@ -233,27 +295,35 @@ public boolean isExists(String owner, String objectName) throws Exception { @Override public boolean createSchema(StatementLogging stLog, String schema) { + if(createdSchemas.contains(schema)) return true; try { Statement st = adapter.getConnection().createStatement(); - ResultSet rs = st.executeQuery("select count(*) cnt from information_schema.schemata where upper(schema_name) = '" + - PREFIX + schema.toUpperCase() + "'"); + String query = MessageFormat.format( + "select count(*) cnt from information_schema.schemata where schema_name = ''{0}{1}''", + PREFIX, schema + ); + ResultSet rs = st.executeQuery(query); rs.next(); if (rs.getInt("cnt") == 0) { - ConsoleWriter.detailsPrintLn(lang.getValue("general", "backup", "creatingSchema").withParams(PREFIX + schema)); - stLog.execute("create schema " + PREFIX + schema); + ConsoleWriter.detailsPrintln(lang.getValue("general", "backup", "creatingSchema").withParams(PREFIX + schema), messageLevel); + stLog.execute("create schema " + adapter.escapeNameIfNeeded(PREFIX + schema)); } rs.close(); st.close(); - + createdSchemas.add(schema); + return true; } catch (SQLException e) { - ConsoleWriter.println(lang.getValue("errors", "backup", "cannotCreateSchema").withParams(e.getLocalizedMessage())); + ConsoleWriter.println(lang.getValue("errors", "backup", "cannotCreateSchema") + .withParams(e.getLocalizedMessage()) + , messageLevel + ); return false; } } - + private Set createdSchemas = new HashSet(); } diff --git a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreDomainPostgres.java b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreDomainPostgres.java new file mode 100644 index 0000000..56039a1 --- /dev/null +++ b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreDomainPostgres.java @@ -0,0 +1,122 @@ +package ru.fusionsoft.dbgit.postgres; + +import java.sql.Connection; +import java.text.MessageFormat; +import java.util.Map; +import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter; +import ru.fusionsoft.dbgit.adapters.IDBAdapter; +import ru.fusionsoft.dbgit.core.DBGitConfig; +import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; +import ru.fusionsoft.dbgit.dbobjects.DBDomain; +import ru.fusionsoft.dbgit.dbobjects.DBSQLObject; +import ru.fusionsoft.dbgit.meta.IMetaObject; +import ru.fusionsoft.dbgit.meta.MetaDomain; +import ru.fusionsoft.dbgit.statement.StatementLogging; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; + +public class DBRestoreDomainPostgres extends DBRestoreAdapter { + @Override + public final boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { + final IDBAdapter adapter = getAdapter(); + final Connection connect = adapter.getConnection(); + try (final StatementLogging st = new StatementLogging( + connect, + adapter.getStreamOutputSqlCommand(), + adapter.isExecSql() + )) { + if (! ( obj instanceof MetaDomain )) { + throw new ExceptionDBGitRestore( + lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName(), + "domain", + obj.getType().getValue() + ) + ); + } + final DBSQLObject restoreDomain = (DBSQLObject) obj.getUnderlyingDbObject(); + final Map domains = adapter.getDomains(restoreDomain.getSchema()); + + if (domains.containsKey(restoreDomain.getName())) { + final DBDomain currentDomain = domains.get(restoreDomain.getName()); + if ( + ! restoreDomain.getOptions().get("attributes").equals( + currentDomain.getOptions().get("attributes") + ) + ) { + st.execute(MessageFormat.format( + "DROP DOMAIN IF EXISTS {0}._deprecated_{1} RESTRICT;\n" + + "ALTER DOMAIN {0}.{1} RENAME TO _deprecated_{1};\n" + + "{2}", + currentDomain.getSchema(), currentDomain.getName(), getDdlEscaped(restoreDomain) + )); + } else { + if (! DBGitConfig.getInstance().getToIgnoreOnwer(false)) { + st.execute(getChangeOwnerDdl(currentDomain, restoreDomain.getOwner())); + } + } + } else { + st.execute(getDdlEscaped(restoreDomain)); + } + + } catch (Exception e) { + throw new ExceptionDBGitRestore( + lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), + e + ); + } finally { + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + } + return true; + } + + @Override + public void removeMetaObject(IMetaObject obj) throws Exception { + final IDBAdapter adapter = getAdapter(); + final Connection connect = adapter.getConnection(); + + try (StatementLogging st = new StatementLogging( + connect, + adapter.getStreamOutputSqlCommand(), + adapter.isExecSql() + )) { + + final DBSQLObject currentObject = (DBSQLObject) obj.getUnderlyingDbObject(); + st.execute(MessageFormat.format( + "DROP DOMAIN IF EXISTS {0}.{1} RESTRICT", + adapter.escapeNameIfNeeded(getPhisicalSchema(currentObject.getSchema())), + adapter.escapeNameIfNeeded(currentObject.getName()) + )); + + } catch (Exception e) { + throw new ExceptionDBGitRestore( + lang.getValue("errors", "restore", "objectRemoveError") + .withParams(obj.getName()), e); + } + } + + private String getDdlEscaped(DBSQLObject dbsqlObject) { + String query = dbsqlObject.getSql(); + final String name = dbsqlObject.getName(); + final String schema = dbsqlObject.getSchema(); + final String nameEscaped = adapter.escapeNameIfNeeded(name); + final String schemaEscaped = adapter.escapeNameIfNeeded(schema); + + if (! name.equalsIgnoreCase(nameEscaped)) { + query = query.replace( + "CREATE DOMAIN " + schema + "." + name, + "CREATE DOMAIN " + schemaEscaped + "." + nameEscaped + ); + } + if (! query.endsWith(";")) query = query + ";\n"; + query = query + "\n"; + return query; + } + + private String getChangeOwnerDdl(DBSQLObject dbsqlObject, String owner) { + return MessageFormat.format("ALTER TYPE {0}.{1} OWNER TO {2}\n" + , adapter.escapeNameIfNeeded(dbsqlObject.getSchema()) + , adapter.escapeNameIfNeeded(dbsqlObject.getName()) + , owner + ); + } +} diff --git a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreEnumPostgres.java b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreEnumPostgres.java new file mode 100644 index 0000000..f781be4 --- /dev/null +++ b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreEnumPostgres.java @@ -0,0 +1,112 @@ +package ru.fusionsoft.dbgit.postgres; + +import java.sql.Connection; +import java.text.MessageFormat; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter; +import ru.fusionsoft.dbgit.adapters.IDBAdapter; +import ru.fusionsoft.dbgit.core.DBGitConfig; +import ru.fusionsoft.dbgit.core.ExceptionDBGit; +import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; +import ru.fusionsoft.dbgit.dbobjects.DBEnum; +import ru.fusionsoft.dbgit.dbobjects.DBSQLObject; +import ru.fusionsoft.dbgit.meta.IMetaObject; +import ru.fusionsoft.dbgit.meta.MetaEnum; +import ru.fusionsoft.dbgit.statement.StatementLogging; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; + +public class DBRestoreEnumPostgres extends DBRestoreAdapter { + @Override + public final boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { + final IDBAdapter adapter = getAdapter(); + final Connection connect = adapter.getConnection(); + try (StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql())) { + if (! ( obj instanceof MetaEnum )) { + throw new ExceptionDBGitRestore( + lang.getValue("errors", "restore", "metaTypeError") + .withParams(obj.getName(), "enum", obj.getType().getValue()) + ); + } + final DBSQLObject restoreEnum = (DBSQLObject) obj.getUnderlyingDbObject(); + final Map enums = adapter.getEnums(restoreEnum.getSchema()); + + if(enums.containsKey(restoreEnum.getName())) { + DBEnum currentEnum = enums.get(restoreEnum.getName()); + if( + ! restoreEnum.getOptions().get("elements").equals( + currentEnum.getOptions().get("elements") + ) + ) { + st.execute(MessageFormat.format( + "ALTER TYPE {0}.{1} RENAME TO _deprecated_{1};\n{2}", + currentEnum.getSchema(), currentEnum.getName(), getDdlEscaped(restoreEnum) + )); + } else{ + if (! DBGitConfig.getInstance().getToIgnoreOnwer(false)) { + st.execute(getChangeOwnerDdl(currentEnum, restoreEnum.getOwner())); + } + } + } else { + st.execute(getDdlEscaped(restoreEnum)); + } + + } catch (Exception e) { + throw new ExceptionDBGitRestore( + lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), + e + ); + } finally { + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + } + return true; + } + + @Override + public void removeMetaObject(IMetaObject obj) throws Exception { + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + + try (StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql())){ + + final DBSQLObject currentObject = (DBSQLObject) obj.getUnderlyingDbObject(); + st.execute(MessageFormat.format( + "DROP TYPE {0}.{1}", + adapter.escapeNameIfNeeded(getPhisicalSchema(currentObject.getSchema())), + adapter.escapeNameIfNeeded(currentObject.getName()) + )); + + } catch (Exception e) { + throw new ExceptionDBGitRestore( + lang.getValue("errors", "restore", "objectRemoveError") + .withParams(obj.getName()), e); + } + } + + private String getDdlEscaped(DBSQLObject dbsqlObject) { + String query = dbsqlObject.getSql(); + final String name = dbsqlObject.getName(); + final String schema = dbsqlObject.getSchema(); + final String nameEscaped = adapter.escapeNameIfNeeded(name); + final String schemaEscaped = adapter.escapeNameIfNeeded(schema); + + if (! name.equalsIgnoreCase(nameEscaped)) { + query = query.replace( + "CREATE TYPE " + schema + "." + name, + "CREATE TYPE " + schemaEscaped + "." + nameEscaped + ); + } + if (! query.endsWith(";")) query = query + ";\n"; + query = query + "\n"; + return query; + } + + private String getChangeOwnerDdl(DBSQLObject dbsqlObject, String owner) { + return MessageFormat.format("ALTER TYPE {0}.{1} OWNER TO {2}\n" + , adapter.escapeNameIfNeeded(dbsqlObject.getSchema()) + , adapter.escapeNameIfNeeded(dbsqlObject.getName()) + , owner + ); + } +} diff --git a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreFunctionPostgres.java b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreFunctionPostgres.java index 3910064..6d1c3ee 100644 --- a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreFunctionPostgres.java +++ b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreFunctionPostgres.java @@ -1,110 +1,101 @@ -package ru.fusionsoft.dbgit.postgres; - -import java.sql.Connection; -import java.util.Map; - -import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter; -import ru.fusionsoft.dbgit.adapters.IDBAdapter; -import ru.fusionsoft.dbgit.core.ExceptionDBGit; -import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; -import ru.fusionsoft.dbgit.dbobjects.DBFunction; -import ru.fusionsoft.dbgit.meta.IMetaObject; -import ru.fusionsoft.dbgit.meta.MetaFunction; -import ru.fusionsoft.dbgit.statement.StatementLogging; -import ru.fusionsoft.dbgit.utils.ConsoleWriter; - -public class DBRestoreFunctionPostgres extends DBRestoreAdapter { - - @Override - public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { - IDBAdapter adapter = getAdapter(); - Connection connect = adapter.getConnection(); - StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "restoreFnc").withParams(obj.getName()), 1); - try { - if (obj instanceof MetaFunction) { - MetaFunction restoreFunction = (MetaFunction)obj; - String restoreFunctionName = DBAdapterPostgres.escapeNameIfNeeded(restoreFunction.getSqlObject().getName()); - Map functions = adapter.getFunctions(restoreFunction.getSqlObject().getSchema()); - boolean exist = false; - if(!(functions.isEmpty() || functions == null)) { - for(DBFunction fnc:functions.values()) { - if(restoreFunctionName.equals(DBAdapterPostgres.escapeNameIfNeeded(fnc.getName()))){ - exist = true; - - //if codes differ - if( !restoreFunction.getSqlObject().getSql() - .replace(" ", "") - .equals(fnc.getSql().replace(" ", "")) - ) { - st.execute(restoreFunction.getSqlObject().getSql()); - } - - //if owners differ - if(!restoreFunction.getSqlObject().getOwner().equals(fnc.getOwner())) { - //without arguments - if(restoreFunction.getSqlObject().getOptions().get("arguments").getData() == null || restoreFunction.getSqlObject().getOptions().get("arguments").getData().isEmpty()) { - st.execute( - "ALTER FUNCTION "+ restoreFunctionName + "() OWNER TO " - + restoreFunction.getSqlObject().getOwner()) - ; - } - //with arguments - else { - st.execute( - "ALTER FUNCTION "+restoreFunctionName +"(" - + restoreFunction.getSqlObject().getOptions().get("arguments").getData() - + ") OWNER TO " + restoreFunction.getSqlObject().getOwner() - ); - } - } - //TODO Восстановление привилегий - } - } - } - if(!exist){ - st.execute(restoreFunction.getSqlObject().getSql()); - //TODO Восстановление привилегий - } - } - else - { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); - } - } catch (Exception e) { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - ConsoleWriter.detailsPrintlnRed(e.getLocalizedMessage()); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); - } finally { - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); - st.close(); - connect.commit(); - } - return true; - } - - @Override - public void removeMetaObject(IMetaObject obj) throws Exception { - IDBAdapter adapter = getAdapter(); - Connection connect = adapter.getConnection(); - StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - - try { - if(! (obj instanceof MetaFunction)) throw new ExceptionDBGit("Wrong IMetaObject type, expected: fnc, was: " + obj.getType().getValue()); - MetaFunction fncMeta = (MetaFunction) obj; - DBFunction fnc = (DBFunction) fncMeta.getSqlObject(); - if (fnc == null) return; - - String schema = getPhisicalSchema(fnc.getSchema()); - st.execute("DROP FUNCTION "+schema+"."+DBAdapterPostgres.escapeNameIfNeeded(fnc.getName())); - connect.commit(); - } catch (Exception e) { - ConsoleWriter.println(lang.getValue("errors", "restore", "objectRestoreError").withParams(e.getLocalizedMessage())); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRemoveError").withParams(obj.getName()), e); - } finally { - st.close(); - } - } - -} +package ru.fusionsoft.dbgit.postgres; + +import java.sql.Connection; +import java.text.MessageFormat; +import java.util.Map; + +import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter; +import ru.fusionsoft.dbgit.adapters.IDBAdapter; +import ru.fusionsoft.dbgit.core.ExceptionDBGit; +import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; +import ru.fusionsoft.dbgit.dbobjects.DBFunction; +import ru.fusionsoft.dbgit.meta.IMetaObject; +import ru.fusionsoft.dbgit.meta.MetaFunction; +import ru.fusionsoft.dbgit.statement.StatementLogging; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; +import ru.fusionsoft.dbgit.utils.StringProperties; + +public class DBRestoreFunctionPostgres extends DBRestoreAdapter { + + @Override + public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + try(StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql());) { + if (obj instanceof MetaFunction) { + + MetaFunction restoreFunction = (MetaFunction)obj; + String restoreFunctionName = restoreFunction.getSqlObject().getName(); + Map functions = adapter.getFunctions(restoreFunction.getSqlObject().getSchema()); + boolean exist = false; + if(!(functions.isEmpty() || functions == null)) { + for(DBFunction fnc:functions.values()) { + if(restoreFunctionName.equals(fnc.getName())){ + exist = true; + + //if codes differ + if( !restoreFunction.getSqlObject().getSql() + .replace(" ", "") + .equals(fnc.getSql().replace(" ", "")) + ) { + st.execute(restoreFunction.getSqlObject().getSql()); + } + + //if owners differ + if(!restoreFunction.getSqlObject().getOwner().equals(fnc.getOwner())) { + StringProperties restoreProcArgs = restoreFunction.getSqlObject().getOptions().get("arguments"); + String args = restoreProcArgs != null ? restoreProcArgs.getData().replaceAll("(\\w+ \\w+) (DEFAULT [^\\,\\n]+)(\\,|\\b)", "$1") : ""; + + st.execute(MessageFormat.format("ALTER FUNCTION {0}.{1}({2}) OWNER TO \"{3}\"" + , restoreFunction.getUnderlyingDbObject().getSchema() + , adapter.escapeNameIfNeeded(restoreFunctionName) + , args + , restoreFunction.getSqlObject().getOwner()) + ); + } + //TODO Восстановление привилегий + } + } + } + if(!exist){ + st.execute(restoreFunction.getSqlObject().getSql()); + //TODO Восстановление привилегий + } + } + else + { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "function", obj.getType().getValue() + )); + } + } catch (Exception e) { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); + } finally { + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + } + return true; + } + + @Override + public void removeMetaObject(IMetaObject obj) throws Exception { + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + + try { + if(! (obj instanceof MetaFunction)) throw new ExceptionDBGit("Wrong IMetaObject type, expected: fnc, was: " + obj.getType().getValue()); + MetaFunction fncMeta = (MetaFunction) obj; + DBFunction fnc = (DBFunction) fncMeta.getSqlObject(); + if (fnc == null) return; + + String schema = getPhisicalSchema(fnc.getSchema()); + st.execute("DROP FUNCTION "+adapter.escapeNameIfNeeded(schema)+"."+adapter.escapeNameIfNeeded(fnc.getName())); + } catch (Exception e) { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRemoveError").withParams(obj.getName()), e); + } finally { + st.close(); + } + } + +} diff --git a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreProcedurePostgres.java b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreProcedurePostgres.java index 88d55e5..a8edf38 100644 --- a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreProcedurePostgres.java +++ b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreProcedurePostgres.java @@ -1,115 +1,105 @@ -package ru.fusionsoft.dbgit.postgres; - -import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter; -import ru.fusionsoft.dbgit.adapters.IDBAdapter; -import ru.fusionsoft.dbgit.core.ExceptionDBGit; -import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; -import ru.fusionsoft.dbgit.dbobjects.DBProcedure; -import ru.fusionsoft.dbgit.meta.IMetaObject; -import ru.fusionsoft.dbgit.meta.MetaProcedure; -import ru.fusionsoft.dbgit.meta.NameMeta; -import ru.fusionsoft.dbgit.statement.StatementLogging; -import ru.fusionsoft.dbgit.utils.ConsoleWriter; - -import java.sql.Connection; -import java.text.MessageFormat; -import java.util.Map; - -public class DBRestoreProcedurePostgres extends DBRestoreAdapter { - - @Override - public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { - IDBAdapter adapter = getAdapter(); - Connection connect = adapter.getConnection(); - StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "restorePrc").withParams(obj.getName()), 1); - try { - if (obj instanceof MetaProcedure) { - MetaProcedure restoreProc = (MetaProcedure)obj; - NameMeta nm = new NameMeta(restoreProc); - String restoreProcName = DBAdapterPostgres.escapeNameIfNeeded(nm.getName()); - Map procs = adapter.getProcedures(nm.getSchema()); - boolean exist = false; - if(!(procs.isEmpty() || procs == null)) { - for(DBProcedure prc : procs.values()) { - if(restoreProcName.equals(DBAdapterPostgres.escapeNameIfNeeded(prc.getName()))){ - exist = true; - - //if codes differ - if( !restoreProc.getSqlObject().getSql() - .replaceAll("\\s+", "") - .equals(prc.getSql().replaceAll("\\s+", "")) - ) { - st.execute(restoreProc.getSqlObject().getSql()); - } - - //if owners differ - if(!restoreProc.getSqlObject().getOwner().equals(prc.getOwner())) { - //without arguments - if( restoreProc.getSqlObject().getOptions().get("arguments").getData() == null || - restoreProc.getSqlObject().getOptions().get("arguments").getData().isEmpty() - ) { - st.execute(MessageFormat.format("ALTER PROCEDURE {0}() OWNER TO {2}" - , restoreProcName - , restoreProc.getSqlObject().getOwner())); - } - //with arguments - else { - st.execute(MessageFormat.format("ALTER PROCEDURE {0}({1}) OWNER TO {2}" - , restoreProcName - , restoreProc.getSqlObject().getOptions().get("arguments").getData() - , restoreProc.getSqlObject().getOwner())); - } - } - //TODO Восстановление привилегий - } - } - } - if(!exist){ - st.execute(restoreProc.getSqlObject().getSql()); - //TODO Восстановление привилегий - } - } - else - { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); - } - } catch (Exception e) { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - ConsoleWriter.detailsPrintlnRed(e.getLocalizedMessage()); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); - } finally { - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); - st.close(); - connect.commit(); - } - return true; - } - - @Override - public void removeMetaObject(IMetaObject obj) throws Exception - { - IDBAdapter adapter = getAdapter(); - Connection connect = adapter.getConnection(); - StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - - try { - if(! (obj instanceof MetaProcedure)) throw new ExceptionDBGit("Wrong IMetaObject type, expected: prc, was: " + obj.getType().getValue()); - MetaProcedure prcMeta = (MetaProcedure) obj; - DBProcedure prc = (DBProcedure) prcMeta.getSqlObject(); - if (prc == null) return; - - String schema = getPhisicalSchema(prc.getSchema()); - st.execute("DROP PROCEDURE "+schema+"."+DBAdapterPostgres.escapeNameIfNeeded(prc.getName())); - connect.commit(); - } catch (Exception e) { - ConsoleWriter.println(lang.getValue("errors", "restore", "objectRestoreError").withParams(e.getLocalizedMessage())); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRemoveError").withParams(obj.getName()), e); - } finally { - st.close(); - } - - } - -} +package ru.fusionsoft.dbgit.postgres; + +import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter; +import ru.fusionsoft.dbgit.adapters.IDBAdapter; +import ru.fusionsoft.dbgit.core.DBGitConfig; +import ru.fusionsoft.dbgit.core.ExceptionDBGit; +import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; +import ru.fusionsoft.dbgit.dbobjects.DBProcedure; +import ru.fusionsoft.dbgit.meta.IMetaObject; +import ru.fusionsoft.dbgit.meta.MetaProcedure; +import ru.fusionsoft.dbgit.meta.NameMeta; +import ru.fusionsoft.dbgit.statement.StatementLogging; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; +import ru.fusionsoft.dbgit.utils.StringProperties; + +import java.sql.Connection; +import java.text.MessageFormat; +import java.util.Map; + +public class DBRestoreProcedurePostgres extends DBRestoreAdapter { + + @Override + public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + try { + if (obj instanceof MetaProcedure) { + MetaProcedure restoreProc = (MetaProcedure)obj; + NameMeta nm = new NameMeta(restoreProc); + String restoreProcName = nm.getName(); + Map procs = adapter.getProcedures(nm.getSchema()); + boolean exist = false; + if(!(procs.isEmpty() || procs == null)) { + for(DBProcedure prc : procs.values()) { + if(restoreProcName.equals(prc.getName())){ + exist = true; + + //if codes differ + if( !restoreProc.getSqlObject().getSql() + .replaceAll("\\s+", "") + .equals(prc.getSql().replaceAll("\\s+", "")) + ) { + st.execute(restoreProc.getSqlObject().getSql()); + } + //if owners differ + if(!DBGitConfig.getInstance().getToIgnoreOnwer(false) && !restoreProc.getSqlObject().getOwner().equals(prc.getOwner())) { + StringProperties restoreProcArgs = restoreProc.getSqlObject().getOptions().get("arguments"); + String args = restoreProcArgs != null ? restoreProcArgs.getData().replaceAll("(\\w+ \\w+) (DEFAULT [^\\,\\n]+)(\\,|\\b)", "$1") : ""; + + st.execute(MessageFormat.format("ALTER PROCEDURE {0}.{1}({2}) OWNER TO \"{3}\"" + , nm.getSchema() + , adapter.escapeNameIfNeeded(restoreProcName) + , args + , restoreProc.getSqlObject().getOwner())); + } + //TODO Восстановление привилегий + } + } + } + if(!exist){ + st.execute(restoreProc.getSqlObject().getSql()); + //TODO Восстановление привилегий + } + } + else + { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "procedure", obj.getType().getValue() + )); + } + } catch (Exception e) { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); + } finally { + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + st.close(); + } + return true; + } + + @Override + public void removeMetaObject(IMetaObject obj) throws Exception + { + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + + try { + if(! (obj instanceof MetaProcedure)) throw new ExceptionDBGit("Wrong IMetaObject type, expected: prc, was: " + obj.getType().getValue()); + MetaProcedure prcMeta = (MetaProcedure) obj; + DBProcedure prc = (DBProcedure) prcMeta.getSqlObject(); + if (prc == null) return; + + String schema = getPhisicalSchema(prc.getSchema()); + st.execute("DROP PROCEDURE "+schema+"."+adapter.escapeNameIfNeeded(prc.getName())); + } catch (Exception e) { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRemoveError").withParams(obj.getName()), e); + } finally { + st.close(); + } + + } + +} diff --git a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreRolePostgres.java b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreRolePostgres.java index 690c950..4f7310d 100644 --- a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreRolePostgres.java +++ b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreRolePostgres.java @@ -19,7 +19,6 @@ public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { IDBAdapter adapter = getAdapter(); Connection connect = adapter.getConnection(); StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "restoreRole").withParams(obj.getName()), 1); try { if (obj instanceof MetaRole) { MetaRole restoreRole = (MetaRole)obj; @@ -193,14 +192,15 @@ public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { } else { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "role", obj.getType().getValue() + )); } } catch (Exception e) { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); } finally { - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); st.close(); } return true; diff --git a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreSchemaPostgres.java b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreSchemaPostgres.java index 4e214ce..6bce6ca 100644 --- a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreSchemaPostgres.java +++ b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreSchemaPostgres.java @@ -1,66 +1,71 @@ -package ru.fusionsoft.dbgit.postgres; -import java.sql.Connection; -import java.util.Map; - -import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter; -import ru.fusionsoft.dbgit.adapters.IDBAdapter; -import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; -import ru.fusionsoft.dbgit.dbobjects.DBSchema; -import ru.fusionsoft.dbgit.meta.IMetaObject; -import ru.fusionsoft.dbgit.meta.MetaSchema; -import ru.fusionsoft.dbgit.statement.StatementLogging; -import ru.fusionsoft.dbgit.utils.ConsoleWriter; - - -public class DBRestoreSchemaPostgres extends DBRestoreAdapter { - @Override - public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { - IDBAdapter adapter = getAdapter(); - Connection connect = adapter.getConnection(); - StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "restoreSchema").withParams(obj.getName()), 1); - try { - if (obj instanceof MetaSchema) { - MetaSchema restoreSchema = (MetaSchema)obj; - Map schs = adapter.getSchemes(); - boolean exist = false; - if(!(schs.isEmpty() || schs == null)) { - for(DBSchema sch:schs.values()) { - if(restoreSchema.getObjectOption().getName().equals(sch.getName())){ - exist = true; - //String test1 = changedsch.getObjectOption().getName(); - //String test2 = changedsch.getObjectOption().getOptions().getChildren().get("usename").getData(); - if(!restoreSchema.getObjectOption().getOptions().getChildren().get("usename").getData().equals(sch.getOptions().getChildren().get("usename").getData())) { - st.execute("ALTER SCHEMA "+ restoreSchema.getObjectOption().getName() +" OWNER TO "+ - restoreSchema.getObjectOption().getOptions().getChildren().get("usename").getData()); - } - //TODO Восстановление привилегий - } - } - } - if(!exist){ - st.execute("CREATE SCHEMA "+restoreSchema.getObjectOption().getName() +" AUTHORIZATION "+ - restoreSchema.getObjectOption().getOptions().getChildren().get("usename").getData()); - //TODO Восстановление привилегий - } - } - else - { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); - } - } catch (Exception e) { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); - } finally { - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); - st.close(); - } - return true; - } - - public void removeMetaObject(IMetaObject obj) { - // TODO Auto-generated method stub - } - -} +package ru.fusionsoft.dbgit.postgres; +import java.sql.Connection; +import java.util.Map; + +import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter; +import ru.fusionsoft.dbgit.adapters.IDBAdapter; +import ru.fusionsoft.dbgit.core.DBGitConfig; +import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; +import ru.fusionsoft.dbgit.dbobjects.DBSchema; +import ru.fusionsoft.dbgit.meta.IMetaObject; +import ru.fusionsoft.dbgit.meta.MetaSchema; +import ru.fusionsoft.dbgit.statement.StatementLogging; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; + + +public class DBRestoreSchemaPostgres extends DBRestoreAdapter { + @Override + public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + try { + if (obj instanceof MetaSchema) { + MetaSchema restoreSchema = (MetaSchema)obj; + Map schs = adapter.getSchemes(); + boolean exist = false; + if(!(schs.isEmpty() || schs == null)) { + for(DBSchema sch:schs.values()) { + if(restoreSchema.getObjectOption().getName().equals(sch.getName())){ + exist = true; + //String test1 = changedsch.getObjectOption().getName(); + //String test2 = changedsch.getObjectOption().getOptions().getChildren().get("usename").getData(); + if(!DBGitConfig.getInstance().getToIgnoreOnwer(false)){ + if(!restoreSchema.getObjectOption().getOptions().getChildren().get("usename").getData().equals(sch.getOptions().getChildren().get("usename").getData())) { + st.execute( + "ALTER SCHEMA "+ restoreSchema.getObjectOption().getName() +" OWNER TO \""+ + restoreSchema.getObjectOption().getOptions().getChildren().get("usename").getData() + "\"" + ); + } + } + //TODO Восстановление привилегий + } + } + } + if(!exist){ + st.execute("CREATE SCHEMA "+restoreSchema.getObjectOption().getName() +" AUTHORIZATION "+ + restoreSchema.getObjectOption().getOptions().getChildren().get("usename").getData()); + //TODO Восстановление привилегий + } + } + else + { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "schema", obj.getType().getValue() + )); + } + } catch (Exception e) { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); + } finally { + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + st.close(); + } + return true; + } + + public void removeMetaObject(IMetaObject obj) { + // TODO Auto-generated method stub + } + +} diff --git a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreSequencePostgres.java b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreSequencePostgres.java index 103b4a9..8c91460 100644 --- a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreSequencePostgres.java +++ b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreSequencePostgres.java @@ -1,137 +1,148 @@ -package ru.fusionsoft.dbgit.postgres; - -import java.sql.Connection; -import java.util.Map; - -import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter; -import ru.fusionsoft.dbgit.adapters.IDBAdapter; -import ru.fusionsoft.dbgit.core.ExceptionDBGit; -import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; -import ru.fusionsoft.dbgit.dbobjects.DBFunction; -import ru.fusionsoft.dbgit.dbobjects.DBSequence; -import ru.fusionsoft.dbgit.meta.IMetaObject; -import ru.fusionsoft.dbgit.meta.MetaFunction; -import ru.fusionsoft.dbgit.meta.MetaSequence; -import ru.fusionsoft.dbgit.statement.StatementLogging; -import ru.fusionsoft.dbgit.utils.ConsoleWriter; - -public class DBRestoreSequencePostgres extends DBRestoreAdapter { - - @Override - public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { - IDBAdapter adapter = getAdapter(); - Connection connect = adapter.getConnection(); - StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "restoreSeq").withParams(obj.getName()), 1); - try { - if (obj instanceof MetaSequence) { - MetaSequence restoreSeq = (MetaSequence)obj; - Map seqs = adapter.getSequences(((MetaSequence) obj).getSequence().getSchema()); - boolean exist = false; - if(!(seqs.isEmpty() || seqs == null)) { - for(DBSequence seq:seqs.values()) { - if(restoreSeq.getSequence().getName().equals(seq.getName())){ - String query=""; - exist = true; - String sequence = restoreSeq.getSequence().getSchema()+ "." +restoreSeq.getSequence().getName(); - if(!restoreSeq.getSequence().getOptions().get("cycle_option").equals(seq.getOptions().get("cycle_option"))) { - if(restoreSeq.getSequence().getOptions().get("cycle_option").equals("YES")) { - query+="alter sequence "+sequence + " cycle;\n"; - } - else { - query+="alter sequence "+sequence + " no cycle;\n"; - } - } - - if(!restoreSeq.getSequence().getOptions().get("increment").equals(seq.getOptions().get("increment"))) { - query+="alter sequence "+sequence+ " increment "+restoreSeq.getSequence().getOptions().get("increment")+";\n"; - } - - if(!restoreSeq.getSequence().getOptions().get("start_value").equals(seq.getOptions().get("start_value"))) { - query+="alter sequence "+sequence+" start "+restoreSeq.getSequence().getOptions().get("start_value")+";\n"; - } - - if(!restoreSeq.getSequence().getOptions().get("minimum_value").equals(seq.getOptions().get("minimum_value"))) { - query+="alter sequence "+sequence+ " minvalue "+restoreSeq.getSequence().getOptions().get("minimum_value")+";\n"; - } - - if(!restoreSeq.getSequence().getOptions().get("maximum_value").equals(seq.getOptions().get("maximum_value"))) { - query+="alter sequence "+sequence + " maxvalue "+restoreSeq.getSequence().getOptions().get("maximum_value")+";\n"; - } - - if(!restoreSeq.getSequence().getOptions().get("owner").equals(seq.getOptions().get("owner"))) { - query+="alter sequence "+sequence+" owner to "+restoreSeq.getSequence().getOptions().get("owner")+";\n"; - } - if(query.length()>1) { - st.execute(query); - } - //TODO Восстановление привилегий - } - } - } - if(!exist){ - String query=""; - String seqName = restoreSeq.getSequence().getName(); - String schema = restoreSeq.getSequence().getSchema(); - if(restoreSeq.getSequence().getOptions().get("cycle_option").equals("YES")){ - query+="create sequence \"" + schema + "\".\"" + seqName+"\"" + - "cycle \n"+ - "increment" + restoreSeq.getSequence().getOptions().get("increment")+"\n"+ - "start " + restoreSeq.getSequence().getOptions().get("start_value")+"\n"+ - "minvalue "+ restoreSeq.getSequence().getOptions().get("minimum_value")+"\n"+ - "maxvalue " + restoreSeq.getSequence().getOptions().get("maximum_value")+";\n"; - query+="alter sequence \""+ schema + "\".\"" + seqName+"\" owner to\""+ restoreSeq.getSequence().getOptions().get("owner")+"\";"; - } - else { - query+="create sequence \"" + schema + "\".\"" + seqName+"\"" + - "no cycle \n"+ - "increment " + restoreSeq.getSequence().getOptions().get("increment")+"\n"+ - "start " + restoreSeq.getSequence().getOptions().get("start_value")+"\n"+ - "minvalue "+ restoreSeq.getSequence().getOptions().get("minimum_value")+"\n"+ - "maxvalue " + restoreSeq.getSequence().getOptions().get("maximum_value")+";\n"; - query+="alter sequence \""+ schema + "\".\"" + seqName+"\" owner to\""+ restoreSeq.getSequence().getOptions().get("owner")+"\";"; - } - st.execute(query); - //TODO Восстановление привилегий - } - } - else - { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); - } - } catch (Exception e) { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); - } finally { - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); - st.close(); - } - return true; - } - - @Override - public void removeMetaObject(IMetaObject obj) throws Exception { - IDBAdapter adapter = getAdapter(); - Connection connect = adapter.getConnection(); - StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - - try { - if(! (obj instanceof MetaSequence)) throw new ExceptionDBGit("Wrong IMetaObject type, expected: seq, was: " + obj.getType().getValue()); - MetaSequence seqMeta = (MetaSequence) obj; - DBSequence seq = seqMeta.getSequence(); - if (seq == null) return; - - String schema = getPhisicalSchema(seq.getSchema()); - st.execute("DROP SEQUENCE IF EXISTS "+schema+"."+DBAdapterPostgres.escapeNameIfNeeded(seq.getName())); - - } catch (Exception e) { - ConsoleWriter.println(lang.getValue("errors", "restore", "objectRestoreError").withParams(e.getLocalizedMessage())); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRemoveError").withParams(obj.getName()), e); - } finally { - st.close(); - } - - } - -} +package ru.fusionsoft.dbgit.postgres; + +import java.sql.Connection; +import java.util.Map; + +import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter; +import ru.fusionsoft.dbgit.adapters.IDBAdapter; +import ru.fusionsoft.dbgit.core.DBGitConfig; +import ru.fusionsoft.dbgit.core.ExceptionDBGit; +import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; +import ru.fusionsoft.dbgit.dbobjects.DBSequence; +import ru.fusionsoft.dbgit.meta.IMetaObject; +import ru.fusionsoft.dbgit.meta.MetaSequence; +import ru.fusionsoft.dbgit.statement.StatementLogging; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; + +public class DBRestoreSequencePostgres extends DBRestoreAdapter { + + @Override + public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + try { + if (obj instanceof MetaSequence) { + MetaSequence restoreSeq = (MetaSequence)obj; + Map seqs = adapter.getSequences(((MetaSequence) obj).getSequence().getSchema()); + boolean exist = false; + if(!(seqs.isEmpty() || seqs == null)) { + for(DBSequence seq:seqs.values()) { + if(restoreSeq.getSequence().getName().equals(seq.getName())){ + String query=""; + exist = true; + String sequence = restoreSeq.getSequence().getSchema()+ "." +restoreSeq.getSequence().getName(); + if(!restoreSeq.getSequence().getOptions().get("cycle_option").equals(seq.getOptions().get("cycle_option"))) { + if(restoreSeq.getSequence().getOptions().get("cycle_option").equals("YES")) { + query+="alter sequence "+sequence + " cycle;\n"; + } + else { + query+="alter sequence "+sequence + " no cycle;\n"; + } + } + + if(!restoreSeq.getSequence().getOptions().get("increment").equals(seq.getOptions().get("increment"))) { + query+="alter sequence "+sequence+ " increment "+restoreSeq.getSequence().getOptions().get("increment")+";\n"; + } + + if(!restoreSeq.getSequence().getOptions().get("start_value").equals(seq.getOptions().get("start_value"))) { + query+="alter sequence "+sequence+" start "+restoreSeq.getSequence().getOptions().get("start_value")+";\n"; + } + + if(!restoreSeq.getSequence().getOptions().get("minimum_value").equals(seq.getOptions().get("minimum_value"))) { + query+="alter sequence "+sequence+ " minvalue "+restoreSeq.getSequence().getOptions().get("minimum_value")+";\n"; + } + + if(!restoreSeq.getSequence().getOptions().get("maximum_value").equals(seq.getOptions().get("maximum_value"))) { + query+="alter sequence "+sequence + " maxvalue "+restoreSeq.getSequence().getOptions().get("maximum_value")+";\n"; + } + + if(!DBGitConfig.getInstance().getToIgnoreOnwer(false)){ + + if(!restoreSeq.getSequence().getOptions().get("owner").equals(seq.getOptions().get("owner"))) { + if(seq.getOptions().get("blocking_table") != null){ + String tableName = adapter.escapeNameIfNeeded(seq.getOptions().get("blocking_table").getData()); + query+="alter table "+tableName+ " owner to \""+restoreSeq.getSequence().getOptions().get("owner")+"\";\n"; + } + query+="alter sequence "+sequence+" owner to \""+restoreSeq.getSequence().getOptions().get("owner")+"\";\n"; + } + } + + if(query.length()>1) { + st.execute(query); + } + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + //TODO Восстановление привилегий + } + } + } + if(!exist){ + String query=""; + String seqName = restoreSeq.getSequence().getName(); + String schema = restoreSeq.getSequence().getSchema(); + if(restoreSeq.getSequence().getOptions().get("cycle_option").equals("YES")){ + query+="create sequence \"" + schema + "\".\"" + seqName+"\"" + + "cycle \n"+ + "increment" + restoreSeq.getSequence().getOptions().get("increment")+"\n"+ + "start " + restoreSeq.getSequence().getOptions().get("start_value")+"\n"+ + "minvalue "+ restoreSeq.getSequence().getOptions().get("minimum_value")+"\n"+ + "maxvalue " + restoreSeq.getSequence().getOptions().get("maximum_value")+";\n"; + if(!DBGitConfig.getInstance().getToIgnoreOnwer(false)){ + query+="alter sequence \""+ schema + "\".\"" + seqName+"\" owner to\""+ restoreSeq.getSequence().getOptions().get("owner")+"\";"; + } + } + else { + query+="create sequence \"" + schema + "\".\"" + seqName+"\"" + + " no cycle \n"+ + "increment " + restoreSeq.getSequence().getOptions().get("increment")+"\n"+ + "start " + restoreSeq.getSequence().getOptions().get("start_value")+"\n"+ + "minvalue "+ restoreSeq.getSequence().getOptions().get("minimum_value")+"\n"+ + "maxvalue " + restoreSeq.getSequence().getOptions().get("maximum_value")+";\n"; + if(!DBGitConfig.getInstance().getToIgnoreOnwer(false)){ + query+="alter sequence \""+ schema + "\".\"" + seqName+"\" owner to \""+ restoreSeq.getSequence().getOptions().get("owner")+"\";"; + } + } + st.execute(query); + //TODO Восстановление привилегий + } + } + else + { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "sequence", obj.getType().getValue() + )); + } + } catch (Exception e) { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); + } finally { + + st.close(); + } + return true; + } + + @Override + public void removeMetaObject(IMetaObject obj) throws Exception { + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + + try { + if(! (obj instanceof MetaSequence)) throw new ExceptionDBGit("Wrong IMetaObject type, expected: seq, was: " + obj.getType().getValue()); + MetaSequence seqMeta = (MetaSequence) obj; + DBSequence seq = seqMeta.getSequence(); + if (seq == null) return; + + String schema = getPhisicalSchema(seq.getSchema()); + st.execute("DROP SEQUENCE IF EXISTS "+adapter.escapeNameIfNeeded(schema)+"."+adapter.escapeNameIfNeeded(seq.getName())); + + } catch (Exception e) { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRemoveError").withParams(obj.getName()), e); + } finally { + st.close(); + } + + } + +} diff --git a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreTableDataPostgres.java b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreTableDataPostgres.java index d5927c6..4b5da5c 100644 --- a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreTableDataPostgres.java +++ b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreTableDataPostgres.java @@ -1,633 +1,591 @@ -package ru.fusionsoft.dbgit.postgres; - -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStreamReader; -import java.sql.Clob; -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.text.SimpleDateFormat; -import java.util.*; -import java.util.stream.Collectors; - -import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter; -import ru.fusionsoft.dbgit.adapters.IDBAdapter; -import ru.fusionsoft.dbgit.core.ExceptionDBGit; -import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; -import ru.fusionsoft.dbgit.core.GitMetaDataManager; -import ru.fusionsoft.dbgit.core.SchemaSynonym; -import ru.fusionsoft.dbgit.data_table.BooleanData; -import ru.fusionsoft.dbgit.data_table.DateData; -import ru.fusionsoft.dbgit.data_table.ICellData; -import ru.fusionsoft.dbgit.data_table.LongData; -import ru.fusionsoft.dbgit.data_table.MapFileData; -import ru.fusionsoft.dbgit.data_table.RowData; -import ru.fusionsoft.dbgit.data_table.StringData; -import ru.fusionsoft.dbgit.data_table.TextFileData; -import ru.fusionsoft.dbgit.data_table.TreeMapRowData; -import ru.fusionsoft.dbgit.dbobjects.DBConstraint; -import ru.fusionsoft.dbgit.dbobjects.DBTableField; -import ru.fusionsoft.dbgit.meta.IMetaObject; -import ru.fusionsoft.dbgit.meta.MetaTable; -import ru.fusionsoft.dbgit.meta.MetaTableData; -import ru.fusionsoft.dbgit.statement.PrepareStatementLogging; -import ru.fusionsoft.dbgit.statement.StatementLogging; -import ru.fusionsoft.dbgit.utils.ConsoleWriter; - -import com.google.common.collect.MapDifference; -import com.google.common.collect.MapDifference.ValueDifference; -import com.google.common.collect.Maps; - -public class DBRestoreTableDataPostgres extends DBRestoreAdapter { - - @Override - public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { - if (obj instanceof MetaTableData) { - MetaTableData currentTableData; - MetaTableData restoreTableData = (MetaTableData)obj; - GitMetaDataManager gitMetaMng = GitMetaDataManager.getInstance(); - //TODO не факт что в кеше есть мета описание нашей таблицы, точнее ее не будет если при старте ресторе таблицы в бд не было совсем - - IMetaObject currentMetaObj = gitMetaMng.getCacheDBMetaObject(obj.getName()); - - if (currentMetaObj instanceof MetaTableData || currentMetaObj == null) { - - if(Integer.valueOf(step).equals(0)) { - removeTableConstraintsPostgres(restoreTableData.getMetaTable()); - return false; - } - if(Integer.valueOf(step).equals(1)) { - String schema = getPhisicalSchema(restoreTableData.getTable().getSchema()); - schema = (SchemaSynonym.getInstance().getSchema(schema) == null) ? schema : SchemaSynonym.getInstance().getSchema(schema); - - if (currentMetaObj != null) { - currentTableData = (MetaTableData) currentMetaObj; - } else { - currentTableData = new MetaTableData(); - currentTableData.setTable(restoreTableData.getTable()); - currentTableData.getTable().setSchema(schema); - - currentTableData.setMapRows(new TreeMapRowData()); - currentTableData.setDataTable(restoreTableData.getDataTable()); - } - currentTableData.getmapRows().clear(); - - if (getAdapter().getTable(schema, currentTableData.getTable().getName()) != null) { - currentTableData.setDataTable(getAdapter().getTableData(schema, currentTableData.getTable().getName())); - - ResultSet rs = currentTableData.getDataTable().getResultSet(); - - TreeMapRowData mapRows = new TreeMapRowData(); - - MetaTable metaTable = new MetaTable(currentTableData.getTable()); - metaTable.loadFromDB(currentTableData.getTable()); - - if (rs != null) { - while(rs.next()) { - RowData rd = new RowData(rs, metaTable); - mapRows.put(rd.calcRowKey(metaTable.getIdColumns()), rd); - } - } - currentTableData.setMapRows(mapRows); - } - /* - ConsoleWriter.println("curr:"); - currentTableData.getmapRows().keySet().forEach(key -> ConsoleWriter.println("hash: " + key)); - ConsoleWriter.println("rest:"); - restoreTableData.getmapRows().keySet().forEach(key -> ConsoleWriter.println("hash: " + key)); - */ - restoreTableDataPostgres(restoreTableData,currentTableData); - return false; - } - if(Integer.valueOf(step).equals(-2)) { - restoreTableConstraintPostgres(restoreTableData.getMetaTable()); - return false; - } - return true; - } - else - { - //TODO WTF???? - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); - //return true; - } - } - else - { - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); - } - } - - public void restoreTableDataPostgres(MetaTableData restoreTableData, MetaTableData currentTableData) throws Exception{ - IDBAdapter adapter = getAdapter(); - Connection connect = adapter.getConnection(); - StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - try { - if (restoreTableData.getmapRows() == null) - restoreTableData.setMapRows(new TreeMapRowData()); - - String fields = ""; - if (restoreTableData.getmapRows().size() > 0) { - //fields = keysToString(restoreTableData.getmapRows().firstEntry().getValue().getData().keySet().stream().map(DBAdapterPostgres::escapeNameIfNeeded).collect(Collectors.toSet())) + " values "; - - Comparator comparator = Comparator.comparing(DBTableField::getOrder); - fields = "(" + restoreTableData.getMetaTableFromFile().getFields().entrySet().stream() - .sorted(Comparator.comparing(e -> e.getValue().getOrder())) - .map(entry -> DBAdapterPostgres.escapeNameIfNeeded(entry.getValue().getName())) - .collect(Collectors.joining(", ")) - + ") values "; - - } - - MapDifference diffTableData = Maps.difference(restoreTableData.getmapRows(),currentTableData.getmapRows()); - String schema = getPhisicalSchema(restoreTableData.getTable().getSchema()); - - schema = (SchemaSynonym.getInstance().getSchema(schema) == null) ? schema : SchemaSynonym.getInstance().getSchema(schema); - String tblNameUnescaped = schema + "." + restoreTableData.getTable().getName(); - String tblNameEscaped = schema + "." + DBAdapterPostgres.escapeNameIfNeeded(restoreTableData.getTable().getName()); - - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "tableData").withParams(tblNameUnescaped) + "\n", 1); - - ResultSet rsTypes = st.executeQuery("select column_name, data_type from information_schema.columns \r\n" + - "where lower(table_schema||'.'||table_name) = lower('" + tblNameUnescaped + "')"); - - HashMap colTypes = new HashMap(); - while (rsTypes.next()) { - colTypes.put(rsTypes.getString("column_name"), rsTypes.getString("data_type")); - } - - - if(!diffTableData.entriesOnlyOnLeft().isEmpty()) { - - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "inserting"), 2); - - for(RowData rowData:diffTableData.entriesOnlyOnLeft().values()) { - ArrayList fieldsList = new ArrayList(rowData.getData().keySet().stream().map(DBAdapterPostgres::escapeNameIfNeeded).collect(Collectors.toList())); - - String insertQuery = "insert into " + tblNameEscaped + - fields+valuesToString(rowData.getData().values(), colTypes, fieldsList) + ";\n"; - - ConsoleWriter.detailsPrintLn(insertQuery); - - PrepareStatementLogging ps = new PrepareStatementLogging(connect, insertQuery, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - int i = 0; - - for (ICellData data : rowData.getData().values()) { - i++; - ConsoleWriter.detailsPrintLn(data.getSQLData()); - - ResultSet rs = st.executeQuery("select data_type from information_schema.columns \r\n" + - "where lower(table_schema||'.'||table_name) = lower('" + tblNameUnescaped + "') and lower(column_name) = '" + fieldsList.get(i - 1) + "'"); - - boolean isBoolean = false; - while (rs.next()) { - if (rs.getString("data_type").contains("boolean")) { - isBoolean = true; - } - } - - //ps = setValues(data, i, ps, isBoolean); - } - - //if (adapter.isExecSql()) - // ps.execute(); - //ps.close(); - - st.execute(insertQuery); - } - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); - } - - if(!diffTableData.entriesOnlyOnRight().isEmpty()){ - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "deleting"), 2); - String deleteQuery=""; - Map primarykeys = new HashMap(); - for(RowData rowData:diffTableData.entriesOnlyOnRight().values()) { - Map tempcols = rowData.getData(); - String[] keysArray = rowData.getKey().split("_"); - for(String key:keysArray) { - for (String o : tempcols.keySet()) { - if (tempcols.get(o) == null || tempcols.get(o).convertToString() == null) continue; - if (tempcols.get(o).convertToString().equals(key)) { - primarykeys.put(o, tempcols.get(o).convertToString()); - tempcols.remove(o); - break; - } - } - } - String delFields="("; - String delValues="("; - StringJoiner fieldJoiner = new StringJoiner(","); - StringJoiner valuejoiner = new StringJoiner(","); - for (Map.Entry entry : primarykeys.entrySet()) { - fieldJoiner.add("\""+entry.getKey()+"\""); - valuejoiner.add("\'"+entry.getValue()+"\'"); - } - delFields+=fieldJoiner.toString()+")"; - delValues+=valuejoiner.toString()+")"; - primarykeys.clear(); - if (delValues.length() > 3) - deleteQuery+="delete from " + tblNameUnescaped+ - " where " + delFields + " = " + delValues + ";\n"; - if(deleteQuery.length() > 50000 ){ - st.execute(deleteQuery); - deleteQuery = ""; - } - } - if(deleteQuery.length()>1) { - st.execute(deleteQuery); - } - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); - } - - if(!diffTableData.entriesDiffering().isEmpty()) { - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "updating"), 2); - String updateQuery=""; - Map primarykeys = new HashMap(); - for(ValueDifference diffRowData:diffTableData.entriesDiffering().values()) { - if(!diffRowData.leftValue().getHashRow().equals(diffRowData.rightValue().getHashRow())) { - Map tempCols = diffRowData.leftValue().getData(); - String[] keysArray = diffRowData.leftValue().getKey().split("_"); - for(String key:keysArray) { - for (String o : tempCols.keySet()) { - if (tempCols.get(o) == null || tempCols.get(o).convertToString() == null) continue; - if (tempCols.get(o).convertToString().equals(key)) { - primarykeys.put(o, tempCols.get(o).convertToString()); - tempCols.remove(o); - break; - } - } - } - if(!tempCols.isEmpty()) { - String keyFields="("; - String keyValues="("; - StringJoiner fieldJoiner = new StringJoiner(","); - StringJoiner valuejoiner = new StringJoiner(","); - for (Map.Entry entry : primarykeys.entrySet()) { - fieldJoiner.add("\""+entry.getKey()+"\""); - valuejoiner.add("\'"+entry.getValue()+"\'"); - } - keyFields+=fieldJoiner.toString()+")"; - keyValues+=valuejoiner.toString()+")"; - primarykeys.clear(); - - StringJoiner updfieldJoiner = new StringJoiner(","); - StringJoiner updvaluejoiner = new StringJoiner(","); - String updFields="("; - String updValues="("; - - for (Map.Entry entry : tempCols.entrySet()) { - updfieldJoiner.add("\""+entry.getKey()+"\""); - //updvaluejoiner.add("\'"+entry.getValue().convertToString()+"\'"); - //updvaluejoiner.add("?"); - } - - ArrayList fieldsList = new ArrayList(diffRowData.leftValue().getData().keySet()); - - updFields+=updfieldJoiner.toString()+")"; - updValues+=updvaluejoiner.toString()+")"; - - updateQuery="update "+tblNameEscaped+ - " set "+updFields + " = " + valuesToString(tempCols.values(), colTypes, fieldsList) + " where " + keyFields+ "=" +keyValues+";\n"; - - ConsoleWriter.detailsPrintLn(updateQuery); - - PrepareStatementLogging ps = new PrepareStatementLogging(connect, updateQuery, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - int i = 0; - - ConsoleWriter.detailsPrintLn("vals for " + keyValues + ":" + diffRowData.leftValue().getData().values()); - for (ICellData data : diffRowData.leftValue().getData().values()) { - i++; - ConsoleWriter.detailsPrintLn(data.getSQLData()); - - ResultSet rs = st.executeQuery("select data_type from information_schema.columns \r\n" + - "where lower(table_schema||'.'||table_name) = lower('" + tblNameUnescaped + "') and lower(column_name) = '" + fieldsList.get(i - 1) + "'"); - - boolean isBoolean = false; - while (rs.next()) { - if (rs.getString("data_type").toLowerCase().contains("boolean")) { - isBoolean = true; - } - } - //ps = setValues(data, i, ps, isBoolean); - } - /* - if (adapter.isExecSql()) - ps.execute(); - ps.close(); - updateQuery = ""; - */ - - - - //if(updateQuery.length() > 50000 ){ - st.execute(updateQuery); - updateQuery = ""; - //} - - } - - } - } - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); - if(updateQuery.length()>1) { - ConsoleWriter.println(updateQuery); - st.execute(updateQuery); - } - } - - } catch (Exception e) { - ConsoleWriter.println(lang.getValue("errors", "restore", "objectRestoreError").withParams(e.getLocalizedMessage())); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(restoreTableData.getTable().getSchema() + "." + restoreTableData.getTable().getName()), e); - } finally { - st.close(); - } - } - - public String valuesToString(Collection datas, HashMap colTypes, ArrayList fieldsList) throws ExceptionDBGit, IOException { - String values="("; - StringJoiner joiner = new StringJoiner(","); - int i = 0; - for (ICellData data : datas) { - boolean isBoolean = ((colTypes.get(fieldsList.get(i)) != null) && (colTypes.get(fieldsList.get(i)).toLowerCase().contains("boolean"))); - - if (data instanceof TextFileData) { - if (((TextFileData) data).getFile() == null || ((TextFileData) data).getFile().getName().contains("null")) { - joiner.add("null"); - } else { - FileInputStream fis = new FileInputStream(((MapFileData) data).getFile()); - BufferedReader br = new BufferedReader(new InputStreamReader(fis)); - - StringBuilder sb = new StringBuilder(); - String line; - while(( line = br.readLine()) != null ) { - sb.append( line ); - sb.append( '\n' ); - } - br.close(); - - fis.close(); - String res = "'" + sb.toString().replace("'", "''") - .replace("\\", "\\\\") - .replace("\n", "' || chr(10) || '") - .replace("\0", "' || '\\000' || '") - + "'"; - - if (res.endsWith(" || chr(10) || ''")) { - res = res.substring(0, res.length() - " || chr(10) || ''".length()); - } - joiner.add(res); - - - } - } else if (data instanceof MapFileData) { - if (((MapFileData) data).getFile() == null || ((MapFileData) data).getFile().getName().contains("null")) { - joiner.add("null"); - } else { - - FileInputStream fis = new FileInputStream(((MapFileData) data).getFile()); - - int byteRead; - StringBuilder sb = new StringBuilder(); - - while ((byteRead = fis.read()) != -1) { - String hex = Integer.toHexString(byteRead); - if (hex.length() == 1) hex = "0" + hex; - - sb.append(hex); - } - fis.close(); - joiner.add("decode('" + sb.toString() + "', 'hex')"); - - /* - joiner1.add("decode('" + sb.toString().replace("'", "''") - .replace("\\", "\\\\") - .replace("\n", "' || chr(10) || '") - .replace("\0", "' || '\\000' || '") - + "', 'escape')");*/ - } - } else if (data instanceof DateData) { - Date date = ((DateData) data).getDate(); - SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss"); - if (date != null) - joiner.add("TO_TIMESTAMP('" + format.format(date) + "', 'YYYYMMDDHH24MISS')"); - else - joiner.add("null"); - } else if (data instanceof BooleanData) { - if (((BooleanData) data).getValue() != null) - joiner.add(((BooleanData) data).getValue().toString()); - else - joiner.add("null"); - } else if (data instanceof LongData) { - String dt = data.getSQLData().replace("'", ""); - - if (isBoolean) { - if (dt == null || dt.equals("")) - joiner.add("null"); - else if (dt.equals("1")) - joiner.add("true"); - else - joiner.add("false"); - } else { - if (!dt.equals("")) - joiner.add(dt); - else - joiner.add("null"); - } - } else { - String dt = ((StringData) data).getValue(); - if (isBoolean) { - if (dt == null || dt.equals("")) - joiner.add("null"); - else if (dt.startsWith("t") || dt.startsWith("T") || dt.equals("1") || dt.startsWith("y") || dt.startsWith("Y")) - joiner.add("true"); - else - joiner.add("false"); - } else { - if (dt != null) - joiner.add("'" + dt.replace("'", "''") + "'"); - else - joiner.add("null"); - } - //joiner.add(data.getSQLData()); - - } - - //joiner.add("?"); - i++; - } - //ConsoleWriter.println("joiner: " + joiner1); - values+=joiner.toString()+")"; - return values; - } - - public String keysToString(Set keys) { - String fields=""; - if(keys.size()>1) { - String[] fieldsArray = keys.toArray(new String[keys.size()]); - fields="("+(fieldsArray[0].equals(fieldsArray[0].toLowerCase()) ? fieldsArray[0] : "\"" + fieldsArray[0] + "\""); - for(int i=1;igetDataTable() too after ^ "else" clause + currentTableData.getmapRows().clear(); + + if (getAdapter().getTable(schema, currentTableData.getTable().getName()) != null) { + //actually load data from database + currentTableData.setDataTable(getAdapter().getTableData(schema, currentTableData.getTable().getName())); + currentTableData.setFields( + getAdapter().getTableFields(schema, currentTableData.getTable().getName()) + .entrySet().stream() + .sorted(Comparator.comparing(x->x.getValue().getOrder())) + .map( x->x.getKey() ) + .collect(Collectors.toList()) + ); + + ResultSet rs = currentTableData.getDataTable().resultSet(); + + TreeMapRowData mapRows = new TreeMapRowData(); + + MetaTable metaTable = new MetaTable(currentTableData.getTable()); + //ALSO loads data from database if fields vary + metaTable.loadFromDB(currentTableData.getTable()); + + if (rs != null) { + while(rs.next()) { + RowData rd = new RowData(rs, metaTable); + mapRows.put(rd.calcRowKey(metaTable.getIdColumns()), rd); + } + } + currentTableData.setMapRows(mapRows); + } + /* + ConsoleWriter.println("curr:"); + currentTableData.getmapRows().keySet().forEach(key -> ConsoleWriter.println("hash: " + key)); + ConsoleWriter.println("rest:"); + restoreTableData.getmapRows().keySet().forEach(key -> ConsoleWriter.println("hash: " + key)); + */ + restoreTableDataPostgres(restoreTableData,currentTableData); + return false; + } + if(Integer.valueOf(step).equals(-2)) { + restoreTableConstraintPostgres(restoreTableData.getMetaTable()); + return false; + } + return true; + } + else + { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "table data cached", obj.getType().getValue() + )); + } + } + else + { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "table data", obj.getType().getValue() + )); + } + } + + public void restoreTableDataPostgres(MetaTableData restoreTableData, MetaTableData currentTableData) throws Exception{ + //if empty restore table data -> delete all currentTableData + if (currentTableData.getFields().size() == 0 ) { + final CharSequence msg = DBGitLang.getInstance().getValue("errors", "restore", "currentFieldsListIsEmpty").toString(); + throw new ExceptionDBGit(msg); + } + if (restoreTableData.getmapRows() == null) { + final CharSequence msg = DBGitLang.getInstance().getValue("errors", "restore", "emptyRowsList").toString(); + throw new ExceptionDBGit(msg); + } + + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + + MapDifference diffTableData = Maps.difference(restoreTableData.getmapRows(), currentTableData.getmapRows()); + try (StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql())) { + + String schema = getPhisicalSchema(restoreTableData.getTable().getSchema()); + String tblNameEscaped = adapter.escapeNameIfNeeded(schema) + "." + adapter.escapeNameIfNeeded(restoreTableData.getTable().getName()); + String fields = getFieldsPrefix(restoreTableData); + Map colTypes = getColumnDataTypes(restoreTableData.getMetaTable(), st); + Set keyNames = restoreTableData.getMetaTable().getFields().values().stream() + .filter(DBTableField::getIsPrimaryKey) + .map(DBTableField::getName) + .collect(Collectors.toSet()); + + //DELETE + if (!diffTableData.entriesOnlyOnRight().isEmpty()) { + ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "deleting"), messageLevel); + StringBuilder deleteQuery = new StringBuilder(); + + for (RowData rowData : diffTableData.entriesOnlyOnRight().values()) { + StringJoiner fieldJoiner = new StringJoiner(","); + StringJoiner valuejoiner = new StringJoiner(","); + + for( Map.Entry entry : rowData.getData(currentTableData.getFields()).entrySet()) { + if (keyNames.contains(entry.getKey())) { + fieldJoiner.add("\"" + entry.getKey() + "\""); + final String value = entry.getValue().convertToString(); + if( value.matches("-?\\d+(\\.0)?") ) { + valuejoiner.add( String.valueOf( (long) Double.parseDouble(value) ) ); + } else { + valuejoiner.add("'" + value + "'"); + } + } + } + + String delFields = "(" + fieldJoiner.toString() + ")"; + String delValues = "(" + valuejoiner.toString() + ")"; + + if (delValues.length() > 2){ + final String ddl = MessageFormat.format( + "DELETE FROM {0} WHERE {1} = {2};", + tblNameEscaped, delFields, delValues + ); + deleteQuery.append(ddl).append("\n"); + ConsoleWriter.detailsPrintln(ddl, messageLevel + 1); + } + if (deleteQuery.length() > 50000) { + st.execute(deleteQuery.toString()); + deleteQuery = new StringBuilder(); + } + } + if (deleteQuery.length() > 1) { + st.execute(deleteQuery.toString()); + } + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + } + + //UPDATE + if (!diffTableData.entriesDiffering().isEmpty()) { + ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "updating"), messageLevel); + String updateQuery = ""; + Map primarykeys = new HashMap(); + + for (ValueDifference diffRowData : diffTableData.entriesDiffering().values()) { + if (!diffRowData.leftValue().getHashRow().equals(diffRowData.rightValue().getHashRow())) { + + Map tempCols = diffRowData.leftValue().getData(restoreTableData.getFields()); + for (String key : tempCols.keySet()) { + if (tempCols.get(key) == null || tempCols.get(key).convertToString() == null) continue; + if (keyNames.contains(key)) { + primarykeys.put(key, tempCols.get(key).convertToString()); + tempCols.remove(key); + } + } + + + if (!tempCols.isEmpty()) { + StringJoiner keyFieldsJoiner = new StringJoiner(","); + StringJoiner keyValuesJoiner = new StringJoiner(","); + for (Map.Entry entry : primarykeys.entrySet()) { + keyFieldsJoiner.add("\"" + entry.getKey() + "\""); + keyValuesJoiner.add("\'" + entry.getValue() + "\'"); + } + primarykeys.clear(); + + + StringJoiner updFieldJoiner = new StringJoiner(","); + tempCols.forEach( (key, value) -> { + updFieldJoiner.add("\"" + key + "\""); + }); + + + updateQuery = "UPDATE " + tblNameEscaped + " SET (" + updFieldJoiner.toString() + ") = " + + valuesToString(tempCols.values(), colTypes, restoreTableData.getFields()) + " " + + "WHERE (" + keyFieldsJoiner.toString() + ") = (" + keyValuesJoiner.toString() + ");\n"; + + + ConsoleWriter.detailsPrintln(updateQuery, messageLevel); + st.execute(updateQuery); + updateQuery = ""; + } + + } + } + + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + if (updateQuery.length() > 1) { + ConsoleWriter.println(updateQuery, messageLevel); + st.execute(updateQuery); + } + } + + //INSERT + if (!diffTableData.entriesOnlyOnLeft().isEmpty()) { + ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "inserting"), messageLevel); + for (RowData rowData : diffTableData.entriesOnlyOnLeft().values()) { + + String insertQuery = MessageFormat.format("INSERT INTO {0}{1}{2};" + , tblNameEscaped, fields + , valuesToString(rowData.getData(restoreTableData.getFields()).values(), colTypes, restoreTableData.getFields()) + ); + + ConsoleWriter.detailsPrintln(insertQuery, messageLevel+1); + st.execute(insertQuery); + } + ConsoleWriter.detailsPrintln(lang.getValue("general", "ok"), messageLevel); + } + + } catch (Exception e) { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(restoreTableData.getTable().getSchema() + "." + restoreTableData.getTable().getName()) + , e + ); + } + } + + public String valuesToString(Collection datas, Map colTypes, List fieldsList) throws ExceptionDBGit, IOException { + String values="("; + StringJoiner joiner = new StringJoiner(","); + int i = 0; + for (ICellData data : datas) { + boolean isBoolean = ((colTypes.get(fieldsList.get(i)) != null) && (colTypes.get(fieldsList.get(i)).toLowerCase().contains("boolean"))); + + if (data instanceof TextFileData) { + if (((TextFileData) data).getFile() == null || ((TextFileData) data).getFile().getName().contains("null")) { + //TODO generalize this behaviour based on some parameter + //TODO nulls if nullable, '' if not + joiner.add("''"); + } else { + FileInputStream fis = new FileInputStream(((MapFileData) data).getFile()); + BufferedReader br = new BufferedReader(new InputStreamReader(fis)); + + StringBuilder sb = new StringBuilder(); + String line; + while(( line = br.readLine()) != null ) { + sb.append( line ); + sb.append( '\n' ); + } + br.close(); + + fis.close(); + String res = "'" + sb.toString().replace("'", "''") + .replace("\\", "\\\\") +// .replace("\n", "' || chr(10) || '") + .replace("\0", "' || '\\000' || '") + + "'"; + + if (res.endsWith(" || chr(10) || ''")) { + res = res.substring(0, res.length() - " || chr(10) || ''".length()); + } + joiner.add(res); + + + } + } else if (data instanceof MapFileData) { + if (((MapFileData) data).getFile() == null || ((MapFileData) data).getFile().getName().contains("null")) { + joiner.add("null"); + } else { + + FileInputStream fis = new FileInputStream(((MapFileData) data).getFile()); + + int byteRead; + StringBuilder sb = new StringBuilder(); + + while ((byteRead = fis.read()) != -1) { + String hex = Integer.toHexString(byteRead); + if (hex.length() == 1) hex = "0" + hex; + + sb.append(hex); + } + fis.close(); + joiner.add("decode('" + sb.toString() + "', 'hex')"); + + /* + joiner1.add("decode('" + sb.toString().replace("'", "''") + .replace("\\", "\\\\") + .replace("\n", "' || chr(10) || '") + .replace("\0", "' || '\\000' || '") + + "', 'escape')");*/ + } + } else if (data instanceof DateData) { + Date date = ((DateData) data).getDate(); + SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss"); + if (date != null) + joiner.add("TO_TIMESTAMP('" + format.format(date) + "', 'YYYYMMDDHH24MISS')"); + else + joiner.add("null"); + } else if (data instanceof BooleanData) { + if (((BooleanData) data).getValue() != null) + joiner.add(((BooleanData) data).getValue().toString()); + else + joiner.add("null"); + } else if (data instanceof LongData) { + String dt = data.getSQLData().replace("'", ""); + + if (isBoolean) { + if (dt == null || dt.equals("")) + joiner.add("null"); + else if (dt.equals("1")) + joiner.add("true"); + else + joiner.add("false"); + } else { + if (!dt.equals("")) + joiner.add(dt); + else + joiner.add("null"); + } + } else { + String dt = ((StringData) data).getValue(); + if (isBoolean) { + if (dt == null || dt.equals("")) + joiner.add("null"); + else if (dt.startsWith("t") || dt.startsWith("T") || dt.equals("1") || dt.startsWith("y") || dt.startsWith("Y")) + joiner.add("true"); + else + joiner.add("false"); + } else { + if (dt != null) + joiner.add("'" + dt.replace("'", "''") + "'"); + else + joiner.add("null"); + } + //joiner.add(data.getSQLData()); + + } + + //joiner.add("?"); + i++; + } + //ConsoleWriter.println("joiner: " + joiner1); + values+=joiner.toString()+")"; + return values; + } + + public String keysToString(Set keys) { + String fields=""; + if(keys.size()>1) { + String[] fieldsArray = keys.toArray(new String[keys.size()]); + fields="("+(fieldsArray[0].equals(fieldsArray[0].toLowerCase()) ? fieldsArray[0] : "\"" + fieldsArray[0] + "\""); + for(int i=1;i e.getValue().getOrder())) + .map(entry -> adapter.escapeNameIfNeeded(entry.getValue().getName())) + .collect(Collectors.joining(", ")) + ); + } + + private Map getColumnDataTypes(MetaTable tbl, StatementLogging st) throws SQLException { + HashMap colTypes = new HashMap(); + NameMeta nm = new NameMeta(tbl); + nm.setSchema(nm.getSchema()); + + ResultSet rsTypes = st.executeQuery(MessageFormat.format( + " select column_name, data_type from information_schema.columns \r\n" + + " where lower(table_schema) = lower(''{0}'') AND lower(table_name) = lower(''{1}'')" + , nm.getSchema(), nm.getName() + )); + + while (rsTypes.next()) { + colTypes.put(rsTypes.getString("column_name"), rsTypes.getString("data_type")); + } + return colTypes; + } + + +} diff --git a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreTablePostgres.java b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreTablePostgres.java index 7d5c496..a7ff235 100644 --- a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreTablePostgres.java +++ b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreTablePostgres.java @@ -1,562 +1,723 @@ -package ru.fusionsoft.dbgit.postgres; - -import com.diogonunes.jcdp.color.api.Ansi; -import com.google.common.collect.MapDifference; -import com.google.common.collect.MapDifference.ValueDifference; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter; -import ru.fusionsoft.dbgit.adapters.IDBAdapter; -import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; -import ru.fusionsoft.dbgit.core.db.FieldType; -import ru.fusionsoft.dbgit.dbobjects.*; -import ru.fusionsoft.dbgit.meta.IMetaObject; -import ru.fusionsoft.dbgit.meta.MetaTable; -import ru.fusionsoft.dbgit.statement.StatementLogging; -import ru.fusionsoft.dbgit.utils.ConsoleWriter; -import ru.fusionsoft.dbgit.utils.StringProperties; - -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.text.MessageFormat; -import java.util.*; -import java.util.stream.Collectors; - -public class DBRestoreTablePostgres extends DBRestoreAdapter { - - @Override - public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { - if(Integer.valueOf(step).equals(0)) { - restoreTablePostgres(obj); - return false; - } - - if(Integer.valueOf(step).equals(1)) { - restoreTableIndexesPostgres(obj); - return false; - } - - if(Integer.valueOf(step).equals(-1)) { - restoreTableConstraintPostgres(obj); - return false; - } - - return true; - } - - public void restoreTablePostgres(IMetaObject obj) throws Exception - { - IDBAdapter adapter = getAdapter(); - Connection connect = adapter.getConnection(); - StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - try { - if (obj instanceof MetaTable) { - MetaTable restoreTable = (MetaTable)obj; - MetaTable existingTable = new MetaTable(restoreTable.getTable()); - - String schema = getPhisicalSchema(restoreTable.getTable().getSchema().toLowerCase()); - String tblName = DBAdapterPostgres.escapeNameIfNeeded(restoreTable.getTable().getName()); - - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "restoreTable").withParams(schema+"."+tblName), 1); - - //find existing table and set tablespace or create - if(existingTable.loadFromDB()){ - String restoreTablespaceSam = MessageFormat.format( - "alter table {0}.{1} set tablespace {2}" - ,schema - ,tblName - ,restoreTable.getTable().getOptions().getChildren().containsKey("tablespace") - ? restoreTable.getTable().getOptions().get("tablespace").getData() - : "pg_default" - ); - st.execute(restoreTablespaceSam); - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); - } else { - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "createTable"), 2); - String createTableDdl = MessageFormat.format( - "create table {0}.{1}() tablespace {2};\n alter table {0}.{1} owner to {3}" - ,schema - ,tblName - ,restoreTable.getTable().getOptions().getChildren().containsKey("tablespace") - ? restoreTable.getTable().getOptions().get("tablespace").getData() - : "pg_default" - ,restoreTable.getTable().getOptions().getChildren().containsKey("owner") - ? restoreTable.getTable().getOptions().get("owner").getData() - : "postgres" - ); - st.execute(createTableDdl); - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); - } - - //restore comment - if (restoreTable.getTable().getComment() != null && restoreTable.getTable().getComment().length() > 0){ - st.execute(MessageFormat.format( - "COMMENT ON TABLE {0}.{1} IS '{2}'" - ,schema - ,tblName - ,restoreTable.getTable().getComment() - )); - } - - //restore tabl fields -// Map currentFileds = adapter.getTableFields(schema.toLowerCase(), restoreTable.getTable().getName().toLowerCase()); - MapDifference diffTableFields = Maps.difference(restoreTable.getFields(),existingTable.getFields()); - String tblSam = schema + "." + DBAdapterPostgres.escapeNameIfNeeded(tblName); - - if(!diffTableFields.entriesOnlyOnLeft().isEmpty()){ - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "addColumns"), 2); - - Comparator comparator = Comparator.comparing(DBTableField::getOrder); - - List values = new ArrayList<>(diffTableFields.entriesOnlyOnLeft().values()); - values.sort(comparator); - - for(DBTableField tblField : values) { - String fieldName = DBAdapterPostgres.escapeNameIfNeeded(tblField.getName()); - st.execute( - "alter table "+ tblSam +" add column " - + fieldName + " " - + tblField.getTypeSQL().replace("NOT NULL", "") - ); - - if (tblField.getDescription() != null && tblField.getDescription().length() > 0) - st.execute( - "COMMENT ON COLUMN " + tblSam + "." - + fieldName - + " IS '" + tblField.getDescription() + "'" - ); - - if (!tblField.getIsNullable()) { - st.execute( - "alter table " + tblSam - + " alter column " + fieldName - + " set not null" - ); - } - - if (tblField.getDefaultValue() != null && tblField.getDefaultValue().length() > 0) { - st.execute("alter table " + tblSam + " alter column " + fieldName - + " SET DEFAULT " + tblField.getDefaultValue()); - } - - } - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); - } - - if(!diffTableFields.entriesOnlyOnRight().isEmpty()) { - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "droppingColumns"), 2); - for(DBTableField tblField:diffTableFields.entriesOnlyOnRight().values()) { - st.execute("alter table "+ tblSam +" drop column "+ DBAdapterPostgres.escapeNameIfNeeded(tblField.getName())); - } - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); - } - - if(!diffTableFields.entriesDiffering().isEmpty()) { - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "modifyColumns"), 2); - for(ValueDifference tblField:diffTableFields.entriesDiffering().values()) { - if(!tblField.leftValue().getName().equals(tblField.rightValue().getName())) { - st.execute( - "alter table " - + tblSam - +" rename column "+ DBAdapterPostgres.escapeNameIfNeeded(tblField.rightValue().getName()) - +" to "+ DBAdapterPostgres.escapeNameIfNeeded(tblField.leftValue().getName()) - ); - } - - if (restoreTable.getTable().getComment() != null && restoreTable.getTable().getComment().length() > 0) - st.execute("COMMENT ON COLUMN " + tblSam + "." + DBAdapterPostgres.escapeNameIfNeeded(tblField.leftValue().getName()) + " IS '" + tblField.leftValue().getDescription() + "'"); - - if( !tblField.leftValue().getTypeSQL().equals(tblField.rightValue().getTypeSQL()) - && tblField.rightValue().getTypeUniversal() != FieldType.BOOLEAN) { - st.execute( - "alter table " - + tblSam - +" alter column "+ DBAdapterPostgres.escapeNameIfNeeded(tblField.leftValue().getName()) - +" type "+ tblField.leftValue().getTypeSQL().replace("NOT NULL", "") - ); - if (!tblField.leftValue().getIsNullable()) { - st.execute( - "alter table " + tblSam - + " alter column " + DBAdapterPostgres.escapeNameIfNeeded(tblField.leftValue().getName()) - + " set not null" - ); - } - } - } - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); - } - - } - else { - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); - } - } catch (Exception e) { - ConsoleWriter.println(lang.getValue("errors", "restore", "objectRestoreError").withParams(e.getLocalizedMessage())); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); - } finally { - connect.commit(); - st.close(); - } - } - public void restoreTableFieldsPostgres(IMetaObject obj) throws Exception - { - IDBAdapter adapter = getAdapter(); - Connection connect = adapter.getConnection(); - StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - try { - if (obj instanceof MetaTable) { - MetaTable restoreTable = (MetaTable)obj; - String schema = getPhisicalSchema(restoreTable.getTable().getSchema()); - String tblName = schema+"."+restoreTable.getTable().getName(); - Map tables = adapter.getTables(schema); - boolean exist = false; - if(!(tables == null || tables.isEmpty() )) { - for(DBTable table:tables.values()) { - if(restoreTable.getTable().getName().equals(table.getName())){ - exist = true; - Map currentFileds = adapter.getTableFields(schema, restoreTable.getTable().getName()); - MapDifference diffTableFields = Maps.difference(restoreTable.getFields(),currentFileds); - - if(!diffTableFields.entriesOnlyOnLeft().isEmpty()){ - for(DBTableField tblField:diffTableFields.entriesOnlyOnLeft().values()) { - st.execute("alter table "+ tblName +" add column " + tblField.getName() + " " + tblField.getTypeSQL()); - - if (tblField.getDescription() != null && tblField.getDescription().length() > 0) - st.execute("COMMENT ON COLUMN " + tblName + "." + ((adapter.isReservedWord(tblField.getName()) || tblField.getNameExactly()) ? "\"" + tblField.getName() + "\" " : tblField.getName()) + " IS '" + tblField.getDescription() + "'"); - - if (!tblField.getIsNullable()) { - st.execute("alter table " + tblName + " alter column " + (adapter.isReservedWord(tblField.getName()) ? "\"" + tblField.getName() + "\" " : tblField.getName()) + " set not null"); - } - - if (tblField.getDefaultValue() != null && tblField.getDefaultValue().length() > 0) { - st.execute("alter table " + tblName + " alter column " + (adapter.isReservedWord(tblField.getName()) ? "\"" + tblField.getName() + "\" " : tblField.getName()) - + " SET DEFAULT " + tblField.getDefaultValue()); - } - } - } - - if(!diffTableFields.entriesOnlyOnRight().isEmpty()) { - for(DBTableField tblField:diffTableFields.entriesOnlyOnRight().values()) { - st.execute("alter table "+ tblName +" drop column IF EXISTS "+ tblField.getName()); - } - } - - if(!diffTableFields.entriesDiffering().isEmpty()) { - for(ValueDifference tblField:diffTableFields.entriesDiffering().values()) { - if(!tblField.leftValue().getName().equals(tblField.rightValue().getName())) { - st.execute("alter table "+ tblName +" rename column "+ tblField.rightValue().getName() +" to "+ tblField.leftValue().getName()); - } - - if(!tblField.leftValue().getTypeSQL().equals(tblField.rightValue().getTypeSQL())) { - st.execute("alter table "+ tblName +" alter column "+ tblField.leftValue().getName() +" type "+ tblField.leftValue().getTypeSQL()); - } - } - } - } - } - } - if(!exist){ - for(DBTableField tblField:restoreTable.getFields().values()) { - st.execute("alter table "+ tblName +" add column " + tblField.getName() + " " + tblField.getTypeSQL()); - - if (tblField.getDescription() != null && tblField.getDescription().length() > 0) - st.execute("COMMENT ON COLUMN " + tblName + "." + ((adapter.isReservedWord(tblField.getName()) || tblField.getNameExactly()) ? "\"" + tblField.getName() + "\" " : tblField.getName()) + " IS '" + tblField.getDescription() + "'"); - - if (!tblField.getIsNullable()) { - st.execute("alter table " + tblName + " alter column " + (adapter.isReservedWord(tblField.getName()) ? "\"" + tblField.getName() + "\" " : tblField.getName()) + " set not null"); - } - - if (tblField.getDefaultValue() != null && tblField.getDefaultValue().length() > 0) { - st.execute("alter table " + tblName + " alter column " + (adapter.isReservedWord(tblField.getName()) ? "\"" + tblField.getName() + "\" " : tblField.getName()) - + " SET DEFAULT " + tblField.getDefaultValue()); - } - - } - } - - ResultSet rs = st.executeQuery("SELECT COUNT(*) as constraintscount FROM pg_catalog.pg_constraint r WHERE r.conrelid = '"+tblName+"'::regclass"); - rs.next(); - Integer constraintsCount = Integer.valueOf(rs.getString("constraintscount")); - if(constraintsCount.intValue()>0) { - removeTableConstraintsPostgres(obj); - } - // set primary key - for(DBConstraint tableconst: restoreTable.getConstraints().values()) { - if(tableconst.getConstraintType().equals("p")) { - st.execute("alter table "+ tblName +" add constraint "+ DBAdapterPostgres.escapeNameIfNeeded(tableconst.getName()) + " "+tableconst.getSql().replace(" " + tableconst.getSql() + ".", " " + schema + ".")); - break; - } - } - } - else - { - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); - } - } catch (Exception e) { - ConsoleWriter.println(lang.getValue("errors", "restore", "objectRestoreError").withParams(e.getLocalizedMessage())); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); - } finally { - st.close(); - } - } - public void restoreTableIndexesPostgres(IMetaObject obj) throws Exception { - IDBAdapter adapter = getAdapter(); - Connection connect = adapter.getConnection(); - StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "restoreIndex").withParams(obj.getName()), 1); - try { - if (obj instanceof MetaTable) { - MetaTable restoreTable = (MetaTable)obj; - MetaTable existingTable = new MetaTable(restoreTable.getTable()); - String schema = getPhisicalSchema(restoreTable.getTable().getSchema()); - - if(existingTable.loadFromDB()){ - MapDifference diffInd = Maps.difference(restoreTable.getIndexes(), existingTable.getIndexes()); - - for(DBIndex ind:diffInd.entriesOnlyOnLeft().values()) { - if(restoreTable.getConstraints().containsKey(ind.getName())) {continue;} - st.execute(MessageFormat.format("{0} {1}" - ,ind.getSql().replace(" INDEX ", " INDEX IF NOT EXISTS ") - ,ind.getOptions().getChildren().containsKey("tablespace") ? " tablespace " + ind.getOptions().get("tablespace").getData() : "" - )); - } - - for(DBIndex ind:diffInd.entriesOnlyOnRight().values()) { - if(existingTable.getConstraints().containsKey(ind.getName())) continue; - st.execute("drop index if exists "+schema+"."+ DBAdapterPostgres.escapeNameIfNeeded(ind.getName())); - } - - for(ValueDifference ind : diffInd.entriesDiffering().values()) { - DBIndex restoreIndex = ind.leftValue(); - DBIndex existingIndex = ind.rightValue(); - if(!restoreIndex.getSql().equalsIgnoreCase(existingIndex.getSql())) { - st.execute(MessageFormat.format("drop index {0}.{1};\n{2};\n", - schema - , DBAdapterPostgres.escapeNameIfNeeded(existingIndex.getName()) - , restoreIndex.getSql() - )); - } - - st.execute(MessageFormat.format( - "alter index {0}.{1} set tablespace {2}" - ,schema - ,DBAdapterPostgres.escapeNameIfNeeded(existingIndex.getName()) - ,restoreIndex.getOptions().getChildren().containsKey("tablespace") - ? restoreIndex.getOptions().get("tablespace").getData() - : "pg_default" - )); - } - connect.commit(); - } else { - // TODO error if not exists - } - } - else { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); - } - } catch (Exception e) { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - ConsoleWriter.println(lang.getValue("errors", "restore", "objectRestoreError").withParams(e.getLocalizedMessage())); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); - } finally { - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); - st.close(); - } - } - public void restoreTableConstraintPostgres(IMetaObject obj) throws Exception { - IDBAdapter adapter = getAdapter(); - Connection connect = adapter.getConnection(); - StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "restoreConstr").withParams(obj.getName()), 1); - try { - if (obj instanceof MetaTable) { - MetaTable restoreTable = (MetaTable)obj; - MetaTable existingTable = new MetaTable(restoreTable.getTable()); - existingTable.loadFromDB(); - - String schema = getPhisicalSchema(restoreTable.getTable().getSchema()); - - MapDifference diff = Maps.difference(existingTable.getConstraints(), restoreTable.getConstraints()); - - //drop unneeded - for(DBConstraint constr : diff.entriesOnlyOnLeft().values()){ - st.execute(MessageFormat.format( - "alter table {0}.{1} drop constraint {2};\n" - , schema - , DBAdapterPostgres.escapeNameIfNeeded(existingTable.getTable().getName()) - , DBAdapterPostgres.escapeNameIfNeeded(constr.getName()) - )); - } - - // restore not existing - // not restore index if not exists and have the same named PK - Set typesFirst = Sets.newHashSet("p", "u"); - Comparator pksFirstComparator = Comparator.comparing(x->!typesFirst.contains(x.getConstraintType())); - for(DBConstraint constr : diff.entriesOnlyOnRight().values().stream().sorted(pksFirstComparator).collect(Collectors.toList()) ) { - createConstraint(restoreTable, constr, st, false); - } - - //process intersects - for (ValueDifference constr : diff.entriesDiffering().values()){ - MapDifference propsDiff = Maps.difference(constr.leftValue().getOptions().getChildren(), constr.leftValue().getOptions().getChildren()); - ConsoleWriter.printlnColor("Difference in constraints: " + propsDiff.toString(), Ansi.FColor.MAGENTA, 1); - createConstraint(restoreTable, constr.rightValue(), st, true); - } - - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); - } - else { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); - } - } catch (Exception e) { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - ConsoleWriter.println(lang.getValue("errors", "restore", "objectRestoreError").withParams(e.getLocalizedMessage())); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); - } finally { - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); - st.close(); - } - } - - private void createConstraint(MetaTable restoreTable, DBConstraint constr, StatementLogging st, boolean replaceExisting) throws Exception { - String schema = getPhisicalSchema(constr.getSchema()); - String tableSam = schema + "." + DBAdapterPostgres.escapeNameIfNeeded(restoreTable.getTable().getName()); - String constrName = DBAdapterPostgres.escapeNameIfNeeded(constr.getName()); - String constrDdl = (replaceExisting) ? MessageFormat.format("alter table {0} drop constraint {1};\n", tableSam, constrName) : ""; - constrDdl += MessageFormat.format( - "alter table {0} add constraint {1} {2};\n" - ,tableSam - ,constrName - ,constr.getSql() - .replace(" " + constr.getSchema() + ".", " " + schema + ".") - .replace("REFERENCES ", "REFERENCES " + schema + ".") - ); - st.execute(constrDdl); - } - - - public void removeTableConstraintsPostgres(IMetaObject obj) throws Exception { - IDBAdapter adapter = getAdapter(); - Connection connect = adapter.getConnection(); - StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - try { - if (obj instanceof MetaTable) { - MetaTable table = (MetaTable)obj; - String schema = getPhisicalSchema(table.getTable().getSchema()); - - Map constraints = table.getConstraints(); - for(DBConstraint constrs :constraints.values()) { - st.execute( - "alter table "+ schema +"."+DBAdapterPostgres.escapeNameIfNeeded(table.getTable().getName()) - +" drop constraint if exists "+DBAdapterPostgres.escapeNameIfNeeded(constrs.getName()) - ); - } - } - else { - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); - } - } catch (Exception e) { - ConsoleWriter.println(lang.getValue("errors", "restore", "objectRestoreError").withParams(e.getLocalizedMessage())); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); - } - } - - public void removeTableIndexesPostgres(IMetaObject obj) throws Exception { - IDBAdapter adapter = getAdapter(); - Connection connect = adapter.getConnection(); - StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - try { - if (obj instanceof MetaTable) { - MetaTable table = (MetaTable)obj; - String schema = getPhisicalSchema(table.getTable().getSchema()); - - Map constraints = table.getIndexes(); - for(DBIndex constrs :constraints.values()) { - st.execute(MessageFormat.format( - "alter table {0}.{1} drop index if exists {2}" - ,schema - ,DBAdapterPostgres.escapeNameIfNeeded(table.getTable().getName()) - ,DBAdapterPostgres.escapeNameIfNeeded(constrs.getName()) - )); - } - } - else - { - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); - } - } catch (Exception e) { - ConsoleWriter.println(lang.getValue("errors", "restore", "objectRestoreError").withParams(e.getLocalizedMessage())); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); - } - } - - /*public void removeIndexesPostgres(IMetaObject obj) throws Exception { - IDBAdapter adapter = getAdapter(); - Connection connect = adapter.getConnection(); - StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - try { - if (obj instanceof MetaTable) { - MetaTable table = (MetaTable)obj; - Map indexes = table.getIndexes(); - for(DBIndex index :indexes.values()) { - st.execute("DROP INDEX IF EXISTS "+index.getName()); - } - } - else - { - throw new ExceptionDBGitRestore("Error restore: Unable to remove TableIndexes."); - } - } - catch(Exception e) { - throw new ExceptionDBGitRestore("Error restore "+obj.getName(), e); - } - }*/ - - public void removeMetaObject(IMetaObject obj) throws Exception { - IDBAdapter adapter = getAdapter(); - Connection connect = adapter.getConnection(); - StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - - try { - MetaTable tblMeta = (MetaTable)obj; - DBTable tbl = tblMeta.getTable(); - if (tbl == null) return; - - String schema = getPhisicalSchema(tbl.getSchema()); - - freeTableSequences(tbl, connect, st); - st.execute("DROP TABLE "+schema+"."+DBAdapterPostgres.escapeNameIfNeeded(tbl.getName())); - connect.commit(); - } catch (Exception e) { - ConsoleWriter.println(lang.getValue("errors", "restore", "objectRestoreError").withParams(e.getLocalizedMessage())); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRemoveError").withParams(obj.getName()), e); - } finally { - st.close(); - } - } - - private void freeTableSequences(DBTable tbl, Connection conn, StatementLogging st) throws SQLException { - Statement stService = conn.createStatement(); - ResultSet rsSequences = stService.executeQuery("SELECT n.nspname as schema, s.relname as sequence, t.relname as table\n" + - " FROM pg_class s, pg_depend d, pg_class t, pg_attribute a, pg_namespace n \n" + - " WHERE s.relkind = 'S' \n" + - " AND n.oid = s.relnamespace \n" + - " AND d.objid = s.oid \n" + - " AND d.refobjid = t.oid \n" + - " AND (d.refobjid, d.refobjsubid) = (a.attrelid, a.attnum)\n" + - " AND n.nspname = '"+tbl.getSchema()+"' AND t.relname = '"+tbl.getName()+"'"); - - while (rsSequences.next()) st.execute(MessageFormat.format( - "ALTER SEQUENCE {0}.{1} OWNED BY NONE" - , rsSequences.getString("schema") - , rsSequences.getString("sequence")) - ); - - stService.close(); - } - -} +package ru.fusionsoft.dbgit.postgres; + +import com.diogonunes.jcdp.color.api.Ansi; +import com.google.common.collect.MapDifference; +import com.google.common.collect.MapDifference.ValueDifference; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter; +import ru.fusionsoft.dbgit.adapters.IDBAdapter; +import ru.fusionsoft.dbgit.core.DBGitConfig; +import ru.fusionsoft.dbgit.core.ExceptionDBGit; +import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; +import ru.fusionsoft.dbgit.core.GitMetaDataManager; +import ru.fusionsoft.dbgit.core.db.FieldType; +import ru.fusionsoft.dbgit.dbobjects.*; +import ru.fusionsoft.dbgit.meta.DBGitMetaType; +import ru.fusionsoft.dbgit.meta.IMetaObject; +import ru.fusionsoft.dbgit.meta.MetaTable; +import ru.fusionsoft.dbgit.meta.NameMeta; +import ru.fusionsoft.dbgit.statement.StatementLogging; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; +import ru.fusionsoft.dbgit.utils.StringProperties; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.text.MessageFormat; +import java.util.*; +import java.util.stream.Collectors; + +public class DBRestoreTablePostgres extends DBRestoreAdapter { + + @Override + public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { + + if(Integer.valueOf(step).equals(0)) { + restoreTablePostgres(obj); + return false; + } + + if(Integer.valueOf(step).equals(1)) { + restoreTableIndexesPostgres(obj); + return false; + } + + if(Integer.valueOf(step).equals(-1)) { + restoreTableConstraintPostgres(obj); + return false; + } + + if(Integer.valueOf(step).equals(-2)) { + removeTableConstraintsPostgres(obj); + removeTableIndexesPostgres(obj); + return false; + } + + return true; + } + public void removeMetaObject(IMetaObject obj) throws Exception { + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + + try { + MetaTable tblMeta = (MetaTable)obj; + DBTable tbl = tblMeta.getTable(); + if (tbl == null) return; + + String schema = getPhisicalSchema(tbl.getSchema()); + + freeTableSequences(tbl, connect, st); + st.execute("DROP TABLE "+adapter.escapeNameIfNeeded(schema)+"."+adapter.escapeNameIfNeeded(tbl.getName())); + } catch (Exception e) { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRemoveError").withParams(obj.getName()), e); + } finally { + st.close(); + } + } + + public void restoreTablePostgres(IMetaObject obj) throws Exception { + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + try { + if (obj instanceof MetaTable) { + MetaTable restoreTable = (MetaTable)obj; + MetaTable existingTable = new MetaTable(restoreTable.getTable()); + + + String schema = adapter.escapeNameIfNeeded(getPhisicalSchema(restoreTable.getTable().getSchema().toLowerCase())); + String tblName = adapter.escapeNameIfNeeded(restoreTable.getTable().getName()); + String tblSam = adapter.escapeNameIfNeeded(schema) + "." + adapter.escapeNameIfNeeded(tblName); + + + //find existing table and set tablespace or create + if (existingTable.loadFromDB()){ + + restoreTableTablespace(st, restoreTable, existingTable); + restoreTableOwner(st, restoreTable, existingTable); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + + } else { + + ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "createTable"), messageLevel); + createTable(st, restoreTable); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + + } + + + restoreTableFields(restoreTable, existingTable, st); + restoreTableComment(restoreTable, existingTable, st); + restoreTablePartition(restoreTable, st); + + } + else { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "table", obj.getType().getValue() + )); + } + } catch (Exception e) { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); + } finally { + st.close(); + } + } + public void restoreTableIndexesPostgres(IMetaObject obj) throws Exception { + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "restoreIndex").withParams(obj.getName()), messageLevel); + try { + if (obj instanceof MetaTable) { + MetaTable restoreTable = (MetaTable)obj; + MetaTable existingTable = new MetaTable(restoreTable.getTable()); + String schema = getPhisicalSchema(restoreTable.getTable().getSchema()); + + if(existingTable.loadFromDB()){ + MapDifference diffInd = Maps.difference(restoreTable.getIndexes(), existingTable.getIndexes()); + + for(DBIndex ind:diffInd.entriesOnlyOnLeft().values()) { + if(restoreTable.getConstraints().containsKey(ind.getName())) {continue;} + st.execute(MessageFormat.format("{0} {1}" + ,ind.getSql()/*.replace(" INDEX ", " INDEX IF NOT EXISTS ")*/ + ,ind.getOptions().getChildren().containsKey("tablespace") ? " tablespace " + ind.getOptions().get("tablespace").getData() : "" + )); + } + + for(DBIndex ind:diffInd.entriesOnlyOnRight().values()) { + if(existingTable.getConstraints().containsKey(ind.getName())) continue; + st.execute(MessageFormat.format("drop index if exists {0}.{1}" + , adapter.escapeNameIfNeeded(schema) + , adapter.escapeNameIfNeeded(ind.getName()) + )); + } + + for(ValueDifference ind : diffInd.entriesDiffering().values()) { + DBIndex restoreIndex = ind.leftValue(); + DBIndex existingIndex = ind.rightValue(); + if(!restoreIndex.getSql().equalsIgnoreCase(existingIndex.getSql())) { + st.execute(MessageFormat.format( + "DROP INDEX {0}.{1} CASCADE;\n" + "{2};\n", //TODO discuss CASCADE + adapter.escapeNameIfNeeded(schema) + , adapter.escapeNameIfNeeded(existingIndex.getName()) + , restoreIndex.getSql() //drop and re-create using full DDL from .getSql() + )); + st.execute(MessageFormat.format( + "alter index {0}.{1} set tablespace {2}" + ,adapter.escapeNameIfNeeded(schema) + ,adapter.escapeNameIfNeeded(restoreIndex.getName()) + ,restoreIndex.getOptions().getChildren().containsKey("tablespace") + ? restoreIndex.getOptions().get("tablespace").getData() + : "pg_default" + )); + } + } + } else { + // TODO error if not exists + } + } + else { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "table", obj.getType().getValue() + )); + } + } catch (Exception e) { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); + } finally { + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + st.close(); + } + } + public void restoreTableConstraintPostgres(IMetaObject obj) throws Exception { + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + try { + if (obj instanceof MetaTable) { + ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "restoreTableConstraints").withParams(obj.getName()), messageLevel); + MetaTable restoreTable = (MetaTable)obj; + MetaTable existingTable = new MetaTable(restoreTable.getTable()); + existingTable.loadFromDB(); + + enrichWithNotNullConstraints(existingTable); + enrichWithNotNullConstraints(restoreTable); + + MapDifference diff = Maps.difference(existingTable.getConstraints(), restoreTable.getConstraints()); + + // 0. drop unneeded + for(DBConstraint constr : diff.entriesOnlyOnLeft().values()){ + dropConstraint(existingTable, constr, st); + } + + // 1. restore not existing + Set typesFirst = Sets.newHashSet("p", "u"); + List newConstraints = diff.entriesOnlyOnRight().values().stream() + .sorted(Comparator.comparing( x -> !typesFirst.contains(x.getConstraintType()) )) + .collect(Collectors.toList()); + + for(DBConstraint constr : newConstraints) { + // * * * not restore index if not exists and have the same named PK + createConstraint(restoreTable, constr, st, false /* * */); + } + + // 2. process intersects + for (ValueDifference constr : diff.entriesDiffering().values()){ + //MapDifference propsDiff = Maps.difference(constr.leftValue().getOptions().getChildren(), constr.leftValue().getOptions().getChildren()); + //ConsoleWriter.printlnColor("Difference in constraints: " + propsDiff.toString(), Ansi.FColor.MAGENTA, 1); + createConstraint(restoreTable, constr.rightValue(), st, true); + } + + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + } + else { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "table", obj.getType().getValue() + )); + } + } catch (Exception e) { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); + } finally { + st.close(); + } + } + + private void dropConstraint(MetaTable existingTable, DBConstraint constr, StatementLogging st) throws SQLException, ExceptionDBGit { + String schema = getPhisicalSchema(existingTable.getTable().getSchema()); + String name = existingTable.getTable().getName(); + + if(constr.getConstraintType().equals("nn")){ + st.execute(MessageFormat.format( + "ALTER TABLE {0}.{1} ALTER {2} DROP NOT NULL;\n" + , adapter.escapeNameIfNeeded(schema) + , adapter.escapeNameIfNeeded(name) + , adapter.escapeNameIfNeeded(constr.getOptions().get("column_name").getData()) + )); + } else { + st.execute(MessageFormat.format( + "ALTER TABLE {0}.{1} DROP CONSTRAINT {2};\n" + , adapter.escapeNameIfNeeded(schema) + , adapter.escapeNameIfNeeded(name) + , adapter.escapeNameIfNeeded(constr.getName()) + )); + } + } + + private NameMeta getEscapedNameMeta(MetaTable table) throws ExceptionDBGit { + NameMeta nm = new NameMeta(); + String schema = adapter.escapeNameIfNeeded(getPhisicalSchema(table.getTable().getSchema().toLowerCase())); + String tblName = adapter.escapeNameIfNeeded(table.getTable().getName()); + + nm.setSchema(schema); + nm.setName(tblName); + nm.setType(DBGitMetaType.DBGitTable); + return nm; + } + + + private void restoreTableFields(MetaTable restoreTable, MetaTable existingTable, StatementLogging st) throws Exception { + String lastField = ""; + try { + NameMeta nme = getEscapedNameMeta(existingTable); + String tblSam = nme.getSchema()+"."+nme.getName(); + + MapDifference diffTableFields = Maps.difference(restoreTable.getFields(),existingTable.getFields()); + + if(!diffTableFields.entriesOnlyOnLeft().isEmpty()){ + ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "addColumns"), messageLevel); + + List fields = diffTableFields.entriesOnlyOnLeft().values().stream() + .sorted(Comparator.comparing(DBTableField::getOrder)) + .collect(Collectors.toList()); + + for(DBTableField tblField : fields) { + lastField = tblField.getName(); + addColumn(tblSam, tblField, st); + } + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + } + + if(!diffTableFields.entriesOnlyOnRight().isEmpty()) { + ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "droppingColumns"), messageLevel); + for(DBTableField tblField:diffTableFields.entriesOnlyOnRight().values()) { + lastField = tblField.getName(); + dropColumn(tblSam, tblField, st); + } + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + } + + if(!diffTableFields.entriesDiffering().isEmpty()) { + ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "modifyColumns"), messageLevel); + for(ValueDifference tblField:diffTableFields.entriesDiffering().values()) { + lastField = tblField.leftValue().getName(); + + DBTableField restoreField = tblField.leftValue(); + DBTableField existingField = tblField.rightValue(); + if( !isSameTypeSql(tblField.leftValue(), tblField.rightValue()) ) { + if( true + &&(existingField.getTypeUniversal() != FieldType.BOOLEAN) + &&(restoreField.getTypeUniversal() != FieldType.BOOLEAN) + &&(existingField.getTypeUniversal() != FieldType.STRING_NATIVE) + &&(restoreField.getTypeUniversal() != FieldType.STRING_NATIVE) + &&(existingField.getTypeUniversal() != FieldType.NATIVE) + &&(restoreField.getTypeUniversal() != FieldType.NATIVE) + && hasNotTypeSql(tblField, "json") + && hasNotTypeSql(tblField, "text[]") + && hasNotTypeSql(tblField, "text") + ){ //Lots of exclusions when this don't work + alterTypeColumn(tblSam, tblField, st); + } else { + dropColumn(tblSam, tblField.rightValue(), st); + addColumn(tblSam, tblField.leftValue(), st); + } + } + + restoreTableFieldComment(tblSam, tblField, st); + restoreTableFieldDefaultValue(tblSam, tblField, st); + + if(!tblField.leftValue().getName().equals(tblField.rightValue().getName())) { + throw new Exception("just 'differing' columns, but differs in names, was: " + tblField.rightValue().getName() + ", to restore: " + tblField.leftValue().getName()); + // st.execute( + // "alter table " + // + tblSam + // +" rename column "+ adapter.escapeNameIfNeeded(tblField.rightValue().getName()) + // +" to "+ adapter.escapeNameIfNeeded(tblField.leftValue().getName()) + // ); + } + } + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + } + } catch (Exception e) { + throw new ExceptionDBGit( + lang.getValue("errors", "restore", "objectRestoreError").withParams(restoreTable.getName()+"#"+lastField) + , e + ); + } + } + private void createTable(StatementLogging st, MetaTable restoreTable) throws Exception { + NameMeta nme = getEscapedNameMeta(restoreTable); + + String createTableDdl = MessageFormat.format( + "create table {0}.{1}() {2};" + ,nme.getSchema() + ,nme.getName() + ,restoreTable.getTable().getOptions().getChildren().containsKey("tablespace") + ? "tablespace " + restoreTable.getTable().getOptions().get("tablespace").getData() + : "" + + ); + + if(!DBGitConfig.getInstance().getToIgnoreOnwer(false)){ + createTableDdl += MessageFormat.format("\n alter table {0}.{1} owner to {2}\n;", + nme.getSchema() ,nme.getName(), + restoreTable.getTable().getOptions().getChildren().containsKey("owner") + ? restoreTable.getTable().getOptions().get("owner").getData() + : "postgres" + ); + } + + if (restoreTable.getTable().getOptions().getChildren().containsKey("partkeydef")) { + createTableDdl = createTableDdl.replace(" ) ", ") PARTITION BY " + + restoreTable.getTable().getOptions().getChildren().get("partkeydef") + + " "); + } + + st.execute(createTableDdl); + } + private void restoreTableOwner(StatementLogging st, MetaTable restoreTable, MetaTable existingTable) throws Exception { + String schema = adapter.escapeNameIfNeeded(getPhisicalSchema(restoreTable.getTable().getSchema().toLowerCase())); + String tblName = adapter.escapeNameIfNeeded(restoreTable.getTable().getName()); + + StringProperties exOwner= existingTable.getTable().getOptions().get("owner"); + StringProperties restoreOwner = restoreTable.getTable().getOptions().get("owner"); + + if(!DBGitConfig.getInstance().getToIgnoreOnwer(false)){ + if(restoreOwner != null && ( exOwner == null || !exOwner.getData().equals(restoreOwner.getData()) ) ){ + String alterTableDdl = MessageFormat.format( + "alter table {0}.{1} owner to {2};\n" + ,schema + ,tblName + ,restoreTable.getTable().getOptions().get("owner").getData() + ); + st.execute(alterTableDdl); + } + } + } + private void restoreTableTablespace(StatementLogging st, MetaTable restoreTable, MetaTable existingTable) throws SQLException, ExceptionDBGit { + NameMeta nme = getEscapedNameMeta(existingTable); + + StringProperties exTablespace = existingTable.getTable().getOptions().get("tablespace"); + StringProperties restoreTablespace = restoreTable.getTable().getOptions().get("tablespace"); + if(restoreTablespace != null && + ( exTablespace == null || !exTablespace.getData().equals(restoreTablespace.getData()) ) ){ + //TODO For now in postgres context tablespace is always missing! + String alterTableDdl = MessageFormat.format( + "alter table {0}.{1} set tablespace {2};\n" + ,nme.getSchema() + ,nme.getName() + ,restoreTable.getTable().getOptions().get("tablespace").getData() + ); + st.execute(alterTableDdl); + } + } + + + //TODO removeMetaObject + private void freeTableSequences(DBTable tbl, Connection conn, StatementLogging st) throws SQLException { + Statement stService = conn.createStatement(); + ResultSet rsSequences = stService.executeQuery("SELECT n.nspname as schema, s.relname as sequence, t.relname as table\n" + + " FROM pg_class s, pg_depend d, pg_class t, pg_attribute a, pg_namespace n \n" + + " WHERE s.relkind = 'S' \n" + + " AND n.oid = s.relnamespace \n" + + " AND d.objid = s.oid \n" + + " AND d.refobjid = t.oid \n" + + " AND (d.refobjid, d.refobjsubid) = (a.attrelid, a.attnum)\n" + + " AND n.nspname = '"+tbl.getSchema()+"' AND t.relname = '"+tbl.getName()+"'"); + + while (rsSequences.next()) st.execute(MessageFormat.format( + "ALTER SEQUENCE {0}.{1} OWNED BY NONE" + , rsSequences.getString("schema") + , rsSequences.getString("sequence")) + ); + + stService.close(); + } + + + //TODO restoreTablePostgres + private void restoreTableComment(MetaTable restoreTable, MetaTable existingTable, Statement st) throws ExceptionDBGit, SQLException + { + + String restoreTableComment = restoreTable.getTable().getComment(); + String existingTableComment = existingTable.getTable().getComment(); + boolean restoreCommentPresent = restoreTableComment != null && restoreTableComment.length() > 0; + boolean existingCommentPresent = existingTableComment != null && existingTableComment.length() > 0; + + if (restoreCommentPresent){ + boolean commentsDiffer = !existingCommentPresent || !existingTableComment.equals(restoreTableComment); + if(commentsDiffer){ + st.execute(MessageFormat.format( + "COMMENT ON TABLE {0}.{1} IS ''{2}''" + ,adapter.escapeNameIfNeeded(getPhisicalSchema(restoreTable.getTable().getSchema())) + ,adapter.escapeNameIfNeeded(restoreTable.getTable().getName()) + ,restoreTableComment + )); + } + } + } + private void restoreTablePartition(MetaTable restoreTable, Statement st) throws ExceptionDBGit, SQLException + { + NameMeta nme = getEscapedNameMeta(restoreTable); + StringProperties parent = restoreTable.getTable().getOptions().getChildren().get("parent"); + StringProperties pg_get_expr = restoreTable.getTable().getOptions().getChildren().get("pg_get_expr"); + + if(parent != null && pg_get_expr != null){ + st.execute(MessageFormat.format( + "ALTER TABLE {0}.{1} ATTACH PARTITION {0}.{2} {3}" + , nme.getSchema() + , parent + , nme.getName() + , pg_get_expr + )); + } + + } + + + //TODO restoreTableConstraintPostgres + private void createConstraint(MetaTable restoreTable, DBConstraint constr, StatementLogging st, boolean replaceExisting) throws Exception { + //dont create constraint on table with 'parent' key + if (restoreTable.getTable().getOptions().getChildren().containsKey("parent")) return; + + NameMeta nme = getEscapedNameMeta(restoreTable); + String tblSam = getPhisicalSchema(nme.getSchema())+"."+nme.getName(); + String constrDdl; + + if(constr.getConstraintType().equals("nn")){ + constrDdl = MessageFormat.format("ALTER TABLE {0} {1};\n", tblSam, constr.getSql()); + + } else { + String constrName = adapter.escapeNameIfNeeded(constr.getName()); + + constrDdl = (replaceExisting) + ? MessageFormat.format("ALTER TABLE {0} DROP CONSTRAINT {1};\n", tblSam, constrName) + : ""; + constrDdl += MessageFormat.format( + "ALTER TABLE {0} ADD CONSTRAINT {1} {2};\n" + ,tblSam + ,constrName + ,constr.getSql() + .replace(" " + constr.getSchema() + ".", " " + nme.getSchema() + ".") + .replace("REFERENCES ", "REFERENCES " + nme.getSchema() + ".") + ); + } + + st.execute(constrDdl); + } + + + //TODO restoreTableFields + private void addColumn(String tblSam, DBTableField tblField, Statement st ) throws SQLException { + String fieldName = adapter.escapeNameIfNeeded(tblField.getName()); + st.execute( + "alter table "+ tblSam +" add column " + + fieldName + " " + + tblField.getTypeSQL().replace("NOT NULL", "") + ); + if (tblField.getDescription() != null && tblField.getDescription().length() > 0) + st.execute( + "COMMENT ON COLUMN " + tblSam + "." + + fieldName + + " IS '" + tblField.getDescription() + "'" + ); + + + if (tblField.getDefaultValue() != null && tblField.getDefaultValue().length() > 0) { + st.execute( + "alter table " + tblSam + " alter column " + fieldName + + " SET DEFAULT " + tblField.getDefaultValue() + ); + } + + } + private void dropColumn(String tblSam, DBTableField tblField, Statement st) throws SQLException { + st.execute("alter table "+ tblSam +" drop column "+ adapter.escapeNameIfNeeded(tblField.getName())); + } + private boolean isSameTypeSql(DBTableField left, DBTableField right){ + return left.getTypeSQL().equals(right.getTypeSQL()); + } + + private boolean hasNotTypeSql(ValueDifference field, String typeSql){ + return !field.leftValue().getTypeSQL().contains(typeSql) && + !field.rightValue().getTypeSQL().contains(typeSql); + } + private void alterTypeColumn(String tblSam, ValueDifference tblField, Statement st) throws SQLException + { + st.execute(MessageFormat.format("ALTER TABLE {0} ALTER COLUMN {1} TYPE {2} USING ({3}::{4})" + , tblSam + , adapter.escapeNameIfNeeded(tblField.leftValue().getName()) + //NOT NULLs are created and dropped with other constraints as transient DBConstraint instances + , tblField.leftValue().getTypeSQL().replace("NOT NULL", "") + , adapter.escapeNameIfNeeded(tblField.leftValue().getName()) + , tblField.leftValue().getTypeSQL().replace("NOT NULL", "") + )); + + } + private void restoreTableFieldComment(String tableSam, ValueDifference tblField, Statement st) throws SQLException + { + + String restoreDesc = tblField.leftValue().getDescription(); + String existingDesc = tblField.rightValue().getDescription(); + boolean restoreDescPresent = restoreDesc != null && restoreDesc.length() > 0; + + if (restoreDescPresent){ + boolean existingDescPresent = existingDesc != null && existingDesc.length() > 0; + boolean needsUpdate = !existingDescPresent || !existingDesc.equals(restoreDesc); + if(needsUpdate){ + st.execute(MessageFormat.format( + "COMMENT ON COLUMN {0}.{1} IS ''{2}''" + ,tableSam + ,adapter.escapeNameIfNeeded(tblField.leftValue().getName()) + ,restoreDesc + )); + } + } + } + private void restoreTableFieldDefaultValue(String tableSam, ValueDifference tblField, Statement st) throws ExceptionDBGit, SQLException + { + + String restoreDefault = tblField.leftValue().getDefaultValue(); + String existingDefault = tblField.rightValue().getDefaultValue(); + boolean restoreDefaultPresent = restoreDefault != null && restoreDefault.length() > 0; + + if (restoreDefaultPresent){ + boolean existingDescPresent = existingDefault != null && existingDefault.length() > 0; + boolean needsUpdate = !existingDescPresent || !existingDefault.equals(restoreDefault); + if(needsUpdate){ + st.execute(MessageFormat.format( + "ALTER TABLE {0} ALTER COLUMN {1} SET DEFAULT {2}" + ,tableSam + ,adapter.escapeNameIfNeeded(tblField.leftValue().getName()) + ,restoreDefault + )); + } + } + } + + + //TODO unused + private void removeTableIndexesPostgres(IMetaObject obj) throws Exception { + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + try { + if (obj instanceof MetaTable) { + MetaTable table = (MetaTable)obj; + String schema = getPhisicalSchema(table.getTable().getSchema()); + + + Map indices = table.getIndexes(); + for(DBIndex index :indices.values()) { + if(table.getConstraints().containsKey(index.getName())) { continue; } + + st.execute(MessageFormat.format( + "DROP INDEX IF EXISTS {0}.{1}" + ,adapter.escapeNameIfNeeded(schema) +// ,adapter.escapeNameIfNeeded(table.getTable().getName()) + ,adapter.escapeNameIfNeeded(index.getName()) + )); + } + } + else { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "table", obj.getType().getValue() + )); + } + } catch (Exception e) { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); + } + } + private void removeTableConstraintsPostgres(IMetaObject obj) throws Exception { + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + try { + if (obj instanceof MetaTable) { + MetaTable table = (MetaTable)obj; + String schema = getPhisicalSchema(table.getTable().getSchema()); + MetaTable dbTable = (MetaTable) GitMetaDataManager.getInstance().getCacheDBMetaObject(obj.getName()); + + enrichWithNotNullConstraints(table); + Map constraints = dbTable.getConstraints(); + for(DBConstraint constrs :constraints.values()) { + dropConstraint(table, constrs, st); + } + } + else { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "table", obj.getType().getValue() + )); + } + } catch (Exception e) { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()) + , e + ); + } + } + + public void enrichWithNotNullConstraints(MetaTable table){ + table.getFields().values().stream() + .filter( field -> field.getIsNullable()) + .map( field -> constructNotNullDBConstraint(table, field)) + .forEach( nnc -> table.getConstraints().put(nnc.getName(), nnc) ); + } + + public DBConstraint constructNotNullDBConstraint(MetaTable table, DBTableField field){ + final String name = "notnull_" + field.getName() + " (Transient)"; + final String type = "nn"; + final String sql = ""; + final StringProperties options = new StringProperties(); + final Set dependencies = Collections.emptySet(); + final DBTable dbTable = table.getTable(); + final String schema = dbTable.getSchema(); + final String owner = dbTable.getOwner(); + + DBConstraint constraint = new DBConstraint(name, options, schema, owner, dependencies, sql, type); + + constraint.getOptions().getChildren().put("column_name", new StringProperties(field.getName())); + constraint.setSql(MessageFormat.format( + "ALTER COLUMN {0} SET NOT NULL" + , adapter.escapeNameIfNeeded(field.getName())) + ); + return constraint; + } + + /*public void removeIndexesPostgres(IMetaObject obj) throws Exception { + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + try { + if (obj instanceof MetaTable) { + MetaTable table = (MetaTable)obj; + Map indexes = table.getIndexes(); + for(DBIndex index :indexes.values()) { + st.execute("DROP INDEX IF EXISTS "+index.getName()); + } + } + else + { + throw new ExceptionDBGitRestore("Error restore: Unable to remove TableIndexes."); + } + } + catch(Exception e) { + throw new ExceptionDBGitRestore("Error restore "+obj.getName(), e); + } + }*/ +} diff --git a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreTableSpacePostgres.java b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreTableSpacePostgres.java index 90e83b3..51ca6e8 100644 --- a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreTableSpacePostgres.java +++ b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreTableSpacePostgres.java @@ -1,89 +1,90 @@ -package ru.fusionsoft.dbgit.postgres; - -import java.sql.Connection; -import java.util.Map; - -import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter; -import ru.fusionsoft.dbgit.adapters.IDBAdapter; -import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; -import ru.fusionsoft.dbgit.dbobjects.DBTableSpace; -import ru.fusionsoft.dbgit.meta.IMetaObject; -import ru.fusionsoft.dbgit.meta.MetaTableSpace; -import ru.fusionsoft.dbgit.statement.StatementLogging; -import ru.fusionsoft.dbgit.utils.ConsoleWriter; - -public class DBRestoreTableSpacePostgres extends DBRestoreAdapter{ - - @Override - public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { - IDBAdapter adapter = getAdapter(); - Connection connect = adapter.getConnection(); - StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "restoreTableSpace").withParams(obj.getName()), 1); - try { - if (obj instanceof MetaTableSpace) { - MetaTableSpace restoreTableSpace = (MetaTableSpace)obj; - Map tblspaces = adapter.getTableSpaces(); - boolean exist = false; - if(!(tblspaces.isEmpty() || tblspaces == null)) { - for(DBTableSpace tblspace:tblspaces.values()) { - if(restoreTableSpace.getObjectOption().getName().equals(tblspace.getName())){ - exist = true; - - String restorename = restoreTableSpace.getObjectOption().getName(); - String restoreowner = restoreTableSpace.getObjectOption().getOptions().getChildren().get("usename").getData(); - String restoreloc = restoreTableSpace.getObjectOption().getOptions().getChildren().get("pg_tablespace_location").getData(); - - st.execute("alter tablespace "+ restorename +" reset (seq_page_cost, random_page_cost, effective_io_concurrency)"); - - String currentname = tblspace.getName(); - String currentowner = tblspace.getOptions().getChildren().get("usename").getData(); - String currentloc = tblspace.getOptions().getChildren().get("pg_tablespace_location").getData(); - - if(!restoreowner.equals(currentowner)) { - st.execute("alter tablespace "+ restorename +" owner to "+ restoreowner); - } - - if(restoreTableSpace.getObjectOption().getOptions().getChildren().containsKey("spcoptions")) { - String options = restoreTableSpace.getObjectOption().getOptions().getChildren().get("spcoptions").getData().replaceAll("[\\{\\}]", ""); - st.execute("alter tablespace "+ restorename +" set ("+ options+")"); - } - - - /*if() { - //TODO Restore location ??? - }*/ - //TODO Восстановление привилегий - } - } - } - if(!exist){ - - //TODO Восстановление привилегий - } - else { - - } - } - else - { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); - } - } catch (Exception e) { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); - } finally { - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); - st.close(); - } - return true; - } - - @Override - public void removeMetaObject(IMetaObject obj) throws Exception { - // TODO Auto-generated method stub - - } - -} +package ru.fusionsoft.dbgit.postgres; + +import java.sql.Connection; +import java.util.Map; + +import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter; +import ru.fusionsoft.dbgit.adapters.IDBAdapter; +import ru.fusionsoft.dbgit.core.DBGitConfig; +import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; +import ru.fusionsoft.dbgit.dbobjects.DBTableSpace; +import ru.fusionsoft.dbgit.meta.IMetaObject; +import ru.fusionsoft.dbgit.meta.MetaTableSpace; +import ru.fusionsoft.dbgit.statement.StatementLogging; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; + +public class DBRestoreTableSpacePostgres extends DBRestoreAdapter{ + + @Override + public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + try { + if (obj instanceof MetaTableSpace) { + MetaTableSpace restoreTableSpace = (MetaTableSpace)obj; + Map tblspaces = adapter.getTableSpaces(); + boolean exist = false; + if(!(tblspaces.isEmpty() || tblspaces == null)) { + for(DBTableSpace tblspace:tblspaces.values()) { + if(restoreTableSpace.getObjectOption().getName().equals(tblspace.getName())){ + exist = true; + + String restorename = restoreTableSpace.getObjectOption().getName(); + String restoreowner = restoreTableSpace.getObjectOption().getOptions().getChildren().get("usename").getData(); + String restoreloc = restoreTableSpace.getObjectOption().getOptions().getChildren().get("pg_tablespace_location").getData(); + + st.execute("alter tablespace "+ restorename +" reset (seq_page_cost, random_page_cost, effective_io_concurrency)"); + + String currentname = tblspace.getName(); + String currentowner = tblspace.getOptions().getChildren().get("usename").getData(); + String currentloc = tblspace.getOptions().getChildren().get("pg_tablespace_location").getData(); + + if(!DBGitConfig.getInstance().getToIgnoreOnwer(false) && !restoreowner.equals(currentowner)) { + st.execute("alter tablespace "+ restorename +" owner to "+ restoreowner); + } + + if(restoreTableSpace.getObjectOption().getOptions().getChildren().containsKey("spcoptions")) { + String options = restoreTableSpace.getObjectOption().getOptions().getChildren().get("spcoptions").getData().replaceAll("[\\{\\}]", ""); + st.execute("alter tablespace "+ restorename +" set ("+ options+")"); + } + + + /*if() { + //TODO Restore location ??? + }*/ + //TODO Восстановление привилегий + } + } + } + if(!exist){ + + //TODO Восстановление привилегий + } + else { + + } + } + else + { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "tablespace", obj.getType().getValue() + )); + } + } catch (Exception e) { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); + } finally { + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + st.close(); + } + return true; + } + + @Override + public void removeMetaObject(IMetaObject obj) throws Exception { + // TODO Auto-generated method stub + + } + +} diff --git a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreTriggerPostgres.java b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreTriggerPostgres.java index 2f53db0..82bd4e3 100644 --- a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreTriggerPostgres.java +++ b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreTriggerPostgres.java @@ -1,100 +1,96 @@ -package ru.fusionsoft.dbgit.postgres; - -import java.sql.Connection; -import java.util.Map; - -import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter; -import ru.fusionsoft.dbgit.adapters.IDBAdapter; -import ru.fusionsoft.dbgit.core.ExceptionDBGit; -import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; -import ru.fusionsoft.dbgit.dbobjects.DBTrigger; -import ru.fusionsoft.dbgit.meta.IMetaObject; -import ru.fusionsoft.dbgit.meta.MetaTrigger; -import ru.fusionsoft.dbgit.statement.StatementLogging; -import ru.fusionsoft.dbgit.utils.ConsoleWriter; - -public class DBRestoreTriggerPostgres extends DBRestoreAdapter { - - - @Override - public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { - IDBAdapter adapter = getAdapter(); - Connection connect = adapter.getConnection(); - StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "restoreTrigger").withParams(obj.getName()), 1); - try { - if (obj instanceof MetaTrigger) { - MetaTrigger restoreTrigger = (MetaTrigger)obj; - Map trgs = adapter.getTriggers(restoreTrigger.getSqlObject().getSchema()); - boolean exist = false; - if(!(trgs.isEmpty() || trgs == null)) { - for(DBTrigger trg:trgs.values()) { - if(restoreTrigger.getSqlObject().getName().equals(trg.getName())){ - exist = true; - if(!restoreTrigger.getSqlObject().getSql().equals(trg.getSql())) { - String query = "DROP TRIGGER IF EXISTS "+restoreTrigger.getSqlObject().getName()+" ON "+restoreTrigger.getSqlObject().getOptions().get("trigger_table")+";\n"; - query+=restoreTrigger.getSqlObject().getSql()+";"; - st.execute(query); - } - //TODO Восстановление привилегий - } - } - } - if(!exist){ - st.execute(restoreTrigger.getSqlObject().getSql()); - //TODO Восстановление привилегий - } - } - else - { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); - } - - - - - } - catch (Exception e) { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); - } finally { - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); - st.close(); - } - - - - - - - - - - return true; - } - - @Override - public void removeMetaObject(IMetaObject obj) throws Exception { - IDBAdapter adapter = getAdapter(); - Connection connect = adapter.getConnection(); - StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - - try { - if(! (obj instanceof MetaTrigger)) throw new ExceptionDBGit("Wrong IMetaObject type, expected: trg, was: " + obj.getType().getValue()); - MetaTrigger trgMeta = (MetaTrigger) obj; - DBTrigger trg = (DBTrigger) trgMeta.getSqlObject(); - if (trg == null) return; - - String schema = getPhisicalSchema(trg.getSchema()); - st.execute("DROP FUNCTION IF EXISTS "+schema+"."+DBAdapterPostgres.escapeNameIfNeeded(trg.getName())); - - } catch (Exception e) { - ConsoleWriter.println(lang.getValue("errors", "restore", "objectRestoreError").withParams(e.getLocalizedMessage())); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRemoveError").withParams(obj.getName()), e); - } finally { - st.close(); - } - } - -} +package ru.fusionsoft.dbgit.postgres; + +import java.sql.Connection; +import java.util.Map; + +import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter; +import ru.fusionsoft.dbgit.adapters.IDBAdapter; +import ru.fusionsoft.dbgit.core.ExceptionDBGit; +import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; +import ru.fusionsoft.dbgit.dbobjects.DBTrigger; +import ru.fusionsoft.dbgit.meta.IMetaObject; +import ru.fusionsoft.dbgit.meta.MetaTrigger; +import ru.fusionsoft.dbgit.statement.StatementLogging; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; + +public class DBRestoreTriggerPostgres extends DBRestoreAdapter { + + + @Override + public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + try { + if (obj instanceof MetaTrigger) { + MetaTrigger restoreTrigger = (MetaTrigger)obj; + Map trgs = adapter.getTriggers(restoreTrigger.getSqlObject().getSchema()); + boolean exist = false; + if(!(trgs.isEmpty() || trgs == null)) { + for(DBTrigger trg:trgs.values()) { + if(restoreTrigger.getSqlObject().getName().equals(trg.getName())){ + exist = true; + if(!restoreTrigger.getSqlObject().getSql().equals(trg.getSql())) { + String query = "DROP TRIGGER IF EXISTS "+restoreTrigger.getSqlObject().getName()+" ON "+restoreTrigger.getSqlObject().getOptions().get("trigger_table")+";\n"; + query+=restoreTrigger.getSqlObject().getSql()+";"; + st.execute(query); + } + //TODO Восстановление привилегий + } + } + } + if(!exist){ + st.execute(restoreTrigger.getSqlObject().getSql()); + //TODO Восстановление привилегий + } + } + else + { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "trigger", obj.getType().getValue() + )); + } + + } + catch (Exception e) { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); + } finally { + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + st.close(); + } + + + + + + + + + + return true; + } + + @Override + public void removeMetaObject(IMetaObject obj) throws Exception { + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); + + try { + if(! (obj instanceof MetaTrigger)) throw new ExceptionDBGit("Wrong IMetaObject type, expected: trg, was: " + obj.getType().getValue()); + MetaTrigger trgMeta = (MetaTrigger) obj; + DBTrigger trg = (DBTrigger) trgMeta.getSqlObject(); + if (trg == null) return; + + String schema = getPhisicalSchema(trg.getSchema()); + st.execute("DROP FUNCTION IF EXISTS "+adapter.escapeNameIfNeeded(schema)+"."+adapter.escapeNameIfNeeded(trg.getName())); + + } catch (Exception e) { + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRemoveError").withParams(obj.getName()), e); + } finally { + st.close(); + } + } + +} diff --git a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreUDTPostgres.java b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreUDTPostgres.java new file mode 100644 index 0000000..14e206c --- /dev/null +++ b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreUDTPostgres.java @@ -0,0 +1,117 @@ +package ru.fusionsoft.dbgit.postgres; + +import java.sql.Connection; +import java.text.MessageFormat; +import java.util.Map; +import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter; +import ru.fusionsoft.dbgit.adapters.IDBAdapter; +import ru.fusionsoft.dbgit.core.DBGitConfig; +import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; +import ru.fusionsoft.dbgit.dbobjects.DBSQLObject; +import ru.fusionsoft.dbgit.dbobjects.DBUserDefinedType; +import ru.fusionsoft.dbgit.meta.IMetaObject; +import ru.fusionsoft.dbgit.meta.MetaUDT; +import ru.fusionsoft.dbgit.statement.StatementLogging; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; + +public class DBRestoreUDTPostgres extends DBRestoreAdapter { + @Override + public final boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { + final IDBAdapter adapter = getAdapter(); + final Connection connect = adapter.getConnection(); + try (final StatementLogging st = new StatementLogging( + connect, + adapter.getStreamOutputSqlCommand(), + adapter.isExecSql() + )) { + if (! ( obj instanceof MetaUDT )) { + throw new ExceptionDBGitRestore( + lang.getValue("errors", "restore", "metaTypeError").withParams(obj.getName(), "udt", obj.getType().getValue()) + ); + } + final DBSQLObject restoreUDT = (DBSQLObject) obj.getUnderlyingDbObject(); + final Map udts = adapter.getUDTs(restoreUDT.getSchema()); + + if (udts.containsKey(restoreUDT.getName())) { + final DBUserDefinedType currentUDT = udts.get(restoreUDT.getName()); + if ( + ! restoreUDT.getOptions().get("attributes").equals( + currentUDT.getOptions().get("attributes") + ) + ) { + st.execute(MessageFormat.format( + "ALTER TYPE {0}.{1} RENAME TO _deprecated_{1};\n" + + "{2}", + currentUDT.getSchema(), currentUDT.getName(), getDdlEscaped(restoreUDT) + )); + } else { + if (! DBGitConfig.getInstance().getToIgnoreOnwer(false)) { + st.execute(getChangeOwnerDdl(currentUDT, restoreUDT.getOwner())); + } + } + } else { + st.execute(getDdlEscaped(restoreUDT)); + } + + } catch (Exception e) { + throw new ExceptionDBGitRestore( + lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), + e + ); + } finally { + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + } + return true; + } + + @Override + public void removeMetaObject(IMetaObject obj) throws Exception { + final IDBAdapter adapter = getAdapter(); + final Connection connect = adapter.getConnection(); + + try (StatementLogging st = new StatementLogging( + connect, + adapter.getStreamOutputSqlCommand(), + adapter.isExecSql() + )) { + + final DBSQLObject currentObject = (DBSQLObject) obj.getUnderlyingDbObject(); + st.execute(MessageFormat.format( + "DROP TYPE {0}.{1}", + adapter.escapeNameIfNeeded(getPhisicalSchema(currentObject.getSchema())), + adapter.escapeNameIfNeeded(currentObject.getName()) + )); + + } catch (Exception e) { + throw new ExceptionDBGitRestore( + lang.getValue("errors", "restore", "objectRemoveError") + .withParams(obj.getName()), e); + } + } + + private String getDdlEscaped(DBSQLObject dbsqlObject) { + String query = dbsqlObject.getSql(); + final String name = dbsqlObject.getName(); + final String schema = dbsqlObject.getSchema(); + final String nameEscaped = adapter.escapeNameIfNeeded(name); + final String schemaEscaped = adapter.escapeNameIfNeeded(schema); + + if (! name.equalsIgnoreCase(nameEscaped)) { + query = query.replace( + "CREATE TYPE " + schema + "." + name, + "CREATE TYPE " + schemaEscaped + "." + nameEscaped + ); + } + if (! query.endsWith(";")) query = query + ";\n"; + query = query + "\n"; + return query; + } + + private String getChangeOwnerDdl(DBSQLObject dbsqlObject, String owner) { + return MessageFormat.format("ALTER TYPE {0}.{1} OWNER TO {2}\n" + , adapter.escapeNameIfNeeded(dbsqlObject.getSchema()) + , adapter.escapeNameIfNeeded(dbsqlObject.getName()) + , owner + ); + } +} diff --git a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreUserPostgres.java b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreUserPostgres.java index 44b24a5..7f1844a 100644 --- a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreUserPostgres.java +++ b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreUserPostgres.java @@ -17,7 +17,6 @@ public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { IDBAdapter adapter = getAdapter(); Connection connect = adapter.getConnection(); StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "restoreUser").withParams(obj.getName()), 1); try { if (obj instanceof MetaUser) { MetaUser usr = (MetaUser)obj; @@ -25,14 +24,15 @@ public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { } else { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "user", obj.getType().getValue() + )); } } catch (Exception e) { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); } finally { - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); st.close(); } return true; diff --git a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreViewPostgres.java b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreViewPostgres.java index 4e324cf..ba9562e 100644 --- a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreViewPostgres.java +++ b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreViewPostgres.java @@ -1,16 +1,16 @@ package ru.fusionsoft.dbgit.postgres; import java.sql.Connection; +import java.text.MessageFormat; import java.util.Map; import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter; import ru.fusionsoft.dbgit.adapters.IDBAdapter; +import ru.fusionsoft.dbgit.core.DBGitConfig; import ru.fusionsoft.dbgit.core.ExceptionDBGit; import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; -import ru.fusionsoft.dbgit.dbobjects.DBTable; import ru.fusionsoft.dbgit.dbobjects.DBView; import ru.fusionsoft.dbgit.meta.IMetaObject; -import ru.fusionsoft.dbgit.meta.MetaTable; import ru.fusionsoft.dbgit.meta.MetaView; import ru.fusionsoft.dbgit.statement.StatementLogging; import ru.fusionsoft.dbgit.utils.ConsoleWriter; @@ -18,68 +18,59 @@ public class DBRestoreViewPostgres extends DBRestoreAdapter { @Override - public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { + public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { IDBAdapter adapter = getAdapter(); Connection connect = adapter.getConnection(); StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql()); - ConsoleWriter.detailsPrint(lang.getValue("general", "restore", "restoreView").withParams(obj.getName()), 1); try { if (obj instanceof MetaView) { MetaView restoreView = (MetaView)obj; Map views = adapter.getViews(restoreView.getSqlObject().getSchema()); boolean exist = false; - if(!(views.isEmpty() || views == null)) { + if(! (views == null || views.isEmpty())) { for(DBView vw:views.values()) { if(restoreView.getSqlObject().getName().equals(vw.getName())){ exist = true; if(!restoreView.getSqlObject().getSql().equals(vw.getSql())) { - //String ss = "CREATE OR REPLACE VIEW "+restoreView.getSqlObject().getName() +" AS\n"+restoreView.getSqlObject().getSql(); - st.execute(restoreView.getSqlObject().getName() +" AS\n"+restoreView.getSqlObject().getSql()); + st.execute(getDdlEscaped(restoreView)); } - if(!restoreView.getSqlObject().getOwner().equals(vw.getOwner())) { - st.execute("ALTER VIEW "+restoreView.getSqlObject().getName() +" OWNER TO "+restoreView.getSqlObject().getOwner()); + if(!DBGitConfig.getInstance().getToIgnoreOnwer(false)){ + if(!restoreView.getSqlObject().getOwner().equals(vw.getOwner())) { + st.execute(getChangeOwnerDdl(restoreView, restoreView.getSqlObject().getOwner())); + } } - //TODO Восстановление привилегий } } } if(!exist){ - String query = restoreView.getSqlObject().getSql(); - String name = restoreView.getSqlObject().getName(); - boolean nameShouldBeEscaped = name.contains(".") || Character.isUpperCase(name.codePointAt(0)); - if (nameShouldBeEscaped) { - query = query.replace( - "create or replace view " + restoreView.getSqlObject().getSchema() + "." + restoreView.getSqlObject().getName(), - "create or replace view " + restoreView.getSqlObject().getSchema() + ".\"" + restoreView.getSqlObject().getName() + "\""); + String query = getDdlEscaped(restoreView); + if(!DBGitConfig.getInstance().getToIgnoreOnwer(false)){ + query += getChangeOwnerDdl(restoreView, restoreView.getSqlObject().getOwner()); } - - if (!query.endsWith(";")) query = query + ";"; - query = query + "\n"; - - query+= "ALTER VIEW "+ restoreView.getSqlObject().getSchema() + "." - + ( nameShouldBeEscaped ?( "\"" + name + "\"") : name) - + " OWNER TO "+restoreView.getSqlObject().getOwner()+";\n"; st.execute(query); - connect.commit(); - //TODO Восстановление привилегий } + //TODO Восстановление привилегий ? } else { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName())); - } + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName() + , "view", obj.getType().getValue() + )); + } } catch (Exception e) { - ConsoleWriter.detailsPrintlnRed(lang.getValue("errors", "meta", "fail")); - throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), e); + throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRestoreError") + .withParams(obj.getName()) + , e + ); } finally { - ConsoleWriter.detailsPrintlnGreen(lang.getValue("general", "ok")); + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); st.close(); } return true; } - + @Override public void removeMetaObject(IMetaObject obj) throws Exception { IDBAdapter adapter = getAdapter(); @@ -93,14 +84,37 @@ public void removeMetaObject(IMetaObject obj) throws Exception { if (vw == null) return; String schema = getPhisicalSchema(vw.getSchema()); - st.execute("DROP VIEW "+schema+"."+DBAdapterPostgres.escapeNameIfNeeded(vw.getName())); - connect.commit(); + st.execute("DROP VIEW "+adapter.escapeNameIfNeeded(schema)+"."+adapter.escapeNameIfNeeded(vw.getName())); } catch (Exception e) { - ConsoleWriter.println(lang.getValue("errors", "restore", "objectRestoreError").withParams(e.getLocalizedMessage())); + ConsoleWriter.println(lang.getValue("errors", "restore", "objectRestoreError").withParams(e.getLocalizedMessage()),0); throw new ExceptionDBGitRestore(lang.getValue("errors", "restore", "objectRemoveError").withParams(obj.getName()), e); } finally { st.close(); } } + private String getDdlEscaped(MetaView view){ + String name = view.getSqlObject().getName(); + String schema = view.getSqlObject().getSchema(); + String query = view.getSqlObject().getSql(); + String nameEscaped = adapter.escapeNameIfNeeded(name); + + if (!name.equalsIgnoreCase(nameEscaped)) { + query = query.replace( + "create or replace view " + schema + "." + name, + "create or replace view " + schema + "." + nameEscaped + ); + } + if (!query.endsWith(";")) query = query + ";\n"; + query = query + "\n"; + return query; + } + + private String getChangeOwnerDdl(MetaView view, String owner){ + return MessageFormat.format("ALTER VIEW {0}.{1} OWNER TO {2}\n" + , view.getSqlObject().getSchema() + , adapter.escapeNameIfNeeded(view.getSqlObject().getName()) + , owner + ); + } } diff --git a/src/main/java/ru/fusionsoft/dbgit/postgres/FactoryDBAdapterRestorePostgres.java b/src/main/java/ru/fusionsoft/dbgit/postgres/FactoryDBAdapterRestorePostgres.java index bb4e8c3..c7c7e1a 100644 --- a/src/main/java/ru/fusionsoft/dbgit/postgres/FactoryDBAdapterRestorePostgres.java +++ b/src/main/java/ru/fusionsoft/dbgit/postgres/FactoryDBAdapterRestorePostgres.java @@ -22,6 +22,9 @@ public class FactoryDBAdapterRestorePostgres implements IFactoryDBAdapterRestote static { Map aMap = new HashMap(); aMap.put(DBGitMetaType.DBGitSchema.getValue(), new DBRestoreSchemaPostgres()); + aMap.put(DBGitMetaType.DBGitUserDefinedType.getValue(), new DBRestoreUDTPostgres()); + aMap.put(DBGitMetaType.DBGitDomain.getValue(), new DBRestoreDomainPostgres()); + aMap.put(DBGitMetaType.DBGitEnum.getValue(), new DBRestoreEnumPostgres()); aMap.put(DBGitMetaType.DBGitTableSpace.getValue(), new DBRestoreTableSpacePostgres()); aMap.put(DBGitMetaType.DBGitRole.getValue(), new DBRestoreRolePostgres()); aMap.put(DBGitMetaType.DBGitSequence.getValue(), new DBRestoreSequencePostgres()); @@ -44,7 +47,7 @@ public class FactoryDBAdapterRestorePostgres implements IFactoryDBAdapterRestote public IDBAdapterRestoreMetaData getAdapterRestore(IDBGitMetaType tp, IDBAdapter adapter) { if (!restoreAdapters.containsKey(tp.getValue())) { //return new DBRestoreMetaNotSupport(); - ConsoleWriter.println(DBGitLang.getInstance().getValue("errors", "restore", "cannotRestore").withParams(tp.getValue())); + ConsoleWriter.println(DBGitLang.getInstance().getValue("errors", "restore", "cannotRestore").withParams(tp.getValue()), messageLevel); return null; } diff --git a/src/main/java/ru/fusionsoft/dbgit/postgres/FactoryDbConvertAdapterPostgres.java b/src/main/java/ru/fusionsoft/dbgit/postgres/FactoryDbConvertAdapterPostgres.java index 76b6d8e..08bdc62 100644 --- a/src/main/java/ru/fusionsoft/dbgit/postgres/FactoryDbConvertAdapterPostgres.java +++ b/src/main/java/ru/fusionsoft/dbgit/postgres/FactoryDbConvertAdapterPostgres.java @@ -6,9 +6,11 @@ import ru.fusionsoft.dbgit.adapters.IDBConvertAdapter; import ru.fusionsoft.dbgit.adapters.IFactoryDBConvertAdapter; +import ru.fusionsoft.dbgit.core.DBGitLang; import ru.fusionsoft.dbgit.core.ExceptionDBGit; import ru.fusionsoft.dbgit.meta.DBGitMetaType; import ru.fusionsoft.dbgit.oracle.converters.TableConverterOracle; +import ru.fusionsoft.dbgit.postgres.converters.BypassVersionConverterPostgresql; import ru.fusionsoft.dbgit.postgres.converters.TableConverterPostgresql; import ru.fusionsoft.dbgit.postgres.converters.TableDataConverterPostgresql; import ru.fusionsoft.dbgit.utils.ConsoleWriter; @@ -21,6 +23,11 @@ public class FactoryDbConvertAdapterPostgres implements IFactoryDBConvertAdapter Map aMap = new HashMap(); aMap.put(DBGitMetaType.DBGitTable.getValue(), new TableConverterPostgresql()); aMap.put(DBGitMetaType.DbGitTableData.getValue(), new TableDataConverterPostgresql()); + aMap.put(DBGitMetaType.DBGitSequence.getValue(), new BypassVersionConverterPostgresql()); +// aMap.put(DBGitMetaType.DBGit.getValue(), new BypassVersionConverterPostgresql()); +// aMap.put(DBGitMetaType.DBGit.getValue(), new BypassVersionConverterPostgresql()); +// aMap.put(DBGitMetaType.DBGit.getValue(), new BypassVersionConverterPostgresql()); +// aMap.put(DBGitMetaType.DBGit.getValue(), new BypassVersionConverterPostgresql()); converters = Collections.unmodifiableMap(aMap); } @@ -28,7 +35,11 @@ public class FactoryDbConvertAdapterPostgres implements IFactoryDBConvertAdapter @Override public IDBConvertAdapter getConvertAdapter(String objectType) throws Exception { if (!converters.containsKey(objectType)) { - ConsoleWriter.detailsPrintlnRed("DBAdapterPostgres cannot convert " + objectType + "!"); + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("errors", "convert", "cannotConvert") + .withParams(objectType) + , 1 + ); return null; } else return converters.get(objectType); diff --git a/src/main/java/ru/fusionsoft/dbgit/postgres/converters/BypassVersionConverterPostgresql.java b/src/main/java/ru/fusionsoft/dbgit/postgres/converters/BypassVersionConverterPostgresql.java new file mode 100644 index 0000000..b98b233 --- /dev/null +++ b/src/main/java/ru/fusionsoft/dbgit/postgres/converters/BypassVersionConverterPostgresql.java @@ -0,0 +1,24 @@ +package ru.fusionsoft.dbgit.postgres.converters; + +import ru.fusionsoft.dbgit.adapters.IDBConvertAdapter; +import ru.fusionsoft.dbgit.core.ExceptionDBGit; +import ru.fusionsoft.dbgit.core.db.DbType; +import ru.fusionsoft.dbgit.meta.IMetaObject; + +import java.text.MessageFormat; + +public class BypassVersionConverterPostgresql implements IDBConvertAdapter { + @Override + public IMetaObject convert(DbType dbType, String dbVersion, IMetaObject obj) throws ExceptionDBGit { + DbType objDbType = obj.getDbType(); + if (dbType == objDbType){ + return obj; + } else { + throw new ExceptionDBGit(MessageFormat.format("Cannot convert {0} from other db type ({1} {2})" + , obj.getName() + , obj.getDbType() + , obj.getDbVersionNumber() + )); + } + } +} diff --git a/src/main/java/ru/fusionsoft/dbgit/postgres/converters/TableConverterPostgresql.java b/src/main/java/ru/fusionsoft/dbgit/postgres/converters/TableConverterPostgresql.java index 47c841d..9bdfd61 100644 --- a/src/main/java/ru/fusionsoft/dbgit/postgres/converters/TableConverterPostgresql.java +++ b/src/main/java/ru/fusionsoft/dbgit/postgres/converters/TableConverterPostgresql.java @@ -5,6 +5,7 @@ import ru.fusionsoft.dbgit.adapters.IDBConvertAdapter; import ru.fusionsoft.dbgit.adapters.IFactoryDBConvertAdapter; +import ru.fusionsoft.dbgit.core.DBGitLang; import ru.fusionsoft.dbgit.core.ExceptionDBGit; import ru.fusionsoft.dbgit.core.db.DbType; import ru.fusionsoft.dbgit.dbobjects.DBConstraint; @@ -25,9 +26,12 @@ public IMetaObject convert(DbType dbType, String dbVersion, IMetaObject obj) thr if (obj instanceof MetaTable) { MetaTable table = (MetaTable) obj; - - ConsoleWriter.println("Processing table " + table.getName()); - + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("general", "convert", "processingTable") + .withParams(table.getName()) + , messageLevel + ); + //types for (DBTableField field : table.getFields().values()) field.setTypeSQL(typeFromAnotherDB(objDbType, field)); @@ -54,26 +58,38 @@ public IMetaObject convert(DbType dbType, String dbVersion, IMetaObject obj) thr } private String indexFromOracle(DBIndex index) { - ConsoleWriter.println("Converting table index " + index.getName() + " from oracle to postgresql..."); - + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("general", "convert", "convertingIndex") + .withParams(index.getName(), "oracle", "postgresql") + , messageLevel + ); + return ""; } private String constraintFromOracle(DBConstraint constraint) { - ConsoleWriter.println("Converting table constraint " + constraint.getName() + " from oracle to postgresql..."); - - Pattern patternConstraint = Pattern.compile("(?<=" + constraint.getName() + ")(.*?)(?=\\))", Pattern.MULTILINE); - Matcher matcher = patternConstraint.matcher(constraint.getSql()); - - if (matcher.find()) { - return matcher.group().replace("\"", "") + ")"; - } else { - return ""; - } + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("general", "convert", "convertingConstraint") + .withParams(constraint.getName(), "oracle", "postgresql") + , messageLevel + ); + + Pattern patternConstraint = Pattern.compile("(?<=" + constraint.getName() + ")(.*?)(?=\\))", Pattern.MULTILINE); + Matcher matcher = patternConstraint.matcher(constraint.getSql()); + + if (matcher.find()) { + return matcher.group().replace("\"", "") + ")"; + } else { + return ""; + } } private String typeFromAnotherDB(DbType dbType, DBTableField field) { - ConsoleWriter.println("Converting table field " + field.getName() + " from " + dbType.toString().toLowerCase() + " to postgresql..."); + ConsoleWriter.println(DBGitLang.getInstance() + .getValue("general", "convert", "convertingField") + .withParams(field.getName(), dbType.toString(), "postgresql") + , messageLevel + ); String result = ""; switch (field.getTypeUniversal()) { case STRING: diff --git a/src/main/java/ru/fusionsoft/dbgit/utils/CalcHash.java b/src/main/java/ru/fusionsoft/dbgit/utils/CalcHash.java index 5b2b499..3f65270 100644 --- a/src/main/java/ru/fusionsoft/dbgit/utils/CalcHash.java +++ b/src/main/java/ru/fusionsoft/dbgit/utils/CalcHash.java @@ -56,7 +56,14 @@ public CalcHash addDataFile(String filename) throws Exception { stream.close(); return this; } - + + public CalcHash addData(boolean data){ + return addData(String.valueOf(data)); + } + + public CalcHash addData(int data){ + return addData(String.valueOf(data)); + } public CalcHash addData(String data) { try { diff --git a/src/main/java/ru/fusionsoft/dbgit/utils/ConsoleWriter.java b/src/main/java/ru/fusionsoft/dbgit/utils/ConsoleWriter.java index 701cf7f..a310377 100644 --- a/src/main/java/ru/fusionsoft/dbgit/utils/ConsoleWriter.java +++ b/src/main/java/ru/fusionsoft/dbgit/utils/ConsoleWriter.java @@ -1,132 +1,119 @@ -package ru.fusionsoft.dbgit.utils; - -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; - -import com.diogonunes.jcdp.color.ColoredPrinter; -import com.diogonunes.jcdp.color.api.Ansi.Attribute; -import com.diogonunes.jcdp.color.api.Ansi.BColor; -import com.diogonunes.jcdp.color.api.Ansi.FColor; - -public class ConsoleWriter { - private static Logger logger = LoggerUtil.getLogger(ConsoleWriter.class); - private static ColoredPrinter cp = new ColoredPrinter.Builder(1, false).build(); - private static boolean showDetailedLog = false; - - - public static void detailsPrintLn(Object msg) { - if (showDetailedLog) - println(msg.toString()); - } - - public static void detailsPrint(Object msg, int level) { - if (showDetailedLog) - print(msg.toString(), level); - } - - public static void detailsPrintlnGreen(Object msg) { - if (showDetailedLog) - printlnColor(msg.toString(), FColor.GREEN, 0); - } - - public static void detailsPrintlnRed(Object msg) { - if (showDetailedLog) - printlnColor(msg.toString(), FColor.RED, 0); - } - - public static void printlnGreen(Object msg) { - printlnColor(msg.toString(), FColor.GREEN, 0); - } - - public static void printlnRed(Object msg) { - printlnColor(msg.toString(), FColor.RED, 0); - } - - public static void detailsPrintLn(String msg) { - if (showDetailedLog) - println(msg); - } - - public static void detailsPrint(String msg, int level) { - if (showDetailedLog) - print(msg, level); - } - - public static void detailsPrintlnGreen(String msg) { - if (showDetailedLog) - printlnColor(msg, FColor.GREEN, 0); - } - - public static void detailsPrintlnRed(String msg) { - if (showDetailedLog) - printlnColor(msg, FColor.RED, 0); - } - - public static void printlnGreen(String msg) { - printlnColor(msg, FColor.GREEN, 0); - } - - public static void printlnRed(String msg) { - printlnColor(msg, FColor.RED, 0); - } - - public static void printlnColor(String msg, FColor color, Integer level) { - String tab = StringUtils.leftPad("", 4*level, " "); - /* - System.out.println(tab + msg); - if (1==1) return ; - */ - cp.println(tab+msg, Attribute.NONE, color, BColor.BLACK); - cp.clear(); - //logger.info(msg); - } - - public static void printColor(String msg, FColor color, Integer level) { - String tab = StringUtils.leftPad("", 4*level, " "); - /* - System.out.println(tab + msg); - if (1==1) return ; - */ - cp.print(tab+msg, Attribute.NONE, color, BColor.BLACK); - cp.clear(); - //logger.info(msg); - } - - public static void println(Object msg) { - println(msg.toString(), 0); - } - - public static void println(String msg) { - println(msg, 0); - } - - public static void println(String msg, Integer level) { - String tab = StringUtils.leftPad("", 4*level, " "); - /* - System.out.println(tab + msg); - if (1==1) return ; - */ - cp.println(tab+msg); - cp.clear(); - //logger.info(msg); - } - - public static void print(String msg, Integer level) { - String tab = StringUtils.leftPad("", 4*level, " "); - /* - System.out.println(tab + msg); - if (1==1) return ; - */ - cp.print(tab+msg); - cp.clear(); - //logger.info(msg); - } - - public static void setDetailedLog(boolean toShowLog) { - showDetailedLog = toShowLog; - } - - public static boolean getDetailedLog() { - return showDetailedLog; - } -} +package ru.fusionsoft.dbgit.utils; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; + +import com.diogonunes.jcdp.color.ColoredPrinter; +import com.diogonunes.jcdp.color.api.Ansi.Attribute; +import com.diogonunes.jcdp.color.api.Ansi.BColor; +import com.diogonunes.jcdp.color.api.Ansi.FColor; + +import java.text.MessageFormat; + +public class ConsoleWriter { + private static Logger logger = LoggerUtil.getLogger(ConsoleWriter.class); + private static ColoredPrinter cp = new ColoredPrinter.Builder(1, false).build(); + private static boolean showDetailedLog = false; + + + public static void print(Object message, FColor color, int level, boolean newLine, boolean onlyDetailed){ + if(onlyDetailed && !showDetailedLog) return; + + String tab = StringUtils.leftPad("", 4*level, " "); + String msg = MessageFormat.format("{0}{1}", + tab, + message.toString() + ); + System.out.print(( newLine ? "\n" : " " ) + msg ); +// cp.print(msg, Attribute.NONE, color, BColor.BLACK); +// cp.clear(); + + } + + public static void setDetailedLog(boolean toShowLog) { + showDetailedLog = toShowLog; + } + public static boolean getDetailedLog() { + return showDetailedLog; + } + + // Just print + // With no color, with color and with hardcoded colors + // - no levels cause them mean nothing without a newline + + public static void print(Object msg){ + print(msg, FColor.WHITE, 0, false, false); + } + + public static void printColor(Object msg, FColor color) { + print(msg, color, 0, false, false); + } + + public static void printGreen(Object msg) { + print(msg, FColor.GREEN, 0, false, false); + } + + public static void printRed(Object msg) { + print(msg, FColor.RED, 0, false, false); + } + + // Print with a newline + // With no color, with color and with hardcoded colors + // - with explicit level + + public static void printLineBreak(){println("", 0);} + + public static void println(Object msg, Integer level) { + print(msg, FColor.WHITE, level, true, false); + } + + public static void printlnColor(Object msg, FColor color, Integer level) { + print(msg, color, level, true, false); + } + + public static void printlnGreen(Object msg, int level) { + print(msg, FColor.GREEN, level, true, false); + } + + public static void printlnRed(Object msg, int level) { + print(msg, FColor.RED, level, true, false); + } + + + // Detailed versions of other methods + // - print if only showDetailedLog is true + + public static void detailsPrint(Object msg){ + print(msg, FColor.WHITE, 0, false, true); + } + + public static void detailsPrintColor(Object msg, FColor color) { + print(msg, color, 0, false, true); + } + + public static void detailsPrintGreen(Object msg) { + print(msg, FColor.GREEN, 0, false, true); + } + + public static void detailsPrintRed(Object msg) { + print(msg, FColor.RED, 0, false, true); + } + + public static void detailsPrintln(Object msg, Integer level) { + print(msg, FColor.WHITE, level, true, true); + } + + public static void detailsPrintlnColor(Object msg, FColor color, Integer level) { + print(msg, color, level, true, true); + } + + public static void detailsPrintlnGreen(Object msg, int level) { + print(msg, FColor.GREEN, level, true, true); + } + + public static void detailsPrintlnRed(Object msg, int level) { + print(msg, FColor.RED, level, true, true); + } + + +} diff --git a/src/main/java/ru/fusionsoft/dbgit/utils/StringProperties.java b/src/main/java/ru/fusionsoft/dbgit/utils/StringProperties.java index a71b179..da14dd2 100644 --- a/src/main/java/ru/fusionsoft/dbgit/utils/StringProperties.java +++ b/src/main/java/ru/fusionsoft/dbgit/utils/StringProperties.java @@ -1,10 +1,12 @@ package ru.fusionsoft.dbgit.utils; -import java.util.HashMap; +import java.sql.ResultSet; import java.util.Map; +import java.util.Objects; import java.util.TreeMap; import org.apache.commons.lang3.StringUtils; +import ru.fusionsoft.dbgit.core.ExceptionDBGitRunTime; /** * Tree string properties @@ -13,44 +15,60 @@ * */ public class StringProperties { - private String data = null; - private StringProperties parent = null; - private Map children = null; + private String data; + private Map children; public StringProperties() { - this.children = new TreeMap(); + this.children = new TreeMap<>(); + this.data = ""; } - public StringProperties(String data) { - this(); - this.data = data; + public StringProperties(String data) { + this.children = new TreeMap<>(); + this.data = data; } - - - public StringProperties addChild(String name) { - StringProperties childNode = new StringProperties(); - childNode.parent = this; - this.children.put(name, childNode); - return childNode; + public StringProperties(Map children) { + this.children = children == null ? new TreeMap<>() : children; + this.data = ""; } + + public StringProperties(ResultSet rs) { + this.children = new TreeMap<>(); + this.data = ""; + try { + final int columnCount = rs.getMetaData().getColumnCount(); + for (int i = 1; i <= columnCount; i++) { + + final String columnName = rs.getMetaData().getColumnName(i); + final String columnValue = rs.getString(i); + + if (columnName.equalsIgnoreCase("dependencies")) continue ; + if (columnValue == null) continue ; + + final String cleanValue = cleanString(columnValue); + final String cleanName = columnName.toLowerCase(); + + addChild(cleanName, cleanValue); + } + } catch(Exception e) { + throw new ExceptionDBGitRunTime(e); + } + } + - public StringProperties addChild(String name, StringProperties properties) { - this.children.put(name, properties); - properties.parent = this; - return properties; + public void addChild(String name, String stringValue) { + StringProperties valueOnlyNode = new StringProperties(stringValue); + this.children.put(name, valueOnlyNode); } - public StringProperties addChild(String name, String val) { - StringProperties childNode = addChild(name); - childNode.setData(val); - return childNode; + public void addChild(String name, StringProperties value) { + this.children.put(name, value); } - public StringProperties deleteChild(String name) { + public void deleteChild(String name) { if (children.containsKey(name)) { children.remove(name); } - return this; } public StringProperties xPath(String path) { @@ -75,10 +93,6 @@ public void setData(String data) { this.data = data; } - public StringProperties getParent() { - return parent; - } - public Map getChildren() { return children; } @@ -116,6 +130,34 @@ public String toString() { return toString(0).toString(); } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + StringProperties that = (StringProperties) o; + if(getData() != null){ + return getData().equals(that.getData()) + && Objects.equals(getChildren(), that.getChildren()); + } else { + return that.getData() == null + && Objects.equals(getChildren(), that.getChildren()); + } + + + } + + @Override + public int hashCode() { + return Objects.hash(getData(), getChildren()); + } + + public String cleanString(String str) { + String dt = str.replace("\r\n", "\n"); + while (dt.contains(" \n")) dt = dt.replace(" \n", "\n"); + dt = dt.replace("\t", " ").trim(); + + return dt; + } } diff --git a/src/main/java/ru/fusionsoft/dbgit/yaml/DBGitYamlConstructor.java b/src/main/java/ru/fusionsoft/dbgit/yaml/DBGitYamlConstructor.java index 337a8da..45aa766 100644 --- a/src/main/java/ru/fusionsoft/dbgit/yaml/DBGitYamlConstructor.java +++ b/src/main/java/ru/fusionsoft/dbgit/yaml/DBGitYamlConstructor.java @@ -9,8 +9,8 @@ import org.yaml.snakeyaml.nodes.MappingNode; import org.yaml.snakeyaml.nodes.Node; import org.yaml.snakeyaml.nodes.ScalarNode; -import org.yaml.snakeyaml.nodes.Tag; +import ru.fusionsoft.dbgit.core.ExceptionDBGitRunTime; import ru.fusionsoft.dbgit.utils.StringProperties; /** @@ -46,34 +46,31 @@ private class ConstructYamlStringProperties extends AbstractConstruct { @Override public Object construct(Node node) { if (node instanceof MappingNode) { - Object obj = constructMapping((MappingNode)node); - - StringProperties properties = new StringProperties(); - parseMap(properties, obj); - - return properties; + + final Map map = constructMapping((MappingNode)node); + return fromTreeNode(map); } if (node instanceof ScalarNode) { - //TODO - StringProperties properties = new StringProperties(); - - return properties; - } - return null; - } - - @SuppressWarnings("unchecked") - public void parseMap(StringProperties pr, Object obj) { - if (obj instanceof Map) { - Map map = (Map)obj; - for( String key : map.keySet()) { - StringProperties newPr = (StringProperties)pr.addChild(key); - parseMap(newPr, map.get(key)); - } - } else { - pr.setData((String)obj); + final String stringValue = constructScalar((ScalarNode)node).toString(); + return new StringProperties(stringValue); } + + throw new ExceptionDBGitRunTime("return null in construct! Gotcha!"); +// return null; } + + public StringProperties fromTreeNode(Object treeNode) { + try { + final Map map = (Map) treeNode; + final StringProperties constructedNode = new StringProperties(); + + map.forEach((key, value) -> constructedNode.addChild(key, fromTreeNode(value))); + return constructedNode; + + } catch (ClassCastException e) { + return new StringProperties(treeNode.toString()); + } + } } } \ No newline at end of file diff --git a/src/main/resources/lang/eng.yaml b/src/main/resources/lang/eng.yaml index b26595b..1a3e5db 100644 --- a/src/main/resources/lang/eng.yaml +++ b/src/main/resources/lang/eng.yaml @@ -3,6 +3,10 @@ general: done: Done! time: Time... {0} ms addToGit: Adding to git... + commandSuccess: Execute command success! + showDbCredentials: "Getting database connection credentials... {0}://{1}@{2}{3}" + gettingRepoLink: Getting link to repo... + repoLink: "Link: {0}" add: processingObject: Processing object {0} savingToFile: Saving to file... @@ -11,13 +15,16 @@ general: size: portion size loading: Loading portion index link: - connectionEstablished: Connection established + connectionEstablished: Testing connection OK... Connection established dblinkCreated: File {0} has been created checkout: - toCreateBranch: To create new branch - branchName: Branch name - commitName: Commit name - updatedFromIndex: Updated {0} path{1} from the index + do: Do checkout... + toCreateBranch: "To create new branch: {0}" + branchName: "Branch name: {0}" + commitName: "Commit name: {0}" + commitMessage: "Commit message: {0}" + updatedFromIndex: Updated {0} path {1} from the index + printBranchAndCommit: "{0} ({1}) {2}" clone: cloned: Repository cloned commit: @@ -28,12 +35,12 @@ general: removed: Remote removed unknown: Unknown command init: - created: Repository created + created: Repository created dump: checking: Checking files... dumping: Dumping... - hash: hash - dbHash: db hash + hash: "hash: {0}" + dbHash: "db hash {0}" hashesDifferent: Hashes are different, saving to file... hashesMatch: Hashes match, no need to dump object... processing: Processing {0} @@ -44,28 +51,38 @@ general: fetch: fetching: Fetching... restore: + do: Do restore... scriptWillSaveTo: Script will be saved to {0} seekingToRemove: Seeking objects to remove... seekingToRestore: Seeking objects to restore... + seekingToRestoreAdditional: Seeking additional dependant objects to restore... toRestore: "Objects to restore:" + toRestoreAdditional: "Additional to restore:" toRemove: "Objects to remove:" notExists: Object {0} not exists in db, it will be removed from index + objectToRemove: Object {0} marked to delete nothingToRemove: No objects to remove nothingToRestore: No objects to restore + nothingToRestoreAdditional: No additional objects to restore restoring: Restoring... removing: Removing... removingObject: Removing {0}... created: Created file {0} + restoreType: Restoring {0} {1} ... restoreView: Restoring view {0} ... restoreTrigger: Restoring trigger {0} ... restoreSeq: Restoring sequence {0} ... restoreSchema: Restoring schema {0} ... + restoreUDT: Restoring user defined type {0} ... + restoreEnum: Restoring enum {0} ... + restoreDomain: Restoring domain {0} ... restoreRole: Restoring role {0} ... restorePrc: Restoring procedure {0} ... restorePkg: Restoring package {0} ... restoreUser: Restoring user {0} ... restoreFnc: Restoring function {0} ... restoreTable: Restoring table {0} ... + restoreTableConstraints: Restoring table {0} constraints ... restoreTableData: Restoring table data for {0} ... restoreTablespace: Restoring tablespace {0} ... restoreConstr: Restoring constraints for table {0} ... @@ -75,14 +92,18 @@ general: addColumns: Adding columns... modifyColumns: Modifying columns... droppingColumns: Dropping columns... + droppingTablesConstraints: Dropping constraints for all updating tables... + droppingTableConstraints: Dropping constraints for table {0}... + restoringTablesConstraints: Restoring constraints for all updated tables... addPk: Adding PK... inserting: Inserting... deleting: Deleting... updating: Updating... unsupportedTypes: Table {0} contains unsupported types, it will be skipped willMakeBackup: Backup option enabled, all objects will be backed up before making changes + wontMakeBackup: Backup option DISABLED, no objects will be backed up before making changes toMakeChanges: Restore key specified, the operation will make changes to database - notMakeChanges: The operation will NOT make changes to database, a sql script was generated at {0}. Use "-r" key to make changes. + notMakeChanges: The operation will NOT make changes to database rm: checking: Checking files deleting: Deleting @@ -91,6 +112,14 @@ general: removingFromIndex: Removing from index... removingFromDb: Removing from db... markingToDelete: Marking item as removing in index + push: + noCommitsFound: No commits found! + remoteName: "remoteName: {0}" + called: Push called... + nullResult: Push result is null! + callResult: "Push call result: {0}" + result: "Push result: {0}" + upToDate: Everything up-to-date status: repVersion: "Repository version: {0}" dbgitVersion: "Dbgit version: {0}" @@ -113,11 +142,32 @@ general: diffSize1: MetaTableData diff size!!! {0} {1} diffSize2: MetaTableData diff size row {0}!!! diffDataRow: MetaTableData diff data row {0} {1} {2} {3} + loadRow: loading row {0} + loadedRow: loaded {0} rows + loadFiles: Loading files... + loadFile: Loading file {0}... backup: tryingToCopy: Trying to copy {0} to {1}... creatingSchema: Creating schema {0} droppingBackup: Dropping backup object {0}... + tryToBackup: Try to backup {0} present of {1} restoring objects ... + dependingBackups: Found {0} depending backups - {1} + rewritingBackups: Dropping {0} backups with {1} found dependencies... + creatingBackups: Creating {0} backups... + dbAdapter: + connectionLost: Connection lost, trying to reconnect... + reconnectTrySuccess: Successful reconnect. + reconnectTry: Try {0}... + convert: + processingTable: Converting table {0}... + convertingIndex: Converting table index {0} from {1} to {2} + convertingConstraint: Converting table constraint {0} from {1} to {2} + convertingField: Converting table field {0} from {1} to {2} + convertingSchema: Converting schema {0}... + convertingView: Converting view {0}... errors: + cmdException: "Error execute dbgit: {0}" + onExceptionTransactionRollbackError: "Failed to rollback connection: {0}" commandNotFound: Command {0} not found! executionError: Error execute dbgit gitRepNotFound: Git repository not found @@ -135,13 +185,15 @@ errors: fileLoadError: Error load file {0} errorParseIndex: Error parse ItemIndex! errorDump: Error write dump file + unsatisfiedDependencies: "There were objects with unsatisfied dependencies, they will NOT be included in restore list:" + metaTypeError: "The restore adapter encountered wrong MetaObject {0} type: expected {1}, got {2}" hash: errorSha: error search MessageDigest SHA-256 nullParam: Calc hash use null params unsupportedEncode: UnsupportedEncodingException UTF-8 link: emptyLink: Url database is empty - cantConnect: Test connection error + cantConnect: "Test connection error: {0}" restore: restoreErrorDidNotReturnTrue: Error restore objects.... restoreMetaObject must return true if object restore restoreError: Restore objects error @@ -153,6 +205,9 @@ errors: pkNotFound: PK not found for table {0}, cannot process row! cantConnect: Can't connect to db! errorLoadDelete: Error load and delete object + fileAlreadyExists: Error write script, file {0} already exists + currentFieldsListIsEmpty: Empty fieldList in current table which means the table is not reconstructed properly... + emptyRowsList: MapRows is null, maybe empty csv... add: badCommand: Bad command. Not found object to add! cantFindObjectInDb: Can't find object {0} in database @@ -184,15 +239,23 @@ errors: encrypted: Could not get ddl of database object {0}, the restoration is impossible tooManyRecords: Table {0} has more than {1} records. dbgit can't save this table data. compareMetaError: compareMeta Error! {0} to {1} + loadMetaFile: Could not load meta file {0}, using dummy version instead! + cantLoadMetaFile: Could not load meta file {0} dataTable: errorCellData: Error create CellData for type {0} differentCount: Different count columns title and line fieldNotFound: Field {0} not found + filesNotFound: Cound not find .data files in directories '{0}', put NULL values instead + tryAgain: Making attempt {0} getting portion of data... + wait: Error while getting portion of data, waiting {0} seconds before next try... + errorTableData: There was error while getting table data, error flag was ({0}) adapter: schemes: Error load schemes! tables: Error load tables! tableFields: Error load table fields! tableData: Error load table data! + tableSpace: Error load tablespace! + sequence: Error load sequence! index: Error load indexes! constraint: Error load constraints! views: Error load views! @@ -205,10 +268,17 @@ errors: roles: Error load roles! rollback: Error while rollback! createSchema: Cannot create schema + nullSchema: Object {0} has no schema set! + objectNotFoundInDb: Object is not found in target database! backup: badCommand: Bad command. Object to backup doesn't specified! backupError: Error on backup {0} cannotCreateSchema: Cannot create schema {0} + convert: + cannotConvert: Cannot convert {0}! + cannotFindAdapter: Could not get convert adapter for {0} ({1} version {2} -> {3} version {4}) + pull: + emptyGitRepository: Repo is empty! help: h: Shows this help v: Outputs full log of command execution @@ -248,6 +318,7 @@ help: Example: dbgit link jdbc:oracle:thin:@:: user= password= link-d: Creates default dblink file + link-ls: Just see current db url backup: | Examples: dbgit backup / -d -s @@ -260,12 +331,18 @@ help: dbgit add /TEST_VIEW.vw add-c: Let you continue adding from last place if it was broken checkout: | + Calls git checkout and 'dbgit restore' then Example: - dbgit checkout master + dbgit checkout master # checkout and restore (only script generated) + dbgit checkout master -r # checkout and restore with changing database + dbgit checkout master -nodb # checkout only + dbgit checkout -ls # see current branch checkout-b: create and checkout a new branch checkout-r: Updates database checkout-u: Upgrades branch to actual db and dbgit version state + checkout-ls: Just see current branch, head and revision number checkout-no-db: Doesn't do restore after checkout + checkout-no-owner: Doesn't restore objects original owner clone: | Example: dbgit clone @@ -335,4 +412,4 @@ help: config: | Example: dbgit config LIMIT_FETCH=true - config-g: sets global parameter \ No newline at end of file + config-g: sets global parameter diff --git a/src/main/resources/lang/rus.yaml b/src/main/resources/lang/rus.yaml index 02191c1..f675906 100644 --- a/src/main/resources/lang/rus.yaml +++ b/src/main/resources/lang/rus.yaml @@ -79,4 +79,4 @@ help: -h Показывает эту помощь -v Выводит полный отчет выполнения команды - \ No newline at end of file + diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml index 4ba1a99..143b89d 100644 --- a/src/main/resources/logback.xml +++ b/src/main/resources/logback.xml @@ -33,7 +33,7 @@ - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + %d{HH:mm} %level [%file:%line] : %msg%n @@ -43,7 +43,7 @@ - --> + diff --git a/src/test/java/ru/fusionsoft/dbgit/DBGitTest.java b/src/test/java/ru/fusionsoft/dbgit/DBGitTest.java new file mode 100644 index 0000000..9af0eac --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/DBGitTest.java @@ -0,0 +1,594 @@ +package ru.fusionsoft.dbgit; + +import com.diogonunes.jcdp.color.api.Ansi; +import com.google.common.collect.MapDifference; +import com.google.common.collect.Maps; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; +import org.apache.commons.io.FileUtils; +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.errors.GitAPIException; +import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription; +import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.transport.RefSpec; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +import ru.fusionsoft.dbgit.adapters.AdapterFactory; +import ru.fusionsoft.dbgit.adapters.IDBAdapter; +import ru.fusionsoft.dbgit.command.*; +import ru.fusionsoft.dbgit.core.*; +import ru.fusionsoft.dbgit.meta.IMapMetaObject; +import ru.fusionsoft.dbgit.meta.IMetaObject; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.Statement; +import java.text.MessageFormat; +import java.util.*; + + +@Tag("deprecated") +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +public class DBGitTest { + + static Path RESOURCES_REPO_DIR = new File("src/test/resources/repo").toPath(); + static Path RECOURCES_REPO_GIT_DIR = RESOURCES_REPO_DIR.resolve(".git"); + + static String REPO_URL = "https://github.com/rocket-3/dbgit-test.git"; + static String REPO_BRANCH = "master"; + static List REPO_COMMIT_NUMBERS = new ArrayList<>(); + + static String TEST_DB_URL = "jdbc:postgresql://localhost/"; + static String TEST_DB_USER = "postgres"; + static String TEST_DB_PASS = ""; + static String TEST_DB_CATALOG = "test#databasegit"; + static boolean TO_CREATE_CATALOG = true; + static int messageLevel = 0; + + private static void addCatalogToUrl() { + TEST_DB_URL = MessageFormat.format( + "{0}{1}{2}", + TEST_DB_URL, + TEST_DB_URL.endsWith("/") ? "" : "/", + TEST_DB_CATALOG + ); + } + + @BeforeAll + public static void setUp() throws Exception { + printMethodHead("Set up", null); + ConsoleWriter.setDetailedLog(true); + + FileUtils.cleanDirectory(RESOURCES_REPO_DIR.toFile()); + DBGit.initUrlInstance(RECOURCES_REPO_GIT_DIR.toString(), false); + dbgitClone(REPO_URL, String.valueOf(RESOURCES_REPO_DIR)); + + configureTestDb(TO_CREATE_CATALOG); + + if(REPO_COMMIT_NUMBERS.isEmpty()){ + loadCommitNumbersFromRepo(); + } + + } + + @BeforeEach + public void setUpEach() throws Exception { +// printMethodHead("Before each", null); + configureDBConnection(); + } + + @Test + public void CmdLink() throws Exception { + printMethodHead("CmdLink", null); + + CmdLink cmd = new CmdLink(); + String notValidUrl = "jdbc:postgresql://4.4.4.4/"; + File dblinkFile = RESOURCES_REPO_DIR.resolve(".dbgit").resolve(".dblink").toFile(); + dblinkFile.delete(); + +// DriverManager.setLoginTimeout(3); +// cmd.execute(getLinkCommandLine(notValidUrl, null, null)); +// assertFalse(dblinkFile.exists(), "'.dblink file not created on non-valid url'"); + + cmd.execute(getLinkCommandLine(TEST_DB_URL, TEST_DB_USER, TEST_DB_PASS)); + assertTrue(dblinkFile.exists()); + + } + + @Test + public void CmdCheckout() throws Exception { + + printMethodHead("CmdCheckout", "init"); + boolean isNoDb = true ; + boolean isRestore = false; + boolean isCreateBranch = false; + boolean isUpgrade = false; + boolean isNoOwner = true; + + String scriptPath = RESOURCES_REPO_DIR.resolve("checkout-r.sql").toAbsolutePath().toString(); + File scriptFile = new File(scriptPath); + scriptFile.delete(); + GitMetaDataManager.getInstance().loadDBMetaData(); + + printMethodHead("CmdCheckout", "just checkout to first commit (-nodb)"); + dbgitCheckout(REPO_BRANCH, REPO_COMMIT_NUMBERS.get(0), isNoDb, isRestore, isCreateBranch, isUpgrade, isNoOwner); + + printMethodHead("CmdCheckout", "try with restore to first commit (-r)"); + dbgitCheckout(REPO_BRANCH, REPO_COMMIT_NUMBERS.get(0), false, true, isCreateBranch, isUpgrade, isNoOwner); + + printMethodHead("CmdCheckout", "try with restore to last commit (-s ...)" ); + assertDoesNotThrow( () -> + dbgitCheckout( + REPO_BRANCH, REPO_COMMIT_NUMBERS.get(REPO_COMMIT_NUMBERS.size() - 1), scriptPath, + false, false, isCreateBranch, isUpgrade, !TO_CREATE_CATALOG + ) + ); + assertTrue(scriptFile.exists()); + assertTrue(FileUtils.readFileToString(scriptFile).length() > 100); + } + + @Test + public void CmdRestore() throws Exception { + + boolean isRestore = false; + boolean isToMakeBackup = true; + boolean isNoDb = true; + boolean isCreateBranch = false; + boolean isUpgrade = false; + + + dbgitReset("hard"); + setToMakeBackup(isToMakeBackup); + + for(String commitNumber : REPO_COMMIT_NUMBERS){ + printMethodHead("CmdRestore", String.valueOf(REPO_COMMIT_NUMBERS.indexOf(commitNumber)) ); + + String scriptPath = RESOURCES_REPO_DIR.resolve(MessageFormat.format( + "restore#{0}.sql", + REPO_COMMIT_NUMBERS.indexOf(commitNumber) + )).toAbsolutePath().toString(); + String scriptPathA = scriptPath+"-again"; + File scriptFile = new File(scriptPath); + File scriptFileA = new File(scriptPathA); + + scriptFile.delete(); + + dbgitCheckout(REPO_BRANCH, commitNumber, scriptPath, isNoDb, isRestore, isCreateBranch, isUpgrade, !TO_CREATE_CATALOG); + ConsoleWriter.printlnGreen(MessageFormat.format( + "\tIndex of commit in list: [{0}]", REPO_COMMIT_NUMBERS.indexOf(commitNumber) + ), messageLevel + ); + + + scriptFile.delete(); + dbgitRestore(true, true, scriptPath); + scriptFileA.delete(); + dbgitRestore(false, true, scriptPathA); + + + ConsoleWriter.printLineBreak(); + //TODO assert sizes have no difference + ConsoleWriter.printlnGreen(MessageFormat.format( + "File 1st: {0} syms.\nFile 2nd: {1} syms.", + scriptFile.exists() ? FileUtils.readFileToString(scriptFile).length() : -1, + scriptFileA.exists() ? FileUtils.readFileToString(scriptFileA).length() :- 1 + ), messageLevel); + } + } + + @Test + public void CmdAdd() throws Exception { + printMethodHead("CmdAdd", null); + + CmdAdd cmd = new CmdAdd(); + // checkout to last commit - restore files and database + // checkout 1st commit - restore files, index + // call cmdAdd + // ensure files added (what files?) - from last commit db state + + String firstCommit = REPO_COMMIT_NUMBERS.get(0); + String lastCommit = REPO_COMMIT_NUMBERS.get(REPO_COMMIT_NUMBERS.size()-1); + + dbgitCheckout(REPO_BRANCH, lastCommit, false, true, false, false, false); + dbgitCheckout(REPO_BRANCH, firstCommit, true, false, false, false, false); + + IMapMetaObject fileImos = GitMetaDataManager.getInstance().loadFileMetaData(); + IMapMetaObject databaseImos = GitMetaDataManager.getInstance().loadDBMetaData(); + + + ConsoleWriter.detailsPrintln("Find file to db object difference: ", messageLevel); + MapDifference diffs = Maps.difference(fileImos, databaseImos); + + diffs.entriesDiffering().forEach( (metaKey, metaObject) -> { + ConsoleWriter.detailsPrintlnGreen(metaKey, messageLevel+1); + + Map fileImoMap = metaObject.leftValue().toMap(); + Map dbImoMap = metaObject.rightValue().toMap(); + printMapsDifference(dbImoMap, fileImoMap, messageLevel+1); + + }); + + } + + //TODO вынести в отдельный метод с параметрами + //@Test + public void CmdClone() throws Exception { + printMethodHead("CmdClone", null); + + FileUtils.cleanDirectory(RESOURCES_REPO_DIR.toFile()); + //TODO кстати, вот он + dbgitClone(REPO_URL, String.valueOf(RESOURCES_REPO_DIR)); + configureDBConnection(); + + + File gitFile = RESOURCES_REPO_DIR.resolve(".git").toFile(); + File dbgitFile = RESOURCES_REPO_DIR.resolve(".dbgit").toFile(); + File[] dbgitFiles = dbgitFile.listFiles(); + + assertTrue(gitFile.exists(), "'.git folder exists'"); + assertTrue(dbgitFile.exists(), "'.dbgit folder exists'"); + assertTrue(dbgitFiles != null && dbgitFiles.length > 0, "'.dbgit folder is not empty'"); + + ConsoleWriter.printlnGreen(MessageFormat.format("Number of files in .dbgit {0}", dbgitFiles.length ), messageLevel); + Arrays.asList(dbgitFiles).forEach(x->ConsoleWriter.printlnRed(x.getPath(), messageLevel+1)); + + } + + //@Test + public void CmdReset() throws Exception { + printMethodHead("CmdReset", null); + + dbgitCheckout(REPO_BRANCH, REPO_COMMIT_NUMBERS.get(0), true, false, false, false, false); + + File dblinkFile = RESOURCES_REPO_DIR.resolve(".dbgit").resolve(".dblink").toFile(); + List modes = Arrays.asList("soft", "mixed", "hard", "merge", "keep"); + + dblinkFile.delete(); + assertFalse(dblinkFile.exists()); + + dbgitReset("hard"); + assertTrue(dblinkFile.exists()); + + } + + private static void dbgitClone(String urlFrom, String dirTo) throws Exception { + CmdClone cmdClone = new CmdClone(); + StringBuilder sb = new StringBuilder(); + + Option directoryOption = Option.builder().longOpt("directory").hasArg(true).numberOfArgs(1).build(); + directoryOption.getValuesList().add(dirTo); + + CommandLine cmdLineClone = new CommandLine.Builder() + .addArg(urlFrom) + .addOption(directoryOption).build(); + + sb.append(urlFrom + " "); + sb.append("-directory " + dirTo); + + ConsoleWriter.printlnGreen(MessageFormat.format("(call) dbgit {0} {1}", "clone", sb.toString()), messageLevel); + + cmdClone.execute(cmdLineClone); + } + + private static void dbgitReset(String mode) throws Exception { + StringBuilder sb = new StringBuilder(); + sb.append(mode); + + CmdReset cmd = new CmdReset(); + Option optionMode = new Option(mode , false, mode); + CommandLine.Builder builder = new CommandLine.Builder(); + ConsoleWriter.println(MessageFormat.format("(call) dbgit {0} {1}", "reset", sb.toString()), messageLevel); + + cmd.execute(builder.addOption(optionMode).build()); + } + + private static void dbgitCheckout(String branchName, String commitNumber, + boolean isNoDb, boolean isRestore, boolean isCreateBranch, + boolean isUpgrade, boolean isNoOwner) throws Exception { + dbgitCheckout(branchName, commitNumber, null, + isNoDb, isRestore, isCreateBranch, + isUpgrade, isNoOwner + ); + } + private static void dbgitCheckout(String branchName, String commitNumber, String scriptPath, + boolean isNoDb, boolean isRestore, boolean isCreateBranch, + boolean isUpgrade, boolean isNoOwner + ) throws Exception { + CmdCheckout cmd = new CmdCheckout(); + CommandLine.Builder builder = new CommandLine.Builder(); + StringBuilder sb = new StringBuilder(); + + String actualBranchName = branchName == null ? "master" : branchName; + + Option nodbOption = Option.builder("nodb").hasArg(false).build(); + Option noOwnerOption = Option.builder("noowner").hasArg(false).build(); + Option restoreOption = Option.builder("r").hasArg(false).build(); + Option newBranchOption = Option.builder("b").hasArg(false).build(); + Option upgradeOption = Option.builder("u").hasArg(false).build(); + Option scriptOption = Option.builder("s").hasArg(true).build(); + + builder.addArg(actualBranchName); + if(commitNumber != null){ + builder.addArg(commitNumber); + sb.append(commitNumber + " "); + } + if(isNoDb){ + builder.addOption(nodbOption); + sb.append("-nodb "); + } + if(isRestore){ + builder.addOption(restoreOption); + sb.append("-r "); + } + if(isCreateBranch){ + builder.addOption(newBranchOption); + sb.append("-b "); + } + if(isUpgrade){ + builder.addOption(upgradeOption); + sb.append("-u "); + } + if(isNoOwner){ + builder.addOption(noOwnerOption); + sb.append("-noowner "); + + } + if(scriptPath != null){ + scriptOption.getValuesList().add(scriptPath); + builder.addOption(scriptOption); + sb.append("-s ").append(scriptPath).append(" "); + } + builder.addOption(Option.builder("v").hasArg(false).build()); + ConsoleWriter.println(MessageFormat.format("(call) dbgit {0} {1}", "checkout", sb.toString()), messageLevel); + + + cmd.execute(builder.build()); + } + + private static void dbgitCheckoutLs() throws Exception { + CmdCheckout cmd = new CmdCheckout(); + CommandLine.Builder builder = new CommandLine.Builder(); + + Option lsOption = Option.builder("ls").hasArg(false).build(); + builder.addOption(lsOption); + + ConsoleWriter.println(MessageFormat.format("(call) dbgit {0}", "checkout -ls"), messageLevel); + cmd.execute(builder.build()); + } + + private static void dbgitRestore(boolean isRestore, boolean isToMakeBackup, String scriptPath) throws Exception { + + CmdRestore cmd = new CmdRestore(); + CommandLine.Builder builder = new CommandLine.Builder(); + StringBuilder sb = new StringBuilder(); + + builder.addOption(Option.builder("v").hasArg(false).build()); + sb.append("-v "); + + if(isRestore){ + Option restoreOption = Option.builder("r").hasArg(false).build(); + builder.addOption(restoreOption); + sb.append("-r "); + } + if(!TO_CREATE_CATALOG){ + Option noownerOption = Option.builder("noowner").hasArg(false).build(); + builder.addOption(noownerOption); + sb.append("-noowner "); + } + if(scriptPath != null){ + Option scriptOption = Option.builder("s").hasArg(true).numberOfArgs(1).build(); + scriptOption.getValuesList().add(scriptPath); + builder.addOption(scriptOption); + sb.append("-s ").append(scriptPath); + } + + ConsoleWriter.println(MessageFormat.format("(call) dbgit {0} {1}", "checkout", sb.toString()), messageLevel); + setToMakeBackup(isToMakeBackup); + cmd.execute(builder.build()); + } + + private static void configureTestDb(boolean tryCreateCatalog) throws Exception { + Properties testDbProps = new Properties(); + + String propDbUrl = System.getProperty("pgTestDbUrl"); + String propDbUser = System.getProperty("pgTestDbUser"); + String propDbPass = System.getProperty("pgTestDbPass"); + + ConsoleWriter.println("(config) Using test database: ", messageLevel); + if(propDbUrl != null){ + ConsoleWriter.print(" "); + TEST_DB_URL = propDbUrl; + TEST_DB_USER = propDbUser; + TEST_DB_PASS = propDbPass; + } else { + ConsoleWriter.print(" "); + } + ConsoleWriter.print(TEST_DB_URL); + + if(TEST_DB_USER != null && TEST_DB_PASS != null){ + testDbProps.put("user", TEST_DB_USER); + testDbProps.put("password", TEST_DB_PASS); + } + + if(tryCreateCatalog){ + try (Connection conn = DriverManager.getConnection(TEST_DB_URL, testDbProps)) { + + if (!conn.getCatalog().isEmpty()) { + throw new Exception("Catalog must not be specified to create test catalog."); + } + + IDBAdapter adapter = AdapterFactory.createAdapter(conn); + + try(Statement stmt = conn.createStatement()){ + stmt.execute(MessageFormat.format( + "DROP DATABASE \"{0}\"'; ", + adapter.escapeNameIfNeeded(TEST_DB_CATALOG) + )); + } catch (Exception ex){ + ConsoleWriter.println( + "(config) failed to drop database: " + ex.getMessage().replaceAll("\n", ";") + , messageLevel + ); + } + + try(Statement stmt = conn.createStatement()){ + stmt.execute(MessageFormat.format( + "CREATE DATABASE \"{0}\"; ", + adapter.escapeNameIfNeeded(TEST_DB_CATALOG) + )); + } catch (Exception ex){ + ConsoleWriter.println( + "(config) failed to create database: " + ex.getMessage().replaceAll("\n", ";") + , messageLevel + ); + //throw ex; + } + + } + } + addCatalogToUrl(); + + + DBConnection.createFileDBLink(TEST_DB_URL, testDbProps, false); + + } + + private static void configureDBConnection() throws Exception { + String dbLinkUrl = DBConnection.loadFileDBLink(new Properties()); + + if( !DBConnection.hasInstance() || + !DBConnection.getInstance().getConnect().getMetaData().getURL().equals(TEST_DB_URL)){ + + new CmdLink().execute(getLinkCommandLine(TEST_DB_URL, TEST_DB_USER, TEST_DB_PASS)); + if(DBConnection.hasInstance()) { + DBConnection.getInstance().flushConnection(); + DBConnection.getInstance(); + } + + ConsoleWriter.printlnGreen(MessageFormat.format( + "(config) Set up DBConnection and ''.dblink'' state, \n\twas\t: {0} \n\tset\t: {1}" + , dbLinkUrl + , DBConnection.getInstance().getConnect().getMetaData().getURL() + ), messageLevel); + } + + //not to broke any other database + assertEquals(TEST_DB_URL, DBConnection.getInstance().getConnect().getMetaData().getURL(), "DBConnection url IS NOT equal to test database url" ); + } + + private static void loadCommitNumbersFromRepo() throws GitAPIException, IOException { + InMemoryRepository repo = new InMemoryRepository(new DfsRepositoryDescription()); + Git git = new Git(repo); + git.fetch() + .setRemote(REPO_URL) + .setRefSpecs(new RefSpec("+refs/heads/"+ REPO_BRANCH +":refs/heads/"+ REPO_BRANCH)) + .call(); + + String treeName = "refs/heads/"+ REPO_BRANCH; // tag or branch + for (RevCommit commit : git.log().add(repo.resolve(treeName)).call()) { + REPO_COMMIT_NUMBERS.add(commit.getName()); + } + } + + private static void setToMakeBackup(boolean isToMakeBackup) throws Exception { + String sectionName = "core"; + String parameterName = "TO_MAKE_BACKUP"; + String was = String.valueOf(DBGitConfig.getInstance().getBoolean(sectionName, parameterName, false)); + + DBGitConfig.getInstance().setValue("TO_MAKE_BACKUP", isToMakeBackup ? "true" : "false"); + + ConsoleWriter.detailsPrintlnRed(MessageFormat.format("(config) Set ''TO_MAKE_BACKUP'' (was, set, now): {0}, {1}, {2}", + was, String.valueOf(isToMakeBackup), + String.valueOf(DBGitConfig.getInstance().getBoolean(sectionName, parameterName, false)) + ), messageLevel); + } + + private static CommandLine getLinkCommandLine(String url, String user, String pass){ + CommandLine.Builder builder = new CommandLine.Builder().addArg(url); + if(user != null) { + builder.addArg("user=" + user); + + } + if(pass != null) { + builder.addArg("password=" + pass); + } + return builder.build(); + } + + private static void printMethodHead(String name, String part){ + String text = name + ((part != null) ? " part '" + part + "'" : "") ; + int length = 92; + int textLength = text.length(); + boolean shouldAddSpace = textLength % 2 != length % 2; + int remSpaceLength = length - textLength - (shouldAddSpace ? 0 : 1); + int sideHeaderLength = remSpaceLength / 2; + StringBuilder sb = new StringBuilder(); + + for ( int step = 0; step < 2; step ++){ + if( step == 0 ) sb.append(text); + for (int i = sideHeaderLength; i > 0;){ + sb.append(" -"); i -= 2; + if( i == 2 ) { sb.append(" "); i--; } + if( i == 1 ) { sb.append("|\n") ; i--; } + } + + sb.reverse(); + } + + ConsoleWriter.printlnColor(sb.toString(), Ansi.FColor.MAGENTA, 0); + } + + private static void printMapsDifference(Map mapBefore, Map mapAfter, int level){ + + MapDifference difference = Maps.difference(mapBefore, mapAfter); + Map add = difference.entriesOnlyOnRight(); + Map remove = difference.entriesOnlyOnLeft(); + Map> change = difference.entriesDiffering(); + + for (Map.Entry addEntry : add.entrySet()) { + ConsoleWriter.println(MessageFormat.format("+ ''{0}'': ", addEntry.getKey()), level); + printNode( addEntry.getValue(), level ); + } + + for (Map.Entry removeEntry : remove.entrySet()) { + ConsoleWriter.println(MessageFormat.format("- ''{0}'': ", removeEntry.getKey()), level); + //printNode( removeEntry.getValue(), level ); + } + + for (Map.Entry> changeEntry : change.entrySet()) { + ConsoleWriter.println(MessageFormat.format("* ''{0}'': ", changeEntry.getKey()), level); + + Object valueBefore = changeEntry.getValue().leftValue(); + Object valueAfter = changeEntry.getValue().rightValue(); + + if( valueBefore instanceof Map && valueAfter instanceof Map ){ + printMapsDifference((Map) valueBefore, (Map) valueAfter, level+1); + } else { + ConsoleWriter.print(MessageFormat.format("\"{0}\" -> \"{1}\"", valueBefore, valueAfter)); + } + + } + } + + private static void printNode(Object node, int level){ + if(node instanceof Map) { + Map map = (Map) node; + + for (Map.Entry entry : map.entrySet()) { + ConsoleWriter.println(MessageFormat.format("''{0}'': " ,entry.getKey()), level+1); + printNode( entry.getValue(), level+1); + } + } + else { + ConsoleWriter.print(node != null ? node : ""); + } + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/MetaObjectTest.java b/src/test/java/ru/fusionsoft/dbgit/MetaObjectTest.java deleted file mode 100644 index 9251afd..0000000 --- a/src/test/java/ru/fusionsoft/dbgit/MetaObjectTest.java +++ /dev/null @@ -1,135 +0,0 @@ -package ru.fusionsoft.dbgit; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; - -//import junit.framework.TestCase; -import ru.fusionsoft.dbgit.dbobjects.DBConstraint; -import ru.fusionsoft.dbgit.dbobjects.DBIndex; -import ru.fusionsoft.dbgit.dbobjects.DBSchema; -import ru.fusionsoft.dbgit.dbobjects.DBTable; -import ru.fusionsoft.dbgit.dbobjects.DBTableField; -import ru.fusionsoft.dbgit.meta.DBGitMetaType; -import ru.fusionsoft.dbgit.meta.MetaObjOptions; -import ru.fusionsoft.dbgit.meta.MetaObjectFactory; -import ru.fusionsoft.dbgit.meta.MetaSchema; -import ru.fusionsoft.dbgit.meta.MetaTable; -import ru.fusionsoft.dbgit.utils.StringProperties; - -public class MetaObjectTest /*extends TestCase*/ { - public final String targetPath = "target"; - - /* - public void testMetaTable() { - DBTable tbl = new DBTable(); - - tbl.setName("mytable"); - tbl.setSchema("myschema"); - tbl.getOptions().addChild("owner", "postgres"); - tbl.getOptions().addChild("table_space", "pg_default"); - StringProperties sub = (StringProperties)tbl.getOptions().addChild("sub"); - sub.addChild("sub1", "val1"); - sub.addChild("sub2", "val2"); - - MetaTable tblMeta = new MetaTable(tbl); - - DBTableField field = new DBTableField(); - field.setName("id"); - field.setTypeSQL("integer"); - field.setIsPrimaryKey(true); - tblMeta.getFields().put(field.getName(), field); - - field = new DBTableField(); - field.setName("field1"); - field.setTypeSQL("character varying(255)"); - field.setIsPrimaryKey(false); - tblMeta.getFields().put(field.getName(), field); - - field = new DBTableField(); - field.setName("field2"); - field.setTypeSQL("timestamp without time zone"); - tblMeta.getFields().put(field.getName(), field); - - field = new DBTableField(); - field.setName("field3"); - field.setTypeSQL("integer"); - tblMeta.getFields().put(field.getName(), field); - - DBIndex idx = new DBIndex(); - idx.setName("idx1"); - idx.setSchema("myschema"); - idx.setSql("CREATE INDEX idx1 ON crtd.notice USING btree (depart);"); - tblMeta.getIndexes().put(idx.getName(), idx); - - idx = new DBIndex(); - idx.setName("idx2"); - idx.setSchema("myschema"); - idx.setSql("CREATE INDEX idx2 ON crtd.notice USING btree (depart);"); - tblMeta.getIndexes().put(idx.getName(), idx); - - DBConstraint ct = new DBConstraint(); - ct.setName("fk1"); - ct.setSchema("myschema"); - ct.setSql("ALTER TABLE crtd.notice ADD CONSTRAINT fk1 FOREIGN KEY (arrive) REFERENCES crtd.ptstation (id) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION;"); - tblMeta.getConstraints().put(ct.getName(), ct); - - ct = new DBConstraint(); - ct.setName("fk2"); - ct.setSchema("myschema"); - ct.setSql("ALTER TABLE crtd.notice ADD CONSTRAINT fk2 FOREIGN KEY (arrive) REFERENCES crtd.ptstation (id) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION;"); - tblMeta.getConstraints().put(ct.getName(), ct); - - try { - String filename = targetPath+"/test.yaml"; - FileOutputStream out = new FileOutputStream(filename); - tblMeta.serialize(out); - out.close(); - - - File file = new File(filename); - FileInputStream fis = new FileInputStream(file); - MetaTable meta2 = (MetaTable)tblMeta.deSerialize(fis); - fis.close(); - - assertEquals("Assert meta name!", "myschema/mytable.tbl", meta2.getName()); - assertEquals("Assert meta name!", "mytable", meta2.getTable().getName()); - assertEquals("Assert meta name!", "val1", meta2.getTable().getOptions().xPath("sub/sub1").getData()); - - assertEquals("Assert meta hash!", tblMeta.getHash(), meta2.getHash()); - //assertEquals("Assert meta hash!", tblMeta.getHash(), "hash"); - - - } catch (Exception e) { - e.printStackTrace(); - assertTrue(e.getMessage(), false ); - } - } - - */ - - public void testMetaShema() throws Exception { - DBSchema sh = new DBSchema("myshema"); - StringProperties pr = sh.getOptions(); - pr.setData("info value"); - pr.addChild("param1", "val1"); - pr.addChild("param2", "val2"); - pr.addChild("param3", "val3"); - - StringProperties sub = pr.addChild("subparams"); - sub.addChild("subparam1", "asd1"); - sub.addChild("subparam2", "asd2"); - - MetaObjOptions meta = (MetaObjOptions)MetaObjectFactory.createMetaObject(DBGitMetaType.DBGitSchema); - meta.setObjectOption(sh); - - //assertEquals("Assert hash!", meta.getHash(), "5c376e1836f4cbc763808fe077a84f2eaf9cdb9dc7e22107fc44a9567f4cf264"); - - /* - System.out.println(meta.getHash()); - - System.out.println(pr.toString()); - */ - //TODO to yaml and assert - } -} diff --git a/src/test/java/ru/fusionsoft/dbgit/UtilTest.java b/src/test/java/ru/fusionsoft/dbgit/UtilTest.java deleted file mode 100644 index 3f8cf80..0000000 --- a/src/test/java/ru/fusionsoft/dbgit/UtilTest.java +++ /dev/null @@ -1,63 +0,0 @@ -package ru.fusionsoft.dbgit; - -import com.jcraft.jsch.jce.Random; -/* -import junit.framework.Test; -import junit.framework.TestCase; -import junit.framework.TestSuite; -*/ -import ru.fusionsoft.dbgit.dbobjects.DBTableField; - -import ru.fusionsoft.dbgit.utils.MaskFilter; - -public class UtilTest /*extends TestCase*/ { - public void testMask() { - /* - MaskFilter mask = new MaskFilter("asd*.txt"); - assertTrue(mask.match("asd12df.txt")); - assertFalse(mask.match("as612df.txt")); - - mask = new MaskFilter("path/asd*.txt"); - assertTrue(mask.match("path/asd12df.txt")); - assertFalse(mask.match("as612df.txt")); - - mask = new MaskFilter("path/*"); - assertTrue(mask.match("path/asd12df.txt")); - assertFalse(mask.match("pat/as612df.txt")); - - mask = new MaskFilter("path/w*"); - assertTrue(mask.match("path\\wsd12df.txt")); - assertFalse(mask.match("pat\\ws612df.txt")); - */ - } - - public void testMapField() { - /* - IMapFields map = new TreeMapFields(); - - DBTableField f1 = new DBTableField(); - f1.setName("f1"); - DBTableField f2 = new DBTableField(); - f2.setName("f2"); - DBTableField f3 = new DBTableField(); - f3.setName("f3"); - DBTableField f4 = new DBTableField(); - f4.setName("f4"); - - - for (int i = 0; i < 10000; i++) { - DBTableField f = new DBTableField(); - f.setName("item_"+Math.random()*10000000); - map.put(f); - } - - - map.put(f2); - map.put(f1); - map.put(f3); - map.put(f4); - */ - - - } -} diff --git a/src/test/java/ru/fusionsoft/dbgit/core/DBGitIgnoreTest.java b/src/test/java/ru/fusionsoft/dbgit/core/DBGitIgnoreTest.java new file mode 100644 index 0000000..f842ad2 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/core/DBGitIgnoreTest.java @@ -0,0 +1,33 @@ +package ru.fusionsoft.dbgit.core; + +import ru.fusionsoft.dbgit.utils.MaskFilter; + +import java.util.HashMap; +import java.util.Map; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +public class DBGitIgnoreTest { + + DBGitIgnore dbGitIgnore; + Map filters = new HashMap<>(); + Map exclusions = new HashMap<>(); + + private void createDbGitIgnore(){ + dbGitIgnore = new DBGitIgnore(filters, exclusions); + } + + private void addFilter(String mask){ filters.put(mask, new MaskFilter(mask)); } + private void addExcl(String mask){ exclusions.put(mask, new MaskFilter(mask)); } + + + + @Test + public void matchOne() { + createDbGitIgnore(); + addExcl("public/*.*"); + + final String textTbl = "public/ad_group_roles.tbl"; + assertFalse(dbGitIgnore.matchOne(textTbl)); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/DbGitIntegrationTestBasic.java b/src/test/java/ru/fusionsoft/dbgit/integration/DbGitIntegrationTestBasic.java new file mode 100644 index 0000000..fdffffe --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/DbGitIntegrationTestBasic.java @@ -0,0 +1,361 @@ +package ru.fusionsoft.dbgit.integration; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import ru.fusionsoft.dbgit.integration.primitives.Patch; +import ru.fusionsoft.dbgit.integration.primitives.PatchSequential; +import ru.fusionsoft.dbgit.integration.primitives.args.specific.ArgsDbGitCheckout; +import ru.fusionsoft.dbgit.integration.primitives.DescribedTestResult; +import ru.fusionsoft.dbgit.integration.primitives.GroupedTestResult; +import ru.fusionsoft.dbgit.integration.primitives.SimpleTest; +import ru.fusionsoft.dbgit.integration.primitives.SimpleTestResult; +import ru.fusionsoft.dbgit.integration.primitives.TestResult; +import ru.fusionsoft.dbgit.integration.primitives.args.ArgsExplicit; +import ru.fusionsoft.dbgit.integration.primitives.args.specific.ArgsDbGitLinkPgAuto; +import ru.fusionsoft.dbgit.integration.primitives.args.specific.ArgsDbGitAddRemoteTestRepo; +import ru.fusionsoft.dbgit.integration.primitives.chars.CommitsFromRepo; +import ru.fusionsoft.dbgit.integration.primitives.chars.LinesOfUnsafeScalar; +import ru.fusionsoft.dbgit.integration.primitives.chars.specific.dbgit.CharsDbIgnoreWithDataAndTypes; +import ru.fusionsoft.dbgit.integration.primitives.chars.specific.dbgit.CharsDbGitConfigBackupEnabled; +import ru.fusionsoft.dbgit.integration.primitives.patch.specific.PathPatchDbGitCheckout; +import ru.fusionsoft.dbgit.integration.primitives.patch.specific.PathPatchDbGitCheckoutHard; +import ru.fusionsoft.dbgit.integration.primitives.patch.specific.PathPatchDbGitClonesRepo; +import ru.fusionsoft.dbgit.integration.primitives.patch.specific.PathPatchDbGitRestore; +import ru.fusionsoft.dbgit.integration.primitives.chars.CharsOfConsoleWhenRunning; +import ru.fusionsoft.dbgit.integration.primitives.chars.specific.dbgit.CharsDbIgnoreWithTableData; +import ru.fusionsoft.dbgit.integration.primitives.chars.specific.NameOfDefaultTargetTestDatabase; +import ru.fusionsoft.dbgit.integration.primitives.chars.specific.UrlOfGitTestRepo; +import ru.fusionsoft.dbgit.integration.primitives.patch.PathPatchCreatingFile; +import ru.fusionsoft.dbgit.integration.primitives.patch.specific.PathPatchDbGitAdd; +import ru.fusionsoft.dbgit.integration.primitives.patch.specific.PathPatchDbGitInitializesRepo; +import ru.fusionsoft.dbgit.integration.primitives.patch.specific.PathPatchDbGitLink; +import ru.fusionsoft.dbgit.integration.primitives.path.PathPatched; +import ru.fusionsoft.dbgit.integration.primitives.path.PathWithFiles; +import ru.fusionsoft.dbgit.integration.primitives.path.specific.dbgit.scenarios.PathAfterDbGitLinkAndAdd; +import ru.fusionsoft.dbgit.integration.primitives.path.PathAfterDbGitRun; +import ru.fusionsoft.dbgit.integration.primitives.path.PathNotProjectRoot; +import ru.fusionsoft.dbgit.integration.primitives.path.specific.dbgit.PathWithDbGitRepoCloned; +import ru.fusionsoft.dbgit.integration.primitives.path.PathWithoutFiles; +import ru.fusionsoft.dbgit.integration.primitives.path.specific.ProjectTestResourcesCleanDirectoryPath; + +@Tag("integration") +public class DbGitIntegrationTestBasic { + + @Test + public final void doesNothingIntegrationTestTemplate() { + final String description = "Does nothing test works"; + final TestResult result = + new GroupedTestResult<>( + description, + new PathPatched( + new ProjectTestResourcesCleanDirectoryPath("00"), + new Patch() { + @Override + public void apply(Path root) throws Exception { + + } + } + ), + new SimpleTest<>( + "Returns true", + (path) -> { + path.toString(); + return true; + } + ) + ); + + System.out.println(result.text()); + Assertions.assertTrue(result.value()); + } + + @Test + public final void gitToFilesCheckoutWorks() { + final String description = "Dbgit checkout and reset works"; + final String branchName = "dsdata"; + final String commitNameOfHead = "9e91d86"; + final String commitNameOfDs2 = "83baf51"; + final String fileName = ".dbgit/.dblink"; + final String reamdeFileName = "README.md"; + final String expectedFileContent = "ds2"; + final TestResult testResult = new GroupedTestResult<>( + description, + + new PathAfterDbGitRun( + new ArgsDbGitCheckout(commitNameOfDs2, "-nodb", "-v"), + + new PathAfterDbGitRun( + new ArgsDbGitCheckout(branchName, "-b", "-nodb", "-v"), + + new PathAfterDbGitRun( + new ArgsDbGitAddRemoteTestRepo("origin"), + + new PathWithDbGitRepoCloned( + new UrlOfGitTestRepo(), + new ProjectTestResourcesCleanDirectoryPath("01") + ) + ) + ) + ), + new SimpleTest<>( + "Printed expected commit hash", + (path) -> { + final CharSequence consoleOutput = new CharsOfConsoleWhenRunning(() -> { + new PathAfterDbGitRun(new ArgsExplicit("checkout", "-ls", "-v"), path).toString(); + }); + System.out.println(consoleOutput); + return new LinesOfUnsafeScalar(consoleOutput) + .list() + .stream() + .anyMatch(x -> x.contains(commitNameOfDs2)); + } + ), + new SimpleTest<>( + "File content of "+fileName+" is as expected", + (path) -> { + return Files.readAllLines(path.resolve(fileName)) + .stream() + .anyMatch(x->x.contains(expectedFileContent)); + } + ), + new SimpleTest<>( + "File "+reamdeFileName+" does not exists", + (path) -> { + return ! path.resolve("README.md").toFile().exists(); + } + ), + new SimpleTest<>( + "File "+reamdeFileName+" exists after checkout back to ", + (path) -> { + return new PathPatched( + new PatchSequential( + new PathPatchDbGitCheckout(branchName, "-nodb", "-v"), + new PathPatchDbGitCheckout("-ls", "-v") + ), + path + ).resolve(reamdeFileName).toFile().exists(); + } + ) + ); + + System.out.println(testResult.text()); + Assertions.assertTrue(testResult.value()); + } + + @Test + public final void dbToFilesDumpWorks() { + final String description = "Dbgit add with table data works"; + final TestResult result = new GroupedTestResult( + description, + + new PathAfterDbGitRun( + new ArgsExplicit("add", "\"*\""), + + new PathWithFiles( + new PathPatchCreatingFile(".dbgit/.dbignore", new CharsDbIgnoreWithDataAndTypes()), + + new PathAfterDbGitRun( + new ArgsDbGitLinkPgAuto("dvdrental"), + + new PathAfterDbGitRun( + new ArgsExplicit("init"), + + new ProjectTestResourcesCleanDirectoryPath("02") + ) + ) + ) + ), + + new SimpleTest<>( + "git folder exists", + (path) -> { + return path.resolve(".git").toFile().exists(); + } + ), + new SimpleTest<>( + "rental table data exists", + (path) -> { + return path.resolve(".dbgit/public/rental.csv").toFile().exists(); + } + ), + new SimpleTest<>( + "city table data (small) is not empty", + (path) -> { + return ! Files.readAllLines(path.resolve(".dbgit/public/city.csv")).isEmpty(); + } + ), + new SimpleTest<>( + "rental table data (10K+ rows) exists and is empty", + (path) -> { + return Files.readAllLines(path.resolve(".dbgit/public/rental.csv")).isEmpty(); + } + ), + new SimpleTest<>( + "mpaa_rating.enum exists", + (path) -> { + return path.resolve(".dbgit/public/mpaa_rating.enum").toFile().exists(); + } + ), + new SimpleTest<>( + "year.domain exists", + (path) -> { + return path.resolve(".dbgit/public/year.domain").toFile().exists(); + } + ), + new SimpleTest<>( + "film_summary.udt exists", + (path) -> { + return path.resolve(".dbgit/public/film_summary.udt").toFile().exists(); + } + ) + ); + + System.out.println(result.text()); + Assertions.assertTrue(result.value()); + } + + @Test + public final void dbToDbRestoreWorks() { + final String nameOfSourceDb = "dsd3"; + final String nameOfTargetDb = new NameOfDefaultTargetTestDatabase().toString(); + final String description = + "Simple add from '" + nameOfSourceDb + "' db with data " + + "and restore to '" + nameOfTargetDb + "' db works"; + + final TestResult result = new GroupedTestResult<>( + description, + new PathPatched( + new PatchSequential( + new PathPatchDbGitInitializesRepo(new ArgsDbGitLinkPgAuto(nameOfSourceDb)), + new PathPatchCreatingFile(".dbgit/.dbignore", new CharsDbIgnoreWithTableData()), + new PathPatchDbGitAdd(), + new PathPatchDbGitLink(new ArgsDbGitLinkPgAuto(nameOfTargetDb)), + new PathPatchDbGitRestore("-r", "-v") + ), + new ProjectTestResourcesCleanDirectoryPath("03") + ), + new SimpleTest<>( + "Should not throw any exceptions", + (path) -> { + path.toString(); + return true; + } + ) + ); + + System.out.println(result.text()); + Assertions.assertTrue(result.value()); + } + + @Test + public final void gitToDbRestoreWorks() throws Exception { + + final String nameOfSourceBranch = "dsdata"; + final String description = + "Simple sequential checkout from '" + nameOfSourceBranch + "' branch " + + "and restore to '" + new NameOfDefaultTargetTestDatabase() + "' db works"; + + final List commitNames = new CommitsFromRepo( + new UrlOfGitTestRepo().toString(), nameOfSourceBranch + ).names(); + + final ArgsDbGitLinkPgAuto linkArgs = new ArgsDbGitLinkPgAuto(new NameOfDefaultTargetTestDatabase()); + final TestResult result = new GroupedTestResult<>( + description, + new PathPatched( + new PatchSequential( + new PathPatchDbGitClonesRepo(new UrlOfGitTestRepo(), new ArgsDbGitAddRemoteTestRepo()), + new PathPatchDbGitCheckout(nameOfSourceBranch, "-b", "-nodb"), + new PathPatchDbGitCheckout(commitNames.get(0), "-nodb", "-v"), + new PathPatchDbGitLink(linkArgs), + new PathPatchCreatingFile(".dbgit/dbgitconfig", new CharsDbGitConfigBackupEnabled()), + new PathPatchDbGitRestore("-r", "-v"), + new PathPatchDbGitCheckoutHard(commitNames.get(1), "-nodb", "-v"), + new PathPatchDbGitLink(linkArgs), + new PathPatchCreatingFile(".dbgit/dbgitconfig", new CharsDbGitConfigBackupEnabled()), + new PathPatchDbGitRestore("-r", "-v"), + new PathPatchDbGitCheckoutHard(commitNames.get(2), "-nodb", "-v"), + new PathPatchDbGitLink(linkArgs), + new PathPatchCreatingFile(".dbgit/dbgitconfig", new CharsDbGitConfigBackupEnabled()), + new PathPatchDbGitRestore("-r", "-v") + ), + new ProjectTestResourcesCleanDirectoryPath("04") + ), + new SimpleTest<>( + "Should not throw any exceptions", + (path) -> { + path.toString(); + return true; + } + ) + ); + + System.out.println(result.text()); + Assertions.assertTrue(result.value()); + } + + @Test + public final void dbToDbRestoreWorksWithCustomTypes() { + final String description = "Hardest sakilla_database sequential add and restore with table data and custom types (mpaa_rating) works"; + final TestResult result = new DescribedTestResult( + description, + new SimpleTestResult<>( + new PathAfterDbGitRun( + //pagilla to test#databasegit over dvdrental + new ArgsExplicit("restore", "-r", "-v"), + + new PathAfterDbGitRun( + new ArgsDbGitLinkPgAuto(new NameOfDefaultTargetTestDatabase()), + + //pagilla to local repo + new PathAfterDbGitLinkAndAdd( + new ArgsDbGitLinkPgAuto("pagilla"), + new CharsDbIgnoreWithDataAndTypes(), + + //dvdrental to test#databasegit + new PathAfterDbGitRun( + new ArgsExplicit("restore", "-r", "-v"), + + new PathAfterDbGitRun( + new ArgsDbGitLinkPgAuto(new NameOfDefaultTargetTestDatabase()), + + //dvdrental to local repo + new PathAfterDbGitLinkAndAdd( + new ArgsDbGitLinkPgAuto("dvdrental"), + new CharsDbIgnoreWithDataAndTypes(), + + new PathAfterDbGitRun( + new ArgsExplicit("init"), + + new PathWithoutFiles( + "*", + new PathNotProjectRoot( + new ProjectTestResourcesCleanDirectoryPath("05") + ) + ) + ) + ) + ) + ) + ) + ) + ), + new SimpleTest<>( + "Should not throw any exceptions", + (path) -> { + path.toString(); + return true; + } + ) + ) + ); + + System.out.println(result.text()); + Assertions.assertTrue(result.value()); + } + +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/DbGitIntegrationTestExtendedCommands.java b/src/test/java/ru/fusionsoft/dbgit/integration/DbGitIntegrationTestExtendedCommands.java new file mode 100644 index 0000000..8124cfc --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/DbGitIntegrationTestExtendedCommands.java @@ -0,0 +1,7 @@ +package ru.fusionsoft.dbgit.integration; + +import org.junit.jupiter.api.Tag; + +@Tag("integration") +public class DbGitIntegrationTestExtendedCommands { +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/DbGitIntegrationTestNotebook.java b/src/test/java/ru/fusionsoft/dbgit/integration/DbGitIntegrationTestNotebook.java new file mode 100644 index 0000000..218bebc --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/DbGitIntegrationTestNotebook.java @@ -0,0 +1,148 @@ +package ru.fusionsoft.dbgit.integration; + +import java.nio.file.Path; +import java.text.MessageFormat; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import ru.fusionsoft.dbgit.integration.primitives.PatchSequential; +import ru.fusionsoft.dbgit.integration.primitives.args.ArgsExplicit; +import ru.fusionsoft.dbgit.integration.primitives.args.specific.ArgsDbGitLinkPgAuto; +import ru.fusionsoft.dbgit.integration.primitives.patch.PathPatchCreatingFile; +import ru.fusionsoft.dbgit.integration.primitives.patch.PathPatchRunningGit; +import ru.fusionsoft.dbgit.integration.primitives.patch.specific.PathPatchGitCheckoutOrphan; +import ru.fusionsoft.dbgit.integration.primitives.path.PathAfterDbGitRun; +import ru.fusionsoft.dbgit.integration.primitives.path.PathAfterGitRun; +import ru.fusionsoft.dbgit.integration.primitives.path.PathPatched; +import ru.fusionsoft.dbgit.integration.primitives.path.specific.dbgit.scenarios.PathAfterDbGitLinkAndAdd; +import ru.fusionsoft.dbgit.integration.primitives.path.specific.dbgit.PathWithDbGitRepoCloned; +import ru.fusionsoft.dbgit.integration.primitives.printstream.DefaultPrintStream; +import ru.fusionsoft.dbgit.integration.primitives.DescribedTestResult; +import ru.fusionsoft.dbgit.integration.primitives.SimpleTest; +import ru.fusionsoft.dbgit.integration.primitives.SimpleTestResult; +import ru.fusionsoft.dbgit.integration.primitives.args.specific.ArgsDbGitAddRemoteTestRepo; +import ru.fusionsoft.dbgit.integration.primitives.args.specific.ArgsDbGitLinkPgLocal; +import ru.fusionsoft.dbgit.integration.primitives.chars.specific.dbgit.CharsDbIgnoreWithTableData; +import ru.fusionsoft.dbgit.integration.primitives.chars.specific.UrlOfGitTestRepo; +import ru.fusionsoft.dbgit.integration.primitives.patch.specific.PathPatchDbGitCheckout; +import ru.fusionsoft.dbgit.integration.primitives.path.specific.ProjectTestResourcesCleanDirectoryPath; +import ru.fusionsoft.dbgit.integration.primitives.path.specific.dbgit.scenarios.PathAfterDbGitDumpsDbSchemaToGit; + +@Tag("notebook") +@Disabled +public class DbGitIntegrationTestNotebook { + @Test + public final void appendsDbSchemaToBranchOfTestRepo() { + final String description = "Appends db schema to existing git branch"; + final String nameOfBranchToAppendTo = "sakilla-data"; + final String nameOfDbToDump = "dvdrental"; + final String nameOfRemote = "origin-test"; + final CharSequence ignoreChars = new CharsDbIgnoreWithTableData(); + final DescribedTestResult result = new DescribedTestResult<>( + description, + new SimpleTestResult<>( + new PathAfterDbGitDumpsDbSchemaToGit( + nameOfDbToDump, + nameOfRemote, + new UrlOfGitTestRepo(), + new ArgsDbGitLinkPgLocal(nameOfDbToDump), + new ArgsDbGitAddRemoteTestRepo(nameOfRemote), + ignoreChars, + new PathPatchDbGitCheckout( + nameOfBranchToAppendTo, + "-b", + "-nodb", + "-v" + ), + new DefaultPrintStream(), + new ProjectTestResourcesCleanDirectoryPath(description) + ), + new SimpleTest<>( + (path) -> { + return path.resolve(".dbgit/public/rental.csv").toFile().exists(); + } + ) + ) + ); + + System.out.println("\n" + result.text()); + Assertions.assertTrue(result.value()); + } + + @Test + public final void dumpsDbSchemaToNewBranchOfTestRepo() { + final String nameOfNewBranch = "sakilla-data"; + final String nameOfDbToDump = "pagilla"; + final String nameOfRemote = "origin-test"; + final String description = "Dumps db schema to new git branch"; + final CharSequence ignoreChars = new CharsDbIgnoreWithTableData(); + + new PathAfterGitRun( + new ArgsExplicit("push", nameOfRemote, nameOfNewBranch, "-v"), + + new PathAfterDbGitRun( + new ArgsExplicit("commit", "-m", nameOfDbToDump), + + new PathAfterDbGitLinkAndAdd( + new ArgsDbGitLinkPgAuto(nameOfDbToDump), + ignoreChars, + + new PathPatched( + new PathPatchGitCheckoutOrphan(nameOfNewBranch), + + new PathAfterDbGitRun( + new ArgsDbGitAddRemoteTestRepo(nameOfRemote), + + new PathWithDbGitRepoCloned( + new UrlOfGitTestRepo(), + + new ProjectTestResourcesCleanDirectoryPath( + description + ) + ) + ) + ) + ) + ) + ).toString(); + + } + + @Test + public final void cleansBranch() { + final String branchToClean = "master"; + final String nameOfNewBranch = "orphan"; + final String nameOfRemote = "origin"; + final String description = "Replaces branch " + + branchToClean + + " with a new git branch"; + + new PathPatched( + new PatchSequential<>( + new PathPatchGitCheckoutOrphan(nameOfNewBranch), + new PathPatchCreatingFile("readme.md", "Just a clean branch"), + new PathPatchRunningGit("add", "readme.md"), + new PathPatchRunningGit("commit", "-m", "\"clean branch\""), + new PathPatchRunningGit("push", nameOfRemote, + MessageFormat.format( + "+{0}:{1}", nameOfNewBranch, branchToClean + ) + ) + ), + new PathAfterDbGitRun( + new ArgsDbGitAddRemoteTestRepo(nameOfRemote), + + new PathWithDbGitRepoCloned( + new UrlOfGitTestRepo(), + new ProjectTestResourcesCleanDirectoryPath( + description + ) + ) + ) + + ).toString(); + + } + +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/SelfTest.java b/src/test/java/ru/fusionsoft/dbgit/integration/SelfTest.java new file mode 100644 index 0000000..73eacc6 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/SelfTest.java @@ -0,0 +1,206 @@ +package ru.fusionsoft.dbgit.integration; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import org.apache.commons.io.FileUtils; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import ru.fusionsoft.dbgit.integration.primitives.TestResult; +import ru.fusionsoft.dbgit.integration.primitives.files.AutoDeletingTempFilePath; +import ru.fusionsoft.dbgit.integration.primitives.patch.PathPatchCreatingFile; +import ru.fusionsoft.dbgit.integration.primitives.path.PathNotProjectRoot; +import ru.fusionsoft.dbgit.integration.primitives.path.PathPatched; +import ru.fusionsoft.dbgit.integration.primitives.path.PathPrintsToConsole; +import ru.fusionsoft.dbgit.integration.primitives.path.specific.CurrentWorkingDirectory; +import ru.fusionsoft.dbgit.integration.primitives.path.specific.ProjectTestResourcesCleanDirectoryPath; +import ru.fusionsoft.dbgit.integration.primitives.DescribedTestResult; +import ru.fusionsoft.dbgit.integration.primitives.GroupedTestResult; +import ru.fusionsoft.dbgit.integration.primitives.Patch; +import ru.fusionsoft.dbgit.integration.primitives.PatchSequential; +import ru.fusionsoft.dbgit.integration.primitives.SimpleTest; +import ru.fusionsoft.dbgit.integration.primitives.SimpleTestResult; + +public class SelfTest { + + @Test + public final void subjectSideEffectAppearsOnceWhenAccessingTwice() throws Exception { + Assertions.assertEquals( + 2, + new DescribedTestResult( + "Test result subject side effect appears once", + new SimpleTestResult( + new PathPrintsToConsole( + "Line printed as side effect...", + new ProjectTestResourcesCleanDirectoryPath( + "Test result subject side effect appears once" + ) + ), + new SimpleTest<>(subj -> { + subj.isAbsolute(); + subj.toString(); + subj.toFile(); + return true; + }) + ) + ) + .text() + .split("\n") + .length + ); + } + + @Test + public final void failsToFalseOnException() { + final ProjectTestResourcesCleanDirectoryPath workingDirectory = + new ProjectTestResourcesCleanDirectoryPath( + "Fails to false on exception"); + + Assertions.assertDoesNotThrow( + () -> { + final TestResult testResult = + new DescribedTestResult( + "Fails to false on exception", + new SimpleTestResult( + new PathPatched( + new PathNotProjectRoot(workingDirectory), + new Patch() { + @Override + public void apply(Path root) throws Exception { + System.out.println("access " + root.toString()); + throw new RuntimeException("dummy error"); + } + } + ), + new SimpleTest<>(path -> { + path.toString(); + path.toString(); + path.toString(); + path.toString(); + return ! path + .resolve("pom.xml") + .toFile() + .exists(); + }) + ) + ); + + Assertions.assertFalse(testResult.value()); + } + ); + } + + @Test + public final void groupedTestResultWorks() { + final TestResult result = new GroupedTestResult( + "Grouped test result works", + new ProjectTestResourcesCleanDirectoryPath( + "Grouped test result works" + ), + new SimpleTest( + "Retruns true", + (path) -> { + path.toString(); + return true; + } + ), + new SimpleTest<>( + "Throws exception", + (path) -> { + path.toString(); + throw new Exception("dummy expection"); + } + ), + new SimpleTest<>( + "Throws error", + (path) -> { + path.toString(); + throw new Error("dummy error the second"); + } + ) + ); + Assertions.assertFalse(result.value()); + } + + @Test + public final void patchedWorks() { + final ProjectTestResourcesCleanDirectoryPath workingDirectory = + new ProjectTestResourcesCleanDirectoryPath( + "Patched works" + ); + + final String fileName = "testFile.txt"; + final String content = "content"; + + final TestResult result = new GroupedTestResult<>( + "Patched works", + new PathPatched( + new PathNotProjectRoot(workingDirectory), + new PathPatchCreatingFile(fileName, content) + ), + + new SimpleTest<>( + "File exists", + path -> { + return path.resolve(fileName).toFile().exists(); + } + ), + new SimpleTest<>( + "File content as expected", + path -> { + return FileUtils.readFileToString( + path.resolve(fileName).toFile() + ) + .contains(content); + } + ) + ); + + System.out.println(result.text()); + Assertions.assertTrue(result.value()); + } + + @Test + public final void patchSequentalWorks() { + final String fileName = "abc.txt"; + final String fileContent = "cba"; + final DescribedTestResult result = new DescribedTestResult( + "Sequental patch works", + new SimpleTestResult<>( + new PathPatched( + new PathNotProjectRoot( + new ProjectTestResourcesCleanDirectoryPath( + "Sequental patch works" + ) + ), + new PatchSequential<>( + new PathPatchCreatingFile(fileName, "abc"), + new PathPatchCreatingFile(fileName, fileContent) + ) + ), + new SimpleTest<>( + "File content is as expected", + x -> FileUtils.readFileToString(x.resolve(fileName).toFile()) + .equals(fileContent) + + ) + ) + ); + + System.out.println(result.text()); + Assertions.assertTrue(result.value()); + + } + + @Test + public final void tempFileWorks() throws IOException { + Path path = new CurrentWorkingDirectory(); + try (AutoDeletingTempFilePath tempFilePath = new AutoDeletingTempFilePath(new CurrentWorkingDirectory(), "some")) { + path = tempFilePath; + final String data = "123"; + FileUtils.writeStringToFile(tempFilePath.toFile(), data); + Files.readAllLines(tempFilePath.toFile().toPath()).contains(data); + } + Assertions.assertFalse(path.toFile().exists()); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/StickyFunctionTest.java b/src/test/java/ru/fusionsoft/dbgit/integration/StickyFunctionTest.java new file mode 100644 index 0000000..caf5371 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/StickyFunctionTest.java @@ -0,0 +1,31 @@ +package ru.fusionsoft.dbgit.integration; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import ru.fusionsoft.dbgit.integration.primitives.Function; +import ru.fusionsoft.dbgit.integration.primitives.StickyFunction; + +import java.util.concurrent.atomic.AtomicInteger; + +public class StickyFunctionTest { + + @Test + public void returnsValue() throws Exception { + Assertions.assertEquals( + 4, + new StickyFunction( (x) -> x+2 ).value(2) + ); + } + + @Test + public void returnsSameValue() throws Exception { + final AtomicInteger accessCount = new AtomicInteger(0); + final Function sticky = new StickyFunction<>( + (x) -> accessCount.incrementAndGet() + ); + Assertions.assertEquals( + sticky.value(0), + sticky.value(0) + ); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/deprecated/PathAfterDbGitMainRun.java b/src/test/java/ru/fusionsoft/dbgit/integration/deprecated/PathAfterDbGitMainRun.java new file mode 100644 index 0000000..97d3d6a --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/deprecated/PathAfterDbGitMainRun.java @@ -0,0 +1,35 @@ +package ru.fusionsoft.dbgit.integration.deprecated; + +import java.nio.file.Path; +import java.util.Arrays; +import ru.fusionsoft.dbgit.integration.primitives.Args; +import ru.fusionsoft.dbgit.integration.primitives.path.PathEnvelope; +import ru.fusionsoft.dbgit.integration.primitives.path.specific.CurrentWorkingDirectory; + +public class PathAfterDbGitMainRun extends PathEnvelope { + public PathAfterDbGitMainRun(Args args, Path origin) { + super(() -> { + final boolean originIsNotAppWorkingDirectory = ( + ! new CurrentWorkingDirectory() + .toAbsolutePath() + .toString() + .equals(origin.toAbsolutePath().toString()) + ); + if ( originIsNotAppWorkingDirectory ) { + throw new RuntimeException( + "Given path:" + + "\n->" + origin.toAbsolutePath().toString() + + "\nis not an App's working directory:" + + "\n->" + new CurrentWorkingDirectory().toAbsolutePath().toString() + + "\nSo App cant apply to the given Path" + ); + } + origin.toString(); + System.out.println("\n> dbgit " + String.join( + " ", + Arrays.asList(args.values()) + )); + return new WithDbGitMainRunScalar<>(args, origin).value(); + }); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/deprecated/PathAfterExecutableRun.java b/src/test/java/ru/fusionsoft/dbgit/integration/deprecated/PathAfterExecutableRun.java new file mode 100644 index 0000000..3950d14 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/deprecated/PathAfterExecutableRun.java @@ -0,0 +1,88 @@ +package ru.fusionsoft.dbgit.integration.deprecated; + +import java.io.PrintStream; +import java.nio.file.Path; +import ru.fusionsoft.dbgit.integration.primitives.Args; +import ru.fusionsoft.dbgit.integration.primitives.printstream.DefaultPrintStream; +import ru.fusionsoft.dbgit.integration.primitives.args.ArgsExplicit; +import ru.fusionsoft.dbgit.integration.primitives.args.ArgsWithPrepend; +import ru.fusionsoft.dbgit.integration.primitives.chars.CharsOf; +import ru.fusionsoft.dbgit.integration.primitives.path.PathAfterProcessRun; +import ru.fusionsoft.dbgit.integration.primitives.path.PathEnvelope; + +public class PathAfterExecutableRun extends PathEnvelope { + public PathAfterExecutableRun( + Args commandInterface, + CharSequence executableName, + Args command, + PrintStream printStream, + Path origin + ) { + super( + () -> + new PathAfterProcessRun( + new ArgsWithPrepend( + new ArgsWithPrepend( + command, + executableName + ), + commandInterface + ), + printStream, + origin + ) + ); + } + + public PathAfterExecutableRun( + Args commandInterface, + CharSequence executableName, + Args executableArgs, + Path workingDirectory + ) { + this( + commandInterface, + executableName, + executableArgs, + new DefaultPrintStream(), + workingDirectory + ); + } + + public PathAfterExecutableRun( + CharSequence executableName, + Args args, + PrintStream printStream, + Path workingDirectory + ) { + this( + new ArgsExplicit(System.getenv("ComSpec"), "/C"), + executableName, + args, + printStream, + workingDirectory + ); + } + + public PathAfterExecutableRun( + CharSequence executableName, + Args args, + Path workingDirectory + ) { + this( + executableName, + args, + new DefaultPrintStream(), + workingDirectory + ); + } + + public PathAfterExecutableRun(Path executablePath, Args args, Path workingDirectory) { + this( + new CharsOf<>(Path::toString, executablePath), + args, + workingDirectory + ); + } + +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/deprecated/SystemUserDirPath.java b/src/test/java/ru/fusionsoft/dbgit/integration/deprecated/SystemUserDirPath.java new file mode 100644 index 0000000..75dc48b --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/deprecated/SystemUserDirPath.java @@ -0,0 +1,10 @@ +package ru.fusionsoft.dbgit.integration.deprecated; + +import java.nio.file.Paths; +import ru.fusionsoft.dbgit.integration.primitives.path.PathEnvelope; + +public class SystemUserDirPath extends PathEnvelope { + public SystemUserDirPath(){ + super(()->Paths.get(System.getProperty("user.dir"))); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/deprecated/WithDbGitMainRunScalar.java b/src/test/java/ru/fusionsoft/dbgit/integration/deprecated/WithDbGitMainRunScalar.java new file mode 100644 index 0000000..b65fc19 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/deprecated/WithDbGitMainRunScalar.java @@ -0,0 +1,26 @@ +package ru.fusionsoft.dbgit.integration.deprecated; + +import java.util.Arrays; +import ru.fusionsoft.dbgit.App; +import ru.fusionsoft.dbgit.integration.primitives.Args; +import ru.fusionsoft.dbgit.integration.primitives.Scalar; + +public class WithDbGitMainRunScalar implements Scalar { + private final Args args; + private final Y origin; + + public WithDbGitMainRunScalar(Args args, Y origin) { + this.args = args; + this.origin = origin; + } + + @Override + public final Y value() throws Exception { + App.main( + Arrays.stream(this.args.values()) + .map(String::valueOf) + .toArray(String[]::new) + ); + return origin; + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/Args.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/Args.java new file mode 100644 index 0000000..a6b95e6 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/Args.java @@ -0,0 +1,5 @@ +package ru.fusionsoft.dbgit.integration.primitives; + +public interface Args { + CharSequence[] values(); +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/Credentials.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/Credentials.java new file mode 100644 index 0000000..08e0b4d --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/Credentials.java @@ -0,0 +1,6 @@ +package ru.fusionsoft.dbgit.integration.primitives; + +public interface Credentials { + String username() ; + String password() ; +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/DescribedTestResult.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/DescribedTestResult.java new file mode 100644 index 0000000..a99af00 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/DescribedTestResult.java @@ -0,0 +1,44 @@ +package ru.fusionsoft.dbgit.integration.primitives; +import java.text.MessageFormat; +import ru.fusionsoft.dbgit.integration.primitives.chars.CharsQuotedToRegexPattern; +import ru.fusionsoft.dbgit.integration.primitives.chars.specific.test.LabelOfTestRunResult; + +public class DescribedTestResult implements TestResult { + private final String description; + private final TestResult testResult; + + public DescribedTestResult(String description, TestResult testResult) { + this.description = description; + this.testResult = testResult; + } + + public DescribedTestResult(String description, Subj subject, Test test) { + this(description, new SimpleTestResult<>(subject, test)); + } + + @Override + public final boolean value() { + return this.testResult.value(); + } + + @Override + public final String text() { + final CharSequence valueChars = new CharsQuotedToRegexPattern( + new LabelOfTestRunResult(this.testResult.value()) + ); + + return this.testResult + .text() + .replaceFirst( + String.valueOf(valueChars), + MessageFormat.format( + "{0} {1}", + valueChars, + this.description + ) + + ); + + } + +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/Function.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/Function.java new file mode 100644 index 0000000..232e585 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/Function.java @@ -0,0 +1,6 @@ +package ru.fusionsoft.dbgit.integration.primitives; + + +public interface Function{ + Y value(X source) throws Exception; +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/GroupedTestResult.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/GroupedTestResult.java new file mode 100644 index 0000000..19467e8 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/GroupedTestResult.java @@ -0,0 +1,26 @@ +package ru.fusionsoft.dbgit.integration.primitives; + +import ru.fusionsoft.dbgit.integration.primitives.chars.specific.test.LabelOfTestRunResult; +import ru.fusionsoft.dbgit.integration.primitives.chars.LinesOfString; +import ru.fusionsoft.dbgit.integration.primitives.chars.specific.test.ReportOfTestGroupRun; + +public class GroupedTestResult implements TestResult { + private final CharSequence text; + + @SafeVarargs + public GroupedTestResult(CharSequence description, Subj subject, Test... tests ) { + this.text = new ReportOfTestGroupRun<>(description, subject, tests); + } + + @Override + public final boolean value() { + return String.valueOf( + new LinesOfString(String.valueOf(this.text)).list().get(0) + ).contains(new LabelOfTestRunResult(true)); + } + + @Override + public final String text() { + return String.valueOf(this.text); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/Patch.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/Patch.java new file mode 100644 index 0000000..c5685e4 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/Patch.java @@ -0,0 +1,8 @@ +package ru.fusionsoft.dbgit.integration.primitives; + +/* + A consumer, but can throw checked + */ +public interface Patch { + void apply(T root) throws Exception; +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/PatchSequential.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/PatchSequential.java new file mode 100644 index 0000000..6fd4353 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/PatchSequential.java @@ -0,0 +1,24 @@ +package ru.fusionsoft.dbgit.integration.primitives; + +import java.util.Arrays; +import java.util.Collection; + +public class PatchSequential implements Patch { + private final Collection> patches; + + public PatchSequential(final Collection> patches) { + this.patches = patches; + } + + @SafeVarargs + public PatchSequential(final Patch... patches) { + this(Arrays.asList(patches)); + } + + @Override + public final void apply(final T root) throws Exception { + for (final Patch patch : patches) { + patch.apply(root); + } + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/PatchedScalar.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/PatchedScalar.java new file mode 100644 index 0000000..9e5ab58 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/PatchedScalar.java @@ -0,0 +1,17 @@ +package ru.fusionsoft.dbgit.integration.primitives; + +public class PatchedScalar implements Scalar { + private final T origin; + private final Patch patch; + + public PatchedScalar(T origin, Patch patch) { + this.origin = origin; + this.patch = patch; + } + + @Override + public final T value() throws Exception { + this.patch.apply(origin); + return origin; + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/RunnableWithException.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/RunnableWithException.java new file mode 100644 index 0000000..c5b7358 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/RunnableWithException.java @@ -0,0 +1,5 @@ +package ru.fusionsoft.dbgit.integration.primitives; + +public interface RunnableWithException { + void run() throws Exception; +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/SafeScalar.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/SafeScalar.java new file mode 100644 index 0000000..f4c756b --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/SafeScalar.java @@ -0,0 +1,5 @@ +package ru.fusionsoft.dbgit.integration.primitives; + +public interface SafeScalar { + T value(); +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/SafeScalarOf.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/SafeScalarOf.java new file mode 100644 index 0000000..82eb6bb --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/SafeScalarOf.java @@ -0,0 +1,28 @@ +package ru.fusionsoft.dbgit.integration.primitives; + +public class SafeScalarOf implements SafeScalar { + private final Scalar origin; + + public SafeScalarOf(Scalar origin) { + this.origin = origin; + } + + public SafeScalarOf(Function origin, X value){ + this( () -> origin.value(value) ) ; + } + + @Override + public final Y value() { + try { + return origin.value(); + } catch (Exception e) { + throw new SafeScalarError(e); + } + } + + public static class SafeScalarError extends Error { + public SafeScalarError(Throwable cause) { + super("Error occurs while constructing safe scalar value", cause); + } + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/Scalar.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/Scalar.java new file mode 100644 index 0000000..cc822de --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/Scalar.java @@ -0,0 +1,8 @@ +package ru.fusionsoft.dbgit.integration.primitives; + + +public interface Scalar { + T value() throws Exception; + + Scalar DONT_CARE = () -> { throw new Exception("Not implemented"); }; +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/SimpleTest.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/SimpleTest.java new file mode 100644 index 0000000..93d0bf2 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/SimpleTest.java @@ -0,0 +1,26 @@ +package ru.fusionsoft.dbgit.integration.primitives; + +public class SimpleTest implements Test { + private final Function predicate; + private final String description; + + public SimpleTest(String description, Function predicate) { + this.description = description; + this.predicate = predicate; + } + + public SimpleTest(Function predicate) { + this.description = "test just runs without errors"; + this.predicate = predicate; + } + + @Override + public final boolean value(Subj subj) throws Exception { + return this.predicate.value(subj); + } + + @Override + public final String description() { + return this.description; + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/SimpleTestResult.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/SimpleTestResult.java new file mode 100644 index 0000000..0285828 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/SimpleTestResult.java @@ -0,0 +1,23 @@ +package ru.fusionsoft.dbgit.integration.primitives; + +import ru.fusionsoft.dbgit.integration.primitives.chars.specific.test.LabelOfTestRunResult; +import ru.fusionsoft.dbgit.integration.primitives.chars.specific.test.ReportOfTestRun; + +public class SimpleTestResult implements TestResult { + private final CharSequence text; + public SimpleTestResult(Subj subject, Test test) { + this.text = new ReportOfTestRun<>(subject, test); + } + + @Override + public final String text() { + return String.valueOf(this.text); + } + + @Override + public final boolean value() { + return this + .text() + .contains(String.valueOf(new LabelOfTestRunResult(true))); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/StickyFunction.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/StickyFunction.java new file mode 100644 index 0000000..73a181c --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/StickyFunction.java @@ -0,0 +1,32 @@ +package ru.fusionsoft.dbgit.integration.primitives; + +import java.util.HashMap; +import java.util.Map; + +public class StickyFunction implements Function { + private final Function origin; + private final Map cachedValues; + + private StickyFunction(Function origin, Map cachedValues) { + this.origin = origin; + this.cachedValues = cachedValues; + } + + public StickyFunction(Function origin){ + this(origin, new HashMap<>()); + } + + public StickyFunction(Scalar origin){ + this((x) -> { + return origin.value(); + }); + } + + @Override + public Y value(X arg) throws Exception { + if (!cachedValues.containsKey(arg)) { + cachedValues.put(arg, origin.value(arg)); + } + return cachedValues.get(arg); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/StickyScalar.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/StickyScalar.java new file mode 100644 index 0000000..a79c5fe --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/StickyScalar.java @@ -0,0 +1,25 @@ +package ru.fusionsoft.dbgit.integration.primitives; + +public class StickyScalar implements Scalar { + private final Function origin; + + public StickyScalar(Scalar origin) { + this.origin = new StickyFunction<>(origin); + } + + public StickyScalar(Function origin, X value) { + this( + new Scalar() { + @Override + public Y value() throws Exception { + return origin.value(value); + } + } + ); + } + + @Override + public final Y value() throws Exception { + return this.origin.value(true); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/Test.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/Test.java new file mode 100644 index 0000000..8686e04 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/Test.java @@ -0,0 +1,6 @@ +package ru.fusionsoft.dbgit.integration.primitives; + +public interface Test { + String description(); + boolean value(Subj subj) throws Exception; +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/TestResult.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/TestResult.java new file mode 100644 index 0000000..1409c54 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/TestResult.java @@ -0,0 +1,6 @@ +package ru.fusionsoft.dbgit.integration.primitives; + +public interface TestResult { + String text(); + boolean value(); +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/ArgsExplicit.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/ArgsExplicit.java new file mode 100644 index 0000000..7559fe9 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/ArgsExplicit.java @@ -0,0 +1,13 @@ +package ru.fusionsoft.dbgit.integration.primitives.args; + +import ru.fusionsoft.dbgit.integration.primitives.Args; + +public class ArgsExplicit implements Args { + private final CharSequence[] args; + public ArgsExplicit(CharSequence... values) { + this.args = values.clone(); + } + public final CharSequence[] values() { + return this.args; + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/ArgsRunningCommand.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/ArgsRunningCommand.java new file mode 100644 index 0000000..09df2d2 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/ArgsRunningCommand.java @@ -0,0 +1,33 @@ +package ru.fusionsoft.dbgit.integration.primitives.args; + +import java.nio.file.Path; +import ru.fusionsoft.dbgit.integration.primitives.Args; +import ru.fusionsoft.dbgit.integration.primitives.chars.CharsOf; +import ru.fusionsoft.dbgit.integration.primitives.chars.CharsOfLines; +import ru.fusionsoft.dbgit.integration.primitives.chars.CharsWithBoundary; + +public class ArgsRunningCommand extends ArgsExplicit { + public ArgsRunningCommand(CharSequence commandName) { + super( + ( System.getenv("ComSpec") == null ) + ? new CharSequence[]{commandName} + : new CharSequence[]{System.getenv("ComSpec"), "/C", commandName} + ); + } + public ArgsRunningCommand(Args commandRunArgs) { + super( + ( System.getenv("ComSpec") == null ) + ? new CharSequence[]{"sh", "-c", new CharsWithBoundary(new CharsOfLines(commandRunArgs), "\"")} + : new CharSequence[]{System.getenv("ComSpec"), "/C", new CharsOfLines(commandRunArgs)} + ); + } + public ArgsRunningCommand(Path executablePath) { + this( + new CharsOf<>( + Object::toString, + executablePath + ) + ); + } + +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/ArgsWithAppend.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/ArgsWithAppend.java new file mode 100644 index 0000000..91964b0 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/ArgsWithAppend.java @@ -0,0 +1,27 @@ +package ru.fusionsoft.dbgit.integration.primitives.args; + +import org.apache.commons.lang3.ArrayUtils; +import ru.fusionsoft.dbgit.integration.primitives.Args; + +public class ArgsWithAppend implements Args { + private final Args origin; + private final Args append; + + public ArgsWithAppend(Args origin, Args append) { + this.origin = origin; + this.append = append; + } + + public ArgsWithAppend(Args origin, String... append) { + this.origin = origin; + this.append = new ArgsExplicit(append.clone()); + } + + @Override + public final CharSequence[] values() { + return ArrayUtils.addAll( + origin.values(), + append.values() + ); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/ArgsWithPrepend.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/ArgsWithPrepend.java new file mode 100644 index 0000000..b3f7b19 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/ArgsWithPrepend.java @@ -0,0 +1,26 @@ +package ru.fusionsoft.dbgit.integration.primitives.args; + +import org.apache.commons.lang3.ArrayUtils; +import ru.fusionsoft.dbgit.integration.primitives.Args; + +public class ArgsWithPrepend implements Args { + private final Args origin; + private final Args prepend; + + public ArgsWithPrepend(Args origin, Args prepend) { + this.origin = origin; + this.prepend = prepend; + } + public ArgsWithPrepend(Args origin, CharSequence... prepend) { + this.origin = origin; + this.prepend = new ArgsExplicit(prepend); + } + + @Override + public final CharSequence[] values() { + return ArrayUtils.addAll( + prepend.values(), + origin.values() + ); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/specific/ArgsDbGitAdd.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/specific/ArgsDbGitAdd.java new file mode 100644 index 0000000..f8d8def --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/specific/ArgsDbGitAdd.java @@ -0,0 +1,13 @@ +package ru.fusionsoft.dbgit.integration.primitives.args.specific; + +import ru.fusionsoft.dbgit.integration.primitives.args.ArgsExplicit; +import ru.fusionsoft.dbgit.integration.primitives.args.ArgsWithPrepend; + +public class ArgsDbGitAdd extends ArgsWithPrepend { + public ArgsDbGitAdd(CharSequence mask) { + super(new ArgsExplicit(mask), "add", "-v"); + } + public ArgsDbGitAdd() { + this("\"*\""); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/specific/ArgsDbGitAddRemote.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/specific/ArgsDbGitAddRemote.java new file mode 100644 index 0000000..0d8ffc4 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/specific/ArgsDbGitAddRemote.java @@ -0,0 +1,17 @@ +package ru.fusionsoft.dbgit.integration.primitives.args.specific; + +import ru.fusionsoft.dbgit.integration.primitives.args.ArgsExplicit; + +public class ArgsDbGitAddRemote extends ArgsExplicit { + public ArgsDbGitAddRemote(String url, String name, String user, String pass) { + super( + "remote", "add", name, + "https://" + + user + + ":" + + pass + + "@" + + url + ); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/specific/ArgsDbGitAddRemoteTestRepo.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/specific/ArgsDbGitAddRemoteTestRepo.java new file mode 100644 index 0000000..126f1e1 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/specific/ArgsDbGitAddRemoteTestRepo.java @@ -0,0 +1,24 @@ +package ru.fusionsoft.dbgit.integration.primitives.args.specific; + +import ru.fusionsoft.dbgit.integration.primitives.Credentials; +import ru.fusionsoft.dbgit.integration.primitives.credentials.specific.CredsOfGitTestRepo; + +public class ArgsDbGitAddRemoteTestRepo extends ArgsDbGitAddRemote { + public ArgsDbGitAddRemoteTestRepo(String url, String name, String user, String pass) { + super(url, name, user, pass); + } + public ArgsDbGitAddRemoteTestRepo(String url, String name, Credentials credentials) { + this(url, name, credentials.username(), credentials.password()); + } + public ArgsDbGitAddRemoteTestRepo(String name) { + this( + "github.com/rocket-3/dbgit-test.git", + name, + new CredsOfGitTestRepo() + ); + } + public ArgsDbGitAddRemoteTestRepo() { + this("origin"); + } + +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/specific/ArgsDbGitCheckout.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/specific/ArgsDbGitCheckout.java new file mode 100644 index 0000000..986cbbb --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/specific/ArgsDbGitCheckout.java @@ -0,0 +1,16 @@ +package ru.fusionsoft.dbgit.integration.primitives.args.specific; + +import ru.fusionsoft.dbgit.integration.primitives.args.ArgsExplicit; +import ru.fusionsoft.dbgit.integration.primitives.args.ArgsWithAppend; +import ru.fusionsoft.dbgit.integration.primitives.args.ArgsWithPrepend; + +public class ArgsDbGitCheckout extends ArgsWithPrepend { + + public ArgsDbGitCheckout(CharSequence... args) { + super( + new ArgsExplicit(args), + "checkout" + ); + } + +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/specific/ArgsDbGitClone.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/specific/ArgsDbGitClone.java new file mode 100644 index 0000000..e642d97 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/specific/ArgsDbGitClone.java @@ -0,0 +1,18 @@ +package ru.fusionsoft.dbgit.integration.primitives.args.specific; + +import java.nio.file.Path; +import ru.fusionsoft.dbgit.integration.primitives.args.ArgsExplicit; +import ru.fusionsoft.dbgit.integration.primitives.chars.CharsOf; +import ru.fusionsoft.dbgit.integration.primitives.path.specific.CurrentWorkingDirectory; + +public class ArgsDbGitClone extends ArgsExplicit { + public ArgsDbGitClone(CharSequence repoUrl, CharSequence directoryToCloneToChars) { + super("clone", repoUrl, "--directory", "\"" + directoryToCloneToChars + "\""); + } + public ArgsDbGitClone(CharSequence repoUrl, Path directoryToCloneTo) { + this(repoUrl, new CharsOf<>(()->directoryToCloneTo.toAbsolutePath().toString())); + } + public ArgsDbGitClone(CharSequence repoUrl) { + this(repoUrl, "."); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/specific/ArgsDbGitInit.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/specific/ArgsDbGitInit.java new file mode 100644 index 0000000..c3b76eb --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/specific/ArgsDbGitInit.java @@ -0,0 +1,9 @@ +package ru.fusionsoft.dbgit.integration.primitives.args.specific; + +import ru.fusionsoft.dbgit.integration.primitives.args.ArgsExplicit; + +public class ArgsDbGitInit extends ArgsExplicit { + public ArgsDbGitInit() { + super("init"); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/specific/ArgsDbGitLink.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/specific/ArgsDbGitLink.java new file mode 100644 index 0000000..596a4e8 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/specific/ArgsDbGitLink.java @@ -0,0 +1,31 @@ +package ru.fusionsoft.dbgit.integration.primitives.args.specific; + +import ru.fusionsoft.dbgit.integration.primitives.Args; +import ru.fusionsoft.dbgit.integration.primitives.SafeScalar; +import ru.fusionsoft.dbgit.integration.primitives.SafeScalarOf; +import ru.fusionsoft.dbgit.integration.primitives.Scalar; +import ru.fusionsoft.dbgit.integration.primitives.StickyScalar; +import ru.fusionsoft.dbgit.integration.primitives.args.ArgsExplicit; + +public class ArgsDbGitLink implements Args { + private final SafeScalar argsScalar; + + public ArgsDbGitLink(Scalar origin) { + this.argsScalar = new SafeScalarOf(new StickyScalar<>(origin)); + } + public ArgsDbGitLink(CharSequence url, CharSequence database, CharSequence user, CharSequence pass) { + this(()-> { + return new ArgsExplicit( + "link", + url + "/" + database, + "user=" + user, + "password=" + pass + ); + }); + } + @Override + public final CharSequence[] values() { + return argsScalar.value().values(); + } + +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/specific/ArgsDbGitLinkPgAuto.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/specific/ArgsDbGitLinkPgAuto.java new file mode 100644 index 0000000..afa53be --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/specific/ArgsDbGitLinkPgAuto.java @@ -0,0 +1,7 @@ +package ru.fusionsoft.dbgit.integration.primitives.args.specific; + +public class ArgsDbGitLinkPgAuto extends ArgsDbGitLink { + public ArgsDbGitLinkPgAuto(CharSequence databaseName) { + super(()->new ArgsDbGitLinkPgRemote(databaseName)); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/specific/ArgsDbGitLinkPgLocal.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/specific/ArgsDbGitLinkPgLocal.java new file mode 100644 index 0000000..6a701db --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/specific/ArgsDbGitLinkPgLocal.java @@ -0,0 +1,22 @@ +package ru.fusionsoft.dbgit.integration.primitives.args.specific; + +import ru.fusionsoft.dbgit.integration.primitives.Credentials; +import ru.fusionsoft.dbgit.integration.primitives.credentials.specific.CredsOfPgTestDatabase; + +public class ArgsDbGitLinkPgLocal extends ArgsDbGitLink { + public ArgsDbGitLinkPgLocal(CharSequence database, CharSequence user, CharSequence pass) { + super( + "jdbc:postgresql://localhost", + database, + user, + pass + ); + + } + public ArgsDbGitLinkPgLocal(CharSequence database, Credentials credentials) { + this(database, credentials.username(), credentials.password()); + } + public ArgsDbGitLinkPgLocal(CharSequence database) { + this(database, new CredsOfPgTestDatabase()); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/specific/ArgsDbGitLinkPgRemote.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/specific/ArgsDbGitLinkPgRemote.java new file mode 100644 index 0000000..9731bdf --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/specific/ArgsDbGitLinkPgRemote.java @@ -0,0 +1,26 @@ +package ru.fusionsoft.dbgit.integration.primitives.args.specific; + +import ru.fusionsoft.dbgit.integration.primitives.Credentials; +import ru.fusionsoft.dbgit.integration.primitives.credentials.specific.CredsOfPgTestDatabase; + +public class ArgsDbGitLinkPgRemote extends ArgsDbGitLink { + public ArgsDbGitLinkPgRemote(CharSequence database, CharSequence username, CharSequence password) { + super( + "jdbc:postgresql://135.181.94.98:31007", + database, + username, + password + ); + } + + public ArgsDbGitLinkPgRemote(CharSequence database, Credentials credentials) { + this(database, credentials.username(), credentials.password()); + } + + public ArgsDbGitLinkPgRemote(CharSequence database) { + this( + database, + new CredsOfPgTestDatabase() + ); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/specific/ArgsDbGitReset.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/specific/ArgsDbGitReset.java new file mode 100644 index 0000000..0c20019 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/specific/ArgsDbGitReset.java @@ -0,0 +1,10 @@ +package ru.fusionsoft.dbgit.integration.primitives.args.specific; + +import ru.fusionsoft.dbgit.integration.primitives.args.ArgsExplicit; +import ru.fusionsoft.dbgit.integration.primitives.args.ArgsWithPrepend; + +public class ArgsDbGitReset extends ArgsWithPrepend { + public ArgsDbGitReset(CharSequence nameOfResetMode) { + super(new ArgsExplicit(nameOfResetMode), "reset"); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/specific/ArgsDbGitRestore.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/specific/ArgsDbGitRestore.java new file mode 100644 index 0000000..edb3b57 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/args/specific/ArgsDbGitRestore.java @@ -0,0 +1,10 @@ +package ru.fusionsoft.dbgit.integration.primitives.args.specific; + +import ru.fusionsoft.dbgit.integration.primitives.args.ArgsExplicit; +import ru.fusionsoft.dbgit.integration.primitives.args.ArgsWithPrepend; + +public class ArgsDbGitRestore extends ArgsWithPrepend { + public ArgsDbGitRestore(CharSequence... restoreCommandArgs) { + super(new ArgsExplicit(restoreCommandArgs), "restore"); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/CharSequenceEnvelope.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/CharSequenceEnvelope.java new file mode 100644 index 0000000..32db886 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/CharSequenceEnvelope.java @@ -0,0 +1,54 @@ +package ru.fusionsoft.dbgit.integration.primitives.chars; + +import java.util.stream.IntStream; +import ru.fusionsoft.dbgit.integration.primitives.Scalar; +import ru.fusionsoft.dbgit.integration.primitives.StickyScalar; +import ru.fusionsoft.dbgit.integration.primitives.SafeScalar; +import ru.fusionsoft.dbgit.integration.primitives.SafeScalarOf; + +public abstract class CharSequenceEnvelope implements CharSequence { + private final SafeScalar origin; + + private CharSequenceEnvelope(final SafeScalar origin) { + this.origin = origin; + } + + public CharSequenceEnvelope(final Scalar origin) { + this( + new SafeScalarOf<>( + new StickyScalar<>(origin) + ) + ); + } + + + @Override + public final int length() { + return origin.value().length(); + } + + @Override + public final char charAt(int i) { + return origin.value().charAt(i); + } + + @Override + public final CharSequence subSequence(int i, int i1) { + return origin.value().subSequence(i, i1); + } + + @Override + public final IntStream chars() { + return origin.value().chars(); + } + + @Override + public final IntStream codePoints() { + return origin.value().codePoints(); + } + + @Override + public final String toString() { + return origin.value().toString(); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/CharsOf.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/CharsOf.java new file mode 100644 index 0000000..20f20c1 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/CharsOf.java @@ -0,0 +1,15 @@ +package ru.fusionsoft.dbgit.integration.primitives.chars; + +import ru.fusionsoft.dbgit.integration.primitives.Function; +import ru.fusionsoft.dbgit.integration.primitives.Scalar; +import ru.fusionsoft.dbgit.integration.primitives.StickyScalar; + +public class CharsOf extends CharSequenceEnvelope { + public CharsOf(Function extraction, X source) { + super(new StickyScalar(extraction, source)); + } + + public CharsOf(Scalar scalar) { + super(new StickyScalar<>(scalar)); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/CharsOfConsoleWhenRunning.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/CharsOfConsoleWhenRunning.java new file mode 100644 index 0000000..ca3a7d2 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/CharsOfConsoleWhenRunning.java @@ -0,0 +1,40 @@ +package ru.fusionsoft.dbgit.integration.primitives.chars; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.util.StringTokenizer; +import ru.fusionsoft.dbgit.integration.primitives.RunnableWithException; + +public class CharsOfConsoleWhenRunning extends CharsOf { + + public CharsOfConsoleWhenRunning(RunnableWithException runnable) { + super(() -> { + final PrintStream original = System.out; + try (final ByteArrayOutputStream cachedOutputStream = new ByteArrayOutputStream();) { + try { + System.setOut(new PrintStream(cachedOutputStream, true, "UTF-8")); + + runnable.run(); + return cachedOutputStream.toString(); + + } catch (Throwable e) { + throw new CharsOfConsoleWhenRunningException(cachedOutputStream, e); + } finally { + System.setOut(original); + } + } + }); + } + + public static class CharsOfConsoleWhenRunningException extends Error { + public CharsOfConsoleWhenRunningException(String text, Throwable cause) { + super( + (text.isEmpty() ? "Execution broken after:\n" : "") + text, + cause + ); + } + public CharsOfConsoleWhenRunningException(ByteArrayOutputStream byteArrayOutputStream, Throwable cause) { + this(byteArrayOutputStream.toString(), cause); + } + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/CharsOfLines.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/CharsOfLines.java new file mode 100644 index 0000000..1287880 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/CharsOfLines.java @@ -0,0 +1,38 @@ +package ru.fusionsoft.dbgit.integration.primitives.chars; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import ru.fusionsoft.dbgit.integration.primitives.Args; +import ru.fusionsoft.dbgit.integration.primitives.SafeScalar; +import ru.fusionsoft.dbgit.integration.primitives.SafeScalarOf; + +public class CharsOfLines extends CharSequenceEnvelope { + public CharsOfLines(SafeScalar> charsListScalar, CharSequence delimiterChars, CharSequence itemPrefixChars) { + super(() -> { + return charsListScalar + .value() + .stream() + .map(x -> String.valueOf(itemPrefixChars) + x) + .collect(Collectors.joining(delimiterChars)); + } + ); + } + public CharsOfLines(Lines lines, CharSequence delimiterChars, CharSequence itemPrefixChars) { + this( new SafeScalarOf<>(lines::list), delimiterChars, itemPrefixChars ); + } + public CharsOfLines(List list, CharSequence delimiterChars, CharSequence itemPrefixChars) { + this( new SafeScalarOf<>(()->list), delimiterChars, itemPrefixChars); + } + public CharsOfLines(Args args, CharSequence delimiterChars, CharSequence itemPrefixChars) { + this( new SafeScalarOf<>(()-> Arrays.asList(args.values())), delimiterChars, itemPrefixChars); + } + public CharsOfLines(Args args) { + this( args, "\n", ""); + } + public CharsOfLines(Lines lines) { + this(lines, "\n", ""); + } + public CharsOfLines(List list) { + this(list, "\n", ""); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/CharsOfPathWithComment.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/CharsOfPathWithComment.java new file mode 100644 index 0000000..4430ee9 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/CharsOfPathWithComment.java @@ -0,0 +1,11 @@ +package ru.fusionsoft.dbgit.integration.primitives.chars; + +import java.nio.file.Path; + +public class CharsOfPathWithComment extends CharsOf { + public CharsOfPathWithComment(Path origin, CharSequence comment) { + super(()->{ + return origin.toAbsolutePath().toString() + " # " + comment; + }); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/CharsQuotedToRegexPattern.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/CharsQuotedToRegexPattern.java new file mode 100644 index 0000000..1da53ac --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/CharsQuotedToRegexPattern.java @@ -0,0 +1,9 @@ +package ru.fusionsoft.dbgit.integration.primitives.chars; + +public class CharsQuotedToRegexPattern extends CharSequenceEnvelope { + public CharsQuotedToRegexPattern(CharSequence origin) { + super(() -> { + return String.valueOf(origin).replaceAll("[\\W]", "\\\\$0"); + }); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/CharsWithBoundary.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/CharsWithBoundary.java new file mode 100644 index 0000000..253b0c3 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/CharsWithBoundary.java @@ -0,0 +1,9 @@ +package ru.fusionsoft.dbgit.integration.primitives.chars; + +import java.text.MessageFormat; + +public class CharsWithBoundary extends CharSequenceEnvelope { + public CharsWithBoundary(CharSequence origin, CharSequence boundaryChars) { + super(()-> MessageFormat.format("{1}{0}{1}", origin, boundaryChars)); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/CharsWithMaskedCredentials.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/CharsWithMaskedCredentials.java new file mode 100644 index 0000000..1032cec --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/CharsWithMaskedCredentials.java @@ -0,0 +1,31 @@ +package ru.fusionsoft.dbgit.integration.primitives.chars; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import ru.fusionsoft.dbgit.integration.primitives.credentials.specific.CredsOfGitTestRepo; +import ru.fusionsoft.dbgit.integration.primitives.credentials.specific.CredsOfPgTestDatabase; + +public class CharsWithMaskedCredentials extends CharSequenceEnvelope { + public CharsWithMaskedCredentials(CharSequence origin) { + super(() -> { + final List replacementsList = new ArrayList<>(); + try { + replacementsList.add(new CredsOfGitTestRepo().password()); + } catch (Throwable e) { } + try { + replacementsList.add(new CredsOfPgTestDatabase().password()); + } catch (Throwable e) { } + + return String + .valueOf(origin) + .replaceAll( + replacementsList + .stream() + .map(CharsQuotedToRegexPattern::new) + .collect(Collectors.joining("|")), + "****" + ); + }); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/CommitsFromRepo.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/CommitsFromRepo.java new file mode 100644 index 0000000..3dc0667 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/CommitsFromRepo.java @@ -0,0 +1,51 @@ +package ru.fusionsoft.dbgit.integration.primitives.chars; + +import com.google.common.collect.Lists; +import java.util.List; +import java.util.stream.Collectors; +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription; +import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository; +import org.eclipse.jgit.lib.AnyObjectId; +import org.eclipse.jgit.transport.RefSpec; + +public class CommitsFromRepo { + private final CharSequence repoUrl; + private final CharSequence branchName; + + public CommitsFromRepo(CharSequence repoUrl, CharSequence branchName) { + this.repoUrl = repoUrl; + this.branchName = branchName; + } + + public final List names() throws Exception { + final String treeName = "refs/heads/" + branchName; // tag or branch + try ( + final Git git = new Git( + new InMemoryRepository( + new DfsRepositoryDescription() + ) + ) + ) { + git.fetch() + .setRemote(String.valueOf(repoUrl)) + .setRefSpecs( + new RefSpec( + "+refs/heads/" + branchName + + ":refs/heads/" + branchName + ) + ) + .call(); + + return Lists.newArrayList( + git + .log() + .add(git.getRepository().resolve(treeName)) + .call() + ) + .stream() + .map(AnyObjectId::getName) + .collect(Collectors.toList()); + } + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/Lines.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/Lines.java new file mode 100644 index 0000000..0f035f7 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/Lines.java @@ -0,0 +1,7 @@ +package ru.fusionsoft.dbgit.integration.primitives.chars; + +import java.util.List; + +public interface Lines { + List list() throws Exception; +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/LinesFromInputStream.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/LinesFromInputStream.java new file mode 100644 index 0000000..5a227b3 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/LinesFromInputStream.java @@ -0,0 +1,40 @@ +package ru.fusionsoft.dbgit.integration.primitives.chars; + +import java.io.BufferedReader; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.util.LinkedList; +import java.util.List; +import ru.fusionsoft.dbgit.integration.primitives.Scalar; +import ru.fusionsoft.dbgit.integration.primitives.StickyScalar; + +public class LinesFromInputStream implements Lines { + private final Scalar> listScalar; + public LinesFromInputStream(InputStream origin, String codepageName) { + this.listScalar = new StickyScalar<>( + () -> { + try ( + final BufferedReader reader = new BufferedReader(new InputStreamReader(origin, codepageName)); + ) { + final LinkedList lines = new LinkedList<>(); + String line; + while (( line = reader.readLine() ) != null) { + lines.add(line); + } + return lines; + } + } + ); + } + + public LinesFromInputStream(InputStream origin) { + this(origin, "default"); + } + + @Override + public final List list() throws Exception { + return listScalar.value(); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/LinesOfString.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/LinesOfString.java new file mode 100644 index 0000000..5bb1c0e --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/LinesOfString.java @@ -0,0 +1,18 @@ +package ru.fusionsoft.dbgit.integration.primitives.chars; + +import java.util.Arrays; +import java.util.List; +import ru.fusionsoft.dbgit.integration.primitives.chars.Lines; + +public class LinesOfString implements Lines { + private final String string; + + public LinesOfString(String string) { + this.string = string; + } + + @Override + public final List list() { + return Arrays.asList(string.split("\n")); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/LinesOfUnsafeScalar.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/LinesOfUnsafeScalar.java new file mode 100644 index 0000000..3a9a3a3 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/LinesOfUnsafeScalar.java @@ -0,0 +1,18 @@ +package ru.fusionsoft.dbgit.integration.primitives.chars; + +import java.util.Arrays; +import java.util.List; +import ru.fusionsoft.dbgit.integration.primitives.Scalar; + +public class LinesOfUnsafeScalar implements Lines { + private final Scalar charsScalar; + + public LinesOfUnsafeScalar(CharSequence charSequence) { + this.charsScalar = charSequence::toString; + } + + @Override + public final List list() throws Exception { + return Arrays.asList(String.valueOf(charsScalar.value()).split("\n")); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/NameOfDefaultTargetTestDatabase.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/NameOfDefaultTargetTestDatabase.java new file mode 100644 index 0000000..c21de49 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/NameOfDefaultTargetTestDatabase.java @@ -0,0 +1,9 @@ +package ru.fusionsoft.dbgit.integration.primitives.chars.specific; + +import ru.fusionsoft.dbgit.integration.primitives.chars.CharSequenceEnvelope; + +public class NameOfDefaultTargetTestDatabase extends CharSequenceEnvelope { + public NameOfDefaultTargetTestDatabase() { + super(()->"test#databasegit"); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/UrlOfGitTestRepo.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/UrlOfGitTestRepo.java new file mode 100644 index 0000000..fccf497 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/UrlOfGitTestRepo.java @@ -0,0 +1,9 @@ +package ru.fusionsoft.dbgit.integration.primitives.chars.specific; + +import ru.fusionsoft.dbgit.integration.primitives.chars.CharSequenceEnvelope; + +public class UrlOfGitTestRepo extends CharSequenceEnvelope { + public UrlOfGitTestRepo() { + super(()-> "https://github.com/rocket-3/dbgit-test.git"); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/dbgit/CharsDbGitConfigBackupEnabled.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/dbgit/CharsDbGitConfigBackupEnabled.java new file mode 100644 index 0000000..c1f79ed --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/dbgit/CharsDbGitConfigBackupEnabled.java @@ -0,0 +1,22 @@ +package ru.fusionsoft.dbgit.integration.primitives.chars.specific.dbgit; + +import ru.fusionsoft.dbgit.integration.primitives.chars.CharSequenceEnvelope; + +public class CharsDbGitConfigBackupEnabled extends CharSequenceEnvelope { + public CharsDbGitConfigBackupEnabled() { + super(() -> { + return "[core]\n" + + "MAX_ROW_COUNT_FETCH = 10000\n" + + "LIMIT_FETCH = true\n" + + "LOG_ROTATE = 31\n" + + "LANG = ENG\n" + + "SCRIPT_ROTATE = 31\n" + + "TO_MAKE_BACKUP = true\n" + + "BACKUP_TO_SCHEME = true\n" + + "BACKUP_TABLEDATA = true\n" + + "PORTION_SIZE = 50000\n" + + "TRY_COUNT = 1000\n" + + "TRY_DELAY = 10\n"; + }); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/dbgit/CharsDbGitConfigDefault.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/dbgit/CharsDbGitConfigDefault.java new file mode 100644 index 0000000..09e219e --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/dbgit/CharsDbGitConfigDefault.java @@ -0,0 +1,22 @@ +package ru.fusionsoft.dbgit.integration.primitives.chars.specific.dbgit; + +import ru.fusionsoft.dbgit.integration.primitives.chars.CharSequenceEnvelope; + +public class CharsDbGitConfigDefault extends CharSequenceEnvelope { + public CharsDbGitConfigDefault() { + super(()->{ + return "[core]\n" + + "MAX_ROW_COUNT_FETCH = 10000\n" + + "LIMIT_FETCH = true\n" + + "LOG_ROTATE = 31\n" + + "LANG = ENG\n" + + "SCRIPT_ROTATE = 31\n" + + "TO_MAKE_BACKUP = false\n" + + "BACKUP_TO_SCHEME = true\n" + + "BACKUP_TABLEDATA = true\n" + + "PORTION_SIZE = 50000\n" + + "TRY_COUNT = 1000\n" + + "TRY_DELAY = 10\n"; + }); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/dbgit/CharsDbIgnoreDefault.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/dbgit/CharsDbIgnoreDefault.java new file mode 100644 index 0000000..018fe9f --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/dbgit/CharsDbIgnoreDefault.java @@ -0,0 +1,23 @@ +package ru.fusionsoft.dbgit.integration.primitives.chars.specific.dbgit; + +import ru.fusionsoft.dbgit.integration.primitives.chars.CharSequenceEnvelope; + +public class CharsDbIgnoreDefault extends CharSequenceEnvelope { + + public CharsDbIgnoreDefault() { + super(() -> { + return + "*\n" + + "!public/*.ts\n" + + "!public/*.sch\n" + + "!public/*.seq\n" + + "!public/*.tbl\n" + + "!public/*.pkg\n" + + "!public/*.trg\n" + + "!public/*.prc\n" + + "!public/*.fnc\n" + + "!public/*.vw\n" + + "!public/*.blob\n"; + }); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/dbgit/CharsDbIgnoreWithDataAndTypes.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/dbgit/CharsDbIgnoreWithDataAndTypes.java new file mode 100644 index 0000000..c3725d4 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/dbgit/CharsDbIgnoreWithDataAndTypes.java @@ -0,0 +1,25 @@ +package ru.fusionsoft.dbgit.integration.primitives.chars.specific.dbgit; + +import ru.fusionsoft.dbgit.integration.primitives.chars.CharSequenceEnvelope; + +public class CharsDbIgnoreWithDataAndTypes extends CharSequenceEnvelope { + public CharsDbIgnoreWithDataAndTypes() { + super(()->{ + return "*\n" + + "!public/*.ts\n" + + "!public/*.sch\n" + + "!public/*.seq\n" + + "!public/*.tbl\n" + + "!public/*.pkg\n" + + "!public/*.trg\n" + + "!public/*.prc\n" + + "!public/*.fnc\n" + + "!public/*.vw\n" + + "!public/*.blob\n" + + "!public/*.udt\n" + + "!public/*.enum\n" + + "!public/*.domain\n" + + "!public/*.csv\n"; + }); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/dbgit/CharsDbIgnoreWithTableData.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/dbgit/CharsDbIgnoreWithTableData.java new file mode 100644 index 0000000..1084bfe --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/dbgit/CharsDbIgnoreWithTableData.java @@ -0,0 +1,23 @@ +package ru.fusionsoft.dbgit.integration.primitives.chars.specific.dbgit; + +import ru.fusionsoft.dbgit.integration.primitives.chars.CharSequenceEnvelope; + +public class CharsDbIgnoreWithTableData extends CharSequenceEnvelope { + public CharsDbIgnoreWithTableData() { + super(() -> { + return + "*\n" + + "!public/*.ts\n" + + "!public/*.sch\n" + + "!public/*.seq\n" + + "!public/*.tbl\n" + + "!public/*.pkg\n" + + "!public/*.trg\n" + + "!public/*.prc\n" + + "!public/*.fnc\n" + + "!public/*.vw\n" + + "!public/*.blob\n" + + "!public/*.csv\n"; + }); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/dbgit/CharsDbLink.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/dbgit/CharsDbLink.java new file mode 100644 index 0000000..5d30711 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/dbgit/CharsDbLink.java @@ -0,0 +1,22 @@ +package ru.fusionsoft.dbgit.integration.primitives.chars.specific.dbgit; + +import java.text.MessageFormat; +import ru.fusionsoft.dbgit.integration.primitives.Credentials; +import ru.fusionsoft.dbgit.integration.primitives.chars.CharSequenceEnvelope; + +public class CharsDbLink extends CharSequenceEnvelope { + public CharsDbLink(String url, String catalog, Credentials credentials) { + super(() -> { + return + MessageFormat.format( + "url=jdbc:postgresql://{0}/{1}\n" + + "user={2}\n" + + "password={3}\n" + , url + , catalog + , credentials.username() + , credentials.password() + ); + }); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/test/LabelOfTestRun.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/test/LabelOfTestRun.java new file mode 100644 index 0000000..9925411 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/test/LabelOfTestRun.java @@ -0,0 +1,10 @@ +package ru.fusionsoft.dbgit.integration.primitives.chars.specific.test; + +import java.text.MessageFormat; +import ru.fusionsoft.dbgit.integration.primitives.chars.CharSequenceEnvelope; + +public abstract class LabelOfTestRun extends CharSequenceEnvelope { + public LabelOfTestRun(CharSequence text) { + super(()-> MessageFormat.format("[{0}]", text)); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/test/LabelOfTestRunBrokenSubject.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/test/LabelOfTestRunBrokenSubject.java new file mode 100644 index 0000000..38dff25 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/test/LabelOfTestRunBrokenSubject.java @@ -0,0 +1,7 @@ +package ru.fusionsoft.dbgit.integration.primitives.chars.specific.test; + +public class LabelOfTestRunBrokenSubject extends LabelOfTestRun { + public LabelOfTestRunBrokenSubject() { + super("SUBJECT ACCESS ERROR"); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/test/LabelOfTestRunExceptional.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/test/LabelOfTestRunExceptional.java new file mode 100644 index 0000000..5baf441 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/test/LabelOfTestRunExceptional.java @@ -0,0 +1,7 @@ +package ru.fusionsoft.dbgit.integration.primitives.chars.specific.test; + +public class LabelOfTestRunExceptional extends LabelOfTestRun { + public LabelOfTestRunExceptional() { + super("TEST FAIL EXCEPTION"); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/test/LabelOfTestRunResult.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/test/LabelOfTestRunResult.java new file mode 100644 index 0000000..600eb54 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/test/LabelOfTestRunResult.java @@ -0,0 +1,7 @@ +package ru.fusionsoft.dbgit.integration.primitives.chars.specific.test; + +public class LabelOfTestRunResult extends LabelOfTestRun { + public LabelOfTestRunResult(boolean checkResult) { + super(checkResult ? "TEST OK" : "TEST FAIL"); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/test/ReportOfTestFormat.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/test/ReportOfTestFormat.java new file mode 100644 index 0000000..53dd209 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/test/ReportOfTestFormat.java @@ -0,0 +1,36 @@ +package ru.fusionsoft.dbgit.integration.primitives.chars.specific.test; + +import java.text.MessageFormat; +import ru.fusionsoft.dbgit.integration.primitives.chars.CharSequenceEnvelope; +import ru.fusionsoft.dbgit.integration.primitives.chars.CharsOfLines; +import ru.fusionsoft.dbgit.integration.primitives.chars.LinesOfUnsafeScalar; + +public class ReportOfTestFormat extends CharSequenceEnvelope { + public ReportOfTestFormat(LabelOfTestRun label, CharSequence description, CharSequence subjectDetails, CharSequence testDetails) { + super(() -> { + final CharSequence subjectPart = String.valueOf(subjectDetails).trim().isEmpty() + ? "" + : new CharsOfLines(new LinesOfUnsafeScalar(subjectDetails), "", "\n| "); + + final CharSequence testPart = String.valueOf(testDetails).trim().isEmpty() + ? "" + : new CharsOfLines(new LinesOfUnsafeScalar(testDetails), "", "\n| "); + + return MessageFormat.format( + "{0} \"{1}\"{2}{3}" + , label + , description + , subjectPart + , testPart + ); + }); + } + + public ReportOfTestFormat(LabelOfTestRun label, CharSequence description, CharSequence details) { + this(label, description, details, ""); + } + + public ReportOfTestFormat(LabelOfTestRun label, CharSequence description) { + this(label, description, ""); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/test/ReportOfTestGroupRun.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/test/ReportOfTestGroupRun.java new file mode 100644 index 0000000..9601a7c --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/test/ReportOfTestGroupRun.java @@ -0,0 +1,46 @@ +package ru.fusionsoft.dbgit.integration.primitives.chars.specific.test; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import org.junit.platform.commons.util.ExceptionUtils; +import ru.fusionsoft.dbgit.integration.primitives.SimpleTestResult; +import ru.fusionsoft.dbgit.integration.primitives.Test; +import ru.fusionsoft.dbgit.integration.primitives.TestResult; +import ru.fusionsoft.dbgit.integration.primitives.chars.CharSequenceEnvelope; +import ru.fusionsoft.dbgit.integration.primitives.chars.CharsOf; +import ru.fusionsoft.dbgit.integration.primitives.chars.CharsOfConsoleWhenRunning; +import ru.fusionsoft.dbgit.integration.primitives.chars.CharsWithMaskedCredentials; + +public class ReportOfTestGroupRun extends CharSequenceEnvelope { + @SafeVarargs + public ReportOfTestGroupRun(CharSequence description, Subj subject, Test... tests) { + super(() -> { + return new CharsWithMaskedCredentials(new CharsOf(() -> { + try { + final String subjectConsoleOutput = String.valueOf(new CharsOfConsoleWhenRunning(subject::toString)); + + final List testResults = Arrays + .stream(tests) + .map(x -> new SimpleTestResult<>(subject, x)) + .collect(Collectors.toList()); + + return new ReportOfTestFormat( + new LabelOfTestRunResult(testResults.stream().allMatch(TestResult::value)), + description, + subjectConsoleOutput, + testResults.stream().map(TestResult::text).collect(Collectors.joining("\n")) + ); + } catch (CharsOfConsoleWhenRunning.CharsOfConsoleWhenRunningException e) { + return new ReportOfTestFormat( + new LabelOfTestRunBrokenSubject(), + description, + e.getMessage(), + ExceptionUtils.readStackTrace(e.getCause().getCause()) + ); + } + + })); + }); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/test/ReportOfTestRun.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/test/ReportOfTestRun.java new file mode 100644 index 0000000..53b44c4 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/test/ReportOfTestRun.java @@ -0,0 +1,47 @@ +package ru.fusionsoft.dbgit.integration.primitives.chars.specific.test; + +import java.util.concurrent.atomic.AtomicBoolean; +import org.junit.platform.commons.util.ExceptionUtils; +import ru.fusionsoft.dbgit.integration.primitives.Test; +import ru.fusionsoft.dbgit.integration.primitives.chars.CharSequenceEnvelope; +import ru.fusionsoft.dbgit.integration.primitives.chars.CharsOf; +import ru.fusionsoft.dbgit.integration.primitives.chars.CharsOfConsoleWhenRunning; +import ru.fusionsoft.dbgit.integration.primitives.chars.CharsWithMaskedCredentials; + +public class ReportOfTestRun extends CharSequenceEnvelope { + public ReportOfTestRun(Subj subject, Test test) { + super(() -> { + return new CharsWithMaskedCredentials(new CharsOf(() -> { + + try { + final CharSequence subjDetails = String.valueOf(new CharsOfConsoleWhenRunning(subject::toString)); + try { + final AtomicBoolean value = new AtomicBoolean(false); + final CharSequence testDetails = String.valueOf(new CharsOfConsoleWhenRunning(()-> value.set(test.value(subject)))); + final LabelOfTestRun label = new LabelOfTestRunResult(value.get()); + return new ReportOfTestFormat( + label, + test.description(), + subjDetails, + testDetails + ); + } catch (Throwable testThrowable) { + return new ReportOfTestFormat( + new LabelOfTestRunExceptional(), + test.description(), + ExceptionUtils.readStackTrace(testThrowable) + ); + } + } catch (CharsOfConsoleWhenRunning.CharsOfConsoleWhenRunningException e) { + return new ReportOfTestFormat( + new LabelOfTestRunBrokenSubject(), + test.description(), + e.getMessage(), + ExceptionUtils.readStackTrace(e.getCause().getCause()) + ); + } + + })); + }); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/credentials/CredentialsEnvelope.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/credentials/CredentialsEnvelope.java new file mode 100644 index 0000000..638e961 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/credentials/CredentialsEnvelope.java @@ -0,0 +1,25 @@ +package ru.fusionsoft.dbgit.integration.primitives.credentials; + +import ru.fusionsoft.dbgit.integration.primitives.Credentials; +import ru.fusionsoft.dbgit.integration.primitives.SafeScalar; +import ru.fusionsoft.dbgit.integration.primitives.SafeScalarOf; +import ru.fusionsoft.dbgit.integration.primitives.Scalar; +import ru.fusionsoft.dbgit.integration.primitives.StickyScalar; + +public class CredentialsEnvelope implements Credentials { + private final SafeScalar credentialsScalar; + + public CredentialsEnvelope(Scalar credentialsScalar) { + this.credentialsScalar = new SafeScalarOf<>(new StickyScalar<>(credentialsScalar)); + } + + @Override + public final String username() { + return this.credentialsScalar.value().username(); + } + + @Override + public final String password() { + return this.credentialsScalar.value().password(); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/credentials/CredentialsFromFile.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/credentials/CredentialsFromFile.java new file mode 100644 index 0000000..8c30ded --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/credentials/CredentialsFromFile.java @@ -0,0 +1,19 @@ +package ru.fusionsoft.dbgit.integration.primitives.credentials; + +import java.nio.file.Path; +import ru.fusionsoft.dbgit.integration.primitives.files.FileContent; + +public class CredentialsFromFile extends CredentialsEnvelope { + + public CredentialsFromFile(Path secretFilePath) { + super(()-> { + final String[] lines = new FileContent(secretFilePath) + .text() + .split("\n"); + return new SimpleCredentials( + lines[0].trim(), + lines[1].trim() + ); + }); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/credentials/CredentialsFromProperties.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/credentials/CredentialsFromProperties.java new file mode 100644 index 0000000..077be9b --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/credentials/CredentialsFromProperties.java @@ -0,0 +1,14 @@ +package ru.fusionsoft.dbgit.integration.primitives.credentials; + +public class CredentialsFromProperties extends CredentialsEnvelope { + public CredentialsFromProperties(String usrPropName, String pwdPropName) { + super(()-> { + final String usrValue = System.getProperty(usrPropName); + final String pwdValue = System.getProperty(pwdPropName); + if (usrValue == null || usrValue.isEmpty() || pwdValue == null || pwdValue.isEmpty()) { + throw new Exception("Could not obtain credentials from props"); + } + return new SimpleCredentials(usrValue, pwdValue); + }); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/credentials/SimpleCredentials.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/credentials/SimpleCredentials.java new file mode 100644 index 0000000..bdd2006 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/credentials/SimpleCredentials.java @@ -0,0 +1,24 @@ +package ru.fusionsoft.dbgit.integration.primitives.credentials; + +import ru.fusionsoft.dbgit.integration.primitives.Credentials; + +public class SimpleCredentials implements Credentials { + + private final String username; + private final String password; + + public SimpleCredentials(String username, String password) { + this.username = username; + this.password = password; + } + + @Override + public final String username() { + return this.username; + } + + @Override + public final String password() { + return this.password; + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/credentials/specific/CredsFromGitMvnDProps.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/credentials/specific/CredsFromGitMvnDProps.java new file mode 100644 index 0000000..98ac81c --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/credentials/specific/CredsFromGitMvnDProps.java @@ -0,0 +1,9 @@ +package ru.fusionsoft.dbgit.integration.primitives.credentials.specific; + +import ru.fusionsoft.dbgit.integration.primitives.credentials.CredentialsFromProperties; + +public class CredsFromGitMvnDProps extends CredentialsFromProperties { + public CredsFromGitMvnDProps() { + super("gitUser", "gitPass"); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/credentials/specific/CredsFromGitSecretFile.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/credentials/specific/CredsFromGitSecretFile.java new file mode 100644 index 0000000..a265b83 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/credentials/specific/CredsFromGitSecretFile.java @@ -0,0 +1,10 @@ +package ru.fusionsoft.dbgit.integration.primitives.credentials.specific; + +import ru.fusionsoft.dbgit.integration.primitives.credentials.CredentialsFromFile; +import ru.fusionsoft.dbgit.integration.primitives.path.specific.CurrentWorkingDirectory; + +public class CredsFromGitSecretFile extends CredentialsFromFile { + public CredsFromGitSecretFile() { + super(new CurrentWorkingDirectory().resolve("../gitSecret.txt")); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/credentials/specific/CredsFromPgMvnDProps.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/credentials/specific/CredsFromPgMvnDProps.java new file mode 100644 index 0000000..389ae9a --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/credentials/specific/CredsFromPgMvnDProps.java @@ -0,0 +1,9 @@ +package ru.fusionsoft.dbgit.integration.primitives.credentials.specific; + +import ru.fusionsoft.dbgit.integration.primitives.credentials.CredentialsFromProperties; + +public class CredsFromPgMvnDProps extends CredentialsFromProperties { + public CredsFromPgMvnDProps() { + super("pgUser", "pgPass"); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/credentials/specific/CredsFromPgSecretFile.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/credentials/specific/CredsFromPgSecretFile.java new file mode 100644 index 0000000..51ba303 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/credentials/specific/CredsFromPgSecretFile.java @@ -0,0 +1,10 @@ +package ru.fusionsoft.dbgit.integration.primitives.credentials.specific; + +import ru.fusionsoft.dbgit.integration.primitives.credentials.CredentialsFromFile; +import ru.fusionsoft.dbgit.integration.primitives.path.specific.CurrentWorkingDirectory; + +public class CredsFromPgSecretFile extends CredentialsFromFile { + public CredsFromPgSecretFile() { + super(new CurrentWorkingDirectory().resolve("../pgSecret.txt")); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/credentials/specific/CredsOfGitTestRepo.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/credentials/specific/CredsOfGitTestRepo.java new file mode 100644 index 0000000..c81dc57 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/credentials/specific/CredsOfGitTestRepo.java @@ -0,0 +1,25 @@ +package ru.fusionsoft.dbgit.integration.primitives.credentials.specific; + +import ru.fusionsoft.dbgit.integration.primitives.Credentials; +import ru.fusionsoft.dbgit.integration.primitives.credentials.CredentialsEnvelope; +import ru.fusionsoft.dbgit.integration.primitives.credentials.SimpleCredentials; + +public class CredsOfGitTestRepo extends CredentialsEnvelope { + public CredsOfGitTestRepo() { + super(() -> { + try { + final Credentials creds = new CredsFromGitMvnDProps(); + return new SimpleCredentials( + creds.username(), + creds.password() + ); + } catch (Throwable e) { + final Credentials creds = new CredsFromGitSecretFile(); + return new SimpleCredentials( + creds.username(), + creds.password() + ); + } + }); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/credentials/specific/CredsOfPgTestDatabase.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/credentials/specific/CredsOfPgTestDatabase.java new file mode 100644 index 0000000..334b1ac --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/credentials/specific/CredsOfPgTestDatabase.java @@ -0,0 +1,25 @@ +package ru.fusionsoft.dbgit.integration.primitives.credentials.specific; + +import ru.fusionsoft.dbgit.integration.primitives.Credentials; +import ru.fusionsoft.dbgit.integration.primitives.credentials.CredentialsEnvelope; +import ru.fusionsoft.dbgit.integration.primitives.credentials.SimpleCredentials; + +public class CredsOfPgTestDatabase extends CredentialsEnvelope { + public CredsOfPgTestDatabase() { + super(() -> { + try { + final Credentials creds = new CredsFromPgMvnDProps(); + return new SimpleCredentials( + creds.username(), + creds.password() + ); + } catch (Throwable e) { + final Credentials creds = new CredsFromPgSecretFile(); + return new SimpleCredentials( + creds.username(), + creds.password() + ); + } + }); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/files/AutoDeletingTempFilePath.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/files/AutoDeletingTempFilePath.java new file mode 100644 index 0000000..9fabb1d --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/files/AutoDeletingTempFilePath.java @@ -0,0 +1,33 @@ +package ru.fusionsoft.dbgit.integration.primitives.files; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Random; +import ru.fusionsoft.dbgit.integration.primitives.chars.CharsOf; +import ru.fusionsoft.dbgit.integration.primitives.path.PathEnvelope; + +public class AutoDeletingTempFilePath extends PathEnvelope implements AutoCloseable { + + public AutoDeletingTempFilePath(CharSequence fileName) { + super(()-> Paths.get(String.valueOf(fileName))); + } + public AutoDeletingTempFilePath(Path directory, CharSequence prefix) { + this( + new CharsOf<>( ()-> { + return directory.resolve( + prefix + + String.format("#%06x", new Random().nextInt(256 * 256 * 256)) + ) + .toAbsolutePath() + .toString(); + }) + ); + } + + @Override + public final void close() throws IOException { + Files.deleteIfExists(this.toFile().toPath()); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/files/DbGitMetaFiles.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/files/DbGitMetaFiles.java new file mode 100644 index 0000000..61ebac4 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/files/DbGitMetaFiles.java @@ -0,0 +1,47 @@ +package ru.fusionsoft.dbgit.integration.primitives.files; + + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class DbGitMetaFiles implements TextResourceGroup { + private final Path workingDirectory; + + public DbGitMetaFiles(Path workingDirectory) { + this.workingDirectory = workingDirectory; + } + + @Override + public final void add(String name, String content) throws IOException { + new FileContent(this.workingDirectory, name).updateText(content); + } + + @Override + public final void clean() throws IOException { + for (TextResource textFile : this.all().values()) { + textFile.delete(); + } + } + + @Override + public final TextResource file(String... name){ + return new FileContent(this.workingDirectory, name); +} + + @Override + public final Map all() throws IOException { + try (Stream paths = Files.walk(this.workingDirectory.resolve(".dbgit"))) { + return paths + .filter( x->x.getParent().getParent().toFile().getName().equals(".dbgit") ) + .filter(Files::isRegularFile ) + .peek(System.out::println) + .collect(Collectors.toMap( x->x.toFile().getName(), FileContent::new) ); + } + } + + +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/files/FileContent.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/files/FileContent.java new file mode 100644 index 0000000..d9edd6d --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/files/FileContent.java @@ -0,0 +1,43 @@ +package ru.fusionsoft.dbgit.integration.primitives.files; + +import org.apache.commons.io.FileUtils; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; + +public class FileContent implements TextResource { + private final File file; + + public FileContent(final File file) { + this.file = file; + } + + public FileContent(final Path path) { + this(path.toFile()); + } + + public FileContent(final Path workingDirectory, final String... name) { + this(workingDirectory.resolve(String.join("//", name))); + } + + @Override + public final String text() throws IOException { + return FileUtils.readFileToString(this.file); + } + + @Override + public final TextResource updateText(final String content) throws IOException { + this.file.getParentFile().mkdirs(); + FileUtils.writeStringToFile(this.file, content); + return this; + } + + @Override + public final TextResource delete() throws IOException { + if (this.file.exists()) { + FileUtils.forceDelete(this.file); + } + return this; + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/files/TextFileTest.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/files/TextFileTest.java new file mode 100644 index 0000000..c148387 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/files/TextFileTest.java @@ -0,0 +1,56 @@ +package ru.fusionsoft.dbgit.integration.primitives.files; + +import org.apache.commons.io.FileUtils; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import ru.fusionsoft.dbgit.integration.primitives.path.specific.CurrentWorkingDirectory; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; + +public class TextFileTest { + + private final Path path; + + public TextFileTest(Path path) { + this.path = path; + } + + public TextFileTest() { + this(new CurrentWorkingDirectory()); + } + + @Test + public void createsFile() throws IOException { + String relativePath = ".dbgit/.dblink"; + + Assertions.assertEquals( + new FileContent(this.path, relativePath) + .updateText("ABC") + .text(), + + FileUtils.readFileToString( + this.path.resolve(relativePath).toFile() + ) + ); + } + + @Test + public void updatesContent() throws IOException { + File file = this.path.resolve("file").toFile(); + String content = "CBD"; + + new FileContent(file).updateText(content); + + Assertions.assertEquals( + content, + FileUtils.readFileToString(file) + ); + } + + @Test + public void pathTest() { + System.out.println(); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/files/TextResource.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/files/TextResource.java new file mode 100644 index 0000000..a7f16fb --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/files/TextResource.java @@ -0,0 +1,11 @@ +package ru.fusionsoft.dbgit.integration.primitives.files; + + +import java.io.IOException; + +public interface TextResource { + String text() throws IOException; + TextResource updateText(String content) throws IOException; + TextResource delete() throws IOException; + +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/files/TextResourceGroup.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/files/TextResourceGroup.java new file mode 100644 index 0000000..cbf5b88 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/files/TextResourceGroup.java @@ -0,0 +1,11 @@ +package ru.fusionsoft.dbgit.integration.primitives.files; + +import java.io.IOException; +import java.util.Map; + +public interface TextResourceGroup { + void add(String name, String content) throws IOException; + void clean() throws IOException; + TextResource file(String... name); + Map all() throws IOException; +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/PathPatchAssertsNotMvnProjectRoot.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/PathPatchAssertsNotMvnProjectRoot.java new file mode 100644 index 0000000..f351279 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/PathPatchAssertsNotMvnProjectRoot.java @@ -0,0 +1,26 @@ +package ru.fusionsoft.dbgit.integration.primitives.patch; + +import java.nio.file.Path; +import ru.fusionsoft.dbgit.integration.primitives.Patch; + +public class PathPatchAssertsNotMvnProjectRoot implements Patch { + @Override + public final void apply(Path root) throws Exception { + if ( + root.resolve(".git").toFile().exists() && + root.resolve("pom.xml").toFile().exists() + ) { + throw new PathIsProjectRootException(root); + } + } + + private static class PathIsProjectRootException extends RuntimeException { + PathIsProjectRootException(Path path) { + super( + "\nGiven path " + path.toString() + " " + + "points to a project root directory.\n" + + "I'm here not to allow that." + ); + } + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/PathPatchCloningGitRepo.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/PathPatchCloningGitRepo.java new file mode 100644 index 0000000..a58c5f9 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/PathPatchCloningGitRepo.java @@ -0,0 +1,38 @@ +package ru.fusionsoft.dbgit.integration.primitives.patch; + +import java.io.PrintStream; +import java.nio.file.Path; +import ru.fusionsoft.dbgit.integration.primitives.printstream.DefaultPrintStream; +import ru.fusionsoft.dbgit.integration.primitives.PatchSequential; +import ru.fusionsoft.dbgit.integration.primitives.args.ArgsExplicit; + +public class PathPatchCloningGitRepo extends PatchSequential { + + public PathPatchCloningGitRepo(final String repoUrl, final String branchName, PrintStream printStream) { + super( + new PathPatchRunningExecutable( + "git", + new ArgsExplicit( + "clone", + repoUrl, + "." + ), + printStream + ), + new PathPatchRunningExecutable( + "git", + new ArgsExplicit( + "reset", + "--hard", + branchName + ), + printStream + ) + + ); + } + + public PathPatchCloningGitRepo(final String repoUrl, final String branchName) { + this(repoUrl, branchName, new DefaultPrintStream()); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/PathPatchConfiguringDbGit.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/PathPatchConfiguringDbGit.java new file mode 100644 index 0000000..9979cc3 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/PathPatchConfiguringDbGit.java @@ -0,0 +1,18 @@ +package ru.fusionsoft.dbgit.integration.primitives.patch; + +import java.nio.file.Path; +import ru.fusionsoft.dbgit.integration.primitives.PatchSequential; + +public class PathPatchConfiguringDbGit extends PatchSequential { + + public PathPatchConfiguringDbGit(final String linkContent, final String ignoreContent, final String configContent, final String indexContent) { + super( + new PathPatchCreatingFile(".dbgit/.dblink", linkContent), + new PathPatchCreatingFile(".dbgit/.dbignore", ignoreContent), + new PathPatchCreatingFile(".dbgit/.dbindex", indexContent), + new PathPatchCreatingFile(".dbgit/dbgitconfig", configContent) + ); + + } + +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/PathPatchCreatingFile.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/PathPatchCreatingFile.java new file mode 100644 index 0000000..f77e472 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/PathPatchCreatingFile.java @@ -0,0 +1,41 @@ +package ru.fusionsoft.dbgit.integration.primitives.patch; + +import java.io.File; +import java.io.PrintStream; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.stream.Collectors; +import org.apache.commons.io.FileUtils; +import ru.fusionsoft.dbgit.integration.primitives.chars.CharsOfPathWithComment; +import ru.fusionsoft.dbgit.integration.primitives.printstream.DefaultPrintStream; + +public class PathPatchCreatingFile extends PathPatchWithPrintStream { + private final String name; + private final String content; + + public PathPatchCreatingFile(final String name, final CharSequence content, PrintStream printStream) { + super(printStream); + this.name = name; + this.content = String.valueOf(content); + } + + public PathPatchCreatingFile(final String name, final CharSequence content) { + this(name, content, new DefaultPrintStream()); + } + + @Override + public final void apply(final Path root) throws Exception { + this.printStream.println( + new CharsOfPathWithComment( + root, + "writing file " + name + " with content:\n" + + Arrays.stream(content.split("\n")) + .map( x-> "> " + x) + .collect(Collectors.joining(System.getProperty("line.separator"))) + ) + ); + final File file = root.resolve(this.name).toFile(); + file.getParentFile().mkdirs(); + FileUtils.writeStringToFile(file, this.content); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/PathPatchDeletingFiles.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/PathPatchDeletingFiles.java new file mode 100644 index 0000000..5400d90 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/PathPatchDeletingFiles.java @@ -0,0 +1,30 @@ +package ru.fusionsoft.dbgit.integration.primitives.patch; + +import java.io.File; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.Collection; +import org.apache.commons.io.FileUtils; +import ru.fusionsoft.dbgit.integration.primitives.Patch; + +public class PathPatchDeletingFiles implements Patch { + private final Collection names; + + private PathPatchDeletingFiles(Collection names) { + this.names = names; + } + + public PathPatchDeletingFiles(String... names) { + this(Arrays.asList(names)); + } + + @Override + public final void apply(Path root) throws Exception { + for (String name : this.names) { + final File file = root.resolve(name).toFile(); + if (file.exists()) { + FileUtils.forceDelete(file); + } + } + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/PathPatchDeletingFilesWildcard.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/PathPatchDeletingFilesWildcard.java new file mode 100644 index 0000000..aee125f --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/PathPatchDeletingFilesWildcard.java @@ -0,0 +1,26 @@ +package ru.fusionsoft.dbgit.integration.primitives.patch; + +import java.io.File; +import java.io.FileFilter; +import java.io.FilenameFilter; +import java.nio.file.Path; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.filefilter.WildcardFileFilter; +import ru.fusionsoft.dbgit.integration.primitives.Patch; + +public class PathPatchDeletingFilesWildcard implements Patch { + private final FileFilter wildcardFileFilter; + + public PathPatchDeletingFilesWildcard(String mask) { + this.wildcardFileFilter = new WildcardFileFilter(mask); + } + + @Override + public final void apply(Path root) throws Exception { + final File[] files = root.toFile().listFiles((FilenameFilter) wildcardFileFilter); + if(files != null) + for (final File file : files) { + FileUtils.forceDelete(file); + } + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/PathPatchRunningDbGit.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/PathPatchRunningDbGit.java new file mode 100644 index 0000000..50a0a90 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/PathPatchRunningDbGit.java @@ -0,0 +1,42 @@ +package ru.fusionsoft.dbgit.integration.primitives.patch; + +import java.io.PrintStream; +import java.nio.file.Path; +import ru.fusionsoft.dbgit.integration.primitives.Args; +import ru.fusionsoft.dbgit.integration.primitives.args.ArgsRunningCommand; +import ru.fusionsoft.dbgit.integration.primitives.args.ArgsWithAppend; +import ru.fusionsoft.dbgit.integration.primitives.path.specific.dbgit.PathOfBuiltDbGitExecutable; +import ru.fusionsoft.dbgit.integration.primitives.path.specific.CurrentWorkingDirectory; +import ru.fusionsoft.dbgit.integration.primitives.printstream.DefaultPrintStream; + +public class PathPatchRunningDbGit extends PathPatchRunningProcessFrom { + public PathPatchRunningDbGit(Args args, Path executablePath, PrintStream printStream) { + super( + new ArgsWithAppend( + new ArgsRunningCommand(executablePath), + args + ), + printStream + ); + } + + public PathPatchRunningDbGit(Args args, Path executablePath) { + this( + args, + executablePath, + System.out + ); + } + + public PathPatchRunningDbGit(Args args, PrintStream printStream) { + this( + args, + new PathOfBuiltDbGitExecutable(new CurrentWorkingDirectory()), + printStream + ); + } + + public PathPatchRunningDbGit(Args args) { + this(args, new DefaultPrintStream()); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/PathPatchRunningExecutable.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/PathPatchRunningExecutable.java new file mode 100644 index 0000000..9a38764 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/PathPatchRunningExecutable.java @@ -0,0 +1,21 @@ +package ru.fusionsoft.dbgit.integration.primitives.patch; + +import java.io.PrintStream; +import java.nio.file.Path; +import ru.fusionsoft.dbgit.integration.primitives.Args; +import ru.fusionsoft.dbgit.integration.primitives.args.ArgsRunningCommand; +import ru.fusionsoft.dbgit.integration.primitives.args.ArgsWithAppend; + +public class PathPatchRunningExecutable extends PathPatchRunningProcessFrom { + + public PathPatchRunningExecutable(CharSequence commandName, Args commandArgs, PrintStream printStream) { + super( + new ArgsWithAppend( + new ArgsRunningCommand(commandName), + commandArgs + ), + printStream + ); + } + +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/PathPatchRunningGit.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/PathPatchRunningGit.java new file mode 100644 index 0000000..c64f90e --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/PathPatchRunningGit.java @@ -0,0 +1,25 @@ +package ru.fusionsoft.dbgit.integration.primitives.patch; + +import java.io.PrintStream; +import ru.fusionsoft.dbgit.integration.primitives.Args; +import ru.fusionsoft.dbgit.integration.primitives.args.ArgsExplicit; +import ru.fusionsoft.dbgit.integration.primitives.printstream.DefaultPrintStream; + +public class PathPatchRunningGit extends PathPatchRunningExecutable { + public PathPatchRunningGit(Args gitArgs, PrintStream printStream) { + super( + "git", + gitArgs, + printStream + ); + } + + public PathPatchRunningGit(Args gitArgs) { + this(gitArgs, new DefaultPrintStream()); + } + + public PathPatchRunningGit(CharSequence... gitArgs) { + this(new ArgsExplicit(gitArgs)); + } +} + diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/PathPatchRunningProcessFrom.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/PathPatchRunningProcessFrom.java new file mode 100644 index 0000000..7dc91fa --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/PathPatchRunningProcessFrom.java @@ -0,0 +1,71 @@ +package ru.fusionsoft.dbgit.integration.primitives.patch; + +import java.io.PrintStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.text.MessageFormat; +import java.util.Arrays; +import java.util.List; +import java.util.function.Consumer; +import java.util.stream.Collectors; +import ru.fusionsoft.dbgit.integration.primitives.Args; +import ru.fusionsoft.dbgit.integration.primitives.Patch; +import ru.fusionsoft.dbgit.integration.primitives.chars.CharsOf; +import ru.fusionsoft.dbgit.integration.primitives.chars.CharsOfLines; +import ru.fusionsoft.dbgit.integration.primitives.files.AutoDeletingTempFilePath; + +public class PathPatchRunningProcessFrom implements Patch { + + private final Args processRunCommandLine; + private final PrintStream printStream; + + public PathPatchRunningProcessFrom(Args processRunCommandLine, PrintStream printStream) { + this.processRunCommandLine = processRunCommandLine; + this.printStream = printStream; + } + + @Override + public final void apply(Path workingDirectory) throws Exception { + final Consumer outputConsumer = printStream::println; + outputConsumer.accept(MessageFormat.format( + "{0} # {1}", + workingDirectory.toString(), + String.join(" ", processRunCommandLine.values()) + )); + + try ( + final AutoDeletingTempFilePath tempOutPath = new AutoDeletingTempFilePath(workingDirectory.resolve("../"), "out"); + final AutoDeletingTempFilePath tempErrPath = new AutoDeletingTempFilePath(workingDirectory.resolve("../"), "err"); + ) { + + final Process process = new ProcessBuilder() + .directory(workingDirectory.toFile()) + .command( + Arrays.stream(processRunCommandLine.values()) + .map(String::valueOf) + .collect(Collectors.toList()) + ) + .redirectOutput(tempOutPath.toFile()) + .redirectError(tempErrPath.toFile()) + .start(); + process.getOutputStream().close(); + + final int exitCode = process.waitFor(); + outputConsumer.accept(new CharsOfLines(Files.readAllLines(tempOutPath.toFile().toPath()), "\n", "> ")); + + if (exitCode != 0) { + throw new Exception(MessageFormat.format( + "Process exited with error, code {0}\nErrors: {1}", + exitCode, + new CharsOf<>(()->{ + final List lines = Files.readAllLines(tempErrPath.toFile().toPath()); + return lines.isEmpty() + ? "...error stream was empty" + : new CharsOfLines(lines, "", "\n> "); + }) + )); + } + + } + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/PathPatchWithPrintStream.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/PathPatchWithPrintStream.java new file mode 100644 index 0000000..12d4586 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/PathPatchWithPrintStream.java @@ -0,0 +1,13 @@ +package ru.fusionsoft.dbgit.integration.primitives.patch; + +import java.io.PrintStream; +import java.nio.file.Path; +import ru.fusionsoft.dbgit.integration.primitives.Patch; + +public abstract class PathPatchWithPrintStream implements Patch { + protected final PrintStream printStream; + + public PathPatchWithPrintStream(PrintStream printStream) { + this.printStream = printStream; + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/specific/PathPatchDbGitAdd.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/specific/PathPatchDbGitAdd.java new file mode 100644 index 0000000..b4ac2cd --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/specific/PathPatchDbGitAdd.java @@ -0,0 +1,21 @@ +package ru.fusionsoft.dbgit.integration.primitives.patch.specific; + +import java.io.PrintStream; +import ru.fusionsoft.dbgit.integration.primitives.args.specific.ArgsDbGitAdd; +import ru.fusionsoft.dbgit.integration.primitives.patch.PathPatchRunningDbGit; +import ru.fusionsoft.dbgit.integration.primitives.printstream.DefaultPrintStream; + +public class PathPatchDbGitAdd extends PathPatchRunningDbGit { + public PathPatchDbGitAdd(CharSequence mask, PrintStream printStream) { + super(new ArgsDbGitAdd(mask), printStream); + } + public PathPatchDbGitAdd(PrintStream printStream) { + super(new ArgsDbGitAdd(), printStream); + } + public PathPatchDbGitAdd(CharSequence mask) { + this(mask, new DefaultPrintStream()); + } + public PathPatchDbGitAdd() { + this(new DefaultPrintStream()); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/specific/PathPatchDbGitCheckout.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/specific/PathPatchDbGitCheckout.java new file mode 100644 index 0000000..6e76963 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/specific/PathPatchDbGitCheckout.java @@ -0,0 +1,18 @@ +package ru.fusionsoft.dbgit.integration.primitives.patch.specific; + +import java.io.PrintStream; +import ru.fusionsoft.dbgit.integration.primitives.printstream.DefaultPrintStream; +import ru.fusionsoft.dbgit.integration.primitives.args.specific.ArgsDbGitCheckout; +import ru.fusionsoft.dbgit.integration.primitives.patch.PathPatchRunningDbGit; + +public class PathPatchDbGitCheckout extends PathPatchRunningDbGit { + public PathPatchDbGitCheckout(ArgsDbGitCheckout args, PrintStream printStream) { + super(args, printStream); + } + public PathPatchDbGitCheckout(ArgsDbGitCheckout args) { + this(args, new DefaultPrintStream()); + } + public PathPatchDbGitCheckout(CharSequence... args) { + this(new ArgsDbGitCheckout(args)); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/specific/PathPatchDbGitCheckoutHard.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/specific/PathPatchDbGitCheckoutHard.java new file mode 100644 index 0000000..502985a --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/specific/PathPatchDbGitCheckoutHard.java @@ -0,0 +1,22 @@ +package ru.fusionsoft.dbgit.integration.primitives.patch.specific; + +import java.io.PrintStream; +import java.nio.file.Path; +import ru.fusionsoft.dbgit.integration.primitives.PatchSequential; +import ru.fusionsoft.dbgit.integration.primitives.args.specific.ArgsDbGitCheckout; + +public class PathPatchDbGitCheckoutHard extends PatchSequential { + public PathPatchDbGitCheckoutHard(ArgsDbGitCheckout argsDbGitCheckout, PrintStream printStream) { + super( + new PathPatchDbGitReset("-hard"), + new PathPatchDbGitCheckout(argsDbGitCheckout, printStream) + ); + } + + public PathPatchDbGitCheckoutHard(CharSequence... checkoutArgs) { + super( + new PathPatchDbGitReset("-hard"), + new PathPatchDbGitCheckout(new ArgsDbGitCheckout(checkoutArgs)) + ); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/specific/PathPatchDbGitCheckoutReset.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/specific/PathPatchDbGitCheckoutReset.java new file mode 100644 index 0000000..ad63502 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/specific/PathPatchDbGitCheckoutReset.java @@ -0,0 +1,25 @@ +package ru.fusionsoft.dbgit.integration.primitives.patch.specific; + +import java.io.PrintStream; +import java.nio.file.Path; +import ru.fusionsoft.dbgit.integration.primitives.printstream.DefaultPrintStream; +import ru.fusionsoft.dbgit.integration.primitives.PatchSequential; +import ru.fusionsoft.dbgit.integration.primitives.args.specific.ArgsDbGitCheckout; + +public class PathPatchDbGitCheckoutReset extends PatchSequential { + public PathPatchDbGitCheckoutReset(ArgsDbGitCheckout checkoutArgs, PrintStream printStream) { + super( + new PathPatchDbGitCheckout(checkoutArgs, printStream), + new PathPatchDbGitReset("-hard") + ); + } + + public PathPatchDbGitCheckoutReset(ArgsDbGitCheckout checkoutArgs) { + this(checkoutArgs, new DefaultPrintStream()); + } + + public PathPatchDbGitCheckoutReset(CharSequence... checkoutParams) { + this(new ArgsDbGitCheckout(checkoutParams)); + } + +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/specific/PathPatchDbGitClonesRepo.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/specific/PathPatchDbGitClonesRepo.java new file mode 100644 index 0000000..776872f --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/specific/PathPatchDbGitClonesRepo.java @@ -0,0 +1,41 @@ +package ru.fusionsoft.dbgit.integration.primitives.patch.specific; + +import java.io.PrintStream; +import java.nio.file.Path; +import ru.fusionsoft.dbgit.integration.primitives.PatchSequential; +import ru.fusionsoft.dbgit.integration.primitives.args.specific.ArgsDbGitAddRemote; +import ru.fusionsoft.dbgit.integration.primitives.args.specific.ArgsDbGitClone; +import ru.fusionsoft.dbgit.integration.primitives.patch.PathPatchAssertsNotMvnProjectRoot; +import ru.fusionsoft.dbgit.integration.primitives.patch.PathPatchDeletingFilesWildcard; +import ru.fusionsoft.dbgit.integration.primitives.patch.PathPatchRunningDbGit; +import ru.fusionsoft.dbgit.integration.primitives.printstream.DefaultPrintStream; + +public class PathPatchDbGitClonesRepo extends PatchSequential { + public PathPatchDbGitClonesRepo(CharSequence repoUrl, ArgsDbGitAddRemote addRemoteArgs, PrintStream printStream) { + super( + new PathPatchAssertsNotMvnProjectRoot(), + new PathPatchDeletingFilesWildcard( + "*" + ), + new PathPatchRunningDbGit( + new ArgsDbGitClone(repoUrl), + printStream + ), + new PathPatchRunningDbGit( + addRemoteArgs, + printStream + ) + ); + } + public PathPatchDbGitClonesRepo(CharSequence repoUrl, PrintStream printStream) { + super( + new PathPatchRunningDbGit( + new ArgsDbGitClone(repoUrl), + printStream + ) + ); + } + public PathPatchDbGitClonesRepo(CharSequence repoUrl, ArgsDbGitAddRemote addRemoteArgs) { + this(repoUrl, addRemoteArgs, new DefaultPrintStream()); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/specific/PathPatchDbGitCommit.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/specific/PathPatchDbGitCommit.java new file mode 100644 index 0000000..008a4b6 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/specific/PathPatchDbGitCommit.java @@ -0,0 +1,16 @@ +package ru.fusionsoft.dbgit.integration.primitives.patch.specific; + +import java.io.PrintStream; +import ru.fusionsoft.dbgit.integration.primitives.printstream.DefaultPrintStream; +import ru.fusionsoft.dbgit.integration.primitives.args.ArgsExplicit; +import ru.fusionsoft.dbgit.integration.primitives.patch.PathPatchRunningDbGit; + +public class PathPatchDbGitCommit extends PathPatchRunningDbGit { + public PathPatchDbGitCommit(CharSequence message, PrintStream printStream) { + super(new ArgsExplicit("commit", "-m", message), printStream); + } + + public PathPatchDbGitCommit(CharSequence message) { + this(message, new DefaultPrintStream()); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/specific/PathPatchDbGitInitializesRepo.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/specific/PathPatchDbGitInitializesRepo.java new file mode 100644 index 0000000..8df7145 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/specific/PathPatchDbGitInitializesRepo.java @@ -0,0 +1,38 @@ +package ru.fusionsoft.dbgit.integration.primitives.patch.specific; + +import java.io.PrintStream; +import java.nio.file.Path; +import ru.fusionsoft.dbgit.integration.primitives.PatchSequential; +import ru.fusionsoft.dbgit.integration.primitives.args.specific.ArgsDbGitInit; +import ru.fusionsoft.dbgit.integration.primitives.args.specific.ArgsDbGitLink; +import ru.fusionsoft.dbgit.integration.primitives.patch.PathPatchAssertsNotMvnProjectRoot; +import ru.fusionsoft.dbgit.integration.primitives.patch.PathPatchDeletingFilesWildcard; +import ru.fusionsoft.dbgit.integration.primitives.patch.PathPatchRunningDbGit; +import ru.fusionsoft.dbgit.integration.primitives.printstream.DefaultPrintStream; + +public class PathPatchDbGitInitializesRepo extends PatchSequential { + public PathPatchDbGitInitializesRepo(ArgsDbGitLink linkArgs, PrintStream printStream) { + super( + new PathPatchAssertsNotMvnProjectRoot(), + new PathPatchDeletingFilesWildcard("*"), + new PathPatchRunningDbGit(new ArgsDbGitInit(), printStream), + new PathPatchRunningDbGit(linkArgs, printStream) + ); + } + + public PathPatchDbGitInitializesRepo(PrintStream printStream) { + super( + new PathPatchAssertsNotMvnProjectRoot(), + new PathPatchDeletingFilesWildcard("*"), + new PathPatchRunningDbGit(new ArgsDbGitInit(), printStream) + ); + } + + public PathPatchDbGitInitializesRepo(ArgsDbGitLink linkArgs) { + this(linkArgs, new DefaultPrintStream()); + } + + public PathPatchDbGitInitializesRepo() { + this(new DefaultPrintStream()); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/specific/PathPatchDbGitLink.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/specific/PathPatchDbGitLink.java new file mode 100644 index 0000000..4b44990 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/specific/PathPatchDbGitLink.java @@ -0,0 +1,17 @@ +package ru.fusionsoft.dbgit.integration.primitives.patch.specific; + +import java.io.PrintStream; +import ru.fusionsoft.dbgit.integration.primitives.printstream.DefaultPrintStream; +import ru.fusionsoft.dbgit.integration.primitives.args.specific.ArgsDbGitLink; +import ru.fusionsoft.dbgit.integration.primitives.patch.PathPatchRunningDbGit; + +public class PathPatchDbGitLink extends PathPatchRunningDbGit { + + public PathPatchDbGitLink(ArgsDbGitLink args, PrintStream printStream) { + super(args, printStream); + } + + public PathPatchDbGitLink(ArgsDbGitLink args) { + this(args, new DefaultPrintStream()); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/specific/PathPatchDbGitReset.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/specific/PathPatchDbGitReset.java new file mode 100644 index 0000000..1faf9f6 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/specific/PathPatchDbGitReset.java @@ -0,0 +1,20 @@ +package ru.fusionsoft.dbgit.integration.primitives.patch.specific; + +import java.io.PrintStream; +import ru.fusionsoft.dbgit.integration.primitives.printstream.DefaultPrintStream; +import ru.fusionsoft.dbgit.integration.primitives.args.specific.ArgsDbGitReset; +import ru.fusionsoft.dbgit.integration.primitives.patch.PathPatchRunningDbGit; + +public class PathPatchDbGitReset extends PathPatchRunningDbGit { + public PathPatchDbGitReset(CharSequence resetMode, PrintStream printStream) { + super(new ArgsDbGitReset(resetMode), printStream); + } + + public PathPatchDbGitReset(CharSequence resetMode) { + this(resetMode, new DefaultPrintStream()); + } + + public PathPatchDbGitReset() { + this("hard", new DefaultPrintStream()); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/specific/PathPatchDbGitRestore.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/specific/PathPatchDbGitRestore.java new file mode 100644 index 0000000..b750867 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/specific/PathPatchDbGitRestore.java @@ -0,0 +1,20 @@ +package ru.fusionsoft.dbgit.integration.primitives.patch.specific; + +import java.io.PrintStream; +import ru.fusionsoft.dbgit.integration.primitives.printstream.DefaultPrintStream; +import ru.fusionsoft.dbgit.integration.primitives.args.specific.ArgsDbGitRestore; +import ru.fusionsoft.dbgit.integration.primitives.patch.PathPatchRunningDbGit; + +public class PathPatchDbGitRestore extends PathPatchRunningDbGit { + public PathPatchDbGitRestore(ArgsDbGitRestore restoreArgs, PrintStream printStream) { + super(restoreArgs, printStream); + } + + public PathPatchDbGitRestore(ArgsDbGitRestore restoreArgs) { + this(restoreArgs, new DefaultPrintStream()); + } + + public PathPatchDbGitRestore(CharSequence... restoreCommandArgs) { + this(new ArgsDbGitRestore(restoreCommandArgs), new DefaultPrintStream()); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/specific/PathPatchGitCheckoutOrphan.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/specific/PathPatchGitCheckoutOrphan.java new file mode 100644 index 0000000..1301792 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/specific/PathPatchGitCheckoutOrphan.java @@ -0,0 +1,27 @@ +package ru.fusionsoft.dbgit.integration.primitives.patch.specific; + +import java.io.PrintStream; +import java.nio.file.Path; +import ru.fusionsoft.dbgit.integration.primitives.PatchSequential; +import ru.fusionsoft.dbgit.integration.primitives.args.ArgsExplicit; +import ru.fusionsoft.dbgit.integration.primitives.patch.PathPatchRunningGit; +import ru.fusionsoft.dbgit.integration.primitives.printstream.DefaultPrintStream; + +public class PathPatchGitCheckoutOrphan extends PatchSequential { + public PathPatchGitCheckoutOrphan(String newBranchName, PrintStream printStream) { + super( + new PathPatchRunningGit( + new ArgsExplicit("checkout", "--orphan", newBranchName), + printStream + ), + new PathPatchRunningGit( + new ArgsExplicit("rm", "-rf", "."), + printStream + ) + ); + } + + public PathPatchGitCheckoutOrphan(String newBranchName) { + this(newBranchName, new DefaultPrintStream()); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/PathAfterDbGitRun.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/PathAfterDbGitRun.java new file mode 100644 index 0000000..7597278 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/PathAfterDbGitRun.java @@ -0,0 +1,49 @@ +package ru.fusionsoft.dbgit.integration.primitives.path; + +import java.io.PrintStream; +import java.nio.file.Path; +import ru.fusionsoft.dbgit.integration.primitives.Args; +import ru.fusionsoft.dbgit.integration.primitives.path.specific.dbgit.PathOfBuiltDbGitExecutable; +import ru.fusionsoft.dbgit.integration.primitives.printstream.DefaultPrintStream; +import ru.fusionsoft.dbgit.integration.primitives.args.ArgsRunningCommand; +import ru.fusionsoft.dbgit.integration.primitives.args.ArgsWithAppend; +import ru.fusionsoft.dbgit.integration.primitives.path.specific.CurrentWorkingDirectory; + +public class PathAfterDbGitRun extends PathAfterProcessRun { + public PathAfterDbGitRun(Args args, Path executablePath, PrintStream printStream, Path workingDirectory) { + super( + new ArgsWithAppend( + new ArgsRunningCommand(executablePath), + args + ), + printStream, + workingDirectory + ); + } + + public PathAfterDbGitRun(Args args, PrintStream printStream, Path workingDirectory) { + this( + args, + new PathOfBuiltDbGitExecutable(new CurrentWorkingDirectory()), + printStream, + workingDirectory + ); + } + + public PathAfterDbGitRun(Args args, Path executablePath, Path workingDirectory) { + this( + args, + executablePath, + new DefaultPrintStream(), + workingDirectory + ); + } + + public PathAfterDbGitRun(Args args, Path workingDirectory) { + this( + args, + new PathOfBuiltDbGitExecutable(new CurrentWorkingDirectory()), + workingDirectory + ); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/PathAfterGitRun.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/PathAfterGitRun.java new file mode 100644 index 0000000..b396a77 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/PathAfterGitRun.java @@ -0,0 +1,21 @@ +package ru.fusionsoft.dbgit.integration.primitives.path; + +import java.io.PrintStream; +import java.nio.file.Path; +import ru.fusionsoft.dbgit.integration.primitives.Args; +import ru.fusionsoft.dbgit.integration.primitives.printstream.DefaultPrintStream; +import ru.fusionsoft.dbgit.integration.primitives.args.ArgsRunningCommand; +import ru.fusionsoft.dbgit.integration.primitives.args.ArgsWithAppend; + +public class PathAfterGitRun extends PathAfterProcessRun { + public PathAfterGitRun(Args gitArgs, PrintStream printStream, Path origin) { + super( + new ArgsWithAppend(new ArgsRunningCommand("git"), gitArgs), + printStream, + origin + ); + } + public PathAfterGitRun(Args gitArgs, Path origin) { + this(gitArgs, new DefaultPrintStream(), origin); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/PathAfterProcessRun.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/PathAfterProcessRun.java new file mode 100644 index 0000000..8ff963f --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/PathAfterProcessRun.java @@ -0,0 +1,15 @@ +package ru.fusionsoft.dbgit.integration.primitives.path; + +import java.io.PrintStream; +import java.nio.file.Path; +import ru.fusionsoft.dbgit.integration.primitives.Args; +import ru.fusionsoft.dbgit.integration.primitives.patch.PathPatchRunningProcessFrom; + +public class PathAfterProcessRun extends PathPatched { + public PathAfterProcessRun(Args processRunCommandLine, PrintStream printStream, Path origin) { + super( + origin, + new PathPatchRunningProcessFrom(processRunCommandLine, printStream) + ); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/PathEnvelope.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/PathEnvelope.java new file mode 100644 index 0000000..437eb2d --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/PathEnvelope.java @@ -0,0 +1,160 @@ +package ru.fusionsoft.dbgit.integration.primitives.path; + +import ru.fusionsoft.dbgit.integration.primitives.Scalar; +import ru.fusionsoft.dbgit.integration.primitives.StickyScalar; +import ru.fusionsoft.dbgit.integration.primitives.SafeScalar; +import ru.fusionsoft.dbgit.integration.primitives.SafeScalarOf; + +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.nio.file.*; +import java.util.Iterator; + +public abstract class PathEnvelope implements Path { + + private final SafeScalar origin; + + public PathEnvelope(Scalar origin) { + this.origin = new SafeScalarOf<>( + new StickyScalar<>( + origin + ) + ); + } + + @Override + public String toString() { + return this.origin.value().toString(); + } + + @Override + public final FileSystem getFileSystem() { + return this.origin.value().getFileSystem(); + } + + @Override + public final boolean isAbsolute() { + return this.origin.value().isAbsolute(); + } + + @Override + public final Path getRoot() { + return this.origin.value().getRoot(); + } + + @Override + public final Path getFileName() { + return this.origin.value().getFileName(); + } + + @Override + public final Path getParent() { + return this.origin.value().getParent(); + } + + @Override + public final int getNameCount() { + return this.origin.value().getNameCount(); + } + + @Override + public final Path getName(int i) { + return this.origin.value().getName(i); + } + + @Override + public final Path subpath(int i, int i1) { + return this.origin.value().subpath(i, i1); + } + + @Override + public final boolean startsWith(Path path) { + return this.origin.value().startsWith(path); + } + + @Override + public final boolean endsWith(Path path) { + return this.origin.value().endsWith(path); + } + + @Override + public final Path normalize() { + return this.origin.value().normalize(); + } + + @Override + public final Path resolve(Path path) { + return this.origin.value().resolve(path); + } + + @Override + public final Path relativize(Path path) { + return this.origin.value().relativize(path); + } + + @Override + public final URI toUri() { + return this.origin.value().toUri(); + } + + @Override + public final Path toAbsolutePath() { + return this.origin.value().toAbsolutePath(); + } + + @Override + public final Path toRealPath(LinkOption... linkOptions) throws IOException { + return this.origin.value().toRealPath(linkOptions); + } + + @Override + public final WatchKey register(WatchService watchService, WatchEvent.Kind[] kinds, WatchEvent.Modifier... modifiers) throws IOException { + return this.origin.value().register(watchService,kinds,modifiers); + } + + @Override + public final int compareTo(Path path) { + return this.origin.value().compareTo(path); + } + + @Override + public final Iterator iterator() { + return origin.value().iterator(); + } + + @Override + public final WatchKey register(WatchService watcher, WatchEvent.Kind... events) throws IOException { + return this.origin.value().register(watcher, events); + } + + @Override + public final boolean startsWith(String other) { + return this.origin.value().startsWith(other); + } + + @Override + public final boolean endsWith(String other) { + return this.origin.value().endsWith(other); + } + + @Override + public final Path resolve(String other) { + return this.origin.value().resolve(other); + } + + @Override + public final Path resolveSibling(Path other) { + return this.origin.value().resolveSibling(other); + } + + @Override + public final Path resolveSibling(String other) { + return this.origin.value().resolveSibling(other); + } + + @Override + public final File toFile() { + return this.origin.value().toFile(); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/PathNotProjectRoot.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/PathNotProjectRoot.java new file mode 100644 index 0000000..fbf43dc --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/PathNotProjectRoot.java @@ -0,0 +1,15 @@ +package ru.fusionsoft.dbgit.integration.primitives.path; + + +import java.nio.file.Path; +import ru.fusionsoft.dbgit.integration.primitives.patch.PathPatchAssertsNotMvnProjectRoot; + +public class PathNotProjectRoot extends PathPatched{ + public PathNotProjectRoot(Path origin) { + super(new PathPatchAssertsNotMvnProjectRoot(), origin); + } + + +} + + diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/PathOf.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/PathOf.java new file mode 100644 index 0000000..25beada --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/PathOf.java @@ -0,0 +1,15 @@ +package ru.fusionsoft.dbgit.integration.primitives.path; + +import java.nio.file.Path; +import ru.fusionsoft.dbgit.integration.primitives.Scalar; + +public class PathOf extends PathEnvelope { + + public PathOf(Scalar origin) { + super(origin); + } + + public PathOf(String path, Path origin) { + super(()->origin.resolve(path).toAbsolutePath()); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/PathPatched.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/PathPatched.java new file mode 100644 index 0000000..c202c5e --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/PathPatched.java @@ -0,0 +1,19 @@ +package ru.fusionsoft.dbgit.integration.primitives.path; + +import java.nio.file.Path; +import ru.fusionsoft.dbgit.integration.primitives.Patch; +import ru.fusionsoft.dbgit.integration.primitives.PatchedScalar; + +public class PathPatched extends PathEnvelope { + + public PathPatched(final Path origin, final Patch patch) { + super( + new PatchedScalar<>(origin, patch) + ); + } + public PathPatched(final Patch patch, final Path origin) { + super( + new PatchedScalar<>(origin, patch) + ); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/PathPrintsToConsole.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/PathPrintsToConsole.java new file mode 100644 index 0000000..2f2f4f0 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/PathPrintsToConsole.java @@ -0,0 +1,26 @@ +package ru.fusionsoft.dbgit.integration.primitives.path; + +import java.nio.file.Path; +import java.util.Arrays; +import java.util.stream.Collectors; + + +public class PathPrintsToConsole extends PathEnvelope { + + public PathPrintsToConsole(String text, Path origin) { + super(() -> { + System.out.println(text); + return origin; + }); + } + public PathPrintsToConsole(Path origin) { + this( + "--> " + origin.toAbsolutePath() + + Arrays + .stream(origin.toFile().listFiles()) + .map( file -> file.getName() + (file.isDirectory() ? " (dir) " : "") ) + .collect(Collectors.joining("\n")), + origin + ); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/PathRelativeTo.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/PathRelativeTo.java new file mode 100644 index 0000000..9c41733 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/PathRelativeTo.java @@ -0,0 +1,21 @@ +package ru.fusionsoft.dbgit.integration.primitives.path; + +import java.nio.file.Path; +import java.nio.file.Paths; + +public class PathRelativeTo extends PathEnvelope { + public PathRelativeTo(Path to, Path origin) { + super(()-> { + return Paths.get( + to + .toAbsolutePath() + .toString() + ) + .relativize(Paths.get( + origin + .toAbsolutePath() + .toString() + )); + }); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/PathWithFiles.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/PathWithFiles.java new file mode 100644 index 0000000..ae2d602 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/PathWithFiles.java @@ -0,0 +1,15 @@ +package ru.fusionsoft.dbgit.integration.primitives.path; + +import java.nio.file.Path; +import ru.fusionsoft.dbgit.integration.primitives.PatchSequential; +import ru.fusionsoft.dbgit.integration.primitives.Scalar; +import ru.fusionsoft.dbgit.integration.primitives.patch.PathPatchCreatingFile; + +public class PathWithFiles extends PathPatched { + public PathWithFiles(PathPatchCreatingFile[] filePatches, Path origin) { + super(origin, new PatchSequential(filePatches)); + } + public PathWithFiles(PathPatchCreatingFile filePatch, Path origin){ + super(filePatch, origin); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/PathWithoutFiles.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/PathWithoutFiles.java new file mode 100644 index 0000000..49dd0d5 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/PathWithoutFiles.java @@ -0,0 +1,22 @@ +package ru.fusionsoft.dbgit.integration.primitives.path; + +import java.nio.file.Path; +import ru.fusionsoft.dbgit.integration.primitives.patch.PathPatchDeletingFiles; +import ru.fusionsoft.dbgit.integration.primitives.patch.PathPatchDeletingFilesWildcard; + +public class PathWithoutFiles extends PathPatched { + + public PathWithoutFiles(String[] names, Path origin) { + super( + new PathPatchDeletingFiles(names), + origin + ); + } + + public PathWithoutFiles(String filterMask, Path origin) { + super( + new PathPatchDeletingFilesWildcard(filterMask), + origin + ); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/specific/CurrentWorkingDirectory.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/specific/CurrentWorkingDirectory.java new file mode 100644 index 0000000..f46b366 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/specific/CurrentWorkingDirectory.java @@ -0,0 +1,12 @@ +package ru.fusionsoft.dbgit.integration.primitives.path.specific; + +import java.nio.file.Paths; +import ru.fusionsoft.dbgit.integration.primitives.path.PathEnvelope; + +public class CurrentWorkingDirectory extends PathEnvelope { + public CurrentWorkingDirectory(){ + super(()-> { + return Paths.get(""); + }); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/specific/ProjectTestResourcesCleanDirectoryPath.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/specific/ProjectTestResourcesCleanDirectoryPath.java new file mode 100644 index 0000000..d671371 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/specific/ProjectTestResourcesCleanDirectoryPath.java @@ -0,0 +1,32 @@ +package ru.fusionsoft.dbgit.integration.primitives.path.specific; + +import java.io.File; +import java.util.concurrent.ThreadLocalRandom; +import org.apache.commons.io.FileUtils; +import ru.fusionsoft.dbgit.integration.primitives.path.PathEnvelope; + +public class ProjectTestResourcesCleanDirectoryPath extends PathEnvelope { + + public ProjectTestResourcesCleanDirectoryPath() { + this( + String.format( + "%#X", + ThreadLocalRandom.current().nextInt( + 0, + 32 + ) + ) + ); + } + + public ProjectTestResourcesCleanDirectoryPath(String name) { + super(() -> { + final File directory = new File( + "target/itoutput/" + name + ); + directory.mkdirs(); + FileUtils.cleanDirectory(directory); + return directory.toPath().toAbsolutePath(); + }); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/specific/dbgit/PathOfBuiltDbGitExecutable.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/specific/dbgit/PathOfBuiltDbGitExecutable.java new file mode 100644 index 0000000..fc3a796 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/specific/dbgit/PathOfBuiltDbGitExecutable.java @@ -0,0 +1,13 @@ +package ru.fusionsoft.dbgit.integration.primitives.path.specific.dbgit; + +import java.nio.file.Path; +import ru.fusionsoft.dbgit.integration.primitives.path.PathOf; + +public class PathOfBuiltDbGitExecutable extends PathOf { + public PathOfBuiltDbGitExecutable(Path dbGitProjectPath) { + super( + "target/dbgit/bin/dbgit", + dbGitProjectPath + ); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/specific/dbgit/PathWithDbGitNewRepoInitialized.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/specific/dbgit/PathWithDbGitNewRepoInitialized.java new file mode 100644 index 0000000..2a7031d --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/specific/dbgit/PathWithDbGitNewRepoInitialized.java @@ -0,0 +1,29 @@ +package ru.fusionsoft.dbgit.integration.primitives.path.specific.dbgit; + +import java.io.PrintStream; +import java.nio.file.Path; +import ru.fusionsoft.dbgit.integration.primitives.args.ArgsExplicit; +import ru.fusionsoft.dbgit.integration.primitives.path.PathAfterDbGitRun; +import ru.fusionsoft.dbgit.integration.primitives.path.PathNotProjectRoot; +import ru.fusionsoft.dbgit.integration.primitives.path.PathWithoutFiles; +import ru.fusionsoft.dbgit.integration.primitives.printstream.DefaultPrintStream; + +public class PathWithDbGitNewRepoInitialized extends PathAfterDbGitRun { + public PathWithDbGitNewRepoInitialized(PrintStream printStream, Path workingDirectory) { + super( + new ArgsExplicit("init"), + printStream, + + new PathWithoutFiles( + "*", + new PathNotProjectRoot( + workingDirectory + ) + ) + ); + } + + public PathWithDbGitNewRepoInitialized(Path workingDirectory) { + this(new DefaultPrintStream(), workingDirectory); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/specific/dbgit/PathWithDbGitRepoCloned.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/specific/dbgit/PathWithDbGitRepoCloned.java new file mode 100644 index 0000000..cbdfb70 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/specific/dbgit/PathWithDbGitRepoCloned.java @@ -0,0 +1,30 @@ +package ru.fusionsoft.dbgit.integration.primitives.path.specific.dbgit; + +import java.io.PrintStream; +import java.nio.file.Path; +import ru.fusionsoft.dbgit.integration.primitives.args.specific.ArgsDbGitAddRemote; +import ru.fusionsoft.dbgit.integration.primitives.patch.specific.PathPatchDbGitClonesRepo; +import ru.fusionsoft.dbgit.integration.primitives.path.PathPatched; +import ru.fusionsoft.dbgit.integration.primitives.printstream.DefaultPrintStream; + +public class PathWithDbGitRepoCloned extends PathPatched { + public PathWithDbGitRepoCloned(CharSequence repoUrl, ArgsDbGitAddRemote addRemoteArgs, PrintStream printStream, Path origin) { + super( + new PathPatchDbGitClonesRepo(repoUrl, addRemoteArgs, printStream), + origin + ); + } + public PathWithDbGitRepoCloned(CharSequence repoUrl, PrintStream printStream, Path origin) { + super( + new PathPatchDbGitClonesRepo(repoUrl, printStream), + origin + ); + } + public PathWithDbGitRepoCloned(CharSequence repoUrl, ArgsDbGitAddRemote addRemoteArgs, Path origin) { + this(repoUrl, addRemoteArgs, new DefaultPrintStream(), origin); + } + public PathWithDbGitRepoCloned(CharSequence repoUrl, Path origin) { + this(repoUrl, new DefaultPrintStream(), origin); + } + +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/specific/dbgit/scenarios/PathAfterDbGitCheckoutAndLink.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/specific/dbgit/scenarios/PathAfterDbGitCheckoutAndLink.java new file mode 100644 index 0000000..48df385 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/specific/dbgit/scenarios/PathAfterDbGitCheckoutAndLink.java @@ -0,0 +1,34 @@ +package ru.fusionsoft.dbgit.integration.primitives.path.specific.dbgit.scenarios; + +import java.io.PrintStream; +import java.nio.file.Path; +import ru.fusionsoft.dbgit.integration.primitives.printstream.DefaultPrintStream; +import ru.fusionsoft.dbgit.integration.primitives.args.specific.ArgsDbGitCheckout; +import ru.fusionsoft.dbgit.integration.primitives.args.specific.ArgsDbGitLink; +import ru.fusionsoft.dbgit.integration.primitives.path.PathAfterDbGitRun; + +public class PathAfterDbGitCheckoutAndLink extends PathAfterDbGitRun { + public PathAfterDbGitCheckoutAndLink( + ArgsDbGitCheckout checkoutArgs, + ArgsDbGitLink linkArgs, + PrintStream printStream, + Path origin + ) { + super( + linkArgs, + printStream, + new PathAfterDbGitRun( + checkoutArgs, + origin + ) + ); + } + + public PathAfterDbGitCheckoutAndLink( + ArgsDbGitCheckout checkoutArgs, + ArgsDbGitLink linkArgs, + Path origin + ) { + this(checkoutArgs, linkArgs, new DefaultPrintStream(), origin); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/specific/dbgit/scenarios/PathAfterDbGitDumpsDbSchemaToGit.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/specific/dbgit/scenarios/PathAfterDbGitDumpsDbSchemaToGit.java new file mode 100644 index 0000000..041af4e --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/specific/dbgit/scenarios/PathAfterDbGitDumpsDbSchemaToGit.java @@ -0,0 +1,41 @@ +package ru.fusionsoft.dbgit.integration.primitives.path.specific.dbgit.scenarios; + +import java.io.PrintStream; +import java.nio.file.Path; +import ru.fusionsoft.dbgit.integration.primitives.Patch; +import ru.fusionsoft.dbgit.integration.primitives.PatchSequential; +import ru.fusionsoft.dbgit.integration.primitives.args.ArgsExplicit; +import ru.fusionsoft.dbgit.integration.primitives.args.specific.ArgsDbGitAddRemote; +import ru.fusionsoft.dbgit.integration.primitives.args.specific.ArgsDbGitLink; +import ru.fusionsoft.dbgit.integration.primitives.patch.PathPatchCreatingFile; +import ru.fusionsoft.dbgit.integration.primitives.patch.PathPatchRunningDbGit; +import ru.fusionsoft.dbgit.integration.primitives.patch.specific.PathPatchDbGitLink; +import ru.fusionsoft.dbgit.integration.primitives.path.PathPatched; +import ru.fusionsoft.dbgit.integration.primitives.path.specific.dbgit.PathWithDbGitRepoCloned; + +public class PathAfterDbGitDumpsDbSchemaToGit extends PathPatched { + public PathAfterDbGitDumpsDbSchemaToGit( + CharSequence commitMessage, + CharSequence pushRemoteName, + CharSequence gitUrl, + ArgsDbGitLink dbLinkArgs, + ArgsDbGitAddRemote addRemoteArgs, + CharSequence ignoreChars, + Patch checkoutPatch, + PrintStream printStream, + Path workingDirectory + ) { + super( + new PatchSequential<>( + checkoutPatch, + new PathPatchDbGitLink(dbLinkArgs, printStream), + new PathPatchCreatingFile(".dbgit/.dbignore", ignoreChars), + new PathPatchRunningDbGit(new ArgsExplicit("add", "\"*\"", "-v"), printStream), + new PathPatchRunningDbGit(new ArgsExplicit("commit", "-m", commitMessage), printStream), + new PathPatchRunningDbGit(new ArgsExplicit("push", pushRemoteName),printStream) + ), + new PathWithDbGitRepoCloned(gitUrl, addRemoteArgs, printStream, workingDirectory) + ); + } + +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/specific/dbgit/scenarios/PathAfterDbGitLinkAndAdd.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/specific/dbgit/scenarios/PathAfterDbGitLinkAndAdd.java new file mode 100644 index 0000000..36632f2 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/specific/dbgit/scenarios/PathAfterDbGitLinkAndAdd.java @@ -0,0 +1,27 @@ +package ru.fusionsoft.dbgit.integration.primitives.path.specific.dbgit.scenarios; + +import java.io.PrintStream; +import java.nio.file.Path; +import ru.fusionsoft.dbgit.integration.primitives.patch.PathPatchCreatingFile; +import ru.fusionsoft.dbgit.integration.primitives.path.PathWithFiles; +import ru.fusionsoft.dbgit.integration.primitives.printstream.DefaultPrintStream; +import ru.fusionsoft.dbgit.integration.primitives.args.ArgsExplicit; +import ru.fusionsoft.dbgit.integration.primitives.args.specific.ArgsDbGitLink; +import ru.fusionsoft.dbgit.integration.primitives.path.PathAfterDbGitRun; + +public class PathAfterDbGitLinkAndAdd extends PathAfterDbGitRun { + public PathAfterDbGitLinkAndAdd(ArgsDbGitLink argsDbGitLink, CharSequence ignoreChars, PrintStream printStream, Path origin) { + super( + new ArgsExplicit("add", "\"*\"", "-v"), + printStream, + new PathWithFiles( + new PathPatchCreatingFile(".dbgit/.dbignore", ignoreChars), + new PathAfterDbGitRun(argsDbGitLink, printStream, origin) + ) + ); + } + + public PathAfterDbGitLinkAndAdd(ArgsDbGitLink argsDbGitLink, CharSequence ignoreChars, Path origin) { + this(argsDbGitLink, ignoreChars, new DefaultPrintStream(), origin); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/specific/dbgit/scenarios/PathWithBuildingDbGitExecutableFromGit.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/specific/dbgit/scenarios/PathWithBuildingDbGitExecutableFromGit.java new file mode 100644 index 0000000..ce96dfc --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/path/specific/dbgit/scenarios/PathWithBuildingDbGitExecutableFromGit.java @@ -0,0 +1,64 @@ +package ru.fusionsoft.dbgit.integration.primitives.path.specific.dbgit.scenarios; + +import java.io.PrintStream; +import java.nio.file.Path; +import ru.fusionsoft.dbgit.integration.primitives.printstream.DefaultPrintStream; +import ru.fusionsoft.dbgit.integration.primitives.PatchSequential; +import ru.fusionsoft.dbgit.integration.primitives.args.ArgsExplicit; +import ru.fusionsoft.dbgit.integration.primitives.args.ArgsWithPrepend; +import ru.fusionsoft.dbgit.integration.primitives.patch.PathPatchCloningGitRepo; +import ru.fusionsoft.dbgit.integration.primitives.patch.PathPatchDeletingFiles; +import ru.fusionsoft.dbgit.integration.primitives.patch.PathPatchDeletingFilesWildcard; +import ru.fusionsoft.dbgit.integration.primitives.path.PathAfterProcessRun; +import ru.fusionsoft.dbgit.integration.primitives.path.PathEnvelope; +import ru.fusionsoft.dbgit.integration.primitives.path.PathNotProjectRoot; +import ru.fusionsoft.dbgit.integration.primitives.path.specific.dbgit.PathOfBuiltDbGitExecutable; +import ru.fusionsoft.dbgit.integration.primitives.path.PathPatched; + +public class PathWithBuildingDbGitExecutableFromGit extends PathEnvelope { + + public PathWithBuildingDbGitExecutableFromGit(String commitHash, PrintStream printStream, Path origin) { + super(() -> { + + return new PathOfBuiltDbGitExecutable( + new PathAfterProcessRun( + new ArgsWithPrepend( + new ArgsExplicit( + "mvn", + "package", + "appassembler:assemble", + "-D", + "skipTests" + ), + new ArgsExplicit( + System.getenv("ComSpec"), + "/C" + ) + ), + printStream, + new PathPatched( + new PathNotProjectRoot(origin), + new PatchSequential<>( + new PathPatchDeletingFilesWildcard( + "*" + ), + new PathPatchCloningGitRepo( + "https://github.com/databasegit/dbgit.git", + commitHash, + printStream + ), + new PathPatchDeletingFiles( + "src/test/java/ru/fusionsoft/dbgit/mssql/DBAdapterMssqlTest.java" + ) + ) + ) + ) + ); + + }); + } + + public PathWithBuildingDbGitExecutableFromGit(String commitHash, Path origin) { + this(commitHash, new DefaultPrintStream(), origin); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/printstream/DefaultPrintStream.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/printstream/DefaultPrintStream.java new file mode 100644 index 0000000..288b0eb --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/printstream/DefaultPrintStream.java @@ -0,0 +1,9 @@ +package ru.fusionsoft.dbgit.integration.primitives.printstream; + +import java.io.PrintStream; + +public class DefaultPrintStream extends PrintStream { + public DefaultPrintStream() { + super(new PrintStreamToConsole()); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/printstream/OutputStreamToConsole.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/printstream/OutputStreamToConsole.java new file mode 100644 index 0000000..5719464 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/printstream/OutputStreamToConsole.java @@ -0,0 +1,10 @@ +package ru.fusionsoft.dbgit.integration.primitives.printstream; + +import java.io.OutputStream; + +public class OutputStreamToConsole extends OutputStream { + @Override + public final void write(int i) { + System.out.write(i); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/printstream/OutputStreamToNowhere.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/printstream/OutputStreamToNowhere.java new file mode 100644 index 0000000..dd8b931 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/printstream/OutputStreamToNowhere.java @@ -0,0 +1,9 @@ +package ru.fusionsoft.dbgit.integration.primitives.printstream; + +import java.io.OutputStream; + +public class OutputStreamToNowhere extends OutputStream { + @Override + public void write(int b) { + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/printstream/PrintStreamToConsole.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/printstream/PrintStreamToConsole.java new file mode 100644 index 0000000..d06d72d --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/printstream/PrintStreamToConsole.java @@ -0,0 +1,9 @@ +package ru.fusionsoft.dbgit.integration.primitives.printstream; + +import java.io.PrintStream; + +public class PrintStreamToConsole extends PrintStream { + public PrintStreamToConsole() { + super(new OutputStreamToConsole()); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/printstream/PrintStreamToNowhere.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/printstream/PrintStreamToNowhere.java new file mode 100644 index 0000000..ae5f3c3 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/printstream/PrintStreamToNowhere.java @@ -0,0 +1,10 @@ +package ru.fusionsoft.dbgit.integration.primitives.printstream; + +import java.io.PrintStream; + +public class PrintStreamToNowhere extends PrintStream { + + public PrintStreamToNowhere() { + super(new OutputStreamToNowhere()); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/mssql/DBAdapterMssqlTest.java b/src/test/java/ru/fusionsoft/dbgit/mssql/DBAdapterMssqlTest.java new file mode 100644 index 0000000..2db84ff --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/mssql/DBAdapterMssqlTest.java @@ -0,0 +1,1524 @@ +package ru.fusionsoft.dbgit.mssql; + +import com.google.common.collect.Lists; + +import org.apache.commons.lang3.time.StopWatch; +import ru.fusionsoft.dbgit.adapters.AdapterFactory; +import ru.fusionsoft.dbgit.core.DBGitConfig; +import ru.fusionsoft.dbgit.core.db.DbType; +import ru.fusionsoft.dbgit.dbobjects.*; +import ru.fusionsoft.dbgit.meta.*; +import ru.fusionsoft.dbgit.statement.StatementLogging; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; + +import java.sql.*; +import java.text.MessageFormat; +import java.util.*; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + + +@Tag("mssqlTest") +@Tag("deprecated") +public class DBAdapterMssqlTest { + + public static Properties testProps; + + /* + * Using SQL EXPRESS 2012\Win 10 Home forced me to: + * - via CLICONFG.EXE -> Aliases: move TCP/IP protocol from disabled to enabled list + * - via CLICONFG.EXE -> Common : create alias with localhost -> localhost:1433 (port 1433 in connString is fake) + * + * Setup of ip an ports via SQLServerManager11.msc also needed, mine was: + * Protocols -> SQL EXPRESS protocols -> Protocol -> Listen all to true and + * Protocols -> SQL EXPRESS protocols -> Protocol -> IP adresses -> IPAll -> TCP Port to 1433 and Dynamic TCP Port to blank + */ + + public static String TEST_CONN_URL = "23.105.226.179:1433"; + public static String TEST_CONN_CATALOG = "testdatabasegit"; + public static String TEST_CONN_STRING = "jdbc:sqlserver://"+TEST_CONN_URL+";databaseName="+TEST_CONN_CATALOG+";integratedSecurity=false;"; + public static String TEST_CONN_USER = "sa"; + public static String TEST_CONN_PASS = "s%G351as"; + + private static DBAdapterMssql testAdapter; + private static DBBackupAdapterMssql testBackup; + private static FactoryDBAdapterRestoreMssql testRestoreFactory = new FactoryDBAdapterRestoreMssql(); + private static DBRestoreTriggerMssql restoreTrigger; + + + private static Connection testConnection; + private static boolean isInitialized = false; + private static boolean isMasterDatabase; + + static{ + testProps = new Properties(); + testProps.setProperty("url", TEST_CONN_STRING); + testProps.setProperty("user", TEST_CONN_USER); + testProps.setProperty("password", TEST_CONN_PASS); + testProps.put("characterEncoding", "UTF-8"); + } + + + private static String tableName = "TestTableSome"; + private static String triggerName = "TestTrigger"; + private static String triggerNameEncr = "TestTriggerEncrypted"; + private static String procedureName = "TestProc"; + private static String functionName = "TestFunc"; + private static String functionNameTable = functionName + "Table"; + private static String triggerTableName = "TestTableTrigger"; + private static String schema; + private static String viewName = "TestView"; + private static String sequenceName = "TestSequence"; + private static int messageLevel = 0; + + + @BeforeEach + public void setUp() throws Exception { + if(!isInitialized){ + try { + String url = testProps.getProperty("url"); + testConnection = DriverManager.getConnection(url, testProps); + testConnection.setAutoCommit(false); + testAdapter = (DBAdapterMssql) AdapterFactory.createAdapter(testConnection); + testBackup = (DBBackupAdapterMssql) testAdapter.getBackupAdapterFactory().getBackupAdapter(testAdapter); + restoreTrigger = (DBRestoreTriggerMssql) testRestoreFactory.getAdapterRestore(DBGitMetaType.DbGitTrigger,testAdapter); + isMasterDatabase = testConnection.getCatalog().equalsIgnoreCase("master"); + schema = testConnection.getSchema(); + isInitialized = true; + } + catch (Exception ex){ + fail(ex.getMessage()); + } + dropBackupObjects(); + } + } + + @AfterEach + public void tearDown() throws Exception + { + } + + @Test + public void getSchemes() { + Map schemes = testAdapter.getSchemes(); + assertTrue(schemes.containsKey("guest")); + assertTrue(schemes.containsKey("dbo")); + } + + @Test + public void getTableSpaces() { + Map tablespaces = testAdapter.getTableSpaces(); + assertEquals("ROWS_FILEGROUP", tablespaces.get("PRIMARY").getOptions().getChildren().get("type_desc").getData()); + } + + @Test + public void getSequences() throws Exception{ + String schemaName = testConnection.getSchema(); + String sequenceName = "TEST_SEQUENCE"; + createTestSequence(sequenceName); + + Map sequences = testAdapter.getSequences(schemaName); + dropTestSequence(sequenceName); + + assertEquals(schemaName, sequences.get(sequenceName).getOptions().get("owner").getData()); + + } + + @Test + public void getSequence() throws Exception{ + String name = "TEST_SEQUENCE"; + + createTestSequence(name); + DBSequence sequence = testAdapter.getSequence("dbo", name); + dropTestSequence(name); + + assertEquals(name, sequence.getOptions().get("name").getData()); + } + + @Test + public void getTables() throws Exception{ + String name = "TEST_TABLE"; + String schema = testConnection.getSchema(); + String sam = schema + "." + name; + + try{ + createTable(sam, + "PersonID int, LastName varchar(255), FirstName varchar(255), Address varchar(255), City varchar(255) " + ); + + Map tables = testAdapter.getTables(schema); + assertEquals(name, tables.get(name).getOptions().get("name").getData()); + } catch (Exception ex) { + fail(ex.toString()); + } finally { + dropTable(sam); + } + + } + + @Test + public void getTableFields() throws Exception{ + String name = "TestTableTypes"; + String schema = testConnection.getSchema(); + try{ + createTable(name, + " [col1] [nchar](10) NULL,\n" + + " [col2] [ntext] NULL,\n" + + " [col3] [numeric](18, 0) NULL,\n" + + " [col4] [nvarchar](50) NULL,\n" + + " [col5] [nvarchar](max) NULL,\n" + + " [col6] [real] NULL,\n" + + " [col7] [smalldatetime] NULL,\n" + + " [col8] [smallint] NULL,\n" + + " [col9] [smallmoney] NULL,\n" + + " [col10] [sql_variant] NULL,\n" + + " [col11] [text] NULL,\n" + + " [col12] [time](7) NULL,\n" + + " [col13] [timestamp] NULL,\n" + + " [col14] [tinyint] NULL,\n" + + " [col15] [uniqueidentifier] NULL,\n" + + " [col16] [varbinary](50) NULL,\n" + + " [col17] [varbinary](max) NULL,\n" + + " [col18] [varchar](50) NULL,\n" + + " [col19] [varchar](max) NULL,\n" + + " [col20] [xml] NULL\n" + ); + + Map fields = testAdapter.getTableFields(schema, name); + assertEquals("sql_variant(0)", fields.get("col10").getTypeSQL()); + assertEquals("native",fields.get("col10").getTypeUniversal().toString()); + + dropTable(schema + "." + name); + } + catch (Exception ex) { + fail(ex.toString()); + } + + } + + @Test + public void getTableData() { + + try{ + StopWatch watch = new StopWatch(); + watch.start(); + createTestTriggerProcedureFunctions(triggerTableName); + + DBTableData data = testAdapter.getTableData(testConnection.getSchema(), triggerTableName); + ResultSet rs = data.resultSet(); + ResultSetMetaData md = rs.getMetaData(); + int cols = md.getColumnCount(); + rs.next(); + + assertEquals(2, cols); + assertEquals(1, rs.getInt(1)); + assertEquals("Hey, I have some!", rs.getString(2)); + + dropTestTriggerProcedureFunctions(triggerTableName); + + System.out.println(watch.toString()); + } + catch (Exception ex) { + fail(ex.getLocalizedMessage()); + } + } + + @Test + public void getTableDataPortion() { + + try{ + createBigDummyTable(); + + int rowsAffected = 0; + int portionSize = DBGitConfig.getInstance().getInteger( "core", "PORTION_SIZE", + DBGitConfig.getInstance().getIntegerGlobal("core", "PORTION_SIZE", 1000) + ); + + DBTableData data = testAdapter.getTableDataPortion("tempdb.", "#bigDummyTable", 2, 0); + ResultSet rs = data.resultSet(); + while (rs.next()) rowsAffected++; + + + assertEquals(portionSize, rowsAffected); + + dropBigDummyTable(); + } + catch (Exception ex) { + fail(ex.toString()); + } + } + + @Test + public void getIndexes() throws Exception{ + + String tableName = "TestTableIndex"; + + String indexCreateDdl = createTestIndex(tableName); + + Map indexes = testAdapter.getIndexes(testConnection.getSchema(), tableName); + assertEquals("2", indexes.get("IX_IdTest").getOptions().getChildren().get("indexid").getData()); + assertEquals(indexCreateDdl, indexes.get("IX_IdTest").getSql()); + + dropTestIndex(tableName); + + } + + @Test + public void getConstraints() throws Exception{ + + String schema = testConnection.getSchema(); + String tableName = "CTestTable"; + String tableSam = schema + "." + tableName; + + String constrDDL1 = "ALTER TABLE "+ tableSam + " ADD CONSTRAINT df_constraint DEFAULT ('{}') FOR [value];"; + String constrDDL2 = "ALTER TABLE "+ tableSam + " ADD CONSTRAINT df_constraintInt DEFAULT ((1)) FOR [valueCheck1];"; + String constrDDL3 = "ALTER TABLE "+ tableSam + " ADD CONSTRAINT u_constraint UNIQUE NONCLUSTERED ([valueUnique]);"; + String constrDDL4 = "ALTER TABLE "+ tableSam + " ADD CONSTRAINT chk_constraint CHECK ([valueCheck1]>(0) AND [valueCheck2]>(0));"; + String constrDDL5 = "ALTER TABLE "+ tableSam + " ADD CONSTRAINT fk_constraint FOREIGN KEY (fkInt) references " + tableSam + "FK(keyInt);"; + + + createTestConstraintsAndTables(schema, tableName); + + + Map constraints = testAdapter.getConstraints(schema, tableName); + assertEquals(constrDDL1, constraints.get("df_constraint").getSql()); + assertEquals(constrDDL2, constraints.get("df_constraintInt").getSql()); + assertEquals(constrDDL3, constraints.get("u_constraint").getSql()); + assertEquals(constrDDL4, constraints.get("chk_constraint").getSql()); + assertEquals(constrDDL5, constraints.get("fk_constraint").getSql()); + + dropTestConstraintsAndTables(schema, tableName); + + } + + @Test + public void getViews() { + + String viewDDl = + "CREATE VIEW dbo.testView AS\n" + + "SELECT 'THE ALLMIGHT ''' + SC.name + ''' FROM ' + SO.name as theBigTitle\n" + + "FROM sys.columns SC JOIN sys.objects SO on SC.object_id = SO.object_id"; + + try{ + Statement stmt = testConnection.createStatement(); + stmt.execute("IF OBJECT_ID('dbo.testView', 'V') IS NOT NULL DROP VIEW dbo.testView \n"); + stmt.execute( + "CREATE VIEW dbo.testView AS\n" + + "SELECT SC.name + '(' + SO.NAME + ')' as theUsualTitle\n" + + "FROM sys.columns SC JOIN sys.objects SO on SC.object_id = SO.object_id\n"); + stmt.execute( + "ALTER VIEW dbo.testView AS\n" + + "SELECT 'THE ALLMIGHT ''' + SC.name + ''' FROM ' + SO.name as theBigTitle\n" + + "FROM sys.columns SC JOIN sys.objects SO on SC.object_id = SO.object_id\n"); + + Map views = testAdapter.getViews("dbo"); + assertEquals(viewDDl, views.get("testView").getSql()); + + stmt.execute("DROP VIEW dbo.testView;" ); + } + catch (Exception ex) { + fail(ex.toString()); + } + + } + + @Test + public void getView() throws Exception { + String schema = testConnection.getSchema(); + String viewName = "TestView"; + String viewDDl = createTestView(schema, viewName); + + DBView view = testAdapter.getView(schema, viewName); + assertEquals(viewDDl, view.getSql()); + + dropTestView(schema, viewName); + } + + @Test + public void getProcedures() { + + try{ + List ddls = createTestTriggerProcedureFunctions(triggerTableName); + + Map procedures = testAdapter.getProcedures(testConnection.getSchema()); + assertEquals(ddls.get(6), procedures.get(procedureName).getSql()); + + dropTestTriggerProcedureFunctions(triggerTableName); + + } + catch (Exception ex) { + fail(ex.toString()); + } + + } + + @Test + public void getProcedure() { + + try{ + List ddls = createTestTriggerProcedureFunctions(triggerTableName);; + + DBProcedure procedure = testAdapter.getProcedure(testConnection.getSchema(), procedureName); + assertEquals(ddls.get(6), procedure.getSql()); + + dropTestTriggerProcedureFunctions(triggerTableName); + } + catch (Exception ex) { + fail(ex.toString()); + } + + } + + @Test + public void getFunctions(){ + + try{ + List ddls = createTestTriggerProcedureFunctions(triggerTableName);; + + Map functions = testAdapter.getFunctions(testConnection.getSchema()); + assertEquals(ddls.get(4), functions.get(functionNameTable).getSql()); + + dropTestTriggerProcedureFunctions(triggerTableName); + } + catch (Exception ex) { + fail(ex.toString()); + } + + } + + @Test + public void getFunction() { + + try{ + List ddls = createTestTriggerProcedureFunctions(triggerTableName);; + + DBFunction function = testAdapter.getFunction(testConnection.getSchema(), functionName); + assertEquals(ddls.get(2), function.getSql()); + + dropTestTriggerProcedureFunctions(triggerTableName); + } + catch (Exception ex) { + fail(ex.toString()); + } + + } + + @Test + public void getTriggers() { + + try{ + List ddls = createTestTriggerProcedureFunctions(triggerTableName);; + + Map triggers = testAdapter.getTriggers(testConnection.getSchema()); + assertEquals(ddls.get(7), triggers.get(triggerName).getSql()); + + dropTestTriggerProcedureFunctions(triggerTableName); + } + catch (Exception ex) { + fail(ex.toString()); + } + + } + + @Test + public void getTrigger() { + + try{ + List ddls = createTestTriggerProcedureFunctions(triggerTableName);; + + //TODO Discuss scenario when we get an encrypted trigger, IMO display a warning, + // it is not possible to get definition of an encrypred trigger + DBTrigger trigger = testAdapter.getTrigger("dbo", triggerName + "Encrypted"); + assertEquals("", trigger.getSql()); + assertEquals("1", trigger.getOptions().getChildren().get("encrypted").getData()); + + + dropTestTriggerProcedureFunctions(triggerTableName); + } + catch (Exception ex) { + fail(ex.toString()); + } + } + + @Test + public void getUsers() { + + try{ + + Statement stmt = testConnection.createStatement(); + + String userName = "testUsr"; + String loginName = "testLgn"; + String schemaName = "public"; + String testPassHashed = "0X0200083FACBD4D7C49EAD537B1690C3E8953C504461E645D22762CED5D7CB241D87AEC312875BDB83DBD367F10C52CE7B1059056C27B8C16B083FFA97DBA2DF2F142318CCC74"; + String testPass = "test"; + + createUserAndLogin(userName, loginName, schemaName, testPassHashed, true); + + Map users = testAdapter.getUsers(); + String ddl = users.get(userName).getOptions().get("ddl").getData(); + String hash = users.get(userName).getOptions().get("passwordhash").getData(); + + assertTrue(users.containsKey(userName)); + assertTrue(ddl.contains(hash)); + assertTrue(ddl.contains("GRANT CONNECT")); + assertTrue(ddl.contains("WITH DEFAULT_SCHEMA")); + + //try create connection and adapter with new login + DBAdapterMssql adapter; + adapter = createAdapterWithCredentials(loginName, testPass, TEST_CONN_STRING); + + //drop and close + adapter.getConnection().close(); + dropUserAndLogin(userName, loginName); + stmt.close(); + } + catch (Exception ex) { + fail(ex.getMessage()); + + } + } + + @Test + public void getRoles() throws Exception{ + + String roleName = "testRol"; + String userName = "testUsr"; + String tableSchemaAndName = "[dbo].[testTablePerm]"; + String roleDdl = createTestRoleAndStuff(roleName, userName, tableSchemaAndName); + + + Map roles = testAdapter.getRoles(); + dropTestRoleAndStuff(roleName, userName, tableSchemaAndName); + + //has role test + assertTrue(roles.containsKey(roleName)); + + //correct ddl test + String ddl = roles.get(roleName).getOptions().get("ddl").getData(); + assertEquals(roleDdl, ddl); + + } + + @Test + public void userHasRightsToGetDdlOfOtherUsers() throws Exception{ + try{ + + String publicUserName = "testUsrPublic"; + String publicLoginName = "testLgnPublic"; + String password = "test"; + String dboUserName = "testUsrDbo"; + String dboLoginName = "testLgnDbo"; + + createUserAndLogin(publicUserName, publicLoginName, "public", password, false); + createUserAndLogin(dboUserName, dboLoginName, "dbo", password, false); + addToRole(dboUserName, "db_owner"); + + DBAdapterMssql publicAdapter = createAdapterWithCredentials(publicLoginName, password, TEST_CONN_STRING); + DBAdapterMssql dboAdapter = createAdapterWithCredentials(dboLoginName, password, TEST_CONN_STRING); + + boolean publicHasRights = publicAdapter.userHasRightsToGetDdlOfOtherUsers(); + boolean dboHasRights = dboAdapter.userHasRightsToGetDdlOfOtherUsers(); + + publicAdapter.getConnection().close(); + dboAdapter.getConnection().close(); + + assertFalse(publicHasRights); + assertTrue(dboHasRights); + + testAdapter.userHasRightsToGetDdlOfOtherUsers(); + + } + catch (Exception e){ + System.out.println(e.getMessage()); + } + + } + + @Test + public void getDbType(){ + DbType type = testAdapter.getDbType(); + assertEquals(DbType.MSSQL, type); + } + + @Test + public void getDbVersion(){ + String version = testAdapter.getDbVersion(); + assertFalse(version.isEmpty()); + } + + @Test + public void createSchemaIfNeed() throws Exception{ + String schemaName = "TESTSCHEMA"; + + testAdapter.createSchemaIfNeed(schemaName); + assertTrue(testAdapter.getSchemes().containsKey(schemaName)); + + dropSchema(schemaName); + assertFalse(testAdapter.getSchemes().containsKey(schemaName)); + + } + + @Test + public void createRoleIfNeed() throws Exception{ + String roleName = "TESTROLETEST"; + + testAdapter.createRoleIfNeed(roleName); + assertTrue(testAdapter.getRoles().containsKey(roleName)); + + dropRole(roleName); + assertFalse(testAdapter.getRoles().containsKey(roleName)); + + } + + @Test + public void getDefaultScheme() throws Exception{ + String schemaName = testAdapter.getDefaultScheme(); + assertNotEquals("", schemaName); + + } + + @Test + public void isReservedWord(){ + assertTrue(testAdapter.isReservedWord("NOT")); + assertTrue(testAdapter.isReservedWord("nOt")); + assertTrue(testAdapter.isReservedWord("CASE WHEN")); + assertTrue(testAdapter.isReservedWord("END-EXEC")); + assertTrue(testAdapter.isReservedWord("PERCENTILE_DISC")); + } + + //backupAdapter methods + + @Test + public void backupMetaSequence() throws Exception{ + try(AutoCloseable testSequence = useTestSequence(sequenceName)){ + + MetaSequence metaSequence = new MetaSequence(testAdapter.getSequences(schema).get(sequenceName)); + testBackup.backupDBObject(metaSequence); + } + } + + @Test + public void backupMetaTable() throws Exception{ + String tableName = "CTestTable"; + String indexTableName = "TestTableIndex"; + String sam = schema + ".PersonsTest"; + + String someTableDdl = createTable(sam, "PersonID int, LastName varchar(255), FirstName varchar(255), Address varchar(255), City varchar(255) "); + createTestIndex(indexTableName); + createTestConstraintsAndTables(schema, tableName); + + Map tables = testAdapter.getTables(schema); + + MetaTable constraintsMetaTable = new MetaTable(tables.get(tableName)); + MetaTable indexedMetaTable = new MetaTable(tables.get(indexTableName)); + testConnection.commit(); + + testBackup.backupDBObject(constraintsMetaTable); + testBackup.backupDBObject(indexedMetaTable); + + dropTable(sam); + dropTestIndex(indexTableName); + dropTestConstraintsAndTables(schema, tableName); + testConnection.commit(); + } + + @Test + public void backupMetaSql() throws Exception{ + dropBackupObjects(); + createTestTriggerProcedureFunctions(triggerTableName); + createTestView(schema, viewName); + + MetaView metaView = new MetaView(testAdapter.getViews(schema).get(viewName)); + MetaTrigger metaTrigger = new MetaTrigger(testAdapter.getTriggers(schema).get(triggerName)); + MetaProcedure metaProcedure = new MetaProcedure(testAdapter.getProcedures(schema).get(procedureName)); + MetaFunction metaFunction = new MetaFunction(testAdapter.getFunctions(schema).get(functionName)); + MetaFunction metaFunctionTable = new MetaFunction(testAdapter.getFunctions(schema).get(functionName+"Table")); + + testBackup.backupDBObject(metaView); + testBackup.backupDBObject(metaTrigger); + testBackup.backupDBObject(metaProcedure); + testBackup.backupDBObject(metaFunction); + testBackup.backupDBObject(metaFunctionTable); + + dropTestView(schema, viewName); + dropTestTriggerProcedureFunctions(triggerTableName); + } + + @Test + public void isExists() throws Exception{ + String objectName = "ShouldExist"; + + try(AutoCloseable view = useTestView(schema, objectName)){ + assertTrue(testBackup.isExists(schema, objectName)); + } + } + + @Test + public void createSchema() throws Exception { + String schemaName = "TESTSCHEMA2"; + String prefix = "BACKUP$"; + StatementLogging stLog = new StatementLogging(testConnection, testAdapter.getStreamOutputSqlCommand(), testAdapter.isExecSql()); + + testBackup.createSchema(stLog, schemaName); + assertTrue(testAdapter.getSchemes().containsKey(prefix+schemaName)); + dropSchema(prefix+schemaName); + } + + public void restoreDBObject() throws Exception{ + + } + public void backupMetaObjOptions() throws Exception{ + String roleName = "TestRoleB"; + String userName = "TestUserB"; + String tableName = "RTestTable"; + String sam = schema + "." + tableName; + createTestRoleAndStuff(roleName, userName, sam); + + MetaRole metaRole = new MetaRole(testAdapter.getRoles().get(roleName)); + MetaUser metaUser = new MetaUser(testAdapter.getUsers().get(userName)); + MetaSchema metaSchema = new MetaSchema(testAdapter.getSchemes().get(schema)); + MetaTableSpace metaTableSpace = new MetaTableSpace(testAdapter.getTableSpaces().get("PRIMARY")); + + List objs = Arrays.asList(metaRole, metaUser, metaSchema, metaTableSpace); + for(MetaObjOptions obj : objs) testBackup.backupDBObject(obj); + + dropTestRoleAndStuff(roleName, userName, sam); + } + + //restoreAdapter methods + + @Test + public void getAdapterRestore(){ + assertEquals( + testRestoreFactory.getAdapterRestore(DBGitMetaType.DBGitSequence,testAdapter).getClass(), + DBRestoreSequenceMssql.class + ); + assertEquals( + testRestoreFactory.getAdapterRestore(DBGitMetaType.DBGitTable,testAdapter).getClass(), + DBRestoreTableMssql.class + ); + assertEquals( + testRestoreFactory.getAdapterRestore(DBGitMetaType.DbGitTableData,testAdapter).getClass(), + DBRestoreTableDataMssql.class + ); + assertEquals( + testRestoreFactory.getAdapterRestore(DBGitMetaType.DBGitSchema,testAdapter).getClass(), + DBRestoreSchemaMssql.class + ); + assertEquals( + testRestoreFactory.getAdapterRestore(DBGitMetaType.DbGitFunction,testAdapter).getClass(), + DBRestoreFunctionMssql.class + ); + assertEquals( + testRestoreFactory.getAdapterRestore(DBGitMetaType.DbGitProcedure,testAdapter).getClass(), + DBRestoreProcedureMssql.class + ); + assertEquals( + testRestoreFactory.getAdapterRestore(DBGitMetaType.DBGitRole,testAdapter).getClass(), + DBRestoreRoleMssql.class + ); + assertEquals( + testRestoreFactory.getAdapterRestore(DBGitMetaType.DbGitTrigger,testAdapter).getClass(), + DBRestoreTriggerMssql.class + ); + assertEquals( + testRestoreFactory.getAdapterRestore(DBGitMetaType.DbGitView,testAdapter).getClass(), + DBRestoreViewMssql.class + ); + assertEquals( + testRestoreFactory.getAdapterRestore(DBGitMetaType.DbGitPackage,testAdapter), + null + ); + + assertEquals( + testRestoreFactory.getAdapterRestore(DBGitMetaType.DBGitTableSpace,testAdapter).getClass(), + DBRestoreTableSpaceMssql.class + ); + + assertEquals( + testRestoreFactory.getAdapterRestore(DBGitMetaType.DBGitUser,testAdapter).getClass(), + DBRestoreUserMssql.class + ); + + } + + @Test + public void restoreSequence() throws Exception{ + String seqName = "testSeq"; + String seqDdl = createTestSequence(seqName); + + DBRestoreSequenceMssql ra = (DBRestoreSequenceMssql) testRestoreFactory.getAdapterRestore(DBGitMetaType.DBGitSequence,testAdapter); + DBSequence dbSequence = testAdapter.getSequence(schema, seqName); + MetaSequence metaSequence = new MetaSequence(dbSequence); + DbType sourceDbType = ra.getSourceDbType(metaSequence); + + dropTestSequence(seqName); + assertFalse(testAdapter.getSequences(schema).containsKey(seqName)); + + ra.restoreMetaObject(metaSequence); + assertTrue(testAdapter.getSequences(schema).containsKey(seqName)); + + dropTestSequence(seqName); + } + + @Test + public void restoreTable() throws Exception{ + DBRestoreTableMssql restoreAdapter = (DBRestoreTableMssql) testRestoreFactory.getAdapterRestore(DBGitMetaType.DBGitTable,testAdapter); + + + String tblNameConstraints = "testConstraintsTable"; + createTestConstraintsAndTables(tblNameConstraints); + MetaTable metaTableConstraints = new MetaTable(testAdapter.getTable(schema, tblNameConstraints)); + metaTableConstraints.loadFromDB(); + + String tblNameIndexes = "testTbl"; + createTestIndex(tblNameIndexes); + MetaTable metaTableIndexes = new MetaTable(testAdapter.getTable(schema, tblNameIndexes)); + metaTableIndexes.loadFromDB(); + + Map constraintsBefore = metaTableConstraints.getConstraints(); + Map indexesBefore = metaTableIndexes.getIndexes(); + + for(MetaTable mt : Arrays.asList(metaTableConstraints, metaTableIndexes)){ + String tableName = mt.getTable().getName(); + dropTable(schema, tableName); + assertFalse(testAdapter.getTables(schema).containsKey(tableName)); + + for(int step : Arrays.asList(0, -1, 1)){ + restoreAdapter.restoreMetaObject(mt, step); + } + assertTrue(testAdapter.getTables(schema).containsKey(tableName)); + } + + Map constraintsAfter = testAdapter.getConstraints(schema, tblNameConstraints); + Map indexesAfter = testAdapter.getIndexes(schema, tblNameIndexes); + + assertTrue(indexesBefore.keySet().containsAll(indexesAfter.keySet())); + assertTrue(constraintsBefore.keySet().containsAll(constraintsAfter.keySet())); + + dropTestConstraintsAndTables(tblNameConstraints); + dropTestIndex(tblNameIndexes); + + testConnection.commit(); + + } + + @Test + public void restoreFunction() throws Exception{ + DBRestoreFunctionMssql restoreAdapter = (DBRestoreFunctionMssql) testRestoreFactory.getAdapterRestore(DBGitMetaType.DbGitFunction,testAdapter); + String tableName = "someTestTable"; + + createTestTriggerProcedureFunctions(tableName); + MetaFunction metaFunction = new MetaFunction(testAdapter.getFunction(schema, functionName)); + MetaFunction metaFunctionTable = new MetaFunction(testAdapter.getFunction(schema, functionNameTable)); + metaFunction.loadFromDB(); + metaFunctionTable.loadFromDB(); + assertTrue(testAdapter.getFunctions(schema).containsKey(functionName)); + assertTrue(testAdapter.getFunctions(schema).containsKey(functionNameTable)); + + restoreAdapter.restoreMetaObject(metaFunction); + restoreAdapter.restoreMetaObject(metaFunctionTable); + + dropTestTriggerProcedureFunctions(tableName); + assertFalse(testAdapter.getFunctions(schema).containsKey(functionName)); + assertFalse(testAdapter.getFunctions(schema).containsKey(functionNameTable)); + + + restoreAdapter.restoreMetaObject(metaFunction); + restoreAdapter.restoreMetaObject(metaFunctionTable); + assertTrue(testAdapter.getFunctions(schema).containsKey(functionName)); + assertTrue(testAdapter.getFunctions(schema).containsKey(functionNameTable)); + } + + @Test + public void restoreProcedure() throws Exception{ + DBRestoreProcedureMssql restoreAdapter = (DBRestoreProcedureMssql) testRestoreFactory.getAdapterRestore(DBGitMetaType.DbGitProcedure,testAdapter); + String tableName = "someTestTable"; + + createTestTriggerProcedureFunctions(tableName); + MetaProcedure metaProcedure = new MetaProcedure(testAdapter.getProcedure(schema, procedureName)); + metaProcedure.loadFromDB(); + restoreAdapter.restoreMetaObject(metaProcedure); + assertTrue(testAdapter.getProcedures(schema).containsKey(procedureName)); + + dropTestTriggerProcedureFunctions(tableName); + assertFalse(testAdapter.getProcedures(schema).containsKey(procedureName)); + + restoreAdapter.restoreMetaObject(metaProcedure); + assertTrue(testAdapter.getProcedures(schema).containsKey(procedureName)); + } + + @Test + public void restoreTriggerEncryptedNotExist() throws Exception{ + List ddls = createTestTriggerProcedureFunctions(tableName); + assertTrue(testAdapter.getTriggers(schema).containsKey(triggerNameEncr)); + + MetaTrigger metaTriggerEncr = new MetaTrigger(testAdapter.getTrigger(schema, triggerNameEncr)); + metaTriggerEncr.loadFromDB(); + + dropTestTriggerProcedureFunctions(tableName); + restoreTrigger.restoreMetaObject(metaTriggerEncr); + + assertFalse(testAdapter.getTriggers(schema).containsKey(triggerNameEncr)); + } + + @Test + public void restoreTriggerExisting() throws Exception{ + List ddls = createTestTriggerProcedureFunctions(tableName); + assertTrue(testAdapter.getTriggers(schema).containsKey(triggerName)); + + MetaTrigger metaTrigger = new MetaTrigger(testAdapter.getTrigger(schema, triggerName)); + metaTrigger.loadFromDB(); + + restoreTrigger.restoreMetaObject(metaTrigger); + + assertTrue(testAdapter.getTriggers(schema).containsKey(triggerName)); + } + + @Test + public void restoreTriggerAltered() throws Exception{ + String triggerDdl = createTestTriggerProcedureFunctions(tableName).get(7); + assertTrue(testAdapter.getTriggers(schema).containsKey(triggerName)); + + MetaTrigger metaTrigger = new MetaTrigger(testAdapter.getTrigger(schema, triggerName)); + metaTrigger.loadFromDB(); + + try(Statement st = testConnection.createStatement()){ + st.execute(MessageFormat.format( + "ALTER TRIGGER {0}.{1} ON {2} {3}", + schema, triggerName, tableName, "AFTER UPDATE AS RAISERROR ('An Update is performed on the "+tableName+" table', 0, 0);" + )); + } + + restoreTrigger.restoreMetaObject(metaTrigger); + + assertTrue(testAdapter.getTriggers(schema).containsKey(triggerName)); + assertTrue(testAdapter.getTrigger(schema, triggerName).getSql().equals(triggerDdl)); + } + + @Test + public void restoreTriggerAfterDrop() throws Exception { + List ddls = createTestTriggerProcedureFunctions(tableName); + String triggerDdl = ddls.get(7); + String tableCreateDdl = ddls.get(0); + assertTrue(testAdapter.getTriggers(schema).containsKey(triggerNameEncr)); + + MetaTrigger metaTrigger = new MetaTrigger(testAdapter.getTrigger(schema, triggerName)); + metaTrigger.loadFromDB(); + + try(Statement st = testConnection.createStatement()){ + st.execute("DROP TRIGGER " + triggerName); + } + restoreTrigger.restoreMetaObject(metaTrigger); + + assertTrue(testAdapter.getTriggers(schema).containsKey(triggerName)); + assertTrue(testAdapter.getTrigger(schema, triggerName).getSql().equals(triggerDdl)); + } + + //heplers + + public void dropBackupObjects() throws Exception{ + Map tables = testAdapter.getTables(schema); + for (DBTable table : tables.values()){ + if(table.getName().startsWith("BACKUP$")){ + ConsoleWriter.println("drop "+table.getName(), messageLevel); + dropTable(schema+"."+table.getName()); + } + } + + Map views = testAdapter.getViews(schema); + for (DBView view : views.values()){ + if(view.getName().startsWith("BACKUP$")){ + ConsoleWriter.println("drop "+view.getName(), messageLevel); + dropView(schema+"."+view.getName()); + } + } + + Map Triggers = testAdapter.getTriggers(schema); + for (DBTrigger Trigger : Triggers.values()){ + if(Trigger.getName().startsWith("BACKUP$")){ + ConsoleWriter.println("drop "+Trigger.getName(), messageLevel); + dropTrigger(schema+"."+Trigger.getName()); + } + } + + Map Procedures = testAdapter.getProcedures(schema); + for (DBProcedure Procedure : Procedures.values()){ + if(Procedure.getName().startsWith("BACKUP$")){ + ConsoleWriter.println("drop "+Procedure.getName(), messageLevel); + dropProcedure(schema+"."+Procedure.getName()); + } + } + + Map Functions = testAdapter.getFunctions(schema); + for (DBFunction Function : Functions.values()){ + if(Function.getName().startsWith("BACKUP$")){ + ConsoleWriter.println("drop "+Function.getName(), messageLevel); + dropFunction(schema+"."+Function.getName()); + } + } + + + } + + + + public boolean trySetMasterCatalog(){ + try { + if (!isMasterDatabase) { + testConnection.setCatalog("master"); + } + return true; + } catch (Exception e){ + System.out.println("Could not switch to master database"); + return false; + } + } + + public boolean trySetInnitialCatalog(){ + try { + testConnection.setCatalog(TEST_CONN_CATALOG); + return true; + } catch (Exception e){ + System.out.println("Could not switch to master database"); + return false; + } + } + + public void executeSqlInMaster(String expression, boolean commitAfter) throws SQLException{ + testConnection.setCatalog("master"); + + Statement stmt = testConnection.createStatement(); + stmt.execute(expression); + stmt.close(); + + if(commitAfter) testConnection.commit(); + testConnection.setCatalog(TEST_CONN_CATALOG); + } + + public void executeSqlInMaster(List expressions, boolean commitAfter) throws SQLException{ + testConnection.setCatalog("master"); + + Statement stmt = testConnection.createStatement(); + for(String expr : expressions) stmt.execute(expr); + stmt.close(); + + if(commitAfter) testConnection.commit(); + testConnection.setCatalog(TEST_CONN_CATALOG); + + } + + public boolean getIsDbOwner() throws Exception{ + Statement stmt = testConnection.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT IS_ROLEMEMBER ('db_owner') "); + + rs.next(); + boolean isDbo = rs.getBoolean(1); + + stmt.close(); + return isDbo; + } + + public void dropSchema(String schemaName) throws Exception{ + Statement stmt = testConnection.createStatement(); + stmt.execute( + "IF EXISTS ( SELECT * FROM sys.schemas WHERE name = N'"+schemaName+"' )\n" + + "DROP SCHEMA ["+schemaName+"];" + ); + stmt.close(); + } + + public void dropRole(String roleName) throws Exception{ + Statement stmt = testConnection.createStatement(); + stmt.execute( + "IF EXISTS (SELECT 1 FROM sys.database_principals WHERE name='"+roleName+"' AND Type = 'R')" + + "DROP ROLE ["+roleName+"];" + ); + stmt.close(); + } + + public DBAdapterMssql createAdapterWithCredentials(String username, String password, String url) throws Exception{ + Properties props = new Properties(); + props.setProperty("url", Objects.nonNull(url) ? url : TEST_CONN_STRING); + props.setProperty("user", Objects.nonNull(username) ? username : TEST_CONN_USER); + props.setProperty("password", Objects.nonNull(password) ? password : TEST_CONN_USER); + props.put("characterEncoding", "UTF-8"); + + Connection conn = DriverManager.getConnection(props.getProperty("url"), props); + conn.setAutoCommit(false); + + DBAdapterMssql adapter = new DBAdapterMssql(); + adapter.setConnection(conn); + adapter.registryMappingTypes(); + + return adapter; + } + + public void createUserAndLogin(String userName, String loginName, String schemaName, String password, boolean isHashed) throws Exception{ + Statement stmt = testConnection.createStatement(); + String passExpr = (isHashed) ? password + " HASHED" : "'" + password + "'"; + + List createUserExprs = Arrays.asList( + ( + "IF EXISTS (SELECT * FROM sys.database_principals WHERE name = N'"+userName+"') DROP USER ["+userName+"];" + + "IF EXISTS (SELECT * FROM sys.server_principals WHERE name = N'"+loginName+"') DROP LOGIN ["+loginName+"];" + + "CREATE LOGIN ["+loginName+"] WITH PASSWORD = "+passExpr+";" + + "CREATE USER ["+userName+"] FOR LOGIN ["+loginName+"] WITH DEFAULT_SCHEMA = ["+schemaName+"];" + ).split(";") + ); + + for(String expr : createUserExprs) stmt.execute(expr); + stmt.close(); + testConnection.commit(); + + executeSqlInMaster("GRANT CONNECT SQL TO ["+loginName+"]", true); + + } + + public void dropUserAndLogin(String userName, String loginName) throws Exception{ + String dropUserExpr = "DROP LOGIN ["+loginName+"]; DROP USER ["+userName+"]"; + Statement stmt = testConnection.createStatement(); + stmt.execute(dropUserExpr); + stmt.close(); + } + + public void addToRole(String userName, String roleName) throws Exception{ + Statement stmt = testConnection.createStatement(); + stmt.execute("EXECUTE sp_AddRoleMember '"+roleName+"', '"+userName+"';"); + stmt.close(); + } + + public String createTable(String schemaAndName, String fieldsExpr) throws Exception{ + + try (Statement stmt = testConnection.createStatement()){ + String name = convertSchemaAndName(schemaAndName); + String ddl = "CREATE TABLE "+schemaAndName+"("+fieldsExpr+") ON [PRIMARY]\n"; + stmt.execute("IF OBJECT_ID('"+name+"', 'U') IS NOT NULL DROP TABLE " + name); + stmt.execute(ddl); + return ddl; + } + } + + public void dropTable(String schemaName, String tableName) throws Exception{ + dropTable(schemaName+"."+tableName); + } + + public void dropTable(String schemaAndName) throws Exception{ + Statement stmt = testConnection.createStatement(); + String name = convertSchemaAndName(schemaAndName); + String ddl = MessageFormat.format("IF OBJECT_ID(''{0}'', ''U'') IS NOT NULL DROP TABLE {0}", name); + stmt.execute(ddl); + stmt.close(); + } + + public void dropView(String schemaAndName) throws Exception{ + Statement stmt = testConnection.createStatement(); + String name = convertSchemaAndName(schemaAndName); + String ddl = MessageFormat.format("IF OBJECT_ID(''{0}'', ''V'') IS NOT NULL DROP VIEW {0}", name); + stmt.execute(ddl); + stmt.close(); + } + + public void dropTrigger(String schemaAndName) throws Exception{ + Statement stmt = testConnection.createStatement(); + String name = convertSchemaAndName(schemaAndName); + String ddl = MessageFormat.format("IF OBJECT_ID(''{0}'', ''TR'') IS NOT NULL DROP TRIGGER {0}", name); + stmt.execute(ddl); + stmt.close(); + } + + public void dropProcedure(String schemaAndName) throws Exception{ + Statement stmt = testConnection.createStatement(); + String name = convertSchemaAndName(schemaAndName); + String ddl = MessageFormat.format("IF OBJECT_ID(''{0}'', ''P'') IS NOT NULL DROP PROCEDURE {0}", name); + stmt.execute(ddl); + stmt.close(); + } + + public void dropFunction(String schemaAndName) throws Exception{ + Statement stmt = testConnection.createStatement(); + String name = convertSchemaAndName(schemaAndName); + String ddl1 = MessageFormat.format("IF OBJECT_ID(''{0}'', ''FN'') IS NOT NULL DROP FUNCTION {0}", name); + String ddl2 = MessageFormat.format("IF OBJECT_ID(''{0}'', ''IF'') IS NOT NULL DROP FUNCTION {0}", name); + String ddl3 = MessageFormat.format("IF OBJECT_ID(''{0}'', ''TF'') IS NOT NULL DROP FUNCTION {0}", name); + stmt.execute(ddl1); + stmt.execute(ddl2); + stmt.execute(ddl3); + stmt.close(); + } + + public String convertSchemaAndName(String san) { + return san.startsWith("#") + ? "tempdb.." + san.substring(1) + : san; + } + + //entire sets + + private void createTestConstraintsAndTables(String tableName) throws SQLException { + createTestConstraintsAndTables(schema, tableName); + } + + private void createTestConstraintsAndTables(String schema, String tableName) throws SQLException { + String constrDDL1 = "ALTER TABLE "+ schema + "." + tableName + " ADD CONSTRAINT df_constraint DEFAULT ('{}') FOR [value];"; + String constrDDL2 = "ALTER TABLE "+ schema + "." + tableName + " ADD CONSTRAINT df_constraintInt DEFAULT ((1)) FOR [valueCheck1];"; + String constrDDL3 = "ALTER TABLE "+ schema + "." + tableName + " ADD CONSTRAINT u_constraint UNIQUE NONCLUSTERED ([valueUnique]);"; + String constrDDL4 = "ALTER TABLE "+ schema + "." + tableName + " ADD CONSTRAINT chk_constraint CHECK (valueCheck1>(0) AND valueCheck2>(0));"; + String constrDDL5 = "ALTER TABLE "+ schema + "." + tableName + " ADD CONSTRAINT fk_constraint FOREIGN KEY (fkInt) references " + schema + "." + tableName + "FK(keyInt);"; + + Statement stmt = testConnection.createStatement(); + stmt.execute( + "IF OBJECT_ID('"+ schema + "." + tableName + "', 'U') IS NOT NULL DROP TABLE "+ schema + "." + tableName + ";\n" + + + "CREATE TABLE "+ schema + "." + tableName + " (\n" + + " [key] varchar(20) PRIMARY KEY, \n" + + " [value] varchar(20) NOT NULL, \n" + + " [valueCheck1] int NOT NULL, \n" + + " [valueCheck2] int NOT NULL, \n" + + " [valueUnique] varchar(20),\n" + + " [fkInt] int\n" + + ") ON [PRIMARY];\n" + + + "IF OBJECT_ID('"+ schema + "." + tableName + "FK', 'U') IS NOT NULL DROP TABLE "+ schema + "." + tableName + "FK ;\n" + + + "CREATE TABLE "+ schema + "." + tableName + "FK ( keyInt int PRIMARY KEY, valueChar nvarchar(100) );\n" + ); + + stmt.execute(constrDDL1 + constrDDL2 + constrDDL3 + constrDDL4 + constrDDL5); + stmt.close(); + } + + private void dropTestConstraintsAndTables(String tableName) throws Exception {dropTestConstraintsAndTables(schema, tableName);} + private void dropTestConstraintsAndTables(String schema, String tableName) throws Exception { + dropTable(schema+"."+tableName); + dropTable(schema+"."+tableName+"FK"); +// testConnection.commit(); + } + + public AutoCloseable useTestSequence(String sequenceName) throws Exception{ + return new AutoCloseable() { + { + createTestSequence(sequenceName); + } + + @Override + public void close() throws Exception { + dropTestSequence(sequenceName); + } + }; + } + + + private String createTestSequence(String sequenceName) throws SQLException { + String dieDdl = + "IF EXISTS (SELECT * FROM sys.sequences WHERE NAME = N'"+sequenceName+"' AND TYPE='SO')\n" + + "DROP Sequence "+sequenceName+"\n"; + String crDdl = + "CREATE SEQUENCE "+sequenceName+"\n" + + "START WITH 1\n" + + "INCREMENT BY 1;\n"; + + try(Statement stmt = testConnection.createStatement()){ + stmt.execute(dieDdl + crDdl); + } + return crDdl; + } + + public void dropTestSequence(String sequenceName) throws Exception{ + Statement stmt = testConnection.createStatement(); + stmt.execute( + "IF EXISTS (SELECT * FROM sys.sequences WHERE NAME = N'"+sequenceName+"' AND TYPE='SO')\n" + + "DROP Sequence "+sequenceName+"\n" + ); + stmt.close(); + } + + public String createTestRoleAndStuff(String roleName, String userName, String tableSchemaAndName) throws Exception{ + Statement stmt = testConnection.createStatement(); + + String createUserExpr = + "CREATE USER ["+userName+"] WITHOUT LOGIN;"; + + String createRoleExpr = + "CREATE ROLE [ROLENAME];" + + "GRANT CONTROL ON [SCHEMA].[TABLENAME] TO [ROLENAME];" + + "GRANT DELETE ON [SCHEMA].[TABLENAME] TO [ROLENAME];" + + "GRANT INSERT ON [SCHEMA].[TABLENAME] TO [ROLENAME];" + + "GRANT TAKE OWNERSHIP ON [SCHEMA].[TABLENAME] TO [ROLENAME];" + + "EXECUTE sp_AddRoleMember '"+roleName+"', '"+userName+"';"; + + createRoleExpr = createRoleExpr + .replace("[ROLENAME]", "["+roleName+"]") + .replace("[SCHEMA].[TABLENAME]", tableSchemaAndName); + + String dropRoleExpr = "IF EXISTS (SELECT * FROM sys.database_principals WHERE name = N'"+roleName+"') DROP ROLE ["+roleName+"];"; + String dropUserExpr = "IF EXISTS (SELECT * FROM sys.database_principals WHERE name = N'"+userName+"') DROP USER ["+userName+"];"; + + //build execution pipeline + ArrayList exprs = new ArrayList<>(); + exprs.add(dropUserExpr); + exprs.add(dropRoleExpr); + exprs.add(createUserExpr); + exprs.addAll(Arrays.asList(createRoleExpr.split(";"))); + + + //table for testing permissions + createTable(tableSchemaAndName, "[someKey] int PRIMARY KEY"); + + + //execute scripts + for(String expr : exprs) { + stmt.execute(expr); + } + + stmt.close(); + + return createRoleExpr; + } + + public void dropTestRoleAndStuff(String roleName, String userName, String tableSchemaAndName) throws Exception{ + Statement stmt = testConnection.createStatement(); + + String dropRoleExpr = "IF EXISTS (SELECT * FROM sys.database_principals WHERE name = N'"+roleName+"') DROP ROLE ["+roleName+"];"; + String dropUserExpr = "IF EXISTS (SELECT * FROM sys.database_principals WHERE name = N'"+userName+"') DROP USER ["+userName+"];"; + + stmt.execute(dropUserExpr); + stmt.execute(dropRoleExpr); + stmt.close(); + + dropTable(tableSchemaAndName); + } + + public String createTestIndex(String tableName) throws Exception{ + String schema = testConnection.getSchema(); + return createTestIndex(schema, tableName); + } + + public String createTestIndex(String schemaName, String tableName) throws Exception{ + dropTestIndex(schemaName, tableName); + String indexCreateDdl = "CREATE NONCLUSTERED INDEX [IX_IdTest] ON ["+schema+"].["+tableName+"] ([Id], [Name]) ON [PRIMARY];"; + createTable( +schema + "." + tableName, + " [Id] [nvarchar](128) NOT NULL, " + + " [Name] [nvarchar](256) NOT NULL, " + + " CONSTRAINT [TestConstraint] PRIMARY KEY CLUSTERED \n" + + " ([Id] ASC) " + + " WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]\n" + ); + + Statement stmt = testConnection.createStatement(); + stmt.execute(indexCreateDdl); + stmt.close(); + return indexCreateDdl; + } + + public void dropTestIndex(String tableName)throws Exception{ dropTestIndex(schema, tableName); } + + public void dropTestIndex(String schema, String tableName)throws Exception{ + Statement stmt = testConnection.createStatement(); + + dropTable(schema + "." + tableName); + String ddl = + "IF EXISTS (SELECT 1 FROM sys.indexes WHERE object_id = OBJECT_ID(N'"+schema+"."+tableName+"') AND name = 'IX_IdTest') " + + "DROP INDEX IX_IdTest ON " + schema + "." + tableName + "\n"; + stmt.execute(ddl); + stmt.close(); + } + + public void createBigDummyTable() throws Exception{ + + Statement stmt = testConnection.createStatement(); + List scripts = Lists.newArrayList( + "IF OBJECT_ID('tempdb..#bigDummyTable', 'U') IS NOT NULL DROP TABLE #bigDummyTable\n", + + "WITH e1(n) AS ( \n" + + " SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL \n" + + " SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL \n" + + " SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 ), -- 10\n" + + "e2(n) AS (SELECT 1 FROM e1 CROSS JOIN e1 b), -- 10*10\n" + + "e3(n) AS (SELECT 1 FROM e1 CROSS JOIN e2), -- 10*100\n" + + "e4(n) AS (SELECT 1 FROM e1 CROSS JOIN e3), -- 10*1000\n" + + "e5(n) AS (SELECT 1 FROM e1 CROSS JOIN e4) -- 10*10000\n" + + "SELECT n1 = ROW_NUMBER() OVER (ORDER BY n) \n" + + "INTO #bigDummyTable FROM e5 ORDER BY n1" + ); + + for (String script : scripts){ + stmt.execute(script); + } + stmt.close(); + } + + public void dropBigDummyTable() throws Exception{ + + Statement stmt = testConnection.createStatement(); + try { stmt.execute("DROP TABLE tempdb..#bigDummyTable\n"); } catch (SQLException ex) { + ConsoleWriter.println("Failed to drop #bigDummyTable", messageLevel); + } + stmt.close(); + } + + public AutoCloseable useTestView(String schemaName, String viewName) throws Exception{ + return new AutoCloseable() { + private Statement stmt = testConnection.createStatement(); + + { + stmt.execute("IF OBJECT_ID('"+schemaName+" ."+viewName+"', 'V') IS NOT NULL DROP VIEW "+schemaName+"."+viewName+" \n"); + stmt.execute( + "CREATE VIEW "+schemaName+"."+viewName+" AS\n" + + "SELECT SC.name + '(' + SO.NAME + ')' as theUsualTitle\n" + + "FROM sys.columns SC JOIN sys.objects SO on SC.object_id = SO.object_id\n" + ); + stmt.execute( + "ALTER VIEW "+schemaName+"."+viewName+" AS\n" + + "SELECT 'THE ALLMIGHT ''' + SC.name + ''' FROM ' + SO.name as theBigTitle\n" + + "FROM sys.columns SC JOIN sys.objects SO on SC.object_id = SO.object_id\n" + ); + } + + @Override + public void close() throws Exception { + //did you know that in MessageFormat.format (') single quotes should be escaped by another ' single quote -> ('') ? + stmt.execute(MessageFormat.format("IF OBJECT_ID(''{0}.{1}'', ''V'') IS NOT NULL DROP VIEW {0}.{1} \n", schemaName, viewName)); + stmt.close(); + } + }; + } + + private String createTestView(String schemaName, String viewName) throws Exception{ + String viewDDl = + "CREATE VIEW "+schemaName+"."+viewName+" AS\n" + + "SELECT 'THE ALLMIGHT ''' + SC.name + ''' FROM ' + SO.name as theBigTitle\n" + + "FROM sys.columns SC JOIN sys.objects SO on SC.object_id = SO.object_id"; + + Statement stmt = testConnection.createStatement(); + stmt.execute("IF OBJECT_ID('"+schemaName+" ."+viewName+"', 'V') IS NOT NULL DROP VIEW "+schemaName+"."+viewName+" \n"); + stmt.execute( + "CREATE VIEW "+schemaName+"."+viewName+" AS\n" + + "SELECT SC.name + '(' + SO.NAME + ')' as theUsualTitle\n" + + "FROM sys.columns SC JOIN sys.objects SO on SC.object_id = SO.object_id\n"); + stmt.execute( + "ALTER VIEW "+schemaName+"."+viewName+" AS\n" + + "SELECT 'THE ALLMIGHT ''' + SC.name + ''' FROM ' + SO.name as theBigTitle\n" + + "FROM sys.columns SC JOIN sys.objects SO on SC.object_id = SO.object_id\n"); + stmt.close(); + + return viewDDl; + + } + + public void dropTestView(String schemaName, String viewName) throws Exception{ + Statement stmt = testConnection.createStatement(); + + stmt.execute("IF OBJECT_ID('"+schemaName+"."+viewName+"', 'V') IS NOT NULL DROP VIEW "+schemaName+"."+viewName+" \n"); + stmt.close(); + testConnection.commit(); + } + + private List createTestTriggerProcedureFunctions(String tableName) throws Exception{ + + Statement stmt = testConnection.createStatement(); + String schema = testConnection.getSchema(); + String sam = schema+"."+tableName; + String functionSam = schema + "." + functionName; + String functionSamTable = functionSam + "Table"; + String functionSamScalar = functionSam; + String procedureSam = MessageFormat.format("{0}.{1}", schema, procedureName); + String triggerSam = MessageFormat.format("{0}.{1}", schema, triggerName); + String triggerSamEncrypted = MessageFormat.format("{0}.{1}", schema, triggerNameEncr); + + ArrayList scripts = Lists.newArrayList( + + // (0) table + "IF OBJECT_ID('"+sam+"', 'U') IS NOT NULL DROP TABLE "+sam+"\n" + + "CREATE TABLE "+sam+" (\n" + + " [id] int PRIMARY KEY, \n" + + " [val] varchar(250) NULL DEFAULT ('Hey, I have some!')\n" + + ") ON [PRIMARY]\n" + + "INSERT INTO "+sam+" VALUES (1, DEFAULT)\n", + + // (1) drop if exists function scalar + "IF object_id(N'"+functionSamScalar+"', N'FN') IS NOT NULL DROP FUNCTION "+functionSamScalar+"\n", + + // (2) function scalar ddl + "CREATE FUNCTION "+functionSamScalar+" (@input VARCHAR(250), @toReplace VARCHAR(100))\n" + + "RETURNS VARCHAR(250)\n" + + "AS BEGIN\n" + + " DECLARE @Work VARCHAR(250)\n" + + " SET @Work = @Input\n" + + " SET @Work = REPLACE(@Work, @toReplace, '[' + @toReplace + ']')\n" + + " RETURN @work\n" + + "END", + + // (3) drop if exists function table + "IF object_id(N'"+functionSamTable+"', N'TF') IS NOT NULL DROP FUNCTION "+functionSamTable+"\n", + + // (4) function table ddl + "CREATE FUNCTION "+functionSamTable+"(\n" + + " @find varchar(100)\n" + + ")\n" + + "RETURNS @Result TABLE\n" + + "(\n" + + " id int ,\n" + + " val char(100)\n" + + ") AS BEGIN\n" + + " INSERT INTO @Result SELECT * FROM "+sam+" et WHERE et.val LIKE '%' + @find + '%'\n" + + " INSERT INTO @Result SELECT\n" + + " (SELECT MAX(ett.id) FROM "+sam+" ett) + 1 as id, "+functionSamScalar+"(et.val, @find) as val FROM "+sam+" et\n" + + " WHERE et.val LIKE '%' + @find + '%'\n" + + "RETURN END", + + // (5) drop if exists procedure and triggers + "IF OBJECT_ID('"+procedureSam+"', 'P') IS NOT NULL DROP PROCEDURE "+procedureSam+"\n" + + "IF OBJECT_ID('"+triggerName+"', 'TR') IS NOT NULL DROP TRIGGER "+triggerName+"\n" + + "IF OBJECT_ID('"+triggerNameEncr+"', 'TR') IS NOT NULL DROP TRIGGER "+triggerNameEncr+"\n", + + // (6) procedure ddl + "CREATE PROCEDURE "+procedureSam+" @word varchar(100) AS\n" + + "BEGIN\n" + + " SELECT *\n" + + " FROM "+functionSamTable+"(@word) t\n" + + "END", + + // (7) trigger ddl + "CREATE TRIGGER "+triggerSam+"\n" + + "ON "+sam+"\n" + + "AFTER DELETE\n" + + "NOT FOR REPLICATION\n" + + "AS INSERT INTO "+sam+" SELECT * FROM deleted", + + // (8) trigger encrypted ddl + "CREATE TRIGGER "+triggerSamEncrypted+"\n" + + "ON "+sam+"\n" + + "WITH ENCRYPTION\n" + + "AFTER DELETE\n" + + "AS INSERT INTO "+sam+" SELECT * FROM deleted" + ); + + for (String script : scripts){ + stmt.execute(script); + } + stmt.close(); + testConnection.commit(); + return scripts; + } + + private void dropTestTriggerProcedureFunctions(String tableName) throws Exception{ + String schema = testConnection.getSchema(); + String sam = schema+"."+tableName; + String functionSam = schema + "." + functionName; + String functionSamTable = functionSam + "Table"; + String functionSamScalar = functionSam; + String procedureSam = MessageFormat.format("{0}.{1}", schema, procedureName); + + Statement stmt = testConnection.createStatement(); + stmt.execute( + MessageFormat.format( + "DROP TABLE {0}\nDROP FUNCTION {1}, {2}\nDROP PROCEDURE {3}\n", + sam, functionSamScalar, functionSamTable, procedureSam + ) + ); + stmt.close(); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/utils/MaskFilterTest.java b/src/test/java/ru/fusionsoft/dbgit/utils/MaskFilterTest.java new file mode 100644 index 0000000..3a7b090 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/utils/MaskFilterTest.java @@ -0,0 +1,29 @@ +package ru.fusionsoft.dbgit.utils; + +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +public class MaskFilterTest { + + @Test + public void match() { + MaskFilter mf = new MaskFilter("pub*.*"); + + String textTbl = "public/ad_group_roles.tbl"; + String textCsv = "public/ad_group_roles.csv"; + + assertTrue(mf.match(textTbl)); + assertTrue(mf.match(textCsv)); + } + + @Test + public void matchExtention() { + MaskFilter mfCsv = new MaskFilter("pub*lic*.csv"); + + String textTbl = "public/ad_group_roles.tbl"; + String textCsv = "public/ad_group_roles.csv"; + + assertFalse(mfCsv.match(textTbl)); + assertTrue(mfCsv.match(textCsv)); + } +} \ No newline at end of file diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml new file mode 100644 index 0000000..61d5b6b --- /dev/null +++ b/src/test/resources/logback-test.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + .dbgit/logs + + + + + + + + + ${log_dir_rep}/log-${time}.log + + + ${log_dir_home}/log-${time}.log + + + + + %date %level [%thread] %logger{10} [%file:%line] %msg%n + + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + --> + + + + \ No newline at end of file