Skip to content

Commit ad2c78e

Browse files
committed
Link against libuuid
* replaces UUID struct with uuid_t array type * uses libuuid to generate version 1 and 4 UUIDs in a cross-platform manner
1 parent dd71296 commit ad2c78e

File tree

3 files changed

+64
-89
lines changed

3 files changed

+64
-89
lines changed

Makefile

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,26 @@
22

33
NAME = uuid
44
PLATFORM := $(shell uname -s)
5-
CFLAGS = -fPIC -Wall -Wextra -O2 -c
5+
CFLAGS = -g -fPIC -Wall -Wextra -O2
66
LDFLAGS = -shared
7-
BUILD_DIR = build
87
DIST_DIR = dist
98
SOURCES := $(wildcard src/*.c)
10-
OBJECTS := $(patsubst src/%.c, $(BUILD_DIR)/%.o, $(SOURCES))
119

1210
ifeq ($(PLATFORM), Darwin)
1311
SO_EXT = dylib
1412
else
15-
SO_EXT = so
13+
SO_EXT = so
14+
LDFLAGS += -luuid
1615
endif
1716

1817
all: $(DIST_DIR)/$(NAME).$(SO_EXT)
1918

2019
clean:
21-
$(RM) -r $(BUILD_DIR) $(DIST_DIR)
20+
$(RM) -r $(DIST_DIR)
2221

2322
print-%:
2423
@echo '$*=$($*)'
2524

26-
$(BUILD_DIR)/%.o: src/%.c
27-
mkdir -p $(BUILD_DIR)
28-
$(CC) $(CFLAGS) -o "$@" $<
29-
30-
$(DIST_DIR)/$(NAME).$(SO_EXT): $(OBJECTS)
25+
$(DIST_DIR)/$(NAME).$(SO_EXT): $(SOURCES)
3126
mkdir -p $(DIST_DIR)
32-
$(CC) $(LDFLAGS) -o $@ $<
27+
$(CC) $< $(CFLAGS) $(LDFLAGS) -o $@

README.md

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,18 @@ This SQLite extension implements functions for creating [RFC 4122](https://www.i
44

55
## Installation
66

7-
1. Install the SQLite development headers. Mac OS X ships with SQLite and the development headers, but you may need to install them on Linux.
7+
1. Install the necessary development headers. Mac OS X ships with SQLite and the development headers, but you may need to install them on Linux.
88

99
* Debian / Ubuntu:
1010

1111
```
12-
sudo apt-get install libsqlite3-dev
12+
sudo apt-get install libsqlite3-dev uuid-dev
1313
```
1414
1515
* Red Hat / CentOS:
1616
1717
```
18-
sudo yum install sqlite-devel
18+
sudo yum install sqlite-devel uuid-devel
1919
```
2020
2121
2. Build the extension. The build will produce a shared library for your platform under `dist/`.
@@ -41,6 +41,15 @@ This SQLite extension implements functions for creating [RFC 4122](https://www.i
4141
4242
## Usage
4343
44+
### `uuid1()`
45+
46+
Generate a version 1 UUID, based on the time and host machine's MAC address.
47+
48+
```sql
49+
SELECT uuid1();
50+
d5a80b20-0d8f-11e5-b8cb-080027b6ec40
51+
```
52+
4453
### `uuid4()`
4554

4655
Generate a version 4 (random) UUID.

src/uuid.c

Lines changed: 46 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -15,94 +15,67 @@
1515
#include <sqlite3ext.h>
1616
SQLITE_EXTENSION_INIT1
1717
#include <assert.h>
18-
#include <fcntl.h>
19-
#include <unistd.h>
20-
#include <stdio.h>
21-
#include <stdlib.h>
18+
#include <uuid/uuid.h>
2219

2320
/*
24-
** A UUID represents an RFC 4122 UUID.
21+
** Implementation of uuid1() function.
2522
*/
26-
typedef struct UUID {
27-
unsigned char bytes[16];
28-
} UUID;
29-
30-
/*
31-
** Set the UUID version.
32-
*/
33-
void set_uuid_version(UUID* u, char version) {
34-
u->bytes[6] = (u->bytes[6] & 0x0f) | (version << 4);
23+
static void uuid1func(
24+
sqlite3_context *context,
25+
int argc,
26+
sqlite3_value **argv
27+
){
28+
assert(argc==0);
29+
uuid_t uuid;
30+
uuid_generate_time(uuid);
31+
char uuid_str[37];
32+
uuid_unparse_lower(uuid, uuid_str);
33+
sqlite3_result_text(context, uuid_str, 37, SQLITE_TRANSIENT);
3534
}
3635

3736
/*
38-
** Set the UUID variant to match the RFC4122 specification.
39-
**
40-
** Example:
41-
**
42-
** e462c464-d4d9-433b-b372-cc90939dbe6d
43-
** ^
44-
** one of {8, 9, a, b}
37+
** Implementation of the uuid4() function.
4538
*/
46-
void set_uuid_variant(UUID* u) {
47-
u->bytes[8] = (u->bytes[8] & 0x3f) | 0x80;
39+
static void uuid4func(
40+
sqlite3_context *context,
41+
int argc,
42+
sqlite3_value **argv
43+
){
44+
assert(argc==0);
45+
uuid_t uuid;
46+
uuid_generate_random(uuid);
47+
char uuid_str[37];
48+
uuid_unparse_lower(uuid, uuid_str);
49+
sqlite3_result_text(context, uuid_str, 37, SQLITE_TRANSIENT);
4850
}
4951

5052
/*
51-
** Represent a UUID in its canonical string form.
53+
** Register UUID functions to database `db`.
5254
*/
53-
char* uuid_to_string(UUID* u) {
54-
55-
int i;
56-
char* buf = sqlite3_malloc(sizeof(char)*36+1);
57-
58-
for (i = 0; i < 4; i++) {
59-
sprintf(&buf[2*i], "%02x", u->bytes[i]);
60-
}
61-
sprintf(&buf[8], "-");
62-
for (i = 4; i < 6; i++) {
63-
sprintf(&buf[2*i + 1], "%02x", u->bytes[i]);
64-
}
65-
sprintf(&buf[13], "-");
66-
for (i = 6; i < 8; i++) {
67-
sprintf(&buf[2*i + 2], "%02x", u->bytes[i]);
68-
}
69-
sprintf(&buf[18], "-");
70-
for (i = 8; i < 10; i++) {
71-
sprintf(&buf[2*i + 3], "%02x", u->bytes[i]);
72-
}
73-
sprintf(&buf[23], "-");
74-
for (i = 10; i < 16; i++) {
75-
sprintf(&buf[2*i + 4], "%02x", u->bytes[i]);
76-
}
55+
int register_uuid_functions(sqlite3 *db) {
56+
typedef struct UUIDScalar {
57+
const char *name;
58+
int argc;
59+
int enc;
60+
void (*func)(sqlite3_context*, int, sqlite3_value**);
61+
} UUIDScalar;
7762

78-
return buf;
79-
}
63+
UUIDScalar scalars[] = {
64+
{"uuid1", 0, SQLITE_UTF8, uuid1func},
65+
{"uuid4", 0, SQLITE_UTF8, uuid4func},
66+
};
8067

81-
UUID random_uuid() {
82-
UUID u;
68+
int rc = SQLITE_OK;
69+
int i, n;
8370

84-
int fd = open("/dev/urandom", O_RDONLY);
85-
read(fd, u.bytes, sizeof(u.bytes));
86-
close(fd);
71+
n = (int)(sizeof(scalars)/sizeof(scalars[0]));
8772

88-
set_uuid_version(&u, 4);
89-
set_uuid_variant(&u);
90-
return u;
91-
}
73+
for (i = 0; rc == SQLITE_OK && i < n; i++) {
74+
UUIDScalar *s = &scalars[i];
75+
rc = sqlite3_create_function(db, s->name, s->argc, s->enc, 0, s->func, 0, 0);
76+
}
9277

93-
/*
94-
** Implementation of the uuid4() function.
95-
*/
96-
static void uuid4func(
97-
sqlite3_context *context,
98-
int argc,
99-
sqlite3_value **argv
100-
){
101-
assert(argc==0);
102-
UUID uuid = random_uuid();
103-
char* buf = uuid_to_string(&uuid);
104-
sqlite3_result_text(context, (char*)buf, 36, SQLITE_TRANSIENT);
105-
sqlite3_free(buf);
78+
return rc;
10679
}
10780

10881
#ifdef _WIN32
@@ -113,8 +86,6 @@ int sqlite3_uuid_init(
11386
char **pzErrMsg,
11487
const sqlite3_api_routines *pApi
11588
){
116-
int rc = SQLITE_OK;
11789
SQLITE_EXTENSION_INIT2(pApi);
118-
rc = sqlite3_create_function(db, "uuid4", 0, SQLITE_UTF8, 0, uuid4func, 0, 0);
119-
return rc;
90+
return register_uuid_functions(db);
12091
}

0 commit comments

Comments
 (0)