Initial Development #1

Merged
danieljsummers merged 88 commits from v1-rc into main 2025-04-16 01:29:20 +00:00
23 changed files with 820 additions and 321 deletions
Showing only changes of commit ecf71de1c4 - Show all commits

View File

@ -43,13 +43,13 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<groupId>org.apache.groovy</groupId>
<artifactId>groovy-test</artifactId>
<version>${groovy.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<groupId>org.apache.groovy</groupId>
<artifactId>groovy-test-junit5</artifactId>
<version>${groovy.version}</version>
<scope>test</scope>
@ -131,7 +131,10 @@
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<configuration>
<argLine>--add-opens java.base/java.lang=ALL-UNNAMED</argLine>
<argLine>
--add-opens=java.base/java.lang=ALL-UNNAMED
--add-opens=java.base/java.util=ALL-UNNAMED
</argLine>
</configuration>
</plugin>
<plugin>

View File

@ -6,7 +6,7 @@ import solutions.bitbadger.documents.AutoId
//import solutions.bitbadger.documents.DocumentException
import solutions.bitbadger.documents.groovy.support.*
import static groovy.test.GroovyAssert.*
import static org.junit.jupiter.api.Assertions.*
/**
* Unit tests for the `AutoId` enum
@ -17,21 +17,21 @@ class AutoIdTest {
@Test
@DisplayName('Generates a UUID string')
void generateUUID() {
assertEquals('The UUID should have been a 32-character string', 32, AutoId.generateUUID().length())
assertEquals 32, AutoId.generateUUID().length(), 'The UUID should have been a 32-character string'
}
@Test
@DisplayName('Generates a random hex character string of an even length')
void generateRandomStringEven() {
def result = AutoId.generateRandomString 8
assertEquals("There should have been 8 characters in $result", 8, result.length())
assertEquals 8, result.length(), "There should have been 8 characters in $result"
}
@Test
@DisplayName('Generates a random hex character string of an odd length')
void generateRandomStringOdd() {
def result = AutoId.generateRandomString 11
assertEquals("There should have been 11 characters in $result", 11, result.length())
assertEquals 11, result.length(), "There should have been 11 characters in $result"
}
@Test
@ -39,7 +39,7 @@ class AutoIdTest {
void generateRandomStringIsRandom() {
def result1 = AutoId.generateRandomString 16
def result2 = AutoId.generateRandomString 16
assertNotEquals('There should have been 2 different strings generated', result1, result2)
assertNotEquals result1, result2, 'There should have been 2 different strings generated'
}
// TODO: resolve java.base open issue
@ -59,63 +59,63 @@ class AutoIdTest {
@Test
@DisplayName('needsAutoId returns false if disabled')
void needsAutoIdFalseIfDisabled() {
assertFalse('Disabled Auto ID should always return false', AutoId.needsAutoId(AutoId.DISABLED, '', ''))
assertFalse AutoId.needsAutoId(AutoId.DISABLED, '', ''), 'Disabled Auto ID should always return false'
}
@Test
@DisplayName('needsAutoId returns true for Number strategy and byte ID of 0')
void needsAutoIdTrueForByteWithZero() {
assertTrue('Number Auto ID with 0 should return true',
AutoId.needsAutoId(AutoId.NUMBER, new ByteIdClass((byte) 0), 'id'))
assertTrue(AutoId.needsAutoId(AutoId.NUMBER, new ByteIdClass((byte) 0), 'id'),
'Number Auto ID with 0 should return true')
}
@Test
@DisplayName('needsAutoId returns false for Number strategy and byte ID of non-0')
void needsAutoIdFalseForByteWithNonZero() {
assertFalse('Number Auto ID with 77 should return false',
AutoId.needsAutoId(AutoId.NUMBER, new ByteIdClass((byte) 77), 'id'))
assertFalse(AutoId.needsAutoId(AutoId.NUMBER, new ByteIdClass((byte) 77), 'id'),
'Number Auto ID with 77 should return false')
}
@Test
@DisplayName('needsAutoId returns true for Number strategy and short ID of 0')
void needsAutoIdTrueForShortWithZero() {
assertTrue('Number Auto ID with 0 should return true',
AutoId.needsAutoId(AutoId.NUMBER, new ShortIdClass((short) 0), 'id'))
assertTrue(AutoId.needsAutoId(AutoId.NUMBER, new ShortIdClass((short) 0), 'id'),
'Number Auto ID with 0 should return true')
}
@Test
@DisplayName('needsAutoId returns false for Number strategy and short ID of non-0')
void needsAutoIdFalseForShortWithNonZero() {
assertFalse('Number Auto ID with 31 should return false',
AutoId.needsAutoId(AutoId.NUMBER, new ShortIdClass((short) 31), 'id'))
assertFalse(AutoId.needsAutoId(AutoId.NUMBER, new ShortIdClass((short) 31), 'id'),
'Number Auto ID with 31 should return false')
}
@Test
@DisplayName('needsAutoId returns true for Number strategy and int ID of 0')
void needsAutoIdTrueForIntWithZero() {
assertTrue('Number Auto ID with 0 should return true',
AutoId.needsAutoId(AutoId.NUMBER, new IntIdClass(0), 'id'))
assertTrue(AutoId.needsAutoId(AutoId.NUMBER, new IntIdClass(0), 'id'),
'Number Auto ID with 0 should return true')
}
@Test
@DisplayName('needsAutoId returns false for Number strategy and int ID of non-0')
void needsAutoIdFalseForIntWithNonZero() {
assertFalse('Number Auto ID with 6 should return false',
AutoId.needsAutoId(AutoId.NUMBER, new IntIdClass(6), 'id'))
assertFalse(AutoId.needsAutoId(AutoId.NUMBER, new IntIdClass(6), 'id'),
'Number Auto ID with 6 should return false')
}
@Test
@DisplayName('needsAutoId returns true for Number strategy and long ID of 0')
void needsAutoIdTrueForLongWithZero() {
assertTrue('Number Auto ID with 0 should return true',
AutoId.needsAutoId(AutoId.NUMBER, new LongIdClass(0L), 'id'))
assertTrue(AutoId.needsAutoId(AutoId.NUMBER, new LongIdClass(0L), 'id'),
'Number Auto ID with 0 should return true')
}
@Test
@DisplayName('needsAutoId returns false for Number strategy and long ID of non-0')
void needsAutoIdFalseForLongWithNonZero() {
assertFalse('Number Auto ID with 2 should return false',
AutoId.needsAutoId(AutoId.NUMBER, new LongIdClass(2L), 'id'))
assertFalse(AutoId.needsAutoId(AutoId.NUMBER, new LongIdClass(2L), 'id'),
'Number Auto ID with 2 should return false')
}
// TODO: resolve java.base open issue
@ -128,15 +128,15 @@ class AutoIdTest {
@Test
@DisplayName('needsAutoId returns true for UUID strategy and blank ID')
void needsAutoIdTrueForUUIDWithBlank() {
assertTrue('UUID Auto ID with blank should return true',
AutoId.needsAutoId(AutoId.UUID, new StringIdClass(''), 'id'))
assertTrue(AutoId.needsAutoId(AutoId.UUID, new StringIdClass(''), 'id'),
'UUID Auto ID with blank should return true')
}
@Test
@DisplayName('needsAutoId returns false for UUID strategy and non-blank ID')
void needsAutoIdFalseForUUIDNotBlank() {
assertFalse('UUID Auto ID with non-blank should return false',
AutoId.needsAutoId(AutoId.UUID, new StringIdClass('howdy'), 'id'))
assertFalse(AutoId.needsAutoId(AutoId.UUID, new StringIdClass('howdy'), 'id'),
'UUID Auto ID with non-blank should return false')
}
// TODO: resolve java.base open issue
@ -149,22 +149,22 @@ class AutoIdTest {
@Test
@DisplayName('needsAutoId returns true for Random String strategy and blank ID')
void needsAutoIdTrueForRandomWithBlank() {
assertTrue('Random String Auto ID with blank should return true',
AutoId.needsAutoId(AutoId.RANDOM_STRING, new StringIdClass(''), 'id'))
assertTrue(AutoId.needsAutoId(AutoId.RANDOM_STRING, new StringIdClass(''), 'id'),
'Random String Auto ID with blank should return true')
}
@Test
@DisplayName('needsAutoId returns false for Random String strategy and non-blank ID')
void needsAutoIdFalseForRandomNotBlank() {
assertFalse('Random String Auto ID with non-blank should return false',
AutoId.needsAutoId(AutoId.RANDOM_STRING, new StringIdClass('full'), 'id'))
assertFalse(AutoId.needsAutoId(AutoId.RANDOM_STRING, new StringIdClass('full'), 'id'),
'Random String Auto ID with non-blank should return false')
}
// TODO: resolve java.base open issue
// @Test
// @DisplayName('needsAutoId fails for Random String strategy and non-string ID')
// void needsAutoIdFailsForRandomNonString() {
// assertThrows(DocumentException.class) {
// assertThrows(DocumentException) {
// AutoId.needsAutoId(AutoId.RANDOM_STRING, new ShortIdClass((short) 55), 'id')
// }
// }

View File

@ -7,7 +7,7 @@ import solutions.bitbadger.documents.Configuration
import solutions.bitbadger.documents.Dialect
//import solutions.bitbadger.documents.DocumentException
import static groovy.test.GroovyAssert.*
import static org.junit.jupiter.api.Assertions.*
/**
* Unit tests for the `Configuration` object
@ -18,19 +18,19 @@ class ConfigurationTest {
@Test
@DisplayName('Default ID field is "id"')
void defaultIdField() {
assertEquals('Default ID field incorrect', 'id', Configuration.idField)
assertEquals 'id', Configuration.idField, 'Default ID field incorrect'
}
@Test
@DisplayName('Default Auto ID strategy is DISABLED')
void defaultAutoId() {
assertEquals('Default Auto ID strategy should be DISABLED', AutoId.DISABLED, Configuration.autoIdStrategy)
assertEquals AutoId.DISABLED, Configuration.autoIdStrategy, 'Default Auto ID strategy should be DISABLED'
}
@Test
@DisplayName('Default ID string length should be 16')
void defaultIdStringLength() {
assertEquals('Default ID string length should be 16', 16, Configuration.idStringLength)
assertEquals 16, Configuration.idStringLength, 'Default ID string length should be 16'
}
@Test
@ -40,7 +40,7 @@ class ConfigurationTest {
// TODO: uncomment once java.base open issue resolved
//assertThrows(DocumentException) { Configuration.dialect() }
Configuration.connectionString = 'jdbc:postgresql:db'
assertEquals(Dialect.POSTGRESQL, Configuration.dialect())
assertEquals Dialect.POSTGRESQL, Configuration.dialect()
} finally {
Configuration.connectionString = null
}

View File

@ -5,7 +5,7 @@ import org.junit.jupiter.api.Test
import solutions.bitbadger.documents.Dialect
import solutions.bitbadger.documents.DocumentException
import static groovy.test.GroovyAssert.*
import static org.junit.jupiter.api.Assertions.*
/**
* Unit tests for the `Dialect` enum
@ -16,27 +16,27 @@ class DialectTest {
@Test
@DisplayName('deriveFromConnectionString derives PostgreSQL correctly')
void derivesPostgres() {
assertEquals('Dialect should have been PostgreSQL', Dialect.POSTGRESQL,
Dialect.deriveFromConnectionString('jdbc:postgresql:db'))
assertEquals(Dialect.POSTGRESQL, Dialect.deriveFromConnectionString('jdbc:postgresql:db'),
'Dialect should have been PostgreSQL')
}
@Test
@DisplayName('deriveFromConnectionString derives SQLite correctly')
void derivesSQLite() {
assertEquals('Dialect should have been SQLite', Dialect.SQLITE,
Dialect.deriveFromConnectionString('jdbc:sqlite:memory'))
assertEquals(Dialect.SQLITE, Dialect.deriveFromConnectionString('jdbc:sqlite:memory'),
'Dialect should have been SQLite')
}
@Test
@DisplayName('deriveFromConnectionString fails when the connection string is unknown')
void deriveFailsWhenUnknown() {
try {
Dialect.deriveFromConnectionString('SQL Server')
fail('Dialect derivation should have failed')
Dialect.deriveFromConnectionString 'SQL Server'
fail 'Dialect derivation should have failed'
} catch (DocumentException ex) {
assertNotNull 'The exception message should not have been null', ex.message
assertTrue('The connection string should have been in the exception message',
ex.message.contains('[SQL Server]'))
assertNotNull ex.message, 'The exception message should not have been null'
assertTrue(ex.message.contains('[SQL Server]'),
'The connection string should have been in the exception message')
}
}
}

View File

@ -4,7 +4,7 @@ import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import solutions.bitbadger.documents.DocumentIndex
import static groovy.test.GroovyAssert.*
import static org.junit.jupiter.api.Assertions.assertEquals
/**
* Unit tests for the `DocumentIndex` enum
@ -15,12 +15,12 @@ class DocumentIndexTest {
@Test
@DisplayName('FULL uses proper SQL')
void fullSQL() {
assertEquals('The SQL for Full is incorrect', '', DocumentIndex.FULL.sql)
assertEquals '', DocumentIndex.FULL.sql, 'The SQL for Full is incorrect'
}
@Test
@DisplayName('OPTIMIZED uses proper SQL')
void optimizedSQL() {
assertEquals('The SQL for Optimized is incorrect', ' jsonb_path_ops', DocumentIndex.OPTIMIZED.sql)
assertEquals ' jsonb_path_ops', DocumentIndex.OPTIMIZED.sql, 'The SQL for Optimized is incorrect'
}
}

View File

@ -4,7 +4,7 @@ import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import solutions.bitbadger.documents.FieldMatch
import static groovy.test.GroovyAssert.assertEquals
import static org.junit.jupiter.api.Assertions.assertEquals
/**
* Unit tests for the `FieldMatch` enum
@ -15,12 +15,12 @@ class FieldMatchTest {
@Test
@DisplayName('ANY uses proper SQL')
void anySQL() {
assertEquals('ANY should use OR', 'OR', FieldMatch.ANY.sql)
assertEquals 'OR', FieldMatch.ANY.sql, 'ANY should use OR'
}
@Test
@DisplayName('ALL uses proper SQL')
void allSQL() {
assertEquals('ALL should use AND', 'AND', FieldMatch.ALL.sql)
assertEquals 'AND', FieldMatch.ALL.sql, 'ALL should use AND'
}
}

View File

@ -10,7 +10,7 @@ import solutions.bitbadger.documents.FieldFormat
import solutions.bitbadger.documents.Op
import solutions.bitbadger.documents.support.ForceDialect
import static groovy.test.GroovyAssert.*
import static org.junit.jupiter.api.Assertions.*
/**
* Unit tests for the `Field` class
@ -38,264 +38,275 @@ class FieldTest {
@Test
@DisplayName('withParameterName works with colon prefix')
void withParamNameColon() {
def field = Field.equal('abc', '22').withQualifier('me')
def withParam = field.withParameterName(':test')
assertNotSame('A new Field instance should have been created', field, withParam)
assertEquals('Name should have been preserved', field.name, withParam.name)
assertEquals('Comparison should have been preserved', field.comparison, withParam.comparison)
assertEquals('Parameter name not set correctly', ':test', withParam.parameterName)
assertEquals('Qualifier should have been preserved', field.qualifier, withParam.qualifier)
def field = Field.equal('abc', '22').withQualifier 'me'
def withParam = field.withParameterName ':test'
assertNotSame field, withParam, 'A new Field instance should have been created'
assertEquals field.name, withParam.name, 'Name should have been preserved'
assertEquals field.comparison, withParam.comparison, 'Comparison should have been preserved'
assertEquals ':test', withParam.parameterName, 'Parameter name not set correctly'
assertEquals field.qualifier, withParam.qualifier, 'Qualifier should have been preserved'
}
@Test
@DisplayName('withParameterName works with at-sign prefix')
void withParamNameAtSign() {
def field = Field.equal('def', '44')
def withParam = field.withParameterName('@unit')
assertNotSame('A new Field instance should have been created', field, withParam)
assertEquals('Name should have been preserved', field.name, withParam.name)
assertEquals('Comparison should have been preserved', field.comparison, withParam.comparison)
assertEquals('Parameter name not set correctly', '@unit', withParam.parameterName)
assertEquals('Qualifier should have been preserved', field.qualifier, withParam.qualifier)
def field = Field.equal 'def', '44'
def withParam = field.withParameterName '@unit'
assertNotSame field, withParam, 'A new Field instance should have been created'
assertEquals field.name, withParam.name, 'Name should have been preserved'
assertEquals field.comparison, withParam.comparison, 'Comparison should have been preserved'
assertEquals '@unit', withParam.parameterName, 'Parameter name not set correctly'
assertEquals field.qualifier, withParam.qualifier, 'Qualifier should have been preserved'
}
@Test
@DisplayName('withQualifier sets qualifier correctly')
void withQualifier() {
def field = Field.equal('j', 'k')
def withQual = field.withQualifier('test')
assertNotSame('A new Field instance should have been created', field, withQual)
assertEquals('Name should have been preserved', field.name, withQual.name)
assertEquals('Comparison should have been preserved', field.comparison, withQual.comparison)
assertEquals('Parameter Name should have been preserved', field.parameterName, withQual.parameterName)
assertEquals('Qualifier not set correctly', 'test', withQual.qualifier)
def field = Field.equal 'j', 'k'
def withQual = field.withQualifier 'test'
assertNotSame field, withQual, 'A new Field instance should have been created'
assertEquals field.name, withQual.name, 'Name should have been preserved'
assertEquals field.comparison, withQual.comparison, 'Comparison should have been preserved'
assertEquals field.parameterName, withQual.parameterName, 'Parameter Name should have been preserved'
assertEquals 'test', withQual.qualifier, 'Qualifier not set correctly'
}
@Test
@DisplayName('path generates for simple unqualified PostgreSQL field')
void pathPostgresSimpleUnqualified() {
assertEquals('Path not correct', "data->>'SomethingCool'",
Field.greaterOrEqual('SomethingCool', 18).path(Dialect.POSTGRESQL, FieldFormat.SQL))
assertEquals("data->>'SomethingCool'",
Field.greaterOrEqual('SomethingCool', 18).path(Dialect.POSTGRESQL, FieldFormat.SQL), 'Path not correct')
}
@Test
@DisplayName('path generates for simple qualified PostgreSQL field')
void pathPostgresSimpleQualified() {
assertEquals('Path not correct', "this.data->>'SomethingElse'",
Field.less('SomethingElse', 9).withQualifier('this').path(Dialect.POSTGRESQL, FieldFormat.SQL))
assertEquals("this.data->>'SomethingElse'",
Field.less('SomethingElse', 9).withQualifier('this').path(Dialect.POSTGRESQL, FieldFormat.SQL),
'Path not correct')
}
@Test
@DisplayName('path generates for nested unqualified PostgreSQL field')
void pathPostgresNestedUnqualified() {
assertEquals('Path not correct', "data#>>'{My,Nested,Field}'",
Field.equal('My.Nested.Field', 'howdy').path(Dialect.POSTGRESQL, FieldFormat.SQL))
assertEquals("data#>>'{My,Nested,Field}'",
Field.equal('My.Nested.Field', 'howdy').path(Dialect.POSTGRESQL, FieldFormat.SQL), 'Path not correct')
}
@Test
@DisplayName('path generates for nested qualified PostgreSQL field')
void pathPostgresNestedQualified() {
assertEquals('Path not correct', "bird.data#>>'{Nest,Away}'",
Field.equal('Nest.Away', 'doc').withQualifier('bird').path(Dialect.POSTGRESQL, FieldFormat.SQL))
assertEquals("bird.data#>>'{Nest,Away}'",
Field.equal('Nest.Away', 'doc').withQualifier('bird').path(Dialect.POSTGRESQL, FieldFormat.SQL),
'Path not correct')
}
@Test
@DisplayName('path generates for simple unqualified SQLite field')
void pathSQLiteSimpleUnqualified() {
assertEquals('Path not correct', "data->>'SomethingCool'",
Field.greaterOrEqual('SomethingCool', 18).path(Dialect.SQLITE, FieldFormat.SQL))
assertEquals("data->>'SomethingCool'",
Field.greaterOrEqual('SomethingCool', 18).path(Dialect.SQLITE, FieldFormat.SQL), 'Path not correct')
}
@Test
@DisplayName('path generates for simple qualified SQLite field')
void pathSQLiteSimpleQualified() {
assertEquals('Path not correct', "this.data->>'SomethingElse'",
Field.less('SomethingElse', 9).withQualifier('this').path(Dialect.SQLITE, FieldFormat.SQL))
assertEquals("this.data->>'SomethingElse'",
Field.less('SomethingElse', 9).withQualifier('this').path(Dialect.SQLITE, FieldFormat.SQL),
'Path not correct')
}
@Test
@DisplayName('path generates for nested unqualified SQLite field')
void pathSQLiteNestedUnqualified() {
assertEquals('Path not correct', "data->'My'->'Nested'->>'Field'",
Field.equal('My.Nested.Field', 'howdy').path(Dialect.SQLITE, FieldFormat.SQL))
assertEquals("data->'My'->'Nested'->>'Field'",
Field.equal('My.Nested.Field', 'howdy').path(Dialect.SQLITE, FieldFormat.SQL), 'Path not correct')
}
@Test
@DisplayName('path generates for nested qualified SQLite field')
void pathSQLiteNestedQualified() {
assertEquals('Path not correct', "bird.data->'Nest'->>'Away'",
Field.equal('Nest.Away', 'doc').withQualifier('bird').path(Dialect.SQLITE, FieldFormat.SQL))
assertEquals("bird.data->'Nest'->>'Away'",
Field.equal('Nest.Away', 'doc').withQualifier('bird').path(Dialect.SQLITE, FieldFormat.SQL),
'Path not correct')
}
@Test
@DisplayName('toWhere generates for exists w/o qualifier | PostgreSQL')
void toWhereExistsNoQualPostgres() {
ForceDialect.postgres()
assertEquals('Field WHERE clause not generated correctly', "data->>'that_field' IS NOT NULL",
Field.exists('that_field').toWhere())
assertEquals("data->>'that_field' IS NOT NULL", Field.exists('that_field').toWhere(),
'Field WHERE clause not generated correctly')
}
@Test
@DisplayName('toWhere generates for exists w/o qualifier | SQLite')
void toWhereExistsNoQualSQLite() {
ForceDialect.sqlite()
assertEquals('Field WHERE clause not generated correctly', "data->>'that_field' IS NOT NULL",
Field.exists('that_field').toWhere())
assertEquals("data->>'that_field' IS NOT NULL", Field.exists('that_field').toWhere(),
'Field WHERE clause not generated correctly')
}
@Test
@DisplayName('toWhere generates for not-exists w/o qualifier | PostgreSQL')
void toWhereNotExistsNoQualPostgres() {
ForceDialect.postgres()
assertEquals('Field WHERE clause not generated correctly', "data->>'a_field' IS NULL",
Field.notExists('a_field').toWhere())
assertEquals("data->>'a_field' IS NULL", Field.notExists('a_field').toWhere(),
'Field WHERE clause not generated correctly')
}
@Test
@DisplayName('toWhere generates for not-exists w/o qualifier | SQLite')
void toWhereNotExistsNoQualSQLite() {
ForceDialect.sqlite()
assertEquals('Field WHERE clause not generated correctly', "data->>'a_field' IS NULL",
Field.notExists('a_field').toWhere())
assertEquals("data->>'a_field' IS NULL", Field.notExists('a_field').toWhere(),
'Field WHERE clause not generated correctly')
}
@Test
@DisplayName('toWhere generates for BETWEEN w/o qualifier, numeric range | PostgreSQL')
void toWhereBetweenNoQualNumericPostgres() {
ForceDialect.postgres()
assertEquals('Field WHERE clause not generated correctly',
"(data->>'age')::numeric BETWEEN @agemin AND @agemax", Field.between('age', 13, 17, '@age').toWhere())
assertEquals("(data->>'age')::numeric BETWEEN @agemin AND @agemax",
Field.between('age', 13, 17, '@age').toWhere(), 'Field WHERE clause not generated correctly')
}
@Test
@DisplayName('toWhere generates for BETWEEN w/o qualifier, alphanumeric range | PostgreSQL')
void toWhereBetweenNoQualAlphaPostgres() {
ForceDialect.postgres()
assertEquals('Field WHERE clause not generated correctly', "data->>'city' BETWEEN :citymin AND :citymax",
Field.between('city', 'Atlanta', 'Chicago', ':city').toWhere())
assertEquals("data->>'city' BETWEEN :citymin AND :citymax",
Field.between('city', 'Atlanta', 'Chicago', ':city').toWhere(),
'Field WHERE clause not generated correctly')
}
@Test
@DisplayName('toWhere generates for BETWEEN w/o qualifier | SQLite')
void toWhereBetweenNoQualSQLite() {
ForceDialect.sqlite()
assertEquals('Field WHERE clause not generated correctly', "data->>'age' BETWEEN @agemin AND @agemax",
Field.between('age', 13, 17, '@age').toWhere())
assertEquals("data->>'age' BETWEEN @agemin AND @agemax", Field.between('age', 13, 17, '@age').toWhere(),
'Field WHERE clause not generated correctly')
}
@Test
@DisplayName('toWhere generates for BETWEEN w/ qualifier, numeric range | PostgreSQL')
void toWhereBetweenQualNumericPostgres() {
ForceDialect.postgres()
assertEquals('Field WHERE clause not generated correctly',
"(test.data->>'age')::numeric BETWEEN @agemin AND @agemax",
Field.between('age', 13, 17, '@age').withQualifier('test').toWhere())
assertEquals("(test.data->>'age')::numeric BETWEEN @agemin AND @agemax",
Field.between('age', 13, 17, '@age').withQualifier('test').toWhere(),
'Field WHERE clause not generated correctly')
}
@Test
@DisplayName('toWhere generates for BETWEEN w/ qualifier, alphanumeric range | PostgreSQL')
void toWhereBetweenQualAlphaPostgres() {
ForceDialect.postgres()
assertEquals('Field WHERE clause not generated correctly', "unit.data->>'city' BETWEEN :citymin AND :citymax",
Field.between('city', 'Atlanta', 'Chicago', ':city').withQualifier('unit').toWhere())
assertEquals("unit.data->>'city' BETWEEN :citymin AND :citymax",
Field.between('city', 'Atlanta', 'Chicago', ':city').withQualifier('unit').toWhere(),
'Field WHERE clause not generated correctly')
}
@Test
@DisplayName('toWhere generates for BETWEEN w/ qualifier | SQLite')
void toWhereBetweenQualSQLite() {
ForceDialect.sqlite()
assertEquals('Field WHERE clause not generated correctly', "my.data->>'age' BETWEEN @agemin AND @agemax",
Field.between('age', 13, 17, '@age').withQualifier('my').toWhere())
assertEquals("my.data->>'age' BETWEEN @agemin AND @agemax",
Field.between('age', 13, 17, '@age').withQualifier('my').toWhere(),
'Field WHERE clause not generated correctly')
}
@Test
@DisplayName('toWhere generates for IN/any, numeric values | PostgreSQL')
void toWhereAnyNumericPostgres() {
ForceDialect.postgres()
assertEquals('Field WHERE clause not generated correctly',
"(data->>'even')::numeric IN (:nbr_0, :nbr_1, :nbr_2)",
Field.any('even', List.of(2, 4, 6), ':nbr').toWhere())
assertEquals("(data->>'even')::numeric IN (:nbr_0, :nbr_1, :nbr_2)",
Field.any('even', List.of(2, 4, 6), ':nbr').toWhere(), 'Field WHERE clause not generated correctly')
}
@Test
@DisplayName('toWhere generates for IN/any, alphanumeric values | PostgreSQL')
void toWhereAnyAlphaPostgres() {
ForceDialect.postgres()
assertEquals('Field WHERE clause not generated correctly', "data->>'test' IN (:city_0, :city_1)",
Field.any('test', List.of('Atlanta', 'Chicago'), ':city').toWhere())
assertEquals("data->>'test' IN (:city_0, :city_1)",
Field.any('test', List.of('Atlanta', 'Chicago'), ':city').toWhere(),
'Field WHERE clause not generated correctly')
}
@Test
@DisplayName('toWhere generates for IN/any | SQLite')
void toWhereAnySQLite() {
ForceDialect.sqlite()
assertEquals('Field WHERE clause not generated correctly', "data->>'test' IN (:city_0, :city_1)",
Field.any('test', List.of('Atlanta', 'Chicago'), ':city').toWhere())
assertEquals("data->>'test' IN (:city_0, :city_1)",
Field.any('test', List.of('Atlanta', 'Chicago'), ':city').toWhere(),
'Field WHERE clause not generated correctly')
}
@Test
@DisplayName('toWhere generates for inArray | PostgreSQL')
void toWhereInArrayPostgres() {
ForceDialect.postgres()
assertEquals('Field WHERE clause not generated correctly', "data->'even' ??| ARRAY[:it_0, :it_1, :it_2, :it_3]",
Field.inArray('even', 'tbl', List.of(2, 4, 6, 8), ':it').toWhere())
assertEquals("data->'even' ??| ARRAY[:it_0, :it_1, :it_2, :it_3]",
Field.inArray('even', 'tbl', List.of(2, 4, 6, 8), ':it').toWhere(),
'Field WHERE clause not generated correctly')
}
@Test
@DisplayName('toWhere generates for inArray | SQLite')
void toWhereInArraySQLite() {
ForceDialect.sqlite()
assertEquals('Field WHERE clause not generated correctly',
"EXISTS (SELECT 1 FROM json_each(tbl.data, '\$.test') WHERE value IN (:city_0, :city_1))",
Field.inArray('test', 'tbl', List.of('Atlanta', 'Chicago'), ':city').toWhere())
assertEquals("EXISTS (SELECT 1 FROM json_each(tbl.data, '\$.test') WHERE value IN (:city_0, :city_1))",
Field.inArray('test', 'tbl', List.of('Atlanta', 'Chicago'), ':city').toWhere(),
'Field WHERE clause not generated correctly')
}
@Test
@DisplayName('toWhere generates for others w/o qualifier | PostgreSQL')
void toWhereOtherNoQualPostgres() {
ForceDialect.postgres()
assertEquals('Field WHERE clause not generated correctly', "data->>'some_field' = :value",
Field.equal('some_field', '', ':value').toWhere())
assertEquals("data->>'some_field' = :value", Field.equal('some_field', '', ':value').toWhere(),
'Field WHERE clause not generated correctly')
}
@Test
@DisplayName('toWhere generates for others w/o qualifier | SQLite')
void toWhereOtherNoQualSQLite() {
ForceDialect.sqlite()
assertEquals('Field WHERE clause not generated correctly', "data->>'some_field' = :value",
Field.equal('some_field', '', ':value').toWhere())
assertEquals("data->>'some_field' = :value", Field.equal('some_field', '', ':value').toWhere(),
'Field WHERE clause not generated correctly')
}
@Test
@DisplayName('toWhere generates no-parameter w/ qualifier | PostgreSQL')
void toWhereNoParamWithQualPostgres() {
ForceDialect.postgres()
assertEquals('Field WHERE clause not generated correctly', "test.data->>'no_field' IS NOT NULL",
Field.exists('no_field').withQualifier('test').toWhere())
assertEquals("test.data->>'no_field' IS NOT NULL", Field.exists('no_field').withQualifier('test').toWhere(),
'Field WHERE clause not generated correctly')
}
@Test
@DisplayName('toWhere generates no-parameter w/ qualifier | SQLite')
void toWhereNoParamWithQualSQLite() {
ForceDialect.sqlite()
assertEquals('Field WHERE clause not generated correctly', "test.data->>'no_field' IS NOT NULL",
Field.exists('no_field').withQualifier('test').toWhere())
assertEquals("test.data->>'no_field' IS NOT NULL", Field.exists('no_field').withQualifier('test').toWhere(),
'Field WHERE clause not generated correctly')
}
@Test
@DisplayName('toWhere generates parameter w/ qualifier | PostgreSQL')
void toWhereParamWithQualPostgres() {
ForceDialect.postgres()
assertEquals('Field WHERE clause not generated correctly', "(q.data->>'le_field')::numeric <= :it",
Field.lessOrEqual('le_field', 18, ':it').withQualifier('q').toWhere())
assertEquals("(q.data->>'le_field')::numeric <= :it",
Field.lessOrEqual('le_field', 18, ':it').withQualifier('q').toWhere(),
'Field WHERE clause not generated correctly')
}
@Test
@DisplayName('toWhere generates parameter w/ qualifier | SQLite')
void toWhereParamWithQualSQLite() {
ForceDialect.sqlite()
assertEquals('Field WHERE clause not generated correctly', "q.data->>'le_field' <= :it",
Field.lessOrEqual('le_field', 18, ':it').withQualifier('q').toWhere())
assertEquals("q.data->>'le_field' <= :it",
Field.lessOrEqual('le_field', 18, ':it').withQualifier('q').toWhere(),
'Field WHERE clause not generated correctly')
}
// ~~~ STATIC CONSTRUCTOR TESTS ~~~
@ -303,236 +314,236 @@ class FieldTest {
@Test
@DisplayName('equal constructs a field w/o parameter name')
void equalCtor() {
def field = Field.equal('Test', 14)
assertEquals('Field name not filled correctly', 'Test', field.name)
assertEquals('Field comparison operation not filled correctly', Op.EQUAL, field.comparison.op)
assertEquals('Field comparison value not filled correctly', 14, field.comparison.value)
assertNull('The parameter name should have been null', field.parameterName)
assertNull('The qualifier should have been null', field.qualifier)
def field = Field.equal 'Test', 14
assertEquals 'Test', field.name, 'Field name not filled correctly'
assertEquals Op.EQUAL, field.comparison.op, 'Field comparison operation not filled correctly'
assertEquals 14, field.comparison.value, 'Field comparison value not filled correctly'
assertNull field.parameterName, 'The parameter name should have been null'
assertNull field.qualifier, 'The qualifier should have been null'
}
@Test
@DisplayName('equal constructs a field w/ parameter name')
void equalParameterCtor() {
def field = Field.equal('Test', 14, ':w')
assertEquals('Field name not filled correctly', 'Test', field.name)
assertEquals('Field comparison operation not filled correctly', Op.EQUAL, field.comparison.op)
assertEquals('Field comparison value not filled correctly', 14, field.comparison.value)
assertEquals('Field parameter name not filled correctly', ':w', field.parameterName)
assertNull('The qualifier should have been null', field.qualifier)
def field = Field.equal 'Test', 14, ':w'
assertEquals 'Test', field.name, 'Field name not filled correctly'
assertEquals Op.EQUAL, field.comparison.op, 'Field comparison operation not filled correctly'
assertEquals 14, field.comparison.value, 'Field comparison value not filled correctly'
assertEquals ':w', field.parameterName, 'Field parameter name not filled correctly'
assertNull field.qualifier, 'The qualifier should have been null'
}
@Test
@DisplayName('greater constructs a field w/o parameter name')
void greaterCtor() {
def field = Field.greater('Great', 'night')
assertEquals('Field name not filled correctly', 'Great', field.name)
assertEquals('Field comparison operation not filled correctly', Op.GREATER, field.comparison.op)
assertEquals('Field comparison value not filled correctly', 'night', field.comparison.value)
assertNull('The parameter name should have been null', field.parameterName)
assertNull('The qualifier should have been null', field.qualifier)
def field = Field.greater 'Great', 'night'
assertEquals 'Great', field.name, 'Field name not filled correctly'
assertEquals Op.GREATER, field.comparison.op, 'Field comparison operation not filled correctly'
assertEquals 'night', field.comparison.value, 'Field comparison value not filled correctly'
assertNull field.parameterName, 'The parameter name should have been null'
assertNull field.qualifier, 'The qualifier should have been null'
}
@Test
@DisplayName('greater constructs a field w/ parameter name')
void greaterParameterCtor() {
def field = Field.greater('Great', 'night', ':yeah')
assertEquals('Field name not filled correctly', 'Great', field.name)
assertEquals('Field comparison operation not filled correctly', Op.GREATER, field.comparison.op)
assertEquals('Field comparison value not filled correctly', 'night', field.comparison.value)
def field = Field.greater 'Great', 'night', ':yeah'
assertEquals 'Great', field.name, 'Field name not filled correctly'
assertEquals Op.GREATER, field.comparison.op, 'Field comparison operation not filled correctly'
assertEquals 'night', field.comparison.value, 'Field comparison value not filled correctly'
assertEquals('Field parameter name not filled correctly', ':yeah', field.parameterName)
assertNull('The qualifier should have been null', field.qualifier)
assertNull field.qualifier, 'The qualifier should have been null'
}
@Test
@DisplayName('greaterOrEqual constructs a field w/o parameter name')
void greaterOrEqualCtor() {
def field = Field.greaterOrEqual('Nice', 88L)
assertEquals('Field name not filled correctly', 'Nice', field.name)
assertEquals('Field comparison operation not filled correctly', Op.GREATER_OR_EQUAL, field.comparison.op)
assertEquals('Field comparison value not filled correctly', 88L, field.comparison.value)
assertNull('The parameter name should have been null', field.parameterName)
assertNull('The qualifier should have been null', field.qualifier)
def field = Field.greaterOrEqual 'Nice', 88L
assertEquals 'Nice', field.name, 'Field name not filled correctly'
assertEquals Op.GREATER_OR_EQUAL, field.comparison.op, 'Field comparison operation not filled correctly'
assertEquals 88L, field.comparison.value, 'Field comparison value not filled correctly'
assertNull field.parameterName, 'The parameter name should have been null'
assertNull field.qualifier, 'The qualifier should have been null'
}
@Test
@DisplayName('greaterOrEqual constructs a field w/ parameter name')
void greaterOrEqualParameterCtor() {
def field = Field.greaterOrEqual('Nice', 88L, ':nice')
assertEquals('Field name not filled correctly', 'Nice', field.name)
assertEquals('Field comparison operation not filled correctly', Op.GREATER_OR_EQUAL, field.comparison.op)
assertEquals('Field comparison value not filled correctly', 88L, field.comparison.value)
assertEquals('Field parameter name not filled correctly', ':nice', field.parameterName)
assertNull('The qualifier should have been null', field.qualifier)
def field = Field.greaterOrEqual 'Nice', 88L, ':nice'
assertEquals 'Nice', field.name, 'Field name not filled correctly'
assertEquals Op.GREATER_OR_EQUAL, field.comparison.op, 'Field comparison operation not filled correctly'
assertEquals 88L, field.comparison.value, 'Field comparison value not filled correctly'
assertEquals ':nice', field.parameterName, 'Field parameter name not filled correctly'
assertNull field.qualifier, 'The qualifier should have been null'
}
@Test
@DisplayName('less constructs a field w/o parameter name')
void lessCtor() {
def field = Field.less('Lesser', 'seven')
assertEquals('Field name not filled correctly', 'Lesser', field.name)
assertEquals('Field comparison operation not filled correctly', Op.LESS, field.comparison.op)
assertEquals('Field comparison value not filled correctly', 'seven', field.comparison.value)
assertNull('The parameter name should have been null', field.parameterName)
assertNull('The qualifier should have been null', field.qualifier)
def field = Field.less 'Lesser', 'seven'
assertEquals 'Lesser', field.name, 'Field name not filled correctly'
assertEquals Op.LESS, field.comparison.op, 'Field comparison operation not filled correctly'
assertEquals 'seven', field.comparison.value, 'Field comparison value not filled correctly'
assertNull field.parameterName, 'The parameter name should have been null'
assertNull field.qualifier, 'The qualifier should have been null'
}
@Test
@DisplayName('less constructs a field w/ parameter name')
void lessParameterCtor() {
def field = Field.less('Lesser', 'seven', ':max')
assertEquals('Field name not filled correctly', 'Lesser', field.name)
assertEquals('Field comparison operation not filled correctly', Op.LESS, field.comparison.op)
assertEquals('Field comparison value not filled correctly', 'seven', field.comparison.value)
assertEquals('Field parameter name not filled correctly', ':max', field.parameterName)
assertNull('The qualifier should have been null', field.qualifier)
def field = Field.less 'Lesser', 'seven', ':max'
assertEquals 'Lesser', field.name, 'Field name not filled correctly'
assertEquals Op.LESS, field.comparison.op, 'Field comparison operation not filled correctly'
assertEquals 'seven', field.comparison.value, 'Field comparison value not filled correctly'
assertEquals ':max', field.parameterName, 'Field parameter name not filled correctly'
assertNull field.qualifier, 'The qualifier should have been null'
}
@Test
@DisplayName('lessOrEqual constructs a field w/o parameter name')
void lessOrEqualCtor() {
def field = Field.lessOrEqual('Nobody', 'KNOWS')
assertEquals('Field name not filled correctly', 'Nobody', field.name)
assertEquals('Field comparison operation not filled correctly', Op.LESS_OR_EQUAL, field.comparison.op)
assertEquals('Field comparison value not filled correctly', 'KNOWS', field.comparison.value)
assertNull('The parameter name should have been null', field.parameterName)
assertNull('The qualifier should have been null', field.qualifier)
def field = Field.lessOrEqual 'Nobody', 'KNOWS'
assertEquals 'Nobody', field.name, 'Field name not filled correctly'
assertEquals Op.LESS_OR_EQUAL, field.comparison.op, 'Field comparison operation not filled correctly'
assertEquals 'KNOWS', field.comparison.value, 'Field comparison value not filled correctly'
assertNull field.parameterName, 'The parameter name should have been null'
assertNull field.qualifier, 'The qualifier should have been null'
}
@Test
@DisplayName('lessOrEqual constructs a field w/ parameter name')
void lessOrEqualParameterCtor() {
def field = Field.lessOrEqual('Nobody', 'KNOWS', ':nope')
assertEquals('Field name not filled correctly', 'Nobody', field.name)
assertEquals('Field comparison operation not filled correctly', Op.LESS_OR_EQUAL, field.comparison.op)
assertEquals('Field comparison value not filled correctly', 'KNOWS', field.comparison.value)
assertEquals('Field parameter name not filled correctly', ':nope', field.parameterName)
assertNull('The qualifier should have been null', field.qualifier)
def field = Field.lessOrEqual 'Nobody', 'KNOWS', ':nope'
assertEquals 'Nobody', field.name, 'Field name not filled correctly'
assertEquals Op.LESS_OR_EQUAL, field.comparison.op, 'Field comparison operation not filled correctly'
assertEquals 'KNOWS', field.comparison.value, 'Field comparison value not filled correctly'
assertEquals ':nope', field.parameterName, 'Field parameter name not filled correctly'
assertNull field.qualifier, 'The qualifier should have been null'
}
@Test
@DisplayName('notEqual constructs a field w/o parameter name')
void notEqualCtor() {
def field = Field.notEqual('Park', 'here')
assertEquals('Field name not filled correctly', 'Park', field.name)
assertEquals('Field comparison operation not filled correctly', Op.NOT_EQUAL, field.comparison.op)
assertEquals('Field comparison value not filled correctly', 'here', field.comparison.value)
assertNull('The parameter name should have been null', field.parameterName)
assertNull('The qualifier should have been null', field.qualifier)
def field = Field.notEqual 'Park', 'here'
assertEquals 'Park', field.name, 'Field name not filled correctly'
assertEquals Op.NOT_EQUAL, field.comparison.op, 'Field comparison operation not filled correctly'
assertEquals 'here', field.comparison.value, 'Field comparison value not filled correctly'
assertNull field.parameterName, 'The parameter name should have been null'
assertNull field.qualifier, 'The qualifier should have been null'
}
@Test
@DisplayName('notEqual constructs a field w/ parameter name')
void notEqualParameterCtor() {
def field = Field.notEqual('Park', 'here', ':now')
assertEquals('Field name not filled correctly', 'Park', field.name)
assertEquals('Field comparison operation not filled correctly', Op.NOT_EQUAL, field.comparison.op)
assertEquals('Field comparison value not filled correctly', 'here', field.comparison.value)
assertEquals('Field parameter name not filled correctly', ':now', field.parameterName)
assertNull('The qualifier should have been null', field.qualifier)
def field = Field.notEqual 'Park', 'here', ':now'
assertEquals 'Park', field.name, 'Field name not filled correctly'
assertEquals Op.NOT_EQUAL, field.comparison.op, 'Field comparison operation not filled correctly'
assertEquals 'here', field.comparison.value, 'Field comparison value not filled correctly'
assertEquals ':now', field.parameterName, 'Field parameter name not filled correctly'
assertNull field.qualifier, 'The qualifier should have been null'
}
@Test
@DisplayName('between constructs a field w/o parameter name')
void betweenCtor() {
def field = Field.between('Age', 18, 49)
assertEquals('Field name not filled correctly', 'Age', field.name)
assertEquals('Field comparison operation not filled correctly', Op.BETWEEN, field.comparison.op)
assertEquals('Field comparison min value not filled correctly', 18, field.comparison.value.first)
assertEquals('Field comparison max value not filled correctly', 49, field.comparison.value.second, )
assertNull('The parameter name should have been null', field.parameterName)
assertNull('The qualifier should have been null', field.qualifier)
def field = Field.between 'Age', 18, 49
assertEquals 'Age', field.name, 'Field name not filled correctly'
assertEquals Op.BETWEEN, field.comparison.op, 'Field comparison operation not filled correctly'
assertEquals 18, field.comparison.value.first, 'Field comparison min value not filled correctly'
assertEquals 49, field.comparison.value.second, 'Field comparison max value not filled correctly'
assertNull field.parameterName, 'The parameter name should have been null'
assertNull field.qualifier, 'The qualifier should have been null'
}
@Test
@DisplayName('between constructs a field w/ parameter name')
void betweenParameterCtor() {
def field = Field.between('Age', 18, 49, ':limit')
assertEquals('Field name not filled correctly', 'Age', field.name)
assertEquals('Field comparison operation not filled correctly', Op.BETWEEN, field.comparison.op)
assertEquals('Field comparison min value not filled correctly', 18, field.comparison.value.first)
assertEquals('Field comparison max value not filled correctly', 49, field.comparison.value.second)
assertEquals('Field parameter name not filled correctly', ':limit', field.parameterName)
assertNull('The qualifier should have been null', field.qualifier)
def field = Field.between 'Age', 18, 49, ':limit'
assertEquals 'Age', field.name, 'Field name not filled correctly'
assertEquals Op.BETWEEN, field.comparison.op, 'Field comparison operation not filled correctly'
assertEquals 18, field.comparison.value.first, 'Field comparison min value not filled correctly'
assertEquals 49, field.comparison.value.second, 'Field comparison max value not filled correctly'
assertEquals ':limit', field.parameterName, 'Field parameter name not filled correctly'
assertNull field.qualifier, 'The qualifier should have been null'
}
@Test
@DisplayName('any constructs a field w/o parameter name')
void anyCtor() {
def field = Field.any('Here', List.of(8, 16, 32))
assertEquals('Field name not filled correctly', 'Here', field.name)
assertEquals('Field comparison operation not filled correctly', Op.IN, field.comparison.op)
assertEquals('Field comparison value not filled correctly', List.of(8, 16, 32), field.comparison.value)
assertNull('The parameter name should have been null', field.parameterName)
assertNull('The qualifier should have been null', field.qualifier)
def field = Field.any 'Here', List.of(8, 16, 32)
assertEquals 'Here', field.name, 'Field name not filled correctly'
assertEquals Op.IN, field.comparison.op, 'Field comparison operation not filled correctly'
assertEquals List.of(8, 16, 32), field.comparison.value, 'Field comparison value not filled correctly'
assertNull field.parameterName, 'The parameter name should have been null'
assertNull field.qualifier, 'The qualifier should have been null'
}
@Test
@DisplayName('any constructs a field w/ parameter name')
void anyParameterCtor() {
def field = Field.any('Here', List.of(8, 16, 32), ':list')
assertEquals('Field name not filled correctly', 'Here', field.name)
assertEquals('Field comparison operation not filled correctly', Op.IN, field.comparison.op)
assertEquals('Field comparison value not filled correctly', List.of(8, 16, 32), field.comparison.value)
assertEquals('Field parameter name not filled correctly', ':list', field.parameterName)
assertNull('The qualifier should have been null', field.qualifier)
def field = Field.any 'Here', List.of(8, 16, 32), ':list'
assertEquals 'Here', field.name, 'Field name not filled correctly'
assertEquals Op.IN, field.comparison.op, 'Field comparison operation not filled correctly'
assertEquals List.of(8, 16, 32), field.comparison.value, 'Field comparison value not filled correctly'
assertEquals ':list', field.parameterName, 'Field parameter name not filled correctly'
assertNull field.qualifier, 'The qualifier should have been null'
}
@Test
@DisplayName('inArray constructs a field w/o parameter name')
void inArrayCtor() {
def field = Field.inArray('ArrayField', 'table', List.of('z'))
assertEquals('Field name not filled correctly', 'ArrayField', field.name)
assertEquals('Field comparison operation not filled correctly', Op.IN_ARRAY, field.comparison.op)
assertEquals('Field comparison table not filled correctly', 'table', field.comparison.value.first)
assertEquals('Field comparison values not filled correctly', List.of('z'), field.comparison.value.second)
assertNull('The parameter name should have been null', field.parameterName)
assertNull('The qualifier should have been null', field.qualifier)
def field = Field.inArray 'ArrayField', 'table', List.of('z')
assertEquals 'ArrayField', field.name, 'Field name not filled correctly'
assertEquals Op.IN_ARRAY, field.comparison.op, 'Field comparison operation not filled correctly'
assertEquals 'table', field.comparison.value.first, 'Field comparison table not filled correctly'
assertEquals List.of('z'), field.comparison.value.second, 'Field comparison values not filled correctly'
assertNull field.parameterName, 'The parameter name should have been null'
assertNull field.qualifier, 'The qualifier should have been null'
}
@Test
@DisplayName('inArray constructs a field w/ parameter name')
void inArrayParameterCtor() {
def field = Field.inArray('ArrayField', 'table', List.of('z'), ':a')
assertEquals('Field name not filled correctly', 'ArrayField', field.name)
assertEquals('Field comparison operation not filled correctly', Op.IN_ARRAY, field.comparison.op)
assertEquals('Field comparison table not filled correctly', 'table', field.comparison.value.first)
assertEquals('Field comparison values not filled correctly', List.of('z'), field.comparison.value.second)
assertEquals('Field parameter name not filled correctly', ':a', field.parameterName)
assertNull('The qualifier should have been null', field.qualifier)
def field = Field.inArray 'ArrayField', 'table', List.of('z'), ':a'
assertEquals 'ArrayField', field.name, 'Field name not filled correctly'
assertEquals Op.IN_ARRAY, field.comparison.op, 'Field comparison operation not filled correctly'
assertEquals 'table', field.comparison.value.first, 'Field comparison table not filled correctly'
assertEquals List.of('z'), field.comparison.value.second, 'Field comparison values not filled correctly'
assertEquals ':a', field.parameterName, 'Field parameter name not filled correctly'
assertNull field.qualifier, 'The qualifier should have been null'
}
@Test
@DisplayName('exists constructs a field')
void existsCtor() {
def field = Field.exists 'Groovy'
assertEquals('Field name not filled correctly', 'Groovy', field.name)
assertEquals('Field comparison operation not filled correctly', Op.EXISTS, field.comparison.op)
assertEquals('Field comparison value not filled correctly', '', field.comparison.value)
assertNull('The parameter name should have been null', field.parameterName)
assertNull('The qualifier should have been null', field.qualifier)
assertEquals 'Groovy', field.name, 'Field name not filled correctly'
assertEquals Op.EXISTS, field.comparison.op, 'Field comparison operation not filled correctly'
assertEquals '', field.comparison.value, 'Field comparison value not filled correctly'
assertNull field.parameterName, 'The parameter name should have been null'
assertNull field.qualifier, 'The qualifier should have been null'
}
@Test
@DisplayName('notExists constructs a field')
void notExistsCtor() {
def field = Field.notExists 'Groovy'
assertEquals('Field name not filled correctly', 'Groovy', field.name)
assertEquals('Field comparison operation not filled correctly', Op.NOT_EXISTS, field.comparison.op)
assertEquals('Field comparison value not filled correctly', '', field.comparison.value)
assertNull('The parameter name should have been null', field.parameterName)
assertNull('The qualifier should have been null', field.qualifier)
assertEquals 'Groovy', field.name, 'Field name not filled correctly'
assertEquals Op.NOT_EXISTS, field.comparison.op, 'Field comparison operation not filled correctly'
assertEquals '', field.comparison.value, 'Field comparison value not filled correctly'
assertNull field.parameterName, 'The parameter name should have been null'
assertNull field.qualifier, 'The qualifier should have been null'
}
@Test
@DisplayName('named constructs a field')
void namedCtor() {
def field = Field.named('Tacos')
assertEquals('Field name not filled correctly', 'Tacos', field.name)
assertEquals('Field comparison operation not filled correctly', Op.EQUAL, field.comparison.op)
assertEquals('Field comparison value not filled correctly', '', field.comparison.value)
assertNull('The parameter name should have been null', field.parameterName)
assertNull('The qualifier should have been null', field.qualifier)
def field = Field.named 'Tacos'
assertEquals 'Tacos', field.name, 'Field name not filled correctly'
assertEquals Op.EQUAL, field.comparison.op, 'Field comparison operation not filled correctly'
assertEquals '', field.comparison.value, 'Field comparison value not filled correctly'
assertNull field.parameterName, 'The parameter name should have been null'
assertNull field.qualifier, 'The qualifier should have been null'
}
// TODO: fix java.base open issue
@ -545,56 +556,60 @@ class FieldTest {
@Test
@DisplayName('nameToPath creates a simple PostgreSQL SQL name')
void nameToPathPostgresSimpleSQL() {
assertEquals('Path not constructed correctly', "data->>'Simple'",
Field.nameToPath('Simple', Dialect.POSTGRESQL, FieldFormat.SQL))
assertEquals("data->>'Simple'", Field.nameToPath('Simple', Dialect.POSTGRESQL, FieldFormat.SQL),
'Path not constructed correctly')
}
@Test
@DisplayName('nameToPath creates a simple SQLite SQL name')
void nameToPathSQLiteSimpleSQL() {
assertEquals('Path not constructed correctly', "data->>'Simple'",
Field.nameToPath('Simple', Dialect.SQLITE, FieldFormat.SQL))
assertEquals("data->>'Simple'", Field.nameToPath('Simple', Dialect.SQLITE, FieldFormat.SQL),
'Path not constructed correctly')
}
@Test
@DisplayName('nameToPath creates a nested PostgreSQL SQL name')
void nameToPathPostgresNestedSQL() {
assertEquals('Path not constructed correctly', "data#>>'{A,Long,Path,to,the,Property}'",
Field.nameToPath('A.Long.Path.to.the.Property', Dialect.POSTGRESQL, FieldFormat.SQL))
assertEquals("data#>>'{A,Long,Path,to,the,Property}'",
Field.nameToPath('A.Long.Path.to.the.Property', Dialect.POSTGRESQL, FieldFormat.SQL),
'Path not constructed correctly')
}
@Test
@DisplayName('nameToPath creates a nested SQLite SQL name')
void nameToPathSQLiteNestedSQL() {
assertEquals('Path not constructed correctly', "data->'A'->'Long'->'Path'->'to'->'the'->>'Property'",
Field.nameToPath('A.Long.Path.to.the.Property', Dialect.SQLITE, FieldFormat.SQL))
assertEquals("data->'A'->'Long'->'Path'->'to'->'the'->>'Property'",
Field.nameToPath('A.Long.Path.to.the.Property', Dialect.SQLITE, FieldFormat.SQL),
'Path not constructed correctly')
}
@Test
@DisplayName('nameToPath creates a simple PostgreSQL JSON name')
void nameToPathPostgresSimpleJSON() {
assertEquals('Path not constructed correctly', "data->'Simple'",
Field.nameToPath('Simple', Dialect.POSTGRESQL, FieldFormat.JSON))
assertEquals("data->'Simple'", Field.nameToPath('Simple', Dialect.POSTGRESQL, FieldFormat.JSON),
'Path not constructed correctly')
}
@Test
@DisplayName('nameToPath creates a simple SQLite JSON name')
void nameToPathSQLiteSimpleJSON() {
assertEquals('Path not constructed correctly', "data->'Simple'",
Field.nameToPath('Simple', Dialect.SQLITE, FieldFormat.JSON))
assertEquals("data->'Simple'", Field.nameToPath('Simple', Dialect.SQLITE, FieldFormat.JSON),
'Path not constructed correctly')
}
@Test
@DisplayName('nameToPath creates a nested PostgreSQL JSON name')
void nameToPathPostgresNestedJSON() {
assertEquals('Path not constructed correctly', "data#>'{A,Long,Path,to,the,Property}'",
Field.nameToPath('A.Long.Path.to.the.Property', Dialect.POSTGRESQL, FieldFormat.JSON))
assertEquals("data#>'{A,Long,Path,to,the,Property}'",
Field.nameToPath('A.Long.Path.to.the.Property', Dialect.POSTGRESQL, FieldFormat.JSON),
'Path not constructed correctly')
}
@Test
@DisplayName('nameToPath creates a nested SQLite JSON name')
void nameToPathSQLiteNestedJSON() {
assertEquals('Path not constructed correctly', "data->'A'->'Long'->'Path'->'to'->'the'->'Property'",
Field.nameToPath('A.Long.Path.to.the.Property', Dialect.SQLITE, FieldFormat.JSON))
assertEquals("data->'A'->'Long'->'Path'->'to'->'the'->'Property'",
Field.nameToPath('A.Long.Path.to.the.Property', Dialect.SQLITE, FieldFormat.JSON),
'Path not constructed correctly')
}
}

View File

@ -4,7 +4,7 @@ import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import solutions.bitbadger.documents.Op
import static groovy.test.GroovyAssert.*
import static org.junit.jupiter.api.Assertions.assertEquals
/**
* Unit tests for the `Op` enum
@ -15,66 +15,66 @@ class OpTest {
@Test
@DisplayName('EQUAL uses proper SQL')
void equalSQL() {
assertEquals('The SQL for equal is incorrect', '=', Op.EQUAL.sql)
assertEquals '=', Op.EQUAL.sql, 'The SQL for equal is incorrect'
}
@Test
@DisplayName('GREATER uses proper SQL')
void greaterSQL() {
assertEquals('The SQL for greater is incorrect', '>', Op.GREATER.sql)
assertEquals '>', Op.GREATER.sql, 'The SQL for greater is incorrect'
}
@Test
@DisplayName('GREATER_OR_EQUAL uses proper SQL')
void greaterOrEqualSQL() {
assertEquals('The SQL for greater-or-equal is incorrect', '>=', Op.GREATER_OR_EQUAL.sql)
assertEquals '>=', Op.GREATER_OR_EQUAL.sql, 'The SQL for greater-or-equal is incorrect'
}
@Test
@DisplayName('LESS uses proper SQL')
void lessSQL() {
assertEquals('The SQL for less is incorrect', '<', Op.LESS.sql)
assertEquals '<', Op.LESS.sql, 'The SQL for less is incorrect'
}
@Test
@DisplayName('LESS_OR_EQUAL uses proper SQL')
void lessOrEqualSQL() {
assertEquals('The SQL for less-or-equal is incorrect', '<=', Op.LESS_OR_EQUAL.sql)
assertEquals '<=', Op.LESS_OR_EQUAL.sql, 'The SQL for less-or-equal is incorrect'
}
@Test
@DisplayName('NOT_EQUAL uses proper SQL')
void notEqualSQL() {
assertEquals('The SQL for not-equal is incorrect', '<>', Op.NOT_EQUAL.sql)
assertEquals '<>', Op.NOT_EQUAL.sql, 'The SQL for not-equal is incorrect'
}
@Test
@DisplayName('BETWEEN uses proper SQL')
void betweenSQL() {
assertEquals('The SQL for between is incorrect', 'BETWEEN', Op.BETWEEN.sql)
assertEquals 'BETWEEN', Op.BETWEEN.sql, 'The SQL for between is incorrect'
}
@Test
@DisplayName('IN uses proper SQL')
void inSQL() {
assertEquals('The SQL for in is incorrect', 'IN', Op.IN.sql)
assertEquals 'IN', Op.IN.sql, 'The SQL for in is incorrect'
}
@Test
@DisplayName('IN_ARRAY uses proper SQL')
void inArraySQL() {
assertEquals('The SQL for in-array is incorrect', '??|', Op.IN_ARRAY.sql)
assertEquals '??|', Op.IN_ARRAY.sql, 'The SQL for in-array is incorrect'
}
@Test
@DisplayName('EXISTS uses proper SQL')
void existsSQL() {
assertEquals('The SQL for exists is incorrect', 'IS NOT NULL', Op.EXISTS.sql)
assertEquals 'IS NOT NULL', Op.EXISTS.sql, 'The SQL for exists is incorrect'
}
@Test
@DisplayName('NOT_EXISTS uses proper SQL')
void notExistsSQL() {
assertEquals('The SQL for not-exists is incorrect', 'IS NULL', Op.NOT_EXISTS.sql)
assertEquals 'IS NULL', Op.NOT_EXISTS.sql, 'The SQL for not-exists is incorrect'
}
}

View File

@ -3,7 +3,9 @@ package solutions.bitbadger.documents.groovy
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import solutions.bitbadger.documents.ParameterName
import static groovy.test.GroovyAssert.assertEquals
import static org.junit.jupiter.api.Assertions.assertEquals
/**
* Unit tests for the `ParameterName` class
*/
@ -14,17 +16,17 @@ class ParameterNameTest {
@DisplayName('derive works when given existing names')
void withExisting() {
def names = new ParameterName()
assertEquals('Name should have been :taco', ':taco', names.derive(':taco'))
assertEquals('Counter should not have advanced for named field', ':field0', names.derive(null))
assertEquals ':taco', names.derive(':taco'), 'Name should have been :taco'
assertEquals ':field0', names.derive(null), 'Counter should not have advanced for named field'
}
@Test
@DisplayName('derive works when given all anonymous fields')
void allAnonymous() {
def names = new ParameterName()
assertEquals('Anonymous field name should have been returned', ':field0', names.derive(null))
assertEquals('Counter should have advanced from previous call', ':field1', names.derive(null))
assertEquals('Counter should have advanced from previous call', ':field2', names.derive(null))
assertEquals('Counter should have advanced from previous call', ':field3', names.derive(null))
assertEquals ':field0', names.derive(null), 'Anonymous field name should have been returned'
assertEquals ':field1', names.derive(null), 'Counter should have advanced from previous call'
assertEquals ':field2', names.derive(null), 'Counter should have advanced from previous call'
assertEquals ':field3', names.derive(null), 'Counter should have advanced from previous call'
}
}

View File

@ -6,7 +6,7 @@ import org.junit.jupiter.api.Test
import solutions.bitbadger.documents.Parameter
import solutions.bitbadger.documents.ParameterType
import static groovy.test.GroovyAssert.*
import static org.junit.jupiter.api.Assertions.*
/**
* Unit tests for the `Parameter` class
@ -15,27 +15,27 @@ import static groovy.test.GroovyAssert.*
class ParameterTest {
@Test
@DisplayName("Construction with colon-prefixed name")
@DisplayName('Construction with colon-prefixed name')
void ctorWithColon() {
def p = new Parameter(":test", ParameterType.STRING, "ABC")
assertEquals("Parameter name was incorrect", ":test", p.name)
assertEquals("Parameter type was incorrect", ParameterType.STRING, p.type)
assertEquals("Parameter value was incorrect", "ABC", p.value)
def p = new Parameter(':test', ParameterType.STRING, 'ABC')
assertEquals ':test', p.name, 'Parameter name was incorrect'
assertEquals ParameterType.STRING, p.type, 'Parameter type was incorrect'
assertEquals 'ABC', p.value, 'Parameter value was incorrect'
}
@Test
@DisplayName("Construction with at-sign-prefixed name")
@DisplayName('Construction with at-sign-prefixed name')
void ctorWithAtSign() {
def p = new Parameter("@yo", ParameterType.NUMBER, null)
assertEquals("Parameter name was incorrect", "@yo", p.name)
assertEquals("Parameter type was incorrect", ParameterType.NUMBER, p.type)
assertNull("Parameter value was incorrect", p.value)
def p = new Parameter('@yo', ParameterType.NUMBER, null)
assertEquals '@yo', p.name, 'Parameter name was incorrect'
assertEquals ParameterType.NUMBER, p.type, 'Parameter type was incorrect'
assertNull p.value, 'Parameter value was incorrect'
}
// TODO: resolve java.base open issue
// @Test
// @DisplayName("Construction fails with incorrect prefix")
// @DisplayName('Construction fails with incorrect prefix')
// void ctorFailsForPrefix() {
// assertThrows(DocumentException) { new Parameter("it", ParameterType.JSON, "") }
// assertThrows(DocumentException) { new Parameter('it', ParameterType.JSON, '') }
// }
}

View File

@ -0,0 +1,122 @@
package solutions.bitbadger.documents.groovy.jvm
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
//import solutions.bitbadger.documents.DocumentException
import solutions.bitbadger.documents.Field
import solutions.bitbadger.documents.Parameter
import solutions.bitbadger.documents.ParameterType
import solutions.bitbadger.documents.jvm.Parameters
import solutions.bitbadger.documents.support.ForceDialect
import static groovy.test.GroovyAssert.*
/**
* Unit tests for the `Parameters` object
*/
@DisplayName('JVM | Groovy | Parameters')
class ParametersTest {
/**
* Reset the dialect
*/
@AfterEach
void cleanUp() {
ForceDialect.none()
}
@Test
@DisplayName('nameFields works with no changes')
void nameFieldsNoChange() {
def fields = List.of(Field.equal('a', '', ':test'), Field.exists('q'), Field.equal('b', '', ':me'))
def named = Parameters.nameFields(fields).toList()
assertEquals('There should have been 3 fields in the list', fields.size(), named.size())
assertSame('The first field should be the same', fields[0], named[0])
assertSame('The second field should be the same', fields[1], named[1])
assertSame('The third field should be the same', fields[2], named[2])
}
@Test
@DisplayName('nameFields works when changing fields')
void nameFieldsChange() {
def fields = List.of(Field.equal('a', ''), Field.equal('e', '', ':hi'), Field.equal('b', ''),
Field.notExists('z'))
def named = Parameters.nameFields(fields).toList()
assertEquals('There should have been 4 fields in the list', fields.size(), named.size())
assertNotSame('The first field should not be the same', fields[0], named[0])
assertEquals('First parameter name incorrect', ':field0', named[0].parameterName)
assertSame('The second field should be the same', fields[1], named[1])
assertNotSame('The third field should not be the same', fields[2], named[2])
assertEquals('Third parameter name incorrect', ':field1', named[2].parameterName)
assertSame('The fourth field should be the same', fields[3], named[3])
}
@Test
@DisplayName('replaceNamesInQuery replaces successfully')
void replaceNamesInQuery() {
def parameters = List.of(new Parameter(':data', ParameterType.JSON, '{}'),
new Parameter(':data_ext', ParameterType.STRING, ''))
def query = 'SELECT data, data_ext FROM tbl WHERE data = :data AND data_ext = :data_ext AND more_data = :data'
assertEquals('Parameters not replaced correctly',
'SELECT data, data_ext FROM tbl WHERE data = ? AND data_ext = ? AND more_data = ?',
Parameters.replaceNamesInQuery(query, parameters))
}
@Test
@DisplayName('fieldNames generates a single parameter (PostgreSQL)')
void fieldNamesSinglePostgres() {
ForceDialect.postgres()
def nameParams = Parameters.fieldNames(List.of('test')).toList()
assertEquals('There should be one name parameter', 1, nameParams.size())
assertEquals('The parameter name is incorrect', ':name', nameParams[0].name)
assertEquals('The parameter type is incorrect', ParameterType.STRING, nameParams[0].type)
assertEquals('The parameter value is incorrect', '{test}', nameParams[0].value)
}
@Test
@DisplayName('fieldNames generates multiple parameters (PostgreSQL)')
void fieldNamesMultiplePostgres() {
ForceDialect.postgres()
def nameParams = Parameters.fieldNames(List.of('test', 'this', 'today')).toList()
assertEquals('There should be one name parameter', 1, nameParams.size())
assertEquals('The parameter name is incorrect', ':name', nameParams[0].name)
assertEquals('The parameter type is incorrect', ParameterType.STRING, nameParams[0].type)
assertEquals('The parameter value is incorrect', '{test,this,today}', nameParams[0].value)
}
@Test
@DisplayName('fieldNames generates a single parameter (SQLite)')
void fieldNamesSingleSQLite() {
ForceDialect.sqlite()
def nameParams = Parameters.fieldNames(List.of('test')).toList()
assertEquals('There should be one name parameter', 1, nameParams.size())
assertEquals('The parameter name is incorrect', ':name0', nameParams[0].name)
assertEquals('The parameter type is incorrect', ParameterType.STRING, nameParams[0].type)
assertEquals('The parameter value is incorrect', 'test', nameParams[0].value)
}
@Test
@DisplayName('fieldNames generates multiple parameters (SQLite)')
void fieldNamesMultipleSQLite() {
ForceDialect.sqlite()
def nameParams = Parameters.fieldNames(List.of('test', 'this', 'today')).toList()
assertEquals('There should be one name parameter', 3, nameParams.size())
assertEquals('The first parameter name is incorrect', ':name0', nameParams[0].name)
assertEquals('The first parameter type is incorrect', ParameterType.STRING, nameParams[0].type)
assertEquals('The first parameter value is incorrect', 'test', nameParams[0].value)
assertEquals('The second parameter name is incorrect', ':name1', nameParams[1].name)
assertEquals('The second parameter type is incorrect', ParameterType.STRING, nameParams[1].type)
assertEquals('The second parameter value is incorrect', 'this', nameParams[1].value)
assertEquals('The third parameter name is incorrect', ':name2', nameParams[2].name)
assertEquals('The third parameter type is incorrect', ParameterType.STRING, nameParams[2].type)
assertEquals('The third parameter value is incorrect', 'today', nameParams[2].value)
}
// TODO: resolve java.base open issue
// @Test
// @DisplayName('fieldNames fails if dialect not set')
// void fieldNamesFails() {
// assertThrows(DocumentException) { Parameters.fieldNames(List.of()) }
// }
}

View File

@ -0,0 +1,53 @@
package solutions.bitbadger.documents.groovy.jvm.integration.common
import solutions.bitbadger.documents.Field
import solutions.bitbadger.documents.groovy.support.JsonDocument
import solutions.bitbadger.documents.support.ThrowawayDatabase
import static solutions.bitbadger.documents.extensions.ConnExt.*
import static solutions.bitbadger.documents.support.TypesKt.TEST_TABLE
import static groovy.test.GroovyAssert.*
class CountFunctions {
static void all(ThrowawayDatabase db) {
JsonDocument.load(db)
assertEquals('There should have been 5 documents in the table', 5L, countAll(db.conn, TEST_TABLE))
}
static void byFieldsNumeric(ThrowawayDatabase db) {
JsonDocument.load(db)
assertEquals('There should have been 3 matching documents', 3L,
countByFields(db.conn, TEST_TABLE, List.of(Field.between('numValue', 10, 20))))
}
static void byFieldsAlpha(ThrowawayDatabase db) {
JsonDocument.load(db)
assertEquals('There should have been 1 matching document', 1L,
countByFields(db.conn, TEST_TABLE, List.of(Field.between('value', 'aardvark', 'apple'))))
}
static void byContainsMatch(ThrowawayDatabase db) {
JsonDocument.load(db)
assertEquals('There should have been 2 matching documents', 2L,
countByContains(db.conn, TEST_TABLE, Map.of('value', 'purple')))
}
static void byContainsNoMatch(ThrowawayDatabase db) {
JsonDocument.load(db)
assertEquals('There should have been no matching documents', 0L,
countByContains(db.conn, TEST_TABLE, Map.of('value', 'magenta')))
}
static void byJsonPathMatch(ThrowawayDatabase db) {
JsonDocument.load(db)
assertEquals('There should have been 2 matching documents', 2L,
countByJsonPath(db.conn, TEST_TABLE, '$.numValue ? (@ < 5)'))
}
static void byJsonPathNoMatch(ThrowawayDatabase db) {
JsonDocument.load(db)
assertEquals('There should have been no matching documents', 0L,
countByJsonPath(db.conn, TEST_TABLE, '$.numValue ? (@ > 100)'))
}
}

View File

@ -0,0 +1,25 @@
package solutions.bitbadger.documents.groovy.jvm.integration.postgresql
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import solutions.bitbadger.documents.groovy.jvm.integration.common.CountFunctions
import solutions.bitbadger.documents.jvm.integration.postgresql.PgDB
/**
* PostgreSQL integration tests for the `Count` object / `count*` connection extension functions
*/
@DisplayName("JVM | Groovy | PostgreSQL: Count")
class CountIT {
@Test
@DisplayName("all counts all documents")
void all() {
PgDB db = new PgDB()
try {
CountFunctions.all(db)
} finally {
db.close()
}
}
}

View File

@ -0,0 +1,33 @@
package solutions.bitbadger.documents.groovy.support
import solutions.bitbadger.documents.jvm.Document
import solutions.bitbadger.documents.support.ThrowawayDatabase
import static solutions.bitbadger.documents.support.TypesKt.TEST_TABLE
class JsonDocument {
String id
String value
int numValue
SubDocument sub
JsonDocument(String id, String value = "", int numValue = 0, SubDocument sub = null) {
this.id = id
this.value = value
this.numValue = numValue
this.sub = sub
}
private static final List<JsonDocument> testDocuments = List.of(
new JsonDocument("one", "FIRST!", 0),
new JsonDocument("two", "another", 10, new SubDocument("green", "blue")),
new JsonDocument("three", "", 4),
new JsonDocument("four", "purple", 17, new SubDocument("green", "red")),
new JsonDocument("five", "purple", 18))
static void load(ThrowawayDatabase db, String tableName = TEST_TABLE) {
for (doc in testDocuments) {
Document.insert(tableName, doc, db.conn)
}
}
}

View File

@ -0,0 +1,11 @@
package solutions.bitbadger.documents.groovy.support
class SubDocument {
String foo
String bar
SubDocument(String foo, String bar) {
this.foo = foo
this.bar = bar
}
}

View File

@ -4,6 +4,7 @@ import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.assertThrows
import solutions.bitbadger.documents.*
import solutions.bitbadger.documents.support.ForceDialect
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNotSame
@ -20,7 +21,7 @@ class ParametersTest {
*/
@AfterEach
fun cleanUp() {
Configuration.connectionString = null
ForceDialect.none()
}
@Test
@ -65,7 +66,7 @@ class ParametersTest {
@Test
@DisplayName("fieldNames generates a single parameter (PostgreSQL)")
fun fieldNamesSinglePostgres() {
Configuration.connectionString = ":postgresql:"
ForceDialect.postgres()
val nameParams = Parameters.fieldNames(listOf("test")).toList()
assertEquals(1, nameParams.size, "There should be one name parameter")
assertEquals(":name", nameParams[0].name, "The parameter name is incorrect")
@ -76,7 +77,7 @@ class ParametersTest {
@Test
@DisplayName("fieldNames generates multiple parameters (PostgreSQL)")
fun fieldNamesMultiplePostgres() {
Configuration.connectionString = ":postgresql:"
ForceDialect.postgres()
val nameParams = Parameters.fieldNames(listOf("test", "this", "today")).toList()
assertEquals(1, nameParams.size, "There should be one name parameter")
assertEquals(":name", nameParams[0].name, "The parameter name is incorrect")
@ -87,7 +88,7 @@ class ParametersTest {
@Test
@DisplayName("fieldNames generates a single parameter (SQLite)")
fun fieldNamesSingleSQLite() {
Configuration.connectionString = ":sqlite:"
ForceDialect.sqlite()
val nameParams = Parameters.fieldNames(listOf("test")).toList()
assertEquals(1, nameParams.size, "There should be one name parameter")
assertEquals(":name0", nameParams[0].name, "The parameter name is incorrect")
@ -98,7 +99,7 @@ class ParametersTest {
@Test
@DisplayName("fieldNames generates multiple parameters (SQLite)")
fun fieldNamesMultipleSQLite() {
Configuration.connectionString = ":sqlite:"
ForceDialect.sqlite()
val nameParams = Parameters.fieldNames(listOf("test", "this", "today")).toList()
assertEquals(3, nameParams.size, "There should be one name parameter")
assertEquals(":name0", nameParams[0].name, "The first parameter name is incorrect")

View File

@ -7,7 +7,7 @@ import kotlin.test.Test
/**
* PostgreSQL integration tests for the `Count` object / `count*` connection extension functions
*/
@DisplayName("Java | Kotlin | PostgreSQL: Count")
@DisplayName("JVM | Kotlin | PostgreSQL: Count")
class CountIT {
@Test

View File

@ -9,7 +9,7 @@ import kotlin.test.Test
/**
* SQLite integration tests for the `Count` object / `count*` connection extension functions
*/
@DisplayName("Java | Kotlin | SQLite: Count")
@DisplayName("JVM | Kotlin | SQLite: Count")
class CountIT {
@Test

View File

@ -0,0 +1,103 @@
package solutions.bitbadger.documents.scala.jvm
import org.junit.jupiter.api.{AfterEach, DisplayName, Test}
import org.junit.jupiter.api.Assertions.*
import solutions.bitbadger.documents.{DocumentException, Field, Parameter, ParameterType}
import solutions.bitbadger.documents.jvm.Parameters
import solutions.bitbadger.documents.support.ForceDialect
import scala.jdk.CollectionConverters.*
@DisplayName("JVM | Scala | Parameters")
class ParametersTest {
/**
* Reset the dialect
*/
@AfterEach
def cleanUp(): Unit =
ForceDialect.none()
@Test
@DisplayName("nameFields works with no changes")
def nameFieldsNoChange(): Unit =
val fields = Field.equal("a", "", ":test") :: Field.exists("q") :: Field.equal("b", "", ":me") :: Nil
val named = Parameters.nameFields(fields.asJava).asScala.toList
assertEquals(fields.size, named.size, "There should have been 3 fields in the list")
assertSame(fields.head, named.head, "The first field should be the same")
assertSame(fields(1), named(1), "The second field should be the same")
assertSame(fields(2), named(2), "The third field should be the same")
@Test
@DisplayName("nameFields works when changing fields")
def nameFieldsChange(): Unit =
val fields = Field.equal("a", "") :: Field.equal("e", "", ":hi") :: Field.equal("b", "") ::
Field.notExists("z") :: Nil
val named = Parameters.nameFields(fields.asJava).asScala.toList
assertEquals(fields.size, named.size, "There should have been 4 fields in the list")
assertNotSame(fields.head, named.head, "The first field should not be the same")
assertEquals(":field0", named.head.getParameterName, "First parameter name incorrect")
assertSame(fields(1), named(1), "The second field should be the same")
assertNotSame(fields(2), named(2), "The third field should not be the same")
assertEquals(":field1", named(2).getParameterName, "Third parameter name incorrect")
assertSame(fields(3), named(3), "The fourth field should be the same")
@Test
@DisplayName("replaceNamesInQuery replaces successfully")
def replaceNamesInQuery(): Unit =
val parameters =
(Parameter(":data", ParameterType.JSON, "{}") :: Parameter(":data_ext", ParameterType.STRING, "") :: Nil).asJava
val query = "SELECT data, data_ext FROM tbl WHERE data = :data AND data_ext = :data_ext AND more_data = :data"
assertEquals("SELECT data, data_ext FROM tbl WHERE data = ? AND data_ext = ? AND more_data = ?",
Parameters.replaceNamesInQuery(query, parameters), "Parameters not replaced correctly")
@Test
@DisplayName("fieldNames generates a single parameter (PostgreSQL)")
def fieldNamesSinglePostgres(): Unit =
ForceDialect.postgres()
val nameParams = Parameters.fieldNames(("test" :: Nil).asJava).asScala.toList
assertEquals(1, nameParams.size, "There should be one name parameter")
assertEquals(":name", nameParams.head.getName, "The parameter name is incorrect")
assertEquals(ParameterType.STRING, nameParams.head.getType, "The parameter type is incorrect")
assertEquals("{test}", nameParams.head.getValue, "The parameter value is incorrect")
@Test
@DisplayName("fieldNames generates multiple parameters (PostgreSQL)")
def fieldNamesMultiplePostgres(): Unit =
ForceDialect.postgres()
val nameParams = Parameters.fieldNames(("test" :: "this" :: "today" :: Nil).asJava).asScala.toList
assertEquals(1, nameParams.size, "There should be one name parameter")
assertEquals(":name", nameParams.head.getName, "The parameter name is incorrect")
assertEquals(ParameterType.STRING, nameParams.head.getType, "The parameter type is incorrect")
assertEquals("{test,this,today}", nameParams.head.getValue, "The parameter value is incorrect")
@Test
@DisplayName("fieldNames generates a single parameter (SQLite)")
def fieldNamesSingleSQLite(): Unit =
ForceDialect.sqlite()
val nameParams = Parameters.fieldNames(("test" :: Nil).asJava).asScala.toList
assertEquals(1, nameParams.size, "There should be one name parameter")
assertEquals(":name0", nameParams.head.getName, "The parameter name is incorrect")
assertEquals(ParameterType.STRING, nameParams.head.getType, "The parameter type is incorrect")
assertEquals("test", nameParams.head.getValue, "The parameter value is incorrect")
@Test
@DisplayName("fieldNames generates multiple parameters (SQLite)")
def fieldNamesMultipleSQLite(): Unit =
ForceDialect.sqlite()
val nameParams = Parameters.fieldNames(("test" :: "this" :: "today" :: Nil).asJava).asScala.toList
assertEquals(3, nameParams.size, "There should be one name parameter")
assertEquals(":name0", nameParams.head.getName, "The first parameter name is incorrect")
assertEquals(ParameterType.STRING, nameParams.head.getType, "The first parameter type is incorrect")
assertEquals("test", nameParams.head.getValue, "The first parameter value is incorrect")
assertEquals(":name1", nameParams(1).getName, "The second parameter name is incorrect")
assertEquals(ParameterType.STRING, nameParams(1).getType, "The second parameter type is incorrect")
assertEquals("this", nameParams(1).getValue, "The second parameter value is incorrect")
assertEquals(":name2", nameParams(2).getName, "The third parameter name is incorrect")
assertEquals(ParameterType.STRING, nameParams(2).getType, "The third parameter type is incorrect")
assertEquals("today", nameParams(2).getValue, "The third parameter value is incorrect")
@Test
@DisplayName("fieldNames fails if dialect not set")
def fieldNamesFails(): Unit =
assertThrows(classOf[DocumentException], () => Parameters.fieldNames(List().asJava))
}

View File

@ -0,0 +1,47 @@
package solutions.bitbadger.documents.scala.jvm.integration.common
import org.junit.jupiter.api.Assertions.*
import solutions.bitbadger.documents.Field
import solutions.bitbadger.documents.extensions.ConnExt.*
import solutions.bitbadger.documents.scala.support.JsonDocument
import solutions.bitbadger.documents.support.ThrowawayDatabase
import solutions.bitbadger.documents.support.TypesKt.TEST_TABLE
import scala.jdk.CollectionConverters.*
object CountFunctions {
def all(db: ThrowawayDatabase): Unit =
JsonDocument.load(db)
assertEquals(5L, countAll(db.getConn, TEST_TABLE), "There should have been 5 documents in the table")
def byFieldsNumeric(db: ThrowawayDatabase): Unit =
JsonDocument.load(db)
assertEquals(3L, countByFields(db.getConn, TEST_TABLE, (Field.between("numValue", 10, 20) :: Nil).asJava),
"There should have been 3 matching documents")
def byFieldsAlpha(db: ThrowawayDatabase): Unit =
JsonDocument.load(db)
assertEquals(1L, countByFields(db.getConn, TEST_TABLE, (Field.between("value", "aardvark", "apple") :: Nil).asJava),
"There should have been 1 matching document")
def byContainsMatch(db: ThrowawayDatabase): Unit =
JsonDocument.load(db)
assertEquals(2L, countByContains(db.getConn, TEST_TABLE, Map.Map1("value", "purple")),
"There should have been 2 matching documents")
def byContainsNoMatch(db: ThrowawayDatabase): Unit =
JsonDocument.load(db)
assertEquals(0L, countByContains(db.getConn, TEST_TABLE, Map.Map1("value", "magenta")),
"There should have been no matching documents")
def byJsonPathMatch(db: ThrowawayDatabase): Unit =
JsonDocument.load(db)
assertEquals(2L, countByJsonPath(db.getConn, TEST_TABLE, "$.numValue ? (@ < 5)"),
"There should have been 2 matching documents")
def byJsonPathNoMatch(db: ThrowawayDatabase): Unit =
JsonDocument.load(db)
assertEquals(0L, countByJsonPath(db.getConn, TEST_TABLE, "$.numValue ? (@ > 100)"),
"There should have been no matching documents")
}

View File

@ -0,0 +1,46 @@
package solutions.bitbadger.documents.scala.jvm.integration.postgresql
import org.junit.jupiter.api.{DisplayName, Test}
import solutions.bitbadger.documents.jvm.integration.postgresql.PgDB
import solutions.bitbadger.documents.scala.jvm.integration.common.CountFunctions
import scala.util.Using
@DisplayName("JVM | Scala | PostgreSQL: Count")
class CountIT {
@Test
@DisplayName("all counts all documents")
def all(): Unit =
Using(PgDB()) { db => CountFunctions.all(db) }
@Test
@DisplayName("byFields counts documents by a numeric value")
def byFieldsNumeric(): Unit =
Using(PgDB()) { db => CountFunctions.byFieldsNumeric(db) }
@Test
@DisplayName("byFields counts documents by a alphanumeric value")
def byFieldsAlpha(): Unit =
Using(PgDB()) { db => CountFunctions.byFieldsAlpha(db) }
@Test
@DisplayName("byContains counts documents when matches are found")
def byContainsMatch(): Unit =
Using(PgDB()) { db => CountFunctions.byContainsMatch(db) }
@Test
@DisplayName("byContains counts documents when no matches are found")
def byContainsNoMatch(): Unit =
Using(PgDB()) { db => CountFunctions.byContainsNoMatch(db) }
@Test
@DisplayName("byJsonPath counts documents when matches are found")
def byJsonPathMatch(): Unit =
Using(PgDB()) { db => CountFunctions.byJsonPathMatch(db) }
@Test
@DisplayName("byJsonPath counts documents when no matches are found")
def byJsonPathNoMatch(): Unit =
Using(PgDB()) { db => CountFunctions.byJsonPathNoMatch(db) }
}

View File

@ -0,0 +1,38 @@
package solutions.bitbadger.documents.scala.jvm.integration.sqlite
import org.junit.jupiter.api.{DisplayName, Test}
import solutions.bitbadger.documents.jvm.integration.sqlite.SQLiteDB
import solutions.bitbadger.documents.scala.jvm.integration.common.CountFunctions
import org.junit.jupiter.api.Assertions.assertThrows
import solutions.bitbadger.documents.DocumentException
import scala.util.Using
@DisplayName("JVM | Scala | SQLite: Count")
class CountIT {
@Test
@DisplayName("all counts all documents")
def all(): Unit =
Using(SQLiteDB()) { db => CountFunctions.all(db) }
@Test
@DisplayName("byFields counts documents by a numeric value")
def byFieldsNumeric(): Unit =
Using(SQLiteDB()) { db => CountFunctions.byFieldsNumeric(db) }
@Test
@DisplayName("byFields counts documents by a alphanumeric value")
def byFieldsAlpha(): Unit =
Using(SQLiteDB()) { db => CountFunctions.byFieldsAlpha(db) }
@Test
@DisplayName("byContains fails")
def byContainsMatch(): Unit =
Using(SQLiteDB()) { db => assertThrows(classOf[DocumentException], () => CountFunctions.byContainsMatch(db)) }
@Test
@DisplayName("byJsonPath fails")
def byJsonPathMatch(): Unit =
Using(SQLiteDB()) { db => assertThrows(classOf[DocumentException], () => CountFunctions.byJsonPathMatch(db)) }
}

View File

@ -43,7 +43,7 @@
<kotlin.version>2.1.10</kotlin.version>
<serialization.version>1.8.0</serialization.version>
<scala.version>3.5.2</scala.version>
<groovy.version>3.0.24</groovy.version>
<groovy.version>4.0.26</groovy.version>
<sqlite.version>3.46.1.2</sqlite.version>
<postgresql.version>42.7.5</postgresql.version>
</properties>