pike.git
/
lib
/
modules
/
Sql.pmod
/
mysql.pike
version
»
Context lines:
10
20
40
80
file
none
3
pike.git/lib/modules/Sql.pmod/mysql.pike:43:
//! unix timestamps on integer form. //! //! @item String types //! All string types are returned as pike strings. The MySQL glue //! can handle charset conversions for text strings - see //! @[set_charset] and @[set_unicode_decode_mode]. //! //! @enddl //! //! @endsection
+
//!
+
//! @seealso
+
//! @[Sql.Connection], @[Sql.Sql()]
#pike __REAL_VERSION__ #require constant(Mysql.mysql) // Cannot dump this since the #require check may depend on the // presence of system libs at runtime.
-
constant dont_dump_program = 1;
+
optional
constant dont_dump_program = 1;
-
+
//!
inherit Mysql.mysql; #define UNICODE_DECODE_MODE 1 // Unicode decode mode #define LATIN1_UNICODE_ENCODE_MODE 2 // Unicode encode mode with latin1 charset #define UTF8_UNICODE_ENCODE_MODE 4 // Unicode encode mode with utf8 charset #ifdef MYSQL_CHARSET_DEBUG #define CH_DEBUG(X...) \ werror(replace (sprintf ("%O", this), "%", "%%") + ": " + X) #else
pike.git/lib/modules/Sql.pmod/mysql.pike:398:
//! //! @param s //! String to quote. string quote(string s) { return replace(s, ({ "\\", "\"", "\0", "\'", "\n", "\r" }), ({ "\\\\", "\\\"", "\\0", "\\\'", "\\n", "\\r" })); }
-
string latin1_to_utf8 (string s)
+
string latin1_to_utf8 (string s
, int extended
)
//! Converts a string in MySQL @expr{latin1@} format to UTF-8. { return string_to_utf8 (replace (s, ([ "\x80": "\u20AC", /*"\x81": "\u0081",*/ "\x82": "\u201A", "\x83": "\u0192", "\x84": "\u201E", "\x85": "\u2026", "\x86": "\u2020", "\x87": "\u2021", "\x88": "\u02C6", "\x89": "\u2030", "\x8a": "\u0160", "\x8b": "\u2039", "\x8c": "\u0152", /*"\x8d": "\u008D",*/ "\x8e": "\u017D", /*"\x8f": "\u008F",*/ /*"\x90": "\u0090",*/ "\x91": "\u2018", "\x92": "\u2019", "\x93": "\u201C", "\x94": "\u201D", "\x95": "\u2022", "\x96": "\u2013", "\x97": "\u2014", "\x98": "\u02DC", "\x99": "\u2122", "\x9a": "\u0161", "\x9b": "\u203A", "\x9c": "\u0153", /*"\x9d": "\u009D",*/ "\x9e": "\u017E", "\x9f": "\u0178",
-
])));
+
]))
, extended
);
}
-
string utf8_encode_query (string q, function(string:string) encode_fn)
+
string utf8_encode_query (string q,
+
function(string
, mixed|void...
:string) encode_fn
,
+
mixed ... extras
)
//! Encodes the appropriate sections of the query with @[encode_fn]. //! Everything except strings prefixed by an introducer (i.e. //! @expr{_something@} or @expr{N@}) is encoded. { // We need to find the segments that shouldn't be encoded. string e = ""; while (1) { sscanf(q, "%[^\'\"]%s", string prefix, string suffix);
-
e += encode_fn (prefix);
+
e += encode_fn (prefix
, @extras
);
if (suffix == "") break; string quote = suffix[..0]; int start = 1; int end; while ((end = search(suffix, quote, start)) >= 0) { if (suffix[end-1] == '\\') { // Count the number of preceding back-slashes. // if odd, continue searching after the quote.
pike.git/lib/modules/Sql.pmod/mysql.pike:518:
else encoding = "utf8"; // Gotta be "N". s = s[1..<1]; if (sizeof (s) > 40) s = sprintf ("%O...", s[..37]); else s = sprintf ("%O", s); predef::error ("A string in the query should be %s encoded " "but it is wide: %s\n", encoding, s); } e += s; } else {
-
e += encode_fn (suffix[..end]);
+
e += encode_fn (suffix[..end]
, @extras
);
} q = suffix[end+1..]; } return e; }
-
// The following time conversion functions assumes the SQL server
-
// handles time in this local timezone. They map the special zero
-
// time/date spec to 0.
-
-
private constant timezone = localtime (0)->timezone;
-
+
//! Converts a system time value to an appropriately formatted time //! spec for the database. //! //! @param time //! Time to encode. //! //! @param date //! If nonzero then time is taken as a "full" unix time spec //! (where the date part is ignored), otherwise it's converted as a //! seconds-since-midnight value. string encode_time (int time, void|int date) {
-
if (date) {
-
if (!time)
return
"000000";
-
mapping(string
:
int) ct = localtime (
time
);
-
return sprintf
(
"%02d%02d%02d"
,
ct->hour,
ct
-
>min,
ct->sec)
;
+
return :
:encode_time
(time
, date
)
-
"
:
";
}
-
else return sprintf ("%02d%02d%02d", time / 3600 % 24, time / 60 % 60, time % 60);
-
}
+
//! Converts a system time value to an appropriately formatted //! date-only spec for the database. //! //! @param time //! Time to encode. string encode_date (int time) {
-
if (!time)
return
"00000000";
-
mapping(string
:
int) ct = localtime
(time)
;
-
return sprintf (
"
%04d%02d%02d", ct
-
>year + 1900, ct->mon + 1, ct->mday)
;
+
return :
:encode_date
(time)
-
"
-
";
} //! Converts a system time value to an appropriately formatted //! date and time spec for the database. //! //! @param time //! Time to encode. string encode_datetime (int time) {
-
if (!time)
return
"00000000000000";
-
mapping
(
string
:
int) ct = localtime
(time)
;
-
return sprintf
("
%04d%02d%02d%02d%02d%02d
",
-
ct->year + 1900
,
ct->mon + 1, ct->mday,
-
ct->hour, ct->min, ct->sec
);
+
return
replace
(:
:encode_datetime
(time)
,
"-:T"/"",
(
{
"",
""
,
""}
)
)
;
}
-
//! Converts a database time spec to a system time value.
-
//!
-
//! @param timestr
-
//! Time spec to decode.
-
//!
-
//! @param date
-
//! Take the date part from this system time value. If zero, a
-
//! seconds-since-midnight value is returned.
-
int decode_time (string timestr, void|int date)
-
{
-
int hour = 0, min = 0, sec = 0;
-
if (sscanf (timestr, "%d:%d:%d", hour, min, sec) <= 1)
-
sscanf (timestr, "%2d%2d%2d", hour, min, sec);
-
if (date && (hour || min || sec)) {
-
mapping(string:int) ct = localtime (date);
-
return mktime (sec, min, hour, ct->mday, ct->mon, ct->year, ct->isdst, ct->timezone);
-
}
-
else return (hour * 60 + min) * 60 + sec;
-
}
-
-
//! Converts a database date-only spec to a system time value.
-
//! Assumes 4-digit years.
-
//!
-
//! @param datestr
-
//! Date spec to decode.
-
int decode_date (string datestr)
-
{
-
int year = 0, mon = 0, mday = 0, n;
-
n = sscanf (datestr, "%d-%d-%d", year, mon, mday);
-
if (n <= 1) n = sscanf (datestr, "%4d%2d%2d", year, mon, mday);
-
if (year || mon || mday)
-
return mktime (0, 0, 0, n == 3 ? mday : 1, n >= 2 && mon - 1, year - 1900,
-
-1, timezone);
-
else return 0;
-
}
-
-
//! Converts a database date and time spec to a system time value.
-
//! Can decode strings missing the time part.
-
//!
-
//! @param datestr
-
//! Date and time spec to decode.
-
int decode_datetime (string timestr)
-
{
-
array(string) a = timestr / " ";
-
if (sizeof (a) == 2)
-
return decode_date (a[0]) + decode_time (a[1]);
-
else {
-
int n = sizeof (timestr);
-
if (n >= 12)
-
return decode_date (timestr[..n-7]) + decode_time (timestr[n-6..n-1]);
-
else
-
return decode_date (timestr);
-
}
-
}
-
+
#if constant (Mysql.mysql.HAVE_MYSQL_FIELD_CHARSETNR) #define HAVE_MYSQL_FIELD_CHARSETNR_IFELSE(TRUE, FALSE) TRUE #else #define HAVE_MYSQL_FIELD_CHARSETNR_IFELSE(TRUE, FALSE) FALSE #endif #define QUERY_BODY(do_query) \ if (bindings) \ query = .sql_util.emulate_bindings(query,bindings,this); \ \
pike.git/lib/modules/Sql.pmod/mysql.pike:664:
} \ \ else if (send_charset) { \ string new_send_charset = send_charset; \ \ if (utf8_mode & LATIN1_UNICODE_ENCODE_MODE) { \ if (String.width (query) == 8) \ new_send_charset = "latin1"; \ else { \ CH_DEBUG ("Converting (mysql-)latin1 query to utf8.\n"); \
-
query = utf8_encode_query (query, latin1_to_utf8);
\
+
query = utf8_encode_query (query, latin1_to_utf8
, 2
); \
new_send_charset = "utf8"; \ } \ } \ \ else { /* utf8_mode & UTF8_UNICODE_ENCODE_MODE */ \ /* NB: The send_charset may only be upgraded from \ * "latin1" to "utf8", not the other way around. \ * This is to avoid extraneous charset changes \ * where the charset is changed from query to query. \ */ \ if ((send_charset == "utf8") || !_can_send_as_latin1(query)) { \ CH_DEBUG ("Converting query to utf8.\n"); \
-
query = utf8_encode_query (query, string_to_utf8);
\
+
query = utf8_encode_query (query, string_to_utf8
, 2
); \
new_send_charset = "utf8"; \ } \ } \ \ if (new_send_charset != send_charset) { \ CH_DEBUG ("Switching charset from %O to %O.\n", \ send_charset, new_send_charset); \ if (mixed err = catch { \ ::big_query ("SET character_set_client=" + new_send_charset); \ /* Can't be changed automatically - has side effects. /mast */ \
pike.git/lib/modules/Sql.pmod/mysql.pike:732:
\ if (utf8_mode & UNICODE_DECODE_MODE) { \ CH_DEBUG ("Using unicode wrapper for result.\n"); \ return \ HAVE_MYSQL_FIELD_CHARSETNR_IFELSE ( \ .sql_util.MySQLUnicodeWrapper(res), \ .sql_util.MySQLBrokenUnicodeWrapper (res)); \ } \ return res;
-
Result big_query (string query,
+
variant
Result big_query (string query,
mapping(string|int:mixed)|void bindings, void|string charset) //! Sends a query to the server. //! //! @param query //! The SQL query. //! //! @param bindings //! An optional bindings mapping. See @[Sql.query] for details about //! this.
pike.git/lib/modules/Sql.pmod/mysql.pike:771:
//! //! The individual fields are returned as strings except for @tt{NULL@}, //! which is returned as @[UNDEFINED]. //! //! @seealso //! @[Sql.big_query()], @[big_typed_query()], @[streaming_query()] { QUERY_BODY (big_query); }
-
Result streaming_query (string query,
+
variant
Result streaming_query (string query,
mapping(string|int:mixed)|void bindings, void|string charset) //! Makes a streaming SQL query. //! //! This function sends the SQL query @[query] to the Mysql-server. //! The result of the query is streamed through the returned //! @[Result] object. Note that the involved database //! tables are locked until all the results has been read. //! //! In all other respects, it behaves like @[big_query]. //! //! @seealso //! @[big_query()], @[streaming_typed_query()] { QUERY_BODY (streaming_query); }
-
Result big_typed_query (string query,
+
variant
Result big_typed_query (string query,
mapping(string|int:mixed)|void bindings, void|string charset) //! Makes a typed SQL query. //! //! This function sends the SQL query @[query] to the MySQL server and //! returns a result object in typed mode, which means that the types //! of the result fields depend on the corresponding SQL types. See //! the class docs for details. //! //! In all other respects, it behaves like @[big_query]. //! //! @seealso //! @[big_query()], @[streaming_typed_query()] { QUERY_BODY (big_typed_query); }
-
Result streaming_typed_query (string query,
+
variant
Result streaming_typed_query (string query,
mapping(string|int:mixed)|void bindings, void|string charset) //! Makes a streaming typed SQL query. //! //! This function acts as the combination of @[streaming_query()] //! and @[big_typed_query()]. //! //! @seealso //! @[big_typed_query()], @[streaming_typed_query()] { QUERY_BODY (streaming_typed_query); }
-
+
array(string) list_dbs(string|void wild)
+
{
+
Result res = ::list_dbs(wild);
+
array(string) ret = ({});
+
array(string) row;
+
while((row = res->fetch_row()) && sizeof(row)) {
+
ret += ({ row[0] });
+
}
+
return ret;
+
}
+
+
array(string) list_tables(string|void wild)
+
{
+
Result res = ::list_tables(wild);
+
array(string) ret = ({});
+
array(string) row;
+
while((row = res->fetch_row()) && sizeof(row)) {
+
ret += ({ row[0] });
+
}
+
return ret;
+
}
+
int(0..1) is_keyword( string name ) //! Return 1 if the argument @[name] is a mysql keyword that needs to //! be quoted in a query. The list is currently up-to-date with MySQL //! 5.1. { return ([ "accessible": 1, "add": 1, "all": 1, "alter": 1, "analyze": 1, "and": 1, "as": 1, "asc": 1, "asensitive": 1, "before": 1, "between": 1, "bigint": 1, "binary": 1, "blob": 1, "both": 1, "by": 1, "call": 1, "cascade": 1, "case": 1, "change": 1, "char": 1, "character": 1, "check": 1, "collate": 1,