Skip to content

Commit

Permalink
Merge branch 'compact'
Browse files Browse the repository at this point in the history
  • Loading branch information
agentzh committed Nov 18, 2010
2 parents df2370c + e41118e commit 3a935bb
Show file tree
Hide file tree
Showing 10 changed files with 1,946 additions and 38 deletions.
50 changes: 50 additions & 0 deletions README
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,56 @@ Description
This module provides an output filter that can format the RDS outputs
generated by ngx_drizzle and ngx_postgres modules.

Directives
rds_json
syntax: rds_json on|off
default: rds_json off

Enables or disables the output filter of this module.

rds_json_buffer_size
syntax: rds_json_buffer_size <bytes>
default: rds_json_buffer_size <page-size>

Controls the buffer size used by this module. default to the page size (4k/8k).
The bigger the buffer size, the less streammy the conversion
will be. But usually increasing the buffer size
does help reduce CPU time.

rds_json_format
syntax: rds_json_format normal|compact
default: rds_json_format normal

Controls the output JSON format. A sample of the default "normal" format
looks like this

[{"id":1,"name":"marry"},{"id":2,"name":"bob"}]

while it looks like below when in the "compact" format

[["id","name"],[1,"marry"],[2,"bob"]]

that is, the first row holds the column name list.

rds_json_ret
syntax: rds_json_ret <error-code> <descrption>
default: none

This directive enables a content handler that simply emits
an response body like this:

{"errcode":<error-code>,"errstr":"<description>"}

while the <description> string will be properly quoted as
a JSON string.

rds_json_content_type
syntax: rds_json_content_type <mime-type>
default: rds_json_content_type application/json

Controls the Content-Type header of the response generated by
this module's output filter.

