#pike __REAL_VERSION__ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define ERROR(X ...) predef::error(X) |
|
|
|
|
|
|
|
|
__deprecated__ this_program `master_sql() |
{ |
return this; |
} |
|
|
|
|
|
|
|
|
|
|
int(0..1) case_convert; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
string quote(string s) |
{ |
return replace(s, "\'", "\'\'"); |
} |
|
private constant timezone = localtime (0)->timezone; |
|
|
|
|
|
|
|
|
|
|
|
|
|
string encode_time(int time, int|void date) |
{ |
if (date) { |
if (!time) return "00:00:00"; |
mapping(string:int) ct = localtime (time); |
return sprintf("%02d:%02d:%02d", ct->hour, ct->min, ct->sec); |
} |
else |
return sprintf("%02d:%02d:%02d", |
(time / 3600) % 24, |
(time / 60) % 60, |
time % 60); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
int decode_time(string timestr, int|void 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; |
} |
|
|
|
|
|
|
|
|
string encode_date(int time) |
{ |
if (!time) return "0000-00-00"; |
mapping(string:int) ct = localtime (time); |
return sprintf("%04d-%02d-%02d", ct->year + 1900, ct->mon + 1, ct->mday); |
} |
|
|
|
|
|
|
|
|
|
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; |
} |
|
|
|
|
|
|
|
|
string encode_datetime(int time) |
{ |
if (!time) return "0000-00-00T00:00:00"; |
mapping(string:int) ct = localtime (time); |
return sprintf ("%04d-%02d-%02dT%02d:%02d:%02d", |
ct->year + 1900, ct->mon + 1, ct->mday, |
ct->hour, ct->min, ct->sec); |
} |
|
|
|
|
|
|
|
|
|
|
|
int decode_datetime(string datetime) |
{ |
array(string) a = datetime / "T"; |
if (sizeof (a) == 2) |
return decode_date(a[0]) + decode_time(a[1]); |
|
a = datetime / " "; |
if (sizeof (a) == 2) |
return decode_date(a[0]) + decode_time(a[1]); |
|
int n = sizeof(datetime); |
if (n >= 12) |
return decode_date(datetime[..n-7]) + decode_time(datetime[n-6..n-1]); |
else |
return decode_date(datetime); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void create(string host, void|string|mapping(string:int|string) db, |
void|string user, void|string _password, |
void|mapping(string:int|string) options); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int is_open() |
{ |
return 1; |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int ping() |
{ |
if (!is_open()) return -1; |
catch { |
return sizeof(query("SELECT 0 AS zero") || ({})) - 1; |
}; |
return -1; |
} |
|
void set_charset (string charset) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{ |
predef::error("This database connection does not " |
"support charset switching.\n"); |
} |
|
string get_charset() |
|
|
|
|
|
|
|
{ |
return UNDEFINED; |
} |
|
protected array(mapping(string:mixed)) res_obj_to_array(.Result res_obj) |
{ |
if (!res_obj) |
return 0; |
|
array(mapping(string:mixed)) res = ({}); |
while (res_obj) |
{ |
|
array(string) fieldnames; |
array(mixed) row; |
|
array(mapping) fields = res_obj->fetch_fields(); |
if(!sizeof(fields)) return ({}); |
|
int has_table = fields[0]->table && fields[0]->table!=""; |
|
if(has_table) |
fieldnames = (map(fields, |
lambda (mapping(string:mixed) m) { |
return (m->table||"") + "." + m->name; |
}) + |
fields->name); |
else |
fieldnames = fields->name; |
|
if (case_convert) |
fieldnames = map(fieldnames, lower_case); |
|
if(has_table) |
while (row = res_obj->fetch_row()) |
res += ({ mkmapping(fieldnames, row + row) }); |
else |
while (row = res_obj->fetch_row()) |
res += ({ mkmapping(fieldnames, row) }); |
|
|
res_obj = res_obj->next_result && res_obj->next_result(); |
} |
return res; |
} |
|
|
int|string error() |
{ |
return "Unknown error"; |
} |
|
|
|
|
string sqlstate() |
{ |
return "IM001"; |
} |
|
|
void select_db(string db); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
string|object compile_query(string q) |
{ |
return q; |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected string emulate_bindings(string query, |
mapping(string|int:mixed) bindings) |
{ |
array(string)k, v; |
v = map(values(bindings), |
lambda(mixed m) { |
if(undefinedp(m)) |
return "NULL"; |
if (objectp (m) && m->is_val_null) |
|
|
|
|
return "NULL"; |
if(multisetp(m)) |
return sizeof(m) ? indices(m)[0] : ""; |
return "'"+(intp(m)?(string)m:quote((string)m))+"'"; |
}); |
|
k = map(indices(bindings),lambda(string s){ |
return ( (stringp(s)&&s[0]==':') ? |
s : ":"+s); |
}); |
return replace(query,k,v); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected array(string|mapping(string|int:mixed)) |
handle_extraargs(string query, array(mixed) extraargs) |
{ |
array(mixed) args = allocate(sizeof(extraargs)); |
mapping(string:mixed) bindings = ([]); |
|
int a; |
foreach(extraargs; int j; mixed s) { |
if (stringp(s) || multisetp(s)) { |
string bind_name = ":arg"+(a++); |
args[j] = bind_name; |
bindings[bind_name] = s; |
continue; |
} |
if (intp(s) || floatp(s)) { |
args[j] = s || .zero; |
continue; |
} |
if (objectp(s) && s->is_val_null) { |
args[j] = .null_arg; |
continue; |
} |
ERROR("Wrong type to query argument %d: %O\n", j + 1, s); |
} |
|
query = sprintf(query, @args); |
|
if (sizeof(bindings)) return ({ query, bindings }); |
return ({ query }); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int|.Result big_query(object|string q); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
variant int|.Result big_query(object|string q, |
mapping(string|int:mixed) bindings) |
{ |
return big_query(emulate_bindings(q, bindings)); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
variant int|.Result big_query(object|string q, |
string|multiset|int|float|object extraarg, |
string|multiset|int|float|object ... extraargs) |
{ |
return big_query(@handle_extraargs(q, ({ extraarg }) + extraargs)); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
array(mapping(string:string)) query(object|string q, |
mixed ... extraargs) |
{ |
return res_obj_to_array(big_query(q, @extraargs)); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int|.Result big_typed_query(object|string q); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
variant int|.Result big_typed_query(object|string q, |
mapping(string|int:mixed) bindings) |
{ |
return big_typed_query(emulate_bindings(q, bindings)); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
variant int|.Result big_typed_query(object|string q, |
string|multiset|int|float|object extraarg, |
string|multiset|int|float|object ... extraargs) |
{ |
return big_typed_query(@handle_extraargs(q, ({ extraarg }) + extraargs)); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
array(mapping(string:mixed)) typed_query(object|string q, mixed ... extraargs) |
{ |
return res_obj_to_array(big_typed_query(q, @extraargs)); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int|.Result streaming_query(object|string q) |
{ |
return big_query(q); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
variant int|.Result streaming_query(object|string q, |
mapping(string:mixed) bindings) |
{ |
return streaming_query(emulate_bindings(q, bindings)); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
variant int|.Result streaming_query(object|string q, |
string|multiset|int|float|object extraarg, |
string|multiset|int|float|object ... extraargs) |
{ |
return streaming_query(@handle_extraargs(q, ({ extraarg }) + extraargs)); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int|.Result streaming_typed_query(object|string q) |
{ |
return big_typed_query(q); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
variant int|.Result streaming_typed_query(object|string q, |
mapping(string|int:mixed) bindings) |
{ |
return streaming_typed_query(emulate_bindings(q, bindings)); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
variant int|.Result streaming_typed_query(object|string q, |
string|multiset|int|float|object extraarg, |
string|multiset|int|float|object ... extraargs) |
{ |
return streaming_typed_query(@handle_extraargs(q, ({ extraarg }) + extraargs)); |
} |
|
|
|
|
|
void create_db(string db); |
|
|
|
|
|
void drop_db(string db); |
|
|
void shutdown() |
{ |
ERROR("Not supported by this database.\n"); |
} |
|
|
void reload() |
{ |
|
} |
|
|
string server_info() |
{ |
return "Unknown SQL-server"; |
} |
|
|
string host_info() |
{ |
return "Unknown connection to host"; |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected array(string) low_list_dbs() |
{ |
catch { |
array(mapping) res = query("SHOW DATABASES"); |
if (res && sizeof(res) && mappingp(res[0])) { |
return map(res, lambda (mapping m) { |
return values(m)[0]; |
} ); |
} |
return res && ({}); |
}; |
|
return 0; |
} |
|
|
|
|
|
|
|
|
|
|
|
array(string) list_dbs(string|void wild) |
{ |
array(string) res = list_dbs(); |
|
if (res && wild) { |
res = filter(res, |
Regexp(replace(wild, ({"%", "_"}), ({".*", "."})))->match); |
} |
return res; |
} |
|
|
|
|
|
|
|
|
|
|
|
|
protected array(string) low_list_tables() |
{ |
array(string)|array(mapping(string:mixed))|object res; |
|
catch { |
array(mapping(string:mixed)) res = query("SHOW TABLES"); |
|
if (res && sizeof(res) && mappingp(res[0])) { |
string col_name = indices(res[0])[0]; |
if (sizeof(res[0]) > 1) { |
if (!zero_type(res[0]["TABLE_NAME"])) { |
col_name = "TABLE_NAME"; |
} |
} |
return map(res, lambda (mapping m, string col_name) { |
return m[col_name]; |
}, col_name); |
} |
return res && ({}); |
}; |
|
return 0; |
} |
|
|
|
|
|
|
|
array(string) list_tables(string|void wild) |
{ |
array(string) res = low_list_tables(); |
|
if (res && wild) { |
res = filter(res, |
Regexp(replace(wild, ({"%", "_"}), ({".*", "."})))->match); |
} |
return res; |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected array(mapping(string:mixed)) low_list_fields(string table) |
{ |
|
catch { |
array(mapping(string:mixed)) res = |
query("SHOW FIELDS FROM \'" + table + "\'"); |
|
res = res && map(res, |
lambda (mapping m, string table) { |
foreach(indices(m), string str) { |
|
string low_str = lower_case(str); |
if (low_str != str && !m[low_str]) |
m[low_str] = m_delete(m, str); |
} |
|
if ((!m->name) && m->field) |
m["name"] = m_delete(m, "field"); |
|
if (!m->table) |
m["table"] = table; |
|
return m; |
}, table); |
return res; |
}; |
return 0; |
} |
|
|
|
|
|
|
|
|
|
|
|
array(mapping(string:mixed)) list_fields(string table, string|void wild) |
{ |
array(mapping(string:mixed)) res = low_list_fields(table); |
|
if (res && wild) { |
res = |
filter(res, |
map(res->name, |
Regexp(replace(wild, ({"%", "_"}), ({".*", "."})))->match)); |
} |
|
return res; |
} |
|
|