├── .idea └── .name ├── .gitignore ├── src ├── main │ ├── resources │ │ └── component.marker │ └── java │ │ └── sirius │ │ └── db │ │ ├── text │ │ ├── ToLowercaseProcessor.java │ │ ├── PurgeProcessor.java │ │ ├── ReduceCharacterProcessor.java │ │ ├── TokenProcessor.java │ │ ├── BasicSearchTokenizer.java │ │ ├── DeduplicateProcessor.java │ │ ├── TokenLimitProcessor.java │ │ └── PatternReplaceProcessor.java │ │ ├── mongo │ │ ├── package-info.java │ │ ├── MongoEntityCache.java │ │ ├── IndexDescription.java │ │ ├── types │ │ │ ├── MultiPointLocation.java │ │ │ └── MongoRefList.java │ │ ├── constraints │ │ │ └── MongoConstraint.java │ │ └── facets │ │ │ └── MongoFacet.java │ │ ├── jdbc │ │ ├── schema │ │ │ ├── MariaDBDatabaseDialect.java │ │ │ └── SQLPropertyInfo.java │ │ ├── constraints │ │ │ ├── Or.java │ │ │ ├── And.java │ │ │ ├── SQLConstraint.java │ │ │ ├── Not.java │ │ │ ├── Filled.java │ │ │ ├── NotFilled.java │ │ │ └── FieldOperator.java │ │ ├── SQLEntityCache.java │ │ ├── Operator.java │ │ ├── MonitoredDataSource.java │ │ ├── batch │ │ │ └── BatchSQLQuery.java │ │ └── TranslationState.java │ │ ├── mixing │ │ ├── types │ │ │ ├── StringMap.java │ │ │ ├── StringIntMap.java │ │ │ ├── StringBooleanMap.java │ │ │ ├── StringLocalDateTimeMap.java │ │ │ ├── StringList.java │ │ │ ├── NestedList.java │ │ │ └── StringNestedMap.java │ │ ├── annotations │ │ │ ├── Lob.java │ │ │ ├── Versioned.java │ │ │ ├── NullAllowed.java │ │ │ ├── Trim.java │ │ │ ├── Transient.java │ │ │ ├── Ordinal.java │ │ │ ├── RemoveWhitespace.java │ │ │ ├── LowerCase.java │ │ │ ├── UpperCase.java │ │ │ ├── MaxValue.java │ │ │ ├── MinValue.java │ │ │ ├── DefaultValue.java │ │ │ ├── Realm.java │ │ │ ├── Positive.java │ │ │ ├── Engine.java │ │ │ ├── RelationName.java │ │ │ ├── Indices.java │ │ │ ├── AfterDelete.java │ │ │ ├── BeforeDelete.java │ │ │ ├── Length.java │ │ │ ├── Mixin.java │ │ │ ├── Numeric.java │ │ │ ├── BeforeSave.java │ │ │ ├── AfterSave.java │ │ │ ├── OnValidate.java │ │ │ ├── SkipDefaultValue.java │ │ │ ├── Unique.java │ │ │ ├── ComplexDelete.java │ │ │ ├── ValidatedBy.java │ │ │ └── TranslationSource.java │ │ ├── Composite.java │ │ ├── query │ │ │ ├── constraints │ │ │ │ └── Constraint.java │ │ │ └── QueryTagHandler.java │ │ ├── PropertyValidator.java │ │ ├── ContextInfo.java │ │ ├── InvalidFieldException.java │ │ ├── MixinLoadAction.java │ │ └── IntegrityConstraintFailedException.java │ │ ├── DB.java │ │ ├── es │ │ ├── annotations │ │ │ ├── RoutedBy.java │ │ │ ├── ESOption.java │ │ │ └── CustomSettings.java │ │ ├── IndexNaming.java │ │ ├── SettingsCustomizer.java │ │ └── types │ │ │ └── ElasticRefList.java │ │ ├── redis │ │ └── Subscriber.java │ │ └── KeyGenerator.java └── test │ ├── resources │ ├── component.marker │ ├── test_de.properties │ ├── docker-db.yml │ └── test.conf │ ├── java │ ├── sirius │ │ └── db │ │ │ ├── mongo │ │ │ ├── properties │ │ │ │ ├── MongoStringMapMixinEntity.java │ │ │ │ ├── MongoStringListMixinEntity.java │ │ │ │ ├── MongoStringMapEntity.java │ │ │ │ ├── MongoStringIntMapEntity.java │ │ │ │ ├── MongoStringListEntity.java │ │ │ │ ├── MongoStringListMapEntity.java │ │ │ │ ├── MongoStringBooleanMapEntity.java │ │ │ │ ├── MongoExistsEntity.java │ │ │ │ ├── MongoMultiPointEntity.java │ │ │ │ ├── MongoStringMapMixin.java │ │ │ │ ├── MongoStringListMixin.java │ │ │ │ ├── MongoFilledEntity.java │ │ │ │ ├── MongoAmountEntity.java │ │ │ │ ├── MongoNestedListEntity.java │ │ │ │ └── MongoStringNestedMapEntity.java │ │ │ ├── MangoListTestEntity.java │ │ │ ├── MangoAggregationsTestEntity.java │ │ │ ├── MongoLockedTestEntity.java │ │ │ ├── MongoUniqueTestEntity.java │ │ │ ├── PrefixTestEntity.java │ │ │ ├── MangoWasCreatedTestEntity.java │ │ │ └── validators │ │ │ │ └── StringTestPropertyValidator.java │ │ │ ├── mixing │ │ │ ├── WriteOnceParentEntity.java │ │ │ ├── MongoComposite.java │ │ │ ├── MongoMixable.java │ │ │ ├── RefListElasticEntity.java │ │ │ ├── RefMongoEntity.java │ │ │ ├── RefElasticEntity.java │ │ │ ├── RefListMongoEntity.java │ │ │ ├── WriteOnceChildEntity.java │ │ │ ├── fieldlookup │ │ │ │ ├── MongoSuperHeroTestMixin.java │ │ │ │ ├── NameFieldsTestComposite.java │ │ │ │ └── SQLSuperHeroTestMixin.java │ │ │ ├── RefEntity.java │ │ │ └── properties │ │ │ │ └── DateEntity.java │ │ │ ├── jdbc │ │ │ ├── TestCompositeWithComposite.java │ │ │ ├── TestClobEntity.java │ │ │ ├── ListTestEntity.java │ │ │ ├── TransformedQueryTestEntity.java │ │ │ ├── TestMixinMixin.java │ │ │ ├── SmartQueryTestMixinEntity.java │ │ │ ├── TestEntityWithComposite.java │ │ │ ├── SQLStringListNonNullAllowedPropertyEntity.java │ │ │ ├── SQLLockedTestEntity.java │ │ │ ├── SQLUniqueTestEntity.java │ │ │ ├── SmartQueryTestParentEntity.java │ │ │ ├── TestMixin.java │ │ │ ├── SmartQueryTestMixinEntityMixin.java │ │ │ ├── SmartQueryTestLargeTableEntity.java │ │ │ ├── LegacyEntity.java │ │ │ ├── TestComposite.java │ │ │ ├── SQLWasCreatedTestEntity.java │ │ │ ├── SQLStringListPropertyEntity.java │ │ │ ├── SmartQueryTestChildChildEntity.java │ │ │ ├── SmartQueryTestEntity.java │ │ │ ├── TestEntityWithNullRef.java │ │ │ ├── SmartQueryTestCountEntity.java │ │ │ ├── TestEntityWithMixin.java │ │ │ ├── GeneratedStatementTestEntity.java │ │ │ ├── SmartQueryTestSortingEntity.java │ │ │ └── SmartQueryTest.java │ │ │ └── es │ │ │ ├── ESListTestEntity.java │ │ │ ├── properties │ │ │ ├── ESStringMapEntity.java │ │ │ ├── ESStringListEntity.java │ │ │ ├── ESStringListMapEntity.java │ │ │ ├── ESStringBooleanMapEntity.java │ │ │ ├── ESFilledEntity.java │ │ │ ├── ESStringLocalDateTimeMapEntity.java │ │ │ ├── ESDenseVectorEntity.java │ │ │ └── ESNestedListEntity.java │ │ │ ├── LockedTestEntity.java │ │ │ ├── BatchTestEntity.java │ │ │ ├── ElasticWasCreatedTestEntity.java │ │ │ ├── RoutedBatchTestEntity.java │ │ │ ├── SuggestTestEntity.java │ │ │ ├── ElasticTestEntity.java │ │ │ ├── RoutedTestEntity.java │ │ │ └── SuppressedRoutedTestEntity.java │ └── TestSuite.java │ └── kotlin │ └── sirius │ └── db │ ├── text │ ├── PatternReplaceProcessorTest.kt │ ├── ToLowercaseProcessorTest.kt │ ├── PatternExtractProcessorTest.kt │ ├── TokenProcessorTest.kt │ ├── ReduceCharactersProcessorTest.kt │ ├── TokenLimitProcessorTest.kt │ ├── PatternSplitProcessorTest.kt │ ├── PipelineProcessorTest.kt │ └── BasicIndexTokenizerTest.kt │ ├── util │ └── TensorsTest.kt │ ├── testutil │ └── MongoMocks.kt │ ├── mixing │ ├── CompositeTest.kt │ └── properties │ │ ├── LocalDatePropertyTest.kt │ │ ├── LocalTimePropertyTest.kt │ │ └── LocalDateTimePropertyTest.kt │ ├── redis │ └── RedisTest.kt │ ├── jdbc │ └── SmartQueryNighlyTest.kt │ ├── mongo │ └── properties │ │ ├── MongoMultiPointTest.kt │ │ ├── MongoStringMapPropertyTest.kt │ │ └── MongoStringIntMapPropertyTest.kt │ └── es │ └── properties │ ├── ElasticStringMapPropertyTest.kt │ ├── ElasticStringListPropertyTest.kt │ ├── ElasticStringListMapPropertyTest.kt │ └── ElasticStringBooleanMapPropertyTest.kt ├── .github ├── workflows │ ├── main.yml │ ├── ga-releases.yml │ └── enforce-pr-label.yml ├── PULL_REQUEST_TEMPLATE.md └── ga-release-drafter.yml └── .run ├── local install.run.xml └── mvn clean test - without nightly.run.xml /.idea/.name: -------------------------------------------------------------------------------- 1 | sirius-db -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | *.iml 3 | .idea -------------------------------------------------------------------------------- /src/main/resources/component.marker: -------------------------------------------------------------------------------- 1 | This file is discovered by sirius.kernel.Classpath and marks a classpath root which will be scanned. -------------------------------------------------------------------------------- /src/test/resources/component.marker: -------------------------------------------------------------------------------- 1 | This file is discovered by sirius.kernel.Classpath and marks a classpath root which will be scanned. -------------------------------------------------------------------------------- /src/test/resources/test_de.properties: -------------------------------------------------------------------------------- 1 | ESDataTypesEntity.enumValue=Enum Value 2 | Model.firstname=Vorname 3 | Model.shortStringList=Model.shortStringList 4 | MongoIntEntity.testIntPositive=MongoIntEntity.testIntPositive 5 | MongoIntEntity.testIntMaxHundred=MongoIntEntity.testIntMaxHundred 6 | MongoIntEntity.testIntMinHundred=MongoIntEntity.testIntMinHundred 7 | ValidatedByTestEntity.stringTest=ValidatedByTestEntity.stringTest 8 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/mongo/properties/MongoStringMapMixinEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mongo.properties; 10 | 11 | import sirius.db.mongo.MongoEntity; 12 | 13 | public class MongoStringMapMixinEntity extends MongoEntity { 14 | } 15 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/mongo/properties/MongoStringListMixinEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mongo.properties; 10 | 11 | import sirius.db.mongo.MongoEntity; 12 | 13 | public class MongoStringListMixinEntity extends MongoEntity { 14 | } 15 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/mixing/WriteOnceParentEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing; 10 | 11 | import sirius.db.jdbc.SQLEntity; 12 | import sirius.db.mixing.annotations.ComplexDelete; 13 | 14 | @ComplexDelete(false) 15 | public class WriteOnceParentEntity extends SQLEntity { 16 | } 17 | -------------------------------------------------------------------------------- /src/test/java/TestSuite.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | import com.googlecode.junittoolbox.SuiteClasses; 10 | import org.junit.runner.RunWith; 11 | import sirius.kernel.ScenarioSuite; 12 | 13 | @RunWith(ScenarioSuite.class) 14 | @SuiteClasses({"**/*Test.class", "**/*Spec.class"}) 15 | public class TestSuite { 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/text/ToLowercaseProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.text; 10 | 11 | /** 12 | * Converts all tokens to lowercase. 13 | */ 14 | public class ToLowercaseProcessor extends ChainableTokenProcessor { 15 | 16 | @Override 17 | public void accept(String token) { 18 | emit(token.toLowerCase()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/jdbc/TestCompositeWithComposite.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc; 10 | 11 | import sirius.db.mixing.Composite; 12 | 13 | public class TestCompositeWithComposite extends Composite { 14 | 15 | private final TestComposite composite = new TestComposite(); 16 | 17 | public TestComposite getComposite() { 18 | return composite; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Automatic Releases 2 | 3 | on: 4 | push: 5 | branches: [ "develop" ] 6 | tags: 7 | - "dev-*.*.*" 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v3 16 | if: startsWith(github.ref, 'refs/tags/') 17 | 18 | - name: Release 19 | uses: softprops/action-gh-release@v0.1.14 20 | if: startsWith(github.ref, 'refs/tags/') 21 | with: 22 | prerelease: true 23 | generate_release_notes: true 24 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/text/PurgeProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.text; 10 | 11 | /** 12 | * Invokes {@link #purge()} after each token which is simply forwarded to the downstream processor. 13 | */ 14 | public class PurgeProcessor extends ChainableTokenProcessor { 15 | 16 | @Override 17 | public void accept(String token) { 18 | emit(token); 19 | purge(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/mixing/MongoComposite.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing; 10 | 11 | import sirius.db.mixing.types.StringMap; 12 | 13 | public class MongoComposite extends Composite { 14 | 15 | public static final Mapping MAP = Mapping.named("map"); 16 | private final StringMap map = new StringMap(); 17 | 18 | public StringMap getMap() { 19 | return map; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mongo/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | /** 10 | * Thin layer above Mongo DB. 11 | *

12 | * Basically this provides a connection pool which can be configured via the system configuration (namely 13 | * mongo.host and mongo.db). 14 | *

15 | * It also provides fluent query builders for CRUD operations. 16 | * 17 | * @see sirius.db.mongo.Mongo 18 | */ 19 | package sirius.db.mongo; -------------------------------------------------------------------------------- /src/test/java/sirius/db/jdbc/TestClobEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc; 10 | 11 | import sirius.db.mixing.annotations.Lob; 12 | 13 | public class TestClobEntity extends SQLEntity { 14 | 15 | @Lob 16 | private String largeValue; 17 | 18 | public String getLargeValue() { 19 | return largeValue; 20 | } 21 | 22 | public void setLargeValue(String largeValue) { 23 | this.largeValue = largeValue; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/jdbc/schema/MariaDBDatabaseDialect.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc.schema; 10 | 11 | import sirius.kernel.di.std.Register; 12 | 13 | /** 14 | * Defines the dialect used to sync the schema against a MariaDB database. 15 | *

16 | * This is for now equal to a MySQL database. 17 | */ 18 | @Register(name = "mariadb", classes = DatabaseDialect.class) 19 | public class MariaDBDatabaseDialect extends MySQLDatabaseDialect { 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/types/StringMap.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.types; 10 | 11 | /** 12 | * Provides a simple string-string map as property value. 13 | */ 14 | public class StringMap extends SafeMap { 15 | 16 | @Override 17 | protected boolean valueNeedsCopy() { 18 | return false; 19 | } 20 | 21 | @Override 22 | protected String copyValue(String value) { 23 | return value; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/jdbc/constraints/Or.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc.constraints; 10 | 11 | import java.util.List; 12 | 13 | /** 14 | * Represents a set of inner constraints combined with OR. 15 | */ 16 | class Or extends CombinedConstraint { 17 | 18 | protected Or(List inner) { 19 | super(inner); 20 | } 21 | 22 | @Override 23 | protected String getCombiner() { 24 | return " OR "; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/jdbc/constraints/And.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc.constraints; 10 | 11 | import java.util.List; 12 | 13 | /** 14 | * Represents a set of inner constraints combined with AND. 15 | */ 16 | class And extends CombinedConstraint { 17 | 18 | protected And(List inner) { 19 | super(inner); 20 | } 21 | 22 | @Override 23 | protected String getCombiner() { 24 | return " AND "; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/jdbc/ListTestEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc; 10 | 11 | import sirius.db.mixing.Mapping; 12 | 13 | public class ListTestEntity extends SQLEntity { 14 | 15 | public static final Mapping COUNTER = Mapping.named("counter"); 16 | private int counter; 17 | 18 | public int getCounter() { 19 | return counter; 20 | } 21 | 22 | public void setCounter(int counter) { 23 | this.counter = counter; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/es/ESListTestEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.es; 10 | 11 | import sirius.db.mixing.Mapping; 12 | 13 | public class ESListTestEntity extends ElasticEntity { 14 | 15 | public static final Mapping COUNTER = Mapping.named("counter"); 16 | private int counter; 17 | 18 | public int getCounter() { 19 | return counter; 20 | } 21 | 22 | public void setCounter(int counter) { 23 | this.counter = counter; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/mixing/MongoMixable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing; 10 | 11 | import sirius.db.mixing.annotations.Mixin; 12 | 13 | @Mixin(RefMongoEntity.class) 14 | public class MongoMixable extends Mixable { 15 | 16 | public static final Mapping COMPOSITE = Mapping.named("composite"); 17 | private final MongoComposite composite = new MongoComposite(); 18 | 19 | public MongoComposite getComposite() { 20 | return composite; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/types/StringIntMap.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.types; 10 | 11 | /** 12 | * Provides a map of String to int as property value. 13 | */ 14 | public class StringIntMap extends SafeMap { 15 | 16 | @Override 17 | protected boolean valueNeedsCopy() { 18 | return false; 19 | } 20 | 21 | @Override 22 | protected Integer copyValue(Integer value) { 23 | return value; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/mongo/MangoListTestEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mongo; 10 | 11 | import sirius.db.mixing.Mapping; 12 | 13 | public class MangoListTestEntity extends MongoEntity { 14 | 15 | public static final Mapping COUNTER = Mapping.named("counter"); 16 | private int counter; 17 | 18 | public int getCounter() { 19 | return counter; 20 | } 21 | 22 | public void setCounter(int counter) { 23 | this.counter = counter; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/types/StringBooleanMap.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.types; 10 | 11 | /** 12 | * Provides a map of String to Boolean as property value. 13 | */ 14 | public class StringBooleanMap extends SafeMap { 15 | 16 | @Override 17 | protected boolean valueNeedsCopy() { 18 | return false; 19 | } 20 | 21 | @Override 22 | protected Boolean copyValue(Boolean value) { 23 | return value; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/es/properties/ESStringMapEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.es.properties; 10 | 11 | import sirius.db.es.ElasticEntity; 12 | import sirius.db.mixing.Mapping; 13 | import sirius.db.mixing.types.StringMap; 14 | 15 | public class ESStringMapEntity extends ElasticEntity { 16 | 17 | public static final Mapping MAP = Mapping.named("map"); 18 | private final StringMap map = new StringMap(); 19 | 20 | public StringMap getMap() { 21 | return map; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/mongo/MangoAggregationsTestEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mongo; 10 | 11 | import sirius.db.mixing.Mapping; 12 | 13 | public class MangoAggregationsTestEntity extends MongoEntity { 14 | 15 | public static final Mapping TEST_INT = Mapping.named("testInt"); 16 | private int testInt; 17 | 18 | public int getTestInt() { 19 | return testInt; 20 | } 21 | 22 | public void setTestInt(int testInt) { 23 | this.testInt = testInt; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/es/properties/ESStringListEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.es.properties; 10 | 11 | import sirius.db.es.ElasticEntity; 12 | import sirius.db.mixing.Mapping; 13 | import sirius.db.mixing.types.StringList; 14 | 15 | public class ESStringListEntity extends ElasticEntity { 16 | 17 | public static final Mapping LIST = Mapping.named("list"); 18 | private final StringList list = new StringList(); 19 | 20 | public StringList getList() { 21 | return list; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/jdbc/TransformedQueryTestEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc; 10 | 11 | import sirius.db.mixing.annotations.Length; 12 | 13 | /** 14 | * Testentity for TransformedQuerySpec 15 | */ 16 | public class TransformedQueryTestEntity extends SQLEntity { 17 | 18 | @Length(50) 19 | private String value; 20 | 21 | public String getValue() { 22 | return value; 23 | } 24 | 25 | public void setValue(String value) { 26 | this.value = value; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/mongo/properties/MongoStringMapEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mongo.properties; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mixing.types.StringMap; 13 | import sirius.db.mongo.MongoEntity; 14 | 15 | public class MongoStringMapEntity extends MongoEntity { 16 | 17 | public static final Mapping MAP = Mapping.named("map"); 18 | private final StringMap map = new StringMap(); 19 | 20 | public StringMap getMap() { 21 | return map; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/es/properties/ESStringListMapEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.es.properties; 10 | 11 | import sirius.db.es.ElasticEntity; 12 | import sirius.db.mixing.Mapping; 13 | import sirius.db.mixing.types.StringListMap; 14 | 15 | public class ESStringListMapEntity extends ElasticEntity { 16 | 17 | public static final Mapping MAP = Mapping.named("map"); 18 | private final StringListMap map = new StringListMap(); 19 | 20 | public StringListMap getMap() { 21 | return map; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/mongo/properties/MongoStringIntMapEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mongo.properties; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mixing.types.StringIntMap; 13 | import sirius.db.mongo.MongoEntity; 14 | 15 | public class MongoStringIntMapEntity extends MongoEntity { 16 | public static final Mapping MAP = Mapping.named("map"); 17 | private final StringIntMap map = new StringIntMap(); 18 | 19 | public StringIntMap getMap() { 20 | return map; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/mongo/properties/MongoStringListEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mongo.properties; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mixing.types.StringList; 13 | import sirius.db.mongo.MongoEntity; 14 | 15 | public class MongoStringListEntity extends MongoEntity { 16 | 17 | public static final Mapping LIST = Mapping.named("list"); 18 | private final StringList list = new StringList(); 19 | 20 | public StringList getList() { 21 | return list; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/es/LockedTestEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.es; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mixing.annotations.Versioned; 13 | 14 | @Versioned 15 | public class LockedTestEntity extends ElasticEntity { 16 | 17 | public static final Mapping VALUE = Mapping.named("value"); 18 | private String value; 19 | 20 | public String getValue() { 21 | return value; 22 | } 23 | 24 | public void setValue(String value) { 25 | this.value = value; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/mongo/properties/MongoStringListMapEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mongo.properties; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mixing.types.StringListMap; 13 | import sirius.db.mongo.MongoEntity; 14 | 15 | public class MongoStringListMapEntity extends MongoEntity { 16 | 17 | public static final Mapping MAP = Mapping.named("map"); 18 | private final StringListMap map = new StringListMap(); 19 | 20 | public StringListMap getMap() { 21 | return map; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/DB.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db; 10 | 11 | import sirius.kernel.health.Log; 12 | 13 | /** 14 | * Provides constants used throughout sirius-db. 15 | */ 16 | public class DB { 17 | 18 | /** 19 | * Contains a generic logger to be used when a slow database query is detected. 20 | */ 21 | public static final Log SLOW_DB_LOG = Log.get("db-slow"); 22 | 23 | /** 24 | * Constructor is locked as this class only has static members. 25 | */ 26 | private DB() { 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/es/properties/ESStringBooleanMapEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.es.properties; 10 | 11 | import sirius.db.es.ElasticEntity; 12 | import sirius.db.mixing.Mapping; 13 | import sirius.db.mixing.types.StringBooleanMap; 14 | 15 | public class ESStringBooleanMapEntity extends ElasticEntity { 16 | 17 | public static final Mapping MAP = Mapping.named("map"); 18 | private final StringBooleanMap map = new StringBooleanMap(); 19 | 20 | public StringBooleanMap getMap() { 21 | return map; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/jdbc/TestMixinMixin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc; 10 | 11 | import sirius.db.mixing.Mixable; 12 | import sirius.db.mixing.annotations.Length; 13 | import sirius.db.mixing.annotations.Mixin; 14 | 15 | @Mixin(TestMixin.class) 16 | public class TestMixinMixin extends Mixable { 17 | @Length(1) 18 | private String initial; 19 | 20 | public String getInitial() { 21 | return initial; 22 | } 23 | 24 | public void setInitial(String initial) { 25 | this.initial = initial; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/mongo/MongoLockedTestEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mongo; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mixing.annotations.Versioned; 13 | 14 | @Versioned 15 | public class MongoLockedTestEntity extends MongoEntity { 16 | 17 | public static final Mapping VALUE = Mapping.named("value"); 18 | private String value; 19 | 20 | public String getValue() { 21 | return value; 22 | } 23 | 24 | public void setValue(String value) { 25 | this.value = value; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/mongo/properties/MongoStringBooleanMapEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mongo.properties; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mixing.types.StringBooleanMap; 13 | import sirius.db.mongo.MongoEntity; 14 | 15 | public class MongoStringBooleanMapEntity extends MongoEntity { 16 | public static final Mapping MAP = Mapping.named("map"); 17 | private final StringBooleanMap map = new StringBooleanMap(); 18 | 19 | public StringBooleanMap getMap() { 20 | return map; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/annotations/Lob.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.annotations; 10 | 11 | import java.lang.annotation.Documented; 12 | import java.lang.annotation.ElementType; 13 | import java.lang.annotation.Retention; 14 | import java.lang.annotation.RetentionPolicy; 15 | import java.lang.annotation.Target; 16 | 17 | /** 18 | * Marks a CHAR column as CLOB / TEXT which can store very large amounts of data. 19 | */ 20 | @Documented 21 | @Retention(RetentionPolicy.RUNTIME) 22 | @Target(ElementType.FIELD) 23 | public @interface Lob { 24 | } 25 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/jdbc/SmartQueryTestMixinEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mixing.annotations.Length; 13 | 14 | public class SmartQueryTestMixinEntity extends SQLEntity { 15 | 16 | @Length(50) 17 | private String value; 18 | public static final Mapping VALUE = Mapping.named("value"); 19 | 20 | public String getValue() { 21 | return value; 22 | } 23 | 24 | public void setValue(String value) { 25 | this.value = value; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/es/BatchTestEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.es; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mixing.annotations.Versioned; 13 | 14 | @Versioned 15 | public class BatchTestEntity extends ElasticEntity { 16 | 17 | public static final Mapping VALUE = Mapping.named("value"); 18 | private int value; 19 | 20 | public int getValue() { 21 | return value; 22 | } 23 | 24 | public BatchTestEntity withValue(int value) { 25 | this.value = value; 26 | return this; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Description 2 | 3 | 4 | 5 | ### Additional Notes 6 | 7 | - This PR fixes or works on following ticket(s): [SIRI-](https://scireum.myjetbrains.com/youtrack/issue/SIRI-) 8 | - This PR is related to PR: 9 | 10 | ### Checklist 11 | 12 | - [ ] Code change has been tested and works locally 13 | - [ ] Code was formatted via IntelliJ and follows SonarLint & [best practices](https://scireum.myjetbrains.com/youtrack/articles/MISC-A-16/CodeStyle-JavaDoc) 14 | - [ ] Patch Tasks: Is local execution of Patch Tasks necessary? If so, please also mark the PR with the tag. 15 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/annotations/Versioned.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.annotations; 10 | 11 | import java.lang.annotation.Documented; 12 | import java.lang.annotation.ElementType; 13 | import java.lang.annotation.Retention; 14 | import java.lang.annotation.RetentionPolicy; 15 | import java.lang.annotation.Target; 16 | 17 | /** 18 | * Marks an entity as versioned and therefore eligibile for optimistic locking. 19 | */ 20 | @Documented 21 | @Retention(RetentionPolicy.RUNTIME) 22 | @Target(ElementType.TYPE) 23 | public @interface Versioned { 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/types/StringLocalDateTimeMap.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.types; 10 | 11 | import java.time.LocalDateTime; 12 | 13 | /** 14 | * Represents map of String pointing to LocalDateTime values. 15 | */ 16 | public class StringLocalDateTimeMap extends SafeMap { 17 | 18 | @Override 19 | protected boolean valueNeedsCopy() { 20 | return false; 21 | } 22 | 23 | @Override 24 | protected LocalDateTime copyValue(LocalDateTime value) { 25 | return value; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/jdbc/TestEntityWithComposite.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc; 10 | 11 | public class TestEntityWithComposite extends SQLEntity { 12 | 13 | private final TestComposite composite = new TestComposite(); 14 | 15 | private final TestCompositeWithComposite compositeWithComposite = new TestCompositeWithComposite(); 16 | 17 | public TestComposite getComposite() { 18 | return composite; 19 | } 20 | 21 | public TestCompositeWithComposite getCompositeWithComposite() { 22 | return compositeWithComposite; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/mongo/properties/MongoExistsEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mongo.properties; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mongo.MongoEntity; 13 | 14 | public class MongoExistsEntity extends MongoEntity { 15 | 16 | public static final Mapping TEST_FIELD = Mapping.named("testField"); 17 | private String testField; 18 | 19 | public String getTestField() { 20 | return testField; 21 | } 22 | 23 | public void setTestField(String testField) { 24 | this.testField = testField; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/mongo/properties/MongoMultiPointEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mongo.properties; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mongo.MongoEntity; 13 | import sirius.db.mongo.types.MultiPointLocation; 14 | 15 | public class MongoMultiPointEntity extends MongoEntity { 16 | public static final Mapping LOCATIONS = Mapping.named("locations"); 17 | private final MultiPointLocation locations = new MultiPointLocation(); 18 | 19 | public MultiPointLocation getLocations() { 20 | return locations; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/jdbc/schema/SQLPropertyInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc.schema; 10 | 11 | /** 12 | * Provides the schema information for a {@link sirius.db.mixing.Property} required to build a database schema in a 13 | * SQL / JDBC database. 14 | */ 15 | public interface SQLPropertyInfo { 16 | 17 | /** 18 | * Appends columns, keys and foreign keys to the given table to match the settings specified by 19 | * this property 20 | * 21 | * @param table the table to add schema infos to 22 | */ 23 | void contributeToTable(Table table); 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/annotations/NullAllowed.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.annotations; 10 | 11 | import java.lang.annotation.Documented; 12 | import java.lang.annotation.ElementType; 13 | import java.lang.annotation.Retention; 14 | import java.lang.annotation.RetentionPolicy; 15 | import java.lang.annotation.Target; 16 | 17 | /** 18 | * Determines the nullability of a column. 19 | *

20 | * By default all columns are NON-NULL. 21 | */ 22 | @Documented 23 | @Retention(RetentionPolicy.RUNTIME) 24 | @Target(ElementType.FIELD) 25 | public @interface NullAllowed { 26 | } 27 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/jdbc/SQLStringListNonNullAllowedPropertyEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mixing.annotations.Length; 13 | import sirius.db.mixing.types.StringList; 14 | 15 | public class SQLStringListNonNullAllowedPropertyEntity extends SQLEntity { 16 | 17 | public static final Mapping STRING_LIST = Mapping.named("stringList"); 18 | @Length(4096) 19 | private final StringList stringList = new StringList(); 20 | 21 | 22 | public StringList getStringList() { 23 | return stringList; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/jdbc/SQLLockedTestEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mixing.annotations.Length; 13 | import sirius.db.mixing.annotations.Versioned; 14 | 15 | @Versioned 16 | public class SQLLockedTestEntity extends SQLEntity { 17 | 18 | public static final Mapping VALUE = Mapping.named("value"); 19 | @Length(50) 20 | private String value; 21 | 22 | public String getValue() { 23 | return value; 24 | } 25 | 26 | public void setValue(String value) { 27 | this.value = value; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /.github/workflows/ga-releases.yml: -------------------------------------------------------------------------------- 1 | name: Automatic GA Release Drafts 2 | 3 | on: 4 | push: 5 | # branches to consider in the event; optional, defaults to all 6 | branches: 7 | - master 8 | 9 | permissions: 10 | contents: read 11 | 12 | jobs: 13 | update_release_draft: 14 | permissions: 15 | # write permission is required to create a github release 16 | contents: write 17 | pull-requests: read 18 | runs-on: ubuntu-latest 19 | steps: 20 | # Drafts your next Release notes as Pull Requests are merged into "master" 21 | - uses: release-drafter/release-drafter@v5 22 | with: 23 | config-name: ga-release-drafter.yml 24 | disable-autolabeler: true 25 | env: 26 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 27 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/annotations/Trim.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.annotations; 10 | 11 | import java.lang.annotation.Documented; 12 | import java.lang.annotation.ElementType; 13 | import java.lang.annotation.Retention; 14 | import java.lang.annotation.RetentionPolicy; 15 | import java.lang.annotation.Target; 16 | 17 | /** 18 | * Marks a string property as auto trimmed. 19 | *

20 | * The value of this property will be trimmed before it is written to the database. 21 | */ 22 | @Documented 23 | @Retention(RetentionPolicy.RUNTIME) 24 | @Target(ElementType.FIELD) 25 | public @interface Trim { 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/jdbc/SQLEntityCache.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc; 10 | 11 | import sirius.db.util.BaseEntityCache; 12 | import sirius.kernel.di.std.Part; 13 | 14 | /** 15 | * Provides a template for caching JDBC/SQL entities in an on-heap cache. 16 | * 17 | * @param the type of entities being cached 18 | */ 19 | public abstract class SQLEntityCache extends BaseEntityCache { 20 | 21 | @Part 22 | protected OMA oma; 23 | 24 | @Override 25 | protected E fetchFromDb(String id) { 26 | return oma.find(getEntityClass(), id).orElse(null); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/text/ReduceCharacterProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.text; 10 | 11 | import sirius.kernel.commons.StringCleanup; 12 | import sirius.kernel.commons.Strings; 13 | 14 | /** 15 | * Reduces characters to a simpler representation. 16 | *

17 | * Many characters like umlauts or ligatures are "down converted" by this processor into their ASCII representation. 18 | */ 19 | public class ReduceCharacterProcessor extends ChainableTokenProcessor { 20 | 21 | @Override 22 | public void accept(String token) { 23 | emit(Strings.cleanup(token, StringCleanup::reduceCharacters)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/mongo/MongoUniqueTestEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mongo; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mixing.annotations.Index; 13 | 14 | @Index(name = "unique_test", columns = "value", columnSettings = Mango.INDEX_ASCENDING, unique = true) 15 | public class MongoUniqueTestEntity extends MongoEntity { 16 | 17 | public static final Mapping VALUE = Mapping.named("value"); 18 | private String value; 19 | 20 | public String getValue() { 21 | return value; 22 | } 23 | 24 | public void setValue(String value) { 25 | this.value = value; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/mongo/properties/MongoStringMapMixin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mongo.properties; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mixing.Mixable; 13 | import sirius.db.mixing.annotations.Mixin; 14 | import sirius.db.mixing.types.StringMap; 15 | 16 | @Mixin(MongoStringMapMixinEntity.class) 17 | public class MongoStringMapMixin extends Mixable { 18 | 19 | public static final Mapping MAP_IN_MIXIN = Mapping.named("mapInMixin"); 20 | private final StringMap mapInMixin = new StringMap(); 21 | 22 | public StringMap getMapInMixin() { 23 | return mapInMixin; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mongo/MongoEntityCache.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mongo; 10 | 11 | import sirius.db.util.BaseEntityCache; 12 | import sirius.kernel.di.std.Part; 13 | 14 | /** 15 | * Provides a template for caching mongo entities in an on-heap cache. 16 | * 17 | * @param the type of entities being cached 18 | */ 19 | public abstract class MongoEntityCache extends BaseEntityCache { 20 | 21 | @Part 22 | protected Mango mango; 23 | 24 | @Override 25 | protected E fetchFromDb(String id) { 26 | return mango.find(getEntityClass(), id).orElse(null); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/es/properties/ESFilledEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.es.properties; 10 | 11 | import sirius.db.es.ElasticEntity; 12 | import sirius.db.mixing.Mapping; 13 | import sirius.db.mixing.annotations.NullAllowed; 14 | 15 | public class ESFilledEntity extends ElasticEntity { 16 | 17 | public static final Mapping TEST_FIELD = Mapping.named("testField"); 18 | @NullAllowed 19 | private String testField; 20 | 21 | public String getTestField() { 22 | return testField; 23 | } 24 | 25 | public void setTestField(String testField) { 26 | this.testField = testField; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/jdbc/Operator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc; 10 | 11 | import sirius.db.mixing.Mapping; 12 | 13 | /** 14 | * Enumerates the operators supported by {@link GeneratedStatement#where(Mapping, Operator, Object)} 15 | * or {@link sirius.db.jdbc.batch.BatchQuery}. 16 | */ 17 | public enum Operator { 18 | LT("<"), LT_EQ("<="), EQ("="), GT_EQ(">="), GT(">"), NE("<>"); 19 | 20 | private final String operation; 21 | 22 | Operator(String operation) { 23 | this.operation = operation; 24 | } 25 | 26 | @Override 27 | public String toString() { 28 | return operation; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/mongo/properties/MongoStringListMixin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mongo.properties; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mixing.Mixable; 13 | import sirius.db.mixing.annotations.Mixin; 14 | import sirius.db.mixing.types.StringList; 15 | 16 | @Mixin(MongoStringListMixinEntity.class) 17 | public class MongoStringListMixin extends Mixable { 18 | 19 | public static final Mapping LIST_IN_MIXIN = Mapping.named("listInMixin"); 20 | private final StringList listInMixin = new StringList(); 21 | 22 | public StringList getListInMixin() { 23 | return listInMixin; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/mixing/RefListElasticEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing; 10 | 11 | import sirius.db.es.ElasticEntity; 12 | import sirius.db.mixing.annotations.ComplexDelete; 13 | import sirius.db.mixing.types.BaseEntityRef; 14 | import sirius.db.mongo.types.MongoRefList; 15 | 16 | @ComplexDelete(false) 17 | public class RefListElasticEntity extends ElasticEntity { 18 | 19 | private final MongoRefList ref = 20 | new MongoRefList<>(RefListMongoEntity.class, BaseEntityRef.OnDelete.CASCADE); 21 | 22 | public MongoRefList getRef() { 23 | return ref; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/mongo/properties/MongoFilledEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mongo.properties; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mixing.annotations.NullAllowed; 13 | import sirius.db.mongo.MongoEntity; 14 | 15 | public class MongoFilledEntity extends MongoEntity { 16 | 17 | public static final Mapping TEST_FIELD = Mapping.named("testField"); 18 | @NullAllowed 19 | private String testField; 20 | 21 | public String getTestField() { 22 | return testField; 23 | } 24 | 25 | public void setTestField(String testField) { 26 | this.testField = testField; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/annotations/Transient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.annotations; 10 | 11 | import java.lang.annotation.Documented; 12 | import java.lang.annotation.ElementType; 13 | import java.lang.annotation.Retention; 14 | import java.lang.annotation.RetentionPolicy; 15 | import java.lang.annotation.Target; 16 | 17 | /** 18 | * Fields marked with this annotation are not transformed into a property. 19 | *

20 | * Can be placed on local caches or other fields which must not be persisted. 21 | */ 22 | @Documented 23 | @Retention(RetentionPolicy.RUNTIME) 24 | @Target(ElementType.FIELD) 25 | public @interface Transient { 26 | } 27 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/es/properties/ESStringLocalDateTimeMapEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.es.properties; 10 | 11 | import sirius.db.es.ElasticEntity; 12 | import sirius.db.mixing.Mapping; 13 | import sirius.db.mixing.annotations.NullAllowed; 14 | import sirius.db.mixing.types.StringLocalDateTimeMap; 15 | 16 | public class ESStringLocalDateTimeMapEntity extends ElasticEntity { 17 | 18 | public static final Mapping MAP = Mapping.named("map"); 19 | @NullAllowed 20 | private final StringLocalDateTimeMap map = new StringLocalDateTimeMap(); 21 | 22 | public StringLocalDateTimeMap getMap() { 23 | return map; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/jdbc/SQLUniqueTestEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mixing.annotations.Index; 13 | import sirius.db.mixing.annotations.Length; 14 | 15 | @Index(name = "unique_test", columns = "value", unique = true) 16 | public class SQLUniqueTestEntity extends SQLEntity { 17 | 18 | public static final Mapping VALUE = Mapping.named("value"); 19 | @Length(50) 20 | private String value; 21 | 22 | public String getValue() { 23 | return value; 24 | } 25 | 26 | public void setValue(String value) { 27 | this.value = value; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/mixing/RefMongoEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing; 10 | 11 | import sirius.db.jdbc.SQLEntityRef; 12 | import sirius.db.mixing.annotations.ComplexDelete; 13 | import sirius.db.mixing.annotations.NullAllowed; 14 | import sirius.db.mixing.types.BaseEntityRef; 15 | import sirius.db.mongo.MongoEntity; 16 | 17 | @ComplexDelete(false) 18 | public class RefMongoEntity extends MongoEntity { 19 | 20 | @NullAllowed 21 | private final SQLEntityRef ref = SQLEntityRef.on(RefEntity.class, BaseEntityRef.OnDelete.CASCADE); 22 | 23 | public SQLEntityRef getRef() { 24 | return ref; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/annotations/Ordinal.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.annotations; 10 | 11 | import java.lang.annotation.Documented; 12 | import java.lang.annotation.ElementType; 13 | import java.lang.annotation.Retention; 14 | import java.lang.annotation.RetentionPolicy; 15 | import java.lang.annotation.Target; 16 | 17 | /** 18 | * Marker annotation used on enums to make {@link sirius.db.mixing.properties.EnumProperty} store the ordinal index of 19 | * the enum constant in the database instead of the name. 20 | */ 21 | @Documented 22 | @Retention(RetentionPolicy.RUNTIME) 23 | @Target(ElementType.FIELD) 24 | public @interface Ordinal { 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/mixing/RefElasticEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing; 10 | 11 | import sirius.db.es.ElasticEntity; 12 | import sirius.db.jdbc.SQLEntityRef; 13 | import sirius.db.mixing.annotations.ComplexDelete; 14 | import sirius.db.mixing.annotations.NullAllowed; 15 | import sirius.db.mixing.types.BaseEntityRef; 16 | 17 | @ComplexDelete(false) 18 | public class RefElasticEntity extends ElasticEntity { 19 | 20 | @NullAllowed 21 | private final SQLEntityRef ref = SQLEntityRef.on(RefEntity.class, BaseEntityRef.OnDelete.CASCADE); 22 | 23 | public SQLEntityRef getRef() { 24 | return ref; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/es/annotations/RoutedBy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.es.annotations; 10 | 11 | import java.lang.annotation.Documented; 12 | import java.lang.annotation.ElementType; 13 | import java.lang.annotation.Retention; 14 | import java.lang.annotation.RetentionPolicy; 15 | import java.lang.annotation.Target; 16 | 17 | /** 18 | * Marks the field / property which is used as routing info for an Elasticsearch index. 19 | *

20 | * Note that this shouldn't be null and also be an non analyzed field. 21 | */ 22 | @Documented 23 | @Retention(RetentionPolicy.RUNTIME) 24 | @Target(ElementType.FIELD) 25 | public @interface RoutedBy { 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/annotations/RemoveWhitespace.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.annotations; 10 | 11 | import java.lang.annotation.Documented; 12 | import java.lang.annotation.ElementType; 13 | import java.lang.annotation.Retention; 14 | import java.lang.annotation.RetentionPolicy; 15 | import java.lang.annotation.Target; 16 | 17 | /** 18 | * Marks a string property to remove any white-spaces. 19 | *

20 | * All white-spaces of the property's value will be removed before it is written to the database. 21 | */ 22 | @Documented 23 | @Retention(RetentionPolicy.RUNTIME) 24 | @Target(ElementType.FIELD) 25 | public @interface RemoveWhitespace { 26 | } 27 | -------------------------------------------------------------------------------- /src/test/kotlin/sirius/db/text/PatternReplaceProcessorTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.text 10 | 11 | import org.junit.jupiter.api.Test 12 | import java.util.regex.Pattern 13 | 14 | /** 15 | * Tests the [PatternReplaceProcessor]. 16 | */ 17 | class PatternReplaceProcessorTest : TokenProcessorTest() { 18 | @Test 19 | fun tokenizing() { 20 | assertExactTokenizing("a7b8\$c", PatternReplaceProcessor(Pattern.compile("[^a-z]"), " "), "a b c") 21 | assertExactTokenizing( 22 | "a7b\u00178\$c\u0008\n\t", 23 | PatternReplaceProcessor.createRemoveControlCharacters(), 24 | "a7b 8\$c " 25 | ) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/Composite.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing; 10 | 11 | /** 12 | * Base class for all composites. 13 | *

14 | * A composite can be embed in an {@link BaseEntity}. All fields declared here will be mapped to properties 15 | * (and therefore columns of the entity). 16 | *

17 | * As the field name containing the composite is prepended to all fields here, the same composite can be 18 | * used several times in one entity. 19 | *

20 | * As it derives from {@link Mixable} a composite can be extended using Mixins. Also a composite can contain 21 | * further composites. 22 | */ 23 | public class Composite extends Mixable { 24 | } 25 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/jdbc/SmartQueryTestParentEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mixing.annotations.ComplexDelete; 13 | import sirius.db.mixing.annotations.Length; 14 | 15 | /** 16 | * Testentity for SmartQuerySpec 17 | */ 18 | @ComplexDelete(false) 19 | public class SmartQueryTestParentEntity extends SQLEntity { 20 | 21 | @Length(50) 22 | private String name; 23 | public static final Mapping NAME = Mapping.named("name"); 24 | 25 | public String getName() { 26 | return name; 27 | } 28 | 29 | public void setName(String name) { 30 | this.name = name; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/jdbc/TestMixin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mixing.Mixable; 13 | import sirius.db.mixing.annotations.Length; 14 | import sirius.db.mixing.annotations.Mixin; 15 | 16 | @Mixin(TestEntityWithMixin.class) 17 | public class TestMixin extends Mixable { 18 | 19 | public static final Mapping MIDDLE_NAME = Mapping.named("middleName"); 20 | @Length(50) 21 | private String middleName; 22 | 23 | public String getMiddleName() { 24 | return middleName; 25 | } 26 | 27 | public void setMiddleName(String middleName) { 28 | this.middleName = middleName; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/test/kotlin/sirius/db/util/TensorsTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.util 10 | 11 | import org.junit.jupiter.api.Assertions 12 | import org.junit.jupiter.api.Test 13 | 14 | /** 15 | * Tests the {@link Tensors} class. 16 | */ 17 | class TensorsTest { 18 | @Test 19 | fun `test string tools`() { 20 | val tensor = floatArrayOf(1f, 2f, 3f, 4f, 5f) 21 | 22 | Assertions.assertArrayEquals(Tensors.parse(Tensors.encode(tensor)), tensor) 23 | } 24 | 25 | @Test 26 | fun `test array tools`() { 27 | val tensor = floatArrayOf(1f, 2f, 3f, 4f, 5f) 28 | 29 | Assertions.assertArrayEquals(Tensors.fromList(tensor.asList()), tensor) 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/mongo/PrefixTestEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mongo; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mixing.annotations.Index; 13 | 14 | @Index(name = "prefix", columns = "prefix", columnSettings = Mango.INDEX_ASCENDING) 15 | @Index(name = "text", columns = "prefix", columnSettings = Mango.INDEX_AS_FULLTEXT) 16 | public class PrefixTestEntity extends MongoEntity { 17 | 18 | public static final Mapping PREFIX = Mapping.named("prefix"); 19 | private String prefix; 20 | 21 | public String getPrefix() { 22 | return prefix; 23 | } 24 | 25 | public void setPrefix(String prefix) { 26 | this.prefix = prefix; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/annotations/LowerCase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.annotations; 10 | 11 | import java.lang.annotation.Documented; 12 | import java.lang.annotation.ElementType; 13 | import java.lang.annotation.Retention; 14 | import java.lang.annotation.RetentionPolicy; 15 | import java.lang.annotation.Target; 16 | 17 | /** 18 | * Marks a string property as auto lower-cased. 19 | *

20 | * The value of this property will be lower-cased before it is written to the database. Also, it is used to optimize 21 | * some system generated queries. 22 | */ 23 | @Documented 24 | @Retention(RetentionPolicy.RUNTIME) 25 | @Target(ElementType.FIELD) 26 | public @interface LowerCase { 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/annotations/UpperCase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.annotations; 10 | 11 | import java.lang.annotation.Documented; 12 | import java.lang.annotation.ElementType; 13 | import java.lang.annotation.Retention; 14 | import java.lang.annotation.RetentionPolicy; 15 | import java.lang.annotation.Target; 16 | 17 | /** 18 | * Marks a string property as auto upper-cased. 19 | *

20 | * The value of this property will be upper-cased before it is written to the database. Also, it is used to optimize 21 | * some system generated queries. 22 | */ 23 | @Documented 24 | @Retention(RetentionPolicy.RUNTIME) 25 | @Target(ElementType.FIELD) 26 | public @interface UpperCase { 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/annotations/MaxValue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.annotations; 10 | 11 | import java.lang.annotation.Documented; 12 | import java.lang.annotation.ElementType; 13 | import java.lang.annotation.Retention; 14 | import java.lang.annotation.RetentionPolicy; 15 | import java.lang.annotation.Target; 16 | 17 | /** 18 | * Sets the maximal value for a {@link sirius.db.mixing.properties.NumberProperty}. 19 | */ 20 | @Documented 21 | @Retention(RetentionPolicy.RUNTIME) 22 | @Target(ElementType.FIELD) 23 | public @interface MaxValue { 24 | 25 | /** 26 | * The maximal value of this property. 27 | * 28 | * @return the maximal value 29 | */ 30 | long value(); 31 | } 32 | -------------------------------------------------------------------------------- /src/test/kotlin/sirius/db/text/ToLowercaseProcessorTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.text 10 | 11 | import org.junit.jupiter.api.Test 12 | 13 | /** 14 | * Tests the [ToLowercaseProcessor]. 15 | */ 16 | class ToLowercaseProcessorTest : TokenProcessorTest() { 17 | @Test 18 | fun tokenizing() { 19 | assertExactTokenizing("HelloWorld", ToLowercaseProcessor(), "helloworld") 20 | assertExactTokenizing("ÄÖÜOUKÁ", ToLowercaseProcessor(), "äöüouká") 21 | assertExactTokenizing("Hello World", ToLowercaseProcessor(), "hello world") 22 | assertExactTokenizing("123", ToLowercaseProcessor(), "123") 23 | assertExactTokenizing("--$--", ToLowercaseProcessor(), "--$--") 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/query/constraints/Constraint.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.query.constraints; 10 | 11 | /** 12 | * Represents a constraint which can be applied to a {@link sirius.db.mixing.query.Query}. 13 | */ 14 | public abstract class Constraint { 15 | 16 | /** 17 | * Creates a string representation of this constraint. 18 | * 19 | * @param builder the target to write the string representation to 20 | */ 21 | public abstract void asString(StringBuilder builder); 22 | 23 | @Override 24 | public String toString() { 25 | StringBuilder builder = new StringBuilder(); 26 | asString(builder); 27 | return builder.toString(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/mixing/RefListMongoEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing; 10 | 11 | import sirius.db.es.types.ElasticRefList; 12 | import sirius.db.mixing.annotations.ComplexDelete; 13 | import sirius.db.mixing.annotations.NullAllowed; 14 | import sirius.db.mixing.types.BaseEntityRef; 15 | import sirius.db.mongo.MongoEntity; 16 | 17 | @ComplexDelete(false) 18 | public class RefListMongoEntity extends MongoEntity { 19 | 20 | @NullAllowed 21 | private final ElasticRefList ref = 22 | new ElasticRefList<>(RefListElasticEntity.class, BaseEntityRef.OnDelete.SET_NULL); 23 | 24 | public ElasticRefList getRef() { 25 | return ref; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/mixing/WriteOnceChildEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing; 10 | 11 | import sirius.db.jdbc.SQLEntity; 12 | import sirius.db.jdbc.SQLEntityRef; 13 | import sirius.db.mixing.annotations.ComplexDelete; 14 | import sirius.db.mixing.annotations.NullAllowed; 15 | import sirius.db.mixing.types.BaseEntityRef; 16 | 17 | @ComplexDelete(false) 18 | public class WriteOnceChildEntity extends SQLEntity { 19 | 20 | @NullAllowed 21 | private final SQLEntityRef parent = 22 | SQLEntityRef.writeOnceOn(WriteOnceParentEntity.class, BaseEntityRef.OnDelete.CASCADE); 23 | 24 | public SQLEntityRef getParent() { 25 | return parent; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/annotations/MinValue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.annotations; 10 | 11 | import java.lang.annotation.Documented; 12 | import java.lang.annotation.ElementType; 13 | import java.lang.annotation.Retention; 14 | import java.lang.annotation.RetentionPolicy; 15 | import java.lang.annotation.Target; 16 | 17 | /** 18 | * Sets the minimal value for a {@link sirius.db.mixing.properties.NumberProperty}. 19 | */ 20 | @Documented 21 | @Retention(RetentionPolicy.RUNTIME) 22 | @Target(ElementType.FIELD) 23 | public @interface MinValue { 24 | 25 | /** 26 | * The minimal value for this property. 27 | * 28 | * @return the minimal value for this property 29 | */ 30 | long value(); 31 | } 32 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/jdbc/SmartQueryTestMixinEntityMixin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mixing.Mixable; 13 | import sirius.db.mixing.annotations.Length; 14 | import sirius.db.mixing.annotations.Mixin; 15 | 16 | @Mixin(SmartQueryTestMixinEntity.class) 17 | public class SmartQueryTestMixinEntityMixin extends Mixable { 18 | 19 | @Length(50) 20 | private String mixinValue; 21 | public static final Mapping MIXIN_VALUE = Mapping.named("mixinValue"); 22 | 23 | public String getMixinValue() { 24 | return mixinValue; 25 | } 26 | 27 | public void setMixinValue(String mixinValue) { 28 | this.mixinValue = mixinValue; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/test/kotlin/sirius/db/text/PatternExtractProcessorTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.text 10 | 11 | import org.junit.jupiter.api.Test 12 | import java.util.regex.Pattern 13 | 14 | /** 15 | * Tests the [PatternExtractProcessor]. 16 | */ 17 | class PatternExtractProcessorTest : TokenProcessorTest() { 18 | @Test 19 | fun tokenizing() { 20 | assertExactTokenizing( 21 | "ABC 85X 84 77X", 22 | PatternExtractProcessor(Pattern.compile("(\\d+)X"), "{1}", "A{1}B", "A {1} B", "C"), 23 | "85", 24 | "A85B", 25 | "A 85 B", 26 | "C", 27 | "77", 28 | "A77B", 29 | "A 77 B", 30 | "C" 31 | ) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/jdbc/constraints/SQLConstraint.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc.constraints; 10 | 11 | import sirius.db.jdbc.OMA; 12 | import sirius.db.jdbc.SmartQuery; 13 | import sirius.db.mixing.query.constraints.Constraint; 14 | 15 | /** 16 | * Defines a constraint which is accepted by {@link SmartQuery} and most probably generated by {@link SQLFilterFactory}. 17 | * 18 | * @see OMA#FILTERS 19 | */ 20 | public abstract class SQLConstraint extends Constraint { 21 | 22 | /** 23 | * Generates the appropriate SQL into the given compiler 24 | * 25 | * @param compiler the current query compiler to apply the constraint to 26 | */ 27 | public abstract void appendSQL(SmartQuery.Compiler compiler); 28 | } 29 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/jdbc/SmartQueryTestLargeTableEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mixing.annotations.ComplexDelete; 13 | import sirius.db.mixing.annotations.Length; 14 | 15 | /** 16 | * Testentity for SmartQuerySpec with many items in the table 17 | */ 18 | @ComplexDelete(false) 19 | public class SmartQueryTestLargeTableEntity extends SQLEntity { 20 | public static final Mapping TEST_NUMBER = Mapping.named("testNumber"); 21 | private int testNumber; 22 | 23 | public int getTestNumber() { 24 | return testNumber; 25 | } 26 | 27 | public void setTestNumber(int testNumber) { 28 | this.testNumber = testNumber; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/text/TokenProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.text; 10 | 11 | import java.util.function.Consumer; 12 | 13 | /** 14 | * Defines the most basic interface to be provided by a processor in the token stream. 15 | *

16 | * Note that almost all processors should and must be chainable and therefore be a subclass of 17 | * {@link ChainableTokenProcessor}. 18 | */ 19 | public interface TokenProcessor extends Consumer { 20 | 21 | /** 22 | * Purges any internal buffered data to the next processor. 23 | *

24 | * If this processor doesn't buffer any data internally, nothing will happen but any 25 | * subsequent processors must also be purged. 26 | */ 27 | default void purge() { 28 | 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/annotations/DefaultValue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.annotations; 10 | 11 | import java.lang.annotation.Documented; 12 | import java.lang.annotation.ElementType; 13 | import java.lang.annotation.Retention; 14 | import java.lang.annotation.RetentionPolicy; 15 | import java.lang.annotation.Target; 16 | 17 | /** 18 | * Defines a default value which is added to the CREATE TABLE statement when generating the schema. 19 | */ 20 | @Documented 21 | @Retention(RetentionPolicy.RUNTIME) 22 | @Target(ElementType.FIELD) 23 | public @interface DefaultValue { 24 | /** 25 | * Contains the string representation of the default value. 26 | * 27 | * @return the default value to use 28 | */ 29 | String value(); 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/annotations/Realm.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.annotations; 10 | 11 | import java.lang.annotation.Documented; 12 | import java.lang.annotation.ElementType; 13 | import java.lang.annotation.Retention; 14 | import java.lang.annotation.RetentionPolicy; 15 | import java.lang.annotation.Target; 16 | 17 | /** 18 | * Specifies the realm to use for an entity. 19 | *

20 | * This can be used to determine which datasource is used to reprenset an entity class. 21 | */ 22 | @Documented 23 | @Retention(RetentionPolicy.RUNTIME) 24 | @Target(ElementType.TYPE) 25 | public @interface Realm { 26 | 27 | /** 28 | * The name of the realm to use. 29 | * 30 | * @return the name of the realm 31 | */ 32 | String value(); 33 | } 34 | -------------------------------------------------------------------------------- /src/test/kotlin/sirius/db/testutil/MongoMocks.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.testutil 10 | 11 | import io.mockk.spyk 12 | import sirius.db.mixing.types.BaseEntityRef 13 | import sirius.db.mongo.MongoEntity 14 | import sirius.db.mongo.types.MongoRef 15 | 16 | /** 17 | * Class contains functionality used for mocking Mongo parts in unit tests. 18 | */ 19 | class MongoMocks { 20 | companion object { 21 | /** 22 | * Wrap an entity as a MongoRef 23 | * @param entity which is to be wrapped 24 | */ 25 | fun asMongoRef(entity: E): MongoRef { 26 | val mongoRef = spyk(MongoRef.on(entity.javaClass, BaseEntityRef.OnDelete.IGNORE)) 27 | mongoRef.setValue(entity) 28 | return mongoRef 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/test/kotlin/sirius/db/text/TokenProcessorTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.text 10 | 11 | import kotlin.test.assertEquals 12 | 13 | /** 14 | * Provides baseclass used to test TokenProcessors. 15 | */ 16 | abstract class TokenProcessorTest { 17 | companion object { 18 | val NO_TOKENS: Array = arrayOfNulls(0) 19 | } 20 | 21 | protected fun assertExactTokenizing( 22 | input: String, 23 | processor: ChainableTokenProcessor, 24 | vararg tokens: String? 25 | ) { 26 | val result: MutableList = ArrayList() 27 | processor.chainConsumer { token: String -> result.add(token) } 28 | listOf(input).forEach(processor) 29 | processor.purge() 30 | assertEquals(listOf(*tokens), result) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/test/kotlin/sirius/db/mixing/CompositeTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing 10 | 11 | import org.junit.jupiter.api.Test 12 | import org.junit.jupiter.api.assertDoesNotThrow 13 | import org.junit.jupiter.api.extension.ExtendWith 14 | import sirius.db.mongo.Mango 15 | import sirius.kernel.SiriusExtension 16 | import sirius.kernel.di.std.Part 17 | 18 | @ExtendWith(SiriusExtension::class) 19 | class CompositeTest { 20 | @Test 21 | fun `Updating Composite inside Mixable works on Mongo`() { 22 | val refMongoEntity = RefMongoEntity() 23 | refMongoEntity.`as`(MongoMixable::class.java).composite.map.modify()["test"] = "data" 24 | 25 | assertDoesNotThrow { mango.update(refMongoEntity) } 26 | } 27 | 28 | companion object { 29 | @Part 30 | private lateinit var mango: Mango 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/test/kotlin/sirius/db/text/ReduceCharactersProcessorTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.text 10 | 11 | import org.junit.jupiter.api.Test 12 | 13 | /** 14 | * Tests the [ReduceCharacterProcessor]. 15 | */ 16 | class ReduceCharactersProcessorTest : TokenProcessorTest() { 17 | @Test 18 | fun tokenizing() { 19 | assertExactTokenizing("Hello", ReduceCharacterProcessor(), "Hello") 20 | assertExactTokenizing("Höllo", ReduceCharacterProcessor(), "Hoello") 21 | assertExactTokenizing("ÄHölloÜ", ReduceCharacterProcessor(), "AEHoelloUE") 22 | assertExactTokenizing("ÄÖßÜ", ReduceCharacterProcessor(), "AEOEssUE") 23 | assertExactTokenizing("Hüüllüü", ReduceCharacterProcessor(), "Hueuellueue") 24 | assertExactTokenizing(" Hüü llüü ", ReduceCharacterProcessor(), " Hueue llueue ") 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /.github/workflows/enforce-pr-label.yml: -------------------------------------------------------------------------------- 1 | name: Enforce PR Labels 2 | on: 3 | pull_request: 4 | types: [opened, labeled, unlabeled, synchronize] 5 | jobs: 6 | label: 7 | runs-on: ubuntu-latest 8 | permissions: 9 | issues: write 10 | pull-requests: write 11 | steps: 12 | - uses: mheap/github-action-required-labels@v5 13 | with: 14 | mode: minimum 15 | count: 1 16 | labels: "💣 BREAKING CHANGE, 🧬 Enhancement, 🐛 Bugfix, 🛠️ Maintenance, ⬆️ Dependencies" 17 | add_comment: true 18 | message: "This PR can only be merged after at least one of our categorizing labels has been added: {{ provided }}" 19 | - uses: mheap/github-action-required-labels@v5 20 | with: 21 | mode: exactly 22 | count: 0 23 | labels: "🎁 Next version, 🖐 Keep open, 🕔 Wait for sirius" 24 | add_comment: true 25 | message: "This PR can only be merged after all blocking labels have been removed: {{ provided }}" 26 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/jdbc/constraints/Not.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc.constraints; 10 | 11 | import sirius.db.jdbc.SmartQuery; 12 | 13 | /** 14 | * Represents a constraint which inverts the inner constraint. 15 | */ 16 | class Not extends SQLConstraint { 17 | 18 | private SQLConstraint inner; 19 | 20 | protected Not(SQLConstraint inner) { 21 | this.inner = inner; 22 | } 23 | 24 | @Override 25 | public void appendSQL(SmartQuery.Compiler compiler) { 26 | compiler.getWHEREBuilder().append("NOT("); 27 | inner.appendSQL(compiler); 28 | compiler.getWHEREBuilder().append(")"); 29 | } 30 | 31 | @Override 32 | public void asString(StringBuilder builder) { 33 | builder.append("NOT("); 34 | inner.asString(builder); 35 | builder.append(")"); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/annotations/Positive.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.annotations; 10 | 11 | import java.lang.annotation.Documented; 12 | import java.lang.annotation.ElementType; 13 | import java.lang.annotation.Retention; 14 | import java.lang.annotation.RetentionPolicy; 15 | import java.lang.annotation.Target; 16 | 17 | /** 18 | * Indicates that a {@link sirius.db.mixing.properties.NumberProperty} must have a positive value. 19 | */ 20 | @Documented 21 | @Retention(RetentionPolicy.RUNTIME) 22 | @Target(ElementType.FIELD) 23 | public @interface Positive { 24 | /** 25 | * Determines if 0 is a valid value for this property. 26 | * 27 | * @return true if 0 is a valid value for this property, false (default) otherwise 28 | */ 29 | boolean includeZero() default false; 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/jdbc/constraints/Filled.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc.constraints; 10 | 11 | import sirius.db.jdbc.SmartQuery; 12 | import sirius.db.mixing.Mapping; 13 | 14 | /** 15 | * Represents a constraint which ensures that a field is filled / non-null. 16 | */ 17 | class Filled extends SQLConstraint { 18 | 19 | private Mapping field; 20 | 21 | protected Filled(Mapping field) { 22 | this.field = field; 23 | } 24 | 25 | @Override 26 | public void appendSQL(SmartQuery.Compiler compiler) { 27 | String columnName = compiler.translateColumnName(field); 28 | compiler.getWHEREBuilder().append(columnName).append(" IS NOT NULL"); 29 | } 30 | 31 | @Override 32 | public void asString(StringBuilder builder) { 33 | builder.append(field.toString()).append(" IS NOT NULL"); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/jdbc/constraints/NotFilled.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc.constraints; 10 | 11 | import sirius.db.jdbc.SmartQuery; 12 | import sirius.db.mixing.Mapping; 13 | 14 | /** 15 | * Represents a constraint which ensures that a field is not filled / null. 16 | */ 17 | class NotFilled extends SQLConstraint { 18 | 19 | private Mapping field; 20 | 21 | protected NotFilled(Mapping field) { 22 | this.field = field; 23 | } 24 | 25 | @Override 26 | public void appendSQL(SmartQuery.Compiler compiler) { 27 | String columnName = compiler.translateColumnName(field); 28 | compiler.getWHEREBuilder().append(columnName).append(" IS NULL"); 29 | } 30 | 31 | @Override 32 | public void asString(StringBuilder builder) { 33 | builder.append(field.toString()).append(" IS NULL"); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/jdbc/LegacyEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc; 10 | 11 | import sirius.db.mixing.annotations.Length; 12 | 13 | public class LegacyEntity extends SQLEntity { 14 | 15 | @Length(50) 16 | private String firstname; 17 | 18 | @Length(50) 19 | private String lastname; 20 | 21 | private final TestComposite composite = new TestComposite(); 22 | 23 | public TestComposite getComposite() { 24 | return composite; 25 | } 26 | 27 | public String getFirstname() { 28 | return firstname; 29 | } 30 | 31 | public void setFirstname(String firstname) { 32 | this.firstname = firstname; 33 | } 34 | 35 | public String getLastname() { 36 | return lastname; 37 | } 38 | 39 | public void setLastname(String lastname) { 40 | this.lastname = lastname; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/text/BasicSearchTokenizer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.text; 10 | 11 | /** 12 | * Provides a tokenizer used to parse search input for content which has been pre-processed by the 13 | * {@link BasicIndexTokenizer}. 14 | */ 15 | public class BasicSearchTokenizer extends Tokenizer { 16 | 17 | @Override 18 | protected ChainableTokenProcessor createProcessor() { 19 | return new PipelineProcessor(new ReduceCharacterProcessor(), 20 | PatternSplitProcessor.createHardBoundarySplitter(), 21 | PatternSplitProcessor.createWhitespaceSplitter(), 22 | new TokenLimitProcessor(2, 80), 23 | new ToLowercaseProcessor(), 24 | new DeduplicateProcessor(true)); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/test/kotlin/sirius/db/text/TokenLimitProcessorTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.text 10 | 11 | import org.junit.jupiter.api.Test 12 | 13 | /** 14 | * Tests the [TokenLimitProcessor]. 15 | */ 16 | class TokenLimitProcessorTest : TokenProcessorTest() { 17 | @Test 18 | fun tokenizing() { 19 | assertExactTokenizing("1234567890", TokenLimitProcessor(0, 0), "1234567890") 20 | assertExactTokenizing("1234", TokenLimitProcessor(5, 0), *NO_TOKENS) 21 | assertExactTokenizing("12345", TokenLimitProcessor(5, 0), "12345") 22 | assertExactTokenizing("123456", TokenLimitProcessor(5, 0), "123456") 23 | assertExactTokenizing("123456", TokenLimitProcessor(0, 5), *NO_TOKENS) 24 | assertExactTokenizing("12345", TokenLimitProcessor(0, 5), "12345") 25 | assertExactTokenizing("1234", TokenLimitProcessor(0, 5), "1234") 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mongo/IndexDescription.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mongo; 10 | 11 | import com.mongodb.client.MongoDatabase; 12 | 13 | /** 14 | * Used to setup indices in Mongo DB on system startup. 15 | *

16 | * Once the first operation is triggered against Mongo DB, the framework finds all classes implementing this interface. 17 | * To be discovered, the class has to wear a {@link sirius.kernel.di.std.Register} annotation. 18 | */ 19 | public interface IndexDescription { 20 | 21 | /** 22 | * Invoked once the Mongo DB is first accessed and permits to create required indices. 23 | * 24 | * @param database the name of the database (in the configuration) for which the indices are created 25 | * @param client can be used to create indices in the Mongo DB 26 | */ 27 | void createIndices(String database, MongoDatabase client); 28 | } 29 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/mongo/MangoWasCreatedTestEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mongo; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mixing.annotations.AfterSave; 13 | import sirius.db.mixing.annotations.Transient; 14 | 15 | public class MangoWasCreatedTestEntity extends MongoEntity { 16 | 17 | public static final Mapping VALUE = Mapping.named("value"); 18 | private String value; 19 | 20 | @Transient 21 | private boolean wasCreatedIndicator; 22 | 23 | @AfterSave 24 | protected void checkIfCreated() { 25 | wasCreatedIndicator = wasCreated(); 26 | } 27 | 28 | public String getValue() { 29 | return value; 30 | } 31 | 32 | public void setValue(String value) { 33 | this.value = value; 34 | } 35 | 36 | public boolean hasJustBeenCreated() { 37 | return wasCreatedIndicator; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/test/resources/docker-db.yml: -------------------------------------------------------------------------------- 1 | services: 2 | redis: 3 | image: redis:8.2.2-alpine 4 | ports: 5 | - "6379" 6 | hostname: redis 7 | 8 | mongo: 9 | image: mongo:8.0.8 10 | ports: 11 | - "27017" 12 | hostname: mongo 13 | 14 | mariadb: 15 | image: mariadb:11.8.3-noble 16 | ports: 17 | - "3306" 18 | environment: 19 | MYSQL_ROOT_PASSWORD: root 20 | hostname: mysql 21 | command: --collation-server=utf8mb4_bin --character-set-server=utf8mb4 22 | 23 | clickhouse: 24 | image: clickhouse/clickhouse-server:25.8.2.29-alpine 25 | ports: 26 | - "8123" 27 | - "9000" 28 | hostname: clickhouse 29 | environment: 30 | CLICKHOUSE_USER: default 31 | CLICKHOUSE_PASSWORD: secret 32 | 33 | elasticsearch: 34 | image: elasticsearch:8.19.3 35 | ports: 36 | - "9200" 37 | environment: 38 | - ES_JAVA_OPTS=-Xms128M -Xmx128M 39 | - discovery.type=single-node 40 | - ingest.geoip.downloader.enabled=false 41 | - xpack.security.enabled=false 42 | hostname: es 43 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/jdbc/TestComposite.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc; 10 | 11 | import sirius.db.mixing.Composite; 12 | import sirius.db.mixing.annotations.Length; 13 | 14 | public class TestComposite extends Composite { 15 | 16 | @Length(100) 17 | private String street; 18 | 19 | @Length(10) 20 | private String zip; 21 | 22 | @Length(100) 23 | private String city; 24 | 25 | public String getStreet() { 26 | return street; 27 | } 28 | 29 | public void setStreet(String street) { 30 | this.street = street; 31 | } 32 | 33 | public String getZip() { 34 | return zip; 35 | } 36 | 37 | public void setZip(String zip) { 38 | this.zip = zip; 39 | } 40 | 41 | public String getCity() { 42 | return city; 43 | } 44 | 45 | public void setCity(String city) { 46 | this.city = city; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/annotations/Engine.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.annotations; 10 | 11 | import java.lang.annotation.Documented; 12 | import java.lang.annotation.ElementType; 13 | import java.lang.annotation.Retention; 14 | import java.lang.annotation.RetentionPolicy; 15 | import java.lang.annotation.Target; 16 | 17 | /** 18 | * Can be placed on a {@link sirius.db.jdbc.SQLEntity} to specify the database engine to use. 19 | *

20 | * Use e.g. InnoDB for MySQL or MergeTree(EventDate, (CounterID, EventDate), 8192) 21 | * for Clickhouse. 22 | */ 23 | @Documented 24 | @Retention(RetentionPolicy.RUNTIME) 25 | @Target(ElementType.TYPE) 26 | public @interface Engine { 27 | 28 | /** 29 | * Contains the engine specification to apply on the generated table. 30 | * 31 | * @return the engine used for the annotated type 32 | */ 33 | String value(); 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/annotations/RelationName.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.annotations; 10 | 11 | import java.lang.annotation.Documented; 12 | import java.lang.annotation.ElementType; 13 | import java.lang.annotation.Retention; 14 | import java.lang.annotation.RetentionPolicy; 15 | import java.lang.annotation.Target; 16 | 17 | /** 18 | * Specifies the relation name to used for an entity. 19 | *

20 | * By default the simple class name (all lowercase) is used as relation name. This annotation can be used to 21 | * provide a custom one. 22 | */ 23 | @Documented 24 | @Retention(RetentionPolicy.RUNTIME) 25 | @Target(ElementType.TYPE) 26 | public @interface RelationName { 27 | 28 | /** 29 | * The relation name (table name / collection name / index name) to use. 30 | * 31 | * @return the name to use to represent an entity in the database 32 | */ 33 | String value(); 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/annotations/Indices.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.annotations; 10 | 11 | import java.lang.annotation.Documented; 12 | import java.lang.annotation.ElementType; 13 | import java.lang.annotation.Retention; 14 | import java.lang.annotation.RetentionPolicy; 15 | import java.lang.annotation.Target; 16 | 17 | /** 18 | * Provides a container to make {@link Index} repeatable. 19 | *

20 | * As of Java 8 several Index annotation can be placed on an entity class, therefore this wrapper is only used 21 | * by the compiler and runtime to carry those annotations. 22 | */ 23 | @Documented 24 | @Target(ElementType.TYPE) 25 | @Retention(RetentionPolicy.RUNTIME) 26 | public @interface Indices { 27 | 28 | /** 29 | * Contains all index annoations placed on an entity class. 30 | * 31 | * @return an array of all index annotations 32 | */ 33 | Index[] value(); 34 | } 35 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/mixing/fieldlookup/MongoSuperHeroTestMixin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.fieldlookup; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mixing.Mixable; 13 | import sirius.db.mixing.annotations.Mixin; 14 | import sirius.db.mixing.types.StringList; 15 | 16 | @Mixin(MongoFieldLookUpTestEntity.class) 17 | public class MongoSuperHeroTestMixin extends Mixable { 18 | 19 | public static final Mapping HERO_NAMES = Mapping.named("heroNames"); 20 | private final NameFieldsTestComposite heroNames = new NameFieldsTestComposite(); 21 | 22 | public static final Mapping SUPER_POWERS = Mapping.named("superPowers"); 23 | private final StringList superPowers = new StringList(); 24 | 25 | public NameFieldsTestComposite getHeroNames() { 26 | return heroNames; 27 | } 28 | 29 | public StringList getSuperPowers() { 30 | return superPowers; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/es/ElasticWasCreatedTestEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.es; 10 | 11 | import sirius.db.es.ElasticEntity; 12 | import sirius.db.mixing.Mapping; 13 | import sirius.db.mixing.annotations.AfterSave; 14 | import sirius.db.mixing.annotations.Transient; 15 | 16 | public class ElasticWasCreatedTestEntity extends ElasticEntity { 17 | 18 | public static final Mapping VALUE = Mapping.named("value"); 19 | private String value; 20 | 21 | @Transient 22 | private boolean wasCreatedIndicator; 23 | 24 | @AfterSave 25 | protected void checkIfCreated() { 26 | wasCreatedIndicator = wasCreated(); 27 | } 28 | 29 | public String getValue() { 30 | return value; 31 | } 32 | 33 | public void setValue(String value) { 34 | this.value = value; 35 | } 36 | 37 | public boolean hasJustBeenCreated() { 38 | return wasCreatedIndicator; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/jdbc/SQLWasCreatedTestEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mixing.annotations.AfterSave; 13 | import sirius.db.mixing.annotations.Length; 14 | import sirius.db.mixing.annotations.Transient; 15 | 16 | public class SQLWasCreatedTestEntity extends SQLEntity { 17 | public static final Mapping VALUE = Mapping.named("value"); 18 | @Length(255) 19 | private String value; 20 | 21 | @Transient 22 | private boolean wasCreatedIndicator; 23 | 24 | @AfterSave 25 | protected void checkIfCreated() { 26 | wasCreatedIndicator = wasCreated(); 27 | } 28 | 29 | public String getValue() { 30 | return value; 31 | } 32 | 33 | public void setValue(String value) { 34 | this.value = value; 35 | } 36 | 37 | public boolean hasJustBeenCreated() { 38 | return wasCreatedIndicator; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/jdbc/SQLStringListPropertyEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mixing.annotations.Length; 13 | import sirius.db.mixing.annotations.NullAllowed; 14 | import sirius.db.mixing.types.StringList; 15 | 16 | public class SQLStringListPropertyEntity extends SQLEntity { 17 | 18 | public static final Mapping STRING_LIST = Mapping.named("stringList"); 19 | @NullAllowed 20 | @Length(4096) 21 | private final StringList stringList = new StringList(); 22 | 23 | public static final Mapping SHORT_STRING_LIST = Mapping.named("shortStringList"); 24 | @NullAllowed 25 | @Length(20) 26 | private final StringList shortStringList = new StringList(); 27 | 28 | public StringList getStringList() { 29 | return stringList; 30 | } 31 | 32 | public StringList getShortStringList() { 33 | return shortStringList; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/redis/Subscriber.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.redis; 10 | 11 | /** 12 | * Subscribes to a publish/subscribe topic which uses redis for one to many communication. 13 | *

14 | * A class implementing this interface must wear a {@link sirius.kernel.di.std.Register} annotation to be 15 | * discovered by {@link Redis}. Once a message is published via {@link Redis#publish(String, String)} all subscribers 16 | * on all connected nodes will be notified via {@link #onMessage(String)}. 17 | */ 18 | public interface Subscriber { 19 | 20 | /** 21 | * Returns the name of the topic to subscribe to. 22 | * 23 | * @return the name of the topic in redis 24 | */ 25 | String getTopic(); 26 | 27 | /** 28 | * Invoked for each message received from redis for the subscribed topic. 29 | * 30 | * @param message the message that was published 31 | */ 32 | void onMessage(String message); 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/es/annotations/ESOption.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.es.annotations; 10 | 11 | /** 12 | * Used to describe a tri-state property which is either true, false or default, which 13 | * will use the default value used by Elasticsearch. 14 | */ 15 | public enum ESOption { 16 | 17 | /** 18 | * Specifies true to elasticsearch as the value for this option 19 | */ 20 | TRUE("true"), 21 | 22 | /** 23 | * Specifies false to elasticsearch as the value for this option 24 | */ 25 | FALSE("false"), 26 | 27 | /** 28 | * Specifies no value to elasticsearch, hence using the default value of elasticserach 29 | */ 30 | ES_DEFAULT(""); 31 | 32 | private final String value; 33 | 34 | ESOption(String value) { 35 | this.value = value; 36 | } 37 | 38 | @Override 39 | public String toString() { 40 | return value; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/es/RoutedBatchTestEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.es; 10 | 11 | import sirius.db.es.annotations.RoutedBy; 12 | import sirius.db.mixing.Mapping; 13 | import sirius.db.mixing.annotations.Versioned; 14 | 15 | @Versioned 16 | public class RoutedBatchTestEntity extends ElasticEntity { 17 | 18 | public static final Mapping VALUE = Mapping.named("value"); 19 | private int value; 20 | 21 | public static final Mapping VALUE1 = Mapping.named("value1"); 22 | @RoutedBy 23 | private int value1; 24 | 25 | public int getValue() { 26 | return value; 27 | } 28 | 29 | public RoutedBatchTestEntity withValue(int value) { 30 | this.value = value; 31 | return this; 32 | } 33 | 34 | public int getValue1() { 35 | return value1; 36 | } 37 | 38 | public RoutedBatchTestEntity withValue1(int value) { 39 | this.value1 = value; 40 | return this; 41 | } 42 | 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/mixing/RefEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing; 10 | 11 | import sirius.db.es.types.ElasticRef; 12 | import sirius.db.jdbc.SQLEntity; 13 | import sirius.db.mixing.annotations.ComplexDelete; 14 | import sirius.db.mixing.annotations.NullAllowed; 15 | import sirius.db.mixing.types.BaseEntityRef; 16 | import sirius.db.mongo.types.MongoRef; 17 | 18 | @ComplexDelete(false) 19 | public class RefEntity extends SQLEntity { 20 | 21 | @NullAllowed 22 | private final ElasticRef elastic = 23 | ElasticRef.on(RefElasticEntity.class, BaseEntityRef.OnDelete.CASCADE); 24 | 25 | @NullAllowed 26 | private final MongoRef mongo = MongoRef.on(RefMongoEntity.class, BaseEntityRef.OnDelete.CASCADE); 27 | 28 | public ElasticRef getElastic() { 29 | return elastic; 30 | } 31 | 32 | public MongoRef getMongo() { 33 | return mongo; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/es/SuggestTestEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.es; 10 | 11 | import sirius.db.es.annotations.Analyzed; 12 | import sirius.db.mixing.Mapping; 13 | import sirius.db.mixing.annotations.NullAllowed; 14 | 15 | public class SuggestTestEntity extends ElasticEntity { 16 | 17 | public static final Mapping CONTENT = Mapping.named("content"); 18 | @Analyzed(analyzer = Analyzed.ANALYZER_WHITESPACE, indexOptions = Analyzed.IndexOption.POSITIONS) 19 | private String content; 20 | 21 | public static final Mapping SHOP = Mapping.named("shop"); 22 | @NullAllowed 23 | private Long shop; 24 | 25 | public String getContent() { 26 | return content; 27 | } 28 | 29 | public void setContent(String content) { 30 | this.content = content; 31 | } 32 | 33 | public Long getShop() { 34 | return shop; 35 | } 36 | 37 | public void setShop(long shop) { 38 | this.shop = shop; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/mixing/fieldlookup/NameFieldsTestComposite.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.fieldlookup; 10 | 11 | import sirius.db.mixing.Composite; 12 | import sirius.db.mixing.Mapping; 13 | import sirius.db.mixing.annotations.Length; 14 | 15 | public class NameFieldsTestComposite extends Composite { 16 | 17 | public static final Mapping FIRSTNAME = Mapping.named("firstname"); 18 | @Length(100) 19 | private String firstname; 20 | 21 | public static final Mapping LASTNAME = Mapping.named("lastname"); 22 | @Length(100) 23 | private String lastname; 24 | 25 | public String getFirstname() { 26 | return firstname; 27 | } 28 | 29 | public void setFirstname(String firstname) { 30 | this.firstname = firstname; 31 | } 32 | 33 | public String getLastname() { 34 | return lastname; 35 | } 36 | 37 | public void setLastname(String lastname) { 38 | this.lastname = lastname; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/es/properties/ESDenseVectorEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.es.properties; 10 | 11 | import sirius.db.es.ElasticEntity; 12 | import sirius.db.es.types.DenseVector; 13 | import sirius.db.mixing.Mapping; 14 | import sirius.db.mixing.annotations.NullAllowed; 15 | 16 | public class ESDenseVectorEntity extends ElasticEntity { 17 | 18 | public static final Mapping TEST_STRING = Mapping.named("testString"); 19 | @NullAllowed 20 | private String testString; 21 | 22 | public static final Mapping DENSE_VECTOR = Mapping.named("denseVector"); 23 | private final DenseVector denseVector = new DenseVector(3, DenseVector.Similarity.COSINE, true); 24 | 25 | public DenseVector getDenseVector() { 26 | return denseVector; 27 | } 28 | 29 | public String getTestString() { 30 | return testString; 31 | } 32 | 33 | public void setTestString(String testString) { 34 | this.testString = testString; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/mixing/properties/DateEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.properties; 10 | 11 | import sirius.db.jdbc.SQLEntity; 12 | import sirius.db.mixing.Mapping; 13 | 14 | import java.time.LocalDate; 15 | import java.time.LocalDateTime; 16 | import java.time.LocalTime; 17 | 18 | public class DateEntity extends SQLEntity { 19 | public static final Mapping LOCAL_DATE_TIME = Mapping.named("localDateTime"); 20 | private LocalDateTime localDateTime; 21 | public static final Mapping LOCAL_TIME = Mapping.named("localTime"); 22 | private LocalTime localTime; 23 | public static final Mapping LOCAL_DATE = Mapping.named("localDate"); 24 | private LocalDate localDate; 25 | 26 | public LocalDateTime getLocalDateTime() { 27 | return localDateTime; 28 | } 29 | 30 | public LocalTime getLocalTime() { 31 | return localTime; 32 | } 33 | 34 | public LocalDate getLocalDate() { 35 | return localDate; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/jdbc/SmartQueryTestChildChildEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mixing.annotations.Length; 13 | 14 | /** 15 | * Testentity for SmartQuerySpec 16 | */ 17 | public class SmartQueryTestChildChildEntity extends SQLEntity { 18 | 19 | @Length(50) 20 | private String name; 21 | public static final Mapping NAME = Mapping.named("name"); 22 | 23 | private final SQLEntityRef parentChild = 24 | SQLEntityRef.on(SmartQueryTestChildEntity.class, SQLEntityRef.OnDelete.CASCADE); 25 | public static final Mapping PARENT_CHILD = Mapping.named("parentChild"); 26 | 27 | public String getName() { 28 | return name; 29 | } 30 | 31 | public void setName(String name) { 32 | this.name = name; 33 | } 34 | 35 | public SQLEntityRef getParentChild() { 36 | return parentChild; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/annotations/AfterDelete.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.annotations; 10 | 11 | import sirius.db.mixing.Mixable; 12 | import sirius.kernel.di.std.Priorized; 13 | 14 | import java.lang.annotation.Documented; 15 | import java.lang.annotation.ElementType; 16 | import java.lang.annotation.Retention; 17 | import java.lang.annotation.RetentionPolicy; 18 | import java.lang.annotation.Target; 19 | 20 | /** 21 | * Used to mark methods in {@link Mixable}s which will be called once an entity was deleted. 22 | */ 23 | @Documented 24 | @Retention(RetentionPolicy.RUNTIME) 25 | @Target(ElementType.METHOD) 26 | public @interface AfterDelete { 27 | 28 | /** 29 | * Determines the execution order of all after delete handlers. 30 | * 31 | * @return the execution priority. Handlers will be executed in ascending order, the one with the lowest value 32 | * will be executed first. 33 | */ 34 | int priority() default Priorized.DEFAULT_PRIORITY; 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/jdbc/SmartQueryTestEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mixing.annotations.ComplexDelete; 13 | import sirius.db.mixing.annotations.Length; 14 | 15 | /** 16 | * Testentity for SmartQuerySpec 17 | */ 18 | @ComplexDelete(false) 19 | public class SmartQueryTestEntity extends SQLEntity { 20 | 21 | @Length(50) 22 | private String value; 23 | public static final Mapping VALUE = Mapping.named("value"); 24 | 25 | private int testNumber; 26 | public static final Mapping TEST_NUMBER = Mapping.named("testNumber"); 27 | 28 | public String getValue() { 29 | return value; 30 | } 31 | 32 | public void setValue(String value) { 33 | this.value = value; 34 | } 35 | 36 | public int getTestNumber() { 37 | return testNumber; 38 | } 39 | 40 | public void setTestNumber(int testNumber) { 41 | this.testNumber = testNumber; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/annotations/BeforeDelete.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.annotations; 10 | 11 | import sirius.db.mixing.Mixable; 12 | import sirius.kernel.di.std.Priorized; 13 | 14 | import java.lang.annotation.Documented; 15 | import java.lang.annotation.ElementType; 16 | import java.lang.annotation.Retention; 17 | import java.lang.annotation.RetentionPolicy; 18 | import java.lang.annotation.Target; 19 | 20 | /** 21 | * Used to mark methods in {@link Mixable}s which will be called before an entity is deleted. 22 | */ 23 | @Documented 24 | @Retention(RetentionPolicy.RUNTIME) 25 | @Target(ElementType.METHOD) 26 | public @interface BeforeDelete { 27 | 28 | /** 29 | * Determines the execution order of all before delete handlers. 30 | * 31 | * @return the execution priority. Handlers will be executed in ascending order, the one with the lowest value 32 | * will be executed first. 33 | */ 34 | int priority() default Priorized.DEFAULT_PRIORITY; 35 | } 36 | -------------------------------------------------------------------------------- /.run/local install.run.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/es/annotations/CustomSettings.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.es.annotations; 10 | 11 | import sirius.db.es.SettingsCustomizer; 12 | 13 | import java.lang.annotation.ElementType; 14 | import java.lang.annotation.Retention; 15 | import java.lang.annotation.RetentionPolicy; 16 | import java.lang.annotation.Target; 17 | 18 | /** 19 | * Specifies a {@link SettingsCustomizer} to use for a given {@link sirius.db.es.ElasticEntity}. 20 | *

21 | * This annotation needs to be placed on an entity class and will then invoke the given customizer during index 22 | * creation. This can be used to add additional settings when creating an index within Elasticsearh. 23 | */ 24 | @Retention(RetentionPolicy.RUNTIME) 25 | @Target(ElementType.TYPE) 26 | public @interface CustomSettings { 27 | 28 | /** 29 | * Specifies the {@link SettingsCustomizer} to use. 30 | * 31 | * @return the type of customizer to use 32 | */ 33 | Class value(); 34 | } 35 | -------------------------------------------------------------------------------- /.github/ga-release-drafter.yml: -------------------------------------------------------------------------------- 1 | name-template: 'GA Release $RESOLVED_VERSION' 2 | tag-template: 'ga-$RESOLVED_VERSION' 3 | categories: 4 | - title: 'Breaking Changes' 5 | label: '💣 BREAKING CHANGE' 6 | - title: 'New Features / Enhancements' 7 | collapse-after: 10 8 | label: '🧬 Enhancement' 9 | - title: 'Bugfixes' 10 | collapse-after: 5 11 | label: '🐛 Bugfix' 12 | - title: 'Maintenance' 13 | collapse-after: 5 14 | labels: 15 | - '🛠️ Maintenance' 16 | - '⬆️ Dependencies' 17 | - title: 'Uncategorized' 18 | exclude-labels: 19 | - '⎇ Sidebranch' 20 | change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks. 21 | filter-by-commitish: true 22 | version-resolver: 23 | major: 24 | labels: 25 | - '💣 BREAKING CHANGE' 26 | minor: 27 | labels: 28 | - '🧬 Enhancement' 29 | patch: 30 | labels: 31 | - '🐛 Bugfix' 32 | - '🛠️ Maintenance' 33 | default: patch 34 | template: | 35 | # Changelog 36 | 37 | $CHANGES 38 | 39 | **Full Changelog:** [$PREVIOUS_TAG...ga-$RESOLVED_VERSION](https://github.com/scireum/$REPOSITORY/compare/$PREVIOUS_TAG...ga-$RESOLVED_VERSION) 40 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/es/IndexNaming.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.es; 10 | 11 | import sirius.db.mixing.EntityDescriptor; 12 | 13 | /** 14 | * Can be supplied to enforce naming conventions for indices and mappings in ElasticSearch on a per product basis. 15 | *

16 | * Use {@link sirius.kernel.di.std.Register} to make a custom implementation visible to the framework. 17 | */ 18 | public interface IndexNaming { 19 | 20 | /** 21 | * Determines the name of the index for the given entity. 22 | * 23 | * @param descriptor the descriptor of the entity to return the index name for 24 | * @return the index name 25 | */ 26 | String determineIndexName(EntityDescriptor descriptor); 27 | 28 | /** 29 | * Determines the name of the mapping for the given entity. 30 | * 31 | * @param descriptor the descriptor of the entity to return the mapping name for 32 | * @return the mapping name 33 | */ 34 | String determineMappingName(EntityDescriptor descriptor); 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/annotations/Length.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.annotations; 10 | 11 | import java.lang.annotation.Documented; 12 | import java.lang.annotation.ElementType; 13 | import java.lang.annotation.Retention; 14 | import java.lang.annotation.RetentionPolicy; 15 | import java.lang.annotation.Target; 16 | 17 | /** 18 | * Specifies the column length, most probably of string (CHAR) columns. 19 | *

20 | * This annotation has no effect on properties other than a string, except the columns 21 | * definitions for Clickhouse, where the length is used also for other types, for example int, 22 | * to define the int size to use. 23 | * 24 | * @see sirius.db.jdbc.schema.ClickhouseDatabaseDialect 25 | */ 26 | @Documented 27 | @Retention(RetentionPolicy.RUNTIME) 28 | @Target(ElementType.FIELD) 29 | public @interface Length { 30 | 31 | /** 32 | * The maximal length of the column. 33 | * 34 | * @return the maximal length of the column 35 | */ 36 | int value(); 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/query/QueryTagHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.query; 10 | 11 | import sirius.db.mixing.EntityDescriptor; 12 | import sirius.db.mixing.query.constraints.Constraint; 13 | import sirius.db.mixing.query.constraints.FilterFactory; 14 | import sirius.kernel.di.std.Named; 15 | 16 | /** 17 | * Compiles a tag value provided by a {@link QueryTag} into a {@link Constraint}. 18 | * 19 | * @param the type of constraints generated by this handler 20 | */ 21 | public interface QueryTagHandler extends Named { 22 | 23 | /** 24 | * Computes the constraint. 25 | * 26 | * @param factory the filter factory to use when generating constraints 27 | * @param descriptor the entity for which the constraint is to be created 28 | * @param tagValue the value to filter on 29 | * @return a constraint representing the given filter 30 | */ 31 | C generateConstraint(FilterFactory factory, EntityDescriptor descriptor, String tagValue); 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/jdbc/TestEntityWithNullRef.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mixing.annotations.Length; 13 | import sirius.db.mixing.annotations.NullAllowed; 14 | 15 | /** 16 | * Test entity with an entityRef object that may be null 17 | */ 18 | public class TestEntityWithNullRef extends SQLEntity { 19 | @Length(50) 20 | private String name; 21 | public static final Mapping NAME = Mapping.named("name"); 22 | 23 | public static final Mapping PARENT = Mapping.named("parent"); 24 | @NullAllowed 25 | private final SQLEntityRef parent = 26 | SQLEntityRef.on(SmartQueryTestParentEntity.class, SQLEntityRef.OnDelete.CASCADE); 27 | 28 | public String getName() { 29 | return name; 30 | } 31 | 32 | public void setName(String name) { 33 | this.name = name; 34 | } 35 | 36 | public SQLEntityRef getParent() { 37 | return parent; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/test/kotlin/sirius/db/redis/RedisTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.redis 10 | 11 | import org.junit.jupiter.api.Test 12 | import org.junit.jupiter.api.assertNotNull 13 | import org.junit.jupiter.api.extension.ExtendWith 14 | import sirius.kernel.SiriusExtension 15 | import sirius.kernel.di.std.Part 16 | import kotlin.test.assertEquals 17 | 18 | @ExtendWith(SiriusExtension::class) 19 | class RedisTest { 20 | 21 | companion object { 22 | @Part 23 | private lateinit var redis: Redis 24 | } 25 | 26 | @Test 27 | fun `getInfo works`() { 28 | val info = redis.info 29 | 30 | assert(info.isNotEmpty()) 31 | assertNotNull(info["redis_version"]) 32 | } 33 | 34 | @Test 35 | fun `basic GET SET works`() { 36 | val testString = System.currentTimeMillis().toString() 37 | 38 | redis.exec({ -> "Setting a test value" }, { db -> db.set("TEST", testString) }) 39 | 40 | assertEquals(redis.query({ -> "Getting a test value" }, { db -> db.get("TEST") }), testString) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/annotations/Mixin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.annotations; 10 | 11 | import sirius.db.mixing.Composite; 12 | 13 | import java.lang.annotation.Documented; 14 | import java.lang.annotation.ElementType; 15 | import java.lang.annotation.Retention; 16 | import java.lang.annotation.RetentionPolicy; 17 | import java.lang.annotation.Target; 18 | 19 | /** 20 | * Marks a class as mixin for another target class (which is either an {@link sirius.db.mixing.BaseEntity} or a {@link Composite}). 21 | *

22 | * A mixin can add properties to an entity or composite, which are not defined in the original class. This can be used 23 | * to defined customer extensions without modifying the standard classes. 24 | */ 25 | @Documented 26 | @Retention(RetentionPolicy.RUNTIME) 27 | @Target(ElementType.TYPE) 28 | public @interface Mixin { 29 | /** 30 | * The target class which will inherit all properties defined by this mixing. 31 | * 32 | * @return the target class to extend 33 | */ 34 | Class value(); 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/es/ElasticTestEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.es; 10 | 11 | import sirius.db.mixing.Mapping; 12 | 13 | public class ElasticTestEntity extends ElasticEntity { 14 | 15 | public static final Mapping FIRSTNAME = Mapping.named("firstname"); 16 | private String firstname; 17 | 18 | public static final Mapping LASTNAME = Mapping.named("lastname"); 19 | private String lastname; 20 | 21 | public static final Mapping AGE = Mapping.named("age"); 22 | private int age; 23 | 24 | public String getFirstname() { 25 | return firstname; 26 | } 27 | 28 | public void setFirstname(String firstname) { 29 | this.firstname = firstname; 30 | } 31 | 32 | public String getLastname() { 33 | return lastname; 34 | } 35 | 36 | public void setLastname(String lastname) { 37 | this.lastname = lastname; 38 | } 39 | 40 | public int getAge() { 41 | return age; 42 | } 43 | 44 | public void setAge(int age) { 45 | this.age = age; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/mixing/fieldlookup/SQLSuperHeroTestMixin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.fieldlookup; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mixing.Mixable; 13 | import sirius.db.mixing.annotations.Length; 14 | import sirius.db.mixing.annotations.Mixin; 15 | import sirius.db.mixing.annotations.NullAllowed; 16 | import sirius.db.mixing.types.StringList; 17 | 18 | @Mixin(SQLFieldLookUpTestEntity.class) 19 | public class SQLSuperHeroTestMixin extends Mixable { 20 | 21 | public static final Mapping HERO_NAMES = Mapping.named("heroNames"); 22 | private final NameFieldsTestComposite heroNames = new NameFieldsTestComposite(); 23 | 24 | public static final Mapping SUPER_POWERS = Mapping.named("superPowers"); 25 | @Length(100) 26 | @NullAllowed 27 | private final StringList superPowers = new StringList(); 28 | 29 | public NameFieldsTestComposite getHeroNames() { 30 | return heroNames; 31 | } 32 | 33 | public StringList getSuperPowers() { 34 | return superPowers; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /.run/mvn clean test - without nightly.run.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/PropertyValidator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing; 10 | 11 | import sirius.kernel.di.std.AutoRegister; 12 | import sirius.kernel.di.std.Named; 13 | 14 | import java.util.function.Consumer; 15 | 16 | /** 17 | * Permits to validate a property before it is written to the database. 18 | */ 19 | @AutoRegister 20 | public interface PropertyValidator extends Named { 21 | 22 | /** 23 | * Validates the given value and reports any warnings/errors to the given consumer. 24 | * 25 | * @param value the value to validate 26 | * @param validationConsumer can be used to report validation errors 27 | */ 28 | void validate(Property property, Object value, Consumer validationConsumer); 29 | 30 | /** 31 | * Validates the given value and reports any warnings/errors to the given consumer. 32 | *

33 | * Throwing any exception will abort the write operation. 34 | * 35 | * @param value the value to validate 36 | */ 37 | void beforeSave(Property property, Object value); 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/ContextInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing; 10 | 11 | import sirius.kernel.commons.Value; 12 | 13 | /** 14 | * Represents a context info which can be supplied for {@link BaseMapper#find(Class, Object, ContextInfo...)}. 15 | */ 16 | public class ContextInfo { 17 | 18 | private String key; 19 | private Value value; 20 | 21 | /** 22 | * Creates a new info object for the given key and value. 23 | * 24 | * @param key the key used to pass in 25 | * @param value the value to pass in 26 | */ 27 | public ContextInfo(String key, Value value) { 28 | this.key = key; 29 | this.value = value; 30 | } 31 | 32 | /** 33 | * Returns the key of this info. 34 | * 35 | * @return the key of this info 36 | */ 37 | public String getKey() { 38 | return key; 39 | } 40 | 41 | /** 42 | * Returns the value of this info. 43 | * 44 | * @return the value of this info 45 | */ 46 | public Value getValue() { 47 | return value; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/jdbc/SmartQueryTestCountEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mixing.annotations.ComplexDelete; 13 | import sirius.db.mixing.annotations.Length; 14 | 15 | /** 16 | * Test entity for SmartQuerySpec concerning distinct and not distinct counts 17 | */ 18 | @ComplexDelete(false) 19 | public class SmartQueryTestCountEntity extends SQLEntity { 20 | 21 | public static final Mapping FIELD_ONE = Mapping.named("fieldOne"); 22 | @Length(50) 23 | private String fieldOne; 24 | 25 | public static final Mapping FIELD_TWO = Mapping.named("fieldTwo"); 26 | @Length(50) 27 | private String fieldTwo; 28 | 29 | public String getFieldOne() { 30 | return fieldOne; 31 | } 32 | 33 | public void setFieldOne(String fieldOne) { 34 | this.fieldOne = fieldOne; 35 | } 36 | 37 | public String getFieldTwo() { 38 | return fieldTwo; 39 | } 40 | 41 | public void setFieldTwo(String fieldTwo) { 42 | this.fieldTwo = fieldTwo; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/jdbc/TestEntityWithMixin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mixing.annotations.Length; 13 | 14 | public class TestEntityWithMixin extends SQLEntity { 15 | 16 | public static final Mapping FIRSTNAME = Mapping.named("firstname"); 17 | @Length(50) 18 | private String firstname; 19 | 20 | public static final Mapping LASTNAME = Mapping.named("lastname"); 21 | @Length(50) 22 | private String lastname; 23 | 24 | private int age; 25 | 26 | public String getFirstname() { 27 | return firstname; 28 | } 29 | 30 | public void setFirstname(String firstname) { 31 | this.firstname = firstname; 32 | } 33 | 34 | public String getLastname() { 35 | return lastname; 36 | } 37 | 38 | public void setLastname(String lastname) { 39 | this.lastname = lastname; 40 | } 41 | 42 | public int getAge() { 43 | return age; 44 | } 45 | 46 | public void setAge(int age) { 47 | this.age = age; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/annotations/Numeric.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.annotations; 10 | 11 | import java.lang.annotation.Documented; 12 | import java.lang.annotation.ElementType; 13 | import java.lang.annotation.Retention; 14 | import java.lang.annotation.RetentionPolicy; 15 | import java.lang.annotation.Target; 16 | 17 | /** 18 | * Specifies the numeric precision of a NUMBER column. 19 | *

20 | * If a column must store values with 12 digits and 3 decimal places, the precision would be 15 and scale 21 | * 3. 22 | */ 23 | @Documented 24 | @Retention(RetentionPolicy.RUNTIME) 25 | @Target(ElementType.FIELD) 26 | public @interface Numeric { 27 | 28 | /** 29 | * The total number of digits which can be stored in that column without rounding. 30 | * 31 | * @return the total number of digits 32 | */ 33 | int precision(); 34 | 35 | /** 36 | * The number of decimal digits after the decimal separator. 37 | * 38 | * @return the number of digits after the decimal separator 39 | */ 40 | int scale(); 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/text/DeduplicateProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.text; 10 | 11 | import java.util.HashSet; 12 | import java.util.Set; 13 | 14 | /** 15 | * Filters duplicate tokens generated by upstream processors. 16 | */ 17 | public class DeduplicateProcessor extends ChainableTokenProcessor { 18 | 19 | private final Set tokens = new HashSet<>(); 20 | private final boolean global; 21 | 22 | /** 23 | * Creates a new processor. 24 | * 25 | * @param global determines if deduplication happens globally (for the lifetime of the processor) 26 | * or locally (until the next {@link #purge()}). 27 | */ 28 | public DeduplicateProcessor(boolean global) { 29 | this.global = global; 30 | } 31 | 32 | @Override 33 | public void accept(String token) { 34 | if (tokens.add(token)) { 35 | emit(token); 36 | } 37 | } 38 | 39 | @Override 40 | public void purge() { 41 | if (!global) { 42 | tokens.clear(); 43 | } 44 | super.purge(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/test/kotlin/sirius/db/jdbc/SmartQueryNighlyTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc 10 | 11 | import org.junit.jupiter.api.Tag 12 | import org.junit.jupiter.api.Test 13 | import org.junit.jupiter.api.assertThrows 14 | import org.junit.jupiter.api.extension.ExtendWith 15 | import sirius.kernel.SiriusExtension 16 | import sirius.kernel.Tags 17 | import sirius.kernel.di.std.Part 18 | import sirius.kernel.health.HandledException 19 | 20 | @ExtendWith(SiriusExtension::class) 21 | @Tag(Tags.NIGHTLY) 22 | class SmartQueryNightlyTest { 23 | @Test 24 | fun `selecting over 1000 entities in queryList throws an exception`() { 25 | oma.select(ListTestEntity::class.java).delete() 26 | 27 | for (i in 0..1000) { 28 | val entityToCreate = ListTestEntity() 29 | entityToCreate.counter = i 30 | oma.update(entityToCreate) 31 | } 32 | 33 | assertThrows { oma.select(ListTestEntity::class.java).queryList() } 34 | } 35 | 36 | companion object { 37 | @Part 38 | private lateinit var oma: OMA 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/test/kotlin/sirius/db/mixing/properties/LocalDatePropertyTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.properties 10 | 11 | import org.junit.jupiter.api.Test 12 | import org.junit.jupiter.api.extension.ExtendWith 13 | import sirius.db.mixing.Mixing 14 | import sirius.kernel.SiriusExtension 15 | import sirius.kernel.commons.Value 16 | import sirius.kernel.di.std.Part 17 | import java.time.LocalDateTime 18 | import kotlin.test.assertEquals 19 | 20 | @ExtendWith(SiriusExtension::class) 21 | class LocalDatePropertyTest { 22 | @Test 23 | fun `local date works when transformed`() { 24 | val dateProperty = mixing.getDescriptor(DateEntity::class.java).getProperty(DateEntity.LOCAL_DATE) 25 | val localDateTime = LocalDateTime.now() 26 | val localDate = localDateTime.toLocalDate() 27 | 28 | assertEquals(localDate, dateProperty.transformValue(Value.of(localDate))) 29 | assertEquals(localDate, dateProperty.transformValue(Value.of(localDateTime))) 30 | } 31 | 32 | companion object { 33 | @Part 34 | private lateinit var mixing: Mixing 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/test/kotlin/sirius/db/mixing/properties/LocalTimePropertyTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.properties 10 | 11 | import org.junit.jupiter.api.Test 12 | import org.junit.jupiter.api.extension.ExtendWith 13 | import sirius.db.mixing.Mixing 14 | import sirius.kernel.SiriusExtension 15 | import sirius.kernel.commons.Value 16 | import sirius.kernel.di.std.Part 17 | import java.time.LocalDateTime 18 | import kotlin.test.assertEquals 19 | 20 | @ExtendWith(SiriusExtension::class) 21 | class LocalTimePropertyTest { 22 | @Test 23 | fun `local time works when transformed`() { 24 | val timeProperty = mixing.getDescriptor(DateEntity::class.java).getProperty(DateEntity.LOCAL_TIME) 25 | val localDateTime = LocalDateTime.now() 26 | val localTime = localDateTime.toLocalTime() 27 | 28 | assertEquals(localTime, timeProperty.transformValue(Value.of(localTime))) 29 | assertEquals(localTime, timeProperty.transformValue(Value.of(localDateTime))) 30 | } 31 | 32 | companion object { 33 | @Part 34 | private lateinit var mixing: Mixing 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/es/SettingsCustomizer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.es; 10 | 11 | import com.fasterxml.jackson.databind.node.ObjectNode; 12 | import sirius.db.mixing.EntityDescriptor; 13 | import sirius.kernel.di.std.AutoRegister; 14 | 15 | /** 16 | * Customizes the settings block of an {@link ElasticEntity} when creating a new index in Elasticsearch. 17 | *

18 | * This class needs to be {@link sirius.kernel.di.std.Register registered} and can then be referenced by placing 19 | * a {@link sirius.db.es.annotations.CustomSettings} annotation on the appropriate entity classes. 20 | */ 21 | @AutoRegister 22 | public interface SettingsCustomizer { 23 | 24 | /** 25 | * Customizes the given settings object for the given entity (descriptor). 26 | * 27 | * @param descriptor the descriptor of the entity to customize 28 | * @param settingsObject the settings object which will be passed to Elasticsearch when creating a new 29 | * index. 30 | */ 31 | void customizeSettings(EntityDescriptor descriptor, ObjectNode settingsObject); 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/jdbc/GeneratedStatementTestEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mixing.annotations.ComplexDelete; 13 | import sirius.db.mixing.annotations.Length; 14 | import sirius.db.mixing.types.BaseEntityRef; 15 | 16 | import javax.annotation.Nullable; 17 | 18 | /** 19 | * Testentity for UpdateStatementSpec 20 | */ 21 | @ComplexDelete(false) 22 | public class GeneratedStatementTestEntity extends SQLEntity { 23 | 24 | public static final Mapping VALUE = Mapping.named("value"); 25 | @Length(50) 26 | private String value; 27 | 28 | public static final Mapping TEST_NUMBER = Mapping.named("testNumber"); 29 | private int testNumber; 30 | 31 | public String getValue() { 32 | return value; 33 | } 34 | 35 | public void setValue(String value) { 36 | this.value = value; 37 | } 38 | 39 | public int getTestNumber() { 40 | return testNumber; 41 | } 42 | 43 | public void setTestNumber(int testNumber) { 44 | this.testNumber = testNumber; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/es/RoutedTestEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.es; 10 | 11 | import sirius.db.es.annotations.RoutedBy; 12 | import sirius.db.mixing.Mapping; 13 | 14 | public class RoutedTestEntity extends ElasticEntity { 15 | 16 | public static final Mapping FIRSTNAME = Mapping.named("firstname"); 17 | private String firstname; 18 | 19 | public static final Mapping LASTNAME = Mapping.named("lastname"); 20 | @RoutedBy 21 | private String lastname; 22 | 23 | public static final Mapping AGE = Mapping.named("age"); 24 | private int age; 25 | 26 | public String getFirstname() { 27 | return firstname; 28 | } 29 | 30 | public void setFirstname(String firstname) { 31 | this.firstname = firstname; 32 | } 33 | 34 | public String getLastname() { 35 | return lastname; 36 | } 37 | 38 | public void setLastname(String lastname) { 39 | this.lastname = lastname; 40 | } 41 | 42 | public int getAge() { 43 | return age; 44 | } 45 | 46 | public void setAge(int age) { 47 | this.age = age; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/InvalidFieldException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing; 10 | 11 | import java.io.Serial; 12 | 13 | /** 14 | * Marker exception to mark which field produced an error. 15 | *

16 | * This is used as "cause" for HandledExceptions that are generated by a failed field check. 17 | * This way, other frameworks can pick up this exception and extract the source field for an error message. 18 | *

19 | * This is used by sirius-biz to highlight the field which caused an error when trying to save an entity. 20 | */ 21 | public class InvalidFieldException extends Exception { 22 | 23 | @Serial 24 | private static final long serialVersionUID = 4954813810676679158L; 25 | private final String field; 26 | 27 | /** 28 | * Creates a new exception for the given field. 29 | * 30 | * @param field the name of the field which produced the error message 31 | */ 32 | public InvalidFieldException(String field) { 33 | super(field); 34 | this.field = field; 35 | } 36 | 37 | public String getField() { 38 | return field; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/MixinLoadAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing; 10 | 11 | import sirius.db.mixing.annotations.Mixin; 12 | import sirius.kernel.Sirius; 13 | import sirius.kernel.di.ClassLoadAction; 14 | import sirius.kernel.di.MutableGlobalContext; 15 | import sirius.kernel.di.std.Framework; 16 | 17 | import java.lang.annotation.Annotation; 18 | 19 | /** 20 | * Loads all {@link Mixin}s so that they don't have to wear a {@link sirius.kernel.di.std.Register} annotation. 21 | */ 22 | public class MixinLoadAction implements ClassLoadAction { 23 | 24 | @Override 25 | public Class getTrigger() { 26 | return Mixin.class; 27 | } 28 | 29 | @Override 30 | public void handle(MutableGlobalContext ctx, Class clazz) throws Exception { 31 | if (clazz.isAnnotationPresent(Framework.class)) { 32 | if (Sirius.isFrameworkEnabled(clazz.getAnnotation(Framework.class).value())) { 33 | ctx.registerPart(clazz, Mixin.class); 34 | } 35 | } else { 36 | ctx.registerPart(clazz, Mixin.class); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/text/TokenLimitProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.text; 10 | 11 | /** 12 | * Discards tokens which are either too long or to too short to be processed. 13 | */ 14 | public class TokenLimitProcessor extends ChainableTokenProcessor { 15 | 16 | private final int tokenMinLength; 17 | private final int tokenMaxLength; 18 | 19 | /** 20 | * Creates a new processor with the given lengths. 21 | * 22 | * @param tokenMinLength the minimal length for a token to be accepted 23 | * @param tokenMaxLength the maximal length for a token to be accepted 24 | */ 25 | public TokenLimitProcessor(int tokenMinLength, int tokenMaxLength) { 26 | this.tokenMinLength = tokenMinLength; 27 | this.tokenMaxLength = tokenMaxLength; 28 | } 29 | 30 | @Override 31 | public void accept(String value) { 32 | if (tokenMinLength > 0 && value.length() < tokenMinLength) { 33 | return; 34 | } 35 | 36 | if (tokenMaxLength > 0 && value.length() > tokenMaxLength) { 37 | return; 38 | } 39 | 40 | emit(value); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/es/SuppressedRoutedTestEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.es; 10 | 11 | import sirius.db.es.annotations.RoutedBy; 12 | import sirius.db.mixing.Mapping; 13 | 14 | public class SuppressedRoutedTestEntity extends ElasticEntity { 15 | 16 | public static final Mapping FIRSTNAME = Mapping.named("firstname"); 17 | private String firstname; 18 | 19 | public static final Mapping LASTNAME = Mapping.named("lastname"); 20 | @RoutedBy 21 | private String lastname; 22 | 23 | public static final Mapping AGE = Mapping.named("age"); 24 | private int age; 25 | 26 | public String getFirstname() { 27 | return firstname; 28 | } 29 | 30 | public void setFirstname(String firstname) { 31 | this.firstname = firstname; 32 | } 33 | 34 | public String getLastname() { 35 | return lastname; 36 | } 37 | 38 | public void setLastname(String lastname) { 39 | this.lastname = lastname; 40 | } 41 | 42 | public int getAge() { 43 | return age; 44 | } 45 | 46 | public void setAge(int age) { 47 | this.age = age; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/test/kotlin/sirius/db/text/PatternSplitProcessorTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.text 10 | 11 | import org.junit.jupiter.api.Test 12 | import java.util.regex.Pattern 13 | 14 | /** 15 | * Tests the [PatternSplitProcessor]. 16 | */ 17 | class PatternSplitProcessorTest : TokenProcessorTest() { 18 | 19 | @Test 20 | fun tokenizing() { 21 | assertExactTokenizing( 22 | "a7b8\$c", 23 | PatternSplitProcessor(Pattern.compile("[^a-z]"), false, true), 24 | "a", 25 | "b", 26 | "c" 27 | ) 28 | assertExactTokenizing( 29 | " A B-6:7C-", 30 | PatternSplitProcessor(Pattern.compile("[^a-zA-Z0-9]"), true, true), 31 | " A B-6:7C-", 32 | "A", 33 | "B", 34 | "6", 35 | "7C" 36 | ) 37 | } 38 | 39 | @Test 40 | fun `tokenizing via hard boundary splitter preset`() { 41 | // Text including a plus or ampersand not surrounded by whitespace should not be split 42 | assertExactTokenizing("A+B&C", PatternSplitProcessor.createHardBoundarySplitter(), "A+B&C") 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/annotations/BeforeSave.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.annotations; 10 | 11 | import sirius.db.mixing.BaseEntity; 12 | import sirius.db.mixing.Mixable; 13 | import sirius.kernel.di.std.Priorized; 14 | 15 | import java.lang.annotation.Documented; 16 | import java.lang.annotation.ElementType; 17 | import java.lang.annotation.Retention; 18 | import java.lang.annotation.RetentionPolicy; 19 | import java.lang.annotation.Target; 20 | 21 | /** 22 | * Used to mark methods in {@link Mixable}s which will be called before an entity is saved. 23 | *

24 | * If you need different logic for updated and newly created entities, use {@link BaseEntity#isNew()} in your method. 25 | */ 26 | @Documented 27 | @Retention(RetentionPolicy.RUNTIME) 28 | @Target(ElementType.METHOD) 29 | public @interface BeforeSave { 30 | 31 | /** 32 | * Determines the execution order of all before save handlers. 33 | * 34 | * @return the execution priority. Handlers will be executed in ascending order, the one with the lowest value 35 | * will be executed first. 36 | */ 37 | int priority() default Priorized.DEFAULT_PRIORITY; 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/types/StringList.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.types; 10 | 11 | /** 12 | * Provides a simple list of strings as property value. 13 | */ 14 | public class StringList extends SafeList { 15 | 16 | private boolean autoparse; 17 | 18 | /** 19 | * Enables auto-parsing when performing a load from a form input or import. 20 | *

21 | * Auto-parsing will expect a single string value and split at each occurrence of a ",". 22 | * 23 | * @return the list itself for fluent method calls 24 | */ 25 | public StringList enableAutoparse() { 26 | this.autoparse = true; 27 | return this; 28 | } 29 | 30 | /** 31 | * Determines if auto-parsing is enabled. 32 | * 33 | * @return true if auto-parse is enabled, false otherwise 34 | */ 35 | public boolean isAutoparse() { 36 | return autoparse; 37 | } 38 | 39 | @Override 40 | protected boolean valueNeedsCopy() { 41 | return false; 42 | } 43 | 44 | @Override 45 | protected String copyValue(String value) { 46 | return value; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/annotations/AfterSave.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.annotations; 10 | 11 | import sirius.db.mixing.BaseEntity; 12 | import sirius.db.mixing.Mixable; 13 | import sirius.kernel.di.std.Priorized; 14 | 15 | import java.lang.annotation.Documented; 16 | import java.lang.annotation.ElementType; 17 | import java.lang.annotation.Retention; 18 | import java.lang.annotation.RetentionPolicy; 19 | import java.lang.annotation.Target; 20 | 21 | /** 22 | * Used to mark methods in {@link Mixable mixables} which will be called once an entity was saved. 23 | *

24 | * If you need different logic for updated and newly created entities, use {@link BaseEntity#wasCreated()} in your method. 25 | */ 26 | @Documented 27 | @Retention(RetentionPolicy.RUNTIME) 28 | @Target(ElementType.METHOD) 29 | public @interface AfterSave { 30 | 31 | /** 32 | * Determines the execution order of all after save handlers. 33 | * 34 | * @return the execution priority. Handlers will be executed in ascending order, the one with the lowest value 35 | * will be executed first. 36 | */ 37 | int priority() default Priorized.DEFAULT_PRIORITY; 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/annotations/OnValidate.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.annotations; 10 | 11 | import sirius.db.mixing.Mixable; 12 | import sirius.kernel.di.std.Priorized; 13 | 14 | import java.lang.annotation.Documented; 15 | import java.lang.annotation.ElementType; 16 | import java.lang.annotation.Retention; 17 | import java.lang.annotation.RetentionPolicy; 18 | import java.lang.annotation.Target; 19 | 20 | /** 21 | * Used to mark methods in {@link Mixable}s which will be called once is validated. 22 | *

23 | * Note that such a method must accept a Consumer<String> as first parameter or the entity 24 | * itself and the consumer as second parameter, when called within a mixin. 25 | */ 26 | @Documented 27 | @Retention(RetentionPolicy.RUNTIME) 28 | @Target(ElementType.METHOD) 29 | public @interface OnValidate { 30 | 31 | /** 32 | * Determines the execution order of all validate handlers. 33 | * 34 | * @return the execution priority. Handlers will be executed in ascending order, the one with the lowest value 35 | * will be executed first. 36 | */ 37 | int priority() default Priorized.DEFAULT_PRIORITY; 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/annotations/SkipDefaultValue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.annotations; 10 | 11 | import java.lang.annotation.ElementType; 12 | import java.lang.annotation.Retention; 13 | import java.lang.annotation.RetentionPolicy; 14 | import java.lang.annotation.Target; 15 | 16 | /** 17 | * Instructs the entity mapper to not store a value in the database if the current value is a default value. 18 | *

19 | * This can e.g. be used for MongoDB where we can simply skip fields which are null or false, as when 20 | * reading them back, the property will restore the default value anyway. 21 | *

22 | * Note that this is not enabled by default as it might lead to unexpected behavior in queries. For example using 23 | * {@code db.collection.find({"non_existent_flag", false})} will not return document which false has been 24 | * skipped by not storing a value at all. 25 | *

26 | * The bottom line is, that this can be used to "optimize away" sparse values which are not used in queries. 27 | */ 28 | @Target(ElementType.FIELD) 29 | @Retention(RetentionPolicy.RUNTIME) 30 | public @interface SkipDefaultValue { 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/types/NestedList.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.types; 10 | 11 | import sirius.db.mixing.Nested; 12 | 13 | /** 14 | * Represents a list of {@link Nested} objects. 15 | * 16 | * @param the type of nested objects in this list 17 | */ 18 | public class NestedList extends SafeList { 19 | 20 | private Class nestedType; 21 | 22 | /** 23 | * Creates a new list for the given type. 24 | * 25 | * @param nestedType the type of objects stored in this list 26 | */ 27 | public NestedList(Class nestedType) { 28 | this.nestedType = nestedType; 29 | } 30 | 31 | /** 32 | * Returns the type of objects stored in this list. 33 | * 34 | * @return the type of objects stored in this list 35 | */ 36 | public Class getNestedType() { 37 | return nestedType; 38 | } 39 | 40 | @Override 41 | protected boolean valueNeedsCopy() { 42 | return true; 43 | } 44 | 45 | @SuppressWarnings("unchecked") 46 | @Override 47 | protected N copyValue(N value) { 48 | return value == null ? null : (N) value.copy(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/jdbc/SmartQueryTestSortingEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mixing.annotations.ComplexDelete; 13 | import sirius.db.mixing.annotations.Length; 14 | import sirius.db.mixing.annotations.NullAllowed; 15 | 16 | import javax.annotation.Nullable; 17 | 18 | /** 19 | * Testentity for SmartQuerySpec 20 | */ 21 | @ComplexDelete(false) 22 | public class SmartQueryTestSortingEntity extends SQLEntity { 23 | 24 | @Length(50) 25 | @NullAllowed 26 | private String valueOne; 27 | public static final Mapping VALUE_ONE = Mapping.named("valueOne"); 28 | 29 | @Length(50) 30 | @NullAllowed 31 | private String valueTwo; 32 | public static final Mapping VALUE_TWO = Mapping.named("valueTwo"); 33 | 34 | public String getValueOne() { 35 | return valueOne; 36 | } 37 | 38 | public void setValueOne(String valueOne) { 39 | this.valueOne = valueOne; 40 | } 41 | 42 | public String getValueTwo() { 43 | return valueTwo; 44 | } 45 | 46 | public void setValueTwo(String valueTwo) { 47 | this.valueTwo = valueTwo; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/test/kotlin/sirius/db/text/PipelineProcessorTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.text 10 | 11 | import org.junit.jupiter.api.Test 12 | 13 | /** 14 | * Tests the [PipelineProcessor]. 15 | */ 16 | class PipelineProcessorTest : TokenProcessorTest() { 17 | private class NOOPProcessor : ChainableTokenProcessor() { 18 | override fun accept(token: String) { 19 | emit(token) 20 | } 21 | } 22 | 23 | @Test 24 | fun tokenizing() { 25 | assertExactTokenizing("HelloWorld", PipelineProcessor(NOOPProcessor()), "HelloWorld") 26 | assertExactTokenizing( 27 | "HelloWorld", 28 | PipelineProcessor(NOOPProcessor(), NOOPProcessor()), 29 | "HelloWorld" 30 | ) 31 | assertExactTokenizing( 32 | "HelloWorld", 33 | PipelineProcessor( 34 | NOOPProcessor(), 35 | NOOPProcessor(), 36 | NOOPProcessor() 37 | ), 38 | "HelloWorld" 39 | ) 40 | assertExactTokenizing( 41 | "Hello World", 42 | PipelineProcessor(NOOPProcessor(), NOOPProcessor()), 43 | "Hello World" 44 | ) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mongo/types/MultiPointLocation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mongo.types; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mixing.types.SafeList; 13 | import sirius.kernel.commons.Tuple; 14 | 15 | /** 16 | * Represents a list of 2D locations which can be stored in MongoDB for geo queries. 17 | * 18 | * @see sirius.db.mongo.constraints.MongoFilterFactory#nearSphere(Mapping, double, double, int) 19 | */ 20 | public class MultiPointLocation extends SafeList> { 21 | 22 | @Override 23 | protected boolean valueNeedsCopy() { 24 | return true; 25 | } 26 | 27 | @Override 28 | protected Tuple copyValue(Tuple value) { 29 | return Tuple.create(value.getFirst(), value.getSecond()); 30 | } 31 | 32 | @Override 33 | public String toString() { 34 | StringBuilder sb = new StringBuilder(); 35 | for (Tuple location : data()) { 36 | sb.append(location.getFirst()); 37 | sb.append(","); 38 | sb.append(location.getSecond()); 39 | sb.append("\n"); 40 | } 41 | 42 | return sb.toString(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/mongo/properties/MongoAmountEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mongo.properties; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mixing.annotations.NullAllowed; 13 | import sirius.db.mixing.annotations.Numeric; 14 | import sirius.db.mongo.MongoEntity; 15 | import sirius.kernel.commons.Amount; 16 | 17 | public class MongoAmountEntity extends MongoEntity { 18 | 19 | public static final int AMOUNT_SCALE = 6; 20 | 21 | public static final Mapping TEST_AMOUNT = Mapping.named("testAmount"); 22 | private Amount testAmount = Amount.NOTHING; 23 | 24 | public static final Mapping SCALED_AMOUNT = Mapping.named("scaledAmount"); 25 | @NullAllowed 26 | @Numeric(precision = 20, scale = AMOUNT_SCALE) 27 | private Amount scaledAmount = Amount.NOTHING; 28 | 29 | public Amount getTestAmount() { 30 | return testAmount; 31 | } 32 | 33 | public void setTestAmount(Amount testAmount) { 34 | this.testAmount = testAmount; 35 | } 36 | 37 | public Amount getScaledAmount() { 38 | return scaledAmount; 39 | } 40 | 41 | public void setScaledAmount(Amount scaledAmount) { 42 | this.scaledAmount = scaledAmount; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/mongo/properties/MongoNestedListEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mongo.properties; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mixing.Nested; 13 | import sirius.db.mixing.types.NestedList; 14 | import sirius.db.mongo.MongoEntity; 15 | 16 | public class MongoNestedListEntity extends MongoEntity { 17 | 18 | public static class NestedEntity extends Nested { 19 | 20 | private String value1; 21 | private String value2; 22 | 23 | public String getValue1() { 24 | return value1; 25 | } 26 | 27 | public String getValue2() { 28 | return value2; 29 | } 30 | 31 | public NestedEntity withValue1(String value) { 32 | this.value1 = value; 33 | return this; 34 | } 35 | 36 | public NestedEntity withValue2(String value) { 37 | this.value2 = value; 38 | return this; 39 | } 40 | } 41 | 42 | public static final Mapping LIST = Mapping.named("list"); 43 | private final NestedList list = new NestedList<>(NestedEntity.class); 44 | 45 | public NestedList getList() { 46 | return list; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/mongo/validators/StringTestPropertyValidator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mongo.validators; 10 | 11 | import sirius.db.mixing.Property; 12 | import sirius.kernel.di.std.Register; 13 | import sirius.kernel.health.Exceptions; 14 | 15 | import javax.annotation.Nonnull; 16 | import java.util.function.Consumer; 17 | 18 | @Register 19 | public class StringTestPropertyValidator implements sirius.db.mixing.PropertyValidator { 20 | @Override 21 | public void validate(Property property, Object value, Consumer validationConsumer) { 22 | if (isInvalidTestString(value)) { 23 | validationConsumer.accept("Invalid value!"); 24 | } 25 | } 26 | 27 | @Override 28 | public void beforeSave(Property property, Object value) { 29 | if (isInvalidTestString(value)) { 30 | throw Exceptions.createHandled().withSystemErrorMessage("Invalid value!").handle(); 31 | } 32 | } 33 | 34 | private static boolean isInvalidTestString(Object value) { 35 | return value instanceof String text && "invalid".equals(text); 36 | } 37 | 38 | @Nonnull 39 | @Override 40 | public String getName() { 41 | return "string-test"; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/annotations/Unique.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.annotations; 10 | 11 | import java.lang.annotation.Documented; 12 | import java.lang.annotation.ElementType; 13 | import java.lang.annotation.Retention; 14 | import java.lang.annotation.RetentionPolicy; 15 | import java.lang.annotation.Target; 16 | 17 | /** 18 | * Marks a property as unique. 19 | *

20 | * A value in this column must only occur once. If within is filled, the value must only occur once while 21 | * having the same values for the properties enumerated in within. 22 | */ 23 | @Documented 24 | @Retention(RetentionPolicy.RUNTIME) 25 | @Target(ElementType.FIELD) 26 | public @interface Unique { 27 | 28 | /** 29 | * Names properties which must also match for two entities to trigger the unique check. 30 | * 31 | * @return the array of properties which determine the scope of the uniqueness 32 | */ 33 | String[] within() default {}; 34 | 35 | /** 36 | * Determines if the null also must be unique. 37 | * 38 | * @return true if null also must occur at most once, false (default) otherwise 39 | */ 40 | boolean includingNull() default false; 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/types/StringNestedMap.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.types; 10 | 11 | import sirius.db.mixing.Nested; 12 | 13 | /** 14 | * Represents map of String pointing to {@link Nested} values. 15 | * 16 | * @param specifies the type of nested objects within this map 17 | */ 18 | public class StringNestedMap extends SafeMap { 19 | 20 | private Class nestedType; 21 | 22 | /** 23 | * Creates a new instance capable of storing the given nested type. 24 | * 25 | * @param nestedType the type of items being stored 26 | */ 27 | public StringNestedMap(Class nestedType) { 28 | this.nestedType = nestedType; 29 | } 30 | 31 | /** 32 | * Returns the type of items stored as values in this map. 33 | * 34 | * @return the type of values in this map 35 | */ 36 | public Class getNestedType() { 37 | return nestedType; 38 | } 39 | 40 | @Override 41 | protected boolean valueNeedsCopy() { 42 | return true; 43 | } 44 | 45 | @SuppressWarnings("unchecked") 46 | @Override 47 | protected N copyValue(N value) { 48 | return value == null ? null : (N) value.copy(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/jdbc/MonitoredDataSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc; 10 | 11 | import org.apache.commons.dbcp2.BasicDataSource; 12 | import org.apache.commons.dbcp2.ConnectionFactory; 13 | 14 | import java.sql.Connection; 15 | import java.sql.SQLException; 16 | 17 | /** 18 | * Tracks how many connections are actually created. 19 | *

20 | * Even if connections are short-lived and not concurrently created, they could still drain the pool of local TCP ports 21 | * of the OS. Therefore we track the number of total created connections and warn if there are too many - this is 22 | * a strong indication that the connection pool is misconfigured and not working as expected anyway. 23 | */ 24 | class MonitoredDataSource extends BasicDataSource { 25 | 26 | @Override 27 | protected ConnectionFactory createConnectionFactory() throws SQLException { 28 | ConnectionFactory actualFactory = super.createConnectionFactory(); 29 | 30 | return new ConnectionFactory() { 31 | @Override 32 | public Connection createConnection() throws SQLException { 33 | Databases.numConnects.inc(); 34 | return actualFactory.createConnection(); 35 | } 36 | }; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/test/kotlin/sirius/db/mongo/properties/MongoMultiPointTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mongo.properties 10 | 11 | import org.junit.jupiter.api.Test 12 | import org.junit.jupiter.api.extension.ExtendWith 13 | import sirius.db.mongo.Mango 14 | import sirius.kernel.SiriusExtension 15 | import sirius.kernel.commons.Tuple 16 | import sirius.kernel.di.std.Part 17 | import kotlin.test.assertEquals 18 | 19 | @ExtendWith(SiriusExtension::class) 20 | class MongoMultiPointTest { 21 | @Test 22 | fun `read and write multipoint works`() { 23 | var mongoMultiPointEntity = MongoMultiPointEntity() 24 | 25 | mango.update(mongoMultiPointEntity) 26 | 27 | mongoMultiPointEntity.locations.isEmpty 28 | 29 | val coords = listOf(Tuple.create(48.81734, 9.376294), Tuple.create(48.823356, 9.424718)) 30 | mongoMultiPointEntity.locations.addAll(coords) 31 | mango.update(mongoMultiPointEntity) 32 | 33 | assertEquals(2, mongoMultiPointEntity.locations.size()) 34 | 35 | mongoMultiPointEntity = mango.refreshOrFail(mongoMultiPointEntity) 36 | 37 | assertEquals(2, mongoMultiPointEntity.locations.size()) 38 | } 39 | 40 | companion object { 41 | @Part 42 | private lateinit var mango: Mango 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/IntegrityConstraintFailedException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing; 10 | 11 | import java.io.Serial; 12 | 13 | /** 14 | * Wraps all database specific exceptions to signal that an integrity constraint was violated. 15 | *

16 | * Sometimes we use a constraint like "UNIQUE" to detect certain race conditions or other parallel behaviour 17 | * without the need for locking. The occurrence of such an error then needs to be handled properly 18 | * (i.e. by retrying an operation). Therefore some methods (e.g. {@link BaseMapper#tryUpdate(BaseEntity)} 19 | * throw this dedicated exception to permit the application code to handle this case properly. 20 | */ 21 | public class IntegrityConstraintFailedException extends Exception { 22 | 23 | @Serial 24 | private static final long serialVersionUID = -3178562817868475776L; 25 | 26 | /** 27 | * Creates a new instance without any reference to another error. 28 | */ 29 | public IntegrityConstraintFailedException() { 30 | } 31 | 32 | /** 33 | * Creates a new instance with a reference to the given cause. 34 | * 35 | * @param cause the cause of this error 36 | */ 37 | public IntegrityConstraintFailedException(Throwable cause) { 38 | super(cause); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/mongo/properties/MongoStringNestedMapEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mongo.properties; 10 | 11 | import sirius.db.mixing.Mapping; 12 | import sirius.db.mixing.Nested; 13 | import sirius.db.mixing.types.StringNestedMap; 14 | import sirius.db.mongo.MongoEntity; 15 | 16 | import java.time.LocalDateTime; 17 | 18 | public class MongoStringNestedMapEntity extends MongoEntity { 19 | 20 | public static class NestedEntity extends Nested { 21 | 22 | private String value1; 23 | private LocalDateTime value2; 24 | 25 | public String getValue1() { 26 | return value1; 27 | } 28 | 29 | public LocalDateTime getValue2() { 30 | return value2; 31 | } 32 | 33 | public NestedEntity withValue1(String value) { 34 | this.value1 = value; 35 | return this; 36 | } 37 | 38 | public NestedEntity withValue2(LocalDateTime value) { 39 | this.value2 = value; 40 | return this; 41 | } 42 | } 43 | 44 | public static final Mapping MAP = Mapping.named("map"); 45 | private final StringNestedMap map = new StringNestedMap<>(NestedEntity.class); 46 | 47 | public StringNestedMap getMap() { 48 | return map; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/test/resources/test.conf: -------------------------------------------------------------------------------- 1 | docker.file = ["src/test/resources/docker-db.yml"] 2 | 3 | jdbc { 4 | 5 | database { 6 | test { 7 | profile = "mariadb" 8 | user = "root" 9 | password = "root" 10 | database = "test" 11 | } 12 | clickhouse { 13 | profile = "clickhouse" 14 | user = "default" 15 | password = "secret" 16 | database = "test" 17 | } 18 | } 19 | 20 | } 21 | 22 | mixing { 23 | legacy { 24 | LegacyEntity { 25 | tableName = "banana" 26 | alias { 27 | firstname: name1 28 | lastname: name2 29 | composite_street: street 30 | } 31 | } 32 | } 33 | 34 | jdbc { 35 | mixing { 36 | dialect = "mariadb" 37 | database = "test" 38 | secondaryDatabase = "test" 39 | secondaryEnabled = true 40 | initSql = "CREATE DATABASE IF NOT EXISTS test" 41 | } 42 | clickhouse { 43 | dialect = "clickhouse" 44 | database = "clickhouse" 45 | initSql = "CREATE DATABASE IF NOT EXISTS test" 46 | } 47 | } 48 | } 49 | 50 | mongo { 51 | databases.mixing { 52 | hosts: "localhost" 53 | db: "test" 54 | } 55 | } 56 | 57 | elasticsearch { 58 | hosts = "localhost" 59 | suppressedRoutings = ["suppressedroutedtestentity"] 60 | } 61 | 62 | redis.pools.system.host = "localhost" 63 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/es/properties/ESNestedListEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.es.properties; 10 | 11 | import sirius.db.es.ElasticEntity; 12 | import sirius.db.mixing.Mapping; 13 | import sirius.db.mixing.Nested; 14 | import sirius.db.mixing.types.NestedList; 15 | 16 | public class ESNestedListEntity extends ElasticEntity { 17 | 18 | public static class NestedEntity extends Nested { 19 | 20 | public static final Mapping VALUE1 = Mapping.named("value1"); 21 | private String value1; 22 | public static final Mapping VALUE2 = Mapping.named("value2"); 23 | private String value2; 24 | 25 | public String getValue1() { 26 | return value1; 27 | } 28 | 29 | public String getValue2() { 30 | return value2; 31 | } 32 | 33 | public NestedEntity withValue1(String value) { 34 | this.value1 = value; 35 | return this; 36 | } 37 | 38 | public NestedEntity withValue2(String value) { 39 | this.value2 = value; 40 | return this; 41 | } 42 | } 43 | 44 | public static final Mapping LIST = Mapping.named("list"); 45 | private final NestedList list = new NestedList<>(NestedEntity.class); 46 | 47 | public NestedList getList() { 48 | return list; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/jdbc/batch/BatchSQLQuery.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc.batch; 10 | 11 | import sirius.db.jdbc.BaseSQLQuery; 12 | import sirius.db.jdbc.Row; 13 | import sirius.kernel.commons.Limit; 14 | import sirius.kernel.commons.Watch; 15 | 16 | import javax.annotation.Nullable; 17 | import java.sql.Blob; 18 | import java.sql.ResultSet; 19 | import java.sql.SQLException; 20 | import java.util.function.Predicate; 21 | 22 | /** 23 | * Represents an {@link BaseSQLQuery sql query} which can be used within a {@link BatchContext} by creating a {@link CustomQuery}. 24 | */ 25 | public class BatchSQLQuery extends BaseSQLQuery { 26 | 27 | protected CustomQuery query; 28 | 29 | protected BatchSQLQuery(CustomQuery customQuery) { 30 | this.query = customQuery; 31 | } 32 | 33 | @Override 34 | protected void doIterate(Predicate handler, @Nullable Limit limit) throws SQLException { 35 | Watch watch = Watch.start(); 36 | 37 | try (ResultSet resultSet = query.prepareStmt().executeQuery()) { 38 | query.average.addValue(watch.elapsedMillis()); 39 | processResultSet(handler, limit, resultSet); 40 | } 41 | } 42 | 43 | @Override 44 | protected void writeBlobToParameter(String name, Blob blob) throws SQLException { 45 | throw new UnsupportedOperationException(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/test/kotlin/sirius/db/mixing/properties/LocalDateTimePropertyTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.properties 10 | 11 | import org.junit.jupiter.api.Test 12 | import org.junit.jupiter.api.extension.ExtendWith 13 | import sirius.db.mixing.Mixing 14 | import sirius.kernel.SiriusExtension 15 | import sirius.kernel.commons.Value 16 | import sirius.kernel.di.std.Part 17 | import java.time.LocalDateTime 18 | import java.time.LocalTime 19 | import java.time.temporal.ChronoUnit 20 | import kotlin.test.assertEquals 21 | 22 | @ExtendWith(SiriusExtension::class) 23 | class LocalDateTimePropertyTest { 24 | @Test 25 | fun `local date time works when transformed`() { 26 | val dateTimeProperty = mixing.getDescriptor(DateEntity::class.java).getProperty(DateEntity.LOCAL_DATE_TIME) 27 | val localDateTime = LocalDateTime.now() 28 | val localDate = localDateTime.toLocalDate() 29 | 30 | assertEquals( 31 | localDateTime.truncatedTo(ChronoUnit.MILLIS), 32 | dateTimeProperty.transformValue(Value.of(localDateTime)) 33 | ) 34 | assertEquals( 35 | LocalDateTime.of(localDate, LocalTime.MIDNIGHT), 36 | dateTimeProperty.transformValue(Value.of(localDate)) 37 | ) 38 | } 39 | 40 | companion object { 41 | @Part 42 | private lateinit var mixing: Mixing 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/text/PatternReplaceProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.text; 10 | 11 | import java.util.regex.Pattern; 12 | 13 | /** 14 | * Replaces characters using a regular expression. 15 | */ 16 | public class PatternReplaceProcessor extends ChainableTokenProcessor { 17 | 18 | private static final Pattern CONTROL_CHARACTERS = Pattern.compile("\\p{Cntrl}"); 19 | 20 | private final Pattern pattern; 21 | private final String replacement; 22 | 23 | /** 24 | * Creates a new processor. 25 | * 26 | * @param pattern the pattern to match 27 | * @param replacement the replacement to use a definec by {@link java.util.regex.Matcher#replaceAll(String)} 28 | */ 29 | public PatternReplaceProcessor(Pattern pattern, String replacement) { 30 | this.pattern = pattern; 31 | this.replacement = replacement; 32 | } 33 | 34 | /** 35 | * Creates a new processor which replaces all control characters by whitespaces. 36 | * 37 | * @return the new processor which replaces all ANSI control characters. 38 | */ 39 | public static PatternReplaceProcessor createRemoveControlCharacters() { 40 | return new PatternReplaceProcessor(CONTROL_CHARACTERS, " "); 41 | } 42 | 43 | @Override 44 | public void accept(String token) { 45 | emit(pattern.matcher(token).replaceAll(replacement)); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/test/kotlin/sirius/db/es/properties/ElasticStringMapPropertyTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.es.properties 10 | 11 | import org.junit.jupiter.api.Test 12 | import org.junit.jupiter.api.extension.ExtendWith 13 | import sirius.db.es.Elastic 14 | import sirius.kernel.SiriusExtension 15 | import sirius.kernel.di.std.Part 16 | import kotlin.test.assertEquals 17 | import kotlin.test.assertFalse 18 | 19 | @ExtendWith(SiriusExtension::class) 20 | class ElasticStringMapPropertyTest { 21 | @Test 22 | fun `reading and writing works`() { 23 | val esStringMapEntity = ESStringMapEntity() 24 | esStringMapEntity.map.put("Test", "1").put("Foo", "2") 25 | elastic.update(esStringMapEntity) 26 | var resolved = elastic.refreshOrFail(esStringMapEntity) 27 | 28 | assertEquals(2,resolved.map.size()) 29 | assertEquals("1",resolved.map.get("Test").get()) 30 | assertEquals("2", resolved.map.get("Foo").get()) 31 | 32 | resolved.map.modify().remove("Test") 33 | elastic.update(resolved) 34 | resolved = elastic.refreshOrFail(esStringMapEntity) 35 | 36 | assertEquals(1,resolved.map.size()) 37 | assertFalse { resolved.map.containsKey("Test") } 38 | assertEquals("2",resolved.map.get("Foo").get()) 39 | } 40 | 41 | companion object { 42 | @Part 43 | private lateinit var elastic: Elastic 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mongo/constraints/MongoConstraint.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mongo.constraints; 10 | 11 | import org.bson.Document; 12 | import sirius.db.mixing.query.constraints.Constraint; 13 | 14 | /** 15 | * Defines a constraint which is accepted by {@link sirius.db.mongo.MongoQuery} and most probably generated by 16 | * {@link MongoFilterFactory}. 17 | * 18 | * @see sirius.db.mongo.QueryBuilder#FILTERS 19 | */ 20 | public class MongoConstraint extends Constraint { 21 | 22 | protected String key; 23 | protected Object object; 24 | 25 | /** 26 | * Creates a new constraint for the given field. 27 | * 28 | * @param key the field to filter 29 | * @param object the constraint most probably as BSON object or list 30 | */ 31 | public MongoConstraint(String key, Object object) { 32 | this.key = key; 33 | this.object = object; 34 | } 35 | 36 | @Override 37 | public void asString(StringBuilder builder) { 38 | builder.append(key); 39 | builder.append(": "); 40 | if (object instanceof Document document) { 41 | builder.append(document.toJson()); 42 | } else { 43 | builder.append(object.toString()); 44 | } 45 | } 46 | 47 | public String getKey() { 48 | return key; 49 | } 50 | 51 | public Object getObject() { 52 | return object; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/annotations/ComplexDelete.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.annotations; 10 | 11 | import java.lang.annotation.Documented; 12 | import java.lang.annotation.ElementType; 13 | import java.lang.annotation.Retention; 14 | import java.lang.annotation.RetentionPolicy; 15 | import java.lang.annotation.Target; 16 | 17 | /** 18 | * Determines if an{@link sirius.db.mixing.BaseEntity entity} is complex to delete. 19 | *

20 | * This can either be placed on the entity class or on any {@link BeforeDelete before delete handler} or 21 | * {@link AfterDelete after delete handler}. 22 | *

23 | * If the value is set to true (default), the entity is considered complex to delete. If false 24 | * is specified, it isn't considered complex to delete, even if there are cascadeing actions (setting fields in other 25 | * entities to null or deleting other entities). 26 | */ 27 | @Documented 28 | @Target({ElementType.TYPE, ElementType.METHOD}) 29 | @Retention(RetentionPolicy.RUNTIME) 30 | public @interface ComplexDelete { 31 | 32 | /** 33 | * Specifies if the entity is complex to delete. 34 | * 35 | * @return true to mark it as complex, false to mark it as non-complex even if there are cascade 36 | * delete actions. Note that this can only be specified on the entity class but not for cascade delete handlers 37 | */ 38 | boolean value() default true; 39 | } 40 | -------------------------------------------------------------------------------- /src/test/kotlin/sirius/db/mongo/properties/MongoStringMapPropertyTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mongo.properties 10 | 11 | import org.junit.jupiter.api.Test 12 | import org.junit.jupiter.api.extension.ExtendWith 13 | import sirius.db.mongo.Mango 14 | import sirius.db.mongo.Mongo 15 | import sirius.kernel.SiriusExtension 16 | import sirius.kernel.di.std.Part 17 | import kotlin.test.assertEquals 18 | import kotlin.test.assertFalse 19 | 20 | @ExtendWith(SiriusExtension::class) 21 | class MongoStringMapPropertyTest { 22 | @Test 23 | fun `reading and writing works`() { 24 | val test = MongoStringMapEntity() 25 | test.map.put("Test", "1").put("Foo", "2") 26 | mango.update(test) 27 | var resolved = mango.refreshOrFail(test) 28 | 29 | assertEquals(2, resolved.map.size()) 30 | assertEquals("1", resolved.map.get("Test").get()) 31 | assertEquals("2", resolved.map.get("Foo").get()) 32 | 33 | resolved.map.modify().remove("Test") 34 | mango.update(resolved) 35 | resolved = mango.refreshOrFail(test) 36 | 37 | assertEquals(1, resolved.map.size()) 38 | assertFalse { resolved.map.containsKey("Test") } 39 | assertEquals("2", resolved.map.get("Foo").get()) 40 | } 41 | 42 | companion object { 43 | @Part 44 | private lateinit var mango: Mango 45 | 46 | @Part 47 | private lateinit var mongo: Mongo 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/test/kotlin/sirius/db/text/BasicIndexTokenizerTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.text 10 | 11 | import org.junit.jupiter.api.Test 12 | import sirius.kernel.commons.Strings 13 | import kotlin.test.assertEquals 14 | 15 | /** 16 | * Tests the [BasicIndexTokenizer]. 17 | */ 18 | class BasicIndexTokenizerTest : TokenProcessorTest() { 19 | @Test 20 | fun tokenizing() { 21 | assertExactTokenizing( 22 | "email:test@test.local", 23 | "[email:test@test.local, email, test, local, email:test, test.local]" 24 | ) 25 | assertExactTokenizing( 26 | "max.mustermann@website.com", 27 | "[max.mustermann@website.com, max, mustermann, website, com, max.mustermann, website.com]" 28 | ) 29 | assertExactTokenizing("test-foobar", "[test-foobar, test, foobar]") 30 | assertExactTokenizing("test123@bla-bar.foo", "[test123@bla-bar.foo, test123, bla, bar, foo, bla-bar.foo]") 31 | } 32 | 33 | private fun assertExactTokenizing(input: String?, vararg tokens: String?) { 34 | val tokenizer = BasicIndexTokenizer() 35 | val result: MutableList = ArrayList() 36 | tokenizer.accept( 37 | input 38 | ) { outputTokens: List? -> 39 | result.add( 40 | "[" + Strings.join(outputTokens, ", ") + "]" 41 | ) 42 | } 43 | assertEquals(listOf(*tokens), result) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/KeyGenerator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db; 10 | 11 | import com.google.common.io.BaseEncoding; 12 | import sirius.kernel.commons.Hasher; 13 | import sirius.kernel.di.std.Register; 14 | 15 | import java.util.concurrent.ThreadLocalRandom; 16 | 17 | /** 18 | * Used to generate IDs or keys in distributed environments where numeric sequences aren't suitable. 19 | */ 20 | @Register(classes = KeyGenerator.class) 21 | public class KeyGenerator { 22 | 23 | private final String seed = Hasher.sha512().hashLong(System.nanoTime()).toString(); 24 | 25 | /** 26 | * Generates an unique random io. 27 | * 28 | * @return a random id in base 32 encoding 29 | */ 30 | public String generateId() { 31 | byte[] rndBytes = new byte[16]; 32 | ThreadLocalRandom.current().nextBytes(rndBytes); 33 | return BaseEncoding.base32Hex().encode(rndBytes).replace("=", ""); 34 | } 35 | 36 | /** 37 | * Generates a long unique id. 38 | *

39 | * Due to its length and secure generation pattern such IDs are suitable for auth tokens and the like. 40 | * 41 | * @return a newly generated secure unique id 42 | */ 43 | public String generateSecureId() { 44 | byte[] input = new byte[256]; 45 | ThreadLocalRandom.current().nextBytes(input); 46 | return Hasher.sha256().hash(seed).hashBytes(input).hashLong(System.nanoTime()).toHexString(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/test/kotlin/sirius/db/mongo/properties/MongoStringIntMapPropertyTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mongo.properties 10 | 11 | import org.junit.jupiter.api.Test 12 | import org.junit.jupiter.api.extension.ExtendWith 13 | import sirius.db.mongo.Mango 14 | import sirius.kernel.SiriusExtension 15 | import sirius.kernel.di.std.Part 16 | import kotlin.test.assertEquals 17 | import kotlin.test.assertFalse 18 | 19 | @ExtendWith(SiriusExtension::class) 20 | class MongoStringIntMapPropertyTe { 21 | @Test 22 | fun `read and write a string int map works`() { 23 | val mongoStringIntMapEntity = MongoStringIntMapEntity() 24 | mongoStringIntMapEntity.map.put("Test", 1).put("Foo", 2).put("Test", 3) 25 | mango.update(mongoStringIntMapEntity) 26 | var resolved = mango.refreshOrFail(mongoStringIntMapEntity) 27 | 28 | assertEquals(2, resolved.map.size()) 29 | assertEquals(3, resolved.map.get("Test").get()) 30 | assertEquals(2, resolved.map.get("Foo").get()) 31 | 32 | resolved.map.modify().remove("Test") 33 | mango.update(resolved) 34 | resolved = mango.refreshOrFail(mongoStringIntMapEntity) 35 | 36 | assertEquals(1, resolved.map.size()) 37 | assertFalse { resolved.map.containsKey("Test") } 38 | assertEquals(2, resolved.map.get("Foo").get()) 39 | } 40 | 41 | companion object { 42 | @Part 43 | private lateinit var mango: Mango 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mongo/types/MongoRefList.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mongo.types; 10 | 11 | import sirius.db.mixing.ContextInfo; 12 | import sirius.db.mixing.types.BaseEntityRef; 13 | import sirius.db.mixing.types.BaseEntityRefList; 14 | import sirius.db.mongo.Mango; 15 | import sirius.db.mongo.MongoEntity; 16 | import sirius.kernel.di.std.Part; 17 | 18 | import java.util.Optional; 19 | 20 | /** 21 | * Represents a list of {@link MongoEntity entities} being referenced by id. 22 | * 23 | * @param the type of entities being referenced 24 | */ 25 | public class MongoRefList extends BaseEntityRefList> { 26 | 27 | @Part 28 | private static Mango mango; 29 | 30 | /** 31 | * Creates a new list for the given type and delete handler. 32 | * 33 | * @param type the type of entities to store in the list 34 | * @param deleteHandler the behaviour when one of the stored entities is deleted. Note that 35 | * {@link sirius.db.mixing.types.BaseEntityRef.OnDelete#SET_NULL} will remove the id from the 36 | * list instead of inserting a null. 37 | */ 38 | public MongoRefList(Class type, BaseEntityRef.OnDelete deleteHandler) { 39 | super(type, deleteHandler); 40 | } 41 | 42 | @Override 43 | protected Optional resolve(String id, ContextInfo... context) { 44 | return mango.find(type, id); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/es/types/ElasticRefList.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.es.types; 10 | 11 | import sirius.db.es.Elastic; 12 | import sirius.db.es.ElasticEntity; 13 | import sirius.db.mixing.ContextInfo; 14 | import sirius.db.mixing.types.BaseEntityRef; 15 | import sirius.db.mixing.types.BaseEntityRefList; 16 | import sirius.kernel.di.std.Part; 17 | 18 | import java.util.Optional; 19 | 20 | /** 21 | * Represents a list of {@link ElasticEntity entities} being referenced by id. 22 | * 23 | * @param the type of entities being referenced 24 | */ 25 | public class ElasticRefList extends BaseEntityRefList> { 26 | 27 | @Part 28 | private static Elastic elastic; 29 | 30 | /** 31 | * Creates a new list for the given type and delete handler. 32 | * 33 | * @param type the type of entities to store in the list 34 | * @param deleteHandler the behaviour when one of the stored entities is deleted. Note that 35 | * {@link sirius.db.mixing.types.BaseEntityRef.OnDelete#SET_NULL} will remove the id from the 36 | * list instead of inserting a null. 37 | */ 38 | public ElasticRefList(Class type, BaseEntityRef.OnDelete deleteHandler) { 39 | super(type, deleteHandler); 40 | } 41 | 42 | @Override 43 | protected Optional resolve(String id, ContextInfo... context) { 44 | return elastic.find(type, id, context); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/test/java/sirius/db/jdbc/SmartQueryTest.java: -------------------------------------------------------------------------------- 1 | package sirius.db.jdbc; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | import sirius.db.jdbc.constraints.SQLConstraint; 6 | import sirius.db.mixing.Mapping; 7 | 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | 11 | public class SmartQueryTest { 12 | @Test 13 | public void testCreateSqlConstraintForSortingColumn_withPreviousColumns_returnValidSqlQuery() { 14 | SmartQuery query = new SmartQuery<>(null, null); 15 | Map previousSortingColumns = new HashMap<>(); 16 | previousSortingColumns.put(SmartQueryTestSortingEntity.VALUE_ONE, "value1"); 17 | previousSortingColumns.put(SmartQueryTestSortingEntity.VALUE_TWO, "value2"); 18 | SQLConstraint constraint = query.createSqlConstraintForSortingColumn(true, 19 | SmartQueryTestSortingEntity.ID, 20 | "1", 21 | previousSortingColumns); 22 | Assert.assertEquals("((valueOne = value1 AND valueTwo = value2) AND id > 1)", constraint.toString()); 23 | } 24 | 25 | @Test 26 | public void testCreateSqlConstraintForSortingColumn_withoutPreviousColumns_returnValidSqlQuery() { 27 | SmartQuery query = new SmartQuery<>(null, null); 28 | Map previousSortingColumns = new HashMap<>(); 29 | SQLConstraint constraint = query.createSqlConstraintForSortingColumn(true, 30 | SmartQueryTestSortingEntity.ID, 31 | "1", 32 | previousSortingColumns); 33 | Assert.assertEquals("id > 1", constraint.toString()); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/test/kotlin/sirius/db/es/properties/ElasticStringListPropertyTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.es.properties 10 | 11 | import org.junit.jupiter.api.Test 12 | import org.junit.jupiter.api.extension.ExtendWith 13 | import sirius.db.es.Elastic 14 | import sirius.kernel.SiriusExtension 15 | import sirius.kernel.di.std.Part 16 | import kotlin.test.assertEquals 17 | import kotlin.test.assertFalse 18 | import kotlin.test.assertTrue 19 | 20 | @ExtendWith(SiriusExtension::class) 21 | class ElasticStringListPropertyTest { 22 | @Test 23 | fun `reading and writing works for Elasticsearch`() { 24 | val test = ESStringListEntity() 25 | test.list.add("Test").add("Hello").add("World") 26 | elastic.update(test) 27 | var resolved = elastic.refreshOrFail(test) 28 | 29 | assertEquals(3, resolved.list.size()) 30 | assertTrue { resolved.list.contains("Test") } 31 | assertTrue { resolved.list.contains("Hello") } 32 | assertTrue { resolved.list.contains("World") } 33 | 34 | resolved.list.modify().remove("World") 35 | elastic.update(resolved) 36 | resolved = elastic.refreshOrFail(test) 37 | 38 | assertEquals(2, resolved.list.size()) 39 | assertTrue { resolved.list.contains("Test") } 40 | assertTrue { resolved.list.contains("Hello") } 41 | assertFalse { resolved.list.contains("World") } 42 | } 43 | 44 | companion object { 45 | @Part 46 | private lateinit var elastic: Elastic 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/annotations/ValidatedBy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.annotations; 10 | 11 | import sirius.db.mixing.PropertyValidator; 12 | 13 | import java.lang.annotation.Documented; 14 | import java.lang.annotation.ElementType; 15 | import java.lang.annotation.Retention; 16 | import java.lang.annotation.RetentionPolicy; 17 | import java.lang.annotation.Target; 18 | 19 | /** 20 | * Allows to specify a custom {@link PropertyValidator} for a property. 21 | *

22 | * This validator will be invoked before the property is written to the database. 23 | * It can be used to perform custom validation that is the same for fields across multiple entities. 24 | */ 25 | @Documented 26 | @Retention(RetentionPolicy.RUNTIME) 27 | @Target(ElementType.FIELD) 28 | public @interface ValidatedBy { 29 | 30 | /** 31 | * Specifies the validator to use. 32 | */ 33 | Class value(); 34 | 35 | /** 36 | * Specifies if the validator should be invoked in strict mode. Strict mode means that the validator gets 37 | * always executed. Non-strict mode means that the validator is only executed if the property value has changed. 38 | *

39 | * The non-strict mode might be useful e.g. for properties that have persisted legacy data which is not valid 40 | * and when validity is not mandatory. 41 | * 42 | * @return true for strict validation, false otherwise 43 | */ 44 | boolean strictValidation() default true; 45 | } 46 | -------------------------------------------------------------------------------- /src/test/kotlin/sirius/db/es/properties/ElasticStringListMapPropertyTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.es.properties 10 | 11 | import org.junit.jupiter.api.Test 12 | import org.junit.jupiter.api.extension.ExtendWith 13 | import sirius.db.es.Elastic 14 | import sirius.kernel.SiriusExtension 15 | import sirius.kernel.di.std.Part 16 | import kotlin.test.assertEquals 17 | import kotlin.test.assertFalse 18 | import kotlin.test.assertTrue 19 | 20 | @ExtendWith(SiriusExtension::class) 21 | class ElasticStringListMapPropertyTest { 22 | @Test 23 | fun `reading and writing works`() { 24 | val test = ESStringListMapEntity() 25 | test.map.add("Test", "1").add("Foo", "2").add("Test", "3") 26 | elastic.update(test) 27 | var resolved = elastic.refreshOrFail(test) 28 | 29 | assertEquals(2, resolved.map.size()) 30 | assertTrue { resolved.map.contains("Test", "1") } 31 | assertTrue { resolved.map.contains("Test", "3") } 32 | assertTrue { resolved.map.contains("Foo", "2") } 33 | 34 | resolved.map.remove("Test", "1") 35 | elastic.update(resolved) 36 | resolved = elastic.refreshOrFail(test) 37 | 38 | assertEquals(2, resolved.map.size()) 39 | assertFalse { resolved.map.contains("Test", "1") } 40 | assertTrue { resolved.map.contains("Test", "3") } 41 | assertTrue { resolved.map.contains("Foo", "2") } 42 | } 43 | 44 | companion object { 45 | @Part 46 | private lateinit var elastic: Elastic 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/jdbc/constraints/FieldOperator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc.constraints; 10 | 11 | import sirius.db.jdbc.SmartQuery; 12 | import sirius.kernel.commons.Strings; 13 | import sirius.kernel.commons.Tuple; 14 | 15 | import java.util.List; 16 | 17 | /** 18 | * Represents a simple field operator as constraint. 19 | */ 20 | class FieldOperator extends SQLConstraint { 21 | 22 | private final CompoundValue leftHandSide; 23 | private final CompoundValue rightHandSide; 24 | private final String operator; 25 | 26 | protected FieldOperator(CompoundValue leftHandSide, String operator, CompoundValue rightHandSide) { 27 | this.leftHandSide = leftHandSide; 28 | this.operator = operator; 29 | this.rightHandSide = rightHandSide; 30 | } 31 | 32 | @Override 33 | public void appendSQL(SmartQuery.Compiler compiler) { 34 | Tuple> compiledLhs = leftHandSide.compileExpression(compiler); 35 | Tuple> compiledRhs = rightHandSide.compileExpression(compiler); 36 | compiler.getWHEREBuilder().append(Strings.join(" ", compiledLhs.getFirst(), operator, compiledRhs.getFirst())); 37 | compiledLhs.getSecond().forEach(compiler::addParameter); 38 | compiledRhs.getSecond().forEach(compiler::addParameter); 39 | } 40 | 41 | @Override 42 | public void asString(StringBuilder builder) { 43 | builder.append(Strings.join(" ", leftHandSide.toString(), operator, rightHandSide.toString())); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mixing/annotations/TranslationSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mixing.annotations; 10 | 11 | import java.lang.annotation.Documented; 12 | import java.lang.annotation.ElementType; 13 | import java.lang.annotation.Retention; 14 | import java.lang.annotation.RetentionPolicy; 15 | import java.lang.annotation.Target; 16 | 17 | /** 18 | * Can be placed on a {@link sirius.db.mixing.BaseEntity entity} to use an alternative class when fetching i18n keys. 19 | *

20 | * By default {@link sirius.db.mixing.EntityDescriptor} and {@link sirius.db.mixing.Property} use the class which 21 | * contains a field or the entity class itself when building property keys. Using this annotation, another class can 22 | * be used to provide the i18n keys. 23 | *

24 | * This is mostly used by database independent frameworks. These define a common interface with shared 25 | * {@link sirius.db.mixing.Mapping mappings} which is then implemented by subclasses of the respective entity types. 26 | * To also share the i18n keys, the database specific entities can delegate all i18n keys by using the interface 27 | * as translation source. 28 | */ 29 | @Documented 30 | @Target(ElementType.TYPE) 31 | @Retention(RetentionPolicy.RUNTIME) 32 | public @interface TranslationSource { 33 | 34 | /** 35 | * Contains the class which is then used to compute the i18n keys of the annotated entity class. 36 | * 37 | * @return the class which is used to provide common names for i18n keys 38 | */ 39 | Class value(); 40 | } 41 | -------------------------------------------------------------------------------- /src/test/kotlin/sirius/db/es/properties/ElasticStringBooleanMapPropertyTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.es.properties 10 | 11 | import org.junit.jupiter.api.Test 12 | import org.junit.jupiter.api.extension.ExtendWith 13 | import sirius.db.es.Elastic 14 | import sirius.kernel.SiriusExtension 15 | import sirius.kernel.di.std.Part 16 | import kotlin.test.assertEquals 17 | import kotlin.test.assertFalse 18 | import kotlin.test.assertTrue 19 | 20 | @ExtendWith(SiriusExtension::class) 21 | class ElasticStringBooleanMapPropertyTest { 22 | @Test 23 | fun `read and write a string boolean map works`() { 24 | val test = ESStringBooleanMapEntity() 25 | test.map.put("a", true).put("b", false).put("c", true).put("d", false) 26 | elastic.update(test) 27 | var resolved = elastic.refreshOrFail(test) 28 | 29 | assertEquals(4, resolved.map.size()) 30 | 31 | assertTrue { resolved.map.get("a").get() } 32 | assertFalse { resolved.map.get("b").get() } 33 | assertTrue { resolved.map.get("c").get() } 34 | assertFalse { resolved.map.get("d").get() } 35 | 36 | resolved.map.modify().remove("a") 37 | elastic.update(resolved) 38 | resolved = elastic.refreshOrFail(test) 39 | 40 | assertEquals(3, resolved.map.size()) 41 | 42 | assertFalse { resolved.map.containsKey("a") } 43 | assertTrue { resolved.map.get("c").get() } 44 | } 45 | 46 | companion object { 47 | @Part 48 | private lateinit var elastic: Elastic 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/jdbc/TranslationState.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.jdbc; 10 | 11 | import sirius.db.jdbc.constraints.Exists; 12 | import sirius.db.mixing.EntityDescriptor; 13 | import sirius.kernel.commons.Tuple; 14 | 15 | import java.util.Map; 16 | 17 | /** 18 | * Keeps track of the internal JOIN and column translation state of a {@link SmartQuery.Compiler}. 19 | *

20 | * This is mainly used by constraints which generate internal JOINS like {@link Exists}. 21 | */ 22 | public class TranslationState { 23 | 24 | private final EntityDescriptor ed; 25 | private final String defaultAlias; 26 | private final StringBuilder joins; 27 | private final Map> joinTable; 28 | 29 | protected TranslationState(EntityDescriptor ed, 30 | String defaultAlias, 31 | StringBuilder joins, 32 | Map> joinTable) { 33 | 34 | this.ed = ed; 35 | this.defaultAlias = defaultAlias; 36 | this.joins = joins; 37 | this.joinTable = joinTable; 38 | } 39 | 40 | protected EntityDescriptor getEd() { 41 | return ed; 42 | } 43 | 44 | protected String getDefaultAlias() { 45 | return defaultAlias; 46 | } 47 | 48 | protected StringBuilder getJoins() { 49 | return joins; 50 | } 51 | 52 | protected Map> getJoinTable() { 53 | return joinTable; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/sirius/db/mongo/facets/MongoFacet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Made with all the love in the world 3 | * by scireum in Remshalden, Germany 4 | * 5 | * Copyright by scireum GmbH 6 | * http://www.scireum.de - info@scireum.de 7 | */ 8 | 9 | package sirius.db.mongo.facets; 10 | 11 | import com.mongodb.DBObject; 12 | import sirius.db.mixing.EntityDescriptor; 13 | import sirius.db.mongo.Doc; 14 | 15 | import java.util.List; 16 | import java.util.function.BiConsumer; 17 | 18 | /** 19 | * Describes a facet which can extend the $facet section of the aggregation pipeline generated by 20 | * {@link sirius.db.mongo.Finder#executeFacets(EntityDescriptor, List)}. 21 | */ 22 | public abstract class MongoFacet { 23 | 24 | protected String name; 25 | 26 | /** 27 | * Creates a new facet with the given name. 28 | * 29 | * @param name the name of the facet, which should be unique within a query 30 | */ 31 | protected MongoFacet(String name) { 32 | this.name = name; 33 | } 34 | 35 | public String getName() { 36 | return name; 37 | } 38 | 39 | /** 40 | * Emits a BSON object to be placed into the $facet stage of the generated pipeline. 41 | * 42 | * @param descriptor the descriptor of the entity to be queried - can be used to perform field renamings 43 | * @param facetConsumer the consumer which adds the generated facets to the $facet stage 44 | */ 45 | public abstract void emitFacets(EntityDescriptor descriptor, BiConsumer facetConsumer); 46 | 47 | /** 48 | * Digests the facet result provided by the database. 49 | * 50 | * @param result the document to digest 51 | */ 52 | public abstract void digest(Doc result); 53 | } 54 | --------------------------------------------------------------------------------