Códigos de ejemplo para aprender distintas tecnologías, o lo que sucede cuando a una cuarentona se la deja sola con una computadora
Acerca de:
sábado, 1 de marzo de 2014
Hacer inserts muy rápidos en SQLite
http://jokecamp.wordpress.com/2012/03/16/make-your-sqlite-bulk-inserts-very-fast-in-c/
jueves, 20 de febrero de 2014
Continuando con el Conjunto de Wirth...
El enlace aquí.
Un mirror aquí.
lunes, 13 de enero de 2014
Resetear campo autoincrementable (serial) en Postgre 9.3
Cuando se crea un dato serial usando el pgAdmin, Postgre automáticamente nos crea una secuencia (en este caso llamada "phonebook_ID_seq") a la cual el campo serial está vinculado mediante la siguiente instrucción:
ALTER TABLE phonebook ALTER COLUMN "ID" SET DEFAULT nextval('"phonebook_ID_seq"'::regclass);
Para Postgre, un dato serial es un dato Integer con la función "nextval".
Esta es mi situación:
Luego de añadir y borrar varios registros a la tabla "phonebook", y finalmente dejarla vacía, quiero resetear el valor del campo "ID" a 1.
Al igual que en MySql, Postgre tiene una función llamada "setval" que me permite ponerle un valor arbitrario a la secuencia desde el cual continuará con los incrementos.
En el pgAdmin seleccionamos el campo "ID", abrimos la ventana de queries mediante el botón "Execute Arbitrary Queries" (el que tiene una lupa y el texto "SQL"), e ingresamos el siguiente query:
select setval('"phonebook_ID_seq"',1);
Hay que notar que lo que se altera es la secuencia, no el campo "ID". Hay que tener cuidado de poner el nombre de la secuencia entre comillas dobles dentro de las comillas simples. Como Postgre es Case Sensitive, saltarán errores si omitimos las comillas dobles y si el nombre de la secuencia contiene mayúsculas.
En la ventana de queries quedará así:
Si todo sale bien, nos aparecerá el valor al que hemos reseteado la secuencia. No tiene que ser 1, puede ser cualquier valor que queramos.
miércoles, 8 de enero de 2014
Postgre 9.3: Errores 42501 y 42703:
El Owner de la base de datos y de la tabla es el superusuario "postgre". La base de datos Prueba tiene como esquema por defecto (Default Schema) igual a público (public), también sus privilegios son públicos.
También he creado un usuario "user01" con las siguientes propiedades:
Al conectar una aplicación en C# mediante el usuario "user01", usando Npgsql (el cual se puede instalar junto con el Postgre usando la aplicación Stack Builder que también viene con el instalador del Postgre) y luego de ver los datos de la tabla phonebook todo iba bien; pero cuando quería modificar la tabla phonebook con un update, insert ó delete me arrojaba el siguiente error:
"Error 42501: permiso denegado a la secuencia phonebook_ID_seq"
Este error salta si el usuario con el que intento modificar la tabla no es su dueño (owner). No interesa si la base de datos tiene como dueño al superusuario "postgre", la tabla debe tener como dueño al usuario que intenta modificarla.
Para cambiar al dueño de la tabla phonebook de "postgre" a "user01" basta este script:
ALTER TABLE phonebook
OWNER TO user01;
Y entonces al usar la siguiente sentencia insert desde C#:
string query = @"insert into phonebook (phone, firstname, lastname, address) values ('1234', 'Wert', 'Asdlo', 'Fake Street 123')";
Los datos se guardaban correctamente, pero al querer actualizar o borrar:
string query1 = @"Update phonebook set phone ='0000', firstname ='Carry', lastname ='Doe', address = 'No signed' where ID = 1";
string query2 = "delete from phonebook where ID = 1";
Me saltaba el siguiente error:
"Error 42703: no existe la columna id
Lo extraño es que la tabla phonebook sí tiene una columna llamada "ID". Buscando por internet, hallé aquí la solución: se debe poner el nombre del campo que contiene mayúsculas entre comillas:
string query1 = "Update phonebook set phone ='0000', firstname ='Carry', " +
" lastname ='Doe', address = 'No signed' where \"ID\" = 1";
string query2 = "delete from phonebook where \"ID\" = 1";
El caracter \ le indica al C# que la comilla que le sigue no indica el final de la cadena. El motor del Postgre convierte todos los nombres de las columnas en una sentencia sql a minúsculas. Por ahí leí que, internamente, Postgre es Case Sensitive.
sábado, 14 de diciembre de 2013
Cómo Convertir de long a LPCWSTR (puntero largo a Wide String constante) en Visual C++
Como práctica, quise calcular el alto de la barra de título de una ventana.
El valor calculado es del tipo long. Luego debía convertirlo a LPCWSTR para pasarlo como parámetro a la api setWindowText que lo escribirá en lugar del título de la ventana.
He usado la información que hallé en estas webs:
La función ltoa (reemplazada por _ltoa)
Convertir de char* a LPCWSTR
La función MultiByteToWideChar
El código es el siguiente:
En el caso de una aplicación tipo win32, coloqué este código dentro de la función que procesa los mensajes de la ventana (WndProc), exactamente en el mensaje que se envía al crearla:
Al ejecutar el programa, mostrará el alto de la barra de título en el texto de... la barra de título.
sábado, 23 de noviembre de 2013
Implementación Thread-safe de una clase Singleton
La implementación WhatILearntToday de una clase Singleton Thread-Safe es la siguiente:
public class SingletonClass
{
private SingletonClass()
{
}
//Implementation #1 NO Thread-Safe: puede fallar si varios hilos intentan instanciarla al mismo tiempo
//static SingletonClass _instance = null;
//public static SingletonClass GetInstance()
//{
// if (_instance == null)
// {
// _instance = new SingletonClass();
// }
// return _instance;
//}
//Implementation #2 Thread-safe
static readonly SingletonClass _instance = new SingletonClass();
public static SingletonClass GetInstance()
{
get
{
return _instance;
}
}
public string GetWelcomeMessage()
{
return "Welcome to the Singleton world!! ";
}
}
Mi implementación (también Thread-Safe) es:
public class SingletonClass
{
private SingletonClass()
{
}
static readonly SingletonClass _instance = null;
static object lockThis; public static SingletonClass GetInstance() { lock(lockThis) {
if (_instance == null)
_instance = new SingletonClass();
}
return _instance;
}
public string GetWelcomeMessage()
{
return "Welcome to the Singleton world!! ";
}
}
miércoles, 23 de octubre de 2013
Cómo evadir la limitación de tamaño de una ventana en Windows
(12 + ancho de la resolución de pantalla) x (12 + alto de la resolución de pantalla)
Más información en StackOverflow.
Por allí hallé quienes afirman que se puede superar esta restricción. Y entonces me topé con este código, de la misma Microsoft, en Visual Basic 6.
Lo copio aquí para que no se vaya a perder:
En un módulo bas:
Option Explicit
Private Const GWL_WNDPROC = -4
Private Const WM_GETMINMAXINFO = &H24
Private Type POINTAPI
x As Long
y As Long
End Type
Private Type MINMAXINFO
ptReserved As POINTAPI
ptMaxSize As POINTAPI
ptMaxPosition As POINTAPI
ptMinTrackSize As POINTAPI
ptMaxTrackSize As POINTAPI
End Type
Global lpPrevWndProc As Long
Global gHW As Long
Private Declare Function DefWindowProc Lib "user32" Alias _
"DefWindowProcA" (ByVal hwnd As Long, ByVal wMsg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function CallWindowProc Lib "user32" Alias _
"CallWindowProcA" (ByVal lpPrevWndFunc As Long, _
ByVal hwnd As Long, ByVal Msg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function SetWindowLong Lib "user32" Alias _
"SetWindowLongA" (ByVal hwnd As Long, _
ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Sub CopyMemoryToMinMaxInfo Lib "KERNEL32" Alias _
"RtlMoveMemory" (hpvDest As MINMAXINFO, ByVal hpvSource As Long, _
ByVal cbCopy As Long)
Private Declare Sub CopyMemoryFromMinMaxInfo Lib "KERNEL32" Alias _
"RtlMoveMemory" (ByVal hpvDest As Long, hpvSource As MINMAXINFO, _
ByVal cbCopy As Long)
Public Sub Hook()
'Start subclassing.
lpPrevWndProc = SetWindowLong(gHW, GWL_WNDPROC, _
AddressOf WindowProc)
End Sub
Public Sub Unhook()
Dim temp As Long
'Cease subclassing.
temp = SetWindowLong(gHW, GWL_WNDPROC, lpPrevWndProc)
End Sub
Function WindowProc(ByVal hw As Long, ByVal uMsg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
Dim MinMax As MINMAXINFO
'Check for request for min/max window sizes.
If uMsg = WM_GETMINMAXINFO Then
'Retrieve default MinMax settings
CopyMemoryToMinMaxInfo MinMax, lParam, Len(MinMax)
'Specify new minimum size for window.
MinMax.ptMinTrackSize.x = 200
MinMax.ptMinTrackSize.y = 200
'Specify new maximum size for window.
MinMax.ptMaxTrackSize.x = 500
MinMax.ptMaxTrackSize.y = 500
'Copy local structure back.
CopyMemoryFromMinMaxInfo lParam, MinMax, Len(MinMax)
WindowProc = DefWindowProc(hw, uMsg, wParam, lParam)
Else
WindowProc = CallWindowProc(lpPrevWndProc, hw, uMsg, _
wParam, lParam)
End If
End Function
El truco es fácil: donde están los números en rojo, escribimos nuestros números enormes favoritos. Yo le puse por código a una ventana (Form) dimensiones de 2050*1600 píxeles, en una resolución de pantalla de 1024*768 (la restricción por defecto sería 1036*780).
Para hacer esto en el form ponemos:
Option Explicit
Private Sub Form_Load()
'Save handle to the form.
gHW = Me.hwnd
'Begin subclassing.
Hook
' le ponemos un tamaño ENORME
Me.Height = 1600
Me.Width = 2050
End Sub
Private Sub Form_Unload(Cancel As Integer)
'Stop subclassing.
Unhook
End Sub
Y funcionó.
Ya no intenté con dimensiones mayores porque una ventana con aproximadamente el doble de alto y ancho que la resolución de pantalla parece ser suficientemente grande. Deduzco que el máximo que puede aguantar el sistema operativo depende de la memoria máxima que le puede asignar a semejante ventanón y antes que la RAM empiece a echar humo.
Como son puras llamadas a Apis de WIndows, se puede traducir este código a Visual C++ o a .Net usando DLLImport.
sábado, 12 de octubre de 2013
Cómo importar datos con carácteres internacionales desde xls a SQLite
y quiero pasar los datos a una tabla en SQLite.
Después de probar distintas aplicaciones para SQLite, descubrí que ninguna importa directamente desde el formato xls (al menos no las que son gratuitas), pero sí importan desde el formato csv.
Tanto MSExcel como OpenOffice Calc pueden exportar datos al formato csv. Pero hay que tener en consideración un par de detalles para no perder los carácteres internacionales.
Para este ejemplo estoy usando OpenOffice Calc 3, pero el procedimiento es muy similar para MS Excel.
En "Guardar Como" elegimos el formato csv. Aparecerá la siguiente ventana:
Los datos deben exportarse con la codificación UTF8 y estar entrecomillados.
Para importar los datos a una base de datos en SQLite, el mejor programa que hallé es el Add-On para Firefox SQLite Manager.
Una vez instalado, lo ejecutamos desde Firefox -> Herramientas -> SQLite Manager (yo uso la versión 0.8.0) y cargamos nuestra base de datos, o la creamos.
Si la creamos no añadimos ninguna tabla, los datos importados crearán una automáticamente (mi base de datos se llama "Prueba01").
Luego vamos a la opción Base de Datos -> importar, o al ícono celeste con la flechita al costado del ícono de Abrir:
Elegimos la pestaña "CSV". Con el botón "Seleccionar Archivo" escogemos el archivo csv donde hemos exportado los datos desde xls. Las opciones a elegir son:
- Tipo de Codificación: UTF-8
- La primera fila contiene los nombres de las columnas
- Campos separados por coma
- Campos limitados por comillas dobles, siempre.
- Le cambié el nombre a la nueva tabla de "sample sales" a "sample_sales". Es mejor que las tablas no tengan nombres con espacios.
Presionamos OK. Aparecerá esta ventanita:
En mi caso, como los datos de "CategoryID" se repiten, debo deseleccionar las opciones "Clave Primaria" "Auto Inc" y "única" si no botará error (y uno bastante feo). Estas opciones se seleccionan sólo si los datos correspondientes son únicos, no hay valores en blanco, y pueden convertirse a enteros.
En una bse de datos SQLIte es mejor no usar el formato DateTime. Lo mejor es guardar las fechas como texto, y recién realizar la conversión en nuestra aplicación. Así se evitan excepciones que se producen en el driver de SQLite y no en nuestro código (esta recomendación es de la misma web de SQLite, y la aprendí después de jugar un poco con el C# y aventar algunas hermosas excepciones de formato...).
Si todo sale bien, nuestros datos se verán así, ya dentro de la base de datos:
Si no se declara una clave primaria, el SQLite Manager nos creará una :D en este caso es "rowid". Y como se puede ver, los carácteres internacionales se conservan intactos.
Ya para
jueves, 8 de agosto de 2013
Cómo ignorar los acentos al hacer una búsqueda en una base de datos en MS Access (mdb) con C#
string nombre = nombreABuscarenlaBD;
string query = String.Concat("Select * from Tabla1 where campoNombre like '", nombre, "'");
Este query funciona mientras no se desee buscar un nombre que incluya acentos como "María" ingresando "Maria" . Lo peor: puede que el usuario ni siquiera sepa si en la base de datos los nombres están guardados con acentos o no.
Para que la búsqueda devuelva todas las coincidencias con y sin acentos, se debe hacer el siguiente cambio a la variable tipo string que contiene el criterio de búsqueda (la idea es sacada de este foro):
nombre = nombre.Replace("a", "[aá]").Replace("e", "[eé]").Replace("i", "[ií]").Replace("o", "[oó]").Replace("u", "[uú]").Trim();
Si se desea ignorar también las diéresis, será:
nombre = nombre.Replace("a", "[aäá]").Replace("e", "[eëé]").Replace("i", "[iïí]").Replace("o", "[oöó]").Replace("u", "[uüú]").Trim();
miércoles, 24 de julio de 2013
Tutorial: Script en Python para montar particiones en Ubuntu 12.04
Mi partición D: como la ve Ubuntu
Pero por ningún lado veía mi partición C:. El problema estaba en que debía montarla. Las instrucciones para hacerlo las saqué de esta web.
Luego de montar y desmontar la partición C: algunas veces, siguiendo las instrucciones de ubuntu-guia y restaurando el archivo /etc/fstab original, pensé que todos esos pasos podían automatizarse, y entonces recordé que Ubuntu ya viene con un intérprete de Python, el cual justamente se utiliza para automatizar ciertas tareas.
En este caso, la tarea consistía en:
-
Ingresar con privilegios de root (en todo momento sudo me pidió la contraseña de root para tener privilegios suficientes, especialmente al copiar y pegar el archivo fstab mediante el comando "gksudo nautilus /etc/").
-
Ejecutar comandos de sudo.
-
Crear una carpeta en un directorio de sistema (/media/).
-
Modificar un archivo de sistema (/etc/fstab).
-
Reiniciar el sistema (esto lo dejé a que lo hiciera el usuario).
Para acceder a las funciones y características del sistema operativo usando Python, se deben importar dos librerías "os" y "sys". El código para que el script ingrese con privilegios de root pidiendo la contraseña lo saqué de este enlace.
Una vez que ya podía ingresar como root, necesitaba una función de Python que me permitiera ejecutar comandos de sudo y almacenar en una variable los resultados. El primer comando de sudo que debía ejecutar mi script es "fdisk -l":
La función que necesito es os.popen() el cual me devuelve en una lista las particiones halladas y sus características, pero como cadenas de caracteres. Con la función print() puedo mostrar en la terminal el resultado y mostrar las particiones halladas. En mi caso la lista (almacenada en una variabble llamada "rem") tiene tres elementos, el script muestra esta lista y pide al usuario que ingrese la partición a montar con la función raw_input(). Se debe ingresar la partición tal y como se muestra en la terminal, en mi caso es "/dev/sde1" (sin las comillas). Luego el script evalúa si la partición existe, cuyo nombre está almacenado en una variable llamada "part", utilizando la función filter(). Si no existe, el script finaliza. Este chequeo es necesario pues el usuario puede ingresar cualquier otra cosa, desde equivocarse al escribir hasta intentar sabotear el sistema operativo. (la función raw_input() interpreta lo ingresado como caracteres, pero la función input() interpreta lo ingresado como comandos de Python; ambas funciones pertenecen a este lenguaje, mucho cuidado con confundirlas!).
La función filter() es el equivalente en Python de las funciones de C# Linq.Where().
La línea:
n = filter(lambda
x: x.find(part,
0, len(x))
> -1,
rem)
en C# 3.0 sería:
var n = rem.Where(c => c.IndexOf(part) != -1);
En Python, si lalongitud de "n" es cero, es que no se ha hallado la partición ingresada.
Luego debo ejecutar el comando de sudo "blkid particion_elegida":
El resultado, guardado en la variable "rem", es una lista con un solo elemento tipo cadena de caracteres, el cual contiene el ID y el tipo de partición. Extraigo ambos con la función filter() y con el código que encontré en este enlace, el cual usa expresiones regulares para extraer la cadena de caracteres que se necesita, por este motivo debo importar también la librería "re".
Una vez que tengo todos los datos que necesito (partición, ID y tipo) le pido al usuario que escriba el nombre de la carpeta dentro de /media/ donde el script montará la partición. Si la carpeta no existe, el script la creará automáticamente. La línea que evalúa si la carpeta existe es:
os.path.isdir("media/carpeta_ingresada")
La variable con la ruta completa es "t2". Para crear la carpeta, si ésta no existe, utilizo el comando "mkdir" de sudo.
Python no posee un "switch" o un "Select Case" como otros lenguajes de programación, pero esto se resuelve con algunos if... else. En este caso, es para evaluar el tipo de partición y "armar" la línea que se añadirá al archivo /etc/fstab.
El código completo es:
|
#! /usr/bin/env python import os; import re; import sys; # http://stackoverflow.com/questions/5222333/authentication-in-python-script-to-run-as-root euid = os.geteuid() if
euid != 0: print "Iniciando
sudo para ingresar como root..."
args =
['sudo',
sys.executable]
+ sys.argv +
[os.environ] #
the next line replaces the currently-running process with the sudo os.execlpe('sudo',
*args) if euid ==
0:
print
'Corriendo, su euid es: ',
euid else: print 'No
se pudo iniciar como root. Cerrando script' sys.exit() #
http://mail.python.org/pipermail/python-es/2007-December/019270.html rem
= os.popen("sudo
fdisk -l").readlines()
# obtengo las particiones for i in
rem: print
i # http://www.daniweb.com/software-development/python/threads/12326/how-to-do-input-in-python #
"input" interpreta lo ingresado como comando, se debe usar
raw_input part
= raw_input("Escriba
la particion a montar: ") n = filter(lambda
x: x.find(part,
0, len(x))
> -1,
rem) if len(n)
== 0:
print
("La
particion no existe") else: t = ("sudo
blkid ", part)
# obtengo el UUID sudo1 = '' sudo1 = sudo1.join(t)
rem =
os.popen(sudo1).readlines() if
len(rem) ==
0:
print("Particion
no valida")
else:
partInfo = rem[0].split()
IdPart = filter(lambda
x: x.upper().find('UUID',
0, len(x))
> -1,
partInfo)
tipoPart = filter(lambda
x: x.upper().find('TYPE',
0, len(x))
> -1,
partInfo)
# http://stackoverflow.com/questions/4666973/how-to-extract-a-substring-from-inside-a-string-in-python
uuID = re.search('"(.+?)"',
IdPart[0]).group(1)
tipoParticion = re.search('"(.+?)"',
tipoPart[0]).group(1)
print
tipoParticion carpeta =
raw_input('ingrese
el nombre de la carpeta dentro de /media/ donde montar la particion. ') t =
('/media/',
carpeta)
t2 =
''
t2 = t2.join(t)
if not
os.path.isdir(t2):
t =
('sudo mkdir
/media/', carpeta)
sudo1 = ''
sudo1 = sudo1.join(t)
rem =
os.popen(sudo1).readlines()
# http://snipplr.com/view/6630/
# http://www.tutorialspoint.com/python/python_files_io.htm
if tipoParticion.upper()
== 'NTFS':
t =
('UUID=',
uuID, '
/media/', carpeta,
'
ntfs-3g default
0 0') elif
tipoParticion.upper()
== 'FAT': t
= ('UUID=',
uuID, '
/media/', carpeta,
'
vfat rw,uid=1000,gid=1000
0 0') elif
tipoParticion.upper()
== 'EXT4': t
= ('UUID=',
uuID, '
/media/', carpeta,
'
ext4 errors=remount-ro 0 1') else: t
= ''
if
len(t) >
0:
linea = ''
linea = linea.join(t)
with open('/etc/fstab',
'a') as
fstab_file:
fstab_file.writelines(linea)
fstab_file.close()
print
'Se ha montado la particion, reinicie el
sistema' else: print('particion desconocida') |
Este script sólo ha sido probado montando particiones NTFS en Ubuntu 12.04 y en carpetas dentro de /media/ cuyos nombres no contengan espacios. La partición no debe estar listada en /host/ o el sistema Ubuntu botará error al iniciar.
















