(
&self,
request: RegisterServerRequest,
now_unix_ms: i64,
)
| 180 | } |
| 181 | |
| 182 | async fn create_post_migration_indexes(&self) -> Result<()> { |
| 183 | sqlx::raw_sql( |
| 184 | "CREATE INDEX IF NOT EXISTS idx_servers_app_version ON servers(app_name, actver, version_tag);", |
| 185 | ) |
| 186 | .execute(&self.pool) |
| 187 | .await |
| 188 | .context("creating post-migration indexes")?; |
| 189 | sqlx::raw_sql( |
| 190 | "CREATE UNIQUE INDEX IF NOT EXISTS idx_servers_token_hash ON servers(token_hash) WHERE token_hash IS NOT NULL;", |
| 191 | ) |
| 192 | .execute(&self.pool) |
| 193 | .await |
| 194 | .context("creating unique server token index; duplicate token hashes require operator cleanup")?; |
| 195 | Ok(()) |
| 196 | } |
| 197 | |
| 198 | /// Current column names of the `servers` table, per dialect. |
| 199 | async fn server_columns(&self) -> Result<Vec<String>> { |
| 200 | let query = match self.dialect { |
| 201 | Dialect::Sqlite => "SELECT name FROM pragma_table_info('servers')", |
| 202 | // column_name is Postgres' internal `name` type, which the sqlx Any driver can't |
| 203 | // decode — cast to text so it reads back as a plain string. |
| 204 | Dialect::Postgres => { |
| 205 | "SELECT column_name::text FROM information_schema.columns WHERE table_name = 'servers'" |
| 206 | } |
| 207 | }; |
| 208 | let rows = sqlx::query(query) |
| 209 | .fetch_all(&self.pool) |
| 210 | .await |
| 211 | .context("reading servers columns")?; |
| 212 | Ok(rows |
| 213 | .iter() |
| 214 | .filter_map(|row| row.try_get::<String, _>(0).ok()) |
| 215 | .collect()) |
| 216 | } |
| 217 | |
| 218 | fn schema(&self) -> &'static str { |
| 219 | match self.dialect { |
| 220 | Dialect::Sqlite => SCHEMA_SQLITE, |
| 221 | Dialect::Postgres => SCHEMA_POSTGRES, |
| 222 | } |
| 223 | } |
| 224 | |
| 225 | /// Adapt a query body written with SQLite-style `?` placeholders to the active dialect. |
| 226 | /// SQLite keeps `?`; Postgres needs `$1..$N`. The sqlx `Any` driver does not translate |
| 227 | /// placeholders, so a `?` reaches Postgres verbatim and is rejected |
| 228 | /// ("syntax error at end of input"). |
| 229 | fn bind_sql<'a>(&self, query: &'a str) -> Cow<'a, str> { |
| 230 | rewrite_placeholders(self.dialect, query) |
| 231 | } |
| 232 | |
| 233 | pub async fn register( |
| 234 | &self, |
| 235 | request: RegisterServerRequest, |
| 236 | now_unix_ms: i64, |
| 237 | ) -> Result<DirectoryServerRecord> { |
| 238 | self.register_record(request, now_unix_ms, None) |
| 239 | .await? |
nothing calls this directly
no test coverage detected