PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
error.c File Reference
#include "postgres_fe.h"
#include "ecpgerrno.h"
#include "ecpgtype.h"
#include "ecpglib.h"
#include "extern.h"
#include "sqlca.h"
Include dependency graph for error.c:

Go to the source code of this file.

Macros

#define POSTGRES_ECPG_INTERNAL
 

Functions

void ecpg_raise (int line, int code, const char *sqlstate, const char *str)
 
void ecpg_raise_backend (int line, PGresult *result, PGconn *conn, int compat)
 
bool ecpg_check_PQresult (PGresult *results, int lineno, PGconn *connection, enum COMPAT_MODE compat)
 
void sqlprint (void)
 

Macro Definition Documentation

#define POSTGRES_ECPG_INTERNAL

Definition at line 3 of file error.c.

Function Documentation

bool ecpg_check_PQresult ( PGresult results,
int  lineno,
PGconn connection,
enum COMPAT_MODE  compat 
)

Definition at line 283 of file error.c.

References ECPG_EMPTY, ecpg_log(), ecpg_raise(), ecpg_raise_backend(), ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, NULL, PGRES_BAD_RESPONSE, PGRES_COMMAND_OK, PGRES_COPY_IN, PGRES_COPY_OUT, PGRES_EMPTY_QUERY, PGRES_FATAL_ERROR, PGRES_NONFATAL_ERROR, PGRES_TUPLES_OK, PQclear(), PQendcopy(), PQerrorMessage(), PQresultErrorMessage(), and PQresultStatus().

Referenced by deallocate_one(), ecpg_autostart_transaction(), ecpg_execute(), ecpg_is_type_an_array(), ECPGdescribe(), ECPGsetcommit(), ECPGtrans(), and prepare_common().

