Max 5 API Reference
00001 /* 00002 ext_database.c 00003 Copyright 2008 - Cycling '74 00004 Timothy Place, tim@cycling74.com 00005 */ 00006 00007 #include "ext.h" 00008 #include "ext_obex.h" 00009 #include "ext_database.h" 00010 #include "ext_strings.h" 00011 00012 00013 #define DATABASE_SQL_MAXLEN 4096 00014 // Define the macro below to enable debug code 00015 //#define DATABASE_DEBUG 00016 00017 00018 t_max_err db_open(t_symbol *dbname, const char *fullpath, t_database **db) 00019 { 00020 long ac=0; 00021 t_atom av[6]; 00022 00023 if (*db) 00024 object_free(*db); 00025 00026 if (fullpath) { 00027 char coercedpath[MAX_PATH_CHARS]; 00028 short err; 00029 char dbpath[MAX_PATH_CHARS]; 00030 #ifdef MAC_VERSION 00031 char *temppath; 00032 #endif 00033 00034 err = path_nameconform((char*)fullpath, coercedpath, PATH_STYLE_NATIVE_PLAT, PATH_TYPE_ABSOLUTE); 00035 if (err) 00036 strncpy_zero(coercedpath, fullpath, MAX_PATH_CHARS); 00037 00038 #ifdef MAC_VERSION 00039 temppath = strchr(coercedpath, ':'); 00040 *temppath = '\0'; 00041 temppath += 1; 00042 00043 // at this point temppath points to the path after the volume, and coercedpath has the volume 00044 snprintf(dbpath, MAX_PATH_CHARS, "/Volumes/%s%s", coercedpath, temppath); 00045 #else // WIN_VERSION 00046 strncpy_zero(dbpath, coercedpath, MAX_PATH_CHARS); 00047 #endif 00048 00049 atom_setsym(av+ac, gensym("@rambased")); 00050 ac++; 00051 atom_setlong(av+ac, 0); 00052 ac++; 00053 atom_setsym(av+ac, gensym("@filename")); 00054 ac++; 00055 atom_setsym(av+ac, gensym(dbpath)); 00056 ac++; 00057 } 00058 atom_setsym(av+ac, gensym("@db")); 00059 ac++; 00060 atom_setsym(av+ac, dbname); 00061 ac++; 00062 00063 *db = (t_database*)object_new_typed(_sym_nobox, _sym_sqlite, ac, av); 00064 if (!*db) 00065 return MAX_ERR_GENERIC; 00066 00067 return MAX_ERR_NONE; 00068 } 00069 00070 t_max_err db_close(t_database **db) 00071 { 00072 object_free(*db); 00073 *db = NULL; 00074 return MAX_ERR_NONE; 00075 } 00076 00077 00078 t_max_err db_query(t_database *db, t_db_result **dbresult, const char *s, ...) 00079 { 00080 char sql[DATABASE_SQL_MAXLEN+2]; 00081 va_list ap; 00082 int err = 0; 00083 int len = 0; 00084 00085 if (db) { 00086 va_start(ap, s); 00087 00088 len = vsnprintf(sql, DATABASE_SQL_MAXLEN, s, ap); 00089 sql[DATABASE_SQL_MAXLEN] = '\0'; 00090 if (len >= DATABASE_SQL_MAXLEN) { 00091 cpost("DB: Query Overrun!\n"); 00092 err = MAX_ERR_GENERIC; 00093 goto out; 00094 } 00095 err = (int)object_method(db, _sym_execstring, sql, dbresult); 00096 #ifdef DATABASE_DEBUG 00097 cpost("SQL: %s\n", sql); 00098 if (err) 00099 cpost(" ERROR: %i\n", err); 00100 #endif // DATABASE_DEBUG 00101 out: 00102 va_end(ap); 00103 } 00104 return err; 00105 } 00106 00107 t_max_err db_query_silent(t_database *db, t_db_result **dbresult, const char *s, ...) 00108 { 00109 char sql[DATABASE_SQL_MAXLEN+2]; 00110 va_list ap; 00111 long logging = false; 00112 t_max_err err; 00113 00114 va_start(ap, s); 00115 vsnprintf(sql, DATABASE_SQL_MAXLEN, s, ap); 00116 sql[DATABASE_SQL_MAXLEN] = '\0'; 00117 00118 logging = object_attr_getlong(db, _sym_log); 00119 object_attr_setlong(db, _sym_log, 0); 00120 err = db_query(db, dbresult, sql, NULL); 00121 object_attr_setlong(db, _sym_log, logging); 00122 return err; 00123 } 00124 00125 t_max_err db_query_getlastinsertid(t_database *db, long *id) 00126 { 00127 *id = (long)object_method(db, _sym_getlastinsertid); 00128 return MAX_ERR_NONE; 00129 } 00130 00131 00132 t_max_err db_query_table_new(t_database *db, const char *tablename) 00133 { 00134 char idname[256]; 00135 00136 // SQLite won't let us add primary keys later, so we have to add it now. 00137 strncpy_zero(idname, tablename, 256); 00138 00139 // singularize 00140 if (idname[strlen(idname)-1 == 's']) 00141 idname[strlen(idname)-1] = 0; 00142 00143 return db_query(db, NULL, "CREATE TABLE IF NOT EXISTS %s ( %s_id INTEGER PRIMARY KEY NOT NULL )", tablename, idname); 00144 } 00145 00146 t_max_err db_query_table_addcolumn(t_database *db, const char *tablename, const char *columnname, const char *columntype, const char *flags) 00147 { 00148 if (flags) 00149 return db_query_silent(db, NULL, "ALTER TABLE %s ADD COLUMN %s %s %s", tablename, columnname, columntype, flags); 00150 else 00151 return db_query_silent(db, NULL, "ALTER TABLE %s ADD COLUMN %s %s", tablename, columnname, columntype); 00152 } 00153 00154 00155 t_max_err db_transaction_start(t_database *db) 00156 { 00157 return (t_max_err)object_method(db, _sym_starttransaction); 00158 } 00159 00160 t_max_err db_transaction_end(t_database *db) 00161 { 00162 return (t_max_err)object_method(db, _sym_endtransaction); 00163 } 00164 00165 t_max_err db_transaction_flush(t_database *db) 00166 { 00167 return (t_max_err)object_method(db, _sym_flush); 00168 } 00169 00170 00171 // DB VIEWS 00172 00173 t_max_err db_view_create(t_database *db, const char *sql, t_db_view **dbview) 00174 { 00175 *dbview = NULL; 00176 00177 if(sql && sql[0]) 00178 *dbview = (t_db_view *)object_method(db, gensym("createview"), gensym((char*)sql)); 00179 else 00180 *dbview = (t_db_view *)object_method(db, gensym("createview"), NULL); 00181 00182 if (!*dbview) 00183 return MAX_ERR_GENERIC; 00184 00185 return MAX_ERR_NONE; 00186 } 00187 00188 t_max_err db_view_remove(t_database *db, t_db_view **dbview) 00189 { 00190 if (db && *dbview) 00191 object_method(db, gensym("removeview"), *dbview); 00192 *dbview = NULL; 00193 return MAX_ERR_NONE; 00194 } 00195 00196 t_max_err db_view_getresult(t_db_view *dbview, t_db_result **result) 00197 { 00198 if (result){ 00199 *result = (t_db_view *)object_method(dbview, gensym("getresult")); 00200 return MAX_ERR_NONE; 00201 } 00202 return MAX_ERR_GENERIC; 00203 } 00204 00205 t_max_err db_view_setquery(t_db_view *dbview, char *newquery) 00206 { 00207 if (dbview) 00208 return object_attr_setsym(dbview, _sym_query, gensym(newquery)); 00209 else 00210 return MAX_ERR_GENERIC; 00211 } 00212 00213 00214 // DB RESULTS 00215 00216 char** db_result_nextrecord(t_db_result *result) 00217 { 00218 if (result) 00219 return (char **)object_method(result, _sym_nextrecord); 00220 else 00221 return NULL; 00222 } 00223 00224 void db_result_reset(t_db_result *result) 00225 { 00226 object_method(result, _sym_reset); 00227 } 00228 00229 void db_result_clear(t_db_result *result) 00230 { 00231 object_method(result, _sym_clear); 00232 } 00233 00234 long db_result_numrecords(t_db_result *result) 00235 { 00236 if (result) 00237 return (long)object_method(result, _sym_numrecords); 00238 else 00239 return 0; 00240 } 00241 00242 long db_result_numfields(t_db_result *result) 00243 { 00244 if (result) 00245 return (long)object_method(result, _sym_numfields); 00246 else 00247 return 0; 00248 } 00249 00250 char* db_result_fieldname(t_db_result *result, long fieldindex) 00251 { 00252 return (char *)object_method(result, _sym_fieldnamebyindex, fieldindex); 00253 } 00254 00255 char* db_result_string(t_db_result *result, long recordindex, long fieldindex) 00256 { 00257 return (char *)object_method(result, _sym_valuebyindex, recordindex, fieldindex); 00258 } 00259 00260 long db_result_long(t_db_result *result, long recordindex, long fieldindex) 00261 { 00262 char* c = (char *)object_method(result, _sym_valuebyindex, recordindex, fieldindex); 00263 long l = 0; 00264 00265 if (c) 00266 sscanf(c, "%ld", &l); 00267 return l; 00268 } 00269 00270 float db_result_float(t_db_result *result, long recordindex, long fieldindex) 00271 { 00272 char* c = (char *)object_method(result, _sym_valuebyindex, recordindex, fieldindex); 00273 float f = 0; 00274 00275 if (c) 00276 sscanf(c, "%f", &f); 00277 return f; 00278 } 00279 00280 unsigned long db_result_datetimeinseconds(t_db_result *result, long recordindex, long fieldindex) 00281 { 00282 char *str = db_result_string(result, recordindex, fieldindex); 00283 unsigned long seconds = 0; 00284 00285 if (str) 00286 db_util_stringtodate(str, &seconds); 00287 return seconds; 00288 } 00289 00290 00291 // UTILITIES 00292 00293 void db_util_stringtodate(const char *string, unsigned long *date) 00294 { 00295 t_datetime datetime; 00296 00297 sscanf(string, "%4lu-%02lu-%02lu %02lu:%02lu:%02lu", 00298 &datetime.year, &datetime.month, &datetime.day, 00299 &datetime.hour, &datetime.minute, &datetime.second); 00300 *date = systime_datetoseconds(&datetime); 00301 } 00302 00303 void db_util_datetostring(const unsigned long date, char *string) 00304 { 00305 t_datetime datetime; 00306 00307 systime_secondstodate(date, &datetime); 00308 sprintf(string, "%4lu-%02lu-%02lu %02lu:%02lu:%02lu", 00309 datetime.year, datetime.month, datetime.day, 00310 datetime.hour, datetime.minute, datetime.second); 00311 } 00312
Copyright © 2008, Cycling '74