83 union\n\ |
84 union\n\ |
84 select\n\ |
85 select\n\ |
85 r.resource_id,\n\ |
86 r.resource_id,\n\ |
86 r.parent_id,\n\ |
87 r.parent_id,\n\ |
87 p.fullpath || '/' || r.nodename,\n\ |
88 p.fullpath || '/' || r.nodename,\n\ |
|
89 r.resoid,\n\ |
88 r.iscollection,\n\ |
90 r.iscollection,\n\ |
89 r.lastmodified,\n\ |
91 r.lastmodified,\n\ |
90 r.creationdate,\n\ |
92 r.creationdate,\n\ |
91 r.contentlength,\n\ |
93 r.contentlength,\n\ |
92 p.pathelm,\n\ |
94 p.pathelm,\n\ |
93 p.pathdepth + 1\n\ |
95 p.pathdepth + 1\n\ |
94 from Resource r\n\ |
96 from Resource r\n\ |
95 inner join resolvepath p on r.parent_id = p.resource_id\n\ |
97 inner join resolvepath p on r.parent_id = p.resource_id\n\ |
96 where p.pathelm[p.pathdepth+1] = r.nodename\n\ |
98 where p.pathelm[p.pathdepth+1] = r.nodename\n\ |
97 )\n\ |
99 )\n\ |
98 select resource_id, parent_id, fullpath, iscollection from resolvepath\n\ |
100 select resource_id, parent_id, fullpath, resoid, iscollection, lastmodified, creationdate, contentlength from resolvepath\n\ |
99 where fullpath = $1 ;"; |
101 where fullpath = $1 ;"; |
100 |
102 |
101 // Same as sql_resolve_path, but it returns the root collection |
103 // Same as sql_resolve_path, but it returns the root collection |
102 // params: $1: path string (should be '/') |
104 // params: $1: path string (should be '/') |
103 static const char *sql_get_root = "select resource_id, parent_id, $1 as fullpath, true as iscollection, lastmodified, creationdate, contentlength from Resource where parent_id is null;"; |
105 static const char *sql_get_root = "select resource_id, parent_id, $1 as fullpath, resoid, true as iscollection, lastmodified, creationdate, contentlength from Resource where parent_id is null;"; |
104 |
106 |
105 // Get all children of a specific collection |
107 // Get all children of a specific collection |
106 // params: $1: parent resource_id |
108 // params: $1: parent resource_id |
107 static const char *sql_get_children = "select resource_id, nodename, iscollection, lastmodified, creationdate, contentlength from Resource where parent_id = $1;"; |
109 static const char *sql_get_children = "select resource_id, nodename, iscollection, lastmodified, creationdate, contentlength from Resource where parent_id = $1;"; |
108 |
110 |
153 int pg_resolve_path( |
155 int pg_resolve_path( |
154 VFSContext *ctx, |
156 VFSContext *ctx, |
155 const char *path, |
157 const char *path, |
156 int64_t *parent_id, |
158 int64_t *parent_id, |
157 int64_t *resource_id, |
159 int64_t *resource_id, |
|
160 Oid *oid, |
158 const char **resource_name, |
161 const char **resource_name, |
159 WSBool *iscollection, |
162 WSBool *iscollection, |
160 struct stat *s) |
163 struct stat *s) |
161 { |
164 { |
162 // basic path validation |
165 // basic path validation |
202 //int nfields = PQnfields(result); |
205 //int nfields = PQnfields(result); |
203 int nrows = PQntuples(result); |
206 int nrows = PQntuples(result); |
204 if(nrows == 1) { |
207 if(nrows == 1) { |
205 char *resource_id_str = PQgetvalue(result, 0, 0); |
208 char *resource_id_str = PQgetvalue(result, 0, 0); |
206 char *parent_id_str = PQgetvalue(result, 0, 1); |
209 char *parent_id_str = PQgetvalue(result, 0, 1); |
207 char *iscol = PQgetvalue(result, 0, 3); |
210 char *iscol = PQgetvalue(result, 0, 4); |
208 char *lastmodified = PQgetvalue(result, 0, 4); |
211 char *lastmodified = PQgetvalue(result, 0, 5); |
209 char *creationdate = PQgetvalue(result, 0, 5); |
212 char *creationdate = PQgetvalue(result, 0, 6); |
210 char *contentlength = PQgetvalue(result, 0, 6); |
213 char *contentlength = PQgetvalue(result, 0, 7); |
211 if(resource_id_str && parent_id_str) { |
214 if(resource_id_str && parent_id_str) { |
212 if(util_strtoint(resource_id_str, resource_id)) { |
215 if(util_strtoint(resource_id_str, resource_id)) { |
213 ret = 0; // success |
216 ret = 0; // success |
214 } |
217 } |
215 // optionally get parent_id |
218 // optionally get parent_id |
216 util_strtoint(parent_id_str, parent_id); |
219 util_strtoint(parent_id_str, parent_id); |
|
220 } |
|
221 |
|
222 if(oid) { |
|
223 char *resoid = PQgetvalue(result, 0, 3); |
|
224 int64_t roid; |
|
225 if(resoid && util_strtoint(resoid, &roid)) { |
|
226 *oid = roid; |
|
227 } |
217 } |
228 } |
218 |
229 |
219 if(iscollection && iscol) { |
230 if(iscollection && iscol) { |
220 *iscollection = iscol[0] == 't' ? TRUE : FALSE; |
231 *iscollection = iscol[0] == 't' ? TRUE : FALSE; |
221 } |
232 } |
257 } |
271 } |
258 |
272 |
259 /* -------------------------- VFS functions -------------------------- */ |
273 /* -------------------------- VFS functions -------------------------- */ |
260 |
274 |
261 SYS_FILE pg_vfs_open(VFSContext *ctx, const char *path, int oflags) { |
275 SYS_FILE pg_vfs_open(VFSContext *ctx, const char *path, int oflags) { |
|
276 VFS *vfs = ctx->vfs; |
|
277 PgVFS *pg = vfs->instance; |
|
278 |
262 const char *resname; |
279 const char *resname; |
263 int64_t resource_id, parent_id; |
280 int64_t resource_id, parent_id; |
264 resource_id = -1; |
281 resource_id = -1; |
265 parent_id = -1; |
282 parent_id = -1; |
266 WSBool iscollection; |
283 WSBool iscollection; |
267 struct stat s; |
284 struct stat s; |
268 if(pg_resolve_path(ctx, path, &parent_id, &resource_id, &resname, &iscollection, &s)) { |
285 Oid oid = 0; |
|
286 if(pg_resolve_path(ctx, path, &parent_id, &resource_id, &oid, &resname, &iscollection, &s)) { |
269 return NULL; |
287 return NULL; |
270 } |
288 } |
271 |
289 |
272 VFSFile *file = pool_malloc(ctx->pool, sizeof(VFSFile)); |
290 VFSFile *file = pool_malloc(ctx->pool, sizeof(VFSFile)); |
273 if(!file) { |
291 if(!file) { |
277 if(!pgfile) { |
295 if(!pgfile) { |
278 pool_free(ctx->pool, file); |
296 pool_free(ctx->pool, file); |
279 return NULL; |
297 return NULL; |
280 } |
298 } |
281 |
299 |
|
300 int fd = -1; |
|
301 if(!iscollection) { |
|
302 if (PQstatus(pg->connection) != CONNECTION_OK) { |
|
303 fd = -2; |
|
304 } |
|
305 |
|
306 int lo_mode = INV_READ; // TODO: evaluate oflags |
|
307 fd = lo_open(pg->connection, oid, lo_mode); |
|
308 } |
|
309 |
282 pgfile->iscollection = iscollection; |
310 pgfile->iscollection = iscollection; |
283 pgfile->resource_id = resource_id; |
311 pgfile->resource_id = resource_id; |
284 pgfile->parent_id = parent_id; |
312 pgfile->parent_id = parent_id; |
|
313 pgfile->oid = oid; |
|
314 pgfile->fd = fd; |
285 pgfile->s = s; |
315 pgfile->s = s; |
286 |
316 |
287 file->ctx = ctx; |
317 file->ctx = ctx; |
288 file->io = iscollection ? &pg_vfs_io_class : &pg_vfs_io_class; |
318 file->io = iscollection ? &pg_vfs_io_class : &pg_vfs_io_class; |
289 file->fd = -1; |
319 file->fd = -1; |
294 |
324 |
295 int pg_vfs_stat(VFSContext *ctx, const char *path, struct stat *buf) { |
325 int pg_vfs_stat(VFSContext *ctx, const char *path, struct stat *buf) { |
296 int64_t parent_id, resource_id; |
326 int64_t parent_id, resource_id; |
297 const char *resname; |
327 const char *resname; |
298 WSBool iscollection; |
328 WSBool iscollection; |
299 return pg_resolve_path(ctx, path, &parent_id, &resource_id, &resname, &iscollection, buf); |
329 return pg_resolve_path(ctx, path, &parent_id, &resource_id, NULL, &resname, &iscollection, buf); |
300 } |
330 } |
301 |
331 |
302 int pg_vfs_fstat(VFSContext *ctx, SYS_FILE fd, struct stat *buf) { |
332 int pg_vfs_fstat(VFSContext *ctx, SYS_FILE fd, struct stat *buf) { |
303 PgFile *pgfile = fd->data; |
333 PgFile *pgfile = fd->data; |
304 memcpy(buf, &pgfile->s, sizeof(struct stat)); |
334 memcpy(buf, &pgfile->s, sizeof(struct stat)); |
357 |
387 |
358 |
388 |
359 /* -------------------------- VFS_IO functions -------------------------- */ |
389 /* -------------------------- VFS_IO functions -------------------------- */ |
360 |
390 |
361 ssize_t pg_vfs_io_read(SYS_FILE fd, void *buf, size_t nbyte) { |
391 ssize_t pg_vfs_io_read(SYS_FILE fd, void *buf, size_t nbyte) { |
|
392 PgVFS *pgvfs = fd->ctx->vfs->instance; |
|
393 PgFile *pg = fd->data; |
|
394 return lo_read(pgvfs->connection, pg->fd, buf, nbyte); |
|
395 } |
|
396 |
|
397 ssize_t pg_vfs_io_write(SYS_FILE fd, const void *buf, size_t nbyte) { |
|
398 PgVFS *pgvfs = fd->ctx->vfs->instance; |
|
399 |
362 return 0; |
400 return 0; |
363 } |
401 } |
364 |
402 |
365 ssize_t pg_vfs_io_write(SYS_FILE fd, const void *buf, size_t nbyte) { |
403 ssize_t pg_vfs_io_pread(SYS_FILE fd, void *buf, size_t nbyte, off_t offset) { |
|
404 PgVFS *pgvfs = fd->ctx->vfs->instance; |
|
405 |
366 return 0; |
406 return 0; |
367 } |
407 } |
368 |
408 |
369 ssize_t pg_vfs_io_pread(SYS_FILE fd, void *buf, size_t nbyte, off_t offset) { |
409 ssize_t pg_vfs_io_pwrite(SYS_FILE fd, const void *buf, size_t nbyte, off_t offset) { |
|
410 PgVFS *pgvfs = fd->ctx->vfs->instance; |
|
411 |
370 return 0; |
412 return 0; |
371 } |
413 } |
372 |
414 |
373 ssize_t pg_vfs_io_pwrite(SYS_FILE fd, const void *buf, size_t nbyte, off_t offset) { |
|
374 return 0; |
|
375 } |
|
376 |
|
377 off_t pg_vfs_io_seek(SYS_FILE fd, off_t offset, int whence) { |
415 off_t pg_vfs_io_seek(SYS_FILE fd, off_t offset, int whence) { |
|
416 PgVFS *pgvfs = fd->ctx->vfs->instance; |
|
417 |
378 return 0; |
418 return 0; |
379 } |
419 } |
380 |
420 |
381 void pg_vfs_io_close(SYS_FILE fd) { |
421 void pg_vfs_io_close(SYS_FILE fd) { |
382 pool_handle_t *pool = fd->ctx->pool; |
422 pool_handle_t *pool = fd->ctx->pool; |
383 PgFile *pg = fd->data; |
423 PgFile *pg = fd->data; |
|
424 |
|
425 if(pg->fd >= 0) { |
|
426 PgVFS *pgvfs = fd->ctx->vfs->instance; |
|
427 lo_close(pgvfs->connection, pg->fd); |
|
428 } |
384 |
429 |
385 pool_free(pool, pg); |
430 pool_free(pool, pg); |
386 pool_free(pool, fd); |
431 pool_free(pool, fd); |
387 } |
432 } |
388 |
433 |