284 {
285  if (results == NULL)
286  {
287  ecpg_log("ecpg_check_PQresult on line %d: no result - %s", lineno, PQerrorMessage(connection));
288  ecpg_raise_backend(lineno, NULL, connection, compat);
289  return (false);
290  }
291 
292  switch (PQresultStatus(results))
293  {
294 
295  case PGRES_TUPLES_OK:
296  return (true);
297  break;
298  case PGRES_EMPTY_QUERY:
299  /* do nothing */
301  PQclear(results);
302  return (false);
303  break;
304  case PGRES_COMMAND_OK:
305  return (true);
306  break;
308  case PGRES_FATAL_ERROR:
309  case PGRES_BAD_RESPONSE:
310  ecpg_log("ecpg_check_PQresult on line %d: bad response - %s", lineno, PQresultErrorMessage(results));
311  ecpg_raise_backend(lineno, results, connection, compat);
312  PQclear(results);
313  return (false);
314  break;
315  case PGRES_COPY_OUT:
316  return (true);
317  break;
318  case PGRES_COPY_IN:
319  ecpg_log("ecpg_check_PQresult on line %d: COPY IN data transfer in progress\n", lineno);
320  PQendcopy(connection);
321  PQclear(results);
322  return (false);
323  break;
324  default:
325  ecpg_log("ecpg_check_PQresult on line %d: unknown execution status type\n",
326  lineno);
327  ecpg_raise_backend(lineno, results, connection, compat);
328  PQclear(results);
329  return (false);
330  break;
331  }
332 }
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:6097
#define ECPG_SQLSTATE_ECPG_INTERNAL_ERROR
Definition: extern.h:220
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:2596
#define ECPG_EMPTY
Definition: ecpgerrno.h:30
void ecpg_log(const char *format,...) pg_attribute_printf(1
void ecpg_raise_backend(int line, PGresult *result, PGconn *conn, int compat)
Definition: error.c:219
void ecpg_raise(int line, int code, const char *sqlstate, const char *str)
Definition: error.c:13
enum COMPAT_MODE compat
Definition: ecpg.c:25
void PQclear(PGresult *res)
Definition: fe-exec.c:650
int PQendcopy(PGconn *conn)
Definition: fe-exec.c:2522
#define NULL
Definition: c.h:229
char * PQresultErrorMessage(const PGresult *res)
Definition: fe-exec.c:2612
void ecpg_raise ( int  line,
int  code,
const char *  sqlstate,
const char *  str 
)

Definition at line 13 of file error.c.

References ECPG_ARRAY_INSERT, ECPG_CONNECT, ECPG_CONVERT_BOOL, ECPG_DATA_NOT_ARRAY, ECPG_EMPTY, ECPG_FLOAT_FORMAT, ecpg_gettext, ECPG_INT_FORMAT, ECPG_INVALID_DESCRIPTOR_INDEX, ECPG_INVALID_STMT, ecpg_log(), ECPG_MISSING_INDICATOR, ECPG_NO_ARRAY, ECPG_NO_CONN, ECPG_NOT_CONN, ECPG_NOT_FOUND, ECPG_OUT_OF_MEMORY, ECPG_TOO_FEW_ARGUMENTS, ECPG_TOO_MANY_ARGUMENTS, ECPG_TRANS, ECPG_UINT_FORMAT, ECPG_UNKNOWN_DESCRIPTOR, ECPG_UNKNOWN_DESCRIPTOR_ITEM, ECPG_UNSUPPORTED, ECPG_VAR_NOT_CHAR, ECPG_VAR_NOT_NUMERIC, ECPGfree_auto_mem(), ECPGget_sqlca(), NULL, snprintf(), sqlca, sqlca_t::sqlcode, sqlca_t::sqlerrm, sqlca_t::sqlerrmc, sqlca_t::sqlerrml, and sqlca_t::sqlstate.

Referenced by deallocate_one(), ecpg_alloc(), ecpg_build_params(), ecpg_check_PQresult(), ecpg_do_prologue(), ecpg_find_desc(), ecpg_get_data(), ecpg_init(), ecpg_process_output(), ecpg_realloc(), ecpg_store_input(), ecpg_store_result(), ecpg_strdup(), ECPGallocate_desc(), ECPGconnect(), ECPGdeallocate(), ECPGdeallocate_desc(), ECPGdescribe(), ECPGdisconnect(), ECPGget_desc(), ECPGget_desc_header(), ECPGset_desc(), ECPGset_var(), ECPGstatus(), get_char_item(), get_int_item(), and set_int_item().

14 {
15  struct sqlca_t *sqlca = ECPGget_sqlca();
16 
17  if (sqlca == NULL)
18  {
19  ecpg_log("out of memory");
21  return;
22  }
23 
24  sqlca->sqlcode = code;
25  strncpy(sqlca->sqlstate, sqlstate, sizeof(sqlca->sqlstate));
26 
27  switch (code)
28  {
29  case ECPG_NOT_FOUND:
30  snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
31  /*------
32  translator: this string will be truncated at 149 characters expanded. */
33  ecpg_gettext("no data found on line %d"), line);
34  break;
35 
36  case ECPG_OUT_OF_MEMORY:
37  snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
38  /*------
39  translator: this string will be truncated at 149 characters expanded. */
40  ecpg_gettext("out of memory on line %d"), line);
41  break;
42 
43  case ECPG_UNSUPPORTED:
44  snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
45  /*------
46  translator: this string will be truncated at 149 characters expanded. */
47  ecpg_gettext("unsupported type \"%s\" on line %d"), str, line);
48  break;
49 
51  snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
52  /*------
53  translator: this string will be truncated at 149 characters expanded. */
54  ecpg_gettext("too many arguments on line %d"), line);
55  break;
56 
58  snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
59  /*------
60  translator: this string will be truncated at 149 characters expanded. */
61  ecpg_gettext("too few arguments on line %d"), line);
62  break;
63 
64  case ECPG_INT_FORMAT:
65  snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
66  /*------
67  translator: this string will be truncated at 149 characters expanded. */
68  ecpg_gettext("invalid input syntax for type int: \"%s\", on line %d"), str, line);
69  break;
70 
71  case ECPG_UINT_FORMAT:
72  snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
73  /*------
74  translator: this string will be truncated at 149 characters expanded. */
75  ecpg_gettext("invalid input syntax for type unsigned int: \"%s\", on line %d"), str, line);
76  break;
77 
78  case ECPG_FLOAT_FORMAT:
79  snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
80  /*------
81  translator: this string will be truncated at 149 characters expanded. */
82  ecpg_gettext("invalid input syntax for floating-point type: \"%s\", on line %d"), str, line);
83  break;
84 
85  case ECPG_CONVERT_BOOL:
86  if (str)
87  snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
88  /*------
89  translator: this string will be truncated at 149 characters expanded. */
90  ecpg_gettext("invalid syntax for type boolean: \"%s\", on line %d"), str, line);
91  else
92  snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
93  /*------
94  translator: this string will be truncated at 149 characters expanded. */
95  ecpg_gettext("could not convert boolean value: size mismatch, on line %d"), line);
96  break;
97 
98  case ECPG_EMPTY:
99  snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
100  /*------
101  translator: this string will be truncated at 149 characters expanded. */
102  ecpg_gettext("empty query on line %d"), line);
103  break;
104 
106  snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
107  /*------
108  translator: this string will be truncated at 149 characters expanded. */
109  ecpg_gettext("null value without indicator on line %d"), line);
110  break;
111 
112  case ECPG_NO_ARRAY:
113  snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
114  /*------
115  translator: this string will be truncated at 149 characters expanded. */
116  ecpg_gettext("variable does not have an array type on line %d"), line);
117  break;
118 
119  case ECPG_DATA_NOT_ARRAY:
120  snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
121  /*------
122  translator: this string will be truncated at 149 characters expanded. */
123  ecpg_gettext("data read from server is not an array on line %d"), line);
124  break;
125 
126  case ECPG_ARRAY_INSERT:
127  snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
128  /*------
129  translator: this string will be truncated at 149 characters expanded. */
130  ecpg_gettext("inserting an array of variables is not supported on line %d"), line);
131  break;
132 
133  case ECPG_NO_CONN:
134  snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
135  /*------
136  translator: this string will be truncated at 149 characters expanded. */
137  ecpg_gettext("connection \"%s\" does not exist on line %d"), str, line);
138  break;
139 
140  case ECPG_NOT_CONN:
141  snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
142  /*------
143  translator: this string will be truncated at 149 characters expanded. */
144  ecpg_gettext("not connected to connection \"%s\" on line %d"), str, line);
145  break;
146 
147  case ECPG_INVALID_STMT:
148  snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
149  /*------
150  translator: this string will be truncated at 149 characters expanded. */
151  ecpg_gettext("invalid statement name \"%s\" on line %d"), str, line);
152  break;
153 
155  snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
156  /*------
157  translator: this string will be truncated at 149 characters expanded. */
158  ecpg_gettext("descriptor \"%s\" not found on line %d"), str, line);
159  break;
160 
162  snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
163  /*------
164  translator: this string will be truncated at 149 characters expanded. */
165  ecpg_gettext("descriptor index out of range on line %d"), line);
166  break;
167 
169  snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
170  /*------
171  translator: this string will be truncated at 149 characters expanded. */
172  ecpg_gettext("unrecognized descriptor item \"%s\" on line %d"), str, line);
173  break;
174 
176  snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
177  /*------
178  translator: this string will be truncated at 149 characters expanded. */
179  ecpg_gettext("variable does not have a numeric type on line %d"), line);
180  break;
181 
182  case ECPG_VAR_NOT_CHAR:
183  snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
184  /*------
185  translator: this string will be truncated at 149 characters expanded. */
186  ecpg_gettext("variable does not have a character type on line %d"), line);
187  break;
188 
189  case ECPG_TRANS:
190  snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
191  /*------
192  translator: this string will be truncated at 149 characters expanded. */
193  ecpg_gettext("error in transaction processing on line %d"), line);
194  break;
195 
196  case ECPG_CONNECT:
197  snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
198  /*------
199  translator: this string will be truncated at 149 characters expanded. */
200  ecpg_gettext("could not connect to database \"%s\" on line %d"), str, line);
201  break;
202 
203  default:
204  snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
205  /*------
206  translator: this string will be truncated at 149 characters expanded. */
207  ecpg_gettext("SQL error %d on line %d"), code, line);
208  break;
209  }
210 
211  sqlca->sqlerrm.sqlerrml = strlen(sqlca->sqlerrm.sqlerrmc);
212  ecpg_log("raising sqlcode %d on line %d: %s\n", code, line, sqlca->sqlerrm.sqlerrmc);
213 
214  /* free all memory we have allocated for the user */
216 }
#define ECPG_DATA_NOT_ARRAY
Definition: ecpgerrno.h:33
#define ECPG_CONNECT
Definition: ecpgerrno.h:51
#define ECPG_NOT_CONN
Definition: ecpgerrno.h:37
struct sqlca_t::@124 sqlerrm
void ECPGfree_auto_mem(void)
Definition: memory.c:138
#define sqlca
Definition: sqlca.h:59
#define ECPG_INVALID_STMT
Definition: ecpgerrno.h:39
#define ECPG_VAR_NOT_CHAR
Definition: ecpgerrno.h:46
#define ECPG_CONVERT_BOOL
Definition: ecpgerrno.h:29
#define ECPG_INVALID_DESCRIPTOR_INDEX
Definition: ecpgerrno.h:43
#define ECPG_UNKNOWN_DESCRIPTOR_ITEM
Definition: ecpgerrno.h:44
int sqlerrml
Definition: sqlca.h:26
#define ECPG_TOO_MANY_ARGUMENTS
Definition: ecpgerrno.h:19
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define ECPG_UINT_FORMAT
Definition: ecpgerrno.h:23
#define ECPG_EMPTY
Definition: ecpgerrno.h:30
#define ECPG_TRANS
Definition: ecpgerrno.h:50
void ecpg_log(const char *format,...) pg_attribute_printf(1
#define ECPG_OUT_OF_MEMORY
Definition: ecpgerrno.h:15
struct sqlca_t * ECPGget_sqlca(void)
Definition: misc.c:142
#define ECPG_NO_ARRAY
Definition: ecpgerrno.h:32
Definition: sqlca.h:19
#define ECPG_FLOAT_FORMAT
Definition: ecpgerrno.h:24
#define ECPG_UNSUPPORTED
Definition: ecpgerrno.h:18
char sqlstate[5]
Definition: sqlca.h:53
#define ECPG_ARRAY_INSERT
Definition: ecpgerrno.h:34
#define ECPG_MISSING_INDICATOR
Definition: ecpgerrno.h:31
#define ECPG_NOT_FOUND
Definition: ecpgerrno.h:10
long sqlcode
Definition: sqlca.h:23
#define ecpg_gettext(x)
Definition: ecpglib.h:18
#define ECPG_VAR_NOT_NUMERIC
Definition: ecpgerrno.h:45
#define ECPG_UNKNOWN_DESCRIPTOR
Definition: ecpgerrno.h:42
#define NULL
Definition: c.h:229
#define ECPG_TOO_FEW_ARGUMENTS
Definition: ecpgerrno.h:20
char sqlerrmc[SQLERRMC_LEN]
Definition: sqlca.h:27
#define ECPG_INT_FORMAT
Definition: ecpgerrno.h:22
#define ECPG_NO_CONN
Definition: ecpgerrno.h:36
void ecpg_raise_backend ( int  line,
PGresult result,
PGconn conn,
int  compat 
)

Definition at line 219 of file error.c.

References CONNECTION_BAD, ECPG_DUPLICATE_KEY, ecpg_gettext, ECPG_INFORMIX_DUPLICATE_KEY, ECPG_INFORMIX_SUBSELECT_NOT_ONE, ecpg_log(), ECPG_PGSQL, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, ECPG_SUBSELECT_NOT_ONE, ECPGfree_auto_mem(), ECPGget_sqlca(), INFORMIX_MODE, NULL, PG_DIAG_MESSAGE_PRIMARY, PG_DIAG_SQLSTATE, PQerrorMessage(), PQresultErrorField(), PQstatus(), snprintf(), sqlca, sqlca_t::sqlcode, sqlca_t::sqlerrm, sqlca_t::sqlerrmc, sqlca_t::sqlerrml, and sqlca_t::sqlstate.

Referenced by ecpg_check_PQresult(), and ecpg_process_output().

220 {
221  struct sqlca_t *sqlca = ECPGget_sqlca();
222  char *sqlstate;
223  char *message;
224 
225  if (sqlca == NULL)
226  {
227  ecpg_log("out of memory");
229  return;
230  }
231 
232  if (result)
233  {
234  sqlstate = PQresultErrorField(result, PG_DIAG_SQLSTATE);
235  if (sqlstate == NULL)
237  message = PQresultErrorField(result, PG_DIAG_MESSAGE_PRIMARY);
238  }
239  else
240  {
242  message = PQerrorMessage(conn);
243  }
244 
245  if (strcmp(sqlstate, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR) == 0)
246  {
247  /*
248  * we might get here if the connection breaks down, so let's check for
249  * this instead of giving just the generic internal error
250  */
251  if (PQstatus(conn) == CONNECTION_BAD)
252  {
253  sqlstate = "57P02";
254  message = ecpg_gettext("the connection to the server was lost");
255  }
256  }
257 
258  /* copy error message */
259  snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc), "%s on line %d", message, line);
260  sqlca->sqlerrm.sqlerrml = strlen(sqlca->sqlerrm.sqlerrmc);
261 
262  /* copy SQLSTATE */
263  strncpy(sqlca->sqlstate, sqlstate, sizeof(sqlca->sqlstate));
264 
265  /* assign SQLCODE for backward compatibility */
266  if (strncmp(sqlca->sqlstate, "23505", sizeof(sqlca->sqlstate)) == 0)
268  else if (strncmp(sqlca->sqlstate, "21000", sizeof(sqlca->sqlstate)) == 0)
270  else
271  sqlca->sqlcode = ECPG_PGSQL;
272 
273  /* %.*s is safe here as long as sqlstate is all-ASCII */
274  ecpg_log("raising sqlstate %.*s (sqlcode %ld): %s\n",
275  (int) sizeof(sqlca->sqlstate), sqlca->sqlstate, sqlca->sqlcode, sqlca->sqlerrm.sqlerrmc);
276 
277  /* free all memory we have allocated for the user */
279 }
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:6097
#define ECPG_SQLSTATE_ECPG_INTERNAL_ERROR
Definition: extern.h:220
#define PG_DIAG_MESSAGE_PRIMARY
Definition: postgres_ext.h:58
struct sqlca_t::@124 sqlerrm
void ECPGfree_auto_mem(void)
Definition: memory.c:138
#define INFORMIX_MODE(X)
Definition: extern.h:23
#define sqlca
Definition: sqlca.h:59
int sqlerrml
Definition: sqlca.h:26
#define ECPG_PGSQL
Definition: ecpgerrno.h:49
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:57
void ecpg_log(const char *format,...) pg_attribute_printf(1
struct sqlca_t * ECPGget_sqlca(void)
Definition: misc.c:142
#define ECPG_SUBSELECT_NOT_ONE
Definition: ecpgerrno.h:53
Definition: sqlca.h:19
#define ECPG_INFORMIX_DUPLICATE_KEY
Definition: ecpgerrno.h:57
char sqlstate[5]
Definition: sqlca.h:53
enum COMPAT_MODE compat
Definition: ecpg.c:25
long sqlcode
Definition: sqlca.h:23
#define ecpg_gettext(x)
Definition: ecpglib.h:18
char * PQresultErrorField(const PGresult *res, int fieldcode)
Definition: fe-exec.c:2658
#define NULL
Definition: c.h:229
#define ECPG_DUPLICATE_KEY
Definition: ecpgerrno.h:52
#define ECPG_INFORMIX_SUBSELECT_NOT_ONE
Definition: ecpgerrno.h:58
char sqlerrmc[SQLERRMC_LEN]
Definition: sqlca.h:27
ConnStatusType PQstatus(const PGconn *conn)
Definition: fe-connect.c:6044
void sqlprint ( void  )

Definition at line 336 of file error.c.

References ecpg_gettext, ecpg_log(), ECPGget_sqlca(), NULL, sqlca, sqlca_t::sqlerrm, sqlca_t::sqlerrmc, and sqlca_t::sqlerrml.

Referenced by fn(), main(), print(), print2(), and test().

337 {
338  struct sqlca_t *sqlca = ECPGget_sqlca();
339 
340  if (sqlca == NULL)
341  {
342  ecpg_log("out of memory");
343  return;
344  }
345 
346  sqlca->sqlerrm.sqlerrmc[sqlca->sqlerrm.sqlerrml] = '\0';
347  fprintf(stderr, ecpg_gettext("SQL error: %s\n"), sqlca->sqlerrm.sqlerrmc);
348 }
struct sqlca_t::@124 sqlerrm
#define sqlca
Definition: sqlca.h:59
int sqlerrml
Definition: sqlca.h:26
void ecpg_log(const char *format,...) pg_attribute_printf(1
struct sqlca_t * ECPGget_sqlca(void)
Definition: misc.c:142
Definition: sqlca.h:19
#define ecpg_gettext(x)
Definition: ecpglib.h:18
#define NULL
Definition: c.h:229
char sqlerrmc[SQLERRMC_LEN]
Definition: sqlca.h:27