NCBI C++ ToolKit
collations.c
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
2  * Copyright (C) 2015 Frediano Ziglio
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19 #undef NDEBUG
20 #include "common.h"
21 #include <freetds/iconv.h>
22 #include "md5.h"
23 
24 #undef NDEBUG
25 #include <ctype.h>
26 #include <assert.h>
27 
28 #if HAVE_UNISTD_H
29 #undef getpid
30 #include <unistd.h>
31 #elif defined(_WIN32)
32 # include <io.h>
33 # undef isatty
34 # define isatty(fd) _isatty(fd)
35 #endif /* HAVE_UNISTD_H */
36 
37 static TDSSOCKET *tds;
38 
39 static void
40 get_coll_md5(const char *name, char *digest)
41 {
42  MD5_CTX ctx;
43  char *p = NULL, *sql = NULL;
44  int ret;
45  TDSRET rc;
46  TDS_INT result_type;
47  int done_flags, i;
48  unsigned char dig[16];
49 
50  ret = asprintf(&sql, "convert(nvarchar(1024), bin) collate %s", name);
51  assert(ret >= 0);
52 
53  ret = asprintf(&p, "convert(varchar(4096), %s)", sql);
54  assert(ret >= 0);
55  free(sql);
56  sql = NULL;
57 
58  ret = asprintf(&sql, "select convert(varbinary(8000), %s) from #all_chars order by id", p);
59  assert(ret >= 0);
60  free(p);
61  p = NULL;
62 
63  rc = tds_submit_query(tds, sql);
64  assert(rc == TDS_SUCCESS);
65  free(sql);
66  sql = NULL;
67 
68  MD5Init(&ctx);
69 
70  while ((rc = tds_process_tokens(tds, &result_type, &done_flags, TDS_RETURN_ROW)) == TDS_SUCCESS) {
71  TDSCOLUMN *curcol;
72 
73  assert(result_type == TDS_ROW_RESULT);
74 
75  curcol = tds->current_results->columns[0];
76 
77  assert(!is_blob_col(curcol));
79 
80  MD5Update(&ctx, curcol->column_data, curcol->column_cur_size);
81  }
83 
84  memset(dig, 0, sizeof(dig));
85  MD5Final(&ctx, dig);
86  for (i = 0; i < 16; ++i)
87  sprintf(digest + i * 2, "%02x", dig[i]);
88 }
89 
90 static void
91 get_encoding_coll(TDS71_COLLATION *coll, char *digest, char *cp, const char *name)
92 {
93  int rc;
94  int done_flags;
95  TDS_INT result_type;
96  char sql[512];
97  static TDS71_COLLATION old_coll = { 0, 0, 0};
98  static char old_digest[33];
99 
100  sprintf(sql, "SELECT CAST(CAST('a' AS NVARCHAR(10)) COLLATE %s AS VARCHAR(10)) COLLATE %s", name, name);
101 
102  /* do a select and check all results */
103  rc = tds_submit_query(tds, sql);
104  assert(rc == TDS_SUCCESS);
105 
107 
108  if (result_type == TDS_DONE_RESULT)
109  return;
110 
111  assert(result_type == TDS_ROWFMT_RESULT);
112 
114 
115  assert(result_type == TDS_ROW_RESULT);
116 
118 
119  TDSCOLUMN *curcol;
120  TDS_UCHAR *c;
121 
122  if (result_type != TDS_ROW_RESULT)
123  break;
124 
125  curcol = tds->current_results->columns[0];
126 
127  strcpy(cp, curcol->char_conv->to.charset.name);
128 
129  c = curcol->column_collation;
130  coll->locale_id = c[0] + 256 * c[1];
131  coll->flags = c[2] + 256 * c[3];
132  coll->charset_id = c[4];
133  }
134 
135  if (rc != TDS_SUCCESS || result_type == TDS_ROW_RESULT || result_type == TDS_COMPUTE_RESULT) {
136  fprintf(stderr, "tds_process_tokens() unexpected return\n");
137  exit(1);
138  }
139 
140  while ((rc = tds_process_tokens(tds, &result_type, &done_flags, TDS_TOKEN_RESULTS)) == TDS_SUCCESS) {
141  switch (result_type) {
142  case TDS_NO_MORE_RESULTS:
143  return;
144 
145  case TDS_DONE_RESULT:
146  case TDS_DONEPROC_RESULT:
148  if (!(done_flags & TDS_DONE_ERROR))
149  break;
150 
151  default:
152  fprintf(stderr, "tds_proces_tokens() unexpected result_type\n");
153  exit(1);
154  break;
155  }
156  }
157 
158  if (old_coll.locale_id && old_coll.locale_id == coll->locale_id && old_coll.charset_id == coll->charset_id) {
159  memcpy(digest, old_digest, 33);
160  } else {
161  get_coll_md5(name, digest);
162  }
163 
164  memcpy(old_digest, digest, 33);
165  memcpy(&old_coll, coll, sizeof(*coll));
166 }
167 
168 static void
170 {
171  FILE *f = fopen("collations.txt", "r");
172  char line[1024];
173 
174  assert(f);
175  while (fgets(line, sizeof(line), f)) {
176  TDS71_COLLATION coll;
177  char cp[128], digest[33];
178  char *s = strtok(line, " \n");
179 
180  if (!s[0])
181  continue;
182 
183  memset(&coll, 0, sizeof(coll));
184  cp[0] = 0;
185  digest[0] = 0;
186 
187  get_encoding_coll(&coll, digest, cp, s);
188  printf("%s %d %d %d %s %s\n", s, coll.locale_id, coll.flags, coll.charset_id, cp, digest);
189  }
190  fclose(f);
191 }
192 
193 static void
194 add_couple(unsigned n)
195 {
196  enum { CHUNK = 512 };
197  static char buf[CHUNK * 4+1];
198  static int cnt = 0;
199  static int id = 0;
200 
201  char *sql = NULL;
202  int ret;
203 
204  sprintf(buf + cnt * 4, "%02x%02x", n & 0xff, (n >> 8) & 0xff);
205 
206  /* time to insert the command into database ? */
207  if (++cnt != CHUNK)
208  return;
209 
210  cnt = 0;
211  ++id;
212  ret = asprintf(&sql, "insert into #all_chars values(%d, convert(varbinary(2048), 0x%s))", id, buf);
213  assert(ret >= 0);
214 
215  if (isatty(fileno(stdout))) {
216  printf("\rInserting: %d", id);
217  fflush(stdout);
218  }
219 
220  ret = run_query(tds, sql);
221  assert(ret == TDS_SUCCESS);
222 
223  free(sql);
224 }
225 
226 static void
228 {
229  unsigned n;
230  for (n = 0; n < 65536; ++n)
231  add_couple(n);
232 }
233 
234 static void
236 {
237  unsigned n;
238  for (n = 0; n <= 0xfffff; ++n) {
239  add_couple( (n >> 10) + 0xd800 );
240  add_couple( (n & 0x3ff) + 0xdc00 );
241  }
242 }
243 
244 static void
246 {
247  int ret;
248 
249  ret = run_query(tds, "CREATE TABLE #all_chars(id int, bin varbinary(2048))");
250  assert(ret == TDS_SUCCESS);
251 
252  add_plane0();
253  add_couples();
254  printf("\n");
255 }
256 
257 static void
259 {
260  TDS_INT result_type;
261  int done_flags;
262  TDSRET rc;
263  FILE *f;
264 
265  f = fopen("collations.txt", "w");
266  assert(f);
267 
268  rc = tds_submit_query(tds, "select name from ::fn_helpcollations() order by name");
269  assert(rc == TDS_SUCCESS);
270 
271  while ((rc = tds_process_tokens(tds, &result_type, &done_flags, TDS_RETURN_ROW)) == TDS_SUCCESS) {
272  TDSCOLUMN *curcol;
273  int len;
274 
275  assert(result_type == TDS_ROW_RESULT);
276 
277  curcol = tds->current_results->columns[0];
278 
279  assert(!is_blob_col(curcol));
280  assert(curcol->column_type == SYBVARCHAR);
281 
282  len = curcol->column_cur_size;
283  fprintf(f, "%*.*s\n", len, len, curcol->column_data);
284  }
286 
287  fclose(f);
288 }
289 
290 int
291 main(int argc, char **argv)
292 {
293  TDSLOGIN *login;
294  int ret;
295  int verbose = 0;
296 
297  /* use UTF-8 as our coding */
298  strcpy(CHARSET, "UTF-8");
299 
300  ret = try_tds_login(&login, &tds, __FILE__, verbose);
301  if (ret != TDS_SUCCESS) {
302  fprintf(stderr, "try_tds_login() failed\n");
303  return 1;
304  }
305 
306  if (IS_TDS71_PLUS(tds->conn)) {
307  printf("Preparing table with all characters\n");
309 
310  printf("Extracting collation list\n");
312 
313  printf("Testing encodings\n");
315  }
316 
318  return 0;
319 }
CS_CONTEXT * ctx
Definition: t0006.c:12
@ XSYBVARBINARY
Definition: proto.h:197
#define TDS_DONEPROC_RESULT
Definition: tds.h:228
#define IS_TDS71_PLUS(x)
Definition: tds.h:1709
#define TDS_ROWFMT_RESULT
Definition: tds.h:224
tds_sysdep_int32_type TDS_INT
Definition: tds.h:149
@ TDS_STOPAT_DONE
Definition: tds.h:255
@ TDS_RETURN_ROW
Definition: tds.h:256
@ TDS_STOPAT_ROWFMT
Definition: tds.h:252
@ TDS_TOKEN_RESULTS
Definition: tds.h:261
@ TDS_RETURN_COMPUTE
Definition: tds.h:257
#define TDS_DONE_RESULT
Definition: tds.h:227
#define TDS_NO_MORE_RESULTS
Definition: tds.h:202
unsigned char TDS_UCHAR
Definition: tds.h:145
#define is_blob_col(x)
Definition: tds.h:445
#define TDS_COMPUTE_RESULT
Definition: tds.h:220
#define TDS_ROW_RESULT
Definition: tds.h:216
@ TDS_DONE_ERROR
error occurred
Definition: tds.h:272
int TDSRET
Definition: tds.h:201
#define TDS_SUCCESS
Definition: tds.h:203
#define TDS_DONEINPROC_RESULT
Definition: tds.h:229
static char sql[1024]
Definition: putdata.c:19
#define asprintf
Definition: replacements.h:54
#define SYBVARCHAR
Definition: sybdb.h:162
static void prepare_all_chars(void)
Definition: collations.c:245
static void add_plane0(void)
Definition: collations.c:227
static void add_couple(unsigned n)
Definition: collations.c:194
static void add_couples(void)
Definition: collations.c:235
int main(int argc, char **argv)
Definition: collations.c:291
static void extract_collations(void)
Definition: collations.c:258
static void get_coll_md5(const char *name, char *digest)
Definition: collations.c:40
static void get_encoding_coll(TDS71_COLLATION *coll, char *digest, char *cp, const char *name)
Definition: collations.c:91
static TDSSOCKET * tds
Definition: collations.c:37
static void test_column_encoding(void)
Definition: collations.c:169
int run_query(TDSSOCKET *tds, const char *query)
Definition: common.c:143
int try_tds_logout(TDSLOGIN *login, TDSSOCKET *tds, int verbose)
Definition: common.c:128
int try_tds_login(TDSLOGIN **login, TDSSOCKET **tds, const char *appname, int verbose)
Definition: common.c:55
char CHARSET[512]
Definition: common.c:11
static TDSLOGIN * login
Definition: dataread.c:31
static FILE * f
Definition: readconf.c:23
#define tds_submit_query
#define tds_process_tokens
#define NULL
Definition: ncbistd.hpp:225
#define MD5Update
Definition: md5.h:10
#define MD5Init
Definition: md5.h:9
#define MD5Final
Definition: md5.h:11
exit(2)
char * buf
int i
yy_size_t n
int len
static unsigned cnt[256]
true_type verbose
Definition: processing.cpp:878
#define assert(x)
Definition: srv_diag.hpp:58
Definition: md5.h:13
TDS 7.1 collation informations.
Definition: proto.h:351
TDS_USMALLINT flags
Definition: proto.h:353
TDS_UCHAR charset_id
Definition: proto.h:354
TDS_USMALLINT locale_id
Definition: proto.h:352
Metadata about columns in regular and compute rows.
Definition: tds.h:761
TDS_UCHAR column_collation[5]
Definition: tds.h:803
TDS_SERVER_TYPE column_type
This type can be different from wire type because conversion (e.g.
Definition: tds.h:768
TDSICONV * char_conv
refers to previously allocated iconv information
Definition: tds.h:784
unsigned char * column_data
Definition: tds.h:793
struct tds_column::@124 on_server
TDS_INT column_cur_size
size written in variable (ie: char, text, binary).
Definition: tds.h:811
Definition: tds.h:584
TDSCOLUMN ** columns
Definition: tds.h:844
Information for a server connection.
Definition: tds.h:1211
TDSCONNECTION conn[1]
Definition: tds.h:1215
TDSRESULTINFO * current_results
Current query information.
Definition: tds.h:1263
void free(voidpf ptr)
Modified on Fri Sep 20 14:57:17 2024 by modify_doxy.py rev. 669887