giovedì 17 febbraio 2011

Export tabella in CSV

Il seguente comando permette di esportare una tabella MySQL in CSV:

mysqldump \
  -c \
  -T/tmp \
  -h localhost \
  --user=root \
  --password=<pwd> \
  --fields-enclosed-by=\" \
  --fields-terminated-by=, \
  <db> \
  <table>

lunedì 14 febbraio 2011

Statische occupazione dati

La seguente query estrae la dimensione dei dati, degli indici e dei database presenti su MySQL:

SELECT table_schema "Data Base Name",
       sum(data_length) / 1024 / 1024 "Data Size in MB",
       sum(index_length) / 1024 /1024 "Index Size in MB",
       sum( data_length + index_length) / 1024 / 1024 "Data Base Size in MB"
  FROM information_schema.TABLES
 GROUP BY table_schema;

lunedì 24 gennaio 2011

Manutenzione MySQL

Il seguente script permette di analizzare e deframmentare le tabelle presenti in un database MySQL:
# -*- coding: utf-8 -*-
import MySQLdb
import sys

def optimize(host, db, user, password):
    con = MySQLdb.connect(host=host, db=db, user=user, passwd=password)
    cur = con.cursor()
    cur.execute("SHOW TABLES")
    for item in cur.fetchall():
        print "Optimizing table " + item[0] + "...",
        cur.execute("ANALYZE TABLE " + item[0])
        cur.execute("OPTIMIZE TABLE " + item[0])
        
        print "Done"
    cur.close()
    con.close()

if __name__ == "__main__":
    if len(sys.argv[1:]) > 0:
        optimize(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4])
    else:
        print "usage: " + sys.argv[0] +
              " <hostname> <database> <user> <password>"

domenica 2 gennaio 2011

Manutenzione Firebird

Il seguente script permette di reindicizzare e ricalcolare le statistiche di un database Firebird:
#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys
import kinterbasdb

def reindex(db_name, hostname, username, pwd):
    query_index=("SELECT RDB$INDEX_NAME FROM RDB$INDICES " +
                "WHERE COALESCE(RDB$UNIQUE_FLAG,0)<>1 " +
                "AND RDB$FOREIGN_KEY IS NULL " +
                "AND RDB$SYSTEM_FLAG<>1")
    con=kinterbasdb.connect(host=hostname, database=db_name,
                            user=username, password=pwd)
    cur=con.cursor()
    cur.execute(query_index)
    all_index=cur.fetchall()

    for index_name in all_index:
        print "Reindex " + index_name[0].strip()
        cur.execute("ALTER INDEX " + index_name[0].strip() + " INACTIVE")
        cur.execute("ALTER INDEX " + index_name[0].strip() + " ACTIVE")
        cur.execute("SET STATISTIC INDEX " + index_name[0].strip())

    cur.close()
    con.close()

if __name__ == "__main__":
    reindex(sys.argv[1], sys.argv[2],
            sys.argv[3], sys.argv[4])

mercoledì 22 dicembre 2010

Dump SVN

Il seguente script permette di eseguire il dump di un repository Subversion (richiede python-subversion installato):
#!/usr/bin/python
# -*- coding: utf-8 -*-

import svn.fs
import svn.core
import svn.repos
from StringIO import StringIO

class SvnManager(object):
    def __init__(self):
        self._repository_path = None
        self._repository = None
        self._fs = None

    def set_repository(self, path):
        self._repository_path = path
        self._repository = svn.repos.open(path)
        self._fs = svn.repos.fs(self._repository)

    def get_last_revision(self):
        return svn.fs.youngest_rev(self._fs)

    def dump_repository(self):
        dumpstream = StringIO()
        feedbackstream = StringIO()
        rev = self.get_last_revision()

        svn.repos.dump_fs2(self._repository,
                           dumpstream,
                           feedbackstream,
                           0,
                           rev,
                           0,
                           0,
                           None)

        self._dump = dumpstream.getvalue()
        self._feedback = feedbackstream.getvalue()

        #print self._feedback.count("* Dumped revision " + str(rev))

    def save_dump(self, dump_name):
        filename = open(dump_name, 'w')
        filename.write(self._dump)
        filename.flush()
        filename.close()

if __name__ == '__main__':
    repository = 'repository'
    filename = 'filename'

    svn_manager = SvnManager()
    svn_manager.set_repository(repository)
    svn_manager.dump_repository()
    svn_manager.save_dump(filename)

