]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-8025 improve column name checks + factor with table name check
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Wed, 14 Sep 2016 09:06:22 +0000 (11:06 +0200)
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Fri, 16 Sep 2016 10:22:12 +0000 (12:22 +0200)
15 files changed:
sonar-db/src/main/java/org/sonar/db/version/BigIntegerColumnDef.java
sonar-db/src/main/java/org/sonar/db/version/BlobColumnDef.java
sonar-db/src/main/java/org/sonar/db/version/BooleanColumnDef.java
sonar-db/src/main/java/org/sonar/db/version/ClobColumnDef.java
sonar-db/src/main/java/org/sonar/db/version/ColumnDefValidation.java [deleted file]
sonar-db/src/main/java/org/sonar/db/version/CreateTableBuilder.java
sonar-db/src/main/java/org/sonar/db/version/DecimalColumnDef.java
sonar-db/src/main/java/org/sonar/db/version/IntegerColumnDef.java
sonar-db/src/main/java/org/sonar/db/version/TinyIntColumnDef.java
sonar-db/src/main/java/org/sonar/db/version/Validations.java [new file with mode: 0644]
sonar-db/src/main/java/org/sonar/db/version/VarcharColumnDef.java
sonar-db/src/test/java/org/sonar/db/version/BlobColumnDefTest.java
sonar-db/src/test/java/org/sonar/db/version/ColumnDefValidationTest.java [deleted file]
sonar-db/src/test/java/org/sonar/db/version/IntegerColumnDefTest.java
sonar-db/src/test/java/org/sonar/db/version/ValidationsTest.java [new file with mode: 0644]

index 687ce188304b06b6df882387d1102a21b8d1a9fa..dc62060e71c2a033af860238562bd169a97d82c7 100644 (file)
@@ -23,7 +23,7 @@ import javax.annotation.CheckForNull;
 import org.sonar.db.dialect.Dialect;
 import org.sonar.db.dialect.Oracle;
 
