upscaledb  2.2.1
uqi2.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2016 Christoph Rupp (chris@crupp.de).
3  * All Rights Reserved.
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * See the file COPYING for License information.
16  */
17 
23 #include <stdio.h>
24 #include <string.h>
25 #include <assert.h>
26 #include <stdlib.h> /* for exit() */
27 
28 #include <ups/upscaledb.h>
29 #include <ups/upscaledb_uqi.h>
30 
31 #define DATABASE_NAME 1
32 
33 void
34 error(const char *foo, ups_status_t st)
35 {
36  printf("%s() returned error %d: %s\n", foo, st, ups_strerror(st));
37  exit(-1);
38 }
39 
40 /*
41  * Aggregation plugin: initialization
42  * Allocates storage for the aggregated counter.
43  */
44 static void *
45 mycount_init(int flags, int key_type, uint32_t key_size,
46  int record_type, uint32_t record_size, const char *reserved)
47 {
48  uint64_t *count = (uint64_t *)malloc(sizeof(uint64_t));
49  *count = 0;
50  return count;
51 }
52 
53 /*
54  * Aggregation plugin: de-initialization.
55  * Releases the storage which was allocated in mycount_init
56  */
57 static void
58 mycount_cleanup(void *state)
59 {
60  free(state);
61 }
62 
63 /*
64  * Aggregation plugin: aggregates a single value
65  * Here we simply increment the counter
66  */
67 static void
68 mycount_single(void *state, const void *key_data, uint32_t key_size,
69  const void *record_data, uint32_t record_size)
70 {
71  *(uint64_t *)state += 1;
72 }
73 
74 /*
75  * Aggregation plugin: aggregates a list of values
76  * Here we simply increase the counter by the number of elements in the list.
77  * This function is called for fixed-length data, but never for
78  * variable-length data.
79  */
80 static void
81 mycount_many(void *state, const void *key_data_list,
82  const void *record_data_list, size_t list_length)
83 {
84  uint64_t *pcount = (uint64_t *)state;
85  *pcount += list_length;
86 }
87 
88 /*
89  * Aggregation plugin: returns the results
90  */
91 static void
92 mycount_results(void *state, uqi_result_t *result)
93 {
94  uint64_t *pcount = (uint64_t *)state;
95  uqi_result_add_row(result, 0, 0, pcount, sizeof(*pcount));
96 }
97 
98 /*
99  * Predicate plugin: checks if the record is 10
100  */
101 static int
102 equals10_predicate(void *state, const void *key_data, uint32_t key_size,
103  const void *record_data, uint32_t record_size)
104 {
105  assert(record_size == sizeof(uint32_t));
106  return *(uint32_t *)record_data == 10;
107 }
108 
109 int
110 main(int argc, char **argv)
111 {
112  ups_status_t st; /* status variable */
113  ups_env_t *env; /* upscaledb environment object */
114  ups_db_t *db; /* upscaledb database object */
115  ups_parameter_t params[] = { /* parameters for ups_env_create_db */
117  {UPS_PARAM_RECORD_TYPE, UPS_TYPE_UINT32},
118  {0, 0}
119  };
120 
121  /* First create a new upscaledb Environment */
122  st = ups_env_create(&env, "test.db", 0, 0664, 0);
123  if (st != UPS_SUCCESS)
124  error("ups_env_create", st);
125 
126  /* And in this Environment we create a new Database for uint32-keys
127  * and uint32-records. */
129  &params[0]);
130  if (st != UPS_SUCCESS)
131  error("ups_env_create_db", st);
132 
133  /*
134  * now insert a bunch of key/value pairs. The IDs are automatically
135  * assigned, the record is a pseudo-random value
136  */
137  for (int i = 0; i < 10000; i++) {
138  uint32_t value = 1 + i % 30;
139  ups_key_t key = {0};
140  ups_record_t record = ups_make_record(&value, sizeof(value));
141 
142  st = ups_db_insert(db, 0, &key, &record, 0);
143  if (st != UPS_SUCCESS)
144  error("ups_db_insert", st);
145  }
146 
147  uqi_result_t *result;
148  ups_record_t record = {0};
149 
150  /* Our query will count all database entries with a record value of 10.
151  * For demonstration purposes we will use our own COUNT function (instead
152  * of the built-in "COUNT". */
153 
154  /* The first plugin will perform the aggregation. */
155  uqi_plugin_t agg;
156  memset(&agg, 0, sizeof(agg));
157  agg.name = "mycount";
159  agg.init = mycount_init;
160  agg.cleanup = mycount_cleanup;
162  agg.agg_many = mycount_many;
163  agg.results = mycount_results;
164  st = uqi_register_plugin(&agg);
165  if (st != UPS_SUCCESS)
166  error("uqi_register_plugin", st);
167 
168  /* Our second plugin will filter the data: all values != 10 are discarded.
169  * This plugin does not keep any state and therefore does not require an
170  * init or cleanup function. */
171  uqi_plugin_t pred;
172  memset(&pred, 0, sizeof(pred));
173  pred.type = UQI_PLUGIN_PREDICATE;
174  pred.name = "equals10";
175  pred.pred = equals10_predicate;
176  st = uqi_register_plugin(&pred);
177  if (st != UPS_SUCCESS)
178  error("uqi_register_plugin", st);
179 
180 
181  /* Now run the query */
182  st = uqi_select(env, "mycount($record) FROM DATABASE 1 "
183  "WHERE equals10($record)", &result);
184  if (st != UPS_SUCCESS)
185  error("uqi_select", st);
186 
187  /* Our aggregation plugin stores the result as a 64bit variable in the
188  * result's record (see mycount_results()) */
189  uqi_result_get_record(result, 0, &record);
190  printf("mycount($record): %lu\n", *(uint64_t *)record.data);
191  uqi_result_close(result);
192 
193  /* we're done! close the handles. UPS_AUTO_CLEANUP will also close the
194  * 'db' handle */
195  st = ups_env_close(env, UPS_AUTO_CLEANUP);
196  if (st != UPS_SUCCESS)
197  error("ups_env_close", st);
198 
199  printf("success!\n");
200  return 0;
201 }
202 
#define ups_make_record(PTR, SIZE)
Definition: upscaledb.h:225
static void mycount_results(void *state, uqi_result_t *result)
Definition: uqi2.c:92
uqi_plugin_aggregate_many_function agg_many
UPS_EXPORT const char *UPS_CALLCONV ups_strerror(ups_status_t status)
int main(int argc, char **argv)
Definition: uqi2.c:110
UPS_EXPORT ups_status_t UPS_CALLCONV ups_env_close(ups_env_t *env, uint32_t flags)
UPS_EXPORT ups_status_t UPS_CALLCONV ups_db_insert(ups_db_t *db, ups_txn_t *txn, ups_key_t *key, ups_record_t *record, uint32_t flags)
unsigned __int64 uint64_t
Definition: msstdint.h:95
uqi_plugin_predicate_function pred
uint32_t type
Include file for upscaledb Query Interface.
#define UQI_PLUGIN_AGGREGATE
void error(const char *foo, ups_status_t st)
Definition: uqi2.c:34
UPS_EXPORT void UPS_CALLCONV uqi_result_add_row(uqi_result_t *result, const void *key_data, uint32_t key_size, const void *record_data, uint32_t record_size)
#define UPS_TYPE_UINT32
Definition: upscaledb.h:322
UPS_EXPORT ups_status_t UPS_CALLCONV uqi_select(ups_env_t *env, const char *query, uqi_result_t **result)
uqi_plugin_cleanup_function cleanup
unsigned int uint32_t
Definition: msstdint.h:85
#define DATABASE_NAME
Definition: uqi2.c:31
UPS_EXPORT void UPS_CALLCONV uqi_result_get_record(uqi_result_t *result, uint32_t row, ups_record_t *record)
#define UPS_PARAM_RECORD_TYPE
Definition: upscaledb.h:1739
UPS_EXPORT void UPS_CALLCONV uqi_result_close(uqi_result_t *result)
Include file for upscaledb embedded database.
uqi_plugin_aggregate_single_function agg_single
uqi_plugin_init_function init
struct ups_db_t ups_db_t
Definition: upscaledb.h:156
uqi_plugin_result_function results
#define UQI_PLUGIN_PREDICATE
#define UPS_AUTO_CLEANUP
Definition: upscaledb.h:1883
#define UPS_SUCCESS
Definition: upscaledb.h:341
UPS_EXPORT ups_status_t UPS_CALLCONV ups_env_create(ups_env_t **env, const char *filename, uint32_t flags, uint32_t mode, const ups_parameter_t *param)
static void mycount_single(void *state, const void *key_data, uint32_t key_size, const void *record_data, uint32_t record_size)
Definition: uqi2.c:68
struct uqi_result_t uqi_result_t
Definition: upscaledb_uqi.h:41
UPS_EXPORT ups_status_t UPS_CALLCONV uqi_register_plugin(uqi_plugin_t *descriptor)
static void mycount_many(void *state, const void *key_data_list, const void *record_data_list, size_t list_length)
Definition: uqi2.c:81
#define UPS_RECORD_NUMBER32
Definition: upscaledb.h:1301
void * data
Definition: upscaledb.h:207
static void * mycount_init(int flags, int key_type, uint32_t key_size, int record_type, uint32_t record_size, const char *reserved)
Definition: uqi2.c:45
const char * name
int ups_status_t
Definition: types.h:139
static void mycount_cleanup(void *state)
Definition: uqi2.c:58
UPS_EXPORT ups_status_t UPS_CALLCONV ups_env_create_db(ups_env_t *env, ups_db_t **db, uint16_t name, uint32_t flags, const ups_parameter_t *params)
#define UPS_PARAM_KEY_TYPE
Definition: upscaledb.h:1710
struct ups_env_t ups_env_t
Definition: upscaledb.h:165
static int equals10_predicate(void *state, const void *key_data, uint32_t key_size, const void *record_data, uint32_t record_size)
Definition: uqi2.c:102