MySQL e sequenze

Premessa: MySQL non gestisce le sequenze. O meglio, MySQL ha un campo auto_increment, ma è possibile specificarne uno per tabella. Di fatto, MySQL non implementa una struttura di creazione, gestione e cancellazione delle sequenze indipendenti dalla tabella (quello che su altri database si ottiene con CREATE SEQUENCE e affini, per capirci). Per ovviare al problema, bisogna quindi emulare la gestione delle sequenze mediante l'uso di costrutti autodefiniti. Di seguito un esempio di come creare, gestire e cancellare le sequenze:


drop table sequences;
drop function create_seq;
drop function drop_seq;
drop function next_value;
drop function cur_value;

create table sequences(seq_name varchar(30),
seq_value integer,
seq_increment integer
)
engine=MyISAM;

delimiter //
create function create_seq(name varchar(30), inc integer)
returns integer
begin
declare exist integer;

select count(*) into exist from sequences where seq_name = name;

if exist = 0 then
insert into sequences(seq_name, seq_value, seq_increment)
values(name, 0, inc);
return 0;
else
return -1;
end if;
end
//

create function drop_seq(name varchar(30))
returns integer
begin
declare exist integer;

select count(*) into exist from sequences where seq_name = name;

if exist = 0 then
return -1;
else
delete from sequences where seq_name = name;
return 0;
end if;
end
//

create function next_value(name varchar(30))
returns integer
begin
declare exist integer;
declare cur_value integer;
declare new_value integer;
declare inc_value integer;

select count(*) into exist from sequences where seq_name = name;

if exist = 0 then
return -1;
else
select seq_value,
seq_increment
into cur_value,
inc_value
from sequences
where seq_name = name;

set new_value = cur_value + inc_value;

update sequences
set seq_value = new_value
where seq_name = name;

return new_value;
end if;
end
//

create function cur_value(name varchar(30))
returns integer
begin
declare exist integer;
declare cur_value integer;

select count(*) into exist from sequences where seq_name = name;

if exist = 0 then
return -1;
else
select seq_value
into cur_value
from sequences
where seq_name = name;

return cur_value;
end if;
end
//

delimiter ;

Il codice in precedenza, sfruttando il fatto che le transazioni su l'engine MyISAM non sono supportate (e, di conseguenza, tutte le operazioni sono, per usare un gergo tecnico, non atomiche), permette di ottenere un incremento sempre univoco, indipendentemente dalla sessione in cui ci si trova. Di seguito, un esempio di utilizzo:


-- Viene creata la sequenza TEST con un incremento di un valore per volta
select create_seq('test', 1);

-- Viene incrementato e riportato il nuovo valore della sequenza
select next_value('test');

-- Viene mostrato il valore corrente della sequenza
select cur_value('test');

-- Viene cancellata la sequenza
select drop_seq('test');

Manipolazione dati su LDAP

Il seguente script permette di modificare un indirizzo email in un albero LDAP:

#!/usr/bin/python

import ldap

server = "ldap://localhost"
base_dn = "dc=domain,dc=net"
user_admin = ["cn=admin", "xxx"]
search_filter = "objectClass=person"
attributes = ["mail"]

search_scope = ldap.SCOPE_SUBTREE
mod_attribute = ldap.MOD_REPLACE

counter = 0

try:
    # Apertura della connessione con server LDAP e successiva
    # autenticazione come admin
    con = ldap.initialize(server)
    con.protocol_version = ldap.VERSION3
    con.simple_bind_s(",".join([user_admin[0], base_dn]),
                      user_admin[1])

    # Estrazione dei dati da modificare
    result_set = con.search_s(",".join(["ou=Users", base_dn]),
                              search_scope, search_filter,
                              attributes)

    # Iterazione dei risultati estratti
    for item in result_set:
        if not item[1] == {}:
            # Verifica che il dato estratto sia quello da modificare
            if item[1]["mail"][0].endswith("domain.net"):
                counter += 1
                fields = item[1]["mail"][0].split("@")

                # Modifica della email dell'utente
                print "Update email for " + item[0]
                modify = [(mod_attribute, "mail",
                           "@".join([fields[0], "dominio.it"])
                          )]
                con.modify_s(item[0], modify)

    print "Updated " + str(counter) + " users"
except ldap.LDAPError, e:
    print "Error"
    print e