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 #if constant(...) check below may depend
- // on the presence of system libs at runtime.
- constant dont_dump_program = 1;
+ // Cannot dump this since the #require check may depend on the
+ // presence of system libs at runtime.
+ optional constant dont_dump_program = 1;
- #if constant(Mysql.mysql)
-
+ //!
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:399:
//!
//! @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:519:
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:665:
} \
\
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:733:
\
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;
- Mysql.mysql_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:760:
//! @endcode
//! is sent to the server first, then @[query] is sent as-is, and then
//! the connection charset is restored again (if necessary).
//!
//! Primarily useful with @[charset] set to @expr{"latin1"@} if
//! unicode encode mode (see @[set_unicode_encode_mode]) is enabled
//! (the default) and you have some large queries (typically blob
//! inserts) where you want to avoid the query parsing overhead.
//!
//! @returns
- //! A @[Mysql.mysql_result] object is returned if the query is of a
+ //! A @[Result] object is returned if the query is of a
//! kind that returns a result. Zero is returned otherwise.
//!
//! 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);
}
- Mysql.mysql_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
- //! @[Mysql.mysql_result] object. Note that the involved database
+ //! @[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);
}
- Mysql.mysql_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);
}
- Mysql.mysql_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,
pike.git/lib/modules/Sql.pmod/mysql.pike:938: Inside #if !constant (Mysql.mysql.HAVE_MYSQL_FIELD_CHARSETNR)
predef::error ("Unicode decode mode not supported - "
"compiled with MySQL client library < 4.1.0.\n");
#endif
} else {
::create(host||"", database||"", user||"", password||"");
update_unicode_encode_mode_from_charset ("latin1");
}
}
-
- #else
- constant this_program_does_not_exist=1;
- #endif /* constant(Mysql.mysql) */
+