6363
6464class Appwrite extends Destination
6565{
66+ public const ON_DUPLICATE_FAIL = 'fail ' ;
67+ public const ON_DUPLICATE_SKIP = 'skip ' ;
68+ public const ON_DUPLICATE_UPSERT = 'upsert ' ;
69+
70+ /**
71+ * @var array<string>
72+ */
73+ public const ON_DUPLICATES = [
74+ self ::ON_DUPLICATE_FAIL ,
75+ self ::ON_DUPLICATE_SKIP ,
76+ self ::ON_DUPLICATE_UPSERT ,
77+ ];
78+
6679 protected Client $ client ;
6780 protected string $ project ;
6881
@@ -92,8 +105,7 @@ class Appwrite extends Destination
92105 * @param UtopiaDatabase $dbForProject
93106 * @param callable(UtopiaDocument $database):UtopiaDatabase $getDatabasesDB
94107 * @param array<array<string, mixed>> $collectionStructure
95- * @param bool $overwrite When true, replace existing rows by calling upsertDocuments instead of createDocuments.
96- * @param bool $skip When true, silently ignore duplicate-id rows by wrapping createDocuments in skipDuplicates.
108+ * @param string $onDuplicate Behavior when a row with an existing $id is encountered. One of ON_DUPLICATE_FAIL (abort), ON_DUPLICATE_SKIP (silently ignore), ON_DUPLICATE_UPSERT (replace existing).
97109 */
98110 public function __construct (
99111 string $ project ,
@@ -102,9 +114,14 @@ public function __construct(
102114 protected UtopiaDatabase $ dbForProject ,
103115 callable $ getDatabasesDB ,
104116 protected array $ collectionStructure ,
105- protected bool $ overwrite = false ,
106- protected bool $ skip = false ,
117+ protected string $ onDuplicate = self ::ON_DUPLICATE_FAIL ,
107118 ) {
119+ if (!\in_array ($ onDuplicate , self ::ON_DUPLICATES , true )) {
120+ throw new \InvalidArgumentException (
121+ "Invalid onDuplicate value ' {$ onDuplicate }'. Must be one of: " . \implode (', ' , self ::ON_DUPLICATES )
122+ );
123+ }
124+
108125 $ this ->project = $ project ;
109126 $ this ->endpoint = $ endpoint ;
110127 $ this ->key = $ key ;
@@ -1073,25 +1090,19 @@ protected function createRecord(Row $resource, bool $isLast): bool
10731090 }
10741091 $ collectionId = 'database_ ' . $ databaseInternalId . '_collection_ ' . $ tableInternalId ;
10751092
1076- if ($ this ->overwrite ) {
1077- // Replace existing rows with the imported values. Upsert naturally
1078- // handles duplicates so skipDuplicates is unnecessary here.
1079- $ dbForDatabases ->skipRelationshipsExistCheck (
1093+ match ($ this ->onDuplicate ) {
1094+ self ::ON_DUPLICATE_UPSERT => $ dbForDatabases ->skipRelationshipsExistCheck (
10801095 fn () => $ dbForDatabases ->upsertDocuments ($ collectionId , $ this ->rowBuffer )
1081- );
1082- } elseif ($ this ->skip ) {
1083- // Silently ignore duplicates via the adapter-level INSERT IGNORE equivalent.
1084- $ dbForDatabases ->skipDuplicates (
1096+ ),
1097+ self ::ON_DUPLICATE_SKIP => $ dbForDatabases ->skipDuplicates (
10851098 fn () => $ dbForDatabases ->skipRelationshipsExistCheck (
10861099 fn () => $ dbForDatabases ->createDocuments ($ collectionId , $ this ->rowBuffer )
10871100 )
1088- );
1089- } else {
1090- // Default: fail fast on duplicate ids (original behavior).
1091- $ dbForDatabases ->skipRelationshipsExistCheck (
1101+ ),
1102+ self ::ON_DUPLICATE_FAIL => $ dbForDatabases ->skipRelationshipsExistCheck (
10921103 fn () => $ dbForDatabases ->createDocuments ($ collectionId , $ this ->rowBuffer )
1093- );
1094- }
1104+ ),
1105+ };
10951106
10961107 } finally {
10971108 $ this ->rowBuffer = [];
0 commit comments