Installation
Grab the nginx source code from nginx.net (<http://nginx.net/>), for
example, the version 0.8.36 (see nginx compatibility), and then build
Expand Down
5 changes: 3 additions & 2 deletions src/ngx_http_rds_json_filter_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@
#define ngx_http_rds_json_content_type "application/json"

static ngx_conf_enum_t ngx_http_rds_json_formats[] = {
{ ngx_string("normal"), json_format_normal },
{ ngx_string("compact"), json_format_compact },
{ ngx_string("pretty"), json_format_pretty },
/* { ngx_string("pretty"), json_format_pretty }, */
{ ngx_null_string, 0 }
};

Expand Down Expand Up @@ -332,7 +333,7 @@ ngx_http_rds_json_merge_conf(ngx_conf_t *cf, void *parent, void *child)

ngx_conf_merge_value(conf->enabled, prev->enabled, 0);

ngx_conf_merge_uint_value(conf->format, prev->format, json_format_compact);
ngx_conf_merge_uint_value(conf->format, prev->format, json_format_normal);

ngx_conf_merge_str_value(conf->content_type, prev->content_type,
ngx_http_rds_json_content_type);
Expand Down
7 changes: 4 additions & 3 deletions src/ngx_http_rds_json_filter_module.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ extern ngx_http_output_body_filter_pt ngx_http_rds_json_next_body_filter;


typedef enum {
json_format_normal,
json_format_compact,
json_format_pretty /* TODO */

Expand Down Expand Up @@ -83,9 +84,9 @@ typedef struct {

uint32_t field_data_rest;

ngx_flag_t header_sent;

ngx_flag_t seen_stream_end;
ngx_flag_t header_sent:1;
ngx_flag_t seen_stream_end:1;
ngx_flag_t generated_col_names:1;
} ngx_http_rds_json_ctx_t;


Expand Down
199 changes: 166 additions & 33 deletions src/ngx_http_rds_json_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,73 @@ ngx_http_rds_json_output_header(ngx_http_request_t *r,
}


ngx_int_t
ngx_http_rds_json_output_cols(ngx_http_request_t *r,
ngx_http_rds_json_ctx_t *ctx)
{
ngx_uint_t i;
ngx_http_rds_column_t *col;
size_t size;
u_char *pos, *last;
uintptr_t key_escape = 0;

size = sizeof("[]") - 1;

for (i = 0; i < ctx->col_count; i++) {
col = &ctx->cols[i];
key_escape = ngx_http_rds_json_escape_json_str(NULL,
col->name.data, col->name.len);

dd("key_escape: %d", (int) key_escape);

size += col->name.len + key_escape
+ sizeof("\"\"") - 1
;

if (i != ctx->col_count - 1) {
/* not the last column */
size += sizeof(",") - 1;
}
}

ctx->generated_col_names = 1;

pos = ngx_http_rds_json_request_mem(r, ctx, size);
if (pos == NULL) {
return NGX_ERROR;
}

last = pos;


*last++ = '[';

for (i = 0; i < ctx->col_count; i++) {
col = &ctx->cols[i];

*last++ = '"';

if (key_escape == 0) {
last = ngx_copy(last, col->name.data, col->name.len);

} else {
last = (u_char *) ngx_http_rds_json_escape_json_str(last,
col->name.data, col->name.len);
}

*last++ = '"';

if (i != ctx->col_count - 1) {
*last++ = ',';
}
}

*last++ = ']';

return ngx_http_rds_json_submit_mem(r, ctx, size, 0);
}


ngx_int_t
ngx_http_rds_json_output_field(ngx_http_request_t *r,
ngx_http_rds_json_ctx_t *ctx, u_char *data, size_t len,
Expand All @@ -223,35 +290,60 @@ ngx_http_rds_json_output_field(ngx_http_request_t *r,
uintptr_t val_escape = 0;
u_char *p;
ngx_uint_t i;
ngx_http_rds_json_conf_t *conf;
ngx_uint_t format;

conf = ngx_http_get_module_loc_conf(r, ngx_http_rds_json_filter_module);

format = conf->format;

dd("reading row %llu, col %d, len %d",
(unsigned long long) ctx->row,
(int) ctx->cur_col, (int) len);

/* calculate the buffer size */

if (ctx->cur_col == 0) {
dd("first column");
if (ctx->row == 1) {
dd("first column, first row");
size = sizeof("{\"") - 1;
if (format == json_format_normal) {
if (ctx->cur_col == 0) {
dd("first column");
if (ctx->row == 1) {
dd("first column, first row");
size = sizeof("{\"") - 1;
} else {
size = sizeof(",{\"") - 1;
}
} else {
size = sizeof(",\"") - 1;
}

} else if (format == json_format_compact) {
if (ctx->cur_col == 0) {
dd("first column");
size = sizeof(",[") - 1;
} else {
size = sizeof(",{\"") - 1;
size = sizeof(",") - 1;
}
} else {
size = sizeof(",\"") - 1;
return NGX_ERROR;
}

col = &ctx->cols[ctx->cur_col];

key_escape = ngx_http_rds_json_escape_json_str(NULL, col->name.data,
col->name.len);
if (format == json_format_normal) {
key_escape = ngx_http_rds_json_escape_json_str(NULL, col->name.data,
col->name.len);

dd("key_escape: %d", (int) key_escape);
dd("key_escape: %d", (int) key_escape);

size += col->name.len + key_escape
+ sizeof("\":") - 1
;
size += col->name.len + key_escape
+ sizeof("\":") - 1
;

} else if (format == json_format_compact) {
/* do nothing */
} else {
return NGX_ERROR;
}

if (len == 0 && ctx->field_data_rest > 0) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
Expand Down Expand Up @@ -344,7 +436,14 @@ ngx_http_rds_json_output_field(ngx_http_request_t *r,
&& ctx->cur_col == ctx->col_count - 1)
{
/* last column in the row */
size += sizeof("}") - 1;
if (format == json_format_normal) {
size += sizeof("}") - 1;

} else if (format == json_format_compact) {
size += sizeof("]") - 1;
} else {
return NGX_ERROR;
}
}

/* allocate the buffer */
Expand All @@ -358,30 +457,43 @@ ngx_http_rds_json_output_field(ngx_http_request_t *r,

/* fill up the buffer */

if (ctx->cur_col == 0) {
dd("first column");
if (ctx->row == 1) {
dd("first column, first row");
*last++ = '{';
if (format == json_format_normal) {
if (ctx->cur_col == 0) {
dd("first column");
if (ctx->row == 1) {
dd("first column, first row");
*last++ = '{';
} else {
*last++ = ','; *last++ = '{';
}
} else {
*last++ = ','; *last++ = '{';
*last++ = ',';
}
} else {
*last++ = ',';
}

*last++ = '"';
*last++ = '"';

if (key_escape == 0) {
last = ngx_copy(last, col->name.data, col->name.len);

} else {
last = (u_char *) ngx_http_rds_json_escape_json_str(last,
col->name.data, col->name.len);
}

if (key_escape == 0) {
last = ngx_copy(last, col->name.data, col->name.len);
*last++ = '"'; *last++ = ':';

} else if (format == json_format_compact) {
if (ctx->cur_col == 0) {
dd("first column");
*last++ = ','; *last++ = '[';
} else {
*last++ = ',';
}

} else {
last = (u_char *) ngx_http_rds_json_escape_json_str(last,
col->name.data, col->name.len);
return NGX_ERROR;
}

*last++ = '"'; *last++ = ':';

if (is_null) {
dd("copy null value over");
last = ngx_copy_const_str(last, "null");
Expand Down Expand Up @@ -443,7 +555,13 @@ ngx_http_rds_json_output_field(ngx_http_request_t *r,
&& ctx->cur_col == ctx->col_count - 1)
{
dd("last column in the row");
*last++ = '}';
if (format == json_format_normal) {
*last++ = '}';
} else if (format == json_format_compact) {
*last++ = ']';
} else {
return NGX_ERROR;
}
}

if ((size_t) (last - pos) != size) {
Expand All @@ -468,6 +586,9 @@ ngx_http_rds_json_output_more_field_data(ngx_http_request_t *r,
uintptr_t escape = 0;
u_char *p;
ngx_uint_t i;
ngx_http_rds_json_conf_t *conf;

conf = ngx_http_get_module_loc_conf(r, ngx_http_rds_json_filter_module);

/* calculate the buffer size */

Expand Down Expand Up @@ -511,7 +632,13 @@ ngx_http_rds_json_output_more_field_data(ngx_http_request_t *r,
&& ctx->cur_col == ctx->col_count - 1)
{
/* last column in the row */
size += sizeof("}") - 1;
if (conf->format == json_format_normal) {
size += sizeof("}") - 1;
} else if (conf->format == json_format_compact) {
size += sizeof("]") - 1;
} else {
return NGX_ERROR;
}
}

/* allocate the buffer */
Expand Down Expand Up @@ -569,7 +696,13 @@ ngx_http_rds_json_output_more_field_data(ngx_http_request_t *r,
ctx->cur_col == ctx->col_count - 1)
{
/* last column in the row */
*last++ = '}';
if (conf->format == json_format_normal) {
*last++ = '}';
} else if (conf->format == json_format_compact) {
*last++ = ']';
} else {
return NGX_ERROR;
}
}

if ((size_t) (last - pos) != size) {
Expand Down
3 changes: 3 additions & 0 deletions src/ngx_http_rds_json_output.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
ngx_int_t ngx_http_rds_json_output_header(ngx_http_request_t *r,
ngx_http_rds_json_ctx_t *ctx, ngx_http_rds_header_t *header);

ngx_int_t ngx_http_rds_json_output_cols(ngx_http_request_t *r,
ngx_http_rds_json_ctx_t *ctx);

ngx_int_t ngx_http_rds_json_output_literal(ngx_http_request_t *r,
ngx_http_rds_json_ctx_t *ctx, u_char *data, size_t len,
ngx_flag_t last_buf);
Expand Down
Loading

0 comments on commit 3a935bb

Please sign in to comment.