-import static org.sonar.db.version.ColumnDefValidation.validateColumnName;
+import static org.sonar.db.version.Validations.validateColumnName;
 
 public class BigIntegerColumnDef extends AbstractColumnDef {
 
index c049be66cd91a48b66f804996bfb4655f8821f05..31e51fb98979e6dce889dcf34bf2520d303f0e4a 100644 (file)
@@ -27,7 +27,7 @@ import org.sonar.db.dialect.MySql;
 import org.sonar.db.dialect.Oracle;
 import org.sonar.db.dialect.PostgreSql;
 
-import static org.sonar.db.version.ColumnDefValidation.validateColumnName;
+import static org.sonar.db.version.Validations.validateColumnName;
 
 public class BlobColumnDef extends AbstractColumnDef {
   public BlobColumnDef(Builder builder) {
index 96d9d19a23bc16ac448c3e2d69bd1f59962b2336..c2cd7d17789c6c5f6f6b4e92cf42f0c586fa834b 100644 (file)
@@ -26,7 +26,7 @@ import org.sonar.db.dialect.MySql;
 import org.sonar.db.dialect.Oracle;
 import org.sonar.db.dialect.PostgreSql;
 
-import static org.sonar.db.version.ColumnDefValidation.validateColumnName;
+import static org.sonar.db.version.Validations.validateColumnName;
 
 /**
  * Used to define VARCHAR column
index 51fa170c4053fab4bd53ac7601a02eadb322e9b8..a57f0043a2e6a236d0e0f7e2ab0b65be5cfb60ec 100644 (file)
@@ -27,7 +27,7 @@ import org.sonar.db.dialect.MySql;
 import org.sonar.db.dialect.Oracle;
 import org.sonar.db.dialect.PostgreSql;
 
-import static org.sonar.db.version.ColumnDefValidation.validateColumnName;
+import static org.sonar.db.version.Validations.validateColumnName;
 
 /**
  * Used to define CLOB columns
diff --git a/sonar-db/src/main/java/org/sonar/db/version/ColumnDefValidation.java b/sonar-db/src/main/java/org/sonar/db/version/ColumnDefValidation.java
deleted file mode 100644 (file)
index 49d64ab..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.db.version;
-
-import com.google.common.base.CharMatcher;
-import javax.annotation.Nullable;
-
-import static com.google.common.base.CharMatcher.JAVA_LOWER_CASE;
-import static com.google.common.base.Preconditions.checkArgument;
-import static java.util.Objects.requireNonNull;
-
-public class ColumnDefValidation {
-
-  private ColumnDefValidation() {
-    // Only static stuff here
-  }
-
-  public static String validateColumnName(@Nullable String columnName) {
-    String name = requireNonNull(columnName, "Column name cannot be null");
-    checkArgument(JAVA_LOWER_CASE.or(CharMatcher.anyOf("_")).or(CharMatcher.DIGIT).matchesAllOf(name),
-      String.format("Column name should only contains lowercase and _ characters, got '%s'", columnName));
-    return name;
-  }
-}
index 462da8dd3d7597da5422ea8070d8c7ed1af414ff..f67b42b1d0ca07663fba974a2f9887fe322957c3 100644 (file)
@@ -19,7 +19,6 @@
  */
 package org.sonar.db.version;
 
-import com.google.common.base.CharMatcher;
 import com.google.common.collect.HashMultimap;
 import com.google.common.collect.Multimap;
 import java.util.ArrayList;
@@ -38,20 +37,15 @@ import org.sonar.db.dialect.MySql;
 import org.sonar.db.dialect.Oracle;
 import org.sonar.db.dialect.PostgreSql;
 
-import static com.google.common.base.CharMatcher.anyOf;
-import static com.google.common.base.CharMatcher.inRange;
 import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkState;
 import static java.util.Objects.requireNonNull;
 import static java.util.stream.Stream.of;
+import static org.sonar.db.version.Validations.CONSTRAINT_NAME_MAX_SIZE;
+import static org.sonar.db.version.Validations.TABLE_NAME_MAX_SIZE;
+import static org.sonar.db.version.Validations.checkDbIdentifier;
 
 public class CreateTableBuilder {
-  private static final int TABLE_NAME_MAX_SIZE = 25;
-  private static final int CONSTRAINT_NAME_MAX_SIZE = 30;
-  private static final CharMatcher DIGIT_CHAR_MATCHER = inRange('0', '9');
-  private static final CharMatcher LOWER_CASE_ASCII_LETTERS_CHAR_MATCHER = inRange('a', 'z');
-  private static final CharMatcher UNDERSCORE_CHAR_MATCHER = anyOf("_");
 
   private final Dialect dialect;
   private final String tableName;
@@ -136,20 +130,6 @@ public class CreateTableBuilder {
     return this;
   }
 
-  private static String checkDbIdentifier(String identifier, String identifierDesc, int maxSize) {
-    String res = checkNotNull(identifier, "%s can't be null", identifierDesc);
-    checkArgument(
-      identifier.length() <= maxSize,
-      "%s length can't be more than %s", identifierDesc, maxSize);
-    checkArgument(
-      LOWER_CASE_ASCII_LETTERS_CHAR_MATCHER.or(DIGIT_CHAR_MATCHER).or(anyOf("_")).matchesAllOf(identifier),
-      "%s must be lower case and contain only alphanumeric chars or '_', got '%s'", identifierDesc, identifier);
-    checkArgument(
-      DIGIT_CHAR_MATCHER.or(UNDERSCORE_CHAR_MATCHER).matchesNoneOf(identifier.subSequence(0, 1)),
-      "%s must not start by a number or '_', got '%s'", identifierDesc, identifier);
-    return res;
-  }
-
   private String createTableStatement() {
     StringBuilder res = new StringBuilder("CREATE TABLE ");
     res.append(tableName);
index 03327d4b6c54bbd2372db720048336c5852c78d8..ba4c46358ef4fa14c7e97f8b82c7d016bf248684 100644 (file)
@@ -27,7 +27,7 @@ import org.sonar.db.dialect.MySql;
 import org.sonar.db.dialect.Oracle;
 import org.sonar.db.dialect.PostgreSql;
 
-import static org.sonar.db.version.ColumnDefValidation.validateColumnName;
+import static org.sonar.db.version.Validations.validateColumnName;
 
 public class DecimalColumnDef extends AbstractColumnDef {
 
index 298bd2e95c2d71fc6742415df4da23426ce4c6e5..8b41a8a4ed8cb52c72b1c1994d60f65706e060e9 100644 (file)
@@ -27,7 +27,7 @@ import org.sonar.db.dialect.MySql;
 import org.sonar.db.dialect.Oracle;
 import org.sonar.db.dialect.PostgreSql;
 
-import static org.sonar.db.version.ColumnDefValidation.validateColumnName;
+import static org.sonar.db.version.Validations.validateColumnName;
 
 public class IntegerColumnDef extends AbstractColumnDef {
 
index 0f1f8ac544a5a37c25d9a9a4f698b031b02ac5c5..81fe6d06eb474f780bce2638097cebbd9cf57e73 100644 (file)
@@ -27,7 +27,7 @@ import org.sonar.db.dialect.MySql;
 import org.sonar.db.dialect.Oracle;
 import org.sonar.db.dialect.PostgreSql;
 
-import static org.sonar.db.version.ColumnDefValidation.validateColumnName;
+import static org.sonar.db.version.Validations.validateColumnName;
 
 /**
  * Integer that supports at least range [0..128]. Full range depends on database vendor.
diff --git a/sonar-db/src/main/java/org/sonar/db/version/Validations.java b/sonar-db/src/main/java/org/sonar/db/version/Validations.java
new file mode 100644 (file)
index 0000000..cf75f9f
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.db.version;
+
+import com.google.common.base.CharMatcher;
+import javax.annotation.Nullable;
+
+import static com.google.common.base.CharMatcher.anyOf;
+import static com.google.common.base.CharMatcher.inRange;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static java.util.Objects.requireNonNull;
+
+public class Validations {
+
+  static final int TABLE_NAME_MAX_SIZE = 25;
+  static final int CONSTRAINT_NAME_MAX_SIZE = 30;
+
+  private static final CharMatcher DIGIT_CHAR_MATCHER = inRange('0', '9');
+  private static final CharMatcher LOWER_CASE_ASCII_LETTERS_CHAR_MATCHER = inRange('a', 'z');
+  private static final CharMatcher UNDERSCORE_CHAR_MATCHER = anyOf("_");
+
+  private Validations() {
+    // Only static stuff here
+  }
+
+  static String validateColumnName(@Nullable String columnName) {
+    String name = requireNonNull(columnName, "Column name cannot be null");
+    checkDbIdentifierCharacters(columnName, "Column name");
+    return name;
+  }
+
+  /**
+   * Ensure {@code identifier} is a valid DB identifier.
+   *
+   * @throws NullPointerException if {@code identifier} is {@code null}
+   * @throws IllegalArgumentException if {@code identifier} is empty
+   * @throws IllegalArgumentException if {@code identifier} is longer than {@code maxSize}
+   * @throws IllegalArgumentException if {@code identifier} is not lowercase
+   * @throws IllegalArgumentException if {@code identifier} contains characters others than ASCII letters, ASCII numbers or {@code _}
+   * @throws IllegalArgumentException if {@code identifier} starts with {@code _} or a number
+   */
+  static String checkDbIdentifier(@Nullable String identifier, String identifierDesc, int maxSize) {
+    String res = checkNotNull(identifier, "%s can't be null", identifierDesc);
+    checkArgument(!res.isEmpty(), "%s, can't be empty", identifierDesc);
+    checkArgument(
+      identifier.length() <= maxSize,
+      "%s length can't be more than %s", identifierDesc, maxSize);
+    checkDbIdentifierCharacters(identifier, identifierDesc);
+    return res;
+  }
+
+  private static void checkDbIdentifierCharacters(String identifier, String identifierDesc) {
+    checkArgument(
+      LOWER_CASE_ASCII_LETTERS_CHAR_MATCHER.or(DIGIT_CHAR_MATCHER).or(anyOf("_")).matchesAllOf(identifier),
+      "%s must be lower case and contain only alphanumeric chars or '_', got '%s'", identifierDesc, identifier);
+    checkArgument(
+      DIGIT_CHAR_MATCHER.or(UNDERSCORE_CHAR_MATCHER).matchesNoneOf(identifier.subSequence(0, 1)),
+      "%s must not start by a number or '_', got '%s'", identifierDesc, identifier);
+  }
+}
index d8da72a48478ac103cf2305f9cec0d8a8a93b9f7..cfab9db27e51c65f9ccf339727b94ea3ce431044 100644 (file)
@@ -25,7 +25,7 @@ import org.sonar.db.dialect.MsSql;
 
 import static java.lang.String.format;
 import static java.util.Objects.requireNonNull;
-import static org.sonar.db.version.ColumnDefValidation.validateColumnName;
+import static org.sonar.db.version.Validations.validateColumnName;
 
 /**
  * Used to define VARCHAR column
index 94b6419b985d63c032aa3922a3a42398fb2f2726..9d06d1109b53b21138b2cfa384b7397608f1039a 100644 (file)
@@ -45,7 +45,7 @@ public class BlobColumnDefTest {
     BlobColumnDef.Builder builder = newBlobColumnDefBuilder();
 
     expectedException.expect(IllegalArgumentException.class);
-    expectedException.expectMessage("Column name should only contains lowercase and _ characters, got 'T'");
+    expectedException.expectMessage("Column name must be lower case and contain only alphanumeric chars or '_', got 'T'");
     builder.setColumnName("T");
   }
 
diff --git a/sonar-db/src/test/java/org/sonar/db/version/ColumnDefValidationTest.java b/sonar-db/src/test/java/org/sonar/db/version/ColumnDefValidationTest.java
deleted file mode 100644 (file)
index 77ed523..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.db.version;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-
-import static org.sonar.db.version.ColumnDefValidation.validateColumnName;
-
-public class ColumnDefValidationTest {
-
-  @Rule
-  public ExpectedException thrown = ExpectedException.none();
-
-  @Test
-  public void accept_valid_table_name() throws Exception {
-    validateColumnName("date_in_ms");
-    validateColumnName("date_in_ms_1");
-  }
-
-  @Test
-  public void fail_with_NPE_if_name_is_null() throws Exception {
-    thrown.expect(NullPointerException.class);
-    thrown.expectMessage("Column name cannot be null");
-
-    validateColumnName(null);
-  }
-
-  @Test
-  public void fail_when_column_name_is_in_upper_case() {
-    thrown.expect(IllegalArgumentException.class);
-    thrown.expectMessage("Column name should only contains lowercase and _ characters, got 'DATE_IN_MS'");
-
-    validateColumnName("DATE_IN_MS");
-  }
-
-  @Test
-  public void fail_when_column_name_contains_invalid_character() {
-    thrown.expect(IllegalArgumentException.class);
-    thrown.expectMessage("Column name should only contains lowercase and _ characters, got 'date-in/ms'");
-
-    validateColumnName("date-in/ms");
-  }
-
-}
index 1508af300ee91303d4036bbf97a7c224dc59e962..935fb96cfd8948b41253ec211712de78dad181e2 100644 (file)
@@ -45,7 +45,7 @@ public class IntegerColumnDefTest {
     IntegerColumnDef.Builder builder = newIntegerColumnDefBuilder();
 
     expectedException.expect(IllegalArgumentException.class);
-    expectedException.expectMessage("Column name should only contains lowercase and _ characters, got 'T'");
+    expectedException.expectMessage("Column name must be lower case and contain only alphanumeric chars or '_', got 'T'");
     builder.setColumnName("T");
   }
 
diff --git a/sonar-db/src/test/java/org/sonar/db/version/ValidationsTest.java b/sonar-db/src/test/java/org/sonar/db/version/ValidationsTest.java
new file mode 100644 (file)
index 0000000..bd66ad3
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.db.version;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.sonar.db.version.Validations.validateColumnName;
+
+public class ValidationsTest {
+
+  @Rule
+  public ExpectedException thrown = ExpectedException.none();
+
+  @Test
+  public void accept_valid_table_name() throws Exception {
+    validateColumnName("date_in_ms");
+    validateColumnName("date_in_ms_1");
+  }
+
+  @Test
+  public void fail_with_NPE_if_name_is_null() throws Exception {
+    thrown.expect(NullPointerException.class);
+    thrown.expectMessage("Column name cannot be null");
+
+    validateColumnName(null);
+  }
+
+  @Test
+  public void fail_when_column_name_is_in_upper_case() {
+    thrown.expect(IllegalArgumentException.class);
+    thrown.expectMessage("Column name must be lower case and contain only alphanumeric chars or '_', got 'DATE_IN_MS'");
+
+    validateColumnName("DATE_IN_MS");
+  }
+
+  @Test
+  public void fail_when_column_name_contains_invalid_character() {
+    thrown.expect(IllegalArgumentException.class);
+    thrown.expectMessage("Column name must be lower case and contain only alphanumeric chars or '_', got 'date-in/ms'");
+
+    validateColumnName("date-in/ms");
+  }
